Convert WeatherSpec to kotlin

Also add getters and setters everywhere for compatibility and remove Serializable as it's not needed anymore
This commit is contained in:
Daniele Gobbetti
2025-07-20 11:50:56 +02:00
committed by José Rebelo
parent 86e53f0e85
commit d845a5a1d8
51 changed files with 1226 additions and 1292 deletions
@@ -365,28 +365,28 @@ public class DebugActivity extends AbstractGBActivity {
public void onClick(View v) { public void onClick(View v) {
if (Weather.INSTANCE.getWeatherSpec() == null) { if (Weather.INSTANCE.getWeatherSpec() == null) {
final WeatherSpec weatherSpec = new WeatherSpec(); final WeatherSpec weatherSpec = new WeatherSpec();
weatherSpec.forecasts = new ArrayList<>(); weatherSpec.setForecasts(new ArrayList<>());
weatherSpec.location = "Green Hill"; weatherSpec.setLocation("Green Hill");
weatherSpec.currentConditionCode = 601; // snow weatherSpec.setCurrentConditionCode(601); // snow
weatherSpec.currentCondition = WeatherMapper.INSTANCE.getConditionString(DebugActivity.this, weatherSpec.currentConditionCode); weatherSpec.setCurrentCondition(WeatherMapper.INSTANCE.getConditionString(DebugActivity.this, weatherSpec.getCurrentConditionCode()));
weatherSpec.currentTemp = 15 + 273; weatherSpec.setCurrentTemp(15 + 273);
weatherSpec.currentHumidity = 30; weatherSpec.setCurrentHumidity(30);
weatherSpec.windSpeed = 10; weatherSpec.setWindSpeed(10);
weatherSpec.windDirection = 12; weatherSpec.setWindDirection(12);
weatherSpec.timestamp = (int) (System.currentTimeMillis() / 1000); weatherSpec.setTimestamp((int) (System.currentTimeMillis() / 1000));
weatherSpec.todayMinTemp = 10 + 273; weatherSpec.setTodayMinTemp(10 + 273);
weatherSpec.todayMaxTemp = 25 + 273; weatherSpec.setTodayMaxTemp(25 + 273);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
final WeatherSpec.Daily gbForecast = new WeatherSpec.Daily(); final WeatherSpec.Daily gbForecast = new WeatherSpec.Daily();
gbForecast.minTemp = 10 + i + 273; gbForecast.setMinTemp(10 + i + 273);
gbForecast.maxTemp = 25 + i + 273; gbForecast.setMaxTemp(25 + i + 273);
gbForecast.conditionCode = 800; // clear gbForecast.setConditionCode(800); // clear
weatherSpec.forecasts.add(gbForecast); weatherSpec.getForecasts().add(gbForecast);
} }
Weather.INSTANCE.setWeatherSpec(new ArrayList<>(Collections.singletonList(weatherSpec))); Weather.INSTANCE.setWeatherSpec(new ArrayList<>(Collections.singletonList(weatherSpec)));
@@ -414,7 +414,7 @@ public class DebugActivity extends AbstractGBActivity {
final String[] weatherLocations = new String[weatherSpecs.size()]; final String[] weatherLocations = new String[weatherSpecs.size()];
for (int i = 0; i < weatherSpecs.size(); i++) { for (int i = 0; i < weatherSpecs.size(); i++) {
weatherLocations[i] = weatherSpecs.get(i).location; weatherLocations[i] = weatherSpecs.get(i).getLocation();
} }
new MaterialAlertDialogBuilder(DebugActivity.this) new MaterialAlertDialogBuilder(DebugActivity.this)
@@ -1160,82 +1160,82 @@ public class DebugActivity extends AbstractGBActivity {
if (weatherSpec == null) if (weatherSpec == null)
return "Weather cache is empty."; return "Weather cache is empty.";
builder.append("Location: ").append(weatherSpec.location).append("\n"); builder.append("Location: ").append(weatherSpec.getLocation()).append("\n");
builder.append("Timestamp: ").append(weatherSpec.timestamp).append("\n"); builder.append("Timestamp: ").append(weatherSpec.getTimestamp()).append("\n");
builder.append("Current Temp: ").append(weatherSpec.currentTemp).append(" K\n"); builder.append("Current Temp: ").append(weatherSpec.getCurrentTemp()).append(" K\n");
builder.append("Max Temp: ").append(weatherSpec.todayMaxTemp).append(" K\n"); builder.append("Max Temp: ").append(weatherSpec.getTodayMaxTemp()).append(" K\n");
builder.append("Min Temp: ").append(weatherSpec.todayMinTemp).append(" K\n"); builder.append("Min Temp: ").append(weatherSpec.getTodayMinTemp()).append(" K\n");
builder.append("Condition: ").append(weatherSpec.currentCondition).append("\n"); builder.append("Condition: ").append(weatherSpec.getCurrentCondition()).append("\n");
builder.append("Condition Code: ").append(weatherSpec.currentConditionCode).append("\n"); builder.append("Condition Code: ").append(weatherSpec.getCurrentConditionCode()).append("\n");
builder.append("Humidity: ").append(weatherSpec.currentHumidity).append("\n"); builder.append("Humidity: ").append(weatherSpec.getCurrentHumidity()).append("\n");
builder.append("Wind Speed: ").append(weatherSpec.windSpeed).append(" kmph\n"); builder.append("Wind Speed: ").append(weatherSpec.getWindSpeed()).append(" kmph\n");
builder.append("Wind Direction: ").append(weatherSpec.windDirection).append(" deg\n"); builder.append("Wind Direction: ").append(weatherSpec.getWindDirection()).append(" deg\n");
builder.append("UV Index: ").append(weatherSpec.uvIndex).append("\n"); builder.append("UV Index: ").append(weatherSpec.getUvIndex()).append("\n");
builder.append("Precip Probability: ").append(weatherSpec.precipProbability).append(" %\n"); builder.append("Precip Probability: ").append(weatherSpec.getPrecipProbability()).append(" %\n");
builder.append("Dew Point: ").append(weatherSpec.dewPoint).append(" K\n"); builder.append("Dew Point: ").append(weatherSpec.getDewPoint()).append(" K\n");
builder.append("Pressure: ").append(weatherSpec.pressure).append(" mb\n"); builder.append("Pressure: ").append(weatherSpec.getPressure()).append(" mb\n");
builder.append("Cloud Cover: ").append(weatherSpec.cloudCover).append(" %\n"); builder.append("Cloud Cover: ").append(weatherSpec.getCloudCover()).append(" %\n");
builder.append("Visibility: ").append(weatherSpec.visibility).append(" m\n"); builder.append("Visibility: ").append(weatherSpec.getVisibility()).append(" m\n");
builder.append("Sun Rise: ").append(sdf.format(new Date(weatherSpec.sunRise * 1000L))).append("\n"); builder.append("Sun Rise: ").append(sdf.format(new Date(weatherSpec.getSunRise() * 1000L))).append("\n");
builder.append("Sun Set: ").append(sdf.format(new Date(weatherSpec.sunSet * 1000L))).append("\n"); builder.append("Sun Set: ").append(sdf.format(new Date(weatherSpec.getSunSet() * 1000L))).append("\n");
builder.append("Moon Rise: ").append(sdf.format(new Date(weatherSpec.moonRise * 1000L))).append("\n"); builder.append("Moon Rise: ").append(sdf.format(new Date(weatherSpec.getMoonRise() * 1000L))).append("\n");
builder.append("Moon Set: ").append(sdf.format(new Date(weatherSpec.moonSet * 1000L))).append("\n"); builder.append("Moon Set: ").append(sdf.format(new Date(weatherSpec.getMoonSet() * 1000L))).append("\n");
builder.append("Moon Phase: ").append(weatherSpec.moonPhase).append(" deg\n"); builder.append("Moon Phase: ").append(weatherSpec.getMoonPhase()).append(" deg\n");
builder.append("Latitude: ").append(weatherSpec.latitude).append("\n"); builder.append("Latitude: ").append(weatherSpec.getLatitude()).append("\n");
builder.append("Longitude: ").append(weatherSpec.longitude).append("\n"); builder.append("Longitude: ").append(weatherSpec.getLongitude()).append("\n");
builder.append("Feels Like Temp: ").append(weatherSpec.feelsLikeTemp).append(" K\n"); builder.append("Feels Like Temp: ").append(weatherSpec.getFeelsLikeTemp()).append(" K\n");
builder.append("Is Current Location: ").append(weatherSpec.isCurrentLocation).append("\n"); builder.append("Is Current Location: ").append(weatherSpec.getIsCurrentLocation()).append("\n");
if (weatherSpec.airQuality != null) { if (weatherSpec.getAirQuality() != null) {
builder.append("Air Quality aqi: ").append(weatherSpec.airQuality.aqi).append("\n"); builder.append("Air Quality aqi: ").append(weatherSpec.getAirQuality().getAqi()).append("\n");
builder.append("Air Quality co: ").append(weatherSpec.airQuality.co).append("\n"); builder.append("Air Quality co: ").append(weatherSpec.getAirQuality().getCo()).append("\n");
builder.append("Air Quality no2: ").append(weatherSpec.airQuality.no2).append("\n"); builder.append("Air Quality no2: ").append(weatherSpec.getAirQuality().getNo2()).append("\n");
builder.append("Air Quality o3: ").append(weatherSpec.airQuality.o3).append("\n"); builder.append("Air Quality o3: ").append(weatherSpec.getAirQuality().getO3()).append("\n");
builder.append("Air Quality pm10: ").append(weatherSpec.airQuality.pm10).append("\n"); builder.append("Air Quality pm10: ").append(weatherSpec.getAirQuality().getPm10()).append("\n");
builder.append("Air Quality pm25: ").append(weatherSpec.airQuality.pm25).append("\n"); builder.append("Air Quality pm25: ").append(weatherSpec.getAirQuality().getPm25()).append("\n");
builder.append("Air Quality so2: ").append(weatherSpec.airQuality.so2).append("\n"); builder.append("Air Quality so2: ").append(weatherSpec.getAirQuality().getSo2()).append("\n");
builder.append("Air Quality coAqi: ").append(weatherSpec.airQuality.coAqi).append("\n"); builder.append("Air Quality coAqi: ").append(weatherSpec.getAirQuality().getCoAqi()).append("\n");
builder.append("Air Quality no2Aqi: ").append(weatherSpec.airQuality.no2Aqi).append("\n"); builder.append("Air Quality no2Aqi: ").append(weatherSpec.getAirQuality().getNo2Aqi()).append("\n");
builder.append("Air Quality o3Aqi: ").append(weatherSpec.airQuality.o3Aqi).append("\n"); builder.append("Air Quality o3Aqi: ").append(weatherSpec.getAirQuality().getO3Aqi()).append("\n");
builder.append("Air Quality pm10Aqi: ").append(weatherSpec.airQuality.pm10Aqi).append("\n"); builder.append("Air Quality pm10Aqi: ").append(weatherSpec.getAirQuality().getPm10Aqi()).append("\n");
builder.append("Air Quality pm25Aqi: ").append(weatherSpec.airQuality.pm25Aqi).append("\n"); builder.append("Air Quality pm25Aqi: ").append(weatherSpec.getAirQuality().getPm25Aqi()).append("\n");
builder.append("Air Quality so2Aqi: ").append(weatherSpec.airQuality.so2Aqi).append("\n"); builder.append("Air Quality so2Aqi: ").append(weatherSpec.getAirQuality().getSo2Aqi()).append("\n");
} else { } else {
builder.append("Air Quality: null\n"); builder.append("Air Quality: null\n");
} }
int i = 0; int i = 0;
for (final WeatherSpec.Daily daily : weatherSpec.forecasts) { for (final WeatherSpec.Daily daily : weatherSpec.getForecasts()) {
builder.append("-------------\n"); builder.append("-------------\n");
builder.append("-->Day ").append(i++).append("\n"); builder.append("-->Day ").append(i++).append("\n");
builder.append("Max Temp: ").append(daily.maxTemp).append(" K\n"); builder.append("Max Temp: ").append(daily.getMaxTemp()).append(" K\n");
builder.append("Min Temp: ").append(daily.minTemp).append(" K\n"); builder.append("Min Temp: ").append(daily.getMinTemp()).append(" K\n");
builder.append("Condition Code: ").append(daily.conditionCode).append("\n"); builder.append("Condition Code: ").append(daily.getConditionCode()).append("\n");
builder.append("Humidity: ").append(daily.humidity).append("\n"); builder.append("Humidity: ").append(daily.getHumidity()).append("\n");
builder.append("Wind Speed: ").append(daily.windSpeed).append(" kmph\n"); builder.append("Wind Speed: ").append(daily.getWindSpeed()).append(" kmph\n");
builder.append("Wind Direction: ").append(daily.windDirection).append(" deg\n"); builder.append("Wind Direction: ").append(daily.getWindDirection()).append(" deg\n");
builder.append("UV Index: ").append(daily.uvIndex).append("\n"); builder.append("UV Index: ").append(daily.getUvIndex()).append("\n");
builder.append("Precip Probability: ").append(daily.precipProbability).append(" %\n"); builder.append("Precip Probability: ").append(daily.getPrecipProbability()).append(" %\n");
builder.append("Sun Rise: ").append(sdf.format(new Date(daily.sunRise * 1000L))).append("\n"); builder.append("Sun Rise: ").append(sdf.format(new Date(daily.getSunRise() * 1000L))).append("\n");
builder.append("Sun Set: ").append(sdf.format(new Date(daily.sunSet * 1000L))).append("\n"); builder.append("Sun Set: ").append(sdf.format(new Date(daily.getSunSet() * 1000L))).append("\n");
builder.append("Moon Rise: ").append(sdf.format(new Date(daily.moonRise * 1000L))).append("\n"); builder.append("Moon Rise: ").append(sdf.format(new Date(daily.getMoonRise() * 1000L))).append("\n");
builder.append("Moon Set: ").append(sdf.format(new Date(daily.moonSet * 1000L))).append("\n"); builder.append("Moon Set: ").append(sdf.format(new Date(daily.getMoonSet() * 1000L))).append("\n");
builder.append("Moon Phase: ").append(daily.moonPhase).append(" deg\n"); builder.append("Moon Phase: ").append(daily.getMoonPhase()).append(" deg\n");
if (daily.airQuality != null) { if (daily.getAirQuality() != null) {
builder.append("Air Quality aqi: ").append(daily.airQuality.aqi).append("\n"); builder.append("Air Quality aqi: ").append(daily.getAirQuality().getAqi()).append("\n");
builder.append("Air Quality co: ").append(daily.airQuality.co).append("\n"); builder.append("Air Quality co: ").append(daily.getAirQuality().getCo()).append("\n");
builder.append("Air Quality no2: ").append(daily.airQuality.no2).append("\n"); builder.append("Air Quality no2: ").append(daily.getAirQuality().getNo2()).append("\n");
builder.append("Air Quality o3: ").append(daily.airQuality.o3).append("\n"); builder.append("Air Quality o3: ").append(daily.getAirQuality().getO3()).append("\n");
builder.append("Air Quality pm10: ").append(daily.airQuality.pm10).append("\n"); builder.append("Air Quality pm10: ").append(daily.getAirQuality().getPm10()).append("\n");
builder.append("Air Quality pm25: ").append(daily.airQuality.pm25).append("\n"); builder.append("Air Quality pm25: ").append(daily.getAirQuality().getPm25()).append("\n");
builder.append("Air Quality so2: ").append(daily.airQuality.so2).append("\n"); builder.append("Air Quality so2: ").append(daily.getAirQuality().getSo2()).append("\n");
builder.append("Air Quality coAqi: ").append(daily.airQuality.coAqi).append("\n"); builder.append("Air Quality coAqi: ").append(daily.getAirQuality().getCoAqi()).append("\n");
builder.append("Air Quality no2Aqi: ").append(daily.airQuality.no2Aqi).append("\n"); builder.append("Air Quality no2Aqi: ").append(daily.getAirQuality().getNo2Aqi()).append("\n");
builder.append("Air Quality o3Aqi: ").append(daily.airQuality.o3Aqi).append("\n"); builder.append("Air Quality o3Aqi: ").append(daily.getAirQuality().getO3Aqi()).append("\n");
builder.append("Air Quality pm10Aqi: ").append(daily.airQuality.pm10Aqi).append("\n"); builder.append("Air Quality pm10Aqi: ").append(daily.getAirQuality().getPm10Aqi()).append("\n");
builder.append("Air Quality pm25Aqi: ").append(daily.airQuality.pm25Aqi).append("\n"); builder.append("Air Quality pm25Aqi: ").append(daily.getAirQuality().getPm25Aqi()).append("\n");
builder.append("Air Quality so2Aqi: ").append(daily.airQuality.so2Aqi).append("\n"); builder.append("Air Quality so2Aqi: ").append(daily.getAirQuality().getSo2Aqi()).append("\n");
} else { } else {
builder.append("Air Quality: null\n"); builder.append("Air Quality: null\n");
} }
@@ -1243,16 +1243,16 @@ public class DebugActivity extends AbstractGBActivity {
builder.append("=============\n"); builder.append("=============\n");
for (final WeatherSpec.Hourly hourly : weatherSpec.hourly) { for (final WeatherSpec.Hourly hourly : weatherSpec.getHourly()) {
builder.append("-------------\n"); builder.append("-------------\n");
builder.append("-->Hour: ").append(sdf.format(new Date(hourly.timestamp * 1000L))).append("\n"); builder.append("-->Hour: ").append(sdf.format(new Date(hourly.getTimestamp() * 1000L))).append("\n");
builder.append("Max Temp: ").append(hourly.temp).append(" K\n"); builder.append("Max Temp: ").append(hourly.getTemp()).append(" K\n");
builder.append("Condition Code: ").append(hourly.conditionCode).append("\n"); builder.append("Condition Code: ").append(hourly.getConditionCode()).append("\n");
builder.append("Humidity: ").append(hourly.humidity).append("\n"); builder.append("Humidity: ").append(hourly.getHumidity()).append("\n");
builder.append("Wind Speed: ").append(hourly.windSpeed).append(" kmph\n"); builder.append("Wind Speed: ").append(hourly.getWindSpeed()).append(" kmph\n");
builder.append("Wind Direction: ").append(hourly.windDirection).append(" deg\n"); builder.append("Wind Direction: ").append(hourly.getWindDirection()).append(" deg\n");
builder.append("UV Index: ").append(hourly.uvIndex).append("\n"); builder.append("UV Index: ").append(hourly.getUvIndex()).append("\n");
builder.append("Precip Probability: ").append(hourly.precipProbability).append(" %\n"); builder.append("Precip Probability: ").append(hourly.getPrecipProbability()).append(" %\n");
} }
return builder.toString(); return builder.toString();
@@ -49,9 +49,9 @@ public class AsteroidOSWeather {
* @param forecast A day in the weather forecast * @param forecast A day in the weather forecast
*/ */
public Day(WeatherSpec.Daily forecast) { public Day(WeatherSpec.Daily forecast) {
minTemp = forecast.minTemp; minTemp = forecast.getMinTemp();
maxTemp = forecast.maxTemp; maxTemp = forecast.getMaxTemp();
condition = forecast.conditionCode; condition = forecast.getConditionCode();
} }
/** /**
@@ -59,9 +59,9 @@ public class AsteroidOSWeather {
* @param spec The weather spec itself * @param spec The weather spec itself
*/ */
public Day(WeatherSpec spec) { public Day(WeatherSpec spec) {
minTemp = spec.todayMinTemp; minTemp = spec.getTodayMinTemp();
maxTemp = spec.todayMaxTemp; maxTemp = spec.getTodayMaxTemp();
condition = spec.currentConditionCode; condition = spec.getCurrentConditionCode();
} }
} }
@@ -80,10 +80,10 @@ public class AsteroidOSWeather {
* @param spec The WeatherSpec given to the device support class * @param spec The WeatherSpec given to the device support class
*/ */
public AsteroidOSWeather(WeatherSpec spec) { public AsteroidOSWeather(WeatherSpec spec) {
cityName = spec.location; cityName = spec.getLocation();
days.add(new Day(spec)); days.add(new Day(spec));
for (int i = 1; i < spec.forecasts.size(); i++) { for (int i = 1; i < spec.getForecasts().size(); i++) {
days.add(new Day(spec.forecasts.get(i - 1))); days.add(new Day(spec.getForecasts().get(i - 1)));
} }
} }
@@ -34,14 +34,14 @@ public class MoyoungWeatherForecast {
} }
public MoyoungWeatherForecast(WeatherSpec.Daily forecast) { public MoyoungWeatherForecast(WeatherSpec.Daily forecast) {
conditionId = MoyoungConstants.openWeatherConditionToMoyoungConditionId(forecast.conditionCode); conditionId = MoyoungConstants.openWeatherConditionToMoyoungConditionId(forecast.getConditionCode());
String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric)); String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric));
if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) { if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) {
minTemp = (byte) WeatherUtils.celsiusToFahrenheit(forecast.minTemp - 273); // Kelvin -> Fahrenheit minTemp = (byte) WeatherUtils.celsiusToFahrenheit(forecast.getMinTemp() - 273); // Kelvin -> Fahrenheit
maxTemp = (byte) WeatherUtils.celsiusToFahrenheit(forecast.maxTemp - 273); // Kelvin -> Fahrenheit maxTemp = (byte) WeatherUtils.celsiusToFahrenheit(forecast.getMaxTemp() - 273); // Kelvin -> Fahrenheit
} else { } else {
minTemp = (byte) (forecast.minTemp - 273); // Kelvin -> Celcius minTemp = (byte) (forecast.getMinTemp() - 273); // Kelvin -> Celcius
maxTemp = (byte) (forecast.maxTemp - 273); // Kelvin -> Celcius maxTemp = (byte) (forecast.getMaxTemp() - 273); // Kelvin -> Celcius
} }
} }
} }
@@ -57,15 +57,15 @@ public class MoyoungWeatherToday {
} }
public MoyoungWeatherToday(WeatherSpec weatherSpec) { public MoyoungWeatherToday(WeatherSpec weatherSpec) {
conditionId = MoyoungConstants.openWeatherConditionToMoyoungConditionId(weatherSpec.currentConditionCode); conditionId = MoyoungConstants.openWeatherConditionToMoyoungConditionId(weatherSpec.getCurrentConditionCode());
String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric)); String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric));
if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) { if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) {
currentTemp = (byte) WeatherUtils.celsiusToFahrenheit(weatherSpec.currentTemp - 273); // Kelvin -> Fahrenheit currentTemp = (byte) WeatherUtils.celsiusToFahrenheit(weatherSpec.getCurrentTemp() - 273); // Kelvin -> Fahrenheit
} else { } else {
currentTemp = (byte) (weatherSpec.currentTemp - 273); // Kelvin -> Celcius currentTemp = (byte) (weatherSpec.getCurrentTemp() - 273); // Kelvin -> Celcius
} }
pm25 = null; pm25 = null;
lunar_or_festival = StringUtils.pad("", 4); lunar_or_festival = StringUtils.pad("", 4);
city = StringUtils.pad(weatherSpec.location.substring(0, 4), 4); city = StringUtils.pad(weatherSpec.getLocation().substring(0, 4), 4);
} }
} }
@@ -260,20 +260,20 @@ public class SMAQ2OSSSupport extends AbstractBTLESingleDeviceSupport {
SMAQ2OSSProtos.SetWeather.Builder setWeather= SMAQ2OSSProtos.SetWeather.newBuilder(); SMAQ2OSSProtos.SetWeather.Builder setWeather= SMAQ2OSSProtos.SetWeather.newBuilder();
setWeather.setTimestamp(weatherSpec.timestamp); setWeather.setTimestamp(weatherSpec.getTimestamp());
setWeather.setCondition(weatherSpec.currentConditionCode); setWeather.setCondition(weatherSpec.getCurrentConditionCode());
setWeather.setTemperature(weatherSpec.currentTemp-273); setWeather.setTemperature(weatherSpec.getCurrentTemp() -273);
setWeather.setTemperatureMin(weatherSpec.todayMinTemp-273); setWeather.setTemperatureMin(weatherSpec.getTodayMinTemp() -273);
setWeather.setTemperatureMax(weatherSpec.todayMaxTemp-273); setWeather.setTemperatureMax(weatherSpec.getTodayMaxTemp() -273);
setWeather.setHumidity(weatherSpec.currentHumidity); setWeather.setHumidity(weatherSpec.getCurrentHumidity());
for (WeatherSpec.Daily f:weatherSpec.forecasts) { for (WeatherSpec.Daily f: weatherSpec.getForecasts()) {
SMAQ2OSSProtos.Forecast.Builder fproto = SMAQ2OSSProtos.Forecast.newBuilder(); SMAQ2OSSProtos.Forecast.Builder fproto = SMAQ2OSSProtos.Forecast.newBuilder();
fproto.setCondition(f.conditionCode); fproto.setCondition(f.getConditionCode());
fproto.setTemperatureMin(f.minTemp-273); fproto.setTemperatureMin(f.getMinTemp() -273);
fproto.setTemperatureMax(f.maxTemp-273); fproto.setTemperatureMax(f.getMaxTemp() -273);
setWeather.addForecasts(fproto); setWeather.addForecasts(fproto);
} }
@@ -140,43 +140,43 @@ public class CMWeatherReceiver extends BroadcastReceiver implements CMWeatherMan
if (weatherInfo != null) { if (weatherInfo != null) {
LOG.info("weather: " + weatherInfo.toString()); LOG.info("weather: " + weatherInfo.toString());
WeatherSpec weatherSpec = new WeatherSpec(); WeatherSpec weatherSpec = new WeatherSpec();
weatherSpec.timestamp = (int) (weatherInfo.getTimestamp() / 1000); weatherSpec.setTimestamp((int) (weatherInfo.getTimestamp() / 1000));
weatherSpec.location = weatherInfo.getCity(); weatherSpec.setLocation(weatherInfo.getCity());
if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) { if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) {
weatherSpec.currentTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTemperature()) + 273; weatherSpec.setCurrentTemp((int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTemperature()) + 273);
weatherSpec.todayMaxTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysHigh()) + 273; weatherSpec.setTodayMaxTemp((int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysHigh()) + 273);
weatherSpec.todayMinTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysLow()) + 273; weatherSpec.setTodayMinTemp((int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysLow()) + 273);
} else { } else {
weatherSpec.currentTemp = (int) weatherInfo.getTemperature() + 273; weatherSpec.setCurrentTemp((int) weatherInfo.getTemperature() + 273);
weatherSpec.todayMaxTemp = (int) weatherInfo.getTodaysHigh() + 273; weatherSpec.setTodayMaxTemp((int) weatherInfo.getTodaysHigh() + 273);
weatherSpec.todayMinTemp = (int) weatherInfo.getTodaysLow() + 273; weatherSpec.setTodayMinTemp((int) weatherInfo.getTodaysLow() + 273);
} }
if (weatherInfo.getWindSpeedUnit() == MPH) { if (weatherInfo.getWindSpeedUnit() == MPH) {
weatherSpec.windSpeed = (float) weatherInfo.getWindSpeed() * 1.609344f; weatherSpec.setWindSpeed((float) weatherInfo.getWindSpeed() * 1.609344f);
} else { } else {
weatherSpec.windSpeed = (float) weatherInfo.getWindSpeed(); weatherSpec.setWindSpeed((float) weatherInfo.getWindSpeed());
} }
weatherSpec.windDirection = (int) weatherInfo.getWindDirection(); weatherSpec.setWindDirection((int) weatherInfo.getWindDirection());
weatherSpec.currentConditionCode = WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(CMtoYahooCondintion(weatherInfo.getConditionCode())); weatherSpec.setCurrentConditionCode(WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(CMtoYahooCondintion(weatherInfo.getConditionCode())));
weatherSpec.currentCondition = WeatherMapper.INSTANCE.getConditionString(mContext, weatherSpec.currentConditionCode); weatherSpec.setCurrentCondition(WeatherMapper.INSTANCE.getConditionString(mContext, weatherSpec.getCurrentConditionCode()));
weatherSpec.currentHumidity = (int) weatherInfo.getHumidity(); weatherSpec.setCurrentHumidity((int) weatherInfo.getHumidity());
weatherSpec.forecasts = new ArrayList<>(); weatherSpec.setForecasts(new ArrayList<>());
List<WeatherInfo.DayForecast> forecasts = weatherInfo.getForecasts(); List<WeatherInfo.DayForecast> forecasts = weatherInfo.getForecasts();
for (int i = 1; i < forecasts.size(); i++) { for (int i = 1; i < forecasts.size(); i++) {
WeatherInfo.DayForecast cmForecast = forecasts.get(i); WeatherInfo.DayForecast cmForecast = forecasts.get(i);
WeatherSpec.Daily gbForecast = new WeatherSpec.Daily(); WeatherSpec.Daily gbForecast = new WeatherSpec.Daily();
if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) { if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) {
gbForecast.maxTemp = (int) WeatherUtils.fahrenheitToCelsius(cmForecast.getHigh()) + 273; gbForecast.setMaxTemp((int) WeatherUtils.fahrenheitToCelsius(cmForecast.getHigh()) + 273);
gbForecast.minTemp = (int) WeatherUtils.fahrenheitToCelsius(cmForecast.getLow()) + 273; gbForecast.setMinTemp((int) WeatherUtils.fahrenheitToCelsius(cmForecast.getLow()) + 273);
} else { } else {
gbForecast.maxTemp = (int) cmForecast.getHigh() + 273; gbForecast.setMaxTemp((int) cmForecast.getHigh() + 273);
gbForecast.minTemp = (int) cmForecast.getLow() + 273; gbForecast.setMinTemp((int) cmForecast.getLow() + 273);
} }
gbForecast.conditionCode = WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(CMtoYahooCondintion(cmForecast.getConditionCode())); gbForecast.setConditionCode(WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(CMtoYahooCondintion(cmForecast.getConditionCode())));
weatherSpec.forecasts.add(gbForecast); weatherSpec.getForecasts().add(gbForecast);
} }
ArrayList<WeatherSpec> weatherSpecs = new ArrayList<>(Collections.singletonList(weatherSpec)); ArrayList<WeatherSpec> weatherSpecs = new ArrayList<>(Collections.singletonList(weatherSpec));
Weather.INSTANCE.setWeatherSpec(weatherSpecs); Weather.INSTANCE.setWeatherSpec(weatherSpecs);
@@ -94,86 +94,86 @@ public class GenericWeatherReceiver extends BroadcastReceiver {
private WeatherSpec weatherFromJson(final JSONObject weatherJson) throws JSONException { private WeatherSpec weatherFromJson(final JSONObject weatherJson) throws JSONException {
final WeatherSpec weatherSpec = new WeatherSpec(); final WeatherSpec weatherSpec = new WeatherSpec();
weatherSpec.timestamp = safelyGet(weatherJson, Integer.class, "timestamp", (int) (System.currentTimeMillis() / 1000)); weatherSpec.setTimestamp(safelyGet(weatherJson, Integer.class, "timestamp", (int) (System.currentTimeMillis() / 1000)));
weatherSpec.location = safelyGet(weatherJson, String.class, "location", ""); weatherSpec.setLocation(safelyGet(weatherJson, String.class, "location", ""));
weatherSpec.currentTemp = safelyGet(weatherJson, Integer.class, "currentTemp", 0); weatherSpec.setCurrentTemp(safelyGet(weatherJson, Integer.class, "currentTemp", 0));
weatherSpec.todayMinTemp = safelyGet(weatherJson, Integer.class, "todayMinTemp", 0); weatherSpec.setTodayMinTemp(safelyGet(weatherJson, Integer.class, "todayMinTemp", 0));
weatherSpec.todayMaxTemp = safelyGet(weatherJson, Integer.class, "todayMaxTemp", 0); weatherSpec.setTodayMaxTemp(safelyGet(weatherJson, Integer.class, "todayMaxTemp", 0));
weatherSpec.currentCondition = safelyGet(weatherJson, String.class, "currentCondition", ""); weatherSpec.setCurrentCondition(safelyGet(weatherJson, String.class, "currentCondition", ""));
weatherSpec.currentConditionCode = safelyGet(weatherJson, Integer.class, "currentConditionCode", 0); weatherSpec.setCurrentConditionCode(safelyGet(weatherJson, Integer.class, "currentConditionCode", 0));
weatherSpec.currentHumidity = safelyGet(weatherJson, Integer.class, "currentHumidity", 0); weatherSpec.setCurrentHumidity(safelyGet(weatherJson, Integer.class, "currentHumidity", 0));
weatherSpec.windSpeed = safelyGet(weatherJson, Number.class, "windSpeed", 0d).floatValue(); weatherSpec.setWindSpeed(safelyGet(weatherJson, Number.class, "windSpeed", 0d).floatValue());
weatherSpec.windDirection = safelyGet(weatherJson, Integer.class, "windDirection", 0); weatherSpec.setWindDirection(safelyGet(weatherJson, Integer.class, "windDirection", 0));
weatherSpec.uvIndex = safelyGet(weatherJson, Number.class, "uvIndex", 0d).floatValue(); weatherSpec.setUvIndex(safelyGet(weatherJson, Number.class, "uvIndex", 0d).floatValue());
weatherSpec.precipProbability = safelyGet(weatherJson, Integer.class, "precipProbability", 0); weatherSpec.setPrecipProbability(safelyGet(weatherJson, Integer.class, "precipProbability", 0));
weatherSpec.dewPoint = safelyGet(weatherJson, Integer.class, "dewPoint", 0); weatherSpec.setDewPoint(safelyGet(weatherJson, Integer.class, "dewPoint", 0));
weatherSpec.pressure = safelyGet(weatherJson, Number.class, "pressure", 0).floatValue(); weatherSpec.setPressure(safelyGet(weatherJson, Number.class, "pressure", 0).floatValue());
weatherSpec.cloudCover = safelyGet(weatherJson, Integer.class, "cloudCover", 0); weatherSpec.setCloudCover(safelyGet(weatherJson, Integer.class, "cloudCover", 0));
weatherSpec.visibility = safelyGet(weatherJson, Number.class, "visibility", 0).floatValue(); weatherSpec.setVisibility(safelyGet(weatherJson, Number.class, "visibility", 0).floatValue());
weatherSpec.sunRise = safelyGet(weatherJson, Integer.class, "sunRise", 0); weatherSpec.setSunRise(safelyGet(weatherJson, Integer.class, "sunRise", 0));
weatherSpec.sunSet = safelyGet(weatherJson, Integer.class, "sunSet", 0); weatherSpec.setSunSet(safelyGet(weatherJson, Integer.class, "sunSet", 0));
weatherSpec.moonRise = safelyGet(weatherJson, Integer.class, "moonRise", 0); weatherSpec.setMoonRise(safelyGet(weatherJson, Integer.class, "moonRise", 0));
weatherSpec.moonSet = safelyGet(weatherJson, Integer.class, "moonSet", 0); weatherSpec.setMoonSet(safelyGet(weatherJson, Integer.class, "moonSet", 0));
weatherSpec.moonPhase = safelyGet(weatherJson, Integer.class, "moonPhase", 0); weatherSpec.setMoonPhase(safelyGet(weatherJson, Integer.class, "moonPhase", 0));
weatherSpec.latitude = safelyGet(weatherJson, Number.class, "latitude", 0).floatValue(); weatherSpec.setLatitude(safelyGet(weatherJson, Number.class, "latitude", 0).floatValue());
weatherSpec.longitude = safelyGet(weatherJson, Number.class, "longitude", 0).floatValue(); weatherSpec.setLongitude(safelyGet(weatherJson, Number.class, "longitude", 0).floatValue());
weatherSpec.feelsLikeTemp = safelyGet(weatherJson, Integer.class, "feelsLikeTemp", 0); weatherSpec.setFeelsLikeTemp(safelyGet(weatherJson, Integer.class, "feelsLikeTemp", 0));
weatherSpec.isCurrentLocation = safelyGet(weatherJson, Integer.class, "isCurrentLocation", -1); weatherSpec.setIsCurrentLocation(safelyGet(weatherJson, Integer.class, "isCurrentLocation", -1));
if (weatherJson.has("airQuality")) { if (weatherJson.has("airQuality")) {
weatherSpec.airQuality = toAirQuality(weatherJson.getJSONObject("airQuality")); weatherSpec.setAirQuality(toAirQuality(weatherJson.getJSONObject("airQuality")));
} }
if (weatherJson.has("forecasts")) { if (weatherJson.has("forecasts")) {
final JSONArray forecastArray = weatherJson.getJSONArray("forecasts"); final JSONArray forecastArray = weatherJson.getJSONArray("forecasts");
weatherSpec.forecasts = new ArrayList<>(); weatherSpec.setForecasts(new ArrayList<>());
for (int i = 0, l = forecastArray.length(); i < l; i++) { for (int i = 0, l = forecastArray.length(); i < l; i++) {
final JSONObject forecastJson = forecastArray.getJSONObject(i); final JSONObject forecastJson = forecastArray.getJSONObject(i);
final WeatherSpec.Daily forecast = new WeatherSpec.Daily(); final WeatherSpec.Daily forecast = new WeatherSpec.Daily();
forecast.conditionCode = safelyGet(forecastJson, Integer.class, "conditionCode", 0); forecast.setConditionCode(safelyGet(forecastJson, Integer.class, "conditionCode", 0));
forecast.humidity = safelyGet(forecastJson, Integer.class, "humidity", 0); forecast.setHumidity(safelyGet(forecastJson, Integer.class, "humidity", 0));
forecast.maxTemp = safelyGet(forecastJson, Integer.class, "maxTemp", 0); forecast.setMaxTemp(safelyGet(forecastJson, Integer.class, "maxTemp", 0));
forecast.minTemp = safelyGet(forecastJson, Integer.class, "minTemp", 0); forecast.setMinTemp(safelyGet(forecastJson, Integer.class, "minTemp", 0));
forecast.windSpeed = safelyGet(forecastJson, Number.class, "windSpeed", 0).floatValue(); forecast.setWindSpeed(safelyGet(forecastJson, Number.class, "windSpeed", 0).floatValue());
forecast.windDirection = safelyGet(forecastJson, Integer.class, "windDirection", 0); forecast.setWindDirection(safelyGet(forecastJson, Integer.class, "windDirection", 0));
forecast.uvIndex = safelyGet(forecastJson, Number.class, "uvIndex", 0d).floatValue(); forecast.setUvIndex(safelyGet(forecastJson, Number.class, "uvIndex", 0d).floatValue());
forecast.precipProbability = safelyGet(forecastJson, Integer.class, "precipProbability", 0); forecast.setPrecipProbability(safelyGet(forecastJson, Integer.class, "precipProbability", 0));
forecast.sunRise = safelyGet(forecastJson, Integer.class, "sunRise", 0); forecast.setSunRise(safelyGet(forecastJson, Integer.class, "sunRise", 0));
forecast.sunSet = safelyGet(forecastJson, Integer.class, "sunSet", 0); forecast.setSunSet(safelyGet(forecastJson, Integer.class, "sunSet", 0));
forecast.moonRise = safelyGet(forecastJson, Integer.class, "moonRise", 0); forecast.setMoonRise(safelyGet(forecastJson, Integer.class, "moonRise", 0));
forecast.moonSet = safelyGet(forecastJson, Integer.class, "moonSet", 0); forecast.setMoonSet(safelyGet(forecastJson, Integer.class, "moonSet", 0));
forecast.moonPhase = safelyGet(forecastJson, Integer.class, "moonPhase", 0); forecast.setMoonPhase(safelyGet(forecastJson, Integer.class, "moonPhase", 0));
if (forecastJson.has("airQuality")) { if (forecastJson.has("airQuality")) {
forecast.airQuality = toAirQuality(forecastJson.getJSONObject("airQuality")); forecast.setAirQuality(toAirQuality(forecastJson.getJSONObject("airQuality")));
} }
weatherSpec.forecasts.add(forecast); weatherSpec.getForecasts().add(forecast);
} }
} }
if (weatherJson.has("hourly")) { if (weatherJson.has("hourly")) {
final JSONArray forecastArray = weatherJson.getJSONArray("hourly"); final JSONArray forecastArray = weatherJson.getJSONArray("hourly");
weatherSpec.hourly = new ArrayList<>(); weatherSpec.setHourly(new ArrayList<>());
for (int i = 0, l = forecastArray.length(); i < l; i++) { for (int i = 0, l = forecastArray.length(); i < l; i++) {
final JSONObject forecastJson = forecastArray.getJSONObject(i); final JSONObject forecastJson = forecastArray.getJSONObject(i);
final WeatherSpec.Hourly forecast = new WeatherSpec.Hourly(); final WeatherSpec.Hourly forecast = new WeatherSpec.Hourly();
forecast.timestamp = safelyGet(forecastJson, Integer.class, "timestamp", 0); forecast.setTimestamp(safelyGet(forecastJson, Integer.class, "timestamp", 0));
forecast.temp = safelyGet(forecastJson, Integer.class, "temp", 0); forecast.setTemp(safelyGet(forecastJson, Integer.class, "temp", 0));
forecast.conditionCode = safelyGet(forecastJson, Integer.class, "conditionCode", 0); forecast.setConditionCode(safelyGet(forecastJson, Integer.class, "conditionCode", 0));
forecast.humidity = safelyGet(forecastJson, Integer.class, "humidity", 0); forecast.setHumidity(safelyGet(forecastJson, Integer.class, "humidity", 0));
forecast.windSpeed = safelyGet(forecastJson, Number.class, "windSpeed", 0).floatValue(); forecast.setWindSpeed(safelyGet(forecastJson, Number.class, "windSpeed", 0).floatValue());
forecast.windDirection = safelyGet(forecastJson, Integer.class, "windDirection", 0); forecast.setWindDirection(safelyGet(forecastJson, Integer.class, "windDirection", 0));
forecast.uvIndex = safelyGet(forecastJson, Number.class, "uvIndex", 0d).floatValue(); forecast.setUvIndex(safelyGet(forecastJson, Number.class, "uvIndex", 0d).floatValue());
forecast.precipProbability = safelyGet(forecastJson, Integer.class, "precipProbability", 0); forecast.setPrecipProbability(safelyGet(forecastJson, Integer.class, "precipProbability", 0));
weatherSpec.hourly.add(forecast); weatherSpec.getHourly().add(forecast);
} }
} }
@@ -182,19 +182,19 @@ public class GenericWeatherReceiver extends BroadcastReceiver {
private WeatherSpec.AirQuality toAirQuality(final JSONObject jsonObject) { private WeatherSpec.AirQuality toAirQuality(final JSONObject jsonObject) {
final WeatherSpec.AirQuality airQuality = new WeatherSpec.AirQuality(); final WeatherSpec.AirQuality airQuality = new WeatherSpec.AirQuality();
airQuality.aqi = safelyGet(jsonObject, Integer.class, "aqi", -1); airQuality.setAqi(safelyGet(jsonObject, Integer.class, "aqi", -1));
airQuality.co = safelyGet(jsonObject, Number.class, "co", -1).floatValue(); airQuality.setCo(safelyGet(jsonObject, Number.class, "co", -1).floatValue());
airQuality.no2 = safelyGet(jsonObject, Number.class, "no2", -1).floatValue(); airQuality.setNo2(safelyGet(jsonObject, Number.class, "no2", -1).floatValue());
airQuality.o3 = safelyGet(jsonObject, Number.class, "o3", -1).floatValue(); airQuality.setO3(safelyGet(jsonObject, Number.class, "o3", -1).floatValue());
airQuality.pm10 = safelyGet(jsonObject, Number.class, "pm10", -1).floatValue(); airQuality.setPm10(safelyGet(jsonObject, Number.class, "pm10", -1).floatValue());
airQuality.pm25 = safelyGet(jsonObject, Number.class, "pm25", -1).floatValue(); airQuality.setPm25(safelyGet(jsonObject, Number.class, "pm25", -1).floatValue());
airQuality.so2 = safelyGet(jsonObject, Number.class, "so2", -1).floatValue(); airQuality.setSo2(safelyGet(jsonObject, Number.class, "so2", -1).floatValue());
airQuality.coAqi = safelyGet(jsonObject, Integer.class, "coAqi", -1); airQuality.setCoAqi(safelyGet(jsonObject, Integer.class, "coAqi", -1));
airQuality.no2Aqi = safelyGet(jsonObject, Integer.class, "no2Aqi", -1); airQuality.setNo2Aqi(safelyGet(jsonObject, Integer.class, "no2Aqi", -1));
airQuality.o3Aqi = safelyGet(jsonObject, Integer.class, "o3Aqi", -1); airQuality.setO3Aqi(safelyGet(jsonObject, Integer.class, "o3Aqi", -1));
airQuality.pm10Aqi = safelyGet(jsonObject, Integer.class, "pm10Aqi", -1); airQuality.setPm10Aqi(safelyGet(jsonObject, Integer.class, "pm10Aqi", -1));
airQuality.pm25Aqi = safelyGet(jsonObject, Integer.class, "pm25Aqi", -1); airQuality.setPm25Aqi(safelyGet(jsonObject, Integer.class, "pm25Aqi", -1));
airQuality.so2Aqi = safelyGet(jsonObject, Integer.class, "so2Aqi", -1); airQuality.setSo2Aqi(safelyGet(jsonObject, Integer.class, "so2Aqi", -1));
return airQuality; return airQuality;
} }
@@ -165,43 +165,43 @@ public class LineageOsWeatherReceiver extends BroadcastReceiver implements Linea
if (weatherInfo != null) { if (weatherInfo != null) {
LOG.info("weather: " + weatherInfo.toString()); LOG.info("weather: " + weatherInfo.toString());
WeatherSpec weatherSpec = new WeatherSpec(); WeatherSpec weatherSpec = new WeatherSpec();
weatherSpec.timestamp = (int) (weatherInfo.getTimestamp() / 1000); weatherSpec.setTimestamp((int) (weatherInfo.getTimestamp() / 1000));
weatherSpec.location = weatherInfo.getCity(); weatherSpec.setLocation(weatherInfo.getCity());
if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) { if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) {
weatherSpec.currentTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTemperature()) + 273; weatherSpec.setCurrentTemp((int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTemperature()) + 273);
weatherSpec.todayMaxTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysHigh()) + 273; weatherSpec.setTodayMaxTemp((int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysHigh()) + 273);
weatherSpec.todayMinTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysLow()) + 273; weatherSpec.setTodayMinTemp((int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysLow()) + 273);
} else { } else {
weatherSpec.currentTemp = (int) weatherInfo.getTemperature() + 273; weatherSpec.setCurrentTemp((int) weatherInfo.getTemperature() + 273);
weatherSpec.todayMaxTemp = (int) weatherInfo.getTodaysHigh() + 273; weatherSpec.setTodayMaxTemp((int) weatherInfo.getTodaysHigh() + 273);
weatherSpec.todayMinTemp = (int) weatherInfo.getTodaysLow() + 273; weatherSpec.setTodayMinTemp((int) weatherInfo.getTodaysLow() + 273);
} }
if (weatherInfo.getWindSpeedUnit() == MPH) { if (weatherInfo.getWindSpeedUnit() == MPH) {
weatherSpec.windSpeed = (float) weatherInfo.getWindSpeed() * 1.609344f; weatherSpec.setWindSpeed((float) weatherInfo.getWindSpeed() * 1.609344f);
} else { } else {
weatherSpec.windSpeed = (float) weatherInfo.getWindSpeed(); weatherSpec.setWindSpeed((float) weatherInfo.getWindSpeed());
} }
weatherSpec.windDirection = (int) weatherInfo.getWindDirection(); weatherSpec.setWindDirection((int) weatherInfo.getWindDirection());
weatherSpec.currentConditionCode = WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(LineageOSToYahooCondition(weatherInfo.getConditionCode())); weatherSpec.setCurrentConditionCode(WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(LineageOSToYahooCondition(weatherInfo.getConditionCode())));
weatherSpec.currentCondition = WeatherMapper.INSTANCE.getConditionString(mContext, weatherSpec.currentConditionCode); weatherSpec.setCurrentCondition(WeatherMapper.INSTANCE.getConditionString(mContext, weatherSpec.getCurrentConditionCode()));
weatherSpec.currentHumidity = (int) weatherInfo.getHumidity(); weatherSpec.setCurrentHumidity((int) weatherInfo.getHumidity());
weatherSpec.forecasts = new ArrayList<>(); weatherSpec.setForecasts(new ArrayList<>());
List<WeatherInfo.DayForecast> forecasts = weatherInfo.getForecasts(); List<WeatherInfo.DayForecast> forecasts = weatherInfo.getForecasts();
for (int i = 1; i < forecasts.size(); i++) { for (int i = 1; i < forecasts.size(); i++) {
WeatherInfo.DayForecast cmForecast = forecasts.get(i); WeatherInfo.DayForecast cmForecast = forecasts.get(i);
WeatherSpec.Daily gbForecast = new WeatherSpec.Daily(); WeatherSpec.Daily gbForecast = new WeatherSpec.Daily();
if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) { if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) {
gbForecast.maxTemp = (int) WeatherUtils.fahrenheitToCelsius(cmForecast.getHigh()) + 273; gbForecast.setMaxTemp((int) WeatherUtils.fahrenheitToCelsius(cmForecast.getHigh()) + 273);
gbForecast.minTemp = (int) WeatherUtils.fahrenheitToCelsius(cmForecast.getLow()) + 273; gbForecast.setMinTemp((int) WeatherUtils.fahrenheitToCelsius(cmForecast.getLow()) + 273);
} else { } else {
gbForecast.maxTemp = (int) cmForecast.getHigh() + 273; gbForecast.setMaxTemp((int) cmForecast.getHigh() + 273);
gbForecast.minTemp = (int) cmForecast.getLow() + 273; gbForecast.setMinTemp((int) cmForecast.getLow() + 273);
} }
gbForecast.conditionCode = WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(LineageOSToYahooCondition(cmForecast.getConditionCode())); gbForecast.setConditionCode(WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(LineageOSToYahooCondition(cmForecast.getConditionCode())));
weatherSpec.forecasts.add(gbForecast); weatherSpec.getForecasts().add(gbForecast);
} }
ArrayList<WeatherSpec> weatherSpecs = new ArrayList<>(Collections.singletonList(weatherSpec)); ArrayList<WeatherSpec> weatherSpecs = new ArrayList<>(Collections.singletonList(weatherSpec));
Weather.INSTANCE.setWeatherSpec(weatherSpecs); Weather.INSTANCE.setWeatherSpec(weatherSpecs);
@@ -105,7 +105,7 @@ public class OmniJawsObserver extends ContentObserver {
try { try {
WeatherSpec weatherSpec = new WeatherSpec(); WeatherSpec weatherSpec = new WeatherSpec();
weatherSpec.forecasts = new ArrayList<>(); weatherSpec.setForecasts(new ArrayList<>());
int count = c.getCount(); int count = c.getCount();
if (count > 0) { if (count > 0) {
@@ -113,28 +113,28 @@ public class OmniJawsObserver extends ContentObserver {
c.moveToPosition(i); c.moveToPosition(i);
if (i == 0) { if (i == 0) {
weatherSpec.location = c.getString(0); weatherSpec.setLocation(c.getString(0));
weatherSpec.currentConditionCode = WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(c.getInt(2)); weatherSpec.setCurrentConditionCode(WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(c.getInt(2)));
weatherSpec.currentCondition = WeatherMapper.INSTANCE.getConditionString(mContext, weatherSpec.currentConditionCode); weatherSpec.setCurrentCondition(WeatherMapper.INSTANCE.getConditionString(mContext, weatherSpec.getCurrentConditionCode()));
//alternatively the following would also be possible //alternatively the following would also be possible
//weatherSpec.currentCondition = c.getString(1); //weatherSpec.currentCondition = c.getString(1);
weatherSpec.currentTemp = toKelvin(c.getFloat(3)); weatherSpec.setCurrentTemp(toKelvin(c.getFloat(3)));
weatherSpec.currentHumidity = (int) c.getFloat(4); weatherSpec.setCurrentHumidity((int) c.getFloat(4));
weatherSpec.windSpeed = toKmh(c.getFloat(11)); weatherSpec.setWindSpeed(toKmh(c.getFloat(11)));
weatherSpec.windDirection = c.getInt(12); weatherSpec.setWindDirection(c.getInt(12));
weatherSpec.timestamp = (int) (Long.parseLong(c.getString(9)) / 1000); weatherSpec.setTimestamp((int) (Long.parseLong(c.getString(9)) / 1000));
} else if (i == 1) { } else if (i == 1) {
weatherSpec.todayMinTemp = toKelvin(c.getFloat(5)); weatherSpec.setTodayMinTemp(toKelvin(c.getFloat(5)));
weatherSpec.todayMaxTemp = toKelvin(c.getFloat(6)); weatherSpec.setTodayMaxTemp(toKelvin(c.getFloat(6)));
} else { } else {
WeatherSpec.Daily gbForecast = new WeatherSpec.Daily(); WeatherSpec.Daily gbForecast = new WeatherSpec.Daily();
gbForecast.minTemp = toKelvin(c.getFloat(5)); gbForecast.setMinTemp(toKelvin(c.getFloat(5)));
gbForecast.maxTemp = toKelvin(c.getFloat(6)); gbForecast.setMaxTemp(toKelvin(c.getFloat(6)));
gbForecast.conditionCode = WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(c.getInt(8)); gbForecast.setConditionCode(WeatherMapper.INSTANCE.mapToOpenWeatherMapCondition(c.getInt(8)));
weatherSpec.forecasts.add(gbForecast); weatherSpec.getForecasts().add(gbForecast);
} }
} }
} }
@@ -42,7 +42,7 @@ public class TinyWeatherForecastGermanyReceiver extends BroadcastReceiver {
WeatherSpec weatherSpec = bundle.getParcelable("WeatherSpec"); WeatherSpec weatherSpec = bundle.getParcelable("WeatherSpec");
if (weatherSpec != null) { if (weatherSpec != null) {
ArrayList<WeatherSpec> weatherSpecs = new ArrayList<>(Collections.singletonList(weatherSpec)); ArrayList<WeatherSpec> weatherSpecs = new ArrayList<>(Collections.singletonList(weatherSpec));
weatherSpec.timestamp = (int) (System.currentTimeMillis() / 1000); weatherSpec.setTimestamp((int) (System.currentTimeMillis() / 1000));
Weather.INSTANCE.setWeatherSpec(weatherSpecs); Weather.INSTANCE.setWeatherSpec(weatherSpecs);
GBApplication.deviceService().onSendWeather(weatherSpecs); GBApplication.deviceService().onSendWeather(weatherSpecs);
} }
@@ -1,505 +0,0 @@
/* Copyright (C) 2016-2024 Andreas Shimokawa, Arjan Schrijver, beardhatcode,
Carsten Pfeiffer, Daniele Gobbetti, Enrico Brambilla, José Rebelo, Taavi
Eomäe
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.model;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;
import java.io.Serializable;
import java.util.ArrayList;
// FIXME: document me and my fields, including units
public class WeatherSpec implements Parcelable, Serializable {
public static final Creator<WeatherSpec> CREATOR = new Creator<WeatherSpec>() {
@Override
public WeatherSpec createFromParcel(Parcel in) {
return new WeatherSpec(in);
}
@Override
public WeatherSpec[] newArray(int size) {
return new WeatherSpec[size];
}
};
public static final int VERSION = 4;
private static final long serialVersionUID = VERSION;
public int timestamp; // unix epoch timestamp, in seconds
public String location;
public int currentTemp; // kelvin
public int currentConditionCode = 3200; // OpenWeatherMap condition code
public String currentCondition;
public int currentHumidity;
public int todayMaxTemp; // kelvin
public int todayMinTemp; // kelvin
public float windSpeed; // km per hour
public int windDirection; // deg
public float uvIndex; // 0.0 to 15.0
public int precipProbability; // %
public int dewPoint; // kelvin
public float pressure; // mb
public int cloudCover; // %
public float visibility; // m
public int sunRise; // unix epoch timestamp, in seconds
public int sunSet; // unix epoch timestamp, in seconds
public int moonRise; // unix epoch timestamp, in seconds
public int moonSet; // unix epoch timestamp, in seconds
public int moonPhase; // deg [0, 360[
public float latitude;
public float longitude;
public int feelsLikeTemp; // kelvin
public int isCurrentLocation = -1; // 0 for false, 1 for true, -1 for unknown
public AirQuality airQuality;
// Forecasts from the next day onward, in chronological order, one entry per day.
// It should not include the current or previous days
public ArrayList<Daily> forecasts = new ArrayList<>();
// Hourly forecasts
public ArrayList<Hourly> hourly = new ArrayList<>();
public WeatherSpec() {
}
// Lower bounds of beaufort regions 1 to 12
// Values from https://en.wikipedia.org/wiki/Beaufort_scale
static final float[] beaufort = new float[] { 2, 6, 12, 20, 29, 39, 50, 62, 75, 89, 103, 118 };
// level: 0 1 2 3 4 5 6 7 8 9 10 11 12
public static int toBeaufort(final float speed) {
int l = 0;
while (l < beaufort.length && beaufort[l] < speed) {
l++;
}
return l;
}
public int windSpeedAsBeaufort() {
return toBeaufort(this.windSpeed);
}
@Nullable
public Location getLocation() {
if (latitude == 0 && longitude == 0) {
return null;
}
final Location location = new Location("weatherSpec");
location.setLatitude(latitude);
location.setLongitude(longitude);
return location;
}
protected WeatherSpec(Parcel in) {
int version = in.readInt();
if (version >= 2) {
timestamp = in.readInt();
location = in.readString();
currentTemp = in.readInt();
currentConditionCode = in.readInt();
currentCondition = in.readString();
currentHumidity = in.readInt();
todayMaxTemp = in.readInt();
todayMinTemp = in.readInt();
windSpeed = in.readFloat();
windDirection = in.readInt();
if (version < 4) {
// Deserialize the old Forecast list and convert them to Daily
final ArrayList<Forecast> oldForecasts = new ArrayList<>();
in.readList(oldForecasts, Forecast.class.getClassLoader());
for (final Forecast forecast : oldForecasts) {
final Daily d = new Daily();
d.minTemp = forecast.minTemp;
d.maxTemp = forecast.maxTemp;
d.conditionCode = forecast.conditionCode;
d.humidity = forecast.humidity;
forecasts.add(d);
}
} else {
in.readList(forecasts, Daily.class.getClassLoader());
}
}
if (version >= 3) {
uvIndex = in.readFloat();
precipProbability = in.readInt();
}
if (version >= 4) {
dewPoint = in.readInt();
pressure = in.readFloat();
cloudCover = in.readInt();
visibility = in.readFloat();
sunRise = in.readInt();
sunSet = in.readInt();
moonRise = in.readInt();
moonSet = in.readInt();
moonPhase = in.readInt();
latitude = in.readFloat();
longitude = in.readFloat();
feelsLikeTemp = in.readInt();
isCurrentLocation = in.readInt();
airQuality = in.readParcelable(AirQuality.class.getClassLoader());
in.readList(hourly, Hourly.class.getClassLoader());
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(VERSION);
dest.writeInt(timestamp);
dest.writeString(location);
dest.writeInt(currentTemp);
dest.writeInt(currentConditionCode);
dest.writeString(currentCondition);
dest.writeInt(currentHumidity);
dest.writeInt(todayMaxTemp);
dest.writeInt(todayMinTemp);
dest.writeFloat(windSpeed);
dest.writeInt(windDirection);
dest.writeList(forecasts);
dest.writeFloat(uvIndex);
dest.writeInt(precipProbability);
dest.writeInt(dewPoint);
dest.writeFloat(pressure);
dest.writeInt(cloudCover);
dest.writeFloat(visibility);
dest.writeInt(sunRise);
dest.writeInt(sunSet);
dest.writeInt(moonRise);
dest.writeInt(moonSet);
dest.writeInt(moonPhase);
dest.writeFloat(latitude);
dest.writeFloat(longitude);
dest.writeInt(feelsLikeTemp);
dest.writeInt(isCurrentLocation);
dest.writeParcelable(airQuality, 0);
dest.writeList(hourly);
}
/**
* Convert the current day's forecast to a {@link Daily} object.
*/
public Daily todayAsDaily() {
final Daily daily = new Daily();
daily.minTemp = this.todayMinTemp;
daily.maxTemp = this.todayMaxTemp;
daily.conditionCode = this.currentConditionCode;
daily.humidity = this.currentHumidity;
daily.windSpeed = this.windSpeed;
daily.windDirection = this.windDirection;
daily.uvIndex = this.uvIndex;
daily.precipProbability = this.precipProbability;
daily.sunRise = this.sunRise;
daily.sunSet = this.sunSet;
daily.moonRise = this.moonRise;
daily.moonSet = this.moonSet;
daily.moonPhase = this.moonPhase;
daily.airQuality = this.airQuality;
return daily;
}
@Deprecated // kept for backwards compatibility with old weather apps
public static class Forecast implements Parcelable, Serializable {
private static final long serialVersionUID = 1L;
public static final Creator<Forecast> CREATOR = new Creator<Forecast>() {
@Override
public Forecast createFromParcel(Parcel in) {
return new Forecast(in);
}
@Override
public Forecast[] newArray(int size) {
return new Forecast[size];
}
};
public int minTemp; // Kelvin
public int maxTemp; // Kelvin
public int conditionCode; // OpenWeatherMap condition code
public int humidity;
public Forecast() {
}
public Forecast(int minTemp, int maxTemp, int conditionCode, int humidity) {
this.minTemp = minTemp;
this.maxTemp = maxTemp;
this.conditionCode = conditionCode;
this.humidity = humidity;
}
Forecast(Parcel in) {
minTemp = in.readInt();
maxTemp = in.readInt();
conditionCode = in.readInt();
humidity = in.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(minTemp);
dest.writeInt(maxTemp);
dest.writeInt(conditionCode);
dest.writeInt(humidity);
}
}
public static class AirQuality implements Parcelable, Serializable {
public static final int VERSION = 1;
private static final long serialVersionUID = VERSION;
public static final Creator<AirQuality> CREATOR = new Creator<AirQuality>() {
@Override
public AirQuality createFromParcel(final Parcel in) {
return new AirQuality(in);
}
@Override
public AirQuality[] newArray(final int size) {
return new AirQuality[size];
}
};
public int aqi = -1; // Air Quality Index - usually the max across all AQI values for pollutants
public float co = -1; // Carbon Monoxide, mg/m^3
public float no2 = -1; // Nitrogen Dioxide, ug/m^3
public float o3 = -1; // Ozone, ug/m^3
public float pm10 = -1; // Particulate Matter, 10 microns or less in diameter, ug/m^3
public float pm25 = -1; // Particulate Matter, 2.5 microns or less in diameter, ug/m^3
public float so2 = -1; // Sulphur Dioxide, ug/m^3
// Air Quality Index values per pollutant
// These are expected to be in the Plume scale (see https://plumelabs.files.wordpress.com/2023/06/plume_aqi_2023.pdf)
// Some apps such as Breezy Weather fallback to the WHO 2021 AQI for pollutants that are not mapped in the Plume AQI
// https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health
//
// Breezy Weather implementation for reference:
// - https://github.com/breezy-weather/breezy-weather/blob/main/app/src/main/java/org/breezyweather/common/basic/models/weather/AirQuality.kt
// - https://github.com/breezy-weather/breezy-weather/blob/main/app/src/main/java/org/breezyweather/common/basic/models/options/index/PollutantIndex.kt
public int coAqi = -1;
public int no2Aqi = -1;
public int o3Aqi = -1;
public int pm10Aqi = -1;
public int pm25Aqi = -1;
public int so2Aqi = -1;
public AirQuality() {
}
AirQuality(final Parcel in) {
in.readInt(); // version
aqi = in.readInt();
co = in.readFloat();
no2 = in.readFloat();
o3 = in.readFloat();
pm10 = in.readFloat();
pm25 = in.readFloat();
so2 = in.readFloat();
coAqi = in.readInt();
no2Aqi = in.readInt();
o3Aqi = in.readInt();
pm10Aqi = in.readInt();
pm25Aqi = in.readInt();
so2Aqi = in.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeInt(VERSION);
dest.writeInt(aqi);
dest.writeFloat(co);
dest.writeFloat(no2);
dest.writeFloat(o3);
dest.writeFloat(pm10);
dest.writeFloat(pm25);
dest.writeFloat(so2);
dest.writeInt(coAqi);
dest.writeInt(no2Aqi);
dest.writeInt(o3Aqi);
dest.writeInt(pm10Aqi);
dest.writeInt(pm25Aqi);
dest.writeInt(so2Aqi);
}
}
public static class Daily implements Parcelable, Serializable {
public static final int VERSION = 1;
private static final long serialVersionUID = VERSION;
public static final Creator<Daily> CREATOR = new Creator<Daily>() {
@Override
public Daily createFromParcel(final Parcel in) {
return new Daily(in);
}
@Override
public Daily[] newArray(final int size) {
return new Daily[size];
}
};
public int minTemp; // Kelvin
public int maxTemp; // Kelvin
public int conditionCode; // OpenWeatherMap condition code
public int humidity;
public float windSpeed; // km per hour
public int windDirection; // deg
public float uvIndex; // 0.0 to 15.0
public int precipProbability; // %
public int sunRise;
public int sunSet;
public int moonRise;
public int moonSet;
public int moonPhase;
public AirQuality airQuality;
public Daily() {
}
Daily(final Parcel in) {
in.readInt(); // version
minTemp = in.readInt();
maxTemp = in.readInt();
conditionCode = in.readInt();
humidity = in.readInt();
windSpeed = in.readFloat();
windDirection = in.readInt();
uvIndex = in.readFloat();
precipProbability = in.readInt();
sunRise = in.readInt();
sunSet = in.readInt();
moonRise = in.readInt();
moonSet = in.readInt();
moonPhase = in.readInt();
airQuality = in.readParcelable(AirQuality.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeInt(VERSION);
dest.writeInt(minTemp);
dest.writeInt(maxTemp);
dest.writeInt(conditionCode);
dest.writeInt(humidity);
dest.writeFloat(windSpeed);
dest.writeInt(windDirection);
dest.writeFloat(uvIndex);
dest.writeInt(precipProbability);
dest.writeInt(sunRise);
dest.writeInt(sunSet);
dest.writeInt(moonRise);
dest.writeInt(moonSet);
dest.writeInt(moonPhase);
dest.writeParcelable(airQuality, 0);
}
public int windSpeedAsBeaufort() {
return toBeaufort(this.windSpeed);
}
}
public static class Hourly implements Parcelable, Serializable {
public static final int VERSION = 1;
private static final long serialVersionUID = VERSION;
public static final Creator<Hourly> CREATOR = new Creator<Hourly>() {
@Override
public Hourly createFromParcel(final Parcel in) {
return new Hourly(in);
}
@Override
public Hourly[] newArray(final int size) {
return new Hourly[size];
}
};
public int timestamp; // unix epoch timestamp, in seconds
public int temp; // Kelvin
public int conditionCode; // OpenWeatherMap condition code
public int humidity;
public float windSpeed; // km per hour
public int windDirection; // deg
public float uvIndex; // 0.0 to 15.0
public int precipProbability; // %
public Hourly() {
}
Hourly(final Parcel in) {
in.readInt(); // version
timestamp = in.readInt();
temp = in.readInt();
conditionCode = in.readInt();
humidity = in.readInt();
windSpeed = in.readFloat();
windDirection = in.readInt();
uvIndex = in.readFloat();
precipProbability = in.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeInt(VERSION);
dest.writeInt(timestamp);
dest.writeInt(temp);
dest.writeInt(conditionCode);
dest.writeInt(humidity);
dest.writeFloat(windSpeed);
dest.writeInt(windDirection);
dest.writeFloat(uvIndex);
dest.writeInt(precipProbability);
}
public int windSpeedAsBeaufort() {
return toBeaufort(this.windSpeed);
}
}
}
@@ -0,0 +1,439 @@
/* Copyright (C) 2016-2024 Andreas Shimokawa, Arjan Schrijver, beardhatcode,
Carsten Pfeiffer, Daniele Gobbetti, Enrico Brambilla, José Rebelo, Taavi
Eomäe
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.model
import android.location.Location
import android.os.Parcel
import android.os.Parcelable
// FIXME: document me and my fields, including units
class WeatherSpec() : Parcelable {
var timestamp: Int = 0 // unix epoch timestamp, in seconds
var location: String? = null
var currentTemp: Int = 0 // kelvin
var currentConditionCode: Int = 3200 // OpenWeatherMap condition code
var currentCondition: String? = null
var currentHumidity: Int = 0
var todayMaxTemp: Int = 0 // kelvin
var todayMinTemp: Int = 0 // kelvin
var windSpeed: Float = 0f // km per hour
var windDirection: Int = 0 // deg
var uvIndex: Float = 0f // 0.0 to 15.0
var precipProbability: Int = 0 // %
var dewPoint: Int = 0 // kelvin
var pressure: Float = 0f // mb
var cloudCover: Int = 0 // %
var visibility: Float = 0f // m
var sunRise: Int = 0 // unix epoch timestamp, in seconds
var sunSet: Int = 0 // unix epoch timestamp, in seconds
var moonRise: Int = 0 // unix epoch timestamp, in seconds
var moonSet: Int = 0 // unix epoch timestamp, in seconds
var moonPhase: Int = 0 // deg [0, 360[
var latitude: Float = 0f
var longitude: Float = 0f
var feelsLikeTemp: Int = 0 // kelvin
var isCurrentLocation: Int = -1 // 0 for false, 1 for true, -1 for unknown
var airQuality: AirQuality? = null
// Forecasts from the next day onward, in chronological order, one entry per day.
// It should not include the current or previous days
var forecasts: ArrayList<Daily?> = ArrayList()
// Hourly forecasts
var hourly: ArrayList<Hourly?> = ArrayList()
constructor(parcel: Parcel) : this() {
val version = parcel.readInt()
if (version >= 2) {
timestamp = parcel.readInt()
location = parcel.readString()
currentTemp = parcel.readInt()
currentConditionCode = parcel.readInt()
currentCondition = parcel.readString()
currentHumidity = parcel.readInt()
todayMaxTemp = parcel.readInt()
todayMinTemp = parcel.readInt()
windSpeed = parcel.readFloat()
windDirection = parcel.readInt()
if (version < 4) {
// Deserialize the old Forecast list and convert them to Daily
val oldForecasts = ArrayList<Forecast>()
parcel.readList(oldForecasts, Forecast::class.java.classLoader)
for (forecast in oldForecasts) {
val d = Daily()
d.minTemp = forecast.minTemp
d.maxTemp = forecast.maxTemp
d.conditionCode = forecast.conditionCode
d.humidity = forecast.humidity
forecasts.add(d)
}
} else {
parcel.readList(forecasts, Daily::class.java.classLoader)
}
}
if (version >= 3) {
uvIndex = parcel.readFloat()
precipProbability = parcel.readInt()
}
if (version >= 4) {
dewPoint = parcel.readInt()
pressure = parcel.readFloat()
cloudCover = parcel.readInt()
visibility = parcel.readFloat()
sunRise = parcel.readInt()
sunSet = parcel.readInt()
moonRise = parcel.readInt()
moonSet = parcel.readInt()
moonPhase = parcel.readInt()
latitude = parcel.readFloat()
longitude = parcel.readFloat()
feelsLikeTemp = parcel.readInt()
isCurrentLocation = parcel.readInt()
airQuality = parcel.readParcelable(
AirQuality::class.java.classLoader
)
parcel.readList(hourly, Hourly::class.java.classLoader)
}
}
fun windSpeedAsBeaufort(): Int = toBeaufort(this.windSpeed)
fun getIsCurrentLocation(): Int = isCurrentLocation
fun setIsCurrentLocation(currLoc: Int) {
isCurrentLocation = currLoc
}
fun getLocationObject(): Location? {
return if (latitude == 0f && longitude == 0f) null
else Location("weatherSpec").apply {
latitude = this@WeatherSpec.latitude.toDouble()
longitude = this@WeatherSpec.longitude.toDouble()
}
}
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(VERSION)
dest.writeInt(timestamp)
dest.writeString(location)
dest.writeInt(currentTemp)
dest.writeInt(currentConditionCode)
dest.writeString(currentCondition)
dest.writeInt(currentHumidity)
dest.writeInt(todayMaxTemp)
dest.writeInt(todayMinTemp)
dest.writeFloat(windSpeed)
dest.writeInt(windDirection)
dest.writeList(forecasts)
dest.writeFloat(uvIndex)
dest.writeInt(precipProbability)
dest.writeInt(dewPoint)
dest.writeFloat(pressure)
dest.writeInt(cloudCover)
dest.writeFloat(visibility)
dest.writeInt(sunRise)
dest.writeInt(sunSet)
dest.writeInt(moonRise)
dest.writeInt(moonSet)
dest.writeInt(moonPhase)
dest.writeFloat(latitude)
dest.writeFloat(longitude)
dest.writeInt(feelsLikeTemp)
dest.writeInt(isCurrentLocation)
dest.writeParcelable(airQuality, 0)
dest.writeList(hourly)
}
/**
* Convert the current day's forecast to a [Daily] object.
*/
fun todayAsDaily(): Daily = Daily().apply {
minTemp = todayMinTemp
maxTemp = todayMaxTemp
conditionCode = currentConditionCode
humidity = currentHumidity
windSpeed = this@WeatherSpec.windSpeed
windDirection = this@WeatherSpec.windDirection
uvIndex = this@WeatherSpec.uvIndex
precipProbability = this@WeatherSpec.precipProbability
sunRise = this@WeatherSpec.sunRise
sunSet = this@WeatherSpec.sunSet
moonRise = this@WeatherSpec.moonRise
moonSet = this@WeatherSpec.moonSet
moonPhase = this@WeatherSpec.moonPhase
airQuality = this@WeatherSpec.airQuality
}
@Deprecated("Kept for backwards compatibility with old weather apps")
class Forecast() : Parcelable {
var minTemp: Int = 0 // Kelvin
var maxTemp: Int = 0 // Kelvin
var conditionCode: Int = 0 // OpenWeatherMap condition code
var humidity: Int = 0
internal constructor(parcel: Parcel) : this() {
minTemp = parcel.readInt()
maxTemp = parcel.readInt()
conditionCode = parcel.readInt()
humidity = parcel.readInt()
}
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(minTemp)
dest.writeInt(maxTemp)
dest.writeInt(conditionCode)
dest.writeInt(humidity)
}
companion object {
const val VERSION = 1
@JvmField
val CREATOR: Parcelable.Creator<Forecast> = object : Parcelable.Creator<Forecast> {
override fun createFromParcel(parcel: Parcel): Forecast = Forecast(parcel)
override fun newArray(size: Int): Array<Forecast?> = arrayOfNulls(size)
}
}
}
class AirQuality : Parcelable {
var aqi: Int =
-1 // Air Quality Index - usually the max across all AQI values for pollutants
var co: Float = -1f // Carbon Monoxide, mg/m^3
var no2: Float = -1f // Nitrogen Dioxide, ug/m^3
var o3: Float = -1f // Ozone, ug/m^3
var pm10: Float = -1f // Particulate Matter, 10 microns or less in diameter, ug/m^3
var pm25: Float = -1f // Particulate Matter, 2.5 microns or less in diameter, ug/m^3
var so2: Float = -1f // Sulphur Dioxide, ug/m^3
// Air Quality Index values per pollutant
// These are expected to be in the Plume scale (see https://plumelabs.files.wordpress.com/2023/06/plume_aqi_2023.pdf)
// Some apps such as Breezy Weather fallback to the WHO 2021 AQI for pollutants that are not mapped in the Plume AQI
// https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health
//
// Breezy Weather implementation for reference:
// - https://github.com/breezy-weather/breezy-weather/blob/main/app/src/main/java/org/breezyweather/common/basic/models/weather/AirQuality.kt
// - https://github.com/breezy-weather/breezy-weather/blob/main/app/src/main/java/org/breezyweather/common/basic/models/options/index/PollutantIndex.kt
var coAqi: Int = -1
var no2Aqi: Int = -1
var o3Aqi: Int = -1
var pm10Aqi: Int = -1
var pm25Aqi: Int = -1
var so2Aqi: Int = -1
constructor()
internal constructor(parcel: Parcel) {
parcel.readInt() // version
aqi = parcel.readInt()
co = parcel.readFloat()
no2 = parcel.readFloat()
o3 = parcel.readFloat()
pm10 = parcel.readFloat()
pm25 = parcel.readFloat()
so2 = parcel.readFloat()
coAqi = parcel.readInt()
no2Aqi = parcel.readInt()
o3Aqi = parcel.readInt()
pm10Aqi = parcel.readInt()
pm25Aqi = parcel.readInt()
so2Aqi = parcel.readInt()
}
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(VERSION)
dest.writeInt(aqi)
dest.writeFloat(co)
dest.writeFloat(no2)
dest.writeFloat(o3)
dest.writeFloat(pm10)
dest.writeFloat(pm25)
dest.writeFloat(so2)
dest.writeInt(coAqi)
dest.writeInt(no2Aqi)
dest.writeInt(o3Aqi)
dest.writeInt(pm10Aqi)
dest.writeInt(pm25Aqi)
dest.writeInt(so2Aqi)
}
companion object {
const val VERSION = 1
@JvmField
val CREATOR: Parcelable.Creator<AirQuality> = object : Parcelable.Creator<AirQuality> {
override fun createFromParcel(parcel: Parcel): AirQuality = AirQuality(parcel)
override fun newArray(size: Int): Array<AirQuality?> = arrayOfNulls(size)
}
}
}
class Daily() : Parcelable {
var minTemp: Int = 0 // Kelvin
var maxTemp: Int = 0 // Kelvin
var conditionCode: Int = 0 // OpenWeatherMap condition code
var humidity: Int = 0
var windSpeed: Float = 0f // km per hour
var windDirection: Int = 0 // deg
var uvIndex: Float = 0f // 0.0 to 15.0
var precipProbability: Int = 0 // %
var sunRise: Int = 0
var sunSet: Int = 0
var moonRise: Int = 0
var moonSet: Int = 0
var moonPhase: Int = 0
var airQuality: AirQuality? = null
internal constructor(parcel: Parcel) : this() {
parcel.readInt() // version
minTemp = parcel.readInt()
maxTemp = parcel.readInt()
conditionCode = parcel.readInt()
humidity = parcel.readInt()
windSpeed = parcel.readFloat()
windDirection = parcel.readInt()
uvIndex = parcel.readFloat()
precipProbability = parcel.readInt()
sunRise = parcel.readInt()
sunSet = parcel.readInt()
moonRise = parcel.readInt()
moonSet = parcel.readInt()
moonPhase = parcel.readInt()
airQuality = parcel.readParcelable(
AirQuality::class.java.classLoader
)
}
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(VERSION)
dest.writeInt(minTemp)
dest.writeInt(maxTemp)
dest.writeInt(conditionCode)
dest.writeInt(humidity)
dest.writeFloat(windSpeed)
dest.writeInt(windDirection)
dest.writeFloat(uvIndex)
dest.writeInt(precipProbability)
dest.writeInt(sunRise)
dest.writeInt(sunSet)
dest.writeInt(moonRise)
dest.writeInt(moonSet)
dest.writeInt(moonPhase)
dest.writeParcelable(airQuality, 0)
}
fun windSpeedAsBeaufort(): Int {
return WeatherSpec.toBeaufort(this.windSpeed)
}
companion object {
const val VERSION = 1
@JvmField
val CREATOR: Parcelable.Creator<Daily> = object : Parcelable.Creator<Daily> {
override fun createFromParcel(parcel: Parcel): Daily = Daily(parcel)
override fun newArray(size: Int): Array<Daily?> = arrayOfNulls(size)
}
}
}
class Hourly() : Parcelable {
var timestamp: Int = 0 // unix epoch timestamp, in seconds
var temp: Int = 0 // Kelvin
var conditionCode: Int = 0 // OpenWeatherMap condition code
var humidity: Int = 0
var windSpeed: Float = 0f // km per hour
var windDirection: Int = 0 // deg
var uvIndex: Float = 0f // 0.0 to 15.0
var precipProbability: Int = 0 // %
internal constructor(parcel: Parcel) : this() {
parcel.readInt() // version
timestamp = parcel.readInt()
temp = parcel.readInt()
conditionCode = parcel.readInt()
humidity = parcel.readInt()
windSpeed = parcel.readFloat()
windDirection = parcel.readInt()
uvIndex = parcel.readFloat()
precipProbability = parcel.readInt()
}
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(VERSION)
dest.writeInt(timestamp)
dest.writeInt(temp)
dest.writeInt(conditionCode)
dest.writeInt(humidity)
dest.writeFloat(windSpeed)
dest.writeInt(windDirection)
dest.writeFloat(uvIndex)
dest.writeInt(precipProbability)
}
fun windSpeedAsBeaufort(): Int {
return WeatherSpec.toBeaufort(this.windSpeed)
}
companion object {
const val VERSION = 1
@JvmField
val CREATOR: Parcelable.Creator<Hourly> = object : Parcelable.Creator<Hourly> {
override fun createFromParcel(parcel: Parcel): Hourly = Hourly(parcel)
override fun newArray(size: Int): Array<Hourly?> = arrayOfNulls(size)
}
}
}
companion object {
const val VERSION: Int = 4
@JvmField
val CREATOR: Parcelable.Creator<WeatherSpec> = object : Parcelable.Creator<WeatherSpec> {
override fun createFromParcel(parcel: Parcel): WeatherSpec = WeatherSpec(parcel)
override fun newArray(size: Int): Array<WeatherSpec?> = arrayOfNulls(size)
}
// Lower bounds of beaufort regions 1 to 12
// Values from https://en.wikipedia.org/wiki/Beaufort_scale
private val beaufort = floatArrayOf(2f, 6f, 12f, 20f, 29f, 39f, 50f, 62f, 75f, 89f, 103f, 118f)
// level: 0 1 2 3 4 5 6 7 8 9 10 11 12
fun toBeaufort(speed: Float): Int {
var level = 0
while (level < beaufort.size && beaufort[level] < speed) {
level++
}
return level
}
}
}
@@ -2017,17 +2017,17 @@ public class BangleJSDeviceSupport extends AbstractBTLESingleDeviceSupport {
o.put("v", 1); o.put("v", 1);
// Current weather // Current weather
o.put("temp", weatherSpec.currentTemp); o.put("temp", weatherSpec.getCurrentTemp());
o.put("hi", weatherSpec.todayMaxTemp); o.put("hi", weatherSpec.getTodayMaxTemp());
o.put("lo", weatherSpec.todayMinTemp); o.put("lo", weatherSpec.getTodayMinTemp());
o.put("hum", weatherSpec.currentHumidity); o.put("hum", weatherSpec.getCurrentHumidity());
o.put("rain", weatherSpec.precipProbability); o.put("rain", weatherSpec.getPrecipProbability());
o.put("uv", Math.round(weatherSpec.uvIndex*10)/10); o.put("uv", Math.round(weatherSpec.getUvIndex() *10)/10);
o.put("code", weatherSpec.currentConditionCode); o.put("code", weatherSpec.getCurrentConditionCode());
o.put("txt", weatherSpec.currentCondition); o.put("txt", weatherSpec.getCurrentCondition());
o.put("wind", Math.round(weatherSpec.windSpeed*100)/100.0); o.put("wind", Math.round(weatherSpec.getWindSpeed() *100)/100.0);
o.put("wdir", weatherSpec.windDirection); o.put("wdir", weatherSpec.getWindDirection());
o.put("loc", weatherSpec.location); o.put("loc", weatherSpec.getLocation());
uartTxJSON("handleWeather", o); uartTxJSON("handleWeather", o);
} catch (JSONException e) { } catch (JSONException e) {
@@ -2046,82 +2046,82 @@ public class BangleJSDeviceSupport extends AbstractBTLESingleDeviceSupport {
JSONObject o = new JSONObject(); JSONObject o = new JSONObject();
o.put("t", "weather"); o.put("t", "weather");
o.put("v", 2); o.put("v", 2);
o.put("l", weatherSpec.location); o.put("l", weatherSpec.getLocation());
o.put("c", weatherSpec.currentCondition); o.put("c", weatherSpec.getCurrentCondition());
ByteArrayOutputStream weatherData = new ByteArrayOutputStream(); ByteArrayOutputStream weatherData = new ByteArrayOutputStream();
// Current weather // Current weather
write1ByteSigned(weatherData, weatherSpec.currentTemp - 273); write1ByteSigned(weatherData, weatherSpec.getCurrentTemp() - 273);
write1ByteSigned(weatherData, weatherSpec.todayMaxTemp - 273); write1ByteSigned(weatherData, weatherSpec.getTodayMaxTemp() - 273);
write1ByteSigned(weatherData, weatherSpec.todayMinTemp - 273); write1ByteSigned(weatherData, weatherSpec.getTodayMinTemp() - 273);
weatherData.write(weatherSpec.currentHumidity); weatherData.write(weatherSpec.getCurrentHumidity());
weatherData.write(weatherSpec.precipProbability); weatherData.write(weatherSpec.getPrecipProbability());
weatherData.write(Math.round(weatherSpec.uvIndex*10)); // fixed point decimal weatherData.write(Math.round(weatherSpec.getUvIndex() *10)); // fixed point decimal
weatherData.write(conditionCodeMapping(weatherSpec.currentConditionCode)); weatherData.write(conditionCodeMapping(weatherSpec.getCurrentConditionCode()));
write2Bytes(weatherData, Math.round(weatherSpec.windSpeed*100)); // fixed point decimal write2Bytes(weatherData, Math.round(weatherSpec.getWindSpeed() *100)); // fixed point decimal
write2Bytes(weatherData, weatherSpec.windDirection); write2Bytes(weatherData, weatherSpec.getWindDirection());
write1ByteSigned(weatherData, weatherSpec.dewPoint - 273); write1ByteSigned(weatherData, weatherSpec.getDewPoint() - 273);
write2Bytes(weatherData, Math.round(weatherSpec.pressure*10)); // fixed point decimal write2Bytes(weatherData, Math.round(weatherSpec.getPressure() *10)); // fixed point decimal
weatherData.write(weatherSpec.cloudCover); weatherData.write(weatherSpec.getCloudCover());
write4Bytes(weatherData, Math.round(weatherSpec.visibility*10)); // fixed point decimal write4Bytes(weatherData, Math.round(weatherSpec.getVisibility() *10)); // fixed point decimal
write4Bytes(weatherData, weatherSpec.sunRise); write4Bytes(weatherData, weatherSpec.getSunRise());
write4Bytes(weatherData, weatherSpec.sunSet); write4Bytes(weatherData, weatherSpec.getSunSet());
write4Bytes(weatherData, weatherSpec.moonRise); write4Bytes(weatherData, weatherSpec.getMoonRise());
write4Bytes(weatherData, weatherSpec.moonSet); write4Bytes(weatherData, weatherSpec.getMoonSet());
write2Bytes(weatherData, weatherSpec.moonPhase); write2Bytes(weatherData, weatherSpec.getMoonPhase());
write1ByteSigned(weatherData, weatherSpec.feelsLikeTemp - 273); write1ByteSigned(weatherData, weatherSpec.getFeelsLikeTemp() - 273);
if (includeForecast) { if (includeForecast) {
// Hourly forecast as Structure of Arrays // Hourly forecast as Structure of Arrays
int hourlyAmount = Math.min(weatherSpec.hourly.size(), 25); int hourlyAmount = Math.min(weatherSpec.getHourly().size(), 25);
weatherData.write(hourlyAmount); weatherData.write(hourlyAmount);
if(hourlyAmount>0) if(hourlyAmount>0)
{ {
write4Bytes(weatherData, weatherSpec.hourly.get(0).timestamp); write4Bytes(weatherData, weatherSpec.getHourly().get(0).getTimestamp());
} }
List<WeatherSpec.Hourly> hourly = weatherSpec.hourly.subList(0, hourlyAmount); List<WeatherSpec.Hourly> hourly = weatherSpec.getHourly().subList(0, hourlyAmount);
for (final WeatherSpec.Hourly hour : hourly) { for (final WeatherSpec.Hourly hour : hourly) {
float hoursDelta = (float) (hour.timestamp - weatherSpec.hourly.get(0).timestamp)/3600; float hoursDelta = (float) (hour.getTimestamp() - weatherSpec.getHourly().get(0).getTimestamp())/3600;
weatherData.write(Math.round(hoursDelta*10)); // fixed point decimal (max 25 hours ahead) weatherData.write(Math.round(hoursDelta*10)); // fixed point decimal (max 25 hours ahead)
} }
for (final WeatherSpec.Hourly hour :hourly) { for (final WeatherSpec.Hourly hour :hourly) {
write1ByteSigned(weatherData, hour.temp - 273); write1ByteSigned(weatherData, hour.getTemp() - 273);
} }
for (final WeatherSpec.Hourly hour : hourly) { for (final WeatherSpec.Hourly hour : hourly) {
weatherData.write(conditionCodeMapping(hour.conditionCode)); weatherData.write(conditionCodeMapping(hour.getConditionCode()));
} }
for (final WeatherSpec.Hourly hour : hourly) { for (final WeatherSpec.Hourly hour : hourly) {
weatherData.write(Math.round(hour.windSpeed)); weatherData.write(Math.round(hour.getWindSpeed()));
} }
for (final WeatherSpec.Hourly hour : hourly) { for (final WeatherSpec.Hourly hour : hourly) {
weatherData.write(hour.windDirection / 2); // Divide 2 by to save 1 Byte weatherData.write(hour.getWindDirection() / 2); // Divide 2 by to save 1 Byte
} }
for (final WeatherSpec.Hourly hour : hourly) { for (final WeatherSpec.Hourly hour : hourly) {
weatherData.write(hour.precipProbability); weatherData.write(hour.getPrecipProbability());
} }
// Daily forecast as Structure of Arrays // Daily forecast as Structure of Arrays
int dailyAmount = Math.min(weatherSpec.forecasts.size(), 7); int dailyAmount = Math.min(weatherSpec.getForecasts().size(), 7);
weatherData.write(dailyAmount); weatherData.write(dailyAmount);
List<WeatherSpec.Daily> daily = weatherSpec.forecasts.subList(0, dailyAmount); List<WeatherSpec.Daily> daily = weatherSpec.getForecasts().subList(0, dailyAmount);
for (final WeatherSpec.Daily day : daily) { for (final WeatherSpec.Daily day : daily) {
write1ByteSigned(weatherData, day.maxTemp - 273); write1ByteSigned(weatherData, day.getMaxTemp() - 273);
} }
for (final WeatherSpec.Daily day : daily) { for (final WeatherSpec.Daily day : daily) {
write1ByteSigned(weatherData, day.minTemp - 273); write1ByteSigned(weatherData, day.getMinTemp() - 273);
} }
for (final WeatherSpec.Daily day : daily) { for (final WeatherSpec.Daily day : daily) {
weatherData.write(conditionCodeMapping(day.conditionCode)); weatherData.write(conditionCodeMapping(day.getConditionCode()));
} }
for (final WeatherSpec.Daily day : daily) { for (final WeatherSpec.Daily day : daily) {
weatherData.write(Math.round(day.windSpeed)); weatherData.write(Math.round(day.getWindSpeed()));
} }
for (final WeatherSpec.Daily day : daily) { for (final WeatherSpec.Daily day : daily) {
weatherData.write(day.windDirection / 2); // Divide 2 by to save 1 Byte weatherData.write(day.getWindDirection() / 2); // Divide 2 by to save 1 Byte
} }
for (final WeatherSpec.Daily day : daily) { for (final WeatherSpec.Daily day : daily) {
weatherData.write(day.precipProbability); weatherData.write(day.getPrecipProbability());
} }
} }
o.put("d", Base64.encodeToString(weatherData.toByteArray(), Base64.DEFAULT)); o.put("d", Base64.encodeToString(weatherData.toByteArray(), Base64.DEFAULT));
@@ -813,29 +813,29 @@ public class CmfWatchProSupport extends AbstractBTLESingleDeviceSupport implemen
final int payloadLength = (7 * 9) + (24 * 2) + (supportsSunriseSunset ? 32 : 30) + (supportsSunriseSunset ? 7 * 8 : 0); final int payloadLength = (7 * 9) + (24 * 2) + (supportsSunriseSunset ? 32 : 30) + (supportsSunriseSunset ? 7 * 8 : 0);
final ByteBuffer buf = ByteBuffer.allocate(payloadLength).order(ByteOrder.BIG_ENDIAN); final ByteBuffer buf = ByteBuffer.allocate(payloadLength).order(ByteOrder.BIG_ENDIAN);
// start with the current day's weather // start with the current day's weather
buf.put(WeatherMapper.INSTANCE.mapToCmfCondition(weatherSpec.currentConditionCode)); buf.put(WeatherMapper.INSTANCE.mapToCmfCondition(weatherSpec.getCurrentConditionCode()));
buf.put((byte) (weatherSpec.currentTemp - 273 + 100)); // convert Kelvin to C, add 100 buf.put((byte) (weatherSpec.getCurrentTemp() - 273 + 100)); // convert Kelvin to C, add 100
buf.put((byte) (weatherSpec.todayMaxTemp - 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.todayMinTemp - 273 + 100)); // convert Kelvin to C, add 100 buf.put((byte) (weatherSpec.getTodayMinTemp() - 273 + 100)); // convert Kelvin to C, add 100
buf.put((byte) weatherSpec.currentHumidity); buf.put((byte) weatherSpec.getCurrentHumidity());
buf.putShort((short) (weatherSpec.airQuality != null ? weatherSpec.airQuality.aqi : 0)); buf.putShort((short) (weatherSpec.getAirQuality() != null ? weatherSpec.getAirQuality().getAqi() : 0));
buf.put((byte) weatherSpec.uvIndex); // UV index isn't shown. uvi decimal/100, so 0x07 = 700 UVI. buf.put((byte) weatherSpec.getUvIndex()); // UV index isn't shown. uvi decimal/100, so 0x07 = 700 UVI.
buf.put((byte) weatherSpec.windSpeed); // isn't shown by watch, unsure of correct units buf.put((byte) weatherSpec.getWindSpeed()); // isn't shown by watch, unsure of correct units
// find out how many future days' forecasts are available // find out how many future days' forecasts are available
int maxForecastsAvailable = weatherSpec.forecasts.size(); int maxForecastsAvailable = weatherSpec.getForecasts().size();
// For each day of the forecast // For each day of the forecast
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
if (i < maxForecastsAvailable) { if (i < maxForecastsAvailable) {
WeatherSpec.Daily forecastDay = weatherSpec.forecasts.get(i); WeatherSpec.Daily forecastDay = weatherSpec.getForecasts().get(i);
buf.put((byte) (WeatherMapper.INSTANCE.mapToCmfCondition(forecastDay.conditionCode))); // weather condition flag buf.put((byte) (WeatherMapper.INSTANCE.mapToCmfCondition(forecastDay.getConditionCode()))); // weather condition flag
buf.put((byte) (forecastDay.maxTemp - 273 + 100)); // temp in C (not shown in future days' forecasts) buf.put((byte) (forecastDay.getMaxTemp() - 273 + 100)); // temp in C (not shown in future days' forecasts)
buf.put((byte) (forecastDay.maxTemp - 273 + 100)); // max temp in C, + 100 buf.put((byte) (forecastDay.getMaxTemp() - 273 + 100)); // max temp in C, + 100
buf.put((byte) (forecastDay.minTemp - 273 + 100)); // min temp in C, + 100 buf.put((byte) (forecastDay.getMinTemp() - 273 + 100)); // min temp in C, + 100
buf.put((byte) forecastDay.humidity); // humidity as a % buf.put((byte) forecastDay.getHumidity()); // humidity as a %
buf.putShort((short) (forecastDay.airQuality != null ? forecastDay.airQuality.aqi : 0)); buf.putShort((short) (forecastDay.getAirQuality() != null ? forecastDay.getAirQuality().getAqi() : 0));
buf.put((byte) forecastDay.uvIndex); // UV index isn't shown. uvi decimal/100, so 0x07 = 700 UVI. buf.put((byte) forecastDay.getUvIndex()); // UV index isn't shown. uvi decimal/100, so 0x07 = 700 UVI.
buf.put((byte) forecastDay.windSpeed); // isn't shown by watch, unsure of correct units buf.put((byte) forecastDay.getWindSpeed()); // isn't shown by watch, unsure of correct units
} else { } else {
// we need to provide a dummy forecast as there's no data available // we need to provide a dummy forecast as there's no data available
buf.put((byte) 0x00); // NULL weather condition buf.put((byte) 0x00); // NULL weather condition
@@ -850,19 +850,19 @@ public class CmfWatchProSupport extends AbstractBTLESingleDeviceSupport implemen
} }
// now add the hourly data for today - just condition and temperature // now add the hourly data for today - just condition and temperature
int maxHourlyForecastsAvailable = weatherSpec.hourly.size(); int maxHourlyForecastsAvailable = weatherSpec.getHourly().size();
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
if (i < maxHourlyForecastsAvailable) { if (i < maxHourlyForecastsAvailable) {
WeatherSpec.Hourly forecastHr = weatherSpec.hourly.get(i); WeatherSpec.Hourly forecastHr = weatherSpec.getHourly().get(i);
buf.put((byte) (forecastHr.temp - 273 + 100)); // temperature buf.put((byte) (forecastHr.getTemp() - 273 + 100)); // temperature
buf.put((byte) forecastHr.conditionCode); // condition buf.put((byte) forecastHr.getConditionCode()); // condition
} else { } else {
buf.put((byte) (weatherSpec.currentTemp - 273 + 100)); // assume current temp buf.put((byte) (weatherSpec.getCurrentTemp() - 273 + 100)); // assume current temp
buf.put((byte) (WeatherMapper.INSTANCE.mapToCmfCondition(weatherSpec.currentConditionCode))); // current condition buf.put((byte) (WeatherMapper.INSTANCE.mapToCmfCondition(weatherSpec.getCurrentConditionCode()))); // current condition
} }
} }
// place name - watch scrolls after ~10 chars. Pad up to 32 bytes. // place name - watch scrolls after ~10 chars. Pad up to 32 bytes.
final byte[] locationNameBytes = nodomain.freeyourgadget.gadgetbridge.util.StringUtils.truncateToBytes(weatherSpec.location, 30); final byte[] locationNameBytes = nodomain.freeyourgadget.gadgetbridge.util.StringUtils.truncateToBytes(weatherSpec.getLocation(), 30);
buf.put(locationNameBytes); buf.put(locationNameBytes);
// Sunrise / sunset // Sunrise / sunset
@@ -870,21 +870,21 @@ public class CmfWatchProSupport extends AbstractBTLESingleDeviceSupport implemen
buf.put(new byte[32 - locationNameBytes.length]); buf.put(new byte[32 - locationNameBytes.length]);
buf.order(ByteOrder.LITTLE_ENDIAN); // why... buf.order(ByteOrder.LITTLE_ENDIAN); // why...
final Location location = weatherSpec.getLocation() != null ? weatherSpec.getLocation() : new CurrentPosition().getLastKnownLocation(); final Location location = weatherSpec.getLocationObject() != null ? weatherSpec.getLocationObject() : new CurrentPosition().getLastKnownLocation();
final GregorianCalendar sunriseDate = new GregorianCalendar(); final GregorianCalendar sunriseDate = new GregorianCalendar();
if (weatherSpec.sunRise != 0 && weatherSpec.sunSet != 0) { if (weatherSpec.getSunRise() != 0 && weatherSpec.getSunSet() != 0) {
buf.putInt(weatherSpec.sunRise); buf.putInt(weatherSpec.getSunRise());
buf.putInt(weatherSpec.sunSet); buf.putInt(weatherSpec.getSunSet());
} else { } else {
putSunriseSunset(buf, location, sunriseDate); putSunriseSunset(buf, location, sunriseDate);
} }
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
sunriseDate.add(Calendar.DAY_OF_MONTH, 1); sunriseDate.add(Calendar.DAY_OF_MONTH, 1);
if (i < weatherSpec.forecasts.size() && weatherSpec.forecasts.get(i).sunRise != 0 && weatherSpec.forecasts.get(i).sunSet != 0) { if (i < weatherSpec.getForecasts().size() && weatherSpec.getForecasts().get(i).getSunRise() != 0 && weatherSpec.getForecasts().get(i).getSunSet() != 0) {
buf.putInt(weatherSpec.forecasts.get(i).sunRise); buf.putInt(weatherSpec.getForecasts().get(i).getSunRise());
buf.putInt(weatherSpec.forecasts.get(i).sunSet); buf.putInt(weatherSpec.getForecasts().get(i).getSunSet());
} else { } else {
putSunriseSunset(buf, location, sunriseDate); putSunriseSunset(buf, location, sunriseDate);
} }
@@ -315,21 +315,21 @@ public class PixooProtocol extends GBDeviceProtocol {
@Override @Override
public byte[] encodeSendWeather(WeatherSpec weatherSpec) { public byte[] encodeSendWeather(WeatherSpec weatherSpec) {
byte pixooWeatherCode = 0; byte pixooWeatherCode = 0;
if (weatherSpec.currentConditionCode >= 200 && weatherSpec.currentConditionCode <= 299) { if (weatherSpec.getCurrentConditionCode() >= 200 && weatherSpec.getCurrentConditionCode() <= 299) {
pixooWeatherCode = 5; pixooWeatherCode = 5;
} else if (weatherSpec.currentConditionCode >= 300 && weatherSpec.currentConditionCode < 600) { } else if (weatherSpec.getCurrentConditionCode() >= 300 && weatherSpec.getCurrentConditionCode() < 600) {
pixooWeatherCode = 6; pixooWeatherCode = 6;
} else if (weatherSpec.currentConditionCode >= 600 && weatherSpec.currentConditionCode < 700) { } else if (weatherSpec.getCurrentConditionCode() >= 600 && weatherSpec.getCurrentConditionCode() < 700) {
pixooWeatherCode = 8; pixooWeatherCode = 8;
} else if (weatherSpec.currentConditionCode >= 700 && weatherSpec.currentConditionCode < 800) { } else if (weatherSpec.getCurrentConditionCode() >= 700 && weatherSpec.getCurrentConditionCode() < 800) {
pixooWeatherCode = 9; pixooWeatherCode = 9;
} else if (weatherSpec.currentConditionCode == 800) { } else if (weatherSpec.getCurrentConditionCode() == 800) {
pixooWeatherCode = 1; pixooWeatherCode = 1;
} else if (weatherSpec.currentConditionCode >= 801 && weatherSpec.currentConditionCode <= 804) { } else if (weatherSpec.getCurrentConditionCode() >= 801 && weatherSpec.getCurrentConditionCode() <= 804) {
pixooWeatherCode = 3; pixooWeatherCode = 3;
} }
byte temp = (byte) (weatherSpec.currentTemp - 273); byte temp = (byte) (weatherSpec.getCurrentTemp() - 273);
String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric)); String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric));
if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) { if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) {
temp = (byte) WeatherUtils.celsiusToFahrenheit(temp); temp = (byte) WeatherUtils.celsiusToFahrenheit(temp);
@@ -237,14 +237,14 @@ public class G1Communications {
this.timeMilliseconds = timeMilliseconds; this.timeMilliseconds = timeMilliseconds;
this.use12HourFormat = use12HourFormat; this.use12HourFormat = use12HourFormat;
if (weatherInfo != null) { if (weatherInfo != null) {
this.weatherIcon = G1Constants.fromOpenWeatherCondition(weatherInfo.currentConditionCode); this.weatherIcon = G1Constants.fromOpenWeatherCondition(weatherInfo.getCurrentConditionCode());
// Convert sunny to a moon if the current time stamp is between sunrise and sunset. // Convert sunny to a moon if the current time stamp is between sunrise and sunset.
if (timeMilliseconds / 1000 >= weatherInfo.sunSet && if (timeMilliseconds / 1000 >= weatherInfo.getSunSet() &&
this.weatherIcon == G1Constants.WeatherId.SUNNY) { this.weatherIcon == G1Constants.WeatherId.SUNNY) {
this.weatherIcon = G1Constants.WeatherId.NIGHT; this.weatherIcon = G1Constants.WeatherId.NIGHT;
} }
// Convert Kelvin -> Celsius. // Convert Kelvin -> Celsius.
this.tempInCelsius = (byte) (weatherInfo.currentTemp - 273); this.tempInCelsius = (byte) (weatherInfo.getCurrentTemp() - 273);
} else { } else {
this.weatherIcon = 0x00; this.weatherIcon = 0x00;
this.tempInCelsius = 0x00; this.tempInCelsius = 0x00;
@@ -546,8 +546,8 @@ public class FitProDeviceSupport extends AbstractBTLESingleDeviceSupport {
public void onSendWeather(ArrayList<WeatherSpec> weatherSpecs) { public void onSendWeather(ArrayList<WeatherSpec> weatherSpecs) {
WeatherSpec weatherSpec = weatherSpecs.get(0); WeatherSpec weatherSpec = weatherSpecs.get(0);
LOG.debug("FitPro send weather"); LOG.debug("FitPro send weather");
short todayMax = (short) (weatherSpec.todayMaxTemp - 273); short todayMax = (short) (weatherSpec.getTodayMaxTemp() - 273);
short todayMin = (short) (weatherSpec.todayMinTemp - 273); short todayMin = (short) (weatherSpec.getTodayMinTemp() - 273);
byte weatherUnit = 0; byte weatherUnit = 0;
String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric)); String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric));
if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) { if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) {
@@ -556,7 +556,7 @@ public class FitProDeviceSupport extends AbstractBTLESingleDeviceSupport {
weatherUnit = 1; weatherUnit = 1;
} }
byte currentConditionCode = WeatherMapper.INSTANCE.mapToFitProCondition(weatherSpec.currentConditionCode); byte currentConditionCode = WeatherMapper.INSTANCE.mapToFitProCondition(weatherSpec.getCurrentConditionCode());
TransactionBuilder builder = createTransactionBuilder("weather"); TransactionBuilder builder = createTransactionBuilder("weather");
writeChunkedData(builder, craftData(CMD_GROUP_GENERAL, CMD_WEATHER, new byte[]{(byte) todayMin, (byte) todayMax, (byte) currentConditionCode, (byte) weatherUnit})); writeChunkedData(builder, craftData(CMD_GROUP_GENERAL, CMD_WEATHER, new byte[]{(byte) todayMin, (byte) todayMax, (byte) currentConditionCode, (byte) weatherUnit}));
builder.queue(); builder.queue();
@@ -493,41 +493,41 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC
RecordData today = new RecordData(recordDefinitionToday, recordDefinitionToday.getRecordHeader()); RecordData today = new RecordData(recordDefinitionToday, recordDefinitionToday.getRecordHeader());
today.setFieldByName("weather_report", 0); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast today.setFieldByName("weather_report", 0); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast
today.setFieldByName("timestamp", weather.timestamp); today.setFieldByName("timestamp", weather.getTimestamp());
today.setFieldByName("observed_at_time", weather.timestamp); today.setFieldByName("observed_at_time", weather.getTimestamp());
today.setFieldByName("temperature", weather.currentTemp); today.setFieldByName("temperature", weather.getCurrentTemp());
today.setFieldByName("low_temperature", weather.todayMinTemp); today.setFieldByName("low_temperature", weather.getTodayMinTemp());
today.setFieldByName("high_temperature", weather.todayMaxTemp); today.setFieldByName("high_temperature", weather.getTodayMaxTemp());
today.setFieldByName("condition", weather.currentConditionCode); today.setFieldByName("condition", weather.getCurrentConditionCode());
today.setFieldByName("wind_direction", weather.windDirection); today.setFieldByName("wind_direction", weather.getWindDirection());
today.setFieldByName("precipitation_probability", weather.precipProbability); today.setFieldByName("precipitation_probability", weather.getPrecipProbability());
today.setFieldByName("wind_speed", Math.round(weather.windSpeed)); today.setFieldByName("wind_speed", Math.round(weather.getWindSpeed()));
today.setFieldByName("temperature_feels_like", weather.feelsLikeTemp); today.setFieldByName("temperature_feels_like", weather.getFeelsLikeTemp());
today.setFieldByName("relative_humidity", weather.currentHumidity); today.setFieldByName("relative_humidity", weather.getCurrentHumidity());
today.setFieldByName("observed_location_lat", weather.latitude); today.setFieldByName("observed_location_lat", weather.getLatitude());
today.setFieldByName("observed_location_long", weather.longitude); today.setFieldByName("observed_location_long", weather.getLongitude());
today.setFieldByName("dew_point", weather.dewPoint); today.setFieldByName("dew_point", weather.getDewPoint());
if (null != weather.airQuality) { if (null != weather.getAirQuality()) {
today.setFieldByName("air_quality", weather.airQuality.aqi); today.setFieldByName("air_quality", weather.getAirQuality().getAqi());
} }
today.setFieldByName("location", weather.location); today.setFieldByName("location", weather.getLocation());
weatherData.add(today); weatherData.add(today);
for (int hour = 0; hour <= 11; hour++) { for (int hour = 0; hour <= 11; hour++) {
if (hour < weather.hourly.size()) { if (hour < weather.getHourly().size()) {
WeatherSpec.Hourly hourly = weather.hourly.get(hour); WeatherSpec.Hourly hourly = weather.getHourly().get(hour);
RecordData weatherHourlyForecast = new RecordData(recordDefinitionHourly, recordDefinitionHourly.getRecordHeader()); RecordData weatherHourlyForecast = new RecordData(recordDefinitionHourly, recordDefinitionHourly.getRecordHeader());
weatherHourlyForecast.setFieldByName("weather_report", 1); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast weatherHourlyForecast.setFieldByName("weather_report", 1); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast
weatherHourlyForecast.setFieldByName("timestamp", hourly.timestamp); weatherHourlyForecast.setFieldByName("timestamp", hourly.getTimestamp());
weatherHourlyForecast.setFieldByName("temperature", hourly.temp); weatherHourlyForecast.setFieldByName("temperature", hourly.getTemp());
weatherHourlyForecast.setFieldByName("condition", hourly.conditionCode); weatherHourlyForecast.setFieldByName("condition", hourly.getConditionCode());
weatherHourlyForecast.setFieldByName("temperature_feels_like", hourly.temp); //TODO: switch to actual feels like field once Hourly contains this information weatherHourlyForecast.setFieldByName("temperature_feels_like", hourly.getTemp()); //TODO: switch to actual feels like field once Hourly contains this information
weatherHourlyForecast.setFieldByName("wind_direction", hourly.windDirection); weatherHourlyForecast.setFieldByName("wind_direction", hourly.getWindDirection());
weatherHourlyForecast.setFieldByName("wind_speed", Math.round(hourly.windSpeed)); weatherHourlyForecast.setFieldByName("wind_speed", Math.round(hourly.getWindSpeed()));
weatherHourlyForecast.setFieldByName("precipitation_probability", hourly.precipProbability); weatherHourlyForecast.setFieldByName("precipitation_probability", hourly.getPrecipProbability());
weatherHourlyForecast.setFieldByName("relative_humidity", hourly.humidity); weatherHourlyForecast.setFieldByName("relative_humidity", hourly.getHumidity());
// weatherHourlyForecast.setFieldByName("dew_point", 0); // TODO: add once Hourly contains this information // weatherHourlyForecast.setFieldByName("dew_point", 0); // TODO: add once Hourly contains this information
weatherHourlyForecast.setFieldByName("uv_index", hourly.uvIndex); weatherHourlyForecast.setFieldByName("uv_index", hourly.getUvIndex());
// weatherHourlyForecast.setFieldByName("air_quality", 0); // TODO: add once Hourly contains this information // weatherHourlyForecast.setFieldByName("air_quality", 0); // TODO: add once Hourly contains this information
weatherData.add(weatherHourlyForecast); weatherData.add(weatherHourlyForecast);
} }
@@ -535,32 +535,32 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC
// //
RecordData todayDailyForecast = new RecordData(recordDefinitionDaily, recordDefinitionDaily.getRecordHeader()); RecordData todayDailyForecast = new RecordData(recordDefinitionDaily, recordDefinitionDaily.getRecordHeader());
todayDailyForecast.setFieldByName("weather_report", 2); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast todayDailyForecast.setFieldByName("weather_report", 2); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast
todayDailyForecast.setFieldByName("timestamp", weather.timestamp); todayDailyForecast.setFieldByName("timestamp", weather.getTimestamp());
todayDailyForecast.setFieldByName("low_temperature", weather.todayMinTemp); todayDailyForecast.setFieldByName("low_temperature", weather.getTodayMinTemp());
todayDailyForecast.setFieldByName("high_temperature", weather.todayMaxTemp); todayDailyForecast.setFieldByName("high_temperature", weather.getTodayMaxTemp());
todayDailyForecast.setFieldByName("condition", weather.currentConditionCode); todayDailyForecast.setFieldByName("condition", weather.getCurrentConditionCode());
todayDailyForecast.setFieldByName("precipitation_probability", weather.precipProbability); todayDailyForecast.setFieldByName("precipitation_probability", weather.getPrecipProbability());
todayDailyForecast.setFieldByName("day_of_week", weather.timestamp); todayDailyForecast.setFieldByName("day_of_week", weather.getTimestamp());
if (null != weather.airQuality) { if (null != weather.getAirQuality()) {
todayDailyForecast.setFieldByName("air_quality", weather.airQuality.aqi); todayDailyForecast.setFieldByName("air_quality", weather.getAirQuality().getAqi());
} }
weatherData.add(todayDailyForecast); weatherData.add(todayDailyForecast);
for (int day = 0; day < 4; day++) { for (int day = 0; day < 4; day++) {
if (day < weather.forecasts.size()) { if (day < weather.getForecasts().size()) {
//noinspection ExtractMethodRecommender //noinspection ExtractMethodRecommender
WeatherSpec.Daily daily = weather.forecasts.get(day); WeatherSpec.Daily daily = weather.getForecasts().get(day);
int ts = weather.timestamp + (day + 1) * 24 * 60 * 60; int ts = weather.getTimestamp() + (day + 1) * 24 * 60 * 60;
RecordData weatherDailyForecast = new RecordData(recordDefinitionDaily, recordDefinitionDaily.getRecordHeader()); RecordData weatherDailyForecast = new RecordData(recordDefinitionDaily, recordDefinitionDaily.getRecordHeader());
weatherDailyForecast.setFieldByName("weather_report", 2); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast weatherDailyForecast.setFieldByName("weather_report", 2); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast
weatherDailyForecast.setFieldByName("timestamp", weather.timestamp); weatherDailyForecast.setFieldByName("timestamp", weather.getTimestamp());
weatherDailyForecast.setFieldByName("low_temperature", daily.minTemp); weatherDailyForecast.setFieldByName("low_temperature", daily.getMinTemp());
weatherDailyForecast.setFieldByName("high_temperature", daily.maxTemp); weatherDailyForecast.setFieldByName("high_temperature", daily.getMaxTemp());
weatherDailyForecast.setFieldByName("condition", daily.conditionCode); weatherDailyForecast.setFieldByName("condition", daily.getConditionCode());
weatherDailyForecast.setFieldByName("precipitation_probability", daily.precipProbability); weatherDailyForecast.setFieldByName("precipitation_probability", daily.getPrecipProbability());
if (null != daily.airQuality) { if (null != daily.getAirQuality()) {
weatherDailyForecast.setFieldByName("air_quality", daily.airQuality.aqi); weatherDailyForecast.setFieldByName("air_quality", daily.getAirQuality().getAqi());
} }
weatherDailyForecast.setFieldByName("day_of_week", ts); weatherDailyForecast.setFieldByName("day_of_week", ts);
weatherData.add(weatherDailyForecast); weatherData.add(weatherDailyForecast);
@@ -63,11 +63,11 @@ public class WeatherHandler {
final List<WeatherForecastDay> ret = new ArrayList<>(duration); final List<WeatherForecastDay> ret = new ArrayList<>(duration);
final GregorianCalendar date = new GregorianCalendar(); final GregorianCalendar date = new GregorianCalendar();
date.setTime(new Date(weatherSpec.timestamp * 1000L)); date.setTime(new Date(weatherSpec.getTimestamp() * 1000L));
ret.add(new WeatherForecastDay(date, weatherSpec.todayAsDaily(), tempUnit, speedUnit)); ret.add(new WeatherForecastDay(date, weatherSpec.todayAsDaily(), tempUnit, speedUnit));
for (int i = 0; i < Math.min(duration, weatherSpec.forecasts.size()) - 1; i++) { for (int i = 0; i < Math.min(duration, weatherSpec.getForecasts().size()) - 1; i++) {
date.add(Calendar.DAY_OF_MONTH, 1); date.add(Calendar.DAY_OF_MONTH, 1);
ret.add(new WeatherForecastDay(date, weatherSpec.forecasts.get(i), tempUnit, speedUnit)); ret.add(new WeatherForecastDay(date, weatherSpec.getForecasts().get(i), tempUnit, speedUnit));
} }
weatherData = ret; weatherData = ret;
break; break;
@@ -89,8 +89,8 @@ public class WeatherHandler {
final String timesOfInterest = getQueryString(query, "timesOfInterest", ""); final String timesOfInterest = getQueryString(query, "timesOfInterest", "");
final List<WeatherForecastHour> ret = new ArrayList<>(duration); final List<WeatherForecastHour> ret = new ArrayList<>(duration);
for (int i = 0; i < Math.min(duration, weatherSpec.hourly.size()); i++) { for (int i = 0; i < Math.min(duration, weatherSpec.getHourly().size()); i++) {
ret.add(new WeatherForecastHour(weatherSpec.hourly.get(i), tempUnit, speedUnit)); ret.add(new WeatherForecastHour(weatherSpec.getHourly().get(i), tempUnit, speedUnit));
} }
weatherData = ret; weatherData = ret;
break; break;
@@ -161,16 +161,16 @@ public class WeatherHandler {
public WeatherForecastDay(final GregorianCalendar date, final WeatherSpec.Daily dailyForecast, final String tempUnit, final String speedUnit) { public WeatherForecastDay(final GregorianCalendar date, final WeatherSpec.Daily dailyForecast, final String tempUnit, final String speedUnit) {
dayOfWeek = BLETypeConversions.dayOfWeekToRawBytes(date); dayOfWeek = BLETypeConversions.dayOfWeekToRawBytes(date);
description = WeatherMapper.INSTANCE.getConditionString(GBApplication.getContext(), dailyForecast.conditionCode); description = WeatherMapper.INSTANCE.getConditionString(GBApplication.getContext(), dailyForecast.getConditionCode());
summary = WeatherMapper.INSTANCE.getConditionString(GBApplication.getContext(), dailyForecast.conditionCode); summary = WeatherMapper.INSTANCE.getConditionString(GBApplication.getContext(), dailyForecast.getConditionCode());
high = getTemperature(dailyForecast.maxTemp, tempUnit); high = getTemperature(dailyForecast.getMaxTemp(), tempUnit);
low = getTemperature(dailyForecast.minTemp, tempUnit); low = getTemperature(dailyForecast.getMinTemp(), tempUnit);
precipProb = dailyForecast.precipProbability; precipProb = dailyForecast.getPrecipProbability();
icon = mapToGarminCondition(dailyForecast.conditionCode); icon = mapToGarminCondition(dailyForecast.getConditionCode());
if (dailyForecast.sunRise != 0 && dailyForecast.sunSet != 0) { if (dailyForecast.getSunRise() != 0 && dailyForecast.getSunSet() != 0) {
epochSunrise = dailyForecast.sunRise; epochSunrise = dailyForecast.getSunRise();
epochSunset = dailyForecast.sunSet; epochSunset = dailyForecast.getSunSet();
} else { } else {
final Location lastKnownLocation = new CurrentPosition().getLastKnownLocation(); final Location lastKnownLocation = new CurrentPosition().getLastKnownLocation();
@@ -189,8 +189,8 @@ public class WeatherHandler {
} }
} }
wind = new Wind(getSpeed(dailyForecast.windSpeed, speedUnit), dailyForecast.windDirection); wind = new Wind(getSpeed(dailyForecast.getWindSpeed(), speedUnit), dailyForecast.getWindDirection());
humidity = dailyForecast.humidity; humidity = dailyForecast.getHumidity();
} }
} }
@@ -212,15 +212,15 @@ public class WeatherHandler {
//public WeatherValue ceilingHeight; // 4700 / FOOT //public WeatherValue ceilingHeight; // 4700 / FOOT
public WeatherForecastHour(final WeatherSpec.Hourly hourlyForecast, final String tempUnit, final String speedUnit) { public WeatherForecastHour(final WeatherSpec.Hourly hourlyForecast, final String tempUnit, final String speedUnit) {
epochSeconds = hourlyForecast.timestamp; epochSeconds = hourlyForecast.getTimestamp();
description = WeatherMapper.INSTANCE.getConditionString(GBApplication.getContext(), hourlyForecast.conditionCode); description = WeatherMapper.INSTANCE.getConditionString(GBApplication.getContext(), hourlyForecast.getConditionCode());
temp = getTemperature(hourlyForecast.temp, tempUnit); temp = getTemperature(hourlyForecast.getTemp(), tempUnit);
precipProb = hourlyForecast.precipProbability; precipProb = hourlyForecast.getPrecipProbability();
wind = new Wind(getSpeed(hourlyForecast.windSpeed, speedUnit), hourlyForecast.windDirection); wind = new Wind(getSpeed(hourlyForecast.getWindSpeed(), speedUnit), hourlyForecast.getWindDirection());
icon = mapToGarminCondition(hourlyForecast.conditionCode); icon = mapToGarminCondition(hourlyForecast.getConditionCode());
//dewPoint = new WeatherValue(hourlyForecast.temp - 273f, "CELSIUS"); // TODO dewPoint //dewPoint = new WeatherValue(hourlyForecast.temp - 273f, "CELSIUS"); // TODO dewPoint
uvIndex = hourlyForecast.uvIndex; uvIndex = hourlyForecast.getUvIndex();
relativeHumidity = hourlyForecast.humidity; relativeHumidity = hourlyForecast.getHumidity();
//feelsLikeTemperature = new WeatherValue(hourlyForecast.temp - 273f, "CELSIUS"); // TODO feelsLikeTemperature //feelsLikeTemperature = new WeatherValue(hourlyForecast.temp - 273f, "CELSIUS"); // TODO feelsLikeTemperature
//visibility = new WeatherValue(0, "METER"); // TODO visibility //visibility = new WeatherValue(0, "METER"); // TODO visibility
//pressure = new WeatherValue(0f, "INCHES_OF_MERCURY"); // TODO pressure //pressure = new WeatherValue(0f, "INCHES_OF_MERCURY"); // TODO pressure
@@ -247,19 +247,19 @@ public class WeatherHandler {
public Integer cloudCoverage; public Integer cloudCoverage;
public WeatherForecastCurrent(final WeatherSpec weatherSpec, final String tempUnit, final String speedUnit) { public WeatherForecastCurrent(final WeatherSpec weatherSpec, final String tempUnit, final String speedUnit) {
epochSeconds = weatherSpec.timestamp; epochSeconds = weatherSpec.getTimestamp();
temperature = getTemperature(weatherSpec.currentTemp, tempUnit); temperature = getTemperature(weatherSpec.getCurrentTemp(), tempUnit);
description = weatherSpec.currentCondition; description = weatherSpec.getCurrentCondition();
icon = mapToGarminCondition(weatherSpec.currentConditionCode); icon = mapToGarminCondition(weatherSpec.getCurrentConditionCode());
feelsLikeTemperature = getTemperature(weatherSpec.currentTemp, tempUnit); feelsLikeTemperature = getTemperature(weatherSpec.getCurrentTemp(), tempUnit);
dewPoint = getTemperature(weatherSpec.dewPoint, tempUnit); dewPoint = getTemperature(weatherSpec.getDewPoint(), tempUnit);
relativeHumidity = weatherSpec.currentHumidity; relativeHumidity = weatherSpec.getCurrentHumidity();
wind = new Wind(getSpeed(weatherSpec.windSpeed, speedUnit), weatherSpec.windDirection); wind = new Wind(getSpeed(weatherSpec.getWindSpeed(), speedUnit), weatherSpec.getWindDirection());
locationName = weatherSpec.location; locationName = weatherSpec.getLocation();
visibility = new WeatherValue(weatherSpec.visibility, "METER"); visibility = new WeatherValue(weatherSpec.getVisibility(), "METER");
pressure = new WeatherValue(weatherSpec.pressure * 0.02953, "INCHES_OF_MERCURY"); pressure = new WeatherValue(weatherSpec.getPressure() * 0.02953, "INCHES_OF_MERCURY");
pressureChange = new WeatherValue(0f, "INCHES_OF_MERCURY"); pressureChange = new WeatherValue(0f, "INCHES_OF_MERCURY");
cloudCoverage = weatherSpec.cloudCover; cloudCoverage = weatherSpec.getCloudCover();
} }
} }
@@ -604,7 +604,7 @@ public class HPlusSupport extends AbstractBTLESingleDeviceSupport {
try { try {
TransactionBuilder builder = performInitialized("sendWeather"); TransactionBuilder builder = performInitialized("sendWeather");
int windSpeed = (int) weatherSpec.windSpeed; int windSpeed = (int) weatherSpec.getWindSpeed();
CurrentPosition currentPosition = new CurrentPosition(); CurrentPosition currentPosition = new CurrentPosition();
@@ -613,20 +613,20 @@ public class HPlusSupport extends AbstractBTLESingleDeviceSupport {
altitude = (int) currentPosition.getLastKnownLocation().getAltitude(); altitude = (int) currentPosition.getLastKnownLocation().getAltitude();
} }
int weatherCode = HPlusWeatherCode.mapOpenWeatherConditionToHPlusCondition(weatherSpec.currentConditionCode); int weatherCode = HPlusWeatherCode.mapOpenWeatherConditionToHPlusCondition(weatherSpec.getCurrentConditionCode());
LOG.info("[WEATHER] currentConditionCode={} altitude={} temp={}", weatherCode, altitude, weatherSpec.currentTemp); LOG.info("[WEATHER] currentConditionCode={} altitude={} temp={}", weatherCode, altitude, weatherSpec.getCurrentTemp());
byte[] weatherInfo = new byte[]{(byte) HPlusConstants.CMD_SET_WEATHER_STATE, byte[] weatherInfo = new byte[]{(byte) HPlusConstants.CMD_SET_WEATHER_STATE,
(byte) ((weatherCode >> 8) & 255), (byte) ((weatherCode >> 8) & 255),
(byte) (weatherCode & 255), (byte) (weatherCode & 255),
(byte) weatherSpec.windDirection, (byte) 0, // weatherSpec.getWinPower(), (byte) weatherSpec.getWindDirection(), (byte) 0, // weatherSpec.getWinPower(),
(byte) ((windSpeed >> 8) & 255), (byte) ((windSpeed >> 8) & 255),
(byte) (windSpeed & 255), (byte) (windSpeed & 255),
(byte) (weatherSpec.currentTemp - 17), (byte) (weatherSpec.getCurrentTemp() - 17),
// base temperature information start at 17d celsius // base temperature information start at 17d celsius
(byte) (weatherSpec.todayMaxTemp - 17), // base temperature information start at 18d celsius (byte) (weatherSpec.getTodayMaxTemp() - 17), // base temperature information start at 18d celsius
(byte) (weatherSpec.todayMinTemp - 17), // base temperature information start at 18d celsius (byte) (weatherSpec.getTodayMinTemp() - 17), // base temperature information start at 18d celsius
(byte) 0, // Life Index always 0 (byte) 0, // Life Index always 0
(byte) 0, // (byte) (weatherSpec.getPressure() & 255), (byte) 0, // (byte) (weatherSpec.getPressure() & 255),
(byte) 0, // (byte) ((weatherSpec.getPressure() >> 8) & 255), (byte) 0, // (byte) ((weatherSpec.getPressure() >> 8) & 255),
@@ -2831,33 +2831,33 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
final WeatherSpec weatherSpec = weatherSpecs.get(0); final WeatherSpec weatherSpec = weatherSpecs.get(0);
MiBandConst.DistanceUnit unit = HuamiCoordinator.getDistanceUnit(); MiBandConst.DistanceUnit unit = HuamiCoordinator.getDistanceUnit();
int tz_offset_hours = SimpleTimeZone.getDefault().getOffset(weatherSpec.timestamp * 1000L) / (1000 * 60 * 60); int tz_offset_hours = SimpleTimeZone.getDefault().getOffset(weatherSpec.getTimestamp() * 1000L) / (1000 * 60 * 60);
try { try {
TransactionBuilder builder; TransactionBuilder builder;
builder = performInitialized("Sending current temp"); builder = performInitialized("Sending current temp");
byte condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode); byte condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.getCurrentConditionCode());
int length = 8; int length = 8;
if (supportsConditionString) { if (supportsConditionString) {
length += weatherSpec.currentCondition.getBytes().length + 1; length += weatherSpec.getCurrentCondition().getBytes().length + 1;
} }
ByteBuffer buf = ByteBuffer.allocate(length); ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 2); buf.put((byte) 2);
buf.putInt(weatherSpec.timestamp); buf.putInt(weatherSpec.getTimestamp());
buf.put((byte) (tz_offset_hours * 4)); buf.put((byte) (tz_offset_hours * 4));
buf.put(condition); buf.put(condition);
int currentTemp = weatherSpec.currentTemp - 273; int currentTemp = weatherSpec.getCurrentTemp() - 273;
if (unit == MiBandConst.DistanceUnit.IMPERIAL) { if (unit == MiBandConst.DistanceUnit.IMPERIAL) {
currentTemp = (int) WeatherUtils.celsiusToFahrenheit(currentTemp); currentTemp = (int) WeatherUtils.celsiusToFahrenheit(currentTemp);
} }
buf.put((byte) currentTemp); buf.put((byte) currentTemp);
if (supportsConditionString) { if (supportsConditionString) {
buf.put(weatherSpec.currentCondition.getBytes()); buf.put(weatherSpec.getCurrentCondition().getBytes());
buf.put((byte) 0); buf.put((byte) 0);
} }
@@ -2876,7 +2876,7 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
TransactionBuilder builder; TransactionBuilder builder;
builder = performInitialized("Sending air quality index"); builder = performInitialized("Sending air quality index");
int length = 8; int length = 8;
int aqi = weatherSpec.airQuality != null ? weatherSpec.airQuality.aqi : -1; int aqi = weatherSpec.getAirQuality() != null ? weatherSpec.getAirQuality().getAqi() : -1;
String aqiString = WeatherMapper.INSTANCE.getAqiLevelString(getContext(), aqi); String aqiString = WeatherMapper.INSTANCE.getAqiLevelString(getContext(), aqi);
if (supportsConditionString) { if (supportsConditionString) {
length += aqiString.getBytes().length + 1; length += aqiString.getBytes().length + 1;
@@ -2884,7 +2884,7 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
ByteBuffer buf = ByteBuffer.allocate(length); ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 4); buf.put((byte) 4);
buf.putInt(weatherSpec.timestamp); buf.putInt(weatherSpec.getTimestamp());
buf.put((byte) (tz_offset_hours * 4)); buf.put((byte) (tz_offset_hours * 4));
buf.putShort((short) aqi); buf.putShort((short) aqi);
if (supportsConditionString) { if (supportsConditionString) {
@@ -2905,18 +2905,18 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
try { try {
TransactionBuilder builder = performInitialized("Sending weather forecast"); TransactionBuilder builder = performInitialized("Sending weather forecast");
if (weatherSpec.forecasts.size() > 6) { //TDOD: find out the limits for each device if (weatherSpec.getForecasts().size() > 6) { //TDOD: find out the limits for each device
weatherSpec.forecasts.subList(6, weatherSpec.forecasts.size()).clear(); weatherSpec.getForecasts().subList(6, weatherSpec.getForecasts().size()).clear();
} }
final byte NR_DAYS = (byte) (1 + weatherSpec.forecasts.size()); final byte NR_DAYS = (byte) (1 + weatherSpec.getForecasts().size());
int bytesPerDay = 4; int bytesPerDay = 4;
int conditionsLength = 0; int conditionsLength = 0;
if (supportsConditionString) { if (supportsConditionString) {
bytesPerDay = 5; bytesPerDay = 5;
conditionsLength = weatherSpec.currentCondition.getBytes().length; conditionsLength = weatherSpec.getCurrentCondition().getBytes().length;
for (WeatherSpec.Daily forecast : weatherSpec.forecasts) { for (WeatherSpec.Daily forecast : weatherSpec.getForecasts()) {
conditionsLength += WeatherMapper.INSTANCE.getConditionString(getContext(), forecast.conditionCode).getBytes().length; conditionsLength += WeatherMapper.INSTANCE.getConditionString(getContext(), forecast.getConditionCode()).getBytes().length;
} }
} }
@@ -2925,17 +2925,17 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 1); buf.put((byte) 1);
buf.putInt(weatherSpec.timestamp); buf.putInt(weatherSpec.getTimestamp());
buf.put((byte) (tz_offset_hours * 4)); buf.put((byte) (tz_offset_hours * 4));
buf.put(NR_DAYS); buf.put(NR_DAYS);
byte condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode); byte condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.getCurrentConditionCode());
buf.put(condition); buf.put(condition);
buf.put(condition); buf.put(condition);
int todayMaxTemp = weatherSpec.todayMaxTemp - 273; int todayMaxTemp = weatherSpec.getTodayMaxTemp() - 273;
int todayMinTemp = weatherSpec.todayMinTemp - 273; int todayMinTemp = weatherSpec.getTodayMinTemp() - 273;
if (unit == MiBandConst.DistanceUnit.IMPERIAL) { if (unit == MiBandConst.DistanceUnit.IMPERIAL) {
todayMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMaxTemp); todayMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMaxTemp);
todayMinTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMinTemp); todayMinTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMinTemp);
@@ -2944,17 +2944,17 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
buf.put((byte) todayMinTemp); buf.put((byte) todayMinTemp);
if (supportsConditionString) { if (supportsConditionString) {
buf.put(weatherSpec.currentCondition.getBytes()); buf.put(weatherSpec.getCurrentCondition().getBytes());
buf.put((byte) 0); buf.put((byte) 0);
} }
for (WeatherSpec.Daily forecast : weatherSpec.forecasts) { for (WeatherSpec.Daily forecast : weatherSpec.getForecasts()) {
condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(forecast.conditionCode); condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(forecast.getConditionCode());
buf.put(condition); buf.put(condition);
buf.put(condition); buf.put(condition);
int forecastMaxTemp = forecast.maxTemp - 273; int forecastMaxTemp = forecast.getMaxTemp() - 273;
int forecastMinTemp = forecast.minTemp - 273; int forecastMinTemp = forecast.getMinTemp() - 273;
if (unit == MiBandConst.DistanceUnit.IMPERIAL) { if (unit == MiBandConst.DistanceUnit.IMPERIAL) {
forecastMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMaxTemp); forecastMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMaxTemp);
forecastMinTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMinTemp); forecastMinTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMinTemp);
@@ -2963,7 +2963,7 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
buf.put((byte) forecastMinTemp); buf.put((byte) forecastMinTemp);
if (supportsConditionString) { if (supportsConditionString) {
buf.put(WeatherMapper.INSTANCE.getConditionString(getContext(), forecast.conditionCode).getBytes()); buf.put(WeatherMapper.INSTANCE.getConditionString(getContext(), forecast.getConditionCode()).getBytes());
buf.put((byte) 0); buf.put((byte) 0);
} }
} }
@@ -2983,11 +2983,11 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
TransactionBuilder builder; TransactionBuilder builder;
builder = performInitialized("Sending forecast location"); builder = performInitialized("Sending forecast location");
int length = 2 + weatherSpec.location.getBytes().length; int length = 2 + weatherSpec.getLocation().getBytes().length;
ByteBuffer buf = ByteBuffer.allocate(length); ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 8); buf.put((byte) 8);
buf.put(weatherSpec.location.getBytes()); buf.put(weatherSpec.getLocation().getBytes());
buf.put((byte) 0); buf.put((byte) 0);
@@ -3008,14 +3008,14 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
builder = performInitialized("Sending wind/humidity"); builder = performInitialized("Sending wind/humidity");
String windString = this.windSpeedString(weatherSpec); String windString = this.windSpeedString(weatherSpec);
String humidityString = weatherSpec.currentHumidity + "%"; String humidityString = weatherSpec.getCurrentHumidity() + "%";
int length = 8 + windString.getBytes().length + humidityString.getBytes().length; int length = 8 + windString.getBytes().length + humidityString.getBytes().length;
ByteBuffer buf = ByteBuffer.allocate(length); ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 64); buf.put((byte) 64);
buf.putInt(weatherSpec.timestamp); buf.putInt(weatherSpec.getTimestamp());
buf.put((byte) (tz_offset_hours * 4)); buf.put((byte) (tz_offset_hours * 4));
buf.put(windString.getBytes()); buf.put(windString.getBytes());
buf.put((byte) 0); buf.put((byte) 0);
@@ -3048,7 +3048,7 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
ByteBuffer buf = ByteBuffer.allocate(10); ByteBuffer buf = ByteBuffer.allocate(10);
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 16); buf.put((byte) 16);
buf.putInt(weatherSpec.timestamp); buf.putInt(weatherSpec.getTimestamp());
buf.put((byte) (tz_offset_hours * 4)); buf.put((byte) (tz_offset_hours * 4));
buf.put((byte) sunriseTransitSet.getSunrise().getHour()); buf.put((byte) sunriseTransitSet.getSunrise().getHour());
buf.put((byte) sunriseTransitSet.getSunrise().getMinute()); buf.put((byte) sunriseTransitSet.getSunrise().getMinute());
@@ -69,7 +69,7 @@ public class AmazfitBipSSupport extends AmazfitBipSupport {
@Override @Override
public String windSpeedString(WeatherSpec weatherSpec){ public String windSpeedString(WeatherSpec weatherSpec){
return weatherSpec.windSpeed + "km/h"; return weatherSpec.getWindSpeed() + "km/h";
} }
@Override @Override
@@ -198,9 +198,9 @@ public class ZeppOsWeatherHandler {
public List<Object> airQualities = new ArrayList<>(); public List<Object> airQualities = new ArrayList<>();
public ForecastResponse(final WeatherSpec weatherSpec, final int days, final boolean sunMoonInUtc) { public ForecastResponse(final WeatherSpec weatherSpec, final int days, final boolean sunMoonInUtc) {
final int actualDays = Math.min(weatherSpec.forecasts.size(), days - 1); // leave one slot for the first day final int actualDays = Math.min(weatherSpec.getForecasts().size(), days - 1); // leave one slot for the first day
pubTime = new Date(weatherSpec.timestamp * 1000L); pubTime = new Date(weatherSpec.getTimestamp() * 1000L);
final Calendar calendar = GregorianCalendar.getInstance(); final Calendar calendar = GregorianCalendar.getInstance();
calendar.setTime(pubTime); calendar.setTime(pubTime);
@@ -210,48 +210,48 @@ public class ZeppOsWeatherHandler {
sunriseDate.setTime(calendar.getTime()); sunriseDate.setTime(calendar.getTime());
// First one is for the current day // First one is for the current day
temperature.add(new Range(weatherSpec.todayMinTemp - 273, weatherSpec.todayMaxTemp - 273)); temperature.add(new Range(weatherSpec.getTodayMinTemp() - 273, weatherSpec.getTodayMaxTemp() - 273));
final String currentWeatherCode = String.valueOf(mapToZeppOsWeatherCode(weatherSpec.currentConditionCode)); final String currentWeatherCode = String.valueOf(mapToZeppOsWeatherCode(weatherSpec.getCurrentConditionCode()));
weather.add(new Range(currentWeatherCode, currentWeatherCode)); weather.add(new Range(currentWeatherCode, currentWeatherCode));
if (weatherSpec.sunRise != 0 && weatherSpec.sunSet != 0) { if (weatherSpec.getSunRise() != 0 && weatherSpec.getSunSet() != 0) {
sunRiseSet.add(getSunriseSunset(new Date(weatherSpec.sunRise * 1000L), new Date(weatherSpec.sunSet * 1000L), sunMoonInUtc)); sunRiseSet.add(getSunriseSunset(new Date(weatherSpec.getSunRise() * 1000L), new Date(weatherSpec.getSunSet() * 1000L), sunMoonInUtc));
} else if (weatherSpec.getLocation() != null) { } else if (weatherSpec.getLocationObject() != null) {
sunRiseSet.add(getSunriseSunset(sunriseDate, weatherSpec.getLocation(), sunMoonInUtc)); sunRiseSet.add(getSunriseSunset(sunriseDate, weatherSpec.getLocationObject(), sunMoonInUtc));
} else { } else {
sunRiseSet.add(getSunriseSunset(sunriseDate, lastKnownLocation, sunMoonInUtc)); sunRiseSet.add(getSunriseSunset(sunriseDate, lastKnownLocation, sunMoonInUtc));
} }
sunriseDate.add(Calendar.DAY_OF_MONTH, 1); sunriseDate.add(Calendar.DAY_OF_MONTH, 1);
windDirection.add(new Range(weatherSpec.windDirection, weatherSpec.windDirection)); windDirection.add(new Range(weatherSpec.getWindDirection(), weatherSpec.getWindDirection()));
windSpeed.add(new Range(Math.round(weatherSpec.windSpeed), Math.round(weatherSpec.windSpeed))); windSpeed.add(new Range(Math.round(weatherSpec.getWindSpeed()), Math.round(weatherSpec.getWindSpeed())));
moonRiseSet.add(weatherSpec.moonRise, weatherSpec.moonSet, weatherSpec.moonPhase, sunMoonInUtc); moonRiseSet.add(weatherSpec.getMoonRise(), weatherSpec.getMoonSet(), weatherSpec.getMoonPhase(), sunMoonInUtc);
for (int i = 0; i < actualDays; i++) { for (int i = 0; i < actualDays; i++) {
final WeatherSpec.Daily forecast = weatherSpec.forecasts.get(i); final WeatherSpec.Daily forecast = weatherSpec.getForecasts().get(i);
temperature.add(new Range(forecast.minTemp - 273, forecast.maxTemp - 273)); temperature.add(new Range(forecast.getMinTemp() - 273, forecast.getMaxTemp() - 273));
final String weatherCode = String.valueOf(mapToZeppOsWeatherCode(forecast.conditionCode)); final String weatherCode = String.valueOf(mapToZeppOsWeatherCode(forecast.getConditionCode()));
weather.add(new Range(weatherCode, weatherCode)); weather.add(new Range(weatherCode, weatherCode));
if (forecast.sunRise != 0 && forecast.sunSet != 0) { if (forecast.getSunRise() != 0 && forecast.getSunSet() != 0) {
sunRiseSet.add(getSunriseSunset(new Date(forecast.sunRise * 1000L), new Date(forecast.sunSet * 1000L), sunMoonInUtc)); sunRiseSet.add(getSunriseSunset(new Date(forecast.getSunRise() * 1000L), new Date(forecast.getSunSet() * 1000L), sunMoonInUtc));
} else { } else {
sunRiseSet.add(getSunriseSunset(sunriseDate, lastKnownLocation, sunMoonInUtc)); sunRiseSet.add(getSunriseSunset(sunriseDate, lastKnownLocation, sunMoonInUtc));
} }
sunriseDate.add(Calendar.DAY_OF_MONTH, 1); sunriseDate.add(Calendar.DAY_OF_MONTH, 1);
if (forecast.windDirection != -1) { if (forecast.getWindDirection() != -1) {
windDirection.add(new Range(forecast.windDirection, forecast.windDirection)); windDirection.add(new Range(forecast.getWindDirection(), forecast.getWindDirection()));
} else { } else {
windDirection.add(new Range(0, 0)); windDirection.add(new Range(0, 0));
} }
if (forecast.windSpeed != -1) { if (forecast.getWindSpeed() != -1) {
windSpeed.add(new Range(Math.round(forecast.windSpeed), Math.round(forecast.windSpeed))); windSpeed.add(new Range(Math.round(forecast.getWindSpeed()), Math.round(forecast.getWindSpeed())));
} else { } else {
windSpeed.add(new Range(0, 0)); windSpeed.add(new Range(0, 0));
} }
moonRiseSet.add(forecast.moonRise, forecast.moonSet, forecast.moonPhase, sunMoonInUtc); moonRiseSet.add(forecast.getMoonRise(), forecast.getMoonSet(), forecast.getMoonPhase(), sunMoonInUtc);
} }
} }
@@ -371,7 +371,7 @@ public class ZeppOsWeatherHandler {
public List<IndexEntry> dataList = new ArrayList<>(); public List<IndexEntry> dataList = new ArrayList<>();
public IndexResponse(final WeatherSpec weatherSpec, final int days) { public IndexResponse(final WeatherSpec weatherSpec, final int days) {
pubTime = new Date(weatherSpec.timestamp * 1000L); pubTime = new Date(weatherSpec.getTimestamp() * 1000L);
} }
public static class Serializer implements JsonSerializer<IndexResponse> { public static class Serializer implements JsonSerializer<IndexResponse> {
@@ -445,14 +445,14 @@ public class ZeppOsWeatherHandler {
public Wind wind; public Wind wind;
public CurrentWeatherModel(final WeatherSpec weatherSpec) { public CurrentWeatherModel(final WeatherSpec weatherSpec) {
humidity = new UnitValue(Unit.PERCENTAGE, weatherSpec.currentHumidity); humidity = new UnitValue(Unit.PERCENTAGE, weatherSpec.getCurrentHumidity());
pressure = new UnitValue(Unit.PRESSURE_MB, Math.round(weatherSpec.pressure)); pressure = new UnitValue(Unit.PRESSURE_MB, Math.round(weatherSpec.getPressure()));
pubTime = new Date(weatherSpec.timestamp * 1000L); pubTime = new Date(weatherSpec.getTimestamp() * 1000L);
temperature = new UnitValue(Unit.TEMPERATURE_C, weatherSpec.currentTemp - 273); temperature = new UnitValue(Unit.TEMPERATURE_C, weatherSpec.getCurrentTemp() - 273);
uvIndex = String.valueOf(Math.round(weatherSpec.uvIndex)); uvIndex = String.valueOf(Math.round(weatherSpec.getUvIndex()));
visibility = new UnitValue(Unit.KM, Math.round(weatherSpec.visibility / 1000)); visibility = new UnitValue(Unit.KM, Math.round(weatherSpec.getVisibility() / 1000));
weather = String.valueOf(mapToZeppOsWeatherCode(weatherSpec.currentConditionCode)); weather = String.valueOf(mapToZeppOsWeatherCode(weatherSpec.getCurrentConditionCode()));
wind = new Wind(weatherSpec.windDirection, Math.round(weatherSpec.windSpeed)); wind = new Wind(weatherSpec.getWindDirection(), Math.round(weatherSpec.getWindSpeed()));
} }
public static class Serializer implements JsonSerializer<CurrentWeatherModel> { public static class Serializer implements JsonSerializer<CurrentWeatherModel> {
@@ -483,18 +483,18 @@ public class ZeppOsWeatherHandler {
public String so2; // float public String so2; // float
public AqiModel(final WeatherSpec weatherSpec) { public AqiModel(final WeatherSpec weatherSpec) {
if (weatherSpec.airQuality == null) { if (weatherSpec.getAirQuality() == null) {
return; return;
} }
this.aqi = String.valueOf(weatherSpec.airQuality.aqi); this.aqi = String.valueOf(weatherSpec.getAirQuality().getAqi());
this.co = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.airQuality.coAqi); this.co = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.getAirQuality().getCoAqi());
this.no2 = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.airQuality.no2Aqi); this.no2 = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.getAirQuality().getNo2Aqi());
this.o3 = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.airQuality.o3Aqi); this.o3 = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.getAirQuality().getO3Aqi());
this.pm10 = String.valueOf(Math.round((float) weatherSpec.airQuality.pm10Aqi)); this.pm10 = String.valueOf(Math.round((float) weatherSpec.getAirQuality().getPm10Aqi()));
this.pm25 = String.valueOf(Math.round((float) weatherSpec.airQuality.pm25Aqi)); this.pm25 = String.valueOf(Math.round((float) weatherSpec.getAirQuality().getPm25Aqi()));
this.pubTime = new Date(weatherSpec.timestamp * 1000L); this.pubTime = new Date(weatherSpec.getTimestamp() * 1000L);
this.so2 = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.airQuality.so2Aqi); this.so2 = String.format(Locale.ROOT, "%.1f", (float) weatherSpec.getAirQuality().getSo2Aqi());
} }
public static class Serializer implements JsonSerializer<AqiModel> { public static class Serializer implements JsonSerializer<AqiModel> {
@@ -529,7 +529,7 @@ public class ZeppOsWeatherHandler {
public List<TideDataEntry> tideData = new ArrayList<>(); public List<TideDataEntry> tideData = new ArrayList<>();
public TideResponse(final WeatherSpec weatherSpec, int tideDays) { public TideResponse(final WeatherSpec weatherSpec, int tideDays) {
pubTime = new Date(weatherSpec.timestamp * 1000L); pubTime = new Date(weatherSpec.getTimestamp() * 1000L);
// Fill all entries, even if without data // Fill all entries, even if without data
final Calendar pubTimeDate = Calendar.getInstance(); final Calendar pubTimeDate = Calendar.getInstance();
@@ -678,9 +678,9 @@ public class ZeppOsWeatherHandler {
public List<String> windScale = new ArrayList<>(); // each element in the form of 1-2 public List<String> windScale = new ArrayList<>(); // each element in the form of 1-2
public HourlyResponse(final WeatherSpec weatherSpec, final int hours) { public HourlyResponse(final WeatherSpec weatherSpec, final int hours) {
pubTime = new Date(weatherSpec.timestamp * 1000L); pubTime = new Date(weatherSpec.getTimestamp() * 1000L);
if (weatherSpec.hourly == null || weatherSpec.hourly.isEmpty()) { if (weatherSpec.getHourly() == null || weatherSpec.getHourly().isEmpty()) {
// We don't have hourly data, but some devices refuse to open the weather app without it // We don't have hourly data, but some devices refuse to open the weather app without it
final Calendar fxTimeCalendar = Calendar.getInstance(); final Calendar fxTimeCalendar = Calendar.getInstance();
@@ -691,12 +691,12 @@ public class ZeppOsWeatherHandler {
fxTimeCalendar.add(Calendar.HOUR, 1); fxTimeCalendar.add(Calendar.HOUR, 1);
for (int i = 0; i < hours; i++) { for (int i = 0; i < hours; i++) {
weather.add(String.valueOf(mapToZeppOsWeatherCode(weatherSpec.currentConditionCode))); weather.add(String.valueOf(mapToZeppOsWeatherCode(weatherSpec.getCurrentConditionCode())));
temperature.add(String.valueOf(weatherSpec.currentTemp - 273)); temperature.add(String.valueOf(weatherSpec.getCurrentTemp() - 273));
humidity.add(String.valueOf(weatherSpec.currentHumidity)); humidity.add(String.valueOf(weatherSpec.getCurrentHumidity()));
fxTime.add(fxTimeCalendar.getTime()); fxTime.add(fxTimeCalendar.getTime());
windDirection.add(String.valueOf(weatherSpec.windDirection)); windDirection.add(String.valueOf(weatherSpec.getWindDirection()));
windSpeed.add(String.valueOf(Math.round(weatherSpec.windSpeed))); windSpeed.add(String.valueOf(Math.round(weatherSpec.getWindSpeed())));
windScale.add("1-2"); windScale.add("1-2");
fxTimeCalendar.add(Calendar.HOUR, 1); fxTimeCalendar.add(Calendar.HOUR, 1);
@@ -704,17 +704,17 @@ public class ZeppOsWeatherHandler {
} else { } else {
int i = 0; int i = 0;
for (final WeatherSpec.Hourly hourly : weatherSpec.hourly) { for (final WeatherSpec.Hourly hourly : weatherSpec.getHourly()) {
if (hourly.timestamp < weatherSpec.timestamp) { if (hourly.getTimestamp() < weatherSpec.getTimestamp()) {
continue; continue;
} }
weather.add(String.valueOf(mapToZeppOsWeatherCode(hourly.conditionCode))); weather.add(String.valueOf(mapToZeppOsWeatherCode(hourly.getConditionCode())));
temperature.add(String.valueOf(hourly.temp - 273)); temperature.add(String.valueOf(hourly.getTemp() - 273));
humidity.add(String.valueOf(hourly.humidity)); humidity.add(String.valueOf(hourly.getHumidity()));
fxTime.add(new Date(hourly.timestamp * 1000L)); fxTime.add(new Date(hourly.getTimestamp() * 1000L));
windDirection.add(String.valueOf(hourly.windDirection)); windDirection.add(String.valueOf(hourly.getWindDirection()));
windSpeed.add(String.valueOf(Math.round(hourly.windSpeed))); windSpeed.add(String.valueOf(Math.round(hourly.getWindSpeed())));
windScale.add(hourly.windSpeedAsBeaufort() + "-" + hourly.windSpeedAsBeaufort()); windScale.add(hourly.windSpeedAsBeaufort() + "-" + hourly.windSpeedAsBeaufort());
if (++i >= hours) { if (++i >= hours) {
@@ -274,15 +274,15 @@ public class ZeppOsAssistantService extends AbstractZeppOsService {
baos.write(0x00); // ? baos.write(0x00); // ?
baos.write(0x00); // ? baos.write(0x00); // ?
baos.write(BLETypeConversions.fromUint32(weather.timestamp)); baos.write(BLETypeConversions.fromUint32(weather.getTimestamp()));
baos.write(StringUtils.ensureNotNull(weather.location).getBytes(StandardCharsets.UTF_8)); baos.write(StringUtils.ensureNotNull(weather.getLocation()).getBytes(StandardCharsets.UTF_8));
baos.write(0); baos.write(0);
// FIXME long date string // FIXME long date string
baos.write(0); baos.write(0);
baos.write(StringUtils.ensureNotNull(weather.currentCondition).getBytes(StandardCharsets.UTF_8)); baos.write(StringUtils.ensureNotNull(weather.getCurrentCondition()).getBytes(StandardCharsets.UTF_8));
baos.write(0); baos.write(0);
// FIXME Second line for the condition // FIXME Second line for the condition
@@ -290,8 +290,8 @@ public class ZeppOsAssistantService extends AbstractZeppOsService {
// FIXME // FIXME
baos.write(weather.forecasts.size()); baos.write(weather.getForecasts().size());
for (final WeatherSpec.Daily forecast : weather.forecasts) { for (final WeatherSpec.Daily forecast : weather.getForecasts()) {
// FIXME // FIXME
} }
} catch (final IOException e) { } catch (final IOException e) {
@@ -64,7 +64,7 @@ public class ZeppOsWeatherService extends AbstractZeppOsService {
// TODO: Support for multiple weather locations // TODO: Support for multiple weather locations
final String locationKey = "1.234,-5.678,xiaomi_accu:" + System.currentTimeMillis(); // dummy final String locationKey = "1.234,-5.678,xiaomi_accu:" + System.currentTimeMillis(); // dummy
final String locationName = weatherSpec.location; final String locationName = weatherSpec.getLocation();
try { try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -152,42 +152,42 @@ public class HuaweiWeatherManager {
Date currentDay = DateTimeUtils.dayStart(DateTimeUtils.todayUTC()); Date currentDay = DateTimeUtils.dayStart(DateTimeUtils.todayUTC());
Date nextDay = DateTimeUtils.shiftByDays(currentDay, 1); Date nextDay = DateTimeUtils.shiftByDays(currentDay, 1);
if (timeOutOfDateInterval(weatherSpec.sunRise, currentDay, nextDay)) { if (timeOutOfDateInterval(weatherSpec.getSunRise(), currentDay, nextDay)) {
LOG.warn("Sun rise for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.sunRise)); LOG.warn("Sun rise for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.getSunRise()));
weatherSpec.sunRise = 0; weatherSpec.setSunRise(0);
} }
if (timeOutOfDateInterval(weatherSpec.sunSet, currentDay, nextDay)) { if (timeOutOfDateInterval(weatherSpec.getSunSet(), currentDay, nextDay)) {
LOG.warn("Sun set for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.sunSet)); LOG.warn("Sun set for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.getSunSet()));
weatherSpec.sunSet = 0; weatherSpec.setSunSet(0);
} }
if (timeOutOfDateInterval(weatherSpec.moonRise, currentDay, nextDay)) { if (timeOutOfDateInterval(weatherSpec.getMoonRise(), currentDay, nextDay)) {
LOG.warn("Moon rise for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.moonRise)); LOG.warn("Moon rise for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.getMoonRise()));
weatherSpec.moonRise = 0; weatherSpec.setMoonRise(0);
} }
if (timeOutOfDateInterval(weatherSpec.moonSet, currentDay, nextDay)) { if (timeOutOfDateInterval(weatherSpec.getMoonSet(), currentDay, nextDay)) {
LOG.warn("Moon set for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.moonSet)); LOG.warn("Moon set for today out of bounds: {}", DateTimeUtils.parseTimeStamp(weatherSpec.getMoonSet()));
weatherSpec.moonSet = 0; weatherSpec.setMoonSet(0);
} }
for (WeatherSpec.Daily point : weatherSpec.forecasts) { for (WeatherSpec.Daily point : weatherSpec.getForecasts()) {
currentDay = nextDay; currentDay = nextDay;
nextDay = DateTimeUtils.shiftByDays(currentDay, 1); nextDay = DateTimeUtils.shiftByDays(currentDay, 1);
if (timeOutOfDateInterval(point.sunRise, currentDay, nextDay)) { if (timeOutOfDateInterval(point.getSunRise(), currentDay, nextDay)) {
LOG.warn("Sun rise for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.sunRise)); LOG.warn("Sun rise for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.getSunRise()));
point.sunRise = 0; point.setSunRise(0);
} }
if (timeOutOfDateInterval(point.sunSet, currentDay, nextDay)) { if (timeOutOfDateInterval(point.getSunSet(), currentDay, nextDay)) {
LOG.warn("Sun set for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.sunSet)); LOG.warn("Sun set for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.getSunSet()));
point.sunSet = 0; point.setSunSet(0);
} }
if (timeOutOfDateInterval(point.moonRise, currentDay, nextDay)) { if (timeOutOfDateInterval(point.getMoonRise(), currentDay, nextDay)) {
LOG.warn("Moon rise for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.moonRise)); LOG.warn("Moon rise for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.getMoonRise()));
point.moonRise = 0; point.setMoonRise(0);
} }
if (timeOutOfDateInterval(point.moonSet, currentDay, nextDay)) { if (timeOutOfDateInterval(point.getMoonSet(), currentDay, nextDay)) {
LOG.warn("Moon set for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.moonSet)); LOG.warn("Moon set for {} out of bounds: {}", currentDay, DateTimeUtils.parseTimeStamp(point.getMoonSet()));
point.moonSet = 0; point.setMoonSet(0);
} }
} }
} }
@@ -47,25 +47,25 @@ public class SendWeatherCurrentRequest extends Request {
try { try {
Short pm25 = null; Short pm25 = null;
Short aqi = null; Short aqi = null;
if (weatherSpec.airQuality != null) { if (weatherSpec.getAirQuality() != null) {
pm25 = (short) weatherSpec.airQuality.pm25; // TODO: does this work? pm25 = (short) weatherSpec.getAirQuality().getPm25(); // TODO: does this work?
aqi = (short) weatherSpec.airQuality.aqi; aqi = (short) weatherSpec.getAirQuality().getAqi();
} }
return new Weather.CurrentWeatherRequest( return new Weather.CurrentWeatherRequest(
this.paramsProvider, this.paramsProvider,
settings, settings,
supportProvider.openWeatherMapConditionCodeToHuaweiIcon(weatherSpec.currentConditionCode), supportProvider.openWeatherMapConditionCodeToHuaweiIcon(weatherSpec.getCurrentConditionCode()),
(byte) weatherSpec.windDirection, (byte) weatherSpec.getWindDirection(),
(byte) weatherSpec.windSpeedAsBeaufort(), (byte) weatherSpec.windSpeedAsBeaufort(),
(byte) (weatherSpec.todayMinTemp - 273), (byte) (weatherSpec.getTodayMinTemp() - 273),
(byte) (weatherSpec.todayMaxTemp - 273), (byte) (weatherSpec.getTodayMaxTemp() - 273),
pm25, pm25,
weatherSpec.location, weatherSpec.getLocation(),
(byte) (weatherSpec.currentTemp - 273), (byte) (weatherSpec.getCurrentTemp() - 273),
temperatureFormat, temperatureFormat,
aqi, aqi,
weatherSpec.timestamp, weatherSpec.getTimestamp(),
weatherSpec.uvIndex, weatherSpec.getUvIndex(),
"Gadgetbridge" "Gadgetbridge"
).serialize(); ).serialize();
} catch (HuaweiPacket.CryptoException e) { } catch (HuaweiPacket.CryptoException e) {
@@ -39,45 +39,45 @@ public class SendWeatherForecastRequest extends Request {
@Override @Override
protected List<byte[]> createRequest() throws RequestCreationException { protected List<byte[]> createRequest() throws RequestCreationException {
int hourlyCount = Math.min(weatherSpec.hourly.size(), 24); int hourlyCount = Math.min(weatherSpec.getHourly().size(), 24);
int dayCount = Math.min(weatherSpec.forecasts.size() + 1, 8); // We add today as well int dayCount = Math.min(weatherSpec.getForecasts().size() + 1, 8); // We add today as well
ArrayList<WeatherForecastData.TimeData> timeDataArrayList = new ArrayList<>(hourlyCount); ArrayList<WeatherForecastData.TimeData> timeDataArrayList = new ArrayList<>(hourlyCount);
ArrayList<WeatherForecastData.DayData> dayDataArrayList = new ArrayList<>(dayCount); ArrayList<WeatherForecastData.DayData> dayDataArrayList = new ArrayList<>(dayCount);
for (int i = 0; i < hourlyCount; i++) { for (int i = 0; i < hourlyCount; i++) {
WeatherSpec.Hourly hourly = weatherSpec.hourly.get(i); WeatherSpec.Hourly hourly = weatherSpec.getHourly().get(i);
WeatherForecastData.TimeData timeData = new WeatherForecastData.TimeData(); WeatherForecastData.TimeData timeData = new WeatherForecastData.TimeData();
timeData.timestamp = hourly.timestamp; timeData.timestamp = hourly.getTimestamp();
timeData.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(hourly.conditionCode); timeData.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(hourly.getConditionCode());
timeData.temperature = (byte) (hourly.temp - 273); timeData.temperature = (byte) (hourly.getTemp() - 273);
timeDataArrayList.add(timeData); timeDataArrayList.add(timeData);
} }
// Add today as well // Add today as well
WeatherForecastData.DayData today = new WeatherForecastData.DayData(); WeatherForecastData.DayData today = new WeatherForecastData.DayData();
today.timestamp = weatherSpec.timestamp; today.timestamp = weatherSpec.getTimestamp();
today.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(weatherSpec.currentConditionCode); today.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(weatherSpec.getCurrentConditionCode());
today.highTemperature = (byte) (weatherSpec.todayMaxTemp - 273); today.highTemperature = (byte) (weatherSpec.getTodayMaxTemp() - 273);
today.lowTemperature = (byte) (weatherSpec.todayMinTemp - 273); today.lowTemperature = (byte) (weatherSpec.getTodayMinTemp() - 273);
today.sunriseTime = weatherSpec.sunRise; today.sunriseTime = weatherSpec.getSunRise();
today.sunsetTime = weatherSpec.sunSet; today.sunsetTime = weatherSpec.getSunSet();
today.moonRiseTime = weatherSpec.moonRise; today.moonRiseTime = weatherSpec.getMoonRise();
today.moonSetTime = weatherSpec.moonSet; today.moonSetTime = weatherSpec.getMoonSet();
today.moonPhase = Weather.degreesToMoonPhase(weatherSpec.moonPhase); today.moonPhase = Weather.degreesToMoonPhase(weatherSpec.getMoonPhase());
dayDataArrayList.add(today); dayDataArrayList.add(today);
for (int i = 0; i < dayCount - 1; i++) { for (int i = 0; i < dayCount - 1; i++) {
WeatherSpec.Daily daily = weatherSpec.forecasts.get(i); WeatherSpec.Daily daily = weatherSpec.getForecasts().get(i);
WeatherForecastData.DayData dayData = new WeatherForecastData.DayData(); WeatherForecastData.DayData dayData = new WeatherForecastData.DayData();
dayData.timestamp = weatherSpec.timestamp + (60*60*24 * (i + 1)); dayData.timestamp = weatherSpec.getTimestamp() + (60*60*24 * (i + 1));
dayData.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(daily.conditionCode); dayData.icon = supportProvider.openWeatherMapConditionCodeToHuaweiIcon(daily.getConditionCode());
dayData.highTemperature = (byte) (daily.maxTemp - 273); dayData.highTemperature = (byte) (daily.getMaxTemp() - 273);
dayData.lowTemperature = (byte) (daily.minTemp - 273); dayData.lowTemperature = (byte) (daily.getMinTemp() - 273);
dayData.sunriseTime = daily.sunRise; dayData.sunriseTime = daily.getSunRise();
dayData.sunsetTime = daily.sunSet; dayData.sunsetTime = daily.getSunSet();
dayData.moonRiseTime = daily.moonRise; dayData.moonRiseTime = daily.getMoonRise();
dayData.moonSetTime = daily.moonSet; dayData.moonSetTime = daily.getMoonSet();
dayData.moonPhase = Weather.degreesToMoonPhase(daily.moonPhase); dayData.moonPhase = Weather.degreesToMoonPhase(daily.getMoonPhase());
dayDataArrayList.add(dayData); dayDataArrayList.add(dayData);
} }
try { try {
@@ -1222,7 +1222,7 @@ public class WatchXPlusDeviceSupport extends AbstractBTLESingleDeviceSupport {
int todayMaxTemp; int todayMaxTemp;
byte[] command = WatchXPlusConstants.CMD_WEATHER_SET; byte[] command = WatchXPlusConstants.CMD_WEATHER_SET;
byte[] weatherInfo = new byte[5]; byte[] weatherInfo = new byte[5];
int currentCondition = weatherSpec.currentConditionCode; int currentCondition = weatherSpec.getCurrentConditionCode();
// set weather icon // set weather icon
int currentConditionCode = 0; // 0 is sunny int currentConditionCode = 0; // 0 is sunny
switch (currentCondition) { switch (currentCondition) {
@@ -1351,15 +1351,15 @@ public class WatchXPlusDeviceSupport extends AbstractBTLESingleDeviceSupport {
} }
LOG.info( " Weather cond: " + currentCondition + " icon: " + currentConditionCode); LOG.info( " Weather cond: " + currentCondition + " icon: " + currentConditionCode);
// calculate for temps under 0 // calculate for temps under 0
currentTemp = (Math.abs(weatherSpec.currentTemp)) - 273; currentTemp = (Math.abs(weatherSpec.getCurrentTemp())) - 273;
if (currentTemp < 0) { if (currentTemp < 0) {
currentTemp = (Math.abs(currentTemp) ^ 255) + 1; currentTemp = (Math.abs(currentTemp) ^ 255) + 1;
} }
todayMinTemp = (Math.abs(weatherSpec.todayMinTemp)) - 273; todayMinTemp = (Math.abs(weatherSpec.getTodayMinTemp())) - 273;
if (todayMinTemp < 0) { if (todayMinTemp < 0) {
todayMinTemp = (Math.abs(todayMinTemp) ^ 255) + 1; todayMinTemp = (Math.abs(todayMinTemp) ^ 255) + 1;
} }
todayMaxTemp = (Math.abs(weatherSpec.todayMaxTemp)) - 273; todayMaxTemp = (Math.abs(weatherSpec.getTodayMaxTemp())) - 273;
if (todayMaxTemp < 0) { if (todayMaxTemp < 0) {
todayMaxTemp = (Math.abs(todayMaxTemp) ^ 255) + 1; todayMaxTemp = (Math.abs(todayMaxTemp) ^ 255) + 1;
} }
@@ -2001,10 +2001,10 @@ public class MoyoungDeviceSupport extends AbstractBTLESingleDeviceSupport {
// Sunrise/sunset packet // Sunrise/sunset packet
Calendar sunrise = Calendar.getInstance(); Calendar sunrise = Calendar.getInstance();
sunrise.setTimeInMillis(weatherSpec.sunRise * 1000L); sunrise.setTimeInMillis(weatherSpec.getSunRise() * 1000L);
Calendar sunset = Calendar.getInstance(); Calendar sunset = Calendar.getInstance();
sunset.setTimeInMillis(weatherSpec.sunSet * 1000L); sunset.setTimeInMillis(weatherSpec.getSunSet() * 1000L);
ByteBuffer packetSunriseSunset = ByteBuffer.allocate(9 + weatherSpec.location.getBytes(StandardCharsets.UTF_8).length); ByteBuffer packetSunriseSunset = ByteBuffer.allocate(9 + weatherSpec.getLocation().getBytes(StandardCharsets.UTF_8).length);
packetSunriseSunset.put((byte) 0x00); packetSunriseSunset.put((byte) 0x00);
packetSunriseSunset.put(weatherToday.conditionId); packetSunriseSunset.put(weatherToday.conditionId);
packetSunriseSunset.put(weatherToday.currentTemp); packetSunriseSunset.put(weatherToday.currentTemp);
@@ -2013,13 +2013,13 @@ public class MoyoungDeviceSupport extends AbstractBTLESingleDeviceSupport {
packetSunriseSunset.put((byte) sunrise.get(Calendar.MINUTE)); packetSunriseSunset.put((byte) sunrise.get(Calendar.MINUTE));
packetSunriseSunset.put((byte) sunset.get(Calendar.HOUR_OF_DAY)); packetSunriseSunset.put((byte) sunset.get(Calendar.HOUR_OF_DAY));
packetSunriseSunset.put((byte) sunset.get(Calendar.MINUTE)); packetSunriseSunset.put((byte) sunset.get(Calendar.MINUTE));
packetSunriseSunset.put(weatherSpec.location.getBytes(StandardCharsets.UTF_8)); packetSunriseSunset.put(weatherSpec.getLocation().getBytes(StandardCharsets.UTF_8));
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_SET_SUNRISE_SUNSET, packetSunriseSunset.array())); sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_SET_SUNRISE_SUNSET, packetSunriseSunset.array()));
// Weather location packet. Prepend the update time to the location, since the watch can't display it separately // Weather location packet. Prepend the update time to the location, since the watch can't display it separately
Calendar updateTime = Calendar.getInstance(); Calendar updateTime = Calendar.getInstance();
updateTime.setTimeInMillis(weatherSpec.timestamp * 1000L); updateTime.setTimeInMillis(weatherSpec.getTimestamp() * 1000L);
String location = String.format(Locale.getDefault(), "%02d:%02d %s", updateTime.get(Calendar.HOUR_OF_DAY), updateTime.get(Calendar.MINUTE), weatherSpec.location); String location = String.format(Locale.getDefault(), "%02d:%02d %s", updateTime.get(Calendar.HOUR_OF_DAY), updateTime.get(Calendar.MINUTE), weatherSpec.getLocation());
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_SET_WEATHER_LOCATION, location.getBytes(StandardCharsets.UTF_8))); sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_SET_WEATHER_LOCATION, location.getBytes(StandardCharsets.UTF_8)));
// Weather forecast packet // Weather forecast packet
@@ -2029,8 +2029,8 @@ public class MoyoungDeviceSupport extends AbstractBTLESingleDeviceSupport {
packetWeatherForecast.put(weatherToday.currentTemp); packetWeatherForecast.put(weatherToday.currentTemp);
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
MoyoungWeatherForecast forecast; MoyoungWeatherForecast forecast;
if (weatherSpec.forecasts.size() > i) if (weatherSpec.getForecasts().size() > i)
forecast = new MoyoungWeatherForecast(weatherSpec.forecasts.get(i)); forecast = new MoyoungWeatherForecast(weatherSpec.getForecasts().get(i));
else else
forecast = new MoyoungWeatherForecast(MoyoungConstants.WEATHER_HAZE, (byte) -100, (byte) -100); // I don't think there is a way to send less (my watch shows only tomorrow anyway...) forecast = new MoyoungWeatherForecast(MoyoungConstants.WEATHER_HAZE, (byte) -100, (byte) -100); // I don't think there is a way to send less (my watch shows only tomorrow anyway...)
packetWeatherForecast.put(forecast.conditionId); packetWeatherForecast.put(forecast.conditionId);
@@ -56,8 +56,8 @@ class AppMessageHandlerHealthify extends AppMessageHandler {
} }
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<>(KEY_CONDITIONS, (Object) weatherSpec.currentCondition)); pairs.add(new Pair<>(KEY_CONDITIONS, (Object) weatherSpec.getCurrentCondition()));
pairs.add(new Pair<>(KEY_TEMPERATURE, (Object) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(KEY_TEMPERATURE, (Object) (weatherSpec.getCurrentTemp() - 273)));
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length); ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length);
@@ -125,16 +125,16 @@ class AppMessageHandlerM7S extends AppMessageHandler {
return null; return null;
} }
String wString1 = String.format(Locale.ENGLISH, "%.0f / %.0f__C \n%.0f %s", (weatherSpec.todayMaxTemp-273.15), (weatherSpec.todayMinTemp-273.15), weatherSpec.windSpeed, "km/h"); String wString1 = String.format(Locale.ENGLISH, "%.0f / %.0f__C \n%.0f %s", (weatherSpec.getTodayMaxTemp() -273.15), (weatherSpec.getTodayMinTemp() -273.15), weatherSpec.getWindSpeed(), "km/h");
String wString2 = String.format(Locale.ENGLISH, "%d %%", weatherSpec.currentHumidity); String wString2 = String.format(Locale.ENGLISH, "%d %%", weatherSpec.getCurrentHumidity());
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<>(KEY_LOCATION_NAME, (Object) (weatherSpec.location))); pairs.add(new Pair<>(KEY_LOCATION_NAME, (Object) (weatherSpec.getLocation())));
pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) ((int) Math.round(weatherSpec.currentTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) ((int) Math.round(weatherSpec.getCurrentTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_DATA_TIME, (Object) (weatherSpec.timestamp))); pairs.add(new Pair<>(KEY_WEATHER_DATA_TIME, (Object) (weatherSpec.getTimestamp())));
pairs.add(new Pair<>(KEY_WEATHER_STRING_1, (Object) (wString1))); pairs.add(new Pair<>(KEY_WEATHER_STRING_1, (Object) (wString1)));
pairs.add(new Pair<>(KEY_WEATHER_STRING_2, (Object) (wString2))); pairs.add(new Pair<>(KEY_WEATHER_STRING_2, (Object) (wString2)));
pairs.add(new Pair<>(KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.currentConditionCode)))); pairs.add(new Pair<>(KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.getCurrentConditionCode()))));
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length); ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length);
@@ -43,7 +43,7 @@ class AppMessageHandlerMarioTime extends AppMessageHandler {
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<>(KEY_WEATHER_ICON_ID, (Object) (byte) 1)); pairs.add(new Pair<>(KEY_WEATHER_ICON_ID, (Object) (byte) 1));
pairs.add(new Pair<>(KEY_WEATHER_TEMPERATURE, (Object) (byte) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(KEY_WEATHER_TEMPERATURE, (Object) (byte) (weatherSpec.getCurrentTemp() - 273)));
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length); ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length);
@@ -152,8 +152,8 @@ class AppMessageHandlerObsidian extends AppMessageHandler {
boolean isNight = false; //TODO: use the night icons when night boolean isNight = false; //TODO: use the night icons when night
pairs.add(new Pair<>(messageKeys.get("CONFIG_WEATHER_REFRESH"), (Object) 60)); pairs.add(new Pair<>(messageKeys.get("CONFIG_WEATHER_REFRESH"), (Object) 60));
pairs.add(new Pair<>(messageKeys.get("CONFIG_WEATHER_UNIT_LOCAL"), (Object) 1)); //celsius pairs.add(new Pair<>(messageKeys.get("CONFIG_WEATHER_UNIT_LOCAL"), (Object) 1)); //celsius
pairs.add(new Pair<>(messageKeys.get("MSG_KEY_WEATHER_ICON"), (Object) getIconForConditionCode(weatherSpec.currentConditionCode, isNight))); //celsius pairs.add(new Pair<>(messageKeys.get("MSG_KEY_WEATHER_ICON"), (Object) getIconForConditionCode(weatherSpec.getCurrentConditionCode(), isNight))); //celsius
pairs.add(new Pair<>(messageKeys.get("MSG_KEY_WEATHER_TEMP"), (Object) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(messageKeys.get("MSG_KEY_WEATHER_TEMP"), (Object) (weatherSpec.getCurrentTemp() - 273)));
return mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); return mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
} }
@@ -97,8 +97,8 @@ class AppMessageHandlerPebStyle extends AppMessageHandler {
if (weather != null) { if (weather != null) {
//comment the same key in the general section above! //comment the same key in the general section above!
pairs.add(new Pair<>(KEY_LOCATION_SERVICE, (Object) 0)); //0 auto, 1 manual pairs.add(new Pair<>(KEY_LOCATION_SERVICE, (Object) 0)); //0 auto, 1 manual
pairs.add(new Pair<>(KEY_WEATHER_CODE, (Object) WeatherMapper.INSTANCE.mapToYahooCondition(weather.currentConditionCode))); pairs.add(new Pair<>(KEY_WEATHER_CODE, (Object) WeatherMapper.INSTANCE.mapToYahooCondition(weather.getCurrentConditionCode())));
pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) (weather.currentTemp - 273))); pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) (weather.getCurrentTemp() - 273)));
} }
byte[] testMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] testMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
@@ -117,8 +117,8 @@ class AppMessageHandlerRealWeather extends AppMessageHandler {
} }
boolean isNight = false; // TODO boolean isNight = false; // TODO
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°", weatherSpec.currentTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°", weatherSpec.getCurrentTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.currentConditionCode, isNight)))); pairs.add(new Pair<>(KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.getCurrentConditionCode(), isNight))));
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length); ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length);
@@ -109,8 +109,8 @@ private int getConditionForConditionCode(int conditionCode) {
} }
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<>(KEY_TEMPERATURE, (Object) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(KEY_TEMPERATURE, (Object) (weatherSpec.getCurrentTemp() - 273)));
pairs.add(new Pair<>(KEY_CONDITION, (Object) (getConditionForConditionCode(weatherSpec.currentConditionCode)))); pairs.add(new Pair<>(KEY_CONDITION, (Object) (getConditionForConditionCode(weatherSpec.getCurrentConditionCode()))));
pairs.add(new Pair<>(KEY_ERR, (Object) 0)); pairs.add(new Pair<>(KEY_ERR, (Object) 0));
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
@@ -63,10 +63,10 @@ class AppMessageHandlerSquare extends AppMessageHandler {
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<>(CfgKeyWeatherMode, (Object) 1)); pairs.add(new Pair<>(CfgKeyWeatherMode, (Object) 1));
pairs.add(new Pair<>(CfgKeyConditions, (Object) weatherSpec.currentCondition)); pairs.add(new Pair<>(CfgKeyConditions, (Object) weatherSpec.getCurrentCondition()));
pairs.add(new Pair<>(CfgKeyUseCelsius, (Object) 1)); pairs.add(new Pair<>(CfgKeyUseCelsius, (Object) 1));
pairs.add(new Pair<>(CfgKeyCelsiusTemperature, (Object) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(CfgKeyCelsiusTemperature, (Object) (weatherSpec.getCurrentTemp() - 273)));
pairs.add(new Pair<>(CfgKeyWeatherLocation, (Object) (weatherSpec.location))); pairs.add(new Pair<>(CfgKeyWeatherLocation, (Object) (weatherSpec.getLocation())));
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length); ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length);
@@ -139,16 +139,16 @@ class AppMessageHandlerTimeStylePebble extends AppMessageHandler {
boolean isNight = false; //TODO: use the night icons when night boolean isNight = false; //TODO: use the night icons when night
pairs.add(new Pair<>(messageKeys.get("SettingUseMetric"), (Object) 1)); //celsius pairs.add(new Pair<>(messageKeys.get("SettingUseMetric"), (Object) 1)); //celsius
pairs.add(new Pair<>(messageKeys.get("WeatherUseNightIcon"), (Object) (isNight ? 1 : 0))); pairs.add(new Pair<>(messageKeys.get("WeatherUseNightIcon"), (Object) (isNight ? 1 : 0)));
pairs.add(new Pair<>(messageKeys.get("WeatherTemperature"), (Object) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(messageKeys.get("WeatherTemperature"), (Object) (weatherSpec.getCurrentTemp() - 273)));
pairs.add(new Pair<>(messageKeys.get("WeatherCondition"), (Object) (getIconForConditionCode(weatherSpec.currentConditionCode, isNight)))); pairs.add(new Pair<>(messageKeys.get("WeatherCondition"), (Object) (getIconForConditionCode(weatherSpec.getCurrentConditionCode(), isNight))));
if (weatherSpec.forecasts.size() > 0) { if (weatherSpec.getForecasts().size() > 0) {
WeatherSpec.Daily tomorrow = weatherSpec.forecasts.get(0); WeatherSpec.Daily tomorrow = weatherSpec.getForecasts().get(0);
pairs.add(new Pair<>(messageKeys.get("WeatherForecastCondition"), (Object) (getIconForConditionCode(tomorrow.conditionCode, isNight)))); pairs.add(new Pair<>(messageKeys.get("WeatherForecastCondition"), (Object) (getIconForConditionCode(tomorrow.getConditionCode(), isNight))));
} }
pairs.add(new Pair<>(messageKeys.get("WeatherForecastHighTemp"), (Object) (weatherSpec.todayMaxTemp - 273))); pairs.add(new Pair<>(messageKeys.get("WeatherForecastHighTemp"), (Object) (weatherSpec.getTodayMaxTemp() - 273)));
pairs.add(new Pair<>(messageKeys.get("WeatherForecastLowTemp"), (Object) (weatherSpec.todayMinTemp - 273))); pairs.add(new Pair<>(messageKeys.get("WeatherForecastLowTemp"), (Object) (weatherSpec.getTodayMinTemp() - 273)));
return mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); return mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
} }
@@ -83,12 +83,12 @@ class AppMessageHandlerTrekVolle extends AppMessageHandler {
boolean isNight = false; // FIXME boolean isNight = false; // FIXME
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>();
pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_TEMPERATURE, (Object) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_TEMPERATURE, (Object) (weatherSpec.getCurrentTemp() - 273)));
pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_CONDITIONS, (Object) (weatherSpec.currentCondition))); pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_CONDITIONS, (Object) (weatherSpec.getCurrentCondition())));
pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.currentConditionCode, isNight)))); pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.getCurrentConditionCode(), isNight))));
pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_TEMPERATURE_MAX, (Object) (weatherSpec.todayMaxTemp - 273))); pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_TEMPERATURE_MAX, (Object) (weatherSpec.getTodayMaxTemp() - 273)));
pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_TEMPERATURE_MIN, (Object) (weatherSpec.todayMinTemp - 273))); pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_TEMPERATURE_MIN, (Object) (weatherSpec.getTodayMinTemp() - 273)));
pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_LOCATION, (Object) weatherSpec.location)); pairs.add(new Pair<>(MESSAGE_KEY_WEATHER_LOCATION, (Object) weatherSpec.getLocation()));
return mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); return mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
@@ -192,30 +192,30 @@ class AppMessageHandlerYWeather extends AppMessageHandler {
} }
boolean isNight = false; // TODO boolean isNight = false; // TODO
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<>(KEY_LOCATION_NAME, (Object) (weatherSpec.location))); pairs.add(new Pair<>(KEY_LOCATION_NAME, (Object) (weatherSpec.getLocation())));
pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°", weatherSpec.currentTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_TEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°", weatherSpec.getCurrentTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_TODAY_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", weatherSpec.todayMinTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_TODAY_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", weatherSpec.getTodayMinTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_TODAY_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", weatherSpec.todayMaxTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_TODAY_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", weatherSpec.getTodayMaxTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.currentConditionCode, isNight)))); pairs.add(new Pair<>(KEY_WEATHER_ICON, (Object) (getIconForConditionCode(weatherSpec.getCurrentConditionCode(), isNight))));
pairs.add(new Pair<>(KEY_WEATHER_WIND_SPEED, (Object) (String.format(Locale.ENGLISH, "%.0f", weatherSpec.windSpeed)))); pairs.add(new Pair<>(KEY_WEATHER_WIND_SPEED, (Object) (String.format(Locale.ENGLISH, "%.0f", weatherSpec.getWindSpeed()))));
pairs.add(new Pair<>(KEY_WEATHER_WIND_DIRECTION, (Object) (formatWindDirection(weatherSpec.windDirection)))); pairs.add(new Pair<>(KEY_WEATHER_WIND_DIRECTION, (Object) (formatWindDirection(weatherSpec.getWindDirection()))));
if (weatherSpec.forecasts.size() > 0) { if (weatherSpec.getForecasts().size() > 0) {
WeatherSpec.Daily day1 = weatherSpec.forecasts.get(0); WeatherSpec.Daily day1 = weatherSpec.getForecasts().get(0);
pairs.add(new Pair<>(KEY_WEATHER_D1_ICON, (Object) (getIconForConditionCode(day1.conditionCode, false)))); pairs.add(new Pair<>(KEY_WEATHER_D1_ICON, (Object) (getIconForConditionCode(day1.getConditionCode(), false))));
pairs.add(new Pair<>(KEY_WEATHER_D1_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day1.minTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_D1_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day1.getMinTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_D1_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day1.maxTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_D1_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day1.getMaxTemp() - 273.15))));
} }
if (weatherSpec.forecasts.size() > 1) { if (weatherSpec.getForecasts().size() > 1) {
WeatherSpec.Daily day2 = weatherSpec.forecasts.get(1); WeatherSpec.Daily day2 = weatherSpec.getForecasts().get(1);
pairs.add(new Pair<>(KEY_WEATHER_D2_ICON, (Object) (getIconForConditionCode(day2.conditionCode, false)))); pairs.add(new Pair<>(KEY_WEATHER_D2_ICON, (Object) (getIconForConditionCode(day2.getConditionCode(), false))));
pairs.add(new Pair<>(KEY_WEATHER_D2_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day2.minTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_D2_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day2.getMinTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_D2_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day2.maxTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_D2_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day2.getMaxTemp() - 273.15))));
} }
if (weatherSpec.forecasts.size() > 2) { if (weatherSpec.getForecasts().size() > 2) {
WeatherSpec.Daily day3 = weatherSpec.forecasts.get(2); WeatherSpec.Daily day3 = weatherSpec.getForecasts().get(2);
pairs.add(new Pair<>(KEY_WEATHER_D3_ICON, (Object) (getIconForConditionCode(day3.conditionCode, false)))); pairs.add(new Pair<>(KEY_WEATHER_D3_ICON, (Object) (getIconForConditionCode(day3.getConditionCode(), false))));
pairs.add(new Pair<>(KEY_WEATHER_D3_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day3.minTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_D3_MINTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day3.getMinTemp() - 273.15))));
pairs.add(new Pair<>(KEY_WEATHER_D3_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day3.maxTemp - 273.15)))); pairs.add(new Pair<>(KEY_WEATHER_D3_MAXTEMP, (Object) (String.format(Locale.ENGLISH, "%.0f°C", day3.getMaxTemp() - 273.15))));
} }
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
@@ -70,8 +70,8 @@ class AppMessageHandlerZalewszczak extends AppMessageHandler {
} }
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(2);
pairs.add(new Pair<Integer, Object>(KEY_TEMP, weatherSpec.currentTemp - 273 + "C")); pairs.add(new Pair<Integer, Object>(KEY_TEMP, weatherSpec.getCurrentTemp() - 273 + "C"));
pairs.add(new Pair<Integer, Object>(KEY_ICON, getIconForConditionCode(weatherSpec.currentConditionCode))); pairs.add(new Pair<Integer, Object>(KEY_ICON, getIconForConditionCode(weatherSpec.getCurrentConditionCode())));
byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null); byte[] weatherMessage = mPebbleProtocol.encodeApplicationMessagePush(PebbleProtocol.ENDPOINT_APPLICATIONMESSAGE, mUUID, pairs, null);
ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length); ByteBuffer buf = ByteBuffer.allocate(weatherMessage.length);
@@ -1143,17 +1143,17 @@ public class PebbleProtocol extends GBDeviceProtocol {
private byte[] encodeWeatherForecast(WeatherSpec weatherSpec) { private byte[] encodeWeatherForecast(WeatherSpec weatherSpec) {
short currentTemp = (short) (weatherSpec.currentTemp - 273); short currentTemp = (short) (weatherSpec.getCurrentTemp() - 273);
short todayMax = (short) (weatherSpec.todayMaxTemp - 273); short todayMax = (short) (weatherSpec.getTodayMaxTemp() - 273);
short todayMin = (short) (weatherSpec.todayMinTemp - 273); short todayMin = (short) (weatherSpec.getTodayMinTemp() - 273);
short tomorrowMax = 0; short tomorrowMax = 0;
short tomorrowMin = 0; short tomorrowMin = 0;
int tomorrowConditionCode = 0; int tomorrowConditionCode = 0;
if (weatherSpec.forecasts.size() > 0) { if (weatherSpec.getForecasts().size() > 0) {
WeatherSpec.Daily tomorrow = weatherSpec.forecasts.get(0); WeatherSpec.Daily tomorrow = weatherSpec.getForecasts().get(0);
tomorrowMax = (short) (tomorrow.maxTemp - 273); tomorrowMax = (short) (tomorrow.getMaxTemp() - 273);
tomorrowMin = (short) (tomorrow.minTemp - 273); tomorrowMin = (short) (tomorrow.getMinTemp() - 273);
tomorrowConditionCode = tomorrow.conditionCode; tomorrowConditionCode = tomorrow.getConditionCode();
} }
String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric)); String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric));
@@ -1166,7 +1166,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
} }
final short WEATHER_FORECAST_LENGTH = 20; final short WEATHER_FORECAST_LENGTH = 20;
String[] parts = {weatherSpec.location, weatherSpec.currentCondition}; String[] parts = {weatherSpec.getLocation(), weatherSpec.getCurrentCondition()};
// Calculate length first // Calculate length first
short attributes_length = 0; short attributes_length = 0;
@@ -1183,13 +1183,13 @@ public class PebbleProtocol extends GBDeviceProtocol {
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 3); // unknown, always 3? buf.put((byte) 3); // unknown, always 3?
buf.putShort(currentTemp); buf.putShort(currentTemp);
buf.put(WeatherMapper.INSTANCE.mapToPebbleCondition(weatherSpec.currentConditionCode)); buf.put(WeatherMapper.INSTANCE.mapToPebbleCondition(weatherSpec.getCurrentConditionCode()));
buf.putShort(todayMax); buf.putShort(todayMax);
buf.putShort(todayMin); buf.putShort(todayMin);
buf.put(WeatherMapper.INSTANCE.mapToPebbleCondition(tomorrowConditionCode)); buf.put(WeatherMapper.INSTANCE.mapToPebbleCondition(tomorrowConditionCode));
buf.putShort(tomorrowMax); buf.putShort(tomorrowMax);
buf.putShort(tomorrowMin); buf.putShort(tomorrowMin);
buf.putInt(weatherSpec.timestamp); buf.putInt(weatherSpec.getTimestamp());
buf.put((byte) 0); // automatic location 0=manual 1=auto buf.put((byte) 0); // automatic location 0=manual 1=auto
buf.putShort(attributes_length); buf.putShort(attributes_length);
@@ -725,7 +725,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
} }
private void onSendWeatherCBOR(WeatherSpec weatherSpec) { private void onSendWeatherCBOR(WeatherSpec weatherSpec) {
if (weatherSpec.location != null) { if (weatherSpec.getLocation() != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -733,7 +733,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h
.put("EventType", WeatherData.EventType.Location.value) .put("EventType", WeatherData.EventType.Location.value)
.put("Location", weatherSpec.location) .put("Location", weatherSpec.getLocation())
.put("Altitude", 0) .put("Altitude", 0)
.put("Latitude", 0) .put("Latitude", 0)
.put("Longitude", 0) .put("Longitude", 0)
@@ -753,12 +753,12 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
} }
// Current condition // Current condition
if (weatherSpec.currentCondition != null) { if (weatherSpec.getCurrentCondition() != null) {
// We can't do anything with this? // We can't do anything with this?
} }
// Current humidity // Current humidity
if (weatherSpec.currentHumidity > 0) { if (weatherSpec.getCurrentHumidity() > 0) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -766,7 +766,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h this should be the weather provider's interval, really .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h this should be the weather provider's interval, really
.put("EventType", WeatherData.EventType.Humidity.value) .put("EventType", WeatherData.EventType.Humidity.value)
.put("Humidity", (int) weatherSpec.currentHumidity) .put("Humidity", (int) weatherSpec.getCurrentHumidity())
.end() .end()
.build() .build()
); );
@@ -783,7 +783,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
} }
// Current temperature // Current temperature
if (weatherSpec.currentTemp >= -273.15) { if (weatherSpec.getCurrentTemp() >= -273.15) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -791,7 +791,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h this should be the weather provider's interval, really .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h this should be the weather provider's interval, really
.put("EventType", WeatherData.EventType.Temperature.value) .put("EventType", WeatherData.EventType.Temperature.value)
.put("Temperature", (int) ((weatherSpec.currentTemp - 273.15) * 100)) .put("Temperature", (int) ((weatherSpec.getCurrentTemp() - 273.15) * 100))
.put("DewPoint", (int) (-32768)) .put("DewPoint", (int) (-32768))
.end() .end()
.build() .build()
@@ -839,7 +839,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
*/ */
// Wind speed // Wind speed
if (weatherSpec.windSpeed != 0.0f) { if (weatherSpec.getWindSpeed() != 0.0f) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -847,10 +847,10 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h
.put("EventType", WeatherData.EventType.Wind.value) .put("EventType", WeatherData.EventType.Wind.value)
.put("SpeedMin", (int) (weatherSpec.windSpeed / 60 / 60 * 1000)) .put("SpeedMin", (int) (weatherSpec.getWindSpeed() / 60 / 60 * 1000))
.put("SpeedMax", (int) (weatherSpec.windSpeed / 60 / 60 * 1000)) .put("SpeedMax", (int) (weatherSpec.getWindSpeed() / 60 / 60 * 1000))
.put("DirectionMin", (int) (0.71 * weatherSpec.windDirection)) .put("DirectionMin", (int) (0.71 * weatherSpec.getWindDirection()))
.put("DirectionMax", (int) (0.71 * weatherSpec.windDirection)) .put("DirectionMax", (int) (0.71 * weatherSpec.getWindDirection()))
.end() .end()
.build() .build()
); );
@@ -867,7 +867,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
} }
// Current weather condition // Current weather condition
if (mapOpenWeatherConditionToPineTimePrecipitation(weatherSpec.currentConditionCode) != WeatherData.PrecipitationType.Length) { if (mapOpenWeatherConditionToPineTimePrecipitation(weatherSpec.getCurrentConditionCode()) != WeatherData.PrecipitationType.Length) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -875,7 +875,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h
.put("EventType", WeatherData.EventType.Precipitation.value) .put("EventType", WeatherData.EventType.Precipitation.value)
.put("Type", (int) mapOpenWeatherConditionToPineTimePrecipitation(weatherSpec.currentConditionCode).value) .put("Type", (int) mapOpenWeatherConditionToPineTimePrecipitation(weatherSpec.getCurrentConditionCode()).value)
.put("Amount", (int) 0) .put("Amount", (int) 0)
.end() .end()
.build() .build()
@@ -892,7 +892,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
builder.queue(); builder.queue();
} }
if (mapOpenWeatherConditionToPineTimeObscuration(weatherSpec.currentConditionCode) != WeatherData.ObscurationType.Length) { if (mapOpenWeatherConditionToPineTimeObscuration(weatherSpec.getCurrentConditionCode()) != WeatherData.ObscurationType.Length) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -900,7 +900,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h
.put("EventType", WeatherData.EventType.Obscuration.value) .put("EventType", WeatherData.EventType.Obscuration.value)
.put("Type", (int) mapOpenWeatherConditionToPineTimeObscuration(weatherSpec.currentConditionCode).value) .put("Type", (int) mapOpenWeatherConditionToPineTimeObscuration(weatherSpec.getCurrentConditionCode()).value)
.put("Amount", (int) 65535) .put("Amount", (int) 65535)
.end() .end()
.build() .build()
@@ -917,7 +917,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
builder.queue(); builder.queue();
} }
if (mapOpenWeatherConditionToPineTimeSpecial(weatherSpec.currentConditionCode) != WeatherData.SpecialType.Length) { if (mapOpenWeatherConditionToPineTimeSpecial(weatherSpec.getCurrentConditionCode()) != WeatherData.SpecialType.Length) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -925,7 +925,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h
.put("EventType", WeatherData.EventType.Special.value) .put("EventType", WeatherData.EventType.Special.value)
.put("Type", mapOpenWeatherConditionToPineTimeSpecial(weatherSpec.currentConditionCode).value) .put("Type", mapOpenWeatherConditionToPineTimeSpecial(weatherSpec.getCurrentConditionCode()).value)
.end() .end()
.build() .build()
); );
@@ -941,7 +941,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
builder.queue(); builder.queue();
} }
if (mapOpenWeatherConditionToCloudCover(weatherSpec.currentConditionCode) != -1) { if (mapOpenWeatherConditionToCloudCover(weatherSpec.getCurrentConditionCode()) != -1) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
new CborEncoder(baos).encode(new CborBuilder() new CborEncoder(baos).encode(new CborBuilder()
@@ -949,7 +949,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
.put("Timestamp", System.currentTimeMillis() / 1000L) .put("Timestamp", System.currentTimeMillis() / 1000L)
.put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h .put("Expires", 60 * 60 * 1 + WEATHER_GRACE_TIME) // 1h
.put("EventType", WeatherData.EventType.Clouds.value) .put("EventType", WeatherData.EventType.Clouds.value)
.put("Amount", (int) (mapOpenWeatherConditionToCloudCover(weatherSpec.currentConditionCode))) .put("Amount", (int) (mapOpenWeatherConditionToCloudCover(weatherSpec.getCurrentConditionCode())))
.end() .end()
.build() .build()
); );
@@ -969,20 +969,20 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
} }
private void onSendWeatherSimple(WeatherSpec weatherSpec) { private void onSendWeatherSimple(WeatherSpec weatherSpec) {
long timestampLocal = weatherSpec.timestamp + Calendar.getInstance().getTimeZone().getOffset(Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis()) / 1000L; long timestampLocal = weatherSpec.getTimestamp() + Calendar.getInstance().getTimeZone().getOffset(Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis()) / 1000L;
ByteBuffer currentPacket = ByteBuffer.allocate(49).order(ByteOrder.LITTLE_ENDIAN); ByteBuffer currentPacket = ByteBuffer.allocate(49).order(ByteOrder.LITTLE_ENDIAN);
currentPacket.putLong(2, timestampLocal); currentPacket.putLong(2, timestampLocal);
currentPacket.putShort(10, (short) ((weatherSpec.currentTemp - 273.15) * 100)); currentPacket.putShort(10, (short) ((weatherSpec.getCurrentTemp() - 273.15) * 100));
currentPacket.putShort(12, (short) ((weatherSpec.todayMinTemp - 273.15) * 100)); currentPacket.putShort(12, (short) ((weatherSpec.getTodayMinTemp() - 273.15) * 100));
currentPacket.putShort(14, (short) ((weatherSpec.todayMaxTemp - 273.15) * 100)); currentPacket.putShort(14, (short) ((weatherSpec.getTodayMaxTemp() - 273.15) * 100));
if (weatherSpec.location != null) { if (weatherSpec.getLocation() != null) {
byte[] locationBytes = nodomain.freeyourgadget.gadgetbridge.util.StringUtils.truncateToBytes(weatherSpec.location, 32); byte[] locationBytes = nodomain.freeyourgadget.gadgetbridge.util.StringUtils.truncateToBytes(weatherSpec.getLocation(), 32);
for (int i = 0; i < locationBytes.length; i++) { for (int i = 0; i < locationBytes.length; i++) {
currentPacket.put(16 + i, locationBytes[i]); currentPacket.put(16 + i, locationBytes[i]);
} }
} }
currentPacket.put(48, mapOpenWeatherConditionToPineTimeCondition(weatherSpec.currentConditionCode).value); currentPacket.put(48, mapOpenWeatherConditionToPineTimeCondition(weatherSpec.getCurrentConditionCode()).value);
TransactionBuilder currentBuilder = createTransactionBuilder("SimpleWeatherData"); TransactionBuilder currentBuilder = createTransactionBuilder("SimpleWeatherData");
safeWriteToCharacteristic(currentBuilder, safeWriteToCharacteristic(currentBuilder,
@@ -991,19 +991,19 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
currentBuilder.queue(); currentBuilder.queue();
if (weatherSpec.forecasts == null) { if (weatherSpec.getForecasts() == null) {
return; return;
} }
ByteBuffer forecastPacket = ByteBuffer.allocate(36).order(ByteOrder.LITTLE_ENDIAN); ByteBuffer forecastPacket = ByteBuffer.allocate(36).order(ByteOrder.LITTLE_ENDIAN);
forecastPacket.put(0, (byte) 1); forecastPacket.put(0, (byte) 1);
forecastPacket.putLong(2, timestampLocal); forecastPacket.putLong(2, timestampLocal);
byte nbDays = (byte) Math.min(weatherSpec.forecasts.size(), 5); byte nbDays = (byte) Math.min(weatherSpec.getForecasts().size(), 5);
forecastPacket.put(10, nbDays); forecastPacket.put(10, nbDays);
for (int i = 0; i < nbDays; i++) { for (int i = 0; i < nbDays; i++) {
forecastPacket.putShort(11 + i * 5, (short) ((weatherSpec.forecasts.get(i).minTemp - 273.15) * 100)); forecastPacket.putShort(11 + i * 5, (short) ((weatherSpec.getForecasts().get(i).getMinTemp() - 273.15) * 100));
forecastPacket.putShort(11 + i * 5 + 2, (short) ((weatherSpec.forecasts.get(i).maxTemp - 273.15) * 100)); forecastPacket.putShort(11 + i * 5 + 2, (short) ((weatherSpec.getForecasts().get(i).getMaxTemp() - 273.15) * 100));
forecastPacket.put(11 + i * 5 + 4, mapOpenWeatherConditionToPineTimeCondition(weatherSpec.forecasts.get(i).conditionCode).value); forecastPacket.put(11 + i * 5 + 4, mapOpenWeatherConditionToPineTimeCondition(weatherSpec.getForecasts().get(i).getConditionCode()).value);
} }
TransactionBuilder forecastBuilder = createTransactionBuilder("SimpleWeatherData"); TransactionBuilder forecastBuilder = createTransactionBuilder("SimpleWeatherData");
@@ -1497,10 +1497,10 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override @Override
public void onSendWeather(WeatherSpec weatherSpec) { public void onSendWeather(WeatherSpec weatherSpec) {
boolean isNight = false; boolean isNight = false;
if (weatherSpec.sunRise != 0 && weatherSpec.sunSet != 0) { if (weatherSpec.getSunRise() != 0 && weatherSpec.getSunSet() != 0) {
isNight = weatherSpec.sunRise * 1000L > System.currentTimeMillis() || weatherSpec.sunSet * 1000L < System.currentTimeMillis(); isNight = weatherSpec.getSunRise() * 1000L > System.currentTimeMillis() || weatherSpec.getSunSet() * 1000L < System.currentTimeMillis();
} else { } else {
Location location = weatherSpec.getLocation(); Location location = weatherSpec.getLocationObject();
if (location == null) { if (location == null) {
location = new CurrentPosition().getLastKnownLocation(); location = new CurrentPosition().getLastKnownLocation();
} }
@@ -1526,8 +1526,8 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
.put("weatherInfo", new JSONObject() .put("weatherInfo", new JSONObject()
.put("alive", ts + 60 * 60) .put("alive", ts + 60 * 60)
.put("unit", "c") // FIXME: do not hardcode .put("unit", "c") // FIXME: do not hardcode
.put("temp", weatherSpec.currentTemp - 273) .put("temp", weatherSpec.getCurrentTemp() - 273)
.put("cond_id", getIconForConditionCode(weatherSpec.currentConditionCode, isNight)) .put("cond_id", getIconForConditionCode(weatherSpec.getCurrentConditionCode(), isNight))
) )
) )
); );
@@ -1537,16 +1537,16 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
JSONArray forecastWeekArray = new JSONArray(); JSONArray forecastWeekArray = new JSONArray();
final String[] weekdays = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; final String[] weekdays = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(weatherSpec.timestamp * 1000L); cal.setTimeInMillis(weatherSpec.getTimestamp() * 1000L);
int i = 0; int i = 0;
for (WeatherSpec.Daily forecast : weatherSpec.forecasts) { for (WeatherSpec.Daily forecast : weatherSpec.getForecasts()) {
cal.add(Calendar.DATE, 1); cal.add(Calendar.DATE, 1);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
forecastWeekArray.put(new JSONObject() forecastWeekArray.put(new JSONObject()
.put("day", weekdays[dayOfWeek]) .put("day", weekdays[dayOfWeek])
.put("cond_id", getIconForConditionCode(forecast.conditionCode, false)) .put("cond_id", getIconForConditionCode(forecast.getConditionCode(), false))
.put("high", forecast.maxTemp - 273) .put("high", forecast.getMaxTemp() - 273)
.put("low", forecast.minTemp - 273) .put("low", forecast.getMinTemp() - 273)
); );
if (++i == 3) break; // max 3 if (++i == 3) break; // max 3
} }
@@ -1569,15 +1569,15 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
.put("weatherApp._.config.locations", new JSONArray() .put("weatherApp._.config.locations", new JSONArray()
.put(new JSONObject() .put(new JSONObject()
.put("alive", ts + 60 * 60) .put("alive", ts + 60 * 60)
.put("city", weatherSpec.location) .put("city", weatherSpec.getLocation())
.put("unit", "c") // FIXME: do not hardcode .put("unit", "c") // FIXME: do not hardcode
.put("temp", weatherSpec.currentTemp - 273) .put("temp", weatherSpec.getCurrentTemp() - 273)
.put("high", weatherSpec.todayMaxTemp - 273) .put("high", weatherSpec.getTodayMaxTemp() - 273)
.put("low", weatherSpec.todayMinTemp - 273) .put("low", weatherSpec.getTodayMinTemp() - 273)
.put("rain", weatherSpec.precipProbability) .put("rain", weatherSpec.getPrecipProbability())
.put("uv", Math.round(weatherSpec.uvIndex)) .put("uv", Math.round(weatherSpec.getUvIndex()))
.put("message", weatherSpec.currentCondition) .put("message", weatherSpec.getCurrentCondition())
.put("cond_id", getIconForConditionCode(weatherSpec.currentConditionCode, isNight)) .put("cond_id", getIconForConditionCode(weatherSpec.getCurrentConditionCode(), isNight))
.put("forecast_day", forecastDayArray) .put("forecast_day", forecastDayArray)
.put("forecast_week", forecastWeekArray) .put("forecast_week", forecastWeekArray)
) )
@@ -1601,7 +1601,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
.put("set", new JSONObject() .put("set", new JSONObject()
.put("widgetChanceOfRain._.config.info", new JSONObject() .put("widgetChanceOfRain._.config.info", new JSONObject()
.put("alive", ts + 60 * 15) .put("alive", ts + 60 * 15)
.put("rain", weatherSpec.precipProbability) .put("rain", weatherSpec.getPrecipProbability())
) )
) )
); );
@@ -1621,7 +1621,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
.put("set", new JSONObject() .put("set", new JSONObject()
.put("widgetUV._.config.info", new JSONObject() .put("widgetUV._.config.info", new JSONObject()
.put("alive", ts + 60 * 15) .put("alive", ts + 60 * 15)
.put("uv", Math.round(weatherSpec.uvIndex)) .put("uv", Math.round(weatherSpec.getUvIndex()))
) )
) )
); );
@@ -601,22 +601,22 @@ public class SonyWena3DeviceSupport extends AbstractBTLESingleDeviceSupport {
@Override @Override
public void onSendWeather(ArrayList<WeatherSpec> weatherSpecs) { public void onSendWeather(ArrayList<WeatherSpec> weatherSpecs) {
WeatherSpec weatherSpec = weatherSpecs.get(0); WeatherSpec weatherSpec = weatherSpecs.get(0);
if(weatherSpec.forecasts.size() < 4) return; if(weatherSpec.getForecasts().size() < 4) return;
ArrayList<WeatherDay> days = new ArrayList<>(); ArrayList<WeatherDay> days = new ArrayList<>();
// Add today // Add today
days.add( days.add(
new WeatherDay( new WeatherDay(
Weather.fromOpenWeatherMap(weatherSpec.currentConditionCode), Weather.fromOpenWeatherMap(weatherSpec.getCurrentConditionCode()),
Weather.fromOpenWeatherMap(weatherSpec.currentConditionCode), Weather.fromOpenWeatherMap(weatherSpec.getCurrentConditionCode()),
weatherSpec.todayMaxTemp, weatherSpec.getTodayMaxTemp(),
weatherSpec.todayMinTemp weatherSpec.getTodayMinTemp()
) )
); );
// Add other days // Add other days
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
days.add(WeatherDay.fromSpec(weatherSpec.forecasts.get(i))); days.add(WeatherDay.fromSpec(weatherSpec.getForecasts().get(i)));
} }
WeatherReport report = new WeatherReport(days); WeatherReport report = new WeatherReport(days);
@@ -36,10 +36,10 @@ public class WeatherDay {
public static WeatherDay fromSpec(WeatherSpec.Daily daily) { public static WeatherDay fromSpec(WeatherSpec.Daily daily) {
return new WeatherDay( return new WeatherDay(
Weather.fromOpenWeatherMap(daily.conditionCode), Weather.fromOpenWeatherMap(daily.getConditionCode()),
Weather.fromOpenWeatherMap(daily.conditionCode), Weather.fromOpenWeatherMap(daily.getConditionCode()),
daily.maxTemp, daily.getMaxTemp(),
daily.minTemp daily.getMinTemp()
); );
} }
} }
@@ -380,12 +380,12 @@ public class WaspOSDeviceSupport extends AbstractBTLESingleDeviceSupport {
try { try {
JSONObject o = new JSONObject(); JSONObject o = new JSONObject();
o.put("t", "weather"); o.put("t", "weather");
o.put("temp", weatherSpec.currentTemp); o.put("temp", weatherSpec.getCurrentTemp());
o.put("hum", weatherSpec.currentHumidity); o.put("hum", weatherSpec.getCurrentHumidity());
o.put("code", weatherSpec.currentConditionCode); o.put("code", weatherSpec.getCurrentConditionCode());
o.put("txt", weatherSpec.currentCondition); o.put("txt", weatherSpec.getCurrentCondition());
o.put("wind", weatherSpec.windSpeed); o.put("wind", weatherSpec.getWindSpeed());
o.put("loc", weatherSpec.location); o.put("loc", weatherSpec.getLocation());
uartTxJSON("onSendWeather", o); uartTxJSON("onSendWeather", o);
} catch (JSONException e) { } catch (JSONException e) {
LOG.info("JSONException: " + e.getLocalizedMessage()); LOG.info("JSONException: " + e.getLocalizedMessage());
@@ -245,20 +245,20 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
} }
private static XiaomiProto.WeatherMetadata getWeatherMetaFromSpec(final WeatherSpec weatherSpec) { private static XiaomiProto.WeatherMetadata getWeatherMetaFromSpec(final WeatherSpec weatherSpec) {
final String location = StringUtils.ensureNotNull(weatherSpec.location); final String location = StringUtils.ensureNotNull(weatherSpec.getLocation());
return XiaomiProto.WeatherMetadata.newBuilder() return XiaomiProto.WeatherMetadata.newBuilder()
.setPublicationTimestamp(unixTimestampToISOWithColons(weatherSpec.timestamp)) .setPublicationTimestamp(unixTimestampToISOWithColons(weatherSpec.getTimestamp()))
.setCityName("") .setCityName("")
.setLocationName(location) .setLocationName(location)
.setLocationKey(getLocationKey(location)) // FIXME: placeholder because key is not present in spec .setLocationKey(getLocationKey(location)) // FIXME: placeholder because key is not present in spec
.setIsCurrentLocation(weatherSpec.isCurrentLocation == 1) .setIsCurrentLocation(weatherSpec.getIsCurrentLocation() == 1)
.build(); .build();
} }
private static XiaomiProto.WeatherLocation getWeatherLocationFromSpec(final WeatherSpec weatherSpec) { private static XiaomiProto.WeatherLocation getWeatherLocationFromSpec(final WeatherSpec weatherSpec) {
return XiaomiProto.WeatherLocation.newBuilder() return XiaomiProto.WeatherLocation.newBuilder()
.setCode(getLocationKey(weatherSpec.location)) .setCode(getLocationKey(weatherSpec.getLocation()))
.setName(StringUtils.ensureNotNull(weatherSpec.location)) .setName(StringUtils.ensureNotNull(weatherSpec.getLocation()))
.build(); .build();
} }
@@ -289,7 +289,7 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
} }
public void sendCurrentConditions(final WeatherSpec weatherSpec) { public void sendCurrentConditions(final WeatherSpec weatherSpec) {
LOG.debug("Sending current weather conditions for {}", weatherSpec.location); LOG.debug("Sending current weather conditions for {}", weatherSpec.getLocation());
XiaomiProto.Command command = XiaomiProto.Command.newBuilder() XiaomiProto.Command command = XiaomiProto.Command.newBuilder()
.setType(COMMAND_TYPE) .setType(COMMAND_TYPE)
@@ -297,17 +297,17 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
.setWeather(XiaomiProto.Weather.newBuilder().setCurrent( .setWeather(XiaomiProto.Weather.newBuilder().setCurrent(
XiaomiProto.WeatherCurrent.newBuilder() XiaomiProto.WeatherCurrent.newBuilder()
.setMetadata(getWeatherMetaFromSpec(weatherSpec)) .setMetadata(getWeatherMetaFromSpec(weatherSpec))
.setWeatherCondition(XiaomiWeatherConditions.convertOwmConditionToXiaomi(weatherSpec.currentConditionCode)) .setWeatherCondition(XiaomiWeatherConditions.convertOwmConditionToXiaomi(weatherSpec.getCurrentConditionCode()))
.setTemperature(buildUnitValue(weatherSpec.currentTemp - 273, "")) .setTemperature(buildUnitValue(weatherSpec.getCurrentTemp() - 273, ""))
.setHumidity(buildUnitValue(weatherSpec.currentHumidity, "%")) .setHumidity(buildUnitValue(weatherSpec.getCurrentHumidity(), "%"))
.setWind(buildUnitValue(weatherSpec.windSpeedAsBeaufort(), Integer.toString(weatherSpec.windDirection))) .setWind(buildUnitValue(weatherSpec.windSpeedAsBeaufort(), Integer.toString(weatherSpec.getWindDirection())))
.setUv(buildUnitValue(Math.round(weatherSpec.uvIndex), "")) // This is sent as an sint but seems to be displayed with a decimal point .setUv(buildUnitValue(Math.round(weatherSpec.getUvIndex()), "")) // This is sent as an sint but seems to be displayed with a decimal point
.setAqi(buildUnitValue( .setAqi(buildUnitValue(
weatherSpec.airQuality != null && weatherSpec.airQuality.aqi >= 0 ? weatherSpec.airQuality.aqi : 0, weatherSpec.getAirQuality() != null && weatherSpec.getAirQuality().getAqi() >= 0 ? weatherSpec.getAirQuality().getAqi() : 0,
"Unknown" // some string like "Moderate" "Unknown" // some string like "Moderate"
)) ))
.setWarning(XiaomiProto.WeatherWarnings.newBuilder()) // TODO add warnings when they become available through spec .setWarning(XiaomiProto.WeatherWarnings.newBuilder()) // TODO add warnings when they become available through spec
.setPressure(weatherSpec.pressure * 100f) .setPressure(weatherSpec.getPressure() * 100f)
)) ))
.build(); .build();
@@ -316,47 +316,47 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
public void sendDailyForecast(final WeatherSpec weatherSpec) { public void sendDailyForecast(final WeatherSpec weatherSpec) {
final XiaomiProto.ForecastEntries.Builder entryListBuilder = XiaomiProto.ForecastEntries.newBuilder(); final XiaomiProto.ForecastEntries.Builder entryListBuilder = XiaomiProto.ForecastEntries.newBuilder();
final int daysToSend = Math.min(6, weatherSpec.forecasts.size()); final int daysToSend = Math.min(6, weatherSpec.getForecasts().size());
// reconstruct first forecast element from current conditions, as the first forecast // reconstruct first forecast element from current conditions, as the first forecast
// is expected to apply to today // is expected to apply to today
{ {
entryListBuilder.addEntry(XiaomiProto.ForecastEntry.newBuilder() entryListBuilder.addEntry(XiaomiProto.ForecastEntry.newBuilder()
.setAqi(buildUnitValue( .setAqi(buildUnitValue(
weatherSpec.airQuality != null && weatherSpec.airQuality.aqi >= 0 ? weatherSpec.airQuality.aqi : 0, weatherSpec.getAirQuality() != null && weatherSpec.getAirQuality().getAqi() >= 0 ? weatherSpec.getAirQuality().getAqi() : 0,
"Unknown" // TODO describe AQI level "Unknown" // TODO describe AQI level
)) ))
.setTemperatureRange(XiaomiProto.WeatherRange.newBuilder() .setTemperatureRange(XiaomiProto.WeatherRange.newBuilder()
.setFrom(weatherSpec.todayMinTemp - 273) .setFrom(weatherSpec.getTodayMinTemp() - 273)
.setTo(weatherSpec.todayMaxTemp - 273)) .setTo(weatherSpec.getTodayMaxTemp() - 273))
// FIXME: should preferable be replaced with a best and worst case condition whenever that becomes available // FIXME: should preferable be replaced with a best and worst case condition whenever that becomes available
.setConditionRange(XiaomiProto.WeatherRange.newBuilder() .setConditionRange(XiaomiProto.WeatherRange.newBuilder()
.setFrom(XiaomiWeatherConditions.convertOwmConditionToXiaomi(weatherSpec.currentConditionCode)) .setFrom(XiaomiWeatherConditions.convertOwmConditionToXiaomi(weatherSpec.getCurrentConditionCode()))
.setTo(XiaomiWeatherConditions.convertOwmConditionToXiaomi(weatherSpec.currentConditionCode))) .setTo(XiaomiWeatherConditions.convertOwmConditionToXiaomi(weatherSpec.getCurrentConditionCode())))
.setTemperatureSymbol("") .setTemperatureSymbol("")
.setSunriseSunset(XiaomiProto.WeatherSunriseSunset.newBuilder() .setSunriseSunset(XiaomiProto.WeatherSunriseSunset.newBuilder()
.setSunrise(weatherSpec.sunRise != 0 ? unixTimestampToISOWithColons(weatherSpec.sunRise) : "") .setSunrise(weatherSpec.getSunRise() != 0 ? unixTimestampToISOWithColons(weatherSpec.getSunRise()) : "")
.setSunset(weatherSpec.sunSet != 0 ? unixTimestampToISOWithColons(weatherSpec.sunSet) : ""))); .setSunset(weatherSpec.getSunSet() != 0 ? unixTimestampToISOWithColons(weatherSpec.getSunSet()) : "")));
} }
// loop over available forecast entries in weatherSpec // loop over available forecast entries in weatherSpec
for (WeatherSpec.Daily currentEntry : weatherSpec.forecasts.subList(0, daysToSend)) { for (WeatherSpec.Daily currentEntry : weatherSpec.getForecasts().subList(0, daysToSend)) {
entryListBuilder.addEntry(XiaomiProto.ForecastEntry.newBuilder() entryListBuilder.addEntry(XiaomiProto.ForecastEntry.newBuilder()
.setAqi(buildUnitValue( .setAqi(buildUnitValue(
currentEntry.airQuality != null && currentEntry.airQuality.aqi >= 0 ? currentEntry.airQuality.aqi : 0, currentEntry.getAirQuality() != null && currentEntry.getAirQuality().getAqi() >= 0 ? currentEntry.getAirQuality().getAqi() : 0,
"Unknown" // TODO describe AQI level "Unknown" // TODO describe AQI level
)) ))
// FIXME should preferable be replaced with a best and worst case condition whenever that becomes available // FIXME should preferable be replaced with a best and worst case condition whenever that becomes available
.setConditionRange(XiaomiProto.WeatherRange.newBuilder() .setConditionRange(XiaomiProto.WeatherRange.newBuilder()
.setFrom(XiaomiWeatherConditions.convertOwmConditionToXiaomi(currentEntry.conditionCode)) .setFrom(XiaomiWeatherConditions.convertOwmConditionToXiaomi(currentEntry.getConditionCode()))
.setTo(XiaomiWeatherConditions.convertOwmConditionToXiaomi(currentEntry.conditionCode))) .setTo(XiaomiWeatherConditions.convertOwmConditionToXiaomi(currentEntry.getConditionCode())))
.setTemperatureRange(XiaomiProto.WeatherRange.newBuilder() .setTemperatureRange(XiaomiProto.WeatherRange.newBuilder()
.setTo(currentEntry.maxTemp - 273) .setTo(currentEntry.getMaxTemp() - 273)
.setFrom(currentEntry.minTemp - 273)) .setFrom(currentEntry.getMinTemp() - 273))
.setTemperatureSymbol("") .setTemperatureSymbol("")
.setSunriseSunset(XiaomiProto.WeatherSunriseSunset.newBuilder() .setSunriseSunset(XiaomiProto.WeatherSunriseSunset.newBuilder()
.setSunrise(currentEntry.sunRise != 0 ? unixTimestampToISOWithColons(currentEntry.sunRise) : "") .setSunrise(currentEntry.getSunRise() != 0 ? unixTimestampToISOWithColons(currentEntry.getSunRise()) : "")
.setSunset(currentEntry.sunSet != 0 ? unixTimestampToISOWithColons(currentEntry.sunSet) : ""))); .setSunset(currentEntry.getSunSet() != 0 ? unixTimestampToISOWithColons(currentEntry.getSunSet()) : "")));
} }
LOG.debug("Sending daily forecast with {} days of info", entryListBuilder.getEntryCount()); LOG.debug("Sending daily forecast with {} days of info", entryListBuilder.getEntryCount());
@@ -375,19 +375,19 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
public void sendHourlyForecast(final WeatherSpec weatherSpec) { public void sendHourlyForecast(final WeatherSpec weatherSpec) {
final XiaomiProto.ForecastEntries.Builder entriesBuilder = XiaomiProto.ForecastEntries.newBuilder(); final XiaomiProto.ForecastEntries.Builder entriesBuilder = XiaomiProto.ForecastEntries.newBuilder();
final int hoursToSend = Math.min(23, weatherSpec.hourly.size()); final int hoursToSend = Math.min(23, weatherSpec.getHourly().size());
for (WeatherSpec.Hourly hourly : weatherSpec.hourly.subList(0, hoursToSend)) { for (WeatherSpec.Hourly hourly : weatherSpec.getHourly().subList(0, hoursToSend)) {
entriesBuilder.addEntry(XiaomiProto.ForecastEntry.newBuilder() entriesBuilder.addEntry(XiaomiProto.ForecastEntry.newBuilder()
.setAqi(buildUnitValue(0, "Unknown")) // FIXME when available through spec .setAqi(buildUnitValue(0, "Unknown")) // FIXME when available through spec
.setTemperatureRange(XiaomiProto.WeatherRange.newBuilder() .setTemperatureRange(XiaomiProto.WeatherRange.newBuilder()
.setFrom(0) // not set, but required .setFrom(0) // not set, but required
.setTo(hourly.temp - 273)) .setTo(hourly.getTemp() - 273))
.setConditionRange(XiaomiProto.WeatherRange.newBuilder() .setConditionRange(XiaomiProto.WeatherRange.newBuilder()
.setFrom(0) // not set, but required .setFrom(0) // not set, but required
.setTo(XiaomiWeatherConditions.convertOwmConditionToXiaomi(hourly.conditionCode))) .setTo(XiaomiWeatherConditions.convertOwmConditionToXiaomi(hourly.getConditionCode())))
.setTemperatureSymbol("") .setTemperatureSymbol("")
.setWind(buildUnitValue(hourly.windSpeedAsBeaufort(), Integer.toString(hourly.windDirection)))); .setWind(buildUnitValue(hourly.windSpeedAsBeaufort(), Integer.toString(hourly.getWindDirection()))));
} }
LOG.debug("Sending hourly forecast with {} hours of info", entriesBuilder.getEntryCount()); LOG.debug("Sending hourly forecast with {} hours of info", entriesBuilder.getEntryCount());
@@ -464,7 +464,7 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
} }
private void sendWeatherSpec(@NonNull final WeatherSpec weatherSpec) { private void sendWeatherSpec(@NonNull final WeatherSpec weatherSpec) {
LOG.debug("Send weather for location {}", weatherSpec.location); LOG.debug("Send weather for location {}", weatherSpec.getLocation());
sendCurrentConditions(weatherSpec); sendCurrentConditions(weatherSpec);
sendDailyForecast(weatherSpec); sendDailyForecast(weatherSpec);
@@ -519,7 +519,7 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
final List<WeatherSpec> knownWeathers = Weather.INSTANCE.getWeatherSpecs(); final List<WeatherSpec> knownWeathers = Weather.INSTANCE.getWeatherSpecs();
for (WeatherSpec spec : knownWeathers) { for (WeatherSpec spec : knownWeathers) {
if (TextUtils.equals(spec.location, locationName)) { if (TextUtils.equals(spec.getLocation(), locationName)) {
sendWeatherSpec(spec); sendWeatherSpec(spec);
return; return;
} }
@@ -553,7 +553,7 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
final List<String> result = new ArrayList<>(); final List<String> result = new ArrayList<>();
for (final WeatherSpec spec : specs) { for (final WeatherSpec spec : specs) {
result.add(StringUtils.ensureNotNull(spec.location)); result.add(StringUtils.ensureNotNull(spec.getLocation()));
} }
return result.toArray(new String[0]); return result.toArray(new String[0]);
@@ -594,16 +594,16 @@ public class ZeTimeDeviceSupport extends AbstractBTLESingleDeviceSupport {
@Override @Override
public void onSendWeather(ArrayList<WeatherSpec> weatherSpecs) { public void onSendWeather(ArrayList<WeatherSpec> weatherSpecs) {
WeatherSpec weatherSpec = weatherSpecs.get(0); WeatherSpec weatherSpec = weatherSpecs.get(0);
byte[] weather = new byte[weatherSpec.location.getBytes(StandardCharsets.UTF_8).length + 26]; // 26 bytes for weatherdata and overhead byte[] weather = new byte[weatherSpec.getLocation().getBytes(StandardCharsets.UTF_8).length + 26]; // 26 bytes for weatherdata and overhead
weather[0] = ZeTimeConstants.CMD_PREAMBLE; weather[0] = ZeTimeConstants.CMD_PREAMBLE;
weather[1] = ZeTimeConstants.CMD_PUSH_WEATHER_DATA; weather[1] = ZeTimeConstants.CMD_PUSH_WEATHER_DATA;
weather[2] = ZeTimeConstants.CMD_SEND; weather[2] = ZeTimeConstants.CMD_SEND;
weather[3] = (byte) ((weatherSpec.location.getBytes(StandardCharsets.UTF_8).length + 20) & 0xff); weather[3] = (byte) ((weatherSpec.getLocation().getBytes(StandardCharsets.UTF_8).length + 20) & 0xff);
weather[4] = (byte) ((weatherSpec.location.getBytes(StandardCharsets.UTF_8).length + 20) >> 8); weather[4] = (byte) ((weatherSpec.getLocation().getBytes(StandardCharsets.UTF_8).length + 20) >> 8);
weather[5] = 0; // celsius weather[5] = 0; // celsius
weather[6] = (byte) (weatherSpec.currentTemp - 273); weather[6] = (byte) (weatherSpec.getCurrentTemp() - 273);
weather[7] = (byte) (weatherSpec.todayMinTemp - 273); weather[7] = (byte) (weatherSpec.getTodayMinTemp() - 273);
weather[8] = (byte) (weatherSpec.todayMaxTemp - 273); weather[8] = (byte) (weatherSpec.getTodayMaxTemp() - 273);
boolean newWeather = false; boolean newWeather = false;
if (versionCmd.fwVersion.length() >= 24) { if (versionCmd.fwVersion.length() >= 24) {
@@ -617,22 +617,22 @@ public class ZeTimeDeviceSupport extends AbstractBTLESingleDeviceSupport {
LOG.warn("We do not have a sane fw version string available, firmware too old/new?"); LOG.warn("We do not have a sane fw version string available, firmware too old/new?");
} }
if (newWeather) { if (newWeather) {
weather[9] = WeatherMapper.INSTANCE.mapToZeTimeCondition(weatherSpec.currentConditionCode); weather[9] = WeatherMapper.INSTANCE.mapToZeTimeCondition(weatherSpec.getCurrentConditionCode());
} else { } else {
weather[9] = WeatherMapper.INSTANCE.mapToZeTimeConditionOld(weatherSpec.currentConditionCode); weather[9] = WeatherMapper.INSTANCE.mapToZeTimeConditionOld(weatherSpec.getCurrentConditionCode());
} }
for (int forecast = 0; forecast < 3; forecast++) { for (int forecast = 0; forecast < 3; forecast++) {
weather[10 + (forecast * 5)] = 0; // celsius weather[10 + (forecast * 5)] = 0; // celsius
weather[11 + (forecast * 5)] = (byte) 0xff; weather[11 + (forecast * 5)] = (byte) 0xff;
weather[12 + (forecast * 5)] = (byte) (weatherSpec.forecasts.get(forecast).minTemp - 273); weather[12 + (forecast * 5)] = (byte) (weatherSpec.getForecasts().get(forecast).getMinTemp() - 273);
weather[13 + (forecast * 5)] = (byte) (weatherSpec.forecasts.get(forecast).maxTemp - 273); weather[13 + (forecast * 5)] = (byte) (weatherSpec.getForecasts().get(forecast).getMaxTemp() - 273);
if (newWeather) { if (newWeather) {
weather[14 + (forecast * 5)] = WeatherMapper.INSTANCE.mapToZeTimeCondition(weatherSpec.forecasts.get(forecast).conditionCode); weather[14 + (forecast * 5)] = WeatherMapper.INSTANCE.mapToZeTimeCondition(weatherSpec.getForecasts().get(forecast).getConditionCode());
} else { } else {
weather[14 + (forecast * 5)] = WeatherMapper.INSTANCE.mapToZeTimeConditionOld(weatherSpec.forecasts.get(forecast).conditionCode); weather[14 + (forecast * 5)] = WeatherMapper.INSTANCE.mapToZeTimeConditionOld(weatherSpec.getForecasts().get(forecast).getConditionCode());
} }
} }
System.arraycopy(weatherSpec.location.getBytes(StandardCharsets.UTF_8), 0, weather, 25, weatherSpec.location.getBytes(StandardCharsets.UTF_8).length); System.arraycopy(weatherSpec.getLocation().getBytes(StandardCharsets.UTF_8), 0, weather, 25, weatherSpec.getLocation().getBytes(StandardCharsets.UTF_8).length);
weather[weather.length - 1] = ZeTimeConstants.CMD_END; weather[weather.length - 1] = ZeTimeConstants.CMD_END;
try { try {
TransactionBuilder builder = performInitialized("sendWeahter"); TransactionBuilder builder = performInitialized("sendWeahter");
@@ -105,24 +105,24 @@ public class WeatherMapperTest extends TestBase {
JSONObject wind = new JSONObject(); JSONObject wind = new JSONObject();
try { try {
condition.put("id", weatherSpec.currentConditionCode); condition.put("id", weatherSpec.getCurrentConditionCode());
condition.put("main", weatherSpec.currentCondition); condition.put("main", weatherSpec.getCurrentCondition());
condition.put("description", weatherSpec.currentCondition); condition.put("description", weatherSpec.getCurrentCondition());
condition.put("icon", Weather.mapToOpenWeatherMapIcon(weatherSpec.currentConditionCode)); condition.put("icon", Weather.mapToOpenWeatherMapIcon(weatherSpec.getCurrentConditionCode()));
weather.put(condition); weather.put(condition);
main.put("temp", weatherSpec.currentTemp); main.put("temp", weatherSpec.getCurrentTemp());
main.put("humidity", weatherSpec.currentHumidity); main.put("humidity", weatherSpec.getCurrentHumidity());
main.put("temp_min", weatherSpec.todayMinTemp); main.put("temp_min", weatherSpec.getTodayMinTemp());
main.put("temp_max", weatherSpec.todayMaxTemp); main.put("temp_max", weatherSpec.getTodayMaxTemp());
wind.put("speed", (weatherSpec.windSpeed / 3.6f)); //meter per second wind.put("speed", (weatherSpec.getWindSpeed() / 3.6f)); //meter per second
wind.put("deg", weatherSpec.windDirection); wind.put("deg", weatherSpec.getWindDirection());
reconstructedOWMWeather.put("weather", weather); reconstructedOWMWeather.put("weather", weather);
reconstructedOWMWeather.put("main", main); reconstructedOWMWeather.put("main", main);
reconstructedOWMWeather.put("name", weatherSpec.location); reconstructedOWMWeather.put("name", weatherSpec.getLocation());
reconstructedOWMWeather.put("wind", wind); reconstructedOWMWeather.put("wind", wind);
} catch (JSONException e) { } catch (JSONException e) {