From feadeb81398ac8f64dc9d7b6f503e924c7fbaf6b Mon Sep 17 00:00:00 2001 From: Arjan Schrijver Date: Mon, 9 Aug 2021 14:27:38 +0200 Subject: [PATCH] Fossil Hybrid HR: Add power saving feature --- .../assets/fossil_hr/openSourceWatchface.bin | Bin 3210 -> 3438 bytes .../HybridHRWatchfaceDesignerActivity.java | 12 ++++ .../qhybrid/HybridHRWatchfaceFactory.java | 68 +++++++++++------- .../qhybrid/HybridHRWatchfaceSettings.java | 18 +++++ .../dialog_hybridhr_watchface_settings.xml | 36 ++++++++++ app/src/main/res/values/strings.xml | 3 + external/fossil-hr-watchface | 2 +- 7 files changed, 111 insertions(+), 28 deletions(-) diff --git a/app/src/main/assets/fossil_hr/openSourceWatchface.bin b/app/src/main/assets/fossil_hr/openSourceWatchface.bin index 32b54f2e2b9c985717d2a18d86a8a789b253aa48..e6cbe5917d80c7e0d46d50cdc482c998623b2bab 100644 GIT binary patch delta 1608 zcmZ`(&rcgy5T56?y-3HX%v9&;}Bk()8pwu~{sYfB=#9 zW8__I*3@ zUnI4(y85|FC%*s@1Iy17;1VQ4kV-#DU0ZYdi4GK^_5jiS^NgAy&~G3M6BS@^AGA3F z`tQq^P82-gjDp69^l|uv<6k^PH+@7u`-!IE`UmmBvs^8!4rbL*Mjf(;!}f@pQ6u(f z)EuG-ut+Wb#Uh1e}l)M-~Z0N+P=n01+A~MAaY%+CX8l zlSKnm)S(MQhf|$ylVhHi!AoeSq1*=rl&nv|fdt5K3Z9p3NpnH+ZIJiaW#{OaZ7^>v zVEWjc{6z7x#T@G?^(qUd-xbW)|77W!H84MzWAc$1fbb8JZo`dK_72dGoFU)$C;lY( z6HE$e31dhzjj%Rj3~TQgs&>&B(H4z}cHM}sOE=lAHNhEG{D#nqu^U}}jM?DFU3r-0 zyYk^0o9-S|mg@3xrgjY?tf$LIN&4gAn3ZQ7b z_(5kF&IRaW2M;a+3(&`q4laTEpohI|cwvJ9@qOfj3Z(8AZ@*QC|H^@f%M(0DJyg6cFxMGs&(#`8nLF) zIbPawCl9%k{nSH28GC)PEY7vfn3x|h=;^C<`jD~V$*e14ey0A!8?EuTpnbVBb-qcB zE7$_8aiaja4Z4VJS;BT;1I3S^2Q-1RZ${%|=;E!=ufhqojBhG`M;t!@8GldOp!zb- zKpQYgtbgWvKIW_-CO#4OjkyLtfO8$dCOTK^^Zxy014s91T7`&zEuTOgk#vOMUrymh z{V)GQQv4LxKm*X%I@zE=a=JHcEHP zyN?zFMOOb+`no4bPGzrnXKQnF>u!BH7*>aq(uix9L?(R`9o!Cyx|J0K`8~+1{+Brx7 delta 1406 zcmZux&2Jl35TCbed%gakS;rr1JN}F}yPIIQ1?+8FtE8okmp~!pP~d_Uh`X_rk1CBK z)Qc-F0Zvr@BYZWg1ec=pf@1Y-$+t?NN-HjiBjQqiZ_}nk!qU$(@Au}-%$u3Fe`dZ< zS60^6K3D1F_nAb*pz?JIT8TJOHXc@1KRTQudT@!66NCJYNRJb_3Ft{8Ck6S(ix*NF zIv`~rvqZ-;L_s)wAP^0GM1T86>YtA6PcX%G6|DUE*6mwNqIysAVQJou!Jn&wN*wmK%WH%xB!pdst^qTNy8e4 zk0JFrNS$taX+gEA1tfdvG>RV}$5BL4yTCZ1ZS3EO18T+sBhdiWQ`$3AVa z$a+*+H3J@D_kUyay#|YI_!N0Th_QNXWKCa=H(2<{48r6w$#>yY#{PXS$-n>7xeVu` zNeL}&B(;)}(o93uE*fcV(a7A9mzaH9bh1jo5XUpDd8+5w1?YK?PqB)}_qdVD)KjB0 zi=65Ol6RJA*(<7F@CB>Y0q!bQac{smkK$Z7X&*19dl7qYqc%Y69qa*m9UNMG*udHX ze+e>*^&;#6J$e}gAYFmH(yxih-k=Ho9H^_nyU@`zK2igW1+Oz7C9e+{D+i6LO@syo zm0(jgiT&E3kP}v>OcsgT(U5)ajgi1^adJvoYASI%7P8~hN7ac?9VZOm&nP2H#v7ul zrW#^KP1n?3c4YXi86#)qhoYwytm04bWr3b^o7qy>3=ntmqo}An zXeIPyBE0r0(Bm_91=wYgl4sfr9r4t73SMCL1Gm+bl@mv{=4JodnWt&i+)%X2%B&&% z*T1V*onH%+96~em`o95<~oYYhddZPG|r6E-B zC{puHgB>m7jqx7}k1s%w`J_ta)w^?+PTF&fef=6*c^&dSa5o@tqMd*@3UJ~AtrjF& zef7T&RJUI~Oi02^@R{L{)(Jod#~-irKAZtA;H>oj@juPGD_DL2|43%=A#`AH3)@(` zcK`RlLD|KUPp$qjQp3c$kUUlXY2ed)xZ1xjT`#vj!AZacoHghOT7=mEy34Wn=$RB} zk5u^!7Lm!>UEgZ&b$1-ot6 gJ6l^g(|;>G?i-P3kq|kZ{q|S8+uOT4{Xlf{U%ILY=l}o! diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java index 6e3f9b035..5c01e775e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java @@ -401,6 +401,12 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem if (watchfaceConfig.has("wrist_flick_move_minute")) { watchfaceSettings.setWristFlickMoveMinute(watchfaceConfig.getInt("wrist_flick_move_minute")); } + if (watchfaceConfig.has("powersave_display")) { + watchfaceSettings.setPowersaveDisplay(watchfaceConfig.getBoolean("powersave_display")); + } + if (watchfaceConfig.has("powersave_hands")) { + watchfaceSettings.setPowersaveHands(watchfaceConfig.getBoolean("powersave_hands")); + } } catch (JSONException e) { LOG.warn("JSON parsing error", e); } @@ -643,6 +649,10 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem wristFlickMoveHourInput.setText(String.valueOf(watchfaceSettings.getWristFlickMoveHour())); final EditText wristFlickMoveMinuteInput = layout.findViewById(R.id.watchface_setting_flick_minute); wristFlickMoveMinuteInput.setText(String.valueOf(watchfaceSettings.getWristFlickMoveMinute())); + final CheckBox powersaveDisplayInput = layout.findViewById(R.id.watchface_setting_powersave_display); + powersaveDisplayInput.setChecked(watchfaceSettings.getPowersaveDisplay()); + final CheckBox powersaveHandsInput = layout.findViewById(R.id.watchface_setting_powersave_hands); + powersaveHandsInput.setChecked(watchfaceSettings.getPowersaveHands()); new AlertDialog.Builder(this) .setView(layout) .setNegativeButton(R.string.fossil_hr_new_action_cancel, null) @@ -655,6 +665,8 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem watchfaceSettings.setWristFlickDuration(Integer.parseInt(wristFlickDurationInput.getText().toString())); watchfaceSettings.setWristFlickMoveHour(Integer.parseInt(wristFlickMoveHourInput.getText().toString())); watchfaceSettings.setWristFlickMoveMinute(Integer.parseInt(wristFlickMoveMinuteInput.getText().toString())); + watchfaceSettings.setPowersaveDisplay(powersaveDisplayInput.isChecked()); + watchfaceSettings.setPowersaveHands(powersaveHandsInput.isChecked()); } }) .setTitle(R.string.watchface_dialog_title_settings) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java index 6754009d4..3598d8cf1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java @@ -116,45 +116,57 @@ public class HybridHRWatchfaceFactory { } } + private boolean includeWidget(String name) { + for (JSONObject widget : this.widgets) { + try { + if (widget.get("name").equals(name)) { + return true; + } + } catch (JSONException e) { + } + } + return false; + } + public byte[] getWapp(Context context) throws IOException { byte[] backgroundBytes = ImageConverter.encodeToRawImage(ImageConverter.get2BitsRAWImageBytes(background)); InputStream backgroundStream = new ByteArrayInputStream(backgroundBytes); LinkedHashMap code = new LinkedHashMap<>(); try { code.put(watchfaceName, context.getAssets().open("fossil_hr/openSourceWatchface.bin")); - code.put("widgetDate", context.getAssets().open("fossil_hr/widgetDate.bin")); - code.put("widgetWeather", context.getAssets().open("fossil_hr/widgetWeather.bin")); - code.put("widgetSteps", context.getAssets().open("fossil_hr/widgetSteps.bin")); - code.put("widgetHR", context.getAssets().open("fossil_hr/widgetHR.bin")); - code.put("widgetBattery", context.getAssets().open("fossil_hr/widgetBattery.bin")); - code.put("widgetCalories", context.getAssets().open("fossil_hr/widgetCalories.bin")); - code.put("widgetActiveMins", context.getAssets().open("fossil_hr/widgetActiveMins.bin")); - code.put("widgetChanceOfRain", context.getAssets().open("fossil_hr/widgetChanceOfRain.bin")); - code.put("widget2ndTZ", context.getAssets().open("fossil_hr/widget2ndTZ.bin")); + if (includeWidget("widgetDate")) code.put("widgetDate", context.getAssets().open("fossil_hr/widgetDate.bin")); + if (includeWidget("widgetWeather")) code.put("widgetWeather", context.getAssets().open("fossil_hr/widgetWeather.bin")); + if (includeWidget("widgetSteps")) code.put("widgetSteps", context.getAssets().open("fossil_hr/widgetSteps.bin")); + if (includeWidget("widgetHR")) code.put("widgetHR", context.getAssets().open("fossil_hr/widgetHR.bin")); + if (includeWidget("widgetBattery")) code.put("widgetBattery", context.getAssets().open("fossil_hr/widgetBattery.bin")); + if (includeWidget("widgetCalories")) code.put("widgetCalories", context.getAssets().open("fossil_hr/widgetCalories.bin")); + if (includeWidget("widgetActiveMins")) code.put("widgetActiveMins", context.getAssets().open("fossil_hr/widgetActiveMins.bin")); + if (includeWidget("widgetChanceOfRain")) code.put("widgetChanceOfRain", context.getAssets().open("fossil_hr/widgetChanceOfRain.bin")); + if (includeWidget("widget2ndTZ")) code.put("widget2ndTZ", context.getAssets().open("fossil_hr/widget2ndTZ.bin")); } catch (IOException e) { LOG.warn("Unable to read asset file", e); } LinkedHashMap icons = new LinkedHashMap<>(); try { icons.put("background.raw", backgroundStream); - icons.put("icWthClearDay", context.getAssets().open("fossil_hr/icWthClearDay.rle")); - icons.put("icWthClearNite", context.getAssets().open("fossil_hr/icWthClearNite.rle")); - icons.put("icWthCloudy", context.getAssets().open("fossil_hr/icWthCloudy.rle")); - icons.put("icWthPartCloudyDay", context.getAssets().open("fossil_hr/icWthPartCloudyDay.rle")); - icons.put("icWthPartCloudyNite", context.getAssets().open("fossil_hr/icWthPartCloudyNite.rle")); - icons.put("icWthRainy", context.getAssets().open("fossil_hr/icWthRainy.rle")); - icons.put("icWthSnowy", context.getAssets().open("fossil_hr/icWthSnowy.rle")); - icons.put("icWthStormy", context.getAssets().open("fossil_hr/icWthStormy.rle")); - icons.put("icWthWindy", context.getAssets().open("fossil_hr/icWthWindy.rle")); - icons.put("icSteps", context.getAssets().open("fossil_hr/icSteps.rle")); icons.put("icTrophy", context.getAssets().open("fossil_hr/icTrophy.rle")); - icons.put("icHeart", context.getAssets().open("fossil_hr/icHeart.rle")); - icons.put("icBattCharging", context.getAssets().open("fossil_hr/icBattCharging.rle")); - icons.put("icBattEmpty", context.getAssets().open("fossil_hr/icBattEmpty.rle")); - icons.put("icBattery", context.getAssets().open("fossil_hr/icBattery.rle")); - icons.put("icCalories", context.getAssets().open("fossil_hr/icCalories.rle")); - icons.put("icActiveMins", context.getAssets().open("fossil_hr/icActiveMins.rle")); - icons.put("icRainChance", context.getAssets().open("fossil_hr/icRainChance.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthClearDay", context.getAssets().open("fossil_hr/icWthClearDay.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthClearNite", context.getAssets().open("fossil_hr/icWthClearNite.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthCloudy", context.getAssets().open("fossil_hr/icWthCloudy.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthPartCloudyDay", context.getAssets().open("fossil_hr/icWthPartCloudyDay.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthPartCloudyNite", context.getAssets().open("fossil_hr/icWthPartCloudyNite.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthRainy", context.getAssets().open("fossil_hr/icWthRainy.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthSnowy", context.getAssets().open("fossil_hr/icWthSnowy.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthStormy", context.getAssets().open("fossil_hr/icWthStormy.rle")); + if (includeWidget("widgetWeather")) icons.put("icWthWindy", context.getAssets().open("fossil_hr/icWthWindy.rle")); + if (includeWidget("widgetSteps")) icons.put("icSteps", context.getAssets().open("fossil_hr/icSteps.rle")); + if (includeWidget("widgetHR")) icons.put("icHeart", context.getAssets().open("fossil_hr/icHeart.rle")); + if (includeWidget("widgetBattery")) icons.put("icBattCharging", context.getAssets().open("fossil_hr/icBattCharging.rle")); + if (includeWidget("widgetBattery")) icons.put("icBattEmpty", context.getAssets().open("fossil_hr/icBattEmpty.rle")); + if (includeWidget("widgetBattery")) icons.put("icBattery", context.getAssets().open("fossil_hr/icBattery.rle")); + if (includeWidget("widgetCalories")) icons.put("icCalories", context.getAssets().open("fossil_hr/icCalories.rle")); + if (includeWidget("widgetActiveMins")) icons.put("icActiveMins", context.getAssets().open("fossil_hr/icActiveMins.rle")); + if (includeWidget("widgetChanceOfRain")) icons.put("icRainChance", context.getAssets().open("fossil_hr/icRainChance.rle")); } catch (IOException e) { LOG.warn("Unable to read asset file", e); } @@ -170,7 +182,7 @@ public class HybridHRWatchfaceFactory { LOG.warn("Could not generate image_layout", e); } try { - layout.put("battery_layout", getBatteryLayout()); + if (includeWidget("widgetBattery")) layout.put("battery_layout", getBatteryLayout()); } catch (JSONException e) { LOG.warn("Could not generate battery_layout", e); } @@ -393,6 +405,8 @@ public class HybridHRWatchfaceFactory { config.put("wrist_flick_duration", settings.getWristFlickDuration()); config.put("wrist_flick_move_hour", settings.getWristFlickMoveHour()); config.put("wrist_flick_move_minute", settings.getWristFlickMoveMinute()); + config.put("powersave_display", settings.getPowersaveDisplay()); + config.put("powersave_hands", settings.getPowersaveHands()); configuration.put("config", config); return configuration.toString(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java index 127b7b151..b70034086 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java @@ -23,6 +23,8 @@ public class HybridHRWatchfaceSettings { private int wristFlickDuration = 2200; private int wristFlickMoveHour = 360; private int wristFlickMoveMinute = -360; + private boolean powersaveDisplay = false; + private boolean powersaveHands = false; public HybridHRWatchfaceSettings() { } @@ -86,4 +88,20 @@ public class HybridHRWatchfaceSettings { this.wristFlickMoveMinute = wristFlickMoveMinute; } } + + public boolean getPowersaveDisplay() { + return powersaveDisplay; + } + + public void setPowersaveDisplay(boolean powersaveDisplay) { + this.powersaveDisplay = powersaveDisplay; + } + + public boolean getPowersaveHands() { + return powersaveHands; + } + + public void setPowersaveHands(boolean powersaveHands) { + this.powersaveHands = powersaveHands; + } } diff --git a/app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml b/app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml index e0bfb59b7..c8fdc6459 100644 --- a/app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml +++ b/app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml @@ -119,4 +119,40 @@ android:inputType="number"/> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4a38d2cd3..761611996 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1251,4 +1251,7 @@ 2nd time zone Active minutes Chance of rain + Power saving + Disable display updates while off wrist + Disable hands movement while off wrist diff --git a/external/fossil-hr-watchface b/external/fossil-hr-watchface index 15aeb1e72..8783cfcbb 160000 --- a/external/fossil-hr-watchface +++ b/external/fossil-hr-watchface @@ -1 +1 @@ -Subproject commit 15aeb1e72595fb285702878632d8a9e42b0eb181 +Subproject commit 8783cfcbbca8282825e25e577467123462175713