mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
igpsport: Weather refactoring. Fixed hourly times and icons.
This commit is contained in:
committed by
José Rebelo
parent
56e67e0761
commit
93c1f78371
+4
-83
@@ -20,29 +20,20 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.igpsport.IGPSportRouteInstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.igpsport.IGPSportConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
@@ -53,7 +44,6 @@ import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Ble;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Config;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.CyclingData;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Firmware;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.GeneralFileOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Ins;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.PeripheralCommon;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.RoutePlan;
|
||||
@@ -86,6 +76,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
public final BatteryInfoProfile<IGPSportDeviceSupport> batteryInfoProfile;
|
||||
private IGPSportRoutesManager routeManager;
|
||||
private IGPSportDownloadManager downloadManager;
|
||||
private IGPSportWeather weatherManager;
|
||||
|
||||
|
||||
private int mtuSize=247; //FIXME use actual device mtu
|
||||
@@ -96,6 +87,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
|
||||
routeManager = new IGPSportRoutesManager(this);
|
||||
downloadManager = new IGPSportDownloadManager(this);
|
||||
weatherManager = new IGPSportWeather(this);
|
||||
|
||||
addSupportedService(GattService.UUID_SERVICE_DEVICE_INFORMATION);
|
||||
addSupportedService(GattService.UUID_SERVICE_BATTERY_SERVICE);
|
||||
@@ -660,7 +652,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
public void onSendWeather(ArrayList<WeatherSpec> weatherSpecs) {
|
||||
if (!weatherSpecs.isEmpty()) {
|
||||
WeatherSpec weatherSpec = weatherSpecs.get(0);
|
||||
handleWeather(weatherSpec);
|
||||
weatherManager.handleWeather(weatherSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,81 +660,10 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
// Send weather
|
||||
final ArrayList<WeatherSpec> specs = new ArrayList<>(nodomain.freeyourgadget.gadgetbridge.model.Weather.getInstance().getWeatherSpecs());
|
||||
if (!specs.isEmpty()) {
|
||||
handleWeather(specs.get(0));
|
||||
weatherManager.handleWeather(specs.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWeather(WeatherSpec weatherSpec) {
|
||||
//example weather packet
|
||||
//010302ff02ffff00fe3601ffffffffffffffff04080310021802221508ac021012180b20002a0a323032342d30382d3330221508ac021015180a20002a0a323032342d30382d3331221408651019180c20002a0a323032342d30392d30312a20081310651812200b2a10323032342d30382d33302030333a34373201303a0132322108651011180d2210323032342d30382d33302030353a30302a0331353832023133322108651012180d2210323032342d30382d33302030363a30302a033136373202313332210865101018112210323032342d30382d33302030373a30302a0331373932023133322208ac02100f18332210323032342d30382d33302030383a30302a03323031320231333a0308e807
|
||||
|
||||
try {
|
||||
LocalDateTime currentTime = LocalDateTime.now();
|
||||
DateTimeFormatter formatterNow = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
|
||||
TransactionBuilder builder = performInitialized("set weather");
|
||||
Back.back_msg.Builder weatherMsg = Back.back_msg.newBuilder();
|
||||
Back.weather_current_data_message.Builder currentWeatherMsg =Back.weather_current_data_message.newBuilder();
|
||||
currentWeatherMsg.setCurDayMinTemp(weatherSpec.todayMinTemp-273);
|
||||
currentWeatherMsg.setCurDayMaxTemp(weatherSpec.todayMaxTemp-273);
|
||||
currentWeatherMsg.setCurTemperature(weatherSpec.currentTemp-273);
|
||||
currentWeatherMsg.setCurWeather(weatherSpec.currentConditionCode);
|
||||
currentWeatherMsg.setWindDeg(String.valueOf(weatherSpec.windDirection));
|
||||
currentWeatherMsg.setWindSpd(String.valueOf(Math.round(weatherSpec.windSpeed)));
|
||||
currentWeatherMsg.setTime(currentTime.format(formatterNow));
|
||||
|
||||
int currentDay=0;
|
||||
|
||||
for (final WeatherSpec.Daily forecast : weatherSpec.forecasts) {
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
currentDay++;
|
||||
LocalDateTime tomorrow = now.plusDays(currentDay);
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; //"yyyy-MM-dd"
|
||||
weatherMsg.addThreeDaysMsg(Back.weather_three_days_data_message.newBuilder()
|
||||
.setWeatherIndex(forecast.conditionCode)
|
||||
.setRainProb(forecast.precipProbability)
|
||||
.setMaxTemp(forecast.maxTemp-273)
|
||||
.setMinTemp(forecast.minTemp-273)
|
||||
.setDate(tomorrow.format(formatter)).build());
|
||||
|
||||
if (currentDay > 2) //we only need 3 days
|
||||
break;
|
||||
}
|
||||
|
||||
int currentHour=0;
|
||||
for (final WeatherSpec.Hourly hourly : weatherSpec.hourly) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
weatherMsg.addThreeHoursMsg(Back.weather_three_hour_data_memsage.newBuilder()
|
||||
.setWatherIndex(hourly.conditionCode)
|
||||
.setRainProb(hourly.precipProbability)
|
||||
.setTemp(hourly.temp-273)
|
||||
.setTime(sdf.format(new Date(hourly.timestamp * 1000L)))
|
||||
.setWindDeg(String.valueOf(hourly.windDirection))
|
||||
.setWindSpd(String.valueOf(Math.round(hourly.windSpeed))).build());
|
||||
currentHour++;
|
||||
if (currentHour > 3 ) // its called three hour weather but shows actually 4 entries
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
weatherMsg.setCurMsg(currentWeatherMsg);
|
||||
weatherMsg.setServiceType(Common.service_type_index.enum_SERVICE_TYPE_INDEX_BACK);
|
||||
weatherMsg.setBackOperateType(Back.BACK_OPERATE_TYPE.enum_BACK_OPERATE_TYPE_SEND);
|
||||
weatherMsg.setBackServiceType(Back.BACK_SERVICE_TYPE.enum_BACK_SERVICE_TYPE_WEATHER);
|
||||
|
||||
|
||||
|
||||
byte[] weatherBytes = craftData(weatherMsg.getServiceType().getNumber(),
|
||||
weatherMsg.getBackServiceType().getNumber(),
|
||||
weatherMsg.getBackOperateType().getNumber(),
|
||||
weatherMsg.build().toByteArray());
|
||||
builder.writeChunkedData(writeCharacteristicFourth, weatherBytes, getMTU());
|
||||
builder.queue(getQueue());
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public File getWritableExportDirectory() throws IOException {
|
||||
return getDevice().getDeviceCoordinator().getWritableExportDirectory(getDevice());
|
||||
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.igpsport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Back;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Common;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
|
||||
public class IGPSportWeather {
|
||||
IGPSportDeviceSupport support;
|
||||
public IGPSportWeather(IGPSportDeviceSupport support) {
|
||||
this.support = support;
|
||||
}
|
||||
|
||||
// A static map to hold the conversion logic from OWM to QWeather.
|
||||
private static final Map<Integer, Integer> codeMap = new HashMap<>();
|
||||
|
||||
// Static initializer block to populate the map with conversion data.
|
||||
static {
|
||||
// === OWM Group 2xx: Thunderstorm ===
|
||||
codeMap.put(200, 302); // thunderstorm with light rain -> Thundershower
|
||||
codeMap.put(201, 302); // thunderstorm with rain -> Thundershower
|
||||
codeMap.put(202, 303); // thunderstorm with heavy rain -> Heavy Thunderstorm
|
||||
codeMap.put(210, 302); // light thunderstorm -> Thundershower
|
||||
codeMap.put(211, 302); // thunderstorm -> Thundershower
|
||||
codeMap.put(212, 303); // heavy thunderstorm -> Heavy Thunderstorm
|
||||
codeMap.put(221, 302); // ragged thunderstorm -> Thundershower
|
||||
codeMap.put(230, 302); // thunderstorm with light drizzle -> Thundershower
|
||||
codeMap.put(231, 302); // thunderstorm with drizzle -> Thundershower
|
||||
codeMap.put(232, 302); // thunderstorm with heavy drizzle -> Thundershower
|
||||
|
||||
// === OWM Group 3xx: Drizzle ===
|
||||
codeMap.put(300, 309); // light intensity drizzle -> Drizzle Rain
|
||||
codeMap.put(301, 309); // drizzle -> Drizzle Rain
|
||||
codeMap.put(302, 309); // heavy intensity drizzle -> Drizzle Rain
|
||||
codeMap.put(310, 309); // light intensity drizzle rain -> Drizzle Rain
|
||||
codeMap.put(311, 309); // drizzle rain -> Drizzle Rain
|
||||
codeMap.put(312, 309); // heavy intensity drizzle rain -> Drizzle Rain
|
||||
codeMap.put(313, 309); // shower rain and drizzle -> Drizzle Rain
|
||||
codeMap.put(314, 309); // heavy shower rain and drizzle -> Drizzle Rain
|
||||
codeMap.put(321, 309); // shower drizzle -> Drizzle Rain
|
||||
|
||||
// === OWM Group 5xx: Rain ===
|
||||
codeMap.put(500, 305); // light rain -> Light Rain
|
||||
codeMap.put(501, 306); // moderate rain -> Moderate Rain
|
||||
codeMap.put(502, 307); // heavy intensity rain -> Heavy Rain
|
||||
codeMap.put(503, 311); // very heavy rain -> Heavy Rainstorm
|
||||
codeMap.put(504, 308); // extreme rain -> Extreme Rain
|
||||
codeMap.put(511, 313); // freezing rain -> Freezing Rain
|
||||
codeMap.put(520, 300); // light intensity shower rain -> Shower Rain
|
||||
codeMap.put(521, 300); // shower rain -> Shower Rain
|
||||
codeMap.put(522, 301); // heavy intensity shower rain -> Heavy Shower Rain
|
||||
codeMap.put(531, 300); // ragged shower rain -> Shower Rain
|
||||
|
||||
// === OWM Group 6xx: Snow ===
|
||||
codeMap.put(600, 400); // light snow -> Light Snow
|
||||
codeMap.put(601, 401); // snow -> Moderate Snow
|
||||
codeMap.put(602, 402); // heavy snow -> Heavy Snow
|
||||
codeMap.put(611, 404); // Sleet -> Sleet
|
||||
codeMap.put(612, 404); // Light shower sleet -> Sleet
|
||||
codeMap.put(613, 404); // Shower sleet -> Sleet
|
||||
codeMap.put(615, 405); // Light rain and snow -> Rain and Snow
|
||||
codeMap.put(616, 405); // Rain and snow -> Rain and Snow
|
||||
codeMap.put(620, 407); // Light shower snow -> Snow Flurry
|
||||
codeMap.put(621, 406); // Shower snow -> Shower Snow
|
||||
codeMap.put(622, 403); // Heavy shower snow -> Snowstorm
|
||||
|
||||
// === OWM Group 7xx: Atmosphere ===
|
||||
codeMap.put(701, 500); // mist -> Mist
|
||||
codeMap.put(711, 502); // Smoke -> Haze
|
||||
codeMap.put(721, 502); // Haze -> Haze
|
||||
codeMap.put(731, 507); // sand/ dust whirls -> Duststorm
|
||||
codeMap.put(741, 501); // fog -> Fog
|
||||
codeMap.put(751, 503); // sand -> Sand
|
||||
codeMap.put(761, 504); // dust -> Dust
|
||||
codeMap.put(762, 999); // volcanic ash -> Unknown
|
||||
codeMap.put(771, 999); // squalls -> Unknown
|
||||
codeMap.put(781, 999); // tornado -> Unknown
|
||||
|
||||
// === OWM Group 800: Clear ===
|
||||
codeMap.put(800, 100); // clear sky -> Sunny (day code)
|
||||
|
||||
// === OWM Group 80x: Clouds ===
|
||||
codeMap.put(801, 102); // few clouds: 11-25% -> Few Clouds
|
||||
codeMap.put(802, 101); // scattered clouds: 25-50% -> Cloudy
|
||||
codeMap.put(803, 103); // broken clouds: 51-84% -> Partly Cloudy
|
||||
codeMap.put(804, 104); // overcast clouds: 85-100% -> Overcast
|
||||
|
||||
// === OWM Group 9xx: Extreme ===
|
||||
codeMap.put(900, 999); // tornado -> Unknown
|
||||
codeMap.put(901, 999); // tropical storm -> Unknown
|
||||
codeMap.put(902, 999); // hurricane -> Unknown
|
||||
codeMap.put(903, 901); // cold -> Cold
|
||||
codeMap.put(904, 900); // hot -> Hot
|
||||
codeMap.put(905, 999); // windy -> Unknown
|
||||
codeMap.put(906, 304); // hail -> Hail
|
||||
}
|
||||
|
||||
|
||||
static int convertOWMtoQWeather(int openWeatherMapCode) {
|
||||
return codeMap.getOrDefault(openWeatherMapCode, 999); // Return 999 for unknown codes
|
||||
}
|
||||
|
||||
public void handleWeather(WeatherSpec weatherSpec) {
|
||||
//example weather packet
|
||||
//010302ff02ffff00fe3601ffffffffffffffff04080310021802221508ac021012180b20002a0a323032342d30382d3330221508ac021015180a20002a0a323032342d30382d3331221408651019180c20002a0a323032342d30392d30312a20081310651812200b2a10323032342d30382d33302030333a34373201303a0132322108651011180d2210323032342d30382d33302030353a30302a0331353832023133322108651012180d2210323032342d30382d33302030363a30302a033136373202313332210865101018112210323032342d30382d33302030373a30302a0331373932023133322208ac02100f18332210323032342d30382d33302030383a30302a03323031320231333a0308e807
|
||||
|
||||
try {
|
||||
Instant currentTime = Instant.now();
|
||||
DateTimeFormatter formatterHourly = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
|
||||
.withZone(ZoneOffset.UTC); //device requires UTC time here and in hourly
|
||||
TransactionBuilder builder = support.performInitialized("set weather");
|
||||
Back.back_msg.Builder weatherMsg = Back.back_msg.newBuilder();
|
||||
Back.weather_current_data_message.Builder currentWeatherMsg =Back.weather_current_data_message.newBuilder();
|
||||
currentWeatherMsg.setCurDayMinTemp(weatherSpec.todayMinTemp-273);
|
||||
currentWeatherMsg.setCurDayMaxTemp(weatherSpec.todayMaxTemp-273);
|
||||
currentWeatherMsg.setCurTemperature(weatherSpec.currentTemp-273);
|
||||
currentWeatherMsg.setCurWeather(IGPSportWeather.convertOWMtoQWeather(weatherSpec.currentConditionCode));
|
||||
currentWeatherMsg.setWindDeg(String.valueOf(weatherSpec.windDirection));
|
||||
currentWeatherMsg.setWindSpd(String.valueOf(Math.round(weatherSpec.windSpeed)));
|
||||
currentWeatherMsg.setTime(formatterHourly.format(currentTime));
|
||||
|
||||
int currentDay=0;
|
||||
|
||||
for (final WeatherSpec.Daily forecast : weatherSpec.forecasts) {
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
currentDay++;
|
||||
LocalDateTime tomorrow = now.plusDays(currentDay);
|
||||
DateTimeFormatter formatterDaily = DateTimeFormatter.ISO_LOCAL_DATE; //"yyyy-MM-dd"
|
||||
weatherMsg.addThreeDaysMsg(Back.weather_three_days_data_message.newBuilder()
|
||||
.setWeatherIndex(IGPSportWeather.convertOWMtoQWeather(forecast.conditionCode))
|
||||
.setRainProb(forecast.precipProbability)
|
||||
.setMaxTemp(forecast.maxTemp-273)
|
||||
.setMinTemp(forecast.minTemp-273)
|
||||
.setDate(tomorrow.format(formatterDaily)).build());
|
||||
|
||||
if (currentDay > 2) //we only need 3 days
|
||||
break;
|
||||
}
|
||||
|
||||
int currentHour=0;
|
||||
for (final WeatherSpec.Hourly hourly : weatherSpec.hourly) {
|
||||
weatherMsg.addThreeHoursMsg(Back.weather_three_hour_data_memsage.newBuilder()
|
||||
.setWatherIndex(IGPSportWeather.convertOWMtoQWeather(hourly.conditionCode))
|
||||
.setRainProb(hourly.precipProbability)
|
||||
.setTemp(hourly.temp-273)
|
||||
.setTime(formatterHourly.format(Instant.ofEpochMilli(hourly.timestamp * 1000L)))
|
||||
.setWindDeg(String.valueOf(hourly.windDirection))
|
||||
.setWindSpd(String.valueOf(Math.round(hourly.windSpeed))).build());
|
||||
|
||||
currentHour++;
|
||||
if (currentHour > 3 ) // its called three hour weather but shows actually 4 entries
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
weatherMsg.setCurMsg(currentWeatherMsg);
|
||||
weatherMsg.setServiceType(Common.service_type_index.enum_SERVICE_TYPE_INDEX_BACK);
|
||||
weatherMsg.setBackOperateType(Back.BACK_OPERATE_TYPE.enum_BACK_OPERATE_TYPE_SEND);
|
||||
weatherMsg.setBackServiceType(Back.BACK_SERVICE_TYPE.enum_BACK_SERVICE_TYPE_WEATHER);
|
||||
|
||||
|
||||
|
||||
byte[] weatherBytes = IGPSportDeviceSupport.craftData(weatherMsg.getServiceType().getNumber(),
|
||||
weatherMsg.getBackServiceType().getNumber(),
|
||||
weatherMsg.getBackOperateType().getNumber(),
|
||||
weatherMsg.build().toByteArray());
|
||||
builder.writeChunkedData(support.writeCharacteristicFourth, weatherBytes, support.getMTU());
|
||||
builder.queue(support.getQueue());
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user