Pebble: support the system weather app.

- enable/disable weather app from the watchapp list
- convert weather data to a format that can be displayed by the system app

TODO: send the weather data periodically
here
Daniele Gobbetti 2016-12-30 20:14:13 +01:00
parent 0e9ce5d186
commit e477d22c88
7 changed files with 161 additions and 3 deletions

View File

@ -199,6 +199,9 @@ public abstract class AbstractAppManagerFragment extends Fragment {
if (baseName.equals("3af858c3-16cb-4561-91e7-f1ad2df8725f")) {
cachedAppList.add(new GBDeviceApp(UUID.fromString(baseName), "Kickstart (System)", "Pebble Inc.", "", GBDeviceApp.Type.WATCHFACE_SYSTEM));
}
if (baseName.equals(PebbleProtocol.UUID_WEATHER.toString())) {
cachedAppList.add(new GBDeviceApp(PebbleProtocol.UUID_WEATHER, "Weather (System)", "Pebble Inc.", "", GBDeviceApp.Type.APP_SYSTEM));
}
}
}
if (uuids == null) {
@ -367,8 +370,12 @@ public abstract class AbstractAppManagerFragment extends Fragment {
case R.id.appmanager_hrm_activate:
GBApplication.deviceService().onInstallApp(Uri.parse("fake://hrm"));
return true;
case R.id.appmanager_weather_activate:
GBApplication.deviceService().onInstallApp(Uri.parse("fake://weather"));
return true;
case R.id.appmanager_health_deactivate:
case R.id.appmanager_hrm_deactivate:
case R.id.appmanager_weather_deactivate:
GBApplication.deviceService().onAppDelete(selectedApp.getUUID());
return true;
case R.id.appmanager_app_configure:

View File

@ -28,6 +28,9 @@ public class AppManagerFragmentInstalledApps extends AbstractAppManagerFragment
if (PebbleUtils.hasHRM(mGBDevice.getModel())) {
systemApps.add(new GBDeviceApp(PebbleProtocol.UUID_WORKOUT, "Workout (System)", "Pebble Inc.", "", GBDeviceApp.Type.APP_SYSTEM));
}
if (PebbleUtils.getFwMajor(mGBDevice.getFirmwareVersion()) >= 4) {
systemApps.add(new GBDeviceApp(PebbleProtocol.UUID_WEATHER, "Weather (System)", "Pebble Inc.", "", GBDeviceApp.Type.APP_SYSTEM));
}
}
return systemApps;

View File

@ -10,6 +10,117 @@ public class Weather {
private static final Weather weather = new Weather();
public static Weather getInstance() {return weather;}
public static byte mapToPebbleCondition(int openWeatherMapCondition) {
/* deducted values:
0 = sun + cloud
1 = clouds
2 = some snow
3 = some rain
4 = heavy rain
5 = heavy snow
6 = sun + cloud + rain (default icon?)
7 = sun
8 = rain + snow
9 = 6
10, 11, ... = empty icon
*/
switch (openWeatherMapCondition) {
//Group 2xx: Thunderstorm
case 200: //thunderstorm with light rain: //11d
case 201: //thunderstorm with rain: //11d
case 202: //thunderstorm with heavy rain: //11d
case 210: //light thunderstorm:: //11d
case 211: //thunderstorm: //11d
case 230: //thunderstorm with light drizzle: //11d
case 231: //thunderstorm with drizzle: //11d
case 232: //thunderstorm with heavy drizzle: //11d
case 212: //heavy thunderstorm: //11d
case 221: //ragged thunderstorm: //11d
return 4;
//Group 3xx: Drizzle
case 300: //light intensity drizzle: //09d
case 301: //drizzle: //09d
case 302: //heavy intensity drizzle: //09d
case 310: //light intensity drizzle rain: //09d
case 311: //drizzle rain: //09d
case 312: //heavy intensity drizzle rain: //09d
case 313: //shower rain and drizzle: //09d
case 314: //heavy shower rain and drizzle: //09d
case 321: //shower drizzle: //09d
case 500: //light rain: //10d
case 501: //moderate rain: //10d
return 3;
//Group 5xx: Rain
case 502: //heavy intensity rain: //10d
case 503: //very heavy rain: //10d
case 504: //extreme rain: //10d
case 511: //freezing rain: //13d
case 520: //light intensity shower rain: //09d
case 521: //shower rain: //09d
case 522: //heavy intensity shower rain: //09d
case 531: //ragged shower rain: //09d
return 4;
//Group 6xx: Snow
case 600: //light snow: //[[file:13d.png]]
case 601: //snow: //[[file:13d.png]]
case 620: //light shower snow: //[[file:13d.png]]
return 2;
case 602: //heavy snow: //[[file:13d.png]]
case 611: //sleet: //[[file:13d.png]]
case 612: //shower sleet: //[[file:13d.png]]
case 621: //shower snow: //[[file:13d.png]]
case 622: //heavy shower snow: //[[file:13d.png]]
return 5;
case 615: //light rain and snow: //[[file:13d.png]]
case 616: //rain and snow: //[[file:13d.png]]
return 8;
//Group 7xx: Atmosphere
case 701: //mist: //[[file:50d.png]]
case 711: //smoke: //[[file:50d.png]]
case 721: //haze: //[[file:50d.png]]
case 731: //sandcase dust whirls: //[[file:50d.png]]
case 741: //fog: //[[file:50d.png]]
case 751: //sand: //[[file:50d.png]]
case 761: //dust: //[[file:50d.png]]
case 762: //volcanic ash: //[[file:50d.png]]
case 771: //squalls: //[[file:50d.png]]
case 781: //tornado: //[[file:50d.png]]
case 900: //tornado
return 6;
//Group 800: Clear
case 800: //clear sky: //[[file:01d.png]] [[file:01n.png]]
return 7;
//Group 80x: Clouds
case 801: //few clouds: //[[file:02d.png]] [[file:02n.png]]
case 802: //scattered clouds: //[[file:03d.png]] [[file:03d.png]]
case 803: //broken clouds: //[[file:04d.png]] [[file:03d.png]]
case 804: //overcast clouds: //[[file:04d.png]] [[file:04d.png]]
return 0;
//Group 90x: Extreme
case 901: //tropical storm
case 903: //cold
case 904: //hot
case 905: //windy
case 906: //hail
//Group 9xx: Additional
case 951: //calm
case 952: //light breeze
case 953: //gentle breeze
case 954: //moderate breeze
case 955: //fresh breeze
case 956: //strong breeze
case 957: //high windcase near gale
case 958: //gale
case 959: //severe gale
case 960: //storm
case 961: //violent storm
case 902: //hurricane
case 962: //hurricane
default:
return 6;
}
}
public static int mapToYahooCondition(int openWeatherMapCondition) {
// openweathermap.org conditions:
// http://openweathermap.org/weather-conditions

View File

@ -613,6 +613,10 @@ class PebbleIoThread extends GBDeviceIoThread {
write(mPebbleProtocol.encodeActivateHRM(true));
return;
}
if (uri.equals(Uri.parse("fake://weather"))) {
write(mPebbleProtocol.encodeActivateWeather(true));
return;
}
if (mIsInstalling) {
return;

View File

@ -38,7 +38,9 @@ import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.model.Weather;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import ru.gelin.android.weather.notification.ParcelableWeather2;
public class PebbleProtocol extends GBDeviceProtocol {
@ -370,6 +372,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
public static final UUID UUID_PEBBLE_HEALTH = UUID.fromString("36d8c6ed-4c83-4fa1-a9e2-8f12dc941f8c"); // FIXME: store somewhere else, this is also accessed by other code
public static final UUID UUID_WORKOUT = UUID.fromString("fef82c82-7176-4e22-88de-35a3fc18d43f"); // FIXME: store somewhere else, this is also accessed by other code
public static final UUID UUID_WEATHER = UUID.fromString("61b22bc8-1e29-460d-a236-3fe409a439ff"); // FIXME: store somewhere else, this is also accessed by other code
private static final UUID UUID_GBPEBBLE = UUID.fromString("61476764-7465-7262-6469-656775527a6c");
private static final UUID UUID_MORPHEUZ = UUID.fromString("5be44f1d-d262-4ea6-aa30-ddbec1e3cab2");
private static final UUID UUID_WHETHERNEAT = UUID.fromString("3684003b-a685-45f9-a713-abc6364ba051");
@ -545,7 +548,8 @@ public class PebbleProtocol extends GBDeviceProtocol {
return encodeActivateWeather(true);
} else {
//return encodeWeatherPin(ts, "Weather", "1°/-1°", "Gadgetbridge is Sunny", "Berlin", 37);
return encodeWeatherForecast(ts, "Berlin", 0, 5, -5, 1, "Sexy", 7, 2, 1);
//return encodeWeatherForecast(ts, "Berlin", 0, 5, -5, 1, "Sexy", 7, 2, 1);
return encodeWeatherForecast(ts);
}
}
@ -1126,6 +1130,24 @@ public class PebbleProtocol extends GBDeviceProtocol {
return encodeBlobdb(uuid, BLOBDB_INSERT, BLOBDB_PIN, buf.array());
}
private byte[] encodeWeatherForecast(int timestamp) {
ParcelableWeather2 weather = Weather.getInstance().getWeather2();
if (weather != null) {
return encodeWeatherForecast(timestamp,
weather.location,
weather.currentTemp - 273,
weather.todayHighTemp - 273,
weather.todayLowTemp - 273,
Weather.mapToPebbleCondition(weather.currentConditionCode),
weather.currentCondition,
weather.forecastHighTemp - 273,
weather.forecastLowTemp - 273,
Weather.mapToPebbleCondition(weather.forecastConditionCode)
);
}
return null;
}
private byte[] encodeWeatherForecast(int timestamp, String location, int tempNow, int tempHighToday, int tempLowToday, int conditionCodeToday, String conditionToday, int tempHighTomorrow, int tempLowTomorrow, int conditionCodeTomorrow) {
final short WEATHER_FORECAST_LENGTH = 20;
@ -1148,10 +1170,10 @@ public class PebbleProtocol extends GBDeviceProtocol {
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put((byte) 3); // unknown, always 3?
buf.putShort((short) tempNow);
buf.put((byte) 1);
buf.put((byte) conditionCodeToday);
buf.putShort((short) tempHighToday);
buf.putShort((short) tempLowToday);
buf.put((byte) 4);
buf.put((byte) conditionCodeTomorrow);
buf.putShort((short) tempHighTomorrow);
buf.putShort((short) tempLowTomorrow);
buf.putInt(timestamp);
@ -1392,6 +1414,9 @@ public class PebbleProtocol extends GBDeviceProtocol {
if (UUID_WORKOUT.equals(uuid)) {
return encodeActivateHRM(false);
}
if (UUID_WEATHER.equals(uuid)) { //TODO: probably it wasn't present in firmware 3
return encodeActivateWeather(false);
}
return encodeBlobdb(uuid, BLOBDB_DELETE, BLOBDB_APP, null);
} else {
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_REMOVEAPP_2X);

View File

@ -21,6 +21,12 @@
<item
android:id="@+id/appmanager_hrm_deactivate"
android:title="@string/appmanager_hrm_deactivate"/>
<item
android:id="@+id/appmanager_weather_activate"
android:title="@string/appmanager_weather_activate" />
<item
android:id="@+id/appmanager_weather_deactivate"
android:title="@string/appmanager_weather_deactivate" />
<item
android:id="@+id/appmanager_app_configure"
android:title="@string/app_configure"/>

View File

@ -30,6 +30,8 @@
<string name="appmanager_health_deactivate">Deactivate</string>
<string name="appmanager_hrm_activate">Activate HRM</string>
<string name="appmanager_hrm_deactivate">Deactivate HRM</string>
<string name="appmanager_weather_activate">Activate system weather app</string>
<string name="appmanager_weather_deactivate">Deactivate system weather app</string>
<string name="app_configure">Configure</string>
<string name="app_move_to_top">Move to top</string>