mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
fix weather CMF Watch
This commit is contained in:
committed by
José Rebelo
parent
78068ecd07
commit
c19ed15dfe
+53
-39
@@ -335,57 +335,71 @@ object WeatherMapper {
|
||||
@JvmStatic
|
||||
fun mapToCmfCondition(openWeatherMapCondition: Int): Byte {
|
||||
/* deducted values:
|
||||
1 = sunny
|
||||
2 = cloudy
|
||||
3 = overcast
|
||||
4 = showers
|
||||
5 = snow showers
|
||||
6 = fog
|
||||
1 = sunny - sun with rays
|
||||
2 = cloudy - cloud
|
||||
3 = overcast - two clouds
|
||||
4 = showers - cloud with rain
|
||||
5 = snow showers - showflake
|
||||
6 = fog - multiple lines showing "fog"
|
||||
|
||||
9 = thunder showers
|
||||
9 = thunder showers - lightning
|
||||
|
||||
14 = sleet
|
||||
14 = sleet - cloud with dots under
|
||||
|
||||
19 = hot (extreme)
|
||||
20 = cold (extreme)
|
||||
19 = hot (extreme) - flame
|
||||
20 = cold (extreme) - snowman
|
||||
|
||||
21 = strong wind
|
||||
22 = (night) sunny - with moon
|
||||
23 = (night) sunny with stars
|
||||
24 = (night) cloudy - with moon
|
||||
21 = strong wind - wind moving icon
|
||||
22 = night haze - with moon haze
|
||||
23 = clear night - moon with star
|
||||
24 = cloudy night - moon with cloud
|
||||
25 = sun with haze
|
||||
26 = cloudy (sun with cloud)
|
||||
26 = cloudy - sun with cloud
|
||||
*/
|
||||
return when (openWeatherMapCondition) {
|
||||
210, 200, 201, 202, 230, 231, 232, 211, 212, 221 -> 9
|
||||
// Group 2xx: Thunderstorm
|
||||
200, 201, 202, 210, 211, 212, 221, 230, 231, 232 -> 9 // Thunderstorm - only one thunderstorm icon on watch
|
||||
// Group 3xx: Drizzle
|
||||
300, 301, 302, 310, 311, 312, 313, 314, 321 -> 4 // showers
|
||||
// Group 5xx: Rain
|
||||
500, 501, 502, 503, 504, 520, 521, 522, 531 -> 4 // showers
|
||||
511 -> 11 // freezing rain, icon used by openweathermap
|
||||
// Group 6xx: Snow
|
||||
600, 601, 602, 620, 621, 622 -> 11 // snow showers
|
||||
611, 612, 613, 615, 616 -> 14 // Sleet
|
||||
// Group 7xx: Atmosphere
|
||||
701, 711, 731, 741, 751, 761, 762 -> 6 // fog
|
||||
721 -> 25 // haze (day & night)
|
||||
781, 771 -> 21 // strong wind (tornado, squalls)
|
||||
// Group 800: Clear
|
||||
800 -> 1 // clear (day & night)
|
||||
// Group 80x: Clouds
|
||||
801, 802 -> 26 // sun/moon with cloud (night & day)
|
||||
803 -> 2 // cloudy
|
||||
804 -> 3 // overcast
|
||||
|
||||
901, 781, 900, 771, 960, 961, 902, 962 -> 21
|
||||
// Other codes
|
||||
900 -> 9 // thunderstorm
|
||||
901, 902, 962, 905 -> 21 // strong wind (tropical storm, hurricane, windy)
|
||||
903 -> 20 // cold
|
||||
904 -> 19 // hot
|
||||
906 -> 11 // hail, snow showers (or should it be sleet?)
|
||||
|
||||
300, 301, 302, 310, 311, 312, 313, 314, 321, 500, 501, 502, 503, 504, 520, 521, 522, 531 -> 4
|
||||
|
||||
906, 615, 616, 511 -> 14
|
||||
|
||||
611, 612, 600, 601, 602, 620, 621, 622 -> 5
|
||||
|
||||
|
||||
701, 711, 721, 731, 741, 751, 761, 762 -> 6
|
||||
|
||||
800 -> 1
|
||||
|
||||
904 -> 19
|
||||
|
||||
801, 802 -> 26
|
||||
803 -> 2
|
||||
|
||||
804 -> 3
|
||||
|
||||
905, 951, 952, 953, 954, 955, 956, 957, 958, 959 -> 21
|
||||
|
||||
903 -> 20
|
||||
else -> 20
|
||||
// strong wind (calm, light,gentle,moderate,fresh,strong-breeze, high,severe,windcase-gale, (violent) storm)
|
||||
951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961 -> 21
|
||||
else -> 0 // no data icon
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun cmfConditionToNight(cmfCondition: Byte): Byte {
|
||||
if (cmfCondition.toInt() == 1) return 23 // clear --> clear night
|
||||
if (cmfCondition.toInt() == 26) return 24 // sun with cloud --> moon with cloud
|
||||
if (cmfCondition.toInt() == 25) return 22 // sun with haze --> moon with haze
|
||||
return cmfCondition
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun mapToFitProCondition(openWeatherMapCondition: Int): Byte {
|
||||
return when (openWeatherMapCondition) {
|
||||
|
||||
+59
-10
@@ -44,6 +44,9 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
@@ -829,8 +832,19 @@ public class CmfWatchProSupport extends AbstractBTLESingleDeviceSupport implemen
|
||||
final boolean supportsSunriseSunset = getCoordinator().supportsSunriseSunset();
|
||||
final int payloadLength = (7 * 9) + (24 * 2) + (supportsSunriseSunset ? 32 : 30) + (supportsSunriseSunset ? 7 * 8 : 0);
|
||||
final ByteBuffer buf = ByteBuffer.allocate(payloadLength).order(ByteOrder.BIG_ENDIAN);
|
||||
|
||||
long currentTime = System.currentTimeMillis() / 1000;
|
||||
long sunrise = weatherSpec.getSunRise(); // epoch seconds
|
||||
long sunset = weatherSpec.getSunSet(); // epoch seconds
|
||||
boolean isDay = currentTime >= sunrise && currentTime < sunset;
|
||||
|
||||
// start with the current day's weather
|
||||
buf.put(WeatherMapper.mapToCmfCondition(weatherSpec.getCurrentConditionCode()));
|
||||
// Condition
|
||||
byte cmfCondition = WeatherMapper.mapToCmfCondition(weatherSpec.getCurrentConditionCode());
|
||||
// If the sun has set, use moon icons where possible
|
||||
if (!isDay) cmfCondition = WeatherMapper.cmfConditionToNight(cmfCondition);
|
||||
buf.put(cmfCondition);
|
||||
// Temperatures, humidity, aqi, uv and wind speed
|
||||
buf.put((byte) (weatherSpec.getCurrentTemp() - 273 + 100)); // convert Kelvin to C, add 100
|
||||
buf.put((byte) (weatherSpec.getTodayMaxTemp() - 273 + 100)); // convert Kelvin to C, add 100
|
||||
buf.put((byte) (weatherSpec.getTodayMinTemp() - 273 + 100)); // convert Kelvin to C, add 100
|
||||
@@ -845,11 +859,12 @@ public class CmfWatchProSupport extends AbstractBTLESingleDeviceSupport implemen
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (i < maxForecastsAvailable) {
|
||||
WeatherSpec.Daily forecastDay = weatherSpec.getForecasts().get(i);
|
||||
// The watch can only show one icon for future days and this is the "day" icon:
|
||||
buf.put(WeatherMapper.mapToCmfCondition(forecastDay.getConditionCode())); // weather condition flag
|
||||
buf.put((byte) (forecastDay.getMaxTemp() - 273 + 100)); // temp in C (not shown in future days' forecasts)
|
||||
buf.put((byte) (forecastDay.getMaxTemp() - 273 + 100)); // max temp in C, + 100
|
||||
buf.put((byte) (forecastDay.getMinTemp() - 273 + 100)); // min temp in C, + 100
|
||||
buf.put((byte) forecastDay.getHumidity()); // humidity as a %
|
||||
buf.put((byte) forecastDay.getHumidity()); // humidity as a %, not shown by watch?
|
||||
buf.putShort((short) (forecastDay.getAirQuality() != null ? forecastDay.getAirQuality().getAqi() : 0));
|
||||
buf.put((byte) forecastDay.getUvIndex()); // UV index isn't shown. uvi decimal/100, so 0x07 = 700 UVI.
|
||||
buf.put((byte) forecastDay.getWindSpeed()); // isn't shown by watch, unsure of correct units
|
||||
@@ -866,18 +881,52 @@ public class CmfWatchProSupport extends AbstractBTLESingleDeviceSupport implemen
|
||||
}
|
||||
|
||||
}
|
||||
// now add the hourly data for today - just condition and temperature
|
||||
|
||||
// hourly data for next 24 hours, the current hour (or hours before that) should not be included! only condition and temperature
|
||||
int maxHourlyForecastsAvailable = weatherSpec.getHourly().size();
|
||||
for (int i = 0; i < 24; i++) {
|
||||
if (i < maxHourlyForecastsAvailable) {
|
||||
int writtenHourlyForecasts = 0;
|
||||
long nextHour = ((currentTime + 3600 - 1) / 3600) * 3600;
|
||||
|
||||
// sunset/sunrise stuff, since we only show 24h, only today and tomorrow is important
|
||||
WeatherSpec.Daily tomorrow = weatherSpec.getForecasts().get(0); // Weatherspec is today, forecasts is tomorrow and onward
|
||||
LocalDate tomorrowDate = Instant.ofEpochSecond(tomorrow.getSunRise()).atZone(ZoneOffset.UTC).toLocalDate();
|
||||
|
||||
for (int i = 0; i < maxHourlyForecastsAvailable && writtenHourlyForecasts < 24; i++) {
|
||||
WeatherSpec.Hourly forecastHr = weatherSpec.getHourly().get(i);
|
||||
buf.put((byte) (forecastHr.getTemp() - 273 + 100)); // temperature
|
||||
buf.put((byte) forecastHr.getConditionCode()); // condition
|
||||
} else {
|
||||
buf.put((byte) (weatherSpec.getCurrentTemp() - 273 + 100)); // assume current temp
|
||||
buf.put(WeatherMapper.mapToCmfCondition(weatherSpec.getCurrentConditionCode())); // current condition
|
||||
// Skip current / past hours
|
||||
if (forecastHr.getTimestamp() < nextHour) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Temperature
|
||||
buf.put((byte) (forecastHr.getTemp() - 273 + 100));
|
||||
|
||||
// If the checked forecast-hour is more the current day sunset, check if the day has ended, if so update the sunset/sunrise to be for tomorrow
|
||||
if (forecastHr.getTimestamp() > sunset) {
|
||||
LocalDate forecastHrDate = Instant.ofEpochSecond(forecastHr.getTimestamp()).atZone(ZoneOffset.UTC).toLocalDate();
|
||||
if (forecastHrDate.equals(tomorrowDate)) {
|
||||
sunrise = tomorrow.getSunRise();
|
||||
sunset = tomorrow.getSunSet();
|
||||
}
|
||||
}
|
||||
isDay = forecastHr.getTimestamp() >= sunrise && forecastHr.getTimestamp() < sunset;
|
||||
|
||||
// Get condition
|
||||
cmfCondition = WeatherMapper.mapToCmfCondition(forecastHr.getConditionCode());
|
||||
// If the sun has set, use moon icons where possible
|
||||
if (!isDay) cmfCondition = WeatherMapper.cmfConditionToNight(cmfCondition);
|
||||
buf.put(cmfCondition); // condition
|
||||
|
||||
writtenHourlyForecasts++;
|
||||
}
|
||||
|
||||
// Pad if fewer than 24 entries were written
|
||||
while (writtenHourlyForecasts < 24) {
|
||||
buf.put((byte) 0x01);
|
||||
buf.put((byte) 0x00);
|
||||
writtenHourlyForecasts++;
|
||||
}
|
||||
|
||||
// place name - watch scrolls after ~10 chars. Pad up to 32 bytes.
|
||||
final byte[] locationNameBytes = nodomain.freeyourgadget.gadgetbridge.util.StringUtils.truncateToBytes(weatherSpec.getLocation(), 30);
|
||||
buf.put(locationNameBytes);
|
||||
|
||||
Reference in New Issue
Block a user