1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-20 12:00:51 +02:00

Implement Huawei weather icons

This commit is contained in:
Martin.JM 2024-02-04 00:59:04 +01:00 committed by José Rebelo
parent f970b7482b
commit 65aa5faec5
4 changed files with 270 additions and 12 deletions

View File

@ -16,7 +16,6 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -48,12 +47,217 @@ public class Weather {
public boolean moonPhaseSupported = false;
}
public enum WeatherIcon {
// Also used for the text on the watch
SUNNY,
CLOUDY,
OVERCAST,
SHOWERS,
THUNDERSTORMS,
THUNDER_AND_HAIL,
SLEET,
LIGHT_RAIN,
RAIN,
HEAVY_RAIN,
RAIN_STORM,
HEAVY_RAIN_STORMS,
SEVERE_RAIN_STORMS,
SNOW_FLURRIES,
LIGHT_SNOW,
SNOW,
HEAVY_SNOW,
SNOWSTORMS,
FOG,
FREEZING_RAIN,
DUST_STORM,
LIGHT_TO_MODERATE_RAIN,
MODERATE_TO_HEAVY_RAIN,
HEAVY_TO_SEVERE_RAIN,
HEAVY_TO_TORRENTIAL_RAIN,
SEVERE_TO_TORRENTIAL_RAIN,
LIGHT_TO_MODERATE_SNOW,
MODERATE_TO_HEAVY_SNOW,
HEAVY_SNOW_TO_BLIZZARD,
DUST,
SAND,
SANDSTORMS,
FREEZING, // misses small/non-moving icon
HOT, // misses small/non-moving icon
COLD, // misses small/non-moving icon
WINDY,
HAZY,
UNKNOWN // Good to have probably
}
private static byte iconToByte(WeatherIcon weatherIcon) {
switch (weatherIcon) {
case SUNNY:
return 0x00;
case CLOUDY:
return 0x01;
case OVERCAST:
return 0x02;
case SHOWERS:
return 0x03;
case THUNDERSTORMS:
return 0x04;
case THUNDER_AND_HAIL:
return 0x05;
case SLEET:
return 0x06;
case LIGHT_RAIN:
return 0x07;
case RAIN:
return 0x08;
case HEAVY_RAIN:
return 0x09;
case RAIN_STORM:
return 0x0a;
case HEAVY_RAIN_STORMS:
return 0x0b;
case SEVERE_RAIN_STORMS:
return 0x0c;
case SNOW_FLURRIES:
return 0x0d;
case LIGHT_SNOW:
return 0x0e;
case SNOW:
return 0x0f;
case HEAVY_SNOW:
return 0x10;
case SNOWSTORMS:
return 0x11;
case FOG:
return 0x12;
case FREEZING_RAIN:
return 0x13;
case DUST_STORM:
return 0x14;
case LIGHT_TO_MODERATE_RAIN:
return 0x15;
case MODERATE_TO_HEAVY_RAIN:
return 0x16;
case HEAVY_TO_SEVERE_RAIN:
return 0x17;
case HEAVY_TO_TORRENTIAL_RAIN:
return 0x18;
case SEVERE_TO_TORRENTIAL_RAIN:
return 0x19;
case LIGHT_TO_MODERATE_SNOW:
return 0x1a;
case MODERATE_TO_HEAVY_SNOW:
return 0x1b;
case HEAVY_SNOW_TO_BLIZZARD:
return 0x1c;
case DUST:
return 0x1d;
case SAND:
return 0x1e;
case SANDSTORMS:
return 0x1f;
case FREEZING:
return 0x20;
case HOT:
return 0x21;
case COLD:
return 0x22;
case WINDY:
return 0x23;
case HAZY:
return 0x35;
default:
return 0x63; // Any higher and the current weather breaks
}
}
private static WeatherIcon byteToIcon(byte weatherIcon) {
switch (weatherIcon) {
case 0x00:
return WeatherIcon.SUNNY;
case 0x01:
return WeatherIcon.CLOUDY;
case 0x02:
return WeatherIcon.OVERCAST;
case 0x03:
return WeatherIcon.SHOWERS;
case 0x04:
return WeatherIcon.THUNDERSTORMS;
case 0x05:
return WeatherIcon.THUNDER_AND_HAIL;
case 0x06:
return WeatherIcon.SLEET;
case 0x07:
return WeatherIcon.LIGHT_RAIN;
case 0x08:
return WeatherIcon.RAIN;
case 0x09:
return WeatherIcon.HEAVY_RAIN;
case 0x0a:
return WeatherIcon.RAIN_STORM;
case 0x0b:
return WeatherIcon.HEAVY_RAIN_STORMS;
case 0x0c:
return WeatherIcon.SEVERE_RAIN_STORMS;
case 0x0d:
return WeatherIcon.SNOW_FLURRIES;
case 0x0e:
return WeatherIcon.LIGHT_SNOW;
case 0x0f:
return WeatherIcon.SNOW;
case 0x10:
return WeatherIcon.HEAVY_SNOW;
case 0x11:
return WeatherIcon.SNOWSTORMS;
case 0x12:
return WeatherIcon.FOG;
case 0x13:
return WeatherIcon.FREEZING_RAIN;
case 0x14:
return WeatherIcon.DUST_STORM;
case 0x15:
return WeatherIcon.LIGHT_TO_MODERATE_RAIN;
case 0x16:
return WeatherIcon.MODERATE_TO_HEAVY_RAIN;
case 0x17:
return WeatherIcon.HEAVY_TO_SEVERE_RAIN;
case 0x18:
return WeatherIcon.HEAVY_TO_TORRENTIAL_RAIN;
case 0x19:
return WeatherIcon.SEVERE_TO_TORRENTIAL_RAIN;
case 0x1a:
return WeatherIcon.LIGHT_TO_MODERATE_SNOW;
case 0x1b:
return WeatherIcon.MODERATE_TO_HEAVY_SNOW;
case 0x1c:
return WeatherIcon.HEAVY_SNOW_TO_BLIZZARD;
case 0x1d:
return WeatherIcon.DUST;
case 0x1e:
return WeatherIcon.SAND;
case 0x1f:
return WeatherIcon.SANDSTORMS;
case 0x20:
return WeatherIcon.FREEZING;
case 0x21:
return WeatherIcon.HOT;
case 0x22:
return WeatherIcon.COLD;
case 0x23:
return WeatherIcon.WINDY;
case 0x35:
return WeatherIcon.HAZY;
default:
return WeatherIcon.UNKNOWN;
}
}
public static class CurrentWeatherRequest extends HuaweiPacket {
public static final byte id = 0x01;
public CurrentWeatherRequest(
ParamsProvider paramsProvider,
Settings settings,
WeatherIcon icon,
Byte windDirection,
Byte windSpeed,
Byte lowestTemperature,
@ -74,8 +278,8 @@ public class Weather {
HuaweiTLV tlv81 = new HuaweiTLV();
if (settings.weatherIconSupported) {
tlv81.put(0x02, (byte) 0x01);
if (icon != null && settings.weatherIconSupported) {
tlv81.put(0x02, iconToByte(icon));
}
if (settings.windSupported) {
@ -235,7 +439,7 @@ public class Weather {
public static class TimeData {
public int timestamp;
public byte icon;
public WeatherIcon icon;
public byte temperature;
@Override
@ -252,7 +456,7 @@ public class Weather {
public static class DayData {
public int timestamp;
public byte icon;
public WeatherIcon icon;
public byte highTemperature;
public byte lowTemperature;
public int sunriseTime;
@ -297,7 +501,7 @@ public class Weather {
// TODO: NULLs?
timeDataTlv.put(0x82, new HuaweiTLV()
.put(0x03, timeData.timestamp)
.put(0x04, timeData.icon)
.put(0x04, iconToByte(timeData.icon))
.put(0x05, timeData.temperature)
);
}
@ -311,7 +515,7 @@ public class Weather {
// TODO: NULLs?
dayDataTlv.put(0x91, new HuaweiTLV()
.put(0x12, dayData.timestamp)
.put(0x13, dayData.icon)
.put(0x13, iconToByte(dayData.icon))
.put(0x14, dayData.highTemperature)
.put(0x15, dayData.lowTemperature)
.put(0x16, dayData.sunriseTime)
@ -346,7 +550,7 @@ public class Weather {
for (HuaweiTLV timeTlv : this.tlv.getObject(0x81).getObjects(0x82)) {
TimeData timeData = new TimeData();
timeData.timestamp = timeTlv.getInteger(0x03);
timeData.icon = timeTlv.getByte(0x04);
timeData.icon = byteToIcon(timeTlv.getByte(0x04));
timeData.temperature = timeTlv.getByte(0x05);
timeDataList.add(timeData);
}
@ -355,7 +559,7 @@ public class Weather {
for (HuaweiTLV dayTlv : this.tlv.getObject(0x90).getObjects(0x91)) {
DayData dayData = new DayData();
dayData.timestamp = dayTlv.getInteger(0x12);
dayData.icon = dayTlv.getByte(0x13);
dayData.icon = byteToIcon(dayTlv.getByte(0x13));
dayData.highTemperature = dayTlv.getByte(0x14);
dayData.lowTemperature = dayTlv.getByte(0x15);
dayData.sunriseTime = dayTlv.getInteger(0x16);

View File

@ -1650,6 +1650,58 @@ public class HuaweiSupportProvider {
}
}
public Weather.WeatherIcon openWeatherMapConditionCodeToHuaweiIcon(int conditionCode) {
// More exact first, groups after
switch (conditionCode) {
case 500:
return Weather.WeatherIcon.LIGHT_RAIN;
case 501:
return Weather.WeatherIcon.RAIN;
case 502:
return Weather.WeatherIcon.HEAVY_RAIN;
case 503:
return Weather.WeatherIcon.RAIN_STORM;
case 504:
return Weather.WeatherIcon.SEVERE_RAIN_STORMS;
case 511:
return Weather.WeatherIcon.FREEZING_RAIN;
case 600:
return Weather.WeatherIcon.LIGHT_SNOW;
case 601:
return Weather.WeatherIcon.SNOW;
case 602:
return Weather.WeatherIcon.HEAVY_SNOW;
case 611:
return Weather.WeatherIcon.SLEET;
case 701:
case 741:
return Weather.WeatherIcon.FOG;
case 721:
return Weather.WeatherIcon.HAZY;
case 751:
return Weather.WeatherIcon.SAND;
case 761:
return Weather.WeatherIcon.DUST;
case 800:
return Weather.WeatherIcon.SUNNY;
case 801:
case 802:
return Weather.WeatherIcon.CLOUDY;
case 803:
case 804:
return Weather.WeatherIcon.OVERCAST;
}
if (conditionCode >= 200 && conditionCode < 300)
return Weather.WeatherIcon.THUNDERSTORMS;
if (conditionCode >= 300 && conditionCode < 400)
return Weather.WeatherIcon.LIGHT_RAIN;
if (conditionCode >= 500 && conditionCode < 600)
return Weather.WeatherIcon.RAIN;
if (conditionCode >= 600 && conditionCode < 700)
return Weather.WeatherIcon.SNOW;
return Weather.WeatherIcon.UNKNOWN;
}
public void onSendWeather(WeatherSpec weatherSpec) {
if (weatherSettings != null && weatherSettings.weatherSupported) {
try {

View File

@ -22,6 +22,7 @@ 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.util.DateTimeUtils;
public class SendWeatherCurrentRequest extends Request {
Weather.Settings settings;
@ -48,6 +49,7 @@ public class SendWeatherCurrentRequest extends Request {
return new Weather.CurrentWeatherRequest(
this.paramsProvider,
settings,
supportProvider.openWeatherMapConditionCodeToHuaweiIcon(weatherSpec.currentConditionCode),
(byte) weatherSpec.windDirection,
(byte) weatherSpec.windSpeedAsBeaufort(),
(byte) (weatherSpec.todayMinTemp - 273),

View File

@ -49,7 +49,7 @@ public class SendWeatherForecastRequest extends Request {
WeatherSpec.Hourly hourly = weatherSpec.hourly.get(i);
WeatherForecastData.TimeData timeData = new WeatherForecastData.TimeData();
timeData.timestamp = hourly.timestamp;
timeData.icon = 1; // TODO: hourly.conditionCode conversion
timeData.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(hourly.conditionCode); // TODO: hourly.conditionCode conversion
timeData.temperature = (byte) (hourly.temp - 273);
timeDataArrayList.add(timeData);
}
@ -57,7 +57,7 @@ public class SendWeatherForecastRequest extends Request {
// Add today as well
WeatherForecastData.DayData today = new WeatherForecastData.DayData();
today.timestamp = weatherSpec.sunRise;
today.icon = 1; // TODO
today.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(weatherSpec.currentConditionCode);
today.highTemperature = (byte) (weatherSpec.todayMaxTemp - 273);
today.lowTemperature = (byte) (weatherSpec.todayMinTemp - 273);
today.sunriseTime = weatherSpec.sunRise;
@ -71,7 +71,7 @@ public class SendWeatherForecastRequest extends Request {
WeatherSpec.Daily daily = weatherSpec.forecasts.get(i);
WeatherForecastData.DayData dayData = new WeatherForecastData.DayData();
dayData.timestamp = daily.sunRise;
dayData.icon = 1; // TODO: daily.conditionCode conversion
dayData.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(daily.conditionCode);
dayData.highTemperature = (byte) (daily.maxTemp - 273);
dayData.lowTemperature = (byte) (daily.minTemp - 273);
dayData.sunriseTime = daily.sunRise;