From a791281a5b6dce931243fbd788331dcdb4c72882 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 22 Sep 2021 21:03:32 -0400 Subject: [PATCH 001/220] Made it compatible with other devices --- .gitignore | 4 +- always-on-source/AlwaysOnDisplay.mc | 15 +- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fr920xt/fonts/fonts.xml | 2 +- resources-fre/strings/strings.fre | 106 ++++++++++++++ resources-fre/strings/strings.org | 106 ++++++++++++++ resources-fre/strings/strings.xml | 129 +++++++++--------- resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + resources-rectangle-205x148/fonts/fonts.xml | 2 +- .../fonts/titillium-web-light-54.fnt | 1 + .../fonts/titillium-web-light-54_0.png | Bin 3617 -> 3782 bytes resources-rectangle-240x240/fonts/fonts.xml | 6 +- resources-round-208x208/fonts/fonts.xml | 2 +- resources-round-260x260/fonts/fonts.xml | 2 +- .../fonts/titillium-web-light-74-tall.fnt | 1 + .../fonts/titillium-web-light-74-tall_0.png | Bin 3505 -> 3691 bytes .../fonts/crystal-icons-large.fnt | 5 +- .../fonts/crystal-icons-large.png | Bin 9383 -> 8590 bytes resources-round-280x280/fonts/fonts.xml | 2 +- .../fonts/titillium-web-light-80-tall.fnt | 3 +- .../fonts/titillium-web-light-80-tall_0.png | Bin 3800 -> 3864 bytes resources-round-360x360/fonts/fonts.xml | 6 +- .../fonts/crystal-icons-extra-large.fnt | 5 +- .../fonts/crystal-icons-extra-large.png | Bin 13234 -> 12228 bytes resources-round-390x390/fonts/fonts.xml | 6 +- resources-round-416x416/fonts/fonts.xml | 6 +- .../fonts/titillium-web-light-85-tall.fnt | 1 + .../fonts/titillium-web-light-85-tall_0.png | Bin 3943 -> 4089 bytes resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + resources-small-time/fonts/fonts.xml | 2 +- resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/fonts/crystal-icons.fnt | 5 +- resources/fonts/crystal-icons.png | Bin 5559 -> 5777 bytes resources/fonts/fonts.xml | 2 +- .../fonts/titillium-web-semibold-24-chars.txt | 6 +- resources/settings/properties.xml | 14 +- resources/settings/settings.xml | 6 + resources/strings/strings.xml | 5 + source/CrystalView.mc | 16 +++ source/DataFields.mc | 12 +- source/Indicators.mc | 5 + 56 files changed, 397 insertions(+), 105 deletions(-) create mode 100644 resources-fre/strings/strings.fre create mode 100644 resources-fre/strings/strings.org diff --git a/.gitignore b/.gitignore index 6bb6d727..a7dcad01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ - build/ - bin/ +.project +.settings/ \ No newline at end of file diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index cd8ad4d0..f946bfe0 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -83,13 +83,14 @@ class AlwaysOnDisplay extends Ui.Drawable { var hours = formattedTime[:hour]; var minutes = formattedTime[:min]; var amPmText = formattedTime[:amPm]; + var colon = ":"; // SG Addition var halfDCWidth = dc.getWidth() / 2; // Centre combined hours and minutes text (not the same as right-aligning hours and left-aligning minutes). // Font has tabular figures (monospaced numbers) even across different weights, so does not matter which of hours or // minutes font is used to calculate total width. - var totalWidth = dc.getTextWidthInPixels(hours + minutes, mHoursFont); + var totalWidth = dc.getTextWidthInPixels(hours + colon + minutes, mHoursFont); // SG Added colon var x = halfDCWidth - (totalWidth / 2); var y = mTimeY + mAdjustY + burnInYOffset; @@ -105,6 +106,16 @@ class AlwaysOnDisplay extends Ui.Drawable { ); x += dc.getTextWidthInPixels(hours, mHoursFont); + // SG Addition - Colon. + dc.drawText( + x, + y, + mHoursFont, + colon, + Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER + ); + x += dc.getTextWidthInPixels(colon, mHoursFont); + // Minutes. dc.drawText( x, @@ -128,7 +139,7 @@ class AlwaysOnDisplay extends Ui.Drawable { // LINE. y = mLineY + burnInYOffset; - dc.setPenWidth(/* mLineStroke */ 2); + dc.setPenWidth(/* mLineStroke */ 1); // SG From 2 to 1 dc.drawLine(halfDCWidth - (mLineWidth / 2), y, halfDCWidth + (mLineWidth / 2), y); // DATA. diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index a32f18c1..a28bd0b0 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 25596ac4..ede06f39 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index fc22c229..4016c611 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -77,6 +77,7 @@ Wetter Feuchtigkeit Druck + Pulse Ox diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index c0d17187..e6b2078a 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -78,6 +78,7 @@ Weeer Vochtigheid Luchtdruk + Pulse Ox diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 8be0eaf1..86e09c76 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-fr920xt/fonts/fonts.xml b/resources-fr920xt/fonts/fonts.xml index 75736182..7185e3f1 100644 --- a/resources-fr920xt/fonts/fonts.xml +++ b/resources-fr920xt/fonts/fonts.xml @@ -9,7 +9,7 @@ - + diff --git a/resources-fre/strings/strings.fre b/resources-fre/strings/strings.fre new file mode 100644 index 00000000..e8dc9c5a --- /dev/null +++ b/resources-fre/strings/strings.fre @@ -0,0 +1,106 @@ + + + + Crystal + Version de l'appli + + Thme + Couleur des heures + Couleur des minutes + Compteur de gauche + Compteur de droite + Objectif de calories (1-10,000kCal) + Apparence des compteurs + Apparence des champs numriques + Ajout de l'heure d'une ville (Beta) + Apparence de la barre d'activit + Masquer les secondes + Masquer le zro avant l'heure + OpenWeatherMap API Key Override + + Nombre de champs de donnes + Champs de donnes 1 + Champs de donnes 2 + Champs de donnes 3 + + Nombre d'indicateurs + Indicateur 1 + Indicateur 2 + Indicateur 3 + + ( partir du thme) + Monochrome brillant + Monochrome + + Tous les segments (fusionns) + Segments remplis seulement (fusionns) + Tous les segments + Segments remplis seulement + Masqu + Actuel/Objectif + Actuel + + Bleu (sur fond noir) + Rose (sur fond noir) + Rouge (sur fond noir) + Vert(sur fond noir) + Bleu pale (sur fond noir) + Crme (sur fond noir) + Jaune vif (sur fond noir) + Orange (sur fond noir) + Monochrome (sur fond noir) + Monochrome (sur fond blanc) + Bleu (sur fond blanc) + Rouge (sur fond blanc) + Vert (sur fond blanc) + Orange (sur fond blanc) + Jaune fonc (sur fond noir) + + Pas + tages montes + Minutes actives (hebdo) + Calories (objectif manuel) + Masqu + + Rythme cardiaque + Rythme cardiaque (actif 5s) + Pile + Pile (Pourcentage masqu) + Notifications + Calories + Distance + Alarmes + Altitude + Thermomtre + Bluetooth + Bluetooth/Notifications + Lever/Coucher du soleil + Mto + Humidit + Pression + + + + + Dim + Lun + Mar + Mer + Jeu + Ven + Sam + + Jan + Fv + Mar + Avr + Mai + Juin + Juil + Aot + Sep + Oct + Nov + Dc + + diff --git a/resources-fre/strings/strings.org b/resources-fre/strings/strings.org new file mode 100644 index 00000000..37d23e41 --- /dev/null +++ b/resources-fre/strings/strings.org @@ -0,0 +1,106 @@ + + + + Crystal + App Version + + Thème + Hours Colour + Minutes Colour + Left Meter + Right Meter + Calories Goal (1-10,000kCal) + Meter Style + Meter Digits Style + Add Local Time in City (Beta) + Move Bar Style + Hide Seconds + Hide Hours Leading Zero + OpenWeatherMap API Key Override + + Number Of Data Fields + Data Field 1 + Data Field 2 + Data Field 3 + + Number Of Indicators + Indicator 1 + Indicator 2 + Indicator 3 + + (From Theme) + Mono Highlight + Mono + + All Segments (Merged) + Filled Segments (Merged) + All Segments + Filled Segments + Hidden + Current/Target + Current + + Blue (Dark) + Pink (Dark) + Red (Dark) + Green (Dark) + Cornflower Blue (Dark) + Lemon Cream (Dark) + Vivid Yellow (Dark) + Dayglo Orange (Dark) + Mono (Dark) + Mono (Light) + Blue (Light) + Red (Light) + Green (Light) + Dayglo Orange (Light) + Corn Yellow (Dark) + + Steps + Floors Climbed + Active Minutes (Weekly) + Calories (Manual Goal) + Off + + Heart Rate + Heart Rate (Live 5s) + Battery + Battery (Hide Percentage) + Notifications + Calories + Distance + Alarms + Altitude + Thermometer + Bluetooth + Bluetooth/Notifications + Sunrise/Sunset + Weather + Humidity + Pressure + + + + + Dim + Lun + Mar + Mer + Jeu + Ven + Sam + + Jan + Fev + Mar + Avr + Mai + Juin + Juil + Aout + Sep + Oct + Nov + Dec + + diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 86a4c4cb..dd12a640 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -2,82 +2,83 @@ Crystal - App Version + Version de l'appli - Theme - Hours Colour - Minutes Colour - Left Meter - Right Meter - Calories Goal (1-10,000kCal) - Meter Style - Meter Digits Style - Add Local Time in City (Beta) - Move Bar Style - Hide Seconds - Hide Hours Leading Zero + Thème + Couleur des heures + Couleur des minutes + Compteur de gauche + Compteur de droite + Objectif de calories (1-10,000kCal) + Apparence des compteurs + Apparence des champs numériques + Ajout de l'heure d'une ville (Beta) + Apparence de la barre d'activité + Masquer les secondes + Masquer le zéro avant l'heure OpenWeatherMap API Key Override - Number Of Data Fields - Data Field 1 - Data Field 2 - Data Field 3 + Nombre de champs de données + Champs de données 1 + Champs de données 2 + Champs de données 3 - Number Of Indicators - Indicator 1 - Indicator 2 - Indicator 3 + Nombre d'indicateurs + Indicateur 1 + Indicateur 2 + Indicateur 3 - (From Theme) - Mono Highlight - Mono + (À partir du thème) + Monochrome brillant + Monochrome - All Segments (Merged) - Filled Segments (Merged) - All Segments - Filled Segments - Hidden - Current/Target - Current + Tous les segments (fusionnés) + Segments remplis seulement (fusionnés) + Tous les segments + Segments remplis seulement + Masqué + Actuel/Objectif + Actuel - Blue (Dark) - Pink (Dark) - Red (Dark) - Green (Dark) - Cornflower Blue (Dark) - Lemon Cream (Dark) - Vivid Yellow (Dark) - Dayglo Orange (Dark) - Mono (Dark) - Mono (Light) - Blue (Light) - Red (Light) - Green (Light) - Dayglo Orange (Light) - Corn Yellow (Dark) + Bleu (sur fond noir) + Rose (sur fond noir) + Rouge (sur fond noir) + Vert(sur fond noir) + Bleu pale (sur fond noir) + Crème (sur fond noir) + Jaune vif (sur fond noir) + Orange (sur fond noir) + Monochrome (sur fond noir) + Monochrome (sur fond blanc) + Bleu (sur fond blanc) + Rouge (sur fond blanc) + Vert (sur fond blanc) + Orange (sur fond blanc) + Jaune foncé (sur fond noir) - Steps - Floors Climbed - Active Minutes (Weekly) - Calories (Manual Goal) - Off + Pas + Étages montées + Minutes actives (hebdo) + Calories (objectif manuel) + Masqué - Heart Rate - Heart Rate (Live 5s) - Battery - Battery (Hide Percentage) + Rythme cardiaque + Rythme cardiaque (actif 5s) + Pile + Pile (Pourcentage masqué) Notifications Calories Distance - Alarms + Alarmes Altitude - Thermometer + Thermomètre Bluetooth Bluetooth/Notifications - Sunrise/Sunset - Weather - Humidity - Pressure + Lever/Coucher du soleil + Météo + Humidité + Pression + Pulse Ox @@ -91,16 +92,16 @@ Sam Jan - Fev + Fév Mar Avr Mai Juin Juil - Aout + Août Sep Oct Nov - Dec + Déc diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index c276bbdd..07fdc357 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index ea52a8c5..fa6cc717 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index fe6c592f..f63c7158 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index cc6715cf..a7d7ff25 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox KOR diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index edb90006..debe2d42 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index ed28931d..1d4d4ea0 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -77,6 +77,7 @@ Pogoda Humidity Ciśnienie + Pulse Ox diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index d0e1a467..5a8018e8 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-rectangle-205x148/fonts/fonts.xml b/resources-rectangle-205x148/fonts/fonts.xml index dec28d6e..80b93802 100644 --- a/resources-rectangle-205x148/fonts/fonts.xml +++ b/resources-rectangle-205x148/fonts/fonts.xml @@ -7,7 +7,7 @@ - + diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt b/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt index 929f1269..599a9744 100644 --- a/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt +++ b/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt @@ -12,3 +12,4 @@ char id=54 x=88 y=0 width=27 height=38 xoffset=2 yoffset=0 char id=55 x=196 y=0 width=25 height=37 xoffset=3 yoffset=1 xadvance=30 page=0 chnl=15 char id=56 x=0 y=0 width=29 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 char id=57 x=59 y=0 width=28 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 +char id=58 x=20 y=39 width=10 height=38 xoffset=1 yoffset=0 xadvance=10 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54_0.png b/resources-rectangle-205x148/fonts/titillium-web-light-54_0.png index b5b01ed0f399d6d22d82a6ddce5792492df915d3..143345f3ba86b7907900c270abdb3eea734ba848 100644 GIT binary patch literal 3782 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 NssVqZTBTwe^*<`I5Yhku literal 3617 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 diff --git a/resources-rectangle-240x240/fonts/fonts.xml b/resources-rectangle-240x240/fonts/fonts.xml index 0e2c8c73..aee5a84d 100644 --- a/resources-rectangle-240x240/fonts/fonts.xml +++ b/resources-rectangle-240x240/fonts/fonts.xml @@ -3,7 +3,7 @@ - + @@ -12,10 +12,10 @@ - + - + diff --git a/resources-round-208x208/fonts/fonts.xml b/resources-round-208x208/fonts/fonts.xml index 5583da69..66390c55 100644 --- a/resources-round-208x208/fonts/fonts.xml +++ b/resources-round-208x208/fonts/fonts.xml @@ -2,7 +2,7 @@ - + diff --git a/resources-round-260x260/fonts/fonts.xml b/resources-round-260x260/fonts/fonts.xml index 42f35466..1e25cc54 100644 --- a/resources-round-260x260/fonts/fonts.xml +++ b/resources-round-260x260/fonts/fonts.xml @@ -2,7 +2,7 @@ - + diff --git a/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt b/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt index 6d98c518..a9d83042 100644 --- a/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt +++ b/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt @@ -12,3 +12,4 @@ char id=54 x=111 y=0 width=34 height=54 xoffset=4 yoffset=35 char id=55 x=0 y=55 width=31 height=53 xoffset=5 yoffset=36 xadvance=41 page=0 chnl=15 char id=56 x=0 y=0 width=37 height=54 xoffset=2 yoffset=35 xadvance=41 page=0 chnl=15 char id=57 x=75 y=0 width=35 height=54 xoffset=3 yoffset=35 xadvance=41 page=0 chnl=15 +char id=58 x=95 y=55 width=10 height=54 xoffset=3 yoffset=35 xadvance=11 page=0 chnl=15 diff --git a/resources-round-260x260/fonts/titillium-web-light-74-tall_0.png b/resources-round-260x260/fonts/titillium-web-light-74-tall_0.png index ad55f660994530d9661ac582a3654e6c8f385015..27fe00c307d96b7285d31e8f00c5ca7cb8be3026 100644 GIT binary patch literal 3691 zcmcgv=Q|sW*G@u=c&M$9+1gvxR(lhB)~HoGL5mherB!N=5=6z`vqscjrDly7rAE~j zt4M9}>+}8*@42pX?(yNi&euD}*if4i!VCcb0F=5q8m0gM@Gk`d$o^hH@V{rRe}ObW z*FckWgPew%NxJ2%+x4$S{!GW(9{`}B{cnNTrPtR002M@6L)AR!$3EI1o_>G<@saYV z_lL7;dIm8yubXu|Eroi~3mq4(r$YSaTP~dbG02E&rFBN3(sV!7M0$+TSkKP78og)o zCwk8UZnc6K_=wMtiK8VV-TqK-6!IyAdygGHt4Nr1!IidEwh~@3_wL0n^R>8@mR?%S zR90C1vA0^2VoYkFDL#4*eXp2+wG#0!>6iI~(%(qQ)fDg4S~m+reu^5pSjTT3;h}ss zcCR#l)D%uFOm$_{-l~g!58li#Hy>L(smOZO@QAlT49(y2qct5fjShAkaUoRBTzU}h z`opXW5skWIXQd_I4O}x8OwNs-1fD}*7DAr$R3NTJ`#X<(;At@|3s ztNOBbVFuAw&OY21M~R&+(Ka6B9inA?!9A-)gIOP<=xaSTH-IkILyX;wN6{swHhT}| znX$qqG3hf9FiGpBXV%tI4d~skW=0+ww7|a52*sdX^XzOnM=~rm5ovJZC^jS&?sOsh z&`%rfegh1*d8@V;;)W?|{Y{A=pq3hyb zM?BX$JLPvx08bnU+6Am5-O}jR!{uXzUmOQ!T(mvbC|QlNOLc39ub5i^%HchnSFJ~x zfo-L@CL5)0WI?Ewxb$q4pXzMN&SVCzg&5PWF40?KXd~^$91HBGN_Z@n{$UY9yi|eV zo0YGQx7BYwnzn$ z`k7>H5Tz+hUmfPjkCUe?gInWpi-Z2_jFyBs- zAO9#)!M#h9mR(_aMSeO`iPX@sY=b-NdSV6gMi{WV^qa5}mE>g(3p-GAh4c#x=~#aL z{Co^hTts4W`Vrn}*#M7{xX0ApRGJ49^oKb4>?gi_!#2(-Y3tCbga0}4) z*9T4X&mL5YsgItc`Z?+3mAyW&nNzV@*}$;e!PmILjCmu!wK+}M4VQQIO{+U79UhIH zv?ELu=lyEaL!|I!;WQbNXIL@T90*_G^9s_Ud1+N~8`aCg?Zdi^!7-?`EnD3wuG;+= zyftq>(U%aLrTVQ|iuVn#^ZO?SF*f3-X_?nV4t2SFZ$Z{R@{(%hn-GX`D+NlDlqr(_ zUf)gDFnLrtUp&Pd24kj(%t$~wq8fjNCDUBKV;B)%J?QkY%nI>MF07w1xqc|SVyGY| zrT&=88?Lci8W+8TzpJMJ)MFls%X-)Rpac&gD|1F!3$AQJbUr*pGKEvgS{DsOFdrB% zP+|ou2LR-KWxOA`^@sEYIzXlrs+^+7%nu-gUO(|SIl!|UVcrohmAgy9-(Yw>G%Ow( zh5Ruo*ykFXK;6c3U zAQZ^sJAH+U?KuBEMt3jcJ*6iv;Nux%f1=#Tk}-zO?dgpx)C7-lhh|+--=(C_@U`~^ zGWaC&;Kco&qXYG!jSJ|xk_?6RQ|V-9g7DEg)pYJ|aVkbQlpuey*6DpGaSbP_D{S{C zdUvuY!yB8bIK?G?qwJA3l@L^nHPIyr7^2Aw>HClb=zq{BZL`CV#ocAq&6P;s+kcxN z(4CNyD1*-_7QVb4H7O8 zJl2zTThbHmP_R$>uBsrV=H{uWjf2f_A)TyU{lJ7QK6#ElZ%$3g(zw7>29lebC87+!D)2^s$hSsDTtLPUxT~!D=4h5Z+tb#-7^Zo5w&|Kr-FpGii_fjZ(94kZ;c#0aq{9(uWV+8^)?$!!y~b&1C5{0UtvlGUrfV1QCmw1 z?R={>rwXysjSJHU*0ClI^*~9*D8IJN1mmTLidToY!d5CX@v7&Z69uqry`>tZGIl@P z<-vCUu~-Y&5yi$s1Ym8V6`HrfYVU*MENZdBwSe$QgSy~|E?~L3D=z@{5UuB zB0p?UYV+SPMboq&MJcDHAHLACMcntlmol7?sdwQQ$BY^gc!z_R`{H=DR88cGSW#JU z!d*uW?YixRRaIwZK7#=}VU#f5@zcR`VnzL->Ef{%%-ug9Q2As+11RXX7OQ6JT0}B zb?46h1)kT=$#fy+S*t$BVGVq=580M;Mm*g}PZ#<~M~wQXDv~KDa?KxUYe_2Eacs1O zw&u9=Joc7Z&@!P+Zn&Ydt=D&Nu%g#_hKY>Y`NPl{XxPyBdSr*^QTAeIXTA56({xaE zSQG6%RYkco-(hAQY0PkO!HLWdhL+f(cKi6@3MyYFl8UGDggP1lYbWGrdTF+Ffq$;Tls;T$FCt(PPJ_kXFgnn^*_kB8YJ$gK-T38{MX=l6RFQz zpNuBX$NwNtvZml;doTAo#g;EsHfvfsW+!pnR<;?J!74;)?g?S$S0TUH8kw_rOXClF z6|H%{3--)>j8pT0R~v9L_)=CG4znY99814bD>oFXNBEd4SM3X((ecaWe>1(^2@)`= zjO?UeS($5k>GNKK$CVPeYR1c3!}XqBN-t`V1YeBka|G=e%HpGRfXrOc*P;h+tSG-7 zj0|5JUUT6mFlz(+!BAu_dxJG$DY@!atNwGOsbnp2et*(Gx7Qm# z@1sC^cFQ;Q_+P%bMU%i6ne=(tAfv+de?q{@z|>n9*|Pun(}PJ>nXR$=iGlk-#?aqf z{#O??&&C70K3^S9NZnk&odrv-r~Z=x6@B!n%CFl zYDRxLCJ;RWeWen`cM7v^kMA^x@M{6=iR5ZYWqz|2vu^BhgnL z5xdC#9&wYmWw6Q(PA!v!Q4C91E5!Gl0jh|C*Q;(*4mQx>^sCkJ^^t&WCggg39bf@xm*0KmV$b&L_P4qr8AQ4F~3nzof#?y-8cOeUJO$y2YEY)vB z4j%MQz17nqR|WF_QgfR9@|VXHfQ(@m7l}7{4aHz87BG0)1om@Hl&xNCju-;zhTS_8 z3v*KTa4~QcXIGh3nY_~~LKifih=y8qvIeM+2>g9NbdRH}==6A`H{pCwOm6X}^W|H3 zeRzX7;f6!`-vH={Bh>l!i9|1y7_Q>7KRN!&LFp)@j3L+oKdoB9nzhD2pR8spREs!GE3%ymLPKTU0l|b+`!3F&;Ael s{Lzz?VHtguzr#EJt8)L3vz>Gc^v@h_j8CBauRQ{EH4Qat)EwXb4-U%p5C8xG literal 3505 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 sM`o)CK_dud!T}0g6XKW&i*H literal 9383 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 k!{2TE|Mh>^f#19P0yJg0z>% diff --git a/resources-round-280x280/fonts/fonts.xml b/resources-round-280x280/fonts/fonts.xml index 497b4c78..cf8da6df 100644 --- a/resources-round-280x280/fonts/fonts.xml +++ b/resources-round-280x280/fonts/fonts.xml @@ -2,7 +2,7 @@ - + diff --git a/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt b/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt index 049b1dfe..aa4e9823 100644 --- a/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt +++ b/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt @@ -1,7 +1,7 @@ info face="Titillium Web Light" size=-80 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=129 base=96 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-light-80-tall_0.png" -chars count=10 +chars count=11 char id=48 x=41 y=0 width=39 height=58 xoffset=3 yoffset=38 xadvance=45 page=0 chnl=15 char id=49 x=231 y=0 width=22 height=56 xoffset=9 yoffset=39 xadvance=45 page=0 chnl=15 char id=50 x=0 y=59 width=35 height=57 xoffset=5 yoffset=38 xadvance=45 page=0 chnl=15 @@ -12,3 +12,4 @@ char id=54 x=120 y=0 width=37 height=58 xoffset=4 yoffset=38 char id=55 x=36 y=59 width=33 height=57 xoffset=6 yoffset=39 xadvance=45 page=0 chnl=15 char id=56 x=0 y=0 width=40 height=58 xoffset=2 yoffset=38 xadvance=45 page=0 chnl=15 char id=57 x=81 y=0 width=38 height=58 xoffset=3 yoffset=38 xadvance=45 page=0 chnl=15 +char id=58 x=114 y=59 width=10 height=56 xoffset=0 yoffset=38 xadvance=10 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-280x280/fonts/titillium-web-light-80-tall_0.png b/resources-round-280x280/fonts/titillium-web-light-80-tall_0.png index c35991dedb1c5a3a33654f4a282b7be71dc280e1..e1ff2fe8843117c0ce65f6ff1b192b2b3c92ccfe 100644 GIT binary patch delta 3770 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 XUaL(2gvof}00000NkvXXu0mjfgKb23 diff --git a/resources-round-360x360/fonts/fonts.xml b/resources-round-360x360/fonts/fonts.xml index 9fba4349..1e69c0db 100644 --- a/resources-round-360x360/fonts/fonts.xml +++ b/resources-round-360x360/fonts/fonts.xml @@ -2,7 +2,7 @@ - + @@ -24,10 +24,10 @@ - + - + diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt index 1b0347a8..44129b8b 100644 --- a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt +++ b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-39 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=39 base=39 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-extra-large.png" -chars count=17 +chars count=18 char id=48 x=0 y=0 width=34 height=39 xoffset=0 yoffset=0 xadvance=34 page=0 chnl=15 char id=49 x=34 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 char id=50 x=73 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 @@ -18,4 +18,5 @@ char id=61 x=163 y=39 width=9 height=9 xoffset=0 yoffset=13 char id=62 x=0 y=78 width=45 height=39 xoffset=0 yoffset=0 xadvance=45 page=0 chnl=15 char id=63 x=45 y=78 width=45 height=39 xoffset=0 yoffset=0 xadvance=45 page=0 chnl=15 char id=64 x=90 y=78 width=33 height=39 xoffset=0 yoffset=0 xadvance=33 page=0 chnl=15 -char id=65 x=123 y=78 width=27 height=39 xoffset=0 yoffset=0 xadvance=27 page=0 chnl=15 \ No newline at end of file +char id=65 x=123 y=78 width=27 height=39 xoffset=0 yoffset=0 xadvance=27 page=0 chnl=15 +char id=66 x=153 y=78 width=43 height=39 xoffset=0 yoffset=0 xadvance=43 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.png b/resources-round-390x390/fonts/crystal-icons-extra-large.png index 3a9378f3edac6292ad997902bbc6e1371c580a86..e988b5950686897c116c925e445397717e8b8f0b 100644 GIT binary patch literal 12228 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 literal 13234 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 - + @@ -22,10 +22,10 @@ - + - + diff --git a/resources-round-416x416/fonts/fonts.xml b/resources-round-416x416/fonts/fonts.xml index 5541a4f7..6ae3349d 100644 --- a/resources-round-416x416/fonts/fonts.xml +++ b/resources-round-416x416/fonts/fonts.xml @@ -2,7 +2,7 @@ - + @@ -23,10 +23,10 @@ - + - + diff --git a/resources-round-416x416/fonts/titillium-web-light-85-tall.fnt b/resources-round-416x416/fonts/titillium-web-light-85-tall.fnt index 89b3b494..f425a1f9 100644 --- a/resources-round-416x416/fonts/titillium-web-light-85-tall.fnt +++ b/resources-round-416x416/fonts/titillium-web-light-85-tall.fnt @@ -12,3 +12,4 @@ char id=54 x=86 y=0 width=40 height=61 xoffset=4 yoffset=41 char id=55 x=37 y=62 width=36 height=60 xoffset=6 yoffset=42 xadvance=48 page=0 chnl=15 char id=56 x=0 y=0 width=43 height=61 xoffset=2 yoffset=41 xadvance=48 page=0 chnl=15 char id=57 x=127 y=0 width=40 height=61 xoffset=3 yoffset=41 xadvance=48 page=0 chnl=15 +char id=58 x=145 y=62 width=12 height=61 xoffset=3 yoffset=41 xadvance=12 page=0 chnl=15 diff --git a/resources-round-416x416/fonts/titillium-web-light-85-tall_0.png b/resources-round-416x416/fonts/titillium-web-light-85-tall_0.png index e28af3b56a1f3b91b0cee61cac14aa644c8f21ae..14126c87a9bc2581386cded84ac23f761487bdcf 100644 GIT binary patch literal 4089 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 F{{YjBt#1GT diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index d4722902..9203a0ee 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -77,6 +77,7 @@ Погода Влажность Давление + Pulse Ox RUS diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index f00d62a9..31b6a10a 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 5bd646b7..5a5f7ce2 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-small-time/fonts/fonts.xml b/resources-small-time/fonts/fonts.xml index dc63011b..281f6a7f 100644 --- a/resources-small-time/fonts/fonts.xml +++ b/resources-small-time/fonts/fonts.xml @@ -2,7 +2,7 @@ - + diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 5bf5b9bc..7afc42a9 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 0f3b06a1..d8943033 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -77,6 +77,7 @@ Väder Luftfuktighet Tryck + Pulse Ox diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 0ccda644..17343bb0 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox ZHS diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index c0d9b744..6ba2fc0e 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -78,6 +78,7 @@ Weather Humidity Pressure + Pulse Ox ZHT diff --git a/resources/fonts/crystal-icons.fnt b/resources/fonts/crystal-icons.fnt index dd5b89a7..2b32067c 100644 --- a/resources/fonts/crystal-icons.fnt +++ b/resources/fonts/crystal-icons.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-24 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=24 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons.png" -chars count=17 +chars count=18 char id=48 x=0 y=0 width=21 height=24 xoffset=1 yoffset=0 xadvance=24 page=0 chnl=15 char id=49 x=22 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=50 x=47 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 @@ -18,4 +18,5 @@ char id=61 x=38 y=25 width=6 height=6 xoffset=0 yoffset=9 char id=62 x=47 y=25 width=28 height=24 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=63 x=76 y=25 width=28 height=24 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=64 x=105 y=25 width=20 height=24 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 -char id=65 x=126 y=25 width=17 height=24 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 \ No newline at end of file +char id=65 x=126 y=25 width=17 height=24 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 +char id=66 x=145 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file diff --git a/resources/fonts/crystal-icons.png b/resources/fonts/crystal-icons.png index 9a7b658cc240defb496353860de929c657458d84..2dbdfae931d1c7c41a9c67de900cca8fa8ed1cc9 100644 GIT binary patch delta 4719 zcmd^@23?2R0X0WfFV;$P1*SM?4IR2TSgr$ zKe4j%I~2pmUwBGZMdipZloeb;cj%m`i0Q;Wp{Qabd4Anqn6(W#k$)d-Gkeyy6cT1F zsbg@uHEuFFsgTM$!XpT;4IgF)RNk;eg5i|$!Pgt`Q{N{fku=i}2W6dGD!Or&-TF8D zu<8rHwLb?l07jaG-29QBEO?tO_)z2W+N=ljVWDfi^e<4+DOo?So6ix(_naJ6G?I-> zI*hf;+E>2B;kOg)dZQs|%?b*XYS@XBpP$q*71)!G!}VC-YjL0FZSS!*#?fIe{IaxB zDtKonWc1k!B6Kj1e!*_h6;arY3K0xPTe_-7QnwE<>`^Pw+O44A`gb8{L^}PS5SBwW zfLm$Y{`Aux+5K)}xA*>uS;le@0a3V64O`@)J-SM|^~6U1>FCf3A+WNp*42mhJxWn5 zOVrq7WSA4QU=eg?CL)^(`-$dSF%30EoktbtMme7TtFwK(ig)OIEw4}>Ow-gIT)w%q zdIi`%X-Y=sOpM3!Q!OTdf{J)c@hb|I2j;=+RF(BY*Sk5U7iF6sDF(M2VjpI$-+QK| z6}3Lzqwv1g#5CDD&kr#xojhqzj;gHsDxE8;$&wkcxQ)F8mENuclONa6jd_&(*pKeE zvPXnUhc$%=bN6zSL7f`hQLo>Xpb8?S53oV?SsMKKQM#RM%CXUBPq_)dVu?7&l@})% z=fXhQ3OU=UhQFT=w%^eD6D5zEqwZ=INnV%Y?%M^R2(&K7 z%w`L4X}jncISJ8A~TCw+Zj4ZXj3eC0`Agr#-bBWE} z{i_AvOI5{Nd<`$n+fxG00FV^+7aq zHxsA*FunSOTE*-7Gvg|}ev&%f#RqV}<-qkZ;}YbI!g=^%7x|7#IE| z0A7e379~eWM{GT4l}5p4F*4k7>Kn0P+1)QKC_2F`IxwDGC5H#EOKV8#C_70O)yUg# z+D7?CreAJai^=eAO|pu*l02Prk?O0-7SPu9?}@CBmx3|WG7m041Q;@VPNt<`U%CnW zZIHuYSQ5XPl!F0t_%-K4+B1^a??xRUSwz@XGo!2~^ny~Yy`1C?mZXZHq}`M zvF#~$g-<~ahXPpHI`%PoH={kHU1Y%OX#Vf0Kxbutk1#-_qoV^Ca*0otP5&rHHa41; z0$6i(nx^6D!ZAzJbDv%$qa)1(POJ^Ve2q{ny)S&1f zAZ<|x-(OBlV5*J}$N%fPO3_W(=5zkdVUz9aexEt<9%i^#iv7C*W<+i^)@XSYq427| z3T|MX{$nEIug_QL>xK8fvMN48duZuQJT&B;UFv)by?J=?h}he=b*(SOV|+`=(0k3qHa_Lqn#fYbEu zDnE_SuLsS2Cga9!p1bU`75#1M40#tLNv$#b^V+_yA)2qQtx%xa!&VwUK2s1GBuiuK z+EMBYf0m_73={Thl4tHpmeN!`h{-n!Z<&HsPNAFRmV2W1f&K1l7P5Ug@vRH`zGWVg zM^hoh79_5NjZR2=3ETLwr?YK$pE2T5$NWJmG^G8_3XLt;wzQ0d>70;jT8aChJ6`EcE`QvmPp9mBg+0XowZa|$6 zL}ui9uuNwH=4P!o`S1-g@!KWO7-3yvXFKTJ#!1?T-^+8?ml`^)PAYC+ka+9D*~9LB z?T(gDT)!?$V6*up;`}&|%<`kSvHH*m-eVcjOM}ZxWc13L$x+$NinNT=(b=W*xMznI zw=HMsppl(fwc=xp6i~HwV^{l94y&ZKD2A@)OUIXDIjls?t!J}^PHp!T`Z*YM&!R#4 z71mV_X4yqPbf_)#zLb*J;)nv10Nwf%wTu?!ct(GWi%GB29!pID?1duFQU z*m+$VHsbDr;!IPR0JEX$lr;uya|k zWks_ZA5IMa9m3jMO*Z?a(w*CTt9aX%qE;#UX(shS6Pb9ad?9SVc@Qa015l6P%hjQ<^5(Fey=$GQ+(9xNU&FhY#Lc0*{vWkBH~hU z)qh9F3}hb9pK4-3?47q*aO__tcu?o$k{WrIy+Hp;TT$FNljY8z;juNDjm0ajKs|Pg zyeZ)QPd&HElTUOtrfWQ<4IB{R!uqdW`j(?LD^JTBwOzqbg8uz%6gGl)eTuJolDp>% zIhP^lq&xo4j4okEuuW+HHKzUBHooQ!3BBxIFJX|}1?sI*0pVObPjLF^75CuDqm2({ z+)COteH9h@xLS%Wf4ZuuHRGbw#Mz|J;(h=j&~`^G>cBJuV=jKWH#ZI;FDsjYG_qV4 zR9>LfCm%j^{$tqoq1&S?$Ld}A;eIwY$6Wj3XTYF;C2MjW`c0jt_GAuAK)%F+jWHPlate%?UaT_7ebhh+pi}OJO+ZQiJijkY#iC=U zvgw;`{zw^wrI7023DoKitRk41z9j*E%clYYospLVbg714dzJ!8vebsWBhJTv#Zbsv zE|y6&`RM1I9jy3Sqeu1hJO*FX0aGpiH1yDxm4=VR%a{MO5maG-g=OGPopn8yzm`AP zq!Pej$)Em$Rns9+#=%DVURm3JsGoa#Ae&H25XC-*H)$86u!cVNrHG5HrsjFpieR^-dEEXH+8s;)ZPCn)d+{J zQAPF7m&|!cYCcX@9?5Pj3HQObl-@g+*$^^CJw2$3E}o>7b3%660u0xh8Rw! z@j>N)KclQaa$j#|F{km~S|53Gc+B$snpP%zR`<*Szc3S9mYkSS8ro~1tS;a9_V3NX z$`-@dVo97k`4(KliRX~FSR0Yn1S{x`-Zm-tH6(H=Pjk%yhIXnc5}vvB$JUB5^w){< zD_sYHWg6t=PXT(Xejh=3dD>CWjkQe0>vJQE-G-*7Cbk>an;X%4>C?xjruwWuUyMFf z%BCk|C@pUlxUDZz3=MeQ=8$2t-6xj>l&Vi<-<;R0cTiJ!Ep}gPZ9&rWM>`g-shqe;^-VJhj&)rS>2khD$AxYV+%}9?FYb78Zv$zy7orZK>*c_61q$WKzY(pc zW)nclQTw-V-%M^^q~8v99M&F_1idZ>B*#oFG7x!Gk+iD`2?@MDn~GlSFROCfZsi)v z%80rcN5S&i+HnuR1;8gXnHIMQ6iQ2698#&XB+qx8#G#W*=3mi$uyNkcdaIS*e=~j! zIwE#$I{?M^sQHfk`1Rh1D#3K;Pe$RXQ7^!_-yl3kNDDt9_2BJH(CbEQi&apKhTE>O zwDpPV!IChFRema^uJQ74GKf`JxxDXNc2T=Jfr85uiaGrqWHs~Y9_`|%>gt=pQ54Vt z;13(%Pi$9j~i*Xm(_ZlONndu!c-};M4=g cdFbyBdAhVgGBSUQ{~bkI>iTNcDt3|o0skRUQvd(} delta 4536 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 WGucZ`dNDr$0000 - + diff --git a/resources/fonts/titillium-web-semibold-24-chars.txt b/resources/fonts/titillium-web-semibold-24-chars.txt index 4a273147..7d872abd 100644 --- a/resources/fonts/titillium-web-semibold-24-chars.txt +++ b/resources/fonts/titillium-web-semibold-24-chars.txt @@ -1,8 +1,8 @@ 0123456789AP - 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÁÄÅÉÍÖØÚČĚŘŚŠŹŽ - 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÁÄÅÉÍÖØÚČĚŘŚŠŹŽ + 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÁÄÅÉÍÖØÚÛČĚŘŚŠŹŽ + 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÁÄÅÉÍÖØÚÛČĚŘŚŠŹŽ %0123456789 %-.0123456789!:?CFabefgikmpsty° %',-.0123456789!:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz°ÅÍÎÖáãäåæèéíðñóôöøûüž - 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÁÄÅÉÍÖØÚČĚŘŚŠŹŽ + 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÁÄÅÉÍÖØÚÛČĚŘŚŠŹŽ %0123456789 \ No newline at end of file diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 23df79c6..3ce69994 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -15,13 +15,13 @@ 3 0 - 1 - 2 + 14 + 11 - 1 - 0 - 1 - 2 + 2 + 5 + 3 + 0 @@ -30,6 +30,6 @@ false true - + 3268578d0f3633073e62b3d8a560a09a diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index d1ad615a..2b2b0b05 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -88,6 +88,7 @@ @Strings.SunriseSunset @Strings.Weather @Strings.Humidity + @Strings.PulseOx @@ -107,6 +108,7 @@ @Strings.SunriseSunset @Strings.Weather @Strings.Humidity + @Strings.PulseOx @@ -126,6 +128,7 @@ @Strings.SunriseSunset @Strings.Weather @Strings.Humidity + @Strings.PulseOx @@ -140,6 +143,7 @@ @Strings.Notifications @Strings.BluetoothOrNotifications @Strings.Battery + @Strings.BatteryNumeric @@ -150,6 +154,7 @@ @Strings.Notifications @Strings.BluetoothOrNotifications @Strings.Battery + @Strings.BatteryNumeric @@ -160,6 +165,7 @@ @Strings.Notifications @Strings.BluetoothOrNotifications @Strings.Battery + @Strings.BatteryNumeric diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 3f805380..c069f6e8 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -64,6 +64,7 @@ Heart Rate Heart Rate (Live 5s) Battery + Battery Numeric Battery (Hide Percentage) Notifications Calories @@ -102,4 +103,8 @@ Nov Dec + Battery Numeric + Pulse Ox + + diff --git a/source/CrystalView.mc b/source/CrystalView.mc index bcae44d1..302043c3 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -76,6 +76,22 @@ function drawBatteryMeter(dc, x, y, width, height) { height - (2 * lineWidthPlusMargin)); } +function writeBatteryLevel(dc, x, y, width, height) { + var batteryLevel = Math.floor(Sys.getSystemStats().battery); + + var textColour; + if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { + textColour = Graphics.COLOR_RED; + } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { + textColour = Graphics.COLOR_YELLOW; + } else { + textColour = gThemeColour; + } + + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, Math.floor(Sys.getSystemStats().battery).format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); +} + class CrystalView extends Ui.WatchFace { private var mIsSleeping = false; private var mIsBurnInProtection = false; // Is burn-in protection required and active? diff --git a/source/DataFields.mc b/source/DataFields.mc index 2f2cf216..cb0d9c1c 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -28,7 +28,8 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_SUNRISE_SUNSET, FIELD_TYPE_WEATHER, FIELD_TYPE_PRESSURE, - FIELD_TYPE_HUMIDITY + FIELD_TYPE_HUMIDITY, + FIELD_TYPE_PULSE_OX } class DataFields extends Ui.Drawable { @@ -316,6 +317,7 @@ class DataFields extends Ui.Drawable { FIELD_TYPE_SUNRISE_SUNSET => "?", FIELD_TYPE_PRESSURE => "@", FIELD_TYPE_HUMIDITY => "A", + FIELD_TYPE_PULSE_OX => "B", // SG Addition }[fieldType]; } @@ -368,6 +370,14 @@ class DataFields extends Ui.Drawable { var unit; switch (type) { + // SG Addition + case FIELD_TYPE_PULSE_OX: + activityInfo = Activity.getActivityInfo(); + sample = activityInfo != null and activityInfo has :currentOxygenSaturation ? activityInfo.currentOxygenSaturation : null; + if (sample != null) { + value = sample.format(INTEGER_FORMAT) + "%"; + } + break; case FIELD_TYPE_HEART_RATE: case FIELD_TYPE_HR_LIVE_5S: // #34 Try to retrieve live HR from Activity::Info, before falling back to historical HR from ActivityMonitor. diff --git a/source/Indicators.mc b/source/Indicators.mc index 816bec50..341a6e71 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -92,6 +92,11 @@ class Indicators extends Ui.Drawable { return; } + if (indicatorType == 5 /* INDICATOR_TYPE_BATTERY_NUMERIC */) { + writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2); + return; + } + // Show notifications icon if connected and there are notifications, bluetoothicon otherwise. var settings = Sys.getDeviceSettings(); if (indicatorType == 3 /* INDICATOR_TYPE_BLUETOOTH_OR_NOTIFICATIONS */) { From 210e1b63932cc6dd70b2299c93aac5a8c12c3725 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 22 Sep 2021 21:11:19 -0400 Subject: [PATCH 002/220] Delete fonts.xml --- resources-fr920xt/fonts/fonts.xml | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 resources-fr920xt/fonts/fonts.xml diff --git a/resources-fr920xt/fonts/fonts.xml b/resources-fr920xt/fonts/fonts.xml deleted file mode 100644 index 7185e3f1..00000000 --- a/resources-fr920xt/fonts/fonts.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 051f66402918787748dc6577bbbb194ea8262fb8 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 22 Sep 2021 21:11:30 -0400 Subject: [PATCH 003/220] Delete .gitignore --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a7dcad01..00000000 --- a/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build/ -bin/ -.project -.settings/ \ No newline at end of file From 2d01faccf61dffa3c4e22fd3cb4ee4dc1721177e Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 28 Nov 2021 23:49:33 -0500 Subject: [PATCH 004/220] Create .gitignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2198afd2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.project +.settings/ +bin/ +manifest.xml +.vscode/launch.json +.vscode/tasks.json From 8322532c59afe42341769a6ec739f76017ef265a Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 24 Mar 2022 08:07:07 -0400 Subject: [PATCH 005/220] Added a Tesla battery level as an indicator --- resources-fre/strings/strings.xml | 5 +- resources/settings/properties.xml | 2 + resources/settings/settings.xml | 7 ++ resources/strings/strings.xml | 3 +- source/BackgroundService.mc | 113 +++++++++++++++++++++++++++++- source/CrystalApp.mc | 62 ++++++++++++++-- source/CrystalView.mc | 79 ++++++++++++++++++--- source/Indicators.mc | 14 +++- 8 files changed, 268 insertions(+), 17 deletions(-) diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index dd12a640..60304b66 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -78,7 +78,6 @@ Météo Humidité Pression - Pulse Ox @@ -104,4 +103,8 @@ Nov Déc + Battery Numeric + Pulse Ox + Tesla battery level + Tesla Token diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 3ce69994..db21d2dd 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -32,4 +32,6 @@ 3268578d0f3633073e62b3d8a560a09a + + diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 2b2b0b05..17eea8dc 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -144,6 +144,7 @@ @Strings.BluetoothOrNotifications @Strings.Battery @Strings.BatteryNumeric + @Strings.Tesla @@ -155,6 +156,7 @@ @Strings.BluetoothOrNotifications @Strings.Battery @Strings.BatteryNumeric + @Strings.Tesla @@ -166,6 +168,7 @@ @Strings.BluetoothOrNotifications @Strings.Battery @Strings.BatteryNumeric + @Strings.Tesla @@ -209,4 +212,8 @@ + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index c069f6e8..191fbcc7 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -105,6 +105,7 @@ Battery Numeric Pulse Ox - + Tesla battery level + Tesla Token diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 17e30159..2a99a9fa 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -2,13 +2,34 @@ using Toybox.Background as Bg; using Toybox.System as Sys; using Toybox.Communications as Comms; using Toybox.Application as App; +using Toybox.Time; +using Toybox.Time.Gregorian; (:background) class BackgroundService extends Sys.ServiceDelegate { - + + var _token; + var _vehicle_id; + (:background_method) function initialize() { Sys.ServiceDelegate.initialize(); + + // Need to get a token since we can't OAUTH from a watch face :-( + // If someone can it, be my guest. I spent too much time on this already + _token = App.getApp().getProperty("TeslaToken"); + if (_token != null) { + _token = "Bearer " + _token; + } + + _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); + if (_vehicle_id == null) { +logMessage("Getting vehicle_id for token '" + _token + "'"); + makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); + } else { +logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); + makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + } } // Read pending web requests, and call appropriate web request function. @@ -16,8 +37,9 @@ class BackgroundService extends Sys.ServiceDelegate { // Pending web request flag will be cleared only once the background data has been successfully received. (:background_method) function onTemporalEvent() { - //Sys.println("onTemporalEvent"); + Sys.println("onTemporalEvent"); var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); +logMessage("PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. @@ -58,6 +80,18 @@ class BackgroundService extends Sys.ServiceDelegate { }, method(:onReceiveOpenWeatherMapCurrent) ); + + // 3. Tesla + } else if (pendingWebRequests["TeslaBatterieLevel"] != null) { +logMessage("TeslaBatterieLevel with vehicle_id at " + _vehicle_id); + + if (_vehicle_id) { +logMessage("Calling makeTeslaWebRequest to get vehicle data"); + makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + } else { +logMessage("NOT calling makeTeslaWebRequest because of null vehicle_id"); + pendingWebRequests["TeslaBatterieLevel"] = null; + } } } /* else { Sys.println("onTemporalEvent() called with no pending web requests!"); @@ -190,6 +224,58 @@ class BackgroundService extends Sys.ServiceDelegate { }); } + (:background_method) + function onReceiveVehicles(responseCode, data) { + var result; + +logMessage("onReceiveVehicles responseCode is " + responseCode); + if (responseCode == 200) { + var vehicles = data.get("response"); + if (vehicles.size() > 0) { + _vehicle_id = vehicles[0].get("id"); +logMessage("vehicle_id is " + _vehicle_id); + } else { +logMessage("No vehicle in account"); + _vehicle_id = 0; + } + result = { "vehicle_id" => _vehicle_id}; + + } else { + result = { "httpError" => responseCode }; + } + + Bg.exit({ "TeslaBatterieLevel" => result }); + } + + (:background_method) + function onReceiveVehicleData(responseCode, data) { + var result; + +logMessage("onReceiveVehicleData responseCode is " + responseCode); + if (responseCode == 200) { + result = data.get("response"); + if (result != null) { + result = result.get("charge_state"); + if (result != null) { + result = result.get("battery_level"); + if (result == null) { + result = "N/A"; + } + } else { + result = "N/A"; + } + } else { + result = "N/A"; + } +logMessage("onReceiveVehicleData received " + result); + result = { "battery_level" => result, "vehicle_id" => _vehicle_id }; + } else { + result = { "httpError" => responseCode }; + } + Bg.exit({ "TeslaBatterieLevel" => result }); + } + + (:background_method) function makeWebRequest(url, params, callback) { var options = { @@ -201,4 +287,27 @@ class BackgroundService extends Sys.ServiceDelegate { Comms.makeWebRequest(url, params, options, callback); } + + (:background_method) + function makeTeslaWebRequest(url, params, callback) { + var options = { + :method => Comms.HTTP_REQUEST_METHOD_GET, + :headers => { + "Authorization" => _token}, + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON + }; +logMessage("makeTeslaWebRequest with url='" + url + "' params='" + params + "' options='" + options + "'"); + Comms.makeWebRequest(url, params, options, callback); + } + +(:debug) +function logMessage(message) { + var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min + ":" + clockTime.sec; + Sys.println(dateStr + " : " + message); +} + +(:release) +function logMessage(output) { +} } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 20d3a0a4..1c54aaca 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -3,6 +3,7 @@ using Toybox.Background as Bg; using Toybox.System as Sys; using Toybox.WatchUi as Ui; using Toybox.Time; +using Toybox.Time.Gregorian; // In-memory current location. // Previously persisted in App.Storage, but now persisted in Object Store due to #86 workaround for App.Storage firmware bug. @@ -76,12 +77,12 @@ class CrystalApp extends App.AppBase { // Currently called on layout initialisation, when settings change, and on exiting sleep. (:background_method) function checkPendingWebRequests() { - +logMessage("In checkPendingWebRequests"); // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. var location = Activity.getActivityInfo().currentLocation; if (location) { - // Sys.println("Saving location"); + // logMessage("Saving location"); location = location.toDegrees(); // Array of Doubles. gLocationLat = location[0].toFloat(); gLocationLng = location[1].toFloat(); @@ -102,13 +103,14 @@ class CrystalApp extends App.AppBase { gLocationLng = lng; } } - // Sys.println(gLocationLat + ", " + gLocationLng); + // logMessage(gLocationLat + ", " + gLocationLng); if (!(Sys has :ServiceDelegate)) { return; } var pendingWebRequests = getProperty("PendingWebRequests"); +logMessage("PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { pendingWebRequests = {}; } @@ -169,6 +171,47 @@ class CrystalApp extends App.AppBase { } } + // 3. Tesla: + if (getProperty("Tesla")) { +logMessage("Tesla!"); + var teslaBatterieLevel = getProperty("TeslaBatterieLevel"); +logMessage("TeslaBatterieLevel=" + teslaBatterieLevel); + + // No existing data. + if (teslaBatterieLevel == null) { +logMessage("Asking first read"); + + pendingWebRequests["TeslaBatterieLevel"] = true; + + // We got something, check what it is + } else { + var batterie_level = teslaBatterieLevel["battery_level"]; + + var result = teslaBatterieLevel["httpError"]; + if (result != null && result != 408) { // We got an error is it's not because the vehicle is asleep +logMessage("Got http error '" + result + "'"); + setProperty("TeslaVehicleID", null); // Try to get a new vehicleID + batterie_level = "N/A"; + } + + var vehicle_id = teslaBatterieLevel["vehicle_id"]; + if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process + if (vehicle_id != 0) { +logMessage("Saving '" + vehicle_id +"' as vehicle_id"); + setProperty("TeslaVehicleID", vehicle_id.toString()); + } else { + setProperty("TeslaVehicleID", null); + batterie_level = "N/A"; + } + } + + if (batterie_level != null) { + setProperty("TeslaBatterieLevelValue", batterie_level); + } + + pendingWebRequests["TeslaBatterieLevel"] = true; + } + } // If there are any pending requests: if (pendingWebRequests.keys().size() > 0) { @@ -199,7 +242,7 @@ class CrystalApp extends App.AppBase { function onBackgroundData(data) { var pendingWebRequests = getProperty("PendingWebRequests"); if (pendingWebRequests == null) { - //Sys.println("onBackgroundData() called with no pending web requests!"); + //logMessage("onBackgroundData() called with no pending web requests!"); pendingWebRequests = {}; } @@ -260,3 +303,14 @@ class CrystalApp extends App.AppBase { }; } } + +(:debug) +function logMessage(message) { + var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min + ":" + clockTime.sec; + Sys.println(dateStr + " : " + message); +} + +(:release) +function logMessage(output) { +} \ No newline at end of file diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 302043c3..cfe45171 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -3,6 +3,7 @@ using Toybox.Graphics as Graphics; using Toybox.System as Sys; using Toybox.Application as App; using Toybox.ActivityMonitor as ActivityMonitor; +using Toybox.Communications as Comms; using Toybox.Math; @@ -76,20 +77,41 @@ function drawBatteryMeter(dc, x, y, width, height) { height - (2 * lineWidthPlusMargin)); } -function writeBatteryLevel(dc, x, y, width, height) { - var batteryLevel = Math.floor(Sys.getSystemStats().battery); +function writeBatteryLevel(dc, x, y, width, height, type) { + var batteryLevel; var textColour; - if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { - textColour = Graphics.COLOR_RED; - } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { - textColour = Graphics.COLOR_YELLOW; + + if (type == 0) { + batteryLevel = Math.floor(Sys.getSystemStats().battery); + } else { + batteryLevel = App.getApp().getProperty("TeslaBatterieLevelValue"); + } +//logMessage(batteryLevel + " is of type " + type_name(batteryLevel)); + + var inText = false; + if (batteryLevel == null || (batteryLevel instanceof Toybox.Lang.String && batteryLevel.equals("N/A"))) { + textColour = Graphics.COLOR_LT_GRAY; + inText = true; + batteryLevel = "???"; } else { - textColour = gThemeColour; + batteryLevel = batteryLevel.toFloat(); + + if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { + textColour = Graphics.COLOR_RED; + } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { + textColour = Graphics.COLOR_YELLOW; + } else { + textColour = gThemeColour; + } } dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, Math.floor(Sys.getSystemStats().battery).format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); + if (inText) { + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel, Graphics.TEXT_JUSTIFY_LEFT); + } else { + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); + } } class CrystalView extends Ui.WatchFace { @@ -445,6 +467,7 @@ class CrystalView extends Ui.WatchFace { // Rather than checking the need for background requests on a timer, or on the hour, easier just to check when exiting // sleep. if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. +logMessage("Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } @@ -499,3 +522,43 @@ class CrystalView extends Ui.WatchFace { mDrawables[:MoveBar].setFullWidth(hideSeconds); } } + +function type_name(obj) { + if (obj instanceof Toybox.Lang.Number) { + return "Number"; + } else if (obj instanceof Toybox.Lang.Long) { + return "Long"; + } else if (obj instanceof Toybox.Lang.Float) { + return "Float"; + } else if (obj instanceof Toybox.Lang.Double) { + return "Double"; + } else if (obj instanceof Toybox.Lang.Boolean) { + return "Boolean"; + } else if (obj instanceof Toybox.Lang.String) { + return "String"; + } else if (obj instanceof Toybox.Lang.Array) { + var s = "Array ["; + for (var i = 0; i < obj.size(); ++i) { + s += type_name(obj); + s += ", "; + } + s += "]"; + return s; + } else if (obj instanceof Toybox.Lang.Dictionary) { + var s = "Dictionary{"; + var keys = obj.keys(); + var vals = obj.values(); + for (var i = 0; i < keys.size(); ++i) { + s += keys; + s += ": "; + s += vals; + s += ", "; + } + s += "}"; + return s; + } else if (obj instanceof Toybox.Time.Gregorian.Info) { + return "Gregorian.Info"; + } else { + return "???"; + } +} \ No newline at end of file diff --git a/source/Indicators.mc b/source/Indicators.mc index 341a6e71..4242c2ac 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -39,6 +39,13 @@ class Indicators extends Ui.Drawable { mIndicator1Type = App.getApp().getProperty("Indicator1Type"); mIndicator2Type = App.getApp().getProperty("Indicator2Type"); mIndicator3Type = App.getApp().getProperty("Indicator3Type"); + + if (mIndicator1Type == 6 || mIndicator2Type == 6 || mIndicator3Type == 6) { + App.getApp().setProperty("Tesla", true); +logMessage("Doing Tesla!"); + } else { + App.getApp().setProperty("Tesla", false); + } } function draw(dc) { @@ -93,7 +100,12 @@ class Indicators extends Ui.Drawable { } if (indicatorType == 5 /* INDICATOR_TYPE_BATTERY_NUMERIC */) { - writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2); + writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 0); + return; + } + + if (indicatorType == 6 /* INDICATOR_TYPE_TESLA */) { // We're reusing the watch batterie indicator to show the Tesla's batterie level + writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 1); return; } From 309493b0867197a3e857a41b52d56fd7fe61e564 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 25 Mar 2022 16:16:16 -0400 Subject: [PATCH 006/220] Better handling of errors and can now refresh an access token through the help of the refresh token (hopefully) --- resources-fre/strings/strings.xml | 5 +- resources/settings/properties.xml | 3 +- resources/settings/settings.xml | 8 ++- resources/strings/strings.xml | 3 +- source/BackgroundService.mc | 90 +++++++++++++++++++++++++------ source/CrystalApp.mc | 65 +++++++++++++++++----- source/CrystalView.mc | 6 ++- source/Indicators.mc | 2 +- 8 files changed, 145 insertions(+), 37 deletions(-) diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 60304b66..34b3a159 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -103,8 +103,9 @@ Nov Déc - Battery Numeric + Batterie Numérique Pulse Ox Tesla battery level - Tesla Token + Tesla Access Token + Tesla Refresh Token diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index db21d2dd..bd631e81 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -32,6 +32,7 @@ 3268578d0f3633073e62b3d8a560a09a - + + diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 17eea8dc..68958f6b 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -212,8 +212,12 @@ - - + + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 191fbcc7..fd4ba42a 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -106,6 +106,7 @@ Battery Numeric Pulse Ox Tesla battery level - Tesla Token + Tesla Access Token + Tesla Refresh Token diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 2a99a9fa..6e72e133 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -14,17 +14,39 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function initialize() { Sys.ServiceDelegate.initialize(); - + + // If we don't have a phone connected, don't go any further. + if (!Sys.getDeviceSettings().phoneConnected) { +logMessage("initialize: No phone connected"); + return; + } + + if (App.getApp().getProperty("Tesla") == null) { +logMessage("initialize: Not requesting Tesla stuff, bailing out"); + return; + } + // Need to get a token since we can't OAUTH from a watch face :-( // If someone can it, be my guest. I spent too much time on this already - _token = App.getApp().getProperty("TeslaToken"); - if (_token != null) { + _token = App.getApp().getProperty("TeslaAccessToken"); + if (_token != null && _token.equals("") == false) { +logMessage("initialize:Using token '" + _token + "'"); _token = "Bearer " + _token; } + else { +logMessage("initialize:Generating Access Token"); + var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); + if (refreshToken != null) { + makeTeslaWebPost(refreshToken, method(:onReceiveToken)); + } else { +logMessage("initialize:No refresh token!"); + } + return; + } _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); if (_vehicle_id == null) { -logMessage("Getting vehicle_id for token '" + _token + "'"); +logMessage("initialize:Getting vehicle_id"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); @@ -37,9 +59,8 @@ logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); // Pending web request flag will be cleared only once the background data has been successfully received. (:background_method) function onTemporalEvent() { - Sys.println("onTemporalEvent"); var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -logMessage("PendingWebRequests is '" + pendingWebRequests + "'"); +logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. @@ -82,15 +103,21 @@ logMessage("PendingWebRequests is '" + pendingWebRequests + "'"); ); // 3. Tesla - } else if (pendingWebRequests["TeslaBatterieLevel"] != null) { -logMessage("TeslaBatterieLevel with vehicle_id at " + _vehicle_id); + } else if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { + if (!Sys.getDeviceSettings().phoneConnected) { +logMessage("onTemporalEvent: No phone connected"); +// pendingWebRequests["TeslaBatterieLevel"] = null; + return; + } + +logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); if (_vehicle_id) { -logMessage("Calling makeTeslaWebRequest to get vehicle data"); +logMessage("onTemporalEvent:Calling makeTeslaWebRequest to get vehicle data"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } else { -logMessage("NOT calling makeTeslaWebRequest because of null vehicle_id"); - pendingWebRequests["TeslaBatterieLevel"] = null; +logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data because of null vehicle_id"); +// pendingWebRequests["TeslaBatterieLevel"] = null; } } } /* else { @@ -224,6 +251,20 @@ logMessage("NOT calling makeTeslaWebRequest because of null vehicle_id"); }); } + (:background_method) + function onReceiveToken(responseCode, data) { + var result; + +logMessage("onReceiveToken responseCode is " + responseCode); +logMessage("onReceiveToken data is " + data); + if (responseCode == 200) { + result = { "Token" => data }; + } else { + result = { "httpErrorTesla" => responseCode }; + } + Bg.exit({ "TeslaBatterieLevel" => result }); + } + (:background_method) function onReceiveVehicles(responseCode, data) { var result; @@ -233,15 +274,15 @@ logMessage("onReceiveVehicles responseCode is " + responseCode); var vehicles = data.get("response"); if (vehicles.size() > 0) { _vehicle_id = vehicles[0].get("id"); -logMessage("vehicle_id is " + _vehicle_id); +logMessage("onReceiveVehicles:vehicle_id is " + _vehicle_id); } else { -logMessage("No vehicle in account"); +logMessage("onReceiveVehicles:No vehicle in account"); _vehicle_id = 0; } result = { "vehicle_id" => _vehicle_id}; } else { - result = { "httpError" => responseCode }; + result = { "httpErrorTesla" => responseCode }; } Bg.exit({ "TeslaBatterieLevel" => result }); @@ -270,7 +311,7 @@ logMessage("onReceiveVehicleData responseCode is " + responseCode); logMessage("onReceiveVehicleData received " + result); result = { "battery_level" => result, "vehicle_id" => _vehicle_id }; } else { - result = { "httpError" => responseCode }; + result = { "httpErrorTesla" => responseCode }; } Bg.exit({ "TeslaBatterieLevel" => result }); } @@ -300,6 +341,25 @@ logMessage("makeTeslaWebRequest with url='" + url + "' params='" + params + "' o Comms.makeWebRequest(url, params, options, callback); } + (:background_method) + function makeTeslaWebPost(token, notify) { + var url = "https://auth.tesla.com/oauth2/v3/token"; + Communications.makeWebRequest( + url, + { + "grant_type" => "refresh_token", + "client_id" => "ownerapi", + "refresh_token" => token, + "scope" => "openid email offline_access" + }, + { + :method => Communications.HTTP_REQUEST_METHOD_POST, + :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + }, + notify + ); + } + (:debug) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 1c54aaca..49712426 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -77,7 +77,7 @@ class CrystalApp extends App.AppBase { // Currently called on layout initialisation, when settings change, and on exiting sleep. (:background_method) function checkPendingWebRequests() { -logMessage("In checkPendingWebRequests"); +logMessage("checkPendingWebRequests:Begining"); // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. var location = Activity.getActivityInfo().currentLocation; @@ -110,7 +110,7 @@ logMessage("In checkPendingWebRequests"); } var pendingWebRequests = getProperty("PendingWebRequests"); -logMessage("PendingWebRequests is '" + pendingWebRequests + "'"); +logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { pendingWebRequests = {}; } @@ -172,14 +172,14 @@ logMessage("PendingWebRequests is '" + pendingWebRequests + "'"); } // 3. Tesla: - if (getProperty("Tesla")) { -logMessage("Tesla!"); + if (getProperty("Tesla") != null) { +logMessage("checkPendingWebRequests:Tesla!"); var teslaBatterieLevel = getProperty("TeslaBatterieLevel"); -logMessage("TeslaBatterieLevel=" + teslaBatterieLevel); +logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel); // No existing data. if (teslaBatterieLevel == null) { -logMessage("Asking first read"); +logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); pendingWebRequests["TeslaBatterieLevel"] = true; @@ -187,26 +187,63 @@ logMessage("Asking first read"); } else { var batterie_level = teslaBatterieLevel["battery_level"]; - var result = teslaBatterieLevel["httpError"]; - if (result != null && result != 408) { // We got an error is it's not because the vehicle is asleep -logMessage("Got http error '" + result + "'"); - setProperty("TeslaVehicleID", null); // Try to get a new vehicleID - batterie_level = "N/A"; + // First handle errors, setting batterie_level to "N/A" if the query returned a vehicle not found. + // If we failed to get access, maybe our token has expired, clear it so next time the background process runs, it will refresh it + // Other errors are silent for now + var result = teslaBatterieLevel["httpErrorTesla"]; + if (result != null) { +logMessage("checkPendingWebRequests:Got http error '" + result + "'"); + if (result == 400 || result == 401) { // Our token has expired, refresh it +logMessage("checkPendingWebRequests:Clearing TeslaAccessToken"); + setProperty("TeslaAccessToken", null); // Try to get a new vehicleID + } + + if (result == 404) { // We got an vehicle not found error, reset our vehicle ID +logMessage("checkPendingWebRequests:Clearing TeslaVehicleID"); + setProperty("TeslaVehicleID", null); // Try to get a new vehicleID + batterie_level = "N/A"; + } + } + + // Check if our access token was refreshed. If so, store the new access and refresh tokens + result = teslaBatterieLevel["Token"]; + if (result != null) { +logMessage("checkPendingWebRequests:Got token data '" + result + "'"); + var accessToken = result["access_token"]; + var refreshToken = result["refresh_token"]; + var expires_in = result["refresh_token"]; + setProperty("TeslaAccessToken", accessToken); + if (refreshToken != null && refreshToken.equals("") != false) { // Only if we received a refresh tokem +logMessage("checkPendingWebRequests:But missing the refresh token"); + setProperty("TeslaRefreshToken", refreshToken); + } + setProperty("TeslaExpiresIn", expires_in); } + // Read our vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. + // If we have no vehicle, set the batterie level to N/A var vehicle_id = teslaBatterieLevel["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { -logMessage("Saving '" + vehicle_id +"' as vehicle_id"); +logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); setProperty("TeslaVehicleID", vehicle_id.toString()); } else { +logMessage("checkPendingWebRequests: vehicle_id we got was 0"); setProperty("TeslaVehicleID", null); batterie_level = "N/A"; } + } else { +logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null"); + setProperty("TeslaVehicleID", null); + batterie_level = "N/A"; } + // Here batterie_level is the same as what was read earlier or changed to N/A for some reason above. if (batterie_level != null) { setProperty("TeslaBatterieLevelValue", batterie_level); + } else { +logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); +// setProperty("TeslaBatterieLevelValue", null); } pendingWebRequests["TeslaBatterieLevel"] = true; @@ -240,9 +277,11 @@ logMessage("Saving '" + vehicle_id +"' as vehicle_id"); // pendingWebRequests keys. (:background_method) function onBackgroundData(data) { +logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = getProperty("PendingWebRequests"); +logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { - //logMessage("onBackgroundData() called with no pending web requests!"); +logMessage("onBackgroundData: called with no pending web requests!"); pendingWebRequests = {}; } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index cfe45171..644c2034 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -199,6 +199,7 @@ class CrystalView extends Ui.WatchFace { // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { mSettingsChangedSinceLastDraw = true; +logMessage("onSettingsChanged called"); updateNormalFont(); @@ -209,6 +210,7 @@ class CrystalView extends Ui.WatchFace { updateHoursMinutesColours(); if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. +logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } } @@ -456,7 +458,7 @@ class CrystalView extends Ui.WatchFace { function onExitSleep() { mIsSleeping = false; - //Sys.println("onExitSleep()"); + logMessage("onExitSleep:onExitSleep()"); // If watch does not support per-second updates, AND HideSeconds property is false, // show seconds, and make move bar original width. @@ -467,7 +469,7 @@ class CrystalView extends Ui.WatchFace { // Rather than checking the need for background requests on a timer, or on the hour, easier just to check when exiting // sleep. if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. -logMessage("Wakeup and checkPendingWebRequests"); +logMessage("onExitSleep:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } diff --git a/source/Indicators.mc b/source/Indicators.mc index 4242c2ac..238f4e9f 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -42,7 +42,7 @@ class Indicators extends Ui.Drawable { if (mIndicator1Type == 6 || mIndicator2Type == 6 || mIndicator3Type == 6) { App.getApp().setProperty("Tesla", true); -logMessage("Doing Tesla!"); +logMessage("onSettingsChanged:Doing Tesla!"); } else { App.getApp().setProperty("Tesla", false); } From 52b56a3b85c7910c7b847fb410941c6262a7e85f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 25 Mar 2022 21:52:43 -0400 Subject: [PATCH 007/220] Will show by a '+' sign after the % when the car is charginh --- resources-round-208x208/fonts/fonts.xml | 2 +- resources-round-280x280/fonts/fonts.xml | 4 +-- resources-round-360x360/fonts/fonts.xml | 4 +-- resources-round-390x390/fonts/fonts.xml | 4 +-- resources-round-416x416/fonts/fonts.xml | 4 +-- resources/fonts/fonts.xml | 4 +-- source/BackgroundService.mc | 32 +++++++++++------- source/CrystalApp.mc | 45 ++++++++++++++++++------- source/CrystalView.mc | 26 ++++++++++---- 9 files changed, 84 insertions(+), 41 deletions(-) diff --git a/resources-round-208x208/fonts/fonts.xml b/resources-round-208x208/fonts/fonts.xml index 66390c55..dc7035f9 100644 --- a/resources-round-208x208/fonts/fonts.xml +++ b/resources-round-208x208/fonts/fonts.xml @@ -4,7 +4,7 @@ - + diff --git a/resources-round-280x280/fonts/fonts.xml b/resources-round-280x280/fonts/fonts.xml index cf8da6df..e286cbf3 100644 --- a/resources-round-280x280/fonts/fonts.xml +++ b/resources-round-280x280/fonts/fonts.xml @@ -3,8 +3,8 @@ - - + + diff --git a/resources-round-360x360/fonts/fonts.xml b/resources-round-360x360/fonts/fonts.xml index 1e69c0db..08607dd0 100644 --- a/resources-round-360x360/fonts/fonts.xml +++ b/resources-round-360x360/fonts/fonts.xml @@ -5,8 +5,8 @@ - - + + diff --git a/resources-round-390x390/fonts/fonts.xml b/resources-round-390x390/fonts/fonts.xml index 3f1e0039..72db0c26 100644 --- a/resources-round-390x390/fonts/fonts.xml +++ b/resources-round-390x390/fonts/fonts.xml @@ -5,8 +5,8 @@ - - + + diff --git a/resources-round-416x416/fonts/fonts.xml b/resources-round-416x416/fonts/fonts.xml index 6ae3349d..e8594698 100644 --- a/resources-round-416x416/fonts/fonts.xml +++ b/resources-round-416x416/fonts/fonts.xml @@ -5,8 +5,8 @@ - - + + diff --git a/resources/fonts/fonts.xml b/resources/fonts/fonts.xml index f4eac92d..77fec8f2 100644 --- a/resources/fonts/fonts.xml +++ b/resources/fonts/fonts.xml @@ -3,8 +3,8 @@ - - + + diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 6e72e133..76220c1a 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -30,7 +30,7 @@ logMessage("initialize: Not requesting Tesla stuff, bailing out"); // If someone can it, be my guest. I spent too much time on this already _token = App.getApp().getProperty("TeslaAccessToken"); if (_token != null && _token.equals("") == false) { -logMessage("initialize:Using token '" + _token + "'"); +logMessage("initialize:Using token '" + _token.substring(0,10) + "...'"); _token = "Bearer " + _token; } else { @@ -291,6 +291,8 @@ logMessage("onReceiveVehicles:No vehicle in account"); (:background_method) function onReceiveVehicleData(responseCode, data) { var result; + var batterieLevel = "N/A"; + var chargingState = "Disconnected"; logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { @@ -298,25 +300,31 @@ logMessage("onReceiveVehicleData responseCode is " + responseCode); if (result != null) { result = result.get("charge_state"); if (result != null) { - result = result.get("battery_level"); - if (result == null) { - result = "N/A"; + batterieLevel = result.get("battery_level"); + chargingState = result.get("charging_state"); + +//batterieLevel = Math.rand() % 100; + if (batterieLevel == null) { + batterieLevel = "N/A"; } - } else { - result = "N/A"; + + result = { + "battery_level" => batterieLevel, + "charging_state" => chargingState +// "charging_state" => "Charging" + }; } - } else { - result = "N/A"; } logMessage("onReceiveVehicleData received " + result); - result = { "battery_level" => result, "vehicle_id" => _vehicle_id }; + result = { "battery_state" => result, "vehicle_id" => _vehicle_id }; } else { result = { "httpErrorTesla" => responseCode }; } + + Bg.exit({ "TeslaBatterieLevel" => result }); } - (:background_method) function makeWebRequest(url, params, callback) { var options = { @@ -337,7 +345,7 @@ logMessage("onReceiveVehicleData received " + result); "Authorization" => _token}, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; -logMessage("makeTeslaWebRequest with url='" + url + "' params='" + params + "' options='" + options + "'"); +//logMessage("makeTeslaWebRequest with url='" + url + "' params='" + params + "' options='" + options + "'"); Comms.makeWebRequest(url, params, options, callback); } @@ -363,7 +371,7 @@ logMessage("makeTeslaWebRequest with url='" + url + "' params='" + params + "' o (:debug) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min + ":" + clockTime.sec; + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); Sys.println(dateStr + " : " + message); } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 49712426..4c5b7edc 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -77,7 +77,7 @@ class CrystalApp extends App.AppBase { // Currently called on layout initialisation, when settings change, and on exiting sleep. (:background_method) function checkPendingWebRequests() { -logMessage("checkPendingWebRequests:Begining"); +//logMessage("checkPendingWebRequests:Begining"); // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. var location = Activity.getActivityInfo().currentLocation; @@ -173,7 +173,6 @@ logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequest // 3. Tesla: if (getProperty("Tesla") != null) { -logMessage("checkPendingWebRequests:Tesla!"); var teslaBatterieLevel = getProperty("TeslaBatterieLevel"); logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel); @@ -185,8 +184,16 @@ logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); // We got something, check what it is } else { - var batterie_level = teslaBatterieLevel["battery_level"]; - + var batterie_state = teslaBatterieLevel["battery_state"]; + var batterie_level = null; + var charging_state = null; + var batterie_stale = false; + + if (batterie_state) { + batterie_level = batterie_state["battery_level"]; + charging_state = batterie_state["charging_state"]; + } + // First handle errors, setting batterie_level to "N/A" if the query returned a vehicle not found. // If we failed to get access, maybe our token has expired, clear it so next time the background process runs, it will refresh it // Other errors are silent for now @@ -194,30 +201,34 @@ logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); if (result != null) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); if (result == 400 || result == 401) { // Our token has expired, refresh it -logMessage("checkPendingWebRequests:Clearing TeslaAccessToken"); setProperty("TeslaAccessToken", null); // Try to get a new vehicleID + batterie_stale = true; } if (result == 404) { // We got an vehicle not found error, reset our vehicle ID -logMessage("checkPendingWebRequests:Clearing TeslaVehicleID"); setProperty("TeslaVehicleID", null); // Try to get a new vehicleID - batterie_level = "N/A"; + batterie_stale = true; } } // Check if our access token was refreshed. If so, store the new access and refresh tokens result = teslaBatterieLevel["Token"]; if (result != null) { -logMessage("checkPendingWebRequests:Got token data '" + result + "'"); +//logMessage("checkPendingWebRequests:Got token data '" + result + "'"); +logMessage("checkPendingWebRequests:Got token data"); var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; var expires_in = result["refresh_token"]; +// var created_at = teslaBatterieLevel["CreatedAt"]; setProperty("TeslaAccessToken", accessToken); if (refreshToken != null && refreshToken.equals("") != false) { // Only if we received a refresh tokem -logMessage("checkPendingWebRequests:But missing the refresh token"); setProperty("TeslaRefreshToken", refreshToken); } - setProperty("TeslaExpiresIn", expires_in); + else { +logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); + } + setProperty("TeslaTokenExpiresIn", expires_in); +// setProperty("TeslaTokenCreatedAt", created_at); } // Read our vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. @@ -230,20 +241,25 @@ logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } else { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); setProperty("TeslaVehicleID", null); + batterie_stale = true; batterie_level = "N/A"; } } else { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null"); setProperty("TeslaVehicleID", null); - batterie_level = "N/A"; + batterie_stale = true; } // Here batterie_level is the same as what was read earlier or changed to N/A for some reason above. if (batterie_level != null) { setProperty("TeslaBatterieLevelValue", batterie_level); + setProperty("TeslaBatterieStale", batterie_stale); + setProperty("TeslaChargingState", charging_state); + } else { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); // setProperty("TeslaBatterieLevelValue", null); + setProperty("TeslaBatterieStale", true); } pendingWebRequests["TeslaBatterieLevel"] = true; @@ -257,8 +273,11 @@ logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our Tesla if (lastTime) { // Events scheduled for a time in the past trigger immediately. var nextTime = lastTime.add(new Time.Duration(5 * 60)); +var clockTime = Gregorian.info(nextTime, Time.FORMAT_MEDIUM); +logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); Bg.registerForTemporalEvent(nextTime); } else { +logMessage("checkPendingWebRequests:Scheduling now"); Bg.registerForTemporalEvent(Time.now()); } } @@ -301,6 +320,8 @@ logMessage("onBackgroundData: called with no pending web requests!"); setProperty("PendingWebRequests", pendingWebRequests); setProperty(type, storedData); + checkPendingWebRequests(); // We just got new data, process them right away before displaying + Ui.requestUpdate(); } @@ -346,7 +367,7 @@ logMessage("onBackgroundData: called with no pending web requests!"); (:debug) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min + ":" + clockTime.sec; + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); Sys.println(dateStr + " : " + message); } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 644c2034..eca3ceca 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -79,25 +79,39 @@ function drawBatteryMeter(dc, x, y, width, height) { function writeBatteryLevel(dc, x, y, width, height, type) { var batteryLevel; - + var batteryStale = false; + var chargingState = false; var textColour; if (type == 0) { batteryLevel = Math.floor(Sys.getSystemStats().battery); } else { batteryLevel = App.getApp().getProperty("TeslaBatterieLevelValue"); + batteryStale = App.getApp().getProperty("TeslaBatterieStale"); + chargingState = App.getApp().getProperty("TeslaChargingState"); + if (chargingState != null) { + if (chargingState.equals("Charging")) { + chargingState = true; + } else { + chargingState = false; + } + } else { + chargingState = false; + } } -//logMessage(batteryLevel + " is of type " + type_name(batteryLevel)); var inText = false; if (batteryLevel == null || (batteryLevel instanceof Toybox.Lang.String && batteryLevel.equals("N/A"))) { textColour = Graphics.COLOR_LT_GRAY; inText = true; + chargingState = false; batteryLevel = "???"; } else { batteryLevel = batteryLevel.toFloat(); - - if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { + + if (batteryStale == true) { + textColour = Graphics.COLOR_LT_GRAY; + } else if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { textColour = Graphics.COLOR_RED; } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { textColour = Graphics.COLOR_YELLOW; @@ -110,7 +124,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (inText) { dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel, Graphics.TEXT_JUSTIFY_LEFT); } else { - dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState ? "+" : ""), Graphics.TEXT_JUSTIFY_LEFT); } } @@ -221,7 +235,7 @@ logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); function updateNormalFont() { var city = App.getApp().getProperty("LocalTimeInCity"); - +logMessage("which font " + ((city != null) && (city.length() > 0))); // #78 Setting with value of empty string may cause corresponding property to be null. gNormalFont = Ui.loadResource(((city != null) && (city.length() > 0)) ? Rez.Fonts.NormalFontCities : Rez.Fonts.NormalFont); From 836d089dfbccb43782b201b47d6002e1bb00d00d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 26 Mar 2022 00:49:20 -0400 Subject: [PATCH 008/220] Better handling of 408 error --- source/CrystalApp.mc | 61 +++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 4c5b7edc..675c728d 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -188,7 +188,8 @@ logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); var batterie_level = null; var charging_state = null; var batterie_stale = false; - + var carAsleep = false; + if (batterie_state) { batterie_level = batterie_state["battery_level"]; charging_state = batterie_state["charging_state"]; @@ -203,11 +204,11 @@ logMessage("checkPendingWebRequests:Got http error '" + result + "'"); if (result == 400 || result == 401) { // Our token has expired, refresh it setProperty("TeslaAccessToken", null); // Try to get a new vehicleID batterie_stale = true; - } - - if (result == 404) { // We got an vehicle not found error, reset our vehicle ID + } else if (result == 404) { // We got an vehicle not found error, reset our vehicle ID setProperty("TeslaVehicleID", null); // Try to get a new vehicleID batterie_stale = true; + } else if (result == 408) { // Car is aslepep keep the old data but stop charging if it still was before going to sleep + carAsleep = true; } } @@ -231,37 +232,45 @@ logMessage("checkPendingWebRequests:But missing the refresh token '" + result + // setProperty("TeslaTokenCreatedAt", created_at); } - // Read our vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. + // If the car isn't asleep, keep the current charge and clear the charging_state + if (!carAsleep) { + // Rad its vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. // If we have no vehicle, set the batterie level to N/A - var vehicle_id = teslaBatterieLevel["vehicle_id"]; - if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process - if (vehicle_id != 0) { + var vehicle_id = teslaBatterieLevel["vehicle_id"]; + if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process + if (vehicle_id != 0) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); - setProperty("TeslaVehicleID", vehicle_id.toString()); - } else { + setProperty("TeslaVehicleID", vehicle_id.toString()); + } else { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); + setProperty("TeslaVehicleID", null); + batterie_stale = true; + batterie_level = "N/A"; + } + } else { +logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null"); setProperty("TeslaVehicleID", null); batterie_stale = true; - batterie_level = "N/A"; } - } else { -logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null"); - setProperty("TeslaVehicleID", null); - batterie_stale = true; - } - // Here batterie_level is the same as what was read earlier or changed to N/A for some reason above. - if (batterie_level != null) { - setProperty("TeslaBatterieLevelValue", batterie_level); - setProperty("TeslaBatterieStale", batterie_stale); - setProperty("TeslaChargingState", charging_state); - - } else { + // Here batterie_level is the same as what was read earlier or changed to N/A for some reason above. + if (batterie_level != null) { + setProperty("TeslaBatterieLevelValue", batterie_level); + setProperty("TeslaBatterieStale", batterie_stale); + setProperty("TeslaChargingState", charging_state); + + } else { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); -// setProperty("TeslaBatterieLevelValue", null); - setProperty("TeslaBatterieStale", true); +// setProperty("TeslaBatterieLevelValue", null); + setProperty("TeslaBatterieStale", true); + } + } else { + if (charging_state != null && charging_state.equals("Charging") == true) { + setProperty("TeslaChargingState", ""); + } + setProperty("TeslaBatterieStale", false); } - + pendingWebRequests["TeslaBatterieLevel"] = true; } } From 8b3d876e34ff8691a61dcaa13d8c6ee4584378b0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 26 Mar 2022 22:09:28 -0400 Subject: [PATCH 009/220] Not as chatty debugging code and needs to handle more than one event per call of onTemporalEvent --- source/BackgroundService.mc | 6 ++++-- source/CrystalApp.mc | 43 +++++++++++++++++++++++-------------- source/CrystalView.mc | 4 ++-- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 76220c1a..a335e5f5 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -74,7 +74,8 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") ); // 2. Weather. - } else if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { + } + if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", @@ -103,7 +104,8 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") ); // 3. Tesla - } else if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { + } + if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { if (!Sys.getDeviceSettings().phoneConnected) { logMessage("onTemporalEvent: No phone connected"); // pendingWebRequests["TeslaBatterieLevel"] = null; diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 675c728d..43b89357 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -18,7 +18,8 @@ class CrystalApp extends App.AppBase { var mView; var mFieldTypes = new [3]; - + var lastBackgroundSchedule = 0; + function initialize() { AppBase.initialize(); } @@ -80,6 +81,17 @@ class CrystalApp extends App.AppBase { //logMessage("checkPendingWebRequests:Begining"); // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. + + var lastTime = Bg.getLastTemporalEventTime(); + var doLog = false; + var teslaBatterieLevel = getProperty("TeslaBatterieLevel"); + +//logMessage("checkPendingWebRequests:lastBackgroundSchedule is " + lastBackgroundSchedule + " lastTime is " + (lastTime == null ? "null" : lastTime.value())); + if (lastTime == null || lastBackgroundSchedule != lastTime.value()) { + lastBackgroundSchedule = lastTime.value(); + doLog = true; + } + var location = Activity.getActivityInfo().currentLocation; if (location) { // logMessage("Saving location"); @@ -110,7 +122,7 @@ class CrystalApp extends App.AppBase { } var pendingWebRequests = getProperty("PendingWebRequests"); -logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); +if (doLog) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); } if (pendingWebRequests == null) { pendingWebRequests = {}; } @@ -173,12 +185,11 @@ logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequest // 3. Tesla: if (getProperty("Tesla") != null) { - var teslaBatterieLevel = getProperty("TeslaBatterieLevel"); -logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel); +if (doLog) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel); } // No existing data. if (teslaBatterieLevel == null) { -logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); +if (doLog) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } pendingWebRequests["TeslaBatterieLevel"] = true; @@ -200,7 +211,7 @@ logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); // Other errors are silent for now var result = teslaBatterieLevel["httpErrorTesla"]; if (result != null) { -logMessage("checkPendingWebRequests:Got http error '" + result + "'"); +if (doLog) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); } if (result == 400 || result == 401) { // Our token has expired, refresh it setProperty("TeslaAccessToken", null); // Try to get a new vehicleID batterie_stale = true; @@ -216,7 +227,7 @@ logMessage("checkPendingWebRequests:Got http error '" + result + "'"); result = teslaBatterieLevel["Token"]; if (result != null) { //logMessage("checkPendingWebRequests:Got token data '" + result + "'"); -logMessage("checkPendingWebRequests:Got token data"); +if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; var expires_in = result["refresh_token"]; @@ -226,7 +237,7 @@ logMessage("checkPendingWebRequests:Got token data"); setProperty("TeslaRefreshToken", refreshToken); } else { -logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); +if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); // setProperty("TeslaTokenCreatedAt", created_at); @@ -239,17 +250,17 @@ logMessage("checkPendingWebRequests:But missing the refresh token '" + result + var vehicle_id = teslaBatterieLevel["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { -logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); +if (doLog) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } setProperty("TeslaVehicleID", vehicle_id.toString()); } else { -logMessage("checkPendingWebRequests: vehicle_id we got was 0"); +if (doLog) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } setProperty("TeslaVehicleID", null); batterie_stale = true; batterie_level = "N/A"; } } else { -logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null"); - setProperty("TeslaVehicleID", null); +if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } +// setProperty("TeslaVehicleID", null); batterie_stale = true; } @@ -260,7 +271,7 @@ logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null"); setProperty("TeslaChargingState", charging_state); } else { -logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); +if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } // setProperty("TeslaBatterieLevelValue", null); setProperty("TeslaBatterieStale", true); } @@ -278,15 +289,15 @@ logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our Tesla if (pendingWebRequests.keys().size() > 0) { // Register for background temporal event as soon as possible. - var lastTime = Bg.getLastTemporalEventTime(); +// var lastTime = Bg.getLastTemporalEventTime(); if (lastTime) { // Events scheduled for a time in the past trigger immediately. var nextTime = lastTime.add(new Time.Duration(5 * 60)); var clockTime = Gregorian.info(nextTime, Time.FORMAT_MEDIUM); -logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); +if (doLog) { logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); } Bg.registerForTemporalEvent(nextTime); } else { -logMessage("checkPendingWebRequests:Scheduling now"); +if (doLog) { logMessage("checkPendingWebRequests:Scheduling now"); } Bg.registerForTemporalEvent(Time.now()); } } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index eca3ceca..0db0b1bd 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -472,7 +472,7 @@ logMessage("which font " + ((city != null) && (city.length() > 0))); function onExitSleep() { mIsSleeping = false; - logMessage("onExitSleep:onExitSleep()"); + //Sys.println("onExitSleep()"); // If watch does not support per-second updates, AND HideSeconds property is false, // show seconds, and make move bar original width. @@ -483,7 +483,7 @@ logMessage("which font " + ((city != null) && (city.length() > 0))); // Rather than checking the need for background requests on a timer, or on the hour, easier just to check when exiting // sleep. if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. -logMessage("onExitSleep:Wakeup and checkPendingWebRequests"); +//logMessage("onExitSleep:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } From f11aa18abf9ca12a0da11712daa4efe3fd05ef08 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 26 Mar 2022 22:52:54 -0400 Subject: [PATCH 010/220] More debugging code --- source/BackgroundService.mc | 3 +++ source/CrystalApp.mc | 2 +- source/CrystalView.mc | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index a335e5f5..ea581111 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -65,6 +65,7 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") // 1. City local time. if (pendingWebRequests["CityLocalTime"] != null) { +logMessage("onTemporalEvent: doing city event"); makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { @@ -76,6 +77,7 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") // 2. Weather. } if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { +logMessage("onTemporalEvent: doing weather event"); var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", @@ -106,6 +108,7 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") // 3. Tesla } if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { +logMessage("onTemporalEvent: doing Tesla event"); if (!Sys.getDeviceSettings().phoneConnected) { logMessage("onTemporalEvent: No phone connected"); // pendingWebRequests["TeslaBatterieLevel"] = null; diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 43b89357..c97e02fb 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -94,7 +94,7 @@ class CrystalApp extends App.AppBase { var location = Activity.getActivityInfo().currentLocation; if (location) { - // logMessage("Saving location"); + logMessage("Saving location"); location = location.toDegrees(); // Array of Doubles. gLocationLat = location[0].toFloat(); gLocationLng = location[1].toFloat(); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 0db0b1bd..b38def5c 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -235,7 +235,7 @@ logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); function updateNormalFont() { var city = App.getApp().getProperty("LocalTimeInCity"); -logMessage("which font " + ((city != null) && (city.length() > 0))); +//logMessage("which font " + ((city != null) && (city.length() > 0))); // #78 Setting with value of empty string may cause corresponding property to be null. gNormalFont = Ui.loadResource(((city != null) && (city.length() > 0)) ? Rez.Fonts.NormalFontCities : Rez.Fonts.NormalFont); From bb399b6a94cbe2a04645566e2a4bf919a22754d0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 26 Mar 2022 23:04:15 -0400 Subject: [PATCH 011/220] Now display a 's' after the % if the car is sleeping --- source/CrystalApp.mc | 4 +--- source/CrystalView.mc | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index c97e02fb..cc702151 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -276,9 +276,7 @@ if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clear setProperty("TeslaBatterieStale", true); } } else { - if (charging_state != null && charging_state.equals("Charging") == true) { - setProperty("TeslaChargingState", ""); - } + setProperty("TeslaChargingState", "Sleeping"); setProperty("TeslaBatterieStale", false); } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index b38def5c..1c2c37ab 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -80,7 +80,7 @@ function drawBatteryMeter(dc, x, y, width, height) { function writeBatteryLevel(dc, x, y, width, height, type) { var batteryLevel; var batteryStale = false; - var chargingState = false; + var chargingState = 0; var textColour; if (type == 0) { @@ -91,12 +91,12 @@ function writeBatteryLevel(dc, x, y, width, height, type) { chargingState = App.getApp().getProperty("TeslaChargingState"); if (chargingState != null) { if (chargingState.equals("Charging")) { - chargingState = true; - } else { - chargingState = false; + chargingState = 1; + } else if (chargingState.equals("Sleeping")) { + chargingState = 2; } } else { - chargingState = false; + chargingState = 0; } } @@ -124,7 +124,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (inText) { dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel, Graphics.TEXT_JUSTIFY_LEFT); } else { - dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState ? "+" : ""), Graphics.TEXT_JUSTIFY_LEFT); + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")), Graphics.TEXT_JUSTIFY_LEFT); } } From ade7252f5f0880070e789df3f809a1fa451e66e2 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 27 Mar 2022 14:13:55 -0400 Subject: [PATCH 012/220] Now preempt token expiry and ask for a new one if it's about to expire --- monkey.jungle | 4 ++ source/BackgroundService.mc | 97 ++++++++++++++++++++++++++----------- source/CrystalApp.mc | 15 ++++-- source/CrystalView.mc | 14 ++++-- 4 files changed, 95 insertions(+), 35 deletions(-) diff --git a/monkey.jungle b/monkey.jungle index a656f7cb..10085136 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -1,5 +1,9 @@ project.manifest = manifest.xml + + + + # Exclude other source directories (default behaviour is to include). base.sourcePath = source diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index ea581111..4664b9c3 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -15,6 +15,9 @@ class BackgroundService extends Sys.ServiceDelegate { function initialize() { Sys.ServiceDelegate.initialize(); + // ************************************************************************************ + // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE + // ************************************************************************************ // If we don't have a phone connected, don't go any further. if (!Sys.getDeviceSettings().phoneConnected) { logMessage("initialize: No phone connected"); @@ -27,16 +30,39 @@ logMessage("initialize: Not requesting Tesla stuff, bailing out"); } // Need to get a token since we can't OAUTH from a watch face :-( - // If someone can it, be my guest. I spent too much time on this already + // If someone can make it work, be my guest. I spent too much time on this already + // Check if the access_token is about to expire and if so, don't wait for the 401 error, renew it now! _token = App.getApp().getProperty("TeslaAccessToken"); - if (_token != null && _token.equals("") == false) { -logMessage("initialize:Using token '" + _token.substring(0,10) + "...'"); + + var createdAt = App.getApp().getProperty("TeslaTokenCreatedAt"); + if (createdAt == null) { + createdAt = 0; + } + else { + createdAt = createdAt.toNumber(); + } + var expireIn = App.getApp().getProperty("TeslaTokenExpiresIn"); + if (expireIn == null) { + expireIn = 0; + } + else { + expireIn = expireIn.toNumber(); + } + + var timeNow = Time.now().value(); + var interval = 5 * 60 * 60; + var answer = (timeNow + interval < createdAt + expireIn); + if (_token != null && _token.equals("") == false && answer == true) { + var expireAt = new Time.Moment(createdAt + expireIn); + var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); +logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { -logMessage("initialize:Generating Access Token"); +logMessage("initialize:Generating Access Token " + (answer == false) ? "because we're about to expire" : "because access token is null or empty"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); - if (refreshToken != null) { + if (refreshToken != null && refreshToken.equals("") == false) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { logMessage("initialize:No refresh token!"); @@ -52,6 +78,9 @@ logMessage("initialize:Getting vehicle_id"); logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } + // ************************************************************************************ + // END OF REMOVED SECTION + // ************************************************************************************ } // Read pending web requests, and call appropriate web request function. @@ -73,9 +102,9 @@ logMessage("onTemporalEvent: doing city event"); }, method(:onReceiveCityLocalTime) ); + } // 2. Weather. - } if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { logMessage("onTemporalEvent: doing weather event"); var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); @@ -104,9 +133,12 @@ logMessage("onTemporalEvent: doing weather event"); }, method(:onReceiveOpenWeatherMapCurrent) ); + } // 3. Tesla - } + // ************************************************************************************ + // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE + // ************************************************************************************ if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { logMessage("onTemporalEvent: doing Tesla event"); if (!Sys.getDeviceSettings().phoneConnected) { @@ -125,6 +157,9 @@ logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data bec // pendingWebRequests["TeslaBatterieLevel"] = null; } } + // ************************************************************************************ + // END OF REMOVED SECTION + // ************************************************************************************ } /* else { Sys.println("onTemporalEvent() called with no pending web requests!"); } */ @@ -256,6 +291,9 @@ logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data bec }); } + // ************************************************************************************ + // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE + // ************************************************************************************ (:background_method) function onReceiveToken(responseCode, data) { var result; @@ -330,18 +368,6 @@ logMessage("onReceiveVehicleData received " + result); Bg.exit({ "TeslaBatterieLevel" => result }); } - (:background_method) - function makeWebRequest(url, params, callback) { - var options = { - :method => Comms.HTTP_REQUEST_METHOD_GET, - :headers => { - "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED}, - :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON - }; - - Comms.makeWebRequest(url, params, options, callback); - } - (:background_method) function makeTeslaWebRequest(url, params, callback) { var options = { @@ -372,15 +398,30 @@ logMessage("onReceiveVehicleData received " + result); notify ); } + // ************************************************************************************ + // END OF REMOVED SECTION + // ************************************************************************************ -(:debug) -function logMessage(message) { - var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - Sys.println(dateStr + " : " + message); -} + (:background_method) + function makeWebRequest(url, params, callback) { + var options = { + :method => Comms.HTTP_REQUEST_METHOD_GET, + :headers => { + "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED}, + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON + }; -(:release) -function logMessage(output) { -} + Comms.makeWebRequest(url, params, options, callback); + } + + (:debug) + function logMessage(message) { + var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + Sys.println(dateStr + " : " + message); + } + + (:release) + function logMessage(output) { + } } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index cc702151..e6241955 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -184,6 +184,9 @@ if (doLog) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pend } // 3. Tesla: + // ************************************************************************************ + // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE + // ************************************************************************************ if (getProperty("Tesla") != null) { if (doLog) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel); } @@ -230,17 +233,17 @@ if (doLog) { logMessage("checkPendingWebRequests:Got http error '" + result + "' if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; - var expires_in = result["refresh_token"]; -// var created_at = teslaBatterieLevel["CreatedAt"]; + var expires_in = result["expires_in"]; + var created_at = Time.now().value(); setProperty("TeslaAccessToken", accessToken); - if (refreshToken != null && refreshToken.equals("") != false) { // Only if we received a refresh tokem + if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem setProperty("TeslaRefreshToken", refreshToken); } else { if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); -// setProperty("TeslaTokenCreatedAt", created_at); + setProperty("TeslaTokenCreatedAt", created_at); } // If the car isn't asleep, keep the current charge and clear the charging_state @@ -283,6 +286,10 @@ if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clear pendingWebRequests["TeslaBatterieLevel"] = true; } } + // ************************************************************************************ + // END OF REMOVED SECTION + // ************************************************************************************ + // If there are any pending requests: if (pendingWebRequests.keys().size() > 0) { diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 1c2c37ab..ff3753bc 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -80,12 +80,17 @@ function drawBatteryMeter(dc, x, y, width, height) { function writeBatteryLevel(dc, x, y, width, height, type) { var batteryLevel; var batteryStale = false; + var inText = false; var chargingState = 0; var textColour; if (type == 0) { batteryLevel = Math.floor(Sys.getSystemStats().battery); - } else { + } + // ************************************************************************************ + // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE + // ************************************************************************************ + else { batteryLevel = App.getApp().getProperty("TeslaBatterieLevelValue"); batteryStale = App.getApp().getProperty("TeslaBatterieStale"); chargingState = App.getApp().getProperty("TeslaChargingState"); @@ -100,13 +105,16 @@ function writeBatteryLevel(dc, x, y, width, height, type) { } } - var inText = false; if (batteryLevel == null || (batteryLevel instanceof Toybox.Lang.String && batteryLevel.equals("N/A"))) { textColour = Graphics.COLOR_LT_GRAY; inText = true; chargingState = false; batteryLevel = "???"; - } else { + } else + // ************************************************************************************ + // END OF REMOVED SECTION + // ************************************************************************************ + { batteryLevel = batteryLevel.toFloat(); if (batteryStale == true) { From 1c77cf82485307161e45a960682a3358419a166f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 27 Mar 2022 14:40:21 -0400 Subject: [PATCH 013/220] Fixed bug 210 --- source/CrystalView.mc | 3 ++- source/DataFields.mc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index ff3753bc..04c55d84 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -54,7 +54,8 @@ function drawBatteryMeter(dc, x, y, width, height) { // Fill. // #8: battery returned as float. Use floor() to match native. Must match getValueForFieldType(). - var batteryLevel = Math.floor(Sys.getSystemStats().battery); + // #210 Changed from floor to round + var batteryLevel = Math.round(Sys.getSystemStats().battery); // Fill colour based on battery level. var fillColour; diff --git a/source/DataFields.mc b/source/DataFields.mc index cb0d9c1c..a959ce0b 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -396,7 +396,8 @@ class DataFields extends Ui.Drawable { case FIELD_TYPE_BATTERY: // #8: battery returned as float. Use floor() to match native. Must match drawBatteryMeter(). - value = Math.floor(Sys.getSystemStats().battery); + // #210 Changed from floor to round + value = Math.round(Sys.getSystemStats().battery); value = value.format(INTEGER_FORMAT) + "%"; break; From 7d6cc11a404a8abb7459966e4baf301b011f883a Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 27 Mar 2022 14:59:49 -0400 Subject: [PATCH 014/220] More elegant and faster way of testing if the token is empty --- source/BackgroundService.mc | 4 ++-- source/CrystalApp.mc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 4664b9c3..dd396dd3 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -52,7 +52,7 @@ logMessage("initialize: Not requesting Tesla stuff, bailing out"); var timeNow = Time.now().value(); var interval = 5 * 60 * 60; var answer = (timeNow + interval < createdAt + expireIn); - if (_token != null && _token.equals("") == false && answer == true) { + if (_token != null && _token.length() != 0 && answer == true) { var expireAt = new Time.Moment(createdAt + expireIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); @@ -62,7 +62,7 @@ logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which exp else { logMessage("initialize:Generating Access Token " + (answer == false) ? "because we're about to expire" : "because access token is null or empty"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); - if (refreshToken != null && refreshToken.equals("") == false) { + if (refreshToken != null && refreshToken.length() != 0) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { logMessage("initialize:No refresh token!"); diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index e6241955..2dd076bb 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -236,7 +236,7 @@ if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } var expires_in = result["expires_in"]; var created_at = Time.now().value(); setProperty("TeslaAccessToken", accessToken); - if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem + if (refreshToken != null && refreshToken.length() != 0) { // Only if we received a refresh tokem setProperty("TeslaRefreshToken", refreshToken); } else { From 6524842a9ebf498bfe38c51eed32f636d0537bbb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 27 Mar 2022 17:08:19 -0400 Subject: [PATCH 015/220] Started getting -403 error so ended up removing some debugging code to free space --- source/BackgroundService.mc | 77 +++++++++++++++++++++++++++++-------- source/CrystalApp.mc | 18 +++++---- source/CrystalView.mc | 6 +-- 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index dd396dd3..78d53a65 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -25,7 +25,7 @@ logMessage("initialize: No phone connected"); } if (App.getApp().getProperty("Tesla") == null) { -logMessage("initialize: Not requesting Tesla stuff, bailing out"); +//logMessage("initialize: Not requesting Tesla stuff, bailing out"); return; } @@ -41,19 +41,21 @@ logMessage("initialize: Not requesting Tesla stuff, bailing out"); else { createdAt = createdAt.toNumber(); } - var expireIn = App.getApp().getProperty("TeslaTokenExpiresIn"); - if (expireIn == null) { - expireIn = 0; + var expiresIn = App.getApp().getProperty("TeslaTokenExpiresIn"); + if (expiresIn == null) { + expiresIn = 0; } else { - expireIn = expireIn.toNumber(); + expiresIn = expiresIn.toNumber(); } var timeNow = Time.now().value(); var interval = 5 * 60 * 60; - var answer = (timeNow + interval < createdAt + expireIn); + +//logMessage("createdAt:" + type_name(createdAt) + " " + createdAt + " expiresIn:" + type_name(expiresIn) + " " + expiresIn + " timeNow:" + type_name(timeNow) + " " + timeNow + " interval:" + type_name(interval) + " " + interval); + var answer = (timeNow + interval < createdAt + expiresIn); if (_token != null && _token.length() != 0 && answer == true) { - var expireAt = new Time.Moment(createdAt + expireIn); + var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); @@ -72,10 +74,10 @@ logMessage("initialize:No refresh token!"); _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); if (_vehicle_id == null) { -logMessage("initialize:Getting vehicle_id"); +//logMessage("initialize:Getting vehicle_id"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { -logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); +//logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } // ************************************************************************************ @@ -89,12 +91,12 @@ logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); +//logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. if (pendingWebRequests["CityLocalTime"] != null) { -logMessage("onTemporalEvent: doing city event"); +//logMessage("onTemporalEvent: doing city event"); makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { @@ -106,7 +108,7 @@ logMessage("onTemporalEvent: doing city event"); // 2. Weather. if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { -logMessage("onTemporalEvent: doing weather event"); +//logMessage("onTemporalEvent: doing weather event"); var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", @@ -142,12 +144,12 @@ logMessage("onTemporalEvent: doing weather event"); if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { logMessage("onTemporalEvent: doing Tesla event"); if (!Sys.getDeviceSettings().phoneConnected) { -logMessage("onTemporalEvent: No phone connected"); +//logMessage("onTemporalEvent: No phone connected"); // pendingWebRequests["TeslaBatterieLevel"] = null; return; } -logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); +//logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); if (_vehicle_id) { logMessage("onTemporalEvent:Calling makeTeslaWebRequest to get vehicle data"); @@ -317,9 +319,9 @@ logMessage("onReceiveVehicles responseCode is " + responseCode); var vehicles = data.get("response"); if (vehicles.size() > 0) { _vehicle_id = vehicles[0].get("id"); -logMessage("onReceiveVehicles:vehicle_id is " + _vehicle_id); +//logMessage("onReceiveVehicles:vehicle_id is " + _vehicle_id); } else { -logMessage("onReceiveVehicles:No vehicle in account"); +//logMessage("onReceiveVehicles:No vehicle in account"); _vehicle_id = 0; } result = { "vehicle_id" => _vehicle_id}; @@ -338,6 +340,7 @@ logMessage("onReceiveVehicles:No vehicle in account"); var chargingState = "Disconnected"; logMessage("onReceiveVehicleData responseCode is " + responseCode); +//logMessage("onReceiveVehicleData responseCode is " + responseCode + " with data '" + data + "'"); if (responseCode == 200) { result = data.get("response"); if (result != null) { @@ -424,4 +427,44 @@ logMessage("onReceiveVehicleData received " + result); (:release) function logMessage(output) { } -} + +/* function type_name(obj) { + if (obj instanceof Toybox.Lang.Number) { + return "Number"; + } else if (obj instanceof Toybox.Lang.Long) { + return "Long"; + } else if (obj instanceof Toybox.Lang.Float) { + return "Float"; + } else if (obj instanceof Toybox.Lang.Double) { + return "Double"; + } else if (obj instanceof Toybox.Lang.Boolean) { + return "Boolean"; + } else if (obj instanceof Toybox.Lang.String) { + return "String"; + } else if (obj instanceof Toybox.Lang.Array) { + var s = "Array ["; + for (var i = 0; i < obj.size(); ++i) { + s += type_name(obj); + s += ", "; + } + s += "]"; + return s; + } else if (obj instanceof Toybox.Lang.Dictionary) { + var s = "Dictionary{"; + var keys = obj.keys(); + var vals = obj.values(); + for (var i = 0; i < keys.size(); ++i) { + s += keys; + s += ": "; + s += vals; + s += ", "; + } + s += "}"; + return s; + } else if (obj instanceof Toybox.Time.Gregorian.Info) { + return "Gregorian.Info"; + } else { + return "???"; + } + }*/ +} \ No newline at end of file diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 2dd076bb..69dc084e 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -63,6 +63,8 @@ class CrystalApp extends App.AppBase { mView.onSettingsChanged(); // Calls checkPendingWebRequests(). + setProperty("TeslaTokenExpiresIn", "28800"); // It gets corrupted somehow so hard code it until we get one. + Ui.requestUpdate(); } @@ -192,7 +194,7 @@ if (doLog) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBat // No existing data. if (teslaBatterieLevel == null) { -if (doLog) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } +//if (doLog) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } pendingWebRequests["TeslaBatterieLevel"] = true; @@ -240,7 +242,7 @@ if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } setProperty("TeslaRefreshToken", refreshToken); } else { -if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } +//if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); setProperty("TeslaTokenCreatedAt", created_at); @@ -253,16 +255,16 @@ if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token ' var vehicle_id = teslaBatterieLevel["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { -if (doLog) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } +//if (doLog) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } setProperty("TeslaVehicleID", vehicle_id.toString()); } else { -if (doLog) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } +//if (doLog) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } setProperty("TeslaVehicleID", null); batterie_stale = true; batterie_level = "N/A"; } } else { -if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } +//if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } // setProperty("TeslaVehicleID", null); batterie_stale = true; } @@ -274,7 +276,7 @@ if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] setProperty("TeslaChargingState", charging_state); } else { -if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } +//if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } // setProperty("TeslaBatterieLevelValue", null); setProperty("TeslaBatterieStale", true); } @@ -323,9 +325,9 @@ if (doLog) { logMessage("checkPendingWebRequests:Scheduling now"); } function onBackgroundData(data) { logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = getProperty("PendingWebRequests"); -logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); +//logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { -logMessage("onBackgroundData: called with no pending web requests!"); +//logMessage("onBackgroundData: called with no pending web requests!"); pendingWebRequests = {}; } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 04c55d84..43f4d47c 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -222,7 +222,7 @@ class CrystalView extends Ui.WatchFace { // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { mSettingsChangedSinceLastDraw = true; -logMessage("onSettingsChanged called"); +//logMessage("onSettingsChanged called"); updateNormalFont(); @@ -548,7 +548,7 @@ logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); } } -function type_name(obj) { +/*function type_name(obj) { if (obj instanceof Toybox.Lang.Number) { return "Number"; } else if (obj instanceof Toybox.Lang.Long) { @@ -586,4 +586,4 @@ function type_name(obj) { } else { return "???"; } -} \ No newline at end of file +}*/ \ No newline at end of file From 47750515f52edfd0a54c6a773162ddba2ff1b6be Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 27 Mar 2022 18:47:44 -0400 Subject: [PATCH 016/220] Moved from vehicle_state to charge_state which receives 1.5KB of data instead of 5KB. Ran out of background process space and this data, converted to a dictionary was even taking more space and was too big for the space left in the background process. --- source/BackgroundService.mc | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 78d53a65..aed45830 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -78,7 +78,7 @@ logMessage("initialize:No refresh token!"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { //logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); - makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/data_request/charge_state", null, method(:onReceiveVehicleData)); } // ************************************************************************************ // END OF REMOVED SECTION @@ -344,30 +344,28 @@ logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { result = data.get("response"); if (result != null) { - result = result.get("charge_state"); - if (result != null) { - batterieLevel = result.get("battery_level"); - chargingState = result.get("charging_state"); + batterieLevel = result.get("battery_level"); + chargingState = result.get("charging_state"); //batterieLevel = Math.rand() % 100; - if (batterieLevel == null) { - batterieLevel = "N/A"; - } + if (batterieLevel == null) { + batterieLevel = "N/A"; + } - result = { - "battery_level" => batterieLevel, - "charging_state" => chargingState + result = { + "battery_level" => batterieLevel, + "charging_state" => chargingState // "charging_state" => "Charging" - }; - } - } + }; + result = { "battery_state" => result, "vehicle_id" => _vehicle_id }; + } else { + result = { "httpErrorTesla" => -400 }; + } logMessage("onReceiveVehicleData received " + result); - result = { "battery_state" => result, "vehicle_id" => _vehicle_id }; } else { result = { "httpErrorTesla" => responseCode }; } - Bg.exit({ "TeslaBatterieLevel" => result }); } From 8d1245586f0e868b6d0bd2a139c6a45e10ff230d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 28 Mar 2022 00:05:48 -0400 Subject: [PATCH 017/220] Revert "Moved from vehicle_state to charge_state which receives 1.5KB of data instead of 5KB." This reverts commit 47750515f52edfd0a54c6a773162ddba2ff1b6be. --- source/BackgroundService.mc | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index aed45830..78d53a65 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -78,7 +78,7 @@ logMessage("initialize:No refresh token!"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { //logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); - makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/data_request/charge_state", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } // ************************************************************************************ // END OF REMOVED SECTION @@ -344,28 +344,30 @@ logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { result = data.get("response"); if (result != null) { - batterieLevel = result.get("battery_level"); - chargingState = result.get("charging_state"); + result = result.get("charge_state"); + if (result != null) { + batterieLevel = result.get("battery_level"); + chargingState = result.get("charging_state"); //batterieLevel = Math.rand() % 100; - if (batterieLevel == null) { - batterieLevel = "N/A"; - } + if (batterieLevel == null) { + batterieLevel = "N/A"; + } - result = { - "battery_level" => batterieLevel, - "charging_state" => chargingState + result = { + "battery_level" => batterieLevel, + "charging_state" => chargingState // "charging_state" => "Charging" - }; - result = { "battery_state" => result, "vehicle_id" => _vehicle_id }; - } else { - result = { "httpErrorTesla" => -400 }; - } + }; + } + } logMessage("onReceiveVehicleData received " + result); + result = { "battery_state" => result, "vehicle_id" => _vehicle_id }; } else { result = { "httpErrorTesla" => responseCode }; } + Bg.exit({ "TeslaBatterieLevel" => result }); } From 63ee9805336b89d8976647ad0f857a4bd82a8672 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 28 Mar 2022 00:06:00 -0400 Subject: [PATCH 018/220] Revert "Started getting -403 error so ended up removing some debugging code to free space" This reverts commit 6524842a9ebf498bfe38c51eed32f636d0537bbb. --- source/BackgroundService.mc | 77 ++++++++----------------------------- source/CrystalApp.mc | 18 ++++----- source/CrystalView.mc | 6 +-- 3 files changed, 28 insertions(+), 73 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 78d53a65..dd396dd3 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -25,7 +25,7 @@ logMessage("initialize: No phone connected"); } if (App.getApp().getProperty("Tesla") == null) { -//logMessage("initialize: Not requesting Tesla stuff, bailing out"); +logMessage("initialize: Not requesting Tesla stuff, bailing out"); return; } @@ -41,21 +41,19 @@ logMessage("initialize: No phone connected"); else { createdAt = createdAt.toNumber(); } - var expiresIn = App.getApp().getProperty("TeslaTokenExpiresIn"); - if (expiresIn == null) { - expiresIn = 0; + var expireIn = App.getApp().getProperty("TeslaTokenExpiresIn"); + if (expireIn == null) { + expireIn = 0; } else { - expiresIn = expiresIn.toNumber(); + expireIn = expireIn.toNumber(); } var timeNow = Time.now().value(); var interval = 5 * 60 * 60; - -//logMessage("createdAt:" + type_name(createdAt) + " " + createdAt + " expiresIn:" + type_name(expiresIn) + " " + expiresIn + " timeNow:" + type_name(timeNow) + " " + timeNow + " interval:" + type_name(interval) + " " + interval); - var answer = (timeNow + interval < createdAt + expiresIn); + var answer = (timeNow + interval < createdAt + expireIn); if (_token != null && _token.length() != 0 && answer == true) { - var expireAt = new Time.Moment(createdAt + expiresIn); + var expireAt = new Time.Moment(createdAt + expireIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); @@ -74,10 +72,10 @@ logMessage("initialize:No refresh token!"); _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); if (_vehicle_id == null) { -//logMessage("initialize:Getting vehicle_id"); +logMessage("initialize:Getting vehicle_id"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { -//logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); +logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } // ************************************************************************************ @@ -91,12 +89,12 @@ logMessage("initialize:No refresh token!"); (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -//logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); +logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. if (pendingWebRequests["CityLocalTime"] != null) { -//logMessage("onTemporalEvent: doing city event"); +logMessage("onTemporalEvent: doing city event"); makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { @@ -108,7 +106,7 @@ logMessage("initialize:No refresh token!"); // 2. Weather. if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { -//logMessage("onTemporalEvent: doing weather event"); +logMessage("onTemporalEvent: doing weather event"); var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", @@ -144,12 +142,12 @@ logMessage("initialize:No refresh token!"); if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { logMessage("onTemporalEvent: doing Tesla event"); if (!Sys.getDeviceSettings().phoneConnected) { -//logMessage("onTemporalEvent: No phone connected"); +logMessage("onTemporalEvent: No phone connected"); // pendingWebRequests["TeslaBatterieLevel"] = null; return; } -//logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); +logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); if (_vehicle_id) { logMessage("onTemporalEvent:Calling makeTeslaWebRequest to get vehicle data"); @@ -319,9 +317,9 @@ logMessage("onReceiveVehicles responseCode is " + responseCode); var vehicles = data.get("response"); if (vehicles.size() > 0) { _vehicle_id = vehicles[0].get("id"); -//logMessage("onReceiveVehicles:vehicle_id is " + _vehicle_id); +logMessage("onReceiveVehicles:vehicle_id is " + _vehicle_id); } else { -//logMessage("onReceiveVehicles:No vehicle in account"); +logMessage("onReceiveVehicles:No vehicle in account"); _vehicle_id = 0; } result = { "vehicle_id" => _vehicle_id}; @@ -340,7 +338,6 @@ logMessage("onReceiveVehicles responseCode is " + responseCode); var chargingState = "Disconnected"; logMessage("onReceiveVehicleData responseCode is " + responseCode); -//logMessage("onReceiveVehicleData responseCode is " + responseCode + " with data '" + data + "'"); if (responseCode == 200) { result = data.get("response"); if (result != null) { @@ -427,44 +424,4 @@ logMessage("onReceiveVehicleData received " + result); (:release) function logMessage(output) { } - -/* function type_name(obj) { - if (obj instanceof Toybox.Lang.Number) { - return "Number"; - } else if (obj instanceof Toybox.Lang.Long) { - return "Long"; - } else if (obj instanceof Toybox.Lang.Float) { - return "Float"; - } else if (obj instanceof Toybox.Lang.Double) { - return "Double"; - } else if (obj instanceof Toybox.Lang.Boolean) { - return "Boolean"; - } else if (obj instanceof Toybox.Lang.String) { - return "String"; - } else if (obj instanceof Toybox.Lang.Array) { - var s = "Array ["; - for (var i = 0; i < obj.size(); ++i) { - s += type_name(obj); - s += ", "; - } - s += "]"; - return s; - } else if (obj instanceof Toybox.Lang.Dictionary) { - var s = "Dictionary{"; - var keys = obj.keys(); - var vals = obj.values(); - for (var i = 0; i < keys.size(); ++i) { - s += keys; - s += ": "; - s += vals; - s += ", "; - } - s += "}"; - return s; - } else if (obj instanceof Toybox.Time.Gregorian.Info) { - return "Gregorian.Info"; - } else { - return "???"; - } - }*/ -} \ No newline at end of file +} diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 69dc084e..2dd076bb 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -63,8 +63,6 @@ class CrystalApp extends App.AppBase { mView.onSettingsChanged(); // Calls checkPendingWebRequests(). - setProperty("TeslaTokenExpiresIn", "28800"); // It gets corrupted somehow so hard code it until we get one. - Ui.requestUpdate(); } @@ -194,7 +192,7 @@ if (doLog) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBat // No existing data. if (teslaBatterieLevel == null) { -//if (doLog) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } +if (doLog) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } pendingWebRequests["TeslaBatterieLevel"] = true; @@ -242,7 +240,7 @@ if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } setProperty("TeslaRefreshToken", refreshToken); } else { -//if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } +if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); setProperty("TeslaTokenCreatedAt", created_at); @@ -255,16 +253,16 @@ if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } var vehicle_id = teslaBatterieLevel["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { -//if (doLog) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } +if (doLog) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } setProperty("TeslaVehicleID", vehicle_id.toString()); } else { -//if (doLog) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } +if (doLog) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } setProperty("TeslaVehicleID", null); batterie_stale = true; batterie_level = "N/A"; } } else { -//if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } +if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } // setProperty("TeslaVehicleID", null); batterie_stale = true; } @@ -276,7 +274,7 @@ if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } setProperty("TeslaChargingState", charging_state); } else { -//if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } +if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } // setProperty("TeslaBatterieLevelValue", null); setProperty("TeslaBatterieStale", true); } @@ -325,9 +323,9 @@ if (doLog) { logMessage("checkPendingWebRequests:Scheduling now"); } function onBackgroundData(data) { logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = getProperty("PendingWebRequests"); -//logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); +logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { -//logMessage("onBackgroundData: called with no pending web requests!"); +logMessage("onBackgroundData: called with no pending web requests!"); pendingWebRequests = {}; } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 43f4d47c..04c55d84 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -222,7 +222,7 @@ class CrystalView extends Ui.WatchFace { // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { mSettingsChangedSinceLastDraw = true; -//logMessage("onSettingsChanged called"); +logMessage("onSettingsChanged called"); updateNormalFont(); @@ -548,7 +548,7 @@ logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); } } -/*function type_name(obj) { +function type_name(obj) { if (obj instanceof Toybox.Lang.Number) { return "Number"; } else if (obj instanceof Toybox.Lang.Long) { @@ -586,4 +586,4 @@ logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); } else { return "???"; } -}*/ \ No newline at end of file +} \ No newline at end of file From 73eb8d2b5f5895eb9b0c8617f8c89b06e80172d4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 28 Mar 2022 00:06:09 -0400 Subject: [PATCH 019/220] Revert "More elegant and faster way of testing if the token is empty" This reverts commit 7d6cc11a404a8abb7459966e4baf301b011f883a. --- source/BackgroundService.mc | 4 ++-- source/CrystalApp.mc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index dd396dd3..4664b9c3 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -52,7 +52,7 @@ logMessage("initialize: Not requesting Tesla stuff, bailing out"); var timeNow = Time.now().value(); var interval = 5 * 60 * 60; var answer = (timeNow + interval < createdAt + expireIn); - if (_token != null && _token.length() != 0 && answer == true) { + if (_token != null && _token.equals("") == false && answer == true) { var expireAt = new Time.Moment(createdAt + expireIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); @@ -62,7 +62,7 @@ logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which exp else { logMessage("initialize:Generating Access Token " + (answer == false) ? "because we're about to expire" : "because access token is null or empty"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); - if (refreshToken != null && refreshToken.length() != 0) { + if (refreshToken != null && refreshToken.equals("") == false) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { logMessage("initialize:No refresh token!"); diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 2dd076bb..e6241955 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -236,7 +236,7 @@ if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } var expires_in = result["expires_in"]; var created_at = Time.now().value(); setProperty("TeslaAccessToken", accessToken); - if (refreshToken != null && refreshToken.length() != 0) { // Only if we received a refresh tokem + if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem setProperty("TeslaRefreshToken", refreshToken); } else { From 9f09a2dff15991ebe2b9185c2747970275a7faa3 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 28 Mar 2022 00:06:21 -0400 Subject: [PATCH 020/220] Revert "Fixed bug 210" This reverts commit 1c77cf82485307161e45a960682a3358419a166f. --- source/CrystalView.mc | 3 +-- source/DataFields.mc | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 04c55d84..ff3753bc 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -54,8 +54,7 @@ function drawBatteryMeter(dc, x, y, width, height) { // Fill. // #8: battery returned as float. Use floor() to match native. Must match getValueForFieldType(). - // #210 Changed from floor to round - var batteryLevel = Math.round(Sys.getSystemStats().battery); + var batteryLevel = Math.floor(Sys.getSystemStats().battery); // Fill colour based on battery level. var fillColour; diff --git a/source/DataFields.mc b/source/DataFields.mc index a959ce0b..cb0d9c1c 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -396,8 +396,7 @@ class DataFields extends Ui.Drawable { case FIELD_TYPE_BATTERY: // #8: battery returned as float. Use floor() to match native. Must match drawBatteryMeter(). - // #210 Changed from floor to round - value = Math.round(Sys.getSystemStats().battery); + value = Math.floor(Sys.getSystemStats().battery); value = value.format(INTEGER_FORMAT) + "%"; break; From 638bb5fde448d692f455b647f82762d43c81c28b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 28 Mar 2022 00:06:26 -0400 Subject: [PATCH 021/220] Revert "Now preempt token expiry and ask for a new one if it's about to expire" This reverts commit ade7252f5f0880070e789df3f809a1fa451e66e2. --- monkey.jungle | 4 -- source/BackgroundService.mc | 97 +++++++++++-------------------------- source/CrystalApp.mc | 15 ++---- source/CrystalView.mc | 14 ++---- 4 files changed, 35 insertions(+), 95 deletions(-) diff --git a/monkey.jungle b/monkey.jungle index 10085136..a656f7cb 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -1,9 +1,5 @@ project.manifest = manifest.xml - - - - # Exclude other source directories (default behaviour is to include). base.sourcePath = source diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 4664b9c3..ea581111 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -15,9 +15,6 @@ class BackgroundService extends Sys.ServiceDelegate { function initialize() { Sys.ServiceDelegate.initialize(); - // ************************************************************************************ - // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE - // ************************************************************************************ // If we don't have a phone connected, don't go any further. if (!Sys.getDeviceSettings().phoneConnected) { logMessage("initialize: No phone connected"); @@ -30,39 +27,16 @@ logMessage("initialize: Not requesting Tesla stuff, bailing out"); } // Need to get a token since we can't OAUTH from a watch face :-( - // If someone can make it work, be my guest. I spent too much time on this already - // Check if the access_token is about to expire and if so, don't wait for the 401 error, renew it now! + // If someone can it, be my guest. I spent too much time on this already _token = App.getApp().getProperty("TeslaAccessToken"); - - var createdAt = App.getApp().getProperty("TeslaTokenCreatedAt"); - if (createdAt == null) { - createdAt = 0; - } - else { - createdAt = createdAt.toNumber(); - } - var expireIn = App.getApp().getProperty("TeslaTokenExpiresIn"); - if (expireIn == null) { - expireIn = 0; - } - else { - expireIn = expireIn.toNumber(); - } - - var timeNow = Time.now().value(); - var interval = 5 * 60 * 60; - var answer = (timeNow + interval < createdAt + expireIn); - if (_token != null && _token.equals("") == false && answer == true) { - var expireAt = new Time.Moment(createdAt + expireIn); - var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); -logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); + if (_token != null && _token.equals("") == false) { +logMessage("initialize:Using token '" + _token.substring(0,10) + "...'"); _token = "Bearer " + _token; } else { -logMessage("initialize:Generating Access Token " + (answer == false) ? "because we're about to expire" : "because access token is null or empty"); +logMessage("initialize:Generating Access Token"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); - if (refreshToken != null && refreshToken.equals("") == false) { + if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { logMessage("initialize:No refresh token!"); @@ -78,9 +52,6 @@ logMessage("initialize:Getting vehicle_id"); logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } - // ************************************************************************************ - // END OF REMOVED SECTION - // ************************************************************************************ } // Read pending web requests, and call appropriate web request function. @@ -102,9 +73,9 @@ logMessage("onTemporalEvent: doing city event"); }, method(:onReceiveCityLocalTime) ); - } // 2. Weather. + } if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { logMessage("onTemporalEvent: doing weather event"); var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); @@ -133,12 +104,9 @@ logMessage("onTemporalEvent: doing weather event"); }, method(:onReceiveOpenWeatherMapCurrent) ); - } // 3. Tesla - // ************************************************************************************ - // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE - // ************************************************************************************ + } if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { logMessage("onTemporalEvent: doing Tesla event"); if (!Sys.getDeviceSettings().phoneConnected) { @@ -157,9 +125,6 @@ logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data bec // pendingWebRequests["TeslaBatterieLevel"] = null; } } - // ************************************************************************************ - // END OF REMOVED SECTION - // ************************************************************************************ } /* else { Sys.println("onTemporalEvent() called with no pending web requests!"); } */ @@ -291,9 +256,6 @@ logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data bec }); } - // ************************************************************************************ - // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE - // ************************************************************************************ (:background_method) function onReceiveToken(responseCode, data) { var result; @@ -368,6 +330,18 @@ logMessage("onReceiveVehicleData received " + result); Bg.exit({ "TeslaBatterieLevel" => result }); } + (:background_method) + function makeWebRequest(url, params, callback) { + var options = { + :method => Comms.HTTP_REQUEST_METHOD_GET, + :headers => { + "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED}, + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON + }; + + Comms.makeWebRequest(url, params, options, callback); + } + (:background_method) function makeTeslaWebRequest(url, params, callback) { var options = { @@ -398,30 +372,15 @@ logMessage("onReceiveVehicleData received " + result); notify ); } - // ************************************************************************************ - // END OF REMOVED SECTION - // ************************************************************************************ - (:background_method) - function makeWebRequest(url, params, callback) { - var options = { - :method => Comms.HTTP_REQUEST_METHOD_GET, - :headers => { - "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED}, - :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON - }; - - Comms.makeWebRequest(url, params, options, callback); - } +(:debug) +function logMessage(message) { + var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + Sys.println(dateStr + " : " + message); +} - (:debug) - function logMessage(message) { - var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - Sys.println(dateStr + " : " + message); - } - - (:release) - function logMessage(output) { - } +(:release) +function logMessage(output) { +} } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index e6241955..cc702151 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -184,9 +184,6 @@ if (doLog) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pend } // 3. Tesla: - // ************************************************************************************ - // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE - // ************************************************************************************ if (getProperty("Tesla") != null) { if (doLog) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel); } @@ -233,17 +230,17 @@ if (doLog) { logMessage("checkPendingWebRequests:Got http error '" + result + "' if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; - var expires_in = result["expires_in"]; - var created_at = Time.now().value(); + var expires_in = result["refresh_token"]; +// var created_at = teslaBatterieLevel["CreatedAt"]; setProperty("TeslaAccessToken", accessToken); - if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem + if (refreshToken != null && refreshToken.equals("") != false) { // Only if we received a refresh tokem setProperty("TeslaRefreshToken", refreshToken); } else { if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); - setProperty("TeslaTokenCreatedAt", created_at); +// setProperty("TeslaTokenCreatedAt", created_at); } // If the car isn't asleep, keep the current charge and clear the charging_state @@ -286,10 +283,6 @@ if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clear pendingWebRequests["TeslaBatterieLevel"] = true; } } - // ************************************************************************************ - // END OF REMOVED SECTION - // ************************************************************************************ - // If there are any pending requests: if (pendingWebRequests.keys().size() > 0) { diff --git a/source/CrystalView.mc b/source/CrystalView.mc index ff3753bc..1c2c37ab 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -80,17 +80,12 @@ function drawBatteryMeter(dc, x, y, width, height) { function writeBatteryLevel(dc, x, y, width, height, type) { var batteryLevel; var batteryStale = false; - var inText = false; var chargingState = 0; var textColour; if (type == 0) { batteryLevel = Math.floor(Sys.getSystemStats().battery); - } - // ************************************************************************************ - // REMOVE THIS IF YOU WANT TO EXCLUDE TESLA CODE - // ************************************************************************************ - else { + } else { batteryLevel = App.getApp().getProperty("TeslaBatterieLevelValue"); batteryStale = App.getApp().getProperty("TeslaBatterieStale"); chargingState = App.getApp().getProperty("TeslaChargingState"); @@ -105,16 +100,13 @@ function writeBatteryLevel(dc, x, y, width, height, type) { } } + var inText = false; if (batteryLevel == null || (batteryLevel instanceof Toybox.Lang.String && batteryLevel.equals("N/A"))) { textColour = Graphics.COLOR_LT_GRAY; inText = true; chargingState = false; batteryLevel = "???"; - } else - // ************************************************************************************ - // END OF REMOVED SECTION - // ************************************************************************************ - { + } else { batteryLevel = batteryLevel.toFloat(); if (batteryStale == true) { From 4367c7676c7b9dc547e196ad1fefbe254746e7c4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 28 Mar 2022 11:49:16 -0400 Subject: [PATCH 022/220] Removed most of the stuff I did yesterday because I hit a memory limitation (I think). Stable now. Log verbosity decreased. Can almost keep an hour worth of output on the watch .TXT files themselves --- source/BackgroundService.mc | 30 +++++++++++------------ source/CrystalApp.mc | 48 ++++++++++++++++++++----------------- source/CrystalView.mc | 9 ++++--- 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index ea581111..71a894c3 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -16,13 +16,13 @@ class BackgroundService extends Sys.ServiceDelegate { Sys.ServiceDelegate.initialize(); // If we don't have a phone connected, don't go any further. - if (!Sys.getDeviceSettings().phoneConnected) { -logMessage("initialize: No phone connected"); - return; - } +// if (!Sys.getDeviceSettings().phoneConnected) { +//logMessage("initialize: No phone connected"); +// return; +// } if (App.getApp().getProperty("Tesla") == null) { -logMessage("initialize: Not requesting Tesla stuff, bailing out"); +//logMessage("initialize: Not requesting Tesla stuff, bailing out"); return; } @@ -49,7 +49,7 @@ logMessage("initialize:No refresh token!"); logMessage("initialize:Getting vehicle_id"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { -logMessage("Reusing vehicle_id and calling for vehicle data" + _vehicle_id); +logMessage("initialize:Asking vehicle data for " + _vehicle_id); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } } @@ -65,7 +65,7 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") // 1. City local time. if (pendingWebRequests["CityLocalTime"] != null) { -logMessage("onTemporalEvent: doing city event"); +//logMessage("onTemporalEvent: doing city event"); makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { @@ -77,7 +77,7 @@ logMessage("onTemporalEvent: doing city event"); // 2. Weather. } if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { -logMessage("onTemporalEvent: doing weather event"); +//logMessage("onTemporalEvent: doing weather event"); var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", @@ -108,20 +108,20 @@ logMessage("onTemporalEvent: doing weather event"); // 3. Tesla } if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { -logMessage("onTemporalEvent: doing Tesla event"); +logMessage("onTemporalEvent: WebRequest for vehicle id " + _vehicle_id); if (!Sys.getDeviceSettings().phoneConnected) { logMessage("onTemporalEvent: No phone connected"); // pendingWebRequests["TeslaBatterieLevel"] = null; return; } -logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); +//logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); if (_vehicle_id) { -logMessage("onTemporalEvent:Calling makeTeslaWebRequest to get vehicle data"); +//logMessage("onTemporalEvent:Calling makeTeslaWebRequest to get vehicle data"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } else { -logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data because of null vehicle_id"); +//logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data because of null vehicle_id"); // pendingWebRequests["TeslaBatterieLevel"] = null; } } @@ -261,7 +261,7 @@ logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data bec var result; logMessage("onReceiveToken responseCode is " + responseCode); -logMessage("onReceiveToken data is " + data); +//logMessage("onReceiveToken data is " + data); if (responseCode == 200) { result = { "Token" => data }; } else { @@ -274,14 +274,12 @@ logMessage("onReceiveToken data is " + data); function onReceiveVehicles(responseCode, data) { var result; -logMessage("onReceiveVehicles responseCode is " + responseCode); +logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { _vehicle_id = vehicles[0].get("id"); -logMessage("onReceiveVehicles:vehicle_id is " + _vehicle_id); } else { -logMessage("onReceiveVehicles:No vehicle in account"); _vehicle_id = 0; } result = { "vehicle_id" => _vehicle_id}; diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index cc702151..9208ed17 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -18,8 +18,8 @@ class CrystalApp extends App.AppBase { var mView; var mFieldTypes = new [3]; - var lastBackgroundSchedule = 0; - + var temporalRan = false; + function initialize() { AppBase.initialize(); } @@ -83,15 +83,11 @@ class CrystalApp extends App.AppBase { // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. var lastTime = Bg.getLastTemporalEventTime(); - var doLog = false; var teslaBatterieLevel = getProperty("TeslaBatterieLevel"); + var gotData = temporalRan; + temporalRan = false; //logMessage("checkPendingWebRequests:lastBackgroundSchedule is " + lastBackgroundSchedule + " lastTime is " + (lastTime == null ? "null" : lastTime.value())); - if (lastTime == null || lastBackgroundSchedule != lastTime.value()) { - lastBackgroundSchedule = lastTime.value(); - doLog = true; - } - var location = Activity.getActivityInfo().currentLocation; if (location) { logMessage("Saving location"); @@ -122,7 +118,7 @@ class CrystalApp extends App.AppBase { } var pendingWebRequests = getProperty("PendingWebRequests"); -if (doLog) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); } +if (gotData) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); } if (pendingWebRequests == null) { pendingWebRequests = {}; } @@ -185,11 +181,11 @@ if (doLog) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pend // 3. Tesla: if (getProperty("Tesla") != null) { -if (doLog) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel); } +if (gotData) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel.toString().substring(0,60) + " ..."); } // No existing data. if (teslaBatterieLevel == null) { -if (doLog) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } +//if (gotData) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } pendingWebRequests["TeslaBatterieLevel"] = true; @@ -211,33 +207,39 @@ if (doLog) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking // Other errors are silent for now var result = teslaBatterieLevel["httpErrorTesla"]; if (result != null) { -if (doLog) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); } +if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); } if (result == 400 || result == 401) { // Our token has expired, refresh it setProperty("TeslaAccessToken", null); // Try to get a new vehicleID batterie_stale = true; + batterie_level = result; } else if (result == 404) { // We got an vehicle not found error, reset our vehicle ID setProperty("TeslaVehicleID", null); // Try to get a new vehicleID batterie_stale = true; + batterie_level = result; } else if (result == 408) { // Car is aslepep keep the old data but stop charging if it still was before going to sleep carAsleep = true; } + else { + batterie_stale = true; + batterie_level = result; + } } // Check if our access token was refreshed. If so, store the new access and refresh tokens result = teslaBatterieLevel["Token"]; if (result != null) { //logMessage("checkPendingWebRequests:Got token data '" + result + "'"); -if (doLog) { logMessage("checkPendingWebRequests:Got token data"); } +if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; var expires_in = result["refresh_token"]; // var created_at = teslaBatterieLevel["CreatedAt"]; setProperty("TeslaAccessToken", accessToken); - if (refreshToken != null && refreshToken.equals("") != false) { // Only if we received a refresh tokem + if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem setProperty("TeslaRefreshToken", refreshToken); } else { -if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } +if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); // setProperty("TeslaTokenCreatedAt", created_at); @@ -250,16 +252,16 @@ if (doLog) { logMessage("checkPendingWebRequests:But missing the refresh token ' var vehicle_id = teslaBatterieLevel["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { -if (doLog) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } +//if (gotData) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } setProperty("TeslaVehicleID", vehicle_id.toString()); } else { -if (doLog) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } +//if (gotData) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } setProperty("TeslaVehicleID", null); batterie_stale = true; batterie_level = "N/A"; } } else { -if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } +//if (gotData) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } // setProperty("TeslaVehicleID", null); batterie_stale = true; } @@ -271,7 +273,7 @@ if (doLog) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] setProperty("TeslaChargingState", charging_state); } else { -if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } +//if (gotData) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } // setProperty("TeslaBatterieLevelValue", null); setProperty("TeslaBatterieStale", true); } @@ -292,10 +294,10 @@ if (doLog) { logMessage("checkPendingWebRequests:batterie_level is null"/* clear // Events scheduled for a time in the past trigger immediately. var nextTime = lastTime.add(new Time.Duration(5 * 60)); var clockTime = Gregorian.info(nextTime, Time.FORMAT_MEDIUM); -if (doLog) { logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); } +if (gotData) { logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); } Bg.registerForTemporalEvent(nextTime); } else { -if (doLog) { logMessage("checkPendingWebRequests:Scheduling now"); } +if (gotData) { logMessage("checkPendingWebRequests:Scheduling now"); } Bg.registerForTemporalEvent(Time.now()); } } @@ -318,7 +320,7 @@ logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = getProperty("PendingWebRequests"); logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { -logMessage("onBackgroundData: called with no pending web requests!"); +//logMessage("onBackgroundData: called with no pending web requests!"); pendingWebRequests = {}; } @@ -338,6 +340,8 @@ logMessage("onBackgroundData: called with no pending web requests!"); setProperty("PendingWebRequests", pendingWebRequests); setProperty(type, storedData); + temporalRan = true; + checkPendingWebRequests(); // We just got new data, process them right away before displaying Ui.requestUpdate(); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 1c2c37ab..21c31a41 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -109,7 +109,10 @@ function writeBatteryLevel(dc, x, y, width, height, type) { } else { batteryLevel = batteryLevel.toFloat(); - if (batteryStale == true) { + if (batteryLevel < 0 || batteryLevel > 100) { + textColour = Graphics.COLOR_PINK; + chargingState = -1; + } else if (batteryStale == true) { textColour = Graphics.COLOR_LT_GRAY; } else if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { textColour = Graphics.COLOR_RED; @@ -124,7 +127,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (inText) { dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel, Graphics.TEXT_JUSTIFY_LEFT); } else { - dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")), Graphics.TEXT_JUSTIFY_LEFT); + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + (chargingState != -1 ? "%" : "") + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")), Graphics.TEXT_JUSTIFY_LEFT); } } @@ -224,7 +227,7 @@ logMessage("onSettingsChanged called"); updateHoursMinutesColours(); if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. -logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); +//logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } } From b86e96af1cce75e1da9e479aa960030042af8e38 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:15:16 -0400 Subject: [PATCH 023/220] Debug code to show when the access token expires --- source/BackgroundService.mc | 18 ++++++++++++++++-- source/CrystalApp.mc | 6 +++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 71a894c3..8a457a03 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -27,10 +27,24 @@ class BackgroundService extends Sys.ServiceDelegate { } // Need to get a token since we can't OAUTH from a watch face :-( - // If someone can it, be my guest. I spent too much time on this already + // If someone can do it, be my guest. I spent too much time on this already _token = App.getApp().getProperty("TeslaAccessToken"); + + var createdAt = App.getApp().getProperty("TeslaTokenCreatedAt"); + if (createdAt == null) { + createdAt = 0; + } + + var expiresIn = App.getApp().getProperty("TeslaTokenExpiresIn"); + if (expiresIn == null) { + expiresIn = 0; + } + if (_token != null && _token.equals("") == false) { -logMessage("initialize:Using token '" + _token.substring(0,10) + "...'"); + var expireAt = new Time.Moment(createdAt + expiresIn); + var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); +logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 9208ed17..0b703240 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -232,8 +232,8 @@ if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; - var expires_in = result["refresh_token"]; -// var created_at = teslaBatterieLevel["CreatedAt"]; + var expires_in = result["expires_in"]; + var created_at = Time.now().value(); setProperty("TeslaAccessToken", accessToken); if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem setProperty("TeslaRefreshToken", refreshToken); @@ -242,7 +242,7 @@ if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); -// setProperty("TeslaTokenCreatedAt", created_at); + setProperty("TeslaTokenCreatedAt", created_at); } // If the car isn't asleep, keep the current charge and clear the charging_state From 445be47ae419301acd4046ae810a48d8e5fd78a5 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 29 Mar 2022 22:08:47 -0400 Subject: [PATCH 024/220] Reinstate the preemptive refresh close to the expiration time. If we launch while the car is asleep, use its last known battery charge --- source/BackgroundService.mc | 6 +++++- source/CrystalApp.mc | 26 +++++++++++++++----------- source/CrystalView.mc | 14 +++++++++++--- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 8a457a03..2d9ff49d 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -40,7 +40,11 @@ class BackgroundService extends Sys.ServiceDelegate { expiresIn = 0; } - if (_token != null && _token.equals("") == false) { + var timeNow = Time.now().value(); + var interval = 5 * 60; + var answer = (timeNow + interval < createdAt + expiresIn); + + if (_token != null && _token.equals("") == false && answer == true) { var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 0b703240..c629a038 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -191,17 +191,11 @@ if (gotData) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaB // We got something, check what it is } else { - var batterie_state = teslaBatterieLevel["battery_state"]; var batterie_level = null; var charging_state = null; var batterie_stale = false; var carAsleep = false; - if (batterie_state) { - batterie_level = batterie_state["battery_level"]; - charging_state = batterie_state["charging_state"]; - } - // First handle errors, setting batterie_level to "N/A" if the query returned a vehicle not found. // If we failed to get access, maybe our token has expired, clear it so next time the background process runs, it will refresh it // Other errors are silent for now @@ -211,18 +205,16 @@ if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + if (result == 400 || result == 401) { // Our token has expired, refresh it setProperty("TeslaAccessToken", null); // Try to get a new vehicleID batterie_stale = true; - batterie_level = result; } else if (result == 404) { // We got an vehicle not found error, reset our vehicle ID setProperty("TeslaVehicleID", null); // Try to get a new vehicleID batterie_stale = true; - batterie_level = result; } else if (result == 408) { // Car is aslepep keep the old data but stop charging if it still was before going to sleep carAsleep = true; } else { batterie_stale = true; - batterie_level = result; } + setProperty("TeslaError", result); } // Check if our access token was refreshed. If so, store the new access and refresh tokens @@ -243,12 +235,20 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token } setProperty("TeslaTokenExpiresIn", expires_in); setProperty("TeslaTokenCreatedAt", created_at); + + setProperty("TeslaError", null); } // If the car isn't asleep, keep the current charge and clear the charging_state if (!carAsleep) { - // Rad its vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. - // If we have no vehicle, set the batterie level to N/A + var batterie_state = teslaBatterieLevel["battery_state"]; + if (batterie_state) { + batterie_level = batterie_state["battery_level"]; + charging_state = batterie_state["charging_state"]; + } + + // Read its vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. + // If we have no vehicle, set the batterie level to N/A var vehicle_id = teslaBatterieLevel["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { @@ -271,15 +271,19 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token setProperty("TeslaBatterieLevelValue", batterie_level); setProperty("TeslaBatterieStale", batterie_stale); setProperty("TeslaChargingState", charging_state); + + setProperty("TeslaError", null); } else { //if (gotData) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } // setProperty("TeslaBatterieLevelValue", null); setProperty("TeslaBatterieStale", true); + setProperty("TeslaError", null); } } else { setProperty("TeslaChargingState", "Sleeping"); setProperty("TeslaBatterieStale", false); + setProperty("TeslaError", null); } pendingWebRequests["TeslaBatterieLevel"] = true; diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 21c31a41..5287b653 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -81,6 +81,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var batteryLevel; var batteryStale = false; var chargingState = 0; + var error = null; var textColour; if (type == 0) { @@ -89,11 +90,14 @@ function writeBatteryLevel(dc, x, y, width, height, type) { batteryLevel = App.getApp().getProperty("TeslaBatterieLevelValue"); batteryStale = App.getApp().getProperty("TeslaBatterieStale"); chargingState = App.getApp().getProperty("TeslaChargingState"); + error = App.getApp().getProperty("TeslaError"); if (chargingState != null) { if (chargingState.equals("Charging")) { chargingState = 1; } else if (chargingState.equals("Sleeping")) { chargingState = 2; + } else { + chargingState = 0; } } else { chargingState = 0; @@ -107,11 +111,15 @@ function writeBatteryLevel(dc, x, y, width, height, type) { chargingState = false; batteryLevel = "???"; } else { - batteryLevel = batteryLevel.toFloat(); + if (error != null) { + batteryLevel = error.toFloat(); + } else { + batteryLevel = batteryLevel.toFloat(); + } if (batteryLevel < 0 || batteryLevel > 100) { textColour = Graphics.COLOR_PINK; - chargingState = -1; + chargingState += 4; } else if (batteryStale == true) { textColour = Graphics.COLOR_LT_GRAY; } else if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { @@ -127,7 +135,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (inText) { dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel, Graphics.TEXT_JUSTIFY_LEFT); } else { - dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + (chargingState != -1 ? "%" : "") + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")), Graphics.TEXT_JUSTIFY_LEFT); + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + ((chargingState & 4) != 4 ? "%" : "") + ((chargingState & 3) == 1 ? "+" : ((chargingState & 3) == 2 ? "s" : "")), Graphics.TEXT_JUSTIFY_LEFT); } } From cb2a8a03166c62773d01f42ca0ab1b5c2a84d03c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:06:38 -0400 Subject: [PATCH 025/220] Removed some debugging line and receiving a token no longer stales the data --- source/CrystalApp.mc | 4 ++-- source/Indicators.mc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index c629a038..097ac096 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -90,7 +90,7 @@ class CrystalApp extends App.AppBase { //logMessage("checkPendingWebRequests:lastBackgroundSchedule is " + lastBackgroundSchedule + " lastTime is " + (lastTime == null ? "null" : lastTime.value())); var location = Activity.getActivityInfo().currentLocation; if (location) { - logMessage("Saving location"); + //logMessage("Saving location"); location = location.toDegrees(); // Array of Doubles. gLocationLat = location[0].toFloat(); gLocationLng = location[1].toFloat(); @@ -240,7 +240,7 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token } // If the car isn't asleep, keep the current charge and clear the charging_state - if (!carAsleep) { + else if (!carAsleep) { var batterie_state = teslaBatterieLevel["battery_state"]; if (batterie_state) { batterie_level = batterie_state["battery_level"]; diff --git a/source/Indicators.mc b/source/Indicators.mc index 238f4e9f..9f1c5f8e 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -42,7 +42,7 @@ class Indicators extends Ui.Drawable { if (mIndicator1Type == 6 || mIndicator2Type == 6 || mIndicator3Type == 6) { App.getApp().setProperty("Tesla", true); -logMessage("onSettingsChanged:Doing Tesla!"); +//logMessage("onSettingsChanged:Doing Tesla!"); } else { App.getApp().setProperty("Tesla", false); } From fea7f4ae0cc1d139ea09a057084556346045c805 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 3 Apr 2022 10:59:41 -0400 Subject: [PATCH 026/220] Now toggles between battery charge, sentry mode, preconditioning and inside temperature --- resources-round-208x208/fonts/fonts.xml | 2 +- resources-round-280x280/fonts/fonts.xml | 2 +- resources-round-360x360/fonts/fonts.xml | 2 +- resources-round-390x390/fonts/fonts.xml | 2 +- resources-round-416x416/fonts/fonts.xml | 2 +- resources/fonts/fonts.xml | 2 +- source/BackgroundService.mc | 49 +++++---- source/CrystalApp.mc | 15 +++ source/CrystalView.mc | 134 +++++++++++++++++------- 9 files changed, 147 insertions(+), 63 deletions(-) diff --git a/resources-round-208x208/fonts/fonts.xml b/resources-round-208x208/fonts/fonts.xml index dc7035f9..6c1cc189 100644 --- a/resources-round-208x208/fonts/fonts.xml +++ b/resources-round-208x208/fonts/fonts.xml @@ -4,7 +4,7 @@ - + diff --git a/resources-round-280x280/fonts/fonts.xml b/resources-round-280x280/fonts/fonts.xml index e286cbf3..d200adc1 100644 --- a/resources-round-280x280/fonts/fonts.xml +++ b/resources-round-280x280/fonts/fonts.xml @@ -3,7 +3,7 @@ - + diff --git a/resources-round-360x360/fonts/fonts.xml b/resources-round-360x360/fonts/fonts.xml index 08607dd0..f5b853b0 100644 --- a/resources-round-360x360/fonts/fonts.xml +++ b/resources-round-360x360/fonts/fonts.xml @@ -5,7 +5,7 @@ - + diff --git a/resources-round-390x390/fonts/fonts.xml b/resources-round-390x390/fonts/fonts.xml index 72db0c26..b7237873 100644 --- a/resources-round-390x390/fonts/fonts.xml +++ b/resources-round-390x390/fonts/fonts.xml @@ -5,7 +5,7 @@ - + diff --git a/resources-round-416x416/fonts/fonts.xml b/resources-round-416x416/fonts/fonts.xml index e8594698..ea9ed613 100644 --- a/resources-round-416x416/fonts/fonts.xml +++ b/resources-round-416x416/fonts/fonts.xml @@ -5,7 +5,7 @@ - + diff --git a/resources/fonts/fonts.xml b/resources/fonts/fonts.xml index 77fec8f2..54d83184 100644 --- a/resources/fonts/fonts.xml +++ b/resources/fonts/fonts.xml @@ -3,7 +3,7 @@ - + diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 2d9ff49d..b19c13d2 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -311,38 +311,47 @@ logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + (:background_method) function onReceiveVehicleData(responseCode, data) { - var result; + var results; + var result = "N/A"; var batterieLevel = "N/A"; var chargingState = "Disconnected"; + var insideTemp = "N/A"; + var precondEnabled = "N/A"; + var sentryEnabled = "N/A"; logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { - result = data.get("response"); - if (result != null) { - result = result.get("charge_state"); + results = data.get("response"); + if (results != null) { + result = results.get("charge_state"); if (result != null) { batterieLevel = result.get("battery_level"); chargingState = result.get("charging_state"); - -//batterieLevel = Math.rand() % 100; - if (batterieLevel == null) { - batterieLevel = "N/A"; - } - - result = { - "battery_level" => batterieLevel, - "charging_state" => chargingState -// "charging_state" => "Charging" - }; + precondEnabled = result.get("preconditioning_enabled"); } + result = results.get("climate_state"); + if (result != null) { + insideTemp = result.get("inside_temp"); + } + + result = results.get("vehicle_state"); + if (result != null) { + sentryEnabled = result.get("sentry_mode"); + } + + result = { + "battery_level" => batterieLevel, + "charging_state" => chargingState + }; } -logMessage("onReceiveVehicleData received " + result); - result = { "battery_state" => result, "vehicle_id" => _vehicle_id }; + + result = { "battery_state" => result, "inside_temp" => insideTemp, "preconditioning" => precondEnabled, "sentry_enabled" => sentryEnabled, "vehicle_id" => _vehicle_id }; } else { result = { "httpErrorTesla" => responseCode }; } - - + +logMessage("onReceiveVehicleData received " + result); + Bg.exit({ "TeslaBatterieLevel" => result }); } @@ -354,7 +363,6 @@ logMessage("onReceiveVehicleData received " + result); "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED}, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; - Comms.makeWebRequest(url, params, options, callback); } @@ -367,6 +375,7 @@ logMessage("onReceiveVehicleData received " + result); :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; //logMessage("makeTeslaWebRequest with url='" + url + "' params='" + params + "' options='" + options + "'"); +//logMessage("url=" + url + "\nparams=" + params + "\noptions=" + options); Comms.makeWebRequest(url, params, options, callback); } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 097ac096..cceb8d3a 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -246,7 +246,22 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token batterie_level = batterie_state["battery_level"]; charging_state = batterie_state["charging_state"]; } + + var inside_temp = teslaBatterieLevel["inside_temp"]; + if (inside_temp != null) { + setProperty("TeslaInsideTemp", inside_temp.toString()); + } + var precond_enabled = teslaBatterieLevel["preconditioning"]; + if (precond_enabled != null) { + setProperty("TeslaPreconditioning", precond_enabled.toString()); + } + + var sentry_enabled = teslaBatterieLevel["sentry_enabled"]; + if (sentry_enabled != null) { + setProperty("TeslaSentryEnabled", sentry_enabled.toString()); + } + // Read its vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. // If we have no vehicle, set the batterie level to N/A var vehicle_id = teslaBatterieLevel["vehicle_id"]; diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 5287b653..9fce8cb9 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -77,65 +77,126 @@ function drawBatteryMeter(dc, x, y, width, height) { height - (2 * lineWidthPlusMargin)); } +var gToggleCounter = 0; // Used to switch between charge and inside temp + function writeBatteryLevel(dc, x, y, width, height, type) { var batteryLevel; - var batteryStale = false; - var chargingState = 0; - var error = null; var textColour; - if (type == 0) { + if (type == 0) { // Standard watch battery is being shown batteryLevel = Math.floor(Sys.getSystemStats().battery); - } else { - batteryLevel = App.getApp().getProperty("TeslaBatterieLevelValue"); + + if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { + textColour = Graphics.COLOR_RED; + } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { + textColour = Graphics.COLOR_YELLOW; + } else { + textColour = gThemeColour; + } + + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); + } + else { // Tesla stuff + var value; + var batteryStale = false; + var chargingState = 0; + var error = null; + var showMode; + + gToggleCounter = (gToggleCounter + 1) & 15; // Increase by one, reset to 0 once 8 is reached + showMode = gToggleCounter / 4; // 0-3 is battery, 4-7 Sentry, 8-11 preconditionning, 12-15 is inside temp changed to 0 to 3 +//logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); batteryStale = App.getApp().getProperty("TeslaBatterieStale"); chargingState = App.getApp().getProperty("TeslaChargingState"); error = App.getApp().getProperty("TeslaError"); + if (chargingState != null) { if (chargingState.equals("Charging")) { chargingState = 1; } else if (chargingState.equals("Sleeping")) { chargingState = 2; + showMode /= 8; // Keep only 0 and 1. } else { chargingState = 0; } } else { chargingState = 0; } - } - var inText = false; - if (batteryLevel == null || (batteryLevel instanceof Toybox.Lang.String && batteryLevel.equals("N/A"))) { - textColour = Graphics.COLOR_LT_GRAY; - inText = true; - chargingState = false; - batteryLevel = "???"; - } else { - if (error != null) { - batteryLevel = error.toFloat(); - } else { - batteryLevel = batteryLevel.toFloat(); + var inText = null; + switch (showMode) { + case 0: + value = App.getApp().getProperty("TeslaBatterieLevelValue"); + break; + case 1: + value = App.getApp().getProperty("TeslaPreconditioning"); + if (value != null && value.equals("true")) { + inText = "P on"; + } + else if (value != null && value.equals("false")) { + inText = "P off"; + } + else { + inText = "P ?"; + } + break; + case 2: + value = App.getApp().getProperty("TeslaSentryEnabled"); + if (value != null && value.equals("true")) { + inText = "S on"; + } + else if (value != null && value.equals("false")) { + inText = "S off"; + } + else { + inText = "S ?"; + } + break; + case 3: + value = App.getApp().getProperty("TeslaInsideTemp"); + break; } - - if (batteryLevel < 0 || batteryLevel > 100) { - textColour = Graphics.COLOR_PINK; - chargingState += 4; - } else if (batteryStale == true) { - textColour = Graphics.COLOR_LT_GRAY; - } else if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { - textColour = Graphics.COLOR_RED; - } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { - textColour = Graphics.COLOR_YELLOW; + + if (inText != null) { + dc.setColor(gThemeColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, inText, Graphics.TEXT_JUSTIFY_LEFT); + } else if (value == null || (value instanceof Toybox.Lang.String && value.equals("N/A"))) { + dc.setColor(Graphics.COLOR_LT_GRAY, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, "???", Graphics.TEXT_JUSTIFY_LEFT); } else { - textColour = gThemeColour; - } - } + var suffixe = ""; - dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); - if (inText) { - dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel, Graphics.TEXT_JUSTIFY_LEFT); - } else { - dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + ((chargingState & 4) != 4 ? "%" : "") + ((chargingState & 3) == 1 ? "+" : ((chargingState & 3) == 2 ? "s" : "")), Graphics.TEXT_JUSTIFY_LEFT); + if (error != null) { + textColour = Graphics.COLOR_PINK; + value = error.toFloat(); + } else { + value = value.toFloat(); + + if (batteryStale == true) { + textColour = Graphics.COLOR_LT_GRAY; + } else if (value <= /* BATTERY_LEVEL_CRITICAL */ 10 && showMode == 0) { + textColour = Graphics.COLOR_RED; + } else if (value <= /* BATTERY_LEVEL_LOW */ 20 && showMode == 0) { + textColour = Graphics.COLOR_YELLOW; + } else { + textColour = gThemeColour; + } + + if (showMode == 0) { + suffixe = "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); + } else { + suffixe = "°C"; + if (Sys.getDeviceSettings().temperatureUnits == Sys. UNIT_STATUTE) { + suffixe = "°F"; + value = value * 9.0 / 5.0 + 32; + } + } + } + + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, value.toNumber().format(INTEGER_FORMAT) + suffixe, Graphics.TEXT_JUSTIFY_LEFT); + } } } @@ -144,7 +205,6 @@ class CrystalView extends Ui.WatchFace { private var mIsBurnInProtection = false; // Is burn-in protection required and active? private var mBurnInProtectionChangedSinceLastDraw = false; // Did burn-in protection change since last full update? private var mSettingsChangedSinceLastDraw = true; // Have settings changed since last full update? - private var mTime; var mDataFields; From ae3d6cfda989cd848e003e5b3f7f367ec17f6791 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 3 Apr 2022 13:05:11 -0400 Subject: [PATCH 027/220] Adjustment to the display times of the Tesla stuff --- source/CrystalView.mc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 9fce8cb9..1ce3b256 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -104,8 +104,8 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var error = null; var showMode; - gToggleCounter = (gToggleCounter + 1) & 15; // Increase by one, reset to 0 once 8 is reached - showMode = gToggleCounter / 4; // 0-3 is battery, 4-7 Sentry, 8-11 preconditionning, 12-15 is inside temp changed to 0 to 3 + gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached + showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 //logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); batteryStale = App.getApp().getProperty("TeslaBatterieStale"); chargingState = App.getApp().getProperty("TeslaChargingState"); @@ -116,7 +116,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { chargingState = 1; } else if (chargingState.equals("Sleeping")) { chargingState = 2; - showMode /= 8; // Keep only 0 and 1. + showMode /= 2; // Keep only 0 and 1. } else { chargingState = 0; } @@ -158,10 +158,15 @@ function writeBatteryLevel(dc, x, y, width, height, type) { break; } - if (inText != null) { + if (inText != null && error == null) { + if (batteryStale == true) { + textColour = Graphics.COLOR_LT_GRAY; + } else { + textColour = gThemeColour; + } dc.setColor(gThemeColour, Graphics.COLOR_TRANSPARENT); dc.drawText(x - (width / 2), y - height, gNormalFont, inText, Graphics.TEXT_JUSTIFY_LEFT); - } else if (value == null || (value instanceof Toybox.Lang.String && value.equals("N/A"))) { + } else if (value == null || (value instanceof Toybox.Lang.String && value.equals("N/A")) && error == null) { dc.setColor(Graphics.COLOR_LT_GRAY, Graphics.COLOR_TRANSPARENT); dc.drawText(x - (width / 2), y - height, gNormalFont, "???", Graphics.TEXT_JUSTIFY_LEFT); } else { From bfc57eb604cd4dc59c5fdb3a3d937589f237a3f1 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 3 Apr 2022 14:56:09 -0400 Subject: [PATCH 028/220] Rewritten Propertie TeslaBatterieLevel to TeslaInfo since it does more than just the battery stuff now --- resources-fre/strings/strings.xml | 2 +- resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 14 +++++++------- source/CrystalApp.mc | 32 +++++++++++++++---------------- source/CrystalView.mc | 9 +++++++-- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 34b3a159..1f9e2f7e 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -105,7 +105,7 @@ Batterie Numérique Pulse Ox - Tesla battery level + Information Tesla Tesla Access Token Tesla Refresh Token diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index fd4ba42a..c91175be 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -105,7 +105,7 @@ Battery Numeric Pulse Ox - Tesla battery level + Tesla Info Tesla Access Token Tesla Refresh Token diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index b19c13d2..7dd5cd92 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -125,22 +125,22 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") // 3. Tesla } - if (pendingWebRequests["TeslaBatterieLevel"] != null && App.getApp().getProperty("Tesla") != null) { + if (pendingWebRequests["TeslaInfo"] != null && App.getApp().getProperty("Tesla") != null) { logMessage("onTemporalEvent: WebRequest for vehicle id " + _vehicle_id); if (!Sys.getDeviceSettings().phoneConnected) { logMessage("onTemporalEvent: No phone connected"); -// pendingWebRequests["TeslaBatterieLevel"] = null; +// pendingWebRequests["TeslaInfo"] = null; return; } -//logMessage("onTemporalEvent:TeslaBatterieLevel with vehicle_id at " + _vehicle_id); +//logMessage("onTemporalEvent:TeslaInfo with vehicle_id at " + _vehicle_id); if (_vehicle_id) { //logMessage("onTemporalEvent:Calling makeTeslaWebRequest to get vehicle data"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } else { //logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data because of null vehicle_id"); -// pendingWebRequests["TeslaBatterieLevel"] = null; +// pendingWebRequests["TeslaInfo"] = null; } } } /* else { @@ -285,7 +285,7 @@ logMessage("onReceiveToken responseCode is " + responseCode); } else { result = { "httpErrorTesla" => responseCode }; } - Bg.exit({ "TeslaBatterieLevel" => result }); + Bg.exit({ "TeslaInfo" => result }); } (:background_method) @@ -306,7 +306,7 @@ logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + result = { "httpErrorTesla" => responseCode }; } - Bg.exit({ "TeslaBatterieLevel" => result }); + Bg.exit({ "TeslaInfo" => result }); } (:background_method) @@ -352,7 +352,7 @@ logMessage("onReceiveVehicleData responseCode is " + responseCode); logMessage("onReceiveVehicleData received " + result); - Bg.exit({ "TeslaBatterieLevel" => result }); + Bg.exit({ "TeslaInfo" => result }); } (:background_method) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index cceb8d3a..9faf5cde 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -83,7 +83,7 @@ class CrystalApp extends App.AppBase { // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. var lastTime = Bg.getLastTemporalEventTime(); - var teslaBatterieLevel = getProperty("TeslaBatterieLevel"); + var TeslaInfo = getProperty("TeslaInfo"); var gotData = temporalRan; temporalRan = false; @@ -181,13 +181,13 @@ if (gotData) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pe // 3. Tesla: if (getProperty("Tesla") != null) { -if (gotData) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaBatterieLevel.toString().substring(0,60) + " ..."); } +if (gotData) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } // No existing data. - if (teslaBatterieLevel == null) { + if (TeslaInfo == null) { //if (gotData) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } - pendingWebRequests["TeslaBatterieLevel"] = true; + pendingWebRequests["TeslaInfo"] = true; // We got something, check what it is } else { @@ -199,7 +199,7 @@ if (gotData) { logMessage("checkPendingWebRequests:TeslaBatterieLevel=" + teslaB // First handle errors, setting batterie_level to "N/A" if the query returned a vehicle not found. // If we failed to get access, maybe our token has expired, clear it so next time the background process runs, it will refresh it // Other errors are silent for now - var result = teslaBatterieLevel["httpErrorTesla"]; + var result = TeslaInfo["httpErrorTesla"]; if (result != null) { if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); } if (result == 400 || result == 401) { // Our token has expired, refresh it @@ -218,7 +218,7 @@ if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + } // Check if our access token was refreshed. If so, store the new access and refresh tokens - result = teslaBatterieLevel["Token"]; + result = TeslaInfo["Token"]; if (result != null) { //logMessage("checkPendingWebRequests:Got token data '" + result + "'"); if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } @@ -241,30 +241,30 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token // If the car isn't asleep, keep the current charge and clear the charging_state else if (!carAsleep) { - var batterie_state = teslaBatterieLevel["battery_state"]; + var batterie_state = TeslaInfo["battery_state"]; if (batterie_state) { batterie_level = batterie_state["battery_level"]; charging_state = batterie_state["charging_state"]; } - var inside_temp = teslaBatterieLevel["inside_temp"]; + var inside_temp = TeslaInfo["inside_temp"]; if (inside_temp != null) { setProperty("TeslaInsideTemp", inside_temp.toString()); } - var precond_enabled = teslaBatterieLevel["preconditioning"]; + var precond_enabled = TeslaInfo["preconditioning"]; if (precond_enabled != null) { setProperty("TeslaPreconditioning", precond_enabled.toString()); } - var sentry_enabled = teslaBatterieLevel["sentry_enabled"]; + var sentry_enabled = TeslaInfo["sentry_enabled"]; if (sentry_enabled != null) { setProperty("TeslaSentryEnabled", sentry_enabled.toString()); } // Read its vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. // If we have no vehicle, set the batterie level to N/A - var vehicle_id = teslaBatterieLevel["vehicle_id"]; + var vehicle_id = TeslaInfo["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { //if (gotData) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } @@ -276,22 +276,22 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token batterie_level = "N/A"; } } else { -//if (gotData) { logMessage("checkPendingWebRequests: teslaBatterieLevel[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } +//if (gotData) { logMessage("checkPendingWebRequests: TeslaInfo[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } // setProperty("TeslaVehicleID", null); batterie_stale = true; } // Here batterie_level is the same as what was read earlier or changed to N/A for some reason above. if (batterie_level != null) { - setProperty("TeslaBatterieLevelValue", batterie_level); + setProperty("TeslaBatterieLevel", batterie_level); setProperty("TeslaBatterieStale", batterie_stale); setProperty("TeslaChargingState", charging_state); setProperty("TeslaError", null); } else { -//if (gotData) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevelValue property"*/); } -// setProperty("TeslaBatterieLevelValue", null); +//if (gotData) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevel property"*/); } +// setProperty("TeslaBatterieLevel", null); setProperty("TeslaBatterieStale", true); setProperty("TeslaError", null); } @@ -301,7 +301,7 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token setProperty("TeslaError", null); } - pendingWebRequests["TeslaBatterieLevel"] = true; + pendingWebRequests["TeslaInfo"] = true; } } // If there are any pending requests: diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 1ce3b256..4d0ae9d4 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -116,7 +116,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { chargingState = 1; } else if (chargingState.equals("Sleeping")) { chargingState = 2; - showMode /= 2; // Keep only 0 and 1. + showMode /= 2; // Keep only 0 and 2. } else { chargingState = 0; } @@ -127,7 +127,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var inText = null; switch (showMode) { case 0: - value = App.getApp().getProperty("TeslaBatterieLevelValue"); + value = App.getApp().getProperty("TeslaBatterieLevel"); break; case 1: value = App.getApp().getProperty("TeslaPreconditioning"); @@ -157,6 +157,11 @@ function writeBatteryLevel(dc, x, y, width, height, type) { value = App.getApp().getProperty("TeslaInsideTemp"); break; } + +//logMessage("value=" + value); + if (value == null) { + value = "N/A"; + } if (inText != null && error == null) { if (batteryStale == true) { From 84829af1576b4541888a3e663c3525d0411121ee Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 3 Apr 2022 15:36:52 -0400 Subject: [PATCH 029/220] Crash in debug code when starting from fresh --- source/CrystalApp.mc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 9faf5cde..f6ce89c4 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -181,7 +181,7 @@ if (gotData) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pe // 3. Tesla: if (getProperty("Tesla") != null) { -if (gotData) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } +if (gotData && TeslaInfo != null) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } // No existing data. if (TeslaInfo == null) { From 47d25972f942dd8b015894d3900c6cad6402c01f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 4 Apr 2022 00:06:06 -0400 Subject: [PATCH 030/220] Fix code to display if we have an error, fix code that disables TeslaInfo when not selected, fix code that always display P and S using theme color. Added more watches by using a more recent SDK version. --- manifest.xml | 11 +++++++++-- source/BackgroundService.mc | 2 +- source/CrystalApp.mc | 10 +++++++--- source/CrystalView.mc | 2 +- source/Indicators.mc | 2 +- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/manifest.xml b/manifest.xml index cc45f74b..e76a147a 100644 --- a/manifest.xml +++ b/manifest.xml @@ -4,14 +4,14 @@ + - - + @@ -22,15 +22,20 @@ + + + + + @@ -39,6 +44,7 @@ + @@ -55,6 +61,7 @@ + diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 7dd5cd92..c87996b3 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -20,7 +20,7 @@ class BackgroundService extends Sys.ServiceDelegate { //logMessage("initialize: No phone connected"); // return; // } - + if (App.getApp().getProperty("Tesla") == null) { //logMessage("initialize: Not requesting Tesla stuff, bailing out"); return; diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index f6ce89c4..eeb12806 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -239,8 +239,8 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token setProperty("TeslaError", null); } - // If the car isn't asleep, keep the current charge and clear the charging_state - else if (!carAsleep) { + // If the car isn't asleep and we didn't get an error, read what was returned + else if (!carAsleep && !batterie_stale) { var batterie_state = TeslaInfo["battery_state"]; if (batterie_state) { batterie_level = batterie_state["battery_level"]; @@ -295,7 +295,7 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token setProperty("TeslaBatterieStale", true); setProperty("TeslaError", null); } - } else { + } else if (!batterie_stale) { // Car is asleap, say so setProperty("TeslaChargingState", "Sleeping"); setProperty("TeslaBatterieStale", false); setProperty("TeslaError", null); @@ -304,6 +304,10 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token pendingWebRequests["TeslaInfo"] = true; } } + else { + pendingWebRequests.remove("TeslaInfo"); + } + // If there are any pending requests: if (pendingWebRequests.keys().size() > 0) { diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 4d0ae9d4..28644f2b 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -169,7 +169,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { } else { textColour = gThemeColour; } - dc.setColor(gThemeColour, Graphics.COLOR_TRANSPARENT); + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); dc.drawText(x - (width / 2), y - height, gNormalFont, inText, Graphics.TEXT_JUSTIFY_LEFT); } else if (value == null || (value instanceof Toybox.Lang.String && value.equals("N/A")) && error == null) { dc.setColor(Graphics.COLOR_LT_GRAY, Graphics.COLOR_TRANSPARENT); diff --git a/source/Indicators.mc b/source/Indicators.mc index 9f1c5f8e..223d4a9b 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -44,7 +44,7 @@ class Indicators extends Ui.Drawable { App.getApp().setProperty("Tesla", true); //logMessage("onSettingsChanged:Doing Tesla!"); } else { - App.getApp().setProperty("Tesla", false); + App.getApp().setProperty("Tesla", null); } } From 369fa635327fd2155b94baa46b7360fb56c26d05 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 5 Apr 2022 00:20:40 -0400 Subject: [PATCH 031/220] Removal of debug code to reduce the size of the executable and additions of new devices --- manifest.xml | 5 ++--- monkey.jungle | 3 +++ source/BackgroundService.mc | 24 ++++++++++++------------ source/CrystalApp.mc | 20 ++++++++++---------- source/CrystalView.mc | 2 +- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/manifest.xml b/manifest.xml index e76a147a..3f97fbfb 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,5 +1,5 @@ - + @@ -22,7 +22,6 @@ - @@ -60,8 +59,8 @@ + - diff --git a/monkey.jungle b/monkey.jungle index a656f7cb..9bd7eb76 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -73,7 +73,10 @@ garminswim2.excludeAnnotations = $(garminswim2.excludeAnnotations);buffered;back venu.sourcePath = $(venu.sourcePath);always-on-source venu2.sourcePath = $(venu2.sourcePath);always-on-source venu2s.sourcePath = $(venu2s.sourcePath);always-on-source +venu2plus.sourcePath = $(venu2plus.sourcePath);always-on-source venud.sourcePath = $(venud.sourcePath);always-on-source venusq.sourcePath = $(venusq.sourcePath);always-on-source venusqm.sourcePath = $(venusqm.sourcePath);always-on-source d2air.sourcePath = $(d2air.sourcePath);always-on-source +d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source +d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index c87996b3..f5ab1871 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -48,26 +48,26 @@ class BackgroundService extends Sys.ServiceDelegate { var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); -logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); +//2022-04-04 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { -logMessage("initialize:Generating Access Token"); +//2022-04-04 logMessage("initialize:Generating Access Token"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { -logMessage("initialize:No refresh token!"); +//2022-04-04 logMessage("initialize:No refresh token!"); } return; } _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); if (_vehicle_id == null) { -logMessage("initialize:Getting vehicle_id"); +//2022-04-04 logMessage("initialize:Getting vehicle_id"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { -logMessage("initialize:Asking vehicle data for " + _vehicle_id); +//2022-04-04 logMessage("initialize:Asking vehicle data for " + _vehicle_id); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } } @@ -78,7 +78,7 @@ logMessage("initialize:Asking vehicle data for " + _vehicle_id); (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); +//2022-04-04 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. @@ -126,9 +126,9 @@ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'") // 3. Tesla } if (pendingWebRequests["TeslaInfo"] != null && App.getApp().getProperty("Tesla") != null) { -logMessage("onTemporalEvent: WebRequest for vehicle id " + _vehicle_id); +//2022-04-04 logMessage("onTemporalEvent: WebRequest for vehicle id " + _vehicle_id); if (!Sys.getDeviceSettings().phoneConnected) { -logMessage("onTemporalEvent: No phone connected"); +//2022-04-04 logMessage("onTemporalEvent: No phone connected"); // pendingWebRequests["TeslaInfo"] = null; return; } @@ -278,7 +278,7 @@ logMessage("onTemporalEvent: No phone connected"); function onReceiveToken(responseCode, data) { var result; -logMessage("onReceiveToken responseCode is " + responseCode); +//2022-04-04 logMessage("onReceiveToken responseCode is " + responseCode); //logMessage("onReceiveToken data is " + data); if (responseCode == 200) { result = { "Token" => data }; @@ -292,7 +292,7 @@ logMessage("onReceiveToken responseCode is " + responseCode); function onReceiveVehicles(responseCode, data) { var result; -logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); +//2022-04-04 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { @@ -319,7 +319,7 @@ logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + var precondEnabled = "N/A"; var sentryEnabled = "N/A"; -logMessage("onReceiveVehicleData responseCode is " + responseCode); +//2022-04-04 logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { results = data.get("response"); if (results != null) { @@ -350,7 +350,7 @@ logMessage("onReceiveVehicleData responseCode is " + responseCode); result = { "httpErrorTesla" => responseCode }; } -logMessage("onReceiveVehicleData received " + result); +//2022-04-04 logMessage("onReceiveVehicleData received " + result); Bg.exit({ "TeslaInfo" => result }); } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index eeb12806..626263b5 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -118,7 +118,7 @@ class CrystalApp extends App.AppBase { } var pendingWebRequests = getProperty("PendingWebRequests"); -if (gotData) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); } +//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); } if (pendingWebRequests == null) { pendingWebRequests = {}; } @@ -181,7 +181,7 @@ if (gotData) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pe // 3. Tesla: if (getProperty("Tesla") != null) { -if (gotData && TeslaInfo != null) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } +//2022-04-04 if (gotData && TeslaInfo != null) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } // No existing data. if (TeslaInfo == null) { @@ -201,7 +201,7 @@ if (gotData && TeslaInfo != null) { logMessage("checkPendingWebRequests:TeslaInf // Other errors are silent for now var result = TeslaInfo["httpErrorTesla"]; if (result != null) { -if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); } +//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); } if (result == 400 || result == 401) { // Our token has expired, refresh it setProperty("TeslaAccessToken", null); // Try to get a new vehicleID batterie_stale = true; @@ -221,7 +221,7 @@ if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + result = TeslaInfo["Token"]; if (result != null) { //logMessage("checkPendingWebRequests:Got token data '" + result + "'"); -if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } +//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; var expires_in = result["expires_in"]; @@ -231,7 +231,7 @@ if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } setProperty("TeslaRefreshToken", refreshToken); } else { -if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } +//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } } setProperty("TeslaTokenExpiresIn", expires_in); setProperty("TeslaTokenCreatedAt", created_at); @@ -316,11 +316,11 @@ if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token if (lastTime) { // Events scheduled for a time in the past trigger immediately. var nextTime = lastTime.add(new Time.Duration(5 * 60)); -var clockTime = Gregorian.info(nextTime, Time.FORMAT_MEDIUM); -if (gotData) { logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); } +//var clockTime = Gregorian.info(nextTime, Time.FORMAT_MEDIUM); +//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); } Bg.registerForTemporalEvent(nextTime); } else { -if (gotData) { logMessage("checkPendingWebRequests:Scheduling now"); } +//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Scheduling now"); } Bg.registerForTemporalEvent(Time.now()); } } @@ -339,9 +339,9 @@ if (gotData) { logMessage("checkPendingWebRequests:Scheduling now"); } // pendingWebRequests keys. (:background_method) function onBackgroundData(data) { -logMessage("onBackgroundData:received '" + data + "'"); +//2022-04-04 logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = getProperty("PendingWebRequests"); -logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); +//2022-04-04 logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { //logMessage("onBackgroundData: called with no pending web requests!"); pendingWebRequests = {}; diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 28644f2b..a834f66e 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -294,7 +294,7 @@ class CrystalView extends Ui.WatchFace { // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { mSettingsChangedSinceLastDraw = true; -logMessage("onSettingsChanged called"); +//2022-04-04 logMessage("onSettingsChanged called"); updateNormalFont(); From 8395941deeb03193f012b8b19a2f15461cc85466 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 6 Apr 2022 20:22:59 -0400 Subject: [PATCH 032/220] Addition of Epix2 to the supported watches --- manifest.xml | 1 + monkey.jungle | 1 + 2 files changed, 2 insertions(+) diff --git a/manifest.xml b/manifest.xml index 3f97fbfb..3d029af9 100644 --- a/manifest.xml +++ b/manifest.xml @@ -12,6 +12,7 @@ + diff --git a/monkey.jungle b/monkey.jungle index 9bd7eb76..47f2fdc7 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -80,3 +80,4 @@ venusqm.sourcePath = $(venusqm.sourcePath);always-on-source d2air.sourcePath = $(d2air.sourcePath);always-on-source d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source +epix2.sourcePath = $(epix2.sourcePath);always-on-source From a23635833c994cfd2d6e89ad9510c17ce738933b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 7 Apr 2022 19:53:29 -0400 Subject: [PATCH 033/220] Disables background service on watches that doesn't support it. --- source/CrystalApp.mc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 626263b5..da8642a0 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -82,11 +82,15 @@ class CrystalApp extends App.AppBase { // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. - var lastTime = Bg.getLastTemporalEventTime(); + var lastTime = null; var TeslaInfo = getProperty("TeslaInfo"); var gotData = temporalRan; temporalRan = false; + if(Toybox.System has :ServiceDelegate) { + lastTime = Bg.getLastTemporalEventTime(); + } + //logMessage("checkPendingWebRequests:lastBackgroundSchedule is " + lastBackgroundSchedule + " lastTime is " + (lastTime == null ? "null" : lastTime.value())); var location = Activity.getActivityInfo().currentLocation; if (location) { @@ -308,9 +312,8 @@ class CrystalApp extends App.AppBase { pendingWebRequests.remove("TeslaInfo"); } - // If there are any pending requests: - if (pendingWebRequests.keys().size() > 0) { - + // If there are any pending requests and we can do background process + if (Toybox.System has :ServiceDelegate && pendingWebRequests.keys().size() > 0) { // Register for background temporal event as soon as possible. // var lastTime = Bg.getLastTemporalEventTime(); if (lastTime) { From de8bcc16f180cb68840abef5040883a400f46692 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 8 Apr 2022 20:18:24 -0400 Subject: [PATCH 034/220] Fix sunrise showing todays instead of tomorrow when sunset has been reached --- source/DataFields.mc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/DataFields.mc b/source/DataFields.mc index cb0d9c1c..433b2ff8 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -499,11 +499,11 @@ class DataFields extends Ui.Drawable { // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). now = now.hour + ((now.min + 1) / 60.0); - //Sys.println(now); + //logMessage(now); // Get today's sunrise/sunset times in current time zone. sunTimes = getSunTimes(gLocationLat, gLocationLng, null, /* tomorrow */ false); - //Sys.println(sunTimes); + //logMessage(sunTimes); // If sunrise/sunset happens today. var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); @@ -653,7 +653,7 @@ class DataFields extends Ui.Drawable { if (tomorrow) { now = now.add(new Time.Duration(24 * 60 * 60)); } - var d = Gregorian.info(Time.now(), Time.FORMAT_SHORT); + var d = Gregorian.info(now, Time.FORMAT_SHORT); var rad = Math.PI / 180.0d; var deg = 180.0d / Math.PI; From 6513254e3746d5f839083b2c00d4fca01f6ffe95 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 9 Apr 2022 14:16:17 -0400 Subject: [PATCH 035/220] GarminWeather can be used instead of OpenWeatherMap --- source/CrystalApp.mc | 45 +++++---- source/CrystalView.mc | 165 +++++++++++++++++++++++++++++++ source/DataFields.mc | 225 +++++++++++++++++++++--------------------- 3 files changed, 303 insertions(+), 132 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index da8642a0..0bc6681b 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -159,33 +159,38 @@ class CrystalApp extends App.AppBase { if ((gLocationLat != null) && (hasField(FIELD_TYPE_WEATHER) || hasField(FIELD_TYPE_HUMIDITY))) { - var owmCurrent = getProperty("OpenWeatherMapCurrent"); - - // No existing data. - if (owmCurrent == null) { - - pendingWebRequests["OpenWeatherMapCurrent"] = true; - - // Successfully received weather data. - } else if (owmCurrent["cod"] == 200) { - - // Existing data is older than 30 mins. - // TODO: Consider requesting weather at sunrise/sunset to update weather icon. - if ((Time.now().value() > (owmCurrent["dt"] + 1800)) || - - // Existing data not for this location. - // Not a great test, as a degree of longitude varies betwee 69 (equator) and 0 (pole) miles, but simpler than - // true distance calculation. 0.02 degree of latitude is just over a mile. - (((gLocationLat - owmCurrent["lat"]).abs() > 0.02) || ((gLocationLng - owmCurrent["lon"]).abs() > 0.02))) { - + var owmKeyOverride = getProperty("OWMKeyOverride"); + if (owmKeyOverride == null || owmKeyOverride.length() == 0) { +//logMessage("Using Garmin Weather so skipping this"); + } else { +//logMessage("Using OpenWeatherMap"); + var owmCurrent = getProperty("OpenWeatherMapCurrent"); + + // No existing data. + if (owmCurrent == null) { pendingWebRequests["OpenWeatherMapCurrent"] = true; + // Successfully received weather data. + } else if (owmCurrent["cod"] == 200) { +//logMessage(owmCurrent["dt"]); + // Existing data is older than 30 mins. + // TODO: Consider requesting weather at sunrise/sunset to update weather icon. + if ((Time.now().value() > (owmCurrent["dt"] + 1800)) || + + // Existing data not for this location. + // Not a great test, as a degree of longitude varies betwee 69 (equator) and 0 (pole) miles, but simpler than + // true distance calculation. 0.02 degree of latitude is just over a mile. + (((gLocationLat - owmCurrent["lat"]).abs() > 0.02) || ((gLocationLng - owmCurrent["lon"]).abs() > 0.02))) { + + pendingWebRequests["OpenWeatherMapCurrent"] = true; + } } } } // 3. Tesla: if (getProperty("Tesla") != null) { -//2022-04-04 if (gotData && TeslaInfo != null) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } +//logMessage("checkPendingWebRequests in Tesla code"); +//if (/*gotData &&*/ TeslaInfo != null) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } // No existing data. if (TeslaInfo == null) { diff --git a/source/CrystalView.mc b/source/CrystalView.mc index a834f66e..55ac2b5c 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -4,6 +4,10 @@ using Toybox.System as Sys; using Toybox.Application as App; using Toybox.ActivityMonitor as ActivityMonitor; using Toybox.Communications as Comms; +using Toybox.Time; +using Toybox.Time.Gregorian; +using Toybox.Weather; +using Toybox.Position; using Toybox.Math; @@ -217,6 +221,63 @@ class CrystalView extends Ui.WatchFace { private var mSettingsChangedSinceLastDraw = true; // Have settings changed since last full update? private var mTime; var mDataFields; + var mHasGarminWeather; + var mGarminToOWM = { + "0" => "01", + "1" => "02", + "2" => "03", + "3" => "10", + "4" => "13", + "5" => "04", + "6" => "11", + "7" => "13", + "8" => "50", + "9" => "50", + "10" => "10", + "11" => "09", + "12" => "11", + "13" => "01", + "14" => "09", + "15" => "10", + "16" => "13", + "17" => "13", + "18" => "13", + "19" => "13", + "20" => "04", + "21" => "13", + "22" => "03", + "23" => "02", + "24" => "09", + "25" => "10", + "26" => "10", + "27" => "09", + "28" => "11", + "29" => "50", + "30" => "04", + "31" => "09", + "32" => "11", + "33" => "04", + "34" => "13", + "35" => "04", + "36" => "04", + "37" => "04", + "38" => "04", + "39" => "50", + "40" => "02", + "41" => "11", + "42" => "11", + "43" => "13", + "44" => "13", + "45" => "09", + "46" => "13", + "47" => "13", + "48" => "13", + "49" => "13", + "50" => "13", + "51" => "13", + "52" => "02", + "53" => "01" + }; // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); private var mDrawables = {}; @@ -250,6 +311,21 @@ class CrystalView extends Ui.WatchFace { function initialize() { WatchFace.initialize(); + + var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); +//logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); + if (owmKeyOverride == null || owmKeyOverride.length() == 0) { + if (Toybox has :Weather) { + mHasGarminWeather = true; +//logMessage("Does support Weather"); + } else { + mHasGarminWeather = false; +//logMessage("Does not support Weather"); + } + } else { + mHasGarminWeather = false; +//logMessage("Using OpenWeatherMap"); + } } // Load your resources here @@ -308,8 +384,93 @@ class CrystalView extends Ui.WatchFace { //logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } + + if (mHasGarminWeather == true) { // Using the Garmin Weather stuff + ReadWeather(); + } } + // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see + function ReadWeather() { + var weather = Weather.getCurrentConditions(); + var result; + if (weather != null) { + var temperature = weather.temperature; + var humidity = weather.relativeHumidity; + var condition = weather.condition; + var icon; + var day = "d"; + +// var myLocation = new Position.Location({:latitude => gLocationLat, :longitude => gLocationLng, :format => :degrees }); + var myLocation = weather.observationLocationPosition; + var myLocationArray = myLocation.toDegrees(); +// var now = Time.now(); + var now = weather.observationTime; + if (Toybox.Weather has :getSunrise) { +//logMessage("We have sunrise and sunset routines!"); + var sunrise = 0; + var sunset = 0; + sunrise = Weather.getSunrise(myLocation, now); + sunset = Weather.getSunset(myLocation, now); + + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); + if (sinceSunrise >= 0 || sinceSunset >= 0) { + day = "n"; + } + + /*var nowtime = Gregorian.info(now, Time.FORMAT_MEDIUM); + var nowStr = nowtime.day + " " + nowtime.hour + ":" + nowtime.min.format("%02d") + ":" + nowtime.sec.format("%02d"); + var sunrisetime = Gregorian.info(sunrise, Time.FORMAT_MEDIUM); + var sunsettime = Gregorian.info(sunset, Time.FORMAT_MEDIUM); + var sunriseStr = sunrisetime.day + " " + sunrisetime.hour + ":" + sunrisetime.min.format("%02d") + ":" + sunrisetime.sec.format("%02d"); + var sunsetStr = sunsettime.day + " " + sunsettime.hour + ":" + sunsettime.min.format("%02d") + ":" + sunsettime.sec.format("%02d"); + logMessage("At=" + nowStr); + logMessage("Sunrise=" + sunriseStr); + logMessage("Sunset=" + sunsetStr); + logMessage("Since sunrize " + sinceSunrise); + logMessage("Since sunset " + sinceSunset);*/ + + now = now.value(); + } else { +//logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); + + var nextSunEvent = 0; + var value = 0; + + now = Gregorian.info(Time.now(), Time.FORMAT_SHORT); + + // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at + // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). + now = now.hour + ((now.min + 1) / 60.0); + //logMessage(now); + + // Get today's sunrise/sunset times in current time zone. + var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); + //logMessage(sunTimes); +//logMessage("now=" + now); +//logMessage("sunTimes=" + sunTimes); + // If sunrise/sunset happens today. + var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); + if (sunriseSunsetToday) { + if (now < sunTimes[0] || now > sunTimes[1]) { + day = "n"; + } + } + + now = Time.now().value(); + } + + icon = mGarminToOWM[condition.toString()] + day; + result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => now, "lat" => myLocationArray[0], "lon" => myLocationArray[1]}; + } else { + now = Time.now().value(); + result = { "cod" => 408, "dt" => now }; + } + App.getApp().setProperty("OpenWeatherMapCurrent", result); +//logMessage("Weather at " + weather.observationLocationName + " is " + result); + } + // Select normal font, based on whether time zone feature is being used. // Saves memory when cities are not in use. // Update drawables that use normal font. @@ -567,6 +728,10 @@ class CrystalView extends Ui.WatchFace { //logMessage("onExitSleep:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } + + if (mHasGarminWeather == true) { // Using the Garmin Weather stuff + ReadWeather(); + } // If watch requires burn-in protection, set flag to false when entering sleep. var settings = Sys.getDeviceSettings(); diff --git a/source/DataFields.mc b/source/DataFields.mc index 433b2ff8..f9e7a960 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -5,6 +5,7 @@ using Toybox.Application as App; using Toybox.Activity as Activity; using Toybox.ActivityMonitor as ActivityMonitor; using Toybox.SensorHistory as SensorHistory; +using Toybox.Math; using Toybox.Time; using Toybox.Time.Gregorian; @@ -47,7 +48,6 @@ class DataFields extends Ui.Drawable { private var mWasHRAvailable = false; // HR availability at last full draw (in high power mode). private var mMaxFieldLength; // Maximum number of characters per field. private var mBatteryWidth; // Width of battery meter. - // private const CM_PER_KM = 100000; // private const MI_PER_KM = 0.621371; // private const FT_PER_M = 3.28084; @@ -624,117 +624,118 @@ class DataFields extends Ui.Drawable { result["value"] = value; return result; } +} - /** - * With thanks to ruiokada. Adapted, then translated to Monkey C, from: - * https://gist.github.com/ruiokada/b28076d4911820ddcbbc - * - * Calculates sunrise and sunset in local time given latitude, longitude, and tz. - * - * Equations taken from: - * https://en.wikipedia.org/wiki/Julian_day#Converting_Julian_or_Gregorian_calendar_date_to_Julian_Day_Number - * https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth - * - * @method getSunTimes - * @param {Float} lat Latitude of location (South is negative) - * @param {Float} lng Longitude of location (West is negative) - * @param {Integer || null} tz Timezone hour offset. e.g. Pacific/Los Angeles is -8 (Specify null for system timezone) - * @param {Boolean} tomorrow Calculate tomorrow's sunrise and sunset, instead of today's. - * @return {Array} Returns array of length 2 with sunrise and sunset as floats. - * Returns array with [null, -1] if the sun never rises, and [-1, null] if the sun never sets. - */ - private function getSunTimes(lat, lng, tz, tomorrow) { - - // Use double precision where possible, as floating point errors can affect result by minutes. - lat = lat.toDouble(); - lng = lng.toDouble(); - - var now = Time.now(); - if (tomorrow) { - now = now.add(new Time.Duration(24 * 60 * 60)); - } - var d = Gregorian.info(now, Time.FORMAT_SHORT); - var rad = Math.PI / 180.0d; - var deg = 180.0d / Math.PI; - - // Calculate Julian date from Gregorian. - var a = Math.floor((14 - d.month) / 12); - var y = d.year + 4800 - a; - var m = d.month + (12 * a) - 3; - var jDate = d.day - + Math.floor(((153 * m) + 2) / 5) - + (365 * y) - + Math.floor(y / 4) - - Math.floor(y / 100) - + Math.floor(y / 400) - - 32045; - - // Number of days since Jan 1st, 2000 12:00. - var n = jDate - 2451545.0d + 0.0008d; - //Sys.println("n " + n); - - // Mean solar noon. - var jStar = n - (lng / 360.0d); - //Sys.println("jStar " + jStar); - - // Solar mean anomaly. - var M = 357.5291d + (0.98560028d * jStar); - var MFloor = Math.floor(M); - var MFrac = M - MFloor; - M = MFloor.toLong() % 360; - M += MFrac; - //Sys.println("M " + M); - - // Equation of the centre. - var C = 1.9148d * Math.sin(M * rad) - + 0.02d * Math.sin(2 * M * rad) - + 0.0003d * Math.sin(3 * M * rad); - //Sys.println("C " + C); - - // Ecliptic longitude. - var lambda = (M + C + 180 + 102.9372d); - var lambdaFloor = Math.floor(lambda); - var lambdaFrac = lambda - lambdaFloor; - lambda = lambdaFloor.toLong() % 360; - lambda += lambdaFrac; - //Sys.println("lambda " + lambda); - - // Solar transit. - var jTransit = 2451545.5d + jStar - + 0.0053d * Math.sin(M * rad) - - 0.0069d * Math.sin(2 * lambda * rad); - //Sys.println("jTransit " + jTransit); - - // Declination of the sun. - var delta = Math.asin(Math.sin(lambda * rad) * Math.sin(23.44d * rad)); - //Sys.println("delta " + delta); - - // Hour angle. - var cosOmega = (Math.sin(-0.83d * rad) - Math.sin(lat * rad) * Math.sin(delta)) - / (Math.cos(lat * rad) * Math.cos(delta)); - //Sys.println("cosOmega " + cosOmega); - - // Sun never rises. - if (cosOmega > 1) { - return [null, -1]; - } - - // Sun never sets. - if (cosOmega < -1) { - return [-1, null]; - } - - // Calculate times from omega. - var omega = Math.acos(cosOmega) * deg; - var jSet = jTransit + (omega / 360.0); - var jRise = jTransit - (omega / 360.0); - var deltaJSet = jSet - jDate; - var deltaJRise = jRise - jDate; - - var tzOffset = (tz == null) ? (Sys.getClockTime().timeZoneOffset / 3600) : tz; - return [ - /* localRise */ (deltaJRise * 24) + tzOffset, - /* localSet */ (deltaJSet * 24) + tzOffset - ]; + +/** +* With thanks to ruiokada. Adapted, then translated to Monkey C, from: +* https://gist.github.com/ruiokada/b28076d4911820ddcbbc +* +* Calculates sunrise and sunset in local time given latitude, longitude, and tz. +* +* Equations taken from: +* https://en.wikipedia.org/wiki/Julian_day#Converting_Julian_or_Gregorian_calendar_date_to_Julian_Day_Number +* https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth +* +* @method getSunTimes +* @param {Float} lat Latitude of location (South is negative) +* @param {Float} lng Longitude of location (West is negative) +* @param {Integer || null} tz Timezone hour offset. e.g. Pacific/Los Angeles is -8 (Specify null for system timezone) +* @param {Boolean} tomorrow Calculate tomorrow's sunrise and sunset, instead of today's. +* @return {Array} Returns array of length 2 with sunrise and sunset as floats. +* Returns array with [null, -1] if the sun never rises, and [-1, null] if the sun never sets. +*/ +function getSunTimes(lat, lng, tz, tomorrow) { + + // Use double precision where possible, as floating point errors can affect result by minutes. + lat = lat.toDouble(); + lng = lng.toDouble(); + + var now = Time.now(); + if (tomorrow) { + now = now.add(new Time.Duration(24 * 60 * 60)); + } + var d = Gregorian.info(now, Time.FORMAT_SHORT); + var rad = Math.PI / 180.0d; + var deg = 180.0d / Math.PI; + + // Calculate Julian date from Gregorian. + var a = Math.floor((14 - d.month) / 12); + var y = d.year + 4800 - a; + var m = d.month + (12 * a) - 3; + var jDate = d.day + + Math.floor(((153 * m) + 2) / 5) + + (365 * y) + + Math.floor(y / 4) + - Math.floor(y / 100) + + Math.floor(y / 400) + - 32045; + + // Number of days since Jan 1st, 2000 12:00. + var n = jDate - 2451545.0d + 0.0008d; + //Sys.println("n " + n); + + // Mean solar noon. + var jStar = n - (lng / 360.0d); + //Sys.println("jStar " + jStar); + + // Solar mean anomaly. + var M = 357.5291d + (0.98560028d * jStar); + var MFloor = Math.floor(M); + var MFrac = M - MFloor; + M = MFloor.toLong() % 360; + M += MFrac; + //Sys.println("M " + M); + + // Equation of the centre. + var C = 1.9148d * Math.sin(M * rad) + + 0.02d * Math.sin(2 * M * rad) + + 0.0003d * Math.sin(3 * M * rad); + //Sys.println("C " + C); + + // Ecliptic longitude. + var lambda = (M + C + 180 + 102.9372d); + var lambdaFloor = Math.floor(lambda); + var lambdaFrac = lambda - lambdaFloor; + lambda = lambdaFloor.toLong() % 360; + lambda += lambdaFrac; + //Sys.println("lambda " + lambda); + + // Solar transit. + var jTransit = 2451545.5d + jStar + + 0.0053d * Math.sin(M * rad) + - 0.0069d * Math.sin(2 * lambda * rad); + //Sys.println("jTransit " + jTransit); + + // Declination of the sun. + var delta = Math.asin(Math.sin(lambda * rad) * Math.sin(23.44d * rad)); + //Sys.println("delta " + delta); + + // Hour angle. + var cosOmega = (Math.sin(-0.83d * rad) - Math.sin(lat * rad) * Math.sin(delta)) + / (Math.cos(lat * rad) * Math.cos(delta)); + //Sys.println("cosOmega " + cosOmega); + + // Sun never rises. + if (cosOmega > 1) { + return [null, -1]; + } + + // Sun never sets. + if (cosOmega < -1) { + return [-1, null]; } + + // Calculate times from omega. + var omega = Math.acos(cosOmega) * deg; + var jSet = jTransit + (omega / 360.0); + var jRise = jTransit - (omega / 360.0); + var deltaJSet = jSet - jDate; + var deltaJRise = jRise - jDate; + + var tzOffset = (tz == null) ? (Sys.getClockTime().timeZoneOffset / 3600) : tz; + return [ + /* localRise */ (deltaJRise * 24) + tzOffset, + /* localSet */ (deltaJSet * 24) + tzOffset + ]; } From e864b5b22fbdab09bfd7bdbeb65fd42eb1e3ddbd Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 9 Apr 2022 15:02:01 -0400 Subject: [PATCH 036/220] Tidying the code a bit --- source/CrystalView.mc | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 55ac2b5c..3c0f5b7a 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -398,7 +398,7 @@ class CrystalView extends Ui.WatchFace { var temperature = weather.temperature; var humidity = weather.relativeHumidity; var condition = weather.condition; - var icon; + var icon = "01"; var day = "d"; // var myLocation = new Position.Location({:latitude => gLocationLat, :longitude => gLocationLng, :format => :degrees }); @@ -408,10 +408,8 @@ class CrystalView extends Ui.WatchFace { var now = weather.observationTime; if (Toybox.Weather has :getSunrise) { //logMessage("We have sunrise and sunset routines!"); - var sunrise = 0; - var sunset = 0; - sunrise = Weather.getSunrise(myLocation, now); - sunset = Weather.getSunset(myLocation, now); + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); var sinceSunrise = sunrise.compare(now); var sinceSunset = now.compare(sunset); @@ -431,14 +429,10 @@ class CrystalView extends Ui.WatchFace { logMessage("Since sunrize " + sinceSunrise); logMessage("Since sunset " + sinceSunset);*/ - now = now.value(); } else { //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); - - var nextSunEvent = 0; - var value = 0; - now = Gregorian.info(Time.now(), Time.FORMAT_SHORT); + now = Gregorian.info(now, Time.FORMAT_SHORT); // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). @@ -448,8 +442,8 @@ class CrystalView extends Ui.WatchFace { // Get today's sunrise/sunset times in current time zone. var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); //logMessage(sunTimes); -//logMessage("now=" + now); -//logMessage("sunTimes=" + sunTimes); +logMessage("now=" + now); +logMessage("sunTimes=" + sunTimes); // If sunrise/sunset happens today. var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); if (sunriseSunsetToday) { @@ -458,10 +452,13 @@ class CrystalView extends Ui.WatchFace { } } - now = Time.now().value(); } - icon = mGarminToOWM[condition.toString()] + day; + now = Time.now().value(); + if (condition < 53) { + icon = mGarminToOWM[condition.toString()] + day; +logMessage("icon=" + icon); + } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => now, "lat" => myLocationArray[0], "lon" => myLocationArray[1]}; } else { now = Time.now().value(); From ee2391b5218618d1d72c61b2c4e1eaaef43ad8da Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 9 Apr 2022 20:47:37 -0400 Subject: [PATCH 037/220] Modification to the Garmin Weather code so it can run on most 64KB watches --- source/CrystalView.mc | 78 +++++++++---------------------------------- 1 file changed, 15 insertions(+), 63 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 3c0f5b7a..ee099114 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -29,6 +29,8 @@ const SCREEN_MULTIPLIER = (Sys.getDeviceSettings().screenWidth < 360) ? 1 : 2; const BATTERY_HEAD_HEIGHT = 4 * SCREEN_MULTIPLIER; const BATTERY_MARGIN = SCREEN_MULTIPLIER; +var mGarminToOWM = [ 1, 2, 3, 10, 13, 4, 11, 13, 50, 50, 10, 9, 11, 1, 9, 10, 13, 13, 13, 13, 4, 13, 3, 2, 9, 10, 10, 9, 11, 50, 4, 9, 11, 4, 13, 4, 4, 4, 4, 50, 2, 11, 11, 13, 13, 9, 13, 13, 13, 13, 13, 13, 2, 1 ]; + //const BATTERY_LEVEL_LOW = 20; //const BATTERY_LEVEL_CRITICAL = 10; @@ -222,63 +224,6 @@ class CrystalView extends Ui.WatchFace { private var mTime; var mDataFields; var mHasGarminWeather; - var mGarminToOWM = { - "0" => "01", - "1" => "02", - "2" => "03", - "3" => "10", - "4" => "13", - "5" => "04", - "6" => "11", - "7" => "13", - "8" => "50", - "9" => "50", - "10" => "10", - "11" => "09", - "12" => "11", - "13" => "01", - "14" => "09", - "15" => "10", - "16" => "13", - "17" => "13", - "18" => "13", - "19" => "13", - "20" => "04", - "21" => "13", - "22" => "03", - "23" => "02", - "24" => "09", - "25" => "10", - "26" => "10", - "27" => "09", - "28" => "11", - "29" => "50", - "30" => "04", - "31" => "09", - "32" => "11", - "33" => "04", - "34" => "13", - "35" => "04", - "36" => "04", - "37" => "04", - "38" => "04", - "39" => "50", - "40" => "02", - "41" => "11", - "42" => "11", - "43" => "13", - "44" => "13", - "45" => "09", - "46" => "13", - "47" => "13", - "48" => "13", - "49" => "13", - "50" => "13", - "51" => "13", - "52" => "02", - "53" => "01" - }; - // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); private var mDrawables = {}; @@ -312,6 +257,11 @@ class CrystalView extends Ui.WatchFace { function initialize() { WatchFace.initialize(); + rereadWeatherMethod(); + } + + // Reread Weather method + function rereadWeatherMethod() { var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); //logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { @@ -327,7 +277,7 @@ class CrystalView extends Ui.WatchFace { //logMessage("Using OpenWeatherMap"); } } - + // Load your resources here function onLayout(dc) { gIconsFont = Ui.loadResource(Rez.Fonts.IconsFont); @@ -370,7 +320,7 @@ class CrystalView extends Ui.WatchFace { // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { mSettingsChangedSinceLastDraw = true; -//2022-04-04 logMessage("onSettingsChanged called"); +//logMessage("onSettingsChanged called"); updateNormalFont(); @@ -385,6 +335,8 @@ class CrystalView extends Ui.WatchFace { App.getApp().checkPendingWebRequests(); } + rereadWeatherMethod(); // Check if we changed from Garmin Weather or OWM + if (mHasGarminWeather == true) { // Using the Garmin Weather stuff ReadWeather(); } @@ -442,8 +394,8 @@ class CrystalView extends Ui.WatchFace { // Get today's sunrise/sunset times in current time zone. var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); //logMessage(sunTimes); -logMessage("now=" + now); -logMessage("sunTimes=" + sunTimes); +//logMessage("now=" + now); +//logMessage("sunTimes=" + sunTimes); // If sunrise/sunset happens today. var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); if (sunriseSunsetToday) { @@ -456,8 +408,8 @@ logMessage("sunTimes=" + sunTimes); now = Time.now().value(); if (condition < 53) { - icon = mGarminToOWM[condition.toString()] + day; -logMessage("icon=" + icon); + icon = (mGarminToOWM[condition]).format("%02d") + day; +//logMessage("icon=" + icon); } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => now, "lat" => myLocationArray[0], "lon" => myLocationArray[1]}; } else { From 742a7e858bccaf1dd5a544b5bf09779000788e10 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 11 Apr 2022 00:41:30 -0400 Subject: [PATCH 038/220] Fixed a crash when no Garmin Weather data returned. Associated the global GPS var to what was returned by Garmin Weather, removed old debig code and added comments specifying where to cut to remove Tesla addition Cut between //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** and //**************************************************************** //******************** END OF REMVOVED SECTION ******************* //**************************************************************** --- source/BackgroundService.mc | 94 +++++++++++++++++-------------------- source/CrystalApp.mc | 88 ++++++++++------------------------ source/CrystalView.mc | 42 ++++++++++------- source/DataFields.mc | 3 +- source/Indicators.mc | 12 +++++ 5 files changed, 104 insertions(+), 135 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index f5ab1871..9a84f6c1 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -15,14 +15,10 @@ class BackgroundService extends Sys.ServiceDelegate { function initialize() { Sys.ServiceDelegate.initialize(); - // If we don't have a phone connected, don't go any further. -// if (!Sys.getDeviceSettings().phoneConnected) { -//logMessage("initialize: No phone connected"); -// return; -// } - +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** if (App.getApp().getProperty("Tesla") == null) { -//logMessage("initialize: Not requesting Tesla stuff, bailing out"); return; } @@ -48,28 +44,29 @@ class BackgroundService extends Sys.ServiceDelegate { var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); -//2022-04-04 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); +//2022-04-10 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { -//2022-04-04 logMessage("initialize:Generating Access Token"); +//2022-04-10 logMessage("initialize:Generating Access Token"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { -//2022-04-04 logMessage("initialize:No refresh token!"); +//2022-04-10 logMessage("initialize:No refresh token!"); } return; } _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); if (_vehicle_id == null) { -//2022-04-04 logMessage("initialize:Getting vehicle_id"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); } else { -//2022-04-04 logMessage("initialize:Asking vehicle data for " + _vehicle_id); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** } // Read pending web requests, and call appropriate web request function. @@ -78,12 +75,11 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -//2022-04-04 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); +//2022-04-10 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. if (pendingWebRequests["CityLocalTime"] != null) { -//logMessage("onTemporalEvent: doing city event"); makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { @@ -92,10 +88,10 @@ class BackgroundService extends Sys.ServiceDelegate { method(:onReceiveCityLocalTime) ); - // 2. Weather. } + + // 2. Weather. if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { -//logMessage("onTemporalEvent: doing weather event"); var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", @@ -123,24 +119,16 @@ class BackgroundService extends Sys.ServiceDelegate { method(:onReceiveOpenWeatherMapCurrent) ); - // 3. Tesla } + + // 3. Tesla if (pendingWebRequests["TeslaInfo"] != null && App.getApp().getProperty("Tesla") != null) { -//2022-04-04 logMessage("onTemporalEvent: WebRequest for vehicle id " + _vehicle_id); if (!Sys.getDeviceSettings().phoneConnected) { -//2022-04-04 logMessage("onTemporalEvent: No phone connected"); -// pendingWebRequests["TeslaInfo"] = null; return; } -//logMessage("onTemporalEvent:TeslaInfo with vehicle_id at " + _vehicle_id); - if (_vehicle_id) { -//logMessage("onTemporalEvent:Calling makeTeslaWebRequest to get vehicle data"); makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); - } else { -//logMessage("onTemporalEvent:NOT calling makeTeslaWebRequest for vehicle data because of null vehicle_id"); -// pendingWebRequests["TeslaInfo"] = null; } } } /* else { @@ -274,11 +262,14 @@ class BackgroundService extends Sys.ServiceDelegate { }); } +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** (:background_method) function onReceiveToken(responseCode, data) { var result; -//2022-04-04 logMessage("onReceiveToken responseCode is " + responseCode); +//2022-04-10 logMessage("onReceiveToken responseCode is " + responseCode); //logMessage("onReceiveToken data is " + data); if (responseCode == 200) { result = { "Token" => data }; @@ -292,7 +283,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveVehicles(responseCode, data) { var result; -//2022-04-04 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); +//2022-04-10 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { @@ -319,7 +310,7 @@ class BackgroundService extends Sys.ServiceDelegate { var precondEnabled = "N/A"; var sentryEnabled = "N/A"; -//2022-04-04 logMessage("onReceiveVehicleData responseCode is " + responseCode); +//2022-04-10 logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { results = data.get("response"); if (results != null) { @@ -350,11 +341,31 @@ class BackgroundService extends Sys.ServiceDelegate { result = { "httpErrorTesla" => responseCode }; } -//2022-04-04 logMessage("onReceiveVehicleData received " + result); - Bg.exit({ "TeslaInfo" => result }); } + (:background_method) + function makeTeslaWebPost(token, notify) { + var url = "https://auth.tesla.com/oauth2/v3/token"; + Communications.makeWebRequest( + url, + { + "grant_type" => "refresh_token", + "client_id" => "ownerapi", + "refresh_token" => token, + "scope" => "openid email offline_access" + }, + { + :method => Communications.HTTP_REQUEST_METHOD_POST, + :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + }, + notify + ); + } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** + (:background_method) function makeWebRequest(url, params, callback) { var options = { @@ -374,30 +385,9 @@ class BackgroundService extends Sys.ServiceDelegate { "Authorization" => _token}, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; -//logMessage("makeTeslaWebRequest with url='" + url + "' params='" + params + "' options='" + options + "'"); -//logMessage("url=" + url + "\nparams=" + params + "\noptions=" + options); Comms.makeWebRequest(url, params, options, callback); } - (:background_method) - function makeTeslaWebPost(token, notify) { - var url = "https://auth.tesla.com/oauth2/v3/token"; - Communications.makeWebRequest( - url, - { - "grant_type" => "refresh_token", - "client_id" => "ownerapi", - "refresh_token" => token, - "scope" => "openid email offline_access" - }, - { - :method => Communications.HTTP_REQUEST_METHOD_POST, - :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON - }, - notify - ); - } - (:debug) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 0bc6681b..876d1cfd 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -18,7 +18,6 @@ class CrystalApp extends App.AppBase { var mView; var mFieldTypes = new [3]; - var temporalRan = false; function initialize() { AppBase.initialize(); @@ -78,23 +77,10 @@ class CrystalApp extends App.AppBase { // Currently called on layout initialisation, when settings change, and on exiting sleep. (:background_method) function checkPendingWebRequests() { -//logMessage("checkPendingWebRequests:Begining"); // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. - - var lastTime = null; - var TeslaInfo = getProperty("TeslaInfo"); - var gotData = temporalRan; - temporalRan = false; - - if(Toybox.System has :ServiceDelegate) { - lastTime = Bg.getLastTemporalEventTime(); - } - -//logMessage("checkPendingWebRequests:lastBackgroundSchedule is " + lastBackgroundSchedule + " lastTime is " + (lastTime == null ? "null" : lastTime.value())); var location = Activity.getActivityInfo().currentLocation; if (location) { - //logMessage("Saving location"); location = location.toDegrees(); // Array of Doubles. gLocationLat = location[0].toFloat(); gLocationLng = location[1].toFloat(); @@ -115,14 +101,12 @@ class CrystalApp extends App.AppBase { gLocationLng = lng; } } - // logMessage(gLocationLat + ", " + gLocationLng); if (!(Sys has :ServiceDelegate)) { return; } var pendingWebRequests = getProperty("PendingWebRequests"); -//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:PendingWebRequests is '" + pendingWebRequests + "'"); } if (pendingWebRequests == null) { pendingWebRequests = {}; } @@ -161,9 +145,9 @@ class CrystalApp extends App.AppBase { var owmKeyOverride = getProperty("OWMKeyOverride"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { -//logMessage("Using Garmin Weather so skipping this"); +//2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); } else { -//logMessage("Using OpenWeatherMap"); +//2022-04-10 logMessage("Using OpenWeatherMap"); var owmCurrent = getProperty("OpenWeatherMapCurrent"); // No existing data. @@ -171,7 +155,6 @@ class CrystalApp extends App.AppBase { pendingWebRequests["OpenWeatherMapCurrent"] = true; // Successfully received weather data. } else if (owmCurrent["cod"] == 200) { -//logMessage(owmCurrent["dt"]); // Existing data is older than 30 mins. // TODO: Consider requesting weather at sunrise/sunset to update weather icon. if ((Time.now().value() > (owmCurrent["dt"] + 1800)) || @@ -188,18 +171,14 @@ class CrystalApp extends App.AppBase { } // 3. Tesla: +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** if (getProperty("Tesla") != null) { -//logMessage("checkPendingWebRequests in Tesla code"); -//if (/*gotData &&*/ TeslaInfo != null) { logMessage("checkPendingWebRequests:TeslaInfo=" + TeslaInfo.toString().substring(0,60) + " ..."); } - - // No existing data. - if (TeslaInfo == null) { -//if (gotData) { logMessage("checkPendingWebRequests:checkPendingWebRequests:Asking first read"); } - - pendingWebRequests["TeslaInfo"] = true; - - // We got something, check what it is - } else { + var TeslaInfo = getProperty("TeslaInfo"); + if (TeslaInfo == null) { // We're not doing Tesla stuff so why asking for it, clear that + pendingWebRequests["TeslaInfo"] = false; + } else { // We're doing Tesla stuff var batterie_level = null; var charging_state = null; var batterie_stale = false; @@ -210,7 +189,6 @@ class CrystalApp extends App.AppBase { // Other errors are silent for now var result = TeslaInfo["httpErrorTesla"]; if (result != null) { -//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Got http error '" + result + "'"); } if (result == 400 || result == 401) { // Our token has expired, refresh it setProperty("TeslaAccessToken", null); // Try to get a new vehicleID batterie_stale = true; @@ -229,8 +207,6 @@ class CrystalApp extends App.AppBase { // Check if our access token was refreshed. If so, store the new access and refresh tokens result = TeslaInfo["Token"]; if (result != null) { -//logMessage("checkPendingWebRequests:Got token data '" + result + "'"); -//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Got token data"); } var accessToken = result["access_token"]; var refreshToken = result["refresh_token"]; var expires_in = result["expires_in"]; @@ -239,9 +215,6 @@ class CrystalApp extends App.AppBase { if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem setProperty("TeslaRefreshToken", refreshToken); } - else { -//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:But missing the refresh token '" + result + "'"); } - } setProperty("TeslaTokenExpiresIn", expires_in); setProperty("TeslaTokenCreatedAt", created_at); @@ -276,17 +249,13 @@ class CrystalApp extends App.AppBase { var vehicle_id = TeslaInfo["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { -//if (gotData) { logMessage("checkPendingWebRequests:Saving '" + vehicle_id +"' as vehicle_id"); } setProperty("TeslaVehicleID", vehicle_id.toString()); } else { -//if (gotData) { logMessage("checkPendingWebRequests: vehicle_id we got was 0"); } setProperty("TeslaVehicleID", null); batterie_stale = true; batterie_level = "N/A"; } } else { -//if (gotData) { logMessage("checkPendingWebRequests: TeslaInfo[vehicle_id] is null, keeping original value. If needed, it will generate a 404 whih will reset it"); } -// setProperty("TeslaVehicleID", null); batterie_stale = true; } @@ -299,8 +268,6 @@ class CrystalApp extends App.AppBase { setProperty("TeslaError", null); } else { -//if (gotData) { logMessage("checkPendingWebRequests:batterie_level is null"/* clearing our TeslaBatterieLevel property"*/); } -// setProperty("TeslaBatterieLevel", null); setProperty("TeslaBatterieStale", true); setProperty("TeslaError", null); } @@ -316,19 +283,19 @@ class CrystalApp extends App.AppBase { else { pendingWebRequests.remove("TeslaInfo"); } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** // If there are any pending requests and we can do background process if (Toybox.System has :ServiceDelegate && pendingWebRequests.keys().size() > 0) { // Register for background temporal event as soon as possible. -// var lastTime = Bg.getLastTemporalEventTime(); + var lastTime = Bg.getLastTemporalEventTime(); if (lastTime) { // Events scheduled for a time in the past trigger immediately. var nextTime = lastTime.add(new Time.Duration(5 * 60)); -//var clockTime = Gregorian.info(nextTime, Time.FORMAT_MEDIUM); -//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Scheduling for " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d")); } Bg.registerForTemporalEvent(nextTime); } else { -//2022-04-04 if (gotData) { logMessage("checkPendingWebRequests:Scheduling now"); } Bg.registerForTemporalEvent(Time.now()); } } @@ -347,11 +314,9 @@ class CrystalApp extends App.AppBase { // pendingWebRequests keys. (:background_method) function onBackgroundData(data) { -//2022-04-04 logMessage("onBackgroundData:received '" + data + "'"); +//2022-04-10 logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = getProperty("PendingWebRequests"); -//2022-04-04 logMessage("onBackgroundData:pendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests == null) { -//logMessage("onBackgroundData: called with no pending web requests!"); pendingWebRequests = {}; } @@ -359,22 +324,17 @@ class CrystalApp extends App.AppBase { var storedData = getProperty(type); var receivedData = data[type]; // The actual data received: strip away type key. - // No value in showing any HTTP error to the user, so no need to modify stored data. - // Leave pendingWebRequests flag set, and simply return early. - if (receivedData["httpError"]) { - return; - } - - // New data received: clear pendingWebRequests flag and overwrite stored data. - storedData = receivedData; - pendingWebRequests.remove(type); - setProperty("PendingWebRequests", pendingWebRequests); - setProperty(type, storedData); + // Do process the data if what we got was an error + if (receivedData["httpError"] == null) { + // New data received: clear pendingWebRequests flag and overwrite stored data. + storedData = receivedData; + pendingWebRequests.remove(type); + setProperty("PendingWebRequests", pendingWebRequests); + setProperty(type, storedData); + + checkPendingWebRequests(); // We just got new data, process them right away before displaying + } - temporalRan = true; - - checkPendingWebRequests(); // We just got new data, process them right away before displaying - Ui.requestUpdate(); } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index ee099114..b1d8e9b1 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -103,6 +103,9 @@ function writeBatteryLevel(dc, x, y, width, height, type) { dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); } +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** else { // Tesla stuff var value; var batteryStale = false; @@ -214,6 +217,9 @@ function writeBatteryLevel(dc, x, y, width, height, type) { dc.drawText(x - (width / 2), y - height, gNormalFont, value.toNumber().format(INTEGER_FORMAT) + suffixe, Graphics.TEXT_JUSTIFY_LEFT); } } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** } class CrystalView extends Ui.WatchFace { @@ -263,18 +269,18 @@ class CrystalView extends Ui.WatchFace { // Reread Weather method function rereadWeatherMethod() { var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); -//logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); +//2022-04-10 logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { if (Toybox has :Weather) { mHasGarminWeather = true; -//logMessage("Does support Weather"); +//2022-04-10 logMessage("Does support Weather"); } else { mHasGarminWeather = false; -//logMessage("Does not support Weather"); +//2022-04-10 logMessage("Does not support Weather"); } } else { mHasGarminWeather = false; -//logMessage("Using OpenWeatherMap"); +//2022-04-10 logMessage("Using OpenWeatherMap"); } } @@ -331,7 +337,6 @@ class CrystalView extends Ui.WatchFace { updateHoursMinutesColours(); if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. -//logMessage("onSettingsChanged:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } @@ -353,11 +358,14 @@ class CrystalView extends Ui.WatchFace { var icon = "01"; var day = "d"; -// var myLocation = new Position.Location({:latitude => gLocationLat, :longitude => gLocationLng, :format => :degrees }); var myLocation = weather.observationLocationPosition; var myLocationArray = myLocation.toDegrees(); -// var now = Time.now(); - var now = weather.observationTime; + + // So the OWM code knows our location since it's background code won't run to fetch it + gLocationLat = myLocationArray[0]; + gLocationLng = myLocationArray[1]; + + var now = Time.now(); if (Toybox.Weather has :getSunrise) { //logMessage("We have sunrise and sunset routines!"); var sunrise = Weather.getSunrise(myLocation, now); @@ -375,7 +383,7 @@ class CrystalView extends Ui.WatchFace { var sunsettime = Gregorian.info(sunset, Time.FORMAT_MEDIUM); var sunriseStr = sunrisetime.day + " " + sunrisetime.hour + ":" + sunrisetime.min.format("%02d") + ":" + sunrisetime.sec.format("%02d"); var sunsetStr = sunsettime.day + " " + sunsettime.hour + ":" + sunsettime.min.format("%02d") + ":" + sunsettime.sec.format("%02d"); - logMessage("At=" + nowStr); + logMessage("For=" + nowStr); logMessage("Sunrise=" + sunriseStr); logMessage("Sunset=" + sunsetStr); logMessage("Since sunrize " + sinceSunrise); @@ -406,18 +414,17 @@ class CrystalView extends Ui.WatchFace { } - now = Time.now().value(); if (condition < 53) { icon = (mGarminToOWM[condition]).format("%02d") + day; //logMessage("icon=" + icon); } - result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => now, "lat" => myLocationArray[0], "lon" => myLocationArray[1]}; + result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => weather.observationTime.value(), "lat" => myLocationArray[0], "lon" => myLocationArray[1]}; +//2022-04-10 logMessage("Weather at " + weather.observationLocationName + " is " + result); } else { - now = Time.now().value(); - result = { "cod" => 408, "dt" => now }; + result = null; +//2022-04-10 logMessage("No weather data, returning null"); } App.getApp().setProperty("OpenWeatherMapCurrent", result); -//logMessage("Weather at " + weather.observationLocationName + " is " + result); } // Select normal font, based on whether time zone feature is being used. @@ -426,7 +433,7 @@ class CrystalView extends Ui.WatchFace { function updateNormalFont() { var city = App.getApp().getProperty("LocalTimeInCity"); -//logMessage("which font " + ((city != null) && (city.length() > 0))); + // #78 Setting with value of empty string may cause corresponding property to be null. gNormalFont = Ui.loadResource(((city != null) && (city.length() > 0)) ? Rez.Fonts.NormalFontCities : Rez.Fonts.NormalFont); @@ -733,7 +740,7 @@ class CrystalView extends Ui.WatchFace { mDrawables[:MoveBar].setFullWidth(hideSeconds); } } - +/* function type_name(obj) { if (obj instanceof Toybox.Lang.Number) { return "Number"; @@ -772,4 +779,5 @@ function type_name(obj) { } else { return "???"; } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/source/DataFields.mc b/source/DataFields.mc index f9e7a960..32c0d7ca 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -566,7 +566,6 @@ class DataFields extends Ui.Drawable { // Stored weather data available. } else if (weather != null) { - // FIELD_TYPE_WEATHER. if (type == FIELD_TYPE_WEATHER) { weatherValue = weather["temp"]; // Celcius. @@ -586,7 +585,7 @@ class DataFields extends Ui.Drawable { // Awaiting response. } else if ((App.getApp().getProperty("PendingWebRequests") != null) && - App.getApp().getProperty("PendingWebRequests")["OpenWeatherMapCurrent"]) { + App.getApp().getProperty("PendingWebRequests")["OpenWeatherMapCurrent"] != null) { value = "..."; } diff --git a/source/Indicators.mc b/source/Indicators.mc index 223d4a9b..38afe004 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -40,12 +40,18 @@ class Indicators extends Ui.Drawable { mIndicator2Type = App.getApp().getProperty("Indicator2Type"); mIndicator3Type = App.getApp().getProperty("Indicator3Type"); +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** if (mIndicator1Type == 6 || mIndicator2Type == 6 || mIndicator3Type == 6) { App.getApp().setProperty("Tesla", true); //logMessage("onSettingsChanged:Doing Tesla!"); } else { App.getApp().setProperty("Tesla", null); } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** } function draw(dc) { @@ -104,10 +110,16 @@ class Indicators extends Ui.Drawable { return; } +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** if (indicatorType == 6 /* INDICATOR_TYPE_TESLA */) { // We're reusing the watch batterie indicator to show the Tesla's batterie level writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 1); return; } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** // Show notifications icon if connected and there are notifications, bluetoothicon otherwise. var settings = Sys.getDeviceSettings(); From 8386e05dcc56f513cefe7c6f34a0d1a31a5eddce Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 15 Apr 2022 19:48:09 -0400 Subject: [PATCH 039/220] Update DataFields.mc --- source/DataFields.mc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/DataFields.mc b/source/DataFields.mc index 32c0d7ca..b4214aef 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -33,6 +33,8 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_PULSE_OX } +var gAltitude = null; // To keep our altitude in case we looe GPS signal + class DataFields extends Ui.Drawable { private var mLeft; @@ -448,13 +450,18 @@ class DataFields extends Ui.Drawable { activityInfo = Activity.getActivityInfo(); altitude = activityInfo.altitude; if ((altitude == null) && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getElevationHistory)) { - sample = SensorHistory.getElevationHistory({ :period => 1, :order => SensorHistory.ORDER_NEWEST_FIRST }) - .next(); + sample = SensorHistory.getElevationHistory({ :period => 1, :order => SensorHistory.ORDER_NEWEST_FIRST }).next(); if ((sample != null) && (sample.data != null)) { altitude = sample.data; } } - if (altitude != null) { + + if (altitude != null || gAltitude != null) { + if (altitude == null) { // If we didn't get an altitude this time, grab the saved one + altitude = gAltitude; + } else { // We got altitude info, store it in case we lose it + gAltitude = altitude; + } // Metres (no conversion necessary). if (settings.elevationUnits == System.UNIT_METRIC) { From e027395e9754e16980203c8734407c4a2bd5888d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 15 Apr 2022 19:48:09 -0400 Subject: [PATCH 040/220] Update to altitude code to keep previous value if GPS is lost --- source/DataFields.mc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/DataFields.mc b/source/DataFields.mc index 32c0d7ca..b4214aef 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -33,6 +33,8 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_PULSE_OX } +var gAltitude = null; // To keep our altitude in case we looe GPS signal + class DataFields extends Ui.Drawable { private var mLeft; @@ -448,13 +450,18 @@ class DataFields extends Ui.Drawable { activityInfo = Activity.getActivityInfo(); altitude = activityInfo.altitude; if ((altitude == null) && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getElevationHistory)) { - sample = SensorHistory.getElevationHistory({ :period => 1, :order => SensorHistory.ORDER_NEWEST_FIRST }) - .next(); + sample = SensorHistory.getElevationHistory({ :period => 1, :order => SensorHistory.ORDER_NEWEST_FIRST }).next(); if ((sample != null) && (sample.data != null)) { altitude = sample.data; } } - if (altitude != null) { + + if (altitude != null || gAltitude != null) { + if (altitude == null) { // If we didn't get an altitude this time, grab the saved one + altitude = gAltitude; + } else { // We got altitude info, store it in case we lose it + gAltitude = altitude; + } // Metres (no conversion necessary). if (settings.elevationUnits == System.UNIT_METRIC) { From b68f22ca514ae8f217cc57b1c165874e9fdf8d2e Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 15 Apr 2022 19:51:45 -0400 Subject: [PATCH 041/220] Removal of Garmin Swim 2 --- manifest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/manifest.xml b/manifest.xml index 3d029af9..c46872ef 100644 --- a/manifest.xml +++ b/manifest.xml @@ -45,7 +45,6 @@ - From d1c5328da1f5bd9df64659c473159bc134e38536 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 16 Apr 2022 23:36:39 -0400 Subject: [PATCH 042/220] Second attempt at fixing the Altitude code so it stays put, even if the watch face loses focus. Also fix a very rare occurrence of a crash when displaying seconds and the area where the seconds are to be displayed is overwritten by the move bar --- source/DataFields.mc | 17 ++++++++--------- source/ThickThinTime.mc | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/source/DataFields.mc b/source/DataFields.mc index b4214aef..0beb6d70 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -33,8 +33,6 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_PULSE_OX } -var gAltitude = null; // To keep our altitude in case we looe GPS signal - class DataFields extends Ui.Drawable { private var mLeft; @@ -449,20 +447,21 @@ class DataFields extends Ui.Drawable { // devices. activityInfo = Activity.getActivityInfo(); altitude = activityInfo.altitude; + if ((altitude == null) && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getElevationHistory)) { sample = SensorHistory.getElevationHistory({ :period => 1, :order => SensorHistory.ORDER_NEWEST_FIRST }).next(); if ((sample != null) && (sample.data != null)) { altitude = sample.data; } } - - if (altitude != null || gAltitude != null) { - if (altitude == null) { // If we didn't get an altitude this time, grab the saved one - altitude = gAltitude; - } else { // We got altitude info, store it in case we lose it - gAltitude = altitude; - } + if (altitude == null) { // If we didn't get an altitude this time, grab the saved one + altitude = App.getApp().getProperty("LastAltitude"); + } else { // We got altitude info, store it in case we lose it + App.getApp().setProperty("LastAltitude", altitude); + } + + if (altitude != null) { // If we didn't get an altitude this time, grab the saved one // Metres (no conversion necessary). if (settings.elevationUnits == System.UNIT_METRIC) { unit = "m"; diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index c8f3d65f..314a7ceb 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -115,7 +115,7 @@ class ThickThinTime extends Ui.Drawable { // If isPartialUpdate flag is set to true, strictly limit the updated screen area: set clip rectangle before clearing old text // and drawing new. Clipping rectangle should not change between seconds. function drawSeconds(dc, isPartialUpdate) { - if (mHideSeconds) { + if (mHideSeconds || mSecondsClipRectX == null || mSecondsClipXAdjust == null || mSecondsClipRectY == null || mSecondsClipRectWidth == null || mSecondsClipRectHeight == null) { // Fixes a crash when null value are found. WHy it get there first, I don't kmow. return; } @@ -123,7 +123,7 @@ class ThickThinTime extends Ui.Drawable { var seconds = clockTime.sec.format("%02d"); if (isPartialUpdate) { - + dc.setClip( mSecondsClipRectX + mSecondsClipXAdjust, mSecondsClipRectY, From 0eeddc1cf09601788e2ca20c239d8ab0526c700d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 18 Apr 2022 09:03:13 -0400 Subject: [PATCH 043/220] Fixed the seconds not displaying by code introduced to fix a crash on a simulated FR55 when in low power mode and seconds should be displayed The real cause of the error is in the 208x208 resource file here With the variables commented out and the FR55 supporting 'partial update', it crashes. No one complained about the frozen seconds in low power mode so I'm leaving it like that for the time being. Might fix later. --- source/ThickThinTime.mc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index 314a7ceb..68bcdf73 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -115,15 +115,18 @@ class ThickThinTime extends Ui.Drawable { // If isPartialUpdate flag is set to true, strictly limit the updated screen area: set clip rectangle before clearing old text // and drawing new. Clipping rectangle should not change between seconds. function drawSeconds(dc, isPartialUpdate) { - if (mHideSeconds || mSecondsClipRectX == null || mSecondsClipXAdjust == null || mSecondsClipRectY == null || mSecondsClipRectWidth == null || mSecondsClipRectHeight == null) { // Fixes a crash when null value are found. WHy it get there first, I don't kmow. + if (mHideSeconds) { return; } - + var clockTime = Sys.getClockTime(); var seconds = clockTime.sec.format("%02d"); if (isPartialUpdate) { - + if (mSecondsClipRectX == null || mSecondsClipXAdjust == null || mSecondsClipRectY == null || mSecondsClipRectWidth == null || mSecondsClipRectHeight == null) { // Fixes a crash when null value are found. WHy it get there first, I don't kmow. + return; + } + dc.setClip( mSecondsClipRectX + mSecondsClipXAdjust, mSecondsClipRectY, From 8c3da6713d894aa3c0aa6c9b994ba0d0b39db971 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 18 Apr 2022 12:06:08 -0400 Subject: [PATCH 044/220] Add floors climbed as a data field --- resources-round-208x208/fonts/fonts.xml | 2 +- resources-round-280x280/fonts/fonts.xml | 2 +- resources-round-360x360/fonts/fonts.xml | 2 +- resources-round-390x390/fonts/fonts.xml | 2 +- resources-round-416x416/fonts/fonts.xml | 2 +- resources/fonts/fonts.xml | 2 +- resources/settings/settings.xml | 3 +++ source/DataFields.mc | 15 ++++++++++++++- 8 files changed, 23 insertions(+), 7 deletions(-) diff --git a/resources-round-208x208/fonts/fonts.xml b/resources-round-208x208/fonts/fonts.xml index 6c1cc189..ab57a970 100644 --- a/resources-round-208x208/fonts/fonts.xml +++ b/resources-round-208x208/fonts/fonts.xml @@ -4,7 +4,7 @@ - + diff --git a/resources-round-280x280/fonts/fonts.xml b/resources-round-280x280/fonts/fonts.xml index d200adc1..60e57e5c 100644 --- a/resources-round-280x280/fonts/fonts.xml +++ b/resources-round-280x280/fonts/fonts.xml @@ -3,7 +3,7 @@ - + diff --git a/resources-round-360x360/fonts/fonts.xml b/resources-round-360x360/fonts/fonts.xml index f5b853b0..f0c170a3 100644 --- a/resources-round-360x360/fonts/fonts.xml +++ b/resources-round-360x360/fonts/fonts.xml @@ -5,7 +5,7 @@ - + diff --git a/resources-round-390x390/fonts/fonts.xml b/resources-round-390x390/fonts/fonts.xml index b7237873..e8da44d3 100644 --- a/resources-round-390x390/fonts/fonts.xml +++ b/resources-round-390x390/fonts/fonts.xml @@ -5,7 +5,7 @@ - + diff --git a/resources-round-416x416/fonts/fonts.xml b/resources-round-416x416/fonts/fonts.xml index ea9ed613..4790b641 100644 --- a/resources-round-416x416/fonts/fonts.xml +++ b/resources-round-416x416/fonts/fonts.xml @@ -5,7 +5,7 @@ - + diff --git a/resources/fonts/fonts.xml b/resources/fonts/fonts.xml index 54d83184..ec58fd38 100644 --- a/resources/fonts/fonts.xml +++ b/resources/fonts/fonts.xml @@ -3,7 +3,7 @@ - + diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 68958f6b..b1372caa 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -89,6 +89,7 @@ @Strings.Weather @Strings.Humidity @Strings.PulseOx + @Strings.FloorsClimbed @@ -109,6 +110,7 @@ @Strings.Weather @Strings.Humidity @Strings.PulseOx + @Strings.FloorsClimbed @@ -129,6 +131,7 @@ @Strings.Weather @Strings.Humidity @Strings.PulseOx + @Strings.FloorsClimbed diff --git a/source/DataFields.mc b/source/DataFields.mc index 0beb6d70..ab9d6252 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -30,7 +30,8 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_WEATHER, FIELD_TYPE_PRESSURE, FIELD_TYPE_HUMIDITY, - FIELD_TYPE_PULSE_OX + FIELD_TYPE_PULSE_OX, + FIELD_FLOOR_CLIMBED } class DataFields extends Ui.Drawable { @@ -318,6 +319,7 @@ class DataFields extends Ui.Drawable { FIELD_TYPE_PRESSURE => "@", FIELD_TYPE_HUMIDITY => "A", FIELD_TYPE_PULSE_OX => "B", // SG Addition + FIELD_FLOOR_CLIMBED => "1", // SG Addition }[fieldType]; } @@ -371,6 +373,17 @@ class DataFields extends Ui.Drawable { switch (type) { // SG Addition + case FIELD_FLOOR_CLIMBED: + var info = ActivityMonitor.getInfo(); + if (info has :floorsClimbed) { + var climbed = info.floorsClimbed; + var goal = info.floorsClimbedGoal; + if (climbed != null && goal != null) { + value = climbed.format(INTEGER_FORMAT) + "/" + goal.format(INTEGER_FORMAT); + } + } + break; + // SG Addition case FIELD_TYPE_PULSE_OX: activityInfo = Activity.getActivityInfo(); sample = activityInfo != null and activityInfo has :currentOxygenSaturation ? activityInfo.currentOxygenSaturation : null; From eaa257486ad9c185b1d2738cd67f68d2c71029c7 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 18 Apr 2022 20:30:01 -0400 Subject: [PATCH 045/220] Fix the '/' in the titillium-web-semibold-28 font in 280x280 plus added the '/' to the NormalFontCities --- resources-round-208x208/fonts/fonts.xml | 2 +- resources-round-280x280/fonts/fonts.xml | 2 +- .../fonts/titillium-web-semibold-28.fnt | 395 ++++++++++++++---- .../fonts/titillium-web-semibold-28_0.png | Bin 9615 -> 9919 bytes resources-round-360x360/fonts/fonts.xml | 2 +- resources-round-390x390/fonts/fonts.xml | 2 +- resources-round-416x416/fonts/fonts.xml | 2 +- resources/fonts/fonts.xml | 2 +- 8 files changed, 323 insertions(+), 84 deletions(-) diff --git a/resources-round-208x208/fonts/fonts.xml b/resources-round-208x208/fonts/fonts.xml index ab57a970..7fc6ca69 100644 --- a/resources-round-208x208/fonts/fonts.xml +++ b/resources-round-208x208/fonts/fonts.xml @@ -2,7 +2,7 @@ - + diff --git a/resources-round-280x280/fonts/fonts.xml b/resources-round-280x280/fonts/fonts.xml index 60e57e5c..23121099 100644 --- a/resources-round-280x280/fonts/fonts.xml +++ b/resources-round-280x280/fonts/fonts.xml @@ -4,7 +4,7 @@ - + diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt index 4fd405ea..2ea69189 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt +++ b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt @@ -1,102 +1,103 @@ info face="Titillium Web SemiBold" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=43 base=32 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-semibold-28_0.png" -chars count=111 +chars count=112 char id=32 x=252 y=0 width=3 height=1 xoffset=-1 yoffset=42 xadvance=6 page=0 chnl=15 -char id=33 x=175 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=33 x=191 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=37 x=0 y=53 width=16 height=21 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 -char id=39 x=251 y=107 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 -char id=44 x=29 y=134 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 -char id=45 x=36 y=134 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 -char id=46 x=249 y=44 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 -char id=48 x=173 y=72 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=49 x=224 y=92 width=10 height=19 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 -char id=50 x=209 y=92 width=14 height=19 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=51 x=91 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=52 x=193 y=92 width=15 height=19 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=53 x=76 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=54 x=190 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=55 x=134 y=94 width=13 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=56 x=156 y=72 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=57 x=206 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=58 x=209 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 -char id=63 x=162 y=93 width=12 height=20 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 +char id=39 x=45 y=134 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 +char id=44 x=38 y=134 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 +char id=45 x=50 y=134 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 +char id=46 x=250 y=65 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 +char id=47 x=155 y=50 width=12 height=21 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 +char id=48 x=123 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=49 x=234 y=92 width=10 height=19 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 +char id=50 x=219 y=92 width=14 height=19 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=51 x=77 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=52 x=203 y=93 width=15 height=19 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=53 x=92 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=54 x=224 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=55 x=136 y=94 width=13 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=56 x=106 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=57 x=16 y=96 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=58 x=219 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 +char id=63 x=178 y=93 width=12 height=20 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 char id=65 x=36 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 -char id=66 x=139 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=67 x=126 y=50 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=68 x=122 y=73 width=16 height=20 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=69 x=61 y=94 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=70 x=46 y=96 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=71 x=50 y=51 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=72 x=18 y=75 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 -char id=73 x=187 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 +char id=66 x=191 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=67 x=66 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=68 x=157 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=69 x=107 y=94 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=70 x=32 y=96 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=71 x=34 y=53 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=72 x=54 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 +char id=73 x=249 y=23 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 char id=74 x=244 y=0 width=7 height=22 xoffset=0 yoffset=12 xadvance=8 page=0 chnl=15 -char id=75 x=222 y=71 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 -char id=76 x=106 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=13 page=0 chnl=15 -char id=77 x=215 y=50 width=21 height=20 xoffset=1 yoffset=12 xadvance=24 page=0 chnl=15 -char id=78 x=237 y=49 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 +char id=75 x=208 y=71 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 +char id=76 x=122 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=13 page=0 chnl=15 +char id=77 x=228 y=50 width=21 height=20 xoffset=1 yoffset=12 xadvance=24 page=0 chnl=15 +char id=78 x=0 y=75 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 char id=79 x=231 y=27 width=17 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=80 x=54 y=73 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=81 x=0 y=28 width=17 height=24 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=82 x=71 y=73 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=83 x=34 y=53 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=84 x=238 y=70 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=80 x=140 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=81 x=18 y=28 width=17 height=24 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=82 x=174 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=83 x=50 y=51 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=84 x=0 y=96 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 char id=85 x=17 y=53 width=16 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=86 x=0 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 -char id=87 x=189 y=50 width=25 height=20 xoffset=0 yoffset=12 xadvance=26 page=0 chnl=15 -char id=88 x=88 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 -char id=89 x=105 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=90 x=0 y=96 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=97 x=53 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 +char id=86 x=18 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 +char id=87 x=202 y=50 width=25 height=20 xoffset=0 yoffset=12 xadvance=26 page=0 chnl=15 +char id=88 x=72 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 +char id=89 x=89 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=90 x=240 y=71 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=97 x=38 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 char id=98 x=96 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 char id=99 x=82 y=115 width=12 height=16 xoffset=0 yoffset=17 xadvance=12 page=0 chnl=15 -char id=100 x=111 y=51 width=14 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=101 x=38 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 -char id=102 x=168 y=50 width=10 height=21 xoffset=0 yoffset=11 xadvance=10 page=0 chnl=15 +char id=100 x=126 y=50 width=14 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=101 x=23 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 +char id=102 x=181 y=50 width=10 height=21 xoffset=0 yoffset=11 xadvance=10 page=0 chnl=15 char id=103 x=52 y=28 width=15 height=22 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=104 x=148 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=105 x=249 y=23 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=104 x=150 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=105 x=250 y=44 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=106 x=100 y=0 width=8 height=27 xoffset=-2 yoffset=12 xadvance=7 page=0 chnl=15 -char id=107 x=120 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=14 page=0 chnl=15 -char id=108 x=181 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=107 x=164 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=14 page=0 chnl=15 +char id=108 x=197 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=109 x=95 y=115 width=21 height=15 xoffset=1 yoffset=17 xadvance=23 page=0 chnl=15 char id=110 x=117 y=115 width=13 height=15 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=111 x=23 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=111 x=53 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 char id=112 x=81 y=51 width=14 height=21 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=113 x=66 y=51 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=114 x=246 y=91 width=9 height=15 xoffset=1 yoffset=17 xadvance=10 page=0 chnl=15 +char id=113 x=111 y=51 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=114 x=145 y=115 width=9 height=15 xoffset=1 yoffset=17 xadvance=10 page=0 chnl=15 char id=115 x=68 y=115 width=13 height=16 xoffset=0 yoffset=17 xadvance=13 page=0 chnl=15 -char id=116 x=235 y=92 width=10 height=19 xoffset=0 yoffset=14 xadvance=10 page=0 chnl=15 +char id=116 x=245 y=92 width=10 height=19 xoffset=0 yoffset=14 xadvance=10 page=0 chnl=15 char id=117 x=131 y=115 width=13 height=15 xoffset=1 yoffset=18 xadvance=15 page=0 chnl=15 -char id=118 x=167 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 -char id=119 x=145 y=115 width=21 height=14 xoffset=0 yoffset=18 xadvance=22 page=0 chnl=15 -char id=120 x=182 y=114 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=121 x=16 y=96 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 -char id=122 x=196 y=112 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=176 x=18 y=134 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 +char id=118 x=177 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=119 x=155 y=114 width=21 height=14 xoffset=0 yoffset=18 xadvance=22 page=0 chnl=15 +char id=120 x=192 y=114 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=121 x=47 y=96 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=122 x=206 y=113 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=176 x=27 y=134 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 char id=193 x=109 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 char id=196 x=127 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 -char id=197 x=18 y=28 width=17 height=24 xoffset=0 yoffset=8 xadvance=17 page=0 chnl=15 +char id=197 x=0 y=28 width=17 height=24 xoffset=0 yoffset=8 xadvance=17 page=0 chnl=15 char id=201 x=194 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 char id=205 x=235 y=0 width=8 height=26 xoffset=0 yoffset=6 xadvance=8 page=0 chnl=15 char id=206 x=224 y=0 width=10 height=26 xoffset=-1 yoffset=6 xadvance=8 page=0 chnl=15 -char id=214 x=18 y=0 width=17 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=216 x=0 y=0 width=17 height=27 xoffset=1 yoffset=9 xadvance=18 page=0 chnl=15 +char id=214 x=0 y=0 width=17 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=216 x=18 y=0 width=17 height=27 xoffset=1 yoffset=9 xadvance=18 page=0 chnl=15 char id=218 x=36 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=225 x=188 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=227 x=68 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=225 x=173 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=227 x=188 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 char id=228 x=158 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=229 x=173 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=229 x=98 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 char id=230 x=0 y=117 width=22 height=16 xoffset=0 yoffset=17 xadvance=22 page=0 chnl=15 -char id=232 x=143 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=233 x=128 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=237 x=179 y=50 width=9 height=21 xoffset=0 yoffset=11 xadvance=7 page=0 chnl=15 +char id=232 x=83 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=233 x=68 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=237 x=192 y=50 width=9 height=21 xoffset=0 yoffset=11 xadvance=7 page=0 chnl=15 char id=240 x=36 y=28 width=15 height=22 xoffset=0 yoffset=11 xadvance=16 page=0 chnl=15 char id=241 x=141 y=50 width=13 height=21 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 char id=243 x=113 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=244 x=98 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=246 x=83 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=248 x=31 y=96 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 +char id=244 x=128 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=246 x=143 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=248 x=62 y=94 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 char id=251 x=203 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 char id=252 x=217 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 char id=268 x=85 y=0 width=14 height=27 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 @@ -106,14 +107,252 @@ char id=346 x=69 y=0 width=15 height=27 xoffset=0 yoffset=6 char id=352 x=53 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=377 x=178 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=381 x=162 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 -char id=382 x=155 y=50 width=12 height=21 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 -char id=8304 x=215 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8308 x=224 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8309 x=233 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8311 x=242 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8312 x=0 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8313 x=9 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -kernings count=280 +char id=382 x=168 y=50 width=12 height=21 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 +char id=8304 x=234 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8308 x=243 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8309 x=0 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8311 x=9 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8312 x=18 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8313 x=225 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +kernings count=518 +kerning first=39 second=47 amount=-2 +kerning first=44 second=86 amount=-1 +kerning first=44 second=118 amount=-1 +kerning first=45 second=86 amount=-1 +kerning first=45 second=88 amount=-1 +kerning first=45 second=120 amount=-1 +kerning first=46 second=86 amount=-1 +kerning first=46 second=118 amount=-1 +kerning first=47 second=47 amount=-8 +kerning first=47 second=65 amount=-1 +kerning first=47 second=97 amount=-1 +kerning first=47 second=99 amount=-1 +kerning first=47 second=100 amount=-1 +kerning first=47 second=101 amount=-1 +kerning first=47 second=103 amount=-1 +kerning first=47 second=109 amount=-1 +kerning first=47 second=110 amount=-1 +kerning first=47 second=111 amount=-1 +kerning first=47 second=112 amount=-1 +kerning first=47 second=113 amount=-1 +kerning first=47 second=114 amount=-1 +kerning first=47 second=115 amount=-1 +kerning first=47 second=117 amount=-1 +kerning first=47 second=193 amount=-1 +kerning first=47 second=196 amount=-1 +kerning first=47 second=197 amount=-1 +kerning first=47 second=225 amount=-1 +kerning first=47 second=227 amount=-1 +kerning first=47 second=228 amount=-1 +kerning first=47 second=229 amount=-1 +kerning first=47 second=230 amount=-1 +kerning first=47 second=232 amount=-1 +kerning first=47 second=233 amount=-1 +kerning first=47 second=241 amount=-1 +kerning first=47 second=243 amount=-1 +kerning first=47 second=244 amount=-1 +kerning first=47 second=246 amount=-1 +kerning first=47 second=248 amount=-1 +kerning first=47 second=251 amount=-1 +kerning first=47 second=252 amount=-1 +kerning first=65 second=63 amount=-1 +kerning first=65 second=86 amount=-1 +kerning first=66 second=89 amount=-1 +kerning first=68 second=88 amount=-1 +kerning first=70 second=44 amount=-2 +kerning first=70 second=46 amount=-2 +kerning first=70 second=47 amount=-1 +kerning first=70 second=65 amount=-1 +kerning first=70 second=97 amount=-1 +kerning first=70 second=100 amount=-1 +kerning first=70 second=103 amount=-1 +kerning first=70 second=109 amount=-1 +kerning first=70 second=110 amount=-1 +kerning first=70 second=112 amount=-1 +kerning first=70 second=113 amount=-1 +kerning first=70 second=114 amount=-1 +kerning first=70 second=193 amount=-1 +kerning first=70 second=196 amount=-1 +kerning first=70 second=197 amount=-1 +kerning first=70 second=225 amount=-1 +kerning first=70 second=227 amount=-1 +kerning first=70 second=228 amount=-1 +kerning first=70 second=229 amount=-1 +kerning first=70 second=230 amount=-1 +kerning first=70 second=241 amount=-1 +kerning first=75 second=118 amount=-1 +kerning first=76 second=86 amount=-2 +kerning first=76 second=118 amount=-1 +kerning first=79 second=88 amount=-1 +kerning first=80 second=44 amount=-2 +kerning first=80 second=46 amount=-2 +kerning first=80 second=47 amount=-1 +kerning first=80 second=65 amount=-1 +kerning first=80 second=89 amount=-1 +kerning first=80 second=193 amount=-1 +kerning first=80 second=196 amount=-1 +kerning first=80 second=197 amount=-1 +kerning first=81 second=88 amount=-1 +kerning first=84 second=47 amount=-1 +kerning first=84 second=118 amount=-2 +kerning first=84 second=120 amount=-2 +kerning first=84 second=227 amount=-2 +kerning first=84 second=228 amount=-2 +kerning first=84 second=240 amount=-1 +kerning first=86 second=44 amount=-1 +kerning first=86 second=45 amount=-1 +kerning first=86 second=46 amount=-1 +kerning first=86 second=47 amount=-1 +kerning first=86 second=65 amount=-1 +kerning first=86 second=74 amount=-1 +kerning first=86 second=97 amount=-1 +kerning first=86 second=99 amount=-1 +kerning first=86 second=100 amount=-1 +kerning first=86 second=101 amount=-1 +kerning first=86 second=103 amount=-1 +kerning first=86 second=109 amount=-1 +kerning first=86 second=110 amount=-1 +kerning first=86 second=111 amount=-1 +kerning first=86 second=112 amount=-1 +kerning first=86 second=113 amount=-1 +kerning first=86 second=114 amount=-1 +kerning first=86 second=115 amount=-1 +kerning first=86 second=117 amount=-1 +kerning first=86 second=193 amount=-1 +kerning first=86 second=196 amount=-1 +kerning first=86 second=197 amount=-1 +kerning first=86 second=225 amount=-1 +kerning first=86 second=227 amount=-1 +kerning first=86 second=228 amount=-1 +kerning first=86 second=229 amount=-1 +kerning first=86 second=230 amount=-1 +kerning first=86 second=232 amount=-1 +kerning first=86 second=233 amount=-1 +kerning first=86 second=240 amount=-1 +kerning first=86 second=241 amount=-1 +kerning first=86 second=243 amount=-1 +kerning first=86 second=244 amount=-1 +kerning first=86 second=246 amount=-1 +kerning first=86 second=248 amount=-1 +kerning first=86 second=251 amount=-1 +kerning first=86 second=252 amount=-1 +kerning first=87 second=47 amount=-1 +kerning first=88 second=45 amount=-1 +kerning first=88 second=71 amount=-1 +kerning first=88 second=79 amount=-1 +kerning first=88 second=81 amount=-1 +kerning first=88 second=99 amount=-1 +kerning first=88 second=100 amount=-1 +kerning first=88 second=101 amount=-1 +kerning first=88 second=103 amount=-1 +kerning first=88 second=111 amount=-1 +kerning first=88 second=113 amount=-1 +kerning first=88 second=117 amount=-1 +kerning first=88 second=118 amount=-1 +kerning first=88 second=119 amount=-1 +kerning first=88 second=121 amount=-1 +kerning first=88 second=214 amount=-1 +kerning first=88 second=216 amount=-1 +kerning first=88 second=232 amount=-1 +kerning first=88 second=233 amount=-1 +kerning first=88 second=243 amount=-1 +kerning first=88 second=244 amount=-1 +kerning first=88 second=246 amount=-1 +kerning first=88 second=248 amount=-1 +kerning first=88 second=251 amount=-1 +kerning first=88 second=252 amount=-1 +kerning first=89 second=47 amount=-2 +kerning first=89 second=102 amount=-1 +kerning first=89 second=118 amount=-1 +kerning first=89 second=120 amount=-1 +kerning first=89 second=227 amount=-1 +kerning first=89 second=228 amount=-1 +kerning first=89 second=240 amount=-1 +kerning first=97 second=86 amount=-1 +kerning first=98 second=63 amount=-1 +kerning first=98 second=86 amount=-1 +kerning first=98 second=88 amount=-1 +kerning first=101 second=86 amount=-1 +kerning first=102 second=44 amount=-1 +kerning first=102 second=45 amount=-1 +kerning first=102 second=46 amount=-1 +kerning first=102 second=47 amount=-1 +kerning first=102 second=65 amount=-1 +kerning first=102 second=193 amount=-1 +kerning first=102 second=196 amount=-1 +kerning first=102 second=197 amount=-1 +kerning first=102 second=240 amount=-1 +kerning first=103 second=106 amount=1 +kerning first=104 second=86 amount=-1 +kerning first=109 second=86 amount=-1 +kerning first=110 second=86 amount=-1 +kerning first=111 second=63 amount=-1 +kerning first=111 second=86 amount=-1 +kerning first=111 second=88 amount=-1 +kerning first=112 second=63 amount=-1 +kerning first=112 second=86 amount=-1 +kerning first=112 second=88 amount=-1 +kerning first=113 second=86 amount=-1 +kerning first=114 second=47 amount=-1 +kerning first=114 second=88 amount=-1 +kerning first=114 second=240 amount=-1 +kerning first=115 second=86 amount=-1 +kerning first=117 second=86 amount=-1 +kerning first=118 second=44 amount=-1 +kerning first=118 second=46 amount=-1 +kerning first=118 second=47 amount=-1 +kerning first=118 second=74 amount=-1 +kerning first=118 second=84 amount=-2 +kerning first=118 second=88 amount=-1 +kerning first=118 second=89 amount=-1 +kerning first=119 second=88 amount=-1 +kerning first=120 second=45 amount=-1 +kerning first=120 second=84 amount=-2 +kerning first=120 second=89 amount=-1 +kerning first=121 second=47 amount=-1 +kerning first=121 second=88 amount=-1 +kerning first=193 second=63 amount=-1 +kerning first=193 second=86 amount=-1 +kerning first=196 second=63 amount=-1 +kerning first=196 second=86 amount=-1 +kerning first=197 second=63 amount=-1 +kerning first=197 second=86 amount=-1 +kerning first=214 second=88 amount=-1 +kerning first=216 second=88 amount=-1 +kerning first=225 second=86 amount=-1 +kerning first=227 second=86 amount=-1 +kerning first=228 second=86 amount=-1 +kerning first=229 second=86 amount=-1 +kerning first=230 second=86 amount=-1 +kerning first=232 second=86 amount=-1 +kerning first=233 second=86 amount=-1 +kerning first=237 second=39 amount=1 +kerning first=237 second=63 amount=1 +kerning first=237 second=98 amount=1 +kerning first=237 second=104 amount=1 +kerning first=237 second=105 amount=1 +kerning first=237 second=106 amount=1 +kerning first=237 second=107 amount=1 +kerning first=237 second=237 amount=1 +kerning first=240 second=74 amount=-1 +kerning first=240 second=84 amount=-1 +kerning first=240 second=88 amount=-1 +kerning first=240 second=89 amount=-1 +kerning first=241 second=86 amount=-1 +kerning first=243 second=63 amount=-1 +kerning first=243 second=86 amount=-1 +kerning first=243 second=88 amount=-1 +kerning first=244 second=63 amount=-1 +kerning first=244 second=86 amount=-1 +kerning first=244 second=88 amount=-1 +kerning first=246 second=63 amount=-1 +kerning first=246 second=86 amount=-1 +kerning first=246 second=88 amount=-1 +kerning first=248 second=63 amount=-1 +kerning first=248 second=86 amount=-1 +kerning first=248 second=88 amount=-1 +kerning first=251 second=86 amount=-1 +kerning first=252 second=86 amount=-1 kerning first=39 second=45 amount=-2 kerning first=39 second=65 amount=-1 kerning first=39 second=193 amount=-1 diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28_0.png b/resources-round-280x280/fonts/titillium-web-semibold-28_0.png index 329cbef4093b453b09b46d98e37624610e3cc4f2..d7aacef653f162797b48b5f79c4f8b71dd103c7e 100644 GIT binary patch literal 9919 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 EKcSP__y7O^ literal 9615 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 diff --git a/resources-round-360x360/fonts/fonts.xml b/resources-round-360x360/fonts/fonts.xml index f0c170a3..6487c4a1 100644 --- a/resources-round-360x360/fonts/fonts.xml +++ b/resources-round-360x360/fonts/fonts.xml @@ -6,7 +6,7 @@ - + diff --git a/resources-round-390x390/fonts/fonts.xml b/resources-round-390x390/fonts/fonts.xml index e8da44d3..15334f53 100644 --- a/resources-round-390x390/fonts/fonts.xml +++ b/resources-round-390x390/fonts/fonts.xml @@ -6,7 +6,7 @@ - + diff --git a/resources-round-416x416/fonts/fonts.xml b/resources-round-416x416/fonts/fonts.xml index 4790b641..5401a717 100644 --- a/resources-round-416x416/fonts/fonts.xml +++ b/resources-round-416x416/fonts/fonts.xml @@ -6,7 +6,7 @@ - + diff --git a/resources/fonts/fonts.xml b/resources/fonts/fonts.xml index ec58fd38..6f8714ce 100644 --- a/resources/fonts/fonts.xml +++ b/resources/fonts/fonts.xml @@ -4,7 +4,7 @@ - + From 6cf44bfc52d82ea288c2d3c853b90679de49c4e3 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 9 May 2022 20:39:40 -0400 Subject: [PATCH 046/220] Added Descent Mk1, Mk2 and MK2S as well as 'Do Not Disturb' as indicator --- manifest.xml | 9 +++++++-- resources-fre/strings/strings.xml | 1 + .../fonts/crystal-icons-large.fnt | 3 ++- .../fonts/crystal-icons-large.png | Bin 8590 -> 8739 bytes .../fonts/crystal-icons-extra-large.fnt | 3 ++- .../fonts/crystal-icons-extra-large.png | Bin 12228 -> 12644 bytes resources-round-390x390/fonts/fonts.xml | 2 +- .../fonts/crystal-icons-small.fnt | 4 +++- .../fonts/crystal-icons-small.png | Bin 4490 -> 5079 bytes resources/fonts/crystal-icons.fnt | 3 ++- resources/fonts/crystal-icons.png | Bin 5777 -> 5822 bytes resources/settings/settings.xml | 3 +++ resources/strings/strings.xml | 1 + source/Indicators.mc | 9 +++++++-- 14 files changed, 29 insertions(+), 9 deletions(-) diff --git a/manifest.xml b/manifest.xml index c46872ef..d8525658 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,4 +1,6 @@ - + + + @@ -12,6 +14,9 @@ + + + @@ -105,4 +110,4 @@ - + \ No newline at end of file diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 1f9e2f7e..de29b67e 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -108,4 +108,5 @@ Information Tesla Tesla Access Token Tesla Refresh Token + Ne Pas Déranger diff --git a/resources-round-280x280/fonts/crystal-icons-large.fnt b/resources-round-280x280/fonts/crystal-icons-large.fnt index b82a0d52..fcb7d0fd 100644 --- a/resources-round-280x280/fonts/crystal-icons-large.fnt +++ b/resources-round-280x280/fonts/crystal-icons-large.fnt @@ -19,4 +19,5 @@ char id=62 x=49 y=28 width=32 height=28 xoffset=0 yoffset=0 char id=63 x=81 y=28 width=32 height=28 xoffset=0 yoffset=0 xadvance=32 page=0 chnl=15 char id=64 x=113 y=28 width=24 height=28 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=65 x=137 y=28 width=19 height=28 xoffset=0 yoffset=0 xadvance=19 page=0 chnl=15 -char id=66 x=158 y=32 width=28 height=25 xoffset=0 yoffset=0 xadvance=32 page=0 chnl=15 \ No newline at end of file +char id=66 x=158 y=28 width=28 height=25 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 +char id=67 x=186 y=28 width=26 height=25 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-280x280/fonts/crystal-icons-large.png b/resources-round-280x280/fonts/crystal-icons-large.png index db99c151ac458ff1b2ad88fe43769b84ccabf87f..c6bf52f47c6362e52f09a3b9d565752a3a306c2c 100644 GIT binary patch literal 8739 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 sM`o)CK_dud!T}0g6XKW&i*H diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt index 44129b8b..089064aa 100644 --- a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt +++ b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt @@ -19,4 +19,5 @@ char id=62 x=0 y=78 width=45 height=39 xoffset=0 yoffset=0 char id=63 x=45 y=78 width=45 height=39 xoffset=0 yoffset=0 xadvance=45 page=0 chnl=15 char id=64 x=90 y=78 width=33 height=39 xoffset=0 yoffset=0 xadvance=33 page=0 chnl=15 char id=65 x=123 y=78 width=27 height=39 xoffset=0 yoffset=0 xadvance=27 page=0 chnl=15 -char id=66 x=153 y=78 width=43 height=39 xoffset=0 yoffset=0 xadvance=43 page=0 chnl=15 \ No newline at end of file +char id=66 x=153 y=78 width=43 height=39 xoffset=0 yoffset=0 xadvance=43 page=0 chnl=15 +char id=67 x=173 y=39 width=34 height=39 xoffset=0 yoffset=0 xadvance=34 page=0 chnl=15 diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.png b/resources-round-390x390/fonts/crystal-icons-extra-large.png index e988b5950686897c116c925e445397717e8b8f0b..28e793adca46690b673dbcc82896e52602a0c0d8 100644 GIT binary patch literal 12644 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 literal 0 HcmV?d00001 diff --git a/prototypes/Crystal-Tesla.jpg b/prototypes/Crystal-Tesla.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94c22d42479bd9b2ed7d11112306a68ab9a53526 GIT binary patch literal 53046 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 literal 0 HcmV?d00001 diff --git a/prototypes/Epix2.jpg b/prototypes/Epix2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c3fd70fb08fe3ac169355fed415bb06991962bb7 GIT binary patch literal 42364 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 literal 0 HcmV?d00001 diff --git a/prototypes/Fenix7.jpg b/prototypes/Fenix7.jpg new file mode 100644 index 0000000000000000000000000000000000000000..acc935f7044481b1826767fd8de38651b1294dd5 GIT binary patch literal 39770 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 d|KIPp_*y6K+mAW^F=PV>`+r?dhxPmHKL9GJQ4# Date: Tue, 10 May 2022 23:42:40 -0400 Subject: [PATCH 049/220] Removal of watches with not enough memory to run reliably --- manifest.xml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/manifest.xml b/manifest.xml index d8525658..42f15a4d 100644 --- a/manifest.xml +++ b/manifest.xml @@ -7,8 +7,6 @@ - - @@ -18,8 +16,6 @@ - - @@ -35,18 +31,12 @@ - - - - - - @@ -69,15 +59,12 @@ - - - From 3cecb9771654654613d50b1b9f345059fb4841d7 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 14 Jul 2022 22:12:26 -0400 Subject: [PATCH 050/220] Added SolarIntensity as a data field --- manifest.xml | 1 + resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + .../fonts/crystal-icons-large.fnt | 5 +-- .../fonts/crystal-icons-large.png | Bin 8739 -> 9029 bytes .../fonts/crystal-icons-extra-large.fnt | 3 +- .../fonts/crystal-icons-extra-large.png | Bin 12644 -> 13434 bytes resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + .../fonts/crystal-icons-small.fnt | 5 +-- .../fonts/crystal-icons-small.png | Bin 5079 -> 5275 bytes resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/fonts/crystal-icons.fnt | 5 +-- resources/fonts/crystal-icons.png | Bin 5822 -> 6018 bytes resources/settings/settings.xml | 3 ++ resources/strings/strings.xml | 1 + source/BackgroundService.mc | 30 +++++++++--------- source/DataFields.mc | 16 ++++++++-- 33 files changed, 65 insertions(+), 24 deletions(-) diff --git a/manifest.xml b/manifest.xml index 42f15a4d..aff34fdf 100644 --- a/manifest.xml +++ b/manifest.xml @@ -40,6 +40,7 @@ + diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index a28bd0b0..2702fce5 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index ede06f39..6c28e154 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 4016c611..89f226a5 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -57,6 +57,7 @@ Schritte Stockwerke + Solar Intensity Aktive Minuten (Wöchentlich) Kalorien (manuelles Ziel) Aus diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index e6b2078a..2eb2ac1d 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -58,6 +58,7 @@ Stappen Trappen Beklommen + Solar Intensity Active Minuten (Wekelijks) Calorien (Manueel Doel) Uit diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 86e09c76..a02eb9a2 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index de29b67e..e62420aa 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -58,6 +58,7 @@ Pas Étages montées + Intensité solaire Minutes actives (hebdo) Calories (objectif manuel) Masqué diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 07fdc357..34b59ae6 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index fa6cc717..feed83b7 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index f63c7158..1850eb53 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index a7d7ff25..1435cf45 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index debe2d42..b8eb2e77 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 1d4d4ea0..9d6718bf 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -57,6 +57,7 @@ Kroki Pokonane Piętra + Solar Intensity Aktywne Minuty (Tygodniowo) Spalone Kalorie (Ręczny Cel) Off diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 5a8018e8..4b7b1245 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-round-280x280/fonts/crystal-icons-large.fnt b/resources-round-280x280/fonts/crystal-icons-large.fnt index fcb7d0fd..8ac06100 100644 --- a/resources-round-280x280/fonts/crystal-icons-large.fnt +++ b/resources-round-280x280/fonts/crystal-icons-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=28 base=28 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-large.png" -chars count=18 +chars count=20 char id=48 x=0 y=0 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 char id=49 x=25 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=50 x=53 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 @@ -20,4 +20,5 @@ char id=63 x=81 y=28 width=32 height=28 xoffset=0 yoffset=0 char id=64 x=113 y=28 width=24 height=28 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=65 x=137 y=28 width=19 height=28 xoffset=0 yoffset=0 xadvance=19 page=0 chnl=15 char id=66 x=158 y=28 width=28 height=25 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 -char id=67 x=186 y=28 width=26 height=25 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 \ No newline at end of file +char id=67 x=186 y=28 width=26 height=25 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 +char id=68 x=213 y=28 width=28 height=28 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-280x280/fonts/crystal-icons-large.png b/resources-round-280x280/fonts/crystal-icons-large.png index c6bf52f47c6362e52f09a3b9d565752a3a306c2c..dc4d69099fe044db5d54afc0d9798bd348fb16b6 100644 GIT binary patch literal 9029 zcmeHNq?nXK#rE_TnluoIoK~g}vLy(Z}ZloKeSsJ9ffAjq(o>$L{ z*_msvxvn{L&V7ICOr*N1JQg}BItT>9QdE%n2m-+YmvA6dc;GYx7Uu#^C~k@>vM9SK z*a*x>(#`=e;4d^M1$|c#2;1$y1J0hVb{+(JyR9fAspYkFoaLQKI9EMb`6+}c3Mwio zhtwM@ozKJ^MGclDK#T^<5D^BMlh5ZycIB#dA;G_mLPe+0+Y& zpiYB}h#T6JE70kt*v?a&vh11G-S*TGu%fnpGE>~DraSjb*iim0nnt6;YSD)j|Enqa z)3!_1+mltXnaqHf`zeVvzuVQm-!Bl^`->gj-$wfC>hWo5-kYJsVWMR+k$CMsx7l14 z0}t0napXcSSNl_A83G&zbtTf_*paJpe-h{eUM_Ru-tbuet+85ebQE`n^`TJt#%E-R zSPdt^As`nP6=fZ`d`n`{Wfu|gnaCES5bcg8JO@ifxA<5{h?Ge3h-a5~Nh$kfE2uZmJk4pk$w1Va!N!ukY} z7-3g$S@(M^EiH$n+i%x=h#|ht62r(?q!Q%8A1KwF|Inv|G@t0(WL?i{s_7S>E>>Gy zAI_b8uD)!$9A|0ZuHIj$%vl+Lyj-NXPKY&@u-7_o$=xOfJRUceKv%3%tmCt@JA7_W z@-?9%Crw*jfe2N;B?SxR`Un<6w$p_hSJ^tpWtAO4#`37p=pQ7N@4 z*h8E4ft#v)B|={YX?}`!^W3!cS)~~ByC2S`4v?V5V@3u$-utUaA*M>?Y>p zkvIOY_J)736s(<06`){tdh`DD)v7dkzMK%h)dG>XZvNyv>3n%OO5I~th}LwGDb_b^tD#a5}W>y}a8J;)3^H6)YlNF)pD~n=7 zIHe>e=XPRX%rWmCI9-1Jbqz)@wjN90eaE6xuJF>I$_nW)a&ed|)mF}7B*~0bUWo%H zL(Sk%VRGwP561a$E@i?f?-?PpmeZaq(1a*P&v5}y1@lsD26db`l1m$3|1>axYJ#Tv z@rM$Pf~7`B9KV4PGH%PE1o{tsBn47k z_`eAM*4n6{uVYC##eJ@9zcEmY6EcZMtKp`?$1Ua!PLFVhW)1M?2gvAqNiYR7C`iC< zA1VYVfgM(x{T@9&k=o%*!D)a5G45D|L7h}#kQrJlBT7?cEiXh-zBOATA8QcGYS4AoMK7LNF}d zNX}&*a&rHC8o=@8DIXypRKnu4e;V-Gy25Nuq9X3Ht?(CGHqVK6FEhz0Ra0^ao#w?+W!6f?2ZQZg}BdY zU+zr|-tbH!>@-XSG3AZSt!&`q8G&nNA-CMuO;gjLa#$^S7DTGC;M-{Y0D)83i) zm3kY6w`8&C#SpE(5<;)V&ntUj86Q->2Zdu|2$n7`4YN1 z+Zw9gpOI0C_m=Zo1f}1mfl;bK)G$kVPNq6t%nINDtb!~!^bIs42?7+n*Ij|mYHV+2 zi9TEI#HS1a$Ct#MCz-A0?e13jFdcl65EG7=0*zvOIUmL9z|O@;>GV-MbGfh@s&vzn zfRpCE+$V=hZAvVuHv{*v2NX2ruSbyA!}reTuznqU9!r86EBfHMlo&d~4FFQ5#u%*Z znV|;`p@SmWl>DFdx`cEfXhF4eWx5$faSH{<(N&hf?0?B{LFzJ=&C(GaQN&OOQTJLD zcABrXd7~xeGP>@K%Z5!ql`5xk%T`92OP1HTAL(3LQ@;g9)`C);D%9oOrJAaD<1SH2LB!-u6lO3Wc>s#&n=fO{YLE< z!<5pL`2lTp+o;4(LII!B^6e%T@A}GmyN~BJm#IE(S=ZcDPdD;g{C|Bke}ntxa}Dl3 z-?ak>Rly>)QRtQTI#1I^{A6uyou99I(QNwlc?pXK`4F}xDT<{7kXQo8GDwtAu)Efv z-i|PrH{L}t43+zk*Rw02|D6-ds(v@+-u5>2-~Fiqgp=M15QCW==oegVP0dPpA+i?$ zx39Onq<<7zO(Z1)pJcU?EM37t;#d{A$MYIqdz!_nd=z9dtQ^9rv{CV(hIO|cBt%R= zVK&u6M&`xjEczmFT@>WU?{R04h9@R&Kih=ZHp-cKeFY!BC;X04$fs;XO@0Ap(6UK> zwF}BsO3>e0%pb?#Clk;{sjKIrM|Y|Ze3*X%tW*+u%d?<}a73urI1Q z>i2-ilB*4pRWmb!%QX;K^D3yv*Dmsy>%H!oNz2bIjrBY{=w{&xHtlP5py|yPc0ZIM zPvL{5dY^}yT9qd))oKw)Isqa8kL9CU)V-sr*3Vs6sPU%!mJGpJe0H zCU$@z{^@fzJY+ z=_w(1mhZ1eTH|vFd;H_)lnC#o&~;dhK!&8s!Fr=(4kBzCmq8dx#*b3CPY{&k8Pbh=MxIWIx2}|{ zUu%6rV+5$+1w_AxtLoTnLFas(3Io{+P`1{ukFqYGW=k}NG>4PfSZF2024yAPL=AaX zsP(&KgWFp<%k`?I_O#jbsw8f=b}IsNs-9uNk>*r_PF-KH&yXuJa9nXXtH1ZqLV!gM z8)tL}Swtkf_ULxd`Cx-f-Rt(E(J~dOOm3+VPmXkNU5{Vf7m+)?D(B zE?$MRh(eb445(-q=mjUX+y#;vjdEH1-SMsgg{NqZST+khaK0z07KJ!e?>{%Jw4RfR zlOrP%>YTQwWe9=0q?QnIomz3S{BHgR-1Sn?g=c1Feqe9zv-|CiAd5##6=Z&r!)u$M zARdoxAVVAPuQift;42Z?QCKru z%~Zlc-EdB~UQA9r`7ihh;C~K_Rd5==q8B3%h;50{$t^mWq>x`FkwuHBjJ_Tep=uW? zaw@9ZA2{u&E|K9)IOGRt0`z6p8#b2CH$vWv$;e^G6+@5)50wl?R(#Ky=`S1;6kG_&i8Hj$9dy~Bh_Asz0UDcD8b#ZlFZulbNwm-RG;xopkIBB8(X_^wt9f<=iNBfSxP3N(Rwc$pbG-z`;Sdb)t$Ee-wg)99P(pCFw@USPE zSR2Y`Kfj_uQu}5qu9tnoW`su1$T^^3Tp}GH`UZ{P@gHjCG?#oE{4Z>8z{B_S- zyH8QvJCJD9I3m=%AVNj4XAIzOno|3P-^L@!Y@6Rgl5{_za)*#@rGOfUx($tjdrNgH z4o^HHgjY$Ic4=}iZpmHYT*2qxUp|%F@xN(tJ4k4|lExmJA`fMS0T91x|2CH&mCC*) z5Pm4+7a;8H2W`9xeby0?F>mizS99En@?GzSm)f+|)vEyh7-4T^6%#Y=K@hzJLua@`T%ULf@D<4CXp#XycLRT$wzEogS zrBU;=7#+qu1`cb1{1y_WcWkgtj;C{wDM6{#m@dKDr^(~9@wh**{;08?>7_;+5S2qOZ{Hnl;>iCLUlvC zj!s%nb#CB8s{q^ zIleDdtSTA&6oO70K}ZAaC;Kkb$q*hXgn{rc@|AH5>cVkwYQG#x4Z z)8esq&+18xDl-Uoq-Go@FG?!7Z!LZr)W$}gf|oNS7xBOx;48FUaJJ^g3G@wk!)+PS zRtmgA=XP#yoU_7o6R|-Z@;u5+o-~ROOSOUkL*uGP#&*C~i~vKjw1GkTO+UJm8pOQ{ znZeS=28H9{-M`gVUA4%@^F49m5Dzcnen0KmN3_PkBsN2xdA6Y9lHj^3nh~X~_`1KX z^5#9wm;pado8h0Xip8~i<51+q)Z4$h>phHcbdqOBf4(|i)+L_%&wrT<2QsQ=a%MC; zblmUed!3zN{4$=`ZdSo0q1n!$kA#QS4`VvU5k6;487DHZ^QaN| zOK%v~4r?dUv8m98Gg6%@^>EI6zm^;lW1r*tgwE(tw;2EiZL+-wTuX614oS9vykqL$ z$?<$e#$V%a2Ihc+NVs^uUH9bRDW~3bZdIcpV+I4L%EQfFQ&R(8Y&!-*pvS8jHBaEq zk3~voZ9C>$m`qUR9b_FxDFwIuG}g?*eU}fgqt?e8R{fN`*Df(3PFT}IM5$P(DwvBj zw|s|9*)ou;k23o?WqN9Np&kuK=0cwIR)bc~(Na7LK5;mhnAnlLu z6eNs~CSg$^l9PYi?dXh?w7=3^OWtqadeU;Vaglaw%G~vhkOiAu5cDTF)s7L9oNgj2 zUo{!A8ZtF&z z%(@bsbAFh<493JASM$Noj3+s&t)!-vUG{xMoWxUIpT=lm5h z1EEqhtn}%#0xuNKb6uFe{Mq0?Y?Biy*J}g{7eGZb&15 z`#>hx?YEq56!3g)*zoy{fJ5fVFTHB>*OzCTvGjVs$D5}o-@CD@8e$`-K!&c`4T2{2 zlNIoKlzrY&oHPoM@Y%B^IG5F;ECYAAyC6PU& zzDlei^pZROUa#jv;;O(390x8ylMue*QB7IHaom#p(i~V8g$Sj*y$-v=NEIhw-A>kxjQdfe1 z_$_tyOBK9VvHB_?e&QipWkAfpdql&a*s+L2kRClm&S?r2C4PH7Iy&loxqA>kVfhtY zo^dOMqX=s}jJH+U*$D)c=pP<@O*oz3M(>sv6-?kP1BuLlSvqs47 zBY;I|JZO|%`491Dy)!!n62%dqfCMn2ml~2YmdZBxVxu5`*QT1GqLm-5io|)LD?ARP znDw|0e+WW36L%5sC@-QPkkUbJXu`h;HA%=v45Y2C*v+EnKh&6FCeYs`2cw#}ss1-K zxE~T4Oi)s(r?2xY}bD5ESf?f+O|d!tmo`~JJ#~HgEf%m?mFzSQE!y~jn$lPs%w@M0sia< zJf7{H9i-wU*<{eH#7!ZyU|5(TVJgq64*~(VX>hSe;T?=XjoA&I)mve+o&#&=%b)7Y@LVUlG z06nXAeXWrrlg0H=6Xr^CW$)1Hd5V2zM?DF9=$*Wy{~#!soOb%4n}X~zq4T(Loky0b6h=g8X*&{e|5VXkH;MJHwGkb8#z4fZze*o&>|wwf66z zkD<#=gK+1+8yXcjt^o%|G`U#HCTj31wXwmf=%7BuZ8iLfF}Kxw?IHEN7f1Xvy+jsu zI5*3~Cv4v)B7*t7{5kX|cTS&m&=eR1 zV@X-4C23?YE2Qoojw+qC1~mIKIyumM-Dz|2CU=IO38+o4Vz2)&80To+Yzf>+S~jI( zCuag)A&rdOjV0hqR#Ke!h`BXf8<6a4*yK6givX3!(-?|DEEU*4D*cfyI7WIG(c3;t zg=y{Pcv%)L&-UQpz`qC!O@j3|){UUXa(dAomrDx=JdxOMMG7uLY91aq zFh9Q*HN3(8nA)m*me4^BTZ8!S?O*zCz?HBDT)S>LKX};3u|Ay=h2lEPYf-Bb zw+SYFyxUkrUsg8+wgZUsaM8&*WOZKB1so~+dcRE-Nhy4z8|&0Y>)IZ|6mF|1``w~M z{I?hRMQH{R4^fYSymZU7VOUP?~)Hg5nCx z+{W3Wn6&&IHJ!#bS*4sn#!lzMtW`qIRva%iK~J_~LS)k5b|v+xuu^^@Ane_oRe&kB zSi3sCh=}1wB_HHrp(m6XEA02<351~^l9&Q7B=gcJw$-b4-%G$H;KUXb8&f;y6Bth^ zX#Si=Lf?8Gl%a(?&JSP4ax~HX(;Fsudm*rWYe6vgQ4DuY)Z~Y6htiD#KHa~T$0%d2 z@23t>AX&XHO5^{MUKlCl0V$U5a=Qocv&(tmblDam0^8G7zPf~5#&9JUJ%JZi=6g9N za7fUP*u%_q3+zthHIAfkgyZ!z{uvpuUu|(8O{b&pt|mmp(6HGddrB{JmeV9eEbe>4 zsBy{lr9o-vYnS7CF)tplab9J_#A}mQDE8&W9?VUtQAj7~ArS0w zIICF0mvXIa#q&vNv=eG4;PUW@q_3|(FR+Xlky1|g**}fbgBy$9T$X5rp}BZ0ze z87;hq3i~$&m>t<3&+x%e7f!||Ju#7`^|v_^SaRZ8d2_@e(j61wE%4Z8qs}1_Uw8T? z=QlCZ$||~=s1rBtxI??E=WrP?X4A?Fe%8>khVDXG0!@*+#t{iX4opvo_d&kEAl(Va zf$lwIf&rpH3zmR<9ql8k584??2~S$_Pv`%#q=y$w27PzvLRyH{Y^n@wkb)bLh?jtJ zzShJatI3lm4BFc^Z04g{S{o&mETLV(&k;eo=KBu)a)`{8^uhjow;+o!Bn?^ zS+=4_br7vvaeGLj^B2=&y|qv?j$0MPRp>yGO}I?U9>kk8Z(o!ZC;_R zyPB%%1h#)67&HJ!E&aTWnN$zBv{Hn{u64v9)1mNY zlS)p96~P~5Bnn?pb*X1IbyY5(8juQ6Dyf2)%Bl?!EA@}$*jggzRPFMDCCr94mz(4d zd$nj$vfj9kur=zTQPW2ebA&n3jsgBX#|wt0Rj3WvZlh*y*xl8YnR!V@ z_e#C$wM}FQWqxmpRugW|NfyGxP(_Dejk zo)^jHBsnL$vorTxb5Fi$sL8*=AjbfKK(7=PWVApa1mGnC2n`W9%;1W10S8nUMO9hU z9WWXqnE*{8+amB5x}$;)6a>O{`S(Dup>LQ2foOUaWh6g%EFEWg`Vh@74%JwN?){CqkLGzrdZRHJ6FIqCyQTtpezgr>B4A#RPaPC&n^8=b#gr-(>Lf?SHpnlCVEs z&8Umttp%|gw0R^8?Pfyr10IhZ{FIN5UTR7|*KO3Bk78hAhT%}d)DM%2m*WD~*4E)N4!otFSrNwEr%h#dvdhT*k-0yxnrCr&C&MglV zk;jSM6Cl_@__~d`tgOuWJvHoZy(q3UqEA z309^YN@$1@~~*!JUitoVck z_oD?(FAT@i&fAmU?Ig)KVqVt=vz*BUj4EjCr`EGwPd9qQ4?31v3Ng*CcC|C>i=8>LcX!nL*`$cl!$&=20+P5F`!%+sR{gKWe zr#6ZX5H|9myAwSZ2t;keG{qt`+&3ZvMB4gX*3*TlgQQ>$tdJm%yD^?g-f`9ArAE<6 z8e%?{u$q&Fx=n@@eMI>0MjLHX7}P=KzSOYuLEFf8y9~78{d~Xc@Vjkx>H6t*HD`FZ z;Zv3Fa&*w4O+AJ6lOL;f@W8dv0ZKcOLFXzqg0S44}%D??|ruCY4`EJcK(@TWZ()!n}#4$H*O{Z;qG4 z;$XHeED~wl=Jsd*M1o6}T5f{Z+kVaQ>s+NZRlUpp^oBTT0)uk0!Z@4mk8rX}4n)wGBPZyBA+BQsAW|ZTrO;V+OJO!G;%l zgrJW-RvYqJ!mg|zd)Qcwx;l{cT67vL=Dt6!j(wnx!>dUCqO>k1~+e`j9CnbT>Z=X>YtRLlWVpuT+(9EY0 z(V6`-Da|$Td#hewUS8%|pHbx_<%7_O&uaES8!%EBTTHx@tUs6LI-cXaN3qlF*@9_| z=jfE@ZkA!TcS8J;$C-Y*(NZ-2E*SRJq5WO9S!~gz1J*!C%vI@r?jv0s~ zDcDL-7c0|ye%uvTriSnNGlP7S$y5e1_X&+)nl)HwNA3E!j;e3vO1C>4Z#+E0b=H&R0`>vgI z8$ioLR)O1;FyXM!pztja;|p5V2U4HE$IWxe)D$Mf(jRd|&io(cuz8HTLAQz-yw-tm zgLbzhKWeW%n#bQ=zU{;c%F0lt9>>iK@5yXYAV26{!JUbrwNi21(8@2SH5^pB|5)zpQs7Q!f+-Tf{6B}<~>IYK!$=*Ix-GxCooD{eX6~y-}5|3SOk??T`+`-cKG$VtKh~hVzX=9K#ZgoPRRJ zI{!c~)NdL(f{^oAU@eUZ(@7~QipbnL3a3(OlCp$Pu^s|f$bwNy5RF-C4m90sqXpGY zU9^uKjrVV9@ZZBtr+h5@Xw60&=6`-r<*g9X;`h4R<6I)k1!Y5!WuUodr+zQqHYp{D zGMVf=WpK~S9r)um2VV}0n8!`&)PYIZ)L~hjzya3y9`hU6nvrckJDY_oSAoc7zC$7)F_nIo;7T~+SbamXZm^U^_~!kH};;GVT3D z`br0kLsG{`TIpxG_=*m>_d7QLMp;E6j7I2#^P>5&VGy1kxubYCW?R*A*|AV~jL1c} zs~lP;FUQsDQpj!~ye|wVtbl#Tx995N`n41mZ~xGD5AsT&FA>4*kj_4=A;*0EFJIPw zT4JP#lzX^z=6ApyQ5dAsMH}p$nU(e3gibyhs|C9mF*W!cw1L3G&ArmzkHl)&apxCZ zkQQ}yNJLCL0w0cuSfmWzQh(24)!s<*-+iHC!dN#7*{D7$)B+Eq`z9l=!#@~-HXNn7 z$!582*GlAmE1_Q5a^fD32YF<4^zz6u*t*%`i-#O8xmc1GS|Jr9dn~pm8o^2$5j-7I z7H={q(o}lsKR%&4i*RhmiU)3)lQ6X!cK=~DUtR_>A~6SapdPbJnSHq<-lIK%NHAyF z0d7zcD9h2)fhf^v-*s;YNfUJjwE5UfH-JYf|8Q?OR%vipS zRL^fA#^#mr!u21>6&-_6Ug6tlsYl*Z8-I9={_mDaWX7nm*eMSKRHWqm#dSBMM4FK1 zwR{vQo@<-ShH#AwMcTe~KiR2@@fAjxm3oC%AP=jd$9hP33QbCv+Lwo`{e^s}e}OFO zBVMM0cmOqwQU-B@%O;-emvkXqxACjr!%PnCgkX2RY-BFdw6#6)9HBB{u3@JaIu;_t zgo{XmEk$otD$x5XyC<6Ge*B^BpuD0mYQmTYoo{^D2%&cjTyC$?WUI62F>l~5n|01H z*~1}j=zBf8cfL=`sG82}Bu|cz>!_p@(GCj_oHb1#ZLk=Rk0X&;0?C<`$-hM1sc=i3Y0Jf(>2nLZEO6hI~b9l6+L+EQl zOhIc$7n0B-<&*>Oj}4ZSbH^$VskyLC8_r_9wCNLE^ z$H5*WW95iIUg5S>-s9g8ap$H}F%TNDQXeVeu_=W;#5=;MVWbh!{r02DY-d)EdY=$x zAT+e`d3UK0hGDjd(2{|)R~W10t`Er4U4Q9J)mv9znmEw428YnS*+sFr1lNnFvi!-k_XeZv!vJWou*@~0LdzO%&}etFBlGio*e@|9p1bvcJsldM5(Z76UZLi$ugLYp^DC$$#vs$6vSzlM zs+NFgK#nmU%xFCM&m8nLiw1C*XuVci9RUyfGz}s0AWSD%F;fdm$BfJ3;C-s4Fr3( zgRAd@V`RBE+55Qsy3q39pWn+mJ3H$(*$P=rG{Nn!ChZP=AqfTeZ}UoaU* zIjBOrrmLCRLLi?yr&S`8t=-s(;qkk0O~fidJ3HNPrReTh_@vI3K4BfB*4tfQ_X2@5 zi+TfEiR?lL4agB>#0N(zDk({Qng{Yu&%PC$r=Z{&5}GR&%mo7*+r)JY@Cj9Zoh?84 z5?0DnndeJ|m7 zwhb;43OGM0J3CtB6Vnc479g!W9Ti6BKAyf0p7YOln=$Qtj2@o_7!MF|b&|9SBvw+` z^mel2!G|HQlNSrl1H(m@d!S=~Wdh9z%gsA$nAhfVm)C=+6Yei}Gwi@f>pED2_`()^ ztdF%N$MWG?Rl1D?t1`fl7wU*Z$_dh}yKzx8`s4$NZ}O_g!wS}K?u#MF1tC%q;nx5& zWgkspaWTL3G`&wTEFx$R+p~o43Z?bd$CI0W*vQo&0l))rVsM76_n^;j%Yg_Yn5Zq2 z|2G1r-abn+GldUP6|cz7mn5umg@>Ji=|RA9B6EY~3jMu5wE)0|@`)k-oYi%3V?b#V zGcqEv-sMIr1~?r7omE$toSv0~0|y-mu>ts|rG*8p9Jdjg(3|c@(er+SaP4&jT6OLc$myj$+@yli08Qh<59^sW*TV=S zaaLs|B_%lQ$zn45dlbbtZYj*iW#GdWk&l4xe95*LOVwQBVOMkts7eRGa#`D?Af3x* zk1$SO-=4BAfP(pyIZ03#{x|8RWeMSpZnteDKx#cLp}fb!lPZ6tAtmfcsMv|}u6Jka z+LSI2TyBbFw^EUF{SW^@lun)@d4F*0r2RDc!J+GZr~j*hlG1eDXN2|rL+rW!;L6I% zHCgcxfOhw3&fT74@BCNQTW|`cLNMy>@n~hU3PY&tD|y`%b2_~l83RYpEQJP$*0kXd zN#w87EF1_lrOMU4}zf z-5+5bMWFv~)1*}t%SH+HaW_Hw?ij=O$1h?@``ckQQ~b6I8qpVeQ`LZ`hqoYlF~x4H zr*RLcM^(3<2$vb{NVV<%Dx0}G-xM|C>y^tg6>&e&hqg2WGyjg`n~wh85X_=2VDQ>9 zwD>GJv5B1{<@N!hDw9!CTx?-x2C4I$q+w#(1WW3`6u-W6f}xPN6w zix~HyIoPSa>ztpORGW?gdKHEW$X!n?jWnnXe_!(XoXr}4Hh`&L6EAtJg zfYCpIrWp7=U8CKP*>DmW?@#~pVM4YfRa|jV5aM?g*At3BBCjuCStV=DoHqSwoPjg@ zQfE^LEd_bfVZF>)q@2cp>D1cV${mX4>v6MaX^Q<9q7eCj>%jDf`#i#P|hpQ}tWo2*TwX;+Hv9F~?Hw4SiIM!pX!q{ZEi{hg&@k+vH8a4pJ5 z;E9eqD{{@``G1Z-YG7;f{AMd$rJAwNe6dJHYGfv9UpAmKc-$qyBnjRPFOj zA+6erC?YAG`~!k9jF|N^1b!}EqS9vc1`Cwl@TCvs(wtpp!4Zw4>yFk8+|H<$8NN2+ zvu+1q*x`JQyHOL9z=~tv&UnU96j^~Dd&^p&nD2v120xp)xHzC0PCS)IKu*;KvY|^4GwnzJTx=+$YUvUqBUSD4efRpvov6~t7a;wv2JSRwH zFX$X%C2EYXk!UGWMRaXu@&CU(P9v(*Zsxz11)BDPAj%GVk%}F zwV)$NQbY<0eXecA&t^)8Azw}Ysy5L3W7lZNQT@Ion!<+h=}g2c=mb6EVI#E>xLjSp zjx-_Zb+PQr>E4vhx+amjskUEk0^<(_(^yz$A%x{J_r>hQ24y314qFxFmVkYL3DH}xlFG3z?5X8dcA<4J4bBxq6 z5{@COXj^7nYd~9~Wlkwv&8%j1extp8GA;X+W-{3~P%|DkW{j_931{3b1>A&gp{`xHZL>Cr8S z({_P#a`pxvX%N3yO@%c-9k72!%Z>3DAU{6WnS`v?p@|zO;A-b`(lc(1?FIV`^GS=X z)l3Kf|qm+8S znELBK^Tx$Mc)e-ap2q-{w_mqZ`C7>^HJjHuKJ-*U3z&>Wc?W>H{Cjh311nWVAy{i1 zNdXEnB_V=9`Ud~`qab1O_NP1x1Zd$GR0e$M#J$!gR>F@WNY(w&)`<6U$X#uCYsfA_ z&f++@oZdqZW(n2mZosMgV0+!}k z>0;tGP4Q~?oH~EeIQ)b-+&mh4^w-5Z(+UR6%KrC}N3CG%?&VK$5D|x(?A*Gr2P<_; z(&}9vBHom=1MEQTpd*1DzW$0fS{A1Z|INRx!zkRV1vL5YksNIdNJ`ym^B&}UBzA5GTc%Zb#TK?KXFHh=KFn&xvn!C=U4l&4eIBSTX@~hPJ6e5c{Du6P3QZr%KPY;s z(S&3x^S6ZkIGn3uLF&XMPkUQ&DBhQNP%n-)L&By@ct%)XUtd^wWtp4R=f`RAr)NkL zUxsEy_HXWgV+hX7pP|&bpb{JB%EL%P)MM;vnumYhxO@y%n-UdZDjA%<*}63)oYfM= z6{4j|^664)QXru}YWo{$z!i6D?~g|(cbAkV;#r^gO~~EIC``iTr1@)7pqT{Rp@a@3 z{ChlWpjRlosU-k2o*Tcy=jG{^oNxfS_pQ(^V4`Am8q}MiC*szr+S{L0HUA->Nyx1J z>GUntPx2FXBF9#Da?3pPAbf$@Vo+tX7Zk+nab~Pg;=_wQ_}N6Y*5}?inB7AP4NC)3 zHz*4NmC26aaeDs%RtnOgSo^=*-N%-UH^;deudZCwhY%zG@%v$5jW7qZbH{5Yug9QR z;@Jvq`J2EW7+ed$(#q92+smKdZYi8ZN|YvpM4MK*{}13_w#f6EekbR1%rD9I`U=FD zYd2}HdHpeY>Yc27v~vF=rek~D<|@bV@NjL{BBMly8N-*$(ctsI5|b)|(4+Cp3g}x9 z{oLSmRZt5_+KitTR4fhjTHJwo7LBuFFD2QWwH*BQ{# z-np|&oxOJG;9_9d9v4_uQB_Ua!qJ>+KkYhfM~;t-AY!2fX>i04YJ5uK;aHn^clzry zW*)eo<<3+_)AA28EAJydH?E91_u4i)dRovL;FA4XX|bMRy#Ei_nE?Bjc6f35TD|Lv zZp;$g?=`9-*et3ekj3 z!5qIb&A=U_EPt%x+<_YS^8-G5KrYWoa~J{@Cl=9B!j-Y^*6wcD2Yy1RpB8w%OIOmS z(+9yFuO9XbX{OeEl=xOQAK!*j7L2XBy9M4=K41YT&axT@y(dcuTHLQ~)m^Nb;Z>a< zvOw9IQ1}&-n6*|8giF?2xpubJD7T>+txklmHzf%AP@0n|iH3YwBk)B}&0JeRiL18Bb%O35y+-hkBi>2c zL+w+kp4I3IVmF~q@Op?^U=dxcB6d4BGg@52b zPZo_nrj@{`$}1ze$C@KLi?{%Guc5&Z@vyhA_Oa!~5~P@hT=#|3Rwb$lo2A9l?2iQJ zN)#~=_EfDq9guMMfxwQF8RWcHvG+9i0%>V!ZJ7e>AY#Jt7T>>ag(YZ4G*1tMF{=j^ z8pbjvS?}CGtxLNECrc)L<+%K>KzNp;M*`j&4j56ebAfRI-*Ky1mU z7%?QEAasKWZaV&`Q8`e?iLY;hsp=KTypb11)%J9=Y;HoV_2cNs)~tG+E++vqYGb7p z3hZ(NB#Q1>vYChx-;fx%XaaSQC(Zx$S1E8h;eq@@5CxviWPBh$fGbI1)iIff0%ndH zU|1$`_{ez)a}w{(OZY?ip$$VqB{rv}B`pXZnNpLov! zcF!Kp-n;kS*UVfqvtg?5#>9rh>e*8Uz9bccBmzIB+wCBgO@8kX;m%WsrA} zvEXTm&+3Ytz(c4G@*kZc5Gz4}B66)>?hk9=ADu14zf2md5ys2iE zV32%6|LYCyGjP>Ejj_#hP@QW2+aG&-dl$Q7mAVb1Q&Ur2lh(6kFY)p5DJUrL@SHDpMs~+C zGlkr+wl@_D-=#Zk|Nb#mSsK7?_FH_9fQFQSfPVB!p9zA0AA~JB5LdEFq+Y2nA|jHG zF%OG6Z-J@Xkuc* z@u~6jaGpmUQ|NnITC4qP`+E1cRK0?zDCNO;`jPSc7xZtvFDK;Yua9?(4(F;}@{U*9 zbW1ha5^CHI=Wv_o=-1aegFL`X-skg0Cmz6Kd}mpAb$zr5=i_5R0Kw9#!)z8+4*30p zMJ0`&i<|oe#`;XD7SlR7J;WX3b!gNjbbs$FY7()AVH?{1$_cz>zMd8R~zEv|&iq_67eQ=4aD7B0(R3*E)p+3R#oBAP|KRI?ljgLu5&PPfN&jcu*b9Zv91z9P}jL-1Vi zX7Mk3H~V9>ic|y45xhjbZ>yC0Z2nXzOh!t6MMFeF`aEAFQ)=>2*z?lz?`(OS*A4rp z#;W4<*-|Zz`Xaxlf5;ozsfyXW_%|o3tL;AbHD*KaGK5i)2N?a=28Di>1t#X3R+|pK z7@VYfbhj&aT1omyb?O@VGZF_+7#vF>fni`SO9H<0?**hhum$H=&+;;Px=Qzl1pg}J zF0Ga?cK?WO&d%QB!->(38r$2C@nM&7P*M3SYgT+}(rfv07KMR^_IognUB9(aX}7PZ zXW;wJ!9fY}lWxOj3H}u!L=;q1E{z5K4&SyfM>@$$A9$iE#q@0~VRkF69ws4sELAT1 zYN5r$5q>wzZsD!OqMT&sr3a=u5rk~`AF1A#NMM~yQWJ!MH6J#wr&f2adjg0L=Fm6(H#9Ufyu8TU|t^G&ts`7diMU_-mgi%!8W(d zsRUGhPY*>hHgA(4nny_nz7xioB3{?Oa<&Gu{GOi<`J;)sXd+&b2z@Ezm);=?^!I(d zn?Q&l;)o6p|D7(x=fmxG{E3%q!|Pg$0?f{|-R@U(q7+^`>jjwo!Y_sQzq6&jiT>Nd zlOVJVwYKas=?X>-baLPS_JF(3XUPJ2C@#e@FY9$VTDTfb7mA;R{pA87uShYQ$dP%CNiDobb7#6cnr^$1D;E>qUu3sfAFr&}?%iY? zN=8Ojrqh$JnDjP@z5K^eXQxCBb6MC%{_{$km#wk9*xLfsU-(&`R|gw!waRtqIqpz& zcSlkSnWzN>UbcGgjc2cVUtsD($vuyk1Q1J+T3A%GAiCeJ%M$bb`x!KX;7z4m+dQw- zj-+C7W-d`tQD2YzG4NBSki;9n>-{vJA>!3TJ5%(Y_Fq9)m6~En*rz5ZX6aa&PoL5V ziO$c@<8AvJR((r#0&8n)weM=>pli+mg(P?+dkR%D^?zBupXotFCnOVaq7%AEO-{Z& z>!+MTI2Y~FalhP)>$H5EA?BBXITMiI*wS*bd=8FWT+jigOnJ7-Na`F1KWX5H@hH*P z(2ujH>)p!MNA-4#E+Ld$;f*L&>@$&9fBz&|b=F#p;q%77?J(ZI-x*0o+aE(h6nCQy z&uL;eXpiL7;!8?RT|C?Dx2o9NvusvS#LYK@HFJHX-09*~ZBw8aJZf*4_ z`T_p9{hr7q&Wu@At=#Z=*^&?gDbP>`p3~fBwrqbQ_uGbmHlCzWO42(ySy|Z>di5Q6 z*$OZnnm^CJBOeki5)g|@7>A-M408KE7-&3z@y@a4g5tdAHS_em!xnphm>~T904Rh( zIYpf3-$G}NbSXWHX4$xpt_CB7==$!;X1O)f=lbXTq&?^8E5SBI(kUkVtdF(k@1Btm z^lWs4=HtGn7Z-R9u>;u2RXKL! zY0a*G&-by(1=Z`UHR?;LH;7SOxRv3DihiFUW04IIp&aBFLr{cVT8M|0Ts<{}^-!on zxAF}-<2zse$}@m`g;Ot9`>L{89AG_D5{KY2g*#k0EBhq?jyRGB>cZ?WUt@-Z`qs+T z-OCHmqTW?uBAf1HL7>(r#;s zts*p^w+?1Xz5lI|gA06Dmwl>Tv!Qk(7arbk0BiT0WBJ|Iupv#{B zi>|INB_A8hVnb62M}lA+Qw^Rs9j#?(MO2wYK>)mLH8@a_3+H6J6raI0Ka$`Z^aejm zzs-}5Bb2N$R+C!~(f{GS?C#&cHiiuMHBfzh{URap?sXahOc-SVnE_R)rCn=xWE|4EC%Y;=#k&roA2Im4kuHXUX=3SoCDTJ|+v zccbsUqQkG*KXqf@-rt)XQg4`U_IH27mWw3r)S*%pbSMXsWSp_;(GWeD7J6qE;NrwF;i_K zH&Y*nNwNmR!AK0Nrou;w!sd~D>P?7`cfqT|4YYg%Sy5Fxnyb@5+0K#(!V#+uplv1% zSR*p#guqnCO~551WJ2J3lY*uA9y;FNGzqtSNI=tlRuYB~J7%l%v(?)Sn0r{ffO!2_l= zp}$7*Xrav%;+?2xh30C@I2mvm={q@p3yO=2-8H1?n)_cHp@w2nt;B!#mC}3#1I!|? zf0nJB13|{7IJ~ikHBG&)a>!#M=DEY!NnHMIttYNOFX9kr<$ga(5!zc#kdV^?q`w(n%LOb@iMMNI5Yt~7NfRvRYsS46FL`-<4~8Mt(O+XaH2v{MsHl)f=_Bl~`v}?%k08v!FWTIhY3aapkMab_0q_^W&uG_#aF!xzta%!rshu!UXDc*va z4Z)o}45?7*XHJU0SgsV|!kQw%2U&PzEcLwU^M(?LbAUXR_qPV<#QF7gbX1gva)F<` z;bOhr#&7MQBt{jAYKwjwZ6-DRk8Tu(*N5|Y+KI!--(3IB#^q>ZcjtiZCNWdh=LdA~($dmgk14r0l;=7=R3*RLU>}=W8#65> z3m-wm)>AMO25&!f9Q_ODVn!Xq_5Tc9N2O!$>ng{{nl z5tJvJbB^;mUTU?{K#Zgoh|RD;>5^Bl>VNqn2Jl8PQE(SIa}WN(+an6X2+x^(jz{zx*<) zAL;M!Ul#iW1jTtRJJ8T(Q~q>AWVt|Tvnf=%R)u7Ndu0MZck#7e-d+7ww&o3%dlrv` z0}D*hkb{$x@yCGja=ZR$a-dO**LXRtvN{-5GJ?kfIXj0^sik1SsCcF;{Re3NhSBe! zC(A8=B1swNqv#&mwKV*TOFuuWA^z&kd#V3Qe-;i7J6UEX;w2G>{&2yTTV!cqnOM8W zMFHT)jqef?5_zU5#9_umKUgd#f7KX9B(dVu1%LY{=6MK(KH`s%kb zDM?ACW}=Zlf0A~hLPKN6Pzva3+o2*{RwD=xx<7i}R$MSaZiFnysb+kb5dK?>l_POv zxT9$pb->EVn9yi8l$f2JefSTvT=$pzQj6PInl?TK>QGmGOf_a6_@YkprhVE_|Pj9s3Dai z(bD@nHX|c?1qB@)j8aAgo45;l6XVNDgAVq2`SBN=7ByD`7+GpF<(0y8BJt<+e718i zdjiwtn-m7w>xi7~{AKN@#pBVRK0prX^5g5bn0(Gd! z3RSqdx!0Q4SNA+Ap$J7T`;&mvf&9BA$_*Ps9Cm`Ff39Tx!F*}|DfIG!hgUjhQxdK zy?AC#C2D{^*muXXrMS%L-+n*6yp+ys_x|V98%=VG;7eK{j3ag7%nU>Zj)8o45QUBJ z)q%#RPfK8T9_BYOMKVMjxRZ5qs!{UfjQIW?zjMb~p@`x>N1UMKn|nT$IjxnI72&&| ze>JUT5IIp%E-gk<=$!`=;BX7KSt!=tl^q9oNU|ugv9*JP&WxEN?LmQKcOyns*ovidk=gj zRYPzp*C^hnQT8MV>C*Al@du4WwVSGKMunJeK* zG#rjUJu)Jq#3Equ0g=ZobS`3(;P{U{?8A*G&*V_Ja^O5U))7hskvTCcZyxlWzMSO$w$MX*K)gZNC=1~#Q=E4V@cJgn1$een*`_#Gdo|ebiMlV|S+tlzE65t$TiC2)VsGf02Ik z!r^O))`=Q%;~3->1k1Xw5V4jrYk-=X`azS7KY&^)1VuFL^mq*x0RL-VF^N52GNw;X zMrI;&Z(EF0SEs>S)b}AdZ*V%OBE%H8CJb($qMvTCC#ho;aEaWV{0lIjhlLRJGXT#6 z1M)UjPJb%&)_Ii|W(&|QEG#@pP57+8zSL}?5y4Kpe#DmF~FhmtH# z@YNB~B;G%m4c8bNXp}*aaAyVkkr`;m#3_gB&;c6w^?Qjg1j%#V=FB0EDJAi>V;3tgPG|FH0?1uG4T0 z^MS)$!rFzOI8eY@s?5yH^rpB(5g;$PJE9HMIaz7z!sZ2p73I^w!~_>TeQ#t)=R+;gG%V}DyQIf+Kz(r_JuYqn?CA&s#96>j3}Wak z8cXJa|E^Mp^Ez2yVkJi=q722a!G0A>Pp{Eo9mqrX+FQ0$+75QHr z615%Rb8P`X!JyS0my%M!FIv-U$b-Jk8=WVFW>tQh6Gvf zb7jL@{DnnC<`K-9Ao)+K@ULc@+f08bOnzQ&4%ia^P4I{GU8ZQd{zGWy#>Pf0Mi^V= zM1g9yWOykp)siYC$Pv2_I3WZg$yU?B$IC6W_*fVi(n4!KIC|AAo$T!Fs@Q_vh>3$! zLZw-6f4q`DzSthxJvjKSXbpsSkCxx>Ec20+Q&+$(@%sdanTVlv2Vpqs5;W?>ya{(` zzOvO9g}~q4Awx9PkuMgz{ULnSAS`b=Re*^={)j_HhEXe%*$w;8VC3fuimRfdqZ>|n zgC0gH=G$sD#Sme=-SGwOXN5*7;lCeO@LQ;Ds2-1ZS9E2pnq|c4?gg--@gGFZ)5fk$ zY1n?r$@-r@Q!5FY=9xVqzVp{t4%44u%Y1W6S7A1EGF^;EI{kACs(nz&&z~}rkOvmc zMu7amx{h=xv%#z%yU1$C;vx?<>s>Or+k9lSkOwkjZ8h(VJT0Is}=17qAQ5Wu4lr#yet)1Nj-L*cvO}b<}hXq*8HkPj)-g2@7v6-tfP*}s%7x^-` z&Yn>bmz-RAEWSJGJS}4x-E>(&t%nT&H##=9)~8C$l^C7l)ee=>d?qJqt_9S^;6oJB z;WFLRC{gXto_^@dH`t@fwqhYa$&fS<0};L=L&zJ#xfrMn-fVB$%P_I7EYo54NOGqa z+dQFaGiGrR9T$Gmx@;FZyp!Xz%OEN}>As_7yVr78{AfENheX4S2?RY2kmoIFKP*}B22DTR9Eavv~NZ&%wW6K;~My|?hc%S%xy^7f_f-V?T8Fm8o zX~p&foXqK01PY0{|99N^6NIfoG}xEDQ7nX9y5kxLMrJbBVd0?`s*O-CV21+{yanuq z>=qDGbeeyxGK9)LZw)47{Y_j_GNEk`fe2Q4-F(i0KXjgsl6YbIVBlpzVIp&ObmkEn zXnT%AC8h0Wixw7oYRXmf5GYP3fihebg%U~y2gQfWIYk+up{bE3{Ah-K&on?$Pc;DZ z53;2(H^s(M!6$}$$$j#-yx*h$7;t+)djk+Z85R6a0(0|x)UXPSVa&&`3tL|D%iujyihA?A?5SP`0B>BOI>@gthSH$$ z9l1xb)6qg5$s6me_{hjefW#Mw80ZT!6=Zd{U2@Ad_dUI8>tJN6OVffj^OrW_*s~Uk>Gl06X}5 z{oMny*OoY}3JEUraIJ6;c|oQdFkmPo%N!=I#p=J7?*!Hc0&DQDsb>c@Jw2jH<~f9}xfj6eRg;;IL${*1ddINaAk;^I_i+;6@AZ6^t0|MI!?&wp(QgItIS@+f8T zuSOt>z$I(35X06tf16^+_Qui50hi$dtnJ(cVHD@U(fhJLiMaC=Pp^1+V7cd8#Ax!f zJE1y~GobQ!Z`>PJgZ8C%L!6PX|F)f`Lvd-1IpMPKB)j*^@H`PLC-W2##`Y+zM76I@ z5d9MV3f9`eaABfe#3b+2>3WwF1Vl_8v_B)Z7VKttVQFM1(|b!;Tfce;h^;Kmx)=OS zz@nL@HBW?*lHYZIb8^#QxpMC{#~6Pamg7`Zy}_UL<7Reryu zh+j*EU^upB{9w@vhhlCcON}U<{!|a1L@v>)JWjqTG3k#MxMyet6cKmsj|n*c%aY@+ zkHTuTU8IM6G^ETvDkkO| z{=5`#HY7Zo6AQIrg434uj+FgtSYmEIWpWa(xtPB`n-<856$vdbuBi*J;n$3iTOR)i zHL8)5Q7;^2>PAMH_i*sn{{}R_&zq@p_SyeXaGU0%D}Q z>P6yJt+^ODl7nf==NSAzQGZ=?)E0|ADi?^`J~9B|u!y5*&cXM{mCGVGnzw7msm{H! zj~4fm&Z!b>rIqd6tK$9LcWyt!R+^kGiq-N>y@|PurPcGr<`mS>Pw8aJ2ckKbEao0# zrD|z0p4T?3P5Mu#+*W-UO>_Xo$dE|&7{D;lcg%2P>D~6nuI-p2B91cFv!N9z`fwSd%pY2ae@0nHA@_t zH0=Ty8H6gy!8gr5_g^j-ke18HIs2(J&Dmlfy@=nD^4j|2MwcdVa5G8>7_G-%~kK0*b!zX^aD}tjP*yb{~jYgjrVe8cWh<6=zEo{2=7|EO9!vG+! z7k;7eT%p(Uz!vioqy`{v&2=t?|4^h#y@y&JOEVfxF65BQ#pH$hmq@}8eyz0zZWnk7 zoDW&ghwW>?B>*NZa%Ug`$*yjaMy@PoOtH5Vq>G%>0cpwYK51}p5Wvw{H|L#E(f(qC{qPGVQ!}%XOfgE$&dwm@-n=wG2>wubaO%VWq}38p z=tC>WdpX7F85mNG0U1Rfpx|&h5?$w&XBF z{dn!B568|>mNbdGJ;<0DjI1_;>TWgP9+nGY#ARQC(`vF9NxLTMB!oWe`JE_v@%Yj%6*qE$o}4i>LvSRW;&4?8}WETtq(^nHD49s z)^f>ycavCGOYe^F?ddwO+OyBIZ;$YDapg%{xiNNwC3eFT3&aPL|Gzc+b76;c2*}#i? zkl)}c0D{^0&W6{iYK(u-V5WS2T$$(^K zucRHmQagZG%b6{#_~R8~$KFDn%{bgRBDjPS*AP3;hk3?^(**FYK#>K9h+sZFAAoO2 z>WzV@X{tw>J&T>Er{I&UeaUM-8Wt&uJW18B;=oJEdx@*EX~G1;>9n-z>1lsnYNWp4 z;NV!E_Z`nq_i8`%m&qAa)x;hzKfwBOl`s-VwkcEi?AdR?JbV$D!Dzc)4n~h*{m-M& z_Bsm6)rKs>+HjH}!#)wKS6p*d-lN%(tXN((O6x5~sZ2Yo^G|yCi zZvH@SEFz+;uHo0*WEpk_?i>++vR;DT$Cm)*DsnabVMXQDU%s!vS6zMqSw@fbZ5auQ zMnms!=fqoG^J>faz|KoD#$vy=U2aiDPK7WuH$>g}1;XK)GYk}3-D}uX9S4&;xLyE- zUh#oKO${qt1G1f)K=G#N&aYp;45gHH^5%0jf?6zI;!yNEW`SZ-qmQZ#2=tveK9;C6 z*Ph@y;W&^xsi~=fAQ?cdNJzGHH6ZvjF~9#xHpld!LKVtl=cPtR{S;~yT*=uw8?BozOBm2HaO~rMMjSrUs&@GL*xg{0ydE%6 zP(&6lt02Bb3khjJXn zF&iurI(NWF`a8ia&ExVZsI08aVNz4q^9qarWT|kyDaZKerb)&9SnyponB2bYz zEN|Vp9W4+zX?PkVgxIR0?@dHDIq&{nmy0GtZF&hpg*Z>JZEtTNGcqzNDx3xC)Z6Y? zViP;)^~X?-)tiYQ{He^8JNsH!?A6l91j3^!?xW*vIaO;mA7&B`ZKpRlabu$Q!=GAT zPO-t5gWpoTvBvKq`3%pB)(^7+0uHmtWjPget1yzxfxG#Ji_7u%cjj1OZCYRiIxaB? zfu_!f!CzKWpYl2^Cvsk(!`BD1hedqt$L?4d^hk6ZO>*LYys7G zrz!Yrg(v9TVW%P7mo-71PIpr654wP;m0WcP%fRxkcwIhSebniR-}9pFcs&j!r9E77 zx|rX}%AjkGs2}Ndfl4O3nW6Md@dvr*@Wj8R_Ztx$WGvNthvQ{_n8Eti-8dxXcK@JE zuOhtGQ2OqQDp*21){>W3y1+FWxLhA0A&YgB@dgE}v_lkc7yX{vRj_Y2AaP>q8EAm2 zBoGzU;rkn`^P}wPokDM3dUn>Bus@((@Vdtm`>{zPl|pg@q$Q?lU12Vn)O?%3icFjm z@xDEs%vZc_Jb(G}CHvs~5iE@d8R)G3O&cMgnPP{BmHMf;9PaW(t{tG9&7)}ow1}MX z{MMh7lNK_+EbZqMKGWt@rM|HtoTsM84k|2aSnN~{xx)VVdKUL-!_PZ6Xt47-O5MQ| z$~akS29kSDqpn~8>?v!Nw-L{bpwvNd0Gu}0SsXVIc34FRvJve@n4Rv^{?~`>U!>Wv zQTy4AeEZhO+_$H_frGs&vIz7JF8}b7Tb%&m{>4plEJyaY=^s1vWK<5Z3&6JnQT}e0 z8+LOZPycp5sHx?d!dh)Qb825^1!-my>c4p6&2^_H`ZrM(gPrm_eN# z*01Y+-DF8{3`$%swS**_;qnlRA+osMMz`0#!JtyPmt1(A6y#aJqNYeZ2Yo_fx7E~4 zY(npNIFDFSG%A!1d+~yhh@=_xAL6W$Y|VZ$tEi}8C$Fk~GJU;b;=Tode1IBswn7*$ zGGoT|F@={w55{Ue)<2sVFZ@+jAs0rt-SxahrUHH9KKYz$^pqt@IvGrqc^C_a&6Jx0 zdvb`|ExGsn96j(wvAH*RcLnd%kImw$eDk-77gnQ38@9Qf^LGz1qt76i3>ozj$kjEh zkM>~PU_1NeV&XJ8By-T5ueQis)H-ec)hlE)gJWI0z|YoKLX6s?o?*t+^T+>vaSUd) z!#Ghxa1Bt%Q<`~tnfM07K9T8sdlktky~C8DH3J=;JTJSD;8f9QJ^|4q7Eb>17XkE; zy+8mm_EQB>N`|Yg9?rnld{K^N(mcHDuHqR4U0|gMF~cAgzpkGx{(yY&LEm|!{&=q1 z1VFcAJ8TrNHV&60&zk02p7D3u*PXoZ^vbRB$tsOF^B15d_z1#_Ayb+V{MRO+9T_Vr zp!v?C|Fe%qk?MLFV}}2_DMuO645)+YKy2=SMi5MB^BET#Vei z6RfoYyi#}Yg7MxbKJRh120u?`NeO-qvIfgk@Ga==?3l>PhD0NmP5hO{0IB^K){n(% z^p23oOZcQ7LJ|y@>um8|Uzw4+ul^ZGQ3D6$j}+osC~iv#B4fySxro4^ws@`w`6>5M z!Jm=UHm^S>ZGy@rto<_S(Y_Q5Yy3g_W!hZxNx7+xCo3W`BjfbF5i-c`cl(7$Unh`4 zzn9JSyCL~Qp zTM7lz7?^G$*MrOBmJ`W#Hr!iP_)l1`?Lh(Pn$M>ZM}QnZ>IoIgC%Gp358Tg%8lRJ7 z&|xr^gzK3EE~a`MxU&3C(h)0!_-TnD6IL&&Z@*RP(u%kWCT*H+P0GG z3(+X)Xp@r=w-K_zY|T3sYHDa=Gd+_FkT=rWwC*;*K%}4i1X45q?e!MLKg*4dxi@$c z8h`nj8e#t}J2UD_^hZZ99h?tuXXgSzr&6FjKV&kF@5QlF%4-Em%Rx)>QCY&a>OQks ziIDVImG8*oB#wZ9&V9fN8I@&WZhmmJ;l83K8aP4I>~_LFQ(@2{YUuG3e&o6}Q?*F5 zoCM>O09lfN9IVbl&Ts4{Cr$pjUh6zzN{Uq}DH>twCV z^}Ri0gv793d~m2>MIG}<(pb{vzpxmwCrexjpH3q8$)!il-49V!opXdR5+Pw6hQ0`{ynOFVFxFFm9uhR4V zl9)zZ{_Wd%6C+E3(cJ~9)V18Cu#}q>uQ6knrjy{;ZS-5^H`%yTN!a`^)tCREDc(f_ z5&@-f2au@VDauERngZARDbda|55yp#<~nlb=d?9|yJy&cP8@3J^>C>IxDFuS&^XCB z$mQ#7{&*@xU^aMxvKz>Oor;xjib(lByK9Z@yO z_R$&agX~F7pO*!18KHlzCiB8FCT=#yNnL`W{CeyWZ#EvJ<-S8DjDrLT{Y_i``r=i< z^`3jou{QcVQPi6uk;L-Qu`u1kN$jixyfCIAcx;2U#4db=;Un zda^SuHhdV?lgL_q_uuur;aH4q>*BX={}|A6WNa=!taoGlFIY?812M6C?0F0L1yA~@ z*kt^tAmmFtZ~R~sQdjamx9@Piwt;Z>h6W@V)W{(l(Thbf zy*?L7D~+Jan0V+0uw%t-Q9@|~vlT(%Thvy?gqivvAD7fcNke#lhhZmN`W&%{@;Az0 z1zzJG6z!up5e`9rMUo$2SbsK#>iZY@JU`wn&;{wafRGn}X+d6I8u((xay!6>Drd0F z<_9SYyPrZt2L}@vgY1OMz7X?*Wokw(^A$f-t& zj-dT~2HuW8%U44mLwaZ!UZZniVJpG$D4i(NU^0Y6N$w z5aGgdt89E1!5JImT+iq()vx?1zqX5t48T4&EnS2^IBOiV(5u6li2hl$V$H_4T>Bx{CW<`afJucfAR` zJNUz48%-@b6;l0xn-r3m_*zb`Gxde_RI$<4#>Ur<@!hFnN-{EG`>Ef(y}i%%OT_%I zdFbh(8*9pcoE9;NSmUNMi-IwT*`>CLpHb4#a1DRuCW1sh%-NT2^c9_9+D(^ykB^tG zw|#niz(YX{pP8L~I33_NCs$HYIXyd@5coZ%aIri2T3cJkUd&}#O1e8)4~l?*aJfI5 zn38h6+=kdl;kA8#bLMw-NGA;r_|KQZ&+O`y9jU?AYDJ-=8AQecHr8NB{Mv z^5^87G>v=|iTvA%54U@zEuFNztBD#C@uY|$F_c2h98T|t(?wS61)UZQo;!!4V83*S zIVwNuLT1916PX{*MkEb~5;8I*0&YG2CCtvv$@FKl7?RUU28ub(RXvlBOu5sFBV)C^ zI$TtYrHUXR;WDm$H}nm>U%=Urkk5Fo;%5p0yLGw3?$5L%Q|{pW60ki_R^{D^AyU8SvqN$D1v_S^LRC z2KVaXLYD|Zl3{ptdAU^|_jjrFNQOg&%2)P-x$3A=OBf7hdg<{?JI|6rh>uVE zC%=%8ko?u#CST(A_#+}ZVc{8LTff`$9Z&#fd_zOR?@uj@OQ3(=U+$+u$Mj*d6;^n! zQ*ocpCp3uPj|ISl*Yzjcs=N;7*eaxQbV8}t!)4eBj^_VxbNf+H>HkE=uiqibV}E${ z>J|7is+$qAip_5D@;`j|a5!7Z!o`Jyja`rBciDzYJ2NwbcB)rwsM~tSi8BhZwzih1 zruzi$Y~`{MEWxTalbsrF#L&|IW++44Xv}vxHS!!01#6U@))=Q;AdQUT5fqCoZ}Y?D zJRAR7<6=uWx#bU$VmT{JGRv zj{FHpF}(?bK{ajQwRBX#<-z=PNCHb}TPSMfgYdh-6l349&IrOTdOk^fBrFR4Ps|1t zmdZXpK5Ze$JBjblHp?UMmnvIMQ(k%&I*Ah!5*k(8S()}Y&s8aFsd#vt&pWqp_99?w zVXOP7rSi#Z;&4C2Nj`gEc0`6tdJ?v`8b`OZJYDQfGvz@QTsuGE-=mePXeEn~&}?U1;1@MQ8#XCW3|-t{w7uPsr#0IHbAy;E zT{4KK(SN-+o;KhdUjmB#EiNt#HVO0YiX^s((vF#QBR-y4pInCM`Ixi>KIqKjG0F)9 zsHtJ8PyA3OJjMGamBHHG|9HKI>#8B({Li?#kmvW`1iKumU<3?&OV{OAC@0t7dQba4 zUys9uH`Pd_q@?BNMvBm7cklff=@&Ac)`KZ#&d#OZYJE;t-v(R|i=I+aQr=A&IgcTo zN_1-1`dyW<&3^%Nbrho%QT62bcsXt3sO3pdJ!q{P``hm~mG9Q+S-Ik$ccpM+;8*@0 z%T-L%op+qC+3}DxCvwGynG}*!3ORAS4n@VKVRc~q8rb#s>g#iTqH$+rWGQ!s$ecPb zKHxn1LdgvccPDE-wk4lFq17v?;^)1A@;vi7+8jzNzElV_aK1iXF^n+du&MYg`IsVc z^!FEG#&6Rm!+07&)6q8{ai~|{($jdt5lJsL*838>-eNXr*L&DXSZwrvwW3fJK=AVN z+RSS)thV#-PiK`9!7eKwB7N&GU77U)59v8OT*9dGo%+$gCgPE{Z+I9JjUK{$92|pj zn&ha_#*>A*oP4WnxHH@}Y@-1oop{6v30C*lM!NT0ri}%5yihzXK`RA??&PGZw&+cww}y)c-0BD&H5@hD8{DeT=0*;Wv~}}iAlpp* zj5&*fXW3&HbwtL=EZ5rJ$G{amU7_EE_qwDK5%7Da`Nb>|Y)ZlP2}MQ4=>n}#N4rnLFA-wYCR+IlPw%p2Kb|6o_}a2V+Hn?{QC_^J zHYLU-ML>J@en-E|(glTchg2#X0tSme1vmEJLft6Ftf*L+L^VkTCQ<7baRRA)gko38#%Bwz~%$=l|jTNKy4 zmhvR$;RvI{Y<`n1C}2Oeo<}SA&v++U2f_=}DY#K2v}YoG4&i~dLgt>kbjD?*q>#CX z&+xoT7ltY#U3EQqtoP!}>rzuu^=jlQ#Ax5kDI&~s;Mf!uc z@JD()cgB&K!otE*?j}dIrAI(3Ak@Re5w+^5Z}< zH)UdAA`?-TR;~gg_a~~_I6XcSWca<7!gQ0LH{pvJYvd}hs+`p{G`50dw%e~rm6Z`R zNn9A-%tn>mq+(C1vnwf6AzNxyn=`Vmk}8&6gH0a)(_yy4aw1&JBN+C;|^RTB&4h(`c=!7p6{aG-O=P7hIE=QU5fdv`bSyH9$=WC zd^(S)`E4}8M!McgD0+>Q6^dv*oGy(@#)aCwxjmL^38Vai7)yChCnmPg)5G#n;4iXy zGqtE!N=1+94YcZ|=dRQ@E%93?AMDY9LTBu!|54 z*O6EHlNw5h(&FG8LDn9WC>`%M!9)Qux=X`N~&iF=0A4*Rk9B_O70h_WrhB99u7L!^ku}?Lq zgdHLv5|T<<2oakh50v9ur}zCvEhC*0Pgz;{nO4$iEC<<0S=ics7%}S#R4A_9kFU#M z3vpn=J4UqAO1=p>)7%kf#U>ELnUKducloxzUdwYh94@us$^(Ei`IU^~nxTJlTCp{% z?j2$w7EK?862`HG4chI9u^CgX=U$RtXO1EBZfhjNzOkGf(gSxi>rE)_6%5)@XE(|I zC_>q!`IT8NL_*SK8Dfqo2fM%jW+oLq+P*Bd-|^+k7uulvcqXwr43E{xBK>MC)ZY*r ztbSNt{53xWKf7+wmLdq>Bw2N zRN$mD(@CLQTJ7YcgfPY@Zj7d;rfQJ0K4W1GEqNb@l-CYO#(gOmf{c{&?y=F)Se)h0 z4a&0CP5Y@38e`=`C-OD))mx9o=m{N<^CIbU!BAw^w!1OXh1W?j;x%{7!)>Y^=eb(HpJPsl}x*diC^ae2HCjkP&c-$k2&#`wWH)lpUe@aV92 z!H>K=^jK0JE751g#I__z>(Py`JW+Of;~B(6>28nK*47RWhnbnrAQ)r@s?Yv?#R``9av3`b<@3eou_WVRjB9TKvr=DGVfem1cLnMao* z6g|tp3FeAL&L>xGj|L+lRwYxL-Q;^dkCn`2Lcth)r^&xG$j3)o->dgEw@mdq5`{|($x3i_Trr` zWqWQ5y+SZxF0EF=qN0_*Tc@UK?59fr6VP>`OyM70N@US!x0X&>-oWm~< z9I-JEV@+@+njNd~J~B=1JedEJ$zz7l5G1=t#7QIM{Ewd?svQyD{oA;XkD2)cZDZ(T zs!0ygsU{RQKZCpiE2vNE`_dHX14s`)DOpHezAM~-nUN7qf`sCk`)>+l8H&JX==dxt z?9KSUDaNtpIQ2e&HmOojQc?n&(!&v&W7I3&=W}yv)u$4Y1Q$unQ$&F$7jgw`(C@^5 zp{+CPKneUshw10%=U-DkXAi}I?5RF}Shd3*%yr&IaUs74Os4QRii0QMJm)P;s!9J5 z_r*kbsVtA;)R!WXc>r0D#q0Sn4#y@Y&f3Eg|vVNa0>d3^aa%)-FZV zyW|;@9MrKtkQvE$=$in8Vys-|SGL#P0|S`xw}1u^J-2HmytYa?mBJeOoR==_D&tRw zjay$V^5Vr=YcS%(PxTjNJ-rYZa_@cj&DoaKc<7rSKYpN*WU9(|&XXdWX4gmPW0(s9 z>YdR+@4lF9s0kfJKzI;w-|Tfb{UOzvdPa`x!lHN8Dwa*WNx}zfg@X$VxL)}b!w5QMVz)>bJSKW%LSk^IaByif@R)>PH~_SW}L+~{~VLn*w7#YA{`Szl59ML2cU z5EbhD$`Lk^Zd9AYI%eT{mI1?kU&Uc6h^)EXBHC^VnZRVJahT-`VAv>@E3-SgNcc_ z_-F19T<^QMpI65RY{Lf4Xi%;cpwUgL?TCN#@k0wyh+EvZhU?t7a&mH(nE)TSAXwCW zCjnml53DT&EFr*XHXckEJ}mF1J=b^lgLJ0RTnx^z?=k);w_*J+boUJoRfm zpMlb$^6sSlNwifAUd|SKFo`f1u-qDaP7rpFeCgoiligSnJ4*(Xq1{jNc6N4|5&=XJ z^bhxSAz%muzIXmNMA({hCfbjN^f9}G#lU)bwgNVtw;{Tl=cnClUZHI7fM^zA8l+;n zip*tD@38~Oq&@b<_3bU7@^)iAX+q95wi76a0;MgzSj!eWD@>pYbQe@F_&Vn2{r0Ac z&s&Z=ELkG+^I10BmWu!*@MzF5Hcn4VqkOC5;lWQX{BfSNg`b{Y`V{ZGKYFdqWUe=x z+JXQa10G6IYdCrfkq3>mnY`MH9!DH2+;8>kZ*327f+20h+4KH}h0QBlnlL3B>ecP7fpcvNjGT3RF* ze!dx)^H^D3mGNe1d&lPQR&L%!KuGw@W#WJ;|J8Tx2UB02vJ!+c7MT`17cZ}=ro-eP za_;sAADH82>ylZHkB{Rd8ztG;*tUu?=y=zw2nL3;Dz6HQXz;uK@&79`lRb6WpD8bV ztK$7LXeihz4F!mX)-kX8pOp@=E;EXouh^;##*DwPxYkBBdcXhNRbXQVM+V<}e zHWl7re!e{xN>b!|Cks}IErJ_jIh)^#kZL;GGX@6aT&eSv2yob`4HDcf%RwK5F-f`h z0maHh<&^RI`0HN)k`^Wg2ErO66GO#d9x@S9zD6d>k&3!H@sHr3P>w<;djbdtnsEWp z&A=6)u%n!f&}brt7P{+3Y{cc&#NC0321bl*Tqus4hX;~+h*qYEJ2Pvh9en|hcu1p3 zgIB5B^}wOS_yweFzgiZjv-d5S*{|9x09&cDONzv8j zrcpLgba0&+c=kq>b;~~HsDxAmk%Y+B4EkGg}6^7*UuAMw|uooybafV`JkC5(*JqJE#CkY`>`2pC9@|(7E~M=jt{Znh>Cz z0g?+qA|U2W`C5$L?*O;oc^Hf%IC9O37IGJ46pPzg5onu^%AaojfDx#T6Khpt%R^=Qh?TC4tjEsF)CzB%O8xZFEg}~j(1R>NrEgm#=;_;R5VzR2cb;>= zruQa`6bUrB~qD?OtA9PCqO9y|2aH z$Nmf4%lkK0Ww#Cph2w@Wavbs*vr6y1sTk_XxO^#&3(0`nDyLh0i@3iEo~U*a1WaCs z3$r=$QDF2DN|xD9FrU8GyR^-1Zf@4d5DTuNhwD*qtpB+TUSr3p97fj^BCsthtFD&+ zYT#}8%S7pP18qN2B)^|Mb5vMhovMN?V80uui1ZZ)UR-pF}51vKpx~sYrjMe!2?H}A{00%wW9I~*mSV8TT)PdB<>U(u|cE-u3pB|}bQ=af5 zjRph3nUETmDSJAq91<-ec_)v;$dlLK*YOR5j_iH~T6cAF5`2^2b5OaxQ1>DozUxU@ z7gkWfDlw=_Cn7T2$&+XF$7!t2@$#R8F2C)#+^MkK^9}`l?Fd@PO76!@0mnI=D?Q>p zABYK=utkrHNWx|&1FU=z~**zH{7P<`*ws3ysw{&VRZjq!MvMYSw6M z|Jd}5y%fS!^*2M`1Q(Wc!vb-Cy_hWnt|co<-wiy6lT$tY89zTi9Ua_+?`uZJ;lTlR zDGM28U*F`!DV(4^)YftE&$2W>m@l!hu_1f!hWJ2-?&Mn)n#z99bG7-!KB&S0QGEb7 zoOnxvjSG*D_iDV&LtEVk-HgFh5q;S~J=D; zB*#sL7_ip+0SFPAN;_^}TJ`VA1%Wa{A1hR4WYiMb+Z}UPU*6)-P(+hCQ(zbrBTH&h zcJbJRV-V9A;)KB?K1#=!6y_qoBy5+p-_RItbCzY(%IO4i(-z@;;Hk>{Qu^iBC)%Y_ zEppt{%n0=N{r#`Iy16wNcqy6H-y4pE@ycNlGq77=?0qD9_q!r3Pt18nC1Xlc0i8aQ zcoHXm>^8gVL&`%_L#clt?N<8T!dBpd-}K!@kN8!<;hyo<%Ps$sy<7j1k0U(R9-amXAc;7I-tKq=vLM@T8{Sh^RO~V*QDuLLPVztJ;PR*s{adRK|UN zo&$+xUs1obP?28U>gWS*lF3l`4dxDNL2#Wwa&2qoqm!9b~6q7rdkMXCyN#5RJ*V&v(_xND>f z^AuDf@ zl-rCwJ8J@B0gx!7cQ=64Yca(wXLLvELTrrrwzE(g7asak!wYG$!(oy~GWP&!T0+Ut zSP+Ot#&o|l7ZF}63*epz(V{=*Nw!(buDuWvB3(Q$GwaAXAV$zImT6PouP+EGlC#}k zq6O%Kr_E}L;8dqjhb?*31GsD-C%F!ra$a(yTS+TC5c(%}Uh=y(kZiwIyEgYekJVKi z>dDft@5um~bhi{su%~6aQg;FX4xeen4U^lfS|sb)#C>Rg^%}?e&@#rzJ|2*3*#r1Y zLAO)vL^Ph6n7HN~V9?qAH>|VXa}N|-5#^6hm7aTg3y&361Lpqrz*QL?Ga0k}<2WzK zz|e6xAp}&oAx&T3`kNbY%Cr*x!oJ97d`c95hMt~^$^ZxhLS~%mI6!gh8yn<1SAT@D z>@)z`Dm7`)3;UzfGgj-^e-NZ`pY1Vl=NpiTumAH>^e=TC@(MmxHI{S z$z|k}7{ilR6YoW2%pb9Y0CusTV^fJgoKIXfY)|BWUVGEaNn@_e$ilKW?lf1m6R$`U zEMT0gfNj7Gj79mQ{AqX=Zvwq20UStq4L)PRmbFSjW+&*?@Nd!M?M@#Sq>O+!lT*@h za z+HMl#Wg6C2k7*@t41C253z!0|y9p$+qhnXwV;yT=Ze#|u{>ReS8J!kt;Fsl=Uc|$p z99`GWkKq~OesdXr2;^F7Ji%8M^91rO*QVjwbhTn8}q&h778yk+BW(H<+K61Snc;5 z>PS|uFwuAsi|**H%pi&9&j$z+IJ>jRfMfIl;cU04RN+E~C!F2|XdFT%V$XF8ks7xD zECtFwhu6@Fiq5-w7JIYn{T2>-^k2`6j}K0Z+#enXysmBV&Y9MiFlRwt10K#&E-)%5Q-YZ{&23o?4HhAytNGLLzd`f#A(&mf~Ix}d*dF#-

xa{owRCn!aRBf)VUPaD= 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 diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 9203a0ee..dbbd5b1b 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -57,6 +57,7 @@ Шаги Пройденные вверх этажи + Solar Intensity Время интенсивной активности (минуты за неделю) Калории (ручной ввод цели) Выключено diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 31b6a10a..e3ff1f09 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 5a5f7ce2..bf05eecd 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-small-icons/fonts/crystal-icons-small.fnt b/resources-small-icons/fonts/crystal-icons-small.fnt index 4f86e59c..68eee85f 100644 --- a/resources-small-icons/fonts/crystal-icons-small.fnt +++ b/resources-small-icons/fonts/crystal-icons-small.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-20 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=20 base=20 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-small.png" -chars count=17 +chars count=20 char id=48 x=0 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=49 x=21 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=50 x=42 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 @@ -20,4 +20,5 @@ char id=63 x=24 y=21 width=23 height=20 xoffset=0 yoffset=0 char id=64 x=48 y=21 width=17 height=20 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 char id=65 x=66 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 char id=66 x=80 y=21 width=26 height=22 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 -char id=67 x=106 y=21 width=24 height=20 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file +char id=67 x=106 y=21 width=24 height=20 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 +char id=68 x=133 y=21 width=21 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file diff --git a/resources-small-icons/fonts/crystal-icons-small.png b/resources-small-icons/fonts/crystal-icons-small.png index c171b8f5f28488920146d6759a3db0ed2880140c..0c3349efcdf540ff28b67bb45ac80f07545b5303 100644 GIT binary patch literal 5275 zcmeHLRaBIL*8PT-&Y??1LXZ||6mXsfq;nXg%OE7ATL}eZ=myE5VaTDRhEj&E z`MK}^`+d1*trP3K?6vkjFZ;ykYC|YUSx5l@piq0E@(KVzw<8E3!M|-z<;MEAjo3>~ zOO<$om2`I;{RPw$04TlwlOU)2HPZlq59n&@t9p5PEi5doudiQUU#qLD z8yFbm<>j@vw>vmEeERfhW@aWLB0@z)rMbEJ=;&yBd)wUH+|10ZxVRXJMDFkJb8~Z7 zS6AEE*wE0>K%vmi&Q2*QDMCWRyLay*5Qs;Q9z{n-CnY7Zv$KndiS_sQ8yXt=`uc{2 zg*iDnq0wkbNl9{YauO1fm6a7cJG-^DH4_sPK0ZEYXJ-!&4*>yzxw*NisVP!YQb9pM zX=&-Gs3>=L_lAas?Ck86loV}kZ8U_O5QSXfw?o}QkNkT5bbLP<%9LZOtEl@%2g zySuw}b#+BWMF$23Qd3h;PEJZoOEon$cXxMtdwc!;{fUW*d3kx=+}zI2&L$=%%F4?A z{rjh+q=dua?CtFf3JR>Otkl%hva+%+E-or7Du<3`yif;@WyC33>u~mp z?o>aryYuo3kD-9ZXS36V4?kHOBFZhm{9@p$DyN&{O<7MFZ-Hsg^NItk+>i6!qKQn0 z;Wub(mJ>r28$$|xo4Uom9(U(WeKP9Uch;BJ?l>~>@HG!FM0K&%p|on?%Jk*f7nU7y z=xeF?R$q2Gx3-FA4gP_KSqe$Yv>d`wo0{2av4a4oK$gj}$m}_ENECcR_2Spg1AOkQ z2BERt>kbj_LZ)#IpKSi^d)yTxTr8_afuIROdi4VjASet%=aKSgXQHI_&l>Pt&(4i^ z9OVLOZWoIFYGiVS*;@0Qs@0aP)zPVw(z2T$(0P%u;7lM#P@jNGZ}J3vux%wEPa0lI zX2}M+o`gx9n=*>9PK2(W#!=B(Uj=7A z7v7Z+x{R0}C`g|EX2cpkb6McBqtx*&*jBGQ+?$I8r-Lir`sgF+7fIw5vyzuN-2Gmn z+c>&h1cBU(lm-SrWV|t|cn@CSOqfJLI6$NB?>NmlUFc8;BuECgMtNDG$s42W5KNfD zURUz#Rf}Y%v<3?o{2SV1npZFpY{JqN8_h^`wRSXtSbO$(rW)3o+>X|lWP7Baftn#d zCBDIb8U~0w?fde!)|El2F2i&5MG!9)n^Fz&WKl|PH~D>7My_p=)Ju8(QV03K@|$Ef zrIQ~q3*F(l`G2W0e~L7Vepb?V@g7brv}eXrTYoRY)s%iVGNbBX&U}dPIi}{ zth$VGV**U#oZn{}>|2%GFXkeKyjFm9ErJ zvV^9y4o|2=AkQg-3vMxXGo=BJ)(KO4wACX(slPagIN01B*g=O*y$2X0Y8 zB>Nd9z)-0?j$%lMb+lLInkZPpB!mL4n zLd--ad-y}&u2aWlK*f;AGbG=VgXFuWH%QUexrH5=|- z4r)9OD5=jIcALesEKy9qbF+kczDf=_+R%t{oQQ9N+oI|5Eb-dwIoiV?0ZJ+Q3AGTA z@uVExPqF;V)6~0?0a>mg^6+78;|MmFm?M?;U574mst~CCs zP-7ITENPbO3zuerPl{4ZzE7wY0!df@!>*K=S%83=5$Fs6_=ADBtK7MTAaXm9>a(oO!U0y{Md@^3d0wjWpjT#I1>S*!k=D^{={hKv^vahl6CR* z4_o@-<@!N^WWiP+6J9E~H-9wD^lJB-?F9Xa57mT|rF+=`qB6&zPv8;{h=5SI&&)kN zD4^Fo_}R>7P`rWx=rbJ|QLba+nXT$zX#oFd>=~6U&JVC=nY=4dz*X*Kct<`0CW)4O z&Ujv8lkNy7xBoDVMC+9-xkjuU!kOQqW#BCEizj3FTp2pM7|J4Y_Z9R)VguswmEUOxU#?jCx+A}od zu^%n;CL#=3nMlD_J(M~m*9)FNnbtIW|HCJEUBh)(C42M)w@5(6s;NzPDLx?MZ$V{V z{QY=m!$Fi~Q#bvavHSodWJVL^a@V2O%^HRjA0DL?9`EkPK|6_Gx}pie2JTU? z%gD->4L0NO9PPX2kAzz%5gfc)?CF8M7?HzFK@i5#aAVl!)ULP4WxE?HRBGr}Bh7v{ zwvVH&l5T@BGVgkOfR2Yz^Lf=Y^0cM|+3{!mz=LnJD(Ua3`NJ3N__0BibMKpV@XqFo;!O{q zis;ZGhAO8U(pc0pPEf=-54WpfWw=x6;2WhdPKt45DjI_H!v319Mv@^ zKz;A%vdcYW>xwMKmT27tZ=S_q3?mvA+_HHx;p$)zmp3k6vd;X1Qz8{9&(6RHfOmSr zr=dfPw$47dHy7r<#^j}0Ja-#Yji&rt#T_!j8Ch+Ts$Oul(ElWQ3-{|T@;L1Ix#zGv zk!6kkrs16GD4x^st5ZHec~9#j+hScxSy-J6SUA}KV(UN$$UWIjwEy;`CRg@B$}GR# zesVNaIzZjASDCF{O+-Td_hi$L((Bm!gi5{fc{2sIRa4_kZgOLiXSqTmRxm-}gkLe$ zd6A~~qW>cGd)pkLd0d$8CYPH4RaW0wAg}S0`7`Fwukmq5vL0O*h6N%{MGw+Ek`+d9 zptzGe)|*(vdG$hPem#|=&Xm%r+B4(k;^Q$&%SwJNPOWZZ2h8jb_>DQ>EY&RtQOo!R zHGY9x*QiZDj!a6P%n`>voH`{5RRu3~B_CF3P<>mDDN2?Q*`%I@@5Dv7K#jUlRen%= z1ta^!9=*Y~_Z`Y-H91mc!sP@_ELT;J*0vAh3>0Na8t?G8nQJ9xH(zSKdu36l^Q*=K z2A_2_2f%rWQ!67mLdgfwjPYJ<=B{c4_V0IW2jP_oj1S1oU6}OuHH%3R%S&jqPX`w4 z!Rc*y#q1M@EH5~VZ^;}7=2m%fmU~{&j$GS2DbW5IoHWZhnPOm#)v2tEoasFMvuN(< zoLwo_YVt1TIeLTl`^s4;Ow_SLy|$MGZEac2$!4thWA z-B$k%-WnhT-`DbZuTAN9UCm`ng63EW$>}Kuj>dwDl#G4p%0k zCG%HZ#$8=qBA&bZh(oN5cdDGuNnUDpmvcukKj#i}ju`Uziu_#|Qy^RIJcb#qlSZ*~ ztVp|c#=-0qh`U&POB@$D^lVV|xkai0^m}Dx>k}UDZNGQ(+QW{PvP;7=aXz6(8vUX> zYOPj^!41nF6C91aS!<_gocQvjzHc@JV9b^`aW=cwdqBF7mcG^lJ$X{TPJ@$x(ND#ZEPAeGTOi2@SuNYD&>YG znfVTqO|a|c6TQ)q0zLaU*8%Ooa#0B{a_bk_X0Gs=!)M2XnE?_*mT2_m|aIu0~5Ta|?w z;TvGOxXV^+H-GinCw8X6SxS`LrCwPoe!E~vL|gD6VLO}R5{uac!)tbi&3=QP%M*c- zx~Ig2(4}N3sZN)&O>$cN^PGR`IkEnCkLuLlwTB<*#-y>9DL@6Y`~#b}%ylBp3JyGR zioj9EWfdo7RIm9uk4eFIkBi?OZMyq7ayZUW4VWSN$pf-vZT~_5cL7Xj0R+hTf6M<7 f^8Xyev?AaI&F}lH+cxo^uZ^0jwo2tQ%lH2WFqT6Z literal 5079 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 Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index d8943033..c971c716 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -57,6 +57,7 @@ Steg Våningar + Solar Intensity Aktiva minuter (Vecka) Kalorier (Manuellt mål) Off diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 17343bb0..572cb46f 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 6ba2fc0e..c69ed2af 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources/fonts/crystal-icons.fnt b/resources/fonts/crystal-icons.fnt index c05a9bcf..c485991b 100644 --- a/resources/fonts/crystal-icons.fnt +++ b/resources/fonts/crystal-icons.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-24 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=24 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons.png" -chars count=18 +chars count=20 char id=48 x=0 y=0 width=21 height=24 xoffset=1 yoffset=0 xadvance=24 page=0 chnl=15 char id=49 x=22 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=50 x=47 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 @@ -20,4 +20,5 @@ char id=63 x=76 y=25 width=28 height=24 xoffset=0 yoffset=0 char id=64 x=105 y=25 width=20 height=24 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=65 x=126 y=25 width=17 height=24 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 char id=66 x=145 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 -char id=67 x=169 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file +char id=67 x=169 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 +char id=68 x=195 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 diff --git a/resources/fonts/crystal-icons.png b/resources/fonts/crystal-icons.png index d0472ad87d91c0a78810486928c32ef6d6d530af..86674c585fca0f923ca2a4747182c80303c4fe1f 100644 GIT binary patch delta 5082 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 literal 5822 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 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 2763dfef..62d09f83 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -90,6 +90,7 @@ @Strings.Humidity @Strings.PulseOx @Strings.FloorsClimbed + @Strings.SolarIntensity @@ -111,6 +112,7 @@ @Strings.Humidity @Strings.PulseOx @Strings.FloorsClimbed + @Strings.SolarIntensity @@ -132,6 +134,7 @@ @Strings.Humidity @Strings.PulseOx @Strings.FloorsClimbed + @Strings.SolarIntensity diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 181343fe..3511f6c0 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -57,6 +57,7 @@ Steps Floors Climbed + Solar Intensity Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 9a84f6c1..d490a673 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -347,7 +347,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function makeTeslaWebPost(token, notify) { var url = "https://auth.tesla.com/oauth2/v3/token"; - Communications.makeWebRequest( + Comms.makeWebRequest( url, { "grant_type" => "refresh_token", @@ -356,12 +356,23 @@ class BackgroundService extends Sys.ServiceDelegate { "scope" => "openid email offline_access" }, { - :method => Communications.HTTP_REQUEST_METHOD_POST, - :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + :method => Comms.HTTP_REQUEST_METHOD_POST, + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }, notify ); } + + (:background_method) + function makeTeslaWebRequest(url, params, callback) { + var options = { + :method => Comms.HTTP_REQUEST_METHOD_GET, + :headers => { + "Authorization" => _token}, + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON + }; + Comms.makeWebRequest(url, params, options, callback); + } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* //**************************************************************** @@ -371,23 +382,12 @@ class BackgroundService extends Sys.ServiceDelegate { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, :headers => { - "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED}, + "Content-Type" => Comms.REQUEST_CONTENT_TYPE_URL_ENCODED}, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; Comms.makeWebRequest(url, params, options, callback); } - (:background_method) - function makeTeslaWebRequest(url, params, callback) { - var options = { - :method => Comms.HTTP_REQUEST_METHOD_GET, - :headers => { - "Authorization" => _token}, - :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON - }; - Comms.makeWebRequest(url, params, options, callback); - } - (:debug) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); diff --git a/source/DataFields.mc b/source/DataFields.mc index ab9d6252..b6441bd7 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -31,7 +31,8 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_PRESSURE, FIELD_TYPE_HUMIDITY, FIELD_TYPE_PULSE_OX, - FIELD_FLOOR_CLIMBED + FIELD_FLOOR_CLIMBED, + FIELD_SOLAR_INTENSITY } class DataFields extends Ui.Drawable { @@ -320,6 +321,7 @@ class DataFields extends Ui.Drawable { FIELD_TYPE_HUMIDITY => "A", FIELD_TYPE_PULSE_OX => "B", // SG Addition FIELD_FLOOR_CLIMBED => "1", // SG Addition + FIELD_SOLAR_INTENSITY => "D", // SG Addition }[fieldType]; } @@ -373,8 +375,18 @@ class DataFields extends Ui.Drawable { switch (type) { // SG Addition + case FIELD_SOLAR_INTENSITY: + var stats = Sys.getSystemStats(); + if (stats has :solarIntensity) { + var solarIntensity = stats.solarIntensity; + if (solarIntensity != null) { + value = solarIntensity.format(INTEGER_FORMAT); + } + } + break; + // SG Addition case FIELD_FLOOR_CLIMBED: - var info = ActivityMonitor.getInfo(); + var info = ActivityMonitor.getInfo(); if (info has :floorsClimbed) { var climbed = info.floorsClimbed; var goal = info.floorsClimbedGoal; From e3ec96f7e01de217042c1b7889af41d790ecac4b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 21 Jul 2022 19:01:29 -0400 Subject: [PATCH 051/220] Added Body Battery as a data field. Bug fix for Solar Intensity on 390x390 watches --- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + .../fonts/crystal-icons-large.fnt | 5 +++-- .../fonts/crystal-icons-large.png | Bin 9029 -> 10105 bytes .../fonts/crystal-icons-extra-large.fnt | 5 +++-- .../fonts/crystal-icons-extra-large.png | Bin 13434 -> 7031 bytes resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + .../fonts/crystal-icons-small.fnt | 5 +++-- .../fonts/crystal-icons-small.png | Bin 5275 -> 5503 bytes resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/fonts/crystal-icons.fnt | 3 ++- resources/fonts/crystal-icons.png | Bin 6018 -> 6340 bytes resources/settings/settings.xml | 3 +++ resources/strings/strings.xml | 1 + source/DataFields.mc | 20 +++++++++++++++++- 31 files changed, 54 insertions(+), 8 deletions(-) diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 2702fce5..1675ba47 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 6c28e154..346bc844 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 89f226a5..50b8dd78 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -58,6 +58,7 @@ Schritte Stockwerke Solar Intensity + Body Battery Aktive Minuten (Wöchentlich) Kalorien (manuelles Ziel) Aus diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 2eb2ac1d..fc0b5184 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -59,6 +59,7 @@ Stappen Trappen Beklommen Solar Intensity + Body Battery Active Minuten (Wekelijks) Calorien (Manueel Doel) Uit diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index a02eb9a2..a621d40e 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index e62420aa..71136f15 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -59,6 +59,7 @@ Pas Étages montées Intensité solaire + Batterie corporelle Minutes actives (hebdo) Calories (objectif manuel) Masqué diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 34b59ae6..d2be4f9e 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index feed83b7..31d154f1 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 1850eb53..33d80630 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 1435cf45..fef97015 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index b8eb2e77..59541907 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 9d6718bf..40fd9a15 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -58,6 +58,7 @@ Kroki Pokonane Piętra Solar Intensity + Body Battery Aktywne Minuty (Tygodniowo) Spalone Kalorie (Ręczny Cel) Off diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 4b7b1245..ef43fc29 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-round-280x280/fonts/crystal-icons-large.fnt b/resources-round-280x280/fonts/crystal-icons-large.fnt index 8ac06100..8bfbf6bd 100644 --- a/resources-round-280x280/fonts/crystal-icons-large.fnt +++ b/resources-round-280x280/fonts/crystal-icons-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=28 base=28 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-large.png" -chars count=20 +chars count=21 char id=48 x=0 y=0 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 char id=49 x=25 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=50 x=53 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 @@ -21,4 +21,5 @@ char id=64 x=113 y=28 width=24 height=28 xoffset=0 yoffset=0 char id=65 x=137 y=28 width=19 height=28 xoffset=0 yoffset=0 xadvance=19 page=0 chnl=15 char id=66 x=158 y=28 width=28 height=25 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=67 x=186 y=28 width=26 height=25 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 -char id=68 x=213 y=28 width=28 height=28 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 \ No newline at end of file +char id=68 x=213 y=28 width=28 height=28 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 +char id=69 x=0 y=56 width=24 height=28 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-280x280/fonts/crystal-icons-large.png b/resources-round-280x280/fonts/crystal-icons-large.png index dc4d69099fe044db5d54afc0d9798bd348fb16b6..67cd902909ed36166585f29528790b0b885b7056 100644 GIT binary patch literal 10105 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 literal 9029 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Шаги Пройденные вверх этажи Solar Intensity + Body Battery Время интенсивной активности (минуты за неделю) Калории (ручной ввод цели) Выключено diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index e3ff1f09..37ad7014 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index bf05eecd..95f6a68a 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-small-icons/fonts/crystal-icons-small.fnt b/resources-small-icons/fonts/crystal-icons-small.fnt index 68eee85f..80e68199 100644 --- a/resources-small-icons/fonts/crystal-icons-small.fnt +++ b/resources-small-icons/fonts/crystal-icons-small.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-20 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=20 base=20 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-small.png" -chars count=20 +chars count=21 char id=48 x=0 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=49 x=21 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=50 x=42 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 @@ -21,4 +21,5 @@ char id=64 x=48 y=21 width=17 height=20 xoffset=0 yoffset=0 char id=65 x=66 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 char id=66 x=80 y=21 width=26 height=22 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=67 x=106 y=21 width=24 height=20 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 -char id=68 x=133 y=21 width=21 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file +char id=68 x=133 y=21 width=21 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 +char id=69 x=154 y=21 width=17 height=20 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 \ No newline at end of file diff --git a/resources-small-icons/fonts/crystal-icons-small.png b/resources-small-icons/fonts/crystal-icons-small.png index 0c3349efcdf540ff28b67bb45ac80f07545b5303..44d4f85011f4733de1b6e71ada8eb259c4373917 100644 GIT binary patch literal 5503 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 HTZQ}|KB>g6 literal 5275 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 diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 176be7d5..da9a762a 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index c971c716..2f860af9 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -58,6 +58,7 @@ Steg Våningar Solar Intensity + Body Battery Aktiva minuter (Vecka) Kalorier (Manuellt mål) Off diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 572cb46f..ea1db44d 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index c69ed2af..af0adcd1 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -59,6 +59,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources/fonts/crystal-icons.fnt b/resources/fonts/crystal-icons.fnt index c485991b..41492848 100644 --- a/resources/fonts/crystal-icons.fnt +++ b/resources/fonts/crystal-icons.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-24 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=24 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons.png" -chars count=20 +chars count=21 char id=48 x=0 y=0 width=21 height=24 xoffset=1 yoffset=0 xadvance=24 page=0 chnl=15 char id=49 x=22 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=50 x=47 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 @@ -22,3 +22,4 @@ char id=65 x=126 y=25 width=17 height=24 xoffset=0 yoffset=0 char id=66 x=145 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=67 x=169 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=68 x=195 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 +char id=69 x=218 y=26 width=21 height=24 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 diff --git a/resources/fonts/crystal-icons.png b/resources/fonts/crystal-icons.png index 86674c585fca0f923ca2a4747182c80303c4fe1f..13064c469e4d352361a918e5fc64c8bc5f04482e 100644 GIT binary patch literal 6340 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.PulseOx @Strings.FloorsClimbed @Strings.SolarIntensity + @Strings.BodyBattery @@ -113,6 +114,7 @@ @Strings.PulseOx @Strings.FloorsClimbed @Strings.SolarIntensity + @Strings.BodyBattery @@ -135,6 +137,7 @@ @Strings.PulseOx @Strings.FloorsClimbed @Strings.SolarIntensity + @Strings.BodyBattery diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 3511f6c0..5b935952 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -58,6 +58,7 @@ Steps Floors Climbed Solar Intensity + Body Battery Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/source/DataFields.mc b/source/DataFields.mc index b6441bd7..49794160 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -32,7 +32,8 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_HUMIDITY, FIELD_TYPE_PULSE_OX, FIELD_FLOOR_CLIMBED, - FIELD_SOLAR_INTENSITY + FIELD_SOLAR_INTENSITY, + FIELD_BODY_BATTERY } class DataFields extends Ui.Drawable { @@ -322,6 +323,7 @@ class DataFields extends Ui.Drawable { FIELD_TYPE_PULSE_OX => "B", // SG Addition FIELD_FLOOR_CLIMBED => "1", // SG Addition FIELD_SOLAR_INTENSITY => "D", // SG Addition + FIELD_BODY_BATTERY => "E", // SG Addition }[fieldType]; } @@ -375,6 +377,22 @@ class DataFields extends Ui.Drawable { switch (type) { // SG Addition + case FIELD_BODY_BATTERY: + var bodyBattery = null; + if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { + bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); + if (bodyBattery != null) { + bodyBattery = bodyBattery.next(); + } + if (bodyBattery !=null) { + bodyBattery = bodyBattery.data; + } + if (bodyBattery != null && bodyBattery >= 0 && bodyBattery <= 100) { + value = bodyBattery.format(INTEGER_FORMAT); + } + } + break; + // SG Addition case FIELD_SOLAR_INTENSITY: var stats = Sys.getSystemStats(); if (stats has :solarIntensity) { From cbd96a215c2c4a19d3b964f768b64dc2a73a2636 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 21 Jul 2022 19:41:54 -0400 Subject: [PATCH 052/220] Addition of Forerunner 255, 255 Music, 255s, 255s Music --- manifest.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/manifest.xml b/manifest.xml index aff34fdf..1e276116 100644 --- a/manifest.xml +++ b/manifest.xml @@ -33,6 +33,10 @@ + + + + From 7cef244aa06dfe1b9241d7d59e6aa503d48d46b6 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 30 Jul 2022 00:13:53 -0400 Subject: [PATCH 053/220] Text that needs to be translated --- resources-deu/strings/strings.xml | 6 +++--- resources-dut/strings/strings.xml | 6 +++--- resources-pol/strings/strings.xml | 6 +++--- resources-rus/strings/strings.xml | 6 +++--- resources-swe/strings/strings.xml | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 50b8dd78..386b9681 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -58,8 +58,8 @@ Schritte Stockwerke Solar Intensity - Body Battery - Aktive Minuten (Wöchentlich) + Body Battery + Aktive Minuten (Wöchentlich) Kalorien (manuelles Ziel) Aus @@ -79,7 +79,7 @@ Wetter Feuchtigkeit Druck - Pulse Ox + Pulse Ox diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index fc0b5184..f505edf0 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -58,8 +58,8 @@ Stappen Trappen Beklommen - Solar Intensity - Body Battery + Solar Intensity + Body Battery Active Minuten (Wekelijks) Calorien (Manueel Doel) Uit @@ -80,7 +80,7 @@ Weeer Vochtigheid Luchtdruk - Pulse Ox + Pulse Ox diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 40fd9a15..18324b82 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -57,8 +57,8 @@ Kroki Pokonane Piętra - Solar Intensity - Body Battery + Solar Intensity + Body Battery Aktywne Minuty (Tygodniowo) Spalone Kalorie (Ręczny Cel) Off @@ -79,7 +79,7 @@ Pogoda Humidity Ciśnienie - Pulse Ox + Pulse Ox diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index c74d7dda..67ccc8fd 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -57,8 +57,8 @@ Шаги Пройденные вверх этажи - Solar Intensity - Body Battery + Solar Intensity + Body Battery Время интенсивной активности (минуты за неделю) Калории (ручной ввод цели) Выключено @@ -79,7 +79,7 @@ Погода Влажность Давление - Pulse Ox + Pulse Ox RUS diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 2f860af9..621ea65e 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -57,8 +57,8 @@ Steg Våningar - Solar Intensity - Body Battery + Solar Intensity + Body Battery Aktiva minuter (Vecka) Kalorier (Manuellt mål) Off @@ -79,7 +79,7 @@ Väder Luftfuktighet Tryck - Pulse Ox + Pulse Ox From c310c698d22eb9ceeea570cd218c95e48367ff8a Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 26 Aug 2022 15:57:24 -0400 Subject: [PATCH 054/220] =?UTF-8?q?Fixed=20'=C3=9B'=20missing=20in=20the?= =?UTF-8?q?=20280x280=20font=20file.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fonts/titillium-web-semibold-28.bmfc | 10 +- .../fonts/titillium-web-semibold-28.fnt | 243 +++++++----------- .../fonts/titillium-web-semibold-28_0.png | Bin 9919 -> 9963 bytes 3 files changed, 107 insertions(+), 146 deletions(-) diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc b/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc index 833b2af2..39bd411f 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc +++ b/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=1 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 @@ -50,8 +54,8 @@ invB=0 outlineThickness=0 # selected chars -chars=32-33,37,39,44-46,48-58,63,65-90,97-122,176,193,196-197,201,205-206,214,216,218,225,227-230,232 -chars=233,237,240-241,243-244,246,248,251-252,268,282,344,346,352,377,381-382,8304,8308-8309,8311-8313 - +chars=32-33,37,39,44-46,48-58,63,65-90,97-122,176,193,196-197,201,205-206,214,216,218-219,225,227-230 +chars=232-233,237,240-241,243-244,246,248,251-252,268,282,344,346,352,377,381-382,8304,8308-8309,8311 +chars=8312-8313 # imported icon images diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt index 2ea69189..7c12b17b 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt +++ b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt @@ -4,118 +4,117 @@ page id=0 file="titillium-web-semibold-28_0.png" chars count=112 char id=32 x=252 y=0 width=3 height=1 xoffset=-1 yoffset=42 xadvance=6 page=0 chnl=15 char id=33 x=191 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 -char id=37 x=0 y=53 width=16 height=21 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 -char id=39 x=45 y=134 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 -char id=44 x=38 y=134 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 -char id=45 x=50 y=134 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 -char id=46 x=250 y=65 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 -char id=47 x=155 y=50 width=12 height=21 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 +char id=37 x=18 y=53 width=16 height=21 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 +char id=39 x=251 y=92 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 +char id=44 x=47 y=134 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 +char id=45 x=60 y=134 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 +char id=46 x=54 y=134 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 char id=48 x=123 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=49 x=234 y=92 width=10 height=19 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 -char id=50 x=219 y=92 width=14 height=19 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=49 x=240 y=92 width=10 height=19 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 +char id=50 x=225 y=92 width=14 height=19 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 char id=51 x=77 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=52 x=203 y=93 width=15 height=19 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=53 x=92 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=52 x=209 y=92 width=15 height=19 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=53 x=62 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 char id=54 x=224 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=55 x=136 y=94 width=13 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=55 x=122 y=94 width=13 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 char id=56 x=106 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=57 x=16 y=96 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=58 x=219 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 +char id=57 x=208 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=58 x=230 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 char id=63 x=178 y=93 width=12 height=20 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 -char id=65 x=36 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 -char id=66 x=191 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=67 x=66 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=68 x=157 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=69 x=107 y=94 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=65 x=18 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 +char id=66 x=89 y=73 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=67 x=84 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=68 x=72 y=73 width=16 height=20 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=69 x=47 y=96 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 char id=70 x=32 y=96 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=71 x=34 y=53 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=72 x=54 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 -char id=73 x=249 y=23 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 -char id=74 x=244 y=0 width=7 height=22 xoffset=0 yoffset=12 xadvance=8 page=0 chnl=15 -char id=75 x=208 y=71 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 -char id=76 x=122 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=13 page=0 chnl=15 -char id=77 x=228 y=50 width=21 height=20 xoffset=1 yoffset=12 xadvance=24 page=0 chnl=15 -char id=78 x=0 y=75 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 -char id=79 x=231 y=27 width=17 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=80 x=140 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=81 x=18 y=28 width=17 height=24 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=71 x=68 y=51 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=72 x=36 y=75 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 +char id=73 x=203 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 +char id=74 x=240 y=27 width=7 height=22 xoffset=0 yoffset=12 xadvance=8 page=0 chnl=15 +char id=75 x=16 y=98 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 +char id=76 x=136 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=13 page=0 chnl=15 +char id=77 x=233 y=50 width=21 height=20 xoffset=1 yoffset=12 xadvance=24 page=0 chnl=15 +char id=78 x=54 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 +char id=79 x=0 y=55 width=17 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=80 x=191 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=81 x=9 y=28 width=17 height=24 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 char id=82 x=174 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=83 x=50 y=51 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=84 x=0 y=96 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=85 x=17 y=53 width=16 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=86 x=18 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 -char id=87 x=202 y=50 width=25 height=20 xoffset=0 yoffset=12 xadvance=26 page=0 chnl=15 -char id=88 x=72 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 -char id=89 x=89 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=83 x=52 y=51 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=84 x=0 y=98 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=85 x=35 y=53 width=16 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=86 x=0 y=77 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 +char id=87 x=207 y=50 width=25 height=20 xoffset=0 yoffset=12 xadvance=26 page=0 chnl=15 +char id=88 x=157 y=72 width=16 height=20 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 +char id=89 x=140 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 char id=90 x=240 y=71 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=97 x=38 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 -char id=98 x=96 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=99 x=82 y=115 width=12 height=16 xoffset=0 yoffset=17 xadvance=12 page=0 chnl=15 -char id=100 x=126 y=50 width=14 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=101 x=23 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 -char id=102 x=181 y=50 width=10 height=21 xoffset=0 yoffset=11 xadvance=10 page=0 chnl=15 -char id=103 x=52 y=28 width=15 height=22 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=104 x=150 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=105 x=250 y=44 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 -char id=106 x=100 y=0 width=8 height=27 xoffset=-2 yoffset=12 xadvance=7 page=0 chnl=15 +char id=97 x=64 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 +char id=98 x=99 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=99 x=93 y=115 width=12 height=16 xoffset=0 yoffset=17 xadvance=12 page=0 chnl=15 +char id=100 x=129 y=51 width=14 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=101 x=49 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 +char id=102 x=186 y=50 width=10 height=21 xoffset=0 yoffset=11 xadvance=10 page=0 chnl=15 +char id=103 x=61 y=28 width=15 height=22 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=104 x=150 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=105 x=197 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=106 x=117 y=0 width=8 height=27 xoffset=-2 yoffset=12 xadvance=7 page=0 chnl=15 char id=107 x=164 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=14 page=0 chnl=15 -char id=108 x=197 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 -char id=109 x=95 y=115 width=21 height=15 xoffset=1 yoffset=17 xadvance=23 page=0 chnl=15 -char id=110 x=117 y=115 width=13 height=15 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=111 x=53 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=112 x=81 y=51 width=14 height=21 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=113 x=111 y=51 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=114 x=145 y=115 width=9 height=15 xoffset=1 yoffset=17 xadvance=10 page=0 chnl=15 -char id=115 x=68 y=115 width=13 height=16 xoffset=0 yoffset=17 xadvance=13 page=0 chnl=15 -char id=116 x=245 y=92 width=10 height=19 xoffset=0 yoffset=14 xadvance=10 page=0 chnl=15 -char id=117 x=131 y=115 width=13 height=15 xoffset=1 yoffset=18 xadvance=15 page=0 chnl=15 -char id=118 x=177 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 -char id=119 x=155 y=114 width=21 height=14 xoffset=0 yoffset=18 xadvance=22 page=0 chnl=15 -char id=120 x=192 y=114 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=121 x=47 y=96 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 -char id=122 x=206 y=113 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=176 x=27 y=134 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 -char id=193 x=109 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 -char id=196 x=127 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 -char id=197 x=0 y=28 width=17 height=24 xoffset=0 yoffset=8 xadvance=17 page=0 chnl=15 -char id=201 x=194 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 -char id=205 x=235 y=0 width=8 height=26 xoffset=0 yoffset=6 xadvance=8 page=0 chnl=15 -char id=206 x=224 y=0 width=10 height=26 xoffset=-1 yoffset=6 xadvance=8 page=0 chnl=15 +char id=108 x=248 y=27 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=109 x=106 y=115 width=21 height=15 xoffset=1 yoffset=17 xadvance=23 page=0 chnl=15 +char id=110 x=142 y=115 width=13 height=15 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 +char id=111 x=34 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=112 x=144 y=50 width=14 height=21 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 +char id=113 x=114 y=51 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=114 x=156 y=115 width=9 height=15 xoffset=1 yoffset=17 xadvance=10 page=0 chnl=15 +char id=115 x=79 y=115 width=13 height=16 xoffset=0 yoffset=17 xadvance=13 page=0 chnl=15 +char id=116 x=0 y=119 width=10 height=19 xoffset=0 yoffset=14 xadvance=10 page=0 chnl=15 +char id=117 x=128 y=115 width=13 height=15 xoffset=1 yoffset=18 xadvance=15 page=0 chnl=15 +char id=118 x=188 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=119 x=166 y=114 width=21 height=14 xoffset=0 yoffset=18 xadvance=22 page=0 chnl=15 +char id=120 x=203 y=114 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=121 x=92 y=94 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=122 x=217 y=112 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=176 x=36 y=134 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 +char id=193 x=144 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 +char id=196 x=126 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 +char id=197 x=27 y=28 width=17 height=24 xoffset=0 yoffset=8 xadvance=17 page=0 chnl=15 +char id=201 x=211 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 +char id=205 x=0 y=28 width=8 height=26 xoffset=0 yoffset=6 xadvance=8 page=0 chnl=15 +char id=206 x=241 y=0 width=10 height=26 xoffset=-1 yoffset=6 xadvance=8 page=0 chnl=15 char id=214 x=0 y=0 width=17 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 char id=216 x=18 y=0 width=17 height=27 xoffset=1 yoffset=9 xadvance=18 page=0 chnl=15 -char id=218 x=36 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=225 x=173 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=227 x=188 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=228 x=158 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=229 x=98 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=230 x=0 y=117 width=22 height=16 xoffset=0 yoffset=17 xadvance=22 page=0 chnl=15 -char id=232 x=83 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=233 x=68 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=237 x=192 y=50 width=9 height=21 xoffset=0 yoffset=11 xadvance=7 page=0 chnl=15 -char id=240 x=36 y=28 width=15 height=22 xoffset=0 yoffset=11 xadvance=16 page=0 chnl=15 -char id=241 x=141 y=50 width=13 height=21 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 -char id=243 x=113 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=244 x=128 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=246 x=143 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=248 x=62 y=94 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 -char id=251 x=203 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 -char id=252 x=217 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 -char id=268 x=85 y=0 width=14 height=27 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 -char id=282 x=209 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 -char id=344 x=145 y=0 width=16 height=26 xoffset=1 yoffset=6 xadvance=17 page=0 chnl=15 -char id=346 x=69 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 -char id=352 x=53 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 -char id=377 x=178 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 -char id=381 x=162 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 -char id=382 x=168 y=50 width=12 height=21 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 -char id=8304 x=234 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8308 x=243 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8309 x=0 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8311 x=9 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8312 x=18 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8313 x=225 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -kernings count=518 -kerning first=39 second=47 amount=-2 +char id=218 x=53 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=219 x=36 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=225 x=107 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=227 x=92 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=228 x=77 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=229 x=197 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=230 x=11 y=119 width=22 height=16 xoffset=0 yoffset=17 xadvance=22 page=0 chnl=15 +char id=232 x=182 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=233 x=167 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=237 x=197 y=50 width=9 height=21 xoffset=0 yoffset=11 xadvance=7 page=0 chnl=15 +char id=240 x=45 y=28 width=15 height=22 xoffset=0 yoffset=11 xadvance=16 page=0 chnl=15 +char id=241 x=159 y=50 width=13 height=21 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 +char id=243 x=152 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=244 x=137 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=246 x=122 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=248 x=107 y=94 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 +char id=251 x=226 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 +char id=252 x=212 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 +char id=268 x=102 y=0 width=14 height=27 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 +char id=282 x=226 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 +char id=344 x=162 y=0 width=16 height=26 xoffset=1 yoffset=6 xadvance=17 page=0 chnl=15 +char id=346 x=86 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 +char id=352 x=70 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 +char id=377 x=195 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 +char id=381 x=179 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 +char id=382 x=173 y=50 width=12 height=21 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 +char id=8304 x=236 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8308 x=245 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8309 x=0 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8311 x=9 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8312 x=18 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8313 x=27 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +kernings count=475 kerning first=44 second=86 amount=-1 kerning first=44 second=118 amount=-1 kerning first=45 second=86 amount=-1 @@ -123,45 +122,12 @@ kerning first=45 second=88 amount=-1 kerning first=45 second=120 amount=-1 kerning first=46 second=86 amount=-1 kerning first=46 second=118 amount=-1 -kerning first=47 second=47 amount=-8 -kerning first=47 second=65 amount=-1 -kerning first=47 second=97 amount=-1 -kerning first=47 second=99 amount=-1 -kerning first=47 second=100 amount=-1 -kerning first=47 second=101 amount=-1 -kerning first=47 second=103 amount=-1 -kerning first=47 second=109 amount=-1 -kerning first=47 second=110 amount=-1 -kerning first=47 second=111 amount=-1 -kerning first=47 second=112 amount=-1 -kerning first=47 second=113 amount=-1 -kerning first=47 second=114 amount=-1 -kerning first=47 second=115 amount=-1 -kerning first=47 second=117 amount=-1 -kerning first=47 second=193 amount=-1 -kerning first=47 second=196 amount=-1 -kerning first=47 second=197 amount=-1 -kerning first=47 second=225 amount=-1 -kerning first=47 second=227 amount=-1 -kerning first=47 second=228 amount=-1 -kerning first=47 second=229 amount=-1 -kerning first=47 second=230 amount=-1 -kerning first=47 second=232 amount=-1 -kerning first=47 second=233 amount=-1 -kerning first=47 second=241 amount=-1 -kerning first=47 second=243 amount=-1 -kerning first=47 second=244 amount=-1 -kerning first=47 second=246 amount=-1 -kerning first=47 second=248 amount=-1 -kerning first=47 second=251 amount=-1 -kerning first=47 second=252 amount=-1 kerning first=65 second=63 amount=-1 kerning first=65 second=86 amount=-1 kerning first=66 second=89 amount=-1 kerning first=68 second=88 amount=-1 kerning first=70 second=44 amount=-2 kerning first=70 second=46 amount=-2 -kerning first=70 second=47 amount=-1 kerning first=70 second=65 amount=-1 kerning first=70 second=97 amount=-1 kerning first=70 second=100 amount=-1 @@ -186,14 +152,12 @@ kerning first=76 second=118 amount=-1 kerning first=79 second=88 amount=-1 kerning first=80 second=44 amount=-2 kerning first=80 second=46 amount=-2 -kerning first=80 second=47 amount=-1 kerning first=80 second=65 amount=-1 kerning first=80 second=89 amount=-1 kerning first=80 second=193 amount=-1 kerning first=80 second=196 amount=-1 kerning first=80 second=197 amount=-1 kerning first=81 second=88 amount=-1 -kerning first=84 second=47 amount=-1 kerning first=84 second=118 amount=-2 kerning first=84 second=120 amount=-2 kerning first=84 second=227 amount=-2 @@ -202,7 +166,6 @@ kerning first=84 second=240 amount=-1 kerning first=86 second=44 amount=-1 kerning first=86 second=45 amount=-1 kerning first=86 second=46 amount=-1 -kerning first=86 second=47 amount=-1 kerning first=86 second=65 amount=-1 kerning first=86 second=74 amount=-1 kerning first=86 second=97 amount=-1 @@ -236,7 +199,6 @@ kerning first=86 second=246 amount=-1 kerning first=86 second=248 amount=-1 kerning first=86 second=251 amount=-1 kerning first=86 second=252 amount=-1 -kerning first=87 second=47 amount=-1 kerning first=88 second=45 amount=-1 kerning first=88 second=71 amount=-1 kerning first=88 second=79 amount=-1 @@ -261,7 +223,6 @@ kerning first=88 second=246 amount=-1 kerning first=88 second=248 amount=-1 kerning first=88 second=251 amount=-1 kerning first=88 second=252 amount=-1 -kerning first=89 second=47 amount=-2 kerning first=89 second=102 amount=-1 kerning first=89 second=118 amount=-1 kerning first=89 second=120 amount=-1 @@ -276,7 +237,6 @@ kerning first=101 second=86 amount=-1 kerning first=102 second=44 amount=-1 kerning first=102 second=45 amount=-1 kerning first=102 second=46 amount=-1 -kerning first=102 second=47 amount=-1 kerning first=102 second=65 amount=-1 kerning first=102 second=193 amount=-1 kerning first=102 second=196 amount=-1 @@ -293,14 +253,12 @@ kerning first=112 second=63 amount=-1 kerning first=112 second=86 amount=-1 kerning first=112 second=88 amount=-1 kerning first=113 second=86 amount=-1 -kerning first=114 second=47 amount=-1 kerning first=114 second=88 amount=-1 kerning first=114 second=240 amount=-1 kerning first=115 second=86 amount=-1 kerning first=117 second=86 amount=-1 kerning first=118 second=44 amount=-1 kerning first=118 second=46 amount=-1 -kerning first=118 second=47 amount=-1 kerning first=118 second=74 amount=-1 kerning first=118 second=84 amount=-2 kerning first=118 second=88 amount=-1 @@ -309,7 +267,6 @@ kerning first=119 second=88 amount=-1 kerning first=120 second=45 amount=-1 kerning first=120 second=84 amount=-2 kerning first=120 second=89 amount=-1 -kerning first=121 second=47 amount=-1 kerning first=121 second=88 amount=-1 kerning first=193 second=63 amount=-1 kerning first=193 second=86 amount=-1 diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28_0.png b/resources-round-280x280/fonts/titillium-web-semibold-28_0.png index d7aacef653f162797b48b5f79c4f8b71dd103c7e..dd7412cccdc7dd9cf3fa3bfb50c3f0193da499ff 100644 GIT binary patch literal 9963 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 A8UO$Q literal 9919 zcmc&)_) z%%?dsbDuLa*EJKWq#%ifPJ#{q0G70rmg5I8iLaXgfC`Wn`>Y1dIP}*2 zMmC%J7ZpW)Kr{f#>y<)~RPha+L&;iQD`LkuQSyhs(ePV{2xFoN(Fc6&%|x~c`j0_u zM&dt52#kAKrh48H=;&5U57tt*(7c)|Gs86b!Gy&`_&rDe9ocvYIiBUrxEV=`yOA(# z*}Y#@fnu~k(a;QNTgJm~l5>ET&HUps0$&>_1d2(y3VaGaIXzN`AuGF}00USZ=W^qS&liIg3_;iZ#}dX}%PF!G5kcTfYKPEVw|%lNakv zW?q7dP6FW_Dc~+sa`prXQjythXz6x}-e4$5m@Fx7d0*hng${g)o8$}EvC_oiv4=sq z(??u4Gj%rTYbDkzX0!|T^uY-_s?wWKgYs$)q!;g}eax1SI02fHZKn--^(fC{9Q`6^ z8RGH*mw6!?`b@Ef+P5hi=*CHC-=xjpgj<9`Wk4zg;B~=A~XCG?xl>fl*%AN zc(dY%>@$8lU;q1jG&Ayk9j176hY4F@N;}BXtS#_9ptSpC)a7Oy5cUc>OXY525s0{v?lq%L6_ZcZ-<9*XJySz%Y5p#opwhH( zO#h=s%6f>nvcF=iUw6pxA+ip1d(LhUA25ps+p#nHgVYb$l6rVT;{Ei5>3l0~sXfPg zvu4Ds6TWqi-V<&`lU^zWKg;;L+_;i&x&x@Vyt9)5e}BP-6h6Q@=e!SW9|Fc$)M6R` z`QD$<3(h-_d0WK?70AwO{rpSr9iY((<(_C2X4$9K)_Gr&{}qSizdPS z6Oq7_{C(xCMPVcwp|S)?8u8LCm zB8df~o+xNL-*Dkcxvi>L@ik0H;Z^C0+J$#~vh%3KEn1jrK)BFgU8D0}=3>be9{(o4 z8)a~NS|#rc1qyT_tmB>epz?>;fEWqoV}(4)PtT6v1(T{H;}KVb5ku-K^D;$WS;^b7 zLFLK^=-dpt8h1lgZVj{vv0i4n0z3g}z9N*Q0V*jK-7jD2L58~bW8Qalt;%`%cd*&Epg25KJR%}cZG|>^<(vAc< zO0~$^WfXnZ)O$)ng@3y(BH3SqJc8d?ZCtOD`_zac*02gMIZ+|#d1NG-kIZby>sv+u zIvj*)A;fA3s~re1R%tH5$GYY&&rQid0ub8}g}Sie%%$s9+{7{*AK=(_gdAW3RjICd zxi-rOe$6DMrM&1z+G!0XP%bPRn(+!mH}Q`qUpYR1M93r8k@P?T`101$z`vlIeK4Wx zufJ~l^2u!6JKmdZXt<6$MJWzcf_Yne23)u&&mG68dh;s9UaL`Sjkkn9T?|BXpz;>? zSq2x5jXq{ht_=W#hp~r|*B`CkjqOg&jlMfCckD^)$U=-Yx|PAkZ8x|Z=n_)2Tp*O$ zp`1|iL8Z!6Sp-|)?T};8#j;u8@jfV^<>QS%3$W^qq!_ld5^SR%DT+p!i+TlQ&kLZ%l&AJy5WXKZiK#19#wAy`7 zvL)mcQpoHUSx!gD}o!{2448>HdM2CykHuV)okFjvK&)3r_#YnnPTqL z2w%!UC86e9uIeq#hT^5@di}O;tZ#5T0p(}Cy{apHKu{}DZL*thHVqts@#EJ$-Vzt} zMV9?ROQqAJk|IFQQpSr|qhEo4=(J4Apuuun2EfL-;1%1v_e z$aYibqXheoy<}B{Gv`{PX--L>&Jg|?SMk<2SgYJ4H)F^gudj=k2U32UJlEBu_csj1 zVa5%X22H0?OS@baREhs00f*fQO7G@3gKqTJBizOsf!ux7?_43JliTXip$TQwcCqRB0khC%l%?~t^08m!edZz$p)Loc0jKuKC)9 z+_JFrkXjGeb3pJ4oA~tygKw1P*PM!OKNg-R=^^l<*WL4b~ZJ&lXe^oZd_1+Hpm z9q^>ksC$q z?9MA&IVMP>uaSkIktPH6E|TMWpz$@pHjCS0S_?3yheYBeRPskxGFQx7OFGFG=nC;Z zmWe}11cr;m5v%B7BhB)D+XyCXoa~;5u%Jp`81m|)duIC-VsOeyNS5`w3^so#nwVQx z)?YcVx5d3&m2csXG{GcCUR_`Kf0+>l8Eb|4n8{WfV#pJBRyU zztt3R?R!xGQ(5&y#YaB*MqObb&LTvD(C`s&)>z z$KCJJ@PXp%==6mWN6dd01+C!=O?z>wYn7mn2>Yj;%0x-9M3Co#zzHf{Y?xhiL*%+D zY$75nj@F3|p?~HH7-SkHFVxOsxkZ;&s(8EA#uuo2=?nglJl|8H0V?|5quiq{(wMzT$ed`zzI${vpp_WcbnH1MKp$Z5QqWr>irb;U{*KQb(kzI+QTecL&L)|@^CFi=Z#|1|_4IusA1r~iDWBK)PJ)sNy4Q^A;aZKv$A zsV2f8DMM~q$X&JfBs;v(;|p0QI~kxdshyFp;y{%pL!Wi1x9$YHo1{2KrD{6r=4zPW zQ6m~)NRZV0Z+hla4+}Tl&1K*8{usBne;%`EauZ80GZawr#8E8 zA0(93{bR=S1&hkvar=C;goHJA8*4RdTpW?^lSro*{thYSF#wp~;R;Ygpb`RLfT~x` zsn-`8JBD0a0#E$9((Ai~egE_K?7>V!a__JWA>JzLf{Rg!KYmPQH>`6SV>sMTnV%V$ zW07+)#`lU|JT0Tx5Xi1=^L$B4>nRx^X1`;*UGzZqkfz4i&fS7MX6bp!?mZ4^YFA5EEsIMCqLocjJ8m8Th{E; z)h7dvS_D0L(1vw>s}AoDEQj=1oK2wpixz?28m5RYCQth1U-shH%+EtoRr<2JnDs{j zZYB2N^Q_L>{Am1#)@_@q0Wj}1%Hw0(?krk@x;;&=yu_oy|uNOj945B;jHUvSWLkF0%+YO2jF4g zZI87#J$tX5T4zm6s>`)2_`2R&#Id{9Qh+TIuU{sV!Od);7)HsafWyAG?ZJYR8n63* zxsRlp9c$ZCuAtv<+pHJu&@~{GlL9(RQTB^E9j@2Q3%2+oRqWK{dmzC$3r^ARBeAF} zh?LprxkaFVHxqfjEOi&ZG&zB}XNu&_w+(#U43=}qF$zTWnsZm}Jyu7zV1BeW%ZC+T zAHmd-@@eAyWp}gL2l}dJhE~mTVnZbS*_A1$WkC!3Pa(3-*^77p5(SpS8 zYb8IzgCX=M7pmA_Xjhx7qiopWfB!eMk5=x9vX$mJa3PO&wm~xiu|?;^1^^n*mk}=9 z`QU7>Amb7KTF5=h%cyFjyoRD|a5}@`Wz=k#et0Ov}-|XLj&6bj49BErp z+a_^X;Mj=97pfWO`7ck@rFbG4k-`Gi#oRQ>L5|F(3$(tb9M87;Gp?->0dvW}=VP;X zKPi-j0#n?$lv#sq_r}z#B9u*BwQalgAaU`F7b{ZltwhWawSs28Yt;It{rRy$oC7_G6()3I^kzke;af;%H<_VpSFl(gLOl1PsoK2GuxHPmPGW)@UiJH398|sG6DuSxxgtYLQ+mGM!mya4R)U2l&w!eAIo91N%zH8Vw@aKlH0}V+9fd zNdHRk=6p8jl|(fCHog8L&9IfKx| zr9CCPfw-}ej3VzCH0@byGi^VHV|p3{|1uW)Yp2DB16Oy!qKP+sC>Y=g?Mi`>WKGDF zA_d*NKIry7&XB60MLIq^?M!6x6XtTi*hNVg3Ku>tGAu@XlPT$mmRiq6WS9zqZD4Er z{>)fI`c9`5_6bK#p5k44wlj|xx0EK#Tiqvun}hBrnu=~}r9)GMvk_87#cp9(>&T=Wth4w~h+J{=CiN?oVhNWVKt+Mt zFXd;f0QD}FKwPO;i@^F&kg;PA^mQbm3ZNCq^sW3k-NUPCHRVb;)@6E&9>}+Mb54K} zDDwGBfa7RYu`~2iKTcTyq9!k00O5?W<}}JyxP0p}O!Fj1n}rg?%u+GHnAOwSkrahT zz(|Ft8ZJ#>&%fJL#>yw=xcqNra7vaJnYbtv{Hiz#RoPYa7on1=%hr(PT#v7S=Ur*4 z0+RVCdteOaHSs^jyl=4$2bvV!Ax72)dJE+M3;R=## znFhb22bz)f0KV@^xdU@G;j3JJvAe*pz&FALn3H8*=dNfk)M+F~x@+<@P5Sj;`u7e1 zZ|rI)vy44La2}j}S=myv8xH`OMfjS&LgP^ztQ;GJFnn5&#Srj5A7{fB+^qK?1? z{luJq&7EOK+l>4 zm0yYOE&7Z$@5q*TZgX?9XXRFYvQ}DFRu(tx@j2eNdnu~vw=IGOAFah}mGkHmvvDDm z?hmUe1Oed8IXB|BJR`2;Qe;XD0@jT7j?^FlT}{pUf8ZF?@cNXw%!$mMqobo4pevrb zzmGCm09lB?$@lr`@l?p{c7ig+5er3QBY~wif$>)CU zpA}a`v~%65TRVYFbir*1ft271P%B(W*8AOTh8xc{-G!jm)r%u5T@v?3xkE=;FeuNF%oh+{*4iKj2iw&ic*2Ek`Gtp0$6SA9h zXO-+nP_*)%cPf-{BO*xIX)8#!T3-;|DO&3zzJIg0=VayLk%Km`sq8ck(gJ*j)!etID<1w zC2rw+Gl>dVSoHHgkMpcdFX&}&dB5Z|yGJBPiB9#}Tq^SJOU__~%E>8c-T#HU_fh5q z&TU-1q`Z%6I+{OAyeg*uq*s~G{l59v@6T5~9799M8u1kz{*$sB-WDN{5@@!OXDRm! zmF_aA(mIqd{&O!?;l~-s-93zC^r!`wnD8MuVgbx@g6<4G&XzkpVVa;z^3Nyw z2BLW&Dlea}Y`ma85{YWo+^rB#h^{FrVl7e~=Jh15j~dbLzJdhHcN!|_`GEwF5`uaC zonLz1LhR;Lmvxkmn`QnY7c+!LMl32uNRx`Vt+b`{C?QTb`wY!SgFRS1n@ZY$4XUZ7 zP^abMqh!ESgS3%aK#Mu@XQOAC`78!s85M=c<>FE=%!b0r=p znQaGO$uy>LWhC%)Bwtw&Fm@atH1D@jYA&9i+P2#dh-oR6`2+fUhG z*}~LI%4iU*71QXSA_WUTRb+@LGZ;`ux$daoVMQM__8;L!^z@B`I9mQs9gq_IEkL%CModr2}~m|+AbV3Q)BI1FS~%4wo+}@-vaRpt2)9)SN0nLpy+ONTewI|U{aEtn)c2Zq2a*E zlE3i2-Q~$hex>sV$~T(XAFa>m<9lZ!C<`uqw|R|?jl^*6vG;t)b=tj##~%uzu_Z#O z54p7{&J&(??!5gUH|g>Lu*X=SI4Oqy=K%0{w~LIpT)QhzuSVJ<#%hcAx}T zHno4V-zE!0P1R(KPQyN-@@Q|F0qzgrcmgET@N4l;k_k4>V67Zw*Yjo42n9|K(ewnZ&vCAizgTHuyfD+2_Af{{HWO+AuH#GhnxAJ_Hj)t0`X6|iU=k& zADjg1AwiSU!HH(^HN{OFW}YNeq9q@Nh4dj7wYnUgNmM~6um5iGtnqU9pHn)TLVu(Nt{Q&^Q zk3#q?fglzGOic^p1g6w3YyV%3|^Oot<=HApR$t zt6g>|Ra=+e6^|zfU}VZOV1#KcVqynyS`aVOoJ}UPY}WXtg5(`W);hR2H~==onXxAO zm5RlwNgv(l3v41!yX?o{_7D(!bM{u(TN5XKn^%=C%8}&{)Cz~m)qL-LKB-APT=3mN zXmpj(z$;}6OpK+L)5Y!U_YOu8i7dG?f?t_X-~;vFMN$I?>6xKf zBK6e*j*^5)S(Mh}SEZ(P_zQ;OVq8miaiv^lOzIaO&Yc-ySxC{PmF002p_$;_Vpo%( zODvG_wrP?0>~1&z$WTvknRnDLs(%_{Q%N?45_fk^VP4#1ZScr86Cq&FVa&3M0d9Z= zbGWS^JGSt3X7$h!U0cL{{wDTPgU-y3FTOlEtI~efB}rWo*^);3({0W2isxxjf_l=j zZvUn)<*)RxhJ>4~nsaMw{(*O&hv(ZOLVIW9f7$zhUE)iw6cKvA%Kb!merNm;#sdl6 zm6&i(LOu7|qUKf%A81fwY7wsNTQDE4MPl)>IePrqD1Lf~Vm4lLFE#x`&Oy1WLWOZq zGh0fGM4kd=fYy)Ty7fyL|3qMf7>(>RX~QXvl7|m()blC7XEH5=n@kIcmz#k6~> z*Taj!W!QUE+$9|gGScx_v3=Jx9_SG>h1x@Mbz{X&h)tC>H(QhwpYr!DD7`cDPN_#o z*2d#=AN~?IZsvZPGxsd1tIH7l1P_e~OAI#@PjpVlIR|6$+qyc|iKU{QEi?1hUU!-A zhlCoPQ@D@Xb?ag=l`Gj5$uL)Ul7rZc0ALTNPkC%bt% zB91C@s9B8@dF}WK^;R5zy5=vf>od#E4{K7ghO>$6OO_e~Xt948ZQfQ_JbSIbKd|c8 zTvTWsbzFz6JlC-hAEiK#s!kJppy# zeL>H~2ZYBzxvv4~^>^vV>!Fdsx(eYXw!xxa9?E@lZ?5{vZ?He$QR`aITHLUn-AXVq zQwQS5KbM1gbT_9WrDcfyK0K+!ncjw0s0=zWa%ft1$f)>?9D@)r-=pF-5Qn?V8W_d~J|y0T(g17go1SzY#*A@|!&eN9kJPZF5Md`loSRD+hp z*cPKOR1rriR_47&&?Kg5C6h!x2kOIRF_q;bL7<{giatbu92tUw)c51`(Fz0BD`ke5 zKX44Yz4!aN)nSpvH^du_h^EH?>T|w7myF?sElP|b0U_Cx|dBujcKvA&b`Ua&0(M^RscJLU--&#Gg+nbC^5*}dWb-~zuCW^gw1~|P{&$%sEv_I|A!6kJ EKcSP__y7O^ From d73c099c518796ca05a946e5ff6d034e5a6010d0 Mon Sep 17 00:00:00 2001 From: ChristopheMB <41425865+ChristopheMB@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:04:58 +0200 Subject: [PATCH 055/220] Fix Dutch translations Correct the spelling of some Dutch translations, add missing translations. --- resources-dut/strings/strings.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index f505edf0..caaf0ad4 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -9,13 +9,13 @@ Minuten Kleur Linker Meter Rechter Meter - Calorien Doel (1-10,000kCal) + Calorieën Doel (1-10,000kCal) Meter Stijl Meter Getallen Stijl Voeg Lokale Tijd In Stad Toe (Beta) Beweeg Balk Stijl Verberg Seconden - Verberg Eerste Nul Bij Uuren + Verberg Eerste Nul Bij Uren OpenWeatherMap API Key Override Hoeveelheid Datavelden @@ -58,29 +58,29 @@ Stappen Trappen Beklommen - Solar Intensity + Zonne-intensiteit Body Battery - Active Minuten (Wekelijks) - Calorien (Manueel Doel) + Actieve Minuten (Wekelijks) + Calorieën (Manueel Doel) Uit - Hartslage + Hartslag Hartslag (Live 5s) Batterij Batterij (Verberg Percentage) Notificaties - Calorien + Calorieën Afstand Alarmen Hoogte Thermometer Bluetooth Bluetooth/Notificaties - Zonopkomst / -Ondergang - Weeer + Zonsopkomst / -Ondergang + Weer Vochtigheid Luchtdruk - Pulse Ox + Pulsoximeter From 4724816f86d0c9166d29fbfc1c42d0f4051501d7 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 15 Sep 2022 21:20:37 -0400 Subject: [PATCH 056/220] Added the Enduro, Venu SQ 2 and Venu SQ 2 Music --- manifest.xml | 3 + resources-rectangle-320x360/fonts/fonts.xml | 24 ++++++ .../layouts/layout.xml | 63 ++++++++++++++ .../settings/properties.xml | 6 ++ .../settings/settings.xml | 82 +++++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 resources-rectangle-320x360/fonts/fonts.xml create mode 100644 resources-rectangle-320x360/layouts/layout.xml create mode 100644 resources-rectangle-320x360/settings/properties.xml create mode 100644 resources-rectangle-320x360/settings/settings.xml diff --git a/manifest.xml b/manifest.xml index 1e276116..2190a3c1 100644 --- a/manifest.xml +++ b/manifest.xml @@ -15,6 +15,7 @@ + @@ -63,6 +64,8 @@ + + diff --git a/resources-rectangle-320x360/fonts/fonts.xml b/resources-rectangle-320x360/fonts/fonts.xml new file mode 100644 index 00000000..14f817ec --- /dev/null +++ b/resources-rectangle-320x360/fonts/fonts.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources-rectangle-320x360/layouts/layout.xml b/resources-rectangle-320x360/layouts/layout.xml new file mode 100644 index 00000000..e09dfa02 --- /dev/null +++ b/resources-rectangle-320x360/layouts/layout.xml @@ -0,0 +1,63 @@ + + + + + + :left + 12 + 360 + 3 + + + + :right + 12 + 360 + 3 + + + + 65 + 189 + 309 + 333 + 303 + 29 + 291 + + + + 87 + 234 + 30 + 62 + 37 + + + + + + 32 + 189 + 48 + 27 + + + + 3 + 229 + 233 + 8 + + + + 53 + 264 + 164 + 17 + 4 + + + diff --git a/resources-rectangle-320x360/settings/properties.xml b/resources-rectangle-320x360/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-rectangle-320x360/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-rectangle-320x360/settings/settings.xml b/resources-rectangle-320x360/settings/settings.xml new file mode 100644 index 00000000..f74f5684 --- /dev/null +++ b/resources-rectangle-320x360/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + From 15b32ec4480516d2675b5df94dd778ca1cfbced6 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 15 Sep 2022 21:49:37 -0400 Subject: [PATCH 057/220] Fixed AlwaysOnDisplay of Venu SQ 2 and Venu SQ 2 Music --- monkey.jungle | 2 ++ resources-rectangle-320x360/layouts/layout.xml | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/monkey.jungle b/monkey.jungle index 47f2fdc7..1b269dde 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -74,6 +74,8 @@ venu.sourcePath = $(venu.sourcePath);always-on-source venu2.sourcePath = $(venu2.sourcePath);always-on-source venu2s.sourcePath = $(venu2s.sourcePath);always-on-source venu2plus.sourcePath = $(venu2plus.sourcePath);always-on-source +venusq2.sourcePath = $(venusq2.sourcePath);always-on-source +venusq2m.sourcePath = $(venusq2m.sourcePath);always-on-source venud.sourcePath = $(venud.sourcePath);always-on-source venusq.sourcePath = $(venusq.sourcePath);always-on-source venusqm.sourcePath = $(venusqm.sourcePath);always-on-source diff --git a/resources-rectangle-320x360/layouts/layout.xml b/resources-rectangle-320x360/layouts/layout.xml index e09dfa02..34e8d8a4 100644 --- a/resources-rectangle-320x360/layouts/layout.xml +++ b/resources-rectangle-320x360/layouts/layout.xml @@ -60,4 +60,19 @@ 4 + + + + + [-57, -29, 29, 57] + -2 + 153 + 200 + + 216 + + 225 + 65 + + From cf0d3ef4c8cc4cfa6525974bb032ba5bf91f3cd1 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 26 Sep 2022 22:11:26 -0400 Subject: [PATCH 058/220] Added Recovery Time left as a data field --- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + .../fonts/crystal-icons-large.fnt | 5 +++-- .../fonts/crystal-icons-large.png | Bin 10105 -> 10889 bytes .../fonts/crystal-icons-extra-large.fnt | 3 ++- .../fonts/crystal-icons-extra-large.png | Bin 7031 -> 7506 bytes resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + .../fonts/crystal-icons-small.fnt | 5 +++-- .../fonts/crystal-icons-small.png | Bin 5503 -> 5706 bytes resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/fonts/crystal-icons.fnt | 3 ++- resources/fonts/crystal-icons.png | Bin 6340 -> 6548 bytes resources/settings/settings.xml | 3 +++ resources/strings/strings.xml | 1 + source/DataFields.mc | 17 +++++++++++++++-- 31 files changed, 49 insertions(+), 8 deletions(-) diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 1675ba47..a781c940 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 346bc844..6cc33468 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 386b9681..18d79f82 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -59,6 +59,7 @@ Stockwerke Solar Intensity Body Battery + Recovery Time Aktive Minuten (Wöchentlich) Kalorien (manuelles Ziel) Aus diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index caaf0ad4..637090b5 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -60,6 +60,7 @@ Trappen Beklommen Zonne-intensiteit Body Battery + Recovery Time Actieve Minuten (Wekelijks) Calorieën (Manueel Doel) Uit diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index a621d40e..968ce8bf 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 71136f15..991f838d 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -60,6 +60,7 @@ Étages montées Intensité solaire Batterie corporelle + Temps de recouvrement Minutes actives (hebdo) Calories (objectif manuel) Masqué diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index d2be4f9e..a5731714 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 31d154f1..22344c33 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 33d80630..4323056a 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index fef97015..e62f4e97 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 59541907..5ef0cbea 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 18324b82..5c947183 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -59,6 +59,7 @@ Pokonane Piętra Solar Intensity Body Battery + Recovery Time Aktywne Minuty (Tygodniowo) Spalone Kalorie (Ręczny Cel) Off diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index ef43fc29..420b3a78 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-round-280x280/fonts/crystal-icons-large.fnt b/resources-round-280x280/fonts/crystal-icons-large.fnt index 8bfbf6bd..51846a6f 100644 --- a/resources-round-280x280/fonts/crystal-icons-large.fnt +++ b/resources-round-280x280/fonts/crystal-icons-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=28 base=28 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-large.png" -chars count=21 +chars count=22 char id=48 x=0 y=0 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 char id=49 x=25 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=50 x=53 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 @@ -22,4 +22,5 @@ char id=65 x=137 y=28 width=19 height=28 xoffset=0 yoffset=0 char id=66 x=158 y=28 width=28 height=25 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=67 x=186 y=28 width=26 height=25 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=68 x=213 y=28 width=28 height=28 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 -char id=69 x=0 y=56 width=24 height=28 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file +char id=69 x=0 y=56 width=24 height=28 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 +char id=70 x=25 y=56 width=20 height=28 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-280x280/fonts/crystal-icons-large.png b/resources-round-280x280/fonts/crystal-icons-large.png index 67cd902909ed36166585f29528790b0b885b7056..854a00a972e9608de2c691b70a0aa5d091ea7673 100644 GIT binary patch literal 10889 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 diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt index a8a3bf8f..f8211ddc 100644 --- a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt +++ b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-39 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=39 base=39 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-extra-large.png" -chars count=21 +chars count=22 char id=48 x=0 y=0 width=34 height=39 xoffset=0 yoffset=0 xadvance=34 page=0 chnl=15 char id=49 x=34 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 char id=50 x=73 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 @@ -23,3 +23,4 @@ char id=66 x=153 y=78 width=43 height=39 xoffset=0 yoffset=0 char id=67 x=173 y=39 width=34 height=39 xoffset=0 yoffset=0 xadvance=34 page=0 chnl=15 char id=68 x=206 y=38 width=40 height=39 xoffset=0 yoffset=0 xadvance=40 page=0 chnl=15 char id=69 x=195 y=78 width=35 height=40 xoffset=0 yoffset=0 xadvance=35 page=0 chnl=15 +char id=70 x=0 y=114 width=29 height=40 xoffset=0 yoffset=0 xadvance=29 page=0 chnl=15 diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.png b/resources-round-390x390/fonts/crystal-icons-extra-large.png index 3ed292d2d672dec8e9584b8ddd26405be7705e11..a10e36500d607546ad8af0e048219ab036fe9142 100644 GIT binary patch delta 6724 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 S@vuU`e<;bR$yQ36efb|F0<-o2 delta 6245 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 ZK;$A15+6P*pMd^{s*;A{cX{)W{{!Gb3zPr= diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 67ccc8fd..a7632041 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -59,6 +59,7 @@ Пройденные вверх этажи Solar Intensity Body Battery + Recovery Time Время интенсивной активности (минуты за неделю) Калории (ручной ввод цели) Выключено diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 37ad7014..b86d803f 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 95f6a68a..17e8a0a0 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-small-icons/fonts/crystal-icons-small.fnt b/resources-small-icons/fonts/crystal-icons-small.fnt index 80e68199..c901e257 100644 --- a/resources-small-icons/fonts/crystal-icons-small.fnt +++ b/resources-small-icons/fonts/crystal-icons-small.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-20 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=20 base=20 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-small.png" -chars count=21 +chars count=22 char id=48 x=0 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=49 x=21 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=50 x=42 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 @@ -22,4 +22,5 @@ char id=65 x=66 y=21 width=14 height=20 xoffset=0 yoffset=0 char id=66 x=80 y=21 width=26 height=22 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=67 x=106 y=21 width=24 height=20 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=68 x=133 y=21 width=21 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 -char id=69 x=154 y=21 width=17 height=20 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 \ No newline at end of file +char id=69 x=154 y=21 width=17 height=20 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 +char id=70 x=172 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 \ No newline at end of file diff --git a/resources-small-icons/fonts/crystal-icons-small.png b/resources-small-icons/fonts/crystal-icons-small.png index 44d4f85011f4733de1b6e71ada8eb259c4373917..4ca84a0dcccd6d517abe9d059378c701c464011c 100644 GIT binary patch literal 5706 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 literal 5503 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 HTZQ}|KB>g6 diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index da9a762a..c4dca522 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 621ea65e..a79fd382 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -59,6 +59,7 @@ Våningar Solar Intensity Body Battery + Recovery Time Aktiva minuter (Vecka) Kalorier (Manuellt mål) Off diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index ea1db44d..a22ab1ef 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index af0adcd1..c6dcfc43 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -60,6 +60,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/resources/fonts/crystal-icons.fnt b/resources/fonts/crystal-icons.fnt index 41492848..ef9dda6f 100644 --- a/resources/fonts/crystal-icons.fnt +++ b/resources/fonts/crystal-icons.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-24 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=24 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons.png" -chars count=21 +chars count=22 char id=48 x=0 y=0 width=21 height=24 xoffset=1 yoffset=0 xadvance=24 page=0 chnl=15 char id=49 x=22 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=50 x=47 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 @@ -23,3 +23,4 @@ char id=66 x=145 y=27 width=24 height=22 xoffset=0 yoffset=0 char id=67 x=169 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=68 x=195 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=69 x=218 y=26 width=21 height=24 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 +char id=70 x=0 y=47 width=18 height=26 xoffset=0 yoffset=0 xadvance=18 page=0 chnl=15 diff --git a/resources/fonts/crystal-icons.png b/resources/fonts/crystal-icons.png index 13064c469e4d352361a918e5fc64c8bc5f04482e..51f1d07ebcea2a3ae729552bfd71bd67bba4de9f 100644 GIT binary patch delta 5616 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 literal 6340 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 nuU~@Strings.FloorsClimbed @Strings.SolarIntensity @Strings.BodyBattery + @Strings.RecoveryTime @@ -115,6 +116,7 @@ @Strings.FloorsClimbed @Strings.SolarIntensity @Strings.BodyBattery + @Strings.RecoveryTime @@ -138,6 +140,7 @@ @Strings.FloorsClimbed @Strings.SolarIntensity @Strings.BodyBattery + @Strings.RecoveryTime diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 5b935952..aeeb0e30 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -59,6 +59,7 @@ Floors Climbed Solar Intensity Body Battery + Recovery Time Active Minutes (Weekly) Calories (Manual Goal) Off diff --git a/source/DataFields.mc b/source/DataFields.mc index 49794160..2e47d1fd 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -33,7 +33,8 @@ enum /* FIELD_TYPES */ { FIELD_TYPE_PULSE_OX, FIELD_FLOOR_CLIMBED, FIELD_SOLAR_INTENSITY, - FIELD_BODY_BATTERY + FIELD_BODY_BATTERY, + FIELD_RECOVERY_TIME } class DataFields extends Ui.Drawable { @@ -324,6 +325,7 @@ class DataFields extends Ui.Drawable { FIELD_FLOOR_CLIMBED => "1", // SG Addition FIELD_SOLAR_INTENSITY => "D", // SG Addition FIELD_BODY_BATTERY => "E", // SG Addition + FIELD_RECOVERY_TIME => "F" // SG Addition }[fieldType]; } @@ -374,9 +376,20 @@ class DataFields extends Ui.Drawable { var weatherValue; var sunTimes; var unit; + var info; switch (type) { // SG Addition + case FIELD_RECOVERY_TIME: + info = ActivityMonitor.getInfo(); + if (info has :timeToRecovery) { + var recoveryTyime = info.timeToRecovery; + if (recoveryTyime != null) { + value = recoveryTyime.format(INTEGER_FORMAT); + } + } + break; + // SG Addition case FIELD_BODY_BATTERY: var bodyBattery = null; if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { @@ -404,7 +417,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_FLOOR_CLIMBED: - var info = ActivityMonitor.getInfo(); + info = ActivityMonitor.getInfo(); if (info has :floorsClimbed) { var climbed = info.floorsClimbed; var goal = info.floorsClimbedGoal; From 4525f1ecb8c4dcd1359c229dbc4b641fc3f89d27 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 19:34:36 -0500 Subject: [PATCH 059/220] Fixed 30 minutes offset time zone, allows Tesla's server to be specified to allow Mainland China and added customizable colors --- resources-ces/strings/strings.xml | 10 +++- resources-dan/strings/strings.xml | 10 +++- resources-deu/strings/strings.xml | 11 +++- resources-dut/strings/strings.xml | 9 +++ resources-fin/strings/strings.xml | 11 +++- resources-fre/strings/strings.xml | 5 ++ resources-hrv/strings/strings.xml | 11 +++- resources-hun/strings/strings.xml | 11 +++- resources-ita/strings/strings.xml | 11 +++- resources-kor/strings/strings.xml | 11 +++- resources-nob/strings/strings.xml | 11 +++- resources-pol/strings/strings.xml | 11 +++- resources-por/strings/strings.xml | 11 +++- resources-rus/strings/strings.xml | 11 +++- resources-slo/strings/strings.xml | 11 +++- resources-slv/strings/strings.xml | 11 +++- resources-spa/strings/strings.xml | 11 +++- resources-swe/strings/strings.xml | 11 +++- resources-zhs/strings/strings.xml | 11 +++- resources-zht/strings/strings.xml | 11 +++- resources/settings/properties.xml | 4 ++ resources/settings/settings.xml | 15 +++++ resources/strings/strings.xml | 6 ++ source/BackgroundService.mc | 8 +-- source/CrystalView.mc | 98 +++++++++++++++++-------------- source/DataFields.mc | 5 +- 26 files changed, 277 insertions(+), 69 deletions(-) diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index a781c940..ee061ab6 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,13 @@ Lis Pro + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 6cc33468..18907ece 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,13 @@ Nov Dec + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 18d79f82..a4ac87ec 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -80,7 +80,6 @@ Wetter Feuchtigkeit Druck - Pulse Ox @@ -106,4 +105,14 @@ Nov Dez + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 637090b5..e0d5c28a 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -107,4 +107,13 @@ Nov Dec + + Battery Numeric + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 968ce8bf..dfb16201 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Mar Jou + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 991f838d..95dbc639 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -111,5 +111,10 @@ Information Tesla Tesla Access Token Tesla Refresh Token + Location du serveur API de Tesla + Location du serveur Auth de Tesla + Entrez le nom de domaine du serveur Ne Pas Déranger + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index a5731714..0f654f8d 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Stu Pro + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 22344c33..8e960710 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ nov dec + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 4323056a..c4cafd52 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Nov Dic + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index e62f4e97..0588793d 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox KOR @@ -107,4 +106,14 @@ 11월 12월 + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 5ef0cbea..99e8cc56 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Nov Des + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 5c947183..a4326066 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -80,7 +80,6 @@ Pogoda Humidity Ciśnienie - Pulse Ox @@ -106,4 +105,14 @@ Lis Gru + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 420b3a78..f86224a7 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Nov Dez + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index a7632041..6d004afb 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -80,7 +80,6 @@ Погода Влажность Давление - Pulse Ox RUS @@ -106,4 +105,14 @@ Ноя Дек + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index b86d803f..0b1589d8 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Nov Dec + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 17e8a0a0..812ab06b 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Nov Dec + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index c4dca522..a5ca25a6 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox @@ -107,4 +106,14 @@ Nov Dic + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index a79fd382..e7692ee7 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -80,7 +80,6 @@ Väder Luftfuktighet Tryck - Pulse Ox @@ -106,4 +105,14 @@ nov dec + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index a22ab1ef..5efd97ad 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox ZHS @@ -107,4 +106,14 @@ 十一月 十二月 + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index c6dcfc43..59e004b8 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -81,7 +81,6 @@ Weather Humidity Pressure - Pulse Ox ZHT @@ -107,4 +106,14 @@ 十一月 十二月 + + Battery Numeric + Pulse Ox + Tesla Info + Tesla Access Token + Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name + Do Not Disturb diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index bd631e81..f814ac27 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -3,6 +3,8 @@ 2.5.0 0 + + false 0 0 @@ -34,5 +36,7 @@ + owner-api.teslamotors.com + auth.tesla.com diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 84d8385b..c23633c4 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -24,6 +24,14 @@ + + + + + + + + @Strings.Steps @@ -234,5 +242,12 @@ + + + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index aeeb0e30..4e3fcb6e 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -111,6 +111,12 @@ Tesla Info Tesla Access Token Tesla Refresh Token + Location of Tesla's API servers? + Location of Tesla's Auth servers? + Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index d490a673..d72d08b7 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -60,9 +60,9 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); if (_vehicle_id == null) { - makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles", null, method(:onReceiveVehicles)); + makeTeslaWebRequest("https://" + App.getApp().getProperty("TeslaServerAPILocation") + "/api/1/vehicles", null, method(:onReceiveVehicles)); } else { - makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://" + App.getApp().getProperty("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* @@ -128,7 +128,7 @@ class BackgroundService extends Sys.ServiceDelegate { } if (_vehicle_id) { - makeTeslaWebRequest("https://owner-api.teslamotors.com/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://" + App.getApp().getProperty("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } } } /* else { @@ -346,7 +346,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function makeTeslaWebPost(token, notify) { - var url = "https://auth.tesla.com/oauth2/v3/token"; + var url = "https://" + App.getApp().getProperty("TeslaServerAUTHLocation") + "/oauth2/v3/token"; Comms.makeWebRequest( url, { diff --git a/source/CrystalView.mc b/source/CrystalView.mc index b1d8e9b1..3d856cdf 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -443,59 +443,67 @@ class CrystalView extends Ui.WatchFace { // #182 Protect against null or unexpected type e.g. String. var theme = App.getApp().getIntProperty("Theme", 0); + var lightFlag; + var themeOverride = App.getApp().getProperty("ThemeOverride"); + if (themeOverride.equals("")) { + // Theme-specific colours. + gThemeColour = [ + Graphics.COLOR_BLUE, // THEME_BLUE_DARK + Graphics.COLOR_PINK, // THEME_PINK_DARK + Graphics.COLOR_GREEN, // THEME_GREEN_DARK + Graphics.COLOR_DK_GRAY, // THEME_MONO_LIGHT + 0x55AAFF, // THEME_CORNFLOWER_BLUE_DARK + 0xFFFFAA, // THEME_LEMON_CREAM_DARK + Graphics.COLOR_ORANGE, // THEME_DAYGLO_ORANGE_DARK + Graphics.COLOR_RED, // THEME_RED_DARK + Graphics.COLOR_WHITE, // THEME_MONO_DARK + Graphics.COLOR_DK_BLUE, // THEME_BLUE_LIGHT + Graphics.COLOR_DK_GREEN, // THEME_GREEN_LIGHT + Graphics.COLOR_DK_RED, // THEME_RED_LIGHT + 0xFFFF00, // THEME_VIVID_YELLOW_DARK + Graphics.COLOR_ORANGE, // THEME_DAYGLO_ORANGE_LIGHT + Graphics.COLOR_YELLOW // THEME_CORN_YELLOW_DARK + ][theme]; + + // Light/dark-specific colours. + var lightFlags = [ + false, // THEME_BLUE_DARK + false, // THEME_PINK_DARK + false, // THEME_GREEN_DARK + true, // THEME_MONO_LIGHT + false, // THEME_CORNFLOWER_BLUE_DARK + false, // THEME_LEMON_CREAM_DARK + false, // THEME_DAYGLO_ORANGE_DARK + false, // THEME_RED_DARK + false, // THEME_MONO_DARK + true, // THEME_BLUE_LIGHT + true, // THEME_GREEN_LIGHT + true, // THEME_RED_LIGHT + false, // THEME_VIVID_YELLOW_DARK + true, // THEME_DAYGLO_ORANGE_LIGHT + false, // THEME_CORN_YELLOW_DARK + ]; + + lightFlag = lightFlags[theme]; + } else { + gThemeColour = themeOverride.toNumberWithBase(16); + lightFlag = App.getApp().getProperty("ThemeLightOverride"); + } - // Theme-specific colours. - gThemeColour = [ - Graphics.COLOR_BLUE, // THEME_BLUE_DARK - Graphics.COLOR_PINK, // THEME_PINK_DARK - Graphics.COLOR_GREEN, // THEME_GREEN_DARK - Graphics.COLOR_DK_GRAY, // THEME_MONO_LIGHT - 0x55AAFF, // THEME_CORNFLOWER_BLUE_DARK - 0xFFFFAA, // THEME_LEMON_CREAM_DARK - Graphics.COLOR_ORANGE, // THEME_DAYGLO_ORANGE_DARK - Graphics.COLOR_RED, // THEME_RED_DARK - Graphics.COLOR_WHITE, // THEME_MONO_DARK - Graphics.COLOR_DK_BLUE, // THEME_BLUE_LIGHT - Graphics.COLOR_DK_GREEN, // THEME_GREEN_LIGHT - Graphics.COLOR_DK_RED, // THEME_RED_LIGHT - 0xFFFF00, // THEME_VIVID_YELLOW_DARK - Graphics.COLOR_ORANGE, // THEME_DAYGLO_ORANGE_LIGHT - Graphics.COLOR_YELLOW // THEME_CORN_YELLOW_DARK - ][theme]; - - // Light/dark-specific colours. - var lightFlags = [ - false, // THEME_BLUE_DARK - false, // THEME_PINK_DARK - false, // THEME_GREEN_DARK - true, // THEME_MONO_LIGHT - false, // THEME_CORNFLOWER_BLUE_DARK - false, // THEME_LEMON_CREAM_DARK - false, // THEME_DAYGLO_ORANGE_DARK - false, // THEME_RED_DARK - false, // THEME_MONO_DARK - true, // THEME_BLUE_LIGHT - true, // THEME_GREEN_LIGHT - true, // THEME_RED_LIGHT - false, // THEME_VIVID_YELLOW_DARK - true, // THEME_DAYGLO_ORANGE_LIGHT - false, // THEME_CORN_YELLOW_DARK - ]; - - // #124: fr45 cannot show grey. - var isFr45 = (Sys.getDeviceSettings().screenWidth == 208); + // #124: fr45 cannot show grey. SG Fr45 not supported + //var isFr45 = (Sys.getDeviceSettings().screenWidth == 208); - if (lightFlags[theme]) { + if (lightFlag) { gMonoLightColour = Graphics.COLOR_BLACK; - gMonoDarkColour = isFr45 ? Graphics.COLOR_BLACK : Graphics.COLOR_DK_GRAY; + gMonoDarkColour = /*isFr45 ? Graphics.COLOR_BLACK : */ Graphics.COLOR_DK_GRAY; - gMeterBackgroundColour = isFr45 ? Graphics.COLOR_BLACK : Graphics.COLOR_LT_GRAY; + gMeterBackgroundColour = /*isFr45 ? Graphics.COLOR_BLACK : */ Graphics.COLOR_LT_GRAY; gBackgroundColour = Graphics.COLOR_WHITE; } else { gMonoLightColour = Graphics.COLOR_WHITE; - gMonoDarkColour = isFr45 ? Graphics.COLOR_WHITE : Graphics.COLOR_LT_GRAY; + gMonoDarkColour = /*isFr45 ? Graphics.COLOR_WHITE : */ Graphics.COLOR_LT_GRAY; - gMeterBackgroundColour = isFr45 ? Graphics.COLOR_WHITE : Graphics.COLOR_DK_GRAY; + gMeterBackgroundColour = /*isFr45 ? Graphics.COLOR_WHITE : */ Graphics.COLOR_DK_GRAY; gBackgroundColour = Graphics.COLOR_BLACK; } } diff --git a/source/DataFields.mc b/source/DataFields.mc index 2e47d1fd..1919b16f 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -562,7 +562,8 @@ class DataFields extends Ui.Drawable { // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). now = now.hour + ((now.min + 1) / 60.0); //logMessage(now); - +gLocationLat=-34.9998826; +gLocationLng=138.3309808; // Get today's sunrise/sunset times in current time zone. sunTimes = getSunTimes(gLocationLat, gLocationLng, null, /* tomorrow */ false); //logMessage(sunTimes); @@ -794,7 +795,7 @@ function getSunTimes(lat, lng, tz, tomorrow) { var deltaJSet = jSet - jDate; var deltaJRise = jRise - jDate; - var tzOffset = (tz == null) ? (Sys.getClockTime().timeZoneOffset / 3600) : tz; + var tzOffset = (tz == null) ? (Sys.getClockTime().timeZoneOffset / 3600.0) : tz; return [ /* localRise */ (deltaJRise * 24) + tzOffset, /* localSet */ (deltaJSet * 24) + tzOffset From 7f28035fec70e39611d82d7f39c2b3d7fafa76d6 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:16:11 -0500 Subject: [PATCH 060/220] Update README.md Too many changes to show in the Garmin "what's new" section so I moved them here instead. --- README.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/README.md b/README.md index f102bda8..38a4b143 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,93 @@ Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. ## What's New +### 2.12.0 +- Fixed sunrize/sunset time error when timezone has a 30 minutes offset +- Added support for Teslas in China. These needs different Tesla servers domain name than the rest of the world. These can be changed through the phone app. +
The default API and AUTH servers are owner-api.teslamotors.com and auth.tesla.com respectively. +
For China, they are owner-api.vn.cloud.tesla.cn and auth.tesla.cn +- Added customizable screen colors. Can be set by entering something other than 0 (or blank) in 'RGB Them override' field +
The format is RRGGBB (Red Green Blue) in hexadecimal (0-F). You can use this web site to figure out the colors you want. Don't enter the leading '#' though: https://www.rapidtables.com/convert/color/rgb-to-hex.html +
Checking Light theme override will give the watchface light background. Unchecking the field gives it a dark background (usefull for OLED display). +
These are the standard Garmin color and their hexadecimal equivalent + - WHITE FFFFFF + - LIGHT GRAY AAAAAA + - DARK GRAY 555555 + - BLACK 000000 + - RED FF0000 + - DARK RED AA0000 + - ORANGE FF5500 + - YELLOW FFAA00 + - GREEN 00FF00 + - DARK GREEN 00AA00 + - BLUE 00AAFF + - DARK BLUE 0000FF + - PURPLE AA00FF + - PINK FF00FF + - + +### 2.11.0 +- Added Recovery Time Left as a data field + +### 2.10.4 +- Fixed AlwaysOnDisplay of Venu SQ 2 and Venu SQ 2 Music + +### 2.10.3a +- Fixed Dutch translations. Thanks ChristopheMB + +### 2.10.3 +- Added the Enduro, Venu SQ 2 and Venu SQ 2 Music + +#### 2.10.2 +- Fixed missing 'Û' in 280x280 font + +### 2.10.1 +- Added Forerunner 255, 255 Music, 255s, 255s Music + +### 2.10.0 +- Added Body Battery as a data field. Bug fix for Solar Intensity on 390x390 watches + +### 2.9.0 +- Added the Solar Intensity as a data field. Relevant only to watches that support solar. + +### 2.8.2 +- Added the Forerunner 955 / Solar + +### 2.8.1 +- Removed the following watch as they have not enough memory for watch faces to work reliably with the newer versions of this watch face: D2 Bravo, D2 Bravo Titanium, fēnix 3 / tactix Bravo / quatix 3, fēnix 3 HR, Forerunner 230, Forerunner 235, Forerunner 630, Forerunner 735xt, Forerunner 920xt, vívoactive, vívoactive HR and vivolife. + +### 2.8.0 +- Added the Tesla battery level to the Always On Display. To stay within the 10% of pixel on, I removed the day of the week from the date to make room for the battery level. + +### 2.7.5 +- Added 'Do Not Disturb' as an indicator + +### 2.7.4.2 +- Added Descent Mk1, Mk2 and Mk2s as supported devices + +### 2.7.4.1 +- Fixed the '/' in the font files missing it. + +### 2.7.4 +- Added Floors climbed as a data field. Some fonts do not have the '/' symbol so for now on these watches (the 416x416 resolution watches), it will be displayed as a rectangle (default for non recognized character). + +### 2.7.3 +- The Altitude will remain on screen, even if the watch face loses focus. Also fix a very rare occurrence of a crash when displaying seconds and the area where the seconds are to be displayed is overwritten by the move bar. + +### 2.7.2 +- Trying to fix the Altitude code so its value doesn't disappear when GPS is lost. Removal of Garmin Swim 2 from supported devices. + +### 2.7.1 +- Fixes a crash when Garmin Weather was not available + +### 2.7.0 +- Addition of the Garmin Weather API. If you're having issue with the OpenWeatherMap API Key and your watch supports Garmin API 3.2 or higher (see https://developer.garmin.com/connect-iq/compatible-devices/), by clearing the field "OpenWeatherMap API Key Override" in the Settings, it will use the Garmin Weather API instead. Weather Options is available for watches with a Garmin API 2.4 and higher. + +### 2.6.3 +- Fix sunrise showing today's time instead of tomorrow's when sunset time has been reached and it's before midnight + +### 2.6.2 +- Disables background services for watch that doesn't support it. Features that won't work without background services are Weather, sunrise/sunset and Tesla Info. ### 2.5.0 - Add support for Venu® 2 and Venu® 2S (thanks to fallingrock for testing help). Thank you for your patience! From b5ee9371311b15a064b55b8c62abdb5d4771d545 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:18:37 -0500 Subject: [PATCH 061/220] Updated App version --- resources/settings/properties.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index f814ac27..5ee6259a 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,6 +1,6 @@ - 2.5.0 + 2.12.0 0 From 65323ded589678c1d6868f3b77a750b420df7c81 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:29:30 -0500 Subject: [PATCH 062/220] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 38a4b143..aefb5c22 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,6 @@ Reviews: - DARK BLUE 0000FF - PURPLE AA00FF - PINK FF00FF - - ### 2.11.0 - Added Recovery Time Left as a data field From 6f05ef24c71e0d5fa82f474790eb400e89937e64 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:55:53 -0500 Subject: [PATCH 063/220] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aefb5c22..a0f9cc3c 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ A Garmin Connect IQ watch face. ## Description -**If you enjoy using Crystal, you can support my work with a small donation:** -https://goo.gl/vFCE4T +**If you enjoy using Crystal, you can support my work with a small donation:**[ +https://bit.ly/garmin_tesla_watchface **FAQs, including how to change watch face settings:** https://github.com/warmsound/crystal-face/wiki/FAQ From 9d6110969b4f33d42ab13547916bcd873831e79a Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 21:04:10 -0500 Subject: [PATCH 064/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a0f9cc3c..f8660e0a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A Garmin Connect IQ watch face. ## Description -**If you enjoy using Crystal, you can support my work with a small donation:**[ +**If you enjoy this maintained version of Crystal with Tesla integration, you can support my work with a small donation:**[ https://bit.ly/garmin_tesla_watchface **FAQs, including how to change watch face settings:** From 66d60887610ba1b3b77343274587aa12a52af7a9 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 21:08:42 -0500 Subject: [PATCH 065/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8660e0a..64171da2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A Garmin Connect IQ watch face. ## Description **If you enjoy this maintained version of Crystal with Tesla integration, you can support my work with a small donation:**[ -https://bit.ly/garmin_tesla_watchface +https://bit.ly/sylvainga **FAQs, including how to change watch face settings:** https://github.com/warmsound/crystal-face/wiki/FAQ From 96639e5f46321fbadeb70c3834dffca9a3a5e50e Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Nov 2022 21:09:00 -0500 Subject: [PATCH 066/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 64171da2..be105957 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A Garmin Connect IQ watch face. ## Description -**If you enjoy this maintained version of Crystal with Tesla integration, you can support my work with a small donation:**[ +**If you enjoy this maintained version of Crystal with Tesla integration, you can support my work with a small donation:** https://bit.ly/sylvainga **FAQs, including how to change watch face settings:** From 76b0d45ad2493de7efc4ae8ec81f8b5edbb9c206 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 4 Dec 2022 20:59:30 -0500 Subject: [PATCH 067/220] Update README.md --- README.md | 236 +----------------------------------------------------- 1 file changed, 4 insertions(+), 232 deletions(-) diff --git a/README.md b/README.md index be105957..180546a3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ This is my first ever Connect IQ watch face (please be kind!), so I look forward Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. -## What's New +## What has been added by me. See https://apps.garmin.com/en-US/apps/9fd04d09-8c80-4c81-9257-17cfa0f0081b for what has been added previously by Pixel Pathos + ### 2.12.0 - Fixed sunrize/sunset time error when timezone has a 30 minutes offset - Added support for Teslas in China. These needs different Tesla servers domain name than the rest of the world. These can be changed through the phone app. @@ -33,7 +34,7 @@ Reviews:
For China, they are owner-api.vn.cloud.tesla.cn and auth.tesla.cn - Added customizable screen colors. Can be set by entering something other than 0 (or blank) in 'RGB Them override' field
The format is RRGGBB (Red Green Blue) in hexadecimal (0-F). You can use this web site to figure out the colors you want. Don't enter the leading '#' though: https://www.rapidtables.com/convert/color/rgb-to-hex.html -
Checking Light theme override will give the watchface light background. Unchecking the field gives it a dark background (usefull for OLED display). +
Checking *Light theme override* will give the watchface light background. Unchecking the field gives it a dark background (usefull for OLED display).
These are the standard Garmin color and their hexadecimal equivalent - WHITE FFFFFF - LIGHT GRAY AAAAAA @@ -113,233 +114,4 @@ Reviews: ### 2.6.2 - Disables background services for watch that doesn't support it. Features that won't work without background services are Weather, sunrise/sunset and Tesla Info. -### 2.5.0 -- Add support for Venu® 2 and Venu® 2S (thanks to fallingrock for testing help). Thank you for your patience! -- Technical update to CIQ 4.0.3. - -### 2.4.7 -- Improve German translation (thanks to 2b2bff). -- Translate Dutch settings (thanks to DRG-developer). -- Allow override of built-in OpenWeatherMap key, in case that key is blocked. -- Technical update to CIQ 3.2.5 SDK. - -### 2.4.6 -- Cycle OpenWeatherMap key to circumvent key abuse that led to blocked account. - -### 2.4.5 -- Add support for Korean language (thanks to nanbean). -- 2nd attempt at settings-related crash fix. - -### 2.4.4 -- Add support for Approach® S62, D2 Air, Descent™ Mk2, Garmin Swim™ 2, Rey™, MARQ® Golfer, Venu® Mercedes-Benz Collection, Venu® Sq, Venu® Sq – Music Edition. -- Fix several settings-related crashes. -- Update Russian translation (thanks to ya_kazachkov). -- Correct German translation (thanks to axcro7). -- Technical update to CIQ 3.2.2 SDK. - -### 2.4.3 -- Putative fix for Venu™ crash on 2.80 firmware. - -### 2.4.2 -- 2nd attempt at fēnix® 5X crash. Bug in 15.10 firmware (requiresBurnInProtection incorrectly set to true) identified with invaluable help from jeriveraf. - -### 2.4.1 -- Putative fix for fēnix® 5X series crash. Thank you everyone for your patience. - -### 2.4.0 -- Add support for Venu™, with new always-on layout. -- Add support for MARQ™ Adventurer and Commander. -- Technical update to CIQ 3.1.5 SDK. - -### 2.3.7 -- Add bespoke fonts and layout for fēnix® 6X. -- Improve readability of small font for all watches. - -### 2.3.6 -- Technical update to CIQ 3.1.4 SDK. Add support for fēnix® 6 series (except fēnix® 6X), Captain Marvel, First Avenger and vívoactive® 4 series. - -### 2.3.5 -- Add support for Forerunner® 45. - -### 2.3.4 -- Fix crash when changing numeric settings (e.g. "Calories Goal") using Connect IQ Store app. - -### 2.3.3 -- New Meter Style options, and new Meter Digits Style setting. -- Fix issue when setting field or indicator count to 0. -- Fix display of weather icon on Forerunner® 735XT. -- Fix German translation typo. -- Technical update to CIQ 3.0.11 SDK. Add support for Forerunner® 245/245 Music/945 and vívolife. - -### 2.3.2 -- Fix issues with weather and humidity not updating. -- Technical update to CIQ 3.0.10 SDK. Add support for MARQ™ series and vívoactive® 3 Mercedes-Benz. - -### 2.3.1 -- Putative fix for intermittent storage-related crashes on fēnix® 5 series, vívoactive® 3 series and Approach® S60. -- Update Swedish translation (thanks to fredrikaverpil). -- Technical update to CIQ 3.0.9 SDK. Add support for vívoactive® 3 Music LTE. - -### 2.3.0 -- Increase time font size and revise layouts for all watches. -- Single line time for vívoactive® HR. - -### 2.2.6 -- Add "Humidity" data field (uses OpenWeatherMap). Many thanks to jrmcsoftware for implementing this. -- Technical update to CIQ 3.0.8 SDK. - -### 2.2.5 -- "Pressure" data field should use historical data, to respect manual pressure calibration on fēnix® 5 watches (thanks to Allalin72 for help with this). - -### 2.2.4 -- Fix issue with move bar not clearing in "Show Filled Segments" mode (thanks to BrettL for reproduction steps). -- Add "Corn Yellow (Dark)" and "Dayglo Orange (Light)" themes. -- Add "Pressure" data field. -- Technical update to CIQ 3.0.7 SDK. - -### 2.2.3 -- Remove need to enter OpenWeatherMap key. -- Technical update to CIQ 3.0.6 SDK. - -### 2.2.2 -- Fix issue with stuck "key!" if weather key is used before it has been activated. - -### 2.2.1 -- Fix intermittent crash after receiving weather data. - -### 2.2.0 -- Add "Weather" data field: CIQ 2.x devices only, requires free OpenWeatherMap API key (https://openweathermap.org/). - -### 2.1.0 -- Add "Sunrise/Sunset" data field. -- Read altitude from more up-to-date source, and enable for all watches. -- Add Croatian date translation (thanks to Kristijan). -- Russian translation updates, and string fixes (thanks to xgsa). -- German translation for settings screen (thanks to dragonito). -- Technical update to CIQ 3.0.4 SDK. - -### 2.0.1 -- Fix crash when changing settings. - -### 2.0.0 -- Russian translation for watch face and settings screen (thanks to xgsa). -- Display of additional time zone: specify city in settings (CIQ 2.x devices only, in beta). See FAQ. -- Re-enable support for Approach® S60. -- Technical update to CIQ 3.0.3 SDK. - -### 1.8.1 -- Added "Heart Rate (Live 5s)" data field. -- Read HR from more up-to-date source. -- Improved clarity of battery indicator. -- "Hide Hours Leading Zero" now setting applies to both 12- and 24-hour modes. -- Technical update to CIQ 2.4.9 SDK, to add support for D2™ Delta, D2™ Delta PX, D2™ Delta S. - -### 1.8.0 -- Added setting to control number of data fields (0-3). -- Added setting to control number of indicators (0-3): Bluetooth, alarms, notifications, bluetooth/notifications. -- Improved memory efficiency. -- Layout adjustments. -- Technical update to CIQ 2.4.8 SDK. - -### 1.7.4 -- Polish translation for settings screen (thanks to Flugcojt). -- Swedish translation for settings screen (thanks to hasselrot). - -### 1.7.3 -- Update to CIQ 2.4.7 SDK, to add support for fēnix® 5 Plus, fēnix® 5S Plus, fēnix® 5X Plus, vívoactive® 3 Music. -- Fixed issue with "ft" altitude units displaying incorrectly (thanks to Matt Reiser). - -### 1.7.2 -- Altitude units now obey statue/metric setting (thanks to Rick Gorham). -- Added "Battery (Hide Percentage)" data field (thanks to Paolo Avezzano). -- Corrected number of move bar segments to 5 (thanks to Viorel). -- Technical update to CIQ 2.4.6 SDK. - -### 1.7.1 -- Re-enabled Forerunner® 920XT, following non-anti-aliased custom font workaround provided by Coleman at Garmin. -- Corrected French translation (thanks to Ju Neusch). - -### 1.7.0 -- Added temperature data field option. -- Added vivid yellow dark theme. -- Added meter style setting. -- Added move bar style setting. -- Corrected German translations (thanks to Christoph Heymann for help with this). -- Temporarily removed support for Approach® S60 and Forerunner® 920XT, pending fixes from Garmin - many thanks for your patience. -- Technical update to CIQ 2.4.5 SDK. - -### 1.6.1 -- Added barometric altitude for supported CIQ 2.x devices. -- Show midnight as "12" instead of "00" in 12-hour mode. -- Fixed incorrect default settings for vívoactive®. - -### 1.6.0 -- Added blue, red and green light themes. -- Allow colour of hours and minutes to be overridden independently. -- Allow hiding of hours leading zero in 12 hr mode. -- Prevent overlapping goal numbers on semi-round watches (thanks to G_stijn for reporting this). - -### 1.5.3 -- Fix crash if floors or active minutes goal is set to 0: show disabled meter instead. - -### 1.5.2 -- Technical update to CIQ 2.4.4 SDK. - -### 1.5.1 -- Added alarms data field option. -- Rollout to CIQ 1.x devices, part 2: Forerunner® 230, Forerunner® 235, Forerunner® 630, Forerunner® 920XT, vívoactive®. - -### 1.5.0 -- Rollout to CIQ 1.x devices, part 1: D2™ Bravo, D2™ Bravo Titanium, fēnix® 3, fēnix® 3 HR. - -### 1.4.3 -- Meters can now show a custom calories goal, specified in settings. -- Fixed issue with wrong strings or crash when changing settings via Garmin Express in non-English locales (thanks to Ezio Pillan for reporting this bug). -- Added app version to settings page. - -### 1.4.2 -- Allow hiding of seconds. - -### 1.4.1 -- Reduce battery drain, part 2: optimise per-minute updates (cache drawable references). -- Allow meters to display battery level. - -### 1.4.0 -- Reduce battery drain, part 1: reduce per-second update time from ~13ms to ~5ms (measured on Approach® S60, simulator). -- Added Red (Dark) and Mono (Dark) themes. -- Added support for vívoactive® HR. - -### 1.3.0 -- Added support for fēnix® 5S, fēnix® Chronos, Forerunner® 735XT. -- Added Dayglo Orange theme. - -### 1.2.1 -- Fixed issue with distance value being too low (thanks to catana.remulus for reporting and assisting with this bug). - -### 1.2.0 -- Added support for Approach® S60, D2™ Charlie, Descent™ Mk1, Forerunner® 645, Forerunner® 645 Music, Forerunner® 935, fēnix® 5, fēnix® 5X. -- Added Cornflower Blue and Lemon Cream themes for better visibility. - -**N.B. Due to a vívoactive® 3 firmware bug, this watch face will be stuck on the language that was active at the time of the 3.30-3.40 firmware upgrade. Hopefully Garmin will fix this in a future firmware.** - -### 1.1.0 -- Internationalisation: added support for Chinese (Simplified/Traditional), Czech, Danish, Dutch, Finnish, French, German, Hungarian, Italian, Norwegian, Polish, Portugese, Slovak, Slovenian, Spanish, Swedish. -- Force language to English for unsupported locales, to prevent garbled characters. -- Fixed issue with battery meter not showing low/critical warning colours soon enough. - -### 1.0.1 -- Fixed issue with showing noon as AM, rather than PM (with thanks to JACalvo for reporting this bug). -- Fixed issue with move bar not updating correctly. - -### 1.0.0 -- Initial public release for vívoactive® 3 only. - -## Credits -Icons: -- "[Distance](https://thenounproject.com/term/distance/1514833/)" icon by Becris from [the Noun Project](https://thenounproject.com). -- "[Fire](https://thenounproject.com/term/fire/24187/)" icon by Jenny Amer from [the Noun Project](https://thenounproject.com). -- "[Steps](https://thenounproject.com/term/steps/87667/)" icon by Eugen Belyakoff from [the Noun Project](https://thenounproject.com). -- "[Upstairs](https://thenounproject.com/term/upstairs/304907/)" icon by Arthur Shlain from [the Noun Project](https://thenounproject.com). -- "[Stopwatch](https://thenounproject.com/term/stopwatch/319102/)" icon by Rohith M S from [the Noun Project](https://thenounproject.com). -- "[Mountains](https://thenounproject.com/term/mountains/1468194/)" icon by Deemak Daksina from [the Noun Project](https://thenounproject.com). -- "[Humidity](https://thenounproject.com/term/humidity/1554816/)" icon by Akriti Bhusal from [the Noun Project](https://thenounproject.com). +See https://apps.garmin.com/en-US/apps/9fd04d09-8c80-4c81-9257-17cfa0f0081b for previous changes made by Pixel Pathos From c9d17b64ecfab48a33c2c1a77fc2dbab77e2b6f2 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 7 Dec 2022 22:33:22 -0500 Subject: [PATCH 068/220] Removed troubleshooting code left by mistake --- resources/settings/properties.xml | 2 +- source/DataFields.mc | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 5ee6259a..ec31751a 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,6 +1,6 @@ - 2.12.0 + 2.12.1 0 diff --git a/source/DataFields.mc b/source/DataFields.mc index 1919b16f..e0a94ee6 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -562,8 +562,7 @@ class DataFields extends Ui.Drawable { // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). now = now.hour + ((now.min + 1) / 60.0); //logMessage(now); -gLocationLat=-34.9998826; -gLocationLng=138.3309808; + // Get today's sunrise/sunset times in current time zone. sunTimes = getSunTimes(gLocationLat, gLocationLng, null, /* tomorrow */ false); //logMessage(sunTimes); From 55f6bb7bbe2905894d7b48c2d38c0e2a66a11143 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 7 Dec 2022 22:35:38 -0500 Subject: [PATCH 069/220] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 180546a3..2c57435b 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,9 @@ Reviews: ## What has been added by me. See https://apps.garmin.com/en-US/apps/9fd04d09-8c80-4c81-9257-17cfa0f0081b for what has been added previously by Pixel Pathos +### 2.12.1 +- Removed troubleshooting code left by mistake + ### 2.12.0 - Fixed sunrize/sunset time error when timezone has a 30 minutes offset - Added support for Teslas in China. These needs different Tesla servers domain name than the rest of the world. These can be changed through the phone app. From f4a1e62b1d2b118351995c027e9078e1e82dc463 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 6 Jan 2023 10:01:24 -0500 Subject: [PATCH 070/220] Added BodyBattery as a Goal Meter --- resources/settings/properties.xml | 2 +- resources/settings/settings.xml | 6 ++++-- source/CrystalView.mc | 23 +++++++++++++++++++++++ source/DataArea.mc | 5 +++-- source/GoalMeter.mc | 3 ++- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index ec31751a..44320281 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,6 +1,6 @@ - 2.12.1 + 2.13.0 0 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index c23633c4..007b0dbd 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -39,7 +39,8 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.BodyBattery + @Strings.Off
@@ -50,7 +51,8 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.BodyBattery + @Strings.Off diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 3d856cdf..75ccdd3e 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -8,6 +8,7 @@ using Toybox.Time; using Toybox.Time.Gregorian; using Toybox.Weather; using Toybox.Position; +using Toybox.SensorHistory as SensorHistory; using Toybox.Math; @@ -634,6 +635,28 @@ class CrystalView extends Ui.WatchFace { values[:max] = 100; break; + case GOAL_TYPE_BODY_BATTERY: + // #8: floor() battery to be consistent. + var bodyBattery = null; + values[:isValid] = false; + values[:max] = 100; + + if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { + bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); + if (bodyBattery != null) { + bodyBattery = bodyBattery.next(); + } + if (bodyBattery !=null) { + bodyBattery = bodyBattery.data; + } + if (bodyBattery != null && bodyBattery >= 0 && bodyBattery <= 100) { + values[:current] = bodyBattery.toFloat(); + values[:isValid] = true; + } + } + + break; + case GOAL_TYPE_CALORIES: values[:current] = info.calories; diff --git a/source/DataArea.mc b/source/DataArea.mc index 078f07b5..888f0eb7 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -41,7 +41,7 @@ class DataArea extends Ui.Drawable { if (leftValues[:isValid]) { mLeftGoalCurrent = leftValues[:current].format(INTEGER_FORMAT); - mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY) ? "%" : leftValues[:max].format(INTEGER_FORMAT); + mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { mLeftGoalCurrent = null; mLeftGoalMax = null; @@ -52,7 +52,7 @@ class DataArea extends Ui.Drawable { if (rightValues[:isValid]) { mRightGoalCurrent = rightValues[:current].format(INTEGER_FORMAT); - mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY) ? "%" : rightValues[:max].format(INTEGER_FORMAT); + mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { mRightGoalCurrent = null; mRightGoalMax = null; @@ -149,6 +149,7 @@ class DataArea extends Ui.Drawable { GOAL_TYPE_STEPS => "0", GOAL_TYPE_FLOORS_CLIMBED => "1", GOAL_TYPE_ACTIVE_MINUTES => "2", + GOAL_TYPE_BODY_BATTERY => "E", }[type]; dc.setColor(isValid ? gThemeColour : gMeterBackgroundColour, Gfx.COLOR_TRANSPARENT); diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index be58e36f..09d2c56f 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -8,7 +8,8 @@ using Toybox.Graphics; enum /* GOAL_TYPES */ { GOAL_TYPE_BATTERY = -1, GOAL_TYPE_CALORIES = -2, - GOAL_TYPE_OFF = -3, + GOAL_TYPE_BODY_BATTERY = -3, + GOAL_TYPE_OFF = -4, GOAL_TYPE_STEPS = 0, // App.GOAL_TYPE_STEPS GOAL_TYPE_FLOORS_CLIMBED, // App.GOAL_TYPE_FLOORS_CLIMBED From db2942b61af1c724169ebf938f32653b8b1c952b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 6 Jan 2023 10:02:35 -0500 Subject: [PATCH 071/220] Added Body Battery as a Goal Meter --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 2c57435b..81ec6c32 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,9 @@ Reviews: ## What has been added by me. See https://apps.garmin.com/en-US/apps/9fd04d09-8c80-4c81-9257-17cfa0f0081b for what has been added previously by Pixel Pathos +### 2.13.0 +- Added Body Battery as a Goal Meter + ### 2.12.1 - Removed troubleshooting code left by mistake From 32321d03512d8bd09a09c362186147492790195a Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 6 Jan 2023 10:28:04 -0500 Subject: [PATCH 072/220] Remove warning at build time --- resources-ces/strings/strings.xml | 3 +++ resources-dan/strings/strings.xml | 3 +++ resources-deu/strings/strings.xml | 3 +++ resources-dut/strings/strings.xml | 3 +++ resources-fin/strings/strings.xml | 3 +++ resources-fre/strings/strings.xml | 5 +++-- resources-hrv/strings/strings.xml | 3 +++ resources-hun/strings/strings.xml | 3 +++ resources-ita/strings/strings.xml | 3 +++ resources-kor/strings/strings.xml | 3 +++ resources-nob/strings/strings.xml | 3 +++ resources-pol/strings/strings.xml | 3 +++ resources-por/strings/strings.xml | 3 +++ resources-rus/strings/strings.xml | 3 +++ resources-slo/strings/strings.xml | 3 +++ resources-slv/strings/strings.xml | 3 +++ resources-spa/strings/strings.xml | 3 +++ resources-swe/strings/strings.xml | 3 +++ resources-zhs/strings/strings.xml | 3 +++ resources-zht/strings/strings.xml | 3 +++ 20 files changed, 60 insertions(+), 2 deletions(-) diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index ee061ab6..17d94ff4 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -115,4 +115,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 18907ece..e71a864d 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -115,4 +115,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index a4ac87ec..9cb1a65a 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -115,4 +115,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index e0d5c28a..e45256e8 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index dfb16201..df85d066 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 95dbc639..86bc49ed 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -115,6 +115,7 @@ Location du serveur Auth de Tesla Entrez le nom de domaine du serveur Ne Pas Déranger - RGB Theme override - In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Remplacement du thème par RGB + En hexadécimal en utilisant ce format RRGGBB. Si celui-ci est différent de 0, c'est cette combinaison de couleurs qui sera utilisée à la place du thème + Remplacement du thème Clair diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 0f654f8d..d9cb8e62 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 8e960710..81c8b759 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index c4cafd52..df462614 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 0588793d..64dcbdcb 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 99e8cc56..c73d8c32 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index a4326066..d0d67fc8 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -115,4 +115,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index f86224a7..38088502 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 6d004afb..70ccef27 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -115,4 +115,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 0b1589d8..4d9d97da 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 812ab06b..9cc27162 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index a5ca25a6..beda1841 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index e7692ee7..6bb1c291 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -115,4 +115,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 5efd97ad..fa273b4f 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 59e004b8..d3ba1762 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -116,4 +116,7 @@ Location of Tesla's Auth servers? Enter the server domain name Do Not Disturb + RGB Theme override + In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme + Light theme override From a55c94a030ef357954d98e634c97b947e8c256f7 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 10 Jan 2023 21:42:26 -0500 Subject: [PATCH 073/220] "Hide seconds" has been changed from a checkbox to a list with three entries - Show seconds - Hide seconds when inactive - Always hide seconds Show and Hide seconds behaves like the old toggle but "Hide seconds when inactive" will not display seconds when the watchface is in low power mode (ie, inactive). "Memory-In-Pixel" watch consumes energy when a pixel is changed. Preventing the seconds to update every secondes can help reduce the energy drawn by the watchface. Has no Effect on AMOLED watches. --- README.md | 8 ++++++++ resources-ces/strings/strings.xml | 3 +++ resources-dan/strings/strings.xml | 3 +++ resources-deu/strings/strings.xml | 3 +++ resources-dut/strings/strings.xml | 4 +++- resources-fin/strings/strings.xml | 3 +++ resources-fre/strings/strings.xml | 4 +++- resources-hrv/strings/strings.xml | 3 +++ resources-hun/strings/strings.xml | 3 +++ resources-ita/strings/strings.xml | 3 +++ resources-kor/strings/strings.xml | 3 +++ resources-nob/strings/strings.xml | 3 +++ resources-pol/strings/strings.xml | 3 +++ resources-por/strings/strings.xml | 3 +++ resources-rus/strings/strings.xml | 3 +++ resources-slo/strings/strings.xml | 3 +++ resources-slv/strings/strings.xml | 3 +++ resources-spa/strings/strings.xml | 3 +++ resources-swe/strings/strings.xml | 3 +++ resources-zhs/strings/strings.xml | 3 +++ resources-zht/strings/strings.xml | 3 +++ resources/settings/properties.xml | 4 ++-- resources/settings/settings.xml | 6 +++++- resources/strings/strings.xml | 3 +++ source/CrystalView.mc | 6 ++++-- 25 files changed, 82 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 81ec6c32..462c47a3 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,14 @@ Reviews: ## What has been added by me. See https://apps.garmin.com/en-US/apps/9fd04d09-8c80-4c81-9257-17cfa0f0081b for what has been added previously by Pixel Pathos +### 2.14.0 +- "Hide seconds" has been changed from a checkbox to a list with three entries: + - Show seconds + - Hide seconds when inactive + - Always hide seconds + + Show and Hide seconds behaves like the old toggle but "Hide seconds when inactive" will not display seconds when the watchface is in low power mode (ie, inactive). "Memory-In-Pixel" watch consumes energy when a pixel is changed. Preventing the seconds to update every secondes can help reduce the energy drawn by the watchface. Has no Effect on AMOLED watches. + ### 2.13.0 - Added Body Battery as a Goal Meter diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 17d94ff4..eda7fe69 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index e71a864d..cc821719 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 9cb1a65a..59009690 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -14,6 +14,9 @@ Städtische Lokalzeit hinzufügen (Beta) Move Bar Style Sekunden ausblenden + Show seconds + Hide seconds when inactive + Always hide seconds Führende Nullen ausblenden OpenWeatherMap API Key Override diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index e45256e8..8ffe622f 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -1,6 +1,5 @@ - Crystal App Versie @@ -15,6 +14,9 @@ Voeg Lokale Tijd In Stad Toe (Beta) Beweeg Balk Stijl Verberg Seconden + Show seconds + Hide seconds when inactive + Always hide seconds Verberg Eerste Nul Bij Uren OpenWeatherMap API Key Override diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index df85d066..bbe660f2 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 86bc49ed..9794b676 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -1,6 +1,5 @@ - Crystal Version de l'appli @@ -15,6 +14,9 @@ Ajout de l'heure d'une ville (Beta) Apparence de la barre d'activité Masquer les secondes + Toujours afficher + Afficher sauf quand inactif + Toujours cacher Masquer le zéro avant l'heure OpenWeatherMap API Key Override diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index d9cb8e62..0db327fe 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 81c8b759..bdde75e4 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index df462614..2ca1f855 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 64dcbdcb..a7a91a86 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index c73d8c32..7c1c80eb 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index d0d67fc8..c5809ced 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -14,6 +14,9 @@ Add Local Time in City (Beta) Wygląd Move Bar'a Ukryj Sekundy + Show seconds + Hide seconds when inactive + Always hide seconds Ukryj Zero Poprzedzające Godzinę OpenWeatherMap API Key Override diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 38088502..f6117501 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 70ccef27..f79d0a02 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -14,6 +14,9 @@ Добавить местное время в городе (бета) Вид полосы подвижности Скрывать секунды + Show seconds + Hide seconds when inactive + Always hide seconds Скрывать нули перед часами OpenWeatherMap API Key Override diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 4d9d97da..e053c768 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 9cc27162..6184937f 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index beda1841..8725bd58 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 6bb1c291..3afbec27 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -14,6 +14,9 @@ Lägg till lokal tid för stad (Beta) Rörelsemätarstil Dölj sekunder + Show seconds + Hide seconds when inactive + Always hide seconds Dölj inledande nollor OpenWeatherMap API Key Override diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index fa273b4f..dc09b82b 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index d3ba1762..57df4cc9 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -15,6 +15,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 44320281..541cbe31 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,6 +1,6 @@ - 2.13.0 + 2.14.0 0 @@ -29,7 +29,7 @@ 0 - false + 0 true 3268578d0f3633073e62b3d8a560a09a diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 007b0dbd..08fce606 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -218,7 +218,11 @@ - + + @Strings.HideSecondsOff + @Strings.HideSecondsLowPower + @Strings.HideSecondsAlways + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 4e3fcb6e..1dab0c0c 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -14,6 +14,9 @@ Add Local Time in City (Beta) Move Bar Style Hide Seconds + Show seconds + Hide seconds when inactive + Always hide seconds Hide Hours Leading Zero OpenWeatherMap API Key Override diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 75ccdd3e..b0b869d9 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -705,7 +705,8 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, AND HideSeconds property is false, // show seconds, and make move bar original width. - if (!PER_SECOND_UPDATES_SUPPORTED && !App.getApp().getProperty("HideSeconds")) { + var hideSeconds = App.getApp().getProperty("HideSeconds"); + if ((!PER_SECOND_UPDATES_SUPPORTED && hideSeconds == 0) || hideSeconds == 1 ) { setHideSeconds(false); } @@ -738,7 +739,8 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, then hide seconds, and make move bar full width. // onUpdate() is about to be called one final time before entering sleep. // If HideSeconds property is true, do not wastefully hide seconds again (they should already be hidden). - if (!PER_SECOND_UPDATES_SUPPORTED && !App.getApp().getProperty("HideSeconds")) { + var hideSeconds = App.getApp().getProperty("HideSeconds"); + if ((!PER_SECOND_UPDATES_SUPPORTED && hideSeconds == 0) || hideSeconds == 1) { setHideSeconds(true); } From c7541686bab364fa51d0f0e454073bd6b0f89fb7 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 10 Jan 2023 22:12:07 -0500 Subject: [PATCH 074/220] Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 462c47a3..616516af 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ This is my first ever Connect IQ watch face (please be kind!), so I look forward Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. -## What has been added by me. See https://apps.garmin.com/en-US/apps/9fd04d09-8c80-4c81-9257-17cfa0f0081b for what has been added previously by Pixel Pathos + +## Below is what has been added by me (SylvainGa). ### 2.14.0 - "Hide seconds" has been changed from a checkbox to a list with three entries: @@ -128,4 +129,15 @@ Reviews: ### 2.6.2 - Disables background services for watch that doesn't support it. Features that won't work without background services are Weather, sunrise/sunset and Tesla Info. +### 2.6.1 +- Better handling of errors and can now refresh an access token through… + +### 2.6.0 +- Added a Tesla battery level as an indicator which is activated by choosing the indicator 'Tesla Info'. If the vehicle is awake, it will display the battery charge level as a percentage, followed by a '+' sign if it's being actively charged. It will also cycle to P on/off for the Preconditioning Status, S on/off for Sentry Status and the vehicle's inside temperature. If the car is asleep, a 's' will be displayed after the battery level and it will only cycle between that and P on/off. If an error is received from the car, it will be displayed in pink instead of the battery level. Scan interval is the standard 5 minutes so give it at least 15 minutes at start to get the access to the car and poll its status. + + You'll need to generate at least a refresh token and enter it in the watch face parameter to give access to your vehicle status. You can get a token through online services or phone apps like Tesla Token. If you give it also an access token, the refresh time before capturing data will be decreased by 5 minutes. Make sure your vehicle is awake for at least 15 minutes when you first launch the watch with the token set so it can connect to it. It will NOT wake the vehicle to retrieve any of the info and it does NOT prevent the vehicle from falling asleep. + +### 2.5.x +- Added PulseOx as a data field + See https://apps.garmin.com/en-US/apps/9fd04d09-8c80-4c81-9257-17cfa0f0081b for previous changes made by Pixel Pathos From d864c857ef8bc993a7c702841e14fd0ffbf6b4ec Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 10 Jan 2023 22:42:57 -0500 Subject: [PATCH 075/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 616516af..732cfbb8 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ Reviews: - Disables background services for watch that doesn't support it. Features that won't work without background services are Weather, sunrise/sunset and Tesla Info. ### 2.6.1 -- Better handling of errors and can now refresh an access token through… +- Better handling of errors and can now refresh an access token through the help of the Refresh token (hopefully) ### 2.6.0 - Added a Tesla battery level as an indicator which is activated by choosing the indicator 'Tesla Info'. If the vehicle is awake, it will display the battery charge level as a percentage, followed by a '+' sign if it's being actively charged. It will also cycle to P on/off for the Preconditioning Status, S on/off for Sentry Status and the vehicle's inside temperature. If the car is asleep, a 's' will be displayed after the battery level and it will only cycle between that and P on/off. If an error is received from the car, it will be displayed in pink instead of the battery level. Scan interval is the standard 5 minutes so give it at least 15 minutes at start to get the access to the car and poll its status. From cbf086f36e4dba1e49e001cb084bf7f536441b59 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 11 Jan 2023 21:42:06 -0500 Subject: [PATCH 076/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 732cfbb8..051d95f1 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Reviews: ### 2.10.3 - Added the Enduro, Venu SQ 2 and Venu SQ 2 Music -#### 2.10.2 +### 2.10.2 - Fixed missing 'Û' in 280x280 font ### 2.10.1 From 1f84ed660bbc095facf77d1d605bf57a391c4f61 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:33:07 -0500 Subject: [PATCH 077/220] Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 and removal of dependencies for devices --- README.md | 19 +- manifest.xml | 3 + monkey.jungle | 5 + resources-approachs60/settings/properties.xml | 9 - resources-approachs60/settings/settings.xml | 82 --- resources-approachs62/settings/properties.xml | 6 - resources-approachs62/settings/settings.xml | 82 --- .../settings/properties.xml | 10 - resources-ciq_1.x-no_hr/settings/settings.xml | 105 ---- resources-ciq_1.x/settings/properties.xml | 7 - resources-ciq_1.x/settings/settings.xml | 105 ---- resources-fr735xt/settings/properties.xml | 6 - resources-fr735xt/settings/settings.xml | 101 ---- resources-no_floors/settings/properties.xml | 6 - resources-no_floors/settings/settings.xml | 23 - .../settings/settings.xml | 8 - .../settings/properties.xml | 6 - .../settings/settings.xml | 82 --- .../settings/properties.xml | 6 - .../settings/settings.xml | 82 --- .../settings/properties.xml | 8 - resources-round-208x208/settings/settings.xml | 131 ----- resources-round-454x454/fonts/fonts.xml | 35 ++ .../fonts/namum-gothic-kor-42.bmfc | 55 ++ .../fonts/namum-gothic-kor-42.fnt | 24 + .../fonts/namum-gothic-kor-42_0.png | Bin 0 -> 4436 bytes .../fonts/noto-sans-cjk-sc-medium-42.bmfc | 56 ++ .../fonts/noto-sans-cjk-sc-medium-42.fnt | 30 + .../fonts/noto-sans-cjk-sc-medium-42_0.png | Bin 0 -> 5951 bytes .../fonts/noto-sans-cjk-tc-medium-42.bmfc | 56 ++ .../fonts/noto-sans-cjk-tc-medium-42.fnt | 30 + .../fonts/noto-sans-cjk-tc-medium-42_0.png | Bin 0 -> 5929 bytes .../fonts/noto-sans-rus-bold-42.bmfc | 55 ++ .../fonts/noto-sans-rus-bold-42.fnt | 47 ++ .../fonts/noto-sans-rus-bold-42_0.png | Bin 0 -> 9285 bytes .../fonts/titillium-web-bold-118-tall.bmfc | 55 ++ .../fonts/titillium-web-bold-118-tall.fnt | 14 + .../fonts/titillium-web-bold-118-tall_0.png | Bin 0 -> 7300 bytes .../fonts/titillium-web-bold-85-tall.bmfc | 55 ++ .../fonts/titillium-web-bold-85-tall.fnt | 14 + .../fonts/titillium-web-bold-85-tall_0.png | Bin 0 -> 3976 bytes .../fonts/titillium-web-light-118-tall.bmfc | 55 ++ .../fonts/titillium-web-light-118-tall.fnt | 14 + .../fonts/titillium-web-light-118-tall_0.png | Bin 0 -> 7656 bytes .../fonts/titillium-web-light-85-tall.bmfc | 55 ++ .../fonts/titillium-web-light-85-tall.fnt | 15 + .../fonts/titillium-web-light-85-tall_0.png | Bin 0 -> 4089 bytes .../fonts/titillium-web-semibold-30.bmfc | 57 ++ .../fonts/titillium-web-semibold-30.fnt | 555 +++++++++++++++++ .../fonts/titillium-web-semibold-30_0.png | Bin 0 -> 12388 bytes .../fonts/titillium-web-semibold-42.bmfc | 57 ++ .../fonts/titillium-web-semibold-42.fnt | 556 ++++++++++++++++++ .../fonts/titillium-web-semibold-42_0.png | Bin 0 -> 12774 bytes .../fonts/titillium-web-semibold-42_1.png | Bin 0 -> 11167 bytes resources-round-454x454/layouts/layout.xml | 78 +++ resources-vivoactive/settings/properties.xml | 10 - resources-vivoactive/settings/settings.xml | 108 ---- source/BackgroundService.mc | 19 +- 58 files changed, 1998 insertions(+), 999 deletions(-) delete mode 100644 resources-approachs60/settings/properties.xml delete mode 100644 resources-approachs60/settings/settings.xml delete mode 100644 resources-approachs62/settings/properties.xml delete mode 100644 resources-approachs62/settings/settings.xml delete mode 100644 resources-ciq_1.x-no_hr/settings/properties.xml delete mode 100644 resources-ciq_1.x-no_hr/settings/settings.xml delete mode 100644 resources-ciq_1.x/settings/properties.xml delete mode 100644 resources-ciq_1.x/settings/settings.xml delete mode 100644 resources-fr735xt/settings/properties.xml delete mode 100644 resources-fr735xt/settings/settings.xml delete mode 100644 resources-no_floors/settings/properties.xml delete mode 100644 resources-no_floors/settings/settings.xml delete mode 100644 resources-rectangle-205x148/settings/settings.xml delete mode 100644 resources-rectangle-240x240/settings/properties.xml delete mode 100644 resources-rectangle-240x240/settings/settings.xml delete mode 100644 resources-rectangle-320x360/settings/properties.xml delete mode 100644 resources-rectangle-320x360/settings/settings.xml delete mode 100644 resources-round-208x208/settings/properties.xml delete mode 100644 resources-round-208x208/settings/settings.xml create mode 100644 resources-round-454x454/fonts/fonts.xml create mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42.bmfc create mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42.fnt create mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42_0.png create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42.bmfc create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42.fnt create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42_0.png create mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42.bmfc create mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42.fnt create mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_1.png create mode 100644 resources-round-454x454/layouts/layout.xml delete mode 100644 resources-vivoactive/settings/properties.xml delete mode 100644 resources-vivoactive/settings/settings.xml diff --git a/README.md b/README.md index 051d95f1..124f5b74 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Crystal -A Garmin Connect IQ watch face. +# Crystal-Tesla +A Garmin Connect IQ watch face based on PixelPathos Crystal. ## Description **If you enjoy this maintained version of Crystal with Tesla integration, you can support my work with a small donation:** @@ -12,22 +12,25 @@ A crystal clear watch face, with LCD-like goal meter segments, written while sno Features (depending on watch support): - Big time digits right in the middle, with hours in bold. Leading zero and seconds can be hidden. Hours and minutes colours can be set independently. -- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). -- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery. -- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal). The meters have auto-scaling segments and current/target value display. +- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). THE FOLLOWING ADDED By SylvainGa: Garmin Weather, Recovery Time Left, Body Battery, Solar Intensity, Floors climbed and Pulse Ox. +- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery, THE FOLLOWING ADDED By SylvainGa: Do Not Disturb and Tesla batterie level/status. +- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal), THE FOLLOWING ADDED By SylvainGa: Body Battery. The meters have auto-scaling segments and current/target value display. - Move bar. -- 12 colour themes. +- 12 colour themes, THE FOLLOWING ADDED By SylvainGa: Customizable themes. The techie bit: to save your watch battery, the goal meters and move bar are drawn from a palette-restricted back buffer, for improved drawing performance, with minimal memory penalty. -This is my first ever Connect IQ watch face (please be kind!), so I look forward to your feedback, improving the watch face, and bringing it to more devices. +This is my first modification of a Connect IQ watch face (please be kind!), so I look forward to your feedback, improving the watch face, and bringing it to more devices. Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. - ## Below is what has been added by me (SylvainGa). +### 2.14.1 +- Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 +- Removed all the depencies between the devices and the sensors, features, themes color, etc. This makes supporting features much more easy but also could create confusion to some as to why a sensor for example doesn't work or a theme color seems odd. That's because your device doesn't specifically support that sensor or theme. For theme, it's basically the devices with less than 64 colors that will be affected. For sensors, it will depend on what your device support. See the specs of your specific devices for its available sensors. + ### 2.14.0 - "Hide seconds" has been changed from a checkbox to a list with three entries: - Show seconds diff --git a/manifest.xml b/manifest.xml index 2190a3c1..38de375f 100644 --- a/manifest.xml +++ b/manifest.xml @@ -38,6 +38,8 @@ + + @@ -46,6 +48,7 @@ + diff --git a/monkey.jungle b/monkey.jungle index 1b269dde..dcfb9db5 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -83,3 +83,8 @@ d2air.sourcePath = $(d2air.sourcePath);always-on-source d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source epix2.sourcePath = $(epix2.sourcePath);always-on-source +fr965.sourcePath = $(fr965.sourcePath);always-on-source +fr265.sourcePath = $(fr265.sourcePath);always-on-source +fr265s.sourcePath = $(fr265s.sourcePath);always-on-source + +project.typecheck = 0 \ No newline at end of file diff --git a/resources-approachs60/settings/properties.xml b/resources-approachs60/settings/properties.xml deleted file mode 100644 index c0e58606..00000000 --- a/resources-approachs60/settings/properties.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - 2 - - - 4 - - \ No newline at end of file diff --git a/resources-approachs60/settings/settings.xml b/resources-approachs60/settings/settings.xml deleted file mode 100644 index b50722b3..00000000 --- a/resources-approachs60/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-approachs62/settings/properties.xml b/resources-approachs62/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-approachs62/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-approachs62/settings/settings.xml b/resources-approachs62/settings/settings.xml deleted file mode 100644 index f74f5684..00000000 --- a/resources-approachs62/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-ciq_1.x-no_hr/settings/properties.xml b/resources-ciq_1.x-no_hr/settings/properties.xml deleted file mode 100644 index cb2de3ec..00000000 --- a/resources-ciq_1.x-no_hr/settings/properties.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -1 - 3 - - - 4 - - \ No newline at end of file diff --git a/resources-ciq_1.x-no_hr/settings/settings.xml b/resources-ciq_1.x-no_hr/settings/settings.xml deleted file mode 100644 index b9ffed38..00000000 --- a/resources-ciq_1.x-no_hr/settings/settings.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/resources-ciq_1.x/settings/properties.xml b/resources-ciq_1.x/settings/properties.xml deleted file mode 100644 index 0981fb4b..00000000 --- a/resources-ciq_1.x/settings/properties.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - -1 - 3 - - \ No newline at end of file diff --git a/resources-ciq_1.x/settings/settings.xml b/resources-ciq_1.x/settings/settings.xml deleted file mode 100644 index f394bc41..00000000 --- a/resources-ciq_1.x/settings/settings.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/resources-fr735xt/settings/properties.xml b/resources-fr735xt/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-fr735xt/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-fr735xt/settings/settings.xml b/resources-fr735xt/settings/settings.xml deleted file mode 100644 index 83800a64..00000000 --- a/resources-fr735xt/settings/settings.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-no_floors/settings/properties.xml b/resources-no_floors/settings/properties.xml deleted file mode 100644 index 97b20a1e..00000000 --- a/resources-no_floors/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - diff --git a/resources-no_floors/settings/settings.xml b/resources-no_floors/settings/settings.xml deleted file mode 100644 index 88f9799d..00000000 --- a/resources-no_floors/settings/settings.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - \ No newline at end of file diff --git a/resources-rectangle-205x148/settings/settings.xml b/resources-rectangle-205x148/settings/settings.xml deleted file mode 100644 index 67715ed0..00000000 --- a/resources-rectangle-205x148/settings/settings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/resources-rectangle-240x240/settings/properties.xml b/resources-rectangle-240x240/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-rectangle-240x240/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-rectangle-240x240/settings/settings.xml b/resources-rectangle-240x240/settings/settings.xml deleted file mode 100644 index f74f5684..00000000 --- a/resources-rectangle-240x240/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-rectangle-320x360/settings/properties.xml b/resources-rectangle-320x360/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-rectangle-320x360/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-rectangle-320x360/settings/settings.xml b/resources-rectangle-320x360/settings/settings.xml deleted file mode 100644 index f74f5684..00000000 --- a/resources-rectangle-320x360/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-round-208x208/settings/properties.xml b/resources-round-208x208/settings/properties.xml deleted file mode 100644 index eaad25bc..00000000 --- a/resources-round-208x208/settings/properties.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -1 - 3 - - \ No newline at end of file diff --git a/resources-round-208x208/settings/settings.xml b/resources-round-208x208/settings/settings.xml deleted file mode 100644 index 4ea9fbcc..00000000 --- a/resources-round-208x208/settings/settings.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - - - - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - - - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - - - - - @Strings.FromTheme - - @Strings.Mono - - - - - - - @Strings.FromTheme - - @Strings.Mono - - - diff --git a/resources-round-454x454/fonts/fonts.xml b/resources-round-454x454/fonts/fonts.xml new file mode 100644 index 00000000..d90b563b --- /dev/null +++ b/resources-round-454x454/fonts/fonts.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc b/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc new file mode 100644 index 00000000..aca274c2 --- /dev/null +++ b/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=NanumGothicExtraBold +fontFile= +charSet=0 +fontSize=42 +aa=2 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=32,40-41,48-57,44552,47785,49688,50900,51068,53664,54868 + +# imported icon images diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42.fnt b/resources-round-454x454/fonts/namum-gothic-kor-42.fnt new file mode 100644 index 00000000..97fe239c --- /dev/null +++ b/resources-round-454x454/fonts/namum-gothic-kor-42.fnt @@ -0,0 +1,24 @@ +info face="NanumGothicExtraBold" size=42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=42 base=34 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="namum-gothic-kor-42_0.png" +chars count=20 +char id=32 x=191 y=35 width=2 height=1 xoffset=0 yoffset=41 xadvance=10 page=0 chnl=15 +char id=40 x=31 y=0 width=11 height=35 xoffset=2 yoffset=5 xadvance=13 page=0 chnl=15 +char id=41 x=43 y=0 width=11 height=35 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 +char id=48 x=22 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=49 x=243 y=0 width=11 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 +char id=50 x=82 y=35 width=18 height=27 xoffset=1 yoffset=8 xadvance=22 page=0 chnl=15 +char id=51 x=101 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=52 x=0 y=36 width=21 height=27 xoffset=0 yoffset=8 xadvance=22 page=0 chnl=15 +char id=53 x=139 y=35 width=17 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 +char id=54 x=42 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=55 x=120 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=56 x=222 y=0 width=20 height=30 xoffset=1 yoffset=7 xadvance=22 page=0 chnl=15 +char id=57 x=62 y=35 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=44552 x=90 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=47785 x=124 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=49688 x=158 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=50900 x=0 y=0 width=30 height=35 xoffset=1 yoffset=4 xadvance=34 page=0 chnl=15 +char id=51068 x=192 y=0 width=29 height=34 xoffset=2 yoffset=5 xadvance=34 page=0 chnl=15 +char id=53664 x=157 y=35 width=33 height=26 xoffset=0 yoffset=7 xadvance=34 page=0 chnl=15 +char id=54868 x=55 y=0 width=34 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42_0.png b/resources-round-454x454/fonts/namum-gothic-kor-42_0.png new file mode 100644 index 0000000000000000000000000000000000000000..5f09960b2eee7c8e792ceedb44c37edcd8cb7301 GIT binary patch literal 4436 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 XH4*=sxsk{2|Lzimk%eJ{0W$7?Yj=5c literal 0 HcmV?d00001 diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc new file mode 100644 index 00000000..9b85ec32 --- /dev/null +++ b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc @@ -0,0 +1,56 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Noto Sans CJK SC Medium +fontFile= +charSet=0 +fontSize=-42 +aa=2 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=10,32,48-57,19968,19971,19977,20061,20108,20116,20843,20845,21313,22235,26085,26143,26376,26399 + + +# imported icon images diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt new file mode 100644 index 00000000..ee5e7127 --- /dev/null +++ b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt @@ -0,0 +1,30 @@ +info face="Noto Sans CJK SC Medium" size=-42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=62 base=49 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="noto-sans-cjk-sc-medium-42_0.png" +chars count=26 +char id=10 x=242 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 +char id=32 x=245 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 +char id=48 x=66 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=49 x=236 y=0 width=18 height=32 xoffset=3 yoffset=17 xadvance=24 page=0 chnl=15 +char id=50 x=0 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=51 x=22 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=52 x=219 y=38 width=22 height=32 xoffset=0 yoffset=17 xadvance=24 page=0 chnl=15 +char id=53 x=44 y=77 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=54 x=87 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=55 x=108 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=56 x=129 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=57 x=150 y=74 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=19968 x=209 y=71 width=39 height=5 xoffset=2 yoffset=30 xadvance=42 page=0 chnl=15 +char id=19971 x=157 y=0 width=39 height=37 xoffset=1 yoffset=14 xadvance=42 page=0 chnl=15 +char id=19977 x=181 y=38 width=37 height=32 xoffset=3 yoffset=17 xadvance=42 page=0 chnl=15 +char id=20061 x=0 y=0 width=39 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 +char id=20108 x=171 y=74 width=37 height=29 xoffset=2 yoffset=19 xadvance=42 page=0 chnl=15 +char id=20116 x=142 y=40 width=38 height=33 xoffset=2 yoffset=17 xadvance=42 page=0 chnl=15 +char id=20843 x=35 y=40 width=40 height=36 xoffset=1 yoffset=16 xadvance=42 page=0 chnl=15 +char id=20845 x=40 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 +char id=21313 x=79 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 +char id=22235 x=106 y=40 width=35 height=35 xoffset=3 yoffset=16 xadvance=42 page=0 chnl=15 +char id=26085 x=76 y=40 width=29 height=36 xoffset=7 yoffset=16 xadvance=42 page=0 chnl=15 +char id=26143 x=197 y=0 width=38 height=37 xoffset=2 yoffset=14 xadvance=42 page=0 chnl=15 +char id=26376 x=0 y=40 width=34 height=37 xoffset=1 yoffset=15 xadvance=42 page=0 chnl=15 +char id=26399 x=118 y=0 width=38 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f10704df52d54dfa7443b3ac8251b24312bc3a6a GIT binary patch literal 5951 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
1ka#F`H+JVGM55cMJdNG6AV3|pZ~L-748 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 literal 0 HcmV?d00001 diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc b/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc new file mode 100644 index 00000000..f1a2adf9 --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web Light +fontFile= +charSet=0 +fontSize=-118 +aa=2 +scaleH=105 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt b/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt new file mode 100644 index 00000000..4e7a6aed --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt @@ -0,0 +1,14 @@ +info face="Titillium Web Light" size=-118 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=189 base=141 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-light-118-tall_0.png" +chars count=10 +char id=48 x=60 y=0 width=56 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 +char id=49 x=206 y=86 width=32 height=83 xoffset=13 yoffset=58 xadvance=66 page=0 chnl=15 +char id=50 x=105 y=86 width=50 height=84 xoffset=8 yoffset=57 xadvance=66 page=0 chnl=15 +char id=51 x=0 y=86 width=51 height=85 xoffset=7 yoffset=57 xadvance=66 page=0 chnl=15 +char id=52 x=0 y=172 width=57 height=83 xoffset=4 yoffset=58 xadvance=66 page=0 chnl=15 +char id=53 x=52 y=86 width=52 height=84 xoffset=7 yoffset=58 xadvance=66 page=0 chnl=15 +char id=54 x=117 y=0 width=55 height=85 xoffset=6 yoffset=57 xadvance=66 page=0 chnl=15 +char id=55 x=156 y=86 width=49 height=84 xoffset=9 yoffset=58 xadvance=66 page=0 chnl=15 +char id=56 x=0 y=0 width=59 height=85 xoffset=3 yoffset=57 xadvance=66 page=0 chnl=15 +char id=57 x=173 y=0 width=55 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png b/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png new file mode 100644 index 0000000000000000000000000000000000000000..a062927290fa50a54ff6d4abe0f0d40c57f8e4f4 GIT binary patch literal 7656 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 W#-8Fq&a->~0000N)-3ol$%f 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 + + + + + :left + 14 + 277 + 3 + + + + :right + 14 + 277 + 3 + + + + 136 + 144 + 336 + 362 + 331 + 92 + 324 + + + + 134 + 282 + 44 + 78 + 49 + + + + + + 49 + 208 + 51 + 41 + + + + -4 + 291 + 252 + + + + 88 + 286 + 192 + 13 + 4 + + + + + + + + [-60, -30, 30, 60] + -4 + 179 + 230 + + 230 + + 258 + 105 + + + \ No newline at end of file diff --git a/resources-vivoactive/settings/properties.xml b/resources-vivoactive/settings/properties.xml deleted file mode 100644 index cb2de3ec..00000000 --- a/resources-vivoactive/settings/properties.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -1 - 3 - - - 4 - - \ No newline at end of file diff --git a/resources-vivoactive/settings/settings.xml b/resources-vivoactive/settings/settings.xml deleted file mode 100644 index 5b0c6ee1..00000000 --- a/resources-vivoactive/settings/settings.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - @Strings.ThemeCornflowerBlueDark - @Strings.ThemeLemonCreamDark - @Strings.ThemeVividYellowDark - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index d72d08b7..ea021588 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -44,16 +44,16 @@ class BackgroundService extends Sys.ServiceDelegate { var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); -//2022-04-10 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); +//2023-03-05 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { -//2022-04-10 logMessage("initialize:Generating Access Token"); +//2023-03-05 logMessage("initialize:Generating Access Token"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { -//2022-04-10 logMessage("initialize:No refresh token!"); +//2023-03-05 logMessage("initialize:No refresh token!"); } return; } @@ -75,7 +75,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -//2022-04-10 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); +//2023-03-05 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. @@ -269,7 +269,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveToken(responseCode, data) { var result; -//2022-04-10 logMessage("onReceiveToken responseCode is " + responseCode); +//2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); //logMessage("onReceiveToken data is " + data); if (responseCode == 200) { result = { "Token" => data }; @@ -283,7 +283,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveVehicles(responseCode, data) { var result; -//2022-04-10 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); +//2023-03-05 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { @@ -310,7 +310,7 @@ class BackgroundService extends Sys.ServiceDelegate { var precondEnabled = "N/A"; var sentryEnabled = "N/A"; -//2022-04-10 logMessage("onReceiveVehicleData responseCode is " + responseCode); +//2023-03-05 logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { results = data.get("response"); if (results != null) { @@ -368,9 +368,12 @@ class BackgroundService extends Sys.ServiceDelegate { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, :headers => { - "Authorization" => _token}, + "Authorization" => _token, + "User-Agent" => "Crystal-Tesla for Garmin", + }, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; +//2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); Comms.makeWebRequest(url, params, options, callback); } //**************************************************************** From 4c00ee32c168791d14a9052097156905b1ace16e Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:43:38 -0500 Subject: [PATCH 078/220] Revert "Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 and removal of dependencies for devices" This reverts commit 1f84ed660bbc095facf77d1d605bf57a391c4f61. --- resources-approachs60/settings/properties.xml | 9 ++ resources-approachs60/settings/settings.xml | 82 +++++++++++ resources-approachs62/settings/properties.xml | 6 + resources-approachs62/settings/settings.xml | 82 +++++++++++ .../settings/properties.xml | 10 ++ resources-ciq_1.x-no_hr/settings/settings.xml | 105 ++++++++++++++ resources-ciq_1.x/settings/properties.xml | 7 + resources-ciq_1.x/settings/settings.xml | 105 ++++++++++++++ resources-fr735xt/settings/properties.xml | 6 + resources-fr735xt/settings/settings.xml | 101 ++++++++++++++ resources-no_floors/settings/properties.xml | 6 + resources-no_floors/settings/settings.xml | 23 +++ .../settings/settings.xml | 8 ++ .../settings/properties.xml | 6 + .../settings/settings.xml | 82 +++++++++++ .../settings/properties.xml | 6 + .../settings/settings.xml | 82 +++++++++++ .../settings/properties.xml | 8 ++ resources-round-208x208/settings/settings.xml | 131 ++++++++++++++++++ resources-vivoactive/settings/properties.xml | 10 ++ resources-vivoactive/settings/settings.xml | 108 +++++++++++++++ 21 files changed, 983 insertions(+) create mode 100644 resources-approachs60/settings/properties.xml create mode 100644 resources-approachs60/settings/settings.xml create mode 100644 resources-approachs62/settings/properties.xml create mode 100644 resources-approachs62/settings/settings.xml create mode 100644 resources-ciq_1.x-no_hr/settings/properties.xml create mode 100644 resources-ciq_1.x-no_hr/settings/settings.xml create mode 100644 resources-ciq_1.x/settings/properties.xml create mode 100644 resources-ciq_1.x/settings/settings.xml create mode 100644 resources-fr735xt/settings/properties.xml create mode 100644 resources-fr735xt/settings/settings.xml create mode 100644 resources-no_floors/settings/properties.xml create mode 100644 resources-no_floors/settings/settings.xml create mode 100644 resources-rectangle-205x148/settings/settings.xml create mode 100644 resources-rectangle-240x240/settings/properties.xml create mode 100644 resources-rectangle-240x240/settings/settings.xml create mode 100644 resources-rectangle-320x360/settings/properties.xml create mode 100644 resources-rectangle-320x360/settings/settings.xml create mode 100644 resources-round-208x208/settings/properties.xml create mode 100644 resources-round-208x208/settings/settings.xml create mode 100644 resources-vivoactive/settings/properties.xml create mode 100644 resources-vivoactive/settings/settings.xml diff --git a/resources-approachs60/settings/properties.xml b/resources-approachs60/settings/properties.xml new file mode 100644 index 00000000..c0e58606 --- /dev/null +++ b/resources-approachs60/settings/properties.xml @@ -0,0 +1,9 @@ + + + + 2 + + + 4 + + \ No newline at end of file diff --git a/resources-approachs60/settings/settings.xml b/resources-approachs60/settings/settings.xml new file mode 100644 index 00000000..b50722b3 --- /dev/null +++ b/resources-approachs60/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-approachs62/settings/properties.xml b/resources-approachs62/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-approachs62/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-approachs62/settings/settings.xml b/resources-approachs62/settings/settings.xml new file mode 100644 index 00000000..f74f5684 --- /dev/null +++ b/resources-approachs62/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-ciq_1.x-no_hr/settings/properties.xml b/resources-ciq_1.x-no_hr/settings/properties.xml new file mode 100644 index 00000000..cb2de3ec --- /dev/null +++ b/resources-ciq_1.x-no_hr/settings/properties.xml @@ -0,0 +1,10 @@ + + + + -1 + 3 + + + 4 + + \ No newline at end of file diff --git a/resources-ciq_1.x-no_hr/settings/settings.xml b/resources-ciq_1.x-no_hr/settings/settings.xml new file mode 100644 index 00000000..b9ffed38 --- /dev/null +++ b/resources-ciq_1.x-no_hr/settings/settings.xml @@ -0,0 +1,105 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + diff --git a/resources-ciq_1.x/settings/properties.xml b/resources-ciq_1.x/settings/properties.xml new file mode 100644 index 00000000..0981fb4b --- /dev/null +++ b/resources-ciq_1.x/settings/properties.xml @@ -0,0 +1,7 @@ + + + + -1 + 3 + + \ No newline at end of file diff --git a/resources-ciq_1.x/settings/settings.xml b/resources-ciq_1.x/settings/settings.xml new file mode 100644 index 00000000..f394bc41 --- /dev/null +++ b/resources-ciq_1.x/settings/settings.xml @@ -0,0 +1,105 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + diff --git a/resources-fr735xt/settings/properties.xml b/resources-fr735xt/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-fr735xt/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-fr735xt/settings/settings.xml b/resources-fr735xt/settings/settings.xml new file mode 100644 index 00000000..83800a64 --- /dev/null +++ b/resources-fr735xt/settings/settings.xml @@ -0,0 +1,101 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-no_floors/settings/properties.xml b/resources-no_floors/settings/properties.xml new file mode 100644 index 00000000..97b20a1e --- /dev/null +++ b/resources-no_floors/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + diff --git a/resources-no_floors/settings/settings.xml b/resources-no_floors/settings/settings.xml new file mode 100644 index 00000000..88f9799d --- /dev/null +++ b/resources-no_floors/settings/settings.xml @@ -0,0 +1,23 @@ + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + \ No newline at end of file diff --git a/resources-rectangle-205x148/settings/settings.xml b/resources-rectangle-205x148/settings/settings.xml new file mode 100644 index 00000000..67715ed0 --- /dev/null +++ b/resources-rectangle-205x148/settings/settings.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources-rectangle-240x240/settings/properties.xml b/resources-rectangle-240x240/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-rectangle-240x240/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-rectangle-240x240/settings/settings.xml b/resources-rectangle-240x240/settings/settings.xml new file mode 100644 index 00000000..f74f5684 --- /dev/null +++ b/resources-rectangle-240x240/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-rectangle-320x360/settings/properties.xml b/resources-rectangle-320x360/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-rectangle-320x360/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-rectangle-320x360/settings/settings.xml b/resources-rectangle-320x360/settings/settings.xml new file mode 100644 index 00000000..f74f5684 --- /dev/null +++ b/resources-rectangle-320x360/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-round-208x208/settings/properties.xml b/resources-round-208x208/settings/properties.xml new file mode 100644 index 00000000..eaad25bc --- /dev/null +++ b/resources-round-208x208/settings/properties.xml @@ -0,0 +1,8 @@ + + + + + -1 + 3 + + \ No newline at end of file diff --git a/resources-round-208x208/settings/settings.xml b/resources-round-208x208/settings/settings.xml new file mode 100644 index 00000000..4ea9fbcc --- /dev/null +++ b/resources-round-208x208/settings/settings.xml @@ -0,0 +1,131 @@ + + + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + + + + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + + + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + + + + + @Strings.FromTheme + + @Strings.Mono + + + + + + + @Strings.FromTheme + + @Strings.Mono + + + diff --git a/resources-vivoactive/settings/properties.xml b/resources-vivoactive/settings/properties.xml new file mode 100644 index 00000000..cb2de3ec --- /dev/null +++ b/resources-vivoactive/settings/properties.xml @@ -0,0 +1,10 @@ + + + + -1 + 3 + + + 4 + + \ No newline at end of file diff --git a/resources-vivoactive/settings/settings.xml b/resources-vivoactive/settings/settings.xml new file mode 100644 index 00000000..5b0c6ee1 --- /dev/null +++ b/resources-vivoactive/settings/settings.xml @@ -0,0 +1,108 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + @Strings.ThemeCornflowerBlueDark + @Strings.ThemeLemonCreamDark + @Strings.ThemeVividYellowDark + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + From 93086efa7f2784cad7efddc98e7eff79b3b4e741 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:45:26 -0500 Subject: [PATCH 079/220] Revert "Revert "Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 and removal of dependencies for devices"" This reverts commit 4c00ee32c168791d14a9052097156905b1ace16e. --- resources-approachs60/settings/properties.xml | 9 -- resources-approachs60/settings/settings.xml | 82 ----------- resources-approachs62/settings/properties.xml | 6 - resources-approachs62/settings/settings.xml | 82 ----------- .../settings/properties.xml | 10 -- resources-ciq_1.x-no_hr/settings/settings.xml | 105 -------------- resources-ciq_1.x/settings/properties.xml | 7 - resources-ciq_1.x/settings/settings.xml | 105 -------------- resources-fr735xt/settings/properties.xml | 6 - resources-fr735xt/settings/settings.xml | 101 -------------- resources-no_floors/settings/properties.xml | 6 - resources-no_floors/settings/settings.xml | 23 --- .../settings/settings.xml | 8 -- .../settings/properties.xml | 6 - .../settings/settings.xml | 82 ----------- .../settings/properties.xml | 6 - .../settings/settings.xml | 82 ----------- .../settings/properties.xml | 8 -- resources-round-208x208/settings/settings.xml | 131 ------------------ resources-vivoactive/settings/properties.xml | 10 -- resources-vivoactive/settings/settings.xml | 108 --------------- 21 files changed, 983 deletions(-) delete mode 100644 resources-approachs60/settings/properties.xml delete mode 100644 resources-approachs60/settings/settings.xml delete mode 100644 resources-approachs62/settings/properties.xml delete mode 100644 resources-approachs62/settings/settings.xml delete mode 100644 resources-ciq_1.x-no_hr/settings/properties.xml delete mode 100644 resources-ciq_1.x-no_hr/settings/settings.xml delete mode 100644 resources-ciq_1.x/settings/properties.xml delete mode 100644 resources-ciq_1.x/settings/settings.xml delete mode 100644 resources-fr735xt/settings/properties.xml delete mode 100644 resources-fr735xt/settings/settings.xml delete mode 100644 resources-no_floors/settings/properties.xml delete mode 100644 resources-no_floors/settings/settings.xml delete mode 100644 resources-rectangle-205x148/settings/settings.xml delete mode 100644 resources-rectangle-240x240/settings/properties.xml delete mode 100644 resources-rectangle-240x240/settings/settings.xml delete mode 100644 resources-rectangle-320x360/settings/properties.xml delete mode 100644 resources-rectangle-320x360/settings/settings.xml delete mode 100644 resources-round-208x208/settings/properties.xml delete mode 100644 resources-round-208x208/settings/settings.xml delete mode 100644 resources-vivoactive/settings/properties.xml delete mode 100644 resources-vivoactive/settings/settings.xml diff --git a/resources-approachs60/settings/properties.xml b/resources-approachs60/settings/properties.xml deleted file mode 100644 index c0e58606..00000000 --- a/resources-approachs60/settings/properties.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - 2 - - - 4 - - \ No newline at end of file diff --git a/resources-approachs60/settings/settings.xml b/resources-approachs60/settings/settings.xml deleted file mode 100644 index b50722b3..00000000 --- a/resources-approachs60/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-approachs62/settings/properties.xml b/resources-approachs62/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-approachs62/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-approachs62/settings/settings.xml b/resources-approachs62/settings/settings.xml deleted file mode 100644 index f74f5684..00000000 --- a/resources-approachs62/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-ciq_1.x-no_hr/settings/properties.xml b/resources-ciq_1.x-no_hr/settings/properties.xml deleted file mode 100644 index cb2de3ec..00000000 --- a/resources-ciq_1.x-no_hr/settings/properties.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -1 - 3 - - - 4 - - \ No newline at end of file diff --git a/resources-ciq_1.x-no_hr/settings/settings.xml b/resources-ciq_1.x-no_hr/settings/settings.xml deleted file mode 100644 index b9ffed38..00000000 --- a/resources-ciq_1.x-no_hr/settings/settings.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/resources-ciq_1.x/settings/properties.xml b/resources-ciq_1.x/settings/properties.xml deleted file mode 100644 index 0981fb4b..00000000 --- a/resources-ciq_1.x/settings/properties.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - -1 - 3 - - \ No newline at end of file diff --git a/resources-ciq_1.x/settings/settings.xml b/resources-ciq_1.x/settings/settings.xml deleted file mode 100644 index f394bc41..00000000 --- a/resources-ciq_1.x/settings/settings.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/resources-fr735xt/settings/properties.xml b/resources-fr735xt/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-fr735xt/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-fr735xt/settings/settings.xml b/resources-fr735xt/settings/settings.xml deleted file mode 100644 index 83800a64..00000000 --- a/resources-fr735xt/settings/settings.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-no_floors/settings/properties.xml b/resources-no_floors/settings/properties.xml deleted file mode 100644 index 97b20a1e..00000000 --- a/resources-no_floors/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - diff --git a/resources-no_floors/settings/settings.xml b/resources-no_floors/settings/settings.xml deleted file mode 100644 index 88f9799d..00000000 --- a/resources-no_floors/settings/settings.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - \ No newline at end of file diff --git a/resources-rectangle-205x148/settings/settings.xml b/resources-rectangle-205x148/settings/settings.xml deleted file mode 100644 index 67715ed0..00000000 --- a/resources-rectangle-205x148/settings/settings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/resources-rectangle-240x240/settings/properties.xml b/resources-rectangle-240x240/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-rectangle-240x240/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-rectangle-240x240/settings/settings.xml b/resources-rectangle-240x240/settings/settings.xml deleted file mode 100644 index f74f5684..00000000 --- a/resources-rectangle-240x240/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-rectangle-320x360/settings/properties.xml b/resources-rectangle-320x360/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-rectangle-320x360/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-rectangle-320x360/settings/settings.xml b/resources-rectangle-320x360/settings/settings.xml deleted file mode 100644 index f74f5684..00000000 --- a/resources-rectangle-320x360/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-round-208x208/settings/properties.xml b/resources-round-208x208/settings/properties.xml deleted file mode 100644 index eaad25bc..00000000 --- a/resources-round-208x208/settings/properties.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -1 - 3 - - \ No newline at end of file diff --git a/resources-round-208x208/settings/settings.xml b/resources-round-208x208/settings/settings.xml deleted file mode 100644 index 4ea9fbcc..00000000 --- a/resources-round-208x208/settings/settings.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - - - - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - - - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - - - - - @Strings.FromTheme - - @Strings.Mono - - - - - - - @Strings.FromTheme - - @Strings.Mono - - - diff --git a/resources-vivoactive/settings/properties.xml b/resources-vivoactive/settings/properties.xml deleted file mode 100644 index cb2de3ec..00000000 --- a/resources-vivoactive/settings/properties.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -1 - 3 - - - 4 - - \ No newline at end of file diff --git a/resources-vivoactive/settings/settings.xml b/resources-vivoactive/settings/settings.xml deleted file mode 100644 index 5b0c6ee1..00000000 --- a/resources-vivoactive/settings/settings.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - @Strings.ThemeCornflowerBlueDark - @Strings.ThemeLemonCreamDark - @Strings.ThemeVividYellowDark - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - From 60dd0cec3b59187c08c77a396165b453b3f7d15d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:47:36 -0500 Subject: [PATCH 080/220] X --- README.md | 19 +- manifest.xml | 3 - monkey.jungle | 5 - resources-round-454x454/fonts/fonts.xml | 35 -- .../fonts/namum-gothic-kor-42.bmfc | 55 -- .../fonts/namum-gothic-kor-42.fnt | 24 - .../fonts/namum-gothic-kor-42_0.png | Bin 4436 -> 0 bytes .../fonts/noto-sans-cjk-sc-medium-42.bmfc | 56 -- .../fonts/noto-sans-cjk-sc-medium-42.fnt | 30 - .../fonts/noto-sans-cjk-sc-medium-42_0.png | Bin 5951 -> 0 bytes .../fonts/noto-sans-cjk-tc-medium-42.bmfc | 56 -- .../fonts/noto-sans-cjk-tc-medium-42.fnt | 30 - .../fonts/noto-sans-cjk-tc-medium-42_0.png | Bin 5929 -> 0 bytes .../fonts/noto-sans-rus-bold-42.bmfc | 55 -- .../fonts/noto-sans-rus-bold-42.fnt | 47 -- .../fonts/noto-sans-rus-bold-42_0.png | Bin 9285 -> 0 bytes .../fonts/titillium-web-bold-118-tall.bmfc | 55 -- .../fonts/titillium-web-bold-118-tall.fnt | 14 - .../fonts/titillium-web-bold-118-tall_0.png | Bin 7300 -> 0 bytes .../fonts/titillium-web-bold-85-tall.bmfc | 55 -- .../fonts/titillium-web-bold-85-tall.fnt | 14 - .../fonts/titillium-web-bold-85-tall_0.png | Bin 3976 -> 0 bytes .../fonts/titillium-web-light-118-tall.bmfc | 55 -- .../fonts/titillium-web-light-118-tall.fnt | 14 - .../fonts/titillium-web-light-118-tall_0.png | Bin 7656 -> 0 bytes .../fonts/titillium-web-light-85-tall.bmfc | 55 -- .../fonts/titillium-web-light-85-tall.fnt | 15 - .../fonts/titillium-web-light-85-tall_0.png | Bin 4089 -> 0 bytes .../fonts/titillium-web-semibold-30.bmfc | 57 -- .../fonts/titillium-web-semibold-30.fnt | 555 ----------------- .../fonts/titillium-web-semibold-30_0.png | Bin 12388 -> 0 bytes .../fonts/titillium-web-semibold-42.bmfc | 57 -- .../fonts/titillium-web-semibold-42.fnt | 556 ------------------ .../fonts/titillium-web-semibold-42_0.png | Bin 12774 -> 0 bytes .../fonts/titillium-web-semibold-42_1.png | Bin 11167 -> 0 bytes resources-round-454x454/layouts/layout.xml | 78 --- source/BackgroundService.mc | 19 +- 37 files changed, 16 insertions(+), 1998 deletions(-) delete mode 100644 resources-round-454x454/fonts/fonts.xml delete mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42.bmfc delete mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42.fnt delete mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42_0.png delete mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc delete mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt delete mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png delete mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42.bmfc delete mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42.fnt delete mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42_0.png delete mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42.bmfc delete mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42.fnt delete mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_1.png delete mode 100644 resources-round-454x454/layouts/layout.xml diff --git a/README.md b/README.md index 124f5b74..051d95f1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Crystal-Tesla -A Garmin Connect IQ watch face based on PixelPathos Crystal. +# Crystal +A Garmin Connect IQ watch face. ## Description **If you enjoy this maintained version of Crystal with Tesla integration, you can support my work with a small donation:** @@ -12,24 +12,21 @@ A crystal clear watch face, with LCD-like goal meter segments, written while sno Features (depending on watch support): - Big time digits right in the middle, with hours in bold. Leading zero and seconds can be hidden. Hours and minutes colours can be set independently. -- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). THE FOLLOWING ADDED By SylvainGa: Garmin Weather, Recovery Time Left, Body Battery, Solar Intensity, Floors climbed and Pulse Ox. -- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery, THE FOLLOWING ADDED By SylvainGa: Do Not Disturb and Tesla batterie level/status. -- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal), THE FOLLOWING ADDED By SylvainGa: Body Battery. The meters have auto-scaling segments and current/target value display. +- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). +- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery. +- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal). The meters have auto-scaling segments and current/target value display. - Move bar. -- 12 colour themes, THE FOLLOWING ADDED By SylvainGa: Customizable themes. +- 12 colour themes. The techie bit: to save your watch battery, the goal meters and move bar are drawn from a palette-restricted back buffer, for improved drawing performance, with minimal memory penalty. -This is my first modification of a Connect IQ watch face (please be kind!), so I look forward to your feedback, improving the watch face, and bringing it to more devices. +This is my first ever Connect IQ watch face (please be kind!), so I look forward to your feedback, improving the watch face, and bringing it to more devices. Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. -## Below is what has been added by me (SylvainGa). -### 2.14.1 -- Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 -- Removed all the depencies between the devices and the sensors, features, themes color, etc. This makes supporting features much more easy but also could create confusion to some as to why a sensor for example doesn't work or a theme color seems odd. That's because your device doesn't specifically support that sensor or theme. For theme, it's basically the devices with less than 64 colors that will be affected. For sensors, it will depend on what your device support. See the specs of your specific devices for its available sensors. +## Below is what has been added by me (SylvainGa). ### 2.14.0 - "Hide seconds" has been changed from a checkbox to a list with three entries: diff --git a/manifest.xml b/manifest.xml index 38de375f..2190a3c1 100644 --- a/manifest.xml +++ b/manifest.xml @@ -38,8 +38,6 @@ - - @@ -48,7 +46,6 @@ - diff --git a/monkey.jungle b/monkey.jungle index dcfb9db5..1b269dde 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -83,8 +83,3 @@ d2air.sourcePath = $(d2air.sourcePath);always-on-source d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source epix2.sourcePath = $(epix2.sourcePath);always-on-source -fr965.sourcePath = $(fr965.sourcePath);always-on-source -fr265.sourcePath = $(fr265.sourcePath);always-on-source -fr265s.sourcePath = $(fr265s.sourcePath);always-on-source - -project.typecheck = 0 \ No newline at end of file diff --git a/resources-round-454x454/fonts/fonts.xml b/resources-round-454x454/fonts/fonts.xml deleted file mode 100644 index d90b563b..00000000 --- a/resources-round-454x454/fonts/fonts.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc b/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc deleted file mode 100644 index aca274c2..00000000 --- a/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=NanumGothicExtraBold -fontFile= -charSet=0 -fontSize=42 -aa=2 -scaleH=100 -useSmoothing=1 -isBold=0 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=32,40-41,48-57,44552,47785,49688,50900,51068,53664,54868 - -# imported icon images diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42.fnt b/resources-round-454x454/fonts/namum-gothic-kor-42.fnt deleted file mode 100644 index 97fe239c..00000000 --- a/resources-round-454x454/fonts/namum-gothic-kor-42.fnt +++ /dev/null @@ -1,24 +0,0 @@ -info face="NanumGothicExtraBold" size=42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=42 base=34 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="namum-gothic-kor-42_0.png" -chars count=20 -char id=32 x=191 y=35 width=2 height=1 xoffset=0 yoffset=41 xadvance=10 page=0 chnl=15 -char id=40 x=31 y=0 width=11 height=35 xoffset=2 yoffset=5 xadvance=13 page=0 chnl=15 -char id=41 x=43 y=0 width=11 height=35 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 -char id=48 x=22 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 -char id=49 x=243 y=0 width=11 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 -char id=50 x=82 y=35 width=18 height=27 xoffset=1 yoffset=8 xadvance=22 page=0 chnl=15 -char id=51 x=101 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 -char id=52 x=0 y=36 width=21 height=27 xoffset=0 yoffset=8 xadvance=22 page=0 chnl=15 -char id=53 x=139 y=35 width=17 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 -char id=54 x=42 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 -char id=55 x=120 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 -char id=56 x=222 y=0 width=20 height=30 xoffset=1 yoffset=7 xadvance=22 page=0 chnl=15 -char id=57 x=62 y=35 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 -char id=44552 x=90 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 -char id=47785 x=124 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 -char id=49688 x=158 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 -char id=50900 x=0 y=0 width=30 height=35 xoffset=1 yoffset=4 xadvance=34 page=0 chnl=15 -char id=51068 x=192 y=0 width=29 height=34 xoffset=2 yoffset=5 xadvance=34 page=0 chnl=15 -char id=53664 x=157 y=35 width=33 height=26 xoffset=0 yoffset=7 xadvance=34 page=0 chnl=15 -char id=54868 x=55 y=0 width=34 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42_0.png b/resources-round-454x454/fonts/namum-gothic-kor-42_0.png deleted file mode 100644 index 5f09960b2eee7c8e792ceedb44c37edcd8cb7301..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4436 zcmd6rhd0}c!-v0#YKU2T&uGP-wH2iVRkLcRy|x;yTA{>NS|ir2J)%Zylr%O$%T<)3 zw-iB9J5g$f{ODP)f9y6r-C+}2rY3t!!RKl4wt;bbMkvHxjpZR7*(J0Nl-<~K$~F30_~ zn0EoE>62M}4M$9h?;uKIOO4xDO|iHY=9AF5>GJ-joPRx^9gnFM&U~`^(&foosD1EC zi$qC{1*S+h^`_a@h#n$j+2BzvS0gjxQ90~wC5H&pTv{qlb?XBghNB$a|8*qP@TPXA3;Osyh4zc0&-5r92|Od%Xqr{7Mwe=ME0s<6Q_I+?6$Y z{_&h83l=hlSzOpyH?{SIm(Bef^nSc!U8hUUmFZM(lM-k71Y&Xi=pl;sLZ0S2n4L;T z^J|n|Xw@O)%w@TKhu{tuS zUDmRQPiZ$?CxqI5UciCYdEV&1xJ)NMi+O~wf|^@RX6dAOU#2j~=`OmRfS zR&+?sTaaa5B_!v1cVoDH$H_y)WD@-S8Uj(kkbokvW2R?lBvE!4KHz#Mh9Wv4;!`Lc zkd1Zk00&^Ou>fOsk$?M)ytv`Q@mq9mL&2Mphdu}c>!)ld7bs)_m``Gp4@l*c@X2gc zsz!Hl@o#_Nnb}|}sdb|X1LHFO37;U2fIkDFtx`UG_ewV8pugPs*xWK%M!RT{%dY^n zMCIZ|=96FafbV@k0HPd9Q`*iEK`0>noHl|knO`FU6 zGP^T^lBCUZ&Lh(%-pOF-Kzhua_?T9Jwd2ytw&4~dWG19fpUkP}dg@>=8^XeTHT?U+ z<88X#{#iT?j(iT)`#lW2BDCB(9}Zd8Hy%d{WpVU=isV;QIXANo$;3Hg&fYX1@e8KC z;^k0>)Hi|nB{oN=pZmS(lM{wiF5X4bFSe~#OSSNPEqbGeDHWM4_@9R}!4L736P|0X9q2_3pf5YKy@-FlW zE|{c_1bRe>5A<&s0>v3_i1}0D=G_4{Y41<;xVZd4IVz6@;}O=4BC`<~+-xUl)91l#3K_B2b^MHc_@TWp+x%{u;Rw1MgX^I~YheC_7l0p#BF>tRZ7|r5 z3Uk`kjI9lv{pdql2$|ZYhWmahXV;icV2*j&=hyk8Z@KvG@LnmDKLQh!-vZvyuKFyNh~BZ5fJ2v}hZ(jd%mnwceY{1`Xq*hEEs zxm&cUZV=>D;N$`<$VDgZPA}wTCbp{lkFCgk6j+ zZyl;*wSB)ER$CryDjiSP$o!~14+M9t0!X=R@`uB0%HCa0uS4fJd|Qt%AJQsJ3oD{z za&&mWzlD>r+a<8~e&gx8PPg_X*5lSCPokKE*n$`dH;5F=C%1wggo+>2whB>B=XcT> z#!tA@Eck;%AVAM+<@cJ(4!>`&(|#96x#3g}A}+s@Dk%EM1w)Z6VHA;h@&bPcjYObQ zj)TPsrEe+YtQMOd|l0!dikv;&O zu_%l**Af|)L+|}O6$X9+f5n8rf+!#4s1p7$-Q6shxIFftvSVfKN09o{G~I8`^m{K_ z)k3GLm$(Di_l(NyF@R; z=yYl%q(`n7TVVy?itOr#TnK>X#@m{7fLa9Ks)8LD=;aV`BX7zsFfT;E= zrOT*okOrkvQ4o1A;l^m!h?X&LOPFKb;QP|^?q(ZXH}9v)#HyD42Y<##%w~dr^{2SU zke%&6*!emi21$mlr26pl<<2|jYTnsV4wz-GeR4Ok5WcOnJNAHR!p#__QJQA#*tWbA ztQnY_V_xhSQd{F^UD2SVbG?#^Q`N#6Ui|0{ADYg;TG;$M(iu~TzcM!evv`&0T=rk zGzgzdZy(g1exOc@3-3#D)uUyT2lBRBq2oG2lHr}Wf;sEChdLubUDrw6bab*)>n~7L z_HK0V_g`TP3@-DQ!8%JIglV+Exg;Esf$I0_mT!AzDuYMfehMqe#(Dv+na-3^ONml> z&<0mNc9YN?US&_}-Zz5lW?>tPrgGNSbIdlY|6b%Sm3)WBv|&G1=^bB3+?7}ob5|MR z?W{0p)5pw%{XW1BA*p#Mk>1%7@@H?y)lybNXe*qYm>;>#0U2(; zbP$JhT7m(Kn?(yu8|IDT=;F;I=~s6|8fA9sjzBdm(o0)@qMX6B3T()~Sar02W>S9n zOB2_U`)%}o(-26PaPDqK&gDrgEAFE2+N{0G0$FHukFJT$wqt^c-;F&idx)X*Ri<$$4gAy6aIQkC3j- z!Kz&ZC48$|5^&_!n{rq-U+Tv=2ayTWdoI_6)@@*LD@NX)uQ#GAg!}23gF>(zmNyXH z3oA;9AB4$g(i~)F+XR^yk2l~hhpCXaefmAdQ(Hti1o4GONAO0V8x?>`&WpjV`0ndH zpFwdWth;;L*{LE&&hapR*&`Y|D$P=ZdlJ}m1(Opb{X!2UUo9)EEfE2E%WtO~fK*J( zAJ5|`GRY&G6$+0r4j&vol?3jAh!9i@k7Prhc1D>22B&@BVTCAfsh8DCJm?KW$Z)-N z&dSUw;^YI{VQ^nMNqn{&iRzJGlQrJx%l_~pFRE=Gzt4-*>xQX@zanEYr|B-CQbv1h z#Gg0CU-qmT!Bcz(j=?Qqvv|ZLE8*2R-O)nL1NlH8fwRf#a}y}!ah|mz#ty?UTCyb% zp*lg^)s-a>OcL&U39xR`qK*vWcmJp%QIzt4tm(IoER_-|tsMevlq|UUMO7;~fgS8} zP}%2USJG7hCWXiQ{{&}9&75wEM@GknVSv4V)_}2f_lvBb1tXezJi-XU&AdOZiR1^a2}~6XlcK?frRg!;`#07>r|i}k{ici7 zgJ{~4_4sXia?`4cl0o~_c#d%#S?8!rhXpyP-h6uPiqOd+ApOhZ#u+aG|M;}$hWweg zHxr?8VN9aLT@jmp%S>c|pFf(z@)lFsTp=w`%A6|I!QQ5D)6@bIt|0a`0`PxnaFREg z(IoHWV&2-CF8g?2CfW=BfrnxW9kRULdS}>ZEI0g#{7v7Ps6diC8=0`+hc2oiCeV_~c&Cde;6Qm5fS_Hg%&i&;?Sbp0s15eY_ z#wmHWk_9+@v5?&v6w(^6rxW6#ZJIeB_$-2+ZvQiVOgwHjKMO;5E}!ktRZ5T3EvT%i z*96d$PU>=KPhyvmuwt~jE6Kl2X7ra9au4Wl&^MR^r>)x$<6X!XhfL2U92XZ4@FF2o2l=e&ZgPCvYNILids=&|kZ6S4m zK5*DP*B~;E_@~zz!zTPu*X(L`MEL5vW6jV(5}xD0IR%|0vCXa1m9+}FcFRQ4 z$AT8y9^Qzmzy!IYLab1gD>g;9*vruqx1@8TzK+Efvs+80WZ;_kkGUr{dcP%YQFJ*8 z&lW$KU5&|?r8lr=57@XbGdB-Y^?%1F_;=UmQP1>v(G2-Hf&7A-^1SRPN#d~Kup%He zps1(L)%0-#-$GrC2|4oe9pMknv*P>Tv4#sT_xAl~lAWqf3XEHvod*;c|3B?zuhXS4 XH4*=sxsk{2|Lzimk%eJ{0W$7?Yj=5c diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc deleted file mode 100644 index 9b85ec32..00000000 --- a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc +++ /dev/null @@ -1,56 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Noto Sans CJK SC Medium -fontFile= -charSet=0 -fontSize=-42 -aa=2 -scaleH=100 -useSmoothing=1 -isBold=0 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=10,32,48-57,19968,19971,19977,20061,20108,20116,20843,20845,21313,22235,26085,26143,26376,26399 - - -# imported icon images diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt deleted file mode 100644 index ee5e7127..00000000 --- a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt +++ /dev/null @@ -1,30 +0,0 @@ -info face="Noto Sans CJK SC Medium" size=-42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=62 base=49 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="noto-sans-cjk-sc-medium-42_0.png" -chars count=26 -char id=10 x=242 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 -char id=32 x=245 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 -char id=48 x=66 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 -char id=49 x=236 y=0 width=18 height=32 xoffset=3 yoffset=17 xadvance=24 page=0 chnl=15 -char id=50 x=0 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 -char id=51 x=22 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 -char id=52 x=219 y=38 width=22 height=32 xoffset=0 yoffset=17 xadvance=24 page=0 chnl=15 -char id=53 x=44 y=77 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 -char id=54 x=87 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 -char id=55 x=108 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 -char id=56 x=129 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 -char id=57 x=150 y=74 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 -char id=19968 x=209 y=71 width=39 height=5 xoffset=2 yoffset=30 xadvance=42 page=0 chnl=15 -char id=19971 x=157 y=0 width=39 height=37 xoffset=1 yoffset=14 xadvance=42 page=0 chnl=15 -char id=19977 x=181 y=38 width=37 height=32 xoffset=3 yoffset=17 xadvance=42 page=0 chnl=15 -char id=20061 x=0 y=0 width=39 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 -char id=20108 x=171 y=74 width=37 height=29 xoffset=2 yoffset=19 xadvance=42 page=0 chnl=15 -char id=20116 x=142 y=40 width=38 height=33 xoffset=2 yoffset=17 xadvance=42 page=0 chnl=15 -char id=20843 x=35 y=40 width=40 height=36 xoffset=1 yoffset=16 xadvance=42 page=0 chnl=15 -char id=20845 x=40 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 -char id=21313 x=79 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 -char id=22235 x=106 y=40 width=35 height=35 xoffset=3 yoffset=16 xadvance=42 page=0 chnl=15 -char id=26085 x=76 y=40 width=29 height=36 xoffset=7 yoffset=16 xadvance=42 page=0 chnl=15 -char id=26143 x=197 y=0 width=38 height=37 xoffset=2 yoffset=14 xadvance=42 page=0 chnl=15 -char id=26376 x=0 y=40 width=34 height=37 xoffset=1 yoffset=15 xadvance=42 page=0 chnl=15 -char id=26399 x=118 y=0 width=38 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png deleted file mode 100644 index f10704df52d54dfa7443b3ac8251b24312bc3a6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5951 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 diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc b/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc deleted file mode 100644 index f1a2adf9..00000000 --- a/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Titillium Web Light -fontFile= -charSet=0 -fontSize=-118 -aa=2 -scaleH=105 -useSmoothing=1 -isBold=0 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=48-57 - -# imported icon images diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt b/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt deleted file mode 100644 index 4e7a6aed..00000000 --- a/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt +++ /dev/null @@ -1,14 +0,0 @@ -info face="Titillium Web Light" size=-118 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=189 base=141 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="titillium-web-light-118-tall_0.png" -chars count=10 -char id=48 x=60 y=0 width=56 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 -char id=49 x=206 y=86 width=32 height=83 xoffset=13 yoffset=58 xadvance=66 page=0 chnl=15 -char id=50 x=105 y=86 width=50 height=84 xoffset=8 yoffset=57 xadvance=66 page=0 chnl=15 -char id=51 x=0 y=86 width=51 height=85 xoffset=7 yoffset=57 xadvance=66 page=0 chnl=15 -char id=52 x=0 y=172 width=57 height=83 xoffset=4 yoffset=58 xadvance=66 page=0 chnl=15 -char id=53 x=52 y=86 width=52 height=84 xoffset=7 yoffset=58 xadvance=66 page=0 chnl=15 -char id=54 x=117 y=0 width=55 height=85 xoffset=6 yoffset=57 xadvance=66 page=0 chnl=15 -char id=55 x=156 y=86 width=49 height=84 xoffset=9 yoffset=58 xadvance=66 page=0 chnl=15 -char id=56 x=0 y=0 width=59 height=85 xoffset=3 yoffset=57 xadvance=66 page=0 chnl=15 -char id=57 x=173 y=0 width=55 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png b/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png deleted file mode 100644 index a062927290fa50a54ff6d4abe0f0d40c57f8e4f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7656 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 W#-8Fq&a->~0000N)-3ol$%f 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 - - - - - :left - 14 - 277 - 3 - - - - :right - 14 - 277 - 3 - - - - 136 - 144 - 336 - 362 - 331 - 92 - 324 - - - - 134 - 282 - 44 - 78 - 49 - - - - - - 49 - 208 - 51 - 41 - - - - -4 - 291 - 252 - - - - 88 - 286 - 192 - 13 - 4 - - - - - - - - [-60, -30, 30, 60] - -4 - 179 - 230 - - 230 - - 258 - 105 - - - \ No newline at end of file diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index ea021588..d72d08b7 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -44,16 +44,16 @@ class BackgroundService extends Sys.ServiceDelegate { var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); -//2023-03-05 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); +//2022-04-10 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { -//2023-03-05 logMessage("initialize:Generating Access Token"); +//2022-04-10 logMessage("initialize:Generating Access Token"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { -//2023-03-05 logMessage("initialize:No refresh token!"); +//2022-04-10 logMessage("initialize:No refresh token!"); } return; } @@ -75,7 +75,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -//2023-03-05 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); +//2022-04-10 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. @@ -269,7 +269,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveToken(responseCode, data) { var result; -//2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); +//2022-04-10 logMessage("onReceiveToken responseCode is " + responseCode); //logMessage("onReceiveToken data is " + data); if (responseCode == 200) { result = { "Token" => data }; @@ -283,7 +283,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveVehicles(responseCode, data) { var result; -//2023-03-05 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); +//2022-04-10 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { @@ -310,7 +310,7 @@ class BackgroundService extends Sys.ServiceDelegate { var precondEnabled = "N/A"; var sentryEnabled = "N/A"; -//2023-03-05 logMessage("onReceiveVehicleData responseCode is " + responseCode); +//2022-04-10 logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { results = data.get("response"); if (results != null) { @@ -368,12 +368,9 @@ class BackgroundService extends Sys.ServiceDelegate { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, :headers => { - "Authorization" => _token, - "User-Agent" => "Crystal-Tesla for Garmin", - }, + "Authorization" => _token}, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; -//2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); Comms.makeWebRequest(url, params, options, callback); } //**************************************************************** From 3292bd5e75aa1b7cc7edbc2b01716b7a4709f4f8 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:48:26 -0500 Subject: [PATCH 081/220] Revert "Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 and removal of dependencies for devices" This reverts commit 1f84ed660bbc095facf77d1d605bf57a391c4f61. --- resources-approachs60/settings/properties.xml | 9 ++ resources-approachs60/settings/settings.xml | 82 +++++++++++ resources-approachs62/settings/properties.xml | 6 + resources-approachs62/settings/settings.xml | 82 +++++++++++ .../settings/properties.xml | 10 ++ resources-ciq_1.x-no_hr/settings/settings.xml | 105 ++++++++++++++ resources-ciq_1.x/settings/properties.xml | 7 + resources-ciq_1.x/settings/settings.xml | 105 ++++++++++++++ resources-fr735xt/settings/properties.xml | 6 + resources-fr735xt/settings/settings.xml | 101 ++++++++++++++ resources-no_floors/settings/properties.xml | 6 + resources-no_floors/settings/settings.xml | 23 +++ .../settings/settings.xml | 8 ++ .../settings/properties.xml | 6 + .../settings/settings.xml | 82 +++++++++++ .../settings/properties.xml | 6 + .../settings/settings.xml | 82 +++++++++++ .../settings/properties.xml | 8 ++ resources-round-208x208/settings/settings.xml | 131 ++++++++++++++++++ resources-vivoactive/settings/properties.xml | 10 ++ resources-vivoactive/settings/settings.xml | 108 +++++++++++++++ 21 files changed, 983 insertions(+) create mode 100644 resources-approachs60/settings/properties.xml create mode 100644 resources-approachs60/settings/settings.xml create mode 100644 resources-approachs62/settings/properties.xml create mode 100644 resources-approachs62/settings/settings.xml create mode 100644 resources-ciq_1.x-no_hr/settings/properties.xml create mode 100644 resources-ciq_1.x-no_hr/settings/settings.xml create mode 100644 resources-ciq_1.x/settings/properties.xml create mode 100644 resources-ciq_1.x/settings/settings.xml create mode 100644 resources-fr735xt/settings/properties.xml create mode 100644 resources-fr735xt/settings/settings.xml create mode 100644 resources-no_floors/settings/properties.xml create mode 100644 resources-no_floors/settings/settings.xml create mode 100644 resources-rectangle-205x148/settings/settings.xml create mode 100644 resources-rectangle-240x240/settings/properties.xml create mode 100644 resources-rectangle-240x240/settings/settings.xml create mode 100644 resources-rectangle-320x360/settings/properties.xml create mode 100644 resources-rectangle-320x360/settings/settings.xml create mode 100644 resources-round-208x208/settings/properties.xml create mode 100644 resources-round-208x208/settings/settings.xml create mode 100644 resources-vivoactive/settings/properties.xml create mode 100644 resources-vivoactive/settings/settings.xml diff --git a/resources-approachs60/settings/properties.xml b/resources-approachs60/settings/properties.xml new file mode 100644 index 00000000..c0e58606 --- /dev/null +++ b/resources-approachs60/settings/properties.xml @@ -0,0 +1,9 @@ + + + + 2 + + + 4 + + \ No newline at end of file diff --git a/resources-approachs60/settings/settings.xml b/resources-approachs60/settings/settings.xml new file mode 100644 index 00000000..b50722b3 --- /dev/null +++ b/resources-approachs60/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-approachs62/settings/properties.xml b/resources-approachs62/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-approachs62/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-approachs62/settings/settings.xml b/resources-approachs62/settings/settings.xml new file mode 100644 index 00000000..f74f5684 --- /dev/null +++ b/resources-approachs62/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-ciq_1.x-no_hr/settings/properties.xml b/resources-ciq_1.x-no_hr/settings/properties.xml new file mode 100644 index 00000000..cb2de3ec --- /dev/null +++ b/resources-ciq_1.x-no_hr/settings/properties.xml @@ -0,0 +1,10 @@ + + + + -1 + 3 + + + 4 + + \ No newline at end of file diff --git a/resources-ciq_1.x-no_hr/settings/settings.xml b/resources-ciq_1.x-no_hr/settings/settings.xml new file mode 100644 index 00000000..b9ffed38 --- /dev/null +++ b/resources-ciq_1.x-no_hr/settings/settings.xml @@ -0,0 +1,105 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + diff --git a/resources-ciq_1.x/settings/properties.xml b/resources-ciq_1.x/settings/properties.xml new file mode 100644 index 00000000..0981fb4b --- /dev/null +++ b/resources-ciq_1.x/settings/properties.xml @@ -0,0 +1,7 @@ + + + + -1 + 3 + + \ No newline at end of file diff --git a/resources-ciq_1.x/settings/settings.xml b/resources-ciq_1.x/settings/settings.xml new file mode 100644 index 00000000..f394bc41 --- /dev/null +++ b/resources-ciq_1.x/settings/settings.xml @@ -0,0 +1,105 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + diff --git a/resources-fr735xt/settings/properties.xml b/resources-fr735xt/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-fr735xt/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-fr735xt/settings/settings.xml b/resources-fr735xt/settings/settings.xml new file mode 100644 index 00000000..83800a64 --- /dev/null +++ b/resources-fr735xt/settings/settings.xml @@ -0,0 +1,101 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-no_floors/settings/properties.xml b/resources-no_floors/settings/properties.xml new file mode 100644 index 00000000..97b20a1e --- /dev/null +++ b/resources-no_floors/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + diff --git a/resources-no_floors/settings/settings.xml b/resources-no_floors/settings/settings.xml new file mode 100644 index 00000000..88f9799d --- /dev/null +++ b/resources-no_floors/settings/settings.xml @@ -0,0 +1,23 @@ + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + \ No newline at end of file diff --git a/resources-rectangle-205x148/settings/settings.xml b/resources-rectangle-205x148/settings/settings.xml new file mode 100644 index 00000000..67715ed0 --- /dev/null +++ b/resources-rectangle-205x148/settings/settings.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources-rectangle-240x240/settings/properties.xml b/resources-rectangle-240x240/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-rectangle-240x240/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-rectangle-240x240/settings/settings.xml b/resources-rectangle-240x240/settings/settings.xml new file mode 100644 index 00000000..f74f5684 --- /dev/null +++ b/resources-rectangle-240x240/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-rectangle-320x360/settings/properties.xml b/resources-rectangle-320x360/settings/properties.xml new file mode 100644 index 00000000..2782de9e --- /dev/null +++ b/resources-rectangle-320x360/settings/properties.xml @@ -0,0 +1,6 @@ + + + + 2 + + \ No newline at end of file diff --git a/resources-rectangle-320x360/settings/settings.xml b/resources-rectangle-320x360/settings/settings.xml new file mode 100644 index 00000000..f74f5684 --- /dev/null +++ b/resources-rectangle-320x360/settings/settings.xml @@ -0,0 +1,82 @@ + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + @Strings.ActiveMinutes + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + + + @Strings.HeartRate + @Strings.HeartRateLive5s + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + @Strings.Weather + @Strings.Humidity + + + + diff --git a/resources-round-208x208/settings/properties.xml b/resources-round-208x208/settings/properties.xml new file mode 100644 index 00000000..eaad25bc --- /dev/null +++ b/resources-round-208x208/settings/properties.xml @@ -0,0 +1,8 @@ + + + + + -1 + 3 + + \ No newline at end of file diff --git a/resources-round-208x208/settings/settings.xml b/resources-round-208x208/settings/settings.xml new file mode 100644 index 00000000..4ea9fbcc --- /dev/null +++ b/resources-round-208x208/settings/settings.xml @@ -0,0 +1,131 @@ + + + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + + + + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + + + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + + + + + @Strings.FromTheme + + @Strings.Mono + + + + + + + @Strings.FromTheme + + @Strings.Mono + + + diff --git a/resources-vivoactive/settings/properties.xml b/resources-vivoactive/settings/properties.xml new file mode 100644 index 00000000..cb2de3ec --- /dev/null +++ b/resources-vivoactive/settings/properties.xml @@ -0,0 +1,10 @@ + + + + -1 + 3 + + + 4 + + \ No newline at end of file diff --git a/resources-vivoactive/settings/settings.xml b/resources-vivoactive/settings/settings.xml new file mode 100644 index 00000000..5b0c6ee1 --- /dev/null +++ b/resources-vivoactive/settings/settings.xml @@ -0,0 +1,108 @@ + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + @Strings.ThemeCornflowerBlueDark + @Strings.ThemeLemonCreamDark + @Strings.ThemeVividYellowDark + + @Strings.ThemeCornYellowDark + @Strings.ThemeDaygloOrangeDark + @Strings.ThemeMonoDark + @Strings.ThemeMonoLight + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + @Strings.ThemeDaygloOrangeLight + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.Off + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + From e2b10d55ff4fa7c369d8bfe05a976204ffe602f4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 5 Mar 2023 23:51:02 -0500 Subject: [PATCH 082/220] Revert "X" This reverts commit 60dd0cec3b59187c08c77a396165b453b3f7d15d. --- README.md | 19 +- manifest.xml | 3 + monkey.jungle | 5 + resources-round-454x454/fonts/fonts.xml | 35 ++ .../fonts/namum-gothic-kor-42.bmfc | 55 ++ .../fonts/namum-gothic-kor-42.fnt | 24 + .../fonts/namum-gothic-kor-42_0.png | Bin 0 -> 4436 bytes .../fonts/noto-sans-cjk-sc-medium-42.bmfc | 56 ++ .../fonts/noto-sans-cjk-sc-medium-42.fnt | 30 + .../fonts/noto-sans-cjk-sc-medium-42_0.png | Bin 0 -> 5951 bytes .../fonts/noto-sans-cjk-tc-medium-42.bmfc | 56 ++ .../fonts/noto-sans-cjk-tc-medium-42.fnt | 30 + .../fonts/noto-sans-cjk-tc-medium-42_0.png | Bin 0 -> 5929 bytes .../fonts/noto-sans-rus-bold-42.bmfc | 55 ++ .../fonts/noto-sans-rus-bold-42.fnt | 47 ++ .../fonts/noto-sans-rus-bold-42_0.png | Bin 0 -> 9285 bytes .../fonts/titillium-web-bold-118-tall.bmfc | 55 ++ .../fonts/titillium-web-bold-118-tall.fnt | 14 + .../fonts/titillium-web-bold-118-tall_0.png | Bin 0 -> 7300 bytes .../fonts/titillium-web-bold-85-tall.bmfc | 55 ++ .../fonts/titillium-web-bold-85-tall.fnt | 14 + .../fonts/titillium-web-bold-85-tall_0.png | Bin 0 -> 3976 bytes .../fonts/titillium-web-light-118-tall.bmfc | 55 ++ .../fonts/titillium-web-light-118-tall.fnt | 14 + .../fonts/titillium-web-light-118-tall_0.png | Bin 0 -> 7656 bytes .../fonts/titillium-web-light-85-tall.bmfc | 55 ++ .../fonts/titillium-web-light-85-tall.fnt | 15 + .../fonts/titillium-web-light-85-tall_0.png | Bin 0 -> 4089 bytes .../fonts/titillium-web-semibold-30.bmfc | 57 ++ .../fonts/titillium-web-semibold-30.fnt | 555 +++++++++++++++++ .../fonts/titillium-web-semibold-30_0.png | Bin 0 -> 12388 bytes .../fonts/titillium-web-semibold-42.bmfc | 57 ++ .../fonts/titillium-web-semibold-42.fnt | 556 ++++++++++++++++++ .../fonts/titillium-web-semibold-42_0.png | Bin 0 -> 12774 bytes .../fonts/titillium-web-semibold-42_1.png | Bin 0 -> 11167 bytes resources-round-454x454/layouts/layout.xml | 78 +++ source/BackgroundService.mc | 19 +- 37 files changed, 1998 insertions(+), 16 deletions(-) create mode 100644 resources-round-454x454/fonts/fonts.xml create mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42.bmfc create mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42.fnt create mode 100644 resources-round-454x454/fonts/namum-gothic-kor-42_0.png create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42.bmfc create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42.fnt create mode 100644 resources-round-454x454/fonts/noto-sans-cjk-tc-medium-42_0.png create mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42.bmfc create mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42.fnt create mode 100644 resources-round-454x454/fonts/noto-sans-rus-bold-42_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-bold-85-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-light-85-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-30_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_1.png create mode 100644 resources-round-454x454/layouts/layout.xml diff --git a/README.md b/README.md index 051d95f1..124f5b74 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Crystal -A Garmin Connect IQ watch face. +# Crystal-Tesla +A Garmin Connect IQ watch face based on PixelPathos Crystal. ## Description **If you enjoy this maintained version of Crystal with Tesla integration, you can support my work with a small donation:** @@ -12,22 +12,25 @@ A crystal clear watch face, with LCD-like goal meter segments, written while sno Features (depending on watch support): - Big time digits right in the middle, with hours in bold. Leading zero and seconds can be hidden. Hours and minutes colours can be set independently. -- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). -- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery. -- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal). The meters have auto-scaling segments and current/target value display. +- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). THE FOLLOWING ADDED By SylvainGa: Garmin Weather, Recovery Time Left, Body Battery, Solar Intensity, Floors climbed and Pulse Ox. +- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery, THE FOLLOWING ADDED By SylvainGa: Do Not Disturb and Tesla batterie level/status. +- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal), THE FOLLOWING ADDED By SylvainGa: Body Battery. The meters have auto-scaling segments and current/target value display. - Move bar. -- 12 colour themes. +- 12 colour themes, THE FOLLOWING ADDED By SylvainGa: Customizable themes. The techie bit: to save your watch battery, the goal meters and move bar are drawn from a palette-restricted back buffer, for improved drawing performance, with minimal memory penalty. -This is my first ever Connect IQ watch face (please be kind!), so I look forward to your feedback, improving the watch face, and bringing it to more devices. +This is my first modification of a Connect IQ watch face (please be kind!), so I look forward to your feedback, improving the watch face, and bringing it to more devices. Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. - ## Below is what has been added by me (SylvainGa). +### 2.14.1 +- Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 +- Removed all the depencies between the devices and the sensors, features, themes color, etc. This makes supporting features much more easy but also could create confusion to some as to why a sensor for example doesn't work or a theme color seems odd. That's because your device doesn't specifically support that sensor or theme. For theme, it's basically the devices with less than 64 colors that will be affected. For sensors, it will depend on what your device support. See the specs of your specific devices for its available sensors. + ### 2.14.0 - "Hide seconds" has been changed from a checkbox to a list with three entries: - Show seconds diff --git a/manifest.xml b/manifest.xml index 2190a3c1..38de375f 100644 --- a/manifest.xml +++ b/manifest.xml @@ -38,6 +38,8 @@ + + @@ -46,6 +48,7 @@ + diff --git a/monkey.jungle b/monkey.jungle index 1b269dde..dcfb9db5 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -83,3 +83,8 @@ d2air.sourcePath = $(d2air.sourcePath);always-on-source d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source epix2.sourcePath = $(epix2.sourcePath);always-on-source +fr965.sourcePath = $(fr965.sourcePath);always-on-source +fr265.sourcePath = $(fr265.sourcePath);always-on-source +fr265s.sourcePath = $(fr265s.sourcePath);always-on-source + +project.typecheck = 0 \ No newline at end of file diff --git a/resources-round-454x454/fonts/fonts.xml b/resources-round-454x454/fonts/fonts.xml new file mode 100644 index 00000000..d90b563b --- /dev/null +++ b/resources-round-454x454/fonts/fonts.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc b/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc new file mode 100644 index 00000000..aca274c2 --- /dev/null +++ b/resources-round-454x454/fonts/namum-gothic-kor-42.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=NanumGothicExtraBold +fontFile= +charSet=0 +fontSize=42 +aa=2 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=32,40-41,48-57,44552,47785,49688,50900,51068,53664,54868 + +# imported icon images diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42.fnt b/resources-round-454x454/fonts/namum-gothic-kor-42.fnt new file mode 100644 index 00000000..97fe239c --- /dev/null +++ b/resources-round-454x454/fonts/namum-gothic-kor-42.fnt @@ -0,0 +1,24 @@ +info face="NanumGothicExtraBold" size=42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=42 base=34 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="namum-gothic-kor-42_0.png" +chars count=20 +char id=32 x=191 y=35 width=2 height=1 xoffset=0 yoffset=41 xadvance=10 page=0 chnl=15 +char id=40 x=31 y=0 width=11 height=35 xoffset=2 yoffset=5 xadvance=13 page=0 chnl=15 +char id=41 x=43 y=0 width=11 height=35 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 +char id=48 x=22 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=49 x=243 y=0 width=11 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 +char id=50 x=82 y=35 width=18 height=27 xoffset=1 yoffset=8 xadvance=22 page=0 chnl=15 +char id=51 x=101 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=52 x=0 y=36 width=21 height=27 xoffset=0 yoffset=8 xadvance=22 page=0 chnl=15 +char id=53 x=139 y=35 width=17 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 +char id=54 x=42 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=55 x=120 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=56 x=222 y=0 width=20 height=30 xoffset=1 yoffset=7 xadvance=22 page=0 chnl=15 +char id=57 x=62 y=35 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=44552 x=90 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=47785 x=124 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=49688 x=158 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=50900 x=0 y=0 width=30 height=35 xoffset=1 yoffset=4 xadvance=34 page=0 chnl=15 +char id=51068 x=192 y=0 width=29 height=34 xoffset=2 yoffset=5 xadvance=34 page=0 chnl=15 +char id=53664 x=157 y=35 width=33 height=26 xoffset=0 yoffset=7 xadvance=34 page=0 chnl=15 +char id=54868 x=55 y=0 width=34 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/namum-gothic-kor-42_0.png b/resources-round-454x454/fonts/namum-gothic-kor-42_0.png new file mode 100644 index 0000000000000000000000000000000000000000..5f09960b2eee7c8e792ceedb44c37edcd8cb7301 GIT binary patch literal 4436 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 XH4*=sxsk{2|Lzimk%eJ{0W$7?Yj=5c literal 0 HcmV?d00001 diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc new file mode 100644 index 00000000..9b85ec32 --- /dev/null +++ b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.bmfc @@ -0,0 +1,56 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Noto Sans CJK SC Medium +fontFile= +charSet=0 +fontSize=-42 +aa=2 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=10,32,48-57,19968,19971,19977,20061,20108,20116,20843,20845,21313,22235,26085,26143,26376,26399 + + +# imported icon images diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt new file mode 100644 index 00000000..ee5e7127 --- /dev/null +++ b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42.fnt @@ -0,0 +1,30 @@ +info face="Noto Sans CJK SC Medium" size=-42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=62 base=49 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="noto-sans-cjk-sc-medium-42_0.png" +chars count=26 +char id=10 x=242 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 +char id=32 x=245 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 +char id=48 x=66 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=49 x=236 y=0 width=18 height=32 xoffset=3 yoffset=17 xadvance=24 page=0 chnl=15 +char id=50 x=0 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=51 x=22 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=52 x=219 y=38 width=22 height=32 xoffset=0 yoffset=17 xadvance=24 page=0 chnl=15 +char id=53 x=44 y=77 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=54 x=87 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=55 x=108 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=56 x=129 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=57 x=150 y=74 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=19968 x=209 y=71 width=39 height=5 xoffset=2 yoffset=30 xadvance=42 page=0 chnl=15 +char id=19971 x=157 y=0 width=39 height=37 xoffset=1 yoffset=14 xadvance=42 page=0 chnl=15 +char id=19977 x=181 y=38 width=37 height=32 xoffset=3 yoffset=17 xadvance=42 page=0 chnl=15 +char id=20061 x=0 y=0 width=39 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 +char id=20108 x=171 y=74 width=37 height=29 xoffset=2 yoffset=19 xadvance=42 page=0 chnl=15 +char id=20116 x=142 y=40 width=38 height=33 xoffset=2 yoffset=17 xadvance=42 page=0 chnl=15 +char id=20843 x=35 y=40 width=40 height=36 xoffset=1 yoffset=16 xadvance=42 page=0 chnl=15 +char id=20845 x=40 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 +char id=21313 x=79 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 +char id=22235 x=106 y=40 width=35 height=35 xoffset=3 yoffset=16 xadvance=42 page=0 chnl=15 +char id=26085 x=76 y=40 width=29 height=36 xoffset=7 yoffset=16 xadvance=42 page=0 chnl=15 +char id=26143 x=197 y=0 width=38 height=37 xoffset=2 yoffset=14 xadvance=42 page=0 chnl=15 +char id=26376 x=0 y=40 width=34 height=37 xoffset=1 yoffset=15 xadvance=42 page=0 chnl=15 +char id=26399 x=118 y=0 width=38 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png b/resources-round-454x454/fonts/noto-sans-cjk-sc-medium-42_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f10704df52d54dfa7443b3ac8251b24312bc3a6a GIT binary patch literal 5951 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 literal 0 HcmV?d00001 diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc b/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc new file mode 100644 index 00000000..f1a2adf9 --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web Light +fontFile= +charSet=0 +fontSize=-118 +aa=2 +scaleH=105 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt b/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt new file mode 100644 index 00000000..4e7a6aed --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt @@ -0,0 +1,14 @@ +info face="Titillium Web Light" size=-118 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=189 base=141 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-light-118-tall_0.png" +chars count=10 +char id=48 x=60 y=0 width=56 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 +char id=49 x=206 y=86 width=32 height=83 xoffset=13 yoffset=58 xadvance=66 page=0 chnl=15 +char id=50 x=105 y=86 width=50 height=84 xoffset=8 yoffset=57 xadvance=66 page=0 chnl=15 +char id=51 x=0 y=86 width=51 height=85 xoffset=7 yoffset=57 xadvance=66 page=0 chnl=15 +char id=52 x=0 y=172 width=57 height=83 xoffset=4 yoffset=58 xadvance=66 page=0 chnl=15 +char id=53 x=52 y=86 width=52 height=84 xoffset=7 yoffset=58 xadvance=66 page=0 chnl=15 +char id=54 x=117 y=0 width=55 height=85 xoffset=6 yoffset=57 xadvance=66 page=0 chnl=15 +char id=55 x=156 y=86 width=49 height=84 xoffset=9 yoffset=58 xadvance=66 page=0 chnl=15 +char id=56 x=0 y=0 width=59 height=85 xoffset=3 yoffset=57 xadvance=66 page=0 chnl=15 +char id=57 x=173 y=0 width=55 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png b/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png new file mode 100644 index 0000000000000000000000000000000000000000..a062927290fa50a54ff6d4abe0f0d40c57f8e4f4 GIT binary patch literal 7656 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 W#-8Fq&a->~0000N)-3ol$%f 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 + + + + + :left + 14 + 277 + 3 + + + + :right + 14 + 277 + 3 + + + + 136 + 144 + 336 + 362 + 331 + 92 + 324 + + + + 134 + 282 + 44 + 78 + 49 + + + + + + 49 + 208 + 51 + 41 + + + + -4 + 291 + 252 + + + + 88 + 286 + 192 + 13 + 4 + + + + + + + + [-60, -30, 30, 60] + -4 + 179 + 230 + + 230 + + 258 + 105 + + + \ No newline at end of file diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index d72d08b7..ea021588 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -44,16 +44,16 @@ class BackgroundService extends Sys.ServiceDelegate { var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); -//2022-04-10 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); +//2023-03-05 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { -//2022-04-10 logMessage("initialize:Generating Access Token"); +//2023-03-05 logMessage("initialize:Generating Access Token"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { -//2022-04-10 logMessage("initialize:No refresh token!"); +//2023-03-05 logMessage("initialize:No refresh token!"); } return; } @@ -75,7 +75,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -//2022-04-10 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); +//2023-03-05 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. @@ -269,7 +269,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveToken(responseCode, data) { var result; -//2022-04-10 logMessage("onReceiveToken responseCode is " + responseCode); +//2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); //logMessage("onReceiveToken data is " + data); if (responseCode == 200) { result = { "Token" => data }; @@ -283,7 +283,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveVehicles(responseCode, data) { var result; -//2022-04-10 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); +//2023-03-05 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { @@ -310,7 +310,7 @@ class BackgroundService extends Sys.ServiceDelegate { var precondEnabled = "N/A"; var sentryEnabled = "N/A"; -//2022-04-10 logMessage("onReceiveVehicleData responseCode is " + responseCode); +//2023-03-05 logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { results = data.get("response"); if (results != null) { @@ -368,9 +368,12 @@ class BackgroundService extends Sys.ServiceDelegate { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, :headers => { - "Authorization" => _token}, + "Authorization" => _token, + "User-Agent" => "Crystal-Tesla for Garmin", + }, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; +//2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); Comms.makeWebRequest(url, params, options, callback); } //**************************************************************** From 7b830f137037a5f1b9a7c2ceba5ed36193d644bb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:43:49 -0500 Subject: [PATCH 083/220] Brought back device dependencies. Added BodyBattery to FR55 and adjusted the 454x454 objects location on screen --- README.md | 2 +- monkey.jungle | 3 + resources-approachs60/settings/settings.xml | 4 +- resources-approachs62/settings/settings.xml | 4 +- resources-ciq_1.x-no_hr/settings/settings.xml | 4 +- resources-ciq_1.x/settings/settings.xml | 4 +- resources-fr55/settings/properties.xml | 8 ++ resources-fr55/settings/settings.xml | 133 ++++++++++++++++++ resources-fr735xt/settings/settings.xml | 4 +- resources-no_floors/settings/settings.xml | 4 +- .../settings/settings.xml | 4 +- .../settings/settings.xml | 4 +- resources-round-208x208/settings/settings.xml | 4 +- resources-round-454x454/layouts/layout.xml | 50 +++---- resources-vivoactive/settings/settings.xml | 4 +- source/BackgroundService.mc | 6 +- 16 files changed, 193 insertions(+), 49 deletions(-) create mode 100644 resources-fr55/settings/properties.xml create mode 100644 resources-fr55/settings/settings.xml diff --git a/README.md b/README.md index 124f5b74..55b18f3a 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Reviews: ### 2.14.1 - Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 -- Removed all the depencies between the devices and the sensors, features, themes color, etc. This makes supporting features much more easy but also could create confusion to some as to why a sensor for example doesn't work or a theme color seems odd. That's because your device doesn't specifically support that sensor or theme. For theme, it's basically the devices with less than 64 colors that will be affected. For sensors, it will depend on what your device support. See the specs of your specific devices for its available sensors. +- Added BodyBattery to the Forerunner 55 ### 2.14.0 - "Hide seconds" has been changed from a checkbox to a list with three entries: diff --git a/monkey.jungle b/monkey.jungle index dcfb9db5..e4d64aaf 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -7,6 +7,9 @@ base.sourcePath = source fr245.resourcePath = $(fr245.resourcePath);resources-no_floors fr245m.resourcePath = $(fr245m.resourcePath);resources-no_floors +# Needs BodyBattery +fr55.resourcePath = $(fr55.resourcePath);resources-small-time;resources-small-icons + # Smaller round watches use small time font. round-218x218.resourcePath = $(round-218x218.resourcePath);resources-small-time diff --git a/resources-approachs60/settings/settings.xml b/resources-approachs60/settings/settings.xml index b50722b3..77bce9d4 100644 --- a/resources-approachs60/settings/settings.xml +++ b/resources-approachs60/settings/settings.xml @@ -7,7 +7,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -18,7 +18,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-approachs62/settings/settings.xml b/resources-approachs62/settings/settings.xml index f74f5684..36351664 100644 --- a/resources-approachs62/settings/settings.xml +++ b/resources-approachs62/settings/settings.xml @@ -7,7 +7,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -18,7 +18,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-ciq_1.x-no_hr/settings/settings.xml b/resources-ciq_1.x-no_hr/settings/settings.xml index b9ffed38..7b2cf620 100644 --- a/resources-ciq_1.x-no_hr/settings/settings.xml +++ b/resources-ciq_1.x-no_hr/settings/settings.xml @@ -26,7 +26,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -37,7 +37,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-ciq_1.x/settings/settings.xml b/resources-ciq_1.x/settings/settings.xml index f394bc41..6d8ef69b 100644 --- a/resources-ciq_1.x/settings/settings.xml +++ b/resources-ciq_1.x/settings/settings.xml @@ -26,7 +26,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -37,7 +37,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-fr55/settings/properties.xml b/resources-fr55/settings/properties.xml new file mode 100644 index 00000000..eaad25bc --- /dev/null +++ b/resources-fr55/settings/properties.xml @@ -0,0 +1,8 @@ + + + + + -1 + 3 + + \ No newline at end of file diff --git a/resources-fr55/settings/settings.xml b/resources-fr55/settings/settings.xml new file mode 100644 index 00000000..2a880759 --- /dev/null +++ b/resources-fr55/settings/settings.xml @@ -0,0 +1,133 @@ + + + + + + @Strings.ThemeBlueDark + @Strings.ThemePinkDark + @Strings.ThemeRedDark + @Strings.ThemeGreenDark + + + + @Strings.ThemeCornYellowDark + + + + @Strings.ThemeBlueLight + @Strings.ThemeGreenLight + @Strings.ThemeRedLight + + + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.BodyBattery + @Strings.Off + + + + + + + @Strings.Steps + + + @Strings.Battery + @Strings.CaloriesManualGoal + @Strings.BodyBattery + @Strings.Off + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + @Strings.HeartRate + + @Strings.Battery + @Strings.BatteryHidePercentage + @Strings.Notifications + @Strings.Calories + @Strings.Distance + @Strings.Alarms + @Strings.Altitude + + + @Strings.SunriseSunset + + + + + + + + + + + + + + @Strings.FromTheme + + @Strings.Mono + + + + + + + @Strings.FromTheme + + @Strings.Mono + + + diff --git a/resources-fr735xt/settings/settings.xml b/resources-fr735xt/settings/settings.xml index 83800a64..f96e4171 100644 --- a/resources-fr735xt/settings/settings.xml +++ b/resources-fr735xt/settings/settings.xml @@ -26,7 +26,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -37,7 +37,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-no_floors/settings/settings.xml b/resources-no_floors/settings/settings.xml index 88f9799d..4b477b96 100644 --- a/resources-no_floors/settings/settings.xml +++ b/resources-no_floors/settings/settings.xml @@ -6,7 +6,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -17,7 +17,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off \ No newline at end of file diff --git a/resources-rectangle-240x240/settings/settings.xml b/resources-rectangle-240x240/settings/settings.xml index f74f5684..36351664 100644 --- a/resources-rectangle-240x240/settings/settings.xml +++ b/resources-rectangle-240x240/settings/settings.xml @@ -7,7 +7,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -18,7 +18,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-rectangle-320x360/settings/settings.xml b/resources-rectangle-320x360/settings/settings.xml index f74f5684..36351664 100644 --- a/resources-rectangle-320x360/settings/settings.xml +++ b/resources-rectangle-320x360/settings/settings.xml @@ -7,7 +7,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -18,7 +18,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-round-208x208/settings/settings.xml b/resources-round-208x208/settings/settings.xml index 4ea9fbcc..447bd10b 100644 --- a/resources-round-208x208/settings/settings.xml +++ b/resources-round-208x208/settings/settings.xml @@ -30,7 +30,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -42,7 +42,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-round-454x454/layouts/layout.xml b/resources-round-454x454/layouts/layout.xml index 6c46bb42..d4a1eaf4 100644 --- a/resources-round-454x454/layouts/layout.xml +++ b/resources-round-454x454/layouts/layout.xml @@ -5,57 +5,57 @@ :left 14 - 277 + 302 3 :right 14 - 277 + 302 3 136 - 144 - 336 - 362 - 331 + 157 + 366 + 395 + 361 92 - 324 + 353 134 - 282 + 318 44 - 78 - 49 + 85 + 53 - 49 - 208 - 51 - 41 + 62 + 227 + 60 + 45 -4 - 291 - 252 + 304 + 263 88 - 286 - 192 - 13 + 312 + 209 + 14 4 @@ -66,13 +66,13 @@ [-60, -30, 30, 60] -4 - 179 - 230 + 195 + 221 - 230 + 251 - 258 - 105 + 281 + 114 \ No newline at end of file diff --git a/resources-vivoactive/settings/settings.xml b/resources-vivoactive/settings/settings.xml index 5b0c6ee1..aa368db8 100644 --- a/resources-vivoactive/settings/settings.xml +++ b/resources-vivoactive/settings/settings.xml @@ -29,7 +29,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -40,7 +40,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index ea021588..6544718f 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -41,9 +41,9 @@ class BackgroundService extends Sys.ServiceDelegate { var answer = (timeNow + interval < createdAt + expiresIn); if (_token != null && _token.equals("") == false && answer == true) { - var expireAt = new Time.Moment(createdAt + expiresIn); - var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); +//2023-03-05 var expireAt = new Time.Moment(createdAt + expiresIn); +//2023-03-05 var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); +//2023-03-05 var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); //2023-03-05 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } From 646aab7e281c5994892418f4a5876444453b9f1d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:44:59 -0500 Subject: [PATCH 084/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 55b18f3a..a46ee06e 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.14.1 -- Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 +- Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 (first 454x454 watch) - Added BodyBattery to the Forerunner 55 ### 2.14.0 From df94fab96dfc1e1aafb559ef77b41e4c6ad7296b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 6 Mar 2023 00:49:39 -0500 Subject: [PATCH 085/220] Removed two unused variables --- always-on-source/AlwaysOnDisplay.mc | 2 -- 1 file changed, 2 deletions(-) diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index dd66c1b1..d529277d 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -203,10 +203,8 @@ class AlwaysOnDisplay extends Ui.Drawable { // Batteries. var battery = Math.floor(Sys.getSystemStats().battery); - var batteryStale = App.getApp().getProperty("TeslaBatterieStale"); var chargingState = App.getApp().getProperty("TeslaChargingState"); var error = App.getApp().getProperty("TeslaError"); - var teslaBat = null; if (chargingState != null) { if (chargingState.equals("Charging")) { From 3363f2fc3f907fe82430bf971a0adcb63751633d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 6 Mar 2023 21:31:28 -0500 Subject: [PATCH 086/220] Update monkey.jungle --- monkey.jungle | 1 - 1 file changed, 1 deletion(-) diff --git a/monkey.jungle b/monkey.jungle index e4d64aaf..58e58551 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -90,4 +90,3 @@ fr965.sourcePath = $(fr965.sourcePath);always-on-source fr265.sourcePath = $(fr265.sourcePath);always-on-source fr265s.sourcePath = $(fr265s.sourcePath);always-on-source -project.typecheck = 0 \ No newline at end of file From c02c70f996f5df62f1564fff6952aae3427d8a30 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 10 Mar 2023 13:59:49 -0500 Subject: [PATCH 087/220] 2.14.2 - Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and weather. Any activity found with GPS data will override this location. This should fix many "gps?" error. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. - Added BodyBattery as a datafield to the Forerunner 55 --- README.md | 4 ++++ resources-ces/strings/strings.xml | 2 ++ resources-dan/strings/strings.xml | 2 ++ resources-deu/strings/strings.xml | 2 ++ resources-dut/strings/strings.xml | 2 ++ resources-fin/strings/strings.xml | 2 ++ resources-fr55/settings/settings.xml | 9 ++++++--- resources-fre/strings/strings.xml | 2 ++ resources-hrv/strings/strings.xml | 2 ++ resources-hun/strings/strings.xml | 2 ++ resources-ita/strings/strings.xml | 2 ++ resources-kor/strings/strings.xml | 2 ++ resources-nob/strings/strings.xml | 2 ++ resources-pol/strings/strings.xml | 2 ++ resources-por/strings/strings.xml | 2 ++ resources-rus/strings/strings.xml | 2 ++ resources-slo/strings/strings.xml | 2 ++ resources-slv/strings/strings.xml | 2 ++ resources-spa/strings/strings.xml | 2 ++ resources-swe/strings/strings.xml | 2 ++ resources-zhs/strings/strings.xml | 2 ++ resources-zht/strings/strings.xml | 2 ++ resources/settings/properties.xml | 6 ++++-- resources/settings/settings.xml | 8 ++++++++ resources/strings/strings.xml | 2 ++ source/CrystalApp.mc | 7 ++++--- 26 files changed, 68 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a46ee06e..e3278042 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.14.2 +- Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and weather. Any activity found with GPS data will override this location. This should fix many "gps?" error. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. +- Added BodyBattery as a datafield to the Forerunner 55 + ### 2.14.1 - Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 (first 454x454 watch) - Added BodyBattery to the Forerunner 55 diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index eda7fe69..2f43b468 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -121,4 +121,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index cc821719..6a994772 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -121,4 +121,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 59009690..1d06ba13 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -121,4 +121,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 8ffe622f..b00c3970 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -121,4 +121,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index bbe660f2..53fbb1a5 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-fr55/settings/settings.xml b/resources-fr55/settings/settings.xml index 2a880759..3eddd2bf 100644 --- a/resources-fr55/settings/settings.xml +++ b/resources-fr55/settings/settings.xml @@ -48,7 +48,7 @@ - + @Strings.HeartRate @@ -65,10 +65,11 @@ @Strings.SunriseSunset + @Strings.BodyBattery - + @Strings.HeartRate @@ -85,10 +86,11 @@ @Strings.SunriseSunset + @Strings.BodyBattery - + @Strings.HeartRate @@ -105,6 +107,7 @@ @Strings.SunriseSunset + @Strings.BodyBattery diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 9794b676..be440831 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -120,4 +120,6 @@ Remplacement du thème par RGB En hexadécimal en utilisant ce format RRGGBB. Si celui-ci est différent de 0, c'est cette combinaison de couleurs qui sera utilisée à la place du thème Remplacement du thème Clair + Latitude + Longitude diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 0db327fe..39855e7d 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index bdde75e4..81692661 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 2ca1f855..e00c2773 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index a7a91a86..4c3165af 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 7c1c80eb..451540fa 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index c5809ced..0578bb30 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -121,4 +121,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index f6117501..96c701f7 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index f79d0a02..c22f4a48 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -121,4 +121,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index e053c768..99b58ca0 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 6184937f..c27ad3d2 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 8725bd58..411de0e7 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 3afbec27..98de12e6 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -121,4 +121,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index dc09b82b..5e9581fd 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 57df4cc9..f8245d42 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -122,4 +122,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 541cbe31..9307e2a5 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,6 +1,6 @@ - 2.14.0 + 2.14.2 0 @@ -33,10 +33,12 @@ true 3268578d0f3633073e62b3d8a560a09a + + + owner-api.teslamotors.com auth.tesla.com - diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 08fce606..e10e1cb6 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -237,6 +237,14 @@ + + + + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 1dab0c0c..dcfe98fc 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -121,5 +121,7 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override + Latitude + Longitude diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 876d1cfd..5bc7d8db 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -79,6 +79,7 @@ class CrystalApp extends App.AppBase { function checkPendingWebRequests() { // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. + var location = Activity.getActivityInfo().currentLocation; if (location) { location = location.toDegrees(); // Array of Doubles. @@ -93,12 +94,12 @@ class CrystalApp extends App.AppBase { } else { var lat = getProperty("LastLocationLat"); if (lat != null) { - gLocationLat = lat; + gLocationLat = lat.toFloat(); } var lng = getProperty("LastLocationLng"); if (lng != null) { - gLocationLng = lng; + gLocationLng = lng.toFloat(); } } @@ -333,7 +334,7 @@ class CrystalApp extends App.AppBase { setProperty(type, storedData); checkPendingWebRequests(); // We just got new data, process them right away before displaying - } + } Ui.requestUpdate(); } From d37f59a814b40ae9b7d168976262b9c0f6e08a14 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 10 Mar 2023 23:50:23 -0500 Subject: [PATCH 088/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e3278042..23bc3acd 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.14.2 -- Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and weather. Any activity found with GPS data will override this location. This should fix many "gps?" error. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. +- Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. - Added BodyBattery as a datafield to the Forerunner 55 ### 2.14.1 From 455cc068084449aa0a5ac0eaef34883c60a70def Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 11 Mar 2023 12:19:44 -0500 Subject: [PATCH 089/220] Increased time for for 454x454 watch and check for phone connection to gray out weather icon --- README.md | 4 +- .../fonts/titillium-web-semibold-28-chars.txt | 4 +- .../fonts/titillium-web-semibold-28.bmfc | 7 +- .../fonts/titillium-web-semibold-28.fnt | 228 +++++++++++------- .../fonts/titillium-web-semibold-28_0.png | Bin 9963 -> 10137 bytes resources-round-454x454/fonts/fonts.xml | 4 +- .../fonts/titillium-web-bold-128-tall.bmfc | 59 +++++ .../fonts/titillium-web-bold-128-tall.fnt | 15 ++ .../fonts/titillium-web-bold-128-tall_0.png | Bin 0 -> 3642 bytes .../fonts/titillium-web-bold-128-tall_1.png | Bin 0 -> 863 bytes .../fonts/titillium-web-light-128-tall.bmfc | 59 +++++ .../fonts/titillium-web-light-128-tall.fnt | 15 ++ .../fonts/titillium-web-light-128-tall_0.png | Bin 0 -> 3642 bytes .../fonts/titillium-web-light-128-tall_1.png | Bin 0 -> 863 bytes source/BackgroundService.mc | 15 +- source/CrystalApp.mc | 7 +- source/DataFields.mc | 13 +- 17 files changed, 322 insertions(+), 108 deletions(-) create mode 100644 resources-round-454x454/fonts/titillium-web-bold-128-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-bold-128-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-bold-128-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-bold-128-tall_1.png create mode 100644 resources-round-454x454/fonts/titillium-web-light-128-tall.bmfc create mode 100644 resources-round-454x454/fonts/titillium-web-light-128-tall.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-light-128-tall_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-light-128-tall_1.png diff --git a/README.md b/README.md index 23bc3acd..67c8a18c 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.14.2 -- Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. +- Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no actvity with GPS have been found to locate your position. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. +- The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happems, the temperature or humidity value displayed will be staled. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpfull at determing the reason of the failure. - Added BodyBattery as a datafield to the Forerunner 55 +- Increased the time font for the 454x454 devices ### 2.14.1 - Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 (first 454x454 watch) diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28-chars.txt b/resources-round-280x280/fonts/titillium-web-semibold-28-chars.txt index 7aff41ce..fbae0607 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28-chars.txt +++ b/resources-round-280x280/fonts/titillium-web-semibold-28-chars.txt @@ -1,5 +1,5 @@ 0123456789AP 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÁÄÅÉÍÖØÚČĚŘŚŠŹŽ AP -%-.0123456789!:?CFabefgikmpsty° - %',-.0123456789!:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz°ÅÍÎÖáãäåæèéíðñóôöøûüž \ No newline at end of file +%/-.0123456789!:?CFabefgikmpsty° + %/',-.0123456789!:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz°ÅÍÎÖáãäåæèéíðñóôöøûüž \ No newline at end of file diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc b/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc index 39bd411f..9db8fab1 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc +++ b/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc @@ -37,7 +37,7 @@ widthPaddingFactor=0.00 outWidth=256 outHeight=256 outBitDepth=8 -fontDescFormat=0 +fontDescFormat=1 fourChnlPacked=0 textureFormat=png textureCompression=0 @@ -54,8 +54,7 @@ invB=0 outlineThickness=0 # selected chars -chars=32-33,37,39,44-46,48-58,63,65-90,97-122,176,193,196-197,201,205-206,214,216,218-219,225,227-230 -chars=232-233,237,240-241,243-244,246,248,251-252,268,282,344,346,352,377,381-382,8304,8308-8309,8311 -chars=8312-8313 +chars=32-33,37,39,44-58,63,65-90,97-122,176,193,196-197,201,205-206,214,216,218-219,225,227-230,232-233 +chars=237,240-241,243-244,246,248,251-252,268,282,344,346,352,377,381-382,8304,8308-8309,8311-8313 # imported icon images diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt index 7c12b17b..f482f1be 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt +++ b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt @@ -1,120 +1,122 @@ info face="Titillium Web SemiBold" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=43 base=32 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-semibold-28_0.png" -chars count=112 +chars count=113 char id=32 x=252 y=0 width=3 height=1 xoffset=-1 yoffset=42 xadvance=6 page=0 chnl=15 -char id=33 x=191 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=33 x=246 y=50 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=37 x=18 y=53 width=16 height=21 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 -char id=39 x=251 y=92 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 -char id=44 x=47 y=134 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 -char id=45 x=60 y=134 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 -char id=46 x=54 y=134 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 -char id=48 x=123 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=49 x=240 y=92 width=10 height=19 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 -char id=50 x=225 y=92 width=14 height=19 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=51 x=77 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=52 x=209 y=92 width=15 height=19 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=53 x=62 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=54 x=224 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=55 x=122 y=94 width=13 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=56 x=106 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=57 x=208 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=58 x=230 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 -char id=63 x=178 y=93 width=12 height=20 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 -char id=65 x=18 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 -char id=66 x=89 y=73 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=67 x=84 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=68 x=72 y=73 width=16 height=20 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=69 x=47 y=96 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=70 x=32 y=96 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=71 x=68 y=51 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=72 x=36 y=75 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 -char id=73 x=203 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 +char id=39 x=251 y=112 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 +char id=44 x=65 y=132 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 +char id=45 x=78 y=132 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 +char id=46 x=72 y=132 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 +char id=47 x=173 y=50 width=12 height=21 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 +char id=48 x=145 y=72 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=49 x=245 y=92 width=10 height=19 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 +char id=50 x=0 y=119 width=14 height=19 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=51 x=79 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=52 x=229 y=93 width=15 height=19 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=53 x=109 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=54 x=230 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=55 x=182 y=93 width=13 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=56 x=128 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=57 x=32 y=96 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=58 x=245 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 +char id=63 x=210 y=93 width=12 height=20 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 +char id=65 x=40 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 +char id=66 x=213 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=67 x=114 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=68 x=179 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=69 x=124 y=94 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=70 x=139 y=94 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=71 x=52 y=51 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=72 x=58 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 +char id=73 x=248 y=27 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 char id=74 x=240 y=27 width=7 height=22 xoffset=0 yoffset=12 xadvance=8 page=0 chnl=15 -char id=75 x=16 y=98 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 -char id=76 x=136 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=13 page=0 chnl=15 -char id=77 x=233 y=50 width=21 height=20 xoffset=1 yoffset=12 xadvance=24 page=0 chnl=15 -char id=78 x=54 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 +char id=75 x=48 y=96 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 +char id=76 x=154 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=13 page=0 chnl=15 +char id=77 x=0 y=77 width=21 height=20 xoffset=1 yoffset=12 xadvance=24 page=0 chnl=15 +char id=78 x=76 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 char id=79 x=0 y=55 width=17 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=80 x=191 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=81 x=9 y=28 width=17 height=24 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=82 x=174 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=83 x=52 y=51 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=84 x=0 y=98 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=80 x=162 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=81 x=27 y=28 width=17 height=24 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 +char id=82 x=196 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=83 x=68 y=51 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=84 x=16 y=98 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 char id=85 x=35 y=53 width=16 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=86 x=0 y=77 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 -char id=87 x=207 y=50 width=25 height=20 xoffset=0 yoffset=12 xadvance=26 page=0 chnl=15 -char id=88 x=157 y=72 width=16 height=20 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 -char id=89 x=140 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=90 x=240 y=71 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=97 x=64 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 +char id=86 x=22 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 +char id=87 x=220 y=50 width=25 height=20 xoffset=0 yoffset=12 xadvance=26 page=0 chnl=15 +char id=88 x=94 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 +char id=89 x=111 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=90 x=0 y=98 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=97 x=79 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 char id=98 x=99 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=99 x=93 y=115 width=12 height=16 xoffset=0 yoffset=17 xadvance=12 page=0 chnl=15 +char id=99 x=108 y=115 width=12 height=16 xoffset=0 yoffset=17 xadvance=12 page=0 chnl=15 char id=100 x=129 y=51 width=14 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 char id=101 x=49 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 -char id=102 x=186 y=50 width=10 height=21 xoffset=0 yoffset=11 xadvance=10 page=0 chnl=15 +char id=102 x=199 y=50 width=10 height=21 xoffset=0 yoffset=11 xadvance=10 page=0 chnl=15 char id=103 x=61 y=28 width=15 height=22 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=104 x=150 y=94 width=13 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=105 x=197 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=104 x=168 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=105 x=223 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=106 x=117 y=0 width=8 height=27 xoffset=-2 yoffset=12 xadvance=7 page=0 chnl=15 -char id=107 x=164 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=14 page=0 chnl=15 -char id=108 x=248 y=27 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 -char id=109 x=106 y=115 width=21 height=15 xoffset=1 yoffset=17 xadvance=23 page=0 chnl=15 -char id=110 x=142 y=115 width=13 height=15 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=111 x=34 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=112 x=144 y=50 width=14 height=21 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=113 x=114 y=51 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=114 x=156 y=115 width=9 height=15 xoffset=1 yoffset=17 xadvance=10 page=0 chnl=15 -char id=115 x=79 y=115 width=13 height=16 xoffset=0 yoffset=17 xadvance=13 page=0 chnl=15 -char id=116 x=0 y=119 width=10 height=19 xoffset=0 yoffset=14 xadvance=10 page=0 chnl=15 -char id=117 x=128 y=115 width=13 height=15 xoffset=1 yoffset=18 xadvance=15 page=0 chnl=15 -char id=118 x=188 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 -char id=119 x=166 y=114 width=21 height=14 xoffset=0 yoffset=18 xadvance=22 page=0 chnl=15 -char id=120 x=203 y=114 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=121 x=92 y=94 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 -char id=122 x=217 y=112 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=176 x=36 y=134 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 -char id=193 x=144 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 -char id=196 x=126 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 -char id=197 x=27 y=28 width=17 height=24 xoffset=0 yoffset=8 xadvance=17 page=0 chnl=15 -char id=201 x=211 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 +char id=107 x=196 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=14 page=0 chnl=15 +char id=108 x=246 y=71 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=109 x=121 y=115 width=21 height=15 xoffset=1 yoffset=17 xadvance=23 page=0 chnl=15 +char id=110 x=143 y=115 width=13 height=15 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 +char id=111 x=64 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=112 x=84 y=51 width=14 height=21 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 +char id=113 x=144 y=50 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=114 x=171 y=114 width=9 height=15 xoffset=1 yoffset=17 xadvance=10 page=0 chnl=15 +char id=115 x=94 y=115 width=13 height=16 xoffset=0 yoffset=17 xadvance=13 page=0 chnl=15 +char id=116 x=15 y=119 width=10 height=19 xoffset=0 yoffset=14 xadvance=10 page=0 chnl=15 +char id=117 x=157 y=114 width=13 height=15 xoffset=1 yoffset=18 xadvance=15 page=0 chnl=15 +char id=118 x=203 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=119 x=181 y=114 width=21 height=14 xoffset=0 yoffset=18 xadvance=22 page=0 chnl=15 +char id=120 x=218 y=114 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=121 x=64 y=94 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=122 x=232 y=113 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=176 x=54 y=134 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 +char id=193 x=126 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 +char id=196 x=144 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 +char id=197 x=9 y=28 width=17 height=24 xoffset=0 yoffset=8 xadvance=17 page=0 chnl=15 +char id=201 x=226 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 char id=205 x=0 y=28 width=8 height=26 xoffset=0 yoffset=6 xadvance=8 page=0 chnl=15 char id=206 x=241 y=0 width=10 height=26 xoffset=-1 yoffset=6 xadvance=8 page=0 chnl=15 char id=214 x=0 y=0 width=17 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 char id=216 x=18 y=0 width=17 height=27 xoffset=1 yoffset=9 xadvance=18 page=0 chnl=15 -char id=218 x=53 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=219 x=36 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=225 x=107 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=227 x=92 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=228 x=77 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=229 x=197 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=230 x=11 y=119 width=22 height=16 xoffset=0 yoffset=17 xadvance=22 page=0 chnl=15 -char id=232 x=182 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=233 x=167 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=237 x=197 y=50 width=9 height=21 xoffset=0 yoffset=11 xadvance=7 page=0 chnl=15 +char id=218 x=36 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=219 x=53 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=225 x=197 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=227 x=182 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=228 x=122 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=229 x=107 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=230 x=26 y=119 width=22 height=16 xoffset=0 yoffset=17 xadvance=22 page=0 chnl=15 +char id=232 x=92 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=233 x=77 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=237 x=210 y=50 width=9 height=21 xoffset=0 yoffset=11 xadvance=7 page=0 chnl=15 char id=240 x=45 y=28 width=15 height=22 xoffset=0 yoffset=11 xadvance=16 page=0 chnl=15 char id=241 x=159 y=50 width=13 height=21 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 -char id=243 x=152 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=244 x=137 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=246 x=122 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=248 x=107 y=94 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 -char id=251 x=226 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 -char id=252 x=212 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 +char id=243 x=137 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=244 x=152 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=246 x=167 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=248 x=94 y=94 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 +char id=251 x=212 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 +char id=252 x=226 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 char id=268 x=102 y=0 width=14 height=27 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 -char id=282 x=226 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 +char id=282 x=211 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 char id=344 x=162 y=0 width=16 height=26 xoffset=1 yoffset=6 xadvance=17 page=0 chnl=15 char id=346 x=86 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=352 x=70 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=377 x=195 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=381 x=179 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 -char id=382 x=173 y=50 width=12 height=21 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 -char id=8304 x=236 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8308 x=245 y=112 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8309 x=0 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8311 x=9 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8312 x=18 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8313 x=27 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -kernings count=475 +char id=382 x=186 y=50 width=12 height=21 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 +char id=8304 x=0 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8308 x=9 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8309 x=18 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8311 x=27 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8312 x=36 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8313 x=45 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +kernings count=518 +kerning first=39 second=47 amount=-2 kerning first=44 second=86 amount=-1 kerning first=44 second=118 amount=-1 kerning first=45 second=86 amount=-1 @@ -122,12 +124,45 @@ kerning first=45 second=88 amount=-1 kerning first=45 second=120 amount=-1 kerning first=46 second=86 amount=-1 kerning first=46 second=118 amount=-1 +kerning first=47 second=47 amount=-8 +kerning first=47 second=65 amount=-1 +kerning first=47 second=97 amount=-1 +kerning first=47 second=99 amount=-1 +kerning first=47 second=100 amount=-1 +kerning first=47 second=101 amount=-1 +kerning first=47 second=103 amount=-1 +kerning first=47 second=109 amount=-1 +kerning first=47 second=110 amount=-1 +kerning first=47 second=111 amount=-1 +kerning first=47 second=112 amount=-1 +kerning first=47 second=113 amount=-1 +kerning first=47 second=114 amount=-1 +kerning first=47 second=115 amount=-1 +kerning first=47 second=117 amount=-1 +kerning first=47 second=193 amount=-1 +kerning first=47 second=196 amount=-1 +kerning first=47 second=197 amount=-1 +kerning first=47 second=225 amount=-1 +kerning first=47 second=227 amount=-1 +kerning first=47 second=228 amount=-1 +kerning first=47 second=229 amount=-1 +kerning first=47 second=230 amount=-1 +kerning first=47 second=232 amount=-1 +kerning first=47 second=233 amount=-1 +kerning first=47 second=241 amount=-1 +kerning first=47 second=243 amount=-1 +kerning first=47 second=244 amount=-1 +kerning first=47 second=246 amount=-1 +kerning first=47 second=248 amount=-1 +kerning first=47 second=251 amount=-1 +kerning first=47 second=252 amount=-1 kerning first=65 second=63 amount=-1 kerning first=65 second=86 amount=-1 kerning first=66 second=89 amount=-1 kerning first=68 second=88 amount=-1 kerning first=70 second=44 amount=-2 kerning first=70 second=46 amount=-2 +kerning first=70 second=47 amount=-1 kerning first=70 second=65 amount=-1 kerning first=70 second=97 amount=-1 kerning first=70 second=100 amount=-1 @@ -152,12 +187,14 @@ kerning first=76 second=118 amount=-1 kerning first=79 second=88 amount=-1 kerning first=80 second=44 amount=-2 kerning first=80 second=46 amount=-2 +kerning first=80 second=47 amount=-1 kerning first=80 second=65 amount=-1 kerning first=80 second=89 amount=-1 kerning first=80 second=193 amount=-1 kerning first=80 second=196 amount=-1 kerning first=80 second=197 amount=-1 kerning first=81 second=88 amount=-1 +kerning first=84 second=47 amount=-1 kerning first=84 second=118 amount=-2 kerning first=84 second=120 amount=-2 kerning first=84 second=227 amount=-2 @@ -166,6 +203,7 @@ kerning first=84 second=240 amount=-1 kerning first=86 second=44 amount=-1 kerning first=86 second=45 amount=-1 kerning first=86 second=46 amount=-1 +kerning first=86 second=47 amount=-1 kerning first=86 second=65 amount=-1 kerning first=86 second=74 amount=-1 kerning first=86 second=97 amount=-1 @@ -199,6 +237,7 @@ kerning first=86 second=246 amount=-1 kerning first=86 second=248 amount=-1 kerning first=86 second=251 amount=-1 kerning first=86 second=252 amount=-1 +kerning first=87 second=47 amount=-1 kerning first=88 second=45 amount=-1 kerning first=88 second=71 amount=-1 kerning first=88 second=79 amount=-1 @@ -223,6 +262,7 @@ kerning first=88 second=246 amount=-1 kerning first=88 second=248 amount=-1 kerning first=88 second=251 amount=-1 kerning first=88 second=252 amount=-1 +kerning first=89 second=47 amount=-2 kerning first=89 second=102 amount=-1 kerning first=89 second=118 amount=-1 kerning first=89 second=120 amount=-1 @@ -237,6 +277,7 @@ kerning first=101 second=86 amount=-1 kerning first=102 second=44 amount=-1 kerning first=102 second=45 amount=-1 kerning first=102 second=46 amount=-1 +kerning first=102 second=47 amount=-1 kerning first=102 second=65 amount=-1 kerning first=102 second=193 amount=-1 kerning first=102 second=196 amount=-1 @@ -253,12 +294,14 @@ kerning first=112 second=63 amount=-1 kerning first=112 second=86 amount=-1 kerning first=112 second=88 amount=-1 kerning first=113 second=86 amount=-1 +kerning first=114 second=47 amount=-1 kerning first=114 second=88 amount=-1 kerning first=114 second=240 amount=-1 kerning first=115 second=86 amount=-1 kerning first=117 second=86 amount=-1 kerning first=118 second=44 amount=-1 kerning first=118 second=46 amount=-1 +kerning first=118 second=47 amount=-1 kerning first=118 second=74 amount=-1 kerning first=118 second=84 amount=-2 kerning first=118 second=88 amount=-1 @@ -267,6 +310,7 @@ kerning first=119 second=88 amount=-1 kerning first=120 second=45 amount=-1 kerning first=120 second=84 amount=-2 kerning first=120 second=89 amount=-1 +kerning first=121 second=47 amount=-1 kerning first=121 second=88 amount=-1 kerning first=193 second=63 amount=-1 kerning first=193 second=86 amount=-1 diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28_0.png b/resources-round-280x280/fonts/titillium-web-semibold-28_0.png index dd7412cccdc7dd9cf3fa3bfb50c3f0193da499ff..e33bef1716100fc2aef5adca8809f95eda60350b 100644 GIT binary patch literal 10137 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 O0eNXGqh literal 9963 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 A8UO$Q diff --git a/resources-round-454x454/fonts/fonts.xml b/resources-round-454x454/fonts/fonts.xml index d90b563b..7913175a 100644 --- a/resources-round-454x454/fonts/fonts.xml +++ b/resources-round-454x454/fonts/fonts.xml @@ -1,6 +1,6 @@ - - + + diff --git a/resources-round-454x454/fonts/titillium-web-bold-128-tall.bmfc b/resources-round-454x454/fonts/titillium-web-bold-128-tall.bmfc new file mode 100644 index 00000000..863d6f9e --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-bold-128-tall.bmfc @@ -0,0 +1,59 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web SemiBold +fontFile= +charSet=0 +fontSize=-128 +aa=2 +scaleH=105 +useSmoothing=1 +isBold=1 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 +widthPaddingFactor=0.00 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-round-454x454/fonts/titillium-web-bold-128-tall.fnt b/resources-round-454x454/fonts/titillium-web-bold-128-tall.fnt new file mode 100644 index 00000000..da3e0ce2 --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-bold-128-tall.fnt @@ -0,0 +1,15 @@ +info face="Titillium Web SemiBold" size=-128 bold=1 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=205 base=153 scaleW=256 scaleH=256 pages=2 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-bold-128-tall_0.png" +page id=1 file="titillium-web-bold-128-tall_1.png" +chars count=10 +char id=48 x=0 y=0 width=64 height=92 xoffset=4 yoffset=62 xadvance=71 page=0 chnl=15 +char id=49 x=63 y=0 width=41 height=89 xoffset=11 yoffset=64 xadvance=71 page=1 chnl=15 +char id=50 x=57 y=93 width=54 height=91 xoffset=9 yoffset=62 xadvance=71 page=0 chnl=15 +char id=51 x=0 y=93 width=56 height=92 xoffset=8 yoffset=62 xadvance=71 page=0 chnl=15 +char id=52 x=0 y=0 width=62 height=89 xoffset=5 yoffset=64 xadvance=71 page=1 chnl=15 +char id=53 x=112 y=93 width=58 height=90 xoffset=7 yoffset=64 xadvance=71 page=0 chnl=15 +char id=54 x=130 y=0 width=62 height=92 xoffset=5 yoffset=62 xadvance=71 page=0 chnl=15 +char id=55 x=171 y=93 width=54 height=90 xoffset=9 yoffset=64 xadvance=71 page=0 chnl=15 +char id=56 x=65 y=0 width=64 height=92 xoffset=4 yoffset=62 xadvance=71 page=0 chnl=15 +char id=57 x=193 y=0 width=62 height=92 xoffset=4 yoffset=62 xadvance=71 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/titillium-web-bold-128-tall_0.png b/resources-round-454x454/fonts/titillium-web-bold-128-tall_0.png new file mode 100644 index 0000000000000000000000000000000000000000..d371fd516dd8bac460321dbb4e991d796d873f6b GIT binary patch literal 3642 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 literal 0 HcmV?d00001 diff --git a/resources-round-454x454/fonts/titillium-web-light-128-tall.bmfc b/resources-round-454x454/fonts/titillium-web-light-128-tall.bmfc new file mode 100644 index 00000000..769c9018 --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-light-128-tall.bmfc @@ -0,0 +1,59 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web SemiBold +fontFile= +charSet=0 +fontSize=-128 +aa=2 +scaleH=105 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 +widthPaddingFactor=0.00 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-round-454x454/fonts/titillium-web-light-128-tall.fnt b/resources-round-454x454/fonts/titillium-web-light-128-tall.fnt new file mode 100644 index 00000000..ad7cee05 --- /dev/null +++ b/resources-round-454x454/fonts/titillium-web-light-128-tall.fnt @@ -0,0 +1,15 @@ +info face="Titillium Web SemiBold" size=-128 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=205 base=153 scaleW=256 scaleH=256 pages=2 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-light-128-tall_0.png" +page id=1 file="titillium-web-light-128-tall_1.png" +chars count=10 +char id=48 x=0 y=0 width=64 height=92 xoffset=4 yoffset=62 xadvance=71 page=0 chnl=15 +char id=49 x=63 y=0 width=41 height=89 xoffset=11 yoffset=64 xadvance=71 page=1 chnl=15 +char id=50 x=57 y=93 width=54 height=91 xoffset=9 yoffset=62 xadvance=71 page=0 chnl=15 +char id=51 x=0 y=93 width=56 height=92 xoffset=8 yoffset=62 xadvance=71 page=0 chnl=15 +char id=52 x=0 y=0 width=62 height=89 xoffset=5 yoffset=64 xadvance=71 page=1 chnl=15 +char id=53 x=112 y=93 width=58 height=90 xoffset=7 yoffset=64 xadvance=71 page=0 chnl=15 +char id=54 x=130 y=0 width=62 height=92 xoffset=5 yoffset=62 xadvance=71 page=0 chnl=15 +char id=55 x=171 y=93 width=54 height=90 xoffset=9 yoffset=64 xadvance=71 page=0 chnl=15 +char id=56 x=65 y=0 width=64 height=92 xoffset=4 yoffset=62 xadvance=71 page=0 chnl=15 +char id=57 x=193 y=0 width=62 height=92 xoffset=4 yoffset=62 xadvance=71 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/titillium-web-light-128-tall_0.png b/resources-round-454x454/fonts/titillium-web-light-128-tall_0.png new file mode 100644 index 0000000000000000000000000000000000000000..d371fd516dd8bac460321dbb4e991d796d873f6b GIT binary patch literal 3642 zcmb`Kbzjqs!$!XgaKuQ7fzk|+ZloCqqof2xKm=)rl+rO`N=P}Sm6lTJuAxYmw2T;1 zN|%6y{O;#HJl7xRb6&!^VvX zAPRBzGenT!DtZNPWAwi*g%(MLxnyHJ*3`B5A1)vfj#|>qZ0t3Tb_7U+y*d9bwK>BS zq|Xa4LNE7|`B!{T@vK6e^cRn@rX;!&8Sg?3*`=!sPqwlY{YZ?V_Sp=zNTLc%R00kHgTkgWpDeu}my0keNi@KdFRu0!2Fx6rS{b zVv)eL5%(|#{@(A4R`ii(A7Fbt%Kz}BjG=1)Rvd_twMrGZ@(B%;aKOcsXxr~P(1%;y z0-U>P--dib2QqPIhNR_0*3Sj80QX_U`Ujq#q^FZMbirP2y2NZA`EpiPDnNaq@Qc9- z*YOlO4!u0l0wD}i;n7GveB(7B{}2O1>F*~&0qd&ee3Be3#>P=@{=D3DifhqTY-j@( z>f$48k*UWA#d!!8;!1>lWSt(4nq8`3OI`jzbMAXFwqD6~`NRTK*^_$M(&Fd1D`(Ej z-{D&(mcwiod(!-1w~?dN0x(E$+%nHL&`On-NH*Jlqou5Co20)ozXDfZN8-4sjt0{CA?9vLMtUkoElj-Z zG!W%xS{xY&o25=DV!nYzJ~(4Pdyj|>R%Fr11f9-2qS{U~QqkBKh5N7%J$y-Kvqp(SZ61DuH`Do49-mo$2C>Za4jBeim@rUGRP^X?tQ*{SdcLV6n8!) zcVKqruLD2IHl*>(UGD7a^{P~AU2k|U?V)bL$6716^`b{qmf27EaDB|?Me5ighpD%M zl4Ar@)*F>B!SZMVIYGXHy^)v?8{DA)*36lUp_g3&fJ9h>P+R~RJC(Q9==zmxK;H^D zFG!b5^#|2nEm+O|4xL}mM=A5rK-LnfT4qxU4cMUAJ%_S2KE4swMJ=k?N2!KovtLiK z?rEsbzmp52r;$HxiIGOhkwNvT%^y!^ojT1w90F3u_iNV36HY+j916X}73qlKcOWkg z5O%~*Y40|K{T$;Ysc&AnT4`#naVLVCPno$fXQ8YoY(!Yq)h5ME-zQBYpJ$U&Q zXt0y+gEgE<5@|7-$Qk(zV~J12W}%|?zSe|{6q`ZohHdF#@K*-83W|>i4x#BS-GaDz z`pP4Q2P8jV#X_4VyirYH;nHhTW$2=RDWl6nyn^q^(-ceo zVmV(-v{j5_>LesK4F$p9t*5fM0}0%$BG61_A^0Ca1^(~?<9U~Ck|U4qN9nTP@mTA?qmfxVP#xL#Oyj@2mQ9o6 zvaz$5n7DbS2g97Xo?PR^mx12To0nXOq9BPj6z#otgwdX3B6yF<2h;s4Az&N!y!uj3 zp`nk-G}FKO5<17ucV<&M6K1a3=pWzW-)L4p!@q<)Z5T*vhdryFPfQGr{Cm19kkryd ze-rfUBQ%PbwSyXA;cYT97a$JNwX^gB2ayk{LkskGmSd*w7v;axJO08C6y?7CCID1k z^3_(t5Ry_I(qtsx)Tk7d;ME=LG3N*A6lKdr?YqIRZ#QuqpQjWQ&w}hMXCk=*^Lgp( zwKxqVXusZOmOvM}tfVhMMqKmGJb~gG$qKZn!qXPtK3rGn4Q)Fh+N1V_oZwbk#hHBm zDmE0ut6o=Qzz~1XugvEtU96LgcwYBpK;BusRJ?#FmNn;{E3M>k2d>_w;>N~yZb;W3S(-KZs2Ix<<8nd z0wZso;&^7IBv7Th&rS-vhVlf0q#K?cAW}95Vza;~7oB7kzgtV}@>Xu;?)AJfKA~12 zFA%F?)I0Md^qczDnVDcLZJf+BFyZGM`*c`n)~boYo&pF)wo@?kq8yQQkE6HFzny;e z&xMz`2ewbxBg8$_-7%ui+9ZRCrOXWV{bFo2uUpDahUua+y{GhUn4$cf7Z404Olw}e znr(>(q_z6(yl?Nxr^cM27)s5d$?x-BYkJ2s{FK?MSN@NC8!~%#J0t;`s}$W0M82ZP ztUFCGSV1RhOe2tbPY4eon!`E1lWXBan}rBzlLL#P~)wcg8U-{}7K*-p)gts^oW+Or1ob6!5Ed zYNbLtVI483Q$ExZ*HN1^W20VNbVUg{;x&LXXlyQu#Xyc5w^M_=< zQper905ED~Z~6+6m7$OPukjuQQzbuM;?>tq{E|WB+K;L0Zkf2hL6|sba0c?5x67f0 zFR2KQR|$A!U-QgQ_B<-{;bs8FO$rjMIUaIl2%2%{>0t1+Y?OKLVsHi7wp&cZvekgG zN(8lKwd2Oei(d*=Q2wW$B_o0$y_d|szy#?v$aqJhDB{bUrn~285RafCgL^EpEx`mb zl49WMH-w;D)hWCPMgoF9_@DJRK_8_gA)|P=Hc7s^`22)@?c|Hmnd}4k!NdFVq(M;J zagXwZ+~8({KBW>d=r&q%zZV2dHcp?cyhFo{CU(G|NE&l2B3Axz&j*q?x zumCHgFgv!o8P%X|fNk;0+{y_Xbok1PPR^D|W0t7KCQdRM^a{Bxp5VuNl4neni|&En z+q*1FF_5#r5kT_(vwM12n{wM`Tm523nF!}l2^l1@;lguIGF)*_93a0gOV>X?Zp>m# zhU^kPSE=tzPap2X&05iVzpGZ%jexLItlnMQ&*IlqRnPkkU#A{tbq;-oZ^KIV_ZoC7 zUTtBZZJ4bs9)__?n&`xw`O76rg4}M2iHIg!tLVYhKmehy+h0tcDusSQd$h_rvu8OX zJmi7NF{$R$n+L#5>RT?`D&YMw5RAr*7p-U%#vWWdvq zc=dAiQCrD(Cky$Ney4}GTM6E`Cpe8xmnm498wF~ ze7!CD7`xrIkJ&a`geUm^&Mvv}G^4%a=$eLyKdXOiE8ER7E9X!1bp7L3|FU}@C{`_q zy#KFH_`)j2?#$^61s8|xmw(^8FXxuBYQakW_D%BsXYL()b^oVO#)j;Q2d8F#m)Bx^ zruWPH!NX^7k9#$6-ko+N`d`JLYQF=!IBo@4dna6ZwY`ov?XFJkW0vZlf1}PfteL$v zeaeddcq!upYZ`8CW;$e7m#MPgMcQ6_moNTxw|=NSIClE|g5Tx8#Wol#yiVI${~$scz}-(}en|Brp6vGOS%1M`~wEYsZLR~*k53MkopZ|}eCTCcwn|JZWv+q@sV znsj;<=S~)%8B5byYJ+OIzx^m>+GH0|?H2Ibw%$gxw|T$Ng{|Cs_G#RCEIyfGH}5;? zM?vh5ZR=h)3TYJGv%RJ7$0X*soAZV2n0)l05_Op6!CM?Y)+!2JGr!TN)1_+8e% zTAZi4AV<1wzBkhuncB0d_X<26!tRznHuy6~ctgt7*lm4>&ss7@mY)w|suvCj$=|qq z@4ERcGjczesD7B#u*T~3v&0`iJskq)mVO3m5i)qK=5UVl#H#f<@@@0Om|lHL{Nbro z##&M*{ZDDqi7Ubmlh$lIXgu{mFw>@2nsPu%qt9v%E|c!EoeyPly>v%4K;@>WK{%&~ zXPR(8&7lvI)#4e=7&lLKn3%Hdpk1JaSEOn8-?QPL^BsTxulCgV6?s{0WC!3kuDr>mdKI;Vst0By5=*Z=?k literal 0 HcmV?d00001 diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 6544718f..95e1393e 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -252,9 +252,18 @@ class BackgroundService extends Sys.ServiceDelegate { // HTTP error: do not save. } else { - result = { - "httpError" => responseCode - }; + result = App.getApp().getProperty("OpenWeatherMapCurrent"); + if (result) { + result["cod"] = responseCode; + } else { + result = { + "httpError" => responseCode + }; + } + + var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var dateStr = clockTime.year + " " + clockTime.month + " " + clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + Sys.println(dateStr + " : httpError=" + responseCode); } Bg.exit({ diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 5bc7d8db..8d1e9ec0 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -156,17 +156,18 @@ class CrystalApp extends App.AppBase { pendingWebRequests["OpenWeatherMapCurrent"] = true; // Successfully received weather data. } else if (owmCurrent["cod"] == 200) { - // Existing data is older than 30 mins. + // Existing data is older than 5 mins. // TODO: Consider requesting weather at sunrise/sunset to update weather icon. - if ((Time.now().value() > (owmCurrent["dt"] + 1800)) || + if ((Time.now().value() > (owmCurrent["dt"] + 300)) || // Existing data not for this location. // Not a great test, as a degree of longitude varies betwee 69 (equator) and 0 (pole) miles, but simpler than // true distance calculation. 0.02 degree of latitude is just over a mile. (((gLocationLat - owmCurrent["lat"]).abs() > 0.02) || ((gLocationLng - owmCurrent["lon"]).abs() > 0.02))) { - pendingWebRequests["OpenWeatherMapCurrent"] = true; } + } else { + pendingWebRequests["OpenWeatherMapCurrent"] = true; } } } diff --git a/source/DataFields.mc b/source/DataFields.mc index e0a94ee6..a707a2b7 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -168,6 +168,7 @@ class DataFields extends Ui.Drawable { // 1. Value: draw first, as top of text overlaps icon. var result = getValueForFieldType(fieldType); var value = result["value"]; + var stale = result["stale"]; // Optimisation: if live HR remains unavailable, skip the rest of this partial update. var isHRAvailable = isHeartRate && (value.length() != 0); @@ -201,7 +202,7 @@ class DataFields extends Ui.Drawable { // Grey out icon if no value was retrieved. // #37 Do not grey out battery icon (getValueForFieldType() returns empty string). - var colour = (value.length() == 0) ? gMeterBackgroundColour : gThemeColour; + var colour = (value.length() == 0 || stale) ? gMeterBackgroundColour : gThemeColour; // Battery. if ((fieldType == FIELD_TYPE_BATTERY) || (fieldType == FIELD_TYPE_BATTERY_HIDE_PERCENT)) { @@ -364,6 +365,7 @@ class DataFields extends Ui.Drawable { private function getValueForFieldType(type) { var result = {}; var value = ""; + var stale = false; var settings = Sys.getDeviceSettings(); @@ -645,11 +647,19 @@ class DataFields extends Ui.Drawable { value = weatherValue.format(INTEGER_FORMAT) + "%"; } + if (weather["cod"] != 200 || !settings.phoneConnected) { + stale = true; + } + // Awaiting response. } else if ((App.getApp().getProperty("PendingWebRequests") != null) && App.getApp().getProperty("PendingWebRequests")["OpenWeatherMapCurrent"] != null) { value = "..."; + + if (!settings.phoneConnected) { + stale = true; + } } break; @@ -683,6 +693,7 @@ class DataFields extends Ui.Drawable { } result["value"] = value; + result["stale"] = stale; return result; } } From 59ae4982fb2e594ac00a1f7d8ef191b80ce43a4c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 11 Mar 2023 12:24:47 -0500 Subject: [PATCH 090/220] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 67c8a18c..1940ab4a 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Reviews: - The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happems, the temperature or humidity value displayed will be staled. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpfull at determing the reason of the failure. - Added BodyBattery as a datafield to the Forerunner 55 - Increased the time font for the 454x454 devices +- Fixed the missing "/" in the floor climbs datafield for 416x416 and 454x454 devices ### 2.14.1 - Compiled with Connect IQ 4.2.1 which added the Forerunner 265, 265s and 965 (first 454x454 watch) From 7c53ca2b540624b91dd7a872e7a77ea0ed6358cb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:09:00 -0500 Subject: [PATCH 091/220] Increased 454x454 devices time and date font --- resources-round-454x454/fonts/fonts.xml | 4 +- .../fonts/titillium-web-bold-118-tall.bmfc | 55 -- .../fonts/titillium-web-bold-118-tall.fnt | 14 - .../fonts/titillium-web-bold-118-tall_0.png | Bin 7300 -> 0 bytes .../fonts/titillium-web-bold-128-tall.bmfc | 2 +- .../fonts/titillium-web-bold-128-tall.fnt | 20 +- .../fonts/titillium-web-bold-128-tall_0.png | Bin 3642 -> 3645 bytes .../fonts/titillium-web-bold-128-tall_1.png | Bin 863 -> 855 bytes .../fonts/titillium-web-light-118-tall.bmfc | 55 -- .../fonts/titillium-web-light-118-tall.fnt | 14 - .../fonts/titillium-web-light-118-tall_0.png | Bin 7656 -> 0 bytes .../fonts/titillium-web-light-128-tall.bmfc | 2 +- .../fonts/titillium-web-light-128-tall.fnt | 20 +- .../fonts/titillium-web-light-128-tall_0.png | Bin 3642 -> 3886 bytes .../fonts/titillium-web-light-128-tall_1.png | Bin 863 -> 592 bytes .../fonts/titillium-web-semibold-42.fnt | 556 -------------- .../fonts/titillium-web-semibold-42_0.png | Bin 12774 -> 0 bytes .../fonts/titillium-web-semibold-42_1.png | Bin 11167 -> 0 bytes ...42.bmfc => titillium-web-semibold-45.bmfc} | 6 +- .../fonts/titillium-web-semibold-45.fnt | 688 ++++++++++++++++++ .../fonts/titillium-web-semibold-45_0.png | Bin 0 -> 13774 bytes .../fonts/titillium-web-semibold-45_1.png | Bin 0 -> 12058 bytes 22 files changed, 717 insertions(+), 719 deletions(-) delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-bold-118-tall_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc delete mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-light-118-tall_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42.fnt delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_0.png delete mode 100644 resources-round-454x454/fonts/titillium-web-semibold-42_1.png rename resources-round-454x454/fonts/{titillium-web-semibold-42.bmfc => titillium-web-semibold-45.bmfc} (91%) create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-45.fnt create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-45_0.png create mode 100644 resources-round-454x454/fonts/titillium-web-semibold-45_1.png diff --git a/resources-round-454x454/fonts/fonts.xml b/resources-round-454x454/fonts/fonts.xml index 7913175a..d651fc57 100644 --- a/resources-round-454x454/fonts/fonts.xml +++ b/resources-round-454x454/fonts/fonts.xml @@ -1,8 +1,8 @@ - - + + diff --git a/resources-round-454x454/fonts/titillium-web-bold-118-tall.bmfc b/resources-round-454x454/fonts/titillium-web-bold-118-tall.bmfc deleted file mode 100644 index 1cc9cf97..00000000 --- a/resources-round-454x454/fonts/titillium-web-bold-118-tall.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Titillium Web -fontFile= -charSet=0 -fontSize=-118 -aa=2 -scaleH=105 -useSmoothing=1 -isBold=1 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=48-57 - -# imported icon images diff --git a/resources-round-454x454/fonts/titillium-web-bold-118-tall.fnt b/resources-round-454x454/fonts/titillium-web-bold-118-tall.fnt deleted file mode 100644 index a409cc89..00000000 --- a/resources-round-454x454/fonts/titillium-web-bold-118-tall.fnt +++ /dev/null @@ -1,14 +0,0 @@ -info face="Titillium Web" size=-118 bold=1 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=189 base=141 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="titillium-web-bold-118-tall_0.png" -chars count=10 -char id=48 x=0 y=0 width=61 height=85 xoffset=2 yoffset=57 xadvance=66 page=0 chnl=15 -char id=49 x=213 y=86 width=41 height=83 xoffset=8 yoffset=58 xadvance=66 page=0 chnl=15 -char id=50 x=110 y=86 width=51 height=84 xoffset=7 yoffset=57 xadvance=66 page=0 chnl=15 -char id=51 x=0 y=86 width=53 height=85 xoffset=6 yoffset=57 xadvance=66 page=0 chnl=15 -char id=52 x=0 y=172 width=57 height=83 xoffset=4 yoffset=58 xadvance=66 page=0 chnl=15 -char id=53 x=54 y=86 width=55 height=84 xoffset=5 yoffset=58 xadvance=66 page=0 chnl=15 -char id=54 x=123 y=0 width=59 height=85 xoffset=4 yoffset=57 xadvance=66 page=0 chnl=15 -char id=55 x=162 y=86 width=50 height=84 xoffset=8 yoffset=58 xadvance=66 page=0 chnl=15 -char id=56 x=62 y=0 width=60 height=85 xoffset=3 yoffset=57 xadvance=66 page=0 chnl=15 -char id=57 x=183 y=0 width=59 height=85 xoffset=3 yoffset=57 xadvance=66 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/titillium-web-bold-118-tall_0.png b/resources-round-454x454/fonts/titillium-web-bold-118-tall_0.png deleted file mode 100644 index 4bafb86461d423e4ad649f10cf928fc1929cca36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7300 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 literal 3642 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 delta 782 zcmcc4cAss6O1+w=i(^Q|oVRxZiyj&9G$dZVTz%A5^4-Y-|7*1i0+!53I_xL%@PGB@ z$rU0;!+27|m%NO&-gf@iM@q z;o;BfAKS`yv&_o*(>z`O_|?Dc-Uo_R3nK6T>l41Pim^L$`a;3Q^&$J^-}mmzxuvXH zu#&%hlf3_#d&geg|0$HQA-m$isoCG(h3Y|1HXy7xejg^2Z(0cUiW?|6|{1tbB^cz`SNZ z%QUz6702_10!lXD+xsuO*6XjtKek-^Htz?oCY@fzxs%0b#?o|_+MrtQZ$C`V&0^ZzT0$cKZxu_;p~Z=KMDuM-`9|4fh3 zZCu0`a`lqyAJgK+@zKwkKQO;PUa`>b(L_hp@Y) zj}89J5#Eq;HFjIy;j@;Ek>%%unCgWCLh?7(FW6NA&P}1nLnuE)vyKLt}nOra3Q4LVJDQXbTDdL$X98h!U!(_F1Ml;6EQynIzY&&Qd zXyFx^ZQA|!Z20GV$KU^}{r69q%lzTmzwL*G6&dd_Rw!d3s^9;fy854q$dBn8wJ)D% z5PBfnV2+E}{!;kDFMd(!Q$J3G#s(i}pUlW?C$6xke*W#Qx)1RmoEU(>)78&qol`;+ E00NPJ^8f$< diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc b/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc deleted file mode 100644 index f1a2adf9..00000000 --- a/resources-round-454x454/fonts/titillium-web-light-118-tall.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Titillium Web Light -fontFile= -charSet=0 -fontSize=-118 -aa=2 -scaleH=105 -useSmoothing=1 -isBold=0 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=48-57 - -# imported icon images diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt b/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt deleted file mode 100644 index 4e7a6aed..00000000 --- a/resources-round-454x454/fonts/titillium-web-light-118-tall.fnt +++ /dev/null @@ -1,14 +0,0 @@ -info face="Titillium Web Light" size=-118 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=189 base=141 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="titillium-web-light-118-tall_0.png" -chars count=10 -char id=48 x=60 y=0 width=56 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 -char id=49 x=206 y=86 width=32 height=83 xoffset=13 yoffset=58 xadvance=66 page=0 chnl=15 -char id=50 x=105 y=86 width=50 height=84 xoffset=8 yoffset=57 xadvance=66 page=0 chnl=15 -char id=51 x=0 y=86 width=51 height=85 xoffset=7 yoffset=57 xadvance=66 page=0 chnl=15 -char id=52 x=0 y=172 width=57 height=83 xoffset=4 yoffset=58 xadvance=66 page=0 chnl=15 -char id=53 x=52 y=86 width=52 height=84 xoffset=7 yoffset=58 xadvance=66 page=0 chnl=15 -char id=54 x=117 y=0 width=55 height=85 xoffset=6 yoffset=57 xadvance=66 page=0 chnl=15 -char id=55 x=156 y=86 width=49 height=84 xoffset=9 yoffset=58 xadvance=66 page=0 chnl=15 -char id=56 x=0 y=0 width=59 height=85 xoffset=3 yoffset=57 xadvance=66 page=0 chnl=15 -char id=57 x=173 y=0 width=55 height=85 xoffset=5 yoffset=57 xadvance=66 page=0 chnl=15 diff --git a/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png b/resources-round-454x454/fonts/titillium-web-light-118-tall_0.png deleted file mode 100644 index a062927290fa50a54ff6d4abe0f0d40c57f8e4f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7656 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 Xacfjo@sV=>cZ78{4K&KtuwnlLVTm;z literal 3642 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 b;woR6%dJaobl&UF0Lgl~`njxgN@xNA2*LNF delta 787 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 literal 0 HcmV?d00001 diff --git a/resources-round-454x454/fonts/titillium-web-semibold-45_1.png b/resources-round-454x454/fonts/titillium-web-semibold-45_1.png new file mode 100644 index 0000000000000000000000000000000000000000..96a819a1ddd605b6667d514fdfe299e9de6c5c28 GIT binary patch literal 12058 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 literal 0 HcmV?d00001 From 94ee8790f358e8aae0634d1692fe749beff15d0d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:10:08 -0500 Subject: [PATCH 092/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1940ab4a..fe902dcf 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Reviews: - Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no actvity with GPS have been found to locate your position. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. - The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happems, the temperature or humidity value displayed will be staled. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpfull at determing the reason of the failure. - Added BodyBattery as a datafield to the Forerunner 55 -- Increased the time font for the 454x454 devices +- Increased the time and date fonts for the 454x454 devices - Fixed the missing "/" in the floor climbs datafield for 416x416 and 454x454 devices ### 2.14.1 From 94884475682b155e8a94681425ebf7fe53feedb4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:46:13 -0500 Subject: [PATCH 093/220] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe902dcf..7894c922 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.14.2 -- Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no actvity with GPS have been found to locate your position. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. -- The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happems, the temperature or humidity value displayed will be staled. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpfull at determing the reason of the failure. +- Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no activity with GPS have been found to locate your position, yet. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. +- The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happens, the temperature or humidity value displayed will be staled. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpful at determining the reason of the failure. - Added BodyBattery as a datafield to the Forerunner 55 - Increased the time and date fonts for the 454x454 devices - Fixed the missing "/" in the floor climbs datafield for 416x416 and 454x454 devices From 8791a7393a895efd316460f8c194f59f96426e46 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 13 Mar 2023 23:40:24 -0400 Subject: [PATCH 094/220] 2.15.0 - Added Stress Level as a goal meter and datafield - Consolidated some of the watches that were missing goal meters or datafields. If you select one and get a gray icon, it means it's not available for your watch model. If there is a goal meter or datafield that your watch support but can't see it, let me know. --- README.md | 4 + resources-approachs60/settings/settings.xml | 4 +- resources-approachs62/settings/settings.xml | 4 +- resources-ces/strings/strings.xml | 1 + resources-ciq_1.x-no_hr/settings/settings.xml | 4 +- resources-ciq_1.x/settings/settings.xml | 4 +- resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fr55/settings/settings.xml | 12 ++- resources-fr735xt/settings/settings.xml | 4 +- resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-no_floors/settings/settings.xml | 8 +- resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + .../settings/properties.xml | 6 -- .../settings/settings.xml | 82 ------------------ .../settings/properties.xml | 6 -- .../settings/settings.xml | 82 ------------------ resources-round-208x208/settings/settings.xml | 4 +- .../fonts/crystal-icons-large.fnt | 5 +- .../fonts/crystal-icons-large.png | Bin 10889 -> 11546 bytes .../fonts/crystal-icons-extra-large.fnt | 3 +- .../fonts/crystal-icons-extra-large.png | Bin 7506 -> 7920 bytes resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + .../fonts/crystal-icons-small.fnt | 5 +- .../fonts/crystal-icons-small.png | Bin 5706 -> 5899 bytes resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-vivoactive/settings/settings.xml | 4 +- resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/fonts/crystal-icons.fnt | 3 +- resources/fonts/crystal-icons.png | Bin 6548 -> 6735 bytes resources/settings/properties.xml | 2 +- resources/settings/settings.xml | 9 +- resources/strings/strings.xml | 2 + source/CrystalView.mc | 24 ++++- source/DataArea.mc | 7 +- source/DataFields.mc | 22 ++++- source/GoalMeter.mc | 5 +- 49 files changed, 124 insertions(+), 211 deletions(-) delete mode 100644 resources-rectangle-240x240/settings/properties.xml delete mode 100644 resources-rectangle-240x240/settings/settings.xml delete mode 100644 resources-rectangle-320x360/settings/properties.xml delete mode 100644 resources-rectangle-320x360/settings/settings.xml diff --git a/README.md b/README.md index 7894c922..42fa5df7 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.15.0 +- Added Stress Level as a goal meter and datafield +- Consolidated some of the watches that were missing goal meters or datafields. If you select one and get a gray icon, it means it's not available for your watch model. If there is a goal meter or datafield that your watch support but can't see it, let me know. + ### 2.14.2 - Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no activity with GPS have been found to locate your position, yet. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. - The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happens, the temperature or humidity value displayed will be staled. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpful at determining the reason of the failure. diff --git a/resources-approachs60/settings/settings.xml b/resources-approachs60/settings/settings.xml index 77bce9d4..a994b1a8 100644 --- a/resources-approachs60/settings/settings.xml +++ b/resources-approachs60/settings/settings.xml @@ -7,7 +7,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -18,7 +18,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-approachs62/settings/settings.xml b/resources-approachs62/settings/settings.xml index 36351664..10fc96a2 100644 --- a/resources-approachs62/settings/settings.xml +++ b/resources-approachs62/settings/settings.xml @@ -7,7 +7,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -18,7 +18,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 2f43b468..fdd2d83c 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -123,4 +123,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-ciq_1.x-no_hr/settings/settings.xml b/resources-ciq_1.x-no_hr/settings/settings.xml index 7b2cf620..81000828 100644 --- a/resources-ciq_1.x-no_hr/settings/settings.xml +++ b/resources-ciq_1.x-no_hr/settings/settings.xml @@ -26,7 +26,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -37,7 +37,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-ciq_1.x/settings/settings.xml b/resources-ciq_1.x/settings/settings.xml index 6d8ef69b..86f08674 100644 --- a/resources-ciq_1.x/settings/settings.xml +++ b/resources-ciq_1.x/settings/settings.xml @@ -26,7 +26,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -37,7 +37,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 6a994772..a9b81af4 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -123,4 +123,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 1d06ba13..7e13bcb9 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -123,4 +123,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index b00c3970..bf7d0bc6 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -123,4 +123,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 53fbb1a5..d910f253 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-fr55/settings/settings.xml b/resources-fr55/settings/settings.xml index 3eddd2bf..9a91fb07 100644 --- a/resources-fr55/settings/settings.xml +++ b/resources-fr55/settings/settings.xml @@ -31,7 +31,8 @@ @Strings.Battery @Strings.CaloriesManualGoal @Strings.BodyBattery - @Strings.Off + @Strings.StressLevel + @Strings.Off @@ -44,7 +45,8 @@ @Strings.Battery @Strings.CaloriesManualGoal @Strings.BodyBattery - @Strings.Off + @Strings.StressLevel + @Strings.Off @@ -66,6 +68,8 @@ @Strings.BodyBattery + @Strings.RecoveryTime + @Strings.StressLevel @@ -87,6 +91,8 @@ @Strings.BodyBattery + @Strings.RecoveryTime + @Strings.StressLevel @@ -108,6 +114,8 @@ @Strings.BodyBattery + @Strings.RecoveryTime + @Strings.StressLevel diff --git a/resources-fr735xt/settings/settings.xml b/resources-fr735xt/settings/settings.xml index f96e4171..52dabaf0 100644 --- a/resources-fr735xt/settings/settings.xml +++ b/resources-fr735xt/settings/settings.xml @@ -26,7 +26,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -37,7 +37,7 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index be440831..51a15d44 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -122,4 +122,5 @@ Remplacement du thème Clair Latitude Longitude + Niveau de stress diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 39855e7d..befd6dcb 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 81692661..a3132e9a 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index e00c2773..285ecbcf 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 4c3165af..32029033 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-no_floors/settings/settings.xml b/resources-no_floors/settings/settings.xml index 4b477b96..6026ec4f 100644 --- a/resources-no_floors/settings/settings.xml +++ b/resources-no_floors/settings/settings.xml @@ -6,7 +6,9 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off @@ -17,7 +19,9 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off \ No newline at end of file diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 451540fa..e8f951d1 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 0578bb30..33e8f009 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -123,4 +123,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 96c701f7..fe4fcfb9 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-rectangle-240x240/settings/properties.xml b/resources-rectangle-240x240/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-rectangle-240x240/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-rectangle-240x240/settings/settings.xml b/resources-rectangle-240x240/settings/settings.xml deleted file mode 100644 index 36351664..00000000 --- a/resources-rectangle-240x240/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-rectangle-320x360/settings/properties.xml b/resources-rectangle-320x360/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-rectangle-320x360/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-rectangle-320x360/settings/settings.xml b/resources-rectangle-320x360/settings/settings.xml deleted file mode 100644 index 36351664..00000000 --- a/resources-rectangle-320x360/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-round-208x208/settings/settings.xml b/resources-round-208x208/settings/settings.xml index 447bd10b..260d467c 100644 --- a/resources-round-208x208/settings/settings.xml +++ b/resources-round-208x208/settings/settings.xml @@ -30,7 +30,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -42,7 +42,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-round-280x280/fonts/crystal-icons-large.fnt b/resources-round-280x280/fonts/crystal-icons-large.fnt index 51846a6f..2cb6e22d 100644 --- a/resources-round-280x280/fonts/crystal-icons-large.fnt +++ b/resources-round-280x280/fonts/crystal-icons-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=28 base=28 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-large.png" -chars count=22 +chars count=23 char id=48 x=0 y=0 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 char id=49 x=25 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=50 x=53 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 @@ -23,4 +23,5 @@ char id=66 x=158 y=28 width=28 height=25 xoffset=0 yoffset=0 char id=67 x=186 y=28 width=26 height=25 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=68 x=213 y=28 width=28 height=28 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=69 x=0 y=56 width=24 height=28 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 -char id=70 x=25 y=56 width=20 height=28 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 \ No newline at end of file +char id=70 x=25 y=56 width=20 height=28 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 +char id=71 x=45 y=56 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-280x280/fonts/crystal-icons-large.png b/resources-round-280x280/fonts/crystal-icons-large.png index 854a00a972e9608de2c691b70a0aa5d091ea7673..66d36a53be7bf8119823d139ef8ca4fc842b90a9 100644 GIT binary patch literal 11546 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 literal 10889 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 XRUK$>J&An}`VTcFEkuQaW$^z2)ZVuU delta 6725 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 Trs83Rfd5dEQLight theme override Latitude Longitude + Stress Level diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 99b58ca0..b152b634 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index c27ad3d2..8215a0c3 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-small-icons/fonts/crystal-icons-small.fnt b/resources-small-icons/fonts/crystal-icons-small.fnt index c901e257..9e84c667 100644 --- a/resources-small-icons/fonts/crystal-icons-small.fnt +++ b/resources-small-icons/fonts/crystal-icons-small.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-20 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=20 base=20 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-small.png" -chars count=22 +chars count=23 char id=48 x=0 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=49 x=21 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=50 x=42 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 @@ -23,4 +23,5 @@ char id=66 x=80 y=21 width=26 height=22 xoffset=0 yoffset=0 char id=67 x=106 y=21 width=24 height=20 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=68 x=133 y=21 width=21 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=69 x=154 y=21 width=17 height=20 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 -char id=70 x=172 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 \ No newline at end of file +char id=70 x=172 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 +char id=71 x=186 y=21 width=18 height=20 xoffset=0 yoffset=0 xadvance=18 page=0 chnl=15 \ No newline at end of file diff --git a/resources-small-icons/fonts/crystal-icons-small.png b/resources-small-icons/fonts/crystal-icons-small.png index 4ca84a0dcccd6d517abe9d059378c701c464011c..4d7402b46a572d1fd1c5d90467e6a070844e43d4 100644 GIT binary patch delta 4412 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 P00000NkvXXu0mjf#i2h? diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 411de0e7..dca99be5 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 98de12e6..c1bf492e 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -123,4 +123,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-vivoactive/settings/settings.xml b/resources-vivoactive/settings/settings.xml index aa368db8..e16ed122 100644 --- a/resources-vivoactive/settings/settings.xml +++ b/resources-vivoactive/settings/settings.xml @@ -29,7 +29,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off @@ -40,7 +40,7 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.Off + @Strings.Off diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 5e9581fd..0b58f125 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index f8245d42..a1a805a1 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -124,4 +124,5 @@ Light theme override Latitude Longitude + Stress Level diff --git a/resources/fonts/crystal-icons.fnt b/resources/fonts/crystal-icons.fnt index ef9dda6f..44aa33ce 100644 --- a/resources/fonts/crystal-icons.fnt +++ b/resources/fonts/crystal-icons.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-24 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=24 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons.png" -chars count=22 +chars count=23 char id=48 x=0 y=0 width=21 height=24 xoffset=1 yoffset=0 xadvance=24 page=0 chnl=15 char id=49 x=22 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=50 x=47 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 @@ -24,3 +24,4 @@ char id=67 x=169 y=27 width=24 height=22 xoffset=0 yoffset=0 char id=68 x=195 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=69 x=218 y=26 width=21 height=24 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=70 x=0 y=47 width=18 height=26 xoffset=0 yoffset=0 xadvance=18 page=0 chnl=15 +char id=71 x=17 y=48 width=22 height=24 xoffset=0 yoffset=0 xadvance=22 page=0 chnl=15 diff --git a/resources/fonts/crystal-icons.png b/resources/fonts/crystal-icons.png index 51f1d07ebcea2a3ae729552bfd71bd67bba4de9f..d4fef93913e449ba1ddabe3b4a0234b798e88398 100644 GIT binary patch delta 5806 zcmcJLWm}Yu)`o8e5Trwf7L;y~mTo0Rxn*<^Tef%X*xJm?x4MGiGDl6#w&CHqMDbcGT z4U5ESkx9RYpD>dZJ!B!H5hV&e2y*G`6To$CHm9+%v7!Lb)*K6QJ+0kSLA>#s;zc%=pf6fE;X_}nyu1X@ zH3SM5aXiQ+6YfZ3O?l$}I0hprzIuNlUcv~|IQ-@IDDD;l$`_R$B{U`e zBSd}00u)KEd$ehTLte6~4~RVtoOwP+%d|j_soF#%!eyN}8y={In{(gD)gAxg6R+>e zRR*2AdbMg$u$j^-PB2i5alvCC_cKf*D@bMtP zz&}q{7#kP_{q!Q6%3Hmq53b;|98BwGJcyOofB9%ejZ8+;HHK6}G>ZC1EQDBUaBWJm zO=U1=`C8{=ryMvL z$A@Ejtbt_2st0Vpr_BlW4tHZt>YhIqw=_+kbL4D`cL=Sn%06S%kE@y=cd8}$d= zqTXXu#^ymJ)*Co=@^i7K6Mh7749;`U^qN>PGTBfrBuhKm)*i{Qe^|aOO|W5`dSrhIgl`5yTx% z66?L}=EogzbXw1D7*Q4*x3grF%#K`fNUF_a(=b~cQv>$AomI&5(nZs$cI%7xIYYBq znH*IiN1RfRBJ8vtMrkX#V!%muV>*B^w?%U{lutJoQvE#AZ5TF6n-WOFQk)8j@^5@( zTXd+u8alu;8^6)vP8H_=-JJ#L*W;SxGE38Xl+dq%O!edbN46usTir2=dy^qqUjAH5z#}S?3Q?jXg@qil zX5L+h8jGD*Vp)vdqU`CH&M3*iE^e3XCb%xIyzE(Zq=Xhv;T}cr@_N!PQEt#-2ZZ@v zzt4u8i4e<&87b%~;SLqE%to1Wx2%y3On+0YSi#sN+kp^fNAmV6R$vdi_Q$qznV^OV zq&TBFd>R}@*uL_Ka%YiVfe+Ur7 z(SHs-K<(^;Fm!DXi5Iqf4c&6dP)!fE`RFt^gJ!k=wk3fA^Y+D&tm8!_+o{n zM(KXOIH-S#STl_v#X1Gho6hC2_av|pXKu&Jn(5s#HX63}0LQxfWZ2iVw%nHuyT0pZlrF7%#%jqwGo-#IEc@6s@r_a_^Zx&x#Do}shM7MBEm*qkNZkDju3cn zU{DS3s8DT$k26%W0#lD3^}k$eZf@pE&sN&5WXzz5OYyEct@nm=;E7UPb4aokW;r#1 zS$xShn02}j3nuc8Q;m^;0HyvXD&2z28K$&$2!`ruv48yfiR? z!&ln5s~#qjuc`lT`qiZpd#(#Gw=ylio(ZSFl6?CG2l1Qo%uo7Z8%EZ&Y>j8JN*!&i z@^q)44Qn7!s3(xKnYR^x`vE}Pg}w6`ObJ6WM3SrESqRw~E#H~d=c$ooA3cr2G^=fB zB2}tmq;OCUp+M;hD^{txx%`v2A5NQ=9bZz0yXF9eg<+saN+-IbJ>@iu1hDObFg04k zbcJ|(BDol2E6C2Az5quSwohj4eEl>Ht$#?-ICq8+4hxXRLKhP&5|jGgnrnfti_Vj0 zpKeK=EsS_d43X9bbg&H5kGL(xA;}cHdAA1tQFU`*m z1%;uR$j-~PSw*7kiPfL{5nnOpV>>C7UL(u`2O_nq1JcYmo4<}08UiL+n7;S;XQ_rm zZ$bla6*9|~cz({7`6uS!9uR;UlFwp=e8ay*8cYnjNBC`*(-ON9?T=X&^TECE`qA-^u)touZA|)>`M^R(tHW(llIrYb%iYsA?_PYM zw@C)oT<_7fwh zf$mAm^cs?#H;<3`(HV__ioq~ITZ z_s4KJuS%UkeAYi*9OW5A53Hyjf^I
S3_Ih@D`B+u_XTA$yK&u~ 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 diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 9307e2a5..ecf1d12b 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,6 +1,6 @@ - 2.14.2 + 2.15.0 0 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index e10e1cb6..3462d5aa 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -40,7 +40,8 @@ @Strings.Battery @Strings.CaloriesManualGoal @Strings.BodyBattery - @Strings.Off + @Strings.StressLevel + @Strings.Off @@ -52,7 +53,8 @@ @Strings.Battery @Strings.CaloriesManualGoal @Strings.BodyBattery - @Strings.Off + @Strings.StressLevel + @Strings.Off @@ -103,6 +105,7 @@ @Strings.SolarIntensity @Strings.BodyBattery @Strings.RecoveryTime + @Strings.StressLevel @@ -127,6 +130,7 @@ @Strings.SolarIntensity @Strings.BodyBattery @Strings.RecoveryTime + @Strings.StressLevel @@ -151,6 +155,7 @@ @Strings.SolarIntensity @Strings.BodyBattery @Strings.RecoveryTime + @Strings.StressLevel diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index dcfe98fc..7b5848fb 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -123,5 +123,7 @@ Light theme override Latitude Longitude + Longitude + Stress Level diff --git a/source/CrystalView.mc b/source/CrystalView.mc index b0b869d9..db16ac8e 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -635,8 +635,8 @@ class CrystalView extends Ui.WatchFace { values[:max] = 100; break; + // SG Addition case GOAL_TYPE_BODY_BATTERY: - // #8: floor() battery to be consistent. var bodyBattery = null; values[:isValid] = false; values[:max] = 100; @@ -657,6 +657,28 @@ class CrystalView extends Ui.WatchFace { break; + // SG Addition + case GOAL_TYPE_STRESS_LEVEL: + var stressLevel = null; + values[:isValid] = false; + values[:max] = 100; + + if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { + stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); + if (stressLevel != null) { + stressLevel = stressLevel.next(); + } + if (stressLevel !=null) { + stressLevel = stressLevel.data; + } + if (stressLevel != null && stressLevel >= 0 && stressLevel <= 100) { + values[:current] = stressLevel.toFloat(); + values[:isValid] = true; + } + } + + break; + case GOAL_TYPE_CALORIES: values[:current] = info.calories; diff --git a/source/DataArea.mc b/source/DataArea.mc index 888f0eb7..abb43761 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -41,7 +41,7 @@ class DataArea extends Ui.Drawable { if (leftValues[:isValid]) { mLeftGoalCurrent = leftValues[:current].format(INTEGER_FORMAT); - mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY) ? "%" : leftValues[:max].format(INTEGER_FORMAT); + mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY || mLeftGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { mLeftGoalCurrent = null; mLeftGoalMax = null; @@ -52,7 +52,7 @@ class DataArea extends Ui.Drawable { if (rightValues[:isValid]) { mRightGoalCurrent = rightValues[:current].format(INTEGER_FORMAT); - mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY) ? "%" : rightValues[:max].format(INTEGER_FORMAT); + mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY || mRightGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { mRightGoalCurrent = null; mRightGoalMax = null; @@ -149,7 +149,8 @@ class DataArea extends Ui.Drawable { GOAL_TYPE_STEPS => "0", GOAL_TYPE_FLOORS_CLIMBED => "1", GOAL_TYPE_ACTIVE_MINUTES => "2", - GOAL_TYPE_BODY_BATTERY => "E", + GOAL_TYPE_BODY_BATTERY => "E", // SG Addition + GOAL_TYPE_STRESS_LEVEL => "G", // SG Addition }[type]; dc.setColor(isValid ? gThemeColour : gMeterBackgroundColour, Gfx.COLOR_TRANSPARENT); diff --git a/source/DataFields.mc b/source/DataFields.mc index a707a2b7..c7a78bd3 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -34,7 +34,8 @@ enum /* FIELD_TYPES */ { FIELD_FLOOR_CLIMBED, FIELD_SOLAR_INTENSITY, FIELD_BODY_BATTERY, - FIELD_RECOVERY_TIME + FIELD_RECOVERY_TIME, + FIELD_STRESS_LEVEL } class DataFields extends Ui.Drawable { @@ -326,7 +327,8 @@ class DataFields extends Ui.Drawable { FIELD_FLOOR_CLIMBED => "1", // SG Addition FIELD_SOLAR_INTENSITY => "D", // SG Addition FIELD_BODY_BATTERY => "E", // SG Addition - FIELD_RECOVERY_TIME => "F" // SG Addition + FIELD_RECOVERY_TIME => "F", // SG Addition + FIELD_STRESS_LEVEL => "G" // SG Addition }[fieldType]; } @@ -408,6 +410,22 @@ class DataFields extends Ui.Drawable { } break; // SG Addition + case FIELD_STRESS_LEVEL: + var stressLevel = null; + if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { + stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); + if (stressLevel != null) { + stressLevel = stressLevel.next(); + } + if (stressLevel !=null) { + stressLevel = stressLevel.data; + } + if (stressLevel != null && stressLevel >= 0 && stressLevel <= 100) { + value = stressLevel.format(INTEGER_FORMAT); + } + } + break; + // SG Addition case FIELD_SOLAR_INTENSITY: var stats = Sys.getSystemStats(); if (stats has :solarIntensity) { diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index 09d2c56f..21468245 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -8,8 +8,9 @@ using Toybox.Graphics; enum /* GOAL_TYPES */ { GOAL_TYPE_BATTERY = -1, GOAL_TYPE_CALORIES = -2, - GOAL_TYPE_BODY_BATTERY = -3, - GOAL_TYPE_OFF = -4, + GOAL_TYPE_BODY_BATTERY = -3, // SG Addition + GOAL_TYPE_STRESS_LEVEL = -4, // SG Addition + GOAL_TYPE_OFF = -5, GOAL_TYPE_STEPS = 0, // App.GOAL_TYPE_STEPS GOAL_TYPE_FLOORS_CLIMBED, // App.GOAL_TYPE_FLOORS_CLIMBED From c71d2a4ce6df1df56edac5d6700ee012d9723776 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 13 Mar 2023 23:54:42 -0400 Subject: [PATCH 095/220] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 42fa5df7..afe8fd0a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Reviews: ### 2.15.0 - Added Stress Level as a goal meter and datafield - Consolidated some of the watches that were missing goal meters or datafields. If you select one and get a gray icon, it means it's not available for your watch model. If there is a goal meter or datafield that your watch support but can't see it, let me know. +- Compiled with Connect IQ 4.2.2 which I hope fixes the missing Body Battery sensor ### 2.14.2 - Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no activity with GPS have been found to locate your position, yet. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. From 95babaae974c5ed51ef557b08857b5678ebea5e5 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 14 Mar 2023 00:00:30 -0400 Subject: [PATCH 096/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index afe8fd0a..3423c34b 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Reviews: ### 2.15.0 - Added Stress Level as a goal meter and datafield - Consolidated some of the watches that were missing goal meters or datafields. If you select one and get a gray icon, it means it's not available for your watch model. If there is a goal meter or datafield that your watch support but can't see it, let me know. -- Compiled with Connect IQ 4.2.2 which I hope fixes the missing Body Battery sensor +- Compiled with Connect IQ 4.2.2 which I hope fixes the missing Body Battery sensor some are seeing ### 2.14.2 - Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no activity with GPS have been found to locate your position, yet. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. From fb03c966df6f7c38df5b6731c32ff432f26d39d4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 14 Mar 2023 20:02:52 -0400 Subject: [PATCH 097/220] 2.15.1 - Reverted to Connect IQ 4.1.7 since there are too many problem with sensors with this 4.2.x version so far. Hopefully this doesn't break the newest Forerunner 265, 265S and 965. - Moved the line between time and date in Always so it doesn't strike the time. --- README.md | 4 ++++ resources-round-454x454/layouts/layout.xml | 2 +- resources/settings/properties.xml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3423c34b..679094ba 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.15.1 +- Reverted to Connect IQ 4.1.7 since there are too many problem with sensors with this 4.2.x version so far. Hopefully this doesn't break the newest Forerunner 265, 265S and 965. +- Moved the line between time and date in Always so it doesn't strike the time. + ### 2.15.0 - Added Stress Level as a goal meter and datafield - Consolidated some of the watches that were missing goal meters or datafields. If you select one and get a gray icon, it means it's not available for your watch model. If there is a goal meter or datafield that your watch support but can't see it, let me know. diff --git a/resources-round-454x454/layouts/layout.xml b/resources-round-454x454/layouts/layout.xml index d4a1eaf4..228f14bb 100644 --- a/resources-round-454x454/layouts/layout.xml +++ b/resources-round-454x454/layouts/layout.xml @@ -67,7 +67,7 @@ [-60, -30, 30, 60] -4 195 - 221 + 241 251 diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index ecf1d12b..e48ceb0d 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,6 +1,6 @@ - 2.15.0 + 2.15.1 0 From fbb5c3a1aa86194796ec4d2fc4c20a3729fce470 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 14 Mar 2023 20:11:47 -0400 Subject: [PATCH 098/220] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 679094ba..23e94323 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.15.1 -- Reverted to Connect IQ 4.1.7 since there are too many problem with sensors with this 4.2.x version so far. Hopefully this doesn't break the newest Forerunner 265, 265S and 965. -- Moved the line between time and date in Always so it doesn't strike the time. +- Reverted to Connect IQ 4.1.7 since there are too many problem with sensors with this 4.2.x version so far. Hopefully this doesn't break the watchface on newest Forerunner 265, 265S and 965. +- Moved the line between time and date in Always On Display so it doesn't strike through the time. ### 2.15.0 - Added Stress Level as a goal meter and datafield From 693e32df0189711561651d3ca817116e866764e1 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 2 Apr 2023 16:17:30 -0400 Subject: [PATCH 099/220] 2.15.2 - Access to stress level is not as stable as the Garmin access to it. To help here, if a value isn't returned, the last good one is used and the icon is greyed out to indicate the data is stale. - Bug fix in the default latitude/longitude when the last activity has no GPS coordinates. --- README.md | 6 +- resources/settings/properties.xml | 2 +- source/CrystalApp.mc | 32 +++++-- source/CrystalView.mc | 142 ++++++++++++++++++++++++++++-- source/DataArea.mc | 12 ++- source/DataFields.mc | 9 +- 6 files changed, 175 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 23e94323..54ab9338 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.15.2 +- Access to stress level is not as stable as the Garmin access to it. To help here, if a value isn't returned, the last good one is used and the icon is greyed out to indicate the data is stale. +- Bug fix in the default latitude/longitude when the last activity has no GPS coordinates. + ### 2.15.1 - Reverted to Connect IQ 4.1.7 since there are too many problem with sensors with this 4.2.x version so far. Hopefully this doesn't break the watchface on newest Forerunner 265, 265S and 965. - Moved the line between time and date in Always On Display so it doesn't strike through the time. @@ -38,7 +42,7 @@ Reviews: ### 2.14.2 - Added Longitude and Latitude as editable fields in the parameters to allow for a DEFAULT location for sunrise/sunset and OpenWeatherMap weather . Any activity found with GPS data will override this location. This should fix many "gps?" error, which simply means no activity with GPS have been found to locate your position, yet. Keep in mind it can take up to 5 minutes before data is retrieved from OWM or Garmin Weather. -- The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happens, the temperature or humidity value displayed will be staled. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpful at determining the reason of the failure. +- The weather icon will be grayed out if the request to get the weather fails for some reason (like Bluetooth off, no Internet access or bad OWM API key). If this happens, the temperature or humidity value displayed will be stale. If you create a file called CRYSTALFACE.TXT in the /GARMIN/APPS/LOGS on your watch (connect to your computer first), it will log inside that file the error code of why it failed (unless it's because BLE is Off). This could be helpful at determining the reason of the failure. - Added BodyBattery as a datafield to the Forerunner 55 - Increased the time and date fonts for the 454x454 devices - Fixed the missing "/" in the floor climbs datafield for 416x416 and 454x454 devices diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index e48ceb0d..0fd10517 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -32,7 +32,7 @@ 0 true - 3268578d0f3633073e62b3d8a560a09a + 2651f49cb20de925fc57590709b86ce6 diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 8d1e9ec0..85b8a7cf 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -5,6 +5,10 @@ using Toybox.WatchUi as Ui; using Toybox.Time; using Toybox.Time.Gregorian; +import Toybox.Application; +import Toybox.Lang; +import Toybox.WatchUi; + // In-memory current location. // Previously persisted in App.Storage, but now persisted in Object Store due to #86 workaround for App.Storage firmware bug. // Current location retrieved/saved in checkPendingWebRequests(). @@ -35,9 +39,17 @@ class CrystalApp extends App.AppBase { // Return the initial view of your application here function getInitialView() { - mView = new CrystalView(); - onSettingsChanged(); // After creating view. - return [mView]; + /*if (WatchUi has :WatchFaceDelegate) { + mView = new CrystalView(); + onSettingsChanged(); // After creating view. + var delegate = new CrystalDelegate(mView); + return [mView, delegate] as Array; + } + else {*/ + mView = new CrystalView(); + onSettingsChanged(); // After creating view. + return [mView]; + //} } function getView() { @@ -83,15 +95,17 @@ class CrystalApp extends App.AppBase { var location = Activity.getActivityInfo().currentLocation; if (location) { location = location.toDegrees(); // Array of Doubles. - gLocationLat = location[0].toFloat(); - gLocationLng = location[1].toFloat(); - - setProperty("LastLocationLat", gLocationLat); - setProperty("LastLocationLng", gLocationLng); + if (location[0] != 0.0 && location[1] != 0.0) { + gLocationLat = location[0]; + gLocationLng = location[1]; + setProperty("LastLocationLat", gLocationLat); + setProperty("LastLocationLng", gLocationLng); + } + } // If current location is not available, read stored value from Object Store, being careful not to overwrite a valid // in-memory value with an invalid stored one. - } else { + else { var lat = getProperty("LastLocationLat"); if (lat != null) { gLocationLat = lat.toFloat(); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index db16ac8e..3c79cdeb 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -14,6 +14,9 @@ using Toybox.Math; const INTEGER_FORMAT = "%d"; +import Toybox.Lang; +import Toybox.WatchUi; + var gThemeColour; var gMonoLightColour; var gMonoDarkColour; @@ -25,6 +28,9 @@ var gMinutesColour; var gNormalFont; var gIconsFont; +var gStressLevel; +//DEBUG*/ var gStressLevelLogText; + const SCREEN_MULTIPLIER = (Sys.getDeviceSettings().screenWidth < 360) ? 1 : 2; //const BATTERY_LINE_WIDTH = 2; const BATTERY_HEAD_HEIGHT = 4 * SCREEN_MULTIPLIER; @@ -599,7 +605,8 @@ class CrystalView extends Ui.WatchFace { var values = { :current => 0, :max => 1, - :isValid => true + :isValid => true, + :staled => false }; var info = ActivityMonitor.getInfo(); @@ -637,12 +644,11 @@ class CrystalView extends Ui.WatchFace { // SG Addition case GOAL_TYPE_BODY_BATTERY: - var bodyBattery = null; values[:isValid] = false; values[:max] = 100; if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { - bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); + var bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); if (bodyBattery != null) { bodyBattery = bodyBattery.next(); } @@ -659,22 +665,116 @@ class CrystalView extends Ui.WatchFace { // SG Addition case GOAL_TYPE_STRESS_LEVEL: - var stressLevel = null; values[:isValid] = false; values[:max] = 100; +/* if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { + var stressLevelIterator; + var stressLevel = null; + + stressLevelIterator = Toybox.SensorHistory.getStressHistory({}); + if (stressLevelIterator == null) { + break; + } + + var sample = stressLevelIterator.next(); + var stressLevelDate = 0; + var count = 0; + var keptCount = 0; + while (sample != null) { + count++; + if (sample.when.value() > stressLevelDate) { + keptCount = count; + stressLevel = sample.data; + stressLevelDate = sample.when.value(); + } + sample = stressLevelIterator.next(); + } + + if (sample != null) { + stressLevel = sample.data; + stressLevelDate = sample.when.value(); + } + + if (stressLevel != null && stressLevel >= 0 && stressLevel <= 100) { + values[:current] = stressLevel.toFloat(); + values[:isValid] = true; + } +*/ + if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { - stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); + var stressLevel = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); + var stressLevelDate = 0; + if (stressLevel != null) { stressLevel = stressLevel.next(); } if (stressLevel !=null) { + stressLevelDate = stressLevel.when.value(); stressLevel = stressLevel.data; } - if (stressLevel != null && stressLevel >= 0 && stressLevel <= 100) { - values[:current] = stressLevel.toFloat(); + + if (stressLevel != null) { + if (stressLevel >= 0 && stressLevel <= 100) { + values[:current] = stressLevel.toFloat(); + values[:isValid] = true; + gStressLevel = stressLevel; + + /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); + var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); + var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + var logText = "stressLevel " + stressLevel + " stressLevelDate " + dateStr + " is GOOD"; + if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { + logMessage(logText); + gStressLevelLogText = logText; + }*/ + } else if (gStressLevel != null) { + values[:current] = gStressLevel.toFloat(); + values[:isValid] = true; + values[:staled] = true; + + /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); + var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); + var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + var logText = "stressLevel " + stressLevel + "is over limit, ignoring"; + if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { + logMessage(logText); + gStressLevelLogText = logText; + }*/ + } else { + /*DEBUG var logText = "stressLevel " + stressLevel + "is over limit and no StressHistory data found yet"; + if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { + logMessage(logText); + gStressLevelLogText = logText; + }*/ + } + } else if (gStressLevel != null) { + values[:current] = gStressLevel.toFloat(); values[:isValid] = true; + values[:staled] = true; + + /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); + var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); + var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + var logText = "stressLevel " + gStressLevel + " IS staled"; + if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { + logMessage(logText); + gStressLevelLogText = logText; + }*/ + } else { + /*DEBUG var logText = "No StressHistory data found yet"; + if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { + logMessage(logText); + gStressLevelLogText = logText; + }*/ } +// logMessage("stressLeve " + stressLevel + " count " + count + " keptCount " + keptCount + " stressLevelDate " + stressLevelDate); + } else { + /*DEBUG var logText = "No StressHistory Sensor found"; + if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { + logMessage(logText); + gStressLevelLogText = logText; + }*/ } break; @@ -795,6 +895,34 @@ class CrystalView extends Ui.WatchFace { mDrawables[:MoveBar].setFullWidth(hideSeconds); } } + +/*class CrystalDelegate extends Ui.WatchFaceDelegate { + private var _view as CrystalView; + + //! Constructor + //! @param view The analog view + public function initialize(view as CrystalView) { + WatchFaceDelegate.initialize(); + _view = view; + } + + public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { + System.println("onPress called!!!"); + } + + //! The onPowerBudgetExceeded callback is called by the system if the + //! onPartialUpdate method exceeds the allowed power budget. If this occurs, + //! the system will stop invoking onPartialUpdate each second, so we notify the + //! view here to let the rendering methods know they should not be rendering a + //! second hand. + //! @param powerInfo Information about the power budget + public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { + System.println("Average execution time: " + powerInfo.executionTimeAverage); + System.println("Allowed execution time: " + powerInfo.executionTimeLimit); +// _view.turnPartialUpdatesOff(); + } +}*/ + /* function type_name(obj) { if (obj instanceof Toybox.Lang.Number) { diff --git a/source/DataArea.mc b/source/DataArea.mc index abb43761..4dcb7258 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -12,11 +12,13 @@ class DataArea extends Ui.Drawable { private var mLeftGoalType; private var mLeftGoalIsValid; + private var mLeftGoalstaled; private var mLeftGoalCurrent; private var mLeftGoalMax; private var mRightGoalType; private var mRightGoalIsValid; + private var mRightGoalstaled; private var mRightGoalCurrent; private var mRightGoalMax; @@ -38,6 +40,7 @@ class DataArea extends Ui.Drawable { function setGoalValues(leftType, leftValues, rightType, rightValues) { mLeftGoalType = leftType; mLeftGoalIsValid = leftValues[:isValid]; + mLeftGoalstaled = leftValues[:staled]; if (leftValues[:isValid]) { mLeftGoalCurrent = leftValues[:current].format(INTEGER_FORMAT); @@ -49,6 +52,7 @@ class DataArea extends Ui.Drawable { mRightGoalType = rightType; mRightGoalIsValid = rightValues[:isValid]; + mRightGoalstaled = leftValues[:staled]; if (rightValues[:isValid]) { mRightGoalCurrent = rightValues[:current].format(INTEGER_FORMAT); @@ -60,8 +64,8 @@ class DataArea extends Ui.Drawable { } function draw(dc) { - drawGoalIcon(dc, mGoalIconLeftX, mLeftGoalType, mLeftGoalIsValid, Graphics.TEXT_JUSTIFY_LEFT); - drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, Graphics.TEXT_JUSTIFY_RIGHT); + drawGoalIcon(dc, mGoalIconLeftX, mLeftGoalType, mLeftGoalIsValid, mLeftGoalstaled, Graphics.TEXT_JUSTIFY_LEFT); + drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, mRightGoalstaled, Graphics.TEXT_JUSTIFY_RIGHT); var city = App.getApp().getProperty("LocalTimeInCity"); @@ -138,7 +142,7 @@ class DataArea extends Ui.Drawable { } } - function drawGoalIcon(dc, x, type, isValid, align) { + function drawGoalIcon(dc, x, type, isValid, staled, align) { if (type == GOAL_TYPE_OFF) { return; } @@ -153,7 +157,7 @@ class DataArea extends Ui.Drawable { GOAL_TYPE_STRESS_LEVEL => "G", // SG Addition }[type]; - dc.setColor(isValid ? gThemeColour : gMeterBackgroundColour, Gfx.COLOR_TRANSPARENT); + dc.setColor(isValid && !staled ? gThemeColour : gMeterBackgroundColour, Gfx.COLOR_TRANSPARENT); dc.drawText( x, mGoalIconY, diff --git a/source/DataFields.mc b/source/DataFields.mc index c7a78bd3..767d11d9 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -395,9 +395,8 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_BODY_BATTERY: - var bodyBattery = null; if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { - bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); + var bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); if (bodyBattery != null) { bodyBattery = bodyBattery.next(); } @@ -411,9 +410,8 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_STRESS_LEVEL: - var stressLevel = null; if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { - stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); + var stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); if (stressLevel != null) { stressLevel = stressLevel.next(); } @@ -462,8 +460,7 @@ class DataFields extends Ui.Drawable { if (sample != null) { value = sample.format(INTEGER_FORMAT); } else if (ActivityMonitor has :getHeartRateHistory) { - sample = ActivityMonitor.getHeartRateHistory(1, /* newestFirst */ true) - .next(); + sample = ActivityMonitor.getHeartRateHistory(1, true).next(); if ((sample != null) && (sample.heartRate != ActivityMonitor.INVALID_HR_SAMPLE)) { value = sample.heartRate.format(INTEGER_FORMAT); } From 09341b294afc6cdb01dd3998b5dbaa9cd62d7849 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 2 Apr 2023 17:48:57 -0400 Subject: [PATCH 100/220] 2.16.0 - Added a optional colon between hours and minutes --- README.md | 3 ++- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + .../titillium-web-bold-48-extra-tall.bmfc | 8 ++++-- .../titillium-web-bold-48-extra-tall.fnt | 24 ++++++++--------- .../titillium-web-bold-48-extra-tall_0.png | Bin 3238 -> 2299 bytes .../fonts/titillium-web-bold-74-tall.bmfc | 4 +++ .../fonts/titillium-web-light-74-tall.bmfc | 6 ++++- .../fonts/titillium-web-light-74-tall.fnt | 4 +-- .../fonts/titillium-web-light-74-tall_0.png | Bin 3691 -> 3540 bytes .../fonts/titillium-web-bold-80-tall.bmfc | 4 +++ .../fonts/titillium-web-light-80-tall.bmfc | 6 ++++- .../fonts/titillium-web-light-80-tall.fnt | 2 +- .../fonts/titillium-web-light-80-tall_0.png | Bin 3864 -> 3829 bytes .../fonts/titillium-web-bold-102-tall.bmfc | 4 +++ .../fonts/titillium-web-light-102-tall.bmfc | 6 ++++- .../fonts/titillium-web-light-102-tall.fnt | 3 ++- .../fonts/titillium-web-light-102-tall_0.png | Bin 6592 -> 6678 bytes .../fonts/titillium-web-light-110-tall.bmfc | 6 ++++- .../fonts/titillium-web-light-110-tall.fnt | 3 ++- .../fonts/titillium-web-light-110-tall_0.png | Bin 7063 -> 7158 bytes .../fonts/titillium-web-bold-118-tall.bmfc | 4 +++ .../fonts/titillium-web-light-118-tall.bmfc | 6 ++++- .../fonts/titillium-web-light-118-tall.fnt | 3 ++- .../fonts/titillium-web-light-118-tall_0.png | Bin 7656 -> 7714 bytes .../fonts/titillium-web-light-128-tall.bmfc | 2 +- .../fonts/titillium-web-light-128-tall.fnt | 3 ++- .../fonts/titillium-web-light-128-tall_0.png | Bin 3886 -> 3915 bytes resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + .../fonts/titillium-web-bold-58-tall.bmfc | 4 +++ .../fonts/titillium-web-bold-58-tall.fnt | 22 +++++++-------- .../fonts/titillium-web-bold-58-tall_0.png | Bin 3776 -> 2695 bytes .../fonts/titillium-web-light-58-tall.bmfc | 6 ++++- .../fonts/titillium-web-light-58-tall.fnt | 25 +++++++++--------- .../fonts/titillium-web-light-58-tall_0.png | Bin 3979 -> 2746 bytes resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + .../fonts/titillium-web-bold-68-tall.bmfc | 4 +++ .../fonts/titillium-web-bold-68-tall.fnt | 22 +++++++-------- .../fonts/titillium-web-bold-68-tall_0.png | Bin 4390 -> 3188 bytes .../fonts/titillium-web-light-68-tall.bmfc | 6 ++++- .../fonts/titillium-web-light-68-tall.fnt | 25 +++++++++--------- .../fonts/titillium-web-light-68-tall_0.png | Bin 4857 -> 3158 bytes resources/settings/properties.xml | 4 ++- resources/settings/settings.xml | 9 +++---- resources/strings/strings.xml | 1 + source/ThickThinTime.mc | 11 ++++++++ 62 files changed, 178 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 54ab9338..c54f0a9f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ Reviews: ## Below is what has been added by me (SylvainGa). -### 2.15.2 +### 2.16.0 +- Added a optional colon between hours and minutes - Access to stress level is not as stable as the Garmin access to it. To help here, if a value isn't returned, the last good one is used and the icon is greyed out to indicate the data is stale. - Bug fix in the default latitude/longitude when the last activity has no GPS coordinates. diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index fdd2d83c..012223dd 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index a9b81af4..9ec616c3 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 7e13bcb9..65f8b636 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Führende Nullen ausblenden + Add colon between hours and minutes OpenWeatherMap API Key Override Anzahl der Datenfelder diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index bf7d0bc6..23d80348 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Verberg Eerste Nul Bij Uren + Add colon between hours and minutes OpenWeatherMap API Key Override Hoeveelheid Datavelden diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index d910f253..21b4a938 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 51a15d44..62aad878 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -18,6 +18,7 @@ Afficher sauf quand inactif Toujours cacher Masquer le zéro avant l'heure + Ajouter un deux-points entre les heures et minutes OpenWeatherMap API Key Override Nombre de champs de données diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index befd6dcb..a658a668 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index a3132e9a..176ac109 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 285ecbcf..20da4f35 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 32029033..2c8bb754 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index e8f951d1..45aa6c28 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 33e8f009..bb6917f2 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Ukryj Zero Poprzedzające Godzinę + Add colon between hours and minutes OpenWeatherMap API Key Override Liczba Pól z Danymi diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index fe4fcfb9..4caa98d5 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc index a4307e4d..7d6c9a09 100644 --- a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc +++ b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc @@ -5,9 +5,9 @@ fileVersion=1 fontName=Titillium Web fontFile= charSet=0 -fontSize=-48 +fontSize=-54 aa=1 -scaleH=110 +scaleH=100 useSmoothing=1 isBold=1 isItalic=0 @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 diff --git a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt index fb557496..e14906e0 100644 --- a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt +++ b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt @@ -1,14 +1,14 @@ -info face="Titillium Web" size=-48 bold=1 italic=0 charset="" unicode=1 stretchH=110 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=37 base=37 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +info face="Titillium Web" size=-54 bold=1 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=82 base=61 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-bold-48-extra-tall_0.png" chars count=10 -char id=48 x=0 y=0 width=26 height=37 xoffset=0 yoffset=0 xadvance=27 page=0 chnl=15 -char id=49 x=228 y=0 width=19 height=35 xoffset=2 yoffset=1 xadvance=27 page=0 chnl=15 -char id=50 x=156 y=0 width=22 height=36 xoffset=2 yoffset=0 xadvance=27 page=0 chnl=15 -char id=51 x=107 y=0 width=23 height=37 xoffset=2 yoffset=0 xadvance=27 page=0 chnl=15 -char id=52 x=202 y=0 width=25 height=35 xoffset=1 yoffset=1 xadvance=27 page=0 chnl=15 -char id=53 x=131 y=0 width=24 height=36 xoffset=1 yoffset=1 xadvance=27 page=0 chnl=15 -char id=54 x=81 y=0 width=25 height=37 xoffset=1 yoffset=0 xadvance=27 page=0 chnl=15 -char id=55 x=179 y=0 width=22 height=36 xoffset=2 yoffset=1 xadvance=27 page=0 chnl=15 -char id=56 x=27 y=0 width=26 height=37 xoffset=0 yoffset=0 xadvance=27 page=0 chnl=15 -char id=57 x=54 y=0 width=26 height=37 xoffset=0 yoffset=0 xadvance=27 page=0 chnl=15 +char id=48 x=0 y=0 width=28 height=38 xoffset=1 yoffset=24 xadvance=30 page=0 chnl=15 +char id=49 x=0 y=39 width=19 height=36 xoffset=4 yoffset=25 xadvance=30 page=0 chnl=15 +char id=50 x=167 y=0 width=24 height=37 xoffset=3 yoffset=24 xadvance=30 page=0 chnl=15 +char id=51 x=115 y=0 width=24 height=38 xoffset=3 yoffset=24 xadvance=30 page=0 chnl=15 +char id=52 x=217 y=0 width=27 height=36 xoffset=2 yoffset=25 xadvance=30 page=0 chnl=15 +char id=53 x=140 y=0 width=26 height=37 xoffset=2 yoffset=25 xadvance=30 page=0 chnl=15 +char id=54 x=87 y=0 width=27 height=38 xoffset=2 yoffset=24 xadvance=30 page=0 chnl=15 +char id=55 x=192 y=0 width=24 height=37 xoffset=3 yoffset=25 xadvance=30 page=0 chnl=15 +char id=56 x=29 y=0 width=28 height=38 xoffset=1 yoffset=24 xadvance=30 page=0 chnl=15 +char id=57 x=58 y=0 width=28 height=38 xoffset=1 yoffset=24 xadvance=30 page=0 chnl=15 diff --git a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall_0.png b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall_0.png index c2c6ab04d03cd75747293904716021a70fb71a2a..af2e1bc21d8a7cf375e2e8e3651623a24904e712 100644 GIT binary patch literal 2299 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 I(f|?jUwt4%Qvd(} diff --git a/resources-round-260x260/fonts/titillium-web-bold-74-tall.bmfc b/resources-round-260x260/fonts/titillium-web-bold-74-tall.bmfc index af96e3a9..64b5ad9d 100644 --- a/resources-round-260x260/fonts/titillium-web-bold-74-tall.bmfc +++ b/resources-round-260x260/fonts/titillium-web-bold-74-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 diff --git a/resources-round-260x260/fonts/titillium-web-light-74-tall.bmfc b/resources-round-260x260/fonts/titillium-web-light-74-tall.bmfc index 39ec74f8..638412d9 100644 --- a/resources-round-260x260/fonts/titillium-web-light-74-tall.bmfc +++ b/resources-round-260x260/fonts/titillium-web-light-74-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 @@ -50,6 +54,6 @@ invB=0 outlineThickness=0 # selected chars -chars=48-57 +chars=48-58 # imported icon images diff --git a/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt b/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt index a9d83042..1e9b0b08 100644 --- a/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt +++ b/resources-round-260x260/fonts/titillium-web-light-74-tall.fnt @@ -1,7 +1,7 @@ info face="Titillium Web Light" size=-74 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=119 base=89 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-light-74-tall_0.png" -chars count=10 +chars count=11 char id=48 x=38 y=0 width=36 height=54 xoffset=3 yoffset=35 xadvance=41 page=0 chnl=15 char id=49 x=69 y=55 width=21 height=52 xoffset=8 yoffset=36 xadvance=41 page=0 chnl=15 char id=50 x=214 y=0 width=32 height=53 xoffset=5 yoffset=35 xadvance=41 page=0 chnl=15 @@ -12,4 +12,4 @@ char id=54 x=111 y=0 width=34 height=54 xoffset=4 yoffset=35 char id=55 x=0 y=55 width=31 height=53 xoffset=5 yoffset=36 xadvance=41 page=0 chnl=15 char id=56 x=0 y=0 width=37 height=54 xoffset=2 yoffset=35 xadvance=41 page=0 chnl=15 char id=57 x=75 y=0 width=35 height=54 xoffset=3 yoffset=35 xadvance=41 page=0 chnl=15 -char id=58 x=95 y=55 width=10 height=54 xoffset=3 yoffset=35 xadvance=11 page=0 chnl=15 +char id=58 x=247 y=0 width=5 height=34 xoffset=5 yoffset=54 xadvance=15 page=0 chnl=15 diff --git a/resources-round-260x260/fonts/titillium-web-light-74-tall_0.png b/resources-round-260x260/fonts/titillium-web-light-74-tall_0.png index 27fe00c307d96b7285d31e8f00c5ca7cb8be3026..c1a84b27fda5b5267829649c6f9146950ff1035a 100644 GIT binary patch literal 3540 zcmcgv`8U*$0{zS&TTH%DNV0`&5r%}3>{+s8-%9ooMZ#D{L}ck3V`LdcW`xk#x0ykj z?7PZf#uiz}k|oQ$-uoloIrrRi?>+bTdv4Mlb3-l;K@I=_xQvbTtN;M?SAqbxzYK&6 z>^1$(bB*aglAy=$zIzrv08<#@jwJQhU4@ob({TOS9U zsY6j_&d@zUBYcqR*2l_7l)(&m5h$`BE4}XmDrEPgK4K1{)E4*3mo2tQl&ShbLziK< zf1pdImj?LWuBW8}1z>vti|c*4Yeetu9xj+Eo33>TUjj|CsPE4uCT`>oRk~BN zx7XAzsA-2Kt3UPK9_0IzCxEKxC(IT@*I)z9=u{`0-+>?f9PEv+9s8`XH1_+wLHyX) z`jE`MQ2l7#rRSV2Q(C5gLSbg`)pX~@xALD{+{^o}(5rgltyq%trHjjjT|;A*pWQCb zl%a4=kVp8~-g@@vr0Z7`cC_c}8sVUB^Bd&uQH#nJ3FSjyEu#o4Ta((3^aFutRSAbH z#iQ>Pq*VD{DEXdBYLVvf@D_$TT9+EE46l6+eVuetk3R|c_o)OX5w+?)8j?4{@iz5| z!MtxNtgcTxS(VbTMjI-}W+}e0GPyf_+T)_&McmE&Z|;*&pANA}KifAPrp+uG$SKus zAGgv8OZP0ft6jrT$zku22eFcllA5G_mjqj}$v~;vQU}exa@4@^?0Y#sP!^7lRQbi> zxL~Or3;rI*L)wTlo(A?c>5-a!10VuOQ4nAd37yalP+rBXY9c8uYGySDqRmCOrH}WC zXZ$kP?6ZIjiEXkVzkQP%o5?#a@>UWQrPl?cSz?ZgS!#-eN9L;tBk3;-rITr=JH2^I zSB$O{m%4M8O?YCvVhe|BlLt_WYH@LcP31PqpbC~MCRkZ`15dy;zR{Qpn;_K^^rO25 z1pxLJZnI)ke8jJx)H-FEYN)>-r;*%`Il;Z~p!o_A3GK3PMgKKW0CY}?j=9>Nr5 z<+pH%-<`MT%e8YX(bf0SbD*#Yf=ox$C9@}-z?lSG|K!ixZ!%J`H{A-Pnvl`o#)wV# z9%0o0^`_%prYOd2H5znE%@$@Jcs4ZrclTZ7g|X&(Y9sp{l^GvE_*>_Zzx(AqRM%}% z&}95T%!8>(;?5|*KWV>g9|k9Hz8nJ*iUu*5v|kK~qr7#EvWgO{ovkbH4|2}s&-L~b z!e^3*@|h-bys6i1G3jDO!_;iTHbIM{< zrt9X;XwBEe3Sx1J%R2|kpu)?E!0|AyaTrJCS(|N3Wr+QAF1Ua8i*x;VDI@o7WK{UN zT8&!nipodMuQe({DpYw&yCgrJ8hczS57lyib4KKP26Hw1cAzvf*Vu12z2QEOhfFFf zd9~PfsDovV6J(G_q>0~TpVgh$gw-YvoN3Znl!&S@iI{f2QvAhVF5wTj^^2L;mCJ|~ zyUP?%ds!XIjgeK|38<%F9)vT|Oz@`Pi(xvCZZZ}{<7cnsFuC(LvXYvEwyNlUtm>MV z8WFo)-0Q%O^w__u(( zuqJ(wq*p;NlgU{wid#{y$X-N2^l+;pkwb`@V!pUT&{5B(DvsuS5nLBr`s(}4@qI3U z9`>EnTr%6t-bPGX$Mj=fPA>;Bf1X_8Al>-2$Y8JOXI+}}6%BQea{ptw{L@^GGs=B| zYBds$n1jX(ys^#|_T2amH<-n?(96YZf`51ptDSv}{YN9{Rf?+b`6c${OKo6UCvD2S zL0fmark4S35i;G8+gDoQ)(UM`MN-T@P?`2S%RY_j3~VB8hc!{r`wdFD?WEAC26Z*ZB?%6-PC)T!>1-e5Fj0_*UV@Nrq&}!Q#r3h+0eV5VO zcmXQYpnhkfiVH(yQIDd125uHJqG0GRtxtv>OA?! z$YExjed8Y)0uvedr_)Df)zaOVRxG6P@lJeW<{}evj!JOF3A&6Jy5^oY+uUbb^ohxT zU(N5}yzZ6R8W!c_X~V_cv$w9b)VpMOb+zt5E|=-hFoJ6wldOhaVjmp1uWTs0qC6<0 zv#lLyLM!pXS{i_&>KK#HC5I|=EqFtMepi9lVeze!T{94kCY8jD^mSOvj{P?3*(XBy zSs~jXhG;=J{=-|$sDT?Fnei~E5GDOJeX<0;O0OHS+$LnuK1H_ti{LS`f!uN!&5l?J zrr9p6F@YEgXX%3Yl5Gnx*W2#>ox& zv+Up1&Z{?irix%k-RV^C$~8!NL4A|4q}>1{kF{ajD@;b?_%+|5dh{N8{Mlv1F6a4{ zl(dJ8NiNC*L^_Ns55cxKy*lYkWzi_;<3+=wj4P!!U?GodzE(!xpYSaV`6Hj> zHJZT|bo7$A0-?e*K9iB3_I$~~05PRljST0GZV=sIxaL$o_xq=S`KDKvu4M zT3K8{`?XOE;XzIDohw0fd%DF#xXg*H+lSEuRHK&qe>*9lIZ%J8H<%tX6bT(a6jz`N zsh43^&RhVifgr3RhUcop9tf!I;2ueWJ%gVEzb|BS}Ne3yl0b+f*=C7Q|nTaCFfge ztkZ?PBx}w)(;Cy$gL^qC=9@9CXP9sPKcOxV1I~DaI?16Uc>jCXjP=d+Ds+}8*@42pX?(yNi&euD}*if4i!VCcb0F=5q8m0gM@Gk`d$o^hH@V{rRe}ObW z*FckWgPew%NxJ2%+x4$S{!GW(9{`}B{cnNTrPtR002M@6L)AR!$3EI1o_>G<@saYV z_lL7;dIm8yubXu|Eroi~3mq4(r$YSaTP~dbG02E&rFBN3(sV!7M0$+TSkKP78og)o zCwk8UZnc6K_=wMtiK8VV-TqK-6!IyAdygGHt4Nr1!IidEwh~@3_wL0n^R>8@mR?%S zR90C1vA0^2VoYkFDL#4*eXp2+wG#0!>6iI~(%(qQ)fDg4S~m+reu^5pSjTT3;h}ss zcCR#l)D%uFOm$_{-l~g!58li#Hy>L(smOZO@QAlT49(y2qct5fjShAkaUoRBTzU}h z`opXW5skWIXQd_I4O}x8OwNs-1fD}*7DAr$R3NTJ`#X<(;At@|3s ztNOBbVFuAw&OY21M~R&+(Ka6B9inA?!9A-)gIOP<=xaSTH-IkILyX;wN6{swHhT}| znX$qqG3hf9FiGpBXV%tI4d~skW=0+ww7|a52*sdX^XzOnM=~rm5ovJZC^jS&?sOsh z&`%rfegh1*d8@V;;)W?|{Y{A=pq3hyb zM?BX$JLPvx08bnU+6Am5-O}jR!{uXzUmOQ!T(mvbC|QlNOLc39ub5i^%HchnSFJ~x zfo-L@CL5)0WI?Ewxb$q4pXzMN&SVCzg&5PWF40?KXd~^$91HBGN_Z@n{$UY9yi|eV zo0YGQx7BYwnzn$ z`k7>H5Tz+hUmfPjkCUe?gInWpi-Z2_jFyBs- zAO9#)!M#h9mR(_aMSeO`iPX@sY=b-NdSV6gMi{WV^qa5}mE>g(3p-GAh4c#x=~#aL z{Co^hTts4W`Vrn}*#M7{xX0ApRGJ49^oKb4>?gi_!#2(-Y3tCbga0}4) z*9T4X&mL5YsgItc`Z?+3mAyW&nNzV@*}$;e!PmILjCmu!wK+}M4VQQIO{+U79UhIH zv?ELu=lyEaL!|I!;WQbNXIL@T90*_G^9s_Ud1+N~8`aCg?Zdi^!7-?`EnD3wuG;+= zyftq>(U%aLrTVQ|iuVn#^ZO?SF*f3-X_?nV4t2SFZ$Z{R@{(%hn-GX`D+NlDlqr(_ zUf)gDFnLrtUp&Pd24kj(%t$~wq8fjNCDUBKV;B)%J?QkY%nI>MF07w1xqc|SVyGY| zrT&=88?Lci8W+8TzpJMJ)MFls%X-)Rpac&gD|1F!3$AQJbUr*pGKEvgS{DsOFdrB% zP+|ou2LR-KWxOA`^@sEYIzXlrs+^+7%nu-gUO(|SIl!|UVcrohmAgy9-(Yw>G%Ow( zh5Ruo*ykFXK;6c3U zAQZ^sJAH+U?KuBEMt3jcJ*6iv;Nux%f1=#Tk}-zO?dgpx)C7-lhh|+--=(C_@U`~^ zGWaC&;Kco&qXYG!jSJ|xk_?6RQ|V-9g7DEg)pYJ|aVkbQlpuey*6DpGaSbP_D{S{C zdUvuY!yB8bIK?G?qwJA3l@L^nHPIyr7^2Aw>HClb=zq{BZL`CV#ocAq&6P;s+kcxN z(4CNyD1*-_7QVb4H7O8 zJl2zTThbHmP_R$>uBsrV=H{uWjf2f_A)TyU{lJ7QK6#ElZ%$3g(zw7>29lebC87+!D)2^s$hSsDTtLPUxT~!D=4h5Z+tb#-7^Zo5w&|Kr-FpGii_fjZ(94kZ;c#0aq{9(uWV+8^)?$!!y~b&1C5{0UtvlGUrfV1QCmw1 z?R={>rwXysjSJHU*0ClI^*~9*D8IJN1mmTLidToY!d5CX@v7&Z69uqry`>tZGIl@P z<-vCUu~-Y&5yi$s1Ym8V6`HrfYVU*MENZdBwSe$QgSy~|E?~L3D=z@{5UuB zB0p?UYV+SPMboq&MJcDHAHLACMcntlmol7?sdwQQ$BY^gc!z_R`{H=DR88cGSW#JU z!d*uW?YixRRaIwZK7#=}VU#f5@zcR`VnzL->Ef{%%-ug9Q2As+11RXX7OQ6JT0}B zb?46h1)kT=$#fy+S*t$BVGVq=580M;Mm*g}PZ#<~M~wQXDv~KDa?KxUYe_2Eacs1O zw&u9=Joc7Z&@!P+Zn&Ydt=D&Nu%g#_hKY>Y`NPl{XxPyBdSr*^QTAeIXTA56({xaE zSQG6%RYkco-(hAQY0PkO!HLWdhL+f(cKi6@3MyYFl8UGDggP1lYbWGrdTF+Ffq$;Tls;T$FCt(PPJ_kXFgnn^*_kB8YJ$gK-T38{MX=l6RFQz zpNuBX$NwNtvZml;doTAo#g;EsHfvfsW+!pnR<;?J!74;)?g?S$S0TUH8kw_rOXClF z6|H%{3--)>j8pT0R~v9L_)=CG4znY99814bD>oFXNBEd4SM3X((ecaWe>1(^2@)`= zjO?UeS($5k>GNKK$CVPeYR1c3!}XqBN-t`V1YeBka|G=e%HpGRfXrOc*P;h+tSG-7 zj0|5JUUT6mFlz(+!BAu_dxJG$DY@!atNwGOsbnp2et*(Gx7Qm# z@1sC^cFQ;Q_+P%bMU%i6ne=(tAfv+de?q{@z|>n9*|Pun(}PJ>nXR$=iGlk-#?aqf z{#O??&&C70K3^S9NZnk&odrv-r~Z=x6@B!n%CFl zYDRxLCJ;RWeWen`cM7v^kMA^x@M{6=iR5ZYWqz|2vu^BhgnL z5xdC#9&wYmWw6Q(PA!v!Q4C91E5!Gl0jh|C*Q;(*4mQx>^sCkJ^^t&WCggg39bf@xm*0KmV$b&L_P4qr8AQ4F~3nzof#?y-8cOeUJO$y2YEY)vB z4j%MQz17nqR|WF_QgfR9@|VXHfQ(@m7l}7{4aHz87BG0)1om@Hl&xNCju-;zhTS_8 z3v*KTa4~QcXIGh3nY_~~LKifih=y8qvIeM+2>g9NbdRH}==6A`H{pCwOm6X}^W|H3 zeRzX7;f6!`-vH={Bh>l!i9|1y7_Q>7KRN!&LFp)@j3L+oKdoB9nzhD2pR8spREs!GE3%ymLPKTU0l|b+`!3F&;Ael s{Lzz?VHtguzr#EJt8)L3vz>Gc^v@h_j8CBauRQ{EH4Qat)EwXb4-U%p5C8xG diff --git a/resources-round-280x280/fonts/titillium-web-bold-80-tall.bmfc b/resources-round-280x280/fonts/titillium-web-bold-80-tall.bmfc index f7ea5091..a9cff5ae 100644 --- a/resources-round-280x280/fonts/titillium-web-bold-80-tall.bmfc +++ b/resources-round-280x280/fonts/titillium-web-bold-80-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 diff --git a/resources-round-280x280/fonts/titillium-web-light-80-tall.bmfc b/resources-round-280x280/fonts/titillium-web-light-80-tall.bmfc index 07c3eb7a..68d1a1af 100644 --- a/resources-round-280x280/fonts/titillium-web-light-80-tall.bmfc +++ b/resources-round-280x280/fonts/titillium-web-light-80-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 @@ -50,6 +54,6 @@ invB=0 outlineThickness=0 # selected chars -chars=48-57 +chars=48-58 # imported icon images diff --git a/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt b/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt index aa4e9823..b5f9858e 100644 --- a/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt +++ b/resources-round-280x280/fonts/titillium-web-light-80-tall.fnt @@ -12,4 +12,4 @@ char id=54 x=120 y=0 width=37 height=58 xoffset=4 yoffset=38 char id=55 x=36 y=59 width=33 height=57 xoffset=6 yoffset=39 xadvance=45 page=0 chnl=15 char id=56 x=0 y=0 width=40 height=58 xoffset=2 yoffset=38 xadvance=45 page=0 chnl=15 char id=57 x=81 y=0 width=38 height=58 xoffset=3 yoffset=38 xadvance=45 page=0 chnl=15 -char id=58 x=114 y=59 width=10 height=56 xoffset=0 yoffset=38 xadvance=10 page=0 chnl=15 \ No newline at end of file +char id=58 x=110 y=59 width=6 height=37 xoffset=5 yoffset=58 xadvance=17 page=0 chnl=15 diff --git a/resources-round-280x280/fonts/titillium-web-light-80-tall_0.png b/resources-round-280x280/fonts/titillium-web-light-80-tall_0.png index e1ff2fe8843117c0ce65f6ff1b192b2b3c92ccfe..189eede868cbad24c6a84675992e48b26ed29d77 100644 GIT binary patch literal 3829 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 aJkat1`tfgezU%nk%ljA%(XDu37x{mOJ7Hu1 diff --git a/resources-round-360x360/fonts/titillium-web-bold-102-tall.bmfc b/resources-round-360x360/fonts/titillium-web-bold-102-tall.bmfc index 15f00110..9ead2a77 100644 --- a/resources-round-360x360/fonts/titillium-web-bold-102-tall.bmfc +++ b/resources-round-360x360/fonts/titillium-web-bold-102-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 diff --git a/resources-round-360x360/fonts/titillium-web-light-102-tall.bmfc b/resources-round-360x360/fonts/titillium-web-light-102-tall.bmfc index 8f963d8b..45619427 100644 --- a/resources-round-360x360/fonts/titillium-web-light-102-tall.bmfc +++ b/resources-round-360x360/fonts/titillium-web-light-102-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 @@ -50,6 +54,6 @@ invB=0 outlineThickness=0 # selected chars -chars=48-57 +chars=48-58 # imported icon images diff --git a/resources-round-360x360/fonts/titillium-web-light-102-tall.fnt b/resources-round-360x360/fonts/titillium-web-light-102-tall.fnt index 006b028b..556befe2 100644 --- a/resources-round-360x360/fonts/titillium-web-light-102-tall.fnt +++ b/resources-round-360x360/fonts/titillium-web-light-102-tall.fnt @@ -1,7 +1,7 @@ info face="Titillium Web Light" size=-102 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=163 base=122 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-light-102-tall_0.png" -chars count=10 +chars count=11 char id=48 x=52 y=0 width=49 height=74 xoffset=4 yoffset=49 xadvance=57 page=0 chnl=15 char id=49 x=185 y=75 width=28 height=72 xoffset=11 yoffset=50 xadvance=57 page=0 chnl=15 char id=50 x=46 y=75 width=44 height=73 xoffset=7 yoffset=49 xadvance=57 page=0 chnl=15 @@ -12,3 +12,4 @@ char id=54 x=102 y=0 width=47 height=74 xoffset=5 yoffset=49 char id=55 x=91 y=75 width=42 height=73 xoffset=8 yoffset=50 xadvance=57 page=0 chnl=15 char id=56 x=0 y=0 width=51 height=74 xoffset=3 yoffset=49 xadvance=57 page=0 chnl=15 char id=57 x=150 y=0 width=47 height=74 xoffset=4 yoffset=49 xadvance=57 page=0 chnl=15 +char id=58 x=243 y=0 width=7 height=47 xoffset=7 yoffset=75 xadvance=21 page=0 chnl=15 diff --git a/resources-round-360x360/fonts/titillium-web-light-102-tall_0.png b/resources-round-360x360/fonts/titillium-web-light-102-tall_0.png index 692d7f9ecf35ccdf96fe5e1bb0723e552a429f4b..956a797bf6db371157dd995a5d6da935d649151c 100644 GIT binary patch literal 6678 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 IGUlQG2bXSl1^@s6 literal 6592 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 b!B5xVm1fLDkQ<|l_8+? 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 XbcexG?wtC64?RUWHQ6c|vmgHliQ}*9 literal 7063 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 literal 7656 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 seconds when inactive Always hide seconds Скрывать нули перед часами + Add colon between hours and minutes OpenWeatherMap API Key Override Количество полей данных diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index b152b634..1b5529ab 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 8215a0c3..1cdf3df3 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-small-time/fonts/titillium-web-bold-58-tall.bmfc b/resources-small-time/fonts/titillium-web-bold-58-tall.bmfc index f44abb3a..5b3f5453 100644 --- a/resources-small-time/fonts/titillium-web-bold-58-tall.bmfc +++ b/resources-small-time/fonts/titillium-web-bold-58-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 diff --git a/resources-small-time/fonts/titillium-web-bold-58-tall.fnt b/resources-small-time/fonts/titillium-web-bold-58-tall.fnt index 09f9daf4..64d1a3e0 100644 --- a/resources-small-time/fonts/titillium-web-bold-58-tall.fnt +++ b/resources-small-time/fonts/titillium-web-bold-58-tall.fnt @@ -1,14 +1,14 @@ info face="Titillium Web" size=-58 bold=1 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=42 base=42 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +common lineHeight=94 base=70 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-bold-58-tall_0.png" chars count=10 -char id=48 x=0 y=0 width=32 height=42 xoffset=0 yoffset=0 xadvance=32 page=0 chnl=15 -char id=49 x=31 y=43 width=22 height=40 xoffset=3 yoffset=1 xadvance=32 page=0 chnl=15 -char id=50 x=187 y=0 width=26 height=41 xoffset=3 yoffset=0 xadvance=32 page=0 chnl=15 -char id=51 x=129 y=0 width=28 height=42 xoffset=2 yoffset=0 xadvance=32 page=0 chnl=15 -char id=52 x=0 y=43 width=30 height=40 xoffset=1 yoffset=1 xadvance=32 page=0 chnl=15 -char id=53 x=158 y=0 width=28 height=41 xoffset=2 yoffset=1 xadvance=32 page=0 chnl=15 -char id=54 x=98 y=0 width=30 height=42 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=15 -char id=55 x=214 y=0 width=26 height=41 xoffset=3 yoffset=1 xadvance=32 page=0 chnl=15 -char id=56 x=33 y=0 width=32 height=42 xoffset=0 yoffset=0 xadvance=32 page=0 chnl=15 -char id=57 x=66 y=0 width=31 height=42 xoffset=0 yoffset=0 xadvance=32 page=0 chnl=15 +char id=48 x=0 y=0 width=30 height=42 xoffset=1 yoffset=28 xadvance=32 page=0 chnl=15 +char id=49 x=234 y=0 width=21 height=41 xoffset=4 yoffset=28 xadvance=32 page=0 chnl=15 +char id=50 x=0 y=43 width=26 height=41 xoffset=3 yoffset=28 xadvance=32 page=0 chnl=15 +char id=51 x=151 y=0 width=26 height=42 xoffset=3 yoffset=28 xadvance=32 page=0 chnl=15 +char id=52 x=204 y=0 width=29 height=41 xoffset=2 yoffset=28 xadvance=32 page=0 chnl=15 +char id=53 x=123 y=0 width=27 height=42 xoffset=3 yoffset=28 xadvance=32 page=0 chnl=15 +char id=54 x=93 y=0 width=29 height=42 xoffset=2 yoffset=28 xadvance=32 page=0 chnl=15 +char id=55 x=178 y=0 width=25 height=42 xoffset=4 yoffset=28 xadvance=32 page=0 chnl=15 +char id=56 x=31 y=0 width=30 height=42 xoffset=1 yoffset=28 xadvance=32 page=0 chnl=15 +char id=57 x=62 y=0 width=30 height=42 xoffset=1 yoffset=28 xadvance=32 page=0 chnl=15 diff --git a/resources-small-time/fonts/titillium-web-bold-58-tall_0.png b/resources-small-time/fonts/titillium-web-bold-58-tall_0.png index 0794c8e0ef4f5e02ec5bc6a39ce70949d72bc1db..900a8290467597a03b82f23fed841212595358a4 100644 GIT binary patch literal 2695 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 DMa&Oi diff --git a/resources-small-time/fonts/titillium-web-light-58-tall.bmfc b/resources-small-time/fonts/titillium-web-light-58-tall.bmfc index 7e5e6342..4ec093fb 100644 --- a/resources-small-time/fonts/titillium-web-light-58-tall.bmfc +++ b/resources-small-time/fonts/titillium-web-light-58-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 @@ -50,6 +54,6 @@ invB=0 outlineThickness=0 # selected chars -chars=48-57 +chars=48-58 # imported icon images diff --git a/resources-small-time/fonts/titillium-web-light-58-tall.fnt b/resources-small-time/fonts/titillium-web-light-58-tall.fnt index 01cf3d79..29abb678 100644 --- a/resources-small-time/fonts/titillium-web-light-58-tall.fnt +++ b/resources-small-time/fonts/titillium-web-light-58-tall.fnt @@ -1,14 +1,15 @@ info face="Titillium Web Light" size=-58 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=42 base=42 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +common lineHeight=94 base=70 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-light-58-tall_0.png" -chars count=10 -char id=48 x=0 y=0 width=30 height=42 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=15 -char id=49 x=231 y=0 width=18 height=40 xoffset=5 yoffset=1 xadvance=32 page=0 chnl=15 -char id=50 x=177 y=0 width=26 height=41 xoffset=3 yoffset=0 xadvance=32 page=0 chnl=15 -char id=51 x=122 y=0 width=26 height=42 xoffset=3 yoffset=0 xadvance=32 page=0 chnl=15 -char id=52 x=0 y=43 width=30 height=40 xoffset=1 yoffset=1 xadvance=32 page=0 chnl=15 -char id=53 x=149 y=0 width=27 height=41 xoffset=3 yoffset=1 xadvance=32 page=0 chnl=15 -char id=54 x=62 y=0 width=29 height=42 xoffset=2 yoffset=0 xadvance=32 page=0 chnl=15 -char id=55 x=204 y=0 width=26 height=41 xoffset=3 yoffset=1 xadvance=32 page=0 chnl=15 -char id=56 x=31 y=0 width=30 height=42 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=15 -char id=57 x=92 y=0 width=29 height=42 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=15 +chars count=11 +char id=48 x=31 y=0 width=28 height=42 xoffset=2 yoffset=28 xadvance=32 page=0 chnl=15 +char id=49 x=0 y=43 width=16 height=41 xoffset=6 yoffset=28 xadvance=32 page=0 chnl=15 +char id=50 x=226 y=0 width=25 height=41 xoffset=4 yoffset=28 xadvance=32 page=0 chnl=15 +char id=51 x=117 y=0 width=26 height=42 xoffset=3 yoffset=28 xadvance=32 page=0 chnl=15 +char id=52 x=196 y=0 width=29 height=41 xoffset=2 yoffset=28 xadvance=32 page=0 chnl=15 +char id=53 x=144 y=0 width=25 height=42 xoffset=4 yoffset=28 xadvance=32 page=0 chnl=15 +char id=54 x=89 y=0 width=27 height=42 xoffset=3 yoffset=28 xadvance=32 page=0 chnl=15 +char id=55 x=170 y=0 width=25 height=42 xoffset=4 yoffset=28 xadvance=32 page=0 chnl=15 +char id=56 x=0 y=0 width=30 height=42 xoffset=1 yoffset=28 xadvance=32 page=0 chnl=15 +char id=57 x=60 y=0 width=28 height=42 xoffset=2 yoffset=28 xadvance=32 page=0 chnl=15 +char id=58 x=17 y=43 width=4 height=27 xoffset=4 yoffset=42 xadvance=12 page=0 chnl=15 diff --git a/resources-small-time/fonts/titillium-web-light-58-tall_0.png b/resources-small-time/fonts/titillium-web-light-58-tall_0.png index 2bd90c66dda702d8126cc68db5a4c7f537d731cd..0779760a3548d612f7501b4319d9f5909ab47ac1 100644 GIT binary patch literal 2746 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 PQ)*&pZt&wW=E;8m=~q3h literal 3979 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 diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index dca99be5..c08b58e4 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index c1bf492e..59237352 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Dölj inledande nollor + Add colon between hours and minutes OpenWeatherMap API Key Override Antal datafält diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 0b58f125..fdaa9f19 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index a1a805a1..cee9a1bc 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -19,6 +19,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/resources/fonts/titillium-web-bold-68-tall.bmfc b/resources/fonts/titillium-web-bold-68-tall.bmfc index 5c36c932..33400b45 100644 --- a/resources/fonts/titillium-web-bold-68-tall.bmfc +++ b/resources/fonts/titillium-web-bold-68-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 diff --git a/resources/fonts/titillium-web-bold-68-tall.fnt b/resources/fonts/titillium-web-bold-68-tall.fnt index 61201be0..ed904213 100644 --- a/resources/fonts/titillium-web-bold-68-tall.fnt +++ b/resources/fonts/titillium-web-bold-68-tall.fnt @@ -1,14 +1,14 @@ info face="Titillium Web" size=-68 bold=1 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=49 base=49 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +common lineHeight=109 base=81 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-bold-68-tall_0.png" chars count=10 -char id=48 x=0 y=0 width=37 height=49 xoffset=0 yoffset=0 xadvance=38 page=0 chnl=15 -char id=49 x=67 y=50 width=25 height=47 xoffset=4 yoffset=1 xadvance=38 page=0 chnl=15 -char id=50 x=215 y=0 width=31 height=48 xoffset=3 yoffset=0 xadvance=38 page=0 chnl=15 -char id=51 x=148 y=0 width=32 height=49 xoffset=3 yoffset=0 xadvance=38 page=0 chnl=15 -char id=52 x=32 y=50 width=34 height=47 xoffset=2 yoffset=1 xadvance=38 page=0 chnl=15 -char id=53 x=181 y=0 width=33 height=48 xoffset=2 yoffset=1 xadvance=38 page=0 chnl=15 -char id=54 x=38 y=0 width=36 height=49 xoffset=1 yoffset=0 xadvance=38 page=0 chnl=15 -char id=55 x=0 y=50 width=31 height=48 xoffset=3 yoffset=1 xadvance=38 page=0 chnl=15 -char id=56 x=75 y=0 width=36 height=49 xoffset=1 yoffset=0 xadvance=38 page=0 chnl=15 -char id=57 x=112 y=0 width=35 height=49 xoffset=1 yoffset=0 xadvance=38 page=0 chnl=15 +char id=48 x=0 y=0 width=36 height=49 xoffset=1 yoffset=33 xadvance=38 page=0 chnl=15 +char id=49 x=66 y=50 width=24 height=47 xoffset=5 yoffset=34 xadvance=38 page=0 chnl=15 +char id=50 x=206 y=0 width=30 height=48 xoffset=4 yoffset=33 xadvance=38 page=0 chnl=15 +char id=51 x=142 y=0 width=30 height=49 xoffset=4 yoffset=33 xadvance=38 page=0 chnl=15 +char id=52 x=31 y=50 width=34 height=47 xoffset=2 yoffset=34 xadvance=38 page=0 chnl=15 +char id=53 x=173 y=0 width=32 height=48 xoffset=3 yoffset=34 xadvance=38 page=0 chnl=15 +char id=54 x=37 y=0 width=34 height=49 xoffset=2 yoffset=33 xadvance=38 page=0 chnl=15 +char id=55 x=0 y=50 width=30 height=48 xoffset=4 yoffset=34 xadvance=38 page=0 chnl=15 +char id=56 x=72 y=0 width=34 height=49 xoffset=2 yoffset=33 xadvance=38 page=0 chnl=15 +char id=57 x=107 y=0 width=34 height=49 xoffset=2 yoffset=33 xadvance=38 page=0 chnl=15 diff --git a/resources/fonts/titillium-web-bold-68-tall_0.png b/resources/fonts/titillium-web-bold-68-tall_0.png index 6661cf1219128eed0f41e618e6ee5059522e9589..84d543fef71c7d8cf2a96e2f8977e9696690721b 100644 GIT binary patch literal 3188 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 NYD(IQRq{5${|A!(i+lh8 diff --git a/resources/fonts/titillium-web-light-68-tall.bmfc b/resources/fonts/titillium-web-light-68-tall.bmfc index 0055f7d2..e95db30c 100644 --- a/resources/fonts/titillium-web-light-68-tall.bmfc +++ b/resources/fonts/titillium-web-light-68-tall.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 @@ -50,6 +54,6 @@ invB=0 outlineThickness=0 # selected chars -chars=48-57 +chars=48-58 # imported icon images diff --git a/resources/fonts/titillium-web-light-68-tall.fnt b/resources/fonts/titillium-web-light-68-tall.fnt index 9bce10ab..dcd50625 100644 --- a/resources/fonts/titillium-web-light-68-tall.fnt +++ b/resources/fonts/titillium-web-light-68-tall.fnt @@ -1,14 +1,15 @@ info face="Titillium Web Light" size=-68 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=49 base=49 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +common lineHeight=109 base=81 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-light-68-tall_0.png" -chars count=10 -char id=48 x=37 y=0 width=34 height=49 xoffset=2 yoffset=0 xadvance=38 page=0 chnl=15 -char id=49 x=66 y=50 width=20 height=48 xoffset=7 yoffset=0 xadvance=38 page=0 chnl=15 -char id=50 x=35 y=50 width=30 height=48 xoffset=4 yoffset=0 xadvance=38 page=0 chnl=15 -char id=51 x=174 y=0 width=31 height=49 xoffset=3 yoffset=0 xadvance=38 page=0 chnl=15 -char id=52 x=0 y=50 width=34 height=48 xoffset=2 yoffset=0 xadvance=38 page=0 chnl=15 -char id=53 x=141 y=0 width=32 height=49 xoffset=3 yoffset=0 xadvance=38 page=0 chnl=15 -char id=54 x=72 y=0 width=34 height=49 xoffset=2 yoffset=0 xadvance=38 page=0 chnl=15 -char id=55 x=206 y=0 width=30 height=49 xoffset=4 yoffset=0 xadvance=38 page=0 chnl=15 -char id=56 x=0 y=0 width=36 height=49 xoffset=1 yoffset=0 xadvance=38 page=0 chnl=15 -char id=57 x=107 y=0 width=33 height=49 xoffset=2 yoffset=0 xadvance=38 page=0 chnl=15 +chars count=11 +char id=48 x=35 y=0 width=32 height=49 xoffset=3 yoffset=33 xadvance=38 page=0 chnl=15 +char id=49 x=228 y=0 width=18 height=47 xoffset=8 yoffset=34 xadvance=38 page=0 chnl=15 +char id=50 x=197 y=0 width=30 height=48 xoffset=4 yoffset=33 xadvance=38 page=0 chnl=15 +char id=51 x=134 y=0 width=30 height=49 xoffset=4 yoffset=33 xadvance=38 page=0 chnl=15 +char id=52 x=29 y=50 width=34 height=47 xoffset=2 yoffset=34 xadvance=38 page=0 chnl=15 +char id=53 x=165 y=0 width=31 height=48 xoffset=4 yoffset=34 xadvance=38 page=0 chnl=15 +char id=54 x=68 y=0 width=32 height=49 xoffset=3 yoffset=33 xadvance=38 page=0 chnl=15 +char id=55 x=0 y=50 width=28 height=48 xoffset=5 yoffset=34 xadvance=38 page=0 chnl=15 +char id=56 x=0 y=0 width=34 height=49 xoffset=2 yoffset=33 xadvance=38 page=0 chnl=15 +char id=57 x=101 y=0 width=32 height=49 xoffset=3 yoffset=33 xadvance=38 page=0 chnl=15 +char id=58 x=247 y=0 width=6 height=31 xoffset=4 yoffset=50 xadvance=14 page=0 chnl=15 diff --git a/resources/fonts/titillium-web-light-68-tall_0.png b/resources/fonts/titillium-web-light-68-tall_0.png index bcde7549865cad5287f3d4be1ce83c81b83ab3db..b740243eff4d45951f6c0c652ee1929269260339 100644 GIT binary patch literal 3158 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 literal 4857 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 g;Q!q+Qoo$i%@~cdPQD>0{okhr=$l-xy6PDHKYG - 2.15.1 + 2.15.2 0 @@ -28,6 +28,8 @@ 0 + + false 0 true diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 3462d5aa..95ad5cfd 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -1,9 +1,4 @@ - - - - - @Strings.ThemeBlueDark @@ -222,6 +217,10 @@ + + + + @Strings.HideSecondsOff diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 7b5848fb..00900f14 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Add colon between hours and minutes OpenWeatherMap API Key Override Number Of Data Fields diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index 68bcdf73..e0feb226 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -87,6 +87,17 @@ class ThickThinTime extends Ui.Drawable { ); x += dc.getTextWidthInPixels(hours, mHoursFont); + if (App.getApp().getProperty("AddColon")) { + dc.drawText( + x, + halfDCHeight, + mMinutesFont, + ":", + Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER + ); + x += dc.getTextWidthInPixels(":", mMinutesFont); + } + // Draw minutes. dc.setColor(gMinutesColour, Graphics.COLOR_TRANSPARENT); dc.drawText( From aeb36ec2fc9ce853c8b1fb27380f1f065129fd4f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 2 Apr 2023 18:49:38 -0400 Subject: [PATCH 101/220] Fixed the Venu2 SQ font --- README.md | 2 +- resources-rectangle-320x360/fonts/fonts.xml | 32 ++++++++++----------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index c54f0a9f..abdba027 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ Reviews: ### 2.16.0 - Added a optional colon between hours and minutes -- Access to stress level is not as stable as the Garmin access to it. To help here, if a value isn't returned, the last good one is used and the icon is greyed out to indicate the data is stale. - Bug fix in the default latitude/longitude when the last activity has no GPS coordinates. +- Notice: Access to stress level is not as stable as the Garmin has access to it. To help here, if a value isn't returned, the last good one is used and the icon is greyed out to indicate the data is stale. ### 2.15.1 - Reverted to Connect IQ 4.1.7 since there are too many problem with sensors with this 4.2.x version so far. Hopefully this doesn't break the watchface on newest Forerunner 265, 265S and 965. diff --git a/resources-rectangle-320x360/fonts/fonts.xml b/resources-rectangle-320x360/fonts/fonts.xml index 14f817ec..f7f39530 100644 --- a/resources-rectangle-320x360/fonts/fonts.xml +++ b/resources-rectangle-320x360/fonts/fonts.xml @@ -1,24 +1,24 @@ - + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + From 87954388fe173cb707b80f112045d2441996b79d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:52:22 -0400 Subject: [PATCH 102/220] Reformat comments and reactivate current debug one --- source/BackgroundService.mc | 16 +++---- source/CrystalApp.mc | 6 +-- source/CrystalView.mc | 94 ++++++++++++------------------------- source/Indicators.mc | 2 +- 4 files changed, 42 insertions(+), 76 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 95e1393e..7c5502ab 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -48,12 +48,12 @@ class BackgroundService extends Sys.ServiceDelegate { _token = "Bearer " + _token; } else { -//2023-03-05 logMessage("initialize:Generating Access Token"); + //2023-03-05 logMessage("initialize:Generating Access Token"); var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { -//2023-03-05 logMessage("initialize:No refresh token!"); + //2023-03-05 logMessage("initialize:No refresh token!"); } return; } @@ -75,7 +75,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onTemporalEvent() { var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); -//2023-03-05 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); + //2023-03-05 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { // 1. City local time. @@ -278,8 +278,8 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveToken(responseCode, data) { var result; -//2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); -//logMessage("onReceiveToken data is " + data); + //2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); + //logMessage("onReceiveToken data is " + data); if (responseCode == 200) { result = { "Token" => data }; } else { @@ -292,7 +292,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveVehicles(responseCode, data) { var result; -//2023-03-05 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); + //2023-03-05 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { @@ -319,7 +319,7 @@ class BackgroundService extends Sys.ServiceDelegate { var precondEnabled = "N/A"; var sentryEnabled = "N/A"; -//2023-03-05 logMessage("onReceiveVehicleData responseCode is " + responseCode); + //2023-03-05 logMessage("onReceiveVehicleData responseCode is " + responseCode); if (responseCode == 200) { results = data.get("response"); if (results != null) { @@ -382,7 +382,7 @@ class BackgroundService extends Sys.ServiceDelegate { }, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; -//2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); + //2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); Comms.makeWebRequest(url, params, options, callback); } //**************************************************************** diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 85b8a7cf..b816a526 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -160,9 +160,9 @@ class CrystalApp extends App.AppBase { var owmKeyOverride = getProperty("OWMKeyOverride"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { -//2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); + //2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); } else { -//2022-04-10 logMessage("Using OpenWeatherMap"); + //2022-04-10 logMessage("Using OpenWeatherMap"); var owmCurrent = getProperty("OpenWeatherMapCurrent"); // No existing data. @@ -330,7 +330,7 @@ class CrystalApp extends App.AppBase { // pendingWebRequests keys. (:background_method) function onBackgroundData(data) { -//2022-04-10 logMessage("onBackgroundData:received '" + data + "'"); + //2022-04-10 logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = getProperty("PendingWebRequests"); if (pendingWebRequests == null) { pendingWebRequests = {}; diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 3c79cdeb..754fe67a 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -29,7 +29,7 @@ var gNormalFont; var gIconsFont; var gStressLevel; -//DEBUG*/ var gStressLevelLogText; +/*DEBUG*/ var gStressLevelLogText; const SCREEN_MULTIPLIER = (Sys.getDeviceSettings().screenWidth < 360) ? 1 : 2; //const BATTERY_LINE_WIDTH = 2; @@ -122,7 +122,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 -//logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); + //logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); batteryStale = App.getApp().getProperty("TeslaBatterieStale"); chargingState = App.getApp().getProperty("TeslaChargingState"); error = App.getApp().getProperty("TeslaError"); @@ -174,7 +174,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { break; } -//logMessage("value=" + value); + //logMessage("value=" + value); if (value == null) { value = "N/A"; } @@ -276,18 +276,18 @@ class CrystalView extends Ui.WatchFace { // Reread Weather method function rereadWeatherMethod() { var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); -//2022-04-10 logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); + //2022-04-10 logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { if (Toybox has :Weather) { mHasGarminWeather = true; -//2022-04-10 logMessage("Does support Weather"); + //2022-04-10 logMessage("Does support Weather"); } else { mHasGarminWeather = false; -//2022-04-10 logMessage("Does not support Weather"); + //2022-04-10 logMessage("Does not support Weather"); } } else { mHasGarminWeather = false; -//2022-04-10 logMessage("Using OpenWeatherMap"); + //2022-04-10 logMessage("Using OpenWeatherMap"); } } @@ -333,7 +333,7 @@ class CrystalView extends Ui.WatchFace { // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { mSettingsChangedSinceLastDraw = true; -//logMessage("onSettingsChanged called"); + //logMessage("onSettingsChanged called"); updateNormalFont(); @@ -374,7 +374,7 @@ class CrystalView extends Ui.WatchFace { var now = Time.now(); if (Toybox.Weather has :getSunrise) { -//logMessage("We have sunrise and sunset routines!"); + //logMessage("We have sunrise and sunset routines!"); var sunrise = Weather.getSunrise(myLocation, now); var sunset = Weather.getSunset(myLocation, now); @@ -397,7 +397,7 @@ class CrystalView extends Ui.WatchFace { logMessage("Since sunset " + sinceSunset);*/ } else { -//logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); + //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); now = Gregorian.info(now, Time.FORMAT_SHORT); @@ -409,8 +409,8 @@ class CrystalView extends Ui.WatchFace { // Get today's sunrise/sunset times in current time zone. var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); //logMessage(sunTimes); -//logMessage("now=" + now); -//logMessage("sunTimes=" + sunTimes); + //logMessage("now=" + now); + //logMessage("sunTimes=" + sunTimes); // If sunrise/sunset happens today. var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); if (sunriseSunsetToday) { @@ -423,13 +423,13 @@ class CrystalView extends Ui.WatchFace { if (condition < 53) { icon = (mGarminToOWM[condition]).format("%02d") + day; -//logMessage("icon=" + icon); + //logMessage("icon=" + icon); } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => weather.observationTime.value(), "lat" => myLocationArray[0], "lon" => myLocationArray[1]}; -//2022-04-10 logMessage("Weather at " + weather.observationLocationName + " is " + result); + //2022-04-10 logMessage("Weather at " + weather.observationLocationName + " is " + result); } else { result = null; -//2022-04-10 logMessage("No weather data, returning null"); + //2022-04-10 logMessage("No weather data, returning null"); } App.getApp().setProperty("OpenWeatherMapCurrent", result); } @@ -668,40 +668,6 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = false; values[:max] = 100; -/* if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { - var stressLevelIterator; - var stressLevel = null; - - stressLevelIterator = Toybox.SensorHistory.getStressHistory({}); - if (stressLevelIterator == null) { - break; - } - - var sample = stressLevelIterator.next(); - var stressLevelDate = 0; - var count = 0; - var keptCount = 0; - while (sample != null) { - count++; - if (sample.when.value() > stressLevelDate) { - keptCount = count; - stressLevel = sample.data; - stressLevelDate = sample.when.value(); - } - sample = stressLevelIterator.next(); - } - - if (sample != null) { - stressLevel = sample.data; - stressLevelDate = sample.when.value(); - } - - if (stressLevel != null && stressLevel >= 0 && stressLevel <= 100) { - values[:current] = stressLevel.toFloat(); - values[:isValid] = true; - } -*/ - if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { var stressLevel = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); var stressLevelDate = 0; @@ -720,61 +686,61 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = true; gStressLevel = stressLevel; - /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); + /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); var logText = "stressLevel " + stressLevel + " stressLevelDate " + dateStr + " is GOOD"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; - }*/ + }/**/ } else if (gStressLevel != null) { values[:current] = gStressLevel.toFloat(); values[:isValid] = true; values[:staled] = true; - /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); + /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); var logText = "stressLevel " + stressLevel + "is over limit, ignoring"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; - }*/ + }/**/ } else { - /*DEBUG var logText = "stressLevel " + stressLevel + "is over limit and no StressHistory data found yet"; + /*DEBUG*/ var logText = "stressLevel " + stressLevel + "is over limit and no StressHistory data found yet"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; - }*/ + }/**/ } } else if (gStressLevel != null) { values[:current] = gStressLevel.toFloat(); values[:isValid] = true; values[:staled] = true; - /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); + /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); var logText = "stressLevel " + gStressLevel + " IS staled"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; - }*/ + }/**/ } else { - /*DEBUG var logText = "No StressHistory data found yet"; + /*DEBUG*/ var logText = "No StressHistory data found yet"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; - }*/ + }/**/ } -// logMessage("stressLeve " + stressLevel + " count " + count + " keptCount " + keptCount + " stressLevelDate " + stressLevelDate); + //logMessage("stressLeve " + stressLevel + " count " + count + " keptCount " + keptCount + " stressLevelDate " + stressLevelDate); } else { - /*DEBUG var logText = "No StressHistory Sensor found"; + /*DEBUG*/ var logText = "No StressHistory Sensor found"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; - }*/ + }/**/ } break; @@ -835,7 +801,7 @@ class CrystalView extends Ui.WatchFace { // Rather than checking the need for background requests on a timer, or on the hour, easier just to check when exiting // sleep. if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. -//logMessage("onExitSleep:Wakeup and checkPendingWebRequests"); + //logMessage("onExitSleep:Wakeup and checkPendingWebRequests"); App.getApp().checkPendingWebRequests(); } @@ -919,7 +885,7 @@ class CrystalView extends Ui.WatchFace { public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { System.println("Average execution time: " + powerInfo.executionTimeAverage); System.println("Allowed execution time: " + powerInfo.executionTimeLimit); -// _view.turnPartialUpdatesOff(); + //_view.turnPartialUpdatesOff(); } }*/ diff --git a/source/Indicators.mc b/source/Indicators.mc index e10e91eb..083793d3 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -45,7 +45,7 @@ class Indicators extends Ui.Drawable { //**************************************************************** if (mIndicator1Type == 6 || mIndicator2Type == 6 || mIndicator3Type == 6) { App.getApp().setProperty("Tesla", true); -//logMessage("onSettingsChanged:Doing Tesla!"); + //logMessage("onSettingsChanged:Doing Tesla!"); } else { App.getApp().setProperty("Tesla", null); } From 55ddfebee8d456af316d286e4230824215844141 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:53:33 -0400 Subject: [PATCH 103/220] Update CrystalView.mc --- source/CrystalView.mc | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 754fe67a..96434d8e 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -701,7 +701,6 @@ class CrystalView extends Ui.WatchFace { /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); - var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); var logText = "stressLevel " + stressLevel + "is over limit, ignoring"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); @@ -721,7 +720,6 @@ class CrystalView extends Ui.WatchFace { /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); - var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); var logText = "stressLevel " + gStressLevel + " IS staled"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); From 858210ca440cecdcab82cd0181494aec8e7a16eb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 4 Apr 2023 23:55:16 -0400 Subject: [PATCH 104/220] Cleaned up strings.xml, reorganized properties.xml to match order in settings.xml. Version number taken from resource\strings\strings.xml --- README.md | 6 ++ manifest.xml.beta | 111 ++++++++++++++++++++++++++++++ manifest.xml.prd | 111 ++++++++++++++++++++++++++++++ resources-ces/strings/strings.xml | 1 - resources-dan/strings/strings.xml | 1 - resources-deu/strings/strings.xml | 1 - resources-dut/strings/strings.xml | 3 +- resources-fin/strings/strings.xml | 2 - resources-fre/strings/strings.xml | 1 - resources-hrv/strings/strings.xml | 2 - resources-hun/strings/strings.xml | 2 - resources-ita/strings/strings.xml | 2 - resources-kor/strings/strings.xml | 2 - resources-nob/strings/strings.xml | 4 +- resources-pol/strings/strings.xml | 1 - resources-por/strings/strings.xml | 2 - resources-rus/strings/strings.xml | 1 - resources-slo/strings/strings.xml | 4 +- resources-slv/strings/strings.xml | 4 +- resources-spa/strings/strings.xml | 4 +- resources-swe/strings/strings.xml | 1 - resources-zhs/strings/strings.xml | 4 +- resources-zht/strings/strings.xml | 4 +- resources/settings/properties.xml | 21 +++--- resources/settings/settings.xml | 6 +- resources/strings/strings.xml | 7 +- source/CrystalView.mc | 16 ++--- 27 files changed, 258 insertions(+), 66 deletions(-) create mode 100644 manifest.xml.beta create mode 100644 manifest.xml.prd diff --git a/README.md b/README.md index abdba027..0d4ae198 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.16.2 +Hopefully fixed the fail to save settings for everyone with the issue. + +### 2.16.1 +Double entry in the english string file was (not) causing Connect to fail saving settings on devices but not in simulator. + ### 2.16.0 - Added a optional colon between hours and minutes - Bug fix in the default latitude/longitude when the last activity has no GPS coordinates. diff --git a/manifest.xml.beta b/manifest.xml.beta new file mode 100644 index 00000000..b26c415d --- /dev/null +++ b/manifest.xml.beta @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ces + dan + deu + dut + eng + fin + fre + hrv + hun + ita + kor + nob + pol + por + rus + slo + slv + spa + swe + zhs + zht + + + + \ No newline at end of file diff --git a/manifest.xml.prd b/manifest.xml.prd new file mode 100644 index 00000000..38de375f --- /dev/null +++ b/manifest.xml.prd @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ces + dan + deu + dut + eng + fin + fre + hrv + hun + ita + kor + nob + pol + por + rus + slo + slv + spa + swe + zhs + zht + + + + \ No newline at end of file diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 012223dd..d0ee781a 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 9ec616c3..e9650da9 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 65f8b636..6ea9984d 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -1,7 +1,6 @@ Crystal - App Version Theme Stunden Farbe diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 23d80348..e55484ce 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -1,7 +1,6 @@ Crystal - App Versie Thema Uren Kleur @@ -84,7 +83,6 @@ Weer Vochtigheid Luchtdruk - Pulsoximeter @@ -112,6 +110,7 @@ Battery Numeric + Pulsoximeter Tesla Info Tesla Access Token Tesla Refresh Token diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 21b4a938..f8ea2175 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Mar Jou - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 62aad878..208b326c 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -1,7 +1,6 @@ Crystal - Version de l'appli Thème Couleur des heures diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index a658a668..41d038ea 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Stu Pro - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 176ac109..cf4e0647 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ nov dec - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 20da4f35..e7c51c0b 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Nov Dic - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 2c8bb754..53ede7e3 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ 11월 12월 - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 45aa6c28..b88596bf 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -1,8 +1,7 @@ - + Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Nov Des - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index bb6917f2..0cbbc4af 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -1,7 +1,6 @@ Crystal - Wersja Motyw Kolor Godzin diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 4caa98d5..b04e0477 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -2,7 +2,6 @@ Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Nov Dez - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index ed5bf115..b4385e7a 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -1,7 +1,6 @@ Crystal - Версия Тема Цвет часов diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 1b5529ab..c1457eff 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -1,8 +1,7 @@ - + Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Nov Dec - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 1cdf3df3..2a4428d1 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -1,8 +1,7 @@ - + Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Nov Dec - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index c08b58e4..5196630b 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -1,8 +1,7 @@ - + Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ Nov Dic - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 59237352..540664de 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -1,7 +1,6 @@ Crystal - App-version Tema Färg timme diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index fdaa9f19..f1913c1c 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -1,8 +1,7 @@ - + Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ 十一月 十二月 - Battery Numeric Pulse Ox Tesla Info diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index cee9a1bc..f2da68d9 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -1,8 +1,7 @@ - + Crystal - App Version Theme Hours Colour @@ -110,7 +109,6 @@ 十一月 十二月 - Battery Numeric Pulse Ox Tesla Info diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 4a0076a6..0c8c62b4 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,14 +1,10 @@ - - 2.15.2 + 0 false - 0 - 0 - 0 1 0 @@ -25,20 +21,21 @@ 3 0 + 0 + 0 + true + false + 0 + 0 - false - - 0 - true - - 2651f49cb20de925fc57590709b86ce6 - + 2651f49cb20de925fc57590709b86ce6 + owner-api.teslamotors.com diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 95ad5cfd..859711bf 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -1,4 +1,8 @@ + + + + @Strings.ThemeBlueDark @@ -26,7 +30,6 @@ - @Strings.Steps @@ -267,5 +270,4 @@ - diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 00900f14..73ea9ffd 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,7 +1,6 @@ - - Crystal - App Version + Crystal + Crystal-Tesla V2.16.2 Theme Hours Colour @@ -71,7 +70,6 @@ Heart Rate Heart Rate (Live 5s) Battery - Battery Numeric Battery (Hide Percentage) Notifications Calories @@ -124,7 +122,6 @@ Light theme override Latitude Longitude - Longitude Stress Level diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 96434d8e..05805693 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -670,13 +670,13 @@ class CrystalView extends Ui.WatchFace { if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { var stressLevel = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); - var stressLevelDate = 0; + //DEBUG*/ var stressLevelDate = 0; if (stressLevel != null) { stressLevel = stressLevel.next(); } if (stressLevel !=null) { - stressLevelDate = stressLevel.when.value(); + //DEBUG*/ stressLevelDate = stressLevel.when.value(); stressLevel = stressLevel.data; } @@ -686,7 +686,7 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = true; gStressLevel = stressLevel; - /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); + /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); var logText = "stressLevel " + stressLevel + " stressLevelDate " + dateStr + " is GOOD"; @@ -699,7 +699,7 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = true; values[:staled] = true; - /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); + /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); var logText = "stressLevel " + stressLevel + "is over limit, ignoring"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { @@ -707,7 +707,7 @@ class CrystalView extends Ui.WatchFace { gStressLevelLogText = logText; }/**/ } else { - /*DEBUG*/ var logText = "stressLevel " + stressLevel + "is over limit and no StressHistory data found yet"; + /*DEBUG var logText = "stressLevel " + stressLevel + "is over limit and no StressHistory data found yet"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; @@ -718,7 +718,7 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = true; values[:staled] = true; - /*DEBUG*/ var timeMoment = new Time.Moment(stressLevelDate); + /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); var logText = "stressLevel " + gStressLevel + " IS staled"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { @@ -726,7 +726,7 @@ class CrystalView extends Ui.WatchFace { gStressLevelLogText = logText; }/**/ } else { - /*DEBUG*/ var logText = "No StressHistory data found yet"; + /*DEBUG var logText = "No StressHistory data found yet"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; @@ -734,7 +734,7 @@ class CrystalView extends Ui.WatchFace { } //logMessage("stressLeve " + stressLevel + " count " + count + " keptCount " + keptCount + " stressLevelDate " + stressLevelDate); } else { - /*DEBUG*/ var logText = "No StressHistory Sensor found"; + /*DEBUG var logText = "No StressHistory Sensor found"; if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { logMessage(logText); gStressLevelLogText = logText; From 288e61d9f579714beb9e5e14ef45a62a02c91a8c Mon Sep 17 00:00:00 2001 From: SylvainGa Date: Wed, 5 Apr 2023 08:44:19 -0400 Subject: [PATCH 105/220] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2198afd2..544c880f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ bin/ manifest.xml .vscode/launch.json .vscode/tasks.json +.vscode/settings.json From 110aadf486494e4ce73ac6f47c6534bc3f2483b4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 7 Apr 2023 22:10:38 -0400 Subject: [PATCH 106/220] Fixed the missing "+" character in the semibold 28pt font. --- .../fonts/titillium-web-semibold-28.bmfc | 4 +- .../fonts/titillium-web-semibold-28.fnt | 115 +++++++++--------- .../fonts/titillium-web-semibold-28_0.png | Bin 10137 -> 10106 bytes 3 files changed, 60 insertions(+), 59 deletions(-) diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc b/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc index 9db8fab1..c84d33ab 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc +++ b/resources-round-280x280/fonts/titillium-web-semibold-28.bmfc @@ -37,7 +37,7 @@ widthPaddingFactor=0.00 outWidth=256 outHeight=256 outBitDepth=8 -fontDescFormat=1 +fontDescFormat=0 fourChnlPacked=0 textureFormat=png textureCompression=0 @@ -54,7 +54,7 @@ invB=0 outlineThickness=0 # selected chars -chars=32-33,37,39,44-58,63,65-90,97-122,176,193,196-197,201,205-206,214,216,218-219,225,227-230,232-233 +chars=32-33,37,39,43-58,63,65-90,97-122,176,193,196-197,201,205-206,214,216,218-219,225,227-230,232-233 chars=237,240-241,243-244,246,248,251-252,268,282,344,346,352,377,381-382,8304,8308-8309,8311-8313 # imported icon images diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt index f482f1be..56d3046c 100644 --- a/resources-round-280x280/fonts/titillium-web-semibold-28.fnt +++ b/resources-round-280x280/fonts/titillium-web-semibold-28.fnt @@ -1,120 +1,121 @@ info face="Titillium Web SemiBold" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=43 base=32 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-semibold-28_0.png" -chars count=113 +chars count=114 char id=32 x=252 y=0 width=3 height=1 xoffset=-1 yoffset=42 xadvance=6 page=0 chnl=15 -char id=33 x=246 y=50 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=33 x=223 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=37 x=18 y=53 width=16 height=21 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 -char id=39 x=251 y=112 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 -char id=44 x=65 y=132 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 -char id=45 x=78 y=132 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 -char id=46 x=72 y=132 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 +char id=39 x=85 y=132 width=4 height=8 xoffset=1 yoffset=12 xadvance=6 page=0 chnl=15 +char id=43 x=203 y=114 width=14 height=14 xoffset=1 yoffset=18 xadvance=16 page=0 chnl=15 +char id=44 x=78 y=132 width=6 height=8 xoffset=0 yoffset=28 xadvance=7 page=0 chnl=15 +char id=45 x=96 y=132 width=10 height=3 xoffset=1 yoffset=23 xadvance=12 page=0 chnl=15 +char id=46 x=90 y=132 width=5 height=4 xoffset=1 yoffset=28 xadvance=7 page=0 chnl=15 char id=47 x=173 y=50 width=12 height=21 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 char id=48 x=145 y=72 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 char id=49 x=245 y=92 width=10 height=19 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 char id=50 x=0 y=119 width=14 height=19 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=51 x=79 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=51 x=94 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 char id=52 x=229 y=93 width=15 height=19 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=53 x=109 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 -char id=54 x=230 y=71 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=53 x=64 y=94 width=14 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 +char id=54 x=16 y=98 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 char id=55 x=182 y=93 width=13 height=20 xoffset=1 yoffset=13 xadvance=16 page=0 chnl=15 char id=56 x=128 y=73 width=16 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=57 x=32 y=96 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 -char id=58 x=245 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 +char id=57 x=0 y=98 width=15 height=20 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 +char id=58 x=247 y=112 width=5 height=13 xoffset=1 yoffset=19 xadvance=7 page=0 chnl=15 char id=63 x=210 y=93 width=12 height=20 xoffset=0 yoffset=12 xadvance=12 page=0 chnl=15 -char id=65 x=40 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 +char id=65 x=22 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 char id=66 x=213 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=67 x=114 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 +char id=67 x=144 y=50 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 char id=68 x=179 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 char id=69 x=124 y=94 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 char id=70 x=139 y=94 width=14 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=71 x=52 y=51 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 +char id=71 x=68 y=51 width=15 height=21 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 char id=72 x=58 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 -char id=73 x=248 y=27 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 +char id=73 x=246 y=50 width=5 height=20 xoffset=1 yoffset=12 xadvance=8 page=0 chnl=15 char id=74 x=240 y=27 width=7 height=22 xoffset=0 yoffset=12 xadvance=8 page=0 chnl=15 -char id=75 x=48 y=96 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 +char id=75 x=32 y=96 width=15 height=20 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 char id=76 x=154 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=13 page=0 chnl=15 char id=77 x=0 y=77 width=21 height=20 xoffset=1 yoffset=12 xadvance=24 page=0 chnl=15 -char id=78 x=76 y=73 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 +char id=78 x=40 y=75 width=17 height=20 xoffset=1 yoffset=12 xadvance=19 page=0 chnl=15 char id=79 x=0 y=55 width=17 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 char id=80 x=162 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 char id=81 x=27 y=28 width=17 height=24 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 char id=82 x=196 y=72 width=16 height=20 xoffset=1 yoffset=12 xadvance=17 page=0 chnl=15 -char id=83 x=68 y=51 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=84 x=16 y=98 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=83 x=52 y=51 width=15 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=84 x=48 y=96 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 char id=85 x=35 y=53 width=16 height=21 xoffset=1 yoffset=12 xadvance=18 page=0 chnl=15 -char id=86 x=22 y=75 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 +char id=86 x=76 y=73 width=17 height=20 xoffset=0 yoffset=12 xadvance=17 page=0 chnl=15 char id=87 x=220 y=50 width=25 height=20 xoffset=0 yoffset=12 xadvance=26 page=0 chnl=15 char id=88 x=94 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=16 page=0 chnl=15 char id=89 x=111 y=73 width=16 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=90 x=0 y=98 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 -char id=97 x=79 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 +char id=90 x=230 y=71 width=15 height=20 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=97 x=64 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 char id=98 x=99 y=51 width=14 height=21 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 char id=99 x=108 y=115 width=12 height=16 xoffset=0 yoffset=17 xadvance=12 page=0 chnl=15 -char id=100 x=129 y=51 width=14 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 +char id=100 x=84 y=51 width=14 height=21 xoffset=0 yoffset=12 xadvance=15 page=0 chnl=15 char id=101 x=49 y=117 width=14 height=16 xoffset=0 yoffset=17 xadvance=14 page=0 chnl=15 char id=102 x=199 y=50 width=10 height=21 xoffset=0 yoffset=11 xadvance=10 page=0 chnl=15 -char id=103 x=61 y=28 width=15 height=22 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=103 x=45 y=28 width=15 height=22 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 char id=104 x=168 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=15 page=0 chnl=15 -char id=105 x=223 y=93 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=105 x=246 y=71 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=106 x=117 y=0 width=8 height=27 xoffset=-2 yoffset=12 xadvance=7 page=0 chnl=15 char id=107 x=196 y=93 width=13 height=20 xoffset=1 yoffset=12 xadvance=14 page=0 chnl=15 -char id=108 x=246 y=71 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 +char id=108 x=248 y=27 width=5 height=20 xoffset=1 yoffset=12 xadvance=7 page=0 chnl=15 char id=109 x=121 y=115 width=21 height=15 xoffset=1 yoffset=17 xadvance=23 page=0 chnl=15 char id=110 x=143 y=115 width=13 height=15 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=111 x=64 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 -char id=112 x=84 y=51 width=14 height=21 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 -char id=113 x=144 y=50 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=111 x=79 y=115 width=14 height=16 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 +char id=112 x=114 y=51 width=14 height=21 xoffset=1 yoffset=17 xadvance=15 page=0 chnl=15 +char id=113 x=129 y=51 width=14 height=21 xoffset=0 yoffset=17 xadvance=15 page=0 chnl=15 char id=114 x=171 y=114 width=9 height=15 xoffset=1 yoffset=17 xadvance=10 page=0 chnl=15 char id=115 x=94 y=115 width=13 height=16 xoffset=0 yoffset=17 xadvance=13 page=0 chnl=15 char id=116 x=15 y=119 width=10 height=19 xoffset=0 yoffset=14 xadvance=10 page=0 chnl=15 char id=117 x=157 y=114 width=13 height=15 xoffset=1 yoffset=18 xadvance=15 page=0 chnl=15 -char id=118 x=203 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=118 x=218 y=114 width=14 height=14 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 char id=119 x=181 y=114 width=21 height=14 xoffset=0 yoffset=18 xadvance=22 page=0 chnl=15 -char id=120 x=218 y=114 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=121 x=64 y=94 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 -char id=122 x=232 y=113 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 -char id=176 x=54 y=134 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 +char id=120 x=233 y=113 width=13 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=121 x=109 y=94 width=14 height=20 xoffset=0 yoffset=18 xadvance=14 page=0 chnl=15 +char id=122 x=0 y=139 width=12 height=14 xoffset=0 yoffset=18 xadvance=13 page=0 chnl=15 +char id=176 x=67 y=132 width=10 height=9 xoffset=3 yoffset=12 xadvance=16 page=0 chnl=15 char id=193 x=126 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 char id=196 x=144 y=0 width=17 height=26 xoffset=0 yoffset=6 xadvance=17 page=0 chnl=15 char id=197 x=9 y=28 width=17 height=24 xoffset=0 yoffset=8 xadvance=17 page=0 chnl=15 -char id=201 x=226 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 +char id=201 x=211 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 char id=205 x=0 y=28 width=8 height=26 xoffset=0 yoffset=6 xadvance=8 page=0 chnl=15 char id=206 x=241 y=0 width=10 height=26 xoffset=-1 yoffset=6 xadvance=8 page=0 chnl=15 -char id=214 x=0 y=0 width=17 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=216 x=18 y=0 width=17 height=27 xoffset=1 yoffset=9 xadvance=18 page=0 chnl=15 -char id=218 x=36 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=219 x=53 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 -char id=225 x=197 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=227 x=182 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=228 x=122 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=229 x=107 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=214 x=18 y=0 width=17 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=216 x=0 y=0 width=17 height=27 xoffset=1 yoffset=9 xadvance=18 page=0 chnl=15 +char id=218 x=53 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=219 x=36 y=0 width=16 height=27 xoffset=1 yoffset=6 xadvance=18 page=0 chnl=15 +char id=225 x=137 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=227 x=152 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=228 x=182 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=229 x=197 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 char id=230 x=26 y=119 width=22 height=16 xoffset=0 yoffset=17 xadvance=22 page=0 chnl=15 -char id=232 x=92 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 -char id=233 x=77 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=232 x=107 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 +char id=233 x=92 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=14 page=0 chnl=15 char id=237 x=210 y=50 width=9 height=21 xoffset=0 yoffset=11 xadvance=7 page=0 chnl=15 -char id=240 x=45 y=28 width=15 height=22 xoffset=0 yoffset=11 xadvance=16 page=0 chnl=15 +char id=240 x=61 y=28 width=15 height=22 xoffset=0 yoffset=11 xadvance=16 page=0 chnl=15 char id=241 x=159 y=50 width=13 height=21 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 -char id=243 x=137 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=244 x=152 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=246 x=167 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 -char id=248 x=94 y=94 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 +char id=243 x=167 y=27 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=244 x=77 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=246 x=122 y=28 width=14 height=22 xoffset=0 yoffset=11 xadvance=15 page=0 chnl=15 +char id=248 x=79 y=94 width=14 height=20 xoffset=0 yoffset=15 xadvance=15 page=0 chnl=15 char id=251 x=212 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 char id=252 x=226 y=27 width=13 height=22 xoffset=1 yoffset=11 xadvance=15 page=0 chnl=15 char id=268 x=102 y=0 width=14 height=27 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 -char id=282 x=211 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 +char id=282 x=226 y=0 width=14 height=26 xoffset=1 yoffset=6 xadvance=15 page=0 chnl=15 char id=344 x=162 y=0 width=16 height=26 xoffset=1 yoffset=6 xadvance=17 page=0 chnl=15 char id=346 x=86 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=352 x=70 y=0 width=15 height=27 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=377 x=195 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=381 x=179 y=0 width=15 height=26 xoffset=0 yoffset=6 xadvance=15 page=0 chnl=15 char id=382 x=186 y=50 width=12 height=21 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 -char id=8304 x=0 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8308 x=9 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8309 x=18 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8311 x=27 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8312 x=36 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 -char id=8313 x=45 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8304 x=22 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8308 x=31 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8309 x=40 y=136 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8311 x=49 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8312 x=58 y=134 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 +char id=8313 x=13 y=139 width=8 height=10 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 kernings count=518 kerning first=39 second=47 amount=-2 kerning first=44 second=86 amount=-1 diff --git a/resources-round-280x280/fonts/titillium-web-semibold-28_0.png b/resources-round-280x280/fonts/titillium-web-semibold-28_0.png index e33bef1716100fc2aef5adca8809f95eda60350b..2d920a4e2d322c07b7d24ac432a8a33414551560 100644 GIT binary patch literal 10106 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�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 literal 10137 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 O0eNXGqh From 0d1a25ca1189182883638e763d83241aac9e0e00 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 7 Apr 2023 22:12:47 -0400 Subject: [PATCH 107/220] Removed manifest.xml from .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 544c880f..255405d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ .project .settings/ bin/ -manifest.xml .vscode/launch.json .vscode/tasks.json .vscode/settings.json From 0956dbb91dfe8af27028617215fc8bd9a27c516c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 7 Apr 2023 22:37:13 -0400 Subject: [PATCH 108/220] Need to think to update the version before compiling --- README.md | 3 +++ resources/strings/strings.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d4ae198..a877bfa6 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.16.3 +Recompiled with ConnectIQ4.1.7 which will hopefully fixed the fail to save settings for everyone with the issue and not create more issues. + ### 2.16.2 Hopefully fixed the fail to save settings for everyone with the issue. diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 73ea9ffd..05415b03 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.16.2 + Crystal-Tesla V2.16.3 Theme Hours Colour From fbff0547e9f8fa02e841ded700389d475d0d68b2 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 7 Apr 2023 22:41:40 -0400 Subject: [PATCH 109/220] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a877bfa6..235aa6bf 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.16.3 -Recompiled with ConnectIQ4.1.7 which will hopefully fixed the fail to save settings for everyone with the issue and not create more issues. +- Recompiled with ConnectIQ4.1.7 which will hopefully fixed the fail to save settings for everyone with the issue and not create more issues. +- Fixed the 416x416 watch font missing a '+' ### 2.16.2 Hopefully fixed the fail to save settings for everyone with the issue. From c627da264b04dac544ea35c29aa44beea6fa5448 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 7 Apr 2023 23:19:59 -0400 Subject: [PATCH 110/220] No point building betas for watches I don't have --- manifest.xml.beta | 70 ----------------------------------------------- 1 file changed, 70 deletions(-) diff --git a/manifest.xml.beta b/manifest.xml.beta index b26c415d..d1c65246 100644 --- a/manifest.xml.beta +++ b/manifest.xml.beta @@ -3,78 +3,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1614253704e5f43d985d45524ee1d0fc6737f472 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 15 Apr 2023 20:41:32 -0400 Subject: [PATCH 111/220] Changed setProperties/getProperties for setValue/getValue and limited lat an lng to 5 decimal when storing in Properties I saw a Lat of 45.3923803809328 which prevented the settings from saving. --- README.md | 4 ++ manifest.xml | 4 +- manifest.xml.beta | 2 +- manifest.xml.prd | 4 +- monkey.jungle | 3 +- resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 40 ++++++------- source/CrystalApp.mc | 95 +++++++++++++++++-------------- source/CrystalView.mc | 103 +++++++++++++++++++--------------- source/DataArea.mc | 8 ++- source/DataFields.mc | 13 +++-- source/GoalMeter.mc | 10 ++-- source/Indicators.mc | 12 ++-- source/MoveBar.mc | 6 +- source/ThickThinTime.mc | 4 +- 15 files changed, 180 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index 235aa6bf..3ee5e06f 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.16.4 +- Recompiled with ConnectIQ4.2.4 since that wasn't the issue with the save settings. It was because watches with ICQ 4.2.0+ didn't support the getProperties/setProperties functions that were used throughout the app. I replaced them all with their corresponding Storage or Properties (for settings) getValue/setValue and was finally able to save the settings on my new Venu2. I was unable to reproduce on my old Venu since it was released pre 4.2.0. +- Added the MARQ® (Gen 2) Athlete / Adventurer / Captain / Golfer / Aviator watches + ### 2.16.3 - Recompiled with ConnectIQ4.1.7 which will hopefully fixed the fail to save settings for everyone with the issue and not create more issues. - Fixed the 416x416 watch font missing a '+' diff --git a/manifest.xml b/manifest.xml index 38de375f..9c0820f8 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + @@ -53,6 +53,8 @@ + + diff --git a/manifest.xml.beta b/manifest.xml.beta index d1c65246..f8d2c32a 100644 --- a/manifest.xml.beta +++ b/manifest.xml.beta @@ -1,7 +1,7 @@ - + diff --git a/manifest.xml.prd b/manifest.xml.prd index 38de375f..9c0820f8 100644 --- a/manifest.xml.prd +++ b/manifest.xml.prd @@ -1,7 +1,7 @@ - + @@ -53,6 +53,8 @@ + + diff --git a/monkey.jungle b/monkey.jungle index 58e58551..dcdc1305 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -89,4 +89,5 @@ epix2.sourcePath = $(epix2.sourcePath);always-on-source fr965.sourcePath = $(fr965.sourcePath);always-on-source fr265.sourcePath = $(fr265.sourcePath);always-on-source fr265s.sourcePath = $(fr265s.sourcePath);always-on-source - +marq2.sourcePath = $(marq2.sourcePath);always-on-source +marq2aviator.sourcePath = $(marq2aviator.sourcePath);always-on-source diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 05415b03..4820bcd3 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.16.3 + Crystal-Tesla V2.16.4 Theme Hours Colour diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 7c5502ab..3864b93d 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -4,6 +4,8 @@ using Toybox.Communications as Comms; using Toybox.Application as App; using Toybox.Time; using Toybox.Time.Gregorian; +using Toybox.Application.Storage; +using Toybox.Application.Properties; (:background) class BackgroundService extends Sys.ServiceDelegate { @@ -18,20 +20,20 @@ class BackgroundService extends Sys.ServiceDelegate { //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - if (App.getApp().getProperty("Tesla") == null) { + if (Storage.getValue("Tesla") == null) { return; } // Need to get a token since we can't OAUTH from a watch face :-( // If someone can do it, be my guest. I spent too much time on this already - _token = App.getApp().getProperty("TeslaAccessToken"); + _token = Properties.getValue("TeslaAccessToken"); - var createdAt = App.getApp().getProperty("TeslaTokenCreatedAt"); + var createdAt = Storage.getValue("TeslaTokenCreatedAt"); if (createdAt == null) { createdAt = 0; } - var expiresIn = App.getApp().getProperty("TeslaTokenExpiresIn"); + var expiresIn = Storage.getValue("TeslaTokenExpiresIn"); if (expiresIn == null) { expiresIn = 0; } @@ -49,7 +51,7 @@ class BackgroundService extends Sys.ServiceDelegate { } else { //2023-03-05 logMessage("initialize:Generating Access Token"); - var refreshToken = App.getApp().getProperty("TeslaRefreshToken"); + var refreshToken = Properties.getValue("TeslaRefreshToken"); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { @@ -58,11 +60,11 @@ class BackgroundService extends Sys.ServiceDelegate { return; } - _vehicle_id = App.getApp().getProperty("TeslaVehicleID"); + _vehicle_id = Storage.getValue("TeslaVehicleID"); if (_vehicle_id == null) { - makeTeslaWebRequest("https://" + App.getApp().getProperty("TeslaServerAPILocation") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + makeTeslaWebRequest("https://" + Properties.getValue("TeslaServerAPILocation") + "/api/1/vehicles", null, method(:onReceiveVehicles)); } else { - makeTeslaWebRequest("https://" + App.getApp().getProperty("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://" + Properties.getValue("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* @@ -74,7 +76,7 @@ class BackgroundService extends Sys.ServiceDelegate { // Pending web request flag will be cleared only once the background data has been successfully received. (:background_method) function onTemporalEvent() { - var pendingWebRequests = App.getApp().getProperty("PendingWebRequests"); + var pendingWebRequests = Storage.getValue("PendingWebRequests"); //2023-03-05 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); if (pendingWebRequests != null) { @@ -83,7 +85,7 @@ class BackgroundService extends Sys.ServiceDelegate { makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { - "city" => App.getApp().getProperty("LocalTimeInCity") + "city" => Properties.getValue("LocalTimeInCity") }, method(:onReceiveCityLocalTime) ); @@ -92,12 +94,12 @@ class BackgroundService extends Sys.ServiceDelegate { // 2. Weather. if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { - var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); + var owmKeyOverride = Properties.getValue("OWMKeyOverride"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", { - "lat" => App.getApp().getProperty("LastLocationLat"), - "lon" => App.getApp().getProperty("LastLocationLng"), + "lat" => Properties.getValue("LastLocationLat"), + "lon" => Properties.getValue("LastLocationLng"), // Polite request from Vince, developer of the Crystal Watch Face: // @@ -122,13 +124,13 @@ class BackgroundService extends Sys.ServiceDelegate { } // 3. Tesla - if (pendingWebRequests["TeslaInfo"] != null && App.getApp().getProperty("Tesla") != null) { + if (pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null) { if (!Sys.getDeviceSettings().phoneConnected) { return; } if (_vehicle_id) { - makeTeslaWebRequest("https://" + App.getApp().getProperty("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://" + Properties.getValue("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } } } /* else { @@ -252,7 +254,7 @@ class BackgroundService extends Sys.ServiceDelegate { // HTTP error: do not save. } else { - result = App.getApp().getProperty("OpenWeatherMapCurrent"); + result = Storage.getValue("OpenWeatherMapCurrent"); if (result) { result["cod"] = responseCode; } else { @@ -261,9 +263,9 @@ class BackgroundService extends Sys.ServiceDelegate { }; } - var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + /*var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); var dateStr = clockTime.year + " " + clockTime.month + " " + clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - Sys.println(dateStr + " : httpError=" + responseCode); + Sys.println(dateStr + " : httpError=" + responseCode);*/ } Bg.exit({ @@ -355,7 +357,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function makeTeslaWebPost(token, notify) { - var url = "https://" + App.getApp().getProperty("TeslaServerAUTHLocation") + "/oauth2/v3/token"; + var url = "https://" + Properties.getValue("TeslaServerAUTHLocation") + "/oauth2/v3/token"; Comms.makeWebRequest( url, { diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index b816a526..408a773b 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -4,6 +4,9 @@ using Toybox.System as Sys; using Toybox.WatchUi as Ui; using Toybox.Time; using Toybox.Time.Gregorian; +//using Toybox.Complications as Complications; +using Toybox.Application.Storage; +using Toybox.Application.Properties; import Toybox.Application; import Toybox.Lang; @@ -30,8 +33,19 @@ class CrystalApp extends App.AppBase { /* // onStart() is called on application start up function onStart(state) { + Complications.registerComplicationChangeCallback(self.method(:onComplicationUpdated)); } + function onComplicationUpdated(complicationId) { + if (mView != null) { + try { + mView.updateComplication(complicationId); + } catch (e) { + logMessage("error passing complication " + complicationId + " to watchface"); + } + } + } + // onStop() is called when your application is exiting function onStop(state) { } @@ -57,7 +71,7 @@ class CrystalApp extends App.AppBase { } function getIntProperty(key, defaultValue) { - var value = getProperty(key); + var value = Properties.getValue(key); if (value == null) { value = defaultValue; } else if (!(value instanceof Number)) { @@ -98,20 +112,19 @@ class CrystalApp extends App.AppBase { if (location[0] != 0.0 && location[1] != 0.0) { gLocationLat = location[0]; gLocationLng = location[1]; - - setProperty("LastLocationLat", gLocationLat); - setProperty("LastLocationLng", gLocationLng); + Properties.setValue("LastLocationLat", gLocationLat.format("%0.5f")); + Properties.setValue("LastLocationLng", gLocationLng.format("%0.5f")); } } // If current location is not available, read stored value from Object Store, being careful not to overwrite a valid // in-memory value with an invalid stored one. else { - var lat = getProperty("LastLocationLat"); + var lat = Properties.getValue("LastLocationLat"); if (lat != null) { gLocationLat = lat.toFloat(); } - var lng = getProperty("LastLocationLng"); + var lng = Properties.getValue("LastLocationLng"); if (lng != null) { gLocationLng = lng.toFloat(); } @@ -121,19 +134,19 @@ class CrystalApp extends App.AppBase { return; } - var pendingWebRequests = getProperty("PendingWebRequests"); + var pendingWebRequests = Storage.getValue("PendingWebRequests"); if (pendingWebRequests == null) { pendingWebRequests = {}; } // 1. City local time: // City has been specified. - var city = getProperty("LocalTimeInCity"); + var city = Properties.getValue("LocalTimeInCity"); // #78 Setting with value of empty string may cause corresponding property to be null. if ((city != null) && (city.length() > 0)) { - var cityLocalTime = getProperty("CityLocalTime"); + var cityLocalTime = Properties.getValue("CityLocalTime"); // No existing data. if ((cityLocalTime == null) || @@ -158,12 +171,12 @@ class CrystalApp extends App.AppBase { if ((gLocationLat != null) && (hasField(FIELD_TYPE_WEATHER) || hasField(FIELD_TYPE_HUMIDITY))) { - var owmKeyOverride = getProperty("OWMKeyOverride"); + var owmKeyOverride = Properties.getValue("OWMKeyOverride"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { //2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); } else { //2022-04-10 logMessage("Using OpenWeatherMap"); - var owmCurrent = getProperty("OpenWeatherMapCurrent"); + var owmCurrent = Storage.getValue("OpenWeatherMapCurrent"); // No existing data. if (owmCurrent == null) { @@ -190,8 +203,8 @@ class CrystalApp extends App.AppBase { //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - if (getProperty("Tesla") != null) { - var TeslaInfo = getProperty("TeslaInfo"); + if (Storage.getValue("Tesla") != null) { + var TeslaInfo = Storage.getValue("TeslaInfo"); if (TeslaInfo == null) { // We're not doing Tesla stuff so why asking for it, clear that pendingWebRequests["TeslaInfo"] = false; } else { // We're doing Tesla stuff @@ -206,10 +219,10 @@ class CrystalApp extends App.AppBase { var result = TeslaInfo["httpErrorTesla"]; if (result != null) { if (result == 400 || result == 401) { // Our token has expired, refresh it - setProperty("TeslaAccessToken", null); // Try to get a new vehicleID + Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID batterie_stale = true; } else if (result == 404) { // We got an vehicle not found error, reset our vehicle ID - setProperty("TeslaVehicleID", null); // Try to get a new vehicleID + Storage.setValue("TeslaVehicleID", null); // Try to get a new vehicleID batterie_stale = true; } else if (result == 408) { // Car is aslepep keep the old data but stop charging if it still was before going to sleep carAsleep = true; @@ -217,7 +230,7 @@ class CrystalApp extends App.AppBase { else { batterie_stale = true; } - setProperty("TeslaError", result); + Storage.setValue("TeslaError", result); } // Check if our access token was refreshed. If so, store the new access and refresh tokens @@ -227,14 +240,14 @@ class CrystalApp extends App.AppBase { var refreshToken = result["refresh_token"]; var expires_in = result["expires_in"]; var created_at = Time.now().value(); - setProperty("TeslaAccessToken", accessToken); + Properties.setValue("TeslaAccessToken", accessToken); if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem - setProperty("TeslaRefreshToken", refreshToken); + Properties.setValue("TeslaRefreshToken", refreshToken); } - setProperty("TeslaTokenExpiresIn", expires_in); - setProperty("TeslaTokenCreatedAt", created_at); + Storage.setValue("TeslaTokenExpiresIn", expires_in); + Storage.setValue("TeslaTokenCreatedAt", created_at); - setProperty("TeslaError", null); + Storage.setValue("TeslaError", null); } // If the car isn't asleep and we didn't get an error, read what was returned @@ -247,17 +260,17 @@ class CrystalApp extends App.AppBase { var inside_temp = TeslaInfo["inside_temp"]; if (inside_temp != null) { - setProperty("TeslaInsideTemp", inside_temp.toString()); + Storage.setValue("TeslaInsideTemp", inside_temp.toString()); } var precond_enabled = TeslaInfo["preconditioning"]; if (precond_enabled != null) { - setProperty("TeslaPreconditioning", precond_enabled.toString()); + Storage.setValue("TeslaPreconditioning", precond_enabled.toString()); } var sentry_enabled = TeslaInfo["sentry_enabled"]; if (sentry_enabled != null) { - setProperty("TeslaSentryEnabled", sentry_enabled.toString()); + Storage.setValue("TeslaSentryEnabled", sentry_enabled.toString()); } // Read its vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. @@ -265,9 +278,9 @@ class CrystalApp extends App.AppBase { var vehicle_id = TeslaInfo["vehicle_id"]; if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process if (vehicle_id != 0) { - setProperty("TeslaVehicleID", vehicle_id.toString()); + Storage.setValue("TeslaVehicleID", vehicle_id.toString()); } else { - setProperty("TeslaVehicleID", null); + Storage.setValue("TeslaVehicleID", null); batterie_stale = true; batterie_level = "N/A"; } @@ -277,20 +290,20 @@ class CrystalApp extends App.AppBase { // Here batterie_level is the same as what was read earlier or changed to N/A for some reason above. if (batterie_level != null) { - setProperty("TeslaBatterieLevel", batterie_level); - setProperty("TeslaBatterieStale", batterie_stale); - setProperty("TeslaChargingState", charging_state); + Storage.setValue("TeslaBatterieLevel", batterie_level); + Storage.setValue("TeslaBatterieStale", batterie_stale); + Storage.setValue("TeslaChargingState", charging_state); - setProperty("TeslaError", null); + Storage.setValue("TeslaError", null); } else { - setProperty("TeslaBatterieStale", true); - setProperty("TeslaError", null); + Storage.setValue("TeslaBatterieStale", true); + Storage.setValue("TeslaError", null); } } else if (!batterie_stale) { // Car is asleap, say so - setProperty("TeslaChargingState", "Sleeping"); - setProperty("TeslaBatterieStale", false); - setProperty("TeslaError", null); + Storage.setValue("TeslaChargingState", "Sleeping"); + Storage.setValue("TeslaBatterieStale", false); + Storage.setValue("TeslaError", null); } pendingWebRequests["TeslaInfo"] = true; @@ -316,7 +329,7 @@ class CrystalApp extends App.AppBase { } } - setProperty("PendingWebRequests", pendingWebRequests); + Storage.setValue("PendingWebRequests", pendingWebRequests); } (:background_method) @@ -331,13 +344,13 @@ class CrystalApp extends App.AppBase { (:background_method) function onBackgroundData(data) { //2022-04-10 logMessage("onBackgroundData:received '" + data + "'"); - var pendingWebRequests = getProperty("PendingWebRequests"); + var pendingWebRequests = Storage.getValue("PendingWebRequests"); if (pendingWebRequests == null) { pendingWebRequests = {}; } var type = data.keys()[0]; // Type of received data. - var storedData = getProperty(type); + var storedData = Storage.getValue(type); var receivedData = data[type]; // The actual data received: strip away type key. // Do process the data if what we got was an error @@ -345,8 +358,8 @@ class CrystalApp extends App.AppBase { // New data received: clear pendingWebRequests flag and overwrite stored data. storedData = receivedData; pendingWebRequests.remove(type); - setProperty("PendingWebRequests", pendingWebRequests); - setProperty(type, storedData); + Storage.setValue("PendingWebRequests", pendingWebRequests); + Storage.setValue(type, storedData); checkPendingWebRequests(); // We just got new data, process them right away before displaying } @@ -383,7 +396,7 @@ class CrystalApp extends App.AppBase { // #10 If in 12-hour mode with Hide Hours Leading Zero set, hide leading zero. Otherwise, show leading zero. // #69 Setting now applies to both 12- and 24-hour modes. - hour = hour.format(getProperty("HideHoursLeadingZero") ? INTEGER_FORMAT : "%02d"); + hour = hour.format(Properties.getValue("HideHoursLeadingZero") ? INTEGER_FORMAT : "%02d"); return { :hour => hour, diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 05805693..c97d2ccd 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -9,6 +9,9 @@ using Toybox.Time.Gregorian; using Toybox.Weather; using Toybox.Position; using Toybox.SensorHistory as SensorHistory; +using Toybox.Complications as Complications; +using Toybox.Application.Storage; +using Toybox.Application.Properties; using Toybox.Math; @@ -123,9 +126,9 @@ function writeBatteryLevel(dc, x, y, width, height, type) { gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 //logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); - batteryStale = App.getApp().getProperty("TeslaBatterieStale"); - chargingState = App.getApp().getProperty("TeslaChargingState"); - error = App.getApp().getProperty("TeslaError"); + batteryStale = Storage.getValue("TeslaBatterieStale"); + chargingState = Storage.getValue("TeslaChargingState"); + error = Storage.getValue("TeslaError"); if (chargingState != null) { if (chargingState.equals("Charging")) { @@ -143,10 +146,10 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var inText = null; switch (showMode) { case 0: - value = App.getApp().getProperty("TeslaBatterieLevel"); + value = Storage.getValue("TeslaBatterieLevel"); break; case 1: - value = App.getApp().getProperty("TeslaPreconditioning"); + value = Storage.getValue("TeslaPreconditioning"); if (value != null && value.equals("true")) { inText = "P on"; } @@ -158,7 +161,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { } break; case 2: - value = App.getApp().getProperty("TeslaSentryEnabled"); + value = Storage.getValue("TeslaSentryEnabled"); if (value != null && value.equals("true")) { inText = "S on"; } @@ -170,7 +173,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { } break; case 3: - value = App.getApp().getProperty("TeslaInsideTemp"); + value = Storage.getValue("TeslaInsideTemp"); break; } @@ -273,9 +276,20 @@ class CrystalView extends Ui.WatchFace { rereadWeatherMethod(); } + // callback that updates the complication value + /*function updateComplication(complication) { + var thisComplication = Complications.getComplication(complication); + var thisType = thisComplication.getType(); + + var value = thisComplication.value; + var label = thisComplication.shortLabel; + + logMessage(label + "=" + value); + }*/ + // Reread Weather method function rereadWeatherMethod() { - var owmKeyOverride = App.getApp().getProperty("OWMKeyOverride"); + var owmKeyOverride = Properties.getValue("OWMKeyOverride"); //2022-04-10 logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { if (Toybox has :Weather) { @@ -317,7 +331,7 @@ class CrystalView extends Ui.WatchFace { mDrawables[:MoveBar] = View.findDrawableById("MoveBar"); - setHideSeconds(App.getApp().getProperty("HideSeconds")); // Requires mTime, mDrawables[:MoveBar]; + setHideSeconds(Properties.getValue("HideSeconds")); // Requires mTime, mDrawables[:MoveBar]; } /* @@ -431,7 +445,7 @@ class CrystalView extends Ui.WatchFace { result = null; //2022-04-10 logMessage("No weather data, returning null"); } - App.getApp().setProperty("OpenWeatherMapCurrent", result); + Storage.setValue("OpenWeatherMapCurrent", result); } // Select normal font, based on whether time zone feature is being used. @@ -439,7 +453,7 @@ class CrystalView extends Ui.WatchFace { // Update drawables that use normal font. function updateNormalFont() { - var city = App.getApp().getProperty("LocalTimeInCity"); + var city = Properties.getValue("LocalTimeInCity"); // #78 Setting with value of empty string may cause corresponding property to be null. gNormalFont = Ui.loadResource(((city != null) && (city.length() > 0)) ? @@ -451,7 +465,7 @@ class CrystalView extends Ui.WatchFace { // #182 Protect against null or unexpected type e.g. String. var theme = App.getApp().getIntProperty("Theme", 0); var lightFlag; - var themeOverride = App.getApp().getProperty("ThemeOverride"); + var themeOverride = Properties.getValue("ThemeOverride"); if (themeOverride.equals("")) { // Theme-specific colours. gThemeColour = [ @@ -494,7 +508,7 @@ class CrystalView extends Ui.WatchFace { lightFlag = lightFlags[theme]; } else { gThemeColour = themeOverride.toNumberWithBase(16); - lightFlag = App.getApp().getProperty("ThemeLightOverride"); + lightFlag = Properties.getValue("ThemeLightOverride"); } // #124: fr45 cannot show grey. SG Fr45 not supported @@ -548,7 +562,7 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, and watch is sleeping, do not show seconds immediately, as they will not // update. Instead, wait for next onExitSleep(). if (PER_SECOND_UPDATES_SUPPORTED || !mIsSleeping) { - setHideSeconds(App.getApp().getProperty("HideSeconds")); + setHideSeconds(Properties.getValue("HideSeconds")); } mSettingsChangedSinceLastDraw = false; @@ -590,11 +604,11 @@ class CrystalView extends Ui.WatchFace { return; } - var leftType = App.getApp().getProperty("LeftGoalType"); + var leftType = Properties.getValue("LeftGoalType"); var leftValues = getValuesForGoalType(leftType); mDrawables[:LeftGoalMeter].setValues(leftValues[:current], leftValues[:max], /* isOff */ leftType == GOAL_TYPE_OFF); - var rightType = App.getApp().getProperty("RightGoalType"); + var rightType = Properties.getValue("RightGoalType"); var rightValues = getValuesForGoalType(rightType); mDrawables[:RightGoalMeter].setValues(rightValues[:current], rightValues[:max], /* isOff */ rightType == GOAL_TYPE_OFF); @@ -791,7 +805,7 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, AND HideSeconds property is false, // show seconds, and make move bar original width. - var hideSeconds = App.getApp().getProperty("HideSeconds"); + var hideSeconds = Properties.getValue("HideSeconds"); if ((!PER_SECOND_UPDATES_SUPPORTED && hideSeconds == 0) || hideSeconds == 1 ) { setHideSeconds(false); } @@ -825,7 +839,7 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, then hide seconds, and make move bar full width. // onUpdate() is about to be called one final time before entering sleep. // If HideSeconds property is true, do not wastefully hide seconds again (they should already be hidden). - var hideSeconds = App.getApp().getProperty("HideSeconds"); + var hideSeconds = Properties.getValue("HideSeconds"); if ((!PER_SECOND_UPDATES_SUPPORTED && hideSeconds == 0) || hideSeconds == 1) { setHideSeconds(true); } @@ -860,32 +874,33 @@ class CrystalView extends Ui.WatchFace { } } -/*class CrystalDelegate extends Ui.WatchFaceDelegate { - private var _view as CrystalView; - - //! Constructor - //! @param view The analog view - public function initialize(view as CrystalView) { - WatchFaceDelegate.initialize(); - _view = view; - } - - public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { - System.println("onPress called!!!"); - } - - //! The onPowerBudgetExceeded callback is called by the system if the - //! onPartialUpdate method exceeds the allowed power budget. If this occurs, - //! the system will stop invoking onPartialUpdate each second, so we notify the - //! view here to let the rendering methods know they should not be rendering a - //! second hand. - //! @param powerInfo Information about the power budget - public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { - System.println("Average execution time: " + powerInfo.executionTimeAverage); - System.println("Allowed execution time: " + powerInfo.executionTimeLimit); - //_view.turnPartialUpdatesOff(); - } -}*/ +// class CrystalDelegate extends Ui.WatchFaceDelegate { +// private var _view as CrystalView; + +// //! Constructor +// //! @param view The analog view +// public function initialize(view as CrystalView) { +// WatchFaceDelegate.initialize(); +// _view = view; +// } + +// public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { +// var complication = /*Complications.getComplication(*/new Complications.Id(Complications.COMPLICATION_TYPE_HEART_RATE)/*)*/; +// System.println("onPress called!!!"); +// } + +// //! The onPowerBudgetExceeded callback is called by the system if the +// //! onPartialUpdate method exceeds the allowed power budget. If this occurs, +// //! the system will stop invoking onPartialUpdate each second, so we notify the +// //! view here to let the rendering methods know they should not be rendering a +// //! second hand. +// //! @param powerInfo Information about the power budget +// public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { +// System.println("Average execution time: " + powerInfo.executionTimeAverage); +// System.println("Allowed execution time: " + powerInfo.executionTimeLimit); +// //_view.turnPartialUpdatesOff(); +// } +// } /* function type_name(obj) { diff --git a/source/DataArea.mc b/source/DataArea.mc index 4dcb7258..8fa0e114 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -4,6 +4,8 @@ using Toybox.Application as App; using Toybox.System as Sys; using Toybox.Time; using Toybox.Time.Gregorian; +using Toybox.Application.Storage; +using Toybox.Application.Properties; class DataArea extends Ui.Drawable { @@ -67,12 +69,12 @@ class DataArea extends Ui.Drawable { drawGoalIcon(dc, mGoalIconLeftX, mLeftGoalType, mLeftGoalIsValid, mLeftGoalstaled, Graphics.TEXT_JUSTIFY_LEFT); drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, mRightGoalstaled, Graphics.TEXT_JUSTIFY_RIGHT); - var city = App.getApp().getProperty("LocalTimeInCity"); + var city = Properties.getValue("LocalTimeInCity"); // #78 Setting with value of empty string may cause corresponding property to be null. if ((city != null) && (city.length() != 0)) { //drawTimeZone(); - var cityLocalTime = App.getApp().getProperty("CityLocalTime"); + var cityLocalTime = Properties.getValue("CityLocalTime"); // If available, use city returned from web request; otherwise, use raw city from settings. // N.B. error response will NOT contain city. @@ -168,7 +170,7 @@ class DataArea extends Ui.Drawable { } function drawGoalValues(dc, x, currentValue, maxValue, align) { - var digitStyle = App.getApp().getProperty("GoalMeterDigitsStyle"); + var digitStyle = Properties.getValue("GoalMeterDigitsStyle"); // #107 Only draw values if digit style is not Hidden. if (digitStyle != 2 /* HIDDEN */) { diff --git a/source/DataFields.mc b/source/DataFields.mc index 767d11d9..17e87854 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -6,9 +6,10 @@ using Toybox.Activity as Activity; using Toybox.ActivityMonitor as ActivityMonitor; using Toybox.SensorHistory as SensorHistory; using Toybox.Math; - using Toybox.Time; using Toybox.Time.Gregorian; +using Toybox.Application.Storage; +using Toybox.Application.Properties; enum /* FIELD_TYPES */ { // Pseudo-fields. @@ -529,9 +530,9 @@ class DataFields extends Ui.Drawable { } if (altitude == null) { // If we didn't get an altitude this time, grab the saved one - altitude = App.getApp().getProperty("LastAltitude"); + altitude = Storage.getValue("LastAltitude"); } else { // We got altitude info, store it in case we lose it - App.getApp().setProperty("LastAltitude", altitude); + Properties.Storage("LastAltitude", altitude); } if (altitude != null) { // If we didn't get an altitude this time, grab the saved one @@ -637,7 +638,7 @@ class DataFields extends Ui.Drawable { result["weatherIcon"] = "01d"; } - weather = App.getApp().getProperty("OpenWeatherMapCurrent"); + weather = Storage.getValue("OpenWeatherMapCurrent"); // Awaiting location. if (gLocationLat == null) { @@ -667,8 +668,8 @@ class DataFields extends Ui.Drawable { } // Awaiting response. - } else if ((App.getApp().getProperty("PendingWebRequests") != null) && - App.getApp().getProperty("PendingWebRequests")["OpenWeatherMapCurrent"] != null) { + } else if ((Storage.getValue("PendingWebRequests") != null) && + Storage.getValue("PendingWebRequests")["OpenWeatherMapCurrent"] != null) { value = "..."; diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index 21468245..af280e00 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -2,6 +2,8 @@ using Toybox.WatchUi as Ui; using Toybox.System as Sys; using Toybox.Application as App; using Toybox.Graphics; +using Toybox.Application.Storage; +using Toybox.Application.Properties; // const MIN_WHOLE_SEGMENT_HEIGHT = 5; @@ -112,7 +114,7 @@ class GoalMeter extends Ui.Drawable { // #18 Only read separator width from layout if multi segment style is selected. // #62 Or if filled segment style is selected. - var goalMeterStyle = App.getApp().getProperty("GoalMeterStyle"); + var goalMeterStyle = Properties.getValue("GoalMeterStyle"); if ((goalMeterStyle == 0 /* ALL_SEGMENTS */) || (goalMeterStyle == 3 /* FILLED_SEGMENTS */)) { // Force recalculation of mSegments in setValues() if mSeparator is about to change. @@ -145,7 +147,7 @@ class GoalMeter extends Ui.Drawable { function draw(dc) { // #114 TODO: Any buffers not yet reclaimed if goal meter set to off. - if ((App.getApp().getProperty("GoalMeterStyle") == 2 /* HIDDEN */) || mIsOff) { + if ((Properties.getValue("GoalMeterStyle") == 2 /* HIDDEN */) || mIsOff) { return; } @@ -167,7 +169,7 @@ class GoalMeter extends Ui.Drawable { // Unfilled segments: fill height --> height. // #62 ALL_SEGMENTS or ALL_SEGMENTS_MERGED. - if (App.getApp().getProperty("GoalMeterStyle") <= 1) { + if (Properties.getValue("GoalMeterStyle") <= 1) { drawSegments(dc, left, top, gMeterBackgroundColour, mSegments, mFillHeight, mHeight); } } @@ -243,7 +245,7 @@ class GoalMeter extends Ui.Drawable { // Draw unfilled segments. // #62 ALL_SEGMENTS or ALL_SEGMENTS_MERGED. - if (App.getApp().getProperty("GoalMeterStyle") <= 1) { + if (Properties.getValue("GoalMeterStyle") <= 1) { clipBottom = clipTop; clipTop = top; clipHeight = clipBottom - clipTop; diff --git a/source/Indicators.mc b/source/Indicators.mc index 083793d3..201b490a 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -2,6 +2,8 @@ using Toybox.WatchUi as Ui; using Toybox.Graphics as Gfx; using Toybox.System as Sys; using Toybox.Application as App; +using Toybox.Application.Storage; +using Toybox.Application.Properties; class Indicators extends Ui.Drawable { @@ -36,18 +38,18 @@ class Indicators extends Ui.Drawable { } function onSettingsChanged() { - mIndicator1Type = App.getApp().getProperty("Indicator1Type"); - mIndicator2Type = App.getApp().getProperty("Indicator2Type"); - mIndicator3Type = App.getApp().getProperty("Indicator3Type"); + mIndicator1Type = Properties.getValue("Indicator1Type"); + mIndicator2Type = Properties.getValue("Indicator2Type"); + mIndicator3Type = Properties.getValue("Indicator3Type"); //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** if (mIndicator1Type == 6 || mIndicator2Type == 6 || mIndicator3Type == 6) { - App.getApp().setProperty("Tesla", true); + Storage.setValue("Tesla", true); //logMessage("onSettingsChanged:Doing Tesla!"); } else { - App.getApp().setProperty("Tesla", null); + Storage.setValue("Tesla", null); } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* diff --git a/source/MoveBar.mc b/source/MoveBar.mc index 4e73e712..8bea2c95 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -3,6 +3,8 @@ using Toybox.System as Sys; using Toybox.Application as App; using Toybox.ActivityMonitor as ActivityMonitor; using Toybox.Graphics; +using Toybox.Application.Storage; +using Toybox.Application.Properties; class MoveBar extends Ui.Drawable { @@ -52,7 +54,7 @@ class MoveBar extends Ui.Drawable { } function draw(dc) { - if (App.getApp().getProperty("MoveBarStyle") == 2 /* HIDDEN */) { + if (Properties.getValue("MoveBarStyle") == 2 /* HIDDEN */) { return; } @@ -135,7 +137,7 @@ class MoveBar extends Ui.Drawable { var thisBarWidth; var thisBarColour = 0; var barX = x + mTailWidth; - var moveBarStyle = App.getApp().getProperty("MoveBarStyle"); + var moveBarStyle = Properties.getValue("MoveBarStyle"); // One-based, to correspond with move bar level (zero means no bars). for (var i = 1; i <= ActivityMonitor.MOVE_BAR_LEVEL_MAX; ++i) { diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index e0feb226..ff127ef4 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -1,6 +1,8 @@ using Toybox.WatchUi as Ui; using Toybox.System as Sys; using Toybox.Application as App; +using Toybox.Application.Storage; +using Toybox.Application.Properties; class ThickThinTime extends Ui.Drawable { @@ -87,7 +89,7 @@ class ThickThinTime extends Ui.Drawable { ); x += dc.getTextWidthInPixels(hours, mHoursFont); - if (App.getApp().getProperty("AddColon")) { + if (Properties.getValue("AddColon")) { dc.drawText( x, halfDCHeight, From 1ca50c0e7901d91c4cd8925d4fb261dbe08a57b4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 15 Apr 2023 20:44:52 -0400 Subject: [PATCH 112/220] Update DataFields.mc --- source/DataFields.mc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/DataFields.mc b/source/DataFields.mc index 17e87854..92e2ce72 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -532,7 +532,7 @@ class DataFields extends Ui.Drawable { if (altitude == null) { // If we didn't get an altitude this time, grab the saved one altitude = Storage.getValue("LastAltitude"); } else { // We got altitude info, store it in case we lose it - Properties.Storage("LastAltitude", altitude); + Storage.setValue("LastAltitude", altitude); } if (altitude != null) { // If we didn't get an altitude this time, grab the saved one From 39c23c3a94d58f00b5611273de550d8dfa54e9fa Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 16 Apr 2023 13:57:48 -0400 Subject: [PATCH 113/220] 2.16.5 - Fixed a crash when entering a City in the "Add a local time in City" --- resources/strings/strings.xml | 2 +- source/CrystalApp.mc | 2 +- source/DataArea.mc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 4820bcd3..234e8b94 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.16.4 + Crystal-Tesla V2.16.5 Theme Hours Colour diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 408a773b..475a04c8 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -146,7 +146,7 @@ class CrystalApp extends App.AppBase { // #78 Setting with value of empty string may cause corresponding property to be null. if ((city != null) && (city.length() > 0)) { - var cityLocalTime = Properties.getValue("CityLocalTime"); + var cityLocalTime = Storage.getValue("CityLocalTime"); // No existing data. if ((cityLocalTime == null) || diff --git a/source/DataArea.mc b/source/DataArea.mc index 8fa0e114..333a64e6 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -74,7 +74,7 @@ class DataArea extends Ui.Drawable { // #78 Setting with value of empty string may cause corresponding property to be null. if ((city != null) && (city.length() != 0)) { //drawTimeZone(); - var cityLocalTime = Properties.getValue("CityLocalTime"); + var cityLocalTime = Storage.getValue("CityLocalTime"); // If available, use city returned from web request; otherwise, use raw city from settings. // N.B. error response will NOT contain city. From 72cbc892d682063b6c5eff75b62f7cf36aedce5b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 20 Apr 2023 00:02:58 -0400 Subject: [PATCH 114/220] 2.16.5a - Fixed two crashes reported through the Error Reporting Application --- README.md | 6 ++++++ resources/strings/strings.xml | 2 +- source/DataFields.mc | 13 +++++++++---- source/ThickThinTime.mc | 3 ++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3ee5e06f..763704b8 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.16.5a +- Fixed two crashes reported through the Error Reporting Application + +### 2.16.5 +- Fixed a crash when entering a City in the "Add a local time in City" + ### 2.16.4 - Recompiled with ConnectIQ4.2.4 since that wasn't the issue with the save settings. It was because watches with ICQ 4.2.0+ didn't support the getProperties/setProperties functions that were used throughout the app. I replaced them all with their corresponding Storage or Properties (for settings) getValue/setValue and was finally able to save the settings on my new Venu2. I was unable to reproduce on my old Venu since it was released pre 4.2.0. - Added the MARQ® (Gen 2) Athlete / Adventurer / Captain / Golfer / Aviator watches diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 234e8b94..e5069c31 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.16.5 + Crystal-Tesla V2.16.5a Theme Hours Colour diff --git a/source/DataFields.mc b/source/DataFields.mc index 92e2ce72..107fb00d 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -649,12 +649,17 @@ class DataFields extends Ui.Drawable { // FIELD_TYPE_WEATHER. if (type == FIELD_TYPE_WEATHER) { weatherValue = weather["temp"]; // Celcius. + try { + if (settings.temperatureUnits == System.UNIT_STATUTE) { + weatherValue = (weatherValue * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + } - if (settings.temperatureUnits == System.UNIT_STATUTE) { - weatherValue = (weatherValue * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + value = weatherValue.format(INTEGER_FORMAT) + "°"; + } + catch (e) { + //DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); + value = "???"; } - - value = weatherValue.format(INTEGER_FORMAT) + "°"; result["weatherIcon"] = weather["icon"]; // FIELD_TYPE_HUMIDITY. diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index ff127ef4..c6d1bf40 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -89,7 +89,8 @@ class ThickThinTime extends Ui.Drawable { ); x += dc.getTextWidthInPixels(hours, mHoursFont); - if (Properties.getValue("AddColon")) { + var addColon = Properties.getValue("AddColon"); + if (addColon != null && addColon == true) { dc.drawText( x, halfDCHeight, From 598a805c22ae4cefa40a30a7eb7b9aafc5a9a672 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 26 Apr 2023 19:32:46 -0400 Subject: [PATCH 115/220] 2.16.5b Fixed a crash reported through the Error Reporting Application (ERA) --- README.md | 5 ++++- source/ThickThinTime.mc | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 763704b8..d953cee7 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,11 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.16.5b +- Fixed a crash reported through the Error Reporting Application (ERA) + ### 2.16.5a -- Fixed two crashes reported through the Error Reporting Application +- Fixed two crashes reported through the Error Reporting Application (ERA) ### 2.16.5 - Fixed a crash when entering a City in the "Add a local time in City" diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index c6d1bf40..c0605ebc 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -89,7 +89,13 @@ class ThickThinTime extends Ui.Drawable { ); x += dc.getTextWidthInPixels(hours, mHoursFont); - var addColon = Properties.getValue("AddColon"); + var addColon; + try { + addColon = Properties.getValue("AddColon"); + } + catch (e) { + addColon = false; + } if (addColon != null && addColon == true) { dc.drawText( x, From a917d15e431d86c03e847489a8c95e068a28f1b4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 26 Apr 2023 19:34:31 -0400 Subject: [PATCH 116/220] Update strings.xml --- resources/strings/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index e5069c31..418e15c9 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.16.5a + Crystal-Tesla V2.16.5b Theme Hours Colour From d1266be0fbd63bf3eaa5affd92306f06cb603dd1 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 1 May 2023 01:35:41 -0400 Subject: [PATCH 117/220] V2.17.0 interim - Tesla-Info now support launching the main Tesla-Link App from the watch face. - Heart rate, PulseOx, BodyBattery and Stress Level are now read through complications if available - Complication read fields will launch their widget when long pressed. Applies to Fields, Indicators (for Tesla-Info only for now) and Goals. --- README.md | 5 + manifest.xml | 1 + resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 56 ++++---- source/CrystalApp.mc | 38 ++---- source/CrystalView.mc | 250 +++++++++++++++++++++++++++++----- source/DataArea.mc | 6 +- source/DataFields.mc | 116 ++++++++++++---- source/GoalMeter.mc | 34 +++++ source/Indicators.mc | 41 ++++-- 10 files changed, 424 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index d953cee7..f16d7494 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,11 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.17.0 +- Tesla-Info now support launching the main Tesla-Link App from the watch face. +- Heart rate, PulseOx, BodyBattery and Stress Level are now read through complications if available +- Complication read fields will launch their widget when long pressed. Applies to Fields, Indicators (for Tesla-Info only for now) and Goals. + ### 2.16.5b - Fixed a crash reported through the Error Reporting Application (ERA) diff --git a/manifest.xml b/manifest.xml index 9c0820f8..8ffece69 100644 --- a/manifest.xml +++ b/manifest.xml @@ -82,6 +82,7 @@ + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 418e15c9..e9f8b01c 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.16.5b + Crystal-Tesla V2.17.0 Theme Hours Colour diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 3864b93d..68c95ebb 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -95,32 +95,36 @@ class BackgroundService extends Sys.ServiceDelegate { // 2. Weather. if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { var owmKeyOverride = Properties.getValue("OWMKeyOverride"); - makeWebRequest( - "https://api.openweathermap.org/data/2.5/weather", - { - "lat" => Properties.getValue("LastLocationLat"), - "lon" => Properties.getValue("LastLocationLng"), - - // Polite request from Vince, developer of the Crystal Watch Face: - // - // Please do not abuse this API key, or else I will be forced to make thousands of users of Crystal - // sign up for their own Open Weather Map free account, and enter their key in settings - a much worse - // user experience for everyone. - // - // Crystal has been registered with OWM on the Open Source Plan, which lifts usage limits for free, so - // that everyone benefits. However, these lifted limits only apply to the Current Weather API, and *not* - // the One Call API. Usage of this key for the One Call API risks blocking the key for everyone. - // - // If you intend to use this key in your own app, especially for the One Call API, please create your own - // OWM account, and own key. You should be able to apply for the Open Source Plan to benefit from the same - // lifted limits as Crystal. Thank you. - "appid" => ((owmKeyOverride != null) && (owmKeyOverride.length() == 0)) ? "2651f49cb20de925fc57590709b86ce6" : owmKeyOverride, - - "units" => "metric" // Celcius. - }, - method(:onReceiveOpenWeatherMapCurrent) - ); - + var lat = Properties.getValue("LastLocationLat"); + var lon = Properties.getValue("LastLocationLng"); + + if (lat != null && lon != null) { + makeWebRequest( + "https://api.openweathermap.org/data/2.5/weather", + { + "lat" => lat, + "lon" => lon, + + // Polite request from Vince, developer of the Crystal Watch Face: + // + // Please do not abuse this API key, or else I will be forced to make thousands of users of Crystal + // sign up for their own Open Weather Map free account, and enter their key in settings - a much worse + // user experience for everyone. + // + // Crystal has been registered with OWM on the Open Source Plan, which lifts usage limits for free, so + // that everyone benefits. However, these lifted limits only apply to the Current Weather API, and *not* + // the One Call API. Usage of this key for the One Call API risks blocking the key for everyone. + // + // If you intend to use this key in your own app, especially for the One Call API, please create your own + // OWM account, and own key. You should be able to apply for the Open Source Plan to benefit from the same + // lifted limits as Crystal. Thank you. + "appid" => ((owmKeyOverride == null) || (owmKeyOverride.length() == 0)) ? "2651f49cb20de925fc57590709b86ce6" : owmKeyOverride, + + "units" => "metric" // Celcius. + }, + method(:onReceiveOpenWeatherMapCurrent) + ); + } } // 3. Tesla diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 475a04c8..3c30500f 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -4,9 +4,9 @@ using Toybox.System as Sys; using Toybox.WatchUi as Ui; using Toybox.Time; using Toybox.Time.Gregorian; -//using Toybox.Complications as Complications; using Toybox.Application.Storage; using Toybox.Application.Properties; +using Toybox.Complications; import Toybox.Application; import Toybox.Lang; @@ -28,42 +28,34 @@ class CrystalApp extends App.AppBase { function initialize() { AppBase.initialize(); + + mFieldTypes[0] = {}; + mFieldTypes[1] = {}; + mFieldTypes[2] = {}; } - /* // onStart() is called on application start up function onStart(state) { - Complications.registerComplicationChangeCallback(self.method(:onComplicationUpdated)); } - function onComplicationUpdated(complicationId) { - if (mView != null) { - try { - mView.updateComplication(complicationId); - } catch (e) { - logMessage("error passing complication " + complicationId + " to watchface"); - } - } - } - // onStop() is called when your application is exiting function onStop(state) { } - */ + // Return the initial view of your application here function getInitialView() { - /*if (WatchUi has :WatchFaceDelegate) { + if (WatchUi has :WatchFaceDelegate) { mView = new CrystalView(); onSettingsChanged(); // After creating view. var delegate = new CrystalDelegate(mView); return [mView, delegate] as Array; } - else {*/ + else { mView = new CrystalView(); onSettingsChanged(); // After creating view. return [mView]; - //} + } } function getView() { @@ -82,9 +74,9 @@ class CrystalApp extends App.AppBase { // New app settings have been received so trigger a UI update function onSettingsChanged() { - mFieldTypes[0] = getIntProperty("Field1Type", 0); - mFieldTypes[1] = getIntProperty("Field2Type", 1); - mFieldTypes[2] = getIntProperty("Field3Type", 2); + mFieldTypes[0].put("type", getIntProperty("Field1Type", 0)); + mFieldTypes[1].put("type", getIntProperty("Field2Type", 1)); + mFieldTypes[2].put("type", getIntProperty("Field3Type", 2)); mView.onSettingsChanged(); // Calls checkPendingWebRequests(). @@ -92,9 +84,9 @@ class CrystalApp extends App.AppBase { } function hasField(fieldType) { - return ((mFieldTypes[0] == fieldType) || - (mFieldTypes[1] == fieldType) || - (mFieldTypes[2] == fieldType)); + return ((mFieldTypes[0].get("type") == fieldType) || + (mFieldTypes[1].get("type") == fieldType) || + (mFieldTypes[2].get("type") == fieldType)); } // Determine if any web requests are needed. diff --git a/source/CrystalView.mc b/source/CrystalView.mc index c97d2ccd..a7dc9c70 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -12,6 +12,7 @@ using Toybox.SensorHistory as SensorHistory; using Toybox.Complications as Complications; using Toybox.Application.Storage; using Toybox.Application.Properties; +using Toybox.Complications; using Toybox.Math; @@ -232,6 +233,36 @@ function writeBatteryLevel(dc, x, y, width, height, type) { //**************************************************************** } +function updateComplications(complicationName, storageName, index, complicationType) { + if (Toybox has :Complications) { + // Check if we should subscribe to our Tesla Complication + var iter = Complications.getComplications(); + var complicationId = iter.next(); + + while (complicationId != null) { + //logMessage(complicationId.longLabel.toString()); + if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel.equals(complicationName))) { + break; + } + complicationId = iter.next(); + } + + if (complicationId != null) { + if (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID) { + complicationId = complicationId.complicationId; + } + else { + complicationId = new Complications.Id(complicationType); + } + if (index != null) { + Storage.setValue(storageName + index, complicationId); + Complications.subscribeToUpdates(complicationId); + } + } + } +} + + class CrystalView extends Ui.WatchFace { private var mIsSleeping = false; private var mIsBurnInProtection = false; // Is burn-in protection required and active? @@ -241,7 +272,7 @@ class CrystalView extends Ui.WatchFace { var mDataFields; var mHasGarminWeather; // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); - private var mDrawables = {}; + var mDrawables = {}; // N.B. Not all watches that support SDK 2.3.0 support per-second updates e.g. 735xt. private const PER_SECOND_UPDATES_SUPPORTED = Ui.WatchFace has :onPartialUpdate; @@ -277,7 +308,7 @@ class CrystalView extends Ui.WatchFace { } // callback that updates the complication value - /*function updateComplication(complication) { + function updateComplication(complication) { var thisComplication = Complications.getComplication(complication); var thisType = thisComplication.getType(); @@ -285,7 +316,7 @@ class CrystalView extends Ui.WatchFace { var label = thisComplication.shortLabel; logMessage(label + "=" + value); - }*/ + } // Reread Weather method function rereadWeatherMethod() { @@ -366,8 +397,44 @@ class CrystalView extends Ui.WatchFace { if (mHasGarminWeather == true) { // Using the Garmin Weather stuff ReadWeather(); } + + // Reread our complications + if (Toybox has :Complications) { + // First we drop all our subscriptions before building a new list + Complications.unsubscribeFromAllUpdates(); + Complications.registerComplicationChangeCallback(self.method(:onComplicationUpdated)); + } + } + function onComplicationUpdated(complicationId) { + var complication = Complications.getComplication(complicationId); + var complicationType = complication.getType(); + var complicationLabel = complication.shortLabel; + var complicationValue = complication.value; + +// logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue); + + // Do fields first + var fieldCount = App.getApp().getIntProperty("FieldCount", 3); + var fieldTypes = App.getApp().mFieldTypes; + + for (var i = 0; i < fieldCount; i++) { + if (fieldTypes[i].get("ComplicationType") == complicationType) { + fieldTypes[i].put("ComplicationValue", complicationValue); + break; + } + } + + // Now do goals + if (mDrawables[:LeftGoalMeter].mComplicationType == complicationType) { + mDrawables[:LeftGoalMeter].mComplicationValue = complicationValue; + } + if (mDrawables[:RightGoalMeter].mComplicationType == complicationType) { + mDrawables[:RightGoalMeter].mComplicationValue = complicationValue; + } + } + // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see function ReadWeather() { var weather = Weather.getCurrentConditions(); @@ -559,6 +626,9 @@ class CrystalView extends Ui.WatchFace { mDrawables[:Indicators].onSettingsChanged(); } + mDrawables[:LeftGoalMeter].setComplication(1); + mDrawables[:RightGoalMeter].setComplication(2); + // If watch does not support per-second updates, and watch is sleeping, do not show seconds immediately, as they will not // update. Instead, wait for next onExitSleep(). if (PER_SECOND_UPDATES_SUPPORTED || !mIsSleeping) { @@ -605,17 +675,17 @@ class CrystalView extends Ui.WatchFace { } var leftType = Properties.getValue("LeftGoalType"); - var leftValues = getValuesForGoalType(leftType); + var leftValues = getValuesForGoalType(0, leftType); mDrawables[:LeftGoalMeter].setValues(leftValues[:current], leftValues[:max], /* isOff */ leftType == GOAL_TYPE_OFF); var rightType = Properties.getValue("RightGoalType"); - var rightValues = getValuesForGoalType(rightType); + var rightValues = getValuesForGoalType(1, rightType); mDrawables[:RightGoalMeter].setValues(rightValues[:current], rightValues[:max], /* isOff */ rightType == GOAL_TYPE_OFF); mDrawables[:DataArea].setGoalValues(leftType, leftValues, rightType, rightValues); } - function getValuesForGoalType(type) { + function getValuesForGoalType(index, type) { var values = { :current => 0, :max => 1, @@ -661,7 +731,14 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = false; values[:max] = 100; - if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { + if (Toybox has :Complications) { + var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + if (tmpValue != null) { + values[:current] = tmpValue.toFloat(); + values[:isValid] = true; + } + } + if (values[:isValid] == false && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { var bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); if (bodyBattery != null) { bodyBattery = bodyBattery.next(); @@ -682,7 +759,14 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = false; values[:max] = 100; - if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { + if (Toybox has :Complications) { + var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + if (tmpValue != null) { + values[:current] = tmpValue.toFloat(); + values[:isValid] = true; + } + } + if (values[:isValid] == false && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { var stressLevel = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); //DEBUG*/ var stressLevelDate = 0; @@ -874,33 +958,129 @@ class CrystalView extends Ui.WatchFace { } } -// class CrystalDelegate extends Ui.WatchFaceDelegate { -// private var _view as CrystalView; - -// //! Constructor -// //! @param view The analog view -// public function initialize(view as CrystalView) { -// WatchFaceDelegate.initialize(); -// _view = view; -// } - -// public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { -// var complication = /*Complications.getComplication(*/new Complications.Id(Complications.COMPLICATION_TYPE_HEART_RATE)/*)*/; -// System.println("onPress called!!!"); -// } - -// //! The onPowerBudgetExceeded callback is called by the system if the -// //! onPartialUpdate method exceeds the allowed power budget. If this occurs, -// //! the system will stop invoking onPartialUpdate each second, so we notify the -// //! view here to let the rendering methods know they should not be rendering a -// //! second hand. -// //! @param powerInfo Information about the power budget -// public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { -// System.println("Average execution time: " + powerInfo.executionTimeAverage); -// System.println("Allowed execution time: " + powerInfo.executionTimeLimit); -// //_view.turnPartialUpdatesOff(); -// } -// } +class CrystalDelegate extends Ui.WatchFaceDelegate { + private var mview as CrystalView; + + //! Constructor + //! @param view The analog view + public function initialize(view as CrystalView) { + WatchFaceDelegate.initialize(); + mview = view; + } + + public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { + var co_ords = clickEvent.getCoordinates(); + logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + + // returns the complicationId within the boundingBoxes + var complicationId = checkBoundingBoxes(co_ords); + if (complicationId != null) { + Complications.exitTo(complicationId); + } + } + + function checkBoundingBoxes(co_ords) { + // First check the indicators + var indicatorCount = App.getApp().getIntProperty("IndicatorCount", 1); + var spacing; + var complicationIndex; + var complicationId; + + if (indicatorCount > 0) { + var indicators = mview.mDrawables[:Indicators]; + var locX = indicators[:locX]; + var locY = indicators[:locY]; + var batteryWidth = indicators[:mBatteryWidth]; + + spacing = indicators[:mSpacing]; + locX -= batteryWidth / 2; + locY -= batteryWidth / 2; + + if (indicatorCount == 3) { + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacing, spacing, "1") + isWithin(co_ords[0], co_ords[1], locX, locY, spacing, "2") + isWithin(co_ords[0], co_ords[1], locX, locY + spacing, spacing, "3"); + } else if (indicatorCount == 2) { + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacing / 2, spacing, "1") + isWithin(co_ords[0], co_ords[1], locX, locY + spacing / 2, spacing, "2"); + } else if (indicatorCount == 1) { + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY, spacing, "1"); + } + + if (complicationIndex.equals("Complication_I") == false) { + complicationId = Storage.getValue(complicationIndex); + } + + logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } + } + + spacing = Sys.getDeviceSettings().screenWidth / 12; + + // Check the fields + var fieldCount = App.getApp().getIntProperty("FieldCount", 3); + if (fieldCount > 0) { + var left = mview.mDataFields.mLeft; + var right = mview.mDataFields.mRight; + var top = mview.mDataFields.mTop; + + if (fieldCount == 3) { + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left - spacing, top - spacing, spacing * 2, "1") + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacing, top - spacing, spacing * 2, "2") + isWithin(co_ords[0], co_ords[1], right - spacing, top - spacing, spacing * 2, "3"); + } else if (fieldCount == 2) { + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.15) - spacing, top - spacing, spacing * 2, "1") + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.85) - spacing, top - spacing, spacing * 2, "2"); + } else if (fieldCount == 1) { + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacing, top - spacing, spacing * 2, "1"); + } + + if (complicationIndex.equals("Complication_F") == false) { + complicationId = Storage.getValue(complicationIndex); + } + + logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } + } + + // Check the goals + var left = mview.mDrawables[:DataArea].mGoalIconLeftX; + var right = mview.mDrawables[:DataArea].mGoalIconRightX; + var y = mview.mDrawables[:DataArea].mGoalIconY; + + // spacing * 3 to give it more room so we can press on the text too. + complicationIndex = "Complication_G" + isWithin(co_ords[0], co_ords[1], left, y, spacing * 3, "1") + isWithin(co_ords[0], co_ords[1], right - spacing * 3, y, spacing * 3, "2"); + if (complicationIndex.equals("Complication_G") == false) { + complicationId = Storage.getValue(complicationIndex); + } + + logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } + + return null; + } + + function isWithin(x, y, startX, startY, spacing, field) { + if (x > startX && x < startX + spacing && y > startY and y < startY + spacing) { + return field; + } + else { + return ""; + } + } + + //! The onPowerBudgetExceeded callback is called by the system if the + //! onPartialUpdate method exceeds the allowed power budget. If this occurs, + //! the system will stop invoking onPartialUpdate each second, so we notify the + //! view here to let the rendering methods know they should not be rendering a + //! second hand. + //! @param powerInfo Information about the power budget + public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { + logMessage("Average execution time: " + powerInfo.executionTimeAverage); + logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); + //mview.turnPartialUpdatesOff(); + } +} /* function type_name(obj) { diff --git a/source/DataArea.mc b/source/DataArea.mc index 333a64e6..40f26895 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -24,9 +24,9 @@ class DataArea extends Ui.Drawable { private var mRightGoalCurrent; private var mRightGoalMax; - private var mGoalIconY; - private var mGoalIconLeftX; - private var mGoalIconRightX; + var mGoalIconY; + var mGoalIconLeftX; + var mGoalIconRightX; function initialize(params) { Drawable.initialize(params); diff --git a/source/DataFields.mc b/source/DataFields.mc index 107fb00d..59ea1a49 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -10,6 +10,7 @@ using Toybox.Time; using Toybox.Time.Gregorian; using Toybox.Application.Storage; using Toybox.Application.Properties; +using Toybox.Complications; enum /* FIELD_TYPES */ { // Pseudo-fields. @@ -41,9 +42,9 @@ enum /* FIELD_TYPES */ { class DataFields extends Ui.Drawable { - private var mLeft; - private var mRight; - private var mTop; + var mLeft; + var mRight; + var mTop; private var mBottom; private var mWeatherIconsFont; @@ -99,6 +100,36 @@ class DataFields extends Ui.Drawable { mWeatherIconsFont = null; mWeatherIconsSubset = null; } + + if (Toybox has :Complications) { + var complications = [{"type" => FIELD_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, + {"type" => FIELD_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS}, + {"type" => FIELD_TYPE_PULSE_OX, "complicationType" => Complications.COMPLICATION_TYPE_PULSE_OX}, + {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE} + ]; + var filled = [false, false, false]; + var i; + + for (i = 0; i < complications.size(); i++) { + if (App.getApp().hasField(complications[i].get("type"))) { + var fieldTypes = App.getApp().mFieldTypes; + for (var j = 0; j < mFieldCount; j++) { + if (fieldTypes[j].get("type") == complications[i].get("type")) { + $.updateComplications("", "Complication_F", j + 1, complications[i].get("complicationType")); + fieldTypes[j].put("ComplicationType", complications[i].get("complicationType")); + filled[j] = true; + } + } + } + } + + // Now delete any fields that doesn't have a Complication + for (i = 1; i < 4; i++) { + if (filled[i - 1] == false) { + Storage.deleteValue("Complication_F" + i); + } + } + } } function draw(dc) { @@ -114,16 +145,16 @@ class DataFields extends Ui.Drawable { switch (mFieldCount) { case 3: - drawDataField(dc, isPartialUpdate, fieldTypes[0], mLeft); - drawDataField(dc, isPartialUpdate, fieldTypes[1], (mRight + mLeft) / 2); - drawDataField(dc, isPartialUpdate, fieldTypes[2], mRight); + drawDataField(dc, isPartialUpdate, fieldTypes[0].get("type"), mLeft, 0); + drawDataField(dc, isPartialUpdate, fieldTypes[1].get("type"), (mRight + mLeft) / 2, 1); + drawDataField(dc, isPartialUpdate, fieldTypes[2].get("type"), mRight, 2); break; case 2: - drawDataField(dc, isPartialUpdate, fieldTypes[0], mLeft + ((mRight - mLeft) * 0.15)); - drawDataField(dc, isPartialUpdate, fieldTypes[1], mLeft + ((mRight - mLeft) * 0.85)); + drawDataField(dc, isPartialUpdate, fieldTypes[0].get("type"), mLeft + ((mRight - mLeft) * 0.15), 0); + drawDataField(dc, isPartialUpdate, fieldTypes[1].get("type"), mLeft + ((mRight - mLeft) * 0.85), 1); break; case 1: - drawDataField(dc, isPartialUpdate, fieldTypes[0], (mRight + mLeft) / 2); + drawDataField(dc, isPartialUpdate, fieldTypes[0].get("type"), (mRight + mLeft) / 2, 0); break; /* case 0: @@ -135,7 +166,7 @@ class DataFields extends Ui.Drawable { // Both regular and small icon fonts use same spot size for easier optimisation. //private const LIVE_HR_SPOT_RADIUS = 3; - private function drawDataField(dc, isPartialUpdate, fieldType, x) { + private function drawDataField(dc, isPartialUpdate, fieldType, x, index) { // Assume we're only drawing live HR spot every 5 seconds; skip all other partial updates. var isLiveHeartRate = (fieldType == FIELD_TYPE_HR_LIVE_5S); @@ -168,7 +199,7 @@ class DataFields extends Ui.Drawable { } // 1. Value: draw first, as top of text overlaps icon. - var result = getValueForFieldType(fieldType); + var result = getValueForFieldType(fieldType, index); var value = result["value"]; var stale = result["stale"]; @@ -365,7 +396,7 @@ class DataFields extends Ui.Drawable { // Return empty result["value"] string if value cannot be retrieved (e.g. unavailable, or unsupported). // result["isSunriseNext"] indicates that sunrise icon should be shown for FIELD_TYPE_SUNRISE_SUNSET, rather than default // sunset icon. - private function getValueForFieldType(type) { + private function getValueForFieldType(type, index) { var result = {}; var value = ""; var stale = false; @@ -396,7 +427,14 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_BODY_BATTERY: - if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { + if (Toybox has :Complications) { + var fieldTypes = App.getApp().mFieldTypes; + var tmpValue = fieldTypes[index].get("ComplicationValue"); + if (tmpValue != null) { + value = tmpValue.toString(); + } + } + if (value.equals("") == true && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { var bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); if (bodyBattery != null) { bodyBattery = bodyBattery.next(); @@ -411,7 +449,14 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_STRESS_LEVEL: - if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { + if (Toybox has :Complications) { + var fieldTypes = App.getApp().mFieldTypes; + var tmpValue = fieldTypes[index].get("ComplicationValue"); + if (tmpValue != null) { + value = tmpValue.toString(); + } + } + if (value.equals("") == true && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { var stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); if (stressLevel != null) { stressLevel = stressLevel.next(); @@ -447,23 +492,42 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_TYPE_PULSE_OX: - activityInfo = Activity.getActivityInfo(); - sample = activityInfo != null and activityInfo has :currentOxygenSaturation ? activityInfo.currentOxygenSaturation : null; - if (sample != null) { - value = sample.format(INTEGER_FORMAT) + "%"; + if (Toybox has :Complications) { + var fieldTypes = App.getApp().mFieldTypes; + var tmpValue = fieldTypes[index].get("ComplicationValue"); + if (tmpValue != null) { + value = tmpValue.toString() + "%"; + } + } + if (value.equals("") == true) { + activityInfo = Activity.getActivityInfo(); + sample = activityInfo != null and activityInfo has :currentOxygenSaturation ? activityInfo.currentOxygenSaturation : null; + if (sample != null) { + value = sample.format(INTEGER_FORMAT) + "%"; + } } break; case FIELD_TYPE_HEART_RATE: + if (Toybox has :Complications) { + var fieldTypes = App.getApp().mFieldTypes; + var tmpValue = fieldTypes[index].get("ComplicationValue"); + if (tmpValue != null) { + value = tmpValue.toString(); + } + } + // Yes, no break. We flow through in case with don't have Complication. FIELD_TYPE_HEART_RATE and FIELD_TYPE_HR_LIVE_5S were doing the same thing case FIELD_TYPE_HR_LIVE_5S: // #34 Try to retrieve live HR from Activity::Info, before falling back to historical HR from ActivityMonitor. - activityInfo = Activity.getActivityInfo(); - sample = activityInfo.currentHeartRate; - if (sample != null) { - value = sample.format(INTEGER_FORMAT); - } else if (ActivityMonitor has :getHeartRateHistory) { - sample = ActivityMonitor.getHeartRateHistory(1, true).next(); - if ((sample != null) && (sample.heartRate != ActivityMonitor.INVALID_HR_SAMPLE)) { - value = sample.heartRate.format(INTEGER_FORMAT); + if (value.equals("") == true) { + activityInfo = Activity.getActivityInfo(); + sample = activityInfo.currentHeartRate; + if (sample != null) { + value = sample.format(INTEGER_FORMAT); + } else if (ActivityMonitor has :getHeartRateHistory) { + sample = ActivityMonitor.getHeartRateHistory(1, true).next(); + if ((sample != null) && (sample.heartRate != ActivityMonitor.INVALID_HR_SAMPLE)) { + value = sample.heartRate.format(INTEGER_FORMAT); + } } } break; diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index af280e00..f1fd386c 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -4,6 +4,7 @@ using Toybox.Application as App; using Toybox.Graphics; using Toybox.Application.Storage; using Toybox.Application.Properties; +using Toybox.Complications; // const MIN_WHOLE_SEGMENT_HEIGHT = 5; @@ -47,6 +48,9 @@ class GoalMeter extends Ui.Drawable { private var mMaxValue; private var mIsOff = false; // #114 Should entire meter on this side be hidden? + var mComplicationType; + var mComplicationValue; + // private enum /* GOAL_METER_STYLES */ { // ALL_SEGMENTS, // ALL_SEGMENTS_MERGED, @@ -135,6 +139,36 @@ class GoalMeter extends Ui.Drawable { } } + function setComplication(index) { + if (Toybox has :Complications) { + var complications = [{"type" => GOAL_TYPE_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, + {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} + ]; + + var leftType = Properties.getValue("LeftGoalType"); + var rightType = Properties.getValue("RightGoalType"); + + mComplicationType = null; + + for (var i = 0; i < complications.size(); i++) { + if (index == 1 && leftType == complications[i].get("type")) { + $.updateComplications("", "Complication_G", index, complications[i].get("complicationType")); + mComplicationType = complications[i].get("complicationType"); + break; + } + else if (index == 2 && rightType == complications[i].get("type")) { + $.updateComplications("", "Complication_G", index, complications[i].get("complicationType")); + mComplicationType = complications[i].get("complicationType"); + break; + } + } + + if (mComplicationType == null) { + Storage.deleteValue("Complication_G" + index); + } + } + } + // Different draw algorithms have been tried: // 1. Draw each segment as a circle, clipped to a rectangle of the desired height, direct to screen DC. // Intuitive, but expensive. diff --git a/source/Indicators.mc b/source/Indicators.mc index 201b490a..d3f21d1c 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -4,16 +4,17 @@ using Toybox.System as Sys; using Toybox.Application as App; using Toybox.Application.Storage; using Toybox.Application.Properties; +using Toybox.Complications; class Indicators extends Ui.Drawable { - private var mSpacing; - private var mIsHorizontal = false; - private var mBatteryWidth; + var mSpacing; + var mIsHorizontal = false; + var mBatteryWidth; - private var mIndicator1Type; - private var mIndicator2Type; - private var mIndicator3Type; + var mIndicator1Type; + var mIndicator2Type; + var mIndicator3Type; // private enum /* INDICATOR_TYPES */ { // INDICATOR_TYPE_BLUETOOTH, @@ -41,16 +42,34 @@ class Indicators extends Ui.Drawable { mIndicator1Type = Properties.getValue("Indicator1Type"); mIndicator2Type = Properties.getValue("Indicator2Type"); mIndicator3Type = Properties.getValue("Indicator3Type"); - + //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - if (mIndicator1Type == 6 || mIndicator2Type == 6 || mIndicator3Type == 6) { - Storage.setValue("Tesla", true); + var teslaIndicator; + if (mIndicator1Type == 6) { + teslaIndicator = 1; + } + if (mIndicator2Type == 6) { + teslaIndicator = 2; + } + if (mIndicator3Type == 6) { + teslaIndicator = 3; + } + if (teslaIndicator != null) { //logMessage("onSettingsChanged:Doing Tesla!"); + Storage.setValue("Tesla", true); + $.updateComplications("Tesla-Link", "Complication_I", teslaIndicator, Complications.COMPLICATION_TYPE_INVALID); } else { - Storage.setValue("Tesla", null); - } + Storage.deleteValue("Tesla"); + teslaIndicator = 0; + } + + for (var i = 1; i < 4; i++) { + if (i != teslaIndicator) { + Storage.deleteValue("Complication_I" + i); + } + } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* //**************************************************************** From c4560bae760231ac31f40c56dd90d17b4506d0ad Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 1 May 2023 15:14:29 -0400 Subject: [PATCH 118/220] V2.17.0 released --- README.md | 1 + source/CrystalView.mc | 30 +++++++++++------------------- source/Indicators.mc | 2 +- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index f16d7494..5835f318 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Reviews: - Tesla-Info now support launching the main Tesla-Link App from the watch face. - Heart rate, PulseOx, BodyBattery and Stress Level are now read through complications if available - Complication read fields will launch their widget when long pressed. Applies to Fields, Indicators (for Tesla-Info only for now) and Goals. +- Fixed a few crashes reported through the Error Reporting Application (ERA) ### 2.16.5b - Fixed a crash reported through the Error Reporting Application (ERA) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index a7dc9c70..62022685 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -242,6 +242,7 @@ function updateComplications(complicationName, storageName, index, complicationT while (complicationId != null) { //logMessage(complicationId.longLabel.toString()); if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel.equals(complicationName))) { + //DEBUG*/ logMessage("Found complication " + complicationName + " with type " + complicationType); break; } complicationId = iter.next(); @@ -307,17 +308,6 @@ class CrystalView extends Ui.WatchFace { rereadWeatherMethod(); } - // callback that updates the complication value - function updateComplication(complication) { - var thisComplication = Complications.getComplication(complication); - var thisType = thisComplication.getType(); - - var value = thisComplication.value; - var label = thisComplication.shortLabel; - - logMessage(label + "=" + value); - } - // Reread Weather method function rereadWeatherMethod() { var owmKeyOverride = Properties.getValue("OWMKeyOverride"); @@ -410,10 +400,10 @@ class CrystalView extends Ui.WatchFace { function onComplicationUpdated(complicationId) { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); - var complicationLabel = complication.shortLabel; + //var complicationLabel = complication.shortLabel; var complicationValue = complication.value; -// logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue); + //logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue); // Do fields first var fieldCount = App.getApp().getIntProperty("FieldCount", 3); @@ -970,7 +960,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes var complicationId = checkBoundingBoxes(co_ords); @@ -1008,7 +998,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { complicationId = Storage.getValue(complicationIndex); } - logMessage(complicationIndex + " = " + complicationId); + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } @@ -1035,7 +1025,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { complicationId = Storage.getValue(complicationIndex); } - logMessage(complicationIndex + " = " + complicationId); + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } @@ -1052,7 +1042,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { complicationId = Storage.getValue(complicationIndex); } - logMessage(complicationIndex + " = " + complicationId); + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } @@ -1062,9 +1052,11 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { function isWithin(x, y, startX, startY, spacing, field) { if (x > startX && x < startX + spacing && y > startY and y < startY + spacing) { + //DEBUG*/ logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); return field; } else { + //DEBUG*/ logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); return ""; } } @@ -1076,8 +1068,8 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { //! second hand. //! @param powerInfo Information about the power budget public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { - logMessage("Average execution time: " + powerInfo.executionTimeAverage); - logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); + //DEBUG*/ logMessage("Average execution time: " + powerInfo.executionTimeAverage); + //DEBUG*/ logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); //mview.turnPartialUpdatesOff(); } } diff --git a/source/Indicators.mc b/source/Indicators.mc index d3f21d1c..a6b4ae6a 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -57,7 +57,7 @@ class Indicators extends Ui.Drawable { teslaIndicator = 3; } if (teslaIndicator != null) { - //logMessage("onSettingsChanged:Doing Tesla!"); + //DEBUG*/ logMessage("onSettingsChanged:Doing Tesla!"); Storage.setValue("Tesla", true); $.updateComplications("Tesla-Link", "Complication_I", teslaIndicator, Complications.COMPLICATION_TYPE_INVALID); } else { From 76ba8e18a0914597b91134c1335b265b8977d875 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 1 May 2023 15:16:13 -0400 Subject: [PATCH 119/220] Reinstated logging after release --- source/CrystalView.mc | 18 +++++++++--------- source/Indicators.mc | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 62022685..ff50a3af 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -242,7 +242,7 @@ function updateComplications(complicationName, storageName, index, complicationT while (complicationId != null) { //logMessage(complicationId.longLabel.toString()); if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel.equals(complicationName))) { - //DEBUG*/ logMessage("Found complication " + complicationName + " with type " + complicationType); + logMessage("Found complication " + complicationName + " with type " + complicationType); break; } complicationId = iter.next(); @@ -960,7 +960,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes var complicationId = checkBoundingBoxes(co_ords); @@ -998,7 +998,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { complicationId = Storage.getValue(complicationIndex); } - //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } @@ -1025,7 +1025,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { complicationId = Storage.getValue(complicationIndex); } - //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } @@ -1042,7 +1042,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { complicationId = Storage.getValue(complicationIndex); } - //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } @@ -1052,11 +1052,11 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { function isWithin(x, y, startX, startY, spacing, field) { if (x > startX && x < startX + spacing && y > startY and y < startY + spacing) { - //DEBUG*/ logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); + logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); return field; } else { - //DEBUG*/ logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); + logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); return ""; } } @@ -1068,8 +1068,8 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { //! second hand. //! @param powerInfo Information about the power budget public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { - //DEBUG*/ logMessage("Average execution time: " + powerInfo.executionTimeAverage); - //DEBUG*/ logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); + logMessage("Average execution time: " + powerInfo.executionTimeAverage); + logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); //mview.turnPartialUpdatesOff(); } } diff --git a/source/Indicators.mc b/source/Indicators.mc index a6b4ae6a..ce8317ad 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -57,7 +57,7 @@ class Indicators extends Ui.Drawable { teslaIndicator = 3; } if (teslaIndicator != null) { - //DEBUG*/ logMessage("onSettingsChanged:Doing Tesla!"); + logMessage("onSettingsChanged:Doing Tesla!"); Storage.setValue("Tesla", true); $.updateComplications("Tesla-Link", "Complication_I", teslaIndicator, Complications.COMPLICATION_TYPE_INVALID); } else { From 5390741a401e03ef43ba9ccbfc6f09e03b960393 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 1 May 2023 23:25:03 -0400 Subject: [PATCH 120/220] Prepping for V2.17.1 --- README.md | 5 ++ always-on-source/AlwaysOnDisplay.mc | 9 +- resources/strings/strings.xml | 2 +- source/CrystalView.mc | 130 ++++++++++++++++++---------- source/DataArea.mc | 10 +++ source/DataFields.mc | 14 +++ source/GoalMeter.mc | 2 + source/Indicators.mc | 22 ++++- 8 files changed, 143 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 5835f318..23dfa71a 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,11 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.17.1 +- Fixed a crash when Complications were received while leaving Always On Display mode +- Added Steps and Floor climbs as Complication for Goals. +- Readded the Tesla Battery display to the Always On Display mode + ### 2.17.0 - Tesla-Info now support launching the main Tesla-Link App from the watch face. - Heart rate, PulseOx, BodyBattery and Stress Level are now read through complications if available diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index d529277d..1b2191ef 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -3,6 +3,7 @@ using Toybox.System as Sys; using Toybox.Application as App; using Toybox.Time; using Toybox.Time.Gregorian; +using Toybox.Application.Storage; // Draw time, line, date, battery. // Combine stripped down versions of ThickThinTime and DateLine. @@ -192,7 +193,7 @@ class AlwaysOnDisplay extends Ui.Drawable { // Date. y = mDataY + burnInYOffset; - if (App.getApp().getProperty("Tesla") != null) { + if (Storage.getValue("Tesla") != null) { dc.drawText( mDataLeft, y, @@ -203,8 +204,8 @@ class AlwaysOnDisplay extends Ui.Drawable { // Batteries. var battery = Math.floor(Sys.getSystemStats().battery); - var chargingState = App.getApp().getProperty("TeslaChargingState"); - var error = App.getApp().getProperty("TeslaError"); + var chargingState = Storage.getValue("TeslaChargingState"); + var error = Storage.getValue("TeslaError"); if (chargingState != null) { if (chargingState.equals("Charging")) { @@ -218,7 +219,7 @@ class AlwaysOnDisplay extends Ui.Drawable { chargingState = 0; } - var value = App.getApp().getProperty("TeslaBatterieLevel"); + var value = Storage.getValue("TeslaBatterieLevel"); if (error != null) { value = error.toNumber().format(INTEGER_FORMAT); } else if (value == null) { diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index e9f8b01c..c2132a8b 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.17.0 + Crystal-Tesla V2.17.1 Theme Hours Colour diff --git a/source/CrystalView.mc b/source/CrystalView.mc index ff50a3af..e311bb67 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -242,7 +242,7 @@ function updateComplications(complicationName, storageName, index, complicationT while (complicationId != null) { //logMessage(complicationId.longLabel.toString()); if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel.equals(complicationName))) { - logMessage("Found complication " + complicationName + " with type " + complicationType); + //DEBUG*/ logMessage("Found complication " + complicationName + " with type " + complicationType); break; } complicationId = iter.next(); @@ -385,7 +385,7 @@ class CrystalView extends Ui.WatchFace { rereadWeatherMethod(); // Check if we changed from Garmin Weather or OWM if (mHasGarminWeather == true) { // Using the Garmin Weather stuff - ReadWeather(); + ReadWeather(false); } // Reread our complications @@ -416,18 +416,25 @@ class CrystalView extends Ui.WatchFace { } } - // Now do goals - if (mDrawables[:LeftGoalMeter].mComplicationType == complicationType) { - mDrawables[:LeftGoalMeter].mComplicationValue = complicationValue; - } - if (mDrawables[:RightGoalMeter].mComplicationType == complicationType) { - mDrawables[:RightGoalMeter].mComplicationValue = complicationValue; + // Now do goals (but only if we're not in burnin protection as our drawables are null in that mode) + if (mDrawables[:LeftGoalMeter] != null && mDrawables[:RightGoalMeter] != null) { + if (mDrawables[:LeftGoalMeter].mComplicationType == complicationType) { + mDrawables[:LeftGoalMeter].mComplicationValue = complicationValue; + } + if (mDrawables[:RightGoalMeter].mComplicationType == complicationType) { + mDrawables[:RightGoalMeter].mComplicationValue = complicationValue; + } } } // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see - function ReadWeather() { - var weather = Weather.getCurrentConditions(); + function ReadWeather(fromComplication) { + var weather; + if (fromComplication) { + } + else { + weather = Weather.getCurrentConditions(); + } var result; if (weather != null) { var temperature = weather.temperature; @@ -687,18 +694,38 @@ class CrystalView extends Ui.WatchFace { switch(type) { case GOAL_TYPE_STEPS: - values[:current] = info.steps; - values[:max] = info.stepGoal; + values[:isValid] = false; + if (Toybox has :Complications) { + var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + if (tmpValue != null) { + values[:current] = tmpValue.toNumber(); + values[:isValid] = true; + } + } + if (values[:isValid] == false) { + values[:isValid] = true; + values[:current] = info.steps; + values[:max] = info.stepGoal; + } break; case GOAL_TYPE_FLOORS_CLIMBED: - if (info has :floorsClimbed) { - values[:current] = info.floorsClimbed; - values[:max] = info.floorsClimbedGoal; - } else { - values[:isValid] = false; + values[:isValid] = false; + if (Toybox has :Complications) { + var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + if (tmpValue != null) { + values[:current] = tmpValue.toNumber(); + values[:isValid] = true; + } + } + if (values[:isValid] == false) { + if (info has :floorsClimbed) { + values[:current] = info.floorsClimbed; + values[:max] = info.floorsClimbedGoal; + } else { + values[:isValid] = false; + } } - break; case GOAL_TYPE_ACTIVE_MINUTES: @@ -892,7 +919,7 @@ class CrystalView extends Ui.WatchFace { } if (mHasGarminWeather == true) { // Using the Garmin Weather stuff - ReadWeather(); + ReadWeather(false); } // If watch requires burn-in protection, set flag to false when entering sleep. @@ -960,7 +987,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes var complicationId = checkBoundingBoxes(co_ords); @@ -972,7 +999,8 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { function checkBoundingBoxes(co_ords) { // First check the indicators var indicatorCount = App.getApp().getIntProperty("IndicatorCount", 1); - var spacing; + var spacingX; + var spacingY; var complicationIndex; var complicationId; @@ -982,67 +1010,79 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { var locY = indicators[:locY]; var batteryWidth = indicators[:mBatteryWidth]; - spacing = indicators[:mSpacing]; - locX -= batteryWidth / 2; - locY -= batteryWidth / 2; + spacingY = indicators[:mSpacing]; + spacingX = batteryWidth * 2; + locX -= (batteryWidth / 1.5).toNumber(); + if (indicatorCount == 1) { + locY -= spacingY; + spacingY *= 2; + } + else { + locY -= spacingY / 2; + } if (indicatorCount == 3) { - complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacing, spacing, "1") + isWithin(co_ords[0], co_ords[1], locX, locY, spacing, "2") + isWithin(co_ords[0], co_ords[1], locX, locY + spacing, spacing, "3"); + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacingY, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], locX, locY, spacingX, spacingY, "2") + isWithin(co_ords[0], co_ords[1], locX, locY + spacingY, spacingX, spacingY, "3"); } else if (indicatorCount == 2) { - complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacing / 2, spacing, "1") + isWithin(co_ords[0], co_ords[1], locX, locY + spacing / 2, spacing, "2"); + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], locX, locY + spacingY / 2, spacingX, spacingY, "2"); } else if (indicatorCount == 1) { - complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY, spacing, "1"); + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY, spacingX, spacingY, "1"); } if (complicationIndex.equals("Complication_I") == false) { complicationId = Storage.getValue(complicationIndex); } - logMessage(complicationIndex + " = " + complicationId); + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } } - spacing = Sys.getDeviceSettings().screenWidth / 12; - // Check the fields var fieldCount = App.getApp().getIntProperty("FieldCount", 3); + if (fieldCount > 0) { + spacingX = Sys.getDeviceSettings().screenWidth / (2 * fieldCount); + spacingY = Sys.getDeviceSettings().screenHeight / 4; + var left = mview.mDataFields.mLeft; var right = mview.mDataFields.mRight; var top = mview.mDataFields.mTop; if (fieldCount == 3) { - complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left - spacing, top - spacing, spacing * 2, "1") + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacing, top - spacing, spacing * 2, "2") + isWithin(co_ords[0], co_ords[1], right - spacing, top - spacing, spacing * 2, "3"); + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacingX / 2, top - spacingY /2, spacingX, spacingY, "2") + isWithin(co_ords[0], co_ords[1], right - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "3"); } else if (fieldCount == 2) { - complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.15) - spacing, top - spacing, spacing * 2, "1") + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.85) - spacing, top - spacing, spacing * 2, "2"); + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.15) - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.85) - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "2"); } else if (fieldCount == 1) { - complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacing, top - spacing, spacing * 2, "1"); + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1"); } if (complicationIndex.equals("Complication_F") == false) { complicationId = Storage.getValue(complicationIndex); } - logMessage(complicationIndex + " = " + complicationId); + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } } // Check the goals - var left = mview.mDrawables[:DataArea].mGoalIconLeftX; - var right = mview.mDrawables[:DataArea].mGoalIconRightX; - var y = mview.mDrawables[:DataArea].mGoalIconY; + spacingX = Sys.getDeviceSettings().screenWidth / 11; + spacingY = Sys.getDeviceSettings().screenHeight / 6; + + var left = mview.mDrawables[:DataArea].mGoalIconLeftX - spacingX / 8; + var right = mview.mDrawables[:DataArea].mGoalIconRightX + spacingX / 8; + var y = mview.mDrawables[:DataArea].mGoalIconY - spacingY / 8; // spacing * 3 to give it more room so we can press on the text too. - complicationIndex = "Complication_G" + isWithin(co_ords[0], co_ords[1], left, y, spacing * 3, "1") + isWithin(co_ords[0], co_ords[1], right - spacing * 3, y, spacing * 3, "2"); + complicationIndex = "Complication_G" + isWithin(co_ords[0], co_ords[1], left, y, spacingX * 3, spacingY, "1") + isWithin(co_ords[0], co_ords[1], right - spacingX * 3, y, spacingX * 3, spacingY, "2"); if (complicationIndex.equals("Complication_G") == false) { complicationId = Storage.getValue(complicationIndex); } - logMessage(complicationIndex + " = " + complicationId); + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); if (complicationId != null) { return complicationId; } @@ -1050,13 +1090,13 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { return null; } - function isWithin(x, y, startX, startY, spacing, field) { - if (x > startX && x < startX + spacing && y > startY and y < startY + spacing) { - logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); + function isWithin(x, y, startX, startY, spacingX, spacingY, field) { + if (x > startX && x < startX + spacingX && y > startY and y < startY + spacingY) { + //DEBUG*/ logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); return field; } else { - logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacing).toString() + "/" + (startY + spacing).toString()); + //DEBUG*/ logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); return ""; } } @@ -1068,8 +1108,8 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { //! second hand. //! @param powerInfo Information about the power budget public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { - logMessage("Average execution time: " + powerInfo.executionTimeAverage); - logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); + //DEBUG*/ logMessage("Average execution time: " + powerInfo.executionTimeAverage); + //DEBUG*/ logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); //mview.turnPartialUpdatesOff(); } } diff --git a/source/DataArea.mc b/source/DataArea.mc index 40f26895..b7b6a8a3 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -142,6 +142,16 @@ class DataArea extends Ui.Drawable { drawGoalValues(dc, locX, mLeftGoalCurrent, mLeftGoalMax, Graphics.TEXT_JUSTIFY_LEFT); drawGoalValues(dc, locX + width, mRightGoalCurrent, mRightGoalMax, Graphics.TEXT_JUSTIFY_RIGHT); } + + /*var spacingX = Sys.getDeviceSettings().screenWidth / 11; + var spacingY = Sys.getDeviceSettings().screenHeight / 6; + + var left = mGoalIconLeftX - spacingX / 8; + var right = mGoalIconRightX + spacingX / 8; + var y = mGoalIconY - spacingY / 8; + + dc.drawRectangle(left, y, spacingX * 3, spacingY); + dc.drawRectangle(right - spacingX * 3, y, spacingX * 3, spacingY);*/ } function drawGoalIcon(dc, x, type, isValid, staled, align) { diff --git a/source/DataFields.mc b/source/DataFields.mc index 59ea1a49..4b567aa2 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -104,6 +104,7 @@ class DataFields extends Ui.Drawable { if (Toybox has :Complications) { var complications = [{"type" => FIELD_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => FIELD_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS}, + {"type" => FIELD_FLOOR_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => FIELD_TYPE_PULSE_OX, "complicationType" => Complications.COMPLICATION_TYPE_PULSE_OX}, {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE} ]; @@ -143,18 +144,31 @@ class DataFields extends Ui.Drawable { var fieldTypes = App.getApp().mFieldTypes; + /*var spacingX = Sys.getDeviceSettings().screenWidth / (2 * mFieldCount); + var spacingY = Sys.getDeviceSettings().screenHeight / 4; + + var left = mLeft; + var right = mRight; + var top = mTop;*/ + switch (mFieldCount) { case 3: drawDataField(dc, isPartialUpdate, fieldTypes[0].get("type"), mLeft, 0); drawDataField(dc, isPartialUpdate, fieldTypes[1].get("type"), (mRight + mLeft) / 2, 1); drawDataField(dc, isPartialUpdate, fieldTypes[2].get("type"), mRight, 2); + // dc.drawRectangle(left - spacingX / 2, top - spacingY / 2, spacingX, spacingY); + // dc.drawRectangle((right + left) / 2 - spacingX / 2, top - spacingY /2, spacingX, spacingY); + // dc.drawRectangle(right - spacingX / 2, top - spacingY / 2, spacingX, spacingY); break; case 2: drawDataField(dc, isPartialUpdate, fieldTypes[0].get("type"), mLeft + ((mRight - mLeft) * 0.15), 0); drawDataField(dc, isPartialUpdate, fieldTypes[1].get("type"), mLeft + ((mRight - mLeft) * 0.85), 1); + // dc.drawRectangle(left + ((right - left) * 0.15) - spacingX / 2, top - spacingY / 2, spacingX, spacingY); + // dc.drawRectangle(left + ((right - left) * 0.85) - spacingX / 2, top - spacingY / 2, spacingX, spacingY); break; case 1: drawDataField(dc, isPartialUpdate, fieldTypes[0].get("type"), (mRight + mLeft) / 2, 0); + // dc.drawRectangle((right + left) / 2 - spacingX / 2, top - spacingY / 2, spacingX, spacingY); break; /* case 0: diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index f1fd386c..d10f0fa9 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -142,6 +142,8 @@ class GoalMeter extends Ui.Drawable { function setComplication(index) { if (Toybox has :Complications) { var complications = [{"type" => GOAL_TYPE_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, + {"type" => GOAL_TYPE_FLOORS_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, + {"type" => GOAL_TYPE_STEPS, "complicationType" => Complications.COMPLICATION_TYPE_STEPS}, {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} ]; diff --git a/source/Indicators.mc b/source/Indicators.mc index ce8317ad..1937d6d8 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -57,7 +57,7 @@ class Indicators extends Ui.Drawable { teslaIndicator = 3; } if (teslaIndicator != null) { - logMessage("onSettingsChanged:Doing Tesla!"); + //DEBUG*/ logMessage("onSettingsChanged:Doing Tesla!"); Storage.setValue("Tesla", true); $.updateComplications("Tesla-Link", "Complication_I", teslaIndicator, Complications.COMPLICATION_TYPE_INVALID); } else { @@ -106,15 +106,35 @@ class Indicators extends Ui.Drawable { (:vertical_indicators) function drawVertical(dc, indicatorCount) { + + /*var spacingY = mSpacing; + var spacingX = mBatteryWidth * 2; + + var xlocX = locX - (mBatteryWidth / 1.5).toNumber(); + var ylocY; + if (indicatorCount == 1) { + ylocY = locY - spacingY; + spacingY *= 2; + } + else { + ylocY = locY - spacingY / 2; + }*/ + if (indicatorCount == 3) { drawIndicator(dc, mIndicator1Type, locX, locY - mSpacing); drawIndicator(dc, mIndicator2Type, locX, locY); drawIndicator(dc, mIndicator3Type, locX, locY + mSpacing); + // dc.drawRectangle(xlocX, ylocY - spacingY, spacingX, spacingY); + // dc.drawRectangle(xlocX, ylocY, spacingX, spacingY); + // dc.drawRectangle(xlocX, ylocY + spacingY, spacingX, spacingY); } else if (indicatorCount == 2) { drawIndicator(dc, mIndicator1Type, locX, locY - (mSpacing / 2)); drawIndicator(dc, mIndicator2Type, locX, locY + (mSpacing / 2)); + // dc.drawRectangle(xlocX, ylocY - spacingY / 2, spacingX, spacingY); + // dc.drawRectangle(xlocX, ylocY + spacingY / 2, spacingX, spacingY); } else if (indicatorCount == 1) { drawIndicator(dc, mIndicator1Type, locX, locY); + // dc.drawRectangle(xlocX, ylocY, spacingX, spacingY); } } From 6b2f772a4c146f46667bf6cea98687287eeb62e0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 1 May 2023 23:47:19 -0400 Subject: [PATCH 121/220] Fixed step and floor goals for Complication since they don't have any (still has to rely on ActivityMonitor for that) --- source/CrystalView.mc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index e311bb67..3e88c28a 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -702,11 +702,11 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = true; } } - if (values[:isValid] == false) { - values[:isValid] = true; + if (values[:isValid] == false) { // ignore steps (but get the max value) if we have Complication values[:current] = info.steps; - values[:max] = info.stepGoal; } + values[:max] = info.stepGoal; + values[:isValid] = true; break; case GOAL_TYPE_FLOORS_CLIMBED: @@ -718,13 +718,14 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = true; } } - if (values[:isValid] == false) { - if (info has :floorsClimbed) { + if (info has :floorsClimbed) { + if (values[:isValid] == false) { // ignore floor climbs (but get the max value) if we have Complication values[:current] = info.floorsClimbed; - values[:max] = info.floorsClimbedGoal; - } else { - values[:isValid] = false; } + values[:max] = info.floorsClimbedGoal; + values[:isValid] = true; + } else { + values[:isValid] = false; } break; From 016787c28365cee15e34ddad028bbeb740b741d0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 1 May 2023 23:49:18 -0400 Subject: [PATCH 122/220] One more crash because mDrawable is null in AoD --- source/CrystalView.mc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 3e88c28a..f4952250 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -621,10 +621,11 @@ class CrystalView extends Ui.WatchFace { mDataFields.onSettingsChanged(); mDrawables[:Indicators].onSettingsChanged(); + + mDrawables[:LeftGoalMeter].setComplication(1); + mDrawables[:RightGoalMeter].setComplication(2); } - mDrawables[:LeftGoalMeter].setComplication(1); - mDrawables[:RightGoalMeter].setComplication(2); // If watch does not support per-second updates, and watch is sleeping, do not show seconds immediately, as they will not // update. Instead, wait for next onExitSleep(). From 507afe7b43d296be4428663b7b03235fb0c09456 Mon Sep 17 00:00:00 2001 From: SylvainGa Date: Tue, 2 May 2023 21:08:15 -0400 Subject: [PATCH 123/220] Made Complications optional, added some sanity check around Goals values to prevent crashes --- README.md | 6 ++++ resources-fre/strings/strings.xml | 1 + resources/settings/properties.xml | 2 ++ resources/settings/settings.xml | 4 +++ resources/strings/strings.xml | 4 +-- source/CrystalView.mc | 53 ++++++++++++++++++++++--------- source/DataArea.mc | 6 ++-- source/DataFields.mc | 10 +++--- source/GoalMeter.mc | 2 +- source/Indicators.mc | 4 ++- 10 files changed, 66 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 23dfa71a..eb608cba 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.17.2 +- Made Complications an optional item, disabled by default since some watches are not reading them properly. Settable through Settings +- Adjusted the touch points around the Fields, Indicators and Goals value. +- Increased the size of the touchpoints as the number of Fields on screen decreases (ie, smallest touchpoint boxes sizes are when three Fields are displayed side by side and the largest touchpoint box is when only one field is dislayed). Doesn't apply to Indicators, just Fields. +- Fixed a few crashes reported through the Error Reporting Application (ERA) + ### 2.17.1 - Fixed a crash when Complications were received while leaving Always On Display mode - Added Steps and Floor climbs as Complication for Goals. diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 208b326c..577cdbc0 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -123,4 +123,5 @@ Latitude Longitude Niveau de stress + Utilisez les complications, si disponible diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 0c8c62b4..5edaaf9b 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -5,6 +5,8 @@ false + false + 0 1 0 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 859711bf..72ebb0ce 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -30,6 +30,10 @@ + + + + @Strings.Steps diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index c2132a8b..07028410 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.17.1 + Crystal-Tesla V2.17.2 Theme Hours Colour @@ -123,5 +123,5 @@ Latitude Longitude Stress Level + Use Complications if available - diff --git a/source/CrystalView.mc b/source/CrystalView.mc index f4952250..e15ed788 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -275,6 +275,8 @@ class CrystalView extends Ui.WatchFace { // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; + private var mUseComplications; + // N.B. Not all watches that support SDK 2.3.0 support per-second updates e.g. 735xt. private const PER_SECOND_UPDATES_SUPPORTED = Ui.WatchFace has :onPartialUpdate; @@ -388,13 +390,14 @@ class CrystalView extends Ui.WatchFace { ReadWeather(false); } - // Reread our complications + // Reread our complications if we're allowed + mUseComplications = Properties.getValue("UseComplications"); if (Toybox has :Complications) { // First we drop all our subscriptions before building a new list Complications.unsubscribeFromAllUpdates(); - Complications.registerComplicationChangeCallback(self.method(:onComplicationUpdated)); + // We listen for complications if we're allowed + Complications.registerComplicationChangeCallback(mUseComplications ? self.method(:onComplicationUpdated) : null); } - } function onComplicationUpdated(complicationId) { @@ -405,6 +408,11 @@ class CrystalView extends Ui.WatchFace { //logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue); + // If we were told to ignore complications, do so (but technicaly, we shouldn't get here as we shouldn't be listening in the first place!) + if (!mUseComplications) { + /*DEBUG*/ logMessage("How did we get here, we're not supposed to be listening!"); + return; + } // Do fields first var fieldCount = App.getApp().getIntProperty("FieldCount", 3); var fieldTypes = App.getApp().mFieldTypes; @@ -622,11 +630,12 @@ class CrystalView extends Ui.WatchFace { mDrawables[:Indicators].onSettingsChanged(); - mDrawables[:LeftGoalMeter].setComplication(1); - mDrawables[:RightGoalMeter].setComplication(2); + if (mUseComplications) { + mDrawables[:LeftGoalMeter].setComplication(1); + mDrawables[:RightGoalMeter].setComplication(2); + } } - // If watch does not support per-second updates, and watch is sleeping, do not show seconds immediately, as they will not // update. Instead, wait for next onExitSleep(). if (PER_SECOND_UPDATES_SUPPORTED || !mIsSleeping) { @@ -696,7 +705,7 @@ class CrystalView extends Ui.WatchFace { switch(type) { case GOAL_TYPE_STEPS: values[:isValid] = false; - if (Toybox has :Complications) { + if (Toybox has :Complications && mUseComplications) { var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; if (tmpValue != null) { values[:current] = tmpValue.toNumber(); @@ -712,7 +721,7 @@ class CrystalView extends Ui.WatchFace { case GOAL_TYPE_FLOORS_CLIMBED: values[:isValid] = false; - if (Toybox has :Complications) { + if (Toybox has :Complications && mUseComplications) { var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; if (tmpValue != null) { values[:current] = tmpValue.toNumber(); @@ -750,7 +759,7 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = false; values[:max] = 100; - if (Toybox has :Complications) { + if (Toybox has :Complications && mUseComplications) { var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; if (tmpValue != null) { values[:current] = tmpValue.toFloat(); @@ -778,7 +787,7 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = false; values[:max] = 100; - if (Toybox has :Complications) { + if (Toybox has :Complications && mUseComplications) { var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; if (tmpValue != null) { values[:current] = tmpValue.toFloat(); @@ -875,10 +884,17 @@ class CrystalView extends Ui.WatchFace { // #16: If user has set goal to zero, or negative (in simulator), show as invalid. Set max to 1 to avoid divide-by-zero // crash in GoalMeter.getSegmentScale(). - if (values[:max] < 1) { + // Sanity check. I've seen weird Invalid Value and "System Error" in DataArea.setGoalValues:48 and :61. Make sure the data is valid + if (values[:isValid] && (!(values[:max] instanceof Lang.Number || values[:max] instanceof Lang.Float) || values[:max] < 1)) { + /*DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); values[:max] = 1; values[:isValid] = false; } + if (values[:isValid] && (!(values[:current] instanceof Lang.Number || values[:current] instanceof Lang.Float))) { + /*DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); + values[:current] = 0; + values[:isValid] = false; + } return values; } @@ -950,6 +966,7 @@ class CrystalView extends Ui.WatchFace { // If watch requires burn-in protection, set flag to true when entering sleep. var settings = Sys.getDeviceSettings(); if (settings has :requiresBurnInProtection && settings.requiresBurnInProtection) { + //DEBUG*/ logMessage("onEnterSleep with needing burning proctection"); mIsBurnInProtection = true; mBurnInProtectionChangedSinceLastDraw = true; } @@ -961,6 +978,10 @@ class CrystalView extends Ui.WatchFace { return mIsSleeping; } + function useComplications() { + return mUseComplications; + } + function setHideSeconds(hideSeconds) { // #158 Venu 2.80 firmware crash: mIsBurnInProtection fails to be set in onEnterSleep(), hopefully because that function @@ -989,12 +1010,14 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + /*DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes - var complicationId = checkBoundingBoxes(co_ords); - if (complicationId != null) { - Complications.exitTo(complicationId); + if (Toybox has :Complications && App.getApp().getView().useComplications()) { + var complicationId = checkBoundingBoxes(co_ords); + if (complicationId != null) { + Complications.exitTo(complicationId); + } } } diff --git a/source/DataArea.mc b/source/DataArea.mc index b7b6a8a3..f0aa8d62 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -44,10 +44,11 @@ class DataArea extends Ui.Drawable { mLeftGoalIsValid = leftValues[:isValid]; mLeftGoalstaled = leftValues[:staled]; - if (leftValues[:isValid]) { + if (leftValues[:isValid] && (leftValues[:current] instanceof Lang.Number || leftValues[:current] instanceof Lang.Float) && (leftValues[:max] instanceof Lang.Number || leftValues[:max] instanceof Lang.Float) ) { mLeftGoalCurrent = leftValues[:current].format(INTEGER_FORMAT); mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY || mLeftGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { + /*DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); mLeftGoalCurrent = null; mLeftGoalMax = null; } @@ -56,10 +57,11 @@ class DataArea extends Ui.Drawable { mRightGoalIsValid = rightValues[:isValid]; mRightGoalstaled = leftValues[:staled]; - if (rightValues[:isValid]) { + if (rightValues[:isValid] && (rightValues[:current] instanceof Lang.Number || rightValues[:current] instanceof Lang.Float) && (rightValues[:max] instanceof Lang.Number || rightValues[:max] instanceof Lang.Float) ) { mRightGoalCurrent = rightValues[:current].format(INTEGER_FORMAT); mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY || mRightGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { + /*DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); mRightGoalCurrent = null; mRightGoalMax = null; } diff --git a/source/DataFields.mc b/source/DataFields.mc index 4b567aa2..07d007ff 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -101,7 +101,7 @@ class DataFields extends Ui.Drawable { mWeatherIconsSubset = null; } - if (Toybox has :Complications) { + if (Toybox has :Complications && App.getApp().getView().useComplications()) { var complications = [{"type" => FIELD_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => FIELD_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS}, {"type" => FIELD_FLOOR_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, @@ -441,7 +441,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_BODY_BATTERY: - if (Toybox has :Complications) { + if (Toybox has :Complications && App.getApp().getView().useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { @@ -463,7 +463,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_STRESS_LEVEL: - if (Toybox has :Complications) { + if (Toybox has :Complications && App.getApp().getView().useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { @@ -506,7 +506,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_TYPE_PULSE_OX: - if (Toybox has :Complications) { + if (Toybox has :Complications && App.getApp().getView().useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { @@ -522,7 +522,7 @@ class DataFields extends Ui.Drawable { } break; case FIELD_TYPE_HEART_RATE: - if (Toybox has :Complications) { + if (Toybox has :Complications && App.getApp().getView().useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index d10f0fa9..1e7402c0 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -140,7 +140,7 @@ class GoalMeter extends Ui.Drawable { } function setComplication(index) { - if (Toybox has :Complications) { + if (Toybox has :Complications && App.getApp().getView().useComplications()) { var complications = [{"type" => GOAL_TYPE_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => GOAL_TYPE_FLOORS_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => GOAL_TYPE_STEPS, "complicationType" => Complications.COMPLICATION_TYPE_STEPS}, diff --git a/source/Indicators.mc b/source/Indicators.mc index 1937d6d8..3ffff334 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -59,7 +59,9 @@ class Indicators extends Ui.Drawable { if (teslaIndicator != null) { //DEBUG*/ logMessage("onSettingsChanged:Doing Tesla!"); Storage.setValue("Tesla", true); - $.updateComplications("Tesla-Link", "Complication_I", teslaIndicator, Complications.COMPLICATION_TYPE_INVALID); + if (App.getApp().getView().useComplications()) { + $.updateComplications("Tesla-Link", "Complication_I", teslaIndicator, Complications.COMPLICATION_TYPE_INVALID); + } } else { Storage.deleteValue("Tesla"); teslaIndicator = 0; From 8dea4cfdb3a6c4425a20a76509389cd97ad29d7c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 2 May 2023 21:57:15 -0400 Subject: [PATCH 124/220] V2.17.2 - Made Complications an optional item, disabled by default since some watches are not reading them properly. Settable through Settings - Adjusted the touch points around the Fields, Indicators and Goals value. - Increased the size of the touchpoints as the number of Fields on screen decreases (ie, smallest touchpoint boxes sizes are when three Fields are displayed side by side and the largest touchpoint box is when only one field is dislayed). Doesn't apply to Indicators, just Fields. - Fixed a few crashes reported through the Error Reporting Application (ERA) --- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + source/BackgroundService.mc | 11 ----------- source/CrystalApp.mc | 8 ++++---- source/CrystalView.mc | 4 ++-- source/DataFields.mc | 2 +- 23 files changed, 26 insertions(+), 18 deletions(-) diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index d0ee781a..ba60984d 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index e9650da9..9cd81223 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 6ea9984d..80a4e370 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index e55484ce..b4a6fe42 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index f8ea2175..3aaccd19 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 41d038ea..b1c3091e 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index cf4e0647..b1e3c259 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index e7c51c0b..5f799ed5 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 53ede7e3..64e9f091 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index b88596bf..b83e7786 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 0cbbc4af..286fa5c9 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index b04e0477..b0bbacae 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index b4385e7a..69028f1e 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index c1457eff..6dfe71c5 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 2a4428d1..6f24ee0c 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 5196630b..689c88c0 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 540664de..58ee12cb 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index f1913c1c..cf3d1f5e 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index f2da68d9..a52c1a53 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -124,4 +124,5 @@ Latitude Longitude Stress Level + Use Complications if available diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 68c95ebb..44e93073 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -405,15 +405,4 @@ class BackgroundService extends Sys.ServiceDelegate { }; Comms.makeWebRequest(url, params, options, callback); } - -(:debug) -function logMessage(message) { - var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - Sys.println(dateStr + " : " + message); -} - -(:release) -function logMessage(output) { -} } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 3c30500f..f0c157c8 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -398,13 +398,13 @@ class CrystalApp extends App.AppBase { } } -(:debug) +(:debug, :background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); Sys.println(dateStr + " : " + message); } -(:release) -function logMessage(output) { -} \ No newline at end of file +(:release, :background) +function logMessage(message) { +} diff --git a/source/CrystalView.mc b/source/CrystalView.mc index e15ed788..7558b03d 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -33,7 +33,7 @@ var gNormalFont; var gIconsFont; var gStressLevel; -/*DEBUG*/ var gStressLevelLogText; +//DEBUG*/ var gStressLevelLogText; const SCREEN_MULTIPLIER = (Sys.getDeviceSettings().screenWidth < 360) ? 1 : 2; //const BATTERY_LINE_WIDTH = 2; @@ -1010,7 +1010,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - /*DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes if (Toybox has :Complications && App.getApp().getView().useComplications()) { diff --git a/source/DataFields.mc b/source/DataFields.mc index 07d007ff..dd7e77f0 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -735,7 +735,7 @@ class DataFields extends Ui.Drawable { value = weatherValue.format(INTEGER_FORMAT) + "°"; } catch (e) { - //DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); + /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); value = "???"; } result["weatherIcon"] = weather["icon"]; From b66ce751ac49532cc5971c266be071ecb29a6443 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 2 May 2023 23:48:57 -0400 Subject: [PATCH 125/220] Trying to fix wierd AoD crash when main display activated Still a work in progress, I can't reproduce it on my Venu 2 --- source/CrystalView.mc | 9 ++++++++- source/DataFields.mc | 25 ++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 7558b03d..e3294fa5 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -310,6 +310,10 @@ class CrystalView extends Ui.WatchFace { rereadWeatherMethod(); } + function burnInProtectionIsOrWasActive() { + return mIsBurnInProtection | mBurnInProtectionChangedSinceLastDraw; + } + // Reread Weather method function rereadWeatherMethod() { var owmKeyOverride = Properties.getValue("OWMKeyOverride"); @@ -654,9 +658,12 @@ class CrystalView extends Ui.WatchFace { // any use of mDrawables cache must only occur when burn in protection is NOT active. // If turning off burn-in protection, recache regular watch face drawables. if (mBurnInProtectionChangedSinceLastDraw) { - mBurnInProtectionChangedSinceLastDraw = false; setLayout(mIsBurnInProtection ? Rez.Layouts.AlwaysOn(dc) : Rez.Layouts.WatchFace(dc)); cacheDrawables(); + mBurnInProtectionChangedSinceLastDraw = false; + if (!mIsBurnInProtection) { + return; + } } // Respond now to any settings change since last full draw, as we can now update the full screen. diff --git a/source/DataFields.mc b/source/DataFields.mc index dd7e77f0..2ce36163 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -42,6 +42,8 @@ enum /* FIELD_TYPES */ { class DataFields extends Ui.Drawable { + private var mView; + var mLeft; var mRight; var mTop; @@ -76,6 +78,8 @@ class DataFields extends Ui.Drawable { // Cache FieldCount setting, and determine appropriate maximum field length. function onSettingsChanged() { + mView = App.getApp().getView(); + // #123 Protect against null or unexpected type e.g. String. mFieldCount = App.getApp().getIntProperty("FieldCount", 3); @@ -101,7 +105,7 @@ class DataFields extends Ui.Drawable { mWeatherIconsSubset = null; } - if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (Toybox has :Complications && mView.useComplications()) { var complications = [{"type" => FIELD_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => FIELD_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS}, {"type" => FIELD_FLOOR_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, @@ -134,7 +138,14 @@ class DataFields extends Ui.Drawable { } function draw(dc) { - update(dc, /* isPartialUpdate */ false); + // I'm getting wierd crashes on AMOLED watchs as if some of the fields of the datafields drawable aren't initialized. Only thing in common is AoD. + // Therefore added a check to make sure we aren't drawing will if are or were in burnin protection. + if (!mView.burnInProtectionIsOrWasActive()) { + update(dc, /* isPartialUpdate */ false); + } + else { + /*DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); + } } function update(dc, isPartialUpdate) { @@ -195,7 +206,7 @@ class DataFields extends Ui.Drawable { if (isHeartRate) { // High power mode: 0 on, 1 off, 2 on, etc. - if (!App.getApp().getView().isSleeping()) { + if (!mView.isSleeping()) { showLiveHRSpot = ((seconds % 2) == 0); // Low power mode: @@ -441,7 +452,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_BODY_BATTERY: - if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (Toybox has :Complications && mView.useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { @@ -463,7 +474,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_STRESS_LEVEL: - if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (Toybox has :Complications && mView.useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { @@ -506,7 +517,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_TYPE_PULSE_OX: - if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (Toybox has :Complications && mView.useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { @@ -522,7 +533,7 @@ class DataFields extends Ui.Drawable { } break; case FIELD_TYPE_HEART_RATE: - if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (Toybox has :Complications && mView.useComplications()) { var fieldTypes = App.getApp().mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { From 75d51d8a13b35ad57009704224040f6438c6adb2 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 3 May 2023 11:28:49 -0400 Subject: [PATCH 126/220] More fix before releasing V2.17.2 Move Complications from mDrawables to mGoalTypes, similar to mFieldTypes --- source/CrystalApp.mc | 16 ++++++++++++-- source/CrystalView.mc | 49 ++++++++++++++++++++++++------------------- source/DataFields.mc | 14 +++++++------ source/GoalMeter.mc | 36 ++++++++++++------------------- 4 files changed, 62 insertions(+), 53 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index f0c157c8..9b1e0c6a 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -25,6 +25,7 @@ class CrystalApp extends App.AppBase { var mView; var mFieldTypes = new [3]; + var mGoalTypes = new [2]; function initialize() { AppBase.initialize(); @@ -32,6 +33,9 @@ class CrystalApp extends App.AppBase { mFieldTypes[0] = {}; mFieldTypes[1] = {}; mFieldTypes[2] = {}; + + mGoalTypes[0] = {}; + mGoalTypes[1] = {}; } // onStart() is called on application start up @@ -78,15 +82,23 @@ class CrystalApp extends App.AppBase { mFieldTypes[1].put("type", getIntProperty("Field2Type", 1)); mFieldTypes[2].put("type", getIntProperty("Field3Type", 2)); + mGoalTypes[0].put("type", getIntProperty("LeftGoalType", 0)); + mGoalTypes[1].put("type", getIntProperty("RightGoalType", 0)); + mView.onSettingsChanged(); // Calls checkPendingWebRequests(). Ui.requestUpdate(); } + function hasGoal(goalType) { + return ((mGoalTypes[0].get("type") == goalType) || + (mGoalTypes[1].get("type") == goalType)); + } + function hasField(fieldType) { return ((mFieldTypes[0].get("type") == fieldType) || - (mFieldTypes[1].get("type") == fieldType) || - (mFieldTypes[2].get("type") == fieldType)); + (mFieldTypes[1].get("type") == fieldType) || + (mFieldTypes[2].get("type") == fieldType)); } // Determine if any web requests are needed. diff --git a/source/CrystalView.mc b/source/CrystalView.mc index e3294fa5..f754ced8 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -407,19 +407,28 @@ class CrystalView extends Ui.WatchFace { function onComplicationUpdated(complicationId) { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); - //var complicationLabel = complication.shortLabel; + var complicationLabel = complication.shortLabel; var complicationValue = complication.value; - //logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue); + if (complicationType == Complications.COMPLICATION_TYPE_STRESS) { + /*DEBUG*/ logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue + " burnIn active? " + mIsBurnInProtection); + } // If we were told to ignore complications, do so (but technicaly, we shouldn't get here as we shouldn't be listening in the first place!) if (!mUseComplications) { /*DEBUG*/ logMessage("How did we get here, we're not supposed to be listening!"); return; } + + // I've seen this while in low power mode, so skip it + if (complicationValue == null) { + return; + } + // Do fields first - var fieldCount = App.getApp().getIntProperty("FieldCount", 3); - var fieldTypes = App.getApp().mFieldTypes; + var app = App.getApp(); + var fieldCount = app.getIntProperty("FieldCount", 3); + var fieldTypes = app.mFieldTypes; for (var i = 0; i < fieldCount; i++) { if (fieldTypes[i].get("ComplicationType") == complicationType) { @@ -429,12 +438,11 @@ class CrystalView extends Ui.WatchFace { } // Now do goals (but only if we're not in burnin protection as our drawables are null in that mode) - if (mDrawables[:LeftGoalMeter] != null && mDrawables[:RightGoalMeter] != null) { - if (mDrawables[:LeftGoalMeter].mComplicationType == complicationType) { - mDrawables[:LeftGoalMeter].mComplicationValue = complicationValue; - } - if (mDrawables[:RightGoalMeter].mComplicationType == complicationType) { - mDrawables[:RightGoalMeter].mComplicationValue = complicationValue; + var goalTypes = app.mGoalTypes; + + for (var i = 0; i < 2; i++) { + if (goalTypes[i].get("ComplicationType") == complicationType) { + goalTypes[i].put("ComplicationValue", complicationValue); } } } @@ -625,19 +633,14 @@ class CrystalView extends Ui.WatchFace { if (!mIsBurnInProtection) { // Recreate background buffers for each meter, in case theme colour has changed. - mDrawables[:LeftGoalMeter].onSettingsChanged(); - mDrawables[:RightGoalMeter].onSettingsChanged(); + mDrawables[:LeftGoalMeter].onSettingsChanged(0); + mDrawables[:RightGoalMeter].onSettingsChanged(1); mDrawables[:MoveBar].onSettingsChanged(); mDataFields.onSettingsChanged(); mDrawables[:Indicators].onSettingsChanged(); - - if (mUseComplications) { - mDrawables[:LeftGoalMeter].setComplication(1); - mDrawables[:RightGoalMeter].setComplication(2); - } } // If watch does not support per-second updates, and watch is sleeping, do not show seconds immediately, as they will not @@ -707,13 +710,15 @@ class CrystalView extends Ui.WatchFace { :staled => false }; + var app = App.getApp(); + var goalTypes = app.mGoalTypes; var info = ActivityMonitor.getInfo(); switch(type) { case GOAL_TYPE_STEPS: values[:isValid] = false; if (Toybox has :Complications && mUseComplications) { - var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + var tmpValue = goalTypes[index].get("ComplicationValue"); if (tmpValue != null) { values[:current] = tmpValue.toNumber(); values[:isValid] = true; @@ -729,7 +734,7 @@ class CrystalView extends Ui.WatchFace { case GOAL_TYPE_FLOORS_CLIMBED: values[:isValid] = false; if (Toybox has :Complications && mUseComplications) { - var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + var tmpValue = goalTypes[index].get("ComplicationValue"); if (tmpValue != null) { values[:current] = tmpValue.toNumber(); values[:isValid] = true; @@ -767,7 +772,7 @@ class CrystalView extends Ui.WatchFace { values[:max] = 100; if (Toybox has :Complications && mUseComplications) { - var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + var tmpValue = goalTypes[index].get("ComplicationValue"); if (tmpValue != null) { values[:current] = tmpValue.toFloat(); values[:isValid] = true; @@ -795,7 +800,7 @@ class CrystalView extends Ui.WatchFace { values[:max] = 100; if (Toybox has :Complications && mUseComplications) { - var tmpValue = mDrawables[(index == 0 ? :LeftGoalMeter : :RightGoalMeter)].mComplicationValue; + var tmpValue = goalTypes[index].get("ComplicationValue"); if (tmpValue != null) { values[:current] = tmpValue.toFloat(); values[:isValid] = true; @@ -881,7 +886,7 @@ class CrystalView extends Ui.WatchFace { // #123 Protect against null value returned by getProperty(). Trigger invalid goal handling code below. // Protect against unexpected type e.g. String. - values[:max] = App.getApp().getIntProperty("CaloriesGoal", 2000); + values[:max] = app.getIntProperty("CaloriesGoal", 2000); break; case GOAL_TYPE_OFF: diff --git a/source/DataFields.mc b/source/DataFields.mc index 2ce36163..9cfb4833 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -78,10 +78,11 @@ class DataFields extends Ui.Drawable { // Cache FieldCount setting, and determine appropriate maximum field length. function onSettingsChanged() { - mView = App.getApp().getView(); + var app = App.getApp(); + mView = app.getView(); // #123 Protect against null or unexpected type e.g. String. - mFieldCount = App.getApp().getIntProperty("FieldCount", 3); + mFieldCount = app.getIntProperty("FieldCount", 3); /* switch (mFieldCount) { case 3: @@ -98,9 +99,9 @@ class DataFields extends Ui.Drawable { // #116 Handle FieldCount = 0 correctly. mMaxFieldLength = [0, 8, 6, 4][mFieldCount]; - mHasLiveHR = App.getApp().hasField(FIELD_TYPE_HR_LIVE_5S); + mHasLiveHR = app.hasField(FIELD_TYPE_HR_LIVE_5S); - if (!App.getApp().hasField(FIELD_TYPE_WEATHER)) { + if (!app.hasField(FIELD_TYPE_WEATHER)) { mWeatherIconsFont = null; mWeatherIconsSubset = null; } @@ -112,12 +113,13 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_TYPE_PULSE_OX, "complicationType" => Complications.COMPLICATION_TYPE_PULSE_OX}, {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE} ]; + + var fieldTypes = app.mFieldTypes; var filled = [false, false, false]; var i; for (i = 0; i < complications.size(); i++) { - if (App.getApp().hasField(complications[i].get("type"))) { - var fieldTypes = App.getApp().mFieldTypes; + if (app.hasField(complications[i].get("type"))) { for (var j = 0; j < mFieldCount; j++) { if (fieldTypes[j].get("type") == complications[i].get("type")) { $.updateComplications("", "Complication_F", j + 1, complications[i].get("complicationType")); diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index 1e7402c0..89716fc4 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -48,9 +48,6 @@ class GoalMeter extends Ui.Drawable { private var mMaxValue; private var mIsOff = false; // #114 Should entire meter on this side be hidden? - var mComplicationType; - var mComplicationValue; - // private enum /* GOAL_METER_STYLES */ { // ALL_SEGMENTS, // ALL_SEGMENTS_MERGED, @@ -68,7 +65,7 @@ class GoalMeter extends Ui.Drawable { mLayoutSeparator = params[:separator]; // Read meter style setting to determine current separator width. - onSettingsChanged(); + onSettingsChanged(mSide == :left ? 0 : 1); mWidth = getWidth(); } @@ -113,7 +110,9 @@ class GoalMeter extends Ui.Drawable { mIsOff = isOff; } - function onSettingsChanged() { + function onSettingsChanged(index) { + var app = App.getApp(); + mBuffersNeedRecreate = true; // #18 Only read separator width from layout if multi segment style is selected. @@ -137,36 +136,27 @@ class GoalMeter extends Ui.Drawable { mSeparator = 0; } - } - function setComplication(index) { - if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (Toybox has :Complications && app.getView().useComplications()) { var complications = [{"type" => GOAL_TYPE_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => GOAL_TYPE_FLOORS_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => GOAL_TYPE_STEPS, "complicationType" => Complications.COMPLICATION_TYPE_STEPS}, {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} ]; - var leftType = Properties.getValue("LeftGoalType"); - var rightType = Properties.getValue("RightGoalType"); - - mComplicationType = null; + var goalTypes = app.mGoalTypes; + var filled = false; for (var i = 0; i < complications.size(); i++) { - if (index == 1 && leftType == complications[i].get("type")) { - $.updateComplications("", "Complication_G", index, complications[i].get("complicationType")); - mComplicationType = complications[i].get("complicationType"); - break; - } - else if (index == 2 && rightType == complications[i].get("type")) { - $.updateComplications("", "Complication_G", index, complications[i].get("complicationType")); - mComplicationType = complications[i].get("complicationType"); - break; + if (goalTypes[index].get("type") == complications[i].get("type")) { + $.updateComplications("", "Complication_G", index + 1, complications[i].get("complicationType")); + goalTypes[index].put("ComplicationType", complications[i].get("complicationType")); + filled = true; } } - if (mComplicationType == null) { - Storage.deleteValue("Complication_G" + index); + if (filled == false) { + Storage.deleteValue("Complication_G" + (index + 1).toString()); } } } From e8f78a87f2be59f7bfac15fb07f8dd059df1acc6 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 3 May 2023 11:49:35 -0400 Subject: [PATCH 127/220] Fixed a crash when Theme color override was invalid --- README.md | 2 +- source/CrystalView.mc | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eb608cba..0f4f00c4 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Reviews: - Made Complications an optional item, disabled by default since some watches are not reading them properly. Settable through Settings - Adjusted the touch points around the Fields, Indicators and Goals value. - Increased the size of the touchpoints as the number of Fields on screen decreases (ie, smallest touchpoint boxes sizes are when three Fields are displayed side by side and the largest touchpoint box is when only one field is dislayed). Doesn't apply to Indicators, just Fields. -- Fixed a few crashes reported through the Error Reporting Application (ERA) +- Fixed a few crashes reported through the Error Reporting Application (ERA) including a crash when Theme color override was invalid. If the color stays to what the selected Theme color is, it's because your override is invalid ### 2.17.1 - Fixed a crash when Complications were received while leaving Always On Display mode diff --git a/source/CrystalView.mc b/source/CrystalView.mc index f754ced8..38615324 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -550,7 +550,18 @@ class CrystalView extends Ui.WatchFace { var theme = App.getApp().getIntProperty("Theme", 0); var lightFlag; var themeOverride = Properties.getValue("ThemeOverride"); - if (themeOverride.equals("")) { + + gThemeColour = null; // Will still be null if our override is invalid + if (themeOverride.equals("") == false) { + try { + gThemeColour = themeOverride.toNumberWithBase(16); + } + catch (e) { + } + lightFlag = Properties.getValue("ThemeLightOverride"); + } + + if (gThemeColour == null) { // Theme-specific colours. gThemeColour = [ Graphics.COLOR_BLUE, // THEME_BLUE_DARK @@ -590,9 +601,6 @@ class CrystalView extends Ui.WatchFace { ]; lightFlag = lightFlags[theme]; - } else { - gThemeColour = themeOverride.toNumberWithBase(16); - lightFlag = Properties.getValue("ThemeLightOverride"); } // #124: fr45 cannot show grey. SG Fr45 not supported From 06ec5b4224c9657187358526c94cdf2236fd729b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 3 May 2023 12:22:41 -0400 Subject: [PATCH 128/220] V2.17.2 - Made Complications an optional item, disabled by default since some watches are not reading them properly. Settable through Settings - Adjusted the touch points around the Fields, Indicators and Goals value. - Increased the size of the touchpoints as the number of Fields on screen decreases (ie, smallest touchpoint boxes sizes are when three Fields are displayed side by side and the largest touchpoint box is when only one field is dislayed). Doesn't apply to Indicators, just Fields. - Fixed a few crashes reported through the Error Reporting Application (ERA) including a crash when Theme color override was invalid. If the color stays to what the selected Theme color is, it's because your override is invalid --- source/CrystalView.mc | 12 ++++++------ source/DataArea.mc | 4 ++-- source/DataFields.mc | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 38615324..faa1bdb1 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -410,13 +410,13 @@ class CrystalView extends Ui.WatchFace { var complicationLabel = complication.shortLabel; var complicationValue = complication.value; - if (complicationType == Complications.COMPLICATION_TYPE_STRESS) { - /*DEBUG*/ logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue + " burnIn active? " + mIsBurnInProtection); - } + //if (complicationType == Complications.COMPLICATION_TYPE_STRESS) { + //DEBUG*/ logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue + " burnIn active? " + mIsBurnInProtection); + //} // If we were told to ignore complications, do so (but technicaly, we shouldn't get here as we shouldn't be listening in the first place!) if (!mUseComplications) { - /*DEBUG*/ logMessage("How did we get here, we're not supposed to be listening!"); + //DEBUG*/ logMessage("How did we get here, we're not supposed to be listening!"); return; } @@ -906,12 +906,12 @@ class CrystalView extends Ui.WatchFace { // crash in GoalMeter.getSegmentScale(). // Sanity check. I've seen weird Invalid Value and "System Error" in DataArea.setGoalValues:48 and :61. Make sure the data is valid if (values[:isValid] && (!(values[:max] instanceof Lang.Number || values[:max] instanceof Lang.Float) || values[:max] < 1)) { - /*DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); + //DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); values[:max] = 1; values[:isValid] = false; } if (values[:isValid] && (!(values[:current] instanceof Lang.Number || values[:current] instanceof Lang.Float))) { - /*DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); + //DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); values[:current] = 0; values[:isValid] = false; } diff --git a/source/DataArea.mc b/source/DataArea.mc index f0aa8d62..503ae77d 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -48,7 +48,7 @@ class DataArea extends Ui.Drawable { mLeftGoalCurrent = leftValues[:current].format(INTEGER_FORMAT); mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY || mLeftGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { - /*DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); + //DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); mLeftGoalCurrent = null; mLeftGoalMax = null; } @@ -61,7 +61,7 @@ class DataArea extends Ui.Drawable { mRightGoalCurrent = rightValues[:current].format(INTEGER_FORMAT); mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY || mRightGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { - /*DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); + //DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); mRightGoalCurrent = null; mRightGoalMax = null; } diff --git a/source/DataFields.mc b/source/DataFields.mc index 9cfb4833..b08c5435 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -146,7 +146,7 @@ class DataFields extends Ui.Drawable { update(dc, /* isPartialUpdate */ false); } else { - /*DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); + //DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); } } @@ -748,7 +748,7 @@ class DataFields extends Ui.Drawable { value = weatherValue.format(INTEGER_FORMAT) + "°"; } catch (e) { - /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); + //DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); value = "???"; } result["weatherIcon"] = weather["icon"]; From 499c267735ca7f6804d9b574d884597a8f569cbb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 3 May 2023 14:27:53 -0400 Subject: [PATCH 129/220] Replaced the 'T' symbol for Tesla in the AoD for the real Tesla icon --- always-on-source/AlwaysOnDisplay.mc | 20 ++++++++++++++++-- .../fonts/crystal-icons-extra-large.fnt | 3 ++- .../fonts/crystal-icons-extra-large.png | Bin 7920 -> 8031 bytes .../fonts/crystal-icons-small.fnt | 5 +++-- .../fonts/crystal-icons-small.png | Bin 5899 -> 6003 bytes 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index 1b2191ef..40f5728d 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -11,7 +11,7 @@ using Toybox.Application.Storage; class AlwaysOnDisplay extends Ui.Drawable { private var mBurnInYOffsets; - private var mHoursFont, mMinutesFont, mSecondsFont, mDateFont, mBatteryFont; + private var mHoursFont, mMinutesFont, mSecondsFont, mDateFont, mBatteryFont, mTeslaFont; // Wide rectangle: time should be moved up slightly to centre within available space. private var mAdjustY = 0; @@ -69,6 +69,11 @@ class AlwaysOnDisplay extends Ui.Drawable { var dateFontOverride = Ui.loadResource(Rez.Strings.DATE_FONT_OVERRIDE); var dateFont = (resourceMap.hasKey(dateFontOverride)) ? resourceMap[dateFontOverride] : rezFonts.AlwaysOnDateFont; mDateFont = Ui.loadResource(dateFont); + + if (Storage.getValue("Tesla") != null) { + mTeslaFont = Ui.loadResource(Rez.Fonts.IconsFont); + } + } function draw(dc) { @@ -228,11 +233,22 @@ class AlwaysOnDisplay extends Ui.Drawable { value = value.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); } + var text = value + " " + battery.format(INTEGER_FORMAT) + "%"; + var widthText = dc.getTextWidthInPixels(text, mBatteryFont); + var widthTeslaT = dc.getTextWidthInPixels("T", mTeslaFont); + + dc.drawText( + dc.getWidth() - mDataLeft - widthText, + y, + mTeslaFont, + "T", + Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER + ); dc.drawText( dc.getWidth() - mDataLeft, y, mBatteryFont, - "T" + value + " " + battery.format(INTEGER_FORMAT) + "%", + value + " " + battery.format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER ); } else { diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt index fecbf0ea..d5e3f12d 100644 --- a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt +++ b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-39 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=39 base=39 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-extra-large.png" -chars count=23 +chars count=24 char id=48 x=0 y=0 width=34 height=39 xoffset=0 yoffset=0 xadvance=34 page=0 chnl=15 char id=49 x=34 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 char id=50 x=73 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 @@ -25,3 +25,4 @@ char id=68 x=206 y=38 width=40 height=39 xoffset=0 yoffset=0 char id=69 x=195 y=78 width=35 height=40 xoffset=0 yoffset=0 xadvance=35 page=0 chnl=15 char id=70 x=0 y=114 width=29 height=40 xoffset=0 yoffset=0 xadvance=29 page=0 chnl=15 char id=71 x=31 y=116 width=36 height=40 xoffset=0 yoffset=0 xadvance=36 page=0 chnl=15 +char id=84 x=67 y=118 width=20 height=30 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.png b/resources-round-390x390/fonts/crystal-icons-extra-large.png index 37abe3990c0891370d7e0f9976cf904fea9599f9..8e75e985a2d69be9ea69f1c7bce9eb24313fd8cf 100644 GIT binary patch delta 6932 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 aiT?pi)rnAVhW4-k0000JW;C|X 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 literal 5899 zcmeHLRaBG>*L`M2K)O3c5Tqo8p+N!ZZg__-XaNmj(qShmN7Uo1q-) z_q+e^znkx@bz<$Cz1BYG;;bE|rJ+cOM~4Rh0HLyyybb_>{*EBvG30M^Dl^ji+i>8@ z>Iyj95F)S`;IcPW{ujb^S2Fel03!H*66C~II}HF3Kub+e0S<>REG%qpZr&v z>+Apc@uRb|^X=QW-@biAp-^FAVe<0wt*x!+=jXe-yJlu)Fc_?$pa6+P9vvM$dGe&D zrpDUZnv|5(*x2~juU}9o6blQBm6f%jp@EN&FETPRE-sFdkx@`ku)n|Gz`(%U+xz3k zk4{cbOG`__!omau1dks-UR_cgac6Rpg@ZjR&nwy)OnwrAH!{g!M z5fc-Oh=_1^cW-KH%FN76NJ!Ao(2$gr+}heID=P~P4P|0tqM)E)V`Bq@!Q|xRK|w)& zetxvHv{Y17^z`&~b#-VodUSNOqoZSQZ!ab$CND29B_#!cK#Yux5D^j0%*@Ei$;rsb zba!`aX=w=v2n-AiBqb$XUS1Xz6{)GI9UL6=_V)Vv`r_c=aBy(Axw&0mUr$U-l$MsB zo}S9e%04_i*xA|T=H^;jS}H3mXJlkxFqn#p3PnZ5>gwv2mKI%I-L$l{fPjGL=x7NE ziNBk9rqKVl{xAMp3Pe!baHmh~;^E?n5oS8ou{6bT_;&z&j1I&ilKDQd5idbJ{N6UL#JAMPZ|9;uS)` z$+n2R;0%r&pw%}_eb}xw&Jj{TO+t7&E=8c5PO0Kr3oukGLjHL+NJqP?&y2&L$oYpq zR?<~^70b1@(YF>Eqaod<2iw+ZV-15~4O!Is-4Yi4eF1BZE?5}Wl1n=eE zFZ4by?{<4cFgadW4|*U!1;sNBGn__eb*<5o&JDAIFuS^`LWQj~A9v$gfIwsKKMG+= zV)>BUX=!W=u!U)zNg;N&Zj0yWl?lE>+)mT5n$xt?;j#5ap>8XFB%DTN>Otz0pHb|ca5wpe zEShVt@YC(*?UK+(d=928S4Y4|Z(M6b61@Dgjsyv*31Pp7Tx+OOL=Sds%9Cx0*A)&t z{}Paq4-?RGZ|Qk)H$7njX9&Lq3IQS_SzXW}`H+!Lw$K{#-g4|d=boo0Occ23?|;^2 zx0h|7_rWWd$eY#4{VrI}RWcumWE-Za7qs|sA`$^U`UM(L)@*OJ#hd$IA zCx6OBWWDgF9^)j=Vt=biIN{>b7|QVlRaT_S-ZmI>fm8(XG(9F2F3*LM;9<)hAgK?I z9^s2Dx#a{2h2oj?wwxF|S0%nxUwSuq@u}|2alo*Y#tPiZ3Drc~ICAI(4UET0DpvpQ?UgDgjXw8jP>*a`q*y>fSM-7vb@nbC)qPVZW zgkV4wNiw45p)eER&t80~^3l35aWN1_#-E+3?`1x02x!DNod9+&l`lQRjEDls04Tg* z;n&ZB8pHw@q->aZ2i&D`uO)Qzz>*L(0YoCg6{HVxhh2h5hH+%ELf%P*;KBg@1ajVK zCalq-MWLT|Z#GtrUZ*4eVV^fA&Th*eTVDrXfs) z%~%5R7AQ0DEb0$-Ap7_?ld3*zJD=k-8md=oLLq$vp?V?ssa|5h7mYxGt*3b5weQn! zBK|&H5R1>=VyIl`ZNY^ku)F@pcbfM%OB{XKD)*@&l-4nyu7o4}r=EO1r3E@wm}R@n z9O3QLPZoS-+)Ss2jjsrmZHe?8bG6+)`$nfUEEz&WbMbBz65{p;#PT{DZ_i5B%Jn)H zBs+4eFd<_M53um`TO`}Cathq%_vTt4px<3TW)tgoRF+yb^S|4Xk33NfLP`sF7hXEE zPWQd5q5PTcb3-Z6t6OhbY!QV-&60lzzGVC|MRiE9O~GLIcAN9+ZHw<;s!mNV(HSBB zJ%B&seM)jtvC3VmuZhk2Lh*@T$#k8fdY*=(&||^4fF`$*EM_uOp%#x3qH%Is%?O`= znAtdt4Y%i(`{r@xN*33w2*)cJO&Er`>>`n0%VQ6G0nNdgrkK)xVt@&3Nwc}MKr#v` zT2t%w@IMr$#hk7ys$(vw3;e`e<=Rh+8!lQLT~*C*D)M8KCU-b0{A`c5XJP$UYg-%r zvwB+Pi#A8_NX`#|LH|4*dO=Wo$x*5qpAMzT5SAkQlvdW!bC-jEI}PDnqrUMNYzPuO?IVamw|)(_`*e{+;Z(F7Fd;ZM9@MtgHIIt6)J$q?48r`jNoU`ocF*}&Kg3S*gV@zO z-{~%Ej|3@(XI;v{du7s4@o2f&C@EXxL1XrafK0*Of8BVTOg|MqQp3;p&XF$v*q%eDpLe&n}x4 z8;;Uc>o>|b*EU}S>{nK|Iwpcb_*A1*4~TT^!7A}D0Jo>OC=z{FnFynR2QI(+gZHPZ zK%|sVzA>Mg=1#kuubong1dafg;_weY$v#jz_6O^gsfzX|m#SJ=vb|q^jAl4mJFVaB z+~~sg3FdCe6MIeeLrywf=P2hfCCb)}MRcb@FA=vSeG03DC*?r)I`o!`B7s(GCPH%% z7v3iLNFLrnN&jQ`)smj8U@TvWewDijTIvIchI-p=HTAMW0acWcoIRlIA@cxDtJ4h0 zh%rT$u72Nylg2i38LsVjq zoRWhrwxQ)syhgpx&-1myHzPo{|EoEl9I~ltrH>e5b1vRGjyy8{ySzkb>an&(91oLQ zPr&Xtq3x}WK&Z(c!w2>E48-&MUJ3yhZ&b(En*?*IG|Crnz`Y0CEcSZlMuhN5zDzHg z5ksBA#5S(9hUEQu6DRENVMC_`0f8?|K~<>Sj5|-25iS&OC4Q)05Iw-zW}^E;V%rZ! zp(c#;ZH{}JK3P2x>$1#ZZ0=-x1o5ddlKP8H`dw2fKRs^6WOz_UQW)+>js)xk)7qvl zd^|@72aPB+RSok+?un2o@AO2&FXmm(#h{RN%mW?X2Vt&NLqanoiE*-BRAGxU(W)&&R;s>Xhqu~&Za)A z){PJ?YZEFEU&LuUDGVim#~bm|tOgO{gSQpwO`hbtg+FP`Yp>$YxBUmDL$un&_%#$UOy0JAPoYHh?$Gb$uNa%;q-m{PJE0_B=aI=5Bi-(x-r1 zrz6uv8N?yWr8#O$#hYN=6T^C+9GzO9JG<|2zIJw2BlenOuq#7M0~^&S$jIK%eZisY zCl>_~O*Lrq9Ng5t;K9w_Y<6jUQ;ny{vq^{I8XLVBT3GW1TD-kg@bdiyfukgNdu9{G!yV6mH=exBAFdra+OR9upPSyp^4%}YFVVp`O%LRN23!!=}ZPP|1^XVSg><(DYz za<6^`%-`?DTzukL?7M_AX9|uLVDYZm$aNwqz&hQ2HCOwM`uj~9AclNzuXp^UBJS96+cub%V@VD-+~jp+G=CPK)Qh6J%@+pdt7+V%)V-Q|bN#zBR2^ggyP8UW?Mb+NNFm`poG0U;qkl z>$=oR7IIQmr}rA{W#@4bsQj;hVz2>R|72`$duL}S2y-xyXx`o8t6XQTh>;*gTZ)L) z{6=m~>mt8c?Jh>?pRE2eexG1cEyXqvajj`}VmDuTBi@_dYjk|*Py)@gANJ~&#LpiC z?;WWGM?0hj_(A3j)DIhixEJX2D!*Ze1S5N(N@>P1Px%(7$PJJ?(!5(~9vE~YjlTy^ zitp^+%DI`Os<%heZiRd!rX|IV~N`m z4b3pO39nhb^>aanaS6V2?z?Q4DGj=FiOenNIpsJIkeQyoAytOB%b0<|npzpOR`Dil z2UYK=IEBH=ZalRYPbd;EBq9xXAb$Ph8+0a9IOln(8^b-qOGOv!)-kh3y?!meTmS i5B#4X|KBm(;lxjX57ZssN&d$rR94WCuXt_o;r{?L19*u5 From 963ff54ed12c0dd0746b9314471eebdd31bb779f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 3 May 2023 20:31:08 -0400 Subject: [PATCH 130/220] Hardened the Properties.getValue calls --- always-on-source/AlwaysOnDisplay.mc | 45 ++++++----- source/BackgroundService.mc | 20 ++--- source/CrystalApp.mc | 112 ++++++++++++++++++++++++---- source/CrystalView.mc | 55 +++++++------- source/DataArea.mc | 12 ++- source/DataFields.mc | 6 +- source/GoalMeter.mc | 8 +- source/Indicators.mc | 8 +- source/MoveBar.mc | 4 +- source/ThickThinTime.mc | 2 +- 10 files changed, 182 insertions(+), 90 deletions(-) diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index 40f5728d..11f7b7d9 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -198,7 +198,29 @@ class AlwaysOnDisplay extends Ui.Drawable { // Date. y = mDataY + burnInYOffset; - if (Storage.getValue("Tesla") != null) { + if (Storage.getValue("Tesla") == null) { + dc.drawText( + mDataLeft, + y, + mDateFont, + Lang.format("$1$ $2$ $3$", [mDayOfWeekString, day, mMonthString]), + Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER + ); + + // Battery. + var battery = Math.floor(Sys.getSystemStats().battery); + dc.drawText( + dc.getWidth() - mDataLeft, + y, + mBatteryFont, + battery.format(INTEGER_FORMAT) + "%", + Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER + ); + } +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** + else { dc.drawText( mDataLeft, y, @@ -251,24 +273,9 @@ class AlwaysOnDisplay extends Ui.Drawable { value + " " + battery.format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER ); - } else { - dc.drawText( - mDataLeft, - y, - mDateFont, - Lang.format("$1$ $2$ $3$", [mDayOfWeekString, day, mMonthString]), - Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER - ); - - // Battery. - var battery = Math.floor(Sys.getSystemStats().battery); - dc.drawText( - dc.getWidth() - mDataLeft, - y, - mBatteryFont, - battery.format(INTEGER_FORMAT) + "%", - Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER - ); } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** } } \ No newline at end of file diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 44e93073..27120352 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -26,7 +26,7 @@ class BackgroundService extends Sys.ServiceDelegate { // Need to get a token since we can't OAUTH from a watch face :-( // If someone can do it, be my guest. I spent too much time on this already - _token = Properties.getValue("TeslaAccessToken"); + _token = $.getStringProperty("TeslaAccessToken",""); var createdAt = Storage.getValue("TeslaTokenCreatedAt"); if (createdAt == null) { @@ -51,7 +51,7 @@ class BackgroundService extends Sys.ServiceDelegate { } else { //2023-03-05 logMessage("initialize:Generating Access Token"); - var refreshToken = Properties.getValue("TeslaRefreshToken"); + var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); } else { @@ -62,9 +62,9 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = Storage.getValue("TeslaVehicleID"); if (_vehicle_id == null) { - makeTeslaWebRequest("https://" + Properties.getValue("TeslaServerAPILocation") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); } else { - makeTeslaWebRequest("https://" + Properties.getValue("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* @@ -85,7 +85,7 @@ class BackgroundService extends Sys.ServiceDelegate { makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { - "city" => Properties.getValue("LocalTimeInCity") + "city" => $.getStringProperty("LocalTimeInCity","") }, method(:onReceiveCityLocalTime) ); @@ -94,9 +94,9 @@ class BackgroundService extends Sys.ServiceDelegate { // 2. Weather. if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { - var owmKeyOverride = Properties.getValue("OWMKeyOverride"); - var lat = Properties.getValue("LastLocationLat"); - var lon = Properties.getValue("LastLocationLng"); + var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); + var lat = $.getStringProperty("LastLocationLat",""); + var lon = $.getStringProperty("LastLocationLng",""); if (lat != null && lon != null) { makeWebRequest( @@ -134,7 +134,7 @@ class BackgroundService extends Sys.ServiceDelegate { } if (_vehicle_id) { - makeTeslaWebRequest("https://" + Properties.getValue("TeslaServerAPILocation") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } } } /* else { @@ -361,7 +361,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function makeTeslaWebPost(token, notify) { - var url = "https://" + Properties.getValue("TeslaServerAUTHLocation") + "/oauth2/v3/token"; + var url = "https://" + $.getStringProperty("TeslaServerAUTHLocation","") + "/oauth2/v3/token"; Comms.makeWebRequest( url, { diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 9b1e0c6a..8b689279 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -66,16 +66,6 @@ class CrystalApp extends App.AppBase { return mView; } - function getIntProperty(key, defaultValue) { - var value = Properties.getValue(key); - if (value == null) { - value = defaultValue; - } else if (!(value instanceof Number)) { - value = value.toNumber(); - } - return value; - } - // New app settings have been received so trigger a UI update function onSettingsChanged() { mFieldTypes[0].put("type", getIntProperty("Field1Type", 0)); @@ -123,12 +113,12 @@ class CrystalApp extends App.AppBase { // If current location is not available, read stored value from Object Store, being careful not to overwrite a valid // in-memory value with an invalid stored one. else { - var lat = Properties.getValue("LastLocationLat"); + var lat = $.getStringProperty("LastLocationLat",""); if (lat != null) { gLocationLat = lat.toFloat(); } - var lng = Properties.getValue("LastLocationLng"); + var lng = $.getStringProperty("LastLocationLng",""); if (lng != null) { gLocationLng = lng.toFloat(); } @@ -145,7 +135,7 @@ class CrystalApp extends App.AppBase { // 1. City local time: // City has been specified. - var city = Properties.getValue("LocalTimeInCity"); + var city = $.getStringProperty("LocalTimeInCity",""); // #78 Setting with value of empty string may cause corresponding property to be null. if ((city != null) && (city.length() > 0)) { @@ -175,7 +165,7 @@ class CrystalApp extends App.AppBase { if ((gLocationLat != null) && (hasField(FIELD_TYPE_WEATHER) || hasField(FIELD_TYPE_HUMIDITY))) { - var owmKeyOverride = Properties.getValue("OWMKeyOverride"); + var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { //2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); } else { @@ -400,7 +390,7 @@ class CrystalApp extends App.AppBase { // #10 If in 12-hour mode with Hide Hours Leading Zero set, hide leading zero. Otherwise, show leading zero. // #69 Setting now applies to both 12- and 24-hour modes. - hour = hour.format(Properties.getValue("HideHoursLeadingZero") ? INTEGER_FORMAT : "%02d"); + hour = hour.format($.getBoolProperty("HideHoursLeadingZero", true) ? INTEGER_FORMAT : "%02d"); return { :hour => hour, @@ -410,6 +400,98 @@ class CrystalApp extends App.AppBase { } } +(:background) +function getIntProperty(key, defaultValue) { + var value; + + try { + value = Properties.getValue(key); + } + catch (e) { + value = defaultValue; + } + if (value == null) { + value = defaultValue; + } else if (!(value instanceof Lang.Number)) { + try { + value = value.toNumber(); + } + catch (e) { + value = defaultValue; + } + } + return value; +} + +(:background) +function getFloatProperty(key, defaultValue) { + var value; + + try { + value = Properties.getValue(key); + } + catch (e) { + value = defaultValue; + } + if (value == null) { + value = defaultValue; + } else if (!(value instanceof Lang.Float)) { + try { + value = value.toFloat(); + } + catch (e) { + value = defaultValue; + } + } + return value; +} + +(:background) +function getStringProperty(key, defaultValue) { + var value; + + try { + value = Properties.getValue(key); + } + catch (e) { + value = defaultValue; + } + if (value == null) { + value = defaultValue; + } else if (!(value instanceof Lang.String)) { + try { + value = value.toString(); + } + catch (e) { + value = defaultValue; + } + } + return value; +} + +(:background) +function getBoolProperty(key, defaultValue) { + var value; + + try { + value = Properties.getValue(key); + } + catch (e) { + value = defaultValue; + } + if (value == null) { + value = defaultValue; + } else if (!(value instanceof Lang.Boolean)) { + try { + value = (value == true); + } + catch (e) { + value = defaultValue; + } + } + return value; +} + (:debug, :background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index faa1bdb1..749df614 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -316,7 +316,7 @@ class CrystalView extends Ui.WatchFace { // Reread Weather method function rereadWeatherMethod() { - var owmKeyOverride = Properties.getValue("OWMKeyOverride"); + var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); //2022-04-10 logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { if (Toybox has :Weather) { @@ -358,7 +358,7 @@ class CrystalView extends Ui.WatchFace { mDrawables[:MoveBar] = View.findDrawableById("MoveBar"); - setHideSeconds(Properties.getValue("HideSeconds")); // Requires mTime, mDrawables[:MoveBar]; + setHideSeconds($.getIntProperty("HideSeconds", 0)); // Requires mTime, mDrawables[:MoveBar]; } /* @@ -395,7 +395,7 @@ class CrystalView extends Ui.WatchFace { } // Reread our complications if we're allowed - mUseComplications = Properties.getValue("UseComplications"); + mUseComplications = $.getBoolProperty("UseComplications", false); if (Toybox has :Complications) { // First we drop all our subscriptions before building a new list Complications.unsubscribeFromAllUpdates(); @@ -407,7 +407,7 @@ class CrystalView extends Ui.WatchFace { function onComplicationUpdated(complicationId) { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); - var complicationLabel = complication.shortLabel; + //DEBUG*/ var complicationLabel = complication.shortLabel; var complicationValue = complication.value; //if (complicationType == Complications.COMPLICATION_TYPE_STRESS) { @@ -416,28 +416,28 @@ class CrystalView extends Ui.WatchFace { // If we were told to ignore complications, do so (but technicaly, we shouldn't get here as we shouldn't be listening in the first place!) if (!mUseComplications) { - //DEBUG*/ logMessage("How did we get here, we're not supposed to be listening!"); + /*DEBUG*/ logMessage("How did we get here, we're not supposed to be listening!"); return; } // I've seen this while in low power mode, so skip it if (complicationValue == null) { + /*DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); return; } // Do fields first var app = App.getApp(); - var fieldCount = app.getIntProperty("FieldCount", 3); + var fieldCount = $.getIntProperty("FieldCount", 3); var fieldTypes = app.mFieldTypes; for (var i = 0; i < fieldCount; i++) { if (fieldTypes[i].get("ComplicationType") == complicationType) { fieldTypes[i].put("ComplicationValue", complicationValue); - break; } } - // Now do goals (but only if we're not in burnin protection as our drawables are null in that mode) + // Now do goals var goalTypes = app.mGoalTypes; for (var i = 0; i < 2; i++) { @@ -536,8 +536,7 @@ class CrystalView extends Ui.WatchFace { // Saves memory when cities are not in use. // Update drawables that use normal font. function updateNormalFont() { - - var city = Properties.getValue("LocalTimeInCity"); + var city = $.getStringProperty("LocalTimeInCity",""); // #78 Setting with value of empty string may cause corresponding property to be null. gNormalFont = Ui.loadResource(((city != null) && (city.length() > 0)) ? @@ -547,9 +546,9 @@ class CrystalView extends Ui.WatchFace { function updateThemeColours() { // #182 Protect against null or unexpected type e.g. String. - var theme = App.getApp().getIntProperty("Theme", 0); + var theme = $.getIntProperty("Theme", 0); var lightFlag; - var themeOverride = Properties.getValue("ThemeOverride"); + var themeOverride = $.getStringProperty("ThemeOverride",""); gThemeColour = null; // Will still be null if our override is invalid if (themeOverride.equals("") == false) { @@ -558,7 +557,7 @@ class CrystalView extends Ui.WatchFace { } catch (e) { } - lightFlag = Properties.getValue("ThemeLightOverride"); + lightFlag = $.getStringProperty("ThemeLightOverride", ""); } if (gThemeColour == null) { @@ -630,10 +629,10 @@ class CrystalView extends Ui.WatchFace { // #182 Protect against null or unexpected type e.g. String. // #182 Protect against invalid integer values (still crashing with getIntProperty()). - var hco = App.getApp().getIntProperty("HoursColourOverride", 0); + var hco = $.getIntProperty("HoursColourOverride", 0); gHoursColour = overrideColours[(hco < 0 || hco > 2) ? 0 : hco]; - var mco = App.getApp().getIntProperty("MinutesColourOverride", 0); + var mco = $.getIntProperty("MinutesColourOverride", 0); gMinutesColour = overrideColours[(mco < 0 || mco > 2) ? 0 : mco]; } @@ -654,7 +653,7 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, and watch is sleeping, do not show seconds immediately, as they will not // update. Instead, wait for next onExitSleep(). if (PER_SECOND_UPDATES_SUPPORTED || !mIsSleeping) { - setHideSeconds(Properties.getValue("HideSeconds")); + setHideSeconds($.getIntProperty("HideSeconds", 0)); } mSettingsChangedSinceLastDraw = false; @@ -699,11 +698,11 @@ class CrystalView extends Ui.WatchFace { return; } - var leftType = Properties.getValue("LeftGoalType"); + var leftType = $.getIntProperty("LeftGoalType", 0); var leftValues = getValuesForGoalType(0, leftType); mDrawables[:LeftGoalMeter].setValues(leftValues[:current], leftValues[:max], /* isOff */ leftType == GOAL_TYPE_OFF); - var rightType = Properties.getValue("RightGoalType"); + var rightType = $.getIntProperty("RightGoalType", 1); var rightValues = getValuesForGoalType(1, rightType); mDrawables[:RightGoalMeter].setValues(rightValues[:current], rightValues[:max], /* isOff */ rightType == GOAL_TYPE_OFF); @@ -894,7 +893,7 @@ class CrystalView extends Ui.WatchFace { // #123 Protect against null value returned by getProperty(). Trigger invalid goal handling code below. // Protect against unexpected type e.g. String. - values[:max] = app.getIntProperty("CaloriesGoal", 2000); + values[:max] = $.getIntProperty("CaloriesGoal", 2000); break; case GOAL_TYPE_OFF: @@ -906,12 +905,12 @@ class CrystalView extends Ui.WatchFace { // crash in GoalMeter.getSegmentScale(). // Sanity check. I've seen weird Invalid Value and "System Error" in DataArea.setGoalValues:48 and :61. Make sure the data is valid if (values[:isValid] && (!(values[:max] instanceof Lang.Number || values[:max] instanceof Lang.Float) || values[:max] < 1)) { - //DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); + /*DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); values[:max] = 1; values[:isValid] = false; } if (values[:isValid] && (!(values[:current] instanceof Lang.Number || values[:current] instanceof Lang.Float))) { - //DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); + /*DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); values[:current] = 0; values[:isValid] = false; } @@ -944,7 +943,7 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, AND HideSeconds property is false, // show seconds, and make move bar original width. - var hideSeconds = Properties.getValue("HideSeconds"); + var hideSeconds = $.getIntProperty("HideSeconds", 0); if ((!PER_SECOND_UPDATES_SUPPORTED && hideSeconds == 0) || hideSeconds == 1 ) { setHideSeconds(false); } @@ -978,7 +977,7 @@ class CrystalView extends Ui.WatchFace { // If watch does not support per-second updates, then hide seconds, and make move bar full width. // onUpdate() is about to be called one final time before entering sleep. // If HideSeconds property is true, do not wastefully hide seconds again (they should already be hidden). - var hideSeconds = Properties.getValue("HideSeconds"); + var hideSeconds = $.getIntProperty("HideSeconds", 0); if ((!PER_SECOND_UPDATES_SUPPORTED && hideSeconds == 0) || hideSeconds == 1) { setHideSeconds(true); } @@ -1030,7 +1029,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + /*DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes if (Toybox has :Complications && App.getApp().getView().useComplications()) { @@ -1043,7 +1042,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { function checkBoundingBoxes(co_ords) { // First check the indicators - var indicatorCount = App.getApp().getIntProperty("IndicatorCount", 1); + var indicatorCount = $.getIntProperty("IndicatorCount", 1); var spacingX; var spacingY; var complicationIndex; @@ -1085,7 +1084,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { } // Check the fields - var fieldCount = App.getApp().getIntProperty("FieldCount", 3); + var fieldCount = $.getIntProperty("FieldCount", 3); if (fieldCount > 0) { spacingX = Sys.getDeviceSettings().screenWidth / (2 * fieldCount); @@ -1137,11 +1136,11 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { function isWithin(x, y, startX, startY, spacingX, spacingY, field) { if (x > startX && x < startX + spacingX && y > startY and y < startY + spacingY) { - //DEBUG*/ logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); + /*DEBUG*/ logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); return field; } else { - //DEBUG*/ logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); + /*DEBUG*/ logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); return ""; } } diff --git a/source/DataArea.mc b/source/DataArea.mc index 503ae77d..4e4ff174 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -48,7 +48,9 @@ class DataArea extends Ui.Drawable { mLeftGoalCurrent = leftValues[:current].format(INTEGER_FORMAT); mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY || mLeftGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { - //DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); + if (leftValues[:isValid]) { + /*DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); + } mLeftGoalCurrent = null; mLeftGoalMax = null; } @@ -61,7 +63,9 @@ class DataArea extends Ui.Drawable { mRightGoalCurrent = rightValues[:current].format(INTEGER_FORMAT); mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY || mRightGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { - //DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); + if (rightValues[:isValid]) { + /*DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); + } mRightGoalCurrent = null; mRightGoalMax = null; } @@ -71,7 +75,7 @@ class DataArea extends Ui.Drawable { drawGoalIcon(dc, mGoalIconLeftX, mLeftGoalType, mLeftGoalIsValid, mLeftGoalstaled, Graphics.TEXT_JUSTIFY_LEFT); drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, mRightGoalstaled, Graphics.TEXT_JUSTIFY_RIGHT); - var city = Properties.getValue("LocalTimeInCity"); + var city = $.getStringProperty("LocalTimeInCity", ""); // #78 Setting with value of empty string may cause corresponding property to be null. if ((city != null) && (city.length() != 0)) { @@ -182,7 +186,7 @@ class DataArea extends Ui.Drawable { } function drawGoalValues(dc, x, currentValue, maxValue, align) { - var digitStyle = Properties.getValue("GoalMeterDigitsStyle"); + var digitStyle = $.getIntProperty("GoalMeterDigitsStyle", 0); // #107 Only draw values if digit style is not Hidden. if (digitStyle != 2 /* HIDDEN */) { diff --git a/source/DataFields.mc b/source/DataFields.mc index b08c5435..d6f72a36 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -82,7 +82,7 @@ class DataFields extends Ui.Drawable { mView = app.getView(); // #123 Protect against null or unexpected type e.g. String. - mFieldCount = app.getIntProperty("FieldCount", 3); + mFieldCount = $.getIntProperty("FieldCount", 3); /* switch (mFieldCount) { case 3: @@ -146,7 +146,7 @@ class DataFields extends Ui.Drawable { update(dc, /* isPartialUpdate */ false); } else { - //DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); + /*DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); } } @@ -748,7 +748,7 @@ class DataFields extends Ui.Drawable { value = weatherValue.format(INTEGER_FORMAT) + "°"; } catch (e) { - //DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); + /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); value = "???"; } result["weatherIcon"] = weather["icon"]; diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index 89716fc4..bff6a1e7 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -117,7 +117,7 @@ class GoalMeter extends Ui.Drawable { // #18 Only read separator width from layout if multi segment style is selected. // #62 Or if filled segment style is selected. - var goalMeterStyle = Properties.getValue("GoalMeterStyle"); + var goalMeterStyle = $.getIntProperty("GoalMeterStyle", 0); if ((goalMeterStyle == 0 /* ALL_SEGMENTS */) || (goalMeterStyle == 3 /* FILLED_SEGMENTS */)) { // Force recalculation of mSegments in setValues() if mSeparator is about to change. @@ -173,7 +173,7 @@ class GoalMeter extends Ui.Drawable { function draw(dc) { // #114 TODO: Any buffers not yet reclaimed if goal meter set to off. - if ((Properties.getValue("GoalMeterStyle") == 2 /* HIDDEN */) || mIsOff) { + if (($.getIntProperty("GoalMeterStyle", 0) == 2 /* HIDDEN */) || mIsOff) { return; } @@ -195,7 +195,7 @@ class GoalMeter extends Ui.Drawable { // Unfilled segments: fill height --> height. // #62 ALL_SEGMENTS or ALL_SEGMENTS_MERGED. - if (Properties.getValue("GoalMeterStyle") <= 1) { + if ($.getIntProperty("GoalMeterStyle", 0) <= 1) { drawSegments(dc, left, top, gMeterBackgroundColour, mSegments, mFillHeight, mHeight); } } @@ -271,7 +271,7 @@ class GoalMeter extends Ui.Drawable { // Draw unfilled segments. // #62 ALL_SEGMENTS or ALL_SEGMENTS_MERGED. - if (Properties.getValue("GoalMeterStyle") <= 1) { + if ($.getIntProperty("GoalMeterStyle", 0) <= 1) { clipBottom = clipTop; clipTop = top; clipHeight = clipBottom - clipTop; diff --git a/source/Indicators.mc b/source/Indicators.mc index 3ffff334..d8a84d62 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -39,9 +39,9 @@ class Indicators extends Ui.Drawable { } function onSettingsChanged() { - mIndicator1Type = Properties.getValue("Indicator1Type"); - mIndicator2Type = Properties.getValue("Indicator2Type"); - mIndicator3Type = Properties.getValue("Indicator3Type"); + mIndicator1Type = $.getIntProperty("Indicator1Type", 5); + mIndicator2Type = $.getIntProperty("Indicator2Type", 3); + mIndicator3Type = $.getIntProperty("Indicator3Type", 0); //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** @@ -80,7 +80,7 @@ class Indicators extends Ui.Drawable { function draw(dc) { // #123 Protect against null or unexpected type e.g. String. - var indicatorCount = App.getApp().getIntProperty("IndicatorCount", 1); + var indicatorCount = $.getIntProperty("IndicatorCount", 1); // Horizontal layout for rectangle-148x205. if (mIsHorizontal) { diff --git a/source/MoveBar.mc b/source/MoveBar.mc index 8bea2c95..b1c8eab5 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -54,7 +54,7 @@ class MoveBar extends Ui.Drawable { } function draw(dc) { - if (Properties.getValue("MoveBarStyle") == 2 /* HIDDEN */) { + if ($.getIntProperty("MoveBarStyle", 0) == 2 /* HIDDEN */) { return; } @@ -137,7 +137,7 @@ class MoveBar extends Ui.Drawable { var thisBarWidth; var thisBarColour = 0; var barX = x + mTailWidth; - var moveBarStyle = Properties.getValue("MoveBarStyle"); + var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); // One-based, to correspond with move bar level (zero means no bars). for (var i = 1; i <= ActivityMonitor.MOVE_BAR_LEVEL_MAX; ++i) { diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index c0605ebc..a7cf8be9 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -91,7 +91,7 @@ class ThickThinTime extends Ui.Drawable { var addColon; try { - addColon = Properties.getValue("AddColon"); + addColon = $.getBoolProperty("AddColon", false); } catch (e) { addColon = false; From 39cfbc295edc196c3d5e85fafbb207f19bdbd7ff Mon Sep 17 00:00:00 2001 From: SylvainGa Date: Thu, 4 May 2023 11:00:52 -0400 Subject: [PATCH 131/220] 2.17.4 - One more attempt at fixing the crash because of the Settings change since 2.17.1 --- README.md | 10 +++++++++ source/CrystalApp.mc | 53 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0f4f00c4..0b7c968a 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,16 @@ Reviews: ## Below is what has been added by me (SylvainGa). +<<<<<<< Updated upstream +======= +### 2.17.4 +- One more attempt at fixing the crash because of the Settings change since 2.17.1 + +### 2.17.3 +- Main change is the hardening of the Properties reading to fix a crash (crash caused by the new Complication checkbox in Settings on some watches) +- Replaced the T letter before the Tesla's battery charge in AlwaysOnDisplays to the Tesla Symbol + +>>>>>>> Stashed changes ### 2.17.2 - Made Complications an optional item, disabled by default since some watches are not reading them properly. Settable through Settings - Adjusted the touch points around the Fields, Indicators and Goals value. diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 8b689279..5a373cf3 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -410,7 +410,13 @@ function getIntProperty(key, defaultValue) { catch (e) { value = defaultValue; } - if (value == null) { + + return validateNumber(value, defaultValue); +} + +(:background) +function validateNumber(value, defaultValue) { + if (value == null || !(value has :toNumber)) { value = defaultValue; } else if (!(value instanceof Lang.Number)) { try { @@ -420,6 +426,9 @@ function getIntProperty(key, defaultValue) { value = defaultValue; } } + if (value == null) { + value = defaultValue; + } return value; } @@ -433,7 +442,12 @@ function getFloatProperty(key, defaultValue) { catch (e) { value = defaultValue; } - if (value == null) { + return validateFloat(value, defaultValue); +} + +(:background) +function validateFloat(value, defaultValue) { + if (value == null || !(value has :toFloat)) { value = defaultValue; } else if (!(value instanceof Lang.Float)) { try { @@ -443,6 +457,9 @@ function getFloatProperty(key, defaultValue) { value = defaultValue; } } + if (value == null) { + value = defaultValue; + } return value; } @@ -456,7 +473,12 @@ function getStringProperty(key, defaultValue) { catch (e) { value = defaultValue; } - if (value == null) { + return validateString(value, defaultValue); +} + +(:background) +function validateString(value, defaultValue) { + if (value == null || !(value has :toString)) { value = defaultValue; } else if (!(value instanceof Lang.String)) { try { @@ -466,6 +488,9 @@ function getStringProperty(key, defaultValue) { value = defaultValue; } } + if (value == null) { + value = defaultValue; + } return value; } @@ -479,16 +504,34 @@ function getBoolProperty(key, defaultValue) { catch (e) { value = defaultValue; } + + return validateBoolean(value, defaultValue); +} + +(:background) +function validateBoolean(value, defaultValue) { if (value == null) { value = defaultValue; - } else if (!(value instanceof Lang.Boolean)) { + } else if ((value instanceof Lang.Boolean) || (value instanceof Lang.Number)) { try { - value = (value == true); + if (value) { + value = true; + } + else { + value = false; + } } catch (e) { value = defaultValue; } } + else { + value = defaultValue; + } + + if (value == null) { + value = defaultValue; + } return value; } From 6d8222b2b25fc3cf63e72c5799904ea1e3085507 Mon Sep 17 00:00:00 2001 From: SylvainGa Date: Thu, 4 May 2023 12:29:47 -0400 Subject: [PATCH 132/220] Changed version in string file --- README.md | 3 --- resources/strings/strings.xml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 0b7c968a..0819a7c9 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,6 @@ Reviews: ## Below is what has been added by me (SylvainGa). -<<<<<<< Updated upstream -======= ### 2.17.4 - One more attempt at fixing the crash because of the Settings change since 2.17.1 @@ -36,7 +34,6 @@ Reviews: - Main change is the hardening of the Properties reading to fix a crash (crash caused by the new Complication checkbox in Settings on some watches) - Replaced the T letter before the Tesla's battery charge in AlwaysOnDisplays to the Tesla Symbol ->>>>>>> Stashed changes ### 2.17.2 - Made Complications an optional item, disabled by default since some watches are not reading them properly. Settable through Settings - Adjusted the touch points around the Fields, Indicators and Goals value. diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 07028410..ce9968d1 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.17.2 + Crystal-Tesla V2.17.4 Theme Hours Colour From f4678851bf22453d191baf0375bdbb9abf52448f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 5 May 2023 15:18:00 -0400 Subject: [PATCH 133/220] Optimize global function calling time, fix bug in themelight dectection --- source/BackgroundService.mc | 12 +++++++---- source/CrystalApp.mc | 43 +++++++++++++++++++++++++++++++++++++ source/CrystalView.mc | 13 +++++------ source/Indicators.mc | 6 +++--- 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 27120352..231d8456 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -50,7 +50,7 @@ class BackgroundService extends Sys.ServiceDelegate { _token = "Bearer " + _token; } else { - //2023-03-05 logMessage("initialize:Generating Access Token"); + /*DEBUG*/ logMessage("initialize:Generating Access Token"); var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { makeTeslaWebPost(refreshToken, method(:onReceiveToken)); @@ -62,8 +62,10 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = Storage.getValue("TeslaVehicleID"); if (_vehicle_id == null) { + /*DEBUG*/ logMessage("initialize:Getting vehicles"); makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); } else { + /*DEBUG*/ logMessage("initialize:Getting vehicle data"); makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } //**************************************************************** @@ -285,7 +287,7 @@ class BackgroundService extends Sys.ServiceDelegate { var result; //2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); - //logMessage("onReceiveToken data is " + data); + /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); if (responseCode == 200) { result = { "Token" => data }; } else { @@ -298,7 +300,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveVehicles(responseCode, data) { var result; - //2023-03-05 logMessage("onReceiveVehicles responseCode is " + responseCode + " with data " + data); + /*DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); if (responseCode == 200) { var vehicles = data.get("response"); if (vehicles.size() > 0) { @@ -325,7 +327,9 @@ class BackgroundService extends Sys.ServiceDelegate { var precondEnabled = "N/A"; var sentryEnabled = "N/A"; - //2023-03-05 logMessage("onReceiveVehicleData responseCode is " + responseCode); + /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); + /*DEBUG*/ var myStats = Sys.getSystemStats(); + /*DEBUG*/ logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); if (responseCode == 200) { results = data.get("response"); if (results != null) { diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 5a373cf3..556a464c 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -403,14 +403,24 @@ class CrystalApp extends App.AppBase { (:background) function getIntProperty(key, defaultValue) { var value; + var exception; try { + exception = false; value = Properties.getValue(key); } catch (e) { + exception = true; value = defaultValue; } + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } return validateNumber(value, defaultValue); } @@ -435,13 +445,24 @@ function validateNumber(value, defaultValue) { (:background) function getFloatProperty(key, defaultValue) { var value; + var exception; try { + exception = false; value = Properties.getValue(key); } catch (e) { + exception = true; value = defaultValue; } + + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } return validateFloat(value, defaultValue); } @@ -466,13 +487,24 @@ function validateFloat(value, defaultValue) { (:background) function getStringProperty(key, defaultValue) { var value; + var exception; try { + exception = false; value = Properties.getValue(key); } catch (e) { + exception = true; value = defaultValue; } + + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } return validateString(value, defaultValue); } @@ -497,14 +529,25 @@ function validateString(value, defaultValue) { (:background) function getBoolProperty(key, defaultValue) { var value; + var exception; try { + exception = false; value = Properties.getValue(key); } catch (e) { + exception = true; value = defaultValue; } + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } + return validateBoolean(value, defaultValue); } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 749df614..b39db1d3 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -237,11 +237,14 @@ function updateComplications(complicationName, storageName, index, complicationT if (Toybox has :Complications) { // Check if we should subscribe to our Tesla Complication var iter = Complications.getComplications(); + if (iter == null) { + return; + } var complicationId = iter.next(); while (complicationId != null) { //logMessage(complicationId.longLabel.toString()); - if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel.equals(complicationName))) { + if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(complicationName))) { //DEBUG*/ logMessage("Found complication " + complicationName + " with type " + complicationType); break; } @@ -422,7 +425,7 @@ class CrystalView extends Ui.WatchFace { // I've seen this while in low power mode, so skip it if (complicationValue == null) { - /*DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); + //DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); return; } @@ -530,6 +533,7 @@ class CrystalView extends Ui.WatchFace { //2022-04-10 logMessage("No weather data, returning null"); } Storage.setValue("OpenWeatherMapCurrent", result); + Storage.setValue("NewOpenWeatherMapCurrent", true); } // Select normal font, based on whether time zone feature is being used. @@ -557,7 +561,7 @@ class CrystalView extends Ui.WatchFace { } catch (e) { } - lightFlag = $.getStringProperty("ThemeLightOverride", ""); + lightFlag = $.getBoolProperty("ThemeLightOverride", false); } if (gThemeColour == null) { @@ -671,9 +675,6 @@ class CrystalView extends Ui.WatchFace { setLayout(mIsBurnInProtection ? Rez.Layouts.AlwaysOn(dc) : Rez.Layouts.WatchFace(dc)); cacheDrawables(); mBurnInProtectionChangedSinceLastDraw = false; - if (!mIsBurnInProtection) { - return; - } } // Respond now to any settings change since last full draw, as we can now update the full screen. diff --git a/source/Indicators.mc b/source/Indicators.mc index d8a84d62..b3cbcaa9 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -144,12 +144,12 @@ class Indicators extends Ui.Drawable { // Battery indicator. if (indicatorType == 4 /* INDICATOR_TYPE_BATTERY */) { - drawBatteryMeter(dc, x, y, mBatteryWidth, mBatteryWidth / 2); + $.drawBatteryMeter(dc, x, y, mBatteryWidth, mBatteryWidth / 2); return; } if (indicatorType == 5 /* INDICATOR_TYPE_BATTERY_NUMERIC */) { - writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 0); + $.writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 0); return; } @@ -157,7 +157,7 @@ class Indicators extends Ui.Drawable { //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** if (indicatorType == 6 /* INDICATOR_TYPE_TESLA */) { // We're reusing the watch batterie indicator to show the Tesla's batterie level - writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 1); + $.writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 1); return; } From 36bb8b7ee1b76a594b3e2ebf03dca7810c2a7252 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 6 May 2023 09:35:10 -0400 Subject: [PATCH 134/220] New Global.mc file. Moved stuff away from App class. Starting new Tesla code --- source/BackgroundService.mc | 12 +- source/CrystalApp.mc | 462 ++++++----------------------------- source/CrystalView.mc | 264 +++----------------- source/DataArea.mc | 2 +- source/DataFields.mc | 24 +- source/Global.mc | 466 ++++++++++++++++++++++++++++++++++++ source/GoalMeter.mc | 5 +- source/ThickThinTime.mc | 2 +- 8 files changed, 596 insertions(+), 641 deletions(-) create mode 100644 source/Global.mc diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 231d8456..3efa34c4 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -64,9 +64,6 @@ class BackgroundService extends Sys.ServiceDelegate { if (_vehicle_id == null) { /*DEBUG*/ logMessage("initialize:Getting vehicles"); makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); - } else { - /*DEBUG*/ logMessage("initialize:Getting vehicle data"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* @@ -84,6 +81,7 @@ class BackgroundService extends Sys.ServiceDelegate { // 1. City local time. if (pendingWebRequests["CityLocalTime"] != null) { + /*DEBUG*/ logMessage("onTemporalEvent: Doing city local time"); makeWebRequest( "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", { @@ -101,6 +99,7 @@ class BackgroundService extends Sys.ServiceDelegate { var lon = $.getStringProperty("LastLocationLng",""); if (lat != null && lon != null) { + /*DEBUG*/ logMessage("onTemporalEvent: Doing OWM"); makeWebRequest( "https://api.openweathermap.org/data/2.5/weather", { @@ -135,7 +134,8 @@ class BackgroundService extends Sys.ServiceDelegate { return; } - if (_vehicle_id) { + if (_token != null && _vehicle_id != null) { + /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); } } @@ -176,6 +176,7 @@ class BackgroundService extends Sys.ServiceDelegate { // HTTP failure: return responseCode. // Otherwise, return data response. + /*DEBUG*/ logMessage("onReceiveCityLocalTime: " + responseCode); if (responseCode != 200) { data = { "httpError" => responseCode @@ -247,6 +248,7 @@ class BackgroundService extends Sys.ServiceDelegate { // Useful data only available if result was successful. // Filter and flatten data response for data that we actually need. // Reduces runtime memory spike in main app. + /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: " + responseCode); if (responseCode == 200) { result = { "cod" => data["cod"], @@ -289,7 +291,7 @@ class BackgroundService extends Sys.ServiceDelegate { //2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); if (responseCode == 200) { - result = { "Token" => data }; + result = { "AccessToken" => data["access_token"], "RefreshToken" => data["refresh_token"], "TokenExpiresIn" => data["expires_in"], "TokenCreatedAt" => Time.now().value() }; } else { result = { "httpErrorTesla" => responseCode }; } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 556a464c..e608160c 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -22,31 +22,12 @@ var gLocationLng = null; (:background) class CrystalApp extends App.AppBase { - var mView; - var mFieldTypes = new [3]; - var mGoalTypes = new [2]; function initialize() { AppBase.initialize(); - - mFieldTypes[0] = {}; - mFieldTypes[1] = {}; - mFieldTypes[2] = {}; - - mGoalTypes[0] = {}; - mGoalTypes[1] = {}; - } - - // onStart() is called on application start up - function onStart(state) { - } - - // onStop() is called when your application is exiting - function onStop(state) { } - // Return the initial view of your application here function getInitialView() { if (WatchUi has :WatchFaceDelegate) { @@ -67,28 +48,61 @@ class CrystalApp extends App.AppBase { } // New app settings have been received so trigger a UI update - function onSettingsChanged() { - mFieldTypes[0].put("type", getIntProperty("Field1Type", 0)); - mFieldTypes[1].put("type", getIntProperty("Field2Type", 1)); - mFieldTypes[2].put("type", getIntProperty("Field3Type", 2)); - - mGoalTypes[0].put("type", getIntProperty("LeftGoalType", 0)); - mGoalTypes[1].put("type", getIntProperty("RightGoalType", 0)); + (:background_method) + function getServiceDelegate() { + return [new BackgroundService()]; + } + function onSettingsChanged() { mView.onSettingsChanged(); // Calls checkPendingWebRequests(). Ui.requestUpdate(); } - function hasGoal(goalType) { - return ((mGoalTypes[0].get("type") == goalType) || - (mGoalTypes[1].get("type") == goalType)); - } + // Handle data received from BackgroundService. + // On success, clear appropriate pendingWebRequests flag. + // data is Dictionary with single key that indicates the data type received. This corresponds with Object Store and + // pendingWebRequests keys. + (:background_method) + function onBackgroundData(data) { + //2022-04-10 logMessage("onBackgroundData:received '" + data + "'"); + var pendingWebRequests = Storage.getValue("PendingWebRequests"); + if (pendingWebRequests == null) { + pendingWebRequests = {}; + } + + var type = data.keys()[0]; // Type of received data. + var receivedData = data[type]; // The actual data received: strip away type key. + + // Do process the data if what we got was an error + if (receivedData["httpError"] == null) { + // New data received: clear pendingWebRequests flag and overwrite stored data. + pendingWebRequests.remove(type); + Storage.setValue("PendingWebRequests", pendingWebRequests); + + if (type.equals("TeslaInfo")) { + // TeslaInfo is refeshed, not overwritten + var storedData = Storage.getValue(type); + if (storedData == null) { + storedData = {}; + } + + var keys = receivedData.keys(); + var values = receivedData.values(); + + for (var i = 0; i < keys.size(); i++) { + storedData.put(keys[i], values[i]); + } + Storage.setValue(type, storedData); + } + else { + Storage.setValue(type, receivedData); + } + + checkPendingWebRequests(); // We just got new data, process them right away before displaying + } - function hasField(fieldType) { - return ((mFieldTypes[0].get("type") == fieldType) || - (mFieldTypes[1].get("type") == fieldType) || - (mFieldTypes[2].get("type") == fieldType)); + Ui.requestUpdate(); } // Determine if any web requests are needed. @@ -163,7 +177,7 @@ class CrystalApp extends App.AppBase { // 2. Weather: // Location must be available, weather or humidity (#113) data field must be shown. if ((gLocationLat != null) && - (hasField(FIELD_TYPE_WEATHER) || hasField(FIELD_TYPE_HUMIDITY))) { + (mView.hasField(FIELD_TYPE_WEATHER) || mView.hasField(FIELD_TYPE_HUMIDITY))) { var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { @@ -198,106 +212,36 @@ class CrystalApp extends App.AppBase { //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** if (Storage.getValue("Tesla") != null) { - var TeslaInfo = Storage.getValue("TeslaInfo"); - if (TeslaInfo == null) { // We're not doing Tesla stuff so why asking for it, clear that + var teslaInfo = Storage.getValue("TeslaInfo"); + if (teslaInfo == null) { // We're not doing Tesla stuff so why asking for it, clear that pendingWebRequests["TeslaInfo"] = false; } else { // We're doing Tesla stuff - var batterie_level = null; - var charging_state = null; - var batterie_stale = false; - var carAsleep = false; - - // First handle errors, setting batterie_level to "N/A" if the query returned a vehicle not found. - // If we failed to get access, maybe our token has expired, clear it so next time the background process runs, it will refresh it - // Other errors are silent for now - var result = TeslaInfo["httpErrorTesla"]; - if (result != null) { - if (result == 400 || result == 401) { // Our token has expired, refresh it - Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID - batterie_stale = true; - } else if (result == 404) { // We got an vehicle not found error, reset our vehicle ID - Storage.setValue("TeslaVehicleID", null); // Try to get a new vehicleID - batterie_stale = true; - } else if (result == 408) { // Car is aslepep keep the old data but stop charging if it still was before going to sleep - carAsleep = true; - } - else { - batterie_stale = true; - } - Storage.setValue("TeslaError", result); - } - - // Check if our access token was refreshed. If so, store the new access and refresh tokens - result = TeslaInfo["Token"]; - if (result != null) { - var accessToken = result["access_token"]; - var refreshToken = result["refresh_token"]; - var expires_in = result["expires_in"]; - var created_at = Time.now().value(); - Properties.setValue("TeslaAccessToken", accessToken); - if (refreshToken != null && refreshToken.equals("") == false) { // Only if we received a refresh tokem - Properties.setValue("TeslaRefreshToken", refreshToken); + var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; + var arrayProp = [true, true, false, false, false ]; + + for (var i = 0; i < arrayKey.size(); i++) { + var value = teslaInfo.get(arrayKey[i]); + if (value != null) { + if (arrayProp[i]) { + Properties.setValue("Tesla" + arrayKey[i], value); + } + else { + Storage.setValue("Tesla" + arrayKey[i], value); + } + teslaInfo.remove(arrayKey[i]); } - Storage.setValue("TeslaTokenExpiresIn", expires_in); - Storage.setValue("TeslaTokenCreatedAt", created_at); - - Storage.setValue("TeslaError", null); } - // If the car isn't asleep and we didn't get an error, read what was returned - else if (!carAsleep && !batterie_stale) { - var batterie_state = TeslaInfo["battery_state"]; - if (batterie_state) { - batterie_level = batterie_state["battery_level"]; - charging_state = batterie_state["charging_state"]; - } - - var inside_temp = TeslaInfo["inside_temp"]; - if (inside_temp != null) { - Storage.setValue("TeslaInsideTemp", inside_temp.toString()); - } - - var precond_enabled = TeslaInfo["preconditioning"]; - if (precond_enabled != null) { - Storage.setValue("TeslaPreconditioning", precond_enabled.toString()); - } - - var sentry_enabled = TeslaInfo["sentry_enabled"]; - if (sentry_enabled != null) { - Storage.setValue("TeslaSentryEnabled", sentry_enabled.toString()); - } - - // Read its vehicleID. If we don't have one, clear our property so the next call made by the background process will try to retrieve it. - // If we have no vehicle, set the batterie level to N/A - var vehicle_id = TeslaInfo["vehicle_id"]; - if (vehicle_id != null) { // We got our vehicle ID. Store it for future use in the background process - if (vehicle_id != 0) { - Storage.setValue("TeslaVehicleID", vehicle_id.toString()); - } else { - Storage.setValue("TeslaVehicleID", null); - batterie_stale = true; - batterie_level = "N/A"; - } - } else { - batterie_stale = true; + // We deal with specific errors here, leaving the good stuff to the battery indicator + var result = teslaInfo["httpErrorTesla"]; + if (result != null) { + if (result == 401) { // Our token has expired and we were unable to get one from within onReceiveVehicleData, refresh it + Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID + } else if (result == 404) { // We got an vehicle not found error and we were unable to get one from within onReceiveVehicleData, reset our vehicle ID + Storage.remove("VehicleID"); // Try to get a new vehicleID } - // Here batterie_level is the same as what was read earlier or changed to N/A for some reason above. - if (batterie_level != null) { - Storage.setValue("TeslaBatterieLevel", batterie_level); - Storage.setValue("TeslaBatterieStale", batterie_stale); - Storage.setValue("TeslaChargingState", charging_state); - - Storage.setValue("TeslaError", null); - - } else { - Storage.setValue("TeslaBatterieStale", true); - Storage.setValue("TeslaError", null); - } - } else if (!batterie_stale) { // Car is asleap, say so - Storage.setValue("TeslaChargingState", "Sleeping"); - Storage.setValue("TeslaBatterieStale", false); - Storage.setValue("TeslaError", null); + Storage.setValue("TeslaInfo", teslaInfo); } pendingWebRequests["TeslaInfo"] = true; @@ -325,266 +269,4 @@ class CrystalApp extends App.AppBase { Storage.setValue("PendingWebRequests", pendingWebRequests); } - - (:background_method) - function getServiceDelegate() { - return [new BackgroundService()]; - } - - // Handle data received from BackgroundService. - // On success, clear appropriate pendingWebRequests flag. - // data is Dictionary with single key that indicates the data type received. This corresponds with Object Store and - // pendingWebRequests keys. - (:background_method) - function onBackgroundData(data) { - //2022-04-10 logMessage("onBackgroundData:received '" + data + "'"); - var pendingWebRequests = Storage.getValue("PendingWebRequests"); - if (pendingWebRequests == null) { - pendingWebRequests = {}; - } - - var type = data.keys()[0]; // Type of received data. - var storedData = Storage.getValue(type); - var receivedData = data[type]; // The actual data received: strip away type key. - - // Do process the data if what we got was an error - if (receivedData["httpError"] == null) { - // New data received: clear pendingWebRequests flag and overwrite stored data. - storedData = receivedData; - pendingWebRequests.remove(type); - Storage.setValue("PendingWebRequests", pendingWebRequests); - Storage.setValue(type, storedData); - - checkPendingWebRequests(); // We just got new data, process them right away before displaying - } - - Ui.requestUpdate(); - } - - // Return a formatted time dictionary that respects is24Hour and HideHoursLeadingZero settings. - // - hour: 0-23. - // - min: 0-59. - function getFormattedTime(hour, min) { - var amPm = ""; - - if (!Sys.getDeviceSettings().is24Hour) { - - // #6 Ensure noon is shown as PM. - var isPm = (hour >= 12); - if (isPm) { - - // But ensure noon is shown as 12, not 00. - if (hour > 12) { - hour = hour - 12; - } - amPm = "p"; - } else { - - // #27 Ensure midnight is shown as 12, not 00. - if (hour == 0) { - hour = 12; - } - amPm = "a"; - } - } - - // #10 If in 12-hour mode with Hide Hours Leading Zero set, hide leading zero. Otherwise, show leading zero. - // #69 Setting now applies to both 12- and 24-hour modes. - hour = hour.format($.getBoolProperty("HideHoursLeadingZero", true) ? INTEGER_FORMAT : "%02d"); - - return { - :hour => hour, - :min => min.format("%02d"), - :amPm => amPm - }; - } -} - -(:background) -function getIntProperty(key, defaultValue) { - var value; - var exception; - - try { - exception = false; - value = Properties.getValue(key); - } - catch (e) { - exception = true; - value = defaultValue; - } - - if (exception) { - try { - Properties.setValue(key, defaultValue); - } - catch (e) { - } - } - return validateNumber(value, defaultValue); -} - -(:background) -function validateNumber(value, defaultValue) { - if (value == null || !(value has :toNumber)) { - value = defaultValue; - } else if (!(value instanceof Lang.Number)) { - try { - value = value.toNumber(); - } - catch (e) { - value = defaultValue; - } - } - if (value == null) { - value = defaultValue; - } - return value; -} - -(:background) -function getFloatProperty(key, defaultValue) { - var value; - var exception; - - try { - exception = false; - value = Properties.getValue(key); - } - catch (e) { - exception = true; - value = defaultValue; - } - - if (exception) { - try { - Properties.setValue(key, defaultValue); - } - catch (e) { - } - } - return validateFloat(value, defaultValue); -} - -(:background) -function validateFloat(value, defaultValue) { - if (value == null || !(value has :toFloat)) { - value = defaultValue; - } else if (!(value instanceof Lang.Float)) { - try { - value = value.toFloat(); - } - catch (e) { - value = defaultValue; - } - } - if (value == null) { - value = defaultValue; - } - return value; -} - -(:background) -function getStringProperty(key, defaultValue) { - var value; - var exception; - - try { - exception = false; - value = Properties.getValue(key); - } - catch (e) { - exception = true; - value = defaultValue; - } - - if (exception) { - try { - Properties.setValue(key, defaultValue); - } - catch (e) { - } - } - return validateString(value, defaultValue); -} - -(:background) -function validateString(value, defaultValue) { - if (value == null || !(value has :toString)) { - value = defaultValue; - } else if (!(value instanceof Lang.String)) { - try { - value = value.toString(); - } - catch (e) { - value = defaultValue; - } - } - if (value == null) { - value = defaultValue; - } - return value; -} - -(:background) -function getBoolProperty(key, defaultValue) { - var value; - var exception; - - try { - exception = false; - value = Properties.getValue(key); - } - catch (e) { - exception = true; - value = defaultValue; - } - - if (exception) { - try { - Properties.setValue(key, defaultValue); - } - catch (e) { - } - } - - return validateBoolean(value, defaultValue); -} - -(:background) -function validateBoolean(value, defaultValue) { - if (value == null) { - value = defaultValue; - } else if ((value instanceof Lang.Boolean) || (value instanceof Lang.Number)) { - try { - if (value) { - value = true; - } - else { - value = false; - } - } - catch (e) { - value = defaultValue; - } - } - else { - value = defaultValue; - } - - if (value == null) { - value = defaultValue; - } - return value; -} - -(:debug, :background) -function logMessage(message) { - var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); - var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - Sys.println(dateStr + " : " + message); -} - -(:release, :background) -function logMessage(message) { } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index b39db1d3..fbf38dc7 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -45,228 +45,6 @@ var mGarminToOWM = [ 1, 2, 3, 10, 13, 4, 11, 13, 50, 50, 10, 9, 11, 1, 9, 10, 13 //const BATTERY_LEVEL_LOW = 20; //const BATTERY_LEVEL_CRITICAL = 10; -// x, y are co-ordinates of centre point. -// width and height are outer dimensions of battery "body". -function drawBatteryMeter(dc, x, y, width, height) { - dc.setColor(gThemeColour, Graphics.COLOR_TRANSPARENT); - dc.setPenWidth(/* BATTERY_LINE_WIDTH */ 2); - - // Body. - // drawRoundedRectangle's x and y are top-left corner of middle of stroke. - // Bottom-right corner of middle of stroke will be (x + width - 1, y + height - 1). - dc.drawRoundedRectangle( - x - (width / 2) + /* (BATTERY_LINE_WIDTH / 2) */ 1, - y - (height / 2) + /* (BATTERY_LINE_WIDTH / 2) */ 1, - width - /* BATTERY_LINE_WIDTH + 1 */ 1, - height - /* BATTERY_LINE_WIDTH + 1 */ 1, - /* BATTERY_CORNER_RADIUS */ 2 * SCREEN_MULTIPLIER); - - // Head. - // fillRectangle() works as expected. - dc.fillRectangle( - x + (width / 2) + BATTERY_MARGIN, - y - (BATTERY_HEAD_HEIGHT / 2), - /* BATTERY_HEAD_WIDTH */ 2, - BATTERY_HEAD_HEIGHT); - - // Fill. - // #8: battery returned as float. Use floor() to match native. Must match getValueForFieldType(). - var batteryLevel = Math.floor(Sys.getSystemStats().battery); - - // Fill colour based on battery level. - var fillColour; - if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { - fillColour = Graphics.COLOR_RED; - } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { - fillColour = Graphics.COLOR_YELLOW; - } else { - fillColour = gThemeColour; - } - - dc.setColor(fillColour, Graphics.COLOR_TRANSPARENT); - - var lineWidthPlusMargin = (/* BATTERY_LINE_WIDTH */ 2 + BATTERY_MARGIN); - var fillWidth = width - (2 * lineWidthPlusMargin); - dc.fillRectangle( - x - (width / 2) + lineWidthPlusMargin, - y - (height / 2) + lineWidthPlusMargin, - Math.ceil(fillWidth * (batteryLevel / 100)), - height - (2 * lineWidthPlusMargin)); -} - -var gToggleCounter = 0; // Used to switch between charge and inside temp - -function writeBatteryLevel(dc, x, y, width, height, type) { - var batteryLevel; - var textColour; - - if (type == 0) { // Standard watch battery is being shown - batteryLevel = Math.floor(Sys.getSystemStats().battery); - - if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { - textColour = Graphics.COLOR_RED; - } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { - textColour = Graphics.COLOR_YELLOW; - } else { - textColour = gThemeColour; - } - - dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); - } -//**************************************************************** -//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** -//**************************************************************** - else { // Tesla stuff - var value; - var batteryStale = false; - var chargingState = 0; - var error = null; - var showMode; - - gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached - showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 - //logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); - batteryStale = Storage.getValue("TeslaBatterieStale"); - chargingState = Storage.getValue("TeslaChargingState"); - error = Storage.getValue("TeslaError"); - - if (chargingState != null) { - if (chargingState.equals("Charging")) { - chargingState = 1; - } else if (chargingState.equals("Sleeping")) { - chargingState = 2; - showMode /= 2; // Keep only 0 and 2. - } else { - chargingState = 0; - } - } else { - chargingState = 0; - } - - var inText = null; - switch (showMode) { - case 0: - value = Storage.getValue("TeslaBatterieLevel"); - break; - case 1: - value = Storage.getValue("TeslaPreconditioning"); - if (value != null && value.equals("true")) { - inText = "P on"; - } - else if (value != null && value.equals("false")) { - inText = "P off"; - } - else { - inText = "P ?"; - } - break; - case 2: - value = Storage.getValue("TeslaSentryEnabled"); - if (value != null && value.equals("true")) { - inText = "S on"; - } - else if (value != null && value.equals("false")) { - inText = "S off"; - } - else { - inText = "S ?"; - } - break; - case 3: - value = Storage.getValue("TeslaInsideTemp"); - break; - } - - //logMessage("value=" + value); - if (value == null) { - value = "N/A"; - } - - if (inText != null && error == null) { - if (batteryStale == true) { - textColour = Graphics.COLOR_LT_GRAY; - } else { - textColour = gThemeColour; - } - dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, inText, Graphics.TEXT_JUSTIFY_LEFT); - } else if (value == null || (value instanceof Toybox.Lang.String && value.equals("N/A")) && error == null) { - dc.setColor(Graphics.COLOR_LT_GRAY, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, "???", Graphics.TEXT_JUSTIFY_LEFT); - } else { - var suffixe = ""; - - if (error != null) { - textColour = Graphics.COLOR_PINK; - value = error.toFloat(); - } else { - value = value.toFloat(); - - if (batteryStale == true) { - textColour = Graphics.COLOR_LT_GRAY; - } else if (value <= /* BATTERY_LEVEL_CRITICAL */ 10 && showMode == 0) { - textColour = Graphics.COLOR_RED; - } else if (value <= /* BATTERY_LEVEL_LOW */ 20 && showMode == 0) { - textColour = Graphics.COLOR_YELLOW; - } else { - textColour = gThemeColour; - } - - if (showMode == 0) { - suffixe = "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); - } else { - suffixe = "°C"; - if (Sys.getDeviceSettings().temperatureUnits == Sys. UNIT_STATUTE) { - suffixe = "°F"; - value = value * 9.0 / 5.0 + 32; - } - } - } - - dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, value.toNumber().format(INTEGER_FORMAT) + suffixe, Graphics.TEXT_JUSTIFY_LEFT); - } - } -//**************************************************************** -//******************** END OF REMVOVED SECTION ******************* -//**************************************************************** -} - -function updateComplications(complicationName, storageName, index, complicationType) { - if (Toybox has :Complications) { - // Check if we should subscribe to our Tesla Complication - var iter = Complications.getComplications(); - if (iter == null) { - return; - } - var complicationId = iter.next(); - - while (complicationId != null) { - //logMessage(complicationId.longLabel.toString()); - if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(complicationName))) { - //DEBUG*/ logMessage("Found complication " + complicationName + " with type " + complicationType); - break; - } - complicationId = iter.next(); - } - - if (complicationId != null) { - if (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID) { - complicationId = complicationId.complicationId; - } - else { - complicationId = new Complications.Id(complicationType); - } - if (index != null) { - Storage.setValue(storageName + index, complicationId); - Complications.subscribeToUpdates(complicationId); - } - } - } -} - - class CrystalView extends Ui.WatchFace { private var mIsSleeping = false; private var mIsBurnInProtection = false; // Is burn-in protection required and active? @@ -278,6 +56,9 @@ class CrystalView extends Ui.WatchFace { // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; + var mFieldTypes = new [3]; + var mGoalTypes = new [2]; + private var mUseComplications; // N.B. Not all watches that support SDK 2.3.0 support per-second updates e.g. 735xt. @@ -310,6 +91,13 @@ class CrystalView extends Ui.WatchFace { function initialize() { WatchFace.initialize(); + mFieldTypes[0] = {}; + mFieldTypes[1] = {}; + mFieldTypes[2] = {}; + + mGoalTypes[0] = {}; + mGoalTypes[1] = {}; + rereadWeatherMethod(); } @@ -376,6 +164,13 @@ class CrystalView extends Ui.WatchFace { // update the full screen immediately. This is true on real hardware, but not in the simulator, which calls onUpdate() // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { + mFieldTypes[0].put("type", $.getIntProperty("Field1Type", 0)); + mFieldTypes[1].put("type", $.getIntProperty("Field2Type", 1)); + mFieldTypes[2].put("type", $.getIntProperty("Field3Type", 2)); + + mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); + mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + mSettingsChangedSinceLastDraw = true; //logMessage("onSettingsChanged called"); @@ -407,6 +202,17 @@ class CrystalView extends Ui.WatchFace { } } + function hasGoal(goalType) { + return ((mGoalTypes[0].get("type") == goalType) || + (mGoalTypes[1].get("type") == goalType)); + } + + function hasField(fieldType) { + return ((mFieldTypes[0].get("type") == fieldType) || + (mFieldTypes[1].get("type") == fieldType) || + (mFieldTypes[2].get("type") == fieldType)); + } + function onComplicationUpdated(complicationId) { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); @@ -430,22 +236,18 @@ class CrystalView extends Ui.WatchFace { } // Do fields first - var app = App.getApp(); var fieldCount = $.getIntProperty("FieldCount", 3); - var fieldTypes = app.mFieldTypes; for (var i = 0; i < fieldCount; i++) { - if (fieldTypes[i].get("ComplicationType") == complicationType) { - fieldTypes[i].put("ComplicationValue", complicationValue); + if (mFieldTypes[i].get("ComplicationType") == complicationType) { + mFieldTypes[i].put("ComplicationValue", complicationValue); } } // Now do goals - var goalTypes = app.mGoalTypes; - for (var i = 0; i < 2; i++) { - if (goalTypes[i].get("ComplicationType") == complicationType) { - goalTypes[i].put("ComplicationValue", complicationValue); + if (mGoalTypes[i].get("ComplicationType") == complicationType) { + mGoalTypes[i].put("ComplicationValue", complicationValue); } } } @@ -719,7 +521,7 @@ class CrystalView extends Ui.WatchFace { }; var app = App.getApp(); - var goalTypes = app.mGoalTypes; + var goalTypes = mGoalTypes; var info = ActivityMonitor.getInfo(); switch(type) { diff --git a/source/DataArea.mc b/source/DataArea.mc index 4e4ff174..84f942f2 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -126,7 +126,7 @@ class DataArea extends Ui.Drawable { // (Local time) - (Local GMT offset) + (Time zone GMT offset) time = Time.now().subtract(localGmtOffset).add(timeZoneGmtOffset); time = Gregorian.info(time, Time.FORMAT_SHORT); - time = App.getApp().getFormattedTime(time.hour, time.min); + time = $.getFormattedTime(time.hour, time.min); time = time[:hour] + ":" + time[:min] + time[:amPm]; } diff --git a/source/DataFields.mc b/source/DataFields.mc index d6f72a36..622330ff 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -99,9 +99,9 @@ class DataFields extends Ui.Drawable { // #116 Handle FieldCount = 0 correctly. mMaxFieldLength = [0, 8, 6, 4][mFieldCount]; - mHasLiveHR = app.hasField(FIELD_TYPE_HR_LIVE_5S); + mHasLiveHR = mView.hasField(FIELD_TYPE_HR_LIVE_5S); - if (!app.hasField(FIELD_TYPE_WEATHER)) { + if (!mView.hasField(FIELD_TYPE_WEATHER)) { mWeatherIconsFont = null; mWeatherIconsSubset = null; } @@ -114,12 +114,12 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE} ]; - var fieldTypes = app.mFieldTypes; + var fieldTypes = mView.mFieldTypes; var filled = [false, false, false]; var i; for (i = 0; i < complications.size(); i++) { - if (app.hasField(complications[i].get("type"))) { + if (mView.hasField(complications[i].get("type"))) { for (var j = 0; j < mFieldCount; j++) { if (fieldTypes[j].get("type") == complications[i].get("type")) { $.updateComplications("", "Complication_F", j + 1, complications[i].get("complicationType")); @@ -155,7 +155,7 @@ class DataFields extends Ui.Drawable { return; } - var fieldTypes = App.getApp().mFieldTypes; + var fieldTypes = mView.mFieldTypes; /*var spacingX = Sys.getDeviceSettings().screenWidth / (2 * mFieldCount); var spacingY = Sys.getDeviceSettings().screenHeight / 4; @@ -455,7 +455,7 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_BODY_BATTERY: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = App.getApp().mFieldTypes; + var fieldTypes = mView.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -477,7 +477,7 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_STRESS_LEVEL: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = App.getApp().mFieldTypes; + var fieldTypes = mView.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -520,7 +520,7 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_TYPE_PULSE_OX: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = App.getApp().mFieldTypes; + var fieldTypes = mView.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString() + "%"; @@ -536,7 +536,7 @@ class DataFields extends Ui.Drawable { break; case FIELD_TYPE_HEART_RATE: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = App.getApp().mFieldTypes; + var fieldTypes = mView.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -656,7 +656,7 @@ class DataFields extends Ui.Drawable { temperature = (temperature * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. } - value = temperature.format(INTEGER_FORMAT) + "°"; + value = temperature.format(INTEGER_FORMAT) + ""; } } break; @@ -710,7 +710,7 @@ class DataFields extends Ui.Drawable { } else { var hour = Math.floor(nextSunEvent).toLong() % 24; var min = Math.floor((nextSunEvent - Math.floor(nextSunEvent)) * 60); // Math.floor(fractional_part * 60) - value = App.getApp().getFormattedTime(hour, min); + value = $.getFormattedTime(hour, min); value = value[:hour] + ":" + value[:min] + value[:amPm]; } @@ -745,7 +745,7 @@ class DataFields extends Ui.Drawable { weatherValue = (weatherValue * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. } - value = weatherValue.format(INTEGER_FORMAT) + "°"; + value = weatherValue.format(INTEGER_FORMAT) + ""; } catch (e) { /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); diff --git a/source/Global.mc b/source/Global.mc new file mode 100644 index 00000000..bcf76df7 --- /dev/null +++ b/source/Global.mc @@ -0,0 +1,466 @@ +using Toybox.WatchUi as Ui; +using Toybox.Graphics as Graphics; +using Toybox.System as Sys; +using Toybox.Application as App; +using Toybox.ActivityMonitor as ActivityMonitor; +using Toybox.Communications as Comms; +using Toybox.Time; +using Toybox.Time.Gregorian; +using Toybox.Weather; +using Toybox.Position; +using Toybox.SensorHistory as SensorHistory; +using Toybox.Complications as Complications; +using Toybox.Application.Storage; +using Toybox.Application.Properties; +using Toybox.Complications; +using Toybox.Math; + +import Toybox.Lang; + +// x, y are co-ordinates of centre point. +// width and height are outer dimensions of battery "body". +function drawBatteryMeter(dc, x, y, width, height) { + dc.setColor(gThemeColour, Graphics.COLOR_TRANSPARENT); + dc.setPenWidth(/* BATTERY_LINE_WIDTH */ 2); + + // Body. + // drawRoundedRectangle's x and y are top-left corner of middle of stroke. + // Bottom-right corner of middle of stroke will be (x + width - 1, y + height - 1). + dc.drawRoundedRectangle( + x - (width / 2) + /* (BATTERY_LINE_WIDTH / 2) */ 1, + y - (height / 2) + /* (BATTERY_LINE_WIDTH / 2) */ 1, + width - /* BATTERY_LINE_WIDTH + 1 */ 1, + height - /* BATTERY_LINE_WIDTH + 1 */ 1, + /* BATTERY_CORNER_RADIUS */ 2 * SCREEN_MULTIPLIER); + + // Head. + // fillRectangle() works as expected. + dc.fillRectangle( + x + (width / 2) + BATTERY_MARGIN, + y - (BATTERY_HEAD_HEIGHT / 2), + /* BATTERY_HEAD_WIDTH */ 2, + BATTERY_HEAD_HEIGHT); + + // Fill. + // #8: battery returned as float. Use floor() to match native. Must match getValueForFieldType(). + var batteryLevel = Math.floor(Sys.getSystemStats().battery); + + // Fill colour based on battery level. + var fillColour; + if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { + fillColour = Graphics.COLOR_RED; + } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { + fillColour = Graphics.COLOR_YELLOW; + } else { + fillColour = gThemeColour; + } + + dc.setColor(fillColour, Graphics.COLOR_TRANSPARENT); + + var lineWidthPlusMargin = (/* BATTERY_LINE_WIDTH */ 2 + BATTERY_MARGIN); + var fillWidth = width - (2 * lineWidthPlusMargin); + dc.fillRectangle( + x - (width / 2) + lineWidthPlusMargin, + y - (height / 2) + lineWidthPlusMargin, + Math.ceil(fillWidth * (batteryLevel / 100)), + height - (2 * lineWidthPlusMargin)); +} + +var gToggleCounter = 0; // Used to switch between charge and inside temp + +function writeBatteryLevel(dc, x, y, width, height, type) { + var batteryLevel; + var textColour; + + if (type == 0) { // Standard watch battery is being shown + batteryLevel = Math.floor(Sys.getSystemStats().battery); + + if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10) { + textColour = Graphics.COLOR_RED; + } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20) { + textColour = Graphics.COLOR_YELLOW; + } else { + textColour = gThemeColour; + } + + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, batteryLevel.toNumber().format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_LEFT); + } +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** + else { // Tesla stuff + var value; + var batteryStale = false; + var chargingState = 0; + var error = null; + var showMode; + + gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached + showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 + //logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); + batteryStale = Storage.getValue("TeslaBatterieStale"); + chargingState = Storage.getValue("TeslaChargingState"); + error = Storage.getValue("TeslaError"); + + if (chargingState != null) { + if (chargingState.equals("Charging")) { + chargingState = 1; + } else if (chargingState.equals("Sleeping")) { + chargingState = 2; + showMode /= 2; // Keep only 0 and 2. + } else { + chargingState = 0; + } + } else { + chargingState = 0; + } + + var inText = null; + switch (showMode) { + case 0: + value = Storage.getValue("TeslaBatterieLevel"); + break; + case 1: + value = Storage.getValue("TeslaPreconditioning"); + if (value != null && value.equals("true")) { + inText = "P on"; + } + else if (value != null && value.equals("false")) { + inText = "P off"; + } + else { + inText = "P ?"; + } + break; + case 2: + value = Storage.getValue("TeslaSentryEnabled"); + if (value != null && value.equals("true")) { + inText = "S on"; + } + else if (value != null && value.equals("false")) { + inText = "S off"; + } + else { + inText = "S ?"; + } + break; + case 3: + value = Storage.getValue("TeslaInsideTemp"); + break; + } + + //logMessage("value=" + value); + if (value == null) { + value = "N/A"; + } + + if (inText != null && error == null) { + if (batteryStale == true) { + textColour = Graphics.COLOR_LT_GRAY; + } else { + textColour = gThemeColour; + } + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, inText, Graphics.TEXT_JUSTIFY_LEFT); + } else if (value == null || (value instanceof Toybox.Lang.String && value.equals("N/A")) && error == null) { + dc.setColor(Graphics.COLOR_LT_GRAY, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, "???", Graphics.TEXT_JUSTIFY_LEFT); + } else { + var suffixe = ""; + + if (error != null) { + textColour = Graphics.COLOR_PINK; + value = error.toFloat(); + } else { + value = value.toFloat(); + + if (batteryStale == true) { + textColour = Graphics.COLOR_LT_GRAY; + } else if (value <= /* BATTERY_LEVEL_CRITICAL */ 10 && showMode == 0) { + textColour = Graphics.COLOR_RED; + } else if (value <= /* BATTERY_LEVEL_LOW */ 20 && showMode == 0) { + textColour = Graphics.COLOR_YELLOW; + } else { + textColour = gThemeColour; + } + + if (showMode == 0) { + suffixe = "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); + } else { + suffixe = "°C"; + if (Sys.getDeviceSettings().temperatureUnits == Sys. UNIT_STATUTE) { + suffixe = "°F"; + value = value * 9.0 / 5.0 + 32; + } + } + } + + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, value.toNumber().format(INTEGER_FORMAT) + suffixe, Graphics.TEXT_JUSTIFY_LEFT); + } + } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** +} + +function updateComplications(complicationName, storageName, index, complicationType) { + if (Toybox has :Complications) { + // Check if we should subscribe to our Tesla Complication + var iter = Complications.getComplications(); + if (iter == null) { + return; + } + var complicationId = iter.next(); + + while (complicationId != null) { + //logMessage(complicationId.longLabel.toString()); + if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(complicationName))) { + //DEBUG*/ logMessage("Found complication " + complicationName + " with type " + complicationType); + break; + } + complicationId = iter.next(); + } + + if (complicationId != null) { + if (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID) { + complicationId = complicationId.complicationId; + } + else { + complicationId = new Complications.Id(complicationType); + } + if (index != null) { + Storage.setValue(storageName + index, complicationId); + Complications.subscribeToUpdates(complicationId); + } + } + } +} + +// Return a formatted time dictionary that respects is24Hour and HideHoursLeadingZero settings. +// - hour: 0-23. +// - min: 0-59. +function getFormattedTime(hour, min) { + var amPm = ""; + + if (!Sys.getDeviceSettings().is24Hour) { + + // #6 Ensure noon is shown as PM. + var isPm = (hour >= 12); + if (isPm) { + + // But ensure noon is shown as 12, not 00. + if (hour > 12) { + hour = hour - 12; + } + amPm = "p"; + } else { + + // #27 Ensure midnight is shown as 12, not 00. + if (hour == 0) { + hour = 12; + } + amPm = "a"; + } + } + + // #10 If in 12-hour mode with Hide Hours Leading Zero set, hide leading zero. Otherwise, show leading zero. + // #69 Setting now applies to both 12- and 24-hour modes. + hour = hour.format($.getBoolProperty("HideHoursLeadingZero", true) ? INTEGER_FORMAT : "%02d"); + + return { + :hour => hour, + :min => min.format("%02d"), + :amPm => amPm + }; +} + +(:background) +function getIntProperty(key, defaultValue) { + var value; + var exception; + + try { + exception = false; + value = Properties.getValue(key); + } + catch (e) { + exception = true; + value = defaultValue; + } + + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } + return validateNumber(value, defaultValue); +} + +(:background) +function validateNumber(value, defaultValue) { + if (value == null || !(value has :toNumber)) { + value = defaultValue; + } else if (!(value instanceof Lang.Number)) { + try { + value = value.toNumber(); + } + catch (e) { + value = defaultValue; + } + } + if (value == null) { + value = defaultValue; + } + return value; +} + +(:background) +function getFloatProperty(key, defaultValue) { + var value; + var exception; + + try { + exception = false; + value = Properties.getValue(key); + } + catch (e) { + exception = true; + value = defaultValue; + } + + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } + return validateFloat(value, defaultValue); +} + +(:background) +function validateFloat(value, defaultValue) { + if (value == null || !(value has :toFloat)) { + value = defaultValue; + } else if (!(value instanceof Lang.Float)) { + try { + value = value.toFloat(); + } + catch (e) { + value = defaultValue; + } + } + if (value == null) { + value = defaultValue; + } + return value; +} + +(:background) +function getStringProperty(key, defaultValue) { + var value; + var exception; + + try { + exception = false; + value = Properties.getValue(key); + } + catch (e) { + exception = true; + value = defaultValue; + } + + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } + return validateString(value, defaultValue); +} + +(:background) +function validateString(value, defaultValue) { + if (value == null || !(value has :toString)) { + value = defaultValue; + } else if (!(value instanceof Lang.String)) { + try { + value = value.toString(); + } + catch (e) { + value = defaultValue; + } + } + if (value == null) { + value = defaultValue; + } + return value; +} + +(:background) +function getBoolProperty(key, defaultValue) { + var value; + var exception; + + try { + exception = false; + value = Properties.getValue(key); + } + catch (e) { + exception = true; + value = defaultValue; + } + + if (exception) { + try { + Properties.setValue(key, defaultValue); + } + catch (e) { + } + } + + return validateBoolean(value, defaultValue); +} + +(:background) +function validateBoolean(value, defaultValue) { + if (value == null) { + value = defaultValue; + } else if ((value instanceof Lang.Boolean) || (value instanceof Lang.Number)) { + try { + if (value) { + value = true; + } + else { + value = false; + } + } + catch (e) { + value = defaultValue; + } + } + else { + value = defaultValue; + } + + if (value == null) { + value = defaultValue; + } + return value; +} + +(:debug, :background) +function logMessage(message) { + var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + Sys.println(dateStr + " : " + message); +} + +(:release, :background) +function logMessage(message) { +} diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index bff6a1e7..acfa10ae 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -48,6 +48,8 @@ class GoalMeter extends Ui.Drawable { private var mMaxValue; private var mIsOff = false; // #114 Should entire meter on this side be hidden? + private var mView; + // private enum /* GOAL_METER_STYLES */ { // ALL_SEGMENTS, // ALL_SEGMENTS_MERGED, @@ -112,6 +114,7 @@ class GoalMeter extends Ui.Drawable { function onSettingsChanged(index) { var app = App.getApp(); + mView = app.getView(); mBuffersNeedRecreate = true; @@ -144,7 +147,7 @@ class GoalMeter extends Ui.Drawable { {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} ]; - var goalTypes = app.mGoalTypes; + var goalTypes = mView.mGoalTypes; var filled = false; for (var i = 0; i < complications.size(); i++) { diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index a7cf8be9..74aa6091 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -62,7 +62,7 @@ class ThickThinTime extends Ui.Drawable { function drawHoursMinutes(dc) { var clockTime = Sys.getClockTime(); - var formattedTime = App.getApp().getFormattedTime(clockTime.hour, clockTime.min); + var formattedTime = $.getFormattedTime(clockTime.hour, clockTime.min); formattedTime[:amPm] = formattedTime[:amPm].toUpper(); var hours = formattedTime[:hour]; From df07e1f99158d04b18ba4b2b8130b010e6581bc6 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 7 May 2023 20:22:08 -0400 Subject: [PATCH 135/220] Redid Tesla code. Fixed Steps Complication where above 10,000 becomes 10.000. --- source/BackgroundService.mc | 259 +++++++++++++++++++++++------------- source/CrystalApp.mc | 13 +- source/CrystalView.mc | 38 ++++-- source/Global.mc | 207 +++++++++++++++------------- 4 files changed, 317 insertions(+), 200 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 3efa34c4..1e74dfdf 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -20,51 +20,68 @@ class BackgroundService extends Sys.ServiceDelegate { //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - if (Storage.getValue("Tesla") == null) { + if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { return; } - // Need to get a token since we can't OAUTH from a watch face :-( - // If someone can do it, be my guest. I spent too much time on this already - _token = $.getStringProperty("TeslaAccessToken",""); + var teslaInfo = Bg.getBackgroundData(); + if (teslaInfo == null) { + teslaInfo = {}; + } + else { + /*DEDUG*/ var keys = teslaInfo.keys(); + /*DEBUG*/ logMessage("onReceiveVehicleData: Buffer has keys " + keys); + } - var createdAt = Storage.getValue("TeslaTokenCreatedAt"); - if (createdAt == null) { - createdAt = 0; + var timeNow = Time.now().value(); + var createdAt; + var expiresIn; + + // Get the unexpired token from the buffer if we have one, otherwise from Properties/Storage + _token = teslaInfo.get("AccessToken"); + createdAt = teslaInfo.get("TokenCreatedAt"); + expiresIn = teslaInfo.get("TokenExpiresIn"); + if (_token != null && createdAt != null && expiresIn != null) { + if (timeNow > createdAt + expiresIn) { + _token = null; + } + } + else { + _token = null; + } + + if (_token == null) { + _token = $.getStringProperty("TeslaAccessToken",""); + createdAt = Storage.getValue("TeslaTokenCreatedAt"); + expiresIn = Storage.getValue("TeslaTokenExpiresIn"); } - var expiresIn = Storage.getValue("TeslaTokenExpiresIn"); - if (expiresIn == null) { - expiresIn = 0; + if (_token != null && createdAt != null && expiresIn != null) { + if (timeNow > createdAt + expiresIn) { + _token = null; + } + } + else { + _token = null; } - var timeNow = Time.now().value(); - var interval = 5 * 60; - var answer = (timeNow + interval < createdAt + expiresIn); - - if (_token != null && _token.equals("") == false && answer == true) { -//2023-03-05 var expireAt = new Time.Moment(createdAt + expiresIn); -//2023-03-05 var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); -//2023-03-05 var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); -//2023-03-05 logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); + + if (_token != null && _token.equals("") == false) { + //DEBUG*/ var expireAt = new Time.Moment(createdAt + expiresIn); + //DEBUG*/ var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); + //DEBUG*/ var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + //DEBUG*/ logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { - /*DEBUG*/ logMessage("initialize:Generating Access Token"); - var refreshToken = $.getStringProperty("TeslaRefreshToken",""); - if (refreshToken != null) { - makeTeslaWebPost(refreshToken, method(:onReceiveToken)); - } else { - //2023-03-05 logMessage("initialize:No refresh token!"); - } - return; + _token = null; } - _vehicle_id = Storage.getValue("TeslaVehicleID"); + _vehicle_id = teslaInfo.get("VehicleID"); if (_vehicle_id == null) { - /*DEBUG*/ logMessage("initialize:Getting vehicles"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + _vehicle_id = Storage.getValue("TeslaVehicleID"); } + //**************************************************************** //******************** END OF REMVOVED SECTION ******************* //**************************************************************** @@ -131,13 +148,29 @@ class BackgroundService extends Sys.ServiceDelegate { // 3. Tesla if (pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null) { if (!Sys.getDeviceSettings().phoneConnected) { + Bg.exit(null); + } + + if (_token == null) { + /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); + var refreshToken = $.getStringProperty("TeslaRefreshToken",""); + if (refreshToken != null) { + makeTeslaWebPost(refreshToken, method(:onReceiveToken)); + } else { + /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); + Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); + } return; } - - if (_token != null && _vehicle_id != null) { - /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + + if (_vehicle_id == null) { + /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + return; } + + /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); } } /* else { Sys.println("onTemporalEvent() called with no pending web requests!"); @@ -171,6 +204,7 @@ class BackgroundService extends Sys.ServiceDelegate { } } */ + (:background_method) function onReceiveCityLocalTime(responseCode, data) { @@ -276,93 +310,138 @@ class BackgroundService extends Sys.ServiceDelegate { Sys.println(dateStr + " : httpError=" + responseCode);*/ } - Bg.exit({ - "OpenWeatherMapCurrent" => result - }); + Bg.exit({ "OpenWeatherMapCurrent" => result }); } //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** (:background_method) - function onReceiveToken(responseCode, data) { - var result; - - //2023-03-05 logMessage("onReceiveToken responseCode is " + responseCode); + function onReceiveToken(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); + + var teslaInfo = Bg.getBackgroundData(); + if (teslaInfo == null) { + teslaInfo = {}; + } + else { + /*DEDUG*/ var keys = teslaInfo.keys(); + /*DEBUG*/ logMessage("onReceiveToken: Buffer has keys " + keys); + } + if (responseCode == 200) { - result = { "AccessToken" => data["access_token"], "RefreshToken" => data["refresh_token"], "TokenExpiresIn" => data["expires_in"], "TokenCreatedAt" => Time.now().value() }; - } else { - result = { "httpErrorTesla" => responseCode }; - } - Bg.exit({ "TeslaInfo" => result }); + teslaInfo.put("AccessToken", responseData["access_token"]); + teslaInfo.put("RefreshToken", responseData["refresh_token"]); + teslaInfo.put("TokenExpiresIn", responseData["expires_in"]); + teslaInfo.put("TokenCreatedAt", Time.now().value()); + } + + teslaInfo.put("httpErrorTesla", 401); + teslaInfo.put("httpInternalErrorTesla", responseCode); + + Bg.exit({ "TeslaInfo" => teslaInfo }); } (:background_method) - function onReceiveVehicles(responseCode, data) { - var result; - + function onReceiveVehicles(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); + + var teslaInfo = Bg.getBackgroundData(); + if (teslaInfo == null) { + teslaInfo = {}; + } + else { + /*DEDUG*/ var keys = teslaInfo.keys(); + /*DEBUG*/ logMessage("onReceiveVehicles: Buffer has keys " + keys); + } + if (responseCode == 200) { - var vehicles = data.get("response"); - if (vehicles.size() > 0) { - _vehicle_id = vehicles[0].get("id"); - } else { - _vehicle_id = 0; - } - result = { "vehicle_id" => _vehicle_id}; - - } else { - result = { "httpErrorTesla" => responseCode }; - } + var vehicles = responseData.get("response"); + var vehice_state; + if (vehicles != null) { + if (vehicles.size() > 0) { + _vehicle_id = vehicles[0].get("id").toString(); + vehice_state = vehicles[0].get("state"); + } else { + _vehicle_id = null; + vehice_state = "NoVehicles"; + } + } + else { + _vehicle_id = null; + vehice_state = "NoVehicleResponse"; + } + teslaInfo.put("VehicleID", _vehicle_id); + teslaInfo.put("VehicleState",vehice_state); + } - Bg.exit({ "TeslaInfo" => result }); + teslaInfo.put("httpErrorTesla", (_vehicle_id == null ? 404 : 408)); + teslaInfo.put("httpInternalErrorTesla", responseCode); + + Bg.exit({ "TeslaInfo" => teslaInfo }); } (:background_method) - function onReceiveVehicleData(responseCode, data) { - var results; - var result = "N/A"; - var batterieLevel = "N/A"; - var chargingState = "Disconnected"; - var insideTemp = "N/A"; - var precondEnabled = "N/A"; - var sentryEnabled = "N/A"; - + function onReceiveVehicleData(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); /*DEBUG*/ var myStats = Sys.getSystemStats(); /*DEBUG*/ logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + + var teslaInfo = Bg.getBackgroundData(); + if (teslaInfo == null) { + teslaInfo = {}; + } + else { + /*DEDUG*/ var keys = teslaInfo.keys(); + /*DEBUG*/ logMessage("onReceiveVehicleData: Buffer has keys " + keys); + } + + teslaInfo.put("httpErrorTesla", responseCode); + if (responseCode == 200) { - results = data.get("response"); - if (results != null) { - result = results.get("charge_state"); + teslaInfo.put("VehicleState", "online"); + + var response = responseData.get("response"); + if (response != null) { + var result = response.get("charge_state"); if (result != null) { - batterieLevel = result.get("battery_level"); - chargingState = result.get("charging_state"); - precondEnabled = result.get("preconditioning_enabled"); + teslaInfo.put("BatteryLevel", result.get("battery_level")); + teslaInfo.put("ChargingState", result.get("charging_state")); + teslaInfo.put("PrecondEnabled", result.get("preconditioning_enabled")); } - result = results.get("climate_state"); + result = response.get("climate_state"); if (result != null) { - insideTemp = result.get("inside_temp"); + teslaInfo.put("InsideTemp", result.get("inside_temp")); } - result = results.get("vehicle_state"); + result = response.get("vehicle_state"); if (result != null) { - sentryEnabled = result.get("sentry_mode"); + teslaInfo.put("SentryEnabled", result.get("sentry_mode")); } - - result = { - "battery_level" => batterieLevel, - "charging_state" => chargingState - }; } - - result = { "battery_state" => result, "inside_temp" => insideTemp, "preconditioning" => precondEnabled, "sentry_enabled" => sentryEnabled, "vehicle_id" => _vehicle_id }; - } else { - result = { "httpErrorTesla" => responseCode }; } + // If no vehicle (rare) or can't contact (much more frequent) is received, try to get a new vehicle (404) or retrieve its state (408) + else if (responseCode == 404 || responseCode == 408) { + // If Tesla can't find our vehicle by its ID, reset it and maybe we'll have better luck next time + if (responseCode == 404) { + teslaInfo.put("VehicleID", null); + _vehicle_id = null; + } + /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + return; + } + // Our access token has expired, ask for a new one + else if (responseCode == 401) { + var refreshToken = $.getStringProperty("TeslaRefreshToken",""); + if (refreshToken != null) { + /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); + makeTeslaWebPost(refreshToken, method(:onReceiveToken)); + return; + } + } - Bg.exit({ "TeslaInfo" => result }); + Bg.exit({ "TeslaInfo" => teslaInfo }); } (:background_method) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index e608160c..2554bff3 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -19,6 +19,7 @@ import Toybox.WatchUi; // location available. var gLocationLat = null; var gLocationLng = null; +var gTeslaComplication = true; (:background) class CrystalApp extends App.AppBase { @@ -211,7 +212,8 @@ class CrystalApp extends App.AppBase { //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - if (Storage.getValue("Tesla") != null) { +//*******************checkPendingWebRequests********************** + if (Storage.getValue("Tesla") != null && gTeslaComplication == false) { var teslaInfo = Storage.getValue("TeslaInfo"); if (teslaInfo == null) { // We're not doing Tesla stuff so why asking for it, clear that pendingWebRequests["TeslaInfo"] = false; @@ -233,11 +235,12 @@ class CrystalApp extends App.AppBase { } // We deal with specific errors here, leaving the good stuff to the battery indicator - var result = teslaInfo["httpErrorTesla"]; - if (result != null) { - if (result == 401) { // Our token has expired and we were unable to get one from within onReceiveVehicleData, refresh it + var responseCode = teslaInfo["httpErrorTesla"]; + var internalResponseCode = teslaInfo["httpInternalErrorTesla"]; + if (responseCode != null && internalResponseCode != null) { + if (responseCode == 401 && internalResponseCode != 200) { // Our token has expired and we were unable to get one, refresh it Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID - } else if (result == 404) { // We got an vehicle not found error and we were unable to get one from within onReceiveVehicleData, reset our vehicle ID + } else if (responseCode == 404 && internalResponseCode != 200) { // We got a vehicle not found error and we were unable to get one, reset our vehicle ID Storage.remove("VehicleID"); // Try to get a new vehicleID } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index fbf38dc7..b6c4c077 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -202,12 +202,10 @@ class CrystalView extends Ui.WatchFace { } } - function hasGoal(goalType) { - return ((mGoalTypes[0].get("type") == goalType) || - (mGoalTypes[1].get("type") == goalType)); - } - function hasField(fieldType) { + if (mFieldTypes[0] == null || mFieldTypes[1] == null || mFieldTypes[2] == null) { + return false; + } return ((mFieldTypes[0].get("type") == fieldType) || (mFieldTypes[1].get("type") == fieldType) || (mFieldTypes[2].get("type") == fieldType)); @@ -216,12 +214,30 @@ class CrystalView extends Ui.WatchFace { function onComplicationUpdated(complicationId) { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); - //DEBUG*/ var complicationLabel = complication.shortLabel; + /*DEBUG*/ var complicationShortLabel = complication.shortLabel; + /*DEBUG*/ var complicationLongLabel = complication.longLabel; var complicationValue = complication.value; - //if (complicationType == Complications.COMPLICATION_TYPE_STRESS) { - //DEBUG*/ logMessage("Type: " + complicationType + " Label: " + complicationLabel + " Value:" + complicationValue + " burnIn active? " + mIsBurnInProtection); - //} + //DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_STEPS) { + //DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); + //DEBUG*/ } + + if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { + var teslaInfo = Storage.getValue("TeslaInfo"); + if (teslaInfo == null){ + teslaInfo = {}; + } + var arrayInfo = $.to_array(complicationValue, "|"); + teslaInfo.put("httpErrorTesla", $.validateNumber(arrayInfo[0], 0)); + teslaInfo.put("BatteryLevel", $.validateNumber(arrayInfo[1], 0)); + teslaInfo.put("ChargingState", $.validateString(arrayInfo[2], "")); + teslaInfo.put("InsideTemp", $.validateNumber(arrayInfo[3], 0)); + teslaInfo.put("SentryEnabled", $.validateBoolean(arrayInfo[4], false)); + teslaInfo.put("PrecondEnabled", $.validateBoolean(arrayInfo[5], false)); + teslaInfo.put("VehicleState", $.validateString(arrayInfo[6], "asleep")); + + Storage.setValue("TeslaInfo", teslaInfo); + } // If we were told to ignore complications, do so (but technicaly, we shouldn't get here as we shouldn't be listening in the first place!) if (!mUseComplications) { @@ -530,6 +546,10 @@ class CrystalView extends Ui.WatchFace { if (Toybox has :Complications && mUseComplications) { var tmpValue = goalTypes[index].get("ComplicationValue"); if (tmpValue != null) { + // For some stupid reason, above 10K, it becomes a float and divided by 1000, so 15,500 becomes 15.500. WTF? + if (tmpValue instanceof Lang.Float) { + tmpValue = tmpValue * 1000; + } values[:current] = tmpValue.toNumber(); values[:isValid] = true; } diff --git a/source/Global.mc b/source/Global.mc index bcf76df7..cb8a1233 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -90,115 +90,107 @@ function writeBatteryLevel(dc, x, y, width, height, type) { //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** else { // Tesla stuff - var value; - var batteryStale = false; - var chargingState = 0; - var error = null; + textColour = Graphics.COLOR_LT_GRAY; // Default in case we get nothing + + var value = "???"; var showMode; - gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached + gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached. Called every second so incremented every second, giving a two second display of each value showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 //logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); - batteryStale = Storage.getValue("TeslaBatterieStale"); - chargingState = Storage.getValue("TeslaChargingState"); - error = Storage.getValue("TeslaError"); - - if (chargingState != null) { - if (chargingState.equals("Charging")) { - chargingState = 1; - } else if (chargingState.equals("Sleeping")) { - chargingState = 2; - showMode /= 2; // Keep only 0 and 2. - } else { - chargingState = 0; - } - } else { - chargingState = 0; - } - var inText = null; - switch (showMode) { - case 0: - value = Storage.getValue("TeslaBatterieLevel"); - break; - case 1: - value = Storage.getValue("TeslaPreconditioning"); - if (value != null && value.equals("true")) { - inText = "P on"; - } - else if (value != null && value.equals("false")) { - inText = "P off"; + var teslaInfo = Storage.getValue("TeslaInfo"); + if (teslaInfo != null) { + var httpErrorTesla = teslaInfo.get("httpErrorTesla"); + var vehicleState = teslaInfo.get("VehicleState"); + var vehicleAsleep = (vehicleState != null && vehicleState.equals("asleep") == true); + + // Only specific error are handled, the others are displayed 'as is' in pink + if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { + if (httpErrorTesla == 401) { // No access token, only show the battery (in gray, default above) + showMode = 0; } - else { - inText = "P ?"; + else if (vehicleAsleep || httpErrorTesla == 200) { // Vehicle confirmed asleep (even if we got a 408, we'll add a "?" after the battery level to show this) or we got valid data + textColour = gThemeColour; // Defaults to theme's color } - break; - case 2: - value = Storage.getValue("TeslaSentryEnabled"); - if (value != null && value.equals("true")) { - inText = "S on"; + + if (vehicleAsleep) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) + showMode &= 2; } - else if (value != null && value.equals("false")) { - inText = "S off"; + + switch (showMode) { + case 0: + var suffix = ""; + + batteryLevel = teslaInfo.get("BatteryLevel"); + if (batteryLevel != null) { + var chargingState = teslaInfo.get("ChargingState"); + if (httpErrorTesla == 401 || (!vehicleAsleep && httpErrorTesla == 408)) { // Can't get or token (will be shown in gray) or we got a 408 while not asleep (will be shown in the theme's color) + suffix = "?"; + } + else if (vehicleAsleep) { + suffix = "s"; + } + else if (chargingState != null && chargingState.equals("Charging") == true) { + suffix = "+"; + } + + value = batteryLevel + "%" + suffix; + + // If we're in theme's color, reset the color based on battery level, similar to the phone's battery + if (batteryLevel <= /* BATTERY_LEVEL_CRITICAL */ 10 && textColour == gThemeColour) { + textColour = Graphics.COLOR_RED; + } else if (batteryLevel <= /* BATTERY_LEVEL_LOW */ 20 && textColour == gThemeColour) { + textColour = Graphics.COLOR_YELLOW; + } + } + else { + value = "???%"; + } + break; + + case 1: + var sentryEnabled = teslaInfo.get("SentryEnabled"); + if (sentryEnabled != null) { + value = (sentryEnabled ? "S on" : "S off"); + } + else { + value = "S ???"; + } + break; + + case 2: + var precondEnabled = teslaInfo.get("PrecondEnabled"); + if (precondEnabled != null) { + value = (sentryEnabled ? "P on" : "P off"); + } + else { + value = "P ???"; + } + break; + + case 3: + var insideTemp = teslaInfo.get("InsideTemp"); + if (insideTemp != null) { + value = (Sys.getDeviceSettings().temperatureUnits == Sys.UNIT_METRIC ? insideTemp.toNumber() + "°C" : ((insideTemp.toNumber() * 9) / 5 + 32).format("%d") + "°F"); + } + else { + value = (Sys.getDeviceSettings().temperatureUnits == Sys.UNIT_METRIC ? "???°C" : "???°F"); + } + break; } - else { - inText = "S ?"; + } + else { + if (httpErrorTesla != null) { + value = httpErrorTesla.toString(); } - break; - case 3: - value = Storage.getValue("TeslaInsideTemp"); - break; + textColour = Graphics.COLOR_PINK; // None handled error + } } //logMessage("value=" + value); - if (value == null) { - value = "N/A"; - } - - if (inText != null && error == null) { - if (batteryStale == true) { - textColour = Graphics.COLOR_LT_GRAY; - } else { - textColour = gThemeColour; - } - dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, inText, Graphics.TEXT_JUSTIFY_LEFT); - } else if (value == null || (value instanceof Toybox.Lang.String && value.equals("N/A")) && error == null) { - dc.setColor(Graphics.COLOR_LT_GRAY, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, "???", Graphics.TEXT_JUSTIFY_LEFT); - } else { - var suffixe = ""; - - if (error != null) { - textColour = Graphics.COLOR_PINK; - value = error.toFloat(); - } else { - value = value.toFloat(); - - if (batteryStale == true) { - textColour = Graphics.COLOR_LT_GRAY; - } else if (value <= /* BATTERY_LEVEL_CRITICAL */ 10 && showMode == 0) { - textColour = Graphics.COLOR_RED; - } else if (value <= /* BATTERY_LEVEL_LOW */ 20 && showMode == 0) { - textColour = Graphics.COLOR_YELLOW; - } else { - textColour = gThemeColour; - } - - if (showMode == 0) { - suffixe = "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); - } else { - suffixe = "°C"; - if (Sys.getDeviceSettings().temperatureUnits == Sys. UNIT_STATUTE) { - suffixe = "°F"; - value = value * 9.0 / 5.0 + 32; - } - } - } - - dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); - dc.drawText(x - (width / 2), y - height, gNormalFont, value.toNumber().format(INTEGER_FORMAT) + suffixe, Graphics.TEXT_JUSTIFY_LEFT); - } + dc.setColor(textColour, Graphics.COLOR_TRANSPARENT); + dc.drawText(x - (width / 2), y - height, gNormalFont, value, Graphics.TEXT_JUSTIFY_LEFT ); } //**************************************************************** //******************** END OF REMVOVED SECTION ******************* @@ -454,6 +446,29 @@ function validateBoolean(value, defaultValue) { return value; } +function to_array(string, splitter) { + var array = new [30]; //Use maximum expected length + var index = 0; + var location; + + do { + location = string.find(splitter); + if (location != null) { + array[index] = string.substring(0, location); + string = string.substring(location + 1, string.length()); + index++; + } + } while (location != null); + + array[index] = string; + + var result = new [index + 1]; + for (var i = 0; i <= index; i++) { + result[i] = array[i]; + } + return result; +} + (:debug, :background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); From 6e58a8a3340da5b876f5d2d9030ab0300c47411b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 7 May 2023 20:35:43 -0400 Subject: [PATCH 136/220] Added the TeslaLink property --- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/settings/properties.xml | 2 ++ resources/settings/settings.xml | 4 ++++ resources/strings/strings.xml | 1 + source/CrystalApp.mc | 4 +++- 24 files changed, 30 insertions(+), 1 deletion(-) diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index ba60984d..5d8fa88b 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 9cd81223..6626461e 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 80a4e370..757d0c3c 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index b4a6fe42..bbb9546a 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 3aaccd19..08cfabef 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 577cdbc0..340803fc 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -124,4 +124,5 @@ Longitude Niveau de stress Utilisez les complications, si disponible + Utilisez les Complications de Tesla-Link pour l'info Tesla diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index b1c3091e..95e6fd71 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index b1e3c259..fd579211 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 5f799ed5..020b061e 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 64e9f091..97d1fc3d 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index b83e7786..11404076 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 286fa5c9..02c01c40 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index b0bbacae..f3a374e5 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 69028f1e..e050a81e 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 6dfe71c5..f62b16a9 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 6f24ee0c..b4aba2ed 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 689c88c0..b3d1e35f 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 58ee12cb..803184fa 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index cf3d1f5e..8340b2d6 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index a52c1a53..735dfffb 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -125,4 +125,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 5edaaf9b..0e28ac94 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -38,6 +38,8 @@ 2651f49cb20de925fc57590709b86ce6 + false + owner-api.teslamotors.com diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 72ebb0ce..a51fb7ab 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -260,6 +260,10 @@ + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index ce9968d1..78ca6c5e 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -124,4 +124,5 @@ Longitude Stress Level Use Complications if available + Get Tesla info from Tesla-Link Complications diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 2554bff3..75a728fa 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -19,7 +19,7 @@ import Toybox.WatchUi; // location available. var gLocationLat = null; var gLocationLng = null; -var gTeslaComplication = true; +var gTeslaComplication = false; (:background) class CrystalApp extends App.AppBase { @@ -27,6 +27,8 @@ class CrystalApp extends App.AppBase { function initialize() { AppBase.initialize(); + + gTeslaComplication = getBoolProperty("TeslaLink", false); } // Return the initial view of your application here From a16c4ff1ae408773c5ede2668e5765799894210d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 7 May 2023 20:58:15 -0400 Subject: [PATCH 137/220] Do not read the whole weather map from storage every seconds, only when we got new data --- source/CrystalApp.mc | 4 ++++ source/DataFields.mc | 13 +++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 75a728fa..e97c7942 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -102,6 +102,10 @@ class CrystalApp extends App.AppBase { Storage.setValue(type, receivedData); } + if (type.equals("OpenWeatherMapCurrent")) { + Storage.setValue("NewOpenWeatherMapCurrent", true); + } + checkPendingWebRequests(); // We just got new data, process them right away before displaying } diff --git a/source/DataFields.mc b/source/DataFields.mc index 622330ff..fa75a298 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -57,6 +57,7 @@ class DataFields extends Ui.Drawable { private var mWasHRAvailable = false; // HR availability at last full draw (in high power mode). private var mMaxFieldLength; // Maximum number of characters per field. private var mBatteryWidth; // Width of battery meter. + private var storedWeather; // private const CM_PER_KM = 100000; // private const MI_PER_KM = 0.621371; // private const FT_PER_M = 3.28084; @@ -266,7 +267,7 @@ class DataFields extends Ui.Drawable { // Battery. if ((fieldType == FIELD_TYPE_BATTERY) || (fieldType == FIELD_TYPE_BATTERY_HIDE_PERCENT)) { - drawBatteryMeter(dc, x, mTop, mBatteryWidth, mBatteryWidth / 2); + $.drawBatteryMeter(dc, x, mTop, mBatteryWidth, mBatteryWidth / 2); // #34 Live HR in low power mode. } else if (isLiveHeartRate && isPartialUpdate) { @@ -729,7 +730,15 @@ class DataFields extends Ui.Drawable { result["weatherIcon"] = "01d"; } - weather = Storage.getValue("OpenWeatherMapCurrent"); + // Only read that dictionnary from Storage if it has changed (or we don't have a local copy), otherwise read our stored weather data + if (storedWeather == null || Storage.getValue("NewOpenWeatherMapCurrent") != null) { + weather = Storage.getValue("OpenWeatherMapCurrent"); + Storage.setValue("NewOpenWeatherMapCurrent", null); + storedWeather = weather; + } + else { + weather = storedWeather; + } // Awaiting location. if (gLocationLat == null) { From 0344d7af33cb43926ad2679a3a80aad34fb79d64 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 7 May 2023 21:03:34 -0400 Subject: [PATCH 138/220] Updated the version to 2.17.5 --- README.md | 3 +++ resources/strings/strings.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0819a7c9..5e31b7d9 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.17.5 +- Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla Info insteading of querying Tesla's servers. No more Token handling + ### 2.17.4 - One more attempt at fixing the crash because of the Settings change since 2.17.1 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 78ca6c5e..c7e13155 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.17.4 + Crystal-Tesla V2.17.5 Theme Hours Colour From 29b43bfa980549ba999796b92317f453d67e862f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 8 May 2023 23:40:44 -0400 Subject: [PATCH 139/220] Code finished, hopefully --- README.md | 8 +- always-on-source/AlwaysOnDisplay.mc | 7 - manifest.xml | 22 +- resources-ces/strings/strings.xml | 3 - resources-dan/strings/strings.xml | 3 - resources-deu/strings/strings.xml | 3 - resources-dut/strings/strings.xml | 3 - resources-fin/strings/strings.xml | 3 - resources-fre/strings/strings.xml | 3 - resources-hrv/strings/strings.xml | 3 - resources-hun/strings/strings.xml | 3 - resources-ita/strings/strings.xml | 3 - resources-kor/strings/strings.xml | 3 - resources-nob/strings/strings.xml | 3 - resources-pol/strings/strings.xml | 3 - resources-por/strings/strings.xml | 3 - resources-rus/strings/strings.xml | 3 - resources-slo/strings/strings.xml | 3 - resources-slv/strings/strings.xml | 3 - resources-spa/strings/strings.xml | 3 - resources-swe/strings/strings.xml | 3 - resources-zhs/strings/strings.xml | 3 - resources-zht/strings/strings.xml | 3 - resources/settings/properties.xml | 5 - resources/settings/settings.xml | 12 - resources/strings/strings.xml | 5 +- source/BackgroundService.mc | 281 +++-------------------- source/CrystalApp.mc | 334 ++++++++++++---------------- source/CrystalView.mc | 288 ++++-------------------- source/DataArea.mc | 83 +++---- source/DataFields.mc | 248 ++++----------------- source/Global.mc | 39 +++- source/GoalMeter.mc | 9 +- source/Indicators.mc | 2 + 34 files changed, 360 insertions(+), 1043 deletions(-) diff --git a/README.md b/README.md index 5e31b7d9..1efc6a9c 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,12 @@ Reviews: ## Below is what has been added by me (SylvainGa). -### 2.17.5 -- Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla Info insteading of querying Tesla's servers. No more Token handling +### 2.18.0 +- Removed Watch model that are not at least at CIQ 3.3.0. This is required for the new Sunrise/Sunset and Weather library by Garmin. From the stats Garmin shows me about the watch face, none of them had downloaded the watch face anyway. +- Removed the OpenWeatherMap and rely solely on Garmin Weather. The OWN and GPS was giving too much problem. +- The area on the screen allocated for alternate TimeZone will display the current weather station name if no alternate TimeZone was entered. +- The "Local time in City" (ie, alternate TimeZone) has been redone, much simplier, doesn't require Background process anymore but will need some work on your side. The field in the setting is now a Comma Separated Value (CSV) with the first value being the city name, second the latitude of the city and third its longitude. The last two in decimal notation (with a period, not comma). You will have to enter these, which are easy to find in Google Map anyway. No type checking done, beside making sure the latitude and logitude are numbers. If invalid, '???' will be shown for the time. +- Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla data instead of querying Tesla's servers. No more Token handling if using Complications and Tesla-Link. ### 2.17.4 - One more attempt at fixing the crash because of the Settings change since 2.17.1 diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index 11f7b7d9..63500f6e 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -217,9 +217,6 @@ class AlwaysOnDisplay extends Ui.Drawable { Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER ); } -//**************************************************************** -//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** -//**************************************************************** else { dc.drawText( mDataLeft, @@ -257,7 +254,6 @@ class AlwaysOnDisplay extends Ui.Drawable { var text = value + " " + battery.format(INTEGER_FORMAT) + "%"; var widthText = dc.getTextWidthInPixels(text, mBatteryFont); - var widthTeslaT = dc.getTextWidthInPixels("T", mTeslaFont); dc.drawText( dc.getWidth() - mDataLeft - widthText, @@ -274,8 +270,5 @@ class AlwaysOnDisplay extends Ui.Drawable { Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER ); } -//**************************************************************** -//******************** END OF REMVOVED SECTION ******************* -//**************************************************************** } } \ No newline at end of file diff --git a/manifest.xml b/manifest.xml index 8ffece69..c0c3066c 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,27 +1,16 @@ - + - - - - - - - - - - - @@ -31,7 +20,6 @@ - @@ -41,10 +29,7 @@ - - - @@ -67,15 +52,10 @@ - - - - - diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 5d8fa88b..91352d4f 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 6626461e..f3abeb67 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 757d0c3c..12283212 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -18,7 +18,6 @@ Always hide seconds Führende Nullen ausblenden Add colon between hours and minutes - OpenWeatherMap API Key Override Anzahl der Datenfelder Datenfeld 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index bbb9546a..1656d90d 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -18,7 +18,6 @@ Always hide seconds Verberg Eerste Nul Bij Uren Add colon between hours and minutes - OpenWeatherMap API Key Override Hoeveelheid Datavelden Data Veld 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 08cfabef..6b7b3666 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 340803fc..b02a88f0 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -18,7 +18,6 @@ Toujours cacher Masquer le zéro avant l'heure Ajouter un deux-points entre les heures et minutes - OpenWeatherMap API Key Override Nombre de champs de données Champs de données 1 @@ -120,8 +119,6 @@ Remplacement du thème par RGB En hexadécimal en utilisant ce format RRGGBB. Si celui-ci est différent de 0, c'est cette combinaison de couleurs qui sera utilisée à la place du thème Remplacement du thème Clair - Latitude - Longitude Niveau de stress Utilisez les complications, si disponible Utilisez les Complications de Tesla-Link pour l'info Tesla diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 95e6fd71..d7271b54 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index fd579211..527d445d 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 020b061e..96f38c87 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 97d1fc3d..336f649f 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 11404076..1977139f 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 02c01c40..5c93bbdf 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -18,7 +18,6 @@ Always hide seconds Ukryj Zero Poprzedzające Godzinę Add colon between hours and minutes - OpenWeatherMap API Key Override Liczba Pól z Danymi Pole Danych 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index f3a374e5..26da765d 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index e050a81e..ab082a08 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -18,7 +18,6 @@ Always hide seconds Скрывать нули перед часами Add colon between hours and minutes - OpenWeatherMap API Key Override Количество полей данных Поле данных 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index f62b16a9..411f0892 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index b4aba2ed..211fd59c 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index b3d1e35f..a358c13d 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index 803184fa..d907eb18 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -18,7 +18,6 @@ Always hide seconds Dölj inledande nollor Add colon between hours and minutes - OpenWeatherMap API Key Override Antal datafält Datafält 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 8340b2d6..3be28473 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 735dfffb..87a0624d 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -19,7 +19,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -121,8 +120,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 0e28ac94..f1a9dbd1 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -33,11 +33,6 @@ 0 - - - - 2651f49cb20de925fc57590709b86ce6 - false diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index a51fb7ab..0323c1df 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -248,18 +248,6 @@ - - - - - - - - - - - - diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index c7e13155..a34afc82 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.17.5 + Crystal-Tesla V2.18.0 Theme Hours Colour @@ -18,7 +18,6 @@ Always hide seconds Hide Hours Leading Zero Add colon between hours and minutes - OpenWeatherMap API Key Override Number Of Data Fields Data Field 1 @@ -120,8 +119,6 @@ RGB Theme override In hexadecimal using this format RRGGBB. If this is other than 0, it's this color combination that will be used instead of the theme Light theme override - Latitude - Longitude Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 1e74dfdf..b2d57594 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -17,9 +17,6 @@ class BackgroundService extends Sys.ServiceDelegate { function initialize() { Sys.ServiceDelegate.initialize(); -//**************************************************************** -//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** -//**************************************************************** if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { return; } @@ -65,7 +62,6 @@ class BackgroundService extends Sys.ServiceDelegate { _token = null; } - if (_token != null && _token.equals("") == false) { //DEBUG*/ var expireAt = new Time.Moment(createdAt + expiresIn); //DEBUG*/ var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); @@ -82,240 +78,36 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = Storage.getValue("TeslaVehicleID"); } -//**************************************************************** -//******************** END OF REMVOVED SECTION ******************* -//**************************************************************** } - // Read pending web requests, and call appropriate web request function. - // This function determines priority of web requests, if multiple are pending. - // Pending web request flag will be cleared only once the background data has been successfully received. (:background_method) function onTemporalEvent() { - var pendingWebRequests = Storage.getValue("PendingWebRequests"); - //2023-03-05 logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "'"); - if (pendingWebRequests != null) { - - // 1. City local time. - if (pendingWebRequests["CityLocalTime"] != null) { - /*DEBUG*/ logMessage("onTemporalEvent: Doing city local time"); - makeWebRequest( - "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", - { - "city" => $.getStringProperty("LocalTimeInCity","") - }, - method(:onReceiveCityLocalTime) - ); - - } - - // 2. Weather. - if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { - var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); - var lat = $.getStringProperty("LastLocationLat",""); - var lon = $.getStringProperty("LastLocationLng",""); - - if (lat != null && lon != null) { - /*DEBUG*/ logMessage("onTemporalEvent: Doing OWM"); - makeWebRequest( - "https://api.openweathermap.org/data/2.5/weather", - { - "lat" => lat, - "lon" => lon, - - // Polite request from Vince, developer of the Crystal Watch Face: - // - // Please do not abuse this API key, or else I will be forced to make thousands of users of Crystal - // sign up for their own Open Weather Map free account, and enter their key in settings - a much worse - // user experience for everyone. - // - // Crystal has been registered with OWM on the Open Source Plan, which lifts usage limits for free, so - // that everyone benefits. However, these lifted limits only apply to the Current Weather API, and *not* - // the One Call API. Usage of this key for the One Call API risks blocking the key for everyone. - // - // If you intend to use this key in your own app, especially for the One Call API, please create your own - // OWM account, and own key. You should be able to apply for the Open Source Plan to benefit from the same - // lifted limits as Crystal. Thank you. - "appid" => ((owmKeyOverride == null) || (owmKeyOverride.length() == 0)) ? "2651f49cb20de925fc57590709b86ce6" : owmKeyOverride, - - "units" => "metric" // Celcius. - }, - method(:onReceiveOpenWeatherMapCurrent) - ); - } - } - - // 3. Tesla - if (pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null) { - if (!Sys.getDeviceSettings().phoneConnected) { - Bg.exit(null); - } - - if (_token == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); - var refreshToken = $.getStringProperty("TeslaRefreshToken",""); - if (refreshToken != null) { - makeTeslaWebPost(refreshToken, method(:onReceiveToken)); - } else { - /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); - Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); - } - return; - } - - if (_vehicle_id == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); - return; - } - - /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); - } - } /* else { - Sys.println("onTemporalEvent() called with no pending web requests!"); - } */ - } - - // Sample time zone data: - /* - { - "requestCity":"london", - "city":"London", - "current":{ - "gmtOffset":3600, - "dst":true - }, - "next":{ - "when":1540688400, - "gmtOffset":0, - "dst":false - } - } - */ - - // Sample error when city is not found: - /* - { - "requestCity":"atlantis", - "error":{ - "code":2, // CITY_NOT_FOUND - "message":"City \"atlantis\" not found." + if (!Sys.getDeviceSettings().phoneConnected) { + Bg.exit(null); } - } - */ - (:background_method) - function onReceiveCityLocalTime(responseCode, data) { - - // HTTP failure: return responseCode. - // Otherwise, return data response. - /*DEBUG*/ logMessage("onReceiveCityLocalTime: " + responseCode); - if (responseCode != 200) { - data = { - "httpError" => responseCode - }; - } - - Bg.exit({ - "CityLocalTime" => data - }); - } - - // Sample invalid API key: - /* - { - "cod":401, - "message": "Invalid API key. Please see http://openweathermap.org/faq#error401 for more info." - } - */ - - // Sample current weather: - /* - { - "coord":{ - "lon":-0.46, - "lat":51.75 - }, - "weather":[ - { - "id":521, - "main":"Rain", - "description":"shower rain", - "icon":"09d" - } - ], - "base":"stations", - "main":{ - "temp":281.82, - "pressure":1018, - "humidity":70, - "temp_min":280.15, - "temp_max":283.15 - }, - "visibility":10000, - "wind":{ - "speed":6.2, - "deg":10 - }, - "clouds":{ - "all":0 - }, - "dt":1540741800, - "sys":{ - "type":1, - "id":5078, - "message":0.0036, - "country":"GB", - "sunrise":1540709390, - "sunset":1540744829 - }, - "id":2647138, - "name":"Hemel Hempstead", - "cod":200 - } - */ - (:background_method) - function onReceiveOpenWeatherMapCurrent(responseCode, data) { - var result; - - // Useful data only available if result was successful. - // Filter and flatten data response for data that we actually need. - // Reduces runtime memory spike in main app. - /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: " + responseCode); - if (responseCode == 200) { - result = { - "cod" => data["cod"], - "lat" => data["coord"]["lat"], - "lon" => data["coord"]["lon"], - "dt" => data["dt"], - "temp" => data["main"]["temp"], - "humidity" => data["main"]["humidity"], - "icon" => data["weather"][0]["icon"] - }; - - // HTTP error: do not save. - } else { - result = Storage.getValue("OpenWeatherMapCurrent"); - if (result) { - result["cod"] = responseCode; + if (_token == null) { + /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); + var refreshToken = $.getStringProperty("TeslaRefreshToken",""); + if (refreshToken != null) { + makeWebPost(refreshToken, method(:onReceiveToken)); } else { - result = { - "httpError" => responseCode - }; + /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); + Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); } + return; + } - /*var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); - var dateStr = clockTime.year + " " + clockTime.month + " " + clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - Sys.println(dateStr + " : httpError=" + responseCode);*/ + if (_vehicle_id == null) { + /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); + makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + return; } - Bg.exit({ "OpenWeatherMapCurrent" => result }); + /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); + makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); } -//**************************************************************** -//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** -//**************************************************************** (:background_method) function onReceiveToken(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); @@ -359,9 +151,22 @@ class BackgroundService extends Sys.ServiceDelegate { var vehicles = responseData.get("response"); var vehice_state; if (vehicles != null) { + var storVehicleIndex = Storage.getValue("TeslaVehicleIndex"); + if (storVehicleIndex == null || storVehicleIndex < 1) { + storVehicleIndex = 0; + } + else { + storVehicleIndex--; // Array are zero based but we want user to start numbering from 1 for ease of use + } if (vehicles.size() > 0) { - _vehicle_id = vehicles[0].get("id").toString(); - vehice_state = vehicles[0].get("state"); + if (vehicles.size() > storVehicleIndex) { + _vehicle_id = vehicles[storVehicleIndex].get("id").toString(); + vehice_state = vehicles[storVehicleIndex].get("state"); + } + else { + _vehicle_id = null; + vehice_state = "VehicleNotFound"; + } } else { _vehicle_id = null; vehice_state = "NoVehicles"; @@ -428,7 +233,7 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = null; } /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); return; } // Our access token has expired, ask for a new one @@ -436,7 +241,7 @@ class BackgroundService extends Sys.ServiceDelegate { var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); - makeTeslaWebPost(refreshToken, method(:onReceiveToken)); + makeWebPost(refreshToken, method(:onReceiveToken)); return; } } @@ -445,7 +250,7 @@ class BackgroundService extends Sys.ServiceDelegate { } (:background_method) - function makeTeslaWebPost(token, notify) { + function makeWebPost(token, notify) { var url = "https://" + $.getStringProperty("TeslaServerAUTHLocation","") + "/oauth2/v3/token"; Comms.makeWebRequest( url, @@ -464,7 +269,7 @@ class BackgroundService extends Sys.ServiceDelegate { } (:background_method) - function makeTeslaWebRequest(url, params, callback) { + function makeWebRequest(url, params, callback) { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, :headers => { @@ -476,18 +281,4 @@ class BackgroundService extends Sys.ServiceDelegate { //2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); Comms.makeWebRequest(url, params, options, callback); } -//**************************************************************** -//******************** END OF REMVOVED SECTION ******************* -//**************************************************************** - - (:background_method) - function makeWebRequest(url, params, callback) { - var options = { - :method => Comms.HTTP_REQUEST_METHOD_GET, - :headers => { - "Content-Type" => Comms.REQUEST_CONTENT_TYPE_URL_ENCODED}, - :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON - }; - Comms.makeWebRequest(url, params, options, callback); - } } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index e97c7942..485573f6 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -12,27 +12,65 @@ import Toybox.Application; import Toybox.Lang; import Toybox.WatchUi; -// In-memory current location. -// Previously persisted in App.Storage, but now persisted in Object Store due to #86 workaround for App.Storage firmware bug. -// Current location retrieved/saved in checkPendingWebRequests(). -// Persistence allows weather and sunrise/sunset features to be used after watch face restart, even if watch no longer has current -// location available. -var gLocationLat = null; -var gLocationLng = null; var gTeslaComplication = false; (:background) class CrystalApp extends App.AppBase { var mView; + var mFieldTypes = new [3]; + var mGoalTypes = new [2]; + + private var mUseComplications; + function initialize() { AppBase.initialize(); + mFieldTypes[0] = {}; + mFieldTypes[1] = {}; + mFieldTypes[2] = {}; + + mGoalTypes[0] = {}; + mGoalTypes[1] = {}; + gTeslaComplication = getBoolProperty("TeslaLink", false); + + // This code check if the user selected a different vehicle index in its property. If so, we'll need to get a new vehicleID + var propVehicleIndex; + var storVehicleIndex; + + try { + propVehicleIndex = Properties.getValue("TeslaVehicleIndex"); + } + catch (e) { + propVehicleIndex = 1; + } + + storVehicleIndex = Storage.getValue("TeslaVehiceIndex"); + if (storVehicleIndex == null || propVehicleIndex != storVehicleIndex) { + storVehicleIndex = propVehicleIndex; + try { + Storage.setValue("TeslaVehiceIndex", storVehicleIndex); + Storage.setValue("TeslaVehiceIndex", storVehicleIndex); + Storage.setValue("TeslaVehicleID", null); + } + catch (e) { + } + } } + // function onStart(state) { + // /* DEBUG*/ logMessage("App starting"); + // } + + // function onStop(state) { + // /* DEBUG*/ logMessage("App stopping"); + // } + // Return the initial view of your application here function getInitialView() { + /* DEBUG*/ logMessage("Getting initial view"); + if (WatchUi has :WatchFaceDelegate) { mView = new CrystalView(); onSettingsChanged(); // After creating view. @@ -53,12 +91,43 @@ class CrystalApp extends App.AppBase { // New app settings have been received so trigger a UI update (:background_method) function getServiceDelegate() { + /* DEBUG*/ logMessage("Getting service delegate"); return [new BackgroundService()]; } function onSettingsChanged() { + mFieldTypes[0].put("type", $.getIntProperty("Field1Type", 0)); + mFieldTypes[1].put("type", $.getIntProperty("Field2Type", 1)); + mFieldTypes[2].put("type", $.getIntProperty("Field3Type", 2)); + + mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); + mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + + // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events + if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { + var lastTime = Bg.getLastTemporalEventTime(); + if (lastTime) { + // Events scheduled for a time in the past trigger immediately. + var nextTime = lastTime.add(new Time.Duration(5 * 60)); + Bg.registerForTemporalEvent(nextTime); + } else { + Bg.registerForTemporalEvent(Time.now()); + } + } + else { + Bg.deleteTemporalEvent(); + } + mView.onSettingsChanged(); // Calls checkPendingWebRequests(). + // Reread our complications if we're allowed + if (Toybox has :Complications) { + // First we drop all our subscriptions before building a new list + Complications.unsubscribeFromAllUpdates(); + // We listen for complications if we're allowed + Complications.registerComplicationChangeCallback(mView.useComplications() ? self.method(:onComplicationUpdated) : null); + } + Ui.requestUpdate(); } @@ -68,214 +137,95 @@ class CrystalApp extends App.AppBase { // pendingWebRequests keys. (:background_method) function onBackgroundData(data) { - //2022-04-10 logMessage("onBackgroundData:received '" + data + "'"); - var pendingWebRequests = Storage.getValue("PendingWebRequests"); - if (pendingWebRequests == null) { - pendingWebRequests = {}; - } - - var type = data.keys()[0]; // Type of received data. - var receivedData = data[type]; // The actual data received: strip away type key. + var receivedData = data["TeslaInfo"]; // What we just received - // Do process the data if what we got was an error - if (receivedData["httpError"] == null) { - // New data received: clear pendingWebRequests flag and overwrite stored data. - pendingWebRequests.remove(type); - Storage.setValue("PendingWebRequests", pendingWebRequests); - - if (type.equals("TeslaInfo")) { - // TeslaInfo is refeshed, not overwritten - var storedData = Storage.getValue(type); - if (storedData == null) { - storedData = {}; - } + var teslaInfo = Storage.getValue("TeslaInfo"); // What we have in Storage + if (teslaInfo == null) { + teslaInfo = {}; + } - var keys = receivedData.keys(); - var values = receivedData.values(); + // Update in TeslaInfo what has been received in receivedData + var keys = receivedData.keys(); + var values = receivedData.values(); + for (var i = 0; i < keys.size(); i++) { + teslaInfo.put(keys[i], values[i]); + } - for (var i = 0; i < keys.size(); i++) { - storedData.put(keys[i], values[i]); + // Copy into their own name some of the entries in TeslaInfo, then delete from TeslaInfo + var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; + var arrayProp = [true, true, false, false, false ]; + for (var i = 0; i < arrayKey.size(); i++) { + var value = teslaInfo.get(arrayKey[i]); + if (value != null) { + if (arrayProp[i]) { + Properties.setValue("Tesla" + arrayKey[i], value); } - Storage.setValue(type, storedData); - } - else { - Storage.setValue(type, receivedData); + else { + Storage.setValue("Tesla" + arrayKey[i], value); + } + teslaInfo.remove(arrayKey[i]); } + } - if (type.equals("OpenWeatherMapCurrent")) { - Storage.setValue("NewOpenWeatherMapCurrent", true); + // Now store our updated copy of TeslaInfo + Storage.setValue("TeslaInfo", teslaInfo); + + // We deal with specific errors here, leaving the good stuff to the battery indicator + var responseCode = teslaInfo["httpErrorTesla"]; + var internalResponseCode = teslaInfo["httpInternalErrorTesla"]; + if (responseCode != null && internalResponseCode != null) { + if (responseCode == 401 && internalResponseCode != 200) { // Our token has expired and we were unable to get one, refresh it + Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID + } else if (responseCode == 404 && internalResponseCode != 200) { // We got a vehicle not found error and we were unable to get one, reset our vehicle ID + Storage.remove("VehicleID"); // Try to get a new vehicleID } - - checkPendingWebRequests(); // We just got new data, process them right away before displaying } Ui.requestUpdate(); } - // Determine if any web requests are needed. - // If so, set approrpiate pendingWebRequests flag for use by BackgroundService, then register for - // temporal event. - // Currently called on layout initialisation, when settings change, and on exiting sleep. - (:background_method) - function checkPendingWebRequests() { - // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. - // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. - - var location = Activity.getActivityInfo().currentLocation; - if (location) { - location = location.toDegrees(); // Array of Doubles. - if (location[0] != 0.0 && location[1] != 0.0) { - gLocationLat = location[0]; - gLocationLng = location[1]; - Properties.setValue("LastLocationLat", gLocationLat.format("%0.5f")); - Properties.setValue("LastLocationLng", gLocationLng.format("%0.5f")); - } - } - // If current location is not available, read stored value from Object Store, being careful not to overwrite a valid - // in-memory value with an invalid stored one. - else { - var lat = $.getStringProperty("LastLocationLat",""); - if (lat != null) { - gLocationLat = lat.toFloat(); - } + function hasField(fieldType) { + return ((mFieldTypes[0].get("type") == fieldType) || + (mFieldTypes[1].get("type") == fieldType) || + (mFieldTypes[2].get("type") == fieldType)); + } - var lng = $.getStringProperty("LastLocationLng",""); - if (lng != null) { - gLocationLng = lng.toFloat(); - } - } + function onComplicationUpdated(complicationId) { + var complication = Complications.getComplication(complicationId); + var complicationType = complication.getType(); + var complicationShortLabel = complication.shortLabel; + //DEBUG*/ var complicationLongLabel = complication.longLabel; + var complicationValue = complication.value; - if (!(Sys has :ServiceDelegate)) { - return; - } + //DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_STEPS) { + //DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); + //DEBUG*/ } - var pendingWebRequests = Storage.getValue("PendingWebRequests"); - if (pendingWebRequests == null) { - pendingWebRequests = {}; + if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { + $.doTeslaComplication(complicationValue); } - // 1. City local time: - // City has been specified. - var city = $.getStringProperty("LocalTimeInCity",""); - - // #78 Setting with value of empty string may cause corresponding property to be null. - if ((city != null) && (city.length() > 0)) { - - var cityLocalTime = Storage.getValue("CityLocalTime"); - - // No existing data. - if ((cityLocalTime == null) || - - // Existing data is old. - ((cityLocalTime["next"] != null) && (Time.now().value() >= cityLocalTime["next"]["when"]))) { - - pendingWebRequests["CityLocalTime"] = true; - - // Existing data not for this city: delete it. - // Error response from server: contains requestCity. Likely due to unrecognised city. Prevent requesting this - // city again. - } else if (!cityLocalTime["requestCity"].equals(city)) { - - deleteProperty("CityLocalTime"); - pendingWebRequests["CityLocalTime"] = true; - } + // I've seen this while in low power mode, so skip it + if (complicationValue == null) { + //DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); + return; } - // 2. Weather: - // Location must be available, weather or humidity (#113) data field must be shown. - if ((gLocationLat != null) && - (mView.hasField(FIELD_TYPE_WEATHER) || mView.hasField(FIELD_TYPE_HUMIDITY))) { + // Do fields first + var fieldCount = $.getIntProperty("FieldCount", 3); - var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); - if (owmKeyOverride == null || owmKeyOverride.length() == 0) { - //2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); - } else { - //2022-04-10 logMessage("Using OpenWeatherMap"); - var owmCurrent = Storage.getValue("OpenWeatherMapCurrent"); - - // No existing data. - if (owmCurrent == null) { - pendingWebRequests["OpenWeatherMapCurrent"] = true; - // Successfully received weather data. - } else if (owmCurrent["cod"] == 200) { - // Existing data is older than 5 mins. - // TODO: Consider requesting weather at sunrise/sunset to update weather icon. - if ((Time.now().value() > (owmCurrent["dt"] + 300)) || - - // Existing data not for this location. - // Not a great test, as a degree of longitude varies betwee 69 (equator) and 0 (pole) miles, but simpler than - // true distance calculation. 0.02 degree of latitude is just over a mile. - (((gLocationLat - owmCurrent["lat"]).abs() > 0.02) || ((gLocationLng - owmCurrent["lon"]).abs() > 0.02))) { - pendingWebRequests["OpenWeatherMapCurrent"] = true; - } - } else { - pendingWebRequests["OpenWeatherMapCurrent"] = true; - } + for (var i = 0; i < fieldCount; i++) { + if (mFieldTypes[i].get("ComplicationType") == complicationType) { + mFieldTypes[i].put("ComplicationValue", complicationValue); } } - // 3. Tesla: -//**************************************************************** -//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** -//**************************************************************** -//*******************checkPendingWebRequests********************** - if (Storage.getValue("Tesla") != null && gTeslaComplication == false) { - var teslaInfo = Storage.getValue("TeslaInfo"); - if (teslaInfo == null) { // We're not doing Tesla stuff so why asking for it, clear that - pendingWebRequests["TeslaInfo"] = false; - } else { // We're doing Tesla stuff - var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; - var arrayProp = [true, true, false, false, false ]; - - for (var i = 0; i < arrayKey.size(); i++) { - var value = teslaInfo.get(arrayKey[i]); - if (value != null) { - if (arrayProp[i]) { - Properties.setValue("Tesla" + arrayKey[i], value); - } - else { - Storage.setValue("Tesla" + arrayKey[i], value); - } - teslaInfo.remove(arrayKey[i]); - } - } - - // We deal with specific errors here, leaving the good stuff to the battery indicator - var responseCode = teslaInfo["httpErrorTesla"]; - var internalResponseCode = teslaInfo["httpInternalErrorTesla"]; - if (responseCode != null && internalResponseCode != null) { - if (responseCode == 401 && internalResponseCode != 200) { // Our token has expired and we were unable to get one, refresh it - Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID - } else if (responseCode == 404 && internalResponseCode != 200) { // We got a vehicle not found error and we were unable to get one, reset our vehicle ID - Storage.remove("VehicleID"); // Try to get a new vehicleID - } - - Storage.setValue("TeslaInfo", teslaInfo); - } - - pendingWebRequests["TeslaInfo"] = true; - } + // Now do goals + if (mGoalTypes[0].get("ComplicationType") == complicationType) { + mGoalTypes[0].put("ComplicationValue", complicationValue); } - else { - pendingWebRequests.remove("TeslaInfo"); + if (mGoalTypes[1].get("ComplicationType") == complicationType) { + mGoalTypes[1].put("ComplicationValue", complicationValue); } -//**************************************************************** -//******************** END OF REMVOVED SECTION ******************* -//**************************************************************** - - // If there are any pending requests and we can do background process - if (Toybox.System has :ServiceDelegate && pendingWebRequests.keys().size() > 0) { - // Register for background temporal event as soon as possible. - var lastTime = Bg.getLastTemporalEventTime(); - if (lastTime) { - // Events scheduled for a time in the past trigger immediately. - var nextTime = lastTime.add(new Time.Duration(5 * 60)); - Bg.registerForTemporalEvent(nextTime); - } else { - Bg.registerForTemporalEvent(Time.now()); - } - } - - Storage.setValue("PendingWebRequests", pendingWebRequests); - } + } } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index b6c4c077..8c7f9e5e 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -52,12 +52,12 @@ class CrystalView extends Ui.WatchFace { private var mSettingsChangedSinceLastDraw = true; // Have settings changed since last full update? private var mTime; var mDataFields; - var mHasGarminWeather; // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; - - var mFieldTypes = new [3]; - var mGoalTypes = new [2]; + var mWeatherStationName; + var mLocalCityName; + var mLocalCityLat; + var mLocalCityLon; private var mUseComplications; @@ -91,38 +91,12 @@ class CrystalView extends Ui.WatchFace { function initialize() { WatchFace.initialize(); - mFieldTypes[0] = {}; - mFieldTypes[1] = {}; - mFieldTypes[2] = {}; - - mGoalTypes[0] = {}; - mGoalTypes[1] = {}; - - rereadWeatherMethod(); } function burnInProtectionIsOrWasActive() { return mIsBurnInProtection | mBurnInProtectionChangedSinceLastDraw; } - // Reread Weather method - function rereadWeatherMethod() { - var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); - //2022-04-10 logMessage("OWMKeyOverride is '" + owmKeyOverride + "'"); - if (owmKeyOverride == null || owmKeyOverride.length() == 0) { - if (Toybox has :Weather) { - mHasGarminWeather = true; - //2022-04-10 logMessage("Does support Weather"); - } else { - mHasGarminWeather = false; - //2022-04-10 logMessage("Does not support Weather"); - } - } else { - mHasGarminWeather = false; - //2022-04-10 logMessage("Using OpenWeatherMap"); - } - } - // Load your resources here function onLayout(dc) { gIconsFont = Ui.loadResource(Rez.Fonts.IconsFont); @@ -155,26 +129,19 @@ class CrystalView extends Ui.WatchFace { /* // Called when this View is brought to the foreground. Restore // the state of this View and prepare it to be shown. This includes - // loading resources into memory. + // loading resources into memory. */ function onShow() { + /* DEBUG*/ logMessage("View showing"); } - */ // Set flag to respond to settings change on next full draw (onUpdate()), as we may be in 1Hz (lower power) mode, and cannot // update the full screen immediately. This is true on real hardware, but not in the simulator, which calls onUpdate() // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. function onSettingsChanged() { - mFieldTypes[0].put("type", $.getIntProperty("Field1Type", 0)); - mFieldTypes[1].put("type", $.getIntProperty("Field2Type", 1)); - mFieldTypes[2].put("type", $.getIntProperty("Field3Type", 2)); - - mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); - mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); - mSettingsChangedSinceLastDraw = true; //logMessage("onSettingsChanged called"); - updateNormalFont(); + gNormalFont = Ui.loadResource(Rez.Fonts.NormalFontCities); // Themes: explicitly set *Colour properties that have no corresponding (user-facing) setting. updateThemeColours(); @@ -182,92 +149,24 @@ class CrystalView extends Ui.WatchFace { // Update hours/minutes colours after theme colours have been set. updateHoursMinutesColours(); - if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. - App.getApp().checkPendingWebRequests(); - } - - rereadWeatherMethod(); // Check if we changed from Garmin Weather or OWM + ReadWeather(false); - if (mHasGarminWeather == true) { // Using the Garmin Weather stuff - ReadWeather(false); - } + // Get our 2nd local time if available + var localTimeInCity = $.getStringProperty("LocalTimeInCity", ""); + var splitArray = $.to_array(localTimeInCity, ","); + if (splitArray.size() == 3) { + mLocalCityName = $.validateString(splitArray[0], "???"); + mLocalCityLat = $.validateFloat(splitArray[1], null); + mLocalCityLon = $.validateFloat(splitArray[2], null); + } + else { + mLocalCityName = null; + } // Reread our complications if we're allowed mUseComplications = $.getBoolProperty("UseComplications", false); - if (Toybox has :Complications) { - // First we drop all our subscriptions before building a new list - Complications.unsubscribeFromAllUpdates(); - // We listen for complications if we're allowed - Complications.registerComplicationChangeCallback(mUseComplications ? self.method(:onComplicationUpdated) : null); - } } - function hasField(fieldType) { - if (mFieldTypes[0] == null || mFieldTypes[1] == null || mFieldTypes[2] == null) { - return false; - } - return ((mFieldTypes[0].get("type") == fieldType) || - (mFieldTypes[1].get("type") == fieldType) || - (mFieldTypes[2].get("type") == fieldType)); - } - - function onComplicationUpdated(complicationId) { - var complication = Complications.getComplication(complicationId); - var complicationType = complication.getType(); - /*DEBUG*/ var complicationShortLabel = complication.shortLabel; - /*DEBUG*/ var complicationLongLabel = complication.longLabel; - var complicationValue = complication.value; - - //DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_STEPS) { - //DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); - //DEBUG*/ } - - if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { - var teslaInfo = Storage.getValue("TeslaInfo"); - if (teslaInfo == null){ - teslaInfo = {}; - } - var arrayInfo = $.to_array(complicationValue, "|"); - teslaInfo.put("httpErrorTesla", $.validateNumber(arrayInfo[0], 0)); - teslaInfo.put("BatteryLevel", $.validateNumber(arrayInfo[1], 0)); - teslaInfo.put("ChargingState", $.validateString(arrayInfo[2], "")); - teslaInfo.put("InsideTemp", $.validateNumber(arrayInfo[3], 0)); - teslaInfo.put("SentryEnabled", $.validateBoolean(arrayInfo[4], false)); - teslaInfo.put("PrecondEnabled", $.validateBoolean(arrayInfo[5], false)); - teslaInfo.put("VehicleState", $.validateString(arrayInfo[6], "asleep")); - - Storage.setValue("TeslaInfo", teslaInfo); - } - - // If we were told to ignore complications, do so (but technicaly, we shouldn't get here as we shouldn't be listening in the first place!) - if (!mUseComplications) { - /*DEBUG*/ logMessage("How did we get here, we're not supposed to be listening!"); - return; - } - - // I've seen this while in low power mode, so skip it - if (complicationValue == null) { - //DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); - return; - } - - // Do fields first - var fieldCount = $.getIntProperty("FieldCount", 3); - - for (var i = 0; i < fieldCount; i++) { - if (mFieldTypes[i].get("ComplicationType") == complicationType) { - mFieldTypes[i].put("ComplicationValue", complicationValue); - } - } - - // Now do goals - for (var i = 0; i < 2; i++) { - if (mGoalTypes[i].get("ComplicationType") == complicationType) { - mGoalTypes[i].put("ComplicationValue", complicationValue); - } - } - } - // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see function ReadWeather(fromComplication) { var weather; @@ -284,87 +183,46 @@ class CrystalView extends Ui.WatchFace { var icon = "01"; var day = "d"; + mWeatherStationName = weather.observationLocationName; var myLocation = weather.observationLocationPosition; - var myLocationArray = myLocation.toDegrees(); - // So the OWM code knows our location since it's background code won't run to fetch it - gLocationLat = myLocationArray[0]; - gLocationLng = myLocationArray[1]; - var now = Time.now(); - if (Toybox.Weather has :getSunrise) { - //logMessage("We have sunrise and sunset routines!"); - var sunrise = Weather.getSunrise(myLocation, now); - var sunset = Weather.getSunset(myLocation, now); - - var sinceSunrise = sunrise.compare(now); - var sinceSunset = now.compare(sunset); - if (sinceSunrise >= 0 || sinceSunset >= 0) { - day = "n"; - } + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); - /*var nowtime = Gregorian.info(now, Time.FORMAT_MEDIUM); - var nowStr = nowtime.day + " " + nowtime.hour + ":" + nowtime.min.format("%02d") + ":" + nowtime.sec.format("%02d"); - var sunrisetime = Gregorian.info(sunrise, Time.FORMAT_MEDIUM); - var sunsettime = Gregorian.info(sunset, Time.FORMAT_MEDIUM); - var sunriseStr = sunrisetime.day + " " + sunrisetime.hour + ":" + sunrisetime.min.format("%02d") + ":" + sunrisetime.sec.format("%02d"); - var sunsetStr = sunsettime.day + " " + sunsettime.hour + ":" + sunsettime.min.format("%02d") + ":" + sunsettime.sec.format("%02d"); - logMessage("For=" + nowStr); - logMessage("Sunrise=" + sunriseStr); - logMessage("Sunset=" + sunsetStr); - logMessage("Since sunrize " + sinceSunrise); - logMessage("Since sunset " + sinceSunset);*/ - - } else { - //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); - - now = Gregorian.info(now, Time.FORMAT_SHORT); - - // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at - // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). - now = now.hour + ((now.min + 1) / 60.0); - //logMessage(now); - - // Get today's sunrise/sunset times in current time zone. - var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); - //logMessage(sunTimes); - //logMessage("now=" + now); - //logMessage("sunTimes=" + sunTimes); - // If sunrise/sunset happens today. - var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); - if (sunriseSunsetToday) { - if (now < sunTimes[0] || now > sunTimes[1]) { - day = "n"; - } - } - + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); + if (sinceSunrise >= 0 || sinceSunset >= 0) { + day = "n"; } + /*var nowtime = Gregorian.info(now, Time.FORMAT_MEDIUM); + var nowStr = nowtime.day + " " + nowtime.hour + ":" + nowtime.min.format("%02d") + ":" + nowtime.sec.format("%02d"); + var sunrisetime = Gregorian.info(sunrise, Time.FORMAT_MEDIUM); + var sunsettime = Gregorian.info(sunset, Time.FORMAT_MEDIUM); + var sunriseStr = sunrisetime.day + " " + sunrisetime.hour + ":" + sunrisetime.min.format("%02d") + ":" + sunrisetime.sec.format("%02d"); + var sunsetStr = sunsettime.day + " " + sunsettime.hour + ":" + sunsettime.min.format("%02d") + ":" + sunsettime.sec.format("%02d"); + logMessage("For=" + nowStr); + logMessage("Sunrise=" + sunriseStr); + logMessage("Sunset=" + sunsetStr); + logMessage("Since sunrize " + sinceSunrise); + logMessage("Since sunset " + sinceSunset);*/ + if (condition < 53) { icon = (mGarminToOWM[condition]).format("%02d") + day; //logMessage("icon=" + icon); } - result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => weather.observationTime.value(), "lat" => myLocationArray[0], "lon" => myLocationArray[1]}; + result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => weather.observationTime.value() }; //2022-04-10 logMessage("Weather at " + weather.observationLocationName + " is " + result); - } else { + } + else { result = null; //2022-04-10 logMessage("No weather data, returning null"); } - Storage.setValue("OpenWeatherMapCurrent", result); - Storage.setValue("NewOpenWeatherMapCurrent", true); + Storage.setValue("WeatherInfo", result); + Storage.setValue("NewWeatherInfo", true); } - // Select normal font, based on whether time zone feature is being used. - // Saves memory when cities are not in use. - // Update drawables that use normal font. - function updateNormalFont() { - var city = $.getStringProperty("LocalTimeInCity",""); - - // #78 Setting with value of empty string may cause corresponding property to be null. - gNormalFont = Ui.loadResource(((city != null) && (city.length() > 0)) ? - Rez.Fonts.NormalFontCities : Rez.Fonts.NormalFont); - } - function updateThemeColours() { // #182 Protect against null or unexpected type e.g. String. @@ -537,7 +395,7 @@ class CrystalView extends Ui.WatchFace { }; var app = App.getApp(); - var goalTypes = mGoalTypes; + var goalTypes = app.mGoalTypes; var info = ActivityMonitor.getInfo(); switch(type) { @@ -653,60 +511,17 @@ class CrystalView extends Ui.WatchFace { values[:current] = stressLevel.toFloat(); values[:isValid] = true; gStressLevel = stressLevel; - - /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); - var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); - var dateStr = clockTime.day + " " + clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - var logText = "stressLevel " + stressLevel + " stressLevelDate " + dateStr + " is GOOD"; - if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { - logMessage(logText); - gStressLevelLogText = logText; - }/**/ } else if (gStressLevel != null) { values[:current] = gStressLevel.toFloat(); values[:isValid] = true; values[:staled] = true; - - /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); - var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); - var logText = "stressLevel " + stressLevel + "is over limit, ignoring"; - if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { - logMessage(logText); - gStressLevelLogText = logText; - }/**/ - } else { - /*DEBUG var logText = "stressLevel " + stressLevel + "is over limit and no StressHistory data found yet"; - if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { - logMessage(logText); - gStressLevelLogText = logText; - }/**/ } } else if (gStressLevel != null) { values[:current] = gStressLevel.toFloat(); values[:isValid] = true; values[:staled] = true; - - /*DEBUG var timeMoment = new Time.Moment(stressLevelDate); - var clockTime = Gregorian.info(timeMoment, Time.FORMAT_SHORT); - var logText = "stressLevel " + gStressLevel + " IS staled"; - if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { - logMessage(logText); - gStressLevelLogText = logText; - }/**/ - } else { - /*DEBUG var logText = "No StressHistory data found yet"; - if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { - logMessage(logText); - gStressLevelLogText = logText; - }/**/ } //logMessage("stressLeve " + stressLevel + " count " + count + " keptCount " + keptCount + " stressLevelDate " + stressLevelDate); - } else { - /*DEBUG var logText = "No StressHistory Sensor found"; - if (gStressLevelLogText == null || logText.equals(gStressLevelLogText) == false) { - logMessage(logText); - gStressLevelLogText = logText; - }/**/ } break; @@ -753,10 +568,10 @@ class CrystalView extends Ui.WatchFace { /* // Called when this View is removed from the screen. Save the // state of this View here. This includes freeing resources from - // memory. + // memory */ function onHide() { + /* DEBUG*/ logMessage("View hidding"); } - */ // The user has just looked at their watch. Timers and animations may be started here. function onExitSleep() { @@ -771,16 +586,7 @@ class CrystalView extends Ui.WatchFace { setHideSeconds(false); } - // Rather than checking the need for background requests on a timer, or on the hour, easier just to check when exiting - // sleep. - if (CrystalApp has :checkPendingWebRequests) { // checkPendingWebRequests() can be excluded to save memory. - //logMessage("onExitSleep:Wakeup and checkPendingWebRequests"); - App.getApp().checkPendingWebRequests(); - } - - if (mHasGarminWeather == true) { // Using the Garmin Weather stuff - ReadWeather(false); - } + ReadWeather(false); // If watch requires burn-in protection, set flag to false when entering sleep. var settings = Sys.getDeviceSettings(); diff --git a/source/DataArea.mc b/source/DataArea.mc index 84f942f2..92bf5165 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -75,19 +75,17 @@ class DataArea extends Ui.Drawable { drawGoalIcon(dc, mGoalIconLeftX, mLeftGoalType, mLeftGoalIsValid, mLeftGoalstaled, Graphics.TEXT_JUSTIFY_LEFT); drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, mRightGoalstaled, Graphics.TEXT_JUSTIFY_RIGHT); - var city = $.getStringProperty("LocalTimeInCity", ""); + var view = App.getApp().getView(); + var city = view.mLocalCityName; + var fromWeather = false; - // #78 Setting with value of empty string may cause corresponding property to be null. - if ((city != null) && (city.length() != 0)) { - //drawTimeZone(); - var cityLocalTime = Storage.getValue("CityLocalTime"); - - // If available, use city returned from web request; otherwise, use raw city from settings. - // N.B. error response will NOT contain city. - if ((cityLocalTime != null) && (cityLocalTime["city"] != null)) { - city = cityLocalTime["city"]; - } + if (city == null || city.length() == 0) { + city = view.mWeatherStationName; + fromWeather = true; + } + // #78 Setting with value of empty string may cause corresponding property to be null. + if ((city != null && city.length() > 0)) { // Time zone 1 city. dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); dc.drawText( @@ -100,50 +98,41 @@ class DataArea extends Ui.Drawable { ); // Time zone 1 time. - var time; - if (cityLocalTime) { + if (!fromWeather) { + var time; - // Web request responded with server error e.g. unknown city. - if (cityLocalTime["error"] != null) { + if (view.mLocalCityLat != null && view.mLocalCityLat >= -90.0 && view.mLocalCityLat <= 90.0 && view.mLocalCityLon != null && view.mLocalCityLon >= -90.0 && view.mLocalCityLon <= 90.0) { + try { + var where = new Position.Location({ + :latitude => view.mLocalCityLat, + :longitude => view.mLocalCityLon, + :format => :degrees + }); - time = "???"; - // Web request responded with time zone data for city. - } else { - var timeZoneGmtOffset; + var local = Gregorian.localMoment(where, Time.now()); + local = Gregorian.info(local, Time.FORMAT_SHORT); - // Use next GMT offset if it's now applicable (new data will be requested shortly). - if ((cityLocalTime["next"] != null) && (Time.now().value() >= cityLocalTime["next"]["when"])) { - timeZoneGmtOffset = cityLocalTime["next"]["gmtOffset"]; - } else { - timeZoneGmtOffset = cityLocalTime["current"]["gmtOffset"]; + time = $.getFormattedTime(local.hour, local.min); + time = time[:hour] + ":" + time[:min] + time[:amPm]; } - timeZoneGmtOffset = new Time.Duration(timeZoneGmtOffset); - - var localGmtOffset = Sys.getClockTime().timeZoneOffset; - localGmtOffset = new Time.Duration(localGmtOffset); - - // (Local time) - (Local GMT offset) + (Time zone GMT offset) - time = Time.now().subtract(localGmtOffset).add(timeZoneGmtOffset); - time = Gregorian.info(time, Time.FORMAT_SHORT); - time = $.getFormattedTime(time.hour, time.min); - time = time[:hour] + ":" + time[:min] + time[:amPm]; + catch (e) { + time = "???"; + } + } + else { + time = "???"; } - // Awaiting response to web request sent by BackgroundService. - } else { - time = "..."; + dc.setColor(gMonoLightColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + locX + (width / 2), + mRow2Y, + gNormalFont, + time, + Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER + ); } - - dc.setColor(gMonoLightColour, Gfx.COLOR_TRANSPARENT); - dc.drawText( - locX + (width / 2), - mRow2Y, - gNormalFont, - time, - Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER - ); - } else { drawGoalValues(dc, locX, mLeftGoalCurrent, mLeftGoalMax, Graphics.TEXT_JUSTIFY_LEFT); drawGoalValues(dc, locX + width, mRightGoalCurrent, mRightGoalMax, Graphics.TEXT_JUSTIFY_RIGHT); diff --git a/source/DataFields.mc b/source/DataFields.mc index fa75a298..272c9955 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -42,6 +42,7 @@ enum /* FIELD_TYPES */ { class DataFields extends Ui.Drawable { + private var mApp; private var mView; var mLeft; @@ -57,7 +58,7 @@ class DataFields extends Ui.Drawable { private var mWasHRAvailable = false; // HR availability at last full draw (in high power mode). private var mMaxFieldLength; // Maximum number of characters per field. private var mBatteryWidth; // Width of battery meter. - private var storedWeather; + private var mWeather; // private const CM_PER_KM = 100000; // private const MI_PER_KM = 0.621371; // private const FT_PER_M = 3.28084; @@ -78,9 +79,8 @@ class DataFields extends Ui.Drawable { // Cache FieldCount setting, and determine appropriate maximum field length. function onSettingsChanged() { - - var app = App.getApp(); - mView = app.getView(); + mApp = App.getApp(); + mView = mApp.getView(); // #123 Protect against null or unexpected type e.g. String. mFieldCount = $.getIntProperty("FieldCount", 3); @@ -100,9 +100,9 @@ class DataFields extends Ui.Drawable { // #116 Handle FieldCount = 0 correctly. mMaxFieldLength = [0, 8, 6, 4][mFieldCount]; - mHasLiveHR = mView.hasField(FIELD_TYPE_HR_LIVE_5S); + mHasLiveHR = mApp.hasField(FIELD_TYPE_HR_LIVE_5S); - if (!mView.hasField(FIELD_TYPE_WEATHER)) { + if (!mApp.hasField(FIELD_TYPE_WEATHER)) { mWeatherIconsFont = null; mWeatherIconsSubset = null; } @@ -115,12 +115,12 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE} ]; - var fieldTypes = mView.mFieldTypes; + var fieldTypes = mApp.mFieldTypes; var filled = [false, false, false]; var i; for (i = 0; i < complications.size(); i++) { - if (mView.hasField(complications[i].get("type"))) { + if (mApp.hasField(complications[i].get("type"))) { for (var j = 0; j < mFieldCount; j++) { if (fieldTypes[j].get("type") == complications[i].get("type")) { $.updateComplications("", "Complication_F", j + 1, complications[i].get("complicationType")); @@ -156,7 +156,7 @@ class DataFields extends Ui.Drawable { return; } - var fieldTypes = mView.mFieldTypes; + var fieldTypes = mApp.mFieldTypes; /*var spacingX = Sys.getDeviceSettings().screenWidth / (2 * mFieldCount); var spacingY = Sys.getDeviceSettings().screenHeight / 4; @@ -436,7 +436,6 @@ class DataFields extends Ui.Drawable { var altitude; var pressure = null; // May never be initialised if no support for pressure (CIQ 1.x devices). var temperature; - var weather; var weatherValue; var sunTimes; var unit; @@ -456,7 +455,7 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_BODY_BATTERY: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mView.mFieldTypes; + var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -478,7 +477,7 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_STRESS_LEVEL: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mView.mFieldTypes; + var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -521,7 +520,7 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_TYPE_PULSE_OX: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mView.mFieldTypes; + var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString() + "%"; @@ -537,7 +536,7 @@ class DataFields extends Ui.Drawable { break; case FIELD_TYPE_HEART_RATE: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mView.mFieldTypes; + var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -663,63 +662,36 @@ class DataFields extends Ui.Drawable { break; case FIELD_TYPE_SUNRISE_SUNSET: - - if (gLocationLat != null) { - var nextSunEvent = 0; - var now = Gregorian.info(Time.now(), Time.FORMAT_SHORT); - - // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at - // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). - now = now.hour + ((now.min + 1) / 60.0); - //logMessage(now); - - // Get today's sunrise/sunset times in current time zone. - sunTimes = getSunTimes(gLocationLat, gLocationLng, null, /* tomorrow */ false); - //logMessage(sunTimes); - - // If sunrise/sunset happens today. - var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); - if (sunriseSunsetToday) { - - // Before sunrise today: today's sunrise is next. - if (now < sunTimes[0]) { - nextSunEvent = sunTimes[0]; - result["isSunriseNext"] = true; - - // After sunrise today, before sunset today: today's sunset is next. - } else if (now < sunTimes[1]) { - nextSunEvent = sunTimes[1]; - - // After sunset today: tomorrow's sunrise (if any) is next. - } else { - sunTimes = getSunTimes(gLocationLat, gLocationLng, null, /* tomorrow */ true); - nextSunEvent = sunTimes[0]; - result["isSunriseNext"] = true; - } - } + var weather = Weather.getCurrentConditions(); + if (weather != null) { + var now = Time.now(); + var myLocation = weather.observationLocationPosition; - // Sun never rises/sets today. - if (!sunriseSunsetToday) { - value = "---"; + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); - // Sun never rises: sunrise is next, but more than a day from now. - if (sunTimes[0] == null) { - result["isSunriseNext"] = true; - } + var sunriseTime = Gregorian.info(sunrise, Time.FORMAT_SHORT); + var sunsetTime = Gregorian.info(sunset, Time.FORMAT_SHORT); - // We have a sunrise/sunset time. - } else { - var hour = Math.floor(nextSunEvent).toLong() % 24; - var min = Math.floor((nextSunEvent - Math.floor(nextSunEvent)) * 60); // Math.floor(fractional_part * 60) - value = $.getFormattedTime(hour, min); - value = value[:hour] + ":" + value[:min] + value[:amPm]; - } + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); - // Waiting for location. - } else { - value = "gps?"; + if (sinceSunrise >= 0 || sinceSunset >= 0) { + result["isSunriseNext"] = true; + value = $.getFormattedTime(sunriseTime.hour, sunriseTime.min); + } + else { + value = $.getFormattedTime(sunsetTime.hour, sunsetTime.min); + } + value = value[:hour] + ":" + value[:min] + value[:amPm]; } + else { + value = "???"; + if (!settings.phoneConnected) { + stale = true; + } + } break; case FIELD_TYPE_WEATHER: @@ -731,24 +703,16 @@ class DataFields extends Ui.Drawable { } // Only read that dictionnary from Storage if it has changed (or we don't have a local copy), otherwise read our stored weather data - if (storedWeather == null || Storage.getValue("NewOpenWeatherMapCurrent") != null) { - weather = Storage.getValue("OpenWeatherMapCurrent"); - Storage.setValue("NewOpenWeatherMapCurrent", null); - storedWeather = weather; - } - else { - weather = storedWeather; + if (mWeather == null || Storage.getValue("NewWeatherInfo") != null) { + mWeather = Storage.getValue("WeatherInfo"); + Storage.setValue("NewWeatherInfo", null); } - // Awaiting location. - if (gLocationLat == null) { - value = "gps?"; - // Stored weather data available. - } else if (weather != null) { + if (mWeather != null) { // FIELD_TYPE_WEATHER. if (type == FIELD_TYPE_WEATHER) { - weatherValue = weather["temp"]; // Celcius. + weatherValue = mWeather["temp"]; // Celcius. try { if (settings.temperatureUnits == System.UNIT_STATUTE) { weatherValue = (weatherValue * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. @@ -758,26 +722,25 @@ class DataFields extends Ui.Drawable { } catch (e) { /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); - value = "???"; + value = "NaN"; } - result["weatherIcon"] = weather["icon"]; + result["weatherIcon"] = mWeather["icon"]; // FIELD_TYPE_HUMIDITY. } else { - weatherValue = weather["humidity"]; + weatherValue = mWeather["humidity"]; value = weatherValue.format(INTEGER_FORMAT) + "%"; } - if (weather["cod"] != 200 || !settings.phoneConnected) { + if (mWeather["cod"] != 200 || !settings.phoneConnected) { stale = true; } // Awaiting response. - } else if ((Storage.getValue("PendingWebRequests") != null) && - Storage.getValue("PendingWebRequests")["OpenWeatherMapCurrent"] != null) { + } + else { + value = "???"; - value = "..."; - if (!settings.phoneConnected) { stale = true; } @@ -819,116 +782,3 @@ class DataFields extends Ui.Drawable { } } - -/** -* With thanks to ruiokada. Adapted, then translated to Monkey C, from: -* https://gist.github.com/ruiokada/b28076d4911820ddcbbc -* -* Calculates sunrise and sunset in local time given latitude, longitude, and tz. -* -* Equations taken from: -* https://en.wikipedia.org/wiki/Julian_day#Converting_Julian_or_Gregorian_calendar_date_to_Julian_Day_Number -* https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth -* -* @method getSunTimes -* @param {Float} lat Latitude of location (South is negative) -* @param {Float} lng Longitude of location (West is negative) -* @param {Integer || null} tz Timezone hour offset. e.g. Pacific/Los Angeles is -8 (Specify null for system timezone) -* @param {Boolean} tomorrow Calculate tomorrow's sunrise and sunset, instead of today's. -* @return {Array} Returns array of length 2 with sunrise and sunset as floats. -* Returns array with [null, -1] if the sun never rises, and [-1, null] if the sun never sets. -*/ -function getSunTimes(lat, lng, tz, tomorrow) { - - // Use double precision where possible, as floating point errors can affect result by minutes. - lat = lat.toDouble(); - lng = lng.toDouble(); - - var now = Time.now(); - if (tomorrow) { - now = now.add(new Time.Duration(24 * 60 * 60)); - } - var d = Gregorian.info(now, Time.FORMAT_SHORT); - var rad = Math.PI / 180.0d; - var deg = 180.0d / Math.PI; - - // Calculate Julian date from Gregorian. - var a = Math.floor((14 - d.month) / 12); - var y = d.year + 4800 - a; - var m = d.month + (12 * a) - 3; - var jDate = d.day - + Math.floor(((153 * m) + 2) / 5) - + (365 * y) - + Math.floor(y / 4) - - Math.floor(y / 100) - + Math.floor(y / 400) - - 32045; - - // Number of days since Jan 1st, 2000 12:00. - var n = jDate - 2451545.0d + 0.0008d; - //Sys.println("n " + n); - - // Mean solar noon. - var jStar = n - (lng / 360.0d); - //Sys.println("jStar " + jStar); - - // Solar mean anomaly. - var M = 357.5291d + (0.98560028d * jStar); - var MFloor = Math.floor(M); - var MFrac = M - MFloor; - M = MFloor.toLong() % 360; - M += MFrac; - //Sys.println("M " + M); - - // Equation of the centre. - var C = 1.9148d * Math.sin(M * rad) - + 0.02d * Math.sin(2 * M * rad) - + 0.0003d * Math.sin(3 * M * rad); - //Sys.println("C " + C); - - // Ecliptic longitude. - var lambda = (M + C + 180 + 102.9372d); - var lambdaFloor = Math.floor(lambda); - var lambdaFrac = lambda - lambdaFloor; - lambda = lambdaFloor.toLong() % 360; - lambda += lambdaFrac; - //Sys.println("lambda " + lambda); - - // Solar transit. - var jTransit = 2451545.5d + jStar - + 0.0053d * Math.sin(M * rad) - - 0.0069d * Math.sin(2 * lambda * rad); - //Sys.println("jTransit " + jTransit); - - // Declination of the sun. - var delta = Math.asin(Math.sin(lambda * rad) * Math.sin(23.44d * rad)); - //Sys.println("delta " + delta); - - // Hour angle. - var cosOmega = (Math.sin(-0.83d * rad) - Math.sin(lat * rad) * Math.sin(delta)) - / (Math.cos(lat * rad) * Math.cos(delta)); - //Sys.println("cosOmega " + cosOmega); - - // Sun never rises. - if (cosOmega > 1) { - return [null, -1]; - } - - // Sun never sets. - if (cosOmega < -1) { - return [-1, null]; - } - - // Calculate times from omega. - var omega = Math.acos(cosOmega) * deg; - var jSet = jTransit + (omega / 360.0); - var jRise = jTransit - (omega / 360.0); - var deltaJSet = jSet - jDate; - var deltaJRise = jRise - jDate; - - var tzOffset = (tz == null) ? (Sys.getClockTime().timeZoneOffset / 3600.0) : tz; - return [ - /* localRise */ (deltaJRise * 24) + tzOffset, - /* localSet */ (deltaJSet * 24) + tzOffset - ]; -} diff --git a/source/Global.mc b/source/Global.mc index cb8a1233..9cf8c0da 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -123,7 +123,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var suffix = ""; batteryLevel = teslaInfo.get("BatteryLevel"); - if (batteryLevel != null) { + if (batteryLevel != null && batteryLevel != 999) { var chargingState = teslaInfo.get("ChargingState"); if (httpErrorTesla == 401 || (!vehicleAsleep && httpErrorTesla == 408)) { // Can't get or token (will be shown in gray) or we got a 408 while not asleep (will be shown in the theme's color) suffix = "?"; @@ -151,7 +151,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { case 1: var sentryEnabled = teslaInfo.get("SentryEnabled"); - if (sentryEnabled != null) { + if (sentryEnabled != null && sentryEnabled instanceof Lang.Boolean) { value = (sentryEnabled ? "S on" : "S off"); } else { @@ -161,7 +161,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { case 2: var precondEnabled = teslaInfo.get("PrecondEnabled"); - if (precondEnabled != null) { + if (precondEnabled != null && precondEnabled instanceof Lang.Boolean) { value = (sentryEnabled ? "P on" : "P off"); } else { @@ -171,7 +171,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { case 3: var insideTemp = teslaInfo.get("InsideTemp"); - if (insideTemp != null) { + if (insideTemp != null && insideTemp != 999) { value = (Sys.getDeviceSettings().temperatureUnits == Sys.UNIT_METRIC ? insideTemp.toNumber() + "°C" : ((insideTemp.toNumber() * 9) / 5 + 32).format("%d") + "°F"); } else { @@ -436,6 +436,17 @@ function validateBoolean(value, defaultValue) { value = defaultValue; } } + else if (value instanceof Lang.String) { + if (value.equals("true")) { + value = true; + } + else if (value.equals("false")) { + value = false; + } + else { + value = defaultValue; + } + } else { value = defaultValue; } @@ -469,6 +480,26 @@ function to_array(string, splitter) { return result; } +function doTeslaComplication(complicationValue) { + /*DEBUG*/ logMessage("Complication read: " + complicationValue); + if (complicationValue instanceof Lang.String) { // Only handle the enhance data sent, not just the battery SoC (a Number) + var teslaInfo = Storage.getValue("TeslaInfo"); + if (teslaInfo == null){ + teslaInfo = {}; + } + var arrayInfo = $.to_array(complicationValue, "|"); + teslaInfo.put("httpErrorTesla", $.validateNumber(arrayInfo[0], 401)); // Defaults to need token + teslaInfo.put("BatteryLevel", $.validateNumber(arrayInfo[1], 999)); // 999 means in writeBatteryLevel that we didn't get any + teslaInfo.put("ChargingState", $.validateString(arrayInfo[2], "")); + teslaInfo.put("InsideTemp", $.validateNumber(arrayInfo[3], 999)); // 999 means in writeBatteryLevel that we didn't get any + teslaInfo.put("SentryEnabled", $.validateBoolean(arrayInfo[4], "")); // Yes, putting an empty string instead of a Boolean. The writeBatteryLevel will know it means I don't have one + teslaInfo.put("PrecondEnabled", $.validateBoolean(arrayInfo[5], "")); // Yes, putting an empty string instead of a Boolean. The writeBatteryLevel will know it means I don't have one + teslaInfo.put("VehicleState", $.validateString(arrayInfo[6], "")); + + Storage.setValue("TeslaInfo", teslaInfo); + } +} + (:debug, :background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index acfa10ae..8e54c949 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -48,6 +48,7 @@ class GoalMeter extends Ui.Drawable { private var mMaxValue; private var mIsOff = false; // #114 Should entire meter on this side be hidden? + private var mApp; private var mView; // private enum /* GOAL_METER_STYLES */ { @@ -113,8 +114,8 @@ class GoalMeter extends Ui.Drawable { } function onSettingsChanged(index) { - var app = App.getApp(); - mView = app.getView(); + mApp = App.getApp(); + mView = mApp.getView(); mBuffersNeedRecreate = true; @@ -140,14 +141,14 @@ class GoalMeter extends Ui.Drawable { mSeparator = 0; } - if (Toybox has :Complications && app.getView().useComplications()) { + if (Toybox has :Complications && mView.useComplications()) { var complications = [{"type" => GOAL_TYPE_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => GOAL_TYPE_FLOORS_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => GOAL_TYPE_STEPS, "complicationType" => Complications.COMPLICATION_TYPE_STEPS}, {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} ]; - var goalTypes = mView.mGoalTypes; + var goalTypes = mApp.mGoalTypes; var filled = false; for (var i = 0; i < complications.size(); i++) { diff --git a/source/Indicators.mc b/source/Indicators.mc index b3cbcaa9..d020fda4 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -22,6 +22,7 @@ class Indicators extends Ui.Drawable { // INDICATOR_TYPE_NOTIFICATIONS, // INDICATOR_TYPE_BLUETOOTH_OR_NOTIFICATIONS, // INDICATOR_TYPE_BATTERY + // INDICATOR_TYPE_TESLA // } function initialize(params) { @@ -47,6 +48,7 @@ class Indicators extends Ui.Drawable { //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** var teslaIndicator; + if (mIndicator1Type == 6) { teslaIndicator = 1; } From 62523b478213d88cda3c7e68c9124eb0547b5b99 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 9 May 2023 15:16:44 -0400 Subject: [PATCH 140/220] Starting implementing weather Complications --- source/CrystalApp.mc | 14 ++++++------ source/CrystalView.mc | 13 ++++++----- source/DataFields.mc | 51 +++++++++++++++++++++++++++++++------------ source/Global.mc | 7 +++++- 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 485573f6..7a12c80e 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -118,16 +118,16 @@ class CrystalApp extends App.AppBase { Bg.deleteTemporalEvent(); } - mView.onSettingsChanged(); // Calls checkPendingWebRequests(). - // Reread our complications if we're allowed if (Toybox has :Complications) { // First we drop all our subscriptions before building a new list Complications.unsubscribeFromAllUpdates(); // We listen for complications if we're allowed - Complications.registerComplicationChangeCallback(mView.useComplications() ? self.method(:onComplicationUpdated) : null); + Complications.registerComplicationChangeCallback($.getBoolProperty("UseComplications", false) ? self.method(:onComplicationUpdated) : null); } + mView.onSettingsChanged(); // Calls checkPendingWebRequests(). + Ui.requestUpdate(); } @@ -194,12 +194,12 @@ class CrystalApp extends App.AppBase { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); var complicationShortLabel = complication.shortLabel; - //DEBUG*/ var complicationLongLabel = complication.longLabel; + /*DEBUG*/ var complicationLongLabel = complication.longLabel; var complicationValue = complication.value; - //DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_STEPS) { - //DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); - //DEBUG*/ } + /*DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_CURRENT_WEATHER) { + /*DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); + /*DEBUG*/ } if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { $.doTeslaComplication(complicationValue); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 8c7f9e5e..83762100 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -208,16 +208,19 @@ class CrystalView extends Ui.WatchFace { logMessage("Since sunrize " + sinceSunrise); logMessage("Since sunset " + sinceSunset);*/ - if (condition < 53) { + if (condition != null && condition < 53) { icon = (mGarminToOWM[condition]).format("%02d") + day; //logMessage("icon=" + icon); } - result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon, "dt" => weather.observationTime.value() }; - //2022-04-10 logMessage("Weather at " + weather.observationLocationName + " is " + result); + else { + /*DEBUG*/ logMessage("Icon index " + condition + " is out of range"); + } + result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; + /*DEBUG*/ logMessage("Weather at " + mWeatherStationName + " is " + result); } else { - result = null; - //2022-04-10 logMessage("No weather data, returning null"); + result = { "cod" => 404 }; + /*DEBUG*/ logMessage("No weather data, returning cod = 404"); } Storage.setValue("WeatherInfo", result); Storage.setValue("NewWeatherInfo", true); diff --git a/source/DataFields.mc b/source/DataFields.mc index 272c9955..bcf4dade 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -112,7 +112,9 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS}, {"type" => FIELD_FLOOR_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => FIELD_TYPE_PULSE_OX, "complicationType" => Complications.COMPLICATION_TYPE_PULSE_OX}, - {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE} + {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE}, + {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_WEATHER} + {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_TEMPERATURE} ]; var fieldTypes = mApp.mFieldTypes; @@ -134,7 +136,23 @@ class DataFields extends Ui.Drawable { // Now delete any fields that doesn't have a Complication for (i = 1; i < 4; i++) { if (filled[i - 1] == false) { - Storage.deleteValue("Complication_F" + i); + var current = Storage.getValue("Complication_F" + i); + if (current != null && current instanceof Lang.Dictionary) { + var keys = current.keys(); + for (var j = 0; j < keys.size(); j++) { + current.remove(keys[i]); + } + if (current.isEmpty()) { + Storage.deleteValue("Complication_F" + i); + } + else { + Storage.setValue("Complication_F" + i, current); + } + + } + else { + Storage.deleteValue("Complication_F" + i); + } } } } @@ -436,7 +454,6 @@ class DataFields extends Ui.Drawable { var altitude; var pressure = null; // May never be initialised if no support for pressure (CIQ 1.x devices). var temperature; - var weatherValue; var sunTimes; var unit; var info; @@ -712,24 +729,30 @@ class DataFields extends Ui.Drawable { if (mWeather != null) { // FIELD_TYPE_WEATHER. if (type == FIELD_TYPE_WEATHER) { - weatherValue = mWeather["temp"]; // Celcius. - try { + value = $.validateNumber(mWeather["temp"], null); // Celcius. + if (value == null) { + value = "NaN"; + } + else { if (settings.temperatureUnits == System.UNIT_STATUTE) { - weatherValue = (weatherValue * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + value = (value * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. } - value = weatherValue.format(INTEGER_FORMAT) + ""; - } - catch (e) { - /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); - value = "NaN"; + value = value.format(INTEGER_FORMAT) + ""; } - result["weatherIcon"] = mWeather["icon"]; + + result["weatherIcon"] = $.validateString(mWeather["icon"], "01d"); // FIELD_TYPE_HUMIDITY. } else { - weatherValue = mWeather["humidity"]; - value = weatherValue.format(INTEGER_FORMAT) + "%"; + value = mWeather["humidity"]; + value = $.validateNumber(value, null); + if (value == null) { + value = "NaN"; + } + else { + value = value.format(INTEGER_FORMAT) + "%"; + } } if (mWeather["cod"] != 200 || !settings.phoneConnected) { diff --git a/source/Global.mc b/source/Global.mc index 9cf8c0da..c94b9676 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -223,7 +223,12 @@ function updateComplications(complicationName, storageName, index, complicationT complicationId = new Complications.Id(complicationType); } if (index != null) { - Storage.setValue(storageName + index, complicationId); + var current = Storage.getValue(storageName + index); + if (current == null || !(current instanceof Lang.Dictionary)) { + current = {}; + } + current.put(complicationType.toString(), true); + Storage.setValue(storageName + index, current); Complications.subscribeToUpdates(complicationId); } } From e830334bea1753272cf9e9efc99a5bd12a45c20a Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 9 May 2023 21:40:32 -0400 Subject: [PATCH 141/220] Weather, sunrise, recovery time addition and bug fix in weather Added Weather and Sunrise as touchpoints. Added RecoveryTime as Complication and touch point.Fixed a crash in weather when temperature is null --- source/CrystalApp.mc | 5 +++-- source/DataFields.mc | 32 ++++++++++++-------------------- source/Global.mc | 19 ++++++++++++------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 7a12c80e..5cd005f3 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -123,7 +123,8 @@ class CrystalApp extends App.AppBase { // First we drop all our subscriptions before building a new list Complications.unsubscribeFromAllUpdates(); // We listen for complications if we're allowed - Complications.registerComplicationChangeCallback($.getBoolProperty("UseComplications", false) ? self.method(:onComplicationUpdated) : null); +// Complications.registerComplicationChangeCallback($.getBoolProperty("UseComplications", false) ? self.method(:onComplicationUpdated) : null); + Complications.registerComplicationChangeCallback(self.method(:onComplicationUpdated)); } mView.onSettingsChanged(); // Calls checkPendingWebRequests(). @@ -197,7 +198,7 @@ class CrystalApp extends App.AppBase { /*DEBUG*/ var complicationLongLabel = complication.longLabel; var complicationValue = complication.value; - /*DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_CURRENT_WEATHER) { + /*DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_RECOVERY_TIME) { /*DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); /*DEBUG*/ } diff --git a/source/DataFields.mc b/source/DataFields.mc index bcf4dade..2234415f 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -113,8 +113,9 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_FLOOR_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => FIELD_TYPE_PULSE_OX, "complicationType" => Complications.COMPLICATION_TYPE_PULSE_OX}, {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE}, - {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_WEATHER} - {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_TEMPERATURE} + {"type" => FIELD_RECOVERY_TIME, "complicationType" => Complications.COMPLICATION_TYPE_RECOVERY_TIME}, + {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_WEATHER}, // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain + {"type" => FIELD_TYPE_SUNRISE_SUNSET, "complicationType" => Complications.COMPLICATION_TYPE_SUNRISE} // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain ]; var fieldTypes = mApp.mFieldTypes; @@ -136,23 +137,7 @@ class DataFields extends Ui.Drawable { // Now delete any fields that doesn't have a Complication for (i = 1; i < 4; i++) { if (filled[i - 1] == false) { - var current = Storage.getValue("Complication_F" + i); - if (current != null && current instanceof Lang.Dictionary) { - var keys = current.keys(); - for (var j = 0; j < keys.size(); j++) { - current.remove(keys[i]); - } - if (current.isEmpty()) { - Storage.deleteValue("Complication_F" + i); - } - else { - Storage.setValue("Complication_F" + i, current); - } - - } - else { - Storage.deleteValue("Complication_F" + i); - } + Storage.deleteValue("Complication_F" + i); } } } @@ -461,8 +446,15 @@ class DataFields extends Ui.Drawable { switch (type) { // SG Addition case FIELD_RECOVERY_TIME: + if (Toybox has :Complications && mView.useComplications()) { + var fieldTypes = mApp.mFieldTypes; + var tmpValue = fieldTypes[index].get("ComplicationValue"); + if (tmpValue != null) { + value = secondsToTimeString(tmpValue); + } + } info = ActivityMonitor.getInfo(); - if (info has :timeToRecovery) { + if (value.equals("") == true && (info has :timeToRecovery)) { var recoveryTyime = info.timeToRecovery; if (recoveryTyime != null) { value = recoveryTyime.format(INTEGER_FORMAT); diff --git a/source/Global.mc b/source/Global.mc index c94b9676..2d83eac6 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -223,13 +223,7 @@ function updateComplications(complicationName, storageName, index, complicationT complicationId = new Complications.Id(complicationType); } if (index != null) { - var current = Storage.getValue(storageName + index); - if (current == null || !(current instanceof Lang.Dictionary)) { - current = {}; - } - current.put(complicationType.toString(), true); - Storage.setValue(storageName + index, current); - Complications.subscribeToUpdates(complicationId); + Storage.setValue(storageName + index, complicationId); } } } @@ -273,6 +267,17 @@ function getFormattedTime(hour, min) { }; } +function secondsToTimeString(totalSeconds) { + var hours = (totalSeconds / 3600).toNumber(); + var minutes = ((totalSeconds - hours * 3600) / 60).toNumber(); + var seconds = totalSeconds - hours * 3600 - minutes * 60; + if (seconds != 0) { + minutes++; + } + var timeString = Lang.format("$1$:$2$", [hours.format("%d"), minutes.format("%02d") ]); + return timeString; +} + (:background) function getIntProperty(key, defaultValue) { var value; From ab723801a0b41719f2bb13c5936fb48cb4707c2d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 9 May 2023 22:45:04 -0400 Subject: [PATCH 142/220] Moved Weather calculation to onExitSleep for efficiency and fixed bug in updateComplications --- README.md | 17 +++++++----- source/CrystalApp.mc | 11 ++++---- source/CrystalView.mc | 63 ++++++++++++++++++++++++------------------- source/DataFields.mc | 31 +++------------------ source/Global.mc | 2 ++ 5 files changed, 57 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 1efc6a9c..7c31d1d5 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,12 @@ A crystal clear watch face, with LCD-like goal meter segments, written while sno Features (depending on watch support): - Big time digits right in the middle, with hours in bold. Leading zero and seconds can be hidden. Hours and minutes colours can be set independently. -- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). THE FOLLOWING ADDED By SylvainGa: Garmin Weather, Recovery Time Left, Body Battery, Solar Intensity, Floors climbed and Pulse Ox. -- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery, THE FOLLOWING ADDED By SylvainGa: Do Not Disturb and Tesla batterie level/status. -- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal), THE FOLLOWING ADDED By SylvainGa: Body Battery. The meters have auto-scaling segments and current/target value display. +- Up to 3 customisable data fields: HR (historical/live), battery, notifications, calories, distance, alarms, altitude, thermometer, sunrise/sunset, weather (OpenWeatherMap). THE FOLLOWING ADDED by SylvainGa: Garmin Weather, Recovery Time Left, Body Battery, Solar Intensity, Floors climbed and Pulse Ox. +- Up to 3 customisable indicators: Bluetooth, alarms, notifications, Bluetooth/notifications, battery, THE FOLLOWING ADDED by SylvainGa: Do Not Disturb and Tesla batterie level/status. +- 2 customisable meters: steps, floors climbed, active minutes (weekly), battery, calories (custom goal), THE FOLLOWING ADDED by SylvainGa: Body Battery. The meters have auto-scaling segments and current/target value display. - Move bar. -- 12 colour themes, THE FOLLOWING ADDED By SylvainGa: Customizable themes. +- 12 colour themes, THE FOLLOWING ADDED by SylvainGa: Customizable themes. +- Complications and touch points added by SylvainGa The techie bit: to save your watch battery, the goal meters and move bar are drawn from a palette-restricted back buffer, for improved drawing performance, with minimal memory penalty. @@ -30,9 +31,11 @@ Reviews: ### 2.18.0 - Removed Watch model that are not at least at CIQ 3.3.0. This is required for the new Sunrise/Sunset and Weather library by Garmin. From the stats Garmin shows me about the watch face, none of them had downloaded the watch face anyway. - Removed the OpenWeatherMap and rely solely on Garmin Weather. The OWN and GPS was giving too much problem. -- The area on the screen allocated for alternate TimeZone will display the current weather station name if no alternate TimeZone was entered. -- The "Local time in City" (ie, alternate TimeZone) has been redone, much simplier, doesn't require Background process anymore but will need some work on your side. The field in the setting is now a Comma Separated Value (CSV) with the first value being the city name, second the latitude of the city and third its longitude. The last two in decimal notation (with a period, not comma). You will have to enter these, which are easy to find in Google Map anyway. No type checking done, beside making sure the latitude and logitude are numbers. If invalid, '???' will be shown for the time. -- Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla data instead of querying Tesla's servers. No more Token handling if using Complications and Tesla-Link. +- Added Recovery Time as Complications and Touch points. +- Added Weather and Sunrise data fields as touch point (but not read from Complications) +- The area on the screen allocated for "Local time in City" will display the current weather station name if no city was entered. +- The "Local time in City" has been redone, much simplier, doesn't require Background process anymore but will need some work on your side. The field in the setting is now a Comma Separated Value (CSV) with the first value being the city name, second the latitude of the city and third its longitude. The last two in decimal notation (with a period, not comma). You will have to enter these, which are easy to find in Google Map anyway. No type checking done, beside making sure the latitude and longitude are numbers. If invalid, '???' will be shown for the time. +- Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla data instead of querying Tesla's servers internally. No more Token handling if using Complications and Tesla-Link. ### 2.17.4 - One more attempt at fixing the crash because of the Settings change since 2.17.1 diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 5cd005f3..abdf9a12 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -123,8 +123,7 @@ class CrystalApp extends App.AppBase { // First we drop all our subscriptions before building a new list Complications.unsubscribeFromAllUpdates(); // We listen for complications if we're allowed -// Complications.registerComplicationChangeCallback($.getBoolProperty("UseComplications", false) ? self.method(:onComplicationUpdated) : null); - Complications.registerComplicationChangeCallback(self.method(:onComplicationUpdated)); + Complications.registerComplicationChangeCallback($.getBoolProperty("UseComplications", false) ? self.method(:onComplicationUpdated) : null); } mView.onSettingsChanged(); // Calls checkPendingWebRequests(). @@ -195,12 +194,12 @@ class CrystalApp extends App.AppBase { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); var complicationShortLabel = complication.shortLabel; - /*DEBUG*/ var complicationLongLabel = complication.longLabel; + //DEBUG*/ var complicationLongLabel = complication.longLabel; var complicationValue = complication.value; - /*DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_RECOVERY_TIME) { - /*DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); - /*DEBUG*/ } + //DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_RECOVERY_TIME) { + //DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); + //DEBUG*/ } if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { $.doTeslaComplication(complicationValue); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 83762100..3d710411 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -177,43 +177,52 @@ class CrystalView extends Ui.WatchFace { } var result; if (weather != null) { - var temperature = weather.temperature; - var humidity = weather.relativeHumidity; - var condition = weather.condition; + var temperature = $.validateNumber(weather.temperature, null); // In Celcius + if (temperature == null) { + temperature = "NaN"; + } + else { + if (Sys.getDeviceSettings().temperatureUnits == System.UNIT_STATUTE) { + temperature = (temperature * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + } + + temperature = temperature.format(INTEGER_FORMAT) + "°"; + } + + var humidity = $.validateNumber(weather.relativeHumidity, null); + if (humidity == null) { + humidity = "NaN"; + } + else { + humidity = humidity.format(INTEGER_FORMAT) + "%"; + } + + mWeatherStationName = $.validateString(weather.observationLocationName, null); + var icon = "01"; var day = "d"; - - mWeatherStationName = weather.observationLocationName; var myLocation = weather.observationLocationPosition; - - var now = Time.now(); - var sunrise = Weather.getSunrise(myLocation, now); - var sunset = Weather.getSunset(myLocation, now); - - var sinceSunrise = sunrise.compare(now); - var sinceSunset = now.compare(sunset); - if (sinceSunrise >= 0 || sinceSunset >= 0) { - day = "n"; + if (myLocation != null) { + var now = Time.now(); + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); + + if (sunrise != null and sunset != null) { + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); + if (sinceSunrise >= 0 || sinceSunset >= 0) { + day = "n"; + } + } } - /*var nowtime = Gregorian.info(now, Time.FORMAT_MEDIUM); - var nowStr = nowtime.day + " " + nowtime.hour + ":" + nowtime.min.format("%02d") + ":" + nowtime.sec.format("%02d"); - var sunrisetime = Gregorian.info(sunrise, Time.FORMAT_MEDIUM); - var sunsettime = Gregorian.info(sunset, Time.FORMAT_MEDIUM); - var sunriseStr = sunrisetime.day + " " + sunrisetime.hour + ":" + sunrisetime.min.format("%02d") + ":" + sunrisetime.sec.format("%02d"); - var sunsetStr = sunsettime.day + " " + sunsettime.hour + ":" + sunsettime.min.format("%02d") + ":" + sunsettime.sec.format("%02d"); - logMessage("For=" + nowStr); - logMessage("Sunrise=" + sunriseStr); - logMessage("Sunset=" + sunsetStr); - logMessage("Since sunrize " + sinceSunrise); - logMessage("Since sunset " + sinceSunset);*/ - + var condition = $.validateNumber(weather.condition, null); if (condition != null && condition < 53) { icon = (mGarminToOWM[condition]).format("%02d") + day; //logMessage("icon=" + icon); } else { - /*DEBUG*/ logMessage("Icon index " + condition + " is out of range"); + /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; /*DEBUG*/ logMessage("Weather at " + mWeatherStationName + " is " + result); diff --git a/source/DataFields.mc b/source/DataFields.mc index 2234415f..3f66afe7 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -718,41 +718,18 @@ class DataFields extends Ui.Drawable { } // Stored weather data available. - if (mWeather != null) { + if (mWeather != null && mWeather instanceof Lang.Dictionary && mWeather["cod"] == 200) { // FIELD_TYPE_WEATHER. if (type == FIELD_TYPE_WEATHER) { - value = $.validateNumber(mWeather["temp"], null); // Celcius. - if (value == null) { - value = "NaN"; - } - else { - if (settings.temperatureUnits == System.UNIT_STATUTE) { - value = (value * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. - } - - value = value.format(INTEGER_FORMAT) + ""; - } - - result["weatherIcon"] = $.validateString(mWeather["icon"], "01d"); + value = mWeather["temp"]; + result["weatherIcon"] = mWeather["icon"]; // FIELD_TYPE_HUMIDITY. } else { value = mWeather["humidity"]; - value = $.validateNumber(value, null); - if (value == null) { - value = "NaN"; - } - else { - value = value.format(INTEGER_FORMAT) + "%"; - } } - - if (mWeather["cod"] != 200 || !settings.phoneConnected) { - stale = true; - } - - // Awaiting response. } + // Didn't receive weather from Garmin else { value = "???"; diff --git a/source/Global.mc b/source/Global.mc index 2d83eac6..e368c2d1 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -222,8 +222,10 @@ function updateComplications(complicationName, storageName, index, complicationT else { complicationId = new Complications.Id(complicationType); } + if (index != null) { Storage.setValue(storageName + index, complicationId); + Complications.subscribeToUpdates(complicationId); } } } From c06e0e27695ece793612fb5f57cbde99aec0f3bb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 10 May 2023 21:31:56 -0400 Subject: [PATCH 143/220] RecoveryTime from complication is in minutes, not second, and Tesla handling for 'offline' --- source/DataFields.mc | 2 +- source/Global.mc | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/source/DataFields.mc b/source/DataFields.mc index 3f66afe7..e97f7862 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -450,7 +450,7 @@ class DataFields extends Ui.Drawable { var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { - value = secondsToTimeString(tmpValue); + value = $.MinutesToTimeString(tmpValue); } } info = ActivityMonitor.getInfo(); diff --git a/source/Global.mc b/source/Global.mc index e368c2d1..3b16e1a2 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -110,11 +110,11 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (httpErrorTesla == 401) { // No access token, only show the battery (in gray, default above) showMode = 0; } - else if (vehicleAsleep || httpErrorTesla == 200) { // Vehicle confirmed asleep (even if we got a 408, we'll add a "?" after the battery level to show this) or we got valid data + else if (vehicleAsleep || httpErrorTesla == 200) { // Vehicle confirmed asleep (even if we got a 408, we'll add a "?" after the battery level to show this) or we got valid data. If the vehicle is offline, the line will show gray for stale data textColour = gThemeColour; // Defaults to theme's color } - if (vehicleAsleep) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) + if (vehicleAsleep || (vehicleState != null && vehicleState.equals("offline") == true)) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) showMode &= 2; } @@ -269,13 +269,9 @@ function getFormattedTime(hour, min) { }; } -function secondsToTimeString(totalSeconds) { - var hours = (totalSeconds / 3600).toNumber(); - var minutes = ((totalSeconds - hours * 3600) / 60).toNumber(); - var seconds = totalSeconds - hours * 3600 - minutes * 60; - if (seconds != 0) { - minutes++; - } +function MinutesToTimeString(totalMinutes) { + var hours = (totalMinutes / 60).toNumber(); + var minutes = (totalMinutes - (hours * 60)).toNumber(); var timeString = Lang.format("$1$:$2$", [hours.format("%d"), minutes.format("%02d") ]); return timeString; } From 0c6defc34558b7d85669f72e76324fb428db8eac Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 10 May 2023 22:51:20 -0400 Subject: [PATCH 144/220] Bug fix in TeslaVehicleIndex and added that property --- README.md | 2 +- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/settings/properties.xml | 2 +- resources/settings/settings.xml | 4 +++ resources/strings/strings.xml | 2 ++ source/BackgroundService.mc | 2 +- source/CrystalApp.mc | 44 +++++++++++++------------------ 26 files changed, 48 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7c31d1d5..5a0a1aae 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Reviews: - Added Weather and Sunrise data fields as touch point (but not read from Complications) - The area on the screen allocated for "Local time in City" will display the current weather station name if no city was entered. - The "Local time in City" has been redone, much simplier, doesn't require Background process anymore but will need some work on your side. The field in the setting is now a Comma Separated Value (CSV) with the first value being the city name, second the latitude of the city and third its longitude. The last two in decimal notation (with a period, not comma). You will have to enter these, which are easy to find in Google Map anyway. No type checking done, beside making sure the latitude and longitude are numbers. If invalid, '???' will be shown for the time. -- Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla data instead of querying Tesla's servers internally. No more Token handling if using Complications and Tesla-Link. +- Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla data instead of querying Tesla's servers internally. No more Token handling if using Complications and Tesla-Link. Because of the size of the data returned when the vehicle is awake, a watch with just 32KB of background space will not be able to show that data and will show error -403 instead (network response out of memory). If it's your case and your watch support Complication, check the Tesla-Link checkbox in the Settings and install the Tesla-Link widget/app. That one has just enough room to download the data and will send it to Crystal-Tesla if asked to send Complication to it. ### 2.17.4 - One more attempt at fixing the crash because of the Settings change since 2.17.1 diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 91352d4f..29e0cf33 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index f3abeb67..ec512529 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 12283212..63baa61c 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 1656d90d..0fea4d20 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 6b7b3666..d5fed67b 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index b02a88f0..69e04d38 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -122,4 +122,5 @@ Niveau de stress Utilisez les complications, si disponible Utilisez les Complications de Tesla-Link pour l'info Tesla + Quel véhicle afficher? diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index d7271b54..4a383afd 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 527d445d..7d2bbdac 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 96f38c87..63d95ea4 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 336f649f..8fad383f 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 1977139f..d40887eb 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 5c93bbdf..dfacdb2a 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 26da765d..44e27e82 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index ab082a08..04a85b05 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 411f0892..ad97e168 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 211fd59c..855e0dbe 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index a358c13d..3f1d43ba 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index d907eb18..d7b9bdf3 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 3be28473..9e266c0e 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 87a0624d..5195171f 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -123,4 +123,5 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index f1a9dbd1..eedac8f8 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -34,7 +34,7 @@ 0 false - + 1 owner-api.teslamotors.com diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 0323c1df..222a6c7b 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -252,6 +252,10 @@ + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index a34afc82..b017cd3b 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -122,4 +122,6 @@ Stress Level Use Complications if available Get Tesla info from Tesla-Link Complications + Which vehicle to show? + diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index b2d57594..7885bf90 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -153,7 +153,7 @@ class BackgroundService extends Sys.ServiceDelegate { if (vehicles != null) { var storVehicleIndex = Storage.getValue("TeslaVehicleIndex"); if (storVehicleIndex == null || storVehicleIndex < 1) { - storVehicleIndex = 0; + storVehicleIndex = 0; // Base 0 so 0, not 1 } else { storVehicleIndex--; // Array are zero based but we want user to start numbering from 1 for ease of use diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index abdf9a12..3ba8a0ea 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -32,31 +32,6 @@ class CrystalApp extends App.AppBase { mGoalTypes[0] = {}; mGoalTypes[1] = {}; - - gTeslaComplication = getBoolProperty("TeslaLink", false); - - // This code check if the user selected a different vehicle index in its property. If so, we'll need to get a new vehicleID - var propVehicleIndex; - var storVehicleIndex; - - try { - propVehicleIndex = Properties.getValue("TeslaVehicleIndex"); - } - catch (e) { - propVehicleIndex = 1; - } - - storVehicleIndex = Storage.getValue("TeslaVehiceIndex"); - if (storVehicleIndex == null || propVehicleIndex != storVehicleIndex) { - storVehicleIndex = propVehicleIndex; - try { - Storage.setValue("TeslaVehiceIndex", storVehicleIndex); - Storage.setValue("TeslaVehiceIndex", storVehicleIndex); - Storage.setValue("TeslaVehicleID", null); - } - catch (e) { - } - } } // function onStart(state) { @@ -103,6 +78,25 @@ class CrystalApp extends App.AppBase { mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + gTeslaComplication = $.getBoolProperty("TeslaLink", false); + + // This code check if the user selected a different vehicle index in its property. If so, we'll need to get a new vehicleID + var propVehicleIndex; + var storVehicleIndex; + + propVehicleIndex = $.getIntProperty("TeslaVehicleIndex", 1); + + storVehicleIndex = Storage.getValue("TeslaVehicleIndex"); + if (storVehicleIndex == null || propVehicleIndex != storVehicleIndex) { + storVehicleIndex = propVehicleIndex; + try { + Storage.setValue("TeslaVehicleIndex", storVehicleIndex); + Storage.setValue("TeslaVehicleID", null); + } + catch (e) { + } + } + // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { var lastTime = Bg.getLastTemporalEventTime(); From d36f36b457b9fdb68e582eb3e46393398bfe84b8 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 10 May 2023 22:54:22 -0400 Subject: [PATCH 145/220] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5a0a1aae..cff03344 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Reviews: - The area on the screen allocated for "Local time in City" will display the current weather station name if no city was entered. - The "Local time in City" has been redone, much simplier, doesn't require Background process anymore but will need some work on your side. The field in the setting is now a Comma Separated Value (CSV) with the first value being the city name, second the latitude of the city and third its longitude. The last two in decimal notation (with a period, not comma). You will have to enter these, which are easy to find in Google Map anyway. No type checking done, beside making sure the latitude and longitude are numbers. If invalid, '???' will be shown for the time. - Redid the Tesla code and added the reading of the Tesla-Link Complications to get Tesla data instead of querying Tesla's servers internally. No more Token handling if using Complications and Tesla-Link. Because of the size of the data returned when the vehicle is awake, a watch with just 32KB of background space will not be able to show that data and will show error -403 instead (network response out of memory). If it's your case and your watch support Complication, check the Tesla-Link checkbox in the Settings and install the Tesla-Link widget/app. That one has just enough room to download the data and will send it to Crystal-Tesla if asked to send Complication to it. +- Added a Setting to select which Tesla vehicle to show. Defaults to 1. If you have more than one vehicle, use this field to select which vehicle to show. If Tesla data is read from Tesla-Link Complication, it's that one that will dictate which vehicle will appear on the watch face. The Settings here will be ignored, just like the tokens. Give it up to 5 minutes to update its data. ### 2.17.4 - One more attempt at fixing the crash because of the Settings change since 2.17.1 From 7f4028152587a9bf4aea5e12fd5ca760a42cba06 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 11 May 2023 00:00:02 -0400 Subject: [PATCH 146/220] New code for offline vehicle --- source/Global.mc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/Global.mc b/source/Global.mc index 3b16e1a2..eb8323d8 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -104,6 +104,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var httpErrorTesla = teslaInfo.get("httpErrorTesla"); var vehicleState = teslaInfo.get("VehicleState"); var vehicleAsleep = (vehicleState != null && vehicleState.equals("asleep") == true); + var vehicleOffline = (vehicleState != null && vehicleState.equals("offline") == true); // Only specific error are handled, the others are displayed 'as is' in pink if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { @@ -114,7 +115,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { textColour = gThemeColour; // Defaults to theme's color } - if (vehicleAsleep || (vehicleState != null && vehicleState.equals("offline") == true)) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) + if (vehicleAsleep || vehicleOffline) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) showMode &= 2; } @@ -125,7 +126,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { batteryLevel = teslaInfo.get("BatteryLevel"); if (batteryLevel != null && batteryLevel != 999) { var chargingState = teslaInfo.get("ChargingState"); - if (httpErrorTesla == 401 || (!vehicleAsleep && httpErrorTesla == 408)) { // Can't get or token (will be shown in gray) or we got a 408 while not asleep (will be shown in the theme's color) + if (httpErrorTesla == 401 || (!vehicleAsleep && !vehicleOffline && httpErrorTesla == 408)) { // Can't get or token (will be shown in gray) or we got a 408 while not asleep (will be shown in the theme's color) suffix = "?"; } else if (vehicleAsleep) { From 276f2155b8f68831571dda683fb69942ad2be507 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 11 May 2023 11:38:15 -0400 Subject: [PATCH 147/220] Tweaking what shows up when an error is received --- source/Global.mc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/Global.mc b/source/Global.mc index eb8323d8..e6c343b6 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -104,10 +104,14 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var httpErrorTesla = teslaInfo.get("httpErrorTesla"); var vehicleState = teslaInfo.get("VehicleState"); var vehicleAsleep = (vehicleState != null && vehicleState.equals("asleep") == true); - var vehicleOffline = (vehicleState != null && vehicleState.equals("offline") == true); + var vehicleOnline = (vehicleState != null && vehicleState.equals("online") == true); // Only specific error are handled, the others are displayed 'as is' in pink if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { + if (!vehicleOnline) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) + showMode &= 2; + } + if (httpErrorTesla == 401) { // No access token, only show the battery (in gray, default above) showMode = 0; } @@ -115,10 +119,6 @@ function writeBatteryLevel(dc, x, y, width, height, type) { textColour = gThemeColour; // Defaults to theme's color } - if (vehicleAsleep || vehicleOffline) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) - showMode &= 2; - } - switch (showMode) { case 0: var suffix = ""; @@ -126,7 +126,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { batteryLevel = teslaInfo.get("BatteryLevel"); if (batteryLevel != null && batteryLevel != 999) { var chargingState = teslaInfo.get("ChargingState"); - if (httpErrorTesla == 401 || (!vehicleAsleep && !vehicleOffline && httpErrorTesla == 408)) { // Can't get or token (will be shown in gray) or we got a 408 while not asleep (will be shown in the theme's color) + if (httpErrorTesla != 200 && httpErrorTesla != 408) { // ResponseCode other than 200 and 408 will show a "?" beside thr battery level suffix = "?"; } else if (vehicleAsleep) { From f14a317042edfcbc0b3a017c424ad0be87b66d0c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 11 May 2023 22:45:08 -0400 Subject: [PATCH 148/220] Done --- source/CrystalApp.mc | 89 --------------------------- source/CrystalView.mc | 140 +++++++++++++++++++++++++++--------------- source/DataFields.mc | 28 ++------- source/Global.mc | 44 ++++++++++++- source/GoalMeter.mc | 2 +- 5 files changed, 141 insertions(+), 162 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 3ba8a0ea..f6f319e4 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -18,20 +18,8 @@ var gTeslaComplication = false; class CrystalApp extends App.AppBase { var mView; - var mFieldTypes = new [3]; - var mGoalTypes = new [2]; - - private var mUseComplications; - function initialize() { AppBase.initialize(); - - mFieldTypes[0] = {}; - mFieldTypes[1] = {}; - mFieldTypes[2] = {}; - - mGoalTypes[0] = {}; - mGoalTypes[1] = {}; } // function onStart(state) { @@ -71,15 +59,6 @@ class CrystalApp extends App.AppBase { } function onSettingsChanged() { - mFieldTypes[0].put("type", $.getIntProperty("Field1Type", 0)); - mFieldTypes[1].put("type", $.getIntProperty("Field2Type", 1)); - mFieldTypes[2].put("type", $.getIntProperty("Field3Type", 2)); - - mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); - mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); - - gTeslaComplication = $.getBoolProperty("TeslaLink", false); - // This code check if the user selected a different vehicle index in its property. If so, we'll need to get a new vehicleID var propVehicleIndex; var storVehicleIndex; @@ -97,29 +76,6 @@ class CrystalApp extends App.AppBase { } } - // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events - if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { - var lastTime = Bg.getLastTemporalEventTime(); - if (lastTime) { - // Events scheduled for a time in the past trigger immediately. - var nextTime = lastTime.add(new Time.Duration(5 * 60)); - Bg.registerForTemporalEvent(nextTime); - } else { - Bg.registerForTemporalEvent(Time.now()); - } - } - else { - Bg.deleteTemporalEvent(); - } - - // Reread our complications if we're allowed - if (Toybox has :Complications) { - // First we drop all our subscriptions before building a new list - Complications.unsubscribeFromAllUpdates(); - // We listen for complications if we're allowed - Complications.registerComplicationChangeCallback($.getBoolProperty("UseComplications", false) ? self.method(:onComplicationUpdated) : null); - } - mView.onSettingsChanged(); // Calls checkPendingWebRequests(). Ui.requestUpdate(); @@ -177,49 +133,4 @@ class CrystalApp extends App.AppBase { Ui.requestUpdate(); } - - function hasField(fieldType) { - return ((mFieldTypes[0].get("type") == fieldType) || - (mFieldTypes[1].get("type") == fieldType) || - (mFieldTypes[2].get("type") == fieldType)); - } - - function onComplicationUpdated(complicationId) { - var complication = Complications.getComplication(complicationId); - var complicationType = complication.getType(); - var complicationShortLabel = complication.shortLabel; - //DEBUG*/ var complicationLongLabel = complication.longLabel; - var complicationValue = complication.value; - - //DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_RECOVERY_TIME) { - //DEBUG*/ logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); - //DEBUG*/ } - - if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { - $.doTeslaComplication(complicationValue); - } - - // I've seen this while in low power mode, so skip it - if (complicationValue == null) { - //DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); - return; - } - - // Do fields first - var fieldCount = $.getIntProperty("FieldCount", 3); - - for (var i = 0; i < fieldCount; i++) { - if (mFieldTypes[i].get("ComplicationType") == complicationType) { - mFieldTypes[i].put("ComplicationValue", complicationValue); - } - } - - // Now do goals - if (mGoalTypes[0].get("ComplicationType") == complicationType) { - mGoalTypes[0].put("ComplicationValue", complicationValue); - } - if (mGoalTypes[1].get("ComplicationType") == complicationType) { - mGoalTypes[1].put("ComplicationValue", complicationValue); - } - } } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 3d710411..763e84f6 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -1,4 +1,5 @@ using Toybox.WatchUi as Ui; +using Toybox.Background as Bg; using Toybox.Graphics as Graphics; using Toybox.System as Sys; using Toybox.Application as App; @@ -52,8 +53,13 @@ class CrystalView extends Ui.WatchFace { private var mSettingsChangedSinceLastDraw = true; // Have settings changed since last full update? private var mTime; var mDataFields; + + var mFieldTypes = new [3]; + var mGoalTypes = new [2]; + // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; + var mWeatherStationName; var mLocalCityName; var mLocalCityLat; @@ -91,6 +97,14 @@ class CrystalView extends Ui.WatchFace { function initialize() { WatchFace.initialize(); + gNormalFont = Ui.loadResource(Rez.Fonts.NormalFontCities); + + mFieldTypes[0] = {}; + mFieldTypes[1] = {}; + mFieldTypes[2] = {}; + + mGoalTypes[0] = {}; + mGoalTypes[1] = {}; } function burnInProtectionIsOrWasActive() { @@ -141,7 +155,12 @@ class CrystalView extends Ui.WatchFace { mSettingsChangedSinceLastDraw = true; //logMessage("onSettingsChanged called"); - gNormalFont = Ui.loadResource(Rez.Fonts.NormalFontCities); + mFieldTypes[0].put("type", $.getIntProperty("Field1Type", 0)); + mFieldTypes[1].put("type", $.getIntProperty("Field2Type", 1)); + mFieldTypes[2].put("type", $.getIntProperty("Field3Type", 2)); + + mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); + mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); // Themes: explicitly set *Colour properties that have no corresponding (user-facing) setting. updateThemeColours(); @@ -165,6 +184,31 @@ class CrystalView extends Ui.WatchFace { // Reread our complications if we're allowed mUseComplications = $.getBoolProperty("UseComplications", false); + gTeslaComplication = $.getBoolProperty("TeslaLink", false); + + + // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events + if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { + var lastTime = Bg.getLastTemporalEventTime(); + if (lastTime) { + // Events scheduled for a time in the past trigger immediately. + var nextTime = lastTime.add(new Time.Duration(5 * 60)); + Bg.registerForTemporalEvent(nextTime); + } else { + Bg.registerForTemporalEvent(Time.now()); + } + } + else { + Bg.deleteTemporalEvent(); + } + + // Reread our complications if we're allowed + if (Toybox has :Complications) { + // First we drop all our subscriptions before building a new list + Complications.unsubscribeFromAllUpdates(); + // We listen for complications if we're allowed + Complications.registerComplicationChangeCallback($.getBoolProperty("UseComplications", false) ? self.method(:onComplicationUpdated) : null); + } } // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see @@ -406,15 +450,13 @@ class CrystalView extends Ui.WatchFace { :staled => false }; - var app = App.getApp(); - var goalTypes = app.mGoalTypes; var info = ActivityMonitor.getInfo(); switch(type) { case GOAL_TYPE_STEPS: values[:isValid] = false; if (Toybox has :Complications && mUseComplications) { - var tmpValue = goalTypes[index].get("ComplicationValue"); + var tmpValue = mGoalTypes[index].get("ComplicationValue"); if (tmpValue != null) { // For some stupid reason, above 10K, it becomes a float and divided by 1000, so 15,500 becomes 15.500. WTF? if (tmpValue instanceof Lang.Float) { @@ -434,7 +476,7 @@ class CrystalView extends Ui.WatchFace { case GOAL_TYPE_FLOORS_CLIMBED: values[:isValid] = false; if (Toybox has :Complications && mUseComplications) { - var tmpValue = goalTypes[index].get("ComplicationValue"); + var tmpValue = mGoalTypes[index].get("ComplicationValue"); if (tmpValue != null) { values[:current] = tmpValue.toNumber(); values[:isValid] = true; @@ -472,7 +514,7 @@ class CrystalView extends Ui.WatchFace { values[:max] = 100; if (Toybox has :Complications && mUseComplications) { - var tmpValue = goalTypes[index].get("ComplicationValue"); + var tmpValue = mGoalTypes[index].get("ComplicationValue"); if (tmpValue != null) { values[:current] = tmpValue.toFloat(); values[:isValid] = true; @@ -500,7 +542,7 @@ class CrystalView extends Ui.WatchFace { values[:max] = 100; if (Toybox has :Complications && mUseComplications) { - var tmpValue = goalTypes[index].get("ComplicationValue"); + var tmpValue = mGoalTypes[index].get("ComplicationValue"); if (tmpValue != null) { values[:current] = tmpValue.toFloat(); values[:isValid] = true; @@ -656,6 +698,48 @@ class CrystalView extends Ui.WatchFace { mTime.setHideSeconds(hideSeconds); mDrawables[:MoveBar].setFullWidth(hideSeconds); } + + function onComplicationUpdated(complicationId) { + var complication = Complications.getComplication(complicationId); + var complicationType = complication.getType(); + var complicationShortLabel = complication.shortLabel; + var complicationValue = complication.value; + + //DEBUG*/ var complicationLongLabel = complication.longLabel; if (complicationType == Complications.COMPLICATION_TYPE_RECOVERY_TIME) { logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); } + + if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { + $.doTeslaComplication(complicationValue); + } + + // I've seen this while in low power mode, so skip it + if (complicationValue == null) { + //DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); + return; + } + + // Do fields first + var fieldCount = $.getIntProperty("FieldCount", 3); + + for (var i = 0; i < fieldCount; i++) { + if (mFieldTypes[i].get("ComplicationType") == complicationType) { + mFieldTypes[i].put("ComplicationValue", complicationValue); + } + } + + // Now do goals + if (mGoalTypes[0].get("ComplicationType") == complicationType) { + mGoalTypes[0].put("ComplicationValue", complicationValue); + } + if (mGoalTypes[1].get("ComplicationType") == complicationType) { + mGoalTypes[1].put("ComplicationValue", complicationValue); + } + } + + function hasField(fieldType) { + return ((mFieldTypes[0].get("type") == fieldType) || + (mFieldTypes[1].get("type") == fieldType) || + (mFieldTypes[2].get("type") == fieldType)); + } } class CrystalDelegate extends Ui.WatchFaceDelegate { @@ -798,45 +882,3 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { //mview.turnPartialUpdatesOff(); } } - -/* -function type_name(obj) { - if (obj instanceof Toybox.Lang.Number) { - return "Number"; - } else if (obj instanceof Toybox.Lang.Long) { - return "Long"; - } else if (obj instanceof Toybox.Lang.Float) { - return "Float"; - } else if (obj instanceof Toybox.Lang.Double) { - return "Double"; - } else if (obj instanceof Toybox.Lang.Boolean) { - return "Boolean"; - } else if (obj instanceof Toybox.Lang.String) { - return "String"; - } else if (obj instanceof Toybox.Lang.Array) { - var s = "Array ["; - for (var i = 0; i < obj.size(); ++i) { - s += type_name(obj); - s += ", "; - } - s += "]"; - return s; - } else if (obj instanceof Toybox.Lang.Dictionary) { - var s = "Dictionary{"; - var keys = obj.keys(); - var vals = obj.values(); - for (var i = 0; i < keys.size(); ++i) { - s += keys; - s += ": "; - s += vals; - s += ", "; - } - s += "}"; - return s; - } else if (obj instanceof Toybox.Time.Gregorian.Info) { - return "Gregorian.Info"; - } else { - return "???"; - } -} -*/ \ No newline at end of file diff --git a/source/DataFields.mc b/source/DataFields.mc index e97f7862..b15f13ef 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -85,24 +85,12 @@ class DataFields extends Ui.Drawable { // #123 Protect against null or unexpected type e.g. String. mFieldCount = $.getIntProperty("FieldCount", 3); - /* switch (mFieldCount) { - case 3: - mMaxFieldLength = 4; - break; - case 2: - mMaxFieldLength = 6; - break; - case 1: - mMaxFieldLength = 8; - break; - } */ - // #116 Handle FieldCount = 0 correctly. mMaxFieldLength = [0, 8, 6, 4][mFieldCount]; - mHasLiveHR = mApp.hasField(FIELD_TYPE_HR_LIVE_5S); + mHasLiveHR = mView.hasField(FIELD_TYPE_HR_LIVE_5S); - if (!mApp.hasField(FIELD_TYPE_WEATHER)) { + if (!mView.hasField(FIELD_TYPE_WEATHER)) { mWeatherIconsFont = null; mWeatherIconsSubset = null; } @@ -118,12 +106,12 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_TYPE_SUNRISE_SUNSET, "complicationType" => Complications.COMPLICATION_TYPE_SUNRISE} // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain ]; - var fieldTypes = mApp.mFieldTypes; + var fieldTypes = mView.mFieldTypes; var filled = [false, false, false]; var i; for (i = 0; i < complications.size(); i++) { - if (mApp.hasField(complications[i].get("type"))) { + if (mView.hasField(complications[i].get("type"))) { for (var j = 0; j < mFieldCount; j++) { if (fieldTypes[j].get("type") == complications[i].get("type")) { $.updateComplications("", "Complication_F", j + 1, complications[i].get("complicationType")); @@ -159,7 +147,7 @@ class DataFields extends Ui.Drawable { return; } - var fieldTypes = mApp.mFieldTypes; + var fieldTypes = mView.mFieldTypes; /*var spacingX = Sys.getDeviceSettings().screenWidth / (2 * mFieldCount); var spacingY = Sys.getDeviceSettings().screenHeight / 4; @@ -442,12 +430,12 @@ class DataFields extends Ui.Drawable { var sunTimes; var unit; var info; + var fieldTypes = mView.mFieldTypes; switch (type) { // SG Addition case FIELD_RECOVERY_TIME: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = $.MinutesToTimeString(tmpValue); @@ -464,7 +452,6 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_BODY_BATTERY: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -486,7 +473,6 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_STRESS_LEVEL: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -529,7 +515,6 @@ class DataFields extends Ui.Drawable { // SG Addition case FIELD_TYPE_PULSE_OX: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString() + "%"; @@ -545,7 +530,6 @@ class DataFields extends Ui.Drawable { break; case FIELD_TYPE_HEART_RATE: if (Toybox has :Complications && mView.useComplications()) { - var fieldTypes = mApp.mFieldTypes; var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); diff --git a/source/Global.mc b/source/Global.mc index e6c343b6..82f6ed2e 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -490,7 +490,7 @@ function to_array(string, splitter) { } function doTeslaComplication(complicationValue) { - /*DEBUG*/ logMessage("Complication read: " + complicationValue); + //DEBUG*/ logMessage("Complication read: " + complicationValue); if (complicationValue instanceof Lang.String) { // Only handle the enhance data sent, not just the battery SoC (a Number) var teslaInfo = Storage.getValue("TeslaInfo"); if (teslaInfo == null){ @@ -519,3 +519,45 @@ function logMessage(message) { (:release, :background) function logMessage(message) { } + +/* +function type_name(obj) { + if (obj instanceof Toybox.Lang.Number) { + return "Number"; + } else if (obj instanceof Toybox.Lang.Long) { + return "Long"; + } else if (obj instanceof Toybox.Lang.Float) { + return "Float"; + } else if (obj instanceof Toybox.Lang.Double) { + return "Double"; + } else if (obj instanceof Toybox.Lang.Boolean) { + return "Boolean"; + } else if (obj instanceof Toybox.Lang.String) { + return "String"; + } else if (obj instanceof Toybox.Lang.Array) { + var s = "Array ["; + for (var i = 0; i < obj.size(); ++i) { + s += type_name(obj); + s += ", "; + } + s += "]"; + return s; + } else if (obj instanceof Toybox.Lang.Dictionary) { + var s = "Dictionary{"; + var keys = obj.keys(); + var vals = obj.values(); + for (var i = 0; i < keys.size(); ++i) { + s += keys; + s += ": "; + s += vals; + s += ", "; + } + s += "}"; + return s; + } else if (obj instanceof Toybox.Time.Gregorian.Info) { + return "Gregorian.Info"; + } else { + return "???"; + } +} +*/ \ No newline at end of file diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index 8e54c949..95d39bcb 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -148,7 +148,7 @@ class GoalMeter extends Ui.Drawable { {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} ]; - var goalTypes = mApp.mGoalTypes; + var goalTypes = mView.mGoalTypes; var filled = false; for (var i = 0; i < complications.size(); i++) { From 6ce5fd73813ef186bf6c8c1207bcb75a65e03a06 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 12 May 2023 21:11:23 -0400 Subject: [PATCH 149/220] Showing when Tesla Complication received --- source/Global.mc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Global.mc b/source/Global.mc index 82f6ed2e..d4209c28 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -490,7 +490,7 @@ function to_array(string, splitter) { } function doTeslaComplication(complicationValue) { - //DEBUG*/ logMessage("Complication read: " + complicationValue); + /*DEBUG*/ logMessage("Complication read: " + complicationValue); if (complicationValue instanceof Lang.String) { // Only handle the enhance data sent, not just the battery SoC (a Number) var teslaInfo = Storage.getValue("TeslaInfo"); if (teslaInfo == null){ From 2ae809605e15b7fb4e916bea5c6906d82c5690c6 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 13 May 2023 20:11:48 -0400 Subject: [PATCH 150/220] Had to reinstate the original sunrise/sunset routine because some watches are still on 3.2.0 --- source/CrystalView.mc | 43 ++++++++++++---- source/DataFields.mc | 77 +++++++++++++++++++++++----- source/Global.mc | 114 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+), 21 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 763e84f6..e513ecce 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -246,16 +246,41 @@ class CrystalView extends Ui.WatchFace { var icon = "01"; var day = "d"; var myLocation = weather.observationLocationPosition; + var now = Time.now(); if (myLocation != null) { - var now = Time.now(); - var sunrise = Weather.getSunrise(myLocation, now); - var sunset = Weather.getSunset(myLocation, now); - - if (sunrise != null and sunset != null) { - var sinceSunrise = sunrise.compare(now); - var sinceSunset = now.compare(sunset); - if (sinceSunrise >= 0 || sinceSunset >= 0) { - day = "n"; + if (Toybox.Weather has :getSunrise) { + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); + + if (sunrise != null and sunset != null) { + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); + if (sinceSunrise >= 0 || sinceSunset >= 0) { + day = "n"; + } + } + } + else { + //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); + var myLocationArray = myLocation.toDegrees(); + now = Gregorian.info(now, Time.FORMAT_SHORT); + + // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at + // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). + now = now.hour + ((now.min + 1) / 60.0); + //logMessage(now); + + // Get today's sunrise/sunset times in current time zone. + var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); + //logMessage(sunTimes); + //logMessage("now=" + now); + //logMessage("sunTimes=" + sunTimes); + // If sunrise/sunset happens today. + var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); + if (sunriseSunsetToday) { + if (now < sunTimes[0] || now > sunTimes[1]) { + day = "n"; + } } } } diff --git a/source/DataFields.mc b/source/DataFields.mc index b15f13ef..1ab865c5 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -659,24 +659,77 @@ class DataFields extends Ui.Drawable { if (weather != null) { var now = Time.now(); var myLocation = weather.observationLocationPosition; + if (Toybox.Weather has :getSunrise) { + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); - var sunrise = Weather.getSunrise(myLocation, now); - var sunset = Weather.getSunset(myLocation, now); + var sunriseTime = Gregorian.info(sunrise, Time.FORMAT_SHORT); + var sunsetTime = Gregorian.info(sunset, Time.FORMAT_SHORT); - var sunriseTime = Gregorian.info(sunrise, Time.FORMAT_SHORT); - var sunsetTime = Gregorian.info(sunset, Time.FORMAT_SHORT); + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); - var sinceSunrise = sunrise.compare(now); - var sinceSunset = now.compare(sunset); - - if (sinceSunrise >= 0 || sinceSunset >= 0) { - result["isSunriseNext"] = true; - value = $.getFormattedTime(sunriseTime.hour, sunriseTime.min); + if (sinceSunrise >= 0 || sinceSunset >= 0) { + result["isSunriseNext"] = true; + value = $.getFormattedTime(sunriseTime.hour, sunriseTime.min); + } + else { + value = $.getFormattedTime(sunsetTime.hour, sunsetTime.min); + } + value = value[:hour] + ":" + value[:min] + value[:amPm]; } else { - value = $.getFormattedTime(sunsetTime.hour, sunsetTime.min); + var myLocationArray = myLocation.toDegrees(); + var nextSunEvent = 0; + now = Gregorian.info(Time.now(), Time.FORMAT_SHORT); + + // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at + // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). + now = now.hour + ((now.min + 1) / 60.0); + //logMessage(now); + + // Get today's sunrise/sunset times in current time zone. + sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); + //logMessage(sunTimes); + + // If sunrise/sunset happens today. + var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); + if (sunriseSunsetToday) { + + // Before sunrise today: today's sunrise is next. + if (now < sunTimes[0]) { + nextSunEvent = sunTimes[0]; + result["isSunriseNext"] = true; + + // After sunrise today, before sunset today: today's sunset is next. + } else if (now < sunTimes[1]) { + nextSunEvent = sunTimes[1]; + + // After sunset today: tomorrow's sunrise (if any) is next. + } else { + sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ true); + nextSunEvent = sunTimes[0]; + result["isSunriseNext"] = true; + } + } + + // Sun never rises/sets today. + if (!sunriseSunsetToday) { + value = "---"; + + // Sun never rises: sunrise is next, but more than a day from now. + if (sunTimes[0] == null) { + result["isSunriseNext"] = true; + } + + // We have a sunrise/sunset time. + } else { + var hour = Math.floor(nextSunEvent).toLong() % 24; + var min = Math.floor((nextSunEvent - Math.floor(nextSunEvent)) * 60); // Math.floor(fractional_part * 60) + value = App.getApp().getFormattedTime(hour, min); + value = value[:hour] + ":" + value[:min] + value[:amPm]; + } } - value = value[:hour] + ":" + value[:min] + value[:amPm]; } else { value = "???"; diff --git a/source/Global.mc b/source/Global.mc index d4209c28..0db5798a 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -509,6 +509,120 @@ function doTeslaComplication(complicationValue) { } } +/** +* With thanks to ruiokada. Adapted, then translated to Monkey C, from: +* https://gist.github.com/ruiokada/b28076d4911820ddcbbc +* +* Calculates sunrise and sunset in local time given latitude, longitude, and tz. +* +* Equations taken from: +* https://en.wikipedia.org/wiki/Julian_day#Converting_Julian_or_Gregorian_calendar_date_to_Julian_Day_Number +* https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth + +* +* @method getSunTimes +* @param {Float} lat Latitude of location (South is negative) +* @param {Float} lng Longitude of location (West is negative) +* @param {Integer || null} tz Timezone hour offset. e.g. Pacific/Los Angeles is -8 (Specify null for system timezone) +* @param {Boolean} tomorrow Calculate tomorrow's sunrise and sunset, instead of today's. +* @return {Array} Returns array of length 2 with sunrise and sunset as floats. +* Returns array with [null, -1] if the sun never rises, and [-1, null] if the sun never sets. +*/ +function getSunTimes(lat, lng, tz, tomorrow) { + + // Use double precision where possible, as floating point errors can affect result by minutes. + lat = lat.toDouble(); + lng = lng.toDouble(); + + var now = Time.now(); + if (tomorrow) { + now = now.add(new Time.Duration(24 * 60 * 60)); + } + var d = Gregorian.info(now, Time.FORMAT_SHORT); + var rad = Math.PI / 180.0d; + var deg = 180.0d / Math.PI; + + // Calculate Julian date from Gregorian. + var a = Math.floor((14 - d.month) / 12); + var y = d.year + 4800 - a; + var m = d.month + (12 * a) - 3; + var jDate = d.day + + Math.floor(((153 * m) + 2) / 5) + + (365 * y) + + Math.floor(y / 4) + - Math.floor(y / 100) + + Math.floor(y / 400) + - 32045; + + // Number of days since Jan 1st, 2000 12:00. + var n = jDate - 2451545.0d + 0.0008d; + //Sys.println("n " + n); + + // Mean solar noon. + var jStar = n - (lng / 360.0d); + //Sys.println("jStar " + jStar); + + // Solar mean anomaly. + var M = 357.5291d + (0.98560028d * jStar); + var MFloor = Math.floor(M); + var MFrac = M - MFloor; + M = MFloor.toLong() % 360; + M += MFrac; + //Sys.println("M " + M); + + // Equation of the centre. + var C = 1.9148d * Math.sin(M * rad) + + 0.02d * Math.sin(2 * M * rad) + + 0.0003d * Math.sin(3 * M * rad); + //Sys.println("C " + C); + + // Ecliptic longitude. + var lambda = (M + C + 180 + 102.9372d); + var lambdaFloor = Math.floor(lambda); + var lambdaFrac = lambda - lambdaFloor; + lambda = lambdaFloor.toLong() % 360; + lambda += lambdaFrac; + //Sys.println("lambda " + lambda); + + // Solar transit. + var jTransit = 2451545.5d + jStar + + 0.0053d * Math.sin(M * rad) + - 0.0069d * Math.sin(2 * lambda * rad); + //Sys.println("jTransit " + jTransit); + + // Declination of the sun. + var delta = Math.asin(Math.sin(lambda * rad) * Math.sin(23.44d * rad)); + //Sys.println("delta " + delta); + + // Hour angle. + var cosOmega = (Math.sin(-0.83d * rad) - Math.sin(lat * rad) * Math.sin(delta)) + / (Math.cos(lat * rad) * Math.cos(delta)); + //Sys.println("cosOmega " + cosOmega); + + // Sun never rises. + if (cosOmega > 1) { + return [null, -1]; + } + + // Sun never sets. + if (cosOmega < -1) { + return [-1, null]; + } + + // Calculate times from omega. + var omega = Math.acos(cosOmega) * deg; + var jSet = jTransit + (omega / 360.0); + var jRise = jTransit - (omega / 360.0); + var deltaJSet = jSet - jDate; + var deltaJRise = jRise - jDate; + + var tzOffset = (tz == null) ? (Sys.getClockTime().timeZoneOffset / 3600.0) : tz; + return [ + /* localRise */ (deltaJRise * 24) + tzOffset, + /* localSet */ (deltaJSet * 24) + tzOffset + ]; +} + (:debug, :background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); From d3d4ea4b43ab6522797b8cc58f2d42d0e294ddde Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 13 May 2023 20:17:16 -0400 Subject: [PATCH 151/220] Consolidated debug statements --- source/BackgroundService.mc | 20 ++++++-------------- source/Global.mc | 2 ++ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 7885bf90..cb7c3ae6 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -26,8 +26,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); - /*DEBUG*/ logMessage("onReceiveVehicleData: Buffer has keys " + keys); + /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); } var timeNow = Time.now().value(); @@ -63,10 +62,7 @@ class BackgroundService extends Sys.ServiceDelegate { } if (_token != null && _token.equals("") == false) { - //DEBUG*/ var expireAt = new Time.Moment(createdAt + expiresIn); - //DEBUG*/ var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); - //DEBUG*/ var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); - //DEBUG*/ logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); + //DEBUG*/ var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } else { @@ -117,8 +113,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); - /*DEBUG*/ logMessage("onReceiveToken: Buffer has keys " + keys); + /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveToken: Buffer has keys " + keys); } if (responseCode == 200) { @@ -143,8 +138,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); - /*DEBUG*/ logMessage("onReceiveVehicles: Buffer has keys " + keys); + /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicles: Buffer has keys " + keys); } if (responseCode == 200) { @@ -189,16 +183,14 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onReceiveVehicleData(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); - /*DEBUG*/ var myStats = Sys.getSystemStats(); - /*DEBUG*/ logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); var teslaInfo = Bg.getBackgroundData(); if (teslaInfo == null) { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); - /*DEBUG*/ logMessage("onReceiveVehicleData: Buffer has keys " + keys); + /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); } teslaInfo.put("httpErrorTesla", responseCode); diff --git a/source/Global.mc b/source/Global.mc index 0db5798a..fe44081b 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -623,12 +623,14 @@ function getSunTimes(lat, lng, tz, tomorrow) { ]; } +//DEBUG (:debug, :background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); Sys.println(dateStr + " : " + message); } +//DEBUG*/ (:release, :background) function logMessage(message) { From 83f54b2369be0916f42c5e67df6e6495c27b705c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 13 May 2023 20:26:04 -0400 Subject: [PATCH 152/220] Some debug fix --- source/CrystalApp.mc | 8 ++++---- source/CrystalView.mc | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index f6f319e4..cf7f5b06 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -23,16 +23,16 @@ class CrystalApp extends App.AppBase { } // function onStart(state) { - // /* DEBUG*/ logMessage("App starting"); + // /*DEBUG*/ logMessage("App starting"); // } // function onStop(state) { - // /* DEBUG*/ logMessage("App stopping"); + // /*DEBUG*/ logMessage("App stopping"); // } // Return the initial view of your application here function getInitialView() { - /* DEBUG*/ logMessage("Getting initial view"); + /*DEBUG*/ logMessage("Getting initial view"); if (WatchUi has :WatchFaceDelegate) { mView = new CrystalView(); @@ -54,7 +54,7 @@ class CrystalApp extends App.AppBase { // New app settings have been received so trigger a UI update (:background_method) function getServiceDelegate() { - /* DEBUG*/ logMessage("Getting service delegate"); + /*DEBUG*/ logMessage("Getting service delegate"); return [new BackgroundService()]; } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index e513ecce..68a2ea7f 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -145,7 +145,7 @@ class CrystalView extends Ui.WatchFace { // the state of this View and prepare it to be shown. This includes // loading resources into memory. */ function onShow() { - /* DEBUG*/ logMessage("View showing"); + /*DEBUG*/ logMessage("View showing"); } // Set flag to respond to settings change on next full draw (onUpdate()), as we may be in 1Hz (lower power) mode, and cannot @@ -649,7 +649,7 @@ class CrystalView extends Ui.WatchFace { // state of this View here. This includes freeing resources from // memory */ function onHide() { - /* DEBUG*/ logMessage("View hidding"); + /*DEBUG*/ logMessage("View hidding"); } // The user has just looked at their watch. Timers and animations may be started here. From edf4b395f21b49122d42182e2fcce3068388d136 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 13 May 2023 20:45:53 -0400 Subject: [PATCH 153/220] Update manifest.xml --- manifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.xml b/manifest.xml index c0c3066c..b71e89fe 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + From ba4aebc684c84ea67c6c44ac0835a7f7f90f98a0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 15 May 2023 00:44:08 -0400 Subject: [PATCH 154/220] V2.18.1 - Gave the weather station name its own line so it doesn't hide the Goals current/max fields. Local City Time will still hide these though. This is how it always was. - Added an option in Settings (Show weather station name) to show or not the weather station name, defaults to True. - Watches that although are at CIQ V3.2.0 and above but are still lacking Garmin Weather will display "N/A" for temperature/humidity/sunrise/sunset. - Trying to free some more room so watches with 98KB of watch face memory doesn't crash with Out of Memory errors. --- README.md | 6 + manifest.xml | 2 +- monkey.jungle | 52 ------ resources-approachs60/settings/properties.xml | 9 - resources-approachs60/settings/settings.xml | 82 --------- resources-approachs62/settings/properties.xml | 6 - resources-approachs62/settings/settings.xml | 82 --------- resources-ces/strings/strings.xml | 1 + .../settings/properties.xml | 10 -- resources-ciq_1.x-no_hr/settings/settings.xml | 105 ------------ resources-ciq_1.x/settings/properties.xml | 7 - resources-ciq_1.x/settings/settings.xml | 105 ------------ resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fr735xt/settings/properties.xml | 6 - resources-fr735xt/settings/settings.xml | 101 ----------- resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + resources-rectangle-148x205/fonts/fonts.xml | 4 - .../titillium-web-bold-48-extra-tall.bmfc | 59 ------- .../titillium-web-bold-48-extra-tall.fnt | 14 -- .../titillium-web-bold-48-extra-tall_0.png | Bin 2299 -> 0 bytes .../titillium-web-light-48-extra-tall.bmfc | 55 ------ .../titillium-web-light-48-extra-tall.fnt | 14 -- .../titillium-web-light-48-extra-tall_0.png | Bin 3365 -> 0 bytes .../layouts/layout.xml | 71 -------- resources-rectangle-205x148/fonts/fonts.xml | 17 -- .../fonts/namum-gothic-kor-16.bmfc | 55 ------ .../fonts/namum-gothic-kor-16.fnt | 24 --- .../fonts/namum-gothic-kor-16_0.png | Bin 1637 -> 0 bytes .../fonts/noto-sans-cjk-sc-medium-16.fnt | 30 ---- .../fonts/noto-sans-cjk-sc-medium-16_0.png | Bin 1722 -> 0 bytes .../fonts/noto-sans-cjk-tc-medium-16.fnt | 30 ---- .../fonts/noto-sans-cjk-tc-medium-16_0.png | Bin 1709 -> 0 bytes .../fonts/noto-sans-rus-bold-16.bmfc | 55 ------ .../fonts/noto-sans-rus-bold-16.fnt | 47 ----- .../fonts/noto-sans-rus-bold-16_0.png | Bin 2561 -> 0 bytes .../fonts/titillium-web-bold-54.bmfc | 55 ------ .../fonts/titillium-web-bold-54.fnt | 14 -- .../fonts/titillium-web-bold-54_0.png | Bin 3515 -> 0 bytes .../fonts/titillium-web-light-54.bmfc | 55 ------ .../fonts/titillium-web-light-54.fnt | 15 -- .../fonts/titillium-web-light-54_0.png | Bin 3782 -> 0 bytes .../layouts/layout.xml | 73 -------- .../settings/settings.xml | 8 - .../layouts/layout.xml | 1 + .../layouts/layout.xml | 1 + resources-round-208x208/layouts/layout.xml | 1 + .../layouts/layout.xml | 70 -------- resources-round-218x218/layouts/layout.xml | 1 + resources-round-260x260/layouts/layout.xml | 1 + resources-round-280x280/layouts/layout.xml | 1 + resources-round-360x360/layouts/layout.xml | 1 + resources-round-390x390/layouts/layout.xml | 1 + resources-round-416x416/layouts/layout.xml | 1 + resources-round-454x454/layouts/layout.xml | 1 + resources-rus/strings/strings.xml | 1 + .../layouts/layout.xml | 72 -------- .../layouts/layout.xml | 67 -------- resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-vivoactive/settings/properties.xml | 10 -- resources-vivoactive/settings/settings.xml | 108 ------------ resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/layouts/layout.xml | 1 + resources/settings/properties.xml | 2 + resources/settings/settings.xml | 4 + resources/strings/strings.xml | 4 +- source/BackgroundService.mc | 20 +-- source/CrystalApp.mc | 4 +- source/CrystalView.mc | 160 ++++++++++-------- source/DataArea.mc | 90 +++++----- source/DataFields.mc | 39 ++--- source/GoalMeter.mc | 10 +- 85 files changed, 211 insertions(+), 1748 deletions(-) delete mode 100644 resources-approachs60/settings/properties.xml delete mode 100644 resources-approachs60/settings/settings.xml delete mode 100644 resources-approachs62/settings/properties.xml delete mode 100644 resources-approachs62/settings/settings.xml delete mode 100644 resources-ciq_1.x-no_hr/settings/properties.xml delete mode 100644 resources-ciq_1.x-no_hr/settings/settings.xml delete mode 100644 resources-ciq_1.x/settings/properties.xml delete mode 100644 resources-ciq_1.x/settings/settings.xml delete mode 100644 resources-fr735xt/settings/properties.xml delete mode 100644 resources-fr735xt/settings/settings.xml delete mode 100644 resources-rectangle-148x205/fonts/fonts.xml delete mode 100644 resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc delete mode 100644 resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt delete mode 100644 resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall_0.png delete mode 100644 resources-rectangle-148x205/fonts/titillium-web-light-48-extra-tall.bmfc delete mode 100644 resources-rectangle-148x205/fonts/titillium-web-light-48-extra-tall.fnt delete mode 100644 resources-rectangle-148x205/fonts/titillium-web-light-48-extra-tall_0.png delete mode 100644 resources-rectangle-148x205/layouts/layout.xml delete mode 100644 resources-rectangle-205x148/fonts/fonts.xml delete mode 100644 resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc delete mode 100644 resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt delete mode 100644 resources-rectangle-205x148/fonts/namum-gothic-kor-16_0.png delete mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt delete mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16_0.png delete mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt delete mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16_0.png delete mode 100644 resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc delete mode 100644 resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt delete mode 100644 resources-rectangle-205x148/fonts/noto-sans-rus-bold-16_0.png delete mode 100644 resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc delete mode 100644 resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt delete mode 100644 resources-rectangle-205x148/fonts/titillium-web-bold-54_0.png delete mode 100644 resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc delete mode 100644 resources-rectangle-205x148/fonts/titillium-web-light-54.fnt delete mode 100644 resources-rectangle-205x148/fonts/titillium-web-light-54_0.png delete mode 100644 resources-rectangle-205x148/layouts/layout.xml delete mode 100644 resources-rectangle-205x148/settings/settings.xml delete mode 100644 resources-round-218x218-ciq_1.x/layouts/layout.xml delete mode 100644 resources-semiround-215x180-ciq_1.x/layouts/layout.xml delete mode 100644 resources-semiround-215x180/layouts/layout.xml delete mode 100644 resources-vivoactive/settings/properties.xml delete mode 100644 resources-vivoactive/settings/settings.xml diff --git a/README.md b/README.md index cff03344..ff3a4b48 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,12 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.1 +- Gave the weather station name its own line so it doesn't hide the Goals current/max fields. Local City Time will still hide these though. This is how it always was. +- Added an option in Settings (Show weather station name) to show or not the weather station name, defaults to True. +- Watches that although are at CIQ V3.2.0 and above but are still lacking Garmin Weather will display "N/A" for temperature/humidity/sunrise/sunset. +- Trying to free some more room so watches with 98KB of watch face memory doesn't crash with Out of Memory errors. + ### 2.18.0 - Removed Watch model that are not at least at CIQ 3.3.0. This is required for the new Sunrise/Sunset and Weather library by Garmin. From the stats Garmin shows me about the watch face, none of them had downloaded the watch face anyway. - Removed the OpenWeatherMap and rely solely on Garmin Weather. The OWN and GPS was giving too much problem. diff --git a/manifest.xml b/manifest.xml index b71e89fe..ea0690e3 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + diff --git a/monkey.jungle b/monkey.jungle index dcdc1305..f19c0c89 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -15,63 +15,11 @@ round-218x218.resourcePath = $(round-218x218.resourcePath);resources-small-time # Flat tyre watches use small time font and small icons. # Ditto smallest round watches. -semiround-215x180.resourcePath = $(semiround-215x180.resourcePath);resources-small-time;resources-small-icons round-208x208.resourcePath = $(round-208x208.resourcePath);resources-small-time;resources-small-icons # Rectangle watches generally same as flat tyre, but have some overrides. rectangle.resourcePath = $(rectangle.resourcePath);resources-small-time;resources-small-icons -# CIQ 1.x watches only have 16 colours, so cannot support all themes. -# No Floors or Active Minutes support, so default to showing Battery in right meter, and Calories in the centre field. -# If a watch also has no HR support, show Distance in left field. -# No BufferedBitmap support, so exclude buffer-specific variables/functions. -# No clip support, so goal meter mask required for round/semiround watches. - -d2bravo.resourcePath = $(d2bravo.resourcePath);resources-round-218x218-ciq_1.x;resources-ciq_1.x-no_hr -d2bravo.excludeAnnotations = buffered - -d2bravo_titanium.resourcePath = $(d2bravo_titanium.resourcePath);resources-round-218x218-ciq_1.x;resources-ciq_1.x -d2bravo_titanium.excludeAnnotations = buffered - -fenix3.resourcePath = $(fenix3.resourcePath);resources-round-218x218-ciq_1.x;resources-ciq_1.x-no_hr -fenix3.excludeAnnotations = buffered - -fenix3_hr.resourcePath = $(fenix3_hr.resourcePath);resources-round-218x218-ciq_1.x;resources-ciq_1.x -fenix3_hr.excludeAnnotations = buffered - -fr230.resourcePath = $(fr230.resourcePath);resources-semiround-215x180-ciq_1.x;resources-ciq_1.x-no_hr -fr230.excludeAnnotations = buffered - -fr235.resourcePath = $(fr235.resourcePath);resources-semiround-215x180-ciq_1.x;resources-ciq_1.x -fr235.excludeAnnotations = buffered - -fr630.resourcePath = $(fr630.resourcePath);resources-semiround-215x180-ciq_1.x;resources-ciq_1.x-no_hr -fr630.excludeAnnotations = buffered - -fr920xt.resourcePath = $(fr920xt.resourcePath);resources-ciq_1.x-no_hr -fr920xt.excludeAnnotations = buffered - -# Reverse order of resources so that 64-colour themes are permitted. -# #25: Repeat ciq_1.x-no_hr properties within resources-vivoactive, as properties were not correctly inherited. -#vivoactive.resourcePath = resources-ciq_1.x-no_hr;$(vivoactive.resourcePath) -vivoactive.excludeAnnotations = buffered - -# #21: Treat fr735xt as CIQ 1.x i.e. unbuffered drawing, due to insufficient memory. -# Continue to use fr735xt-specific properties and settings, however, as does support active minutes. -fr735xt.resourcePath = $(fr735xt.resourcePath);resources-semiround-215x180-ciq_1.x -fr735xt.excludeAnnotations = buffered - -# Exclude unused date/indicator code from 60kB devices (extend to other devices as necessary). -fr735xt.excludeAnnotations = $(fr735xt.excludeAnnotations);double_line_date;horizontal_indicators -vivoactive_hr.excludeAnnotations = $(vivoactive_hr.excludeAnnotations);double_line_date;vertical_indicators - -# #124: fr45's settings.xml repeats whole of resources-ciq_1.x, then overrides, as settings were not correct inherited. -# Exclude background methods as memory is very limited (extend to other devices as necessary). -fr45.excludeAnnotations = $(fr45.excludeAnnotations);buffered;background_method;double_line_date;horizontal_indicators - -# garminswim2 has same limitations as fr45 (CIQ 1.x, low memory, low colours). -garminswim2.excludeAnnotations = $(garminswim2.excludeAnnotations);buffered;background_method;double_line_date;horizontal_indicators - # #144: Always on display. venu.sourcePath = $(venu.sourcePath);always-on-source venu2.sourcePath = $(venu2.sourcePath);always-on-source diff --git a/resources-approachs60/settings/properties.xml b/resources-approachs60/settings/properties.xml deleted file mode 100644 index c0e58606..00000000 --- a/resources-approachs60/settings/properties.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - 2 - - - 4 - - \ No newline at end of file diff --git a/resources-approachs60/settings/settings.xml b/resources-approachs60/settings/settings.xml deleted file mode 100644 index a994b1a8..00000000 --- a/resources-approachs60/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-approachs62/settings/properties.xml b/resources-approachs62/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-approachs62/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-approachs62/settings/settings.xml b/resources-approachs62/settings/settings.xml deleted file mode 100644 index 10fc96a2..00000000 --- a/resources-approachs62/settings/settings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - @Strings.HeartRateLive5s - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 29e0cf33..29fe42bf 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-ciq_1.x-no_hr/settings/properties.xml b/resources-ciq_1.x-no_hr/settings/properties.xml deleted file mode 100644 index cb2de3ec..00000000 --- a/resources-ciq_1.x-no_hr/settings/properties.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -1 - 3 - - - 4 - - \ No newline at end of file diff --git a/resources-ciq_1.x-no_hr/settings/settings.xml b/resources-ciq_1.x-no_hr/settings/settings.xml deleted file mode 100644 index 81000828..00000000 --- a/resources-ciq_1.x-no_hr/settings/settings.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/resources-ciq_1.x/settings/properties.xml b/resources-ciq_1.x/settings/properties.xml deleted file mode 100644 index 0981fb4b..00000000 --- a/resources-ciq_1.x/settings/properties.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - -1 - 3 - - \ No newline at end of file diff --git a/resources-ciq_1.x/settings/settings.xml b/resources-ciq_1.x/settings/settings.xml deleted file mode 100644 index 86f08674..00000000 --- a/resources-ciq_1.x/settings/settings.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index ec512529..fd395cd1 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 63baa61c..fee8493a 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 0fea4d20..29431d91 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index d5fed67b..3bc17ab2 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-fr735xt/settings/properties.xml b/resources-fr735xt/settings/properties.xml deleted file mode 100644 index 2782de9e..00000000 --- a/resources-fr735xt/settings/properties.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 2 - - \ No newline at end of file diff --git a/resources-fr735xt/settings/settings.xml b/resources-fr735xt/settings/settings.xml deleted file mode 100644 index 52dabaf0..00000000 --- a/resources-fr735xt/settings/settings.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - @Strings.ActiveMinutes - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - - - @Strings.HeartRate - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - @Strings.Weather - @Strings.Humidity - - - - diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 69e04d38..a745186c 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -123,4 +123,5 @@ Utilisez les complications, si disponible Utilisez les Complications de Tesla-Link pour l'info Tesla Quel véhicle afficher? + Montrer le nom de la station météo? diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 4a383afd..6b767be0 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 7d2bbdac..c07103a1 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 63d95ea4..90d4c7bf 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 8fad383f..39a0302a 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index d40887eb..371198e1 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index dfacdb2a..fbe0cdea 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 44e27e82..7ec9fc74 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-rectangle-148x205/fonts/fonts.xml b/resources-rectangle-148x205/fonts/fonts.xml deleted file mode 100644 index caea187e..00000000 --- a/resources-rectangle-148x205/fonts/fonts.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc deleted file mode 100644 index 7d6c9a09..00000000 --- a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.bmfc +++ /dev/null @@ -1,59 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Titillium Web -fontFile= -charSet=0 -fontSize=-54 -aa=1 -scaleH=100 -useSmoothing=1 -isBold=1 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 -autoFitNumPages=0 -autoFitFontSizeMin=0 -autoFitFontSizeMax=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 -widthPaddingFactor=0.00 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=48-57 - -# imported icon images diff --git a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt deleted file mode 100644 index e14906e0..00000000 --- a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall.fnt +++ /dev/null @@ -1,14 +0,0 @@ -info face="Titillium Web" size=-54 bold=1 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=82 base=61 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="titillium-web-bold-48-extra-tall_0.png" -chars count=10 -char id=48 x=0 y=0 width=28 height=38 xoffset=1 yoffset=24 xadvance=30 page=0 chnl=15 -char id=49 x=0 y=39 width=19 height=36 xoffset=4 yoffset=25 xadvance=30 page=0 chnl=15 -char id=50 x=167 y=0 width=24 height=37 xoffset=3 yoffset=24 xadvance=30 page=0 chnl=15 -char id=51 x=115 y=0 width=24 height=38 xoffset=3 yoffset=24 xadvance=30 page=0 chnl=15 -char id=52 x=217 y=0 width=27 height=36 xoffset=2 yoffset=25 xadvance=30 page=0 chnl=15 -char id=53 x=140 y=0 width=26 height=37 xoffset=2 yoffset=25 xadvance=30 page=0 chnl=15 -char id=54 x=87 y=0 width=27 height=38 xoffset=2 yoffset=24 xadvance=30 page=0 chnl=15 -char id=55 x=192 y=0 width=24 height=37 xoffset=3 yoffset=25 xadvance=30 page=0 chnl=15 -char id=56 x=29 y=0 width=28 height=38 xoffset=1 yoffset=24 xadvance=30 page=0 chnl=15 -char id=57 x=58 y=0 width=28 height=38 xoffset=1 yoffset=24 xadvance=30 page=0 chnl=15 diff --git a/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall_0.png b/resources-rectangle-148x205/fonts/titillium-web-bold-48-extra-tall_0.png deleted file mode 100644 index af2e1bc21d8a7cf375e2e8e3651623a24904e712..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2299 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 Qzy84*m|m^8?DXLO093RsW&i*H diff --git a/resources-rectangle-148x205/layouts/layout.xml b/resources-rectangle-148x205/layouts/layout.xml deleted file mode 100644 index ca94f62e..00000000 --- a/resources-rectangle-148x205/layouts/layout.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - :left - 6 - 205 - 2 - - - - :right - 6 - 205 - 2 - - - - 34 - 80 - 180 - 196 - 178 - 11 - 137 - - - - 33 - 115 - 11 - 30 - 24 - - - - - - 74 - 154 - 32 - 22 - - - - 105 - 113 - - - - - - - - -6 - - - 0 - - - - 23 - 130 - 75 - 7 - 3 - - - \ No newline at end of file diff --git a/resources-rectangle-205x148/fonts/fonts.xml b/resources-rectangle-205x148/fonts/fonts.xml deleted file mode 100644 index 80b93802..00000000 --- a/resources-rectangle-205x148/fonts/fonts.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc b/resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc deleted file mode 100644 index a8b43eaa..00000000 --- a/resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=NanumGothicExtraBold -fontFile= -charSet=0 -fontSize=16 -aa=2 -scaleH=100 -useSmoothing=1 -isBold=0 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=32,40-41,48-57,44552,47785,49688,50900,51068,53664,54868 - -# imported icon images diff --git a/resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt b/resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt deleted file mode 100644 index 61fc88fb..00000000 --- a/resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt +++ /dev/null @@ -1,24 +0,0 @@ -info face="NanumGothicExtraBold" size=16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=16 base=13 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="namum-gothic-kor-16_0.png" -chars count=20 -char id=32 x=191 y=0 width=2 height=1 xoffset=0 yoffset=15 xadvance=4 page=0 chnl=15 -char id=40 x=0 y=0 width=5 height=14 xoffset=0 yoffset=2 xadvance=5 page=0 chnl=15 -char id=41 x=6 y=0 width=5 height=14 xoffset=0 yoffset=2 xadvance=5 page=0 chnl=15 -char id=48 x=104 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=49 x=172 y=0 width=4 height=11 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=15 -char id=50 x=140 y=0 width=7 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=51 x=148 y=0 width=7 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=52 x=94 y=0 width=9 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=53 x=156 y=0 width=7 height=11 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=15 -char id=54 x=113 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=55 x=164 y=0 width=7 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=56 x=122 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=57 x=131 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 -char id=44552 x=27 y=0 width=13 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 -char id=47785 x=41 y=0 width=13 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 -char id=49688 x=55 y=0 width=13 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 -char id=50900 x=69 y=0 width=12 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 -char id=51068 x=82 y=0 width=11 height=13 xoffset=1 yoffset=2 xadvance=13 page=0 chnl=15 -char id=53664 x=177 y=0 width=13 height=10 xoffset=0 yoffset=3 xadvance=13 page=0 chnl=15 -char id=54868 x=12 y=0 width=14 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/namum-gothic-kor-16_0.png b/resources-rectangle-205x148/fonts/namum-gothic-kor-16_0.png deleted file mode 100644 index d90c20372bef217c67c5b9d9aea0f4fb6e805eed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1637 zcmc(g`#aMM0EfTZw3+**oWu^2C|jiFlIvWOrz~{j(xJKJmc?O=RyLGMB~FI5)hJIl zD^xCFNFo`FXfDeXtAow9$S`y|f5rLy@ILSJynn#wiXYZnU1ggJ008PfhdcuS0Q5^i zfbuT_nfmf30DvNWJTZS{FvL7^;?NI7x6HiK&9uu#xnQ^~ukKmcV9%{M-jJF)ni|i# z8kHJs@jME21XVg<5>Y7GwZpW;7Bx#!059N+D3%NHg@ zG)&n~D5ezbdYz4_FH7BXGOnD&55a~v8=eYI2(%t1X#=B+wOb%>VDFk@ntq?Vw)XF zbWFOs*6ZsG4{j6+s(pWA=n@e`B3S-#&7mi=n3LsrfOx7>M#?0w6MAwunKcrRe{gdc zi*swL;pZ}u?O{rM@AL;Iz(@qO9c!5z82(J?p9IZVMZ%0lC80x>S;K!X(Hv9tPE>!` zdgF70miCDr%O&js2Y?+DQ9d}4$L;gZ8l>Y*6llitfLnO&QHU(@zVD?|A2r&oP)BkD z)qZ@g!B28#Fc6Mm_g{vwnW0@wgaMH8(S@QvpL=_a4qmpoV$g2;t65P*JFjwGaJ6TR z+Mz`FGRkxN?EPtI&8SPg_4~Nt_qaf0gEP7f1^GIDF$a}Crn+?5S>26|hggip(&6eb zYgEzV=iVDlpvJqEufeCG#(FSijWHp#aThQL$&*vUDLg2?d}~7Wm|5ABeZka=^f#eM z&(7m&TuP2-(xZ#75Z45TW2pETgKPn9bjEP`QecM{vF2s2Eo?U@QS|~co~;Uu;EX^S zpvqIzcc4|E^4>dn<+oG%gHitb6eeM|ECF6je1P^NzjT2aHzz<}+@ghiaUVaf>Q5Nv zKvnoa$CVs9Sb6kH{K~qIQEO^U316AJ19lsm3bDtLC^Oj9#PZ8a3)ipjrE4Y+?DkeF z41FBGm3+{J2Wl)Mns2T>-`6?oZang-?>_vsIFcX)X(a@q&ALX(Q_Yx(%xB~oZfOu=Le@2smOXDJ znT6%t2nz)h2-2xG(Vc(+h__v!?JIuI`Rg9%L-t?18-mBbFDd{cC;AY8Ra@&>G%sAK z-snP8^^2BMhLc?&M7Hvr`Kz{a$D6E^plrS0qZ5Eu?d8~S6JL@#bpMP#DYJiTjM;OQ z#2_(yb8%V%nI#D)=AU-`UcaPCJEAEyvY~u~Ymmbs%dvIr;=BQf{u8q)P?@_@PB+ha zwLibVVl3*zr@56ROjy5F%U~R0$QLXj8ACZvO1=O&@q#cUytm*IWsqnp$SWB}qi7d{ zG?MdgdC1qNLoG|6F{rw+De&@Xxjv?Bfo>r5rsU7{In)vMx^BpkuH-yEtU3w%<57Z+ zU#BTh8+67s+eV>eY@P`!vF}&ZlgDZI9{F0&iWN}neRYcgH)A>r+@2~FwE}lHDpB&W zi3Aw*AssYFB4T=|QnxnR=$VJM`^LRy`CGm=(n84DBp?A)GKRGxH4pa_9Bo3+E~GS9 zBraluZMKx5lUvcmhgk}Yv>!n>5bA||ee(N@NEXQ%&XUDY=tB>(E!tJ_f;u+BZG|M? zxkTtFTI-hhF!<`1Ae~1=W@+>J-=|s44h<3{*JZE6z&cb*Qzl<|X|2 zzx~`4xoO|QWI9Ux P-+%acVLhL^<8uB5B4+G) diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt b/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt deleted file mode 100644 index 6b3d7750..00000000 --- a/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt +++ /dev/null @@ -1,30 +0,0 @@ -info face="Noto Sans CJK SC Medium" size=-16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=24 base=19 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="noto-sans-cjk-sc-medium-16_0.png" -chars count=26 -char id=10 x=50 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 -char id=32 x=54 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 -char id=48 x=18 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=49 x=219 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=50 x=228 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=51 x=237 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=52 x=199 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=53 x=246 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=54 x=0 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=55 x=209 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=56 x=9 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=57 x=26 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=19968 x=34 y=16 width=15 height=2 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 -char id=19971 x=110 y=0 width=15 height=14 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 -char id=19977 x=169 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 -char id=20061 x=0 y=0 width=14 height=16 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=20108 x=184 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 -char id=20116 x=153 y=0 width=15 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 -char id=20843 x=93 y=0 width=16 height=14 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 -char id=20845 x=15 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=21313 x=31 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=22235 x=63 y=0 width=14 height=15 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26085 x=141 y=0 width=11 height=14 xoffset=3 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26143 x=126 y=0 width=14 height=14 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26376 x=78 y=0 width=14 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26399 x=47 y=0 width=15 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16_0.png b/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16_0.png deleted file mode 100644 index 5d6d6a9afc0937be4648cf4fe38bdd771b0f6d7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1722 zcmchY{Xf%*1HeC{%y%;Cj)viY7?MOO658ivX zbfILL-zQjP9%ZD6bEbYBFI38Q=J*VyO8%J!48R$67fZ;KmR%y}DdVjj#G=4Q1>q1! zTVwEG!sOsj$yxE%)v}0|@jDaHWc)M1hIx22f1GLwWVYS<&j9PivH;rMA(b9I{6Y1u zr`F0Lb-kybhDG5Yd<<-KRwulgA|f?P)=JO4L03B5e<~gR@+6O4-Je9spb>sP((Ec) z6u!{gCzc$PC>JmjYu%#v9K3+*tZ{hrGyuMtqFMwY*$a3@2Wd$$X^srp*nUsi+13`b zxVrirKI%el@EpIvs+vOt3#ymX%5)E%MzGR`P8nRki?rr=o6?;=(B?7y&$+=k`3%7g z55Ux(YVdr27>b+jtEp))Cw0=);ll@(r`oU-vD@}~1d#{OKV{X5-fN+yE6P^5(3I_v zx21!xdyND7k~k*;+lZ4cGo&k(yrZ1Jou))Rv=FiPf1ZhJWLqJtKZnJ>F%865g+@I) z%2wS|ASq7$_g^Z*q=lu_ORW>9RRor+NLFj6==HanvFI&neB3WYr9F|_R49SZ?0TcG zoOEt)t)^t5mPalE0{-*S8vppz@yp!cO=|rUYazvyOmbIX024RRNC8x@xWTh%z?&-y7#eANohf8M3@$b&1l?m(BRcJ)t*(1$1PheE$` z<{a^0w}(d#ITw`4LlTzu6qf0Z?q~Geq@n!u6_2xco(SbfEl4)k{YMBKZD$C5+k70n z3O!qco1FT3b9Mqzj^!oc_xagQV-lBG-?Ai0Dk##6HL~3}QCnccNz3L^Qr}RXiwHX- z?cSUB)+G=V@%BBw|4!%(sHKBSXoy>FHk#-~{c?h8vZ!XX9bMy!GR%V2T!`B$HEPlF zXmmJ#%V1h|+OZeF&$kds@rhtsz%_M-quf2TtszcgnRDJXCngD5&4bJpJIob3$t=Y1 z!*`UkZ`Rjbj@es5+k#0Wc7yF9bP!(N7*O7{8>7`k+)B_nOGs%rtSi^-Nlx=08%w#`s=oML=1whJehlyo6FHhGtfOR6(fjMLpLj1L&qci$ zYl)_()pfhk)4F;#?by)^=vG4>@xZG53Ue_!QYp0Z8+EDT0{p0$qO)G+x8Lb@{c?M- zI@r6SoRoLyQ84qTn-(9rBS5(Q5&LHchk-b^1HQxNu)!f?Uz;hAXT~l6^jEP0seS5D zGZ9Mou2s$ILX^KL^UP9V!>OF;oH=#f@jYGn19^;sI#N_l1;pOY7LLy6vt}aKbuSJs zSbFAeG?a!&o}sU{m5%jg{?XIqE3XmAEUJ#fF&Kx(uo+y_@312C;(hO7^MAshuIHL& zmLYEH5Ab^#3@bzc9f2Wa6hI$VdTC`FdA?~ng(yfW#PvcDzD>+Ulvd| zfJ>HP;lGlBKAmJQ^0nH5{0)FtR_L~4%c*6A2JG1KH|Cz4cx%<=r2(DUgH2d$AU>AKns?MVy F{0;HicBTLT diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt b/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt deleted file mode 100644 index 6552f496..00000000 --- a/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt +++ /dev/null @@ -1,30 +0,0 @@ -info face="Noto Sans CJK TC Medium" size=-16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=24 base=19 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="noto-sans-cjk-tc-medium-16_0.png" -chars count=26 -char id=10 x=50 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 -char id=32 x=54 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 -char id=48 x=18 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=49 x=217 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=50 x=226 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=51 x=235 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=52 x=197 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=53 x=244 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=54 x=0 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=55 x=207 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 -char id=56 x=9 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=57 x=26 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 -char id=19968 x=34 y=16 width=15 height=2 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 -char id=19971 x=109 y=0 width=14 height=14 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=19977 x=167 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 -char id=20061 x=0 y=0 width=14 height=16 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=20108 x=182 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 -char id=20116 x=151 y=0 width=15 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 -char id=20843 x=93 y=0 width=15 height=14 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 -char id=20845 x=15 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=21313 x=31 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=22235 x=63 y=0 width=14 height=15 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26085 x=139 y=0 width=11 height=14 xoffset=3 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26143 x=124 y=0 width=14 height=14 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26376 x=78 y=0 width=14 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 -char id=26399 x=47 y=0 width=15 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16_0.png b/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16_0.png deleted file mode 100644 index 62e918e913a3db1f89fa4c09f4c7351441234ce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1709 zcmchY|3A|S1HeBYi-|LvLbC4mT;U$m&9}$5@~wQ$#c_9y45K(@WbGJ+(~vR_%MHyI zIXtd>iDR_18RAaHle@AoBVS@>W|fWb-1AR7?;qZ;_kZxd{dJ(Pp3YGn008v-{k%c| z0Q@^aK>Ke4=_Xr`0YK{qe=pB()2d~Y?(xVKlOaW`M@{$bqTH89sCouRLXa+I@YZDF zbOdoQy6UhoT@V~=Q%r+bK%RLG8cu{4JvcFFQ5;Mx`p5hQ_!^dK zP4TvGVINjTaT~d%HF(92{VC;BJNb@qXE{CU3JjHt{%)u8uG(+oaJM{XoBMkQ zgCeuWgTz|w&x{9+aCY$g+7zFz-5kSevg8wVcH5D{idF20E(sofnrl0f)i?c)SrpVI zJuEaxXgLl%0lg5Vrf{vr?;hwW?E5jPO zGzQ3~tCaZmApJDOKjk>6WPYKX(Y&EA*|?Z)nnmeZTlhWiIv#+PE~0rt zbZ+EO&DId>G2|tzD`;tmHU?U&cC~Wk=l4Ejvt+Jz8lGjbiLi|;$ndWYK{NsaZ-Y&s zlP>c`=KOryM@t&Bko%rL9;5wWbM?6i4Kv(vb@1%vy2pyYAYsAoiZ42}eOB-i8g&`W zfU;hE>NbN?soh`I-bIY`M$}XzUeSoW!=$D(HctZ`TdAwUHYUD;fgiTzNf69dN#t&F zrzoV(jdKk%4}R&0ZXs+Lj7cng2O~Pl0;g~)tGF8~ylLngxrOr1;7m*i0dac!t(zRu zSJ!FDeY=o>s@4N%b*5ROxnrR?m^s5m=@Fubn?5#l)ye8!@P*4&Bq5U|9G%q63?xI; z=bpNfLK5h-*=WkkKPT>YS3<>$m}Y@sPpT*BtGnkat=9a*VRq$YhDuSR%bqE;4zF7%Pz2nZK2K2g0@Rpp)N_1xWDhHBm!rv1ne;F#+J zeyOS28HcFkY@J{m`SJ~B>qx}$NpM|}ki#kw>&E@y(X~&1ql+o&u$)Wdni8|En^IvA zffQ4?Hrp&_ujjm%MC%uRGoHjb0yS1Ka$}QR*aWiB%-3|rDY=K_i@4LTA2y)4Oi80* z92`Ych1kzDhY~*C7~P}n7++8)sz3g_(ph-RwTOUg;23#Q4*p_PWEX>`k8&>(7n(kY zFYzn-p!BQMAk8Ur?d^t|z_re9iah8tR@Phyu6BmF*I#~vZ7 zG-G|@(^EuO-;HbKEzuvY<*b_{%H>`}B=dM;V7X_~SwPDnRp{(Uo$N8!>TZgV5C$%= zO?2O?4tr!6kO$*vtXM#Pj(IW2hcokv9JJ~ykv zj#5Xg$R6=w)nR=83(q)^mA_iBFJIalGh=Z7G%yI5A29H|ybUu`WPpreK-8X(V%Y}!e);1cwy zcJ`%?>H7^3!SwTc`zCmX9`q6^k5PPmg!&kQ`swb$>q&+MTho3gbIR&d;CZVHlorFY zxWUs;Y}!l5ec+w@NGDEV&~xSHj}BFca%k-U{kOd-)khs$(`VwFPD*cU)X^y?YBGUw vASz10{L+u4gy5|mP8C>0ApXyk?F)He**5q|VL+wD|32jJ9q83^22cGj>%=90 diff --git a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc deleted file mode 100644 index 70857ad9..00000000 --- a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Noto Sans -fontFile= -charSet=0 -fontSize=-16 -aa=1 -scaleH=100 -useSmoothing=1 -isBold=1 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=1 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=32,48-57,1040-1071 - -# imported icon images diff --git a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt deleted file mode 100644 index c4e15ff6..00000000 --- a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt +++ /dev/null @@ -1,47 +0,0 @@ -info face="Noto Sans" size=-16 bold=1 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=22 base=17 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="noto-sans-rus-bold-16_0.png" -chars count=43 -char id=32 x=250 y=13 width=3 height=1 xoffset=-1 yoffset=21 xadvance=4 page=0 chnl=15 -char id=48 x=163 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 -char id=49 x=242 y=13 width=7 height=11 xoffset=0 yoffset=6 xadvance=9 page=0 chnl=15 -char id=50 x=153 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 -char id=51 x=143 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 -char id=52 x=211 y=13 width=10 height=11 xoffset=-1 yoffset=6 xadvance=9 page=0 chnl=15 -char id=53 x=232 y=13 width=9 height=11 xoffset=0 yoffset=6 xadvance=9 page=0 chnl=15 -char id=54 x=133 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 -char id=55 x=222 y=13 width=9 height=11 xoffset=0 yoffset=6 xadvance=9 page=0 chnl=15 -char id=56 x=123 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 -char id=57 x=183 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 -char id=1040 x=180 y=0 width=13 height=12 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15 -char id=1041 x=103 y=13 width=9 height=12 xoffset=1 yoffset=5 xadvance=10 page=0 chnl=15 -char id=1042 x=81 y=13 width=10 height=12 xoffset=1 yoffset=5 xadvance=11 page=0 chnl=15 -char id=1043 x=202 y=13 width=8 height=12 xoffset=1 yoffset=5 xadvance=9 page=0 chnl=15 -char id=1044 x=30 y=0 width=14 height=15 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15 -char id=1045 x=193 y=13 width=8 height=12 xoffset=1 yoffset=5 xadvance=9 page=0 chnl=15 -char id=1046 x=58 y=0 width=17 height=12 xoffset=-1 yoffset=5 xadvance=15 page=0 chnl=15 -char id=1047 x=92 y=13 width=10 height=12 xoffset=0 yoffset=5 xadvance=10 page=0 chnl=15 -char id=1048 x=12 y=16 width=11 height=12 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 -char id=1049 x=0 y=0 width=11 height=16 xoffset=1 yoffset=1 xadvance=13 page=0 chnl=15 -char id=1050 x=24 y=16 width=11 height=12 xoffset=1 yoffset=5 xadvance=11 page=0 chnl=15 -char id=1051 x=221 y=0 width=12 height=12 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15 -char id=1052 x=194 y=0 width=13 height=12 xoffset=1 yoffset=5 xadvance=15 page=0 chnl=15 -char id=1053 x=59 y=13 width=10 height=12 xoffset=1 yoffset=5 xadvance=12 page=0 chnl=15 -char id=1054 x=166 y=0 width=13 height=12 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 -char id=1055 x=48 y=16 width=10 height=12 xoffset=1 yoffset=5 xadvance=12 page=0 chnl=15 -char id=1056 x=246 y=0 width=9 height=12 xoffset=1 yoffset=5 xadvance=10 page=0 chnl=15 -char id=1057 x=70 y=13 width=10 height=12 xoffset=0 yoffset=5 xadvance=10 page=0 chnl=15 -char id=1058 x=113 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 -char id=1059 x=208 y=0 width=12 height=12 xoffset=0 yoffset=5 xadvance=11 page=0 chnl=15 -char id=1060 x=109 y=0 width=14 height=12 xoffset=0 yoffset=5 xadvance=14 page=0 chnl=15 -char id=1061 x=152 y=0 width=13 height=12 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15 -char id=1062 x=45 y=0 width=12 height=15 xoffset=1 yoffset=5 xadvance=12 page=0 chnl=15 -char id=1063 x=0 y=17 width=11 height=12 xoffset=0 yoffset=5 xadvance=12 page=0 chnl=15 -char id=1064 x=93 y=0 width=15 height=12 xoffset=1 yoffset=5 xadvance=17 page=0 chnl=15 -char id=1065 x=12 y=0 width=17 height=15 xoffset=1 yoffset=5 xadvance=18 page=0 chnl=15 -char id=1066 x=138 y=0 width=13 height=12 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15 -char id=1067 x=124 y=0 width=13 height=12 xoffset=1 yoffset=5 xadvance=14 page=0 chnl=15 -char id=1068 x=173 y=13 width=9 height=12 xoffset=1 yoffset=5 xadvance=10 page=0 chnl=15 -char id=1069 x=234 y=0 width=11 height=12 xoffset=0 yoffset=5 xadvance=11 page=0 chnl=15 -char id=1070 x=76 y=0 width=16 height=12 xoffset=1 yoffset=5 xadvance=17 page=0 chnl=15 -char id=1071 x=36 y=16 width=11 height=12 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16_0.png b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16_0.png deleted file mode 100644 index 42d424ee6675c2b299eb1127b7e5d4c473691100..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2561 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 GPy8=AdCNZl diff --git a/resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc b/resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc deleted file mode 100644 index 7d9f47cf..00000000 --- a/resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Titillium Web -fontFile= -charSet=0 -fontSize=-54 -aa=1 -scaleH=100 -useSmoothing=1 -isBold=1 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=48-57 - -# imported icon images diff --git a/resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt b/resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt deleted file mode 100644 index bc476b44..00000000 --- a/resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt +++ /dev/null @@ -1,14 +0,0 @@ -info face="Titillium Web" size=-54 bold=1 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=38 base=38 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="titillium-web-bold-54_0.png" -chars count=10 -char id=48 x=0 y=0 width=30 height=38 xoffset=0 yoffset=0 xadvance=30 page=0 chnl=15 -char id=49 x=230 y=0 width=21 height=36 xoffset=3 yoffset=1 xadvance=30 page=0 chnl=15 -char id=50 x=177 y=0 width=26 height=37 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 -char id=51 x=122 y=0 width=26 height=38 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 -char id=52 x=0 y=39 width=28 height=36 xoffset=1 yoffset=1 xadvance=30 page=0 chnl=15 -char id=53 x=149 y=0 width=27 height=37 xoffset=2 yoffset=1 xadvance=30 page=0 chnl=15 -char id=54 x=62 y=0 width=29 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 -char id=55 x=204 y=0 width=25 height=37 xoffset=3 yoffset=1 xadvance=30 page=0 chnl=15 -char id=56 x=31 y=0 width=30 height=38 xoffset=0 yoffset=0 xadvance=30 page=0 chnl=15 -char id=57 x=92 y=0 width=29 height=38 xoffset=0 yoffset=0 xadvance=30 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/titillium-web-bold-54_0.png b/resources-rectangle-205x148/fonts/titillium-web-bold-54_0.png deleted file mode 100644 index e35a6edde9d259d1b08f0145fee760a528c8a5df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3515 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 diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc b/resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc deleted file mode 100644 index 04f032e7..00000000 --- a/resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc +++ /dev/null @@ -1,55 +0,0 @@ -# AngelCode Bitmap Font Generator configuration file -fileVersion=1 - -# font settings -fontName=Titillium Web Light -fontFile= -charSet=0 -fontSize=-54 -aa=1 -scaleH=100 -useSmoothing=1 -isBold=0 -isItalic=0 -useUnicode=1 -disableBoxChars=1 -outputInvalidCharGlyph=0 -dontIncludeKerningPairs=0 -useHinting=1 -renderFromOutline=0 -useClearType=0 - -# character alignment -paddingDown=0 -paddingUp=0 -paddingRight=0 -paddingLeft=0 -spacingHoriz=1 -spacingVert=1 -useFixedHeight=0 -forceZero=0 - -# output file -outWidth=256 -outHeight=256 -outBitDepth=8 -fontDescFormat=0 -fourChnlPacked=0 -textureFormat=png -textureCompression=0 -alphaChnl=1 -redChnl=0 -greenChnl=0 -blueChnl=0 -invA=0 -invR=0 -invG=0 -invB=0 - -# outline -outlineThickness=0 - -# selected chars -chars=48-57 - -# imported icon images diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt b/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt deleted file mode 100644 index 599a9744..00000000 --- a/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt +++ /dev/null @@ -1,15 +0,0 @@ -info face="Titillium Web Light" size=-54 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 -common lineHeight=38 base=38 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 -page id=0 file="titillium-web-light-54_0.png" -chars count=10 -char id=48 x=30 y=0 width=28 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 -char id=49 x=0 y=39 width=17 height=36 xoffset=5 yoffset=1 xadvance=30 page=0 chnl=15 -char id=50 x=170 y=0 width=25 height=37 xoffset=3 yoffset=0 xadvance=30 page=0 chnl=15 -char id=51 x=116 y=0 width=26 height=38 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 -char id=52 x=222 y=0 width=29 height=36 xoffset=1 yoffset=1 xadvance=30 page=0 chnl=15 -char id=53 x=143 y=0 width=26 height=37 xoffset=2 yoffset=1 xadvance=30 page=0 chnl=15 -char id=54 x=88 y=0 width=27 height=38 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 -char id=55 x=196 y=0 width=25 height=37 xoffset=3 yoffset=1 xadvance=30 page=0 chnl=15 -char id=56 x=0 y=0 width=29 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 -char id=57 x=59 y=0 width=28 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 -char id=58 x=20 y=39 width=10 height=38 xoffset=1 yoffset=0 xadvance=10 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54_0.png b/resources-rectangle-205x148/fonts/titillium-web-light-54_0.png deleted file mode 100644 index 143345f3ba86b7907900c270abdb3eea734ba848..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3782 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 NssVqZTBTwe^*<`I5Yhku diff --git a/resources-rectangle-205x148/layouts/layout.xml b/resources-rectangle-205x148/layouts/layout.xml deleted file mode 100644 index 1c8140d2..00000000 --- a/resources-rectangle-205x148/layouts/layout.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - :left - 6 - 148 - 2 - - - - :right - 6 - 148 - 2 - - - - 42 - 121 - 122 - 138 - 120 - 14 - 191 - - - - 92 - 174 - 14 - 33 - 24 - - - - - - 23 - 80 - 26 - 20 - - - - 137 - 85 - - - - - - - - -5 - - - 4 - - - - 45 - 102 - 87 - 7 - 3 - - - \ No newline at end of file diff --git a/resources-rectangle-205x148/settings/settings.xml b/resources-rectangle-205x148/settings/settings.xml deleted file mode 100644 index 67715ed0..00000000 --- a/resources-rectangle-205x148/settings/settings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/resources-rectangle-240x240/layouts/layout.xml b/resources-rectangle-240x240/layouts/layout.xml index b04c3918..f2f41285 100644 --- a/resources-rectangle-240x240/layouts/layout.xml +++ b/resources-rectangle-240x240/layouts/layout.xml @@ -19,6 +19,7 @@ 49 142 + 190 206 222 202 diff --git a/resources-rectangle-320x360/layouts/layout.xml b/resources-rectangle-320x360/layouts/layout.xml index 34e8d8a4..469f2708 100644 --- a/resources-rectangle-320x360/layouts/layout.xml +++ b/resources-rectangle-320x360/layouts/layout.xml @@ -19,6 +19,7 @@ 65 189 + 285 309 333 303 diff --git a/resources-round-208x208/layouts/layout.xml b/resources-round-208x208/layouts/layout.xml index 2f91f9d9..ed7e3aab 100644 --- a/resources-round-208x208/layouts/layout.xml +++ b/resources-round-208x208/layouts/layout.xml @@ -23,6 +23,7 @@ 63 81 + 152 165 181 163 diff --git a/resources-round-218x218-ciq_1.x/layouts/layout.xml b/resources-round-218x218-ciq_1.x/layouts/layout.xml deleted file mode 100644 index 84ee8b09..00000000 --- a/resources-round-218x218-ciq_1.x/layouts/layout.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - :left - 8 - 138 - 2 - - - - :right - 8 - 138 - 2 - - - - - 8 - - - - 67 - 84 - 170 - 186 - 166 - 40 - 178 - - - - 69 - 149 - 24 - 45 - 28 - - - - - - 30 - 109 - 30 - 22 - - - - 149 - 129 - - - - - - - - - 49 - 146 - 94 - 9 - 3 - - - \ No newline at end of file diff --git a/resources-round-218x218/layouts/layout.xml b/resources-round-218x218/layouts/layout.xml index 5e8978c5..a7be5f0b 100644 --- a/resources-round-218x218/layouts/layout.xml +++ b/resources-round-218x218/layouts/layout.xml @@ -18,6 +18,7 @@ 67 84 + 157 170 186 166 diff --git a/resources-round-260x260/layouts/layout.xml b/resources-round-260x260/layouts/layout.xml index 53bb4eda..8f523394 100644 --- a/resources-round-260x260/layouts/layout.xml +++ b/resources-round-260x260/layouts/layout.xml @@ -18,6 +18,7 @@ 85 90 + 196 212 228 208 diff --git a/resources-round-280x280/layouts/layout.xml b/resources-round-280x280/layouts/layout.xml index a73c487d..2f5d262c 100644 --- a/resources-round-280x280/layouts/layout.xml +++ b/resources-round-280x280/layouts/layout.xml @@ -18,6 +18,7 @@ 94 92 + 210 228 246 223 diff --git a/resources-round-360x360/layouts/layout.xml b/resources-round-360x360/layouts/layout.xml index 5f3baefc..7ae1ddda 100644 --- a/resources-round-360x360/layouts/layout.xml +++ b/resources-round-360x360/layouts/layout.xml @@ -19,6 +19,7 @@ 116 128 + 266 286 312 280 diff --git a/resources-round-390x390/layouts/layout.xml b/resources-round-390x390/layouts/layout.xml index 45aa5d98..303c58cd 100644 --- a/resources-round-390x390/layouts/layout.xml +++ b/resources-round-390x390/layouts/layout.xml @@ -19,6 +19,7 @@ 123 144 + 286 312 338 307 diff --git a/resources-round-416x416/layouts/layout.xml b/resources-round-416x416/layouts/layout.xml index 6c46bb42..301e9039 100644 --- a/resources-round-416x416/layouts/layout.xml +++ b/resources-round-416x416/layouts/layout.xml @@ -19,6 +19,7 @@ 136 144 + 310 336 362 331 diff --git a/resources-round-454x454/layouts/layout.xml b/resources-round-454x454/layouts/layout.xml index 228f14bb..236987f6 100644 --- a/resources-round-454x454/layouts/layout.xml +++ b/resources-round-454x454/layouts/layout.xml @@ -19,6 +19,7 @@ 136 157 + 337 366 395 361 diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 04a85b05..3599bdb5 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-semiround-215x180-ciq_1.x/layouts/layout.xml b/resources-semiround-215x180-ciq_1.x/layouts/layout.xml deleted file mode 100644 index ddf82b7f..00000000 --- a/resources-semiround-215x180-ciq_1.x/layouts/layout.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - :left - 6 - 180 - 2 - - - - :right - 6 - 180 - 2 - - - - - 6 - - - - 65 - 85 - 147 - 163 - 145 - 42 - 173 - - - - 68 - 147 - 12 - 31 - 24 - - - - - - 28 - 90 - 28 - 20 - - - - 147 - 109 - - - - - - - 1 - - - - 46 - 126 - 93 - 7 - 3 - - - \ No newline at end of file diff --git a/resources-semiround-215x180/layouts/layout.xml b/resources-semiround-215x180/layouts/layout.xml deleted file mode 100644 index bf300a65..00000000 --- a/resources-semiround-215x180/layouts/layout.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - :left - 6 - 180 - 2 - - - - :right - 6 - 180 - 2 - - - - 65 - 85 - 147 - 163 - 145 - 42 - 173 - - - - 68 - 147 - 12 - 31 - 24 - - - - - - 28 - 90 - 28 - 20 - - - - 147 - 109 - - - - - - - 1 - - - - 46 - 126 - 93 - 7 - 3 - - - \ No newline at end of file diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index ad97e168..7cfd7483 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 855e0dbe..61bb38ed 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 3f1d43ba..a911f7dd 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index d7b9bdf3..b6609b46 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-vivoactive/settings/properties.xml b/resources-vivoactive/settings/properties.xml deleted file mode 100644 index cb2de3ec..00000000 --- a/resources-vivoactive/settings/properties.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -1 - 3 - - - 4 - - \ No newline at end of file diff --git a/resources-vivoactive/settings/settings.xml b/resources-vivoactive/settings/settings.xml deleted file mode 100644 index e16ed122..00000000 --- a/resources-vivoactive/settings/settings.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - @Strings.ThemeBlueDark - @Strings.ThemePinkDark - @Strings.ThemeRedDark - @Strings.ThemeGreenDark - - - @Strings.ThemeCornflowerBlueDark - @Strings.ThemeLemonCreamDark - @Strings.ThemeVividYellowDark - - @Strings.ThemeCornYellowDark - @Strings.ThemeDaygloOrangeDark - @Strings.ThemeMonoDark - @Strings.ThemeMonoLight - @Strings.ThemeBlueLight - @Strings.ThemeGreenLight - @Strings.ThemeRedLight - @Strings.ThemeDaygloOrangeLight - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - @Strings.Steps - - - @Strings.Battery - @Strings.CaloriesManualGoal - @Strings.Off - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - @Strings.Battery - @Strings.BatteryHidePercentage - @Strings.Notifications - @Strings.Calories - @Strings.Distance - @Strings.Alarms - @Strings.Altitude - - - @Strings.SunriseSunset - - - - - - - - - - diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 9e266c0e..78fe660d 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 5195171f..d075f05d 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -124,4 +124,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? + Show weather station name? diff --git a/resources/layouts/layout.xml b/resources/layouts/layout.xml index 149ad044..329104db 100644 --- a/resources/layouts/layout.xml +++ b/resources/layouts/layout.xml @@ -19,6 +19,7 @@ 76 88 + 176 192 208 188 diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index eedac8f8..18fa5645 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -29,6 +29,8 @@ false 0 + true + 0 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 222a6c7b..e2558b00 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -236,6 +236,10 @@ + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index b017cd3b..ef9dd56b 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.0 + Crystal-Tesla V2.18.1 Theme Hours Colour @@ -123,5 +123,5 @@ Use Complications if available Get Tesla info from Tesla-Link Complications Which vehicle to show? - + Show weather station name? diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index cb7c3ae6..d1688ce2 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -83,30 +83,30 @@ class BackgroundService extends Sys.ServiceDelegate { } if (_token == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); + //DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { makeWebPost(refreshToken, method(:onReceiveToken)); } else { - /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); + //DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); } return; } if (_vehicle_id == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); + //DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); return; } - /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); + //DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); } (:background_method) function onReceiveToken(responseCode, responseData) { - /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); + //DEBUG*/ logMessage("onReceiveToken: " + responseCode); var teslaInfo = Bg.getBackgroundData(); if (teslaInfo == null) { @@ -131,7 +131,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onReceiveVehicles(responseCode, responseData) { - /*DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); + //DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); var teslaInfo = Bg.getBackgroundData(); if (teslaInfo == null) { @@ -182,8 +182,8 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onReceiveVehicleData(responseCode, responseData) { - /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); - /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + //DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); + //DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); var teslaInfo = Bg.getBackgroundData(); if (teslaInfo == null) { @@ -224,7 +224,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("VehicleID", null); _vehicle_id = null; } - /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); + //DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); return; } @@ -232,7 +232,7 @@ class BackgroundService extends Sys.ServiceDelegate { else if (responseCode == 401) { var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { - /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); + //DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); makeWebPost(refreshToken, method(:onReceiveToken)); return; } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index cf7f5b06..3c40f7a5 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -32,7 +32,7 @@ class CrystalApp extends App.AppBase { // Return the initial view of your application here function getInitialView() { - /*DEBUG*/ logMessage("Getting initial view"); + //DEBUG*/ logMessage("Getting initial view"); if (WatchUi has :WatchFaceDelegate) { mView = new CrystalView(); @@ -54,7 +54,7 @@ class CrystalApp extends App.AppBase { // New app settings have been received so trigger a UI update (:background_method) function getServiceDelegate() { - /*DEBUG*/ logMessage("Getting service delegate"); + //DEBUG*/ logMessage("Getting service delegate"); return [new BackgroundService()]; } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 68a2ea7f..4856647d 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -66,6 +66,8 @@ class CrystalView extends Ui.WatchFace { var mLocalCityLon; private var mUseComplications; + var mDigitStyle; + var mShowWeatherStationName; // N.B. Not all watches that support SDK 2.3.0 support per-second updates e.g. 735xt. private const PER_SECOND_UPDATES_SUPPORTED = Ui.WatchFace has :onPartialUpdate; @@ -145,7 +147,7 @@ class CrystalView extends Ui.WatchFace { // the state of this View and prepare it to be shown. This includes // loading resources into memory. */ function onShow() { - /*DEBUG*/ logMessage("View showing"); + //DEBUG*/ logMessage("View showing"); } // Set flag to respond to settings change on next full draw (onUpdate()), as we may be in 1Hz (lower power) mode, and cannot @@ -186,6 +188,9 @@ class CrystalView extends Ui.WatchFace { mUseComplications = $.getBoolProperty("UseComplications", false); gTeslaComplication = $.getBoolProperty("TeslaLink", false); + mDigitStyle = $.getIntProperty("GoalMeterDigitsStyle", 0); + mShowWeatherStationName = $.getBoolProperty("ShowWeatherStationName", true); + // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { @@ -214,91 +219,95 @@ class CrystalView extends Ui.WatchFace { // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see function ReadWeather(fromComplication) { var weather; + var result; if (fromComplication) { } - else { + else if (Toybox has :Weather && Toybox.Weather has :getCurrentConditions) { weather = Weather.getCurrentConditions(); - } - var result; - if (weather != null) { - var temperature = $.validateNumber(weather.temperature, null); // In Celcius - if (temperature == null) { - temperature = "NaN"; - } - else { - if (Sys.getDeviceSettings().temperatureUnits == System.UNIT_STATUTE) { - temperature = (temperature * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + if (weather != null) { + var temperature = $.validateNumber(weather.temperature, null); // In Celcius + if (temperature == null) { + temperature = "NaN"; } + else { + if (Sys.getDeviceSettings().temperatureUnits == System.UNIT_STATUTE) { + temperature = (temperature * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + } - temperature = temperature.format(INTEGER_FORMAT) + "°"; - } - - var humidity = $.validateNumber(weather.relativeHumidity, null); - if (humidity == null) { - humidity = "NaN"; - } - else { - humidity = humidity.format(INTEGER_FORMAT) + "%"; - } + temperature = temperature.format(INTEGER_FORMAT) + "°"; + } + + var humidity = $.validateNumber(weather.relativeHumidity, null); + if (humidity == null) { + humidity = "NaN"; + } + else { + humidity = humidity.format(INTEGER_FORMAT) + "%"; + } - mWeatherStationName = $.validateString(weather.observationLocationName, null); - - var icon = "01"; - var day = "d"; - var myLocation = weather.observationLocationPosition; - var now = Time.now(); - if (myLocation != null) { - if (Toybox.Weather has :getSunrise) { - var sunrise = Weather.getSunrise(myLocation, now); - var sunset = Weather.getSunset(myLocation, now); - - if (sunrise != null and sunset != null) { - var sinceSunrise = sunrise.compare(now); - var sinceSunset = now.compare(sunset); - if (sinceSunrise >= 0 || sinceSunset >= 0) { - day = "n"; + mWeatherStationName = $.validateString(weather.observationLocationName, null); + + var icon = "01"; + var day = "d"; + var myLocation = weather.observationLocationPosition; + var now = Time.now(); + if (myLocation != null) { + if (Toybox.Weather has :getSunrise) { + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); + + if (sunrise != null and sunset != null) { + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); + if (sinceSunrise >= 0 || sinceSunset >= 0) { + day = "n"; + } } } - } - else { - //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); - var myLocationArray = myLocation.toDegrees(); - now = Gregorian.info(now, Time.FORMAT_SHORT); - - // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at - // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). - now = now.hour + ((now.min + 1) / 60.0); - //logMessage(now); - - // Get today's sunrise/sunset times in current time zone. - var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); - //logMessage(sunTimes); - //logMessage("now=" + now); - //logMessage("sunTimes=" + sunTimes); - // If sunrise/sunset happens today. - var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); - if (sunriseSunsetToday) { - if (now < sunTimes[0] || now > sunTimes[1]) { - day = "n"; + else { + //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); + var myLocationArray = myLocation.toDegrees(); + now = Gregorian.info(now, Time.FORMAT_SHORT); + + // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at + // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). + now = now.hour + ((now.min + 1) / 60.0); + //logMessage(now); + + // Get today's sunrise/sunset times in current time zone. + var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); + //logMessage(sunTimes); + //logMessage("now=" + now); + //logMessage("sunTimes=" + sunTimes); + // If sunrise/sunset happens today. + var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); + if (sunriseSunsetToday) { + if (now < sunTimes[0] || now > sunTimes[1]) { + day = "n"; + } } } } - } - var condition = $.validateNumber(weather.condition, null); - if (condition != null && condition < 53) { - icon = (mGarminToOWM[condition]).format("%02d") + day; - //logMessage("icon=" + icon); + var condition = $.validateNumber(weather.condition, null); + if (condition != null && condition < 53) { + icon = (mGarminToOWM[condition]).format("%02d") + day; + //logMessage("icon=" + icon); + } + else { + //DEBUG*/ logMessage("Icon index " + condition + " is invalid"); + } + result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; + //DEBUG*/ logMessage("Weather at " + mWeatherStationName + " is " + result); } else { - /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); + result = { "cod" => 404 }; + /*DEBUG*/ logMessage("No weather data, returning cod = 404"); } - result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; - /*DEBUG*/ logMessage("Weather at " + mWeatherStationName + " is " + result); } else { - result = { "cod" => 404 }; - /*DEBUG*/ logMessage("No weather data, returning cod = 404"); + result = { "cod" => 400 }; + /*DEBUG*/ logMessage("No weather data, returning cod = 400"); } Storage.setValue("WeatherInfo", result); Storage.setValue("NewWeatherInfo", true); @@ -423,6 +432,7 @@ class CrystalView extends Ui.WatchFace { // Update the view function onUpdate(dc) { //Sys.println("onUpdate()"); + /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); // If burn-in protection has changed, set layout appropriate to new burn-in protection state. // If turning on burn-in protection, free memory for regular watch face drawables by clearing references. This means that @@ -622,12 +632,12 @@ class CrystalView extends Ui.WatchFace { // crash in GoalMeter.getSegmentScale(). // Sanity check. I've seen weird Invalid Value and "System Error" in DataArea.setGoalValues:48 and :61. Make sure the data is valid if (values[:isValid] && (!(values[:max] instanceof Lang.Number || values[:max] instanceof Lang.Float) || values[:max] < 1)) { - /*DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); + //DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); values[:max] = 1; values[:isValid] = false; } if (values[:isValid] && (!(values[:current] instanceof Lang.Number || values[:current] instanceof Lang.Float))) { - /*DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); + //DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); values[:current] = 0; values[:isValid] = false; } @@ -649,7 +659,7 @@ class CrystalView extends Ui.WatchFace { // state of this View here. This includes freeing resources from // memory */ function onHide() { - /*DEBUG*/ logMessage("View hidding"); + //DEBUG*/ logMessage("View hidding"); } // The user has just looked at their watch. Timers and animations may be started here. @@ -779,7 +789,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - /*DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes if (Toybox has :Complications && App.getApp().getView().useComplications()) { @@ -886,11 +896,11 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { function isWithin(x, y, startX, startY, spacingX, spacingY, field) { if (x > startX && x < startX + spacingX && y > startY and y < startY + spacingY) { - /*DEBUG*/ logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); + //DEBUG*/ logMessage("True: " + x + "/" + y + " is within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); return field; } else { - /*DEBUG*/ logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); + //DEBUG*/ logMessage("False: " + x + "/" + y + " is NOT within " + startX + "/" + startY + " and " + (startX + spacingX).toString() + "/" + (startY + spacingY).toString()); return ""; } } diff --git a/source/DataArea.mc b/source/DataArea.mc index 92bf5165..5b1981b9 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -9,6 +9,7 @@ using Toybox.Application.Properties; class DataArea extends Ui.Drawable { + private var mRow0Y; private var mRow1Y; private var mRow2Y; @@ -31,6 +32,7 @@ class DataArea extends Ui.Drawable { function initialize(params) { Drawable.initialize(params); + mRow0Y = params[:row0Y]; mRow1Y = params[:row1Y]; mRow2Y = params[:row2Y]; @@ -49,7 +51,7 @@ class DataArea extends Ui.Drawable { mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY || mLeftGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { if (leftValues[:isValid]) { - /*DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); + //DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); } mLeftGoalCurrent = null; mLeftGoalMax = null; @@ -64,7 +66,7 @@ class DataArea extends Ui.Drawable { mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY || mRightGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { if (rightValues[:isValid]) { - /*DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); + //DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); } mRightGoalCurrent = null; mRightGoalMax = null; @@ -76,16 +78,22 @@ class DataArea extends Ui.Drawable { drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, mRightGoalstaled, Graphics.TEXT_JUSTIFY_RIGHT); var view = App.getApp().getView(); - var city = view.mLocalCityName; - var fromWeather = false; - - if (city == null || city.length() == 0) { - city = view.mWeatherStationName; - fromWeather = true; + var city = view.mWeatherStationName; + if (view.mShowWeatherStationName && city != null && city.length() > 0) { + dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + locX + (width / 2), + mRow0Y, + gNormalFont, + // Limit string length. + city.substring(0, 16), + Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER + ); } // #78 Setting with value of empty string may cause corresponding property to be null. - if ((city != null && city.length() > 0)) { + city = view.mLocalCityName; + if (city != null && city.length() > 0) { // Time zone 1 city. dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); dc.drawText( @@ -98,42 +106,40 @@ class DataArea extends Ui.Drawable { ); // Time zone 1 time. - if (!fromWeather) { - var time; - - if (view.mLocalCityLat != null && view.mLocalCityLat >= -90.0 && view.mLocalCityLat <= 90.0 && view.mLocalCityLon != null && view.mLocalCityLon >= -90.0 && view.mLocalCityLon <= 90.0) { - try { - var where = new Position.Location({ - :latitude => view.mLocalCityLat, - :longitude => view.mLocalCityLon, - :format => :degrees - }); - - - var local = Gregorian.localMoment(where, Time.now()); - local = Gregorian.info(local, Time.FORMAT_SHORT); - - time = $.getFormattedTime(local.hour, local.min); - time = time[:hour] + ":" + time[:min] + time[:amPm]; - } - catch (e) { - time = "???"; - } + var time; + if (view.mLocalCityLat != null && view.mLocalCityLat >= -90.0 && view.mLocalCityLat <= 90.0 && view.mLocalCityLon != null && view.mLocalCityLon >= -90.0 && view.mLocalCityLon <= 90.0) { + try { + var where = new Position.Location({ + :latitude => view.mLocalCityLat, + :longitude => view.mLocalCityLon, + :format => :degrees + }); + + + var local = Gregorian.localMoment(where, Time.now()); + local = Gregorian.info(local, Time.FORMAT_SHORT); + + time = $.getFormattedTime(local.hour, local.min); + time = time[:hour] + ":" + time[:min] + time[:amPm]; } - else { + catch (e) { time = "???"; } - - dc.setColor(gMonoLightColour, Gfx.COLOR_TRANSPARENT); - dc.drawText( - locX + (width / 2), - mRow2Y, - gNormalFont, - time, - Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER - ); } - } else { + else { + time = "???"; + } + + dc.setColor(gMonoLightColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + locX + (width / 2), + mRow2Y, + gNormalFont, + time, + Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER + ); + } + else { drawGoalValues(dc, locX, mLeftGoalCurrent, mLeftGoalMax, Graphics.TEXT_JUSTIFY_LEFT); drawGoalValues(dc, locX + width, mRightGoalCurrent, mRightGoalMax, Graphics.TEXT_JUSTIFY_RIGHT); } @@ -175,7 +181,7 @@ class DataArea extends Ui.Drawable { } function drawGoalValues(dc, x, currentValue, maxValue, align) { - var digitStyle = $.getIntProperty("GoalMeterDigitsStyle", 0); + var digitStyle = App.getApp().getView().mDigitStyle; // #107 Only draw values if digit style is not Hidden. if (digitStyle != 2 /* HIDDEN */) { diff --git a/source/DataFields.mc b/source/DataFields.mc index 1ab865c5..7ffe17c1 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -42,9 +42,6 @@ enum /* FIELD_TYPES */ { class DataFields extends Ui.Drawable { - private var mApp; - private var mView; - var mLeft; var mRight; var mTop; @@ -79,8 +76,7 @@ class DataFields extends Ui.Drawable { // Cache FieldCount setting, and determine appropriate maximum field length. function onSettingsChanged() { - mApp = App.getApp(); - mView = mApp.getView(); + var view = App.getApp().getView(); // #123 Protect against null or unexpected type e.g. String. mFieldCount = $.getIntProperty("FieldCount", 3); @@ -88,14 +84,14 @@ class DataFields extends Ui.Drawable { // #116 Handle FieldCount = 0 correctly. mMaxFieldLength = [0, 8, 6, 4][mFieldCount]; - mHasLiveHR = mView.hasField(FIELD_TYPE_HR_LIVE_5S); + mHasLiveHR = view.hasField(FIELD_TYPE_HR_LIVE_5S); - if (!mView.hasField(FIELD_TYPE_WEATHER)) { + if (!view.hasField(FIELD_TYPE_WEATHER)) { mWeatherIconsFont = null; mWeatherIconsSubset = null; } - if (Toybox has :Complications && mView.useComplications()) { + if (Toybox has :Complications && view.useComplications()) { var complications = [{"type" => FIELD_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => FIELD_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS}, {"type" => FIELD_FLOOR_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, @@ -106,12 +102,12 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_TYPE_SUNRISE_SUNSET, "complicationType" => Complications.COMPLICATION_TYPE_SUNRISE} // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain ]; - var fieldTypes = mView.mFieldTypes; + var fieldTypes = view.mFieldTypes; var filled = [false, false, false]; var i; for (i = 0; i < complications.size(); i++) { - if (mView.hasField(complications[i].get("type"))) { + if (view.hasField(complications[i].get("type"))) { for (var j = 0; j < mFieldCount; j++) { if (fieldTypes[j].get("type") == complications[i].get("type")) { $.updateComplications("", "Complication_F", j + 1, complications[i].get("complicationType")); @@ -134,11 +130,11 @@ class DataFields extends Ui.Drawable { function draw(dc) { // I'm getting wierd crashes on AMOLED watchs as if some of the fields of the datafields drawable aren't initialized. Only thing in common is AoD. // Therefore added a check to make sure we aren't drawing will if are or were in burnin protection. - if (!mView.burnInProtectionIsOrWasActive()) { + if (!App.getApp().getView().burnInProtectionIsOrWasActive()) { update(dc, /* isPartialUpdate */ false); } else { - /*DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); + //DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); } } @@ -147,7 +143,7 @@ class DataFields extends Ui.Drawable { return; } - var fieldTypes = mView.mFieldTypes; + var fieldTypes = App.getApp().getView().mFieldTypes; /*var spacingX = Sys.getDeviceSettings().screenWidth / (2 * mFieldCount); var spacingY = Sys.getDeviceSettings().screenHeight / 4; @@ -200,7 +196,7 @@ class DataFields extends Ui.Drawable { if (isHeartRate) { // High power mode: 0 on, 1 off, 2 on, etc. - if (!mView.isSleeping()) { + if (!App.getApp().getView().isSleeping()) { showLiveHRSpot = ((seconds % 2) == 0); // Low power mode: @@ -430,12 +426,13 @@ class DataFields extends Ui.Drawable { var sunTimes; var unit; var info; - var fieldTypes = mView.mFieldTypes; + var view = App.getApp().getView(); + var fieldTypes = view.mFieldTypes; switch (type) { // SG Addition case FIELD_RECOVERY_TIME: - if (Toybox has :Complications && mView.useComplications()) { + if (Toybox has :Complications && view.useComplications()) { var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = $.MinutesToTimeString(tmpValue); @@ -451,7 +448,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_BODY_BATTERY: - if (Toybox has :Complications && mView.useComplications()) { + if (Toybox has :Complications && view.useComplications()) { var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -472,7 +469,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_STRESS_LEVEL: - if (Toybox has :Complications && mView.useComplications()) { + if (Toybox has :Complications && view.useComplications()) { var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -514,7 +511,7 @@ class DataFields extends Ui.Drawable { break; // SG Addition case FIELD_TYPE_PULSE_OX: - if (Toybox has :Complications && mView.useComplications()) { + if (Toybox has :Complications && view.useComplications()) { var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString() + "%"; @@ -529,7 +526,7 @@ class DataFields extends Ui.Drawable { } break; case FIELD_TYPE_HEART_RATE: - if (Toybox has :Complications && mView.useComplications()) { + if (Toybox has :Complications && view.useComplications()) { var tmpValue = fieldTypes[index].get("ComplicationValue"); if (tmpValue != null) { value = tmpValue.toString(); @@ -768,7 +765,7 @@ class DataFields extends Ui.Drawable { } // Didn't receive weather from Garmin else { - value = "???"; + value = "N/A"; if (!settings.phoneConnected) { stale = true; diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index 95d39bcb..4273a946 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -48,9 +48,6 @@ class GoalMeter extends Ui.Drawable { private var mMaxValue; private var mIsOff = false; // #114 Should entire meter on this side be hidden? - private var mApp; - private var mView; - // private enum /* GOAL_METER_STYLES */ { // ALL_SEGMENTS, // ALL_SEGMENTS_MERGED, @@ -114,9 +111,6 @@ class GoalMeter extends Ui.Drawable { } function onSettingsChanged(index) { - mApp = App.getApp(); - mView = mApp.getView(); - mBuffersNeedRecreate = true; // #18 Only read separator width from layout if multi segment style is selected. @@ -141,14 +135,14 @@ class GoalMeter extends Ui.Drawable { mSeparator = 0; } - if (Toybox has :Complications && mView.useComplications()) { + if (Toybox has :Complications && App.getApp().getView().useComplications()) { var complications = [{"type" => GOAL_TYPE_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => GOAL_TYPE_FLOORS_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => GOAL_TYPE_STEPS, "complicationType" => Complications.COMPLICATION_TYPE_STEPS}, {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} ]; - var goalTypes = mView.mGoalTypes; + var goalTypes = App.getApp().getView().mGoalTypes; var filled = false; for (var i = 0; i < complications.size(); i++) { From 30aa74a1fad48e5d897ceb98c3d62016beceaf72 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 15 May 2023 00:57:12 -0400 Subject: [PATCH 155/220] Gave the Forerunner 55 access to the weather and humidity since it supports Garmin Weather --- README.md | 1 + resources-fr55/settings/settings.xml | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ff3a4b48..11288929 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Reviews: - Added an option in Settings (Show weather station name) to show or not the weather station name, defaults to True. - Watches that although are at CIQ V3.2.0 and above but are still lacking Garmin Weather will display "N/A" for temperature/humidity/sunrise/sunset. - Trying to free some more room so watches with 98KB of watch face memory doesn't crash with Out of Memory errors. +- Gave the Forerunner 55 access to the weather and humidity since it supports Garmin Weather ### 2.18.0 - Removed Watch model that are not at least at CIQ 3.3.0. This is required for the new Sunrise/Sunset and Weather library by Garmin. From the stats Garmin shows me about the watch face, none of them had downloaded the watch face anyway. diff --git a/resources-fr55/settings/settings.xml b/resources-fr55/settings/settings.xml index 9a91fb07..b0bce9f7 100644 --- a/resources-fr55/settings/settings.xml +++ b/resources-fr55/settings/settings.xml @@ -65,8 +65,8 @@ @Strings.SunriseSunset - - + @Strings.Weather + @Strings.Humidity @Strings.BodyBattery @Strings.RecoveryTime @Strings.StressLevel @@ -88,8 +88,8 @@ @Strings.SunriseSunset - - + @Strings.Weather + @Strings.Humidity @Strings.BodyBattery @Strings.RecoveryTime @Strings.StressLevel @@ -111,8 +111,8 @@ @Strings.SunriseSunset - - + @Strings.Weather + @Strings.Humidity @Strings.BodyBattery @Strings.RecoveryTime @Strings.StressLevel From 7f56fcb531b4cbfd6ee092de0316022c3ed86a00 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 15 May 2023 01:10:46 -0400 Subject: [PATCH 156/220] Needed for the 240 x 240 watches --- resources-rectangle-205x148/fonts/fonts.xml | 17 ++++++ .../fonts/namum-gothic-kor-16.bmfc | 55 ++++++++++++++++++ .../fonts/namum-gothic-kor-16.fnt | 24 ++++++++ .../fonts/namum-gothic-kor-16_0.png | Bin 0 -> 1637 bytes .../fonts/noto-sans-cjk-sc-medium-16.fnt | 30 ++++++++++ .../fonts/noto-sans-cjk-sc-medium-16_0.png | Bin 0 -> 1722 bytes .../fonts/noto-sans-cjk-tc-medium-16.fnt | 30 ++++++++++ .../fonts/noto-sans-cjk-tc-medium-16_0.png | Bin 0 -> 1709 bytes .../fonts/noto-sans-rus-bold-16.bmfc | 55 ++++++++++++++++++ .../fonts/noto-sans-rus-bold-16.fnt | 47 +++++++++++++++ .../fonts/noto-sans-rus-bold-16_0.png | Bin 0 -> 2561 bytes .../fonts/titillium-web-bold-54.bmfc | 55 ++++++++++++++++++ .../fonts/titillium-web-bold-54.fnt | 14 +++++ .../fonts/titillium-web-bold-54_0.png | Bin 0 -> 3515 bytes .../fonts/titillium-web-light-54.bmfc | 55 ++++++++++++++++++ .../fonts/titillium-web-light-54.fnt | 15 +++++ .../fonts/titillium-web-light-54_0.png | Bin 0 -> 3782 bytes 17 files changed, 397 insertions(+) create mode 100644 resources-rectangle-205x148/fonts/fonts.xml create mode 100644 resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc create mode 100644 resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt create mode 100644 resources-rectangle-205x148/fonts/namum-gothic-kor-16_0.png create mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt create mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16_0.png create mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt create mode 100644 resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16_0.png create mode 100644 resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc create mode 100644 resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt create mode 100644 resources-rectangle-205x148/fonts/noto-sans-rus-bold-16_0.png create mode 100644 resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc create mode 100644 resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt create mode 100644 resources-rectangle-205x148/fonts/titillium-web-bold-54_0.png create mode 100644 resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc create mode 100644 resources-rectangle-205x148/fonts/titillium-web-light-54.fnt create mode 100644 resources-rectangle-205x148/fonts/titillium-web-light-54_0.png diff --git a/resources-rectangle-205x148/fonts/fonts.xml b/resources-rectangle-205x148/fonts/fonts.xml new file mode 100644 index 00000000..80b93802 --- /dev/null +++ b/resources-rectangle-205x148/fonts/fonts.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc b/resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc new file mode 100644 index 00000000..a8b43eaa --- /dev/null +++ b/resources-rectangle-205x148/fonts/namum-gothic-kor-16.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=NanumGothicExtraBold +fontFile= +charSet=0 +fontSize=16 +aa=2 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=32,40-41,48-57,44552,47785,49688,50900,51068,53664,54868 + +# imported icon images diff --git a/resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt b/resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt new file mode 100644 index 00000000..b3fa1733 --- /dev/null +++ b/resources-rectangle-205x148/fonts/namum-gothic-kor-16.fnt @@ -0,0 +1,24 @@ +info face="NanumGothicExtraBold" size=16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=16 base=13 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="namum-gothic-kor-16_0.png" +chars count=20 +char id=32 x=191 y=0 width=2 height=1 xoffset=0 yoffset=15 xadvance=4 page=0 chnl=15 +char id=40 x=0 y=0 width=5 height=14 xoffset=0 yoffset=2 xadvance=5 page=0 chnl=15 +char id=41 x=6 y=0 width=5 height=14 xoffset=0 yoffset=2 xadvance=5 page=0 chnl=15 +char id=48 x=104 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=49 x=172 y=0 width=4 height=11 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=15 +char id=50 x=140 y=0 width=7 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=51 x=148 y=0 width=7 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=52 x=94 y=0 width=9 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=53 x=156 y=0 width=7 height=11 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=15 +char id=54 x=113 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=55 x=164 y=0 width=7 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=56 x=122 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=57 x=131 y=0 width=8 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=15 +char id=44552 x=27 y=0 width=13 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 +char id=47785 x=41 y=0 width=13 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 +char id=49688 x=55 y=0 width=13 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 +char id=50900 x=69 y=0 width=12 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 +char id=51068 x=82 y=0 width=11 height=13 xoffset=1 yoffset=2 xadvance=13 page=0 chnl=15 +char id=53664 x=177 y=0 width=13 height=10 xoffset=0 yoffset=3 xadvance=13 page=0 chnl=15 +char id=54868 x=12 y=0 width=14 height=13 xoffset=0 yoffset=2 xadvance=13 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/namum-gothic-kor-16_0.png b/resources-rectangle-205x148/fonts/namum-gothic-kor-16_0.png new file mode 100644 index 0000000000000000000000000000000000000000..d90c20372bef217c67c5b9d9aea0f4fb6e805eed GIT binary patch literal 1637 zcmc(g`#aMM0EfTZw3+**oWu^2C|jiFlIvWOrz~{j(xJKJmc?O=RyLGMB~FI5)hJIl zD^xCFNFo`FXfDeXtAow9$S`y|f5rLy@ILSJynn#wiXYZnU1ggJ008PfhdcuS0Q5^i zfbuT_nfmf30DvNWJTZS{FvL7^;?NI7x6HiK&9uu#xnQ^~ukKmcV9%{M-jJF)ni|i# z8kHJs@jME21XVg<5>Y7GwZpW;7Bx#!059N+D3%NHg@ zG)&n~D5ezbdYz4_FH7BXGOnD&55a~v8=eYI2(%t1X#=B+wOb%>VDFk@ntq?Vw)XF zbWFOs*6ZsG4{j6+s(pWA=n@e`B3S-#&7mi=n3LsrfOx7>M#?0w6MAwunKcrRe{gdc zi*swL;pZ}u?O{rM@AL;Iz(@qO9c!5z82(J?p9IZVMZ%0lC80x>S;K!X(Hv9tPE>!` zdgF70miCDr%O&js2Y?+DQ9d}4$L;gZ8l>Y*6llitfLnO&QHU(@zVD?|A2r&oP)BkD z)qZ@g!B28#Fc6Mm_g{vwnW0@wgaMH8(S@QvpL=_a4qmpoV$g2;t65P*JFjwGaJ6TR z+Mz`FGRkxN?EPtI&8SPg_4~Nt_qaf0gEP7f1^GIDF$a}Crn+?5S>26|hggip(&6eb zYgEzV=iVDlpvJqEufeCG#(FSijWHp#aThQL$&*vUDLg2?d}~7Wm|5ABeZka=^f#eM z&(7m&TuP2-(xZ#75Z45TW2pETgKPn9bjEP`QecM{vF2s2Eo?U@QS|~co~;Uu;EX^S zpvqIzcc4|E^4>dn<+oG%gHitb6eeM|ECF6je1P^NzjT2aHzz<}+@ghiaUVaf>Q5Nv zKvnoa$CVs9Sb6kH{K~qIQEO^U316AJ19lsm3bDtLC^Oj9#PZ8a3)ipjrE4Y+?DkeF z41FBGm3+{J2Wl)Mns2T>-`6?oZang-?>_vsIFcX)X(a@q&ALX(Q_Yx(%xB~oZfOu=Le@2smOXDJ znT6%t2nz)h2-2xG(Vc(+h__v!?JIuI`Rg9%L-t?18-mBbFDd{cC;AY8Ra@&>G%sAK z-snP8^^2BMhLc?&M7Hvr`Kz{a$D6E^plrS0qZ5Eu?d8~S6JL@#bpMP#DYJiTjM;OQ z#2_(yb8%V%nI#D)=AU-`UcaPCJEAEyvY~u~Ymmbs%dvIr;=BQf{u8q)P?@_@PB+ha zwLibVVl3*zr@56ROjy5F%U~R0$QLXj8ACZvO1=O&@q#cUytm*IWsqnp$SWB}qi7d{ zG?MdgdC1qNLoG|6F{rw+De&@Xxjv?Bfo>r5rsU7{In)vMx^BpkuH-yEtU3w%<57Z+ zU#BTh8+67s+eV>eY@P`!vF}&ZlgDZI9{F0&iWN}neRYcgH)A>r+@2~FwE}lHDpB&W zi3Aw*AssYFB4T=|QnxnR=$VJM`^LRy`CGm=(n84DBp?A)GKRGxH4pa_9Bo3+E~GS9 zBraluZMKx5lUvcmhgk}Yv>!n>5bA||ee(N@NEXQ%&XUDY=tB>(E!tJ_f;u+BZG|M? zxkTtFTI-hhF!<`1Ae~1=W@+>J-=|s44h<3{*JZE6z&cb*Qzl<|X|2 zzx~`4xoO|QWI9Ux P-+%acVLhL^<8uB5B4+G) literal 0 HcmV?d00001 diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt b/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt new file mode 100644 index 00000000..f3d4a86a --- /dev/null +++ b/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16.fnt @@ -0,0 +1,30 @@ +info face="Noto Sans CJK SC Medium" size=-16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=24 base=19 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="noto-sans-cjk-sc-medium-16_0.png" +chars count=26 +char id=10 x=50 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 +char id=32 x=54 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 +char id=48 x=18 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=49 x=219 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=50 x=228 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=51 x=237 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=52 x=199 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=53 x=246 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=54 x=0 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=55 x=209 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=56 x=9 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=57 x=26 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=19968 x=34 y=16 width=15 height=2 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 +char id=19971 x=110 y=0 width=15 height=14 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 +char id=19977 x=169 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 +char id=20061 x=0 y=0 width=14 height=16 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=20108 x=184 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 +char id=20116 x=153 y=0 width=15 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 +char id=20843 x=93 y=0 width=16 height=14 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 +char id=20845 x=15 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=21313 x=31 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=22235 x=63 y=0 width=14 height=15 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26085 x=141 y=0 width=11 height=14 xoffset=3 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26143 x=126 y=0 width=14 height=14 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26376 x=78 y=0 width=14 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26399 x=47 y=0 width=15 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16_0.png b/resources-rectangle-205x148/fonts/noto-sans-cjk-sc-medium-16_0.png new file mode 100644 index 0000000000000000000000000000000000000000..5d6d6a9afc0937be4648cf4fe38bdd771b0f6d7b GIT binary patch literal 1722 zcmchY{Xf%*1HeC{%y%;Cj)viY7?MOO658ivX zbfILL-zQjP9%ZD6bEbYBFI38Q=J*VyO8%J!48R$67fZ;KmR%y}DdVjj#G=4Q1>q1! zTVwEG!sOsj$yxE%)v}0|@jDaHWc)M1hIx22f1GLwWVYS<&j9PivH;rMA(b9I{6Y1u zr`F0Lb-kybhDG5Yd<<-KRwulgA|f?P)=JO4L03B5e<~gR@+6O4-Je9spb>sP((Ec) z6u!{gCzc$PC>JmjYu%#v9K3+*tZ{hrGyuMtqFMwY*$a3@2Wd$$X^srp*nUsi+13`b zxVrirKI%el@EpIvs+vOt3#ymX%5)E%MzGR`P8nRki?rr=o6?;=(B?7y&$+=k`3%7g z55Ux(YVdr27>b+jtEp))Cw0=);ll@(r`oU-vD@}~1d#{OKV{X5-fN+yE6P^5(3I_v zx21!xdyND7k~k*;+lZ4cGo&k(yrZ1Jou))Rv=FiPf1ZhJWLqJtKZnJ>F%865g+@I) z%2wS|ASq7$_g^Z*q=lu_ORW>9RRor+NLFj6==HanvFI&neB3WYr9F|_R49SZ?0TcG zoOEt)t)^t5mPalE0{-*S8vppz@yp!cO=|rUYazvyOmbIX024RRNC8x@xWTh%z?&-y7#eANohf8M3@$b&1l?m(BRcJ)t*(1$1PheE$` z<{a^0w}(d#ITw`4LlTzu6qf0Z?q~Geq@n!u6_2xco(SbfEl4)k{YMBKZD$C5+k70n z3O!qco1FT3b9Mqzj^!oc_xagQV-lBG-?Ai0Dk##6HL~3}QCnccNz3L^Qr}RXiwHX- z?cSUB)+G=V@%BBw|4!%(sHKBSXoy>FHk#-~{c?h8vZ!XX9bMy!GR%V2T!`B$HEPlF zXmmJ#%V1h|+OZeF&$kds@rhtsz%_M-quf2TtszcgnRDJXCngD5&4bJpJIob3$t=Y1 z!*`UkZ`Rjbj@es5+k#0Wc7yF9bP!(N7*O7{8>7`k+)B_nOGs%rtSi^-Nlx=08%w#`s=oML=1whJehlyo6FHhGtfOR6(fjMLpLj1L&qci$ zYl)_()pfhk)4F;#?by)^=vG4>@xZG53Ue_!QYp0Z8+EDT0{p0$qO)G+x8Lb@{c?M- zI@r6SoRoLyQ84qTn-(9rBS5(Q5&LHchk-b^1HQxNu)!f?Uz;hAXT~l6^jEP0seS5D zGZ9Mou2s$ILX^KL^UP9V!>OF;oH=#f@jYGn19^;sI#N_l1;pOY7LLy6vt}aKbuSJs zSbFAeG?a!&o}sU{m5%jg{?XIqE3XmAEUJ#fF&Kx(uo+y_@312C;(hO7^MAshuIHL& zmLYEH5Ab^#3@bzc9f2Wa6hI$VdTC`FdA?~ng(yfW#PvcDzD>+Ulvd| zfJ>HP;lGlBKAmJQ^0nH5{0)FtR_L~4%c*6A2JG1KH|Cz4cx%<=r2(DUgH2d$AU>AKns?MVy F{0;HicBTLT literal 0 HcmV?d00001 diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt b/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt new file mode 100644 index 00000000..63073c2f --- /dev/null +++ b/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16.fnt @@ -0,0 +1,30 @@ +info face="Noto Sans CJK TC Medium" size=-16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=24 base=19 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="noto-sans-cjk-tc-medium-16_0.png" +chars count=26 +char id=10 x=50 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 +char id=32 x=54 y=16 width=3 height=1 xoffset=-1 yoffset=23 xadvance=4 page=0 chnl=15 +char id=48 x=18 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=49 x=217 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=50 x=226 y=0 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=51 x=235 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=52 x=197 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=53 x=244 y=0 width=8 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=54 x=0 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=55 x=207 y=0 width=9 height=12 xoffset=0 yoffset=7 xadvance=9 page=0 chnl=15 +char id=56 x=9 y=17 width=8 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=57 x=26 y=16 width=7 height=12 xoffset=1 yoffset=7 xadvance=9 page=0 chnl=15 +char id=19968 x=34 y=16 width=15 height=2 xoffset=1 yoffset=12 xadvance=16 page=0 chnl=15 +char id=19971 x=109 y=0 width=14 height=14 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=19977 x=167 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 +char id=20061 x=0 y=0 width=14 height=16 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=20108 x=182 y=0 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 +char id=20116 x=151 y=0 width=15 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 +char id=20843 x=93 y=0 width=15 height=14 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 +char id=20845 x=15 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=21313 x=31 y=0 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=22235 x=63 y=0 width=14 height=15 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26085 x=139 y=0 width=11 height=14 xoffset=3 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26143 x=124 y=0 width=14 height=14 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26376 x=78 y=0 width=14 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 +char id=26399 x=47 y=0 width=15 height=15 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16_0.png b/resources-rectangle-205x148/fonts/noto-sans-cjk-tc-medium-16_0.png new file mode 100644 index 0000000000000000000000000000000000000000..62e918e913a3db1f89fa4c09f4c7351441234ce2 GIT binary patch literal 1709 zcmchY|3A|S1HeBYi-|LvLbC4mT;U$m&9}$5@~wQ$#c_9y45K(@WbGJ+(~vR_%MHyI zIXtd>iDR_18RAaHle@AoBVS@>W|fWb-1AR7?;qZ;_kZxd{dJ(Pp3YGn008v-{k%c| z0Q@^aK>Ke4=_Xr`0YK{qe=pB()2d~Y?(xVKlOaW`M@{$bqTH89sCouRLXa+I@YZDF zbOdoQy6UhoT@V~=Q%r+bK%RLG8cu{4JvcFFQ5;Mx`p5hQ_!^dK zP4TvGVINjTaT~d%HF(92{VC;BJNb@qXE{CU3JjHt{%)u8uG(+oaJM{XoBMkQ zgCeuWgTz|w&x{9+aCY$g+7zFz-5kSevg8wVcH5D{idF20E(sofnrl0f)i?c)SrpVI zJuEaxXgLl%0lg5Vrf{vr?;hwW?E5jPO zGzQ3~tCaZmApJDOKjk>6WPYKX(Y&EA*|?Z)nnmeZTlhWiIv#+PE~0rt zbZ+EO&DId>G2|tzD`;tmHU?U&cC~Wk=l4Ejvt+Jz8lGjbiLi|;$ndWYK{NsaZ-Y&s zlP>c`=KOryM@t&Bko%rL9;5wWbM?6i4Kv(vb@1%vy2pyYAYsAoiZ42}eOB-i8g&`W zfU;hE>NbN?soh`I-bIY`M$}XzUeSoW!=$D(HctZ`TdAwUHYUD;fgiTzNf69dN#t&F zrzoV(jdKk%4}R&0ZXs+Lj7cng2O~Pl0;g~)tGF8~ylLngxrOr1;7m*i0dac!t(zRu zSJ!FDeY=o>s@4N%b*5ROxnrR?m^s5m=@Fubn?5#l)ye8!@P*4&Bq5U|9G%q63?xI; z=bpNfLK5h-*=WkkKPT>YS3<>$m}Y@sPpT*BtGnkat=9a*VRq$YhDuSR%bqE;4zF7%Pz2nZK2K2g0@Rpp)N_1xWDhHBm!rv1ne;F#+J zeyOS28HcFkY@J{m`SJ~B>qx}$NpM|}ki#kw>&E@y(X~&1ql+o&u$)Wdni8|En^IvA zffQ4?Hrp&_ujjm%MC%uRGoHjb0yS1Ka$}QR*aWiB%-3|rDY=K_i@4LTA2y)4Oi80* z92`Ych1kzDhY~*C7~P}n7++8)sz3g_(ph-RwTOUg;23#Q4*p_PWEX>`k8&>(7n(kY zFYzn-p!BQMAk8Ur?d^t|z_re9iah8tR@Phyu6BmF*I#~vZ7 zG-G|@(^EuO-;HbKEzuvY<*b_{%H>`}B=dM;V7X_~SwPDnRp{(Uo$N8!>TZgV5C$%= zO?2O?4tr!6kO$*vtXM#Pj(IW2hcokv9JJ~ykv zj#5Xg$R6=w)nR=83(q)^mA_iBFJIalGh=Z7G%yI5A29H|ybUu`WPpreK-8X(V%Y}!e);1cwy zcJ`%?>H7^3!SwTc`zCmX9`q6^k5PPmg!&kQ`swb$>q&+MTho3gbIR&d;CZVHlorFY zxWUs;Y}!l5ec+w@NGDEV&~xSHj}BFca%k-U{kOd-)khs$(`VwFPD*cU)X^y?YBGUw vASz10{L+u4gy5|mP8C>0ApXyk?F)He**5q|VL+wD|32jJ9q83^22cGj>%=90 literal 0 HcmV?d00001 diff --git a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc new file mode 100644 index 00000000..70857ad9 --- /dev/null +++ b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Noto Sans +fontFile= +charSet=0 +fontSize=-16 +aa=1 +scaleH=100 +useSmoothing=1 +isBold=1 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=1 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=32,48-57,1040-1071 + +# imported icon images diff --git a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt new file mode 100644 index 00000000..cb192fd2 --- /dev/null +++ b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16.fnt @@ -0,0 +1,47 @@ +info face="Noto Sans" size=-16 bold=1 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=22 base=17 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="noto-sans-rus-bold-16_0.png" +chars count=43 +char id=32 x=250 y=13 width=3 height=1 xoffset=-1 yoffset=21 xadvance=4 page=0 chnl=15 +char id=48 x=163 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 +char id=49 x=242 y=13 width=7 height=11 xoffset=0 yoffset=6 xadvance=9 page=0 chnl=15 +char id=50 x=153 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 +char id=51 x=143 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 +char id=52 x=211 y=13 width=10 height=11 xoffset=-1 yoffset=6 xadvance=9 page=0 chnl=15 +char id=53 x=232 y=13 width=9 height=11 xoffset=0 yoffset=6 xadvance=9 page=0 chnl=15 +char id=54 x=133 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 +char id=55 x=222 y=13 width=9 height=11 xoffset=0 yoffset=6 xadvance=9 page=0 chnl=15 +char id=56 x=123 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 +char id=57 x=183 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 +char id=1040 x=180 y=0 width=13 height=12 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15 +char id=1041 x=103 y=13 width=9 height=12 xoffset=1 yoffset=5 xadvance=10 page=0 chnl=15 +char id=1042 x=81 y=13 width=10 height=12 xoffset=1 yoffset=5 xadvance=11 page=0 chnl=15 +char id=1043 x=202 y=13 width=8 height=12 xoffset=1 yoffset=5 xadvance=9 page=0 chnl=15 +char id=1044 x=30 y=0 width=14 height=15 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15 +char id=1045 x=193 y=13 width=8 height=12 xoffset=1 yoffset=5 xadvance=9 page=0 chnl=15 +char id=1046 x=58 y=0 width=17 height=12 xoffset=-1 yoffset=5 xadvance=15 page=0 chnl=15 +char id=1047 x=92 y=13 width=10 height=12 xoffset=0 yoffset=5 xadvance=10 page=0 chnl=15 +char id=1048 x=12 y=16 width=11 height=12 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 +char id=1049 x=0 y=0 width=11 height=16 xoffset=1 yoffset=1 xadvance=13 page=0 chnl=15 +char id=1050 x=24 y=16 width=11 height=12 xoffset=1 yoffset=5 xadvance=11 page=0 chnl=15 +char id=1051 x=221 y=0 width=12 height=12 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15 +char id=1052 x=194 y=0 width=13 height=12 xoffset=1 yoffset=5 xadvance=15 page=0 chnl=15 +char id=1053 x=59 y=13 width=10 height=12 xoffset=1 yoffset=5 xadvance=12 page=0 chnl=15 +char id=1054 x=166 y=0 width=13 height=12 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 +char id=1055 x=48 y=16 width=10 height=12 xoffset=1 yoffset=5 xadvance=12 page=0 chnl=15 +char id=1056 x=246 y=0 width=9 height=12 xoffset=1 yoffset=5 xadvance=10 page=0 chnl=15 +char id=1057 x=70 y=13 width=10 height=12 xoffset=0 yoffset=5 xadvance=10 page=0 chnl=15 +char id=1058 x=113 y=13 width=9 height=12 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15 +char id=1059 x=208 y=0 width=12 height=12 xoffset=0 yoffset=5 xadvance=11 page=0 chnl=15 +char id=1060 x=109 y=0 width=14 height=12 xoffset=0 yoffset=5 xadvance=14 page=0 chnl=15 +char id=1061 x=152 y=0 width=13 height=12 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15 +char id=1062 x=45 y=0 width=12 height=15 xoffset=1 yoffset=5 xadvance=12 page=0 chnl=15 +char id=1063 x=0 y=17 width=11 height=12 xoffset=0 yoffset=5 xadvance=12 page=0 chnl=15 +char id=1064 x=93 y=0 width=15 height=12 xoffset=1 yoffset=5 xadvance=17 page=0 chnl=15 +char id=1065 x=12 y=0 width=17 height=15 xoffset=1 yoffset=5 xadvance=18 page=0 chnl=15 +char id=1066 x=138 y=0 width=13 height=12 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15 +char id=1067 x=124 y=0 width=13 height=12 xoffset=1 yoffset=5 xadvance=14 page=0 chnl=15 +char id=1068 x=173 y=13 width=9 height=12 xoffset=1 yoffset=5 xadvance=10 page=0 chnl=15 +char id=1069 x=234 y=0 width=11 height=12 xoffset=0 yoffset=5 xadvance=11 page=0 chnl=15 +char id=1070 x=76 y=0 width=16 height=12 xoffset=1 yoffset=5 xadvance=17 page=0 chnl=15 +char id=1071 x=36 y=16 width=11 height=12 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16_0.png b/resources-rectangle-205x148/fonts/noto-sans-rus-bold-16_0.png new file mode 100644 index 0000000000000000000000000000000000000000..42d424ee6675c2b299eb1127b7e5d4c473691100 GIT binary patch literal 2561 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 GPy8=AdCNZl literal 0 HcmV?d00001 diff --git a/resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc b/resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc new file mode 100644 index 00000000..7d9f47cf --- /dev/null +++ b/resources-rectangle-205x148/fonts/titillium-web-bold-54.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web +fontFile= +charSet=0 +fontSize=-54 +aa=1 +scaleH=100 +useSmoothing=1 +isBold=1 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt b/resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt new file mode 100644 index 00000000..ee9fe3bb --- /dev/null +++ b/resources-rectangle-205x148/fonts/titillium-web-bold-54.fnt @@ -0,0 +1,14 @@ +info face="Titillium Web" size=-54 bold=1 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=38 base=38 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-bold-54_0.png" +chars count=10 +char id=48 x=0 y=0 width=30 height=38 xoffset=0 yoffset=0 xadvance=30 page=0 chnl=15 +char id=49 x=230 y=0 width=21 height=36 xoffset=3 yoffset=1 xadvance=30 page=0 chnl=15 +char id=50 x=177 y=0 width=26 height=37 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 +char id=51 x=122 y=0 width=26 height=38 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 +char id=52 x=0 y=39 width=28 height=36 xoffset=1 yoffset=1 xadvance=30 page=0 chnl=15 +char id=53 x=149 y=0 width=27 height=37 xoffset=2 yoffset=1 xadvance=30 page=0 chnl=15 +char id=54 x=62 y=0 width=29 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 +char id=55 x=204 y=0 width=25 height=37 xoffset=3 yoffset=1 xadvance=30 page=0 chnl=15 +char id=56 x=31 y=0 width=30 height=38 xoffset=0 yoffset=0 xadvance=30 page=0 chnl=15 +char id=57 x=92 y=0 width=29 height=38 xoffset=0 yoffset=0 xadvance=30 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/titillium-web-bold-54_0.png b/resources-rectangle-205x148/fonts/titillium-web-bold-54_0.png new file mode 100644 index 0000000000000000000000000000000000000000..e35a6edde9d259d1b08f0145fee760a528c8a5df GIT binary patch literal 3515 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 literal 0 HcmV?d00001 diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc b/resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc new file mode 100644 index 00000000..04f032e7 --- /dev/null +++ b/resources-rectangle-205x148/fonts/titillium-web-light-54.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web Light +fontFile= +charSet=0 +fontSize=-54 +aa=1 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt b/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt new file mode 100644 index 00000000..e0dfd7b6 --- /dev/null +++ b/resources-rectangle-205x148/fonts/titillium-web-light-54.fnt @@ -0,0 +1,15 @@ +info face="Titillium Web Light" size=-54 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=38 base=38 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-light-54_0.png" +chars count=10 +char id=48 x=30 y=0 width=28 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 +char id=49 x=0 y=39 width=17 height=36 xoffset=5 yoffset=1 xadvance=30 page=0 chnl=15 +char id=50 x=170 y=0 width=25 height=37 xoffset=3 yoffset=0 xadvance=30 page=0 chnl=15 +char id=51 x=116 y=0 width=26 height=38 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 +char id=52 x=222 y=0 width=29 height=36 xoffset=1 yoffset=1 xadvance=30 page=0 chnl=15 +char id=53 x=143 y=0 width=26 height=37 xoffset=2 yoffset=1 xadvance=30 page=0 chnl=15 +char id=54 x=88 y=0 width=27 height=38 xoffset=2 yoffset=0 xadvance=30 page=0 chnl=15 +char id=55 x=196 y=0 width=25 height=37 xoffset=3 yoffset=1 xadvance=30 page=0 chnl=15 +char id=56 x=0 y=0 width=29 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 +char id=57 x=59 y=0 width=28 height=38 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 +char id=58 x=20 y=39 width=10 height=38 xoffset=1 yoffset=0 xadvance=10 page=0 chnl=15 diff --git a/resources-rectangle-205x148/fonts/titillium-web-light-54_0.png b/resources-rectangle-205x148/fonts/titillium-web-light-54_0.png new file mode 100644 index 0000000000000000000000000000000000000000..143345f3ba86b7907900c270abdb3eea734ba848 GIT binary patch literal 3782 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 NssVqZTBTwe^*<`I5Yhku literal 0 HcmV?d00001 From eba42cdb4e202935c854a698c9dafa1ab43070ae Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 15 May 2023 09:21:59 -0400 Subject: [PATCH 157/220] V2.18.2 - Fixed a crash on a VenuSQ - Fixed a crash when invalid data is received from the background process --- README.md | 4 ++++ manifest.xml | 2 +- resources-rectangle-240x240/layouts/layout.xml | 2 +- resources/strings/strings.xml | 2 +- source/CrystalApp.mc | 16 ++++++++++------ 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 11288929..8c48873b 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.2 +- Fixed a crash on a VenuSQ +- Fixed a crash when invalid data is received from the background process + ### 2.18.1 - Gave the weather station name its own line so it doesn't hide the Goals current/max fields. Local City Time will still hide these though. This is how it always was. - Added an option in Settings (Show weather station name) to show or not the weather station name, defaults to True. diff --git a/manifest.xml b/manifest.xml index ea0690e3..e03339da 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + diff --git a/resources-rectangle-240x240/layouts/layout.xml b/resources-rectangle-240x240/layouts/layout.xml index f2f41285..3271228b 100644 --- a/resources-rectangle-240x240/layouts/layout.xml +++ b/resources-rectangle-240x240/layouts/layout.xml @@ -19,7 +19,7 @@ 49 142 - 190 + 190 206 222 202 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index ef9dd56b..9a2b6f98 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.1 + Crystal-Tesla V2.18.2 Theme Hours Colour diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 3c40f7a5..7df0dc65 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -87,18 +87,22 @@ class CrystalApp extends App.AppBase { // pendingWebRequests keys. (:background_method) function onBackgroundData(data) { - var receivedData = data["TeslaInfo"]; // What we just received - var teslaInfo = Storage.getValue("TeslaInfo"); // What we have in Storage if (teslaInfo == null) { teslaInfo = {}; } // Update in TeslaInfo what has been received in receivedData - var keys = receivedData.keys(); - var values = receivedData.values(); - for (var i = 0; i < keys.size(); i++) { - teslaInfo.put(keys[i], values[i]); + var receivedData = data["TeslaInfo"]; // What we just received + if (receivedData != null && receivedData instanceof Lang.Dictionary) { + var keys = receivedData.keys(); + var values = receivedData.values(); + for (var i = 0; i < keys.size(); i++) { + teslaInfo.put(keys[i], values[i]); + } + } + else { + //DEBUG*/ logMessage("Unexpected invalid receivedData: " + receivedData); } // Copy into their own name some of the entries in TeslaInfo, then delete from TeslaInfo From 103bf1af7c0c9ef92716574716dab98756674335 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 15 May 2023 10:04:09 -0400 Subject: [PATCH 158/220] Reinstated debug statements --- source/BackgroundService.mc | 20 ++++++++++---------- source/CrystalView.mc | 12 ++++++------ source/DataArea.mc | 4 ++-- source/DataFields.mc | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index d1688ce2..cb7c3ae6 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -83,30 +83,30 @@ class BackgroundService extends Sys.ServiceDelegate { } if (_token == null) { - //DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); + /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { makeWebPost(refreshToken, method(:onReceiveToken)); } else { - //DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); + /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); } return; } if (_vehicle_id == null) { - //DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); + /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); return; } - //DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); + /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); } (:background_method) function onReceiveToken(responseCode, responseData) { - //DEBUG*/ logMessage("onReceiveToken: " + responseCode); + /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); var teslaInfo = Bg.getBackgroundData(); if (teslaInfo == null) { @@ -131,7 +131,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onReceiveVehicles(responseCode, responseData) { - //DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); + /*DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); var teslaInfo = Bg.getBackgroundData(); if (teslaInfo == null) { @@ -182,8 +182,8 @@ class BackgroundService extends Sys.ServiceDelegate { (:background_method) function onReceiveVehicleData(responseCode, responseData) { - //DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); - //DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); + /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); var teslaInfo = Bg.getBackgroundData(); if (teslaInfo == null) { @@ -224,7 +224,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("VehicleID", null); _vehicle_id = null; } - //DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); + /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); return; } @@ -232,7 +232,7 @@ class BackgroundService extends Sys.ServiceDelegate { else if (responseCode == 401) { var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { - //DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); + /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); makeWebPost(refreshToken, method(:onReceiveToken)); return; } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 4856647d..c65d20ab 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -147,7 +147,7 @@ class CrystalView extends Ui.WatchFace { // the state of this View and prepare it to be shown. This includes // loading resources into memory. */ function onShow() { - //DEBUG*/ logMessage("View showing"); + /*DEBUG*/ logMessage("View showing"); } // Set flag to respond to settings change on next full draw (onUpdate()), as we may be in 1Hz (lower power) mode, and cannot @@ -295,10 +295,10 @@ class CrystalView extends Ui.WatchFace { //logMessage("icon=" + icon); } else { - //DEBUG*/ logMessage("Icon index " + condition + " is invalid"); + /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; - //DEBUG*/ logMessage("Weather at " + mWeatherStationName + " is " + result); + /*DEBUG*/ logMessage("Weather at " + mWeatherStationName + " is " + result); } else { result = { "cod" => 404 }; @@ -632,12 +632,12 @@ class CrystalView extends Ui.WatchFace { // crash in GoalMeter.getSegmentScale(). // Sanity check. I've seen weird Invalid Value and "System Error" in DataArea.setGoalValues:48 and :61. Make sure the data is valid if (values[:isValid] && (!(values[:max] instanceof Lang.Number || values[:max] instanceof Lang.Float) || values[:max] < 1)) { - //DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); + /*DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); values[:max] = 1; values[:isValid] = false; } if (values[:isValid] && (!(values[:current] instanceof Lang.Number || values[:current] instanceof Lang.Float))) { - //DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); + /*DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); values[:current] = 0; values[:isValid] = false; } @@ -659,7 +659,7 @@ class CrystalView extends Ui.WatchFace { // state of this View here. This includes freeing resources from // memory */ function onHide() { - //DEBUG*/ logMessage("View hidding"); + /*DEBUG*/ logMessage("View hidding"); } // The user has just looked at their watch. Timers and animations may be started here. diff --git a/source/DataArea.mc b/source/DataArea.mc index 5b1981b9..b1edc3dd 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -51,7 +51,7 @@ class DataArea extends Ui.Drawable { mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY || mLeftGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { if (leftValues[:isValid]) { - //DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); + /*DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); } mLeftGoalCurrent = null; mLeftGoalMax = null; @@ -66,7 +66,7 @@ class DataArea extends Ui.Drawable { mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY || mRightGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { if (rightValues[:isValid]) { - //DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); + /*DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); } mRightGoalCurrent = null; mRightGoalMax = null; diff --git a/source/DataFields.mc b/source/DataFields.mc index 7ffe17c1..68d125bf 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -134,7 +134,7 @@ class DataFields extends Ui.Drawable { update(dc, /* isPartialUpdate */ false); } else { - //DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); + /*DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); } } From 26f2b537e875577809d9a1533362e81dc8220950 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 15 May 2023 14:16:00 -0400 Subject: [PATCH 159/220] Reinstated debug statements --- source/CrystalApp.mc | 6 +++--- source/CrystalView.mc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 7df0dc65..37f29421 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -32,7 +32,7 @@ class CrystalApp extends App.AppBase { // Return the initial view of your application here function getInitialView() { - //DEBUG*/ logMessage("Getting initial view"); + /*DEBUG*/ logMessage("Getting initial view"); if (WatchUi has :WatchFaceDelegate) { mView = new CrystalView(); @@ -54,7 +54,7 @@ class CrystalApp extends App.AppBase { // New app settings have been received so trigger a UI update (:background_method) function getServiceDelegate() { - //DEBUG*/ logMessage("Getting service delegate"); + /*DEBUG*/ logMessage("Getting service delegate"); return [new BackgroundService()]; } @@ -102,7 +102,7 @@ class CrystalApp extends App.AppBase { } } else { - //DEBUG*/ logMessage("Unexpected invalid receivedData: " + receivedData); + /*DEBUG*/ logMessage("Unexpected invalid receivedData: " + receivedData); } // Copy into their own name some of the entries in TeslaInfo, then delete from TeslaInfo diff --git a/source/CrystalView.mc b/source/CrystalView.mc index c65d20ab..b4d3507b 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -748,7 +748,7 @@ class CrystalView extends Ui.WatchFace { // I've seen this while in low power mode, so skip it if (complicationValue == null) { - //DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); + /*DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); return; } From da4b4577fdfc97b36f6ec5631eed25700b0c6c3c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 16 May 2023 23:18:54 -0400 Subject: [PATCH 160/220] For 2.18.3 - Corrected invalid value for Stress read from sensor, not Complications - For performance, ignore Tesla-Link Complications if we're told not to use them - Changed the logic for when the background process should run next --- README.md | 5 +++++ resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 14 +++++++------- source/CrystalApp.mc | 10 +++++----- source/CrystalView.mc | 10 +++++----- source/DataArea.mc | 1 + 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8c48873b..45cd80d1 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,11 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.3 +- Corrected invalid value for Stress read from sensor, not Complications +- For performance, ignore Tesla-Link Complications if we're told not to use them +- Changed the logic for when the background process should run next + ### 2.18.2 - Fixed a crash on a VenuSQ - Fixed a crash when invalid data is received from the background process diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 9a2b6f98..b887deca 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.2 + Crystal-Tesla V2.18.3 Theme Hours Colour diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index cb7c3ae6..abe981e0 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -13,7 +13,7 @@ class BackgroundService extends Sys.ServiceDelegate { var _token; var _vehicle_id; - (:background_method) + (:background) function initialize() { Sys.ServiceDelegate.initialize(); @@ -76,7 +76,7 @@ class BackgroundService extends Sys.ServiceDelegate { } - (:background_method) + (:background) function onTemporalEvent() { if (!Sys.getDeviceSettings().phoneConnected) { Bg.exit(null); @@ -104,7 +104,7 @@ class BackgroundService extends Sys.ServiceDelegate { makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); } - (:background_method) + (:background) function onReceiveToken(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); @@ -129,7 +129,7 @@ class BackgroundService extends Sys.ServiceDelegate { Bg.exit({ "TeslaInfo" => teslaInfo }); } - (:background_method) + (:background) function onReceiveVehicles(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); @@ -180,7 +180,7 @@ class BackgroundService extends Sys.ServiceDelegate { Bg.exit({ "TeslaInfo" => teslaInfo }); } - (:background_method) + (:background) function onReceiveVehicleData(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); @@ -241,7 +241,7 @@ class BackgroundService extends Sys.ServiceDelegate { Bg.exit({ "TeslaInfo" => teslaInfo }); } - (:background_method) + (:background) function makeWebPost(token, notify) { var url = "https://" + $.getStringProperty("TeslaServerAUTHLocation","") + "/oauth2/v3/token"; Comms.makeWebRequest( @@ -260,7 +260,7 @@ class BackgroundService extends Sys.ServiceDelegate { ); } - (:background_method) + (:background) function makeWebRequest(url, params, callback) { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 37f29421..ddec7830 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -52,7 +52,7 @@ class CrystalApp extends App.AppBase { } // New app settings have been received so trigger a UI update - (:background_method) + (:background) function getServiceDelegate() { /*DEBUG*/ logMessage("Getting service delegate"); return [new BackgroundService()]; @@ -82,10 +82,8 @@ class CrystalApp extends App.AppBase { } // Handle data received from BackgroundService. - // On success, clear appropriate pendingWebRequests flag. - // data is Dictionary with single key that indicates the data type received. This corresponds with Object Store and - // pendingWebRequests keys. - (:background_method) + // data is Dictionary with single key that indicates the data type received. + (:background) function onBackgroundData(data) { var teslaInfo = Storage.getValue("TeslaInfo"); // What we have in Storage if (teslaInfo == null) { @@ -135,6 +133,8 @@ class CrystalApp extends App.AppBase { } } + Bg.registerForTemporalEvent(new Time.Duration(5 * 60)); // Since onSettingsChanged go for a specific time, go for duration here once we get going, otherwise we'll get background data only once the view is shown + Ui.requestUpdate(); } } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index b4d3507b..903b035a 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -191,9 +191,9 @@ class CrystalView extends Ui.WatchFace { mDigitStyle = $.getIntProperty("GoalMeterDigitsStyle", 0); mShowWeatherStationName = $.getBoolProperty("ShowWeatherStationName", true); - // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { + /*DEBUG*/ logMessage("Registering for Temporal Events"); var lastTime = Bg.getLastTemporalEventTime(); if (lastTime) { // Events scheduled for a time in the past trigger immediately. @@ -432,7 +432,7 @@ class CrystalView extends Ui.WatchFace { // Update the view function onUpdate(dc) { //Sys.println("onUpdate()"); - /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + //DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); // If burn-in protection has changed, set layout appropriate to new burn-in protection state. // If turning on burn-in protection, free memory for regular watch face drawables by clearing references. This means that @@ -584,7 +584,7 @@ class CrystalView extends Ui.WatchFace { } } if (values[:isValid] == false && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { - var stressLevel = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); + var stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); //DEBUG*/ var stressLevelDate = 0; if (stressLevel != null) { @@ -742,13 +742,13 @@ class CrystalView extends Ui.WatchFace { //DEBUG*/ var complicationLongLabel = complication.longLabel; if (complicationType == Complications.COMPLICATION_TYPE_RECOVERY_TIME) { logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); } - if (complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { + if (gTeslaComplication == true && complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { $.doTeslaComplication(complicationValue); } // I've seen this while in low power mode, so skip it if (complicationValue == null) { - /*DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); + //DEBUG*/ logMessage("We got a Complication value of null for " + complicationType); return; } diff --git a/source/DataArea.mc b/source/DataArea.mc index b1edc3dd..08452d62 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -181,6 +181,7 @@ class DataArea extends Ui.Drawable { } function drawGoalValues(dc, x, currentValue, maxValue, align) { + //DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); var digitStyle = App.getApp().getView().mDigitStyle; // #107 Only draw values if digit style is not Hidden. From 79ac979cf660a4055df7b914f18f18db1f2cad24 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 17 May 2023 09:25:27 -0400 Subject: [PATCH 161/220] Fixed AOD and Tesla battery not showing and added debug log message for Temporal Event time triggering --- README.md | 1 + always-on-source/AlwaysOnDisplay.mc | 29 +++++++++++++++++------------ source/BackgroundService.mc | 4 +++- source/CrystalApp.mc | 3 +++ source/CrystalView.mc | 4 +++- source/DataArea.mc | 2 +- source/DataFields.mc | 6 +++--- source/Global.mc | 4 +++- source/ThickThinTime.mc | 2 +- 9 files changed, 35 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 45cd80d1..34f99596 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Reviews: - Corrected invalid value for Stress read from sensor, not Complications - For performance, ignore Tesla-Link Complications if we're told not to use them - Changed the logic for when the background process should run next +- Fixed Always On Display for Tesla Battery ### 2.18.2 - Fixed a crash on a VenuSQ diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index 63500f6e..57a3cf21 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -80,7 +80,7 @@ class AlwaysOnDisplay extends Ui.Drawable { // TIME. var clockTime = Sys.getClockTime(); - var formattedTime = App.getApp().getFormattedTime(clockTime.hour, clockTime.min); + var formattedTime = App.getApp().getFormattedTime(clockTime.hour, clockTime.min, clockTime.sec); formattedTime[:amPm] = formattedTime[:amPm].toUpper(); // Change vertical offset every minute. @@ -227,9 +227,14 @@ class AlwaysOnDisplay extends Ui.Drawable { ); // Batteries. - var battery = Math.floor(Sys.getSystemStats().battery); - var chargingState = Storage.getValue("TeslaChargingState"); - var error = Storage.getValue("TeslaError"); + var watchBattery = Math.floor(Sys.getSystemStats().battery); + + var teslaInfo = Storage.getValue("TeslaInfo"); + if (teslaInfo == null) { + teslaInfo = {}; + } + var chargingState = teslaInfo.get("ChargingState"); + var error = teslaInfo.get("httpErrorTesla"); if (chargingState != null) { if (chargingState.equals("Charging")) { @@ -243,16 +248,16 @@ class AlwaysOnDisplay extends Ui.Drawable { chargingState = 0; } - var value = Storage.getValue("TeslaBatterieLevel"); - if (error != null) { - value = error.toNumber().format(INTEGER_FORMAT); - } else if (value == null) { - value = "???"; + var vehicleBattery = teslaInfo.get("BatteryLevel"); + if (error != null && error != 200) { + vehicleBattery = error.toNumber().format(INTEGER_FORMAT); + } else if (vehicleBattery == null) { + vehicleBattery = "???"; } else { - value = value.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); + vehicleBattery = vehicleBattery.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); } - var text = value + " " + battery.format(INTEGER_FORMAT) + "%"; + var text = vehicleBattery + " " + watchBattery.format(INTEGER_FORMAT) + "%"; var widthText = dc.getTextWidthInPixels(text, mBatteryFont); dc.drawText( @@ -266,7 +271,7 @@ class AlwaysOnDisplay extends Ui.Drawable { dc.getWidth() - mDataLeft, y, mBatteryFont, - value + " " + battery.format(INTEGER_FORMAT) + "%", + vehicleBattery + " " + watchBattery.format(INTEGER_FORMAT) + "%", Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER ); } diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index abe981e0..678f9d7f 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -15,9 +15,11 @@ class BackgroundService extends Sys.ServiceDelegate { (:background) function initialize() { + /*DEBUG*/ logMessage("In ServiceDelegate"); Sys.ServiceDelegate.initialize(); if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { + /*DEBUG*/ logMessage("returning because Storage.getValue(\"Tesla\") is " + Storage.getValue("Tesla") + " or gTeslaComplication is " + gTeslaComplication); return; } @@ -73,12 +75,12 @@ class BackgroundService extends Sys.ServiceDelegate { if (_vehicle_id == null) { _vehicle_id = Storage.getValue("TeslaVehicleID"); } - } (:background) function onTemporalEvent() { if (!Sys.getDeviceSettings().phoneConnected) { + /*DEBUG*/ logMessage("Our phone isn't connected, bailing out"); Bg.exit(null); } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index ddec7830..6c4d33c8 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -20,6 +20,8 @@ class CrystalApp extends App.AppBase { function initialize() { AppBase.initialize(); + + gTeslaComplication = $.getBoolProperty("TeslaLink", false); } // function onStart(state) { @@ -133,6 +135,7 @@ class CrystalApp extends App.AppBase { } } + /*DEBUG*/ var nextTime = Time.now().add(new Time.Duration(5 * 60)); var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next temporal event at " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); Bg.registerForTemporalEvent(new Time.Duration(5 * 60)); // Since onSettingsChanged go for a specific time, go for duration here once we get going, otherwise we'll get background data only once the view is shown Ui.requestUpdate(); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 903b035a..f0d19f31 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -193,13 +193,15 @@ class CrystalView extends Ui.WatchFace { // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { - /*DEBUG*/ logMessage("Registering for Temporal Events"); var lastTime = Bg.getLastTemporalEventTime(); if (lastTime) { // Events scheduled for a time in the past trigger immediately. var nextTime = lastTime.add(new Time.Duration(5 * 60)); + + /*DEBUG*/ var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next temporal event at " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); Bg.registerForTemporalEvent(nextTime); } else { + /*DEBUG*/ logMessage("Next Temporal Events should happen NOW"); Bg.registerForTemporalEvent(Time.now()); } } diff --git a/source/DataArea.mc b/source/DataArea.mc index 08452d62..d78d0993 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -119,7 +119,7 @@ class DataArea extends Ui.Drawable { var local = Gregorian.localMoment(where, Time.now()); local = Gregorian.info(local, Time.FORMAT_SHORT); - time = $.getFormattedTime(local.hour, local.min); + time = $.getFormattedTime(local.hour, local.min, local.sec); time = time[:hour] + ":" + time[:min] + time[:amPm]; } catch (e) { diff --git a/source/DataFields.mc b/source/DataFields.mc index 68d125bf..0a88386b 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -668,10 +668,10 @@ class DataFields extends Ui.Drawable { if (sinceSunrise >= 0 || sinceSunset >= 0) { result["isSunriseNext"] = true; - value = $.getFormattedTime(sunriseTime.hour, sunriseTime.min); + value = $.getFormattedTime(sunriseTime.hour, sunriseTime.min, sunriseTime.sec); } else { - value = $.getFormattedTime(sunsetTime.hour, sunsetTime.min); + value = $.getFormattedTime(sunsetTime.hour, sunsetTime.min, sunsetTime.sec); } value = value[:hour] + ":" + value[:min] + value[:amPm]; } @@ -723,7 +723,7 @@ class DataFields extends Ui.Drawable { } else { var hour = Math.floor(nextSunEvent).toLong() % 24; var min = Math.floor((nextSunEvent - Math.floor(nextSunEvent)) * 60); // Math.floor(fractional_part * 60) - value = App.getApp().getFormattedTime(hour, min); + value = App.getApp().getFormattedTime(hour, min, 0); value = value[:hour] + ":" + value[:min] + value[:amPm]; } } diff --git a/source/Global.mc b/source/Global.mc index fe44081b..b1e5b7fe 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -235,7 +235,8 @@ function updateComplications(complicationName, storageName, index, complicationT // Return a formatted time dictionary that respects is24Hour and HideHoursLeadingZero settings. // - hour: 0-23. // - min: 0-59. -function getFormattedTime(hour, min) { +// - sec: 0-59 +function getFormattedTime(hour, min, sec) { var amPm = ""; if (!Sys.getDeviceSettings().is24Hour) { @@ -266,6 +267,7 @@ function getFormattedTime(hour, min) { return { :hour => hour, :min => min.format("%02d"), + :sec => sec.format("%02d"), :amPm => amPm }; } diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index 74aa6091..31b8eb7c 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -62,7 +62,7 @@ class ThickThinTime extends Ui.Drawable { function drawHoursMinutes(dc) { var clockTime = Sys.getClockTime(); - var formattedTime = $.getFormattedTime(clockTime.hour, clockTime.min); + var formattedTime = $.getFormattedTime(clockTime.hour, clockTime.min, clockTime.sec); formattedTime[:amPm] = formattedTime[:amPm].toUpper(); var hours = formattedTime[:hour]; From 1d3313453da9f3eb3281175c311403f9f53016cd Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 17 May 2023 21:39:15 -0400 Subject: [PATCH 162/220] Made some annotation to help devices with low memory to exclude stuff they can't use (Complications for this round) --- README.md | 3 +++ manifest.xml | 2 +- monkey.jungle | 36 +++++++++++++++++++++++++ resources/strings/strings.xml | 2 +- source/CrystalView.mc | 49 ++++++++++++++++++++++++++++++++++- source/DataFields.mc | 19 ++++++++++++++ source/Global.mc | 10 +++++++ source/GoalMeter.mc | 29 +++++++++++++++++++++ 8 files changed, 147 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 34f99596..dc57f009 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.4 +- Made some conditional compiling so watches that don't support Complications do not include functions related to that. This is to help watches with low allocated watchface memory, like the Venu SQ, to run without crashing because of Out of Memory errors + ### 2.18.3 - Corrected invalid value for Stress read from sensor, not Complications - For performance, ignore Tesla-Link Complications if we're told not to use them diff --git a/manifest.xml b/manifest.xml index e03339da..29466cac 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + diff --git a/monkey.jungle b/monkey.jungle index f19c0c89..91320dca 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -39,3 +39,39 @@ fr265.sourcePath = $(fr265.sourcePath);always-on-source fr265s.sourcePath = $(fr265s.sourcePath);always-on-source marq2.sourcePath = $(marq2.sourcePath);always-on-source marq2aviator.sourcePath = $(marq2aviator.sourcePath);always-on-source + +base.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;noComplications +descentmk2.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications +descentmk2s.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +enduro.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications +fenix5plus.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +fenix5splus.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +fenix5xplus.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +fenix6.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications +fenix6pro.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications +fenix6s.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +fenix6spro.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +fenix6xpro.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications +fr245.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +fr245m.excludeAnnotations = highMemoryWatchface;bkgnd32kb;hasComplications +fr55.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +fr745.excludeAnnotations = highMemoryWatchface;bkgnd32kb;hasComplications +fr945.excludeAnnotations = highMemoryWatchface;bkgnd32kb;hasComplications +fr945lte.excludeAnnotations = highMemoryWatchface;bkgnd32kb;hasComplications +legacyherocaptainmarvel.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;hasComplications +legacyherofirstavenger.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;hasComplications +legacysagadarthvader.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;hasComplications +legacysagarey.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;hasComplications +marqadventurer.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +marqathlete.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +marqaviator.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +marqcaptain.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +marqcommander.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +marqdriver.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +marqexpedition.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +marqgolfer.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +venu.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications +venusq.excludeAnnotations = highMemoryWatchface;bkgnd64kb;hasComplications +venusqm.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications +vivoactive4.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;hasComplications +vivoactive4s.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;hasComplications diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index b887deca..f827c9f6 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.3 + Crystal-Tesla V2.18.4 Theme Hours Colour diff --git a/source/CrystalView.mc b/source/CrystalView.mc index f0d19f31..5ce7c0c0 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -153,6 +153,40 @@ class CrystalView extends Ui.WatchFace { // Set flag to respond to settings change on next full draw (onUpdate()), as we may be in 1Hz (lower power) mode, and cannot // update the full screen immediately. This is true on real hardware, but not in the simulator, which calls onUpdate() // immediately. Ui.requestUpdate() does not appear to work in 1Hz mode on real hardware. + (:noComplications) + function onSettingsChanged() { + mSettingsChangedSinceLastDraw = true; + //logMessage("onSettingsChanged called"); + + mFieldTypes[0].put("type", $.getIntProperty("Field1Type", 0)); + mFieldTypes[1].put("type", $.getIntProperty("Field2Type", 1)); + mFieldTypes[2].put("type", $.getIntProperty("Field3Type", 2)); + + mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); + mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + + // Themes: explicitly set *Colour properties that have no corresponding (user-facing) setting. + updateThemeColours(); + + // Update hours/minutes colours after theme colours have been set. + updateHoursMinutesColours(); + + ReadWeather(false); + + // Get our 2nd local time if available + var localTimeInCity = $.getStringProperty("LocalTimeInCity", ""); + var splitArray = $.to_array(localTimeInCity, ","); + if (splitArray.size() == 3) { + mLocalCityName = $.validateString(splitArray[0], "???"); + mLocalCityLat = $.validateFloat(splitArray[1], null); + mLocalCityLon = $.validateFloat(splitArray[2], null); + } + else { + mLocalCityName = null; + } + } + + (:hasComplications) function onSettingsChanged() { mSettingsChangedSinceLastDraw = true; //logMessage("onSettingsChanged called"); @@ -434,7 +468,7 @@ class CrystalView extends Ui.WatchFace { // Update the view function onUpdate(dc) { //Sys.println("onUpdate()"); - //DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); // If burn-in protection has changed, set layout appropriate to new burn-in protection state. // If turning on burn-in protection, free memory for regular watch face drawables by clearing references. This means that @@ -736,6 +770,11 @@ class CrystalView extends Ui.WatchFace { mDrawables[:MoveBar].setFullWidth(hideSeconds); } + (:noComplications) + function onComplicationUpdated(complicationId) { + } + + (:hasComplications) function onComplicationUpdated(complicationId) { var complication = Complications.getComplication(complicationId); var complicationType = complication.getType(); @@ -779,6 +818,14 @@ class CrystalView extends Ui.WatchFace { } } +(:noComplications) +class CrystalDelegate extends Ui.WatchFaceDelegate { + public function initialize(view as CrystalView) { + WatchFaceDelegate.initialize(); + } +} + +(:hasComplications) class CrystalDelegate extends Ui.WatchFaceDelegate { private var mview as CrystalView; diff --git a/source/DataFields.mc b/source/DataFields.mc index 0a88386b..5cb71159 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -75,6 +75,25 @@ class DataFields extends Ui.Drawable { } // Cache FieldCount setting, and determine appropriate maximum field length. + (:noComplications) + function onSettingsChanged() { + var view = App.getApp().getView(); + + // #123 Protect against null or unexpected type e.g. String. + mFieldCount = $.getIntProperty("FieldCount", 3); + + // #116 Handle FieldCount = 0 correctly. + mMaxFieldLength = [0, 8, 6, 4][mFieldCount]; + + mHasLiveHR = view.hasField(FIELD_TYPE_HR_LIVE_5S); + + if (!view.hasField(FIELD_TYPE_WEATHER)) { + mWeatherIconsFont = null; + mWeatherIconsSubset = null; + } + } + + (:hasComplications) function onSettingsChanged() { var view = App.getApp().getView(); diff --git a/source/Global.mc b/source/Global.mc index b1e5b7fe..eb2782fa 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -198,6 +198,11 @@ function writeBatteryLevel(dc, x, y, width, height, type) { //**************************************************************** } +(:noComplications) +function updateComplications(complicationName, storageName, index, complicationType) { +} + +(:hasComplications) function updateComplications(complicationName, storageName, index, complicationType) { if (Toybox has :Complications) { // Check if we should subscribe to our Tesla Complication @@ -491,6 +496,11 @@ function to_array(string, splitter) { return result; } +(:noComplications) +function doTeslaComplication(complicationValue) { +} + +(:hasComplications) function doTeslaComplication(complicationValue) { /*DEBUG*/ logMessage("Complication read: " + complicationValue); if (complicationValue instanceof Lang.String) { // Only handle the enhance data sent, not just the battery SoC (a Number) diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index 4273a946..f2745fe2 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -110,6 +110,35 @@ class GoalMeter extends Ui.Drawable { mIsOff = isOff; } + (:noComplications) + function onSettingsChanged(index) { + mBuffersNeedRecreate = true; + + // #18 Only read separator width from layout if multi segment style is selected. + // #62 Or if filled segment style is selected. + var goalMeterStyle = $.getIntProperty("GoalMeterStyle", 0); + if ((goalMeterStyle == 0 /* ALL_SEGMENTS */) || (goalMeterStyle == 3 /* FILLED_SEGMENTS */)) { + + // Force recalculation of mSegments in setValues() if mSeparator is about to change. + if (mSeparator != mLayoutSeparator) { + mMaxValue = null; + } + + mSeparator = mLayoutSeparator; + + } else { + + // Force recalculation of mSegments in setValues() if mSeparator is about to change. + if (mSeparator != 0) { + mMaxValue = null; + } + + mSeparator = 0; + } + } + + + (:hasComplications) function onSettingsChanged(index) { mBuffersNeedRecreate = true; From 38eb3e8ccd31297d7241f19d31bfd494ae4f75a9 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 17 May 2023 21:51:26 -0400 Subject: [PATCH 163/220] Saw a weird crash in onPress so I added type checking to prevent it from happening again --- README.md | 1 + source/CrystalView.mc | 102 ++++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index dc57f009..fe9b1dda 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Reviews: ### 2.18.4 - Made some conditional compiling so watches that don't support Complications do not include functions related to that. This is to help watches with low allocated watchface memory, like the Venu SQ, to run without crashing because of Out of Memory errors +- Saw a weird crash in onPress so I added type checking to prevent it from happening again ### 2.18.3 - Corrected invalid value for Stress read from sensor, not Complications diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 5ce7c0c0..0f3e425a 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -859,36 +859,38 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { if (indicatorCount > 0) { var indicators = mview.mDrawables[:Indicators]; - var locX = indicators[:locX]; - var locY = indicators[:locY]; - var batteryWidth = indicators[:mBatteryWidth]; - - spacingY = indicators[:mSpacing]; - spacingX = batteryWidth * 2; - locX -= (batteryWidth / 1.5).toNumber(); - if (indicatorCount == 1) { - locY -= spacingY; - spacingY *= 2; - } - else { - locY -= spacingY / 2; - } + if (indicators != null) { + var locX = indicators[:locX]; + var locY = indicators[:locY]; + var batteryWidth = indicators[:mBatteryWidth]; + + spacingY = indicators[:mSpacing]; + spacingX = batteryWidth * 2; + locX -= (batteryWidth / 1.5).toNumber(); + if (indicatorCount == 1) { + locY -= spacingY; + spacingY *= 2; + } + else { + locY -= spacingY / 2; + } - if (indicatorCount == 3) { - complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacingY, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], locX, locY, spacingX, spacingY, "2") + isWithin(co_ords[0], co_ords[1], locX, locY + spacingY, spacingX, spacingY, "3"); - } else if (indicatorCount == 2) { - complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], locX, locY + spacingY / 2, spacingX, spacingY, "2"); - } else if (indicatorCount == 1) { - complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY, spacingX, spacingY, "1"); - } + if (indicatorCount == 3) { + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacingY, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], locX, locY, spacingX, spacingY, "2") + isWithin(co_ords[0], co_ords[1], locX, locY + spacingY, spacingX, spacingY, "3"); + } else if (indicatorCount == 2) { + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], locX, locY + spacingY / 2, spacingX, spacingY, "2"); + } else if (indicatorCount == 1) { + complicationIndex = "Complication_I" + isWithin(co_ords[0], co_ords[1], locX, locY, spacingX, spacingY, "1"); + } - if (complicationIndex.equals("Complication_I") == false) { - complicationId = Storage.getValue(complicationIndex); - } + if (complicationIndex.equals("Complication_I") == false) { + complicationId = Storage.getValue(complicationIndex); + } - //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); - if (complicationId != null) { - return complicationId; + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } } } @@ -903,21 +905,23 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { var right = mview.mDataFields.mRight; var top = mview.mDataFields.mTop; - if (fieldCount == 3) { - complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacingX / 2, top - spacingY /2, spacingX, spacingY, "2") + isWithin(co_ords[0], co_ords[1], right - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "3"); - } else if (fieldCount == 2) { - complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.15) - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.85) - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "2"); - } else if (fieldCount == 1) { - complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1"); - } + if (left != null && right != null && top != null) { + if (fieldCount == 3) { + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacingX / 2, top - spacingY /2, spacingX, spacingY, "2") + isWithin(co_ords[0], co_ords[1], right - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "3"); + } else if (fieldCount == 2) { + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.15) - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1") + isWithin(co_ords[0], co_ords[1], left + ((right - left) * 0.85) - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "2"); + } else if (fieldCount == 1) { + complicationIndex = "Complication_F" + isWithin(co_ords[0], co_ords[1], (right + left) / 2 - spacingX / 2, top - spacingY / 2, spacingX, spacingY, "1"); + } - if (complicationIndex.equals("Complication_F") == false) { - complicationId = Storage.getValue(complicationIndex); - } + if (complicationIndex.equals("Complication_F") == false) { + complicationId = Storage.getValue(complicationIndex); + } - //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); - if (complicationId != null) { - return complicationId; + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } } } @@ -929,15 +933,17 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { var right = mview.mDrawables[:DataArea].mGoalIconRightX + spacingX / 8; var y = mview.mDrawables[:DataArea].mGoalIconY - spacingY / 8; - // spacing * 3 to give it more room so we can press on the text too. - complicationIndex = "Complication_G" + isWithin(co_ords[0], co_ords[1], left, y, spacingX * 3, spacingY, "1") + isWithin(co_ords[0], co_ords[1], right - spacingX * 3, y, spacingX * 3, spacingY, "2"); - if (complicationIndex.equals("Complication_G") == false) { - complicationId = Storage.getValue(complicationIndex); - } + if (left != null && right != null && y != null) { + // spacing * 3 to give it more room so we can press on the text too. + complicationIndex = "Complication_G" + isWithin(co_ords[0], co_ords[1], left, y, spacingX * 3, spacingY, "1") + isWithin(co_ords[0], co_ords[1], right - spacingX * 3, y, spacingX * 3, spacingY, "2"); + if (complicationIndex.equals("Complication_G") == false) { + complicationId = Storage.getValue(complicationIndex); + } - //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); - if (complicationId != null) { - return complicationId; + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } } return null; From c1a6263be79f2eb3c9117e222bc3024041826757 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 18 May 2023 21:44:10 -0400 Subject: [PATCH 164/220] Reduced the logMessage quantity to get more lines in log file --- source/BackgroundService.mc | 10 +++++----- source/CrystalApp.mc | 2 +- source/CrystalView.mc | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 678f9d7f..fef23ebb 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -15,7 +15,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background) function initialize() { - /*DEBUG*/ logMessage("In ServiceDelegate"); + //DEBUG*/ logMessage("In ServiceDelegate"); Sys.ServiceDelegate.initialize(); if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { @@ -102,7 +102,7 @@ class BackgroundService extends Sys.ServiceDelegate { return; } - /*DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); + //DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); } @@ -226,7 +226,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("VehicleID", null); _vehicle_id = null; } - /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); + //DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); return; } @@ -234,7 +234,7 @@ class BackgroundService extends Sys.ServiceDelegate { else if (responseCode == 401) { var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { - /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); + //DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); makeWebPost(refreshToken, method(:onReceiveToken)); return; } @@ -270,7 +270,7 @@ class BackgroundService extends Sys.ServiceDelegate { "Authorization" => _token, "User-Agent" => "Crystal-Tesla for Garmin", }, - :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN }; //2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); Comms.makeWebRequest(url, params, options, callback); diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 6c4d33c8..fae2039c 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -135,7 +135,7 @@ class CrystalApp extends App.AppBase { } } - /*DEBUG*/ var nextTime = Time.now().add(new Time.Duration(5 * 60)); var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next temporal event at " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); + /*DEBUG*/ var nextTime = Time.now().add(new Time.Duration(5 * 60)); var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next event: " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); Bg.registerForTemporalEvent(new Time.Duration(5 * 60)); // Since onSettingsChanged go for a specific time, go for duration here once we get going, otherwise we'll get background data only once the view is shown Ui.requestUpdate(); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 0f3e425a..55ba7735 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -468,7 +468,7 @@ class CrystalView extends Ui.WatchFace { // Update the view function onUpdate(dc) { //Sys.println("onUpdate()"); - /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + //DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); // If burn-in protection has changed, set layout appropriate to new burn-in protection state. // If turning on burn-in protection, free memory for regular watch face drawables by clearing references. This means that From 3536ebf5f9babaef207947a71b448b9e356ae3f0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 20 May 2023 16:41:33 -0400 Subject: [PATCH 165/220] Fix for mDigitStyle and mShowWeatherStationName not included when in :noComplications --- source/CrystalView.mc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 55ba7735..49e46bc2 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -184,6 +184,9 @@ class CrystalView extends Ui.WatchFace { else { mLocalCityName = null; } + + mDigitStyle = $.getIntProperty("GoalMeterDigitsStyle", 0); + mShowWeatherStationName = $.getBoolProperty("ShowWeatherStationName", true); } (:hasComplications) @@ -218,13 +221,13 @@ class CrystalView extends Ui.WatchFace { mLocalCityName = null; } + mDigitStyle = $.getIntProperty("GoalMeterDigitsStyle", 0); + mShowWeatherStationName = $.getBoolProperty("ShowWeatherStationName", true); + // Reread our complications if we're allowed mUseComplications = $.getBoolProperty("UseComplications", false); gTeslaComplication = $.getBoolProperty("TeslaLink", false); - mDigitStyle = $.getIntProperty("GoalMeterDigitsStyle", 0); - mShowWeatherStationName = $.getBoolProperty("ShowWeatherStationName", true); - // We're not looking at the Complication sent by Tesla-Link and we have a refesh token, register for temporal events if (gTeslaComplication == false && $.getStringProperty("TeslaRefreshToken", "").length() > 0) { var lastTime = Bg.getLastTemporalEventTime(); From 4a2f62c5f8bc56b95dd6172b8f840e2f929e0539 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 22 May 2023 08:24:55 -0400 Subject: [PATCH 166/220] try/catch to prevent out of memory in Bg.exit --- source/BackgroundService.mc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index fef23ebb..47673c8e 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -128,8 +128,13 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("httpErrorTesla", 401); teslaInfo.put("httpInternalErrorTesla", responseCode); + try { Bg.exit({ "TeslaInfo" => teslaInfo }); } + catch (e) { + Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); + } + } (:background) function onReceiveVehicles(responseCode, responseData) { @@ -179,8 +184,13 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("httpErrorTesla", (_vehicle_id == null ? 404 : 408)); teslaInfo.put("httpInternalErrorTesla", responseCode); + try { Bg.exit({ "TeslaInfo" => teslaInfo }); } + catch (e) { + Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); + } + } (:background) function onReceiveVehicleData(responseCode, responseData) { @@ -198,6 +208,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("httpErrorTesla", responseCode); if (responseCode == 200) { + teslaInfo.remove("httpInternalErrorTesla"); teslaInfo.put("VehicleState", "online"); var response = responseData.get("response"); @@ -240,8 +251,13 @@ class BackgroundService extends Sys.ServiceDelegate { } } + try { Bg.exit({ "TeslaInfo" => teslaInfo }); } + catch (e) { + Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); + } + } (:background) function makeWebPost(token, notify) { @@ -270,7 +286,7 @@ class BackgroundService extends Sys.ServiceDelegate { "Authorization" => _token, "User-Agent" => "Crystal-Tesla for Garmin", }, - :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; //2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); Comms.makeWebRequest(url, params, options, callback); From d4ec93a4a4641da7f92090e0db6d49161a35dedb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 1 Jun 2023 21:52:02 -0400 Subject: [PATCH 167/220] 2.18.6 - Added a default custom Complication to launch when pressing anywhere that's it's not a field, indicator or goal configured as a complication. By Default, this field is set to "Flashlight" (new Widget I created), which if installed on the watch, will transform the screen into a flashlight with three intensity, with the launched one being the dimmest - Fixed a crash in onPress --- README.md | 8 ++++++ resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/settings/properties.xml | 1 + resources/settings/settings.xml | 4 +++ resources/strings/strings.xml | 3 +- source/BackgroundService.mc | 4 +-- source/CrystalView.mc | 48 ++++++++++++++++++++++--------- 26 files changed, 72 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index fe9b1dda..73a37eb3 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,14 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.6 +- Added a default custom Complication to launch when pressing anywhere that's it's not a field, indicator or goal configured as a complication. By Default, this field is set to "Flashlight" (new Widget I created), which if installed on the watch, will transform the screen into a flashlight with three intensity, with the launched one being the dimmest +- Fixed a crash in onPress + +### 2.18.5 +- Fixed for crashing when too much data in the background buffer +- Fixed for not showing goal's max value on watches not having Complications + ### 2.18.4 - Made some conditional compiling so watches that don't support Complications do not include functions related to that. This is to help watches with low allocated watchface memory, like the Venu SQ, to run without crashing because of Out of Memory errors - Saw a weird crash in onPress so I added type checking to prevent it from happening again diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 29fe42bf..9e8d9493 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index fd395cd1..422fd198 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index fee8493a..864112f2 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 29431d91..b5d1cad2 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 3bc17ab2..43669add 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index a745186c..90546b02 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -124,4 +124,5 @@ Utilisez les Complications de Tesla-Link pour l'info Tesla Quel véhicle afficher? Montrer le nom de la station météo? + Long nom de la complication diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 6b767be0..f75f640b 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index c07103a1..ca52daeb 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 90d4c7bf..d26181d0 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 39a0302a..416ee072 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 371198e1..17eb8635 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index fbe0cdea..975ceadf 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 7ec9fc74..103f93c0 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 3599bdb5..4f25e572 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 7cfd7483..37933169 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 61bb38ed..0284b578 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index a911f7dd..060b6524 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index b6609b46..e0bb748d 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 78fe660d..bf574032 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index d075f05d..623cb5c0 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -125,4 +125,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 18fa5645..9b84c73d 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -6,6 +6,7 @@ false false + Flashlight 0 1 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index e2558b00..cb32f8be 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -34,6 +34,10 @@ + + + + @Strings.Steps diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index f827c9f6..0600a2b9 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.4 + Crystal-Tesla V2.18.6 Theme Hours Colour @@ -124,4 +124,5 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? + Complication Long Name diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 47673c8e..4b10858f 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -185,8 +185,8 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("httpInternalErrorTesla", responseCode); try { - Bg.exit({ "TeslaInfo" => teslaInfo }); - } + Bg.exit({ "TeslaInfo" => teslaInfo }); + } catch (e) { Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 49e46bc2..c4ea29c6 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -830,13 +830,13 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { (:hasComplications) class CrystalDelegate extends Ui.WatchFaceDelegate { - private var mview as CrystalView; + private var mView as CrystalView; //! Constructor //! @param view The analog view public function initialize(view as CrystalView) { WatchFaceDelegate.initialize(); - mview = view; + mView = view; } public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { @@ -845,9 +845,31 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { // returns the complicationId within the boundingBoxes if (Toybox has :Complications && App.getApp().getView().useComplications()) { - var complicationId = checkBoundingBoxes(co_ords); - if (complicationId != null) { - Complications.exitTo(complicationId); + if (mView != null && mView.mDrawables != null && mView.mDataFields != null) { // Saw an unexpected error because one of these were null, although it shouldn't have happened + var defComplicationName = $.getStringProperty("ComplicationName", ""); + var complicationId = checkBoundingBoxes(co_ords); + if (complicationId != null) { + Complications.exitTo(complicationId); + } + else if (defComplicationName.length() > 0 ) { + // We're outside our hotspots, see if we can launch our Flashlight + var iter = Complications.getComplications(); + if (iter == null) { + return; + } + complicationId = iter.next(); + + while (complicationId != null) { + //logMessage(complicationId.longLabel.toString()); + if ((complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(defComplicationName))) { + //DEBUG*/ logMessage("Found our flashlight complication"); + complicationId = complicationId.complicationId; + Complications.exitTo(complicationId); + return; + } + complicationId = iter.next(); + } + } } } } @@ -861,7 +883,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { var complicationId; if (indicatorCount > 0) { - var indicators = mview.mDrawables[:Indicators]; + var indicators = mView.mDrawables[:Indicators]; if (indicators != null) { var locX = indicators[:locX]; var locY = indicators[:locY]; @@ -904,9 +926,9 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { spacingX = Sys.getDeviceSettings().screenWidth / (2 * fieldCount); spacingY = Sys.getDeviceSettings().screenHeight / 4; - var left = mview.mDataFields.mLeft; - var right = mview.mDataFields.mRight; - var top = mview.mDataFields.mTop; + var left = mView.mDataFields.mLeft; + var right = mView.mDataFields.mRight; + var top = mView.mDataFields.mTop; if (left != null && right != null && top != null) { if (fieldCount == 3) { @@ -932,9 +954,9 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { spacingX = Sys.getDeviceSettings().screenWidth / 11; spacingY = Sys.getDeviceSettings().screenHeight / 6; - var left = mview.mDrawables[:DataArea].mGoalIconLeftX - spacingX / 8; - var right = mview.mDrawables[:DataArea].mGoalIconRightX + spacingX / 8; - var y = mview.mDrawables[:DataArea].mGoalIconY - spacingY / 8; + var left = mView.mDrawables[:DataArea].mGoalIconLeftX - spacingX / 8; + var right = mView.mDrawables[:DataArea].mGoalIconRightX + spacingX / 8; + var y = mView.mDrawables[:DataArea].mGoalIconY - spacingY / 8; if (left != null && right != null && y != null) { // spacing * 3 to give it more room so we can press on the text too. @@ -972,6 +994,6 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void { //DEBUG*/ logMessage("Average execution time: " + powerInfo.executionTimeAverage); //DEBUG*/ logMessage("Allowed execution time: " + powerInfo.executionTimeLimit); - //mview.turnPartialUpdatesOff(); + //mView.turnPartialUpdatesOff(); } } From fe18389c41e104266e5c722284f7ddc944cea9b3 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 1 Jun 2023 23:18:42 -0400 Subject: [PATCH 168/220] Update BackgroundService.mc --- source/BackgroundService.mc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 4b10858f..edaac683 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -252,7 +252,7 @@ class BackgroundService extends Sys.ServiceDelegate { } try { - Bg.exit({ "TeslaInfo" => teslaInfo }); + Bg.exit({ "TeslaInfo" => teslaInfo }); } catch (e) { Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); From 4cc116653d8fcf8bcc6f5f4a7d3e1012b853ad66 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:37:57 -0400 Subject: [PATCH 169/220] Added support for new watches --- manifest.xml | 8 ++++++++ monkey.jungle | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/manifest.xml b/manifest.xml index 29466cac..0fe0e452 100644 --- a/manifest.xml +++ b/manifest.xml @@ -3,12 +3,17 @@ + + + + + @@ -18,8 +23,11 @@ + + + diff --git a/monkey.jungle b/monkey.jungle index 91320dca..d2b98a2e 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -39,6 +39,11 @@ fr265.sourcePath = $(fr265.sourcePath);always-on-source fr265s.sourcePath = $(fr265s.sourcePath);always-on-source marq2.sourcePath = $(marq2.sourcePath);always-on-source marq2aviator.sourcePath = $(marq2aviator.sourcePath);always-on-source +approachs7042mm.sourcePath = $(approachs7042mm.sourcePath);always-on-source +approachs7047mm.sourcePath = $(approachs7047mm.sourcePath);always-on-source +epix2pro42mm.sourcePath = $(epix2pro42mm.sourcePath);always-on-source +epix2pro47mm.sourcePath = $(epix2pro47mm.sourcePath);always-on-source +epix2pro51mm.sourcePath = $(epix2pro51mm.sourcePath);always-on-source base.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;noComplications descentmk2.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications From d44374fac315721b6828acb95544325d35fc3699 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 30 Aug 2023 19:28:26 -0400 Subject: [PATCH 170/220] Added support for the Venu3 and Venu3S --- README.md | 3 +++ manifest.xml | 2 ++ monkey.jungle | 2 ++ resources/strings/strings.xml | 2 +- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73a37eb3..17187185 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.7 +- Added support for the Venu3 and Venu3S + ### 2.18.6 - Added a default custom Complication to launch when pressing anywhere that's it's not a field, indicator or goal configured as a complication. By Default, this field is set to "Flashlight" (new Widget I created), which if installed on the watch, will transform the screen into a flashlight with three intensity, with the launched one being the dimmest - Fixed a crash in onPress diff --git a/manifest.xml b/manifest.xml index 0fe0e452..000c1cfb 100644 --- a/manifest.xml +++ b/manifest.xml @@ -60,6 +60,8 @@ + + diff --git a/monkey.jungle b/monkey.jungle index d2b98a2e..d58fea14 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -30,6 +30,8 @@ venusq2m.sourcePath = $(venusq2m.sourcePath);always-on-source venud.sourcePath = $(venud.sourcePath);always-on-source venusq.sourcePath = $(venusq.sourcePath);always-on-source venusqm.sourcePath = $(venusqm.sourcePath);always-on-source +venu3.sourcePath = $(venu3.sourcePath);always-on-source +venu3s.sourcePath = $(venu3s.sourcePath);always-on-source d2air.sourcePath = $(d2air.sourcePath);always-on-source d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 0600a2b9..1f60f097 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.6 + Crystal-Tesla V2.18.7 Theme Hours Colour From cf9da496097ab6cade916683746157fc75bc8191 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 20 Sep 2023 19:40:21 -0400 Subject: [PATCH 171/220] 2.18.8 - Added support for the VivoActive5 --- README.md | 3 +++ manifest.xml | 1 + monkey.jungle | 1 + 3 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 17187185..e304e55e 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.8 +- Added support for the VivoActive5 + ### 2.18.7 - Added support for the Venu3 and Venu3S diff --git a/manifest.xml b/manifest.xml index 000c1cfb..06b16806 100644 --- a/manifest.xml +++ b/manifest.xml @@ -68,6 +68,7 @@ + diff --git a/monkey.jungle b/monkey.jungle index d58fea14..b3c2980e 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -46,6 +46,7 @@ approachs7047mm.sourcePath = $(approachs7047mm.sourcePath);always-on-source epix2pro42mm.sourcePath = $(epix2pro42mm.sourcePath);always-on-source epix2pro47mm.sourcePath = $(epix2pro47mm.sourcePath);always-on-source epix2pro51mm.sourcePath = $(epix2pro51mm.sourcePath);always-on-source +vivoactive5.sourcePath = $(vivoactive5.sourcePath);always-on-source base.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;noComplications descentmk2.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications From f760cd79a42ad05f6e40352bac31837d632bb497 Mon Sep 17 00:00:00 2001 From: Adrien Chenu Date: Thu, 21 Sep 2023 08:34:42 +0100 Subject: [PATCH 172/220] Extend Longitude to between -180 to +180 --- source/DataArea.mc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/DataArea.mc b/source/DataArea.mc index d78d0993..3ec45e89 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -107,7 +107,7 @@ class DataArea extends Ui.Drawable { // Time zone 1 time. var time; - if (view.mLocalCityLat != null && view.mLocalCityLat >= -90.0 && view.mLocalCityLat <= 90.0 && view.mLocalCityLon != null && view.mLocalCityLon >= -90.0 && view.mLocalCityLon <= 90.0) { + if (view.mLocalCityLat != null && view.mLocalCityLat >= -90.0 && view.mLocalCityLat <= 90.0 && view.mLocalCityLon != null && view.mLocalCityLon >= -180.0 && view.mLocalCityLon <= 180.0) { try { var where = new Position.Location({ :latitude => view.mLocalCityLat, From fe3b81c3ee79d86ce9dac8a0ae641639640afea8 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 26 Sep 2023 20:05:16 -0400 Subject: [PATCH 173/220] 2.18.9 Adjusted the fonts of the Venu Sq2 --- README.md | 3 +++ resources-rectangle-320x360/fonts/fonts.xml | 13 ++++++++----- resources-rectangle-320x360/layouts/layout.xml | 4 ++-- resources/strings/strings.xml | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e304e55e..6140685a 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.9 +- Adjusted the fonts for the Venu Sq2 + ### 2.18.8 - Added support for the VivoActive5 diff --git a/resources-rectangle-320x360/fonts/fonts.xml b/resources-rectangle-320x360/fonts/fonts.xml index f7f39530..3e4aa06c 100644 --- a/resources-rectangle-320x360/fonts/fonts.xml +++ b/resources-rectangle-320x360/fonts/fonts.xml @@ -1,9 +1,12 @@ - + - - - - + + + + + + + diff --git a/resources-rectangle-320x360/layouts/layout.xml b/resources-rectangle-320x360/layouts/layout.xml index 469f2708..a84bf770 100644 --- a/resources-rectangle-320x360/layouts/layout.xml +++ b/resources-rectangle-320x360/layouts/layout.xml @@ -31,12 +31,12 @@ 87 234 30 - 62 + 53 37 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 1f60f097..9afcebfb 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.7 + Crystal-Tesla V2.18.9 Theme Hours Colour From ebd3efb57ed65b5228c5457cf9818d9864de05ab Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 26 Sep 2023 20:13:50 -0400 Subject: [PATCH 174/220] Fixed DEDUG for DEBUG --- source/BackgroundService.mc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index edaac683..d9ddca8e 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -28,7 +28,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); + /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); } var timeNow = Time.now().value(); @@ -115,7 +115,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveToken: Buffer has keys " + keys); + /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveToken: Buffer has keys " + keys); } if (responseCode == 200) { @@ -145,7 +145,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicles: Buffer has keys " + keys); + /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicles: Buffer has keys " + keys); } if (responseCode == 200) { @@ -202,7 +202,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo = {}; } else { - /*DEDUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); + /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); } teslaInfo.put("httpErrorTesla", responseCode); From c78bd422501517d2c390f970616fa0ee8e88d0d9 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 5 Nov 2023 22:17:17 -0500 Subject: [PATCH 175/220] V2.19.0 Adds the following - Added Altitude as a Complication - Fixed bug in longitude typechecking for second time (thanks AdrienChenu) --- README.md | 4 ++++ resources/strings/strings.xml | 2 +- source/DataFields.mc | 12 +++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6140685a..19858889 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.19.0 +- Added Altitude as a Complication +- Fixed bug in longitude typechecking for second time (thanks AdrienChenu) + ### 2.18.9 - Adjusted the fonts for the Venu Sq2 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 9afcebfb..c8e111c3 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.9 + Crystal-Tesla V2.19.0 Theme Hours Colour diff --git a/source/DataFields.mc b/source/DataFields.mc index 5cb71159..b82afc29 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -117,6 +117,7 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_TYPE_PULSE_OX, "complicationType" => Complications.COMPLICATION_TYPE_PULSE_OX}, {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE}, {"type" => FIELD_RECOVERY_TIME, "complicationType" => Complications.COMPLICATION_TYPE_RECOVERY_TIME}, + {"type" => FIELD_TYPE_ALTITUDE, "complicationType" => Complications.COMPLICATION_TYPE_ALTITUDE}, {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_WEATHER}, // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain {"type" => FIELD_TYPE_SUNRISE_SUNSET, "complicationType" => Complications.COMPLICATION_TYPE_SUNRISE} // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain ]; @@ -619,9 +620,14 @@ class DataFields extends Ui.Drawable { // #67 Try to retrieve altitude from current activity, before falling back on elevation history. // Note that Activity::Info.altitude is supported by CIQ 1.x, but elevation history only on select CIQ 2.x // devices. - activityInfo = Activity.getActivityInfo(); - altitude = activityInfo.altitude; - + if (Toybox has :Complications && view.useComplications()) { // Try Complication first + altitude = fieldTypes[index].get("ComplicationValue"); + } + if (altitude == null) { + activityInfo = Activity.getActivityInfo(); + altitude = activityInfo.altitude; + } + if ((altitude == null) && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getElevationHistory)) { sample = SensorHistory.getElevationHistory({ :period => 1, :order => SensorHistory.ORDER_NEWEST_FIRST }).next(); if ((sample != null) && (sample.data != null)) { From 61da380621878edec7ecdd6288eb83d03ea167ac Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 4 Dec 2023 21:48:11 -0500 Subject: [PATCH 176/220] 2.18.12 (in progress) - Fixed crash when complicationId is unexpectedly null - Added Battery as a complication (to launch the battery widget) --- README.md | 11 +++++-- resources/strings/strings.xml | 2 +- source/CrystalView.mc | 6 ++-- source/Indicators.mc | 60 ++++++++++++++++++++++++----------- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 19858889..924abecf 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,16 @@ Reviews: ## Below is what has been added by me (SylvainGa). -### 2.19.0 -- Added Altitude as a Complication +### 2.18.12 +- Fixed crash when complicationId is unexpectedly null +- Added Battery as a complication (to launch the battery widget) + +### 2.18.11 - Fixed bug in longitude typechecking for second time (thanks AdrienChenu) +- Altitude reads from Complication if available + +### 2.18.10 +- Added Altitude as a Complication ### 2.18.9 - Adjusted the fonts for the Venu Sq2 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index c8e111c3..0191b46e 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0 + Crystal-Tesla V2.18.12 Theme Hours Colour diff --git a/source/CrystalView.mc b/source/CrystalView.mc index c4ea29c6..9098c977 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -864,8 +864,10 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { if ((complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(defComplicationName))) { //DEBUG*/ logMessage("Found our flashlight complication"); complicationId = complicationId.complicationId; - Complications.exitTo(complicationId); - return; + if (complicationId != null) { // Got a crash caused by a null complicationId (while holding over 'Steps' while in a indoor walk activity) + Complications.exitTo(complicationId); + return; + } } complicationId = iter.next(); } diff --git a/source/Indicators.mc b/source/Indicators.mc index d020fda4..4d0cddfb 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -22,6 +22,7 @@ class Indicators extends Ui.Drawable { // INDICATOR_TYPE_NOTIFICATIONS, // INDICATOR_TYPE_BLUETOOTH_OR_NOTIFICATIONS, // INDICATOR_TYPE_BATTERY + // INDICATOR_TYPE_BATTERY_NUMERIC // INDICATOR_TYPE_TESLA // } @@ -44,39 +45,62 @@ class Indicators extends Ui.Drawable { mIndicator2Type = $.getIntProperty("Indicator2Type", 3); mIndicator3Type = $.getIntProperty("Indicator3Type", 0); + var indicator; + var filled = [false, false, false]; + + if (App.getApp().getView().useComplications()) { + indicator = findIndicator(4); // INDICATOR_TYPE_BATTERY + if (indicator != null) { + $.updateComplications("", "Complication_I", indicator, Complications.COMPLICATION_TYPE_BATTERY); + filled[indicator - 1] = true; + } + + indicator = findIndicator(5); // INDICATOR_TYPE_BATTERY_NUMERIC + if (indicator != null) { + $.updateComplications("", "Complication_I", indicator, Complications.COMPLICATION_TYPE_BATTERY); + filled[indicator - 1] = true; + } + } + //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - var teslaIndicator; - - if (mIndicator1Type == 6) { - teslaIndicator = 1; - } - if (mIndicator2Type == 6) { - teslaIndicator = 2; - } - if (mIndicator3Type == 6) { - teslaIndicator = 3; - } - if (teslaIndicator != null) { + indicator = findIndicator(6); // INDICATOR_TYPE_TESLA + if (indicator != null) { //DEBUG*/ logMessage("onSettingsChanged:Doing Tesla!"); Storage.setValue("Tesla", true); if (App.getApp().getView().useComplications()) { - $.updateComplications("Tesla-Link", "Complication_I", teslaIndicator, Complications.COMPLICATION_TYPE_INVALID); + $.updateComplications("Tesla-Link", "Complication_I", indicator, Complications.COMPLICATION_TYPE_INVALID); + filled[indicator - 1] = true; } } else { Storage.deleteValue("Tesla"); - teslaIndicator = 0; } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** for (var i = 1; i < 4; i++) { - if (i != teslaIndicator) { + if (filled[i - 1] == false) { Storage.deleteValue("Complication_I" + i); } } -//**************************************************************** -//******************** END OF REMVOVED SECTION ******************* -//**************************************************************** + } + + function findIndicator(complicationType) { + var indicator = null; + + if (mIndicator1Type == complicationType) { + indicator = 1; + } + if (mIndicator2Type == complicationType) { + indicator = 2; + } + if (mIndicator3Type == complicationType) { + indicator = 3; + } + + return indicator; } function draw(dc) { From f9663599dd288c46646084174e92a681ed4eef0b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 8 Dec 2023 21:42:19 -0500 Subject: [PATCH 177/220] V2.18.12 (in progress) Found the cause for the crash at line 862. onPress caught exception PreviousOperationNotCompleteException Added try/catch around exitto calls. --- source/CrystalView.mc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 9098c977..6263be84 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -849,7 +849,10 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { var defComplicationName = $.getStringProperty("ComplicationName", ""); var complicationId = checkBoundingBoxes(co_ords); if (complicationId != null) { - Complications.exitTo(complicationId); + try { + Complications.exitTo(complicationId); + } + catch (e) {} } else if (defComplicationName.length() > 0 ) { // We're outside our hotspots, see if we can launch our Flashlight @@ -864,8 +867,13 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { if ((complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(defComplicationName))) { //DEBUG*/ logMessage("Found our flashlight complication"); complicationId = complicationId.complicationId; + /*DEBUG*/ logMessage("complicationId is '" + complicationId + "'"); if (complicationId != null) { // Got a crash caused by a null complicationId (while holding over 'Steps' while in a indoor walk activity) - Complications.exitTo(complicationId); + try { + Complications.exitTo(complicationId); + } + catch (e) {} + return; } } From d2e89347c764505d4350492412e6164b87146920 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 8 Dec 2023 21:43:30 -0500 Subject: [PATCH 178/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 924abecf..a735fa84 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.18.12 -- Fixed crash when complicationId is unexpectedly null +- Fixed crash when calling a complication while there is already one running - Added Battery as a complication (to launch the battery widget) ### 2.18.11 From c2393ad9f7652cd8a231aa66f0fcba4d9a77364e Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:18:24 -0400 Subject: [PATCH 179/220] 2.18.13 - Compiled with CIQ 7.1.1 - Added Forerunner 165 and 165m - Updated the Tesla status when the car is asleep to match the returned data from Tessie - Fixed a broken weather icon --- README.md | 6 ++++++ manifest.xml | 2 ++ monkey.jungle | 2 ++ resources/strings/strings.xml | 2 +- source/CrystalView.mc | 1 + source/Global.mc | 2 +- 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a735fa84..428836de 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,12 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.18.13 +- Compiled with CIQ 7.1.1 +- Added Forerunner 165 and 165m +- Updated the Tesla status when the car is asleep to match the returned data from Tessie +- Fixed a broken weather icon + ### 2.18.12 - Fixed crash when calling a complication while there is already one running - Added Battery as a complication (to launch the battery widget) diff --git a/manifest.xml b/manifest.xml index 06b16806..57f1da95 100644 --- a/manifest.xml +++ b/manifest.xml @@ -28,6 +28,8 @@ + + diff --git a/monkey.jungle b/monkey.jungle index b3c2980e..7934d33f 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -37,6 +37,8 @@ d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source epix2.sourcePath = $(epix2.sourcePath);always-on-source fr965.sourcePath = $(fr965.sourcePath);always-on-source +fr165.sourcePath = $(fr165.sourcePath);always-on-source +fr165m.sourcePath = $(fr165m.sourcePath);always-on-source fr265.sourcePath = $(fr265.sourcePath);always-on-source fr265s.sourcePath = $(fr265s.sourcePath);always-on-source marq2.sourcePath = $(marq2.sourcePath);always-on-source diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 0191b46e..79a3f02a 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.12 + Crystal-Tesla V2.18.13 Theme Hours Colour diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 6263be84..fd5aceb3 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -334,6 +334,7 @@ class CrystalView extends Ui.WatchFace { //logMessage("icon=" + icon); } else { + icon = icon + day; /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; diff --git a/source/Global.mc b/source/Global.mc index eb2782fa..10add69a 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -104,7 +104,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { var httpErrorTesla = teslaInfo.get("httpErrorTesla"); var vehicleState = teslaInfo.get("VehicleState"); var vehicleAsleep = (vehicleState != null && vehicleState.equals("asleep") == true); - var vehicleOnline = (vehicleState != null && vehicleState.equals("online") == true); + var vehicleOnline = (vehicleState != null && vehicleState.equals("awake") == true); // Only specific error are handled, the others are displayed 'as is' in pink if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { From fa4fbe5b3be53f0e50334c992c5e344c7399f500 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:55:02 -0400 Subject: [PATCH 180/220] V2.18.4 Added the Descent MK3 variants --- manifest.xml | 2 ++ monkey.jungle | 2 ++ 2 files changed, 4 insertions(+) diff --git a/manifest.xml b/manifest.xml index 57f1da95..caa26ee4 100644 --- a/manifest.xml +++ b/manifest.xml @@ -9,6 +9,8 @@ + + diff --git a/monkey.jungle b/monkey.jungle index 7934d33f..01ae348e 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -49,6 +49,8 @@ epix2pro42mm.sourcePath = $(epix2pro42mm.sourcePath);always-on-source epix2pro47mm.sourcePath = $(epix2pro47mm.sourcePath);always-on-source epix2pro51mm.sourcePath = $(epix2pro51mm.sourcePath);always-on-source vivoactive5.sourcePath = $(vivoactive5.sourcePath);always-on-source +descentmk343mm.sourcePath = $(descentmk343mm.sourcePath);always-on-source +descentmk351mm.sourcePath = $(descentmk351mm.sourcePath);always-on-source base.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;noComplications descentmk2.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications From 5dbc710fb340e21f57317e5410bde5e86d727648 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:56:47 -0400 Subject: [PATCH 181/220] 2.19.0 - Compiled with CIQ 7.1.1 - Added Active calories as a data fiel and goal. This value is calculated and not provided by Garmin so it might be off to what Garmin is showing. On Complication enabled watches, since it shows only Active calories, the calculated rested calories are added to the Calories fields and goals. To get the previous active calories, select Active Calories field or goal. --- README.md | 4 + manifest.xml | 1 + resources-ces/strings/strings.xml | 2 + resources-dan/strings/strings.xml | 2 + resources-deu/strings/strings.xml | 2 + resources-dut/strings/strings.xml | 2 + resources-fin/strings/strings.xml | 2 + resources-fr55/settings/settings.xml | 17 ++-- resources-fre/strings/strings.xml | 2 + resources-hrv/strings/strings.xml | 2 + resources-hun/strings/strings.xml | 2 + resources-ita/strings/strings.xml | 2 + resources-kor/strings/strings.xml | 2 + resources-no_floors/settings/settings.xml | 14 +-- resources-nob/strings/strings.xml | 2 + resources-pol/strings/strings.xml | 2 + resources-por/strings/strings.xml | 2 + .../fonts/crystal-icons-large.fnt | 5 +- .../fonts/crystal-icons-large.png | Bin 11546 -> 11859 bytes .../fonts/crystal-icons-extra-large.fnt | 3 +- .../fonts/crystal-icons-extra-large.png | Bin 8031 -> 8196 bytes resources-rus/strings/strings.xml | 2 + resources-slo/strings/strings.xml | 2 + resources-slv/strings/strings.xml | 2 + .../fonts/crystal-icons-small.fnt | 5 +- .../fonts/crystal-icons-small.png | Bin 6003 -> 6125 bytes resources-spa/strings/strings.xml | 2 + resources-swe/strings/strings.xml | 2 + resources-zhs/strings/strings.xml | 2 + resources-zht/strings/strings.xml | 2 + resources/fonts/crystal-icons.fnt | 3 +- resources/fonts/crystal-icons.png | Bin 6735 -> 6895 bytes resources/settings/settings.xml | 17 ++-- resources/strings/strings.xml | 4 +- source/CrystalView.mc | 44 ++++++++- source/DataArea.mc | 1 + source/DataFields.mc | 84 +++++++++++++----- source/Global.mc | 2 + source/GoalMeter.mc | 11 ++- 39 files changed, 200 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 428836de..da7157f5 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.19.0 +- Compiled with CIQ 7.1.1 +- Added Active calories as a data fiel and goal. This value is calculated and not provided by Garmin so it might be off to what Garmin is showing. On Complication enabled watches, since it shows only Active calories, the calculated rested calories are added to the Calories fields and goals. To get the previous active calories, select Active Calories field or goal. + ### 2.18.13 - Compiled with CIQ 7.1.1 - Added Forerunner 165 and 165m diff --git a/manifest.xml b/manifest.xml index caa26ee4..77d6803f 100644 --- a/manifest.xml +++ b/manifest.xml @@ -80,6 +80,7 @@ + ces diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 9e8d9493..f87a65de 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 422fd198..0852199f 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 864112f2..a904449e 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -64,6 +64,7 @@ Recovery Time Aktive Minuten (Wöchentlich) Kalorien (manuelles Ziel) + Active Calories (Manual Goal) Aus Herzfrequenz @@ -72,6 +73,7 @@ Batterie (Prozente ausgeblendet) Hinweise Kalorien + Active Calories Distanz Alarme Höhe diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index b5d1cad2..6797f396 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -64,6 +64,7 @@ Recovery Time Actieve Minuten (Wekelijks) Calorieën (Manueel Doel) + Active Calories (Manual Goal) Uit Hartslag @@ -72,6 +73,7 @@ Batterij (Verberg Percentage) Notificaties Calorieën + Active Calories Afstand Alarmen Hoogte diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 43669add..dcbe52a9 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-fr55/settings/settings.xml b/resources-fr55/settings/settings.xml index b0bce9f7..b83d66ab 100644 --- a/resources-fr55/settings/settings.xml +++ b/resources-fr55/settings/settings.xml @@ -30,9 +30,10 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.BodyBattery - @Strings.StressLevel - @Strings.Off + @Strings.ActiveCaloriesManualGoal + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off @@ -44,9 +45,10 @@ @Strings.Battery @Strings.CaloriesManualGoal - @Strings.BodyBattery - @Strings.StressLevel - @Strings.Off + @Strings.ActiveCaloriesManualGoal + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off @@ -59,6 +61,7 @@ @Strings.BatteryHidePercentage @Strings.Notifications @Strings.Calories + @Strings.ActiveCalories @Strings.Distance @Strings.Alarms @Strings.Altitude @@ -82,6 +85,7 @@ @Strings.BatteryHidePercentage @Strings.Notifications @Strings.Calories + @Strings.ActiveCalories @Strings.Distance @Strings.Alarms @Strings.Altitude @@ -105,6 +109,7 @@ @Strings.BatteryHidePercentage @Strings.Notifications @Strings.Calories + @Strings.ActiveCalories @Strings.Distance @Strings.Alarms @Strings.Altitude diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 90546b02..e102a706 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -64,6 +64,7 @@ Temps de recouvrement Minutes actives (hebdo) Calories (objectif manuel) + Calories actives (objectif manuel) Masqué Rythme cardiaque @@ -72,6 +73,7 @@ Pile (Pourcentage masqué) Notifications Calories + Calories active Distance Alarmes Altitude diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index f75f640b..ceba2ec6 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index ca52daeb..d3d6e6cc 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index d26181d0..5b4bf17e 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 416ee072..4e880431 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-no_floors/settings/settings.xml b/resources-no_floors/settings/settings.xml index 6026ec4f..34de3768 100644 --- a/resources-no_floors/settings/settings.xml +++ b/resources-no_floors/settings/settings.xml @@ -6,9 +6,10 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.BodyBattery - @Strings.StressLevel - @Strings.Off + @Strings.ActiveCaloriesManualGoal + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off @@ -19,9 +20,10 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.BodyBattery - @Strings.StressLevel - @Strings.Off + @Strings.ActiveCaloriesManualGoal + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off \ No newline at end of file diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 17eb8635..6ac7d306 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 975ceadf..cdcbe962 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -64,6 +64,7 @@ Recovery Time Aktywne Minuty (Tygodniowo) Spalone Kalorie (Ręczny Cel) + Active Calories (Manual Goal) Off Tętno @@ -72,6 +73,7 @@ Bateria (Sama Wartość) Powiadomienia Kalorie + Active Calories Odległość Budziki Wysokość diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 103f93c0..ce5de5ab 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-round-280x280/fonts/crystal-icons-large.fnt b/resources-round-280x280/fonts/crystal-icons-large.fnt index 2cb6e22d..57e72afe 100644 --- a/resources-round-280x280/fonts/crystal-icons-large.fnt +++ b/resources-round-280x280/fonts/crystal-icons-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-28 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=28 base=28 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-large.png" -chars count=23 +chars count=24 char id=48 x=0 y=0 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 char id=49 x=25 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=50 x=53 y=0 width=28 height=28 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 @@ -24,4 +24,5 @@ char id=67 x=186 y=28 width=26 height=25 xoffset=0 yoffset=0 char id=68 x=213 y=28 width=28 height=28 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=69 x=0 y=56 width=24 height=28 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=70 x=25 y=56 width=20 height=28 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 -char id=71 x=45 y=56 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 \ No newline at end of file +char id=71 x=45 y=56 width=25 height=28 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 +char id=72 x=70 y=56 width=17 height=28 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 \ No newline at end of file diff --git a/resources-round-280x280/fonts/crystal-icons-large.png b/resources-round-280x280/fonts/crystal-icons-large.png index 66d36a53be7bf8119823d139ef8ca4fc842b90a9..890a15c2680bdc4cbc19f726dab67e2e59f5a0a7 100644 GIT binary patch literal 11859 zcmeI2Wmgp5*M^6ZF6od?>5%S58bm-!>F#b2=@_~Mr2L7ZlynR^bR%8T-JSpAr+D5x zYYj8AW?r!7oE`Ul?H#SDu8566jsbx{u$7hMv>^}#@D>4rh6r9J@FaP_3#x~*nmp<@ zDh3GxwG~5zANUB}MajS&0>Sb4_lIE5P(1~KaGWa3Nx$)#JIF<^SKGL4^VUu-fEv=# zR@c|58p}Qx#P7!wwESi>yx{OX_?u=jtvg&bt6_1XA+?f)^3B&lBOQEU+PNpwyCH8$ z`?FRA9}?@l}0NY@%HCCY-)*szGTMb;HL*%$@>bo zjeg}6ra$GTlC1;1sjL&rPmfn7Eq-b_0*(iBH9d*c%Qg0TW@f8jq(9Ep*k^E=wqge6 z%jg+<{#j^nhus}Efd^OM$eUs%e7R-f4R}07Q*5p^$_m+Ur^QCYIw!H@JaK=Ci%A{J zfpoQH3fI=&G`8si*~ofx@MXOG}KCHr{&hgle_71(<4sbJfbh)cP89MVv#)$P?{<; z5cS;U_u8K!Vtc#4*yMe(+8ua%-j^>4Yhs|7l}Cut%9Is?c21lq-R7<^SF>*Bc{K4WvL{~Mt{?BB(@-$@F~GaVq4~6*ZDd~D_4s-% zalo?7pnCIkfJ>u%BH;06>(KOZuN<}-vT((jFTXQhQs*$69E9QW^l)`FTa7vpnP^h) zLJN0m3qfe#5dS$>s`DT8B94sjHIKw`TKr)$r8;A~o;*aS8hNqfHl+5`P>cswnK!<4 zyq99#@q$Z2KF2HH;F*YoMJ~rErhYpmwGFIq%QCHb%(R-^0z6Zg)P6M`irjmhZ4U9= zUoL$+)v9>ko*#7Er-Lx#fAL4J+@xi$a&It;Z;S7g{oU_v5EBoF2Rjr0iF#~9)3;>V z@71Ro+^u0n^*XiZDd{Eoh$~*;uFd!Bn8PPgaVXIg&Go{+b$^S&IJk9g-1&-6uW%0z zSu63CCb+rLqwMnfRSc^CSf37?j`}a{%Uh;61>Dw^be>Ufy9{ifwFcg)hJKs61(|W# z{7wrZEIQj@euPRL0NqUdlQQoNdpQ2vsdaP!o{Of_gxxpOISeHp&L=)$l3cRMZW6kX z2b64SDM=b+uqp^?Ra*`5>xJ0;`F^qchmDr@@7)pXzs>b^3$uc&C4XF%!~+k)po5xe zGm;_wFETnefme&xDt0j|QZV8;(WB-GPUTFtd1~MFB&(t9EVEc*4qi)gew&qFk*AkC z$C9YHRO{bBGPsrRCui|mn(0*_hSMbse_%?W5|0r|iU~OFV=jf&MG4iBG;OBqdvoqa z=4U*<5X-&6uCD-z?N3Z^g)O8AlHNQiNT893Mm7Q~_@YoQ`ni@oHNAC?xS-HyI{BEH z$iX~u(FbQU7ooKJ;LRN8)*Timlf!KLUw@MdsI&(Kj=_<5OzV8p zEC{K7+B1FPHQ7!OJ*@DibqqH-H6RT6&Yc~=V$xhMt9y+OLO`Wc)TqWzw+Gi3T)nyE zX9o_IboN%>t`RTF(OO4CZyr^L7*6~#qe`<+tjAM^&V62Wh}ShFj7&_=R3rucwuW=H zGvBu;CQ^X|md*F|$rbU;=CzC=HK#;`_39@bwcc@J=VL<`bR4^5h{WkPQ)L+6SU#!p zs@p!R!QTtX-Q=5*st~CVf{YnJ^n&KF=Q!sy zRaFa_l!#so5teP8T}Yl6cxm8F)}PLi6F7|=lsRvYr*-`&=>FPOv3>^{gq1m)_7+34 z%0ii^E?nH`=e&wcgWE>yfNH^5>Q+eP`!6JJ3h6d5qK|WKd8m)Ri{u*D>;IoM5OPTj7 zk|+7L7E-sSK7UcFuezcM{OMN87j+Ln*&8u%DO)sBN|%9fTMcFoaKXe_SxeuPYJ>D$ zRg9qXT>|x6O-brBaPMbb0<~n`$iv-L2HbhyfJLo92CIOcC_?8yb>Z53a#}l{?{;H_ zp8}X7cV;S!?uyf1>aGTZo8Q+pwgI-LL^)x+`6CHA_MC0-D9X!;qf>+)3JEj3ApJwmi z6wY!jLi0#MbKNjc=|g8uiZNE>#^1(yJ#a62Vi^$ijQclRl26f2u(M%NTZ_`*NQ{Gh z9h>D=@l7(rn)mI9v%C&76%=$(*Zy=+2ed=X2)!sDXRY)5x<%g!U|U3n`zj_-@)){p z4L=O>jm%i0EhL@p{c6Ht-O8ics1mnB(pqi}Y|u;Kd#?R@mA0{Ghg-amJAtOd!aya1 zvn0f|gB7u+%&4L2CT5XeFIKbUw}2@l1J8wM#JqJKGo4}HPxV?mH^YOxs-+hHp2A!N zj1_cRn!1l2T(J8p^NjyMSx~dm4z98L^LUy8%M9SWINmQE9qURM&C#hAq}<8oX(sb;n*_Qz+~yjvT!&>v;*YWiDA<-+6l zc@2fSeub`t#%JpH>@WnK@rP=NUl2Au!=WU-$S&IK@p%Ue&$F4>hD6ufR3WX|X_rFW zh=mv4Lfn#tUY=7vB!vozN=>RF(P<$+vs!HQ^xU0f)vs82xLQtpAtSo?=SQT35*eb$ zL_p|)caC*CL;JHs&$#b&N~ZKzjPmUz#ZGSQcGS@EE}S$azmJ>q^V9*y(gf!34f=G^ zJO_vVB4wdd%rY9X?32Dx8H7JE=Ld|tDj=&naorxxbi4lz28zUWvh?0K(*))v+tn6+ zeUGQ{(X*RKulRB4*-B}fE0u1MLOi5Iy1#^!%tB~(xLGxg4OWnn_z36thnEMj&r}2Ta$@Os)VD~M~dItG?{aa-K?~K zJZOuE+vr5Q?4`qae|Mm1Li0fix#4fZ!RAt9kB!H{oUT_^l6#OGc4%^Pve-Ns&q0C~ zX&!z!dj2>oGA|XAJQT+ljo@$)A2tVlqs-GIRO_;iFdv_zfU0V5p3Nd9j7cC%zx>xd z=dB}(kSizK+cK!}HD`mv-D~Z+&kk)jlizg*-h7hR=xj#R{JHz*hp52nOEo?50utCT zF-p;{n9c~=65cCxre#k|GQ$`WE~=RDvVy3r41F}VH5OaH^l^H0PMxo+0dZ%=XasFtHV?nwZcmhVdmVvElG= z{EXnI{BW}5fApyttKqjNMv-EoRV*12r9@q4{)*fj`u(vz&GV=p%8!GZxJi$QC>R0f zV~Pbzl5M|jCq@x$`Rg!q2vrEbSo9^kdLZIe&S1P}&oEpz3t!$A56k7diN9^U*~}@4 zBWt%JnBb-lMv1ay*OZP`&EoBYH+t?x&_9^w<(dW!X7bPncnL+Q0d=;JqyQoOrCk!! z6eQO^W=250){~f#M^;GVfA?9~eScyoS2P1FT=c!j3MB`z{^&I)z?mSzK)+4-V^NcSrnrA?mfoum9mv(WvEEqs zU6(3YOffCiBUE+5E9fGe66yABT@k}CZg?$v@m`YbY_ZYCYeCMT4tXt?QV8L%#3N+B zq$7OHH!s#IQdq)0ie}D}8dKf}mf@3Pr=u{&%(LhyrN-4Fnb#HfMyfv9*<)X>r(BBF zxZw?w<5yjl1p9u(G@A(`3b!C^y#`t+U?-iGQrdsF1MBRoQ4xip0@BZ&u70U-wVYEw zT}Mtrp-`7jY(b%H`^7Ix&sXVLE-w*~o<*I1^cYQ!r+KKij69E|SN8J5iij1xuB62~ z&8@XcjAqd;Ml;wfl#f+98dPB4NYRi`?j_}~Jv7>%6pf~u@GPK;619TS0)VwRK4^YYAAZ=aS=c$i@Dz(!9;&XM~z7)ySD`Qk?@h&l?6Fo)aKm z4;LEFK%rSpXZTHWB`=_CcUU)t#FL2pd=k%P350pjKTm;R9E3b$wOi>tmdRr-7MmoM zGryM}#1}x%(mc{%4Y^r*zu_wdp%jy9JeByIM*uv*<7obUTmA5I`D3z5?{IXQ z+SwFP3{&N%!E5n?>72&z#*u>DpB^8YJa&>lf2Leh#-BpLB#!F)uY>%Ro!o(df;N6v zcPt43zZ=3KZT?AnTA5*80$$YiK=ts+T2D#?%An#!F)*+e9+&AZ3@(Cv{#c;6xM)CE zZ@}%&f4sgNYC)|ztKG5Fzl`U{qC=&ne?P+}m!q zARn3^;nYKQKcku_HruL4iZ)_Ks^T%|YJSq0SDTMlA{C0b^+dceoJ;ZdaHf)8tI~ES zxwb4-n&H5vkBKzObrDB$_#+~k*vseTzzmW`0xdoNI_+h5Ua9Fi-eQusNaGUJf21#k zN9NIP>QxrMt+tf%0{a!;u1EgO+16c6MJ_66tx=KG!fwTK-A0aa_~iuQ&;HO3%r8O?Bj30>Bb1K);Vq%9sz^N^^Cdb3$gd5eP*R|KDqOsSdvWikSGjA7l9(6pZmBtVi z3@L@(kk`nIYz5Z_EvUlWPR2`hn0?;>W08yBjwNZ8k?P9zdz)0BS`}#3jc?byi{BRf zk6N^Yf$v!RK?}s{SFX1-Vh`5HJ#FC)?px2eZdn}`8~;!ykHhnyOq33Mh_~*_t{>{> zrTz*0Jz{*;Z0UCaP|K28M#sy;q)gl6`QBUm@1lf>B8_MxPvOU)a5WQeH^-9Ayep8_rN~hMr(nxR}w^qx$_l}5MY^p zZM~rv$mW4l2VEB|F5a~v;m$0U_(TKZ@VYNo)Vnc*OaOXT-}xUY#Y-iEhAkkqUkJM~ zL=R2lKPMo#JKvcoR!#x_pywoYgn~p0!Q!Q$kRO3rmnwhCrxYx!2FB=%#Xx@?gN%Zw zl{`w)nDA+fKY7l~Xa?At2^$;^7NIpZ3s|m z|8Py8tg0F_7DDot@=2dIWJF=f8P0mmF-RVRMf%sniq^*i;yqcSLJ}v_lknp1>IfEa zD0L0qIYDsV@=-94Ot7+FqA1* za^B`dUOKY3@EtUWUxCK2(liBGV05)OMQ#hI--(s6l>G%3(F&*UP;STQa z?S}V4{b$j8xJxyQAMzmZ@@GYm%zRdzuf5h1nY1Z~te+6R2 zdCxx^)|k!E@7~4ImpDixU0!jEfRDqZkzT=UUk<$Meqsbvm$OaWjt$2IK&*-jILG1o z*@&bw`EzjUeCt|Fs%}cVBYVvxP8*xP^OjKD%Kp4dE(_MSkGK*--iJmvgQ%_W0tgN` zB?`C&sa=)?#>gIO#H64?qRmDSBq*2S<{6TVA?q<0h}urrt?V znkAeTgw9s^vZ%s6&rG&y)2@GtSQzT~`f!`Wu|{4ypk(q{Cj@ND?h;86+u#H5ER7}Z zyd=h#^l8hwT$UX5Qf3{HU2$o#f(G%R858sof|MZS-y?)Tnl-!X!Xss#>-$%(_H#ASro&jD#=_uZCjG*Ypk0qy4&8rD2Xm2);k*LEcC{pYKeQ z=iK^5YSnQNEg)JOP9pJ@oai|UkOh{6VuTV*s_PqlMhe~P>+x1pE^&ea#j zLl}F+ii+R7{aFaX{1NH1lpjk7Px$@S`518Y=^n%bgo?3L(qSG;Nse1XIn&0FGj`=& zAUqHwR(t6pw?E{G`R?X+8@T{)srFRI@AqEXPLbwYH&!fv4$+AvI#zqR;AC@bw@I?r z+raM6IjnM8?Oe*k6#+M=E6G*8&%ZpYV*HtG&cE;%GIYxA#e-477~hlsEHiiwnR0V^ z1id&CF_Wa=8S-kenKo0xn6%Y;qG^xJcG(j)>Lqp#?_so@u-kgY7Dv4^B9oC<->un# z<3x@Evg+VL(3(!Kou|B{T3Mnbx*~jgfPA>}{nBPFkgFlzo`t55Qp>LCu^+DMTeaqt zTiMcFeJ*wh`1pv#&4-1QDd3pxUo?+itbo9s-bJCINK?U6`&O0QRlQB4e)s#2uCVNk z1&g8V8u?gaZNndLf3k$UaV1NXqgj4+z%i~82of*^{&u3n{GJO@v4Wwdpb+$PzTA+* zP2Zk@xPPih5g{OKpNm{-TkzaH>^LGGlZ5J@mG)s-PVIJ@VNbYPWqXu zB}yH(f{$^N{+d};tcM^V?a!f&zPQMlQue*6X15}4+Z@X2O#0NZvG>m}&oQZgjzWyh zQq+F&EXVi~*|$d|hh+)$T6y%b-{U1JcZ-e;Aw~=QGwxq(?bGvmMrT{m*!^OdJmqvl z08$-@#yk16Wp++`xlW3d;X|BtVMRe=AdUK}&3!YT=BLFt21DRhL9aH+*JQ#AtBzo+ ziIOV8cGvnHv2>D!erpNRP&Au@I#W;TghAzu5wp9Z)_h|ON)ZpG*6hwt*c1XYM>Rd4 z2k5A2VvpnlryIIRt#loGZlPj)>KyhItF1%zdZETcIfAB@W+>vKid#Kc ztCkvEqPlOBeInl+&ShgP5&w8cd51Y+i6f!d7t=w;Yq9d^GO>^2Mp%}O%ObU#vUWU+ zrxeEW(O|4MRdoQ5C4F1+B@+R+@p<^7+?iFHn1qrGm#KL`a9q1hsW8+gPm!^_Jegx0 zIojA8R>}7AbP0QVtSHhn3+N1`tZ(L5Lmp_V8Oz^wpCNjm1&K~T%p#f^s`WpAw27rK zf~F?vZ-6NV6H5$6$4lX>D17?Sc_1$e!n*_pGPugY+cz4?OnsH~=)@gKY0lTq<#00f z9}GfjgD@I4)P4%L3dX}%F*p4RDfuPaB0NfRkxKtH^W&JaS27Le2;y?}5zujekqTHm zMTRJGuqw7~kKw!!!Sj=Nyk66??}X0>+5wDq>cOt>q5YwH64WH16Psr`XUMxvr9;q{z9-T_pbLBINhIml*Hs#7&F6RKYDN0~dPFbH> z#G3mejZ`{iGR4P{BR$b|k6FJsI(tPDM=3mhGAw{_lAIQPAV~0)FfYbDm%B>PzihZ0 zBJy4v?!rJ$J90Q%&5WBolN%L#_g=%r^?X0`k=Pf-j(by{2p&jFc^V`UfP(O0(ly+o z<#Yw=X-4Z`LllRZhP;(wn@K4u(qR!Q;_o^6dml|j_RRUSR0U!M4-N_q7Na^;uy+{@ zPOONAqY0R^wYrp*m4#ecKjyn8GGo#J?y96*RQ(S`(efBUzJBX7U?ErwhWHvD zs~OhVrTG$l4Bbm==~X-C)-}riy&O4We3dAN600s%@3!$8CM?^bt7i=KWW9~iXZpDh zTyysS={iwz-Bc%8Opm!!#);{WVI*Z{+W2GPf9E$0;lUn)g%Cg^+s&JRE*xh-mLXoO zj{LAaT0r`8Kjrs(5&b4F$GFb_ST}=8F#fhyh9z8_q6EpuUFhKUe@t!SN`6hb$3pI6 zW2I{1(rOXV4Vdo11+8*C7=$sO5DEU9x#s<_!EZ_tRsJqu*-zN>l2tAOXz-2Wl^O-@ zY|6V(&kU($tO!~En@}IpYG{%Vl2Q6vx7`Weau^&zv%q%)tADP_Ql$tfV8xzNnfvrZ z`83=4!TfYD_Oo&Ra0=+ojGo$AKpo0>=b9p(v0Y8HSmVg`Zik$P4jxgoz^TL)DU6>ArS&vS8 z<5quKY>z@m%zpni|IH|vZ&0m+(X(c)gF*GM%NuSLFi_zAl{IQ0f~JPxwHS1F@KqQM z_D@jz&f2iM2#wQRxW_89l_Vvw6Obi;RYgWgOTY9CB2S!XrsX5ngm`E8f+^AgNm4zT zs8^Z6a1Lf$m>Y$l(}I$c>~+j}4w+=okMhE{^48mzNtyVqNT@h2*7YS{(}abE$(Toh zhWE-snw@VA^jGz%b6Sj&?Kt^$tqh@mm;k7cH~x(imESfkyE+(I1TL?wu8t{Ezu+;G z1IWOf`q(>*HG~;hzCh4?#3@L~bXw1#I`xLM)gOK43 zXfc!on@TK`-xlCx5ZE^-J=8ZE)#GSI`-Opg2h(+461!0!L zVcL;6(FF%9CaS7QO8F`#<2It^Tc0a?@pAEXTxod+Zg|8f8Ol%HAL((NO!6v9N;K~A z;-?KEc*TFp49+@nB^RnJF+*R!`{_eP-F2d*-Qsr|qwyKlWK-nB>}VgdpWfUQuJ9cJO`L}3V@&bAMYAHl!XE| zxAIe7AgcWxk+=h-GV>_2RO$L|ul&Co%--AR=94=xL8JS0d%_-Ir2@2~dGx@>!;DPh zg7gNAoX)c=*JiNnaT-LEtpL+5BTo-*DvK5!;SNr~W|lP$wM4W1G-vp@G10s82@S=u z(Dn6vyQ%xYB zvXvyw;+Ymq4(eFB@cDuj2t#mrf9)kHQh|9dN$cVKmGc;F?`B*r;`yc>t z+C>W33z!NoB-^|$Pha`aGB-(I7TR;X<$TtQ@C=uV-Fd#uq(#Imax4vRdn-SfN+RGN zuuf`_jl^+Ws2@AC)D-}O8evyDvc1Q(M8%i7-{roT5kmC-5mkoM^Bo;ngvJ^kqKR`< ze?bR|Ty8%f}BR=$exAKE^;6;xeROfOEOGew@m=r1`gl7hPTTSEX%ZWp?hMT z^2p{Y#*y+kFEwKZuBBlP9?@e$e}eUcT92J^xjxc4B>Y}%wD_p~Bw=JH&?`VN#*`d* z0lsjJ;kFEfgrMD|%k4SY)9rK^pw?g{KM%AlXOq|(z(Ge1|Ct;&aVzm16HQ9}=CkZi z1@T;zFDGh&54s@(#P@8oWi#8p%5nhCc+)ai@4Vcapp_0B1N3u_OG1>*Mt>TzC&?`< z3kkwM#;Jv17HY}3F7zT4H(;^aIuVPPRqvP4NS=674p_^P55zS%+r-7+RXTPTKox2M zoE2bbIv<-~A*Jcc8em=pDxZu?lIKp!NE#c-FJ+Uxc&pnXQ(AsE*zJ5=d%7o^HXpO} zjVV%A+b;b{R4ae;u`eiyiQ<>~m1f<**vp4_&>{NC(5U<2i7~ahZ>cNXDko6;Z5IF~ z*m^#$;!f9mIcM*Cx_%;>ZXv7i-3?*lKMiWhAhEDKMwN8QhaC+DhV?F9stDd7+vu!R z8(DT{|Dksx0rjJTCJjQpxuRE~NzsmTIewYZ>xyOY`P=b{Mb^xWPMM=!83@|xGJ}sy zc*>~F&{wB8&C8C#AZ49eF5Y%rW${@HfC~hateA}SJq&@?hoSoWuiuESgnCh!Rf^qT zl!7MQA0oc2w8x##zbs&Zaa5WShFqii{?sh!0J}O+Pnly}iEF8t4-F^J2&H5zhJtFy zQ1pLq>zG{uu-5Oe_^!sTkF=~mjm>;z$P8Nms6@svWe7}Qbm}%{Cehb)0 zIx%GFCiXL;E!;El`k)3(hiK^yvvyqWh4Y;&*FEq3qu20uf^`;$6zx$TH z?NNgn`pMr&Y9?VSF&`I}aZxtbF5qea=3E3d=ZY5X3N&Y{k-YfBPjo5Y0ciV($I%r}&+piw!zXVP(>qErGK!$0vPvzEMG?5)}PuHkV)y~TjwzunZ zGrRy{T;8fN{mxh+l(^ld_X1i%Lp;O`Eqk4*>Jzu+;I(1rM%{9d{hVr}*TK6|ZARax zGs_I)%?ynB*tf<(Hyf82CSdP|j!uSgX1i`hRj8_#O+jpb+tPrCrz7St(ofX;tyfKB~yF-`a8f9z^$sml@*%6idlGaOHj4B{hvk^ zw-A7~@h(XfLpzKpXx%pl!OjUC1y1Wr{_wLU7h(xi_VM+GVU*$iZ^-#C9{2+^ATjQsf~t&*QH>Z7usfP$E}Q$OWAyzYeYG zAA-&@oGYpq=gLx5_^-6zTQwyu60>NwxqnM6iwghsZ;h=orete{t}wWd5&2#!#svQL zUW=PbN_&aZxbeLvDEk^{2_?)Jb_?~c0P>=*CNb}@W9o1GFsMeg=-tZVgT49T<^S_t z4e$=Z z`-OQIfsh&85J@F`>EAw|9A>yUh)!j7_4G<9r6=qBKqkx47$BOEoB4hKky;2@4mi62 z@eRELQ#jDk?!gL?bVjd}ICClVjY~SnutKWC*=2$K5-dhm=gl6WXHS{wY&WlIx`MOz z7#_OjaKGH6YC$ZF>B2#-|J$$oghABdK+jSi2BtbWzszdI&Ib7qKJwh1`?B$FY+$`R zzk&&tth%njwGG=)-VdrEks7!bm7e>JmY-mKn>S)7l`K zHhJUv;Um=gf~66w${EsvdqBfMh>*o#o$=4BeK{h-4+QgNI0Z|v>Tn+y*zQ;aMOkxw z5hGLgMrv@hSed}=D#J9$7wrF4g^^dHHsX6`-wX*pO&Qc$sXZ5w=a;X|<}iEkx2cp`F zrSa|U&p8lQT1c?g?+~>3-auu@;GNhM!_UpVD$CX*nto7a0n=T_CTHCM6B{saP5$lK z&p>+SMC$!_baw0u$!$6tNv69zjTutoA5501x(M0DD+|L(OIB$LijhoI^ z9WBFV=R)eBMV`7p-o`(qNeHlLfLvK0dK+$i+DcE+(`0e{-0qGjG4FkG7dxUQx#22z zI%q{ix$i2?N*rc^)Mw$%Ual6~Vw_-k_uD1_qfLvFjm?F2w%5Bo3}wSO)@kNX#Ru5~ z49#IJ2oF?lx390S>QntHnD`*ey9yy>o%H^->i^Rk2xFDH+@BSfy=OP5n*3=v%}#-j zN@@SLhne|sx|}*1L)&RS=tk8iq9;=_`0=K7xnEud)Udfa=fo~iVm3~r`eRTqTC9f1 zdzx&Essit(K$A>?9&1#WnD^lD3a(_^izy_EFhRN^eY?wO>~OylHj--l)qKq^B&F(>Ewd0548k^UYH>gQSFj!)E%(tc z(wM~TncN=`B|*+OZarMSBoTemf-rE=(uTIZ2dlMS(O_$UnThF_DU6C4&%b4R@c1u1 zbwEXyZ-EEP>Cy;bKN_EfPG)#;SxxJljE|ODkW4hGFy-t)Z|<54;(MOI;{D~Ff!Q6{ zxp(*6=UktwqBYdy(NKs{prD}86cuFNK|w)-r_fMHFyLVhQ=AJtAi686$|4@XqQh`= zZSXlGapN5!yO)q zC)sKL_ln!*PU4p1nRLqOPxm{Ci0Guct*(35 zM{^_sj-(rAxj`=v%^QLLf}vq8r}8@;*V;bcwwy1smzNs0 zy0U?%IZj=zHwy+lw`$;uGS?28j_Vz*Zd_8sZG6OD|yVmYi zz-u!bgU8}|w*Gtpq3FKfj+KqUbt&JaELV`=#&$y{aP>jJzdmyR^Gh-CS2~*kd*}6R za4H^)whZZK<$M#DWs3}1w+**Rp@VP&V`syzz~@J=bstC`8zM)?c^{89J^E?;nV3%; zpWQ+(_y>_kj=I>x!1Gwp>$4X#rPngv&kBvAzD1LuJQoz_6^G`N-%W4E3F);tz_LSTJrn?Bw5=%BmC zz|A}fr)2%>x?A^yW)goo@7KWfzg@PPSzXNhkTWIzN-7BDiIvER%%9T#j>$5@F*Hi%{Frg{Z0k( zj1+@0c>f*_3PkaO8wiZtXa3B8Co5OW7xAGNoqG3G$>De7NR7REuHa0Q-J;AoM%{V4 zULv{ZQ+08v{SgD}m>_)NZzkQ^!n%$8&39)j%^bMVWS^+%X;`=$ue!HmScVeF{;fE5 z%XTbCn6ht4bz6a*&r&m28nl}(pEz>pdC2D!Xo=U5RLV%@_8;RyMm+Q}EH|cP# zdUM5pDGyf%<*$QF<2eHAuGI$3jxq%dgzOABcT@f^4+mr;rRnY9i1=7kMA9~(`GY&R z`hd$}EV6m}`Y;uw!sh;bv$#^8#Ba#)z=|TFO{glC%A_?^#QYQn(Bf?foneEeDg?u4 zKg+7PJJ*`c;HP~T_rR2=;dG@IgBQ1oy-H$~b+v9?AFcORIKgg<0rb=F*mqi5pT8D_ zu6G5r(+=r@+wN2%7e8%fYq9xqt9J9C2{`h4n%LfXS& zReuW<2bd-b`Ax}c=ltm(8Ai7ei&5z%Nl_@h7|@uo9NnDP+B~d@n<5W`8KEX&Ok@$y z|8YIhi!zyALeZFp$#3dhshN##CCigvq!*D2xh{RBKkr{{LLd(}Ih9W&_h`vMKY|2j zX+^&acHJ9|ZXG@ZeU*RT%Oc7^SFi})fZID(g595a z-RXCij?rS9HW%Xa8$9hmpalKqV zJAA2+%Hl5tHs%tK6hTieZnpq#*6<=8f9K7g0tn0tjcICr6aCH^ie4?(d)?>Yhf(`a z|A))Da`gjw`tY5O@HYg+8Nr+X{(P^==e9s8h(sl#j^9{nC=HW}Ae544M1>?$c#%Gc zstlN$&;N8Vcu+x|`(Yq(r~2i~mxqlqRgwqav(CHApt&+t`rggn&ufyL^DX}C;FVw! zy}@VIZE^l|8cv#H-n{DiMsD;JLo%aGEiVQ=jzYXkIuiX7M`{ZJ>K(a|>u%S-({=#! zD!y}CAr>+Qfe(8bf=V~w%=3vyGC&Tv%1uv(-?Z%>l^5J<5u+yN&DI`{SyeWu=qQg~qE zt@~k;Pzr}hS0qK?lG^8;gj51X4Jf8^l_Xao^12Y~=|aiWw4H>ORBZ34Q7SBnCb854asgdZ|Yw(0hihuVyzC zIWNW?(e1&S2n{oR8J`(YiEt%VtxfE{{cXqCy<(SE5TPNr<1c@mfOOpbbg6t7&SN?5 z%*#bnGMr9Bq-`Qrss(*{Fr_|0Z(+w0eBvmZ=tcUpWR?hTxO2!tCFpmM=k<5?;3m^k zjx~$zx$LKE3(WcZB4?KTe#JK$P)S={vnE_Vm%D;W(_a+7&?gu1b`wWnP&l3{*I|CI z(r+3KB$NsJoXaiWGB62!5b`-w7jiNXbj2HjA$Ct$9)U)Jf00Eq1o_n%2rar^HUkag zGGmTd_D!)IX4q)g)c`t5aeH{$?OLAx=`WNf4_cHr7GdVi@uC1&aNRo7<~2_ePoxw3 zUlmx7ls3-Os#owoHyrZeao|W8j~PG6CUwb;($OEhlM-mfZ^A&bDUMX3?U1}W+4*76 z%rAzJo~8@01Hnb7h*A+8W)hMzg%s-h^S_9n_rNB+rFMSTaoD|sdlvp0@OWKRtafnL zcm3EzLX9vqco6ALTveslP}Xe^d;We?u;v>;)!J(NdkDm;+;?#Z#0}V^95b`!5r`{uR=5YRdMlLta!Bf;B3^?2i z4S85|r-b2KN0NkhOrH%YwfYC(wvr+_HS>g?bVx#(7551t_$b{U+g;`kgKZpCqF~f48QPX~zPH>J4` ziN}LA4YIuz!e_tcJ`2d8hDLj>Nev}~=|dZCv`|``MPP!&vZG+*o6b#*1c2YvU-pj; z*DF-XwpVfMhUT>;Wt^m&=5ENJqc-r2aPXK^KW zG0G~+->E`qSd9a2=4m;k*&Xuw!jN$UO^2W&)y~c#Ldl*m;!ng;a8FziN}gZRrQOyu z#ZFxhmhW09KHmOaJ`Co~UWrzXqC?TBHf$9XhCbJ|hv!Tm`{AV7=X6cpJDK++7hvSG zmzFXV_pu?`HZ!>!MurE!B6ARoV-7^XF9}iZf_yv!AGp9wny%a;H8gg~#XZLX_yNyYS?xV0#AK z`Ul+hEEc_R59|u;yK&smFt4yJByV)pMC=WvLd%KlQ!2yHh#36H!tRHgf_~SBGk`!@ zG{ShltNkcBQe->-P1869%oif)KSJy%GZ*#~&eHY4IS77UGn_#${ya6de|}Z&3u2rR z-bbGhP^jSgEmj*jy7iE_i}>?S1xKq22kedwC)11=mKM~s@XA3?OBef0{)UCeT!M*!5bx2G35fPfw8Zk;U zvYgPJ{A0eieXh|I-2EyRMB(+kAH#F3lcf8ie?~%M>oB0%tpO26Fo|Ch#__IlJd39r z;C+g;lG3O}hS9!twZ~`b=-9-v>E$4Ob@<(Grr* z8u|QGWJXfxqPYn;j8(j?&`p^ryf>i@hYIUF%FQsCT$0G)8I9T+ue-007dcE#c@hsM z-=3i=L`)(!B5F80mTV^Rmog;igpP%Ty9rcfQAr3woswg~I?4?PNn!V%0v!^iWHF#7 z(>?57v`P3+7K{5HgXlapknvq9QqebFvu+X&iVQ?%xoCzzovYTeMsxEI-0NRsXez@QL&8eu4CL3Dq>`j|5UVK0uxVeqA= z3FaR>P7maXqS>OgCFI~Ly+aep@g+6NtTV;^I8!X!oR_c`cL>2?KX2H>#n)Ng(D43t zKOwMT?^U%;tZ70-BlF|ryy%(oH@`<`t;ezUkr_(xhN&e?;Sz2go1%!yR$qAZA7Wl> zjdC?I!(_%iJTxllRl;t#CH>ImOoT{0=J&&ECzvQ+cA5MbA)^~^L9e2k$=U1fFPG?kw(_yZds4jMCD$!# z@*++3Y5~Yp0sAFqFq?HMG$i|A1Fw>(qP&v2)r*+F;*U)^3npbILEPVWF|U9QnC?DE;Uj+gndj~pfbkP=wVwc zv$#I2w~Aj3;5f!3pDx5lRYIRvaaU+y-od}YZ;3Sj)Op{_?aQluKCIQ}ed|-8h$N@U z2Jx2-DTr{CKYLml&*bW7XF(0K;*O&e-e=VP^GSUrG4@@f^$d@R%){lLbW6L(afFV& zep@LU3;%g38QZcTtY-Df7KBIxDnv(i(__)dOOpynRVE=Jp+|*h4)k?0m-3QhwAQ;^ z5hA*Q8cU-uM|0(frKQW@GxiJ%a0%=I1=aY!Yv!3jf{ry5-b z1hdg*ZnkFHN(K7mwG2=~Z#}^4`d1)yjoRF^gguzCghIHh;Z4Bn$hA~G zcH#w0^8stkoS|V)yAJ(9%wrkXUcFn$WtLE_CDNMt&BGtIRb!u#j`T~n-)NA^owRTOGqO8$Zm} zyh{B55b|voDGC9*{i7-T>ReEy3#!V0-1WS;pbzZ03A#G|m!|-##vP;FqxN@akTrz= z5LmAnNqq)&cKb6c%LJ26gID6fKx^C!dyotK{bKiv1**7suJ3;YMfY)gFm`8TI5L6k zZMLijI=Kkp46=ytb;a7a$DFEw#Q?_Z_Y28Po&cTDO*2S>kY%2{A`tF-bj#n%==97Y zzB);^T{xT{om?xRzEp1zH>R=Zq=@e^1TCSCq69eX@OdKyq!qi6~1VT@cj6XsjApYKKa%Q6%e+{U8Hj|PJeD8%cIF3r`tU~_x&W*~xp1?M65s6dTR#aC0 z2gXVcuZ^oG!9B(%D`T+enP7raPnE@TSHQp0a}_QdyPfZ(0zZC(UH7}ghsP=O^_DwB z>Z?-PcqyB@&{e+z13!16X57{nTWRT=g_z?W65FvkQG!)= z9-WZ;5xazOC6IKdTEX1K7Byokv1g|8P0mmnut~JM3A>k+!jcgh-B(N18){DO&MLR0 z`2sb9za{}^67=jLGkpk!7do6Zz-h_OK^0=XGn&S-=Cds`QXy8KRzv}dh@RS4>i>kV zTRxk#6;SE}5Voe{QmK6&?+4AL<3iOkkk_AuHLYP0P?3xc-bz4IvtN?ORWVp`)Z$?g zHB5vbwbme>S}>6Im!|Zc+zE093K7EhJdNiHX^CC+qGq|PGoeCFJnVi^|2tynz4RWb zrt_A#zOV9Af5evIGR``^N@lJ7GWVUC-{n-$%hlDCI0dgYkWm6o>xdNo&QJFjz`HbP z_hbv?(Y`H?W#>k|XEO{v-kyxVH#U6J@FFP8X){X;;U*$5_NL;4^;~qcNuoj^<(=C= z)pcYN4$LN%G*ZRf6EaQRl($SO)X{y0!a)4OpuB|B1Ox)*qt53sW{gepCOkyo&zTSZ zc8N{#|62!9k%pnTw~Y`P4O3)Sd=1F6*wS`fZ_Yz_!2JH#<~4;C-g>R=rZ4=>9uLJm zaU_gj3otoPh*l$XymAvya&uIz+%G{4;xtr&?I$Kn- zxLtpcU29!sQXG=k+R!HmsiiT0uzh~KF(oLrnJg148hR7HXcATL;Q=N{k@Fj;K9Xef z83MmXo5NqeJ@rpC$k=`m@eAHpaQrfZdK<8ZDdDYuRU{iGm>g%SNg%QCM5yHoV%<%r zws{=K+|@g6h^+*gbzG=^WgpVH&Bb*}x-9@ZbCc3R7`~`BFUOud#BI=uR7el?zVmLq zpDCkogS?v6l}UZiah9$z$!fp%uSSluav7rxkBwT-UDAfNXCZPAt0Y5{Da>axJ-gxR zak@CJn-o?;>H7P1SIpknNkzJk<3SR1NmwW!QK?=5mO?I!5}Go7WMND z9`mkRuunRr2asOS(k|x7($~N+4~v1l!&KzMKEAZjdc4&H?YGHP#) zz^}i9rW_-T-@8mFCvc0SG&mH;YrzQJOsyZrE<|vp)$HXWKCOV7xa9QY#&)Ld-BE`f z@2-R+-QTFe9!7%aBq>4=+zvBMp--5RwA@WJfk@3(J__J23E0oJFktUZ=B?y6Z?eOw zwB)AT3^F>*pbytk3%VgA4g$tq;;X8*)SQKvVqH;*=B7-H3{&rA<2@xX@q&t$|p zaQi(>3*Cn>^_&9V@YK1%41I*0AiaR1z*uVCRe~A#??hm7)cc$6)g4`ekpK)cbOUK? z0SsK+x{Lj?`2s`Q&J)H96}RCyYC5T~dqo}zdK*p9oG??4_?W3BwEc2D9j-B>VOIhn zSKlOXoNX9uGks|1Kh+9Zs3&<MOv z=`+XHa-x6o;x`iZ!y(PcnKWD8)CRDKBqQ;rvvWRxQG~%rEcPU^MZBGMsXM6KpD*JL z2wEENnjpDj)D)DlXR@ouhW@Ax-+r0}D6A7Tr#GQhc1^VCglK_ppjT%KzuyWd!EFS) z;ugLHQ*-ZU#2qW)GL0)~Byw{xmSXh~4&#o@!(uQu7=I8+nU-qs=TqTdUT2F?87Qhi z?KGP=A0-dIcD=aEtVW{@9QDPPq!wc&kbNR)vRJOSK#pg0Hjb%!;`6yQALz#_Q4UXH zpS5`*OM{}9x17HCS>5$$+b~Q{anG!ZLyJ_alFN)UN3MPqquS8n5>Ce5SzP?2fz>ic?vY9H(E!p5S+TV0bt76P$(xM-Ylxlc8tXZos zRtR;3ksw`eNa<3HYAH+eg*%yDgLgehMuqlc+o4PQ#r_1dk3Z&tahF_cP+YHdWhgW{}oc|() zhHH55k-V&YcZtBpgJT$YdQ5#6!s`tN> z=1MvrX+Z?qs2T%uM5s!-T_i%$-%WNphEqTtbC^0VdAF-O0P>oT_Xa;tV~O?Nb_kv> z&vpno?+=u#gthW@Xx#u}4(F#(qFgK6V37MMv&o2Q;&Z4|D-UcdUXd^j0nBqQu__4g zy!kVa1xcf&74#JN%x^O*Q{R+vqhiiuEj8XP(UjwE`x@%9GbD6tkAumfr?|A9#i{Mh zlHk!7wf?tGI0$|k8izZgZym|S^Y!J~C;9%=+c5RBXz$=mgW02j`I}!K$K~+K9;F1$ zgT(%zkoHCGAVvG`4N@K7OWoSC5E5`BCve~plD-x0GY=8=^Y|s>8Adn#l%qtc3oS?( z39}io%`l99DX{Kcq8IK44z4Bc1z3j40XnpsI6o0RD3D~zDP`vsg9r{idJCFUmQ77E zn~@-{6+~B2E1_@xi@7XW5MZZhtdes!KYe>2FdIlA9Iz%1gU2e2z6A);^FAsvNFP)3 zjlNlb6O3%`*K1rv|Gp~7|Im>9adF0tG_FI72qif?+jfzV`aQBiFjvUFNg;MpMz38v z@KABKVW?tHm-{(we=(xs-74yHl2sWrvyX1g(YiTRhPFFZ6`FPWhnQelyzG9yq})4= zq{V><#~?8C^3Zb#8gqLL0z3ZXh6*{JUOk`n1rJ`g)7N9_L*w~cbRO;d93i(dvou_h zeh?SA_?+w0)FD6uKdueV2z=g}HV&lZi_;rcu!a4`3K_D!z}yHOf=()0c15soSgg*Q zffhUGOQ0lts9ik9LqH=o-$j76A?`yPcEA2!=5y*0a((`YC8HO=CV8ISnW`wEE=n1Kr*`6&%} zubMfRup(2nVz(bYDrNIK5N}|+E6%_}LhWPhnWa;+{zO62O(2L}#Aq1WqA}b%h%)tMjWD)G8H)ZwDen#K;oLYzez-BjKS?= z9U!y0m7{f}SIst0zuJecEyUd^Q_XRkT@MEp^u6`hJbwCrAHoR%ZsI^sK zmj)ljy92nz*aY!}T%nvcfb0RU>k+7)dv(GgWl1-|W9!mB?&4|?33KQ-TKlG##L^4m z*D?iaQP*_8_;#0>6N#kc-=%04!sfpvc0T7|e-5o8wH{!3j_n^Thl1Iv+W3KQ*VE3Di`-EzmVmx`%R%({W-6t&?x}kldHlDWn+?nZ_!DAI;<5C0 z%9Puez~Z$5{V~TYCviK@GiATl)&w$&)2eiKBW#qsr@ai`NQp1^C5dAGAfzSb!E*@$ z2|ip9w5E8zz|9LF1IR^z!tez`v$dc4QT1{4A1Gkd$y^{LJl|hEj%H=E<1c)X$14#* z;+lhditc~E6^TJE(qaZd51Y-y)4#r&ikt~)Y%DmQ|L2x`00KS0)Va_vn}c34EZ4dt z$$gXl3bnW$B(PMs^j$3{odFcDG3kCW&jk6{3EF1@KOm4mlJBDJA)(0O?Kh0So-lrM zy6_`M6G|)!W;m0rkFpEFJ$mtIonEd&jZ_Z%R^NSt9@*7&^1JR1>zD*Id0%V;msC7Ec#+Fxd%)VYBt|gsNymM2x(F6P zKZ)=)Ue`MY%x-?Wg}?U~X0FWM#R#G7u$UE5|HX;`WPo!|6j`oSt_I?kT^oz2F<()Pi2VOELbRL&rd*6;9k;dN*RoUOE)^0sp` z^bP3TJT4fxy<8PwtOtqn0YwJxl;~XtD?p&mhkdzTzfYK!8ahd^>yyCewi?e23EV!x zl&vyqPlqbhD3T&D@pnle74j~1ceJcx4B~x8C*eospcso8bD>71xNoytWG6BQmVesI z^S?V_YkHlnW8G2N&F!lhlDPz`4MH)1oqO2>dxwZIfd^U(R9V-lDJk!|{2x|Z-Dr+y z843iPjK9$@FOW>2W_A}da{cGyR*7LJ9xC_0De(Hc4~V?5cHHn{0Fp7*NFUJ+G3+-?e`TgY`EjBX|NTD8pRW(H0iFkZQ@Ydo>P*)%c033rLw2 zi=U1_*jk`!0}jM>Zdr$r1GYT|F>jQ$B&(=YB1yz?lh>KCP+!nw7id6W5h!Wmisx#P zN-YqJS@&tFi-zZ>0S*d0V*h7w3U*mtS(Wh&L5(3dzU5^Gm}X#Fv4`$p(a4?SQOHR} zfu4+7CTEdy2K%Wp<|&AjrwYU=)|64yzkSoKqZaPzq{ZG8v~uY$rns(QM9)R}nD~_L z5DQFacA7q}2TRD??HRD4K6NN+{j}HfQ`JT+)>wMk-8FC6%|k<6v$Lkp(?>4RsWFCw z8ff=^{jYtoj;`LPDs;J@&9sjD7-ps)zUu7`!#qUQo<0%Cv99cey^h}HDK7_H6yBvvazWS z!B9QR^rs;FSZa1M>B-m26ZXJ{zrP&g(5^NNSWeQ!V-O>{RP`5tK@65(bXCE z`d?gPf((UDCd})5eF)&N$#KnhsrD13AG6~YglXGthM>eE2|YWT0P1)?I)*Or**%M5 z0ipcVj2eYK9X?m%rgfT9kD%Ye0^ZN6{V5fgrGpuOJX!;P{hhZH{P;KjVE~`8_-yBE z1-^eO!BH7SvArih90D^t)UEq+R9tur?9EuUEmf=^`@_j=P6#URyfv8j3;s}R2Sr?i z2Hyx+Y3jRi&6mXrqjvt=d}63C9Q`;T6>SRm=lKh2ieX{ZIX)@?8EQO`+-{+I|G3_w z%Ma7YxfdQ7oJnN7rh6d!{LcyO*^iIe-sdgX%NCQ~QiTD)*n2SlU1#SI(#%N+eJXVD zlq|kgL%MwROu;AD!@g^6G?C3$vM~!m*s}pekDdj`nC&4N+tfOQ%Vpl512bFtAf}zE z1O>v;WRS1Whs$62l^t}+5QFU&qYm8?V>d!2dVJ6HYL{CEMJ??82ar!!xbAIGn-P?C zQAiv2-n|5%I-D%(_o5M;E9B^_wF4M9hvl80=Z~*c6J+Z&pnCM+Cb=LFn$1v(vT8EbQXfPA2c%0xjsO4v diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt index d5e3f12d..9fc82936 100644 --- a/resources-round-390x390/fonts/crystal-icons-extra-large.fnt +++ b/resources-round-390x390/fonts/crystal-icons-extra-large.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-39 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=39 base=39 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-extra-large.png" -chars count=24 +chars count=25 char id=48 x=0 y=0 width=34 height=39 xoffset=0 yoffset=0 xadvance=34 page=0 chnl=15 char id=49 x=34 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 char id=50 x=73 y=0 width=39 height=39 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15 @@ -26,3 +26,4 @@ char id=69 x=195 y=78 width=35 height=40 xoffset=0 yoffset=0 char id=70 x=0 y=114 width=29 height=40 xoffset=0 yoffset=0 xadvance=29 page=0 chnl=15 char id=71 x=31 y=116 width=36 height=40 xoffset=0 yoffset=0 xadvance=36 page=0 chnl=15 char id=84 x=67 y=118 width=20 height=30 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 +char id=72 x=87 y=118 width=23 height=39 xoffset=0 yoffset=0 xadvance=23 page=0 chnl=15 diff --git a/resources-round-390x390/fonts/crystal-icons-extra-large.png b/resources-round-390x390/fonts/crystal-icons-extra-large.png index 8e75e985a2d69be9ea69f1c7bce9eb24313fd8cf..f06c57752064cae1cd6c789035841b7982a255ba 100644 GIT binary patch delta 7420 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 delta 7254 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 Battery Recovery Time Время интенсивной активности (минуты за неделю) + Active Calories (Manual Goal) Калории (ручной ввод цели) Выключено @@ -72,6 +73,7 @@ Заряд аккумулятора (скрывать проценты) Уведомления Калории + Active Calories Расстояние Будильники Высота diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 37933169..a3c78eff 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 0284b578..477bb599 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-small-icons/fonts/crystal-icons-small.fnt b/resources-small-icons/fonts/crystal-icons-small.fnt index b2928604..2c6562de 100644 --- a/resources-small-icons/fonts/crystal-icons-small.fnt +++ b/resources-small-icons/fonts/crystal-icons-small.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-20 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=20 base=20 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons-small.png" -chars count=24 +chars count=25 char id=48 x=0 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=49 x=21 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=50 x=42 y=0 width=20 height=20 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 @@ -25,4 +25,5 @@ char id=68 x=133 y=21 width=21 height=22 xoffset=0 yoffset=0 char id=69 x=154 y=21 width=17 height=20 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 char id=70 x=172 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 char id=71 x=187 y=21 width=18 height=20 xoffset=0 yoffset=0 xadvance=18 page=0 chnl=15 -char id=84 x=205 y=21 width=15 height=17 xoffset=0 yoffset=0 xadvance=15 page=0 chnl=15 \ No newline at end of file +char id=84 x=205 y=21 width=15 height=17 xoffset=0 yoffset=0 xadvance=15 page=0 chnl=15 +char id=72 x=220 y=21 width=12 height=17 xoffset=0 yoffset=0 xadvance=12 page=0 chnl=15 \ No newline at end of file diff --git a/resources-small-icons/fonts/crystal-icons-small.png b/resources-small-icons/fonts/crystal-icons-small.png index 75b71b307cee04ddfa7b7ad106742f0769c45b35..8dbfa29581d24d7c852e8ce1f61d2959a16f5e72 100644 GIT binary patch literal 6125 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 Cqzrce literal 6003 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 diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 060b6524..501b0c34 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index e0bb748d..d8899599 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -64,6 +64,7 @@ Recovery Time Aktiva minuter (Vecka) Kalorier (Manuellt mål) + Active Calories (Manual Goal) Off Puls @@ -72,6 +73,7 @@ Batteri (Dölj procent) Notifieringar Kalorier + Active Calories Distans Alarm Altitud diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index bf574032..9f573a17 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 623cb5c0..b35350f7 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -65,6 +65,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -73,6 +74,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/resources/fonts/crystal-icons.fnt b/resources/fonts/crystal-icons.fnt index 44aa33ce..c079d204 100644 --- a/resources/fonts/crystal-icons.fnt +++ b/resources/fonts/crystal-icons.fnt @@ -1,7 +1,7 @@ info face="Crystal Icons" size=-24 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=24 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="crystal-icons.png" -chars count=23 +chars count=24 char id=48 x=0 y=0 width=21 height=24 xoffset=1 yoffset=0 xadvance=24 page=0 chnl=15 char id=49 x=22 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 char id=50 x=47 y=0 width=24 height=24 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 @@ -25,3 +25,4 @@ char id=68 x=195 y=27 width=24 height=22 xoffset=0 yoffset=0 char id=69 x=218 y=26 width=21 height=24 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 char id=70 x=0 y=47 width=18 height=26 xoffset=0 yoffset=0 xadvance=18 page=0 chnl=15 char id=71 x=17 y=48 width=22 height=24 xoffset=0 yoffset=0 xadvance=22 page=0 chnl=15 +char id=72 x=39 y=48 width=14 height=24 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 diff --git a/resources/fonts/crystal-icons.png b/resources/fonts/crystal-icons.png index d4fef93913e449ba1ddabe3b4a0234b798e88398..69b968a1b9d0e7ebfbe3889053d119f90cc83e16 100644 GIT binary patch delta 5945 zcmcJQ~kdT!IX$i?|DQQqrK}xz&5RhEDL*)jf1(sY& zI`_H%f#1yYd-0r^@4GW|KJ%S9b0$O&#NKfeZxImF;=xyQDiB{pzu>OYJV1P;`HF<#!01*Z8CWAT5X#x$t@CirOyb&7$kO#K z|FBhCtI;Ww7MnAtc*Ya)=nw^KxxB*9&(B!$S5toGpSELudb#^I(iG49a?x$Fc`rAi z)diEOQP4A^*X48NRYid*Lz$4tpVBE35)QXtC%46z+jC%8iZG@vZtV_^j$fk`z-B|5 zd3%7Ul0>=^c6H?H^pB!0KyxFCi%JX*l8}&SIwb-6M47gPtVg(UM0;9k!p4}!8auxx zw0{Was4Eq{i`78QZ33{dfD~lLrM7TO}H0lDF!qXcCRsF07Mw=d&Q4c zl&(bppCuAdc3-fRPDyIWA(4-W5yB>5k%l&T_%@5k2eaPU3e-bjw^RC_q)EizpPhiN zYqb{c?y*v_;B<^}wnJD>gMqEV-Njq!wzVuN?VJqG`5Nt_JhQs^rn_T-x6%t6E=9-2 zOR-r1_2PN?-@sxAeBcxIu!QXNdC+d~!qGsZp8QCYIMCO5Wg%Ep`}H$lW^N)hQ~6_I ztBtw?td~>l8~)ukTXvxKgf)ewp~?%Ki!=2n_oBlefU(jwsom5+Yp(@J{+QanEHkc$ z0I_ni!!z9MikMspKN~|8h&ns)+ItRuQ>^h6@7Cn*cP|S#D+z#B z%6PazM2%!Y-=3K?O;o<<61OFLW-f4~CN?fUw&g1hn3qkCDYqG35A!2K9Qw(w_AxjE zY^v}xHS%SPMqqcAGUP^$(Dj5hDP_ec+WDPr0OG$J6qp}QJm(K zov(f4ZU5zfQX%EiyayIL;pM%S07zT|$HtAPU-*0Oyzp#|Y~_L+UU?a~RM{-n?TEJb zKCm$XlGOKbQS#AYRYCW3Mf}Khf**a>V;4ELOnN~YbGJdqvtHk^^eDO1$}C2n7DZcA zKWLBC`|yecL%D?Bbtayimjx(a;OUUUW#f}v*}TgSQ&dE4OBsCQu<=?MAQ7@i?WQXQ zsMDKjX@pgG^V$>LWYK=D1Z>IaUiuXfCdfU!e7ZQ8D73t@m(aeNT8-Vpf1EP*HYFz3 zJ1EMI8)FzYct3{(wvUNCzb&LvSxZjDogNF&sVEa{vKgt{E6XLiDO9TU7xChKN{Z@O z1z(8OK`Fu?@BrfM%wRvLVq^J(+d&Y5GI(qnCSAZ?%Qm$Y zc7}I?CW2)lRFq?-hps5$!Zj>UzMVy`i>GLub4d`-qK!Iyj|~+_{jo7Lcd@Qx9Lmr* zh)(&6wirLKWn?^*MAXE9PBI7@OaUy7^aUTiKiJ+bFmoX*?)0;KBC0#xH@-Zbn8P@w zxt_P4hNP+31|1qT<8Cuwkp!~6LK{7(1t}^h<^v*RBdYx)6$SM)$&w`z5<5AL*{-Sj zy)#A7Jb4q-MOc@i24I@7wZ%rtzY0%-Im*N)gP?yjAx zQ)+_;T>kAG4HG zcRcIe0rN+ZE}9|!eF~tE2%4XjikmO(1&L}P9p8Oh%ArHu;s!;AQ{DCHkU8>Tb;lj0 zfp?U!;ElIZT77lwEG0gIjmnd+K0s0a@1vYD7yk%7kNUoks3IlcSL~D(G!NEjR95G2 z@)83>qNaJ=YogwQWK!5cvres0FLj;ckpHIGa&h#ey-J`wZ;t?fUr z4K91IY0m&R--7+!BY0U8UOVZYx1r=t)64_%q6Y>07vLq#CdM*7^sB}74x-IM4SGSb zjgmQ3It}Go_V_BlX2o81U{K|k!D}fvy#$E@3O&DnCwp2ssFhr469}6KBno_&)TqE| zUEbne|G=7Nq1~+EB?8ShpG^uJ z{f+#vgQuJex@X zVo0c9B5cX$BDNwle%d9=CrZkwJMY7|t5SiZ_5K~Pdlt_b_9pE+5)UiN#O(zB7$Oys z86SKc(1RGdTQrO*)sW;o3f#k6obJ!qsoLRBKpbkI6f%m1rFugIwvMqe(*E9DhIJtW zSJL7w#;YAm?O)rAjEE1G&%tlcLS9xbXXfH4TDZqu1iF7ms11A?&vFWks%UeJta0Jd zF7RWV<4bVMRwkfYKFMofXw}APhO|cCP;rNFt2nKK z&zG!oSxWjeyeiOrXAR%=uN?x_Q%a8sVMgk6wQoI^SF9o*Sp5eV0L=ix@sVXxMYQC` zqX0gA?N;QWlDsd2kY)1u8}Q& zwUxkoqg^$+mOI3)iw{_+3(rA;{Ua6yJ%ef8>Zno@HnX@J_J>+3ghO;K&(K>W<{Iy` zc=-~>J;=O$J5L2I+M-s2N>{5Xz5GbJ4li1I=(gTn{g}k{1AmnZhsV(3pek_oJY=Bx zttyGHI~p-du~0;+Y=I9YE3kA`8;u8)pAbJZfq4u}uUDQiFN6ziJ2_L*rAG~HU6qX) zQ$QJ7TOBZ5NfP~vf%Nm@WRGTL8nO#E?3mkf-w**$_LYTQwaT9G)a;^rr>CDD#PDRM zfBOi{S4DgWHzObbCd#K>9tOAl6k7b`To2RvEc$?z$fz?VUxS`u>))Xf5d9o#E?g8 z30B%*Yi&MMlUd#A6*3+Qms~sO3yigouWHvd7+WB&i(fs7bV?}rzL3575O2$zxa0PU zpNB=<2vCecv3{0u(nQviouvC6C(J$3aHpfYKhDAfIXB2q=C$l>XX3{7_s-^vlqeAS z@ec^k5U;A44p#9JHSqYPb|utbJ<8S5xMTX5+3a#)p<*R$ckLl#r+PBlHYy$}ZarUD zxOi~RLV^YmM)pJ}_=zm!FBqsiCll)az9R+ppiPm-;$QHt>5H$M6}mv$zpUFlb4O!C zM10Dg|KMpX7Nl?Moc!2alFZONzKKEMq-exXRjo^Be3;hu&cQ)G*QAC+8W%XL1}={w zHiJU4RLf);A=5Y?;}Awr*4M(N5p9kfP(}cW;jVMtHz$3cz;(lS#eg=-OQocw2cvwa z$6e|s7g+e7IuZl!%QVIhX%=bREQVcgfiJ7iGvm*eM3}DXp>@uT^q==>h3<+WC@PyQ zVprL><208pA5Co;gY_(BWr8dbuw5RWfnW<)VOW66je|YfIifu!tNfDCCTxOC&-kq> zv{w6#l7jxZ10=uq@M|u*6GvegG=Z_LU|sQ$?5N82tF3$&*)(Wu9T@7JAcav>ywNklc6o zef~(=S_xAo^pxb@JdA4fpqZza*Z$&NifB1Iz;1vP>)>(}pB!0!^?53?7 z7jclfzxpG??RUYZJp}P>;PfV4P16SQB6`h4}~JYGvaukg+)1jb`DhI1~stnd!3mr-zao%h*&YbOOipOh2jAv zU4&);2kQEoaKX`OoDYA{yS+fi{{e9995pgq`+1(Ul|%2E{;)kjM!OaFhV%2NulXW0 znp&RUl!(yG{RtDzs;kqWxS!jYjKeQH!!WrWJJOMOd6g_;YPVf*CGgX~yC|GagesAC zR%BZy@n)NiZgj{Q?H)>Kd4edO+iUg8YTqRnm;0HJMp?1sY?ECMAo`jyne#aLUwp2WK&l-f~V{ z>AAcp`L|}ZW;@Cdc~-z_2zTZ1jprfNmuPl>XU{`Uu^b~%U+(0Do&C%&B&2;d3x09N z03W{o+mXKUwrKvC`CSlh7k3@GPRz?CSrkL(b*XO^2Tr<=1>zk6xk+nW(!3F4!BS}Z zjjijsEmMH%t+k99{%^(&Uwq$hYRqq&$*tGWRHk7qm7~ALcno%ZKPvrZJ<10of*F)$RIX^$|c=6MU z$&v+AoFO2iu8u$1E{P|pZ*2TNV@{4DlWTNl3kSsoTDuDrSd~3Ii+yLk^ks)iDA=c@ zG}ZnA50-hoiy|m+6{LMsonhp`he)pJu3{ntyy11^{uJMNxwB%CYX_T`ux`bl_30e{ z3>~n)qyo;SbwdaGoZ+{sqxRD+9=f`EyGx?p3E!@!tIk=BEN$Rq6HoFuUMjEoRHyLy z^?lt0dvF0~`pos+o1BIO_{1m4jiMoLT)jrSq~>@h2r}Kc?D(jy5M#wBxhyIwYWD(X zoaSB;rz$R>&4^4{0M=Xk)QD)(O_k%;hHgt%eq~HFiP@tR5@?mqY~li+)Q2iiaB`x5 zjTz^L>{$iWPzMQ4U`Mc(J8FdvP}Fhwq6`>y`Q3b0T5-L8Y1Wrt&S-Q0AD;{nj1!&ywjlQO z9J%_$k2H)x6F?C$Hnq#d&~1V?+UuOc{)NN)<3~YU!+%*anO7Dh4gLg;_q~oC0@<{H z23h3b>U@q^bW4C2bwpetR3N*o9<+VBH*r6>Dd{#B5F|(4-qv0h=D~MZw4a65w!3`1 zAgD?qzjQkjW656*A#N{z6> z!VpQTydU8K)ZN3A?ib1fXYZ2RreSEJ*ZrNew;e#*ILVh4MXRy!;ViyQaQlqF+x$4A z7$AfpM~_;e$lADNp@ULACO&oPmv<92-Q6_`(dqI0*dOo0dJa^Gk(_iFtPe}JG6Fu) zlH!lZ(-olVRca5h@dX1oI{SDr8k%798F=;dvL(f|Wh7c!FYTSi;D)e4JcFy;KF74`rj2RBg*n4EF>1q3#ffs zz{NJphvGRd7V;XmA*md8%^n>KR^A6oBc9iuT`LG_msZ=(4&ReM>idug;SM8*%52ZV zA=e8>6My=p+yoly@Z-ELo$JqwyxDVC!#Hg`XrBfv6C=u!dJ%BMY6KI~`VVQ(ILlt@ z26XLVdnrutG1?;Nt2u4mwf*d;KWm}w)bi#@Dp;<}*%t>}(1h&Nz(@X45_Sjsb8~OK zU)hHCy|Ju??i_#5=(qyTcdyb+?WJ;0-qdxhT%&jWPPemjV7iODQdUUoQ`~bWDeKeY z(r;|}&O4Jk(|^GQ@US*}=TSUxzxe5{)!x48;gV|zfm2K0^;jYU(WMOPe8aP;Ms52H z`D^VMJlCIbZ=7JpSlVdI70ci-o;inc^wZsv->v zM5&R9zlWbOk`+8;B6}iKNX@_~hr)vNeWT(3hQ=SesBA}j6zh7vJXwfNa<`tJpS<>d z`yao9f4A|RzC4{c73a*f#Q>CP$qy|J`N0Ts(eCqp9ldUj zR*KIcsT!aRDPkivv87R9H!X~$@_1|C=qd|;PtMNxgy%TrZ8#uS{B?Y%r|4nRccL3; z-c%(io(BZERQwEZS)0vjY;3H^1GF^8f?ZB)_mmNDeW$pQjYa5-R(AN%H%m`X{&RJ{ z{6!pha`E^((iju2*gpk*wKs zz^-1+8We1%q>3F3(4=2*AISa+Q%`y~#WMPud%DLIbC0J;@8T&udd+#LqzQaF@Ynat z(GkQ320>rlh^F#ZFR6no_$(X4x+xc8<;_2yC!>bOBdO{`D#7Xn{UhcAOf|UHMVThj zn6q5X^RZJloV4)-L!hlSakQ(z@?{|yxBG=Z>}>ZQTk#5Q^u%$(29UERjX$x4eMiTI zVS229&xlob*nUr&BkVoy#+>9mZwzipiXQveA+#CjhoR0DvnVETZ%gscUJ4ra``@BI zU{l28K*ZJ?*mTs7?+9CCbYp{`;4$hYxfXZpJAYv8)1sm;+~+r94`Rkjrvm9=QEAe( zA%?6Nr=%ABoGK;lRmD6Ab*I;&i2Lyx1qZ7?J1zh@vN%|iCi(Lh4srKq@vS;IA!AC zwA2tekdB=)sUDymTcauXA%z(6mh*iLS>o(9TB|F^id7(X6HKd&E5|hi6Zy#NRZWOW?GCZ&F?sL_xbM&E{ABy90q^N&0op z{nAyLQ-BH)0y_O}FZ5)&-_LG>&hakussSxQX2~>VMxx~sntbk&>6C~fZAmQTkQL+Z zLgZM?ydu+L)D}fgzf@XL8g^m3csIdydF5r#ssjbIa0>S*YM0xCdWm9#2HQW>=lVk? z%uvUXBh;|dW~rt zd19e{MIy~l_#dr50(w(9-1nXZG~&$dSXwc>U&cnm)*j$kb)O9TnAG-rWlg-_q~6UV zMwqY1PR!KT*GKo*ohFLu7yZUdcvt#L)&l_D^m_I44N7{;@P$9*2Vw>Kb%d}^CukLt zR0k=A#q37tR7gK-Bwibl?u~_bUnjfHw~W8;oR=*O1D~7fMkOGu<#ai(bYcmC5BmDm z@QwRj2h{a5g;QN7roPEcqFZO&K81 zXKTzl&Bq0l$(7#UU4~G#E|CSsA%-wI z?VME)6Uf)pemDKyQc^{@>iV^X%pwOFNwHd21R z)6ar65FpSKz~0Q=iog8;pzgxn`I-cVBIzQ?mGR64Yz>$1OzU%0NivU~M`D^)H#CsS z)zOkTDEkngWQ7^4M9oa@*}IRYP0J3iD8gK_fc*SW&^@UW-O-+Onn42CbU_#ztzbF= z+&vK-^f47=XO7>1BXgT)Gqygy8U|KBB%e5S1``hRk;Xt56DkrC``(#pz5xr)KhHkj zk~~`&@ems#tqts=t{C1)%v}0x#31v8y=Vu!Q}{X5=pcr!Tx1xZa0>s}gAjgcc6P`w z2u(+JUark55M@rR{^SiW#+Z%mBvE*dF!CJ;)v63gG2(3gI$CJ(pJZYv?eWV{34`8* z1l-D}mo0JqoGtT9$ih7!PzS|d#0dC=eUH$e7<3Ew-7cplb|Kmyvnb?&6)RCxIO=5l z8W!?~rSnO;Im#?HtO3XJt9_Sl-WN<}X~v1)??;1UCSI+o^A0BNpbkWv2*g=m!oQ9{ zKcMqXDv_^#$&%D$pHUJCI^M4|;w&}X&V+3ZIggcwb{9h4h{ZL%^SAF`ex$Yj z463@^qif0WcEX=xiSp7RBr}-)63DsEu&oo+#Hxg*mM#}885 zq@;Td$j+O`$9!oF#}vRICXb3+b88l-T5*A@!aO2jhDl9_q%UviUI7N78Wpy<`7--s zIBZz=c+J%U6(i%E12S&}{aJ-KH8KZwt+U=PG@o(CZajsZvF8-gTlx8bGU?s8t`c`j z`t3?iLYhq-*&NHSHSFs0higQAKwMEx%G-AEuNf+&J&T0$=N7mYo@hma)>15EYEZCi0gG%(0;*U9|>)?U(wDX+qZw@Wc zxnmq*m#()mrlm496JT1<14P~2lVh(%k6)kS#B(M_&InTcWXYR)E4agE-0kc6>jJBd z;Qwd>+%&4eNH7S3F!=pZpGeQC0}rbNRwj4sb4Xm(^>;O3lz{H$xH7@D*@8KV`W(8jmwR*q*M(jj?0 zZsn$}x*&SqfL16(h9}S+CHIBdQtkLI7hMe;C`_FT#y1n41k|*I<~&}aQ+;pF_P(zU zZcN;Sg<@?Qt-oUx%U2!^a#Kap@NklebaYarWczk~aSPR^m#!;4{p!U;v*&Kb@#g%( z#X}nGHvMHAZtlc?M7j4(D9}~$Hv0JfF20u3^7S}UR-R=N-tOpgl}g{tfiktWeR`>3 z;Qj)be(`w(3b@5%uKYe#zjfr1vVHPPXN`^g6^+8n?%}VTs&>N?AsW^WR_}w{6UuJC zW}#OG9xqB#x)Mj$!12TXOi^~rHIK*Ns35aISPHq46fIytX}{}AiZ~zh+@g57)m#~}nUC)dyopUDhgbk6t^TRw?I_9Dy6m3!<*k~em884AwQ{v|M`9-p24Il?a++juyLH?3@_y=nurudbLc78{61r4M7}uo0 zHI}tiG$ifLow#vL9*oCK1%5Z~@!}S!NL!P@18Nf3IU&w%nnv-bo7i0ma9`#&dhXj2 zycd+ezTwDi*ue1ohSYGx006CTiJq(7VWQUdmA#=^)2*cK?~r=@Xs}K`W0>Q>$Q}ly z;LJpxa&z1U*G>+WRt?WF@Mzc(04|HrRypn_o|(F2^bKJByM`B}+HbX!IJ3pI920w? zG|y*!r;d$a=@O!x_9e>UIhlA-*)4XJ+u-Yc(SU+Z8XCl1*G=0)PsXnXdV9wn_;U#B zo|1P#^5}C*iK1{UijP9t3JwM!a#72+|B^A@cfO`9F$hc%CGZ*8Omq4dki;W)J9jX7 z<}LCJc&h_r)d1I}KkCn!KH{`YK?qvFLjptvpSLrQ3G~qBRSD+475}0zR+&@KfxF;J zZ%k!w69>cMymlQ9TaEGRRpS33l77k3!Jn2~Kl$)SetS5*Be(L|n6td{=JhCL0%R`G zaqar_M+OhPBkdeaViZVa<%~R>+qc$bR)j@8W~>{p+>dI$JqXH7!l!)x zxNV=A{h*P~%&2p)UaWd}M|{8jMYaneJ_60fJ?idr*^rP7m}cn!4O9DhE+5d{8q8ck z%7ayVI&fPdRLPR)`8pr4u%Nmmqv+`(AeXu;{H}=*EB!T>S+@-3yvsC?-%LEhbzs(b zhGmJ0-1f)V4pi*Rk$a<>9Lhs?2T5k9s90C!}uAc!f=K{WgL2m&{L*Z5t@;?YKUK3!HFXj2+uEZ?D=;>^^Id-Eq)+wLBHe z#~oIKct=ovBk70jOr-6S4EJf9wo3$E*s-GF*CkXW3@69jgFfD-h`7SpDMXor3O^8h zI^$J;@7N$zsA%_qO~eK3vmJi7=N-LgX8?mL>yh~!?_cI1B2xI?>tTv>&__J*^yMc` z@Q`JliTSnlOQkE8FD8+CwB%Y~lo)|cM4Ziw=kw6?Bi2uoRV#HRy-mb3H)rQlv)4s! zy*dnA_x($wbq{+_3j9ib^K`I8Z=GUc$$7E@5q~~@OpBanZdCvHQS|$Ec1USKG264M z`rX~#-;?F2G{X|Dg|y2GAyMY}+-hAlP!?bfdH~8Z327jesNg2-xe^=lY0bg1J!MKHOu8T#K$>Prv zRrc3DYRh&D#-S@2@@XY0It_Fbiq5S5A+L9;=(L+c&nw9~%c80#0_n3uj*naT&>(Yf zFG%PXsOA%f)?t=eaR1THzH82qIXD@yuMUU9MKNOom<`PFp9AAjx5eqt(pskUBZ4uO z{tXos@51@!Cw`s(vT(evhTGTx^U=Bp?35Hrhwt;)?ok~9u`)o+$@;~knJ`Z4JpAi* z`Z5@Kr>b3(q!G0GL`Am3c1+g?4Jn+7!9%feee?d3JWvv#qI-g z+Zl`>a_(S{Sg|bsd7nt~!nn5Cta)oDy*xcWnA|o6!^03+{Q#6M7 z=4W6B*jq2VSt_q`6k7Qq2H2AJ{uSwAz-D-Zs-NFSURKBt zv`!fuEuUnb@=JNkox?LsU()o0MIc)$Oy&wDULfPIjz!{P3|5ZeYVG{noyXiT|3lPU zw|nYk(FXk!4r~G z!I1_oFJ%wn+YC!UZtaI{b-lJL49JuD#Vt%48wCIwT1_c&jd}lekM&l`-3yMLWH_(c zoRhkq`V2lqZQsN|`-{j7!o54GB{@Z0m|C&TtI;OP-i9Eer#)x1Z0I~c>FeQxMVC8lu$JTc0op zNRJ>#6s!in?pvkWd29o3Qq#Wfl9m30Aq6hLrGmnnEk}R7-2SQlp=tAj2F6M;pEdV zC79D!l%eaS;jHv`7-l?fj4>yB*uPCtU zxK?-V82(MYwi6j_BbsHGozr3!N;*hq>EDv$?UC0;Y+TNl^X`d(MLqWgbvm}Q=B933 zc=7p{9ELu;Hd0KBRb>1C-I9w`dK+=xB?a$b+5y7-&gMxg7(AIlNi6XfFx;SNJGA@*3BSU(Zp024V~fG7X|9)tg{^#2_W{{LP3-^>5gO@%8& Y>Tss~DnLEs1@IreQidu0P_PX7AGEjk^#A|> diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index cb32f8be..8ed2c464 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -45,9 +45,10 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.BodyBattery - @Strings.StressLevel - @Strings.Off + @Strings.ActiveCaloriesManualGoal + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off @@ -58,9 +59,10 @@ @Strings.ActiveMinutes @Strings.Battery @Strings.CaloriesManualGoal - @Strings.BodyBattery - @Strings.StressLevel - @Strings.Off + @Strings.ActiveCaloriesManualGoal + @Strings.BodyBattery + @Strings.StressLevel + @Strings.Off @@ -98,6 +100,7 @@ @Strings.BatteryHidePercentage @Strings.Notifications @Strings.Calories + @Strings.ActiveCalories @Strings.Distance @Strings.Alarms @Strings.Altitude @@ -123,6 +126,7 @@ @Strings.BatteryHidePercentage @Strings.Notifications @Strings.Calories + @Strings.ActiveCalories @Strings.Distance @Strings.Alarms @Strings.Altitude @@ -148,6 +152,7 @@ @Strings.BatteryHidePercentage @Strings.Notifications @Strings.Calories + @Strings.ActiveCalories @Strings.Distance @Strings.Alarms @Strings.Altitude diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 79a3f02a..137fde71 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.18.13 + Crystal-Tesla V2.19.0 Theme Hours Colour @@ -64,6 +64,7 @@ Recovery Time Active Minutes (Weekly) Calories (Manual Goal) + Active Calories (Manual Goal) Off Heart Rate @@ -72,6 +73,7 @@ Battery (Hide Percentage) Notifications Calories + Active Calories Distance Alarms Altitude diff --git a/source/CrystalView.mc b/source/CrystalView.mc index fd5aceb3..f07a9546 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -503,7 +503,7 @@ class CrystalView extends Ui.WatchFace { // Update each goal meter separately, then also pass types and values to data area to draw goal icons. function updateGoalMeters() { if (mIsBurnInProtection) { - return; + return; } var leftType = $.getIntProperty("LeftGoalType", 0); @@ -655,8 +655,46 @@ class CrystalView extends Ui.WatchFace { break; + // SG Addition + case GOAL_TYPE_ACTIVE_CALORIES: case GOAL_TYPE_CALORIES: - values[:current] = info.calories; + var fromComplication = false; + var today = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var profile = UserProfile.getProfile(); + var age = today.year - profile.birthYear; + var weight = profile.weight / 1000.0; + var restCalories = ((profile.gender == UserProfile.GENDER_MALE) ? 5.2 : -197.6) - 6.116 * age + 7.628 * profile.height + 12.2 * weight; + restCalories = Math.round((today.hour * 60 + today.min) * restCalories / 1440 ).toNumber(); + + values[:isValid] = false; + if (Toybox has :Complications && mUseComplications) { + var tmpValue = mGoalTypes[index].get("ComplicationValue"); + if (tmpValue != null) { + values[:current] = tmpValue.toFloat(); + values[:isValid] = true; + fromComplication = true; + /*DEBUG*/ logMessage("From Complications"); + } + } + + if (values[:isValid] == false) { + values[:current] = info.calories; + values[:isValid] = true; + /*DEBUG*/ logMessage("From activityInfo"); + } + + /*DEBUG*/ logMessage("calories: " + values[:current] + " rest: " + restCalories + " isValid: " + values[:isValid]); + // Now deal with either total calories and active calories (activityInfo returns Total while Complications returns Active) + if (type == GOAL_TYPE_CALORIES) { + if (fromComplication) { + values[:current] += restCalories; + } + } + else { + if (!fromComplication) { + values[:current] -= restCalories; + } + } // #123 Protect against null value returned by getProperty(). Trigger invalid goal handling code below. // Protect against unexpected type e.g. String. @@ -805,7 +843,7 @@ class CrystalView extends Ui.WatchFace { mFieldTypes[i].put("ComplicationValue", complicationValue); } } - +/* DEBUG */ if (complicationType == Complications.COMPLICATION_TYPE_CALORIES || true) { logMessage("longLabel=" + complication.longLabel + ", unit=" + complication.unit + ", value=" + complication.value); } // Now do goals if (mGoalTypes[0].get("ComplicationType") == complicationType) { mGoalTypes[0].put("ComplicationValue", complicationValue); diff --git a/source/DataArea.mc b/source/DataArea.mc index 3ec45e89..fd9daaa0 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -163,6 +163,7 @@ class DataArea extends Ui.Drawable { var icon = { GOAL_TYPE_BATTERY => "9", GOAL_TYPE_CALORIES => "6", + GOAL_TYPE_ACTIVE_CALORIES => "H", GOAL_TYPE_STEPS => "0", GOAL_TYPE_FLOORS_CLIMBED => "1", GOAL_TYPE_ACTIVE_MINUTES => "2", diff --git a/source/DataFields.mc b/source/DataFields.mc index b82afc29..e1be09ed 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -19,25 +19,26 @@ enum /* FIELD_TYPES */ { // Real fields (used by properties). FIELD_TYPE_HEART_RATE = 0, - FIELD_TYPE_BATTERY, - FIELD_TYPE_NOTIFICATIONS, - FIELD_TYPE_CALORIES, - FIELD_TYPE_DISTANCE, - FIELD_TYPE_ALARMS, - FIELD_TYPE_ALTITUDE, - FIELD_TYPE_TEMPERATURE, - FIELD_TYPE_BATTERY_HIDE_PERCENT, - FIELD_TYPE_HR_LIVE_5S, - FIELD_TYPE_SUNRISE_SUNSET, - FIELD_TYPE_WEATHER, - FIELD_TYPE_PRESSURE, - FIELD_TYPE_HUMIDITY, - FIELD_TYPE_PULSE_OX, - FIELD_FLOOR_CLIMBED, - FIELD_SOLAR_INTENSITY, - FIELD_BODY_BATTERY, - FIELD_RECOVERY_TIME, - FIELD_STRESS_LEVEL + FIELD_TYPE_BATTERY, // 1 + FIELD_TYPE_NOTIFICATIONS, // 2 + FIELD_TYPE_CALORIES, // 3 + FIELD_TYPE_DISTANCE, // 4 + FIELD_TYPE_ALARMS, // 5 + FIELD_TYPE_ALTITUDE, // 6 + FIELD_TYPE_TEMPERATURE, // 7 + FIELD_TYPE_BATTERY_HIDE_PERCENT, // 8 + FIELD_TYPE_HR_LIVE_5S, // 9 + FIELD_TYPE_SUNRISE_SUNSET, // 10 + FIELD_TYPE_WEATHER, // 11 + FIELD_TYPE_PRESSURE, // 12 + FIELD_TYPE_HUMIDITY, // 13 + FIELD_TYPE_PULSE_OX, // 14 + FIELD_FLOOR_CLIMBED, // 15 + FIELD_SOLAR_INTENSITY, // 16 + FIELD_BODY_BATTERY, // 17 + FIELD_RECOVERY_TIME, // 18 + FIELD_STRESS_LEVEL, // 19 + FIELD_TYPE_ACTIVE_CALORIES, // 20 } class DataFields extends Ui.Drawable { @@ -119,7 +120,9 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_RECOVERY_TIME, "complicationType" => Complications.COMPLICATION_TYPE_RECOVERY_TIME}, {"type" => FIELD_TYPE_ALTITUDE, "complicationType" => Complications.COMPLICATION_TYPE_ALTITUDE}, {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_WEATHER}, // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain - {"type" => FIELD_TYPE_SUNRISE_SUNSET, "complicationType" => Complications.COMPLICATION_TYPE_SUNRISE} // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain + {"type" => FIELD_TYPE_SUNRISE_SUNSET, "complicationType" => Complications.COMPLICATION_TYPE_SUNRISE}, // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain + {"type" => FIELD_TYPE_CALORIES, "complicationType" => Complications.COMPLICATION_TYPE_CALORIES}, + {"type" => FIELD_TYPE_ACTIVE_CALORIES, "complicationType" => Complications.COMPLICATION_TYPE_CALORIES} ]; var fieldTypes = view.mFieldTypes; @@ -395,7 +398,8 @@ class DataFields extends Ui.Drawable { FIELD_SOLAR_INTENSITY => "D", // SG Addition FIELD_BODY_BATTERY => "E", // SG Addition FIELD_RECOVERY_TIME => "F", // SG Addition - FIELD_STRESS_LEVEL => "G" // SG Addition + FIELD_STRESS_LEVEL => "G", // SG Addition + FIELD_TYPE_ACTIVE_CALORIES => "H" // SG Addition }[fieldType]; } @@ -585,9 +589,43 @@ class DataFields extends Ui.Drawable { } break; + // SG Addition + case FIELD_TYPE_ACTIVE_CALORIES: case FIELD_TYPE_CALORIES: - activityInfo = ActivityMonitor.getInfo(); - value = activityInfo.calories.format(INTEGER_FORMAT); + var fromComplication = false; + var today = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var profile = UserProfile.getProfile(); + var age = today.year - profile.birthYear; + var weight = profile.weight / 1000.0; + var restCalories = ((profile.gender == UserProfile.GENDER_MALE) ? 5.2 : -197.6) - 6.116 * age + 7.628 * profile.height + 12.2 * weight; + restCalories = Math.round((today.hour * 60 + today.min) * restCalories / 1440 ).toNumber(); + + if (Toybox has :Complications && view.useComplications()) { + var tmpValue = fieldTypes[index].get("ComplicationValue"); + if (tmpValue != null) { + value = tmpValue; + fromComplication = true; + } + } + + if (!fromComplication) { + activityInfo = ActivityMonitor.getInfo(); + value = activityInfo.calories; + } + + if (type == FIELD_TYPE_CALORIES) { + if (fromComplication) { + value += restCalories; + } + } + else { + if (!fromComplication) { + value -= restCalories; + } + } + + value = value.format(INTEGER_FORMAT); + break; case FIELD_TYPE_DISTANCE: diff --git a/source/Global.mc b/source/Global.mc index 10add69a..b9dc0f76 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -644,6 +644,8 @@ function logMessage(message) { } //DEBUG*/ + + (:release, :background) function logMessage(message) { } diff --git a/source/GoalMeter.mc b/source/GoalMeter.mc index f2745fe2..9de246b1 100644 --- a/source/GoalMeter.mc +++ b/source/GoalMeter.mc @@ -11,9 +11,10 @@ using Toybox.Complications; enum /* GOAL_TYPES */ { GOAL_TYPE_BATTERY = -1, GOAL_TYPE_CALORIES = -2, - GOAL_TYPE_BODY_BATTERY = -3, // SG Addition - GOAL_TYPE_STRESS_LEVEL = -4, // SG Addition - GOAL_TYPE_OFF = -5, + GOAL_TYPE_ACTIVE_CALORIES = -3, // SG Addition + GOAL_TYPE_BODY_BATTERY = -4, // SG Addition + GOAL_TYPE_STRESS_LEVEL = -5, // SG Addition + GOAL_TYPE_OFF = -6, GOAL_TYPE_STEPS = 0, // App.GOAL_TYPE_STEPS GOAL_TYPE_FLOORS_CLIMBED, // App.GOAL_TYPE_FLOORS_CLIMBED @@ -168,7 +169,9 @@ class GoalMeter extends Ui.Drawable { var complications = [{"type" => GOAL_TYPE_BODY_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BODY_BATTERY}, {"type" => GOAL_TYPE_FLOORS_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => GOAL_TYPE_STEPS, "complicationType" => Complications.COMPLICATION_TYPE_STEPS}, - {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS} + {"type" => GOAL_TYPE_STRESS_LEVEL, "complicationType" => Complications.COMPLICATION_TYPE_STRESS}, + {"type" => GOAL_TYPE_CALORIES, "complicationType" => Complications.COMPLICATION_TYPE_CALORIES}, + {"type" => GOAL_TYPE_ACTIVE_CALORIES, "complicationType" => Complications.COMPLICATION_TYPE_CALORIES} ]; var goalTypes = App.getApp().getView().mGoalTypes; From fff0c319cf1af0d5141e0ca3d7138f726c6ec51f Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:31:04 -0400 Subject: [PATCH 182/220] Update CrystalView.mc --- source/CrystalView.mc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/CrystalView.mc b/source/CrystalView.mc index f07a9546..2582e30d 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -673,17 +673,17 @@ class CrystalView extends Ui.WatchFace { values[:current] = tmpValue.toFloat(); values[:isValid] = true; fromComplication = true; - /*DEBUG*/ logMessage("From Complications"); + //DEBUG*/ logMessage("From Complications"); } } if (values[:isValid] == false) { values[:current] = info.calories; values[:isValid] = true; - /*DEBUG*/ logMessage("From activityInfo"); + //DEBUG*/ logMessage("From activityInfo"); } - /*DEBUG*/ logMessage("calories: " + values[:current] + " rest: " + restCalories + " isValid: " + values[:isValid]); + //DEBUG*/ logMessage("calories: " + values[:current] + " rest: " + restCalories + " isValid: " + values[:isValid]); // Now deal with either total calories and active calories (activityInfo returns Total while Complications returns Active) if (type == GOAL_TYPE_CALORIES) { if (fromComplication) { @@ -843,7 +843,7 @@ class CrystalView extends Ui.WatchFace { mFieldTypes[i].put("ComplicationValue", complicationValue); } } -/* DEBUG */ if (complicationType == Complications.COMPLICATION_TYPE_CALORIES || true) { logMessage("longLabel=" + complication.longLabel + ", unit=" + complication.unit + ", value=" + complication.value); } +//DEBUG*/ if (complicationType == Complications.COMPLICATION_TYPE_CALORIES || true) { logMessage("longLabel=" + complication.longLabel + ", unit=" + complication.unit + ", value=" + complication.value); } // Now do goals if (mGoalTypes[0].get("ComplicationType") == complicationType) { mGoalTypes[0].put("ComplicationValue", complicationValue); @@ -906,7 +906,7 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { if ((complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(defComplicationName))) { //DEBUG*/ logMessage("Found our flashlight complication"); complicationId = complicationId.complicationId; - /*DEBUG*/ logMessage("complicationId is '" + complicationId + "'"); + //DEBUG*/ logMessage("complicationId is '" + complicationId + "'"); if (complicationId != null) { // Got a crash caused by a null complicationId (while holding over 'Steps' while in a indoor walk activity) try { Complications.exitTo(complicationId); From 37b0b906805a6f14f1e770ec0fb41a473e1b5b98 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 22 Jul 2024 00:40:31 -0400 Subject: [PATCH 183/220] Small optimization of the Complication code --- README.md | 2 +- manifest.xml.beta | 5 +- manifest.xml.prd | 113 -------------------------------- prototypes/cover-image-Beta.jpg | Bin 0 -> 66087 bytes source/CrystalView.mc | 9 ++- source/Global.mc | 38 +++++++---- 6 files changed, 35 insertions(+), 132 deletions(-) delete mode 100644 manifest.xml.prd create mode 100644 prototypes/cover-image-Beta.jpg diff --git a/README.md b/README.md index da7157f5..407dc814 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.19.0 -- Compiled with CIQ 7.1.1 +- Compiled with CIQ 6.4.2 as 7.x currently breaks custom complications (used by Tesla-Info). - Added Active calories as a data fiel and goal. This value is calculated and not provided by Garmin so it might be off to what Garmin is showing. On Complication enabled watches, since it shows only Active calories, the calculated rested calories are added to the Calories fields and goals. To get the previous active calories, select Active Calories field or goal. ### 2.18.13 diff --git a/manifest.xml.beta b/manifest.xml.beta index f8d2c32a..45d67388 100644 --- a/manifest.xml.beta +++ b/manifest.xml.beta @@ -3,15 +3,16 @@ - - + + + ces diff --git a/manifest.xml.prd b/manifest.xml.prd deleted file mode 100644 index 9c0820f8..00000000 --- a/manifest.xml.prd +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ces - dan - deu - dut - eng - fin - fre - hrv - hun - ita - kor - nob - pol - por - rus - slo - slv - spa - swe - zhs - zht - - - - \ No newline at end of file diff --git a/prototypes/cover-image-Beta.jpg b/prototypes/cover-image-Beta.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e9c12be6a2731ee6241558d0698fc7137690c2b3 GIT binary patch literal 66087 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�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 a44II_LB6w2jipEd(CB|!t?2(+{C@y!507F1 literal 0 HcmV?d00001 diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 2582e30d..c0df5ec5 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -823,10 +823,13 @@ class CrystalView extends Ui.WatchFace { var complicationShortLabel = complication.shortLabel; var complicationValue = complication.value; - //DEBUG*/ var complicationLongLabel = complication.longLabel; if (complicationType == Complications.COMPLICATION_TYPE_RECOVERY_TIME) { logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); } + /*DEBUG*/ var complicationLongLabel = complication.longLabel; if (complicationType == Complications.COMPLICATION_TYPE_INVALID) { logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); } - if (gTeslaComplication == true && complicationType == Complications.COMPLICATION_TYPE_INVALID && complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { - $.doTeslaComplication(complicationValue); + if (gTeslaComplication == true && complicationType == Complications.COMPLICATION_TYPE_INVALID) { + if (complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { + /*DEBUG*/ logMessage("Doing Tesla Complication!"); + $.doTeslaComplication(complicationValue); + } } // I've seen this while in low power mode, so skip it diff --git a/source/Global.mc b/source/Global.mc index b9dc0f76..79da6099 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -205,34 +205,46 @@ function updateComplications(complicationName, storageName, index, complicationT (:hasComplications) function updateComplications(complicationName, storageName, index, complicationType) { if (Toybox has :Complications) { - // Check if we should subscribe to our Tesla Complication var iter = Complications.getComplications(); if (iter == null) { return; } + + if (index == null) { + return; + } + var complicationId = iter.next(); + var found = false; while (complicationId != null) { - //logMessage(complicationId.longLabel.toString()); - if (complicationId.getType() == complicationType || (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(complicationName))) { - //DEBUG*/ logMessage("Found complication " + complicationName + " with type " + complicationType); + //DEBUG*/logMessage(complicationId.longLabel.toString()); + var type = complicationId.getType(); + if (type == Complications.COMPLICATION_TYPE_HIGH_LOW_TEMPERATURE) { + /*DEBUG*/logMessage("Last one before us"); + } + if (type == complicationType && type != Complications.COMPLICATION_TYPE_INVALID) { + /*DEBUG*/logMessage(complicationId.longLabel.toString() + " available"); + complicationId = new Complications.Id(complicationType); + break; + } + else if (type == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(complicationName)) { + /*DEBUG*/logMessage(complicationId.longLabel.toString() + " available"); + complicationId = complicationId.complicationId; break; } + complicationId = iter.next(); } if (complicationId != null) { - if (complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID) { - complicationId = complicationId.complicationId; - } - else { - complicationId = new Complications.Id(complicationType); - } - - if (index != null) { - Storage.setValue(storageName + index, complicationId); + Storage.setValue(storageName + index, complicationId); + try { Complications.subscribeToUpdates(complicationId); } + catch (e) { + logMessage("Error subscribing to complication " + complicationName); + } } } } From 3646c3fe1b0bbc6499b3880790af3c8dc3c71637 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 23 Jul 2024 00:55:24 -0400 Subject: [PATCH 184/220] Bugfix in Tesla code and new handling of Tesla data since 'asleep' has been replaced with 'offline' --- manifest.xml | 70 +--------------------- manifest.xml.beta | 42 ------------- manifest.xml.prd | 110 ++++++++++++++++++++++++++++++++++ resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 3 +- source/CrystalApp.mc | 2 +- source/Global.mc | 12 ++-- 7 files changed, 120 insertions(+), 121 deletions(-) delete mode 100644 manifest.xml.beta create mode 100644 manifest.xml.prd diff --git a/manifest.xml b/manifest.xml index 77d6803f..45d67388 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,78 +1,10 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/manifest.xml.beta b/manifest.xml.beta deleted file mode 100644 index 45d67388..00000000 --- a/manifest.xml.beta +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - ces - dan - deu - dut - eng - fin - fre - hrv - hun - ita - kor - nob - pol - por - rus - slo - slv - spa - swe - zhs - zht - - - - \ No newline at end of file diff --git a/manifest.xml.prd b/manifest.xml.prd new file mode 100644 index 00000000..77d6803f --- /dev/null +++ b/manifest.xml.prd @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ces + dan + deu + dut + eng + fin + fre + hrv + hun + ita + kor + nob + pol + por + rus + slo + slv + spa + swe + zhs + zht + + + + \ No newline at end of file diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 137fde71..3cd02d5e 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0 + Crystal-Tesla V2.19.0b3 Theme Hours Colour diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index d9ddca8e..64b2d8e3 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -288,7 +288,8 @@ class BackgroundService extends Sys.ServiceDelegate { }, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; - //2023-03-05 logMessage("makeWebRequest url: '" + url + "'"); + /*DEBUG*/ logMessage("makeWebRequest url: '" + url + "'"); + /*DEBUG*/ logMessage("makeWebRequest options: '" + options + "'"); Comms.makeWebRequest(url, params, options, callback); } } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index fae2039c..71e5a62a 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -131,7 +131,7 @@ class CrystalApp extends App.AppBase { if (responseCode == 401 && internalResponseCode != 200) { // Our token has expired and we were unable to get one, refresh it Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID } else if (responseCode == 404 && internalResponseCode != 200) { // We got a vehicle not found error and we were unable to get one, reset our vehicle ID - Storage.remove("VehicleID"); // Try to get a new vehicleID + Storage.deleteValue("VehicleID"); // Try to get a new vehicleID } } diff --git a/source/Global.mc b/source/Global.mc index 79da6099..dca50936 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -103,8 +103,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (teslaInfo != null) { var httpErrorTesla = teslaInfo.get("httpErrorTesla"); var vehicleState = teslaInfo.get("VehicleState"); - var vehicleAsleep = (vehicleState != null && vehicleState.equals("asleep") == true); - var vehicleOnline = (vehicleState != null && vehicleState.equals("awake") == true); + var vehicleOnline = (vehicleState != null && vehicleState.equals("online") == true); // Only specific error are handled, the others are displayed 'as is' in pink if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { @@ -115,7 +114,7 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (httpErrorTesla == 401) { // No access token, only show the battery (in gray, default above) showMode = 0; } - else if (vehicleAsleep || httpErrorTesla == 200) { // Vehicle confirmed asleep (even if we got a 408, we'll add a "?" after the battery level to show this) or we got valid data. If the vehicle is offline, the line will show gray for stale data + else if (httpErrorTesla == 200 || (!vehicleOnline && httpErrorTesla == 408 )) { // We got our vehicle data or we're sleeping ('not online' and error 408) textColour = gThemeColour; // Defaults to theme's color } @@ -129,12 +128,12 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (httpErrorTesla != 200 && httpErrorTesla != 408) { // ResponseCode other than 200 and 408 will show a "?" beside thr battery level suffix = "?"; } - else if (vehicleAsleep) { - suffix = "s"; - } else if (chargingState != null && chargingState.equals("Charging") == true) { suffix = "+"; } + else if (!vehicleOnline) { + suffix = "s"; + } value = batteryLevel + "%" + suffix; @@ -215,7 +214,6 @@ function updateComplications(complicationName, storageName, index, complicationT } var complicationId = iter.next(); - var found = false; while (complicationId != null) { //DEBUG*/logMessage(complicationId.longLabel.toString()); From 8ea865874e70099e4478962058ec2d39772e27fb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:19:16 -0400 Subject: [PATCH 185/220] Fix for Tesla error 412 --- README.md | 2 ++ resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 407dc814..5856081e 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ Reviews: ### 2.19.0 - Compiled with CIQ 6.4.2 as 7.x currently breaks custom complications (used by Tesla-Info). +- Updated the Tesla status when the car is asleep to match the returned data from the new version of Tesla-Link app. +- Fixes the 412 error introduced by Tesla with the change to the API - Added Active calories as a data fiel and goal. This value is calculated and not provided by Garmin so it might be off to what Garmin is showing. On Complication enabled watches, since it shows only Active calories, the calculated rested calories are added to the Calories fields and goals. To get the previous active calories, select Active Calories field or goal. ### 2.18.13 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 3cd02d5e..3ee92167 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0b3 + Crystal-Tesla V2.19.0b4 Theme Hours Colour diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 64b2d8e3..d5845116 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -98,7 +98,7 @@ class BackgroundService extends Sys.ServiceDelegate { if (_vehicle_id == null) { /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); - makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", null, method(:onReceiveVehicles)); return; } @@ -238,7 +238,7 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = null; } //DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); - makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles", null, method(:onReceiveVehicles)); + makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", null, method(:onReceiveVehicles)); return; } // Our access token has expired, ask for a new one @@ -288,8 +288,8 @@ class BackgroundService extends Sys.ServiceDelegate { }, :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON }; - /*DEBUG*/ logMessage("makeWebRequest url: '" + url + "'"); - /*DEBUG*/ logMessage("makeWebRequest options: '" + options + "'"); + //DEBUG*/ logMessage("makeWebRequest url: '" + url + "'"); + //DEBUG*/ logMessage("makeWebRequest options: '" + options + "'"); Comms.makeWebRequest(url, params, options, callback); } } From f0abca7549b87aa80898a5436262d08bcdf0dc8c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:42:23 -0400 Subject: [PATCH 186/220] Bug fix in Tesla online/offline detection --- resources/strings/strings.xml | 2 +- source/Global.mc | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 3ee92167..a55cbb1a 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0b4 + Crystal-Tesla V2.19.0b5 Theme Hours Colour diff --git a/source/Global.mc b/source/Global.mc index dca50936..d7c2a339 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -107,14 +107,14 @@ function writeBatteryLevel(dc, x, y, width, height, type) { // Only specific error are handled, the others are displayed 'as is' in pink if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { - if (!vehicleOnline) { // If confirnmed asleep, only show battery and preconditionning (0 and 2) + if (!vehicleOnline) { // If not online, only show battery and preconditionning (0 and 2) showMode &= 2; } if (httpErrorTesla == 401) { // No access token, only show the battery (in gray, default above) showMode = 0; } - else if (httpErrorTesla == 200 || (!vehicleOnline && httpErrorTesla == 408 )) { // We got our vehicle data or we're sleeping ('not online' and error 408) + else if (!vehicleOnline || httpErrorTesla == 200) { // Vehicle not online (even if we got a 408, we'll add a "?" after the battery level to show this) or we got valid data. If the vehicle is offline, the line will show gray for stale data textColour = gThemeColour; // Defaults to theme's color } @@ -128,12 +128,12 @@ function writeBatteryLevel(dc, x, y, width, height, type) { if (httpErrorTesla != 200 && httpErrorTesla != 408) { // ResponseCode other than 200 and 408 will show a "?" beside thr battery level suffix = "?"; } - else if (chargingState != null && chargingState.equals("Charging") == true) { - suffix = "+"; - } else if (!vehicleOnline) { suffix = "s"; } + else if (chargingState != null && chargingState.equals("Charging") == true) { + suffix = "+"; + } value = batteryLevel + "%" + suffix; @@ -203,24 +203,25 @@ function updateComplications(complicationName, storageName, index, complicationT (:hasComplications) function updateComplications(complicationName, storageName, index, complicationType) { + if (index == null) { + return; + } + if (Toybox has :Complications) { var iter = Complications.getComplications(); if (iter == null) { return; } - if (index == null) { - return; - } var complicationId = iter.next(); while (complicationId != null) { //DEBUG*/logMessage(complicationId.longLabel.toString()); var type = complicationId.getType(); - if (type == Complications.COMPLICATION_TYPE_HIGH_LOW_TEMPERATURE) { - /*DEBUG*/logMessage("Last one before us"); - } + + // DEBUG */ if (type == Complications.COMPLICATION_TYPE_HIGH_LOW_TEMPERATURE) { logMessage("Last one before us"); } + if (type == complicationType && type != Complications.COMPLICATION_TYPE_INVALID) { /*DEBUG*/logMessage(complicationId.longLabel.toString() + " available"); complicationId = new Complications.Id(complicationType); @@ -241,7 +242,7 @@ function updateComplications(complicationName, storageName, index, complicationT Complications.subscribeToUpdates(complicationId); } catch (e) { - logMessage("Error subscribing to complication " + complicationName); + /*DEBUG*/ logMessage("Error subscribing to complication " + complicationName); } } } From de95120f50730dae5fe7a7871ccbc5478e7d8994 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:19:10 -0400 Subject: [PATCH 187/220] Update strings.xml --- resources/strings/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index a55cbb1a..35cbd4fe 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0b5 + Crystal-Tesla V2.19.0.b6 Theme Hours Colour From 9e9ad99d34bb68a34e278cfabd17df6170f2b773 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 1 Aug 2024 20:57:46 -0400 Subject: [PATCH 188/220] Debug code for TeslaInfo --- resources/strings/strings.xml | 2 +- source/Global.mc | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 35cbd4fe..836600cd 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0.b6 + Crystal-Tesla V2.19.0.b7 Theme Hours Colour diff --git a/source/Global.mc b/source/Global.mc index d7c2a339..7e48e6e1 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -97,24 +97,28 @@ function writeBatteryLevel(dc, x, y, width, height, type) { gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached. Called every second so incremented every second, giving a two second display of each value showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 - //logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); + /*DEBUG*/ logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); var teslaInfo = Storage.getValue("TeslaInfo"); if (teslaInfo != null) { var httpErrorTesla = teslaInfo.get("httpErrorTesla"); var vehicleState = teslaInfo.get("VehicleState"); var vehicleOnline = (vehicleState != null && vehicleState.equals("online") == true); - + /*DEBUG*/ logMessage("httpErrorTesla=" + httpErrorTesla + " vehicleState=" + vehicleState + " vehicleOnline=" + vehicleOnline); + /*DEBUG*/ logMessage("TeslaInfo=" + teslaInfo); // Only specific error are handled, the others are displayed 'as is' in pink if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { if (!vehicleOnline) { // If not online, only show battery and preconditionning (0 and 2) showMode &= 2; + /*DEBUG*/ logMessage("Not online, showing Bat et P"); } if (httpErrorTesla == 401) { // No access token, only show the battery (in gray, default above) + /*DEBUG*/ logMessage("401, sticking to Bat"); showMode = 0; } else if (!vehicleOnline || httpErrorTesla == 200) { // Vehicle not online (even if we got a 408, we'll add a "?" after the battery level to show this) or we got valid data. If the vehicle is offline, the line will show gray for stale data + /*DEBUG*/ logMessage("Showing in theme color"); textColour = gThemeColour; // Defaults to theme's color } @@ -647,7 +651,8 @@ function getSunTimes(lat, lng, tz, tomorrow) { } //DEBUG -(:debug, :background) +//(:debug, :background) +//(:background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); @@ -655,11 +660,9 @@ function logMessage(message) { } //DEBUG*/ - - -(:release, :background) -function logMessage(message) { -} +// (:release, :background) +// function logMessage(message) { +// } /* function type_name(obj) { From 9206e5454d041d467f4ef5664ada902cddaed4f6 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 1 Aug 2024 23:50:26 -0400 Subject: [PATCH 189/220] Fixed timezone from preventing goals to be displayed --- .../layouts/layout.xml | 1 + .../layouts/layout.xml | 1 + resources-round-208x208/layouts/layout.xml | 1 + resources-round-218x218/layouts/layout.xml | 1 + resources-round-260x260/layouts/layout.xml | 1 + resources-round-280x280/layouts/layout.xml | 1 + resources-round-360x360/layouts/layout.xml | 1 + resources-round-390x390/layouts/layout.xml | 1 + resources-round-416x416/layouts/layout.xml | 1 + resources-round-454x454/layouts/layout.xml | 1 + resources/layouts/layout.xml | 1 + source/DataArea.mc | 88 +++++++++++++------ 12 files changed, 74 insertions(+), 25 deletions(-) diff --git a/resources-rectangle-240x240/layouts/layout.xml b/resources-rectangle-240x240/layouts/layout.xml index 3271228b..87543f9e 100644 --- a/resources-rectangle-240x240/layouts/layout.xml +++ b/resources-rectangle-240x240/layouts/layout.xml @@ -19,6 +19,7 @@ 49 142 + 174 190 206 222 diff --git a/resources-rectangle-320x360/layouts/layout.xml b/resources-rectangle-320x360/layouts/layout.xml index a84bf770..90d2e6c7 100644 --- a/resources-rectangle-320x360/layouts/layout.xml +++ b/resources-rectangle-320x360/layouts/layout.xml @@ -19,6 +19,7 @@ 65 189 + 261 285 309 333 diff --git a/resources-round-208x208/layouts/layout.xml b/resources-round-208x208/layouts/layout.xml index ed7e3aab..49c4a2d4 100644 --- a/resources-round-208x208/layouts/layout.xml +++ b/resources-round-208x208/layouts/layout.xml @@ -23,6 +23,7 @@ 63 81 + 139 152 165 181 diff --git a/resources-round-218x218/layouts/layout.xml b/resources-round-218x218/layouts/layout.xml index a7be5f0b..b2c18944 100644 --- a/resources-round-218x218/layouts/layout.xml +++ b/resources-round-218x218/layouts/layout.xml @@ -18,6 +18,7 @@ 67 84 + 144 157 170 186 diff --git a/resources-round-260x260/layouts/layout.xml b/resources-round-260x260/layouts/layout.xml index 8f523394..faa22cc6 100644 --- a/resources-round-260x260/layouts/layout.xml +++ b/resources-round-260x260/layouts/layout.xml @@ -18,6 +18,7 @@ 85 90 + 180 196 212 228 diff --git a/resources-round-280x280/layouts/layout.xml b/resources-round-280x280/layouts/layout.xml index 2f5d262c..ce9d7d2b 100644 --- a/resources-round-280x280/layouts/layout.xml +++ b/resources-round-280x280/layouts/layout.xml @@ -18,6 +18,7 @@ 94 92 + 192 210 228 246 diff --git a/resources-round-360x360/layouts/layout.xml b/resources-round-360x360/layouts/layout.xml index 7ae1ddda..2faab391 100644 --- a/resources-round-360x360/layouts/layout.xml +++ b/resources-round-360x360/layouts/layout.xml @@ -19,6 +19,7 @@ 116 128 + 246 266 286 312 diff --git a/resources-round-390x390/layouts/layout.xml b/resources-round-390x390/layouts/layout.xml index 303c58cd..8f48ab7f 100644 --- a/resources-round-390x390/layouts/layout.xml +++ b/resources-round-390x390/layouts/layout.xml @@ -19,6 +19,7 @@ 123 144 + 260 286 312 338 diff --git a/resources-round-416x416/layouts/layout.xml b/resources-round-416x416/layouts/layout.xml index 301e9039..c7b67e1a 100644 --- a/resources-round-416x416/layouts/layout.xml +++ b/resources-round-416x416/layouts/layout.xml @@ -19,6 +19,7 @@ 136 144 + 284 310 336 362 diff --git a/resources-round-454x454/layouts/layout.xml b/resources-round-454x454/layouts/layout.xml index 236987f6..88fdb65c 100644 --- a/resources-round-454x454/layouts/layout.xml +++ b/resources-round-454x454/layouts/layout.xml @@ -19,6 +19,7 @@ 136 157 + 308 337 366 395 diff --git a/resources/layouts/layout.xml b/resources/layouts/layout.xml index 329104db..f76747cc 100644 --- a/resources/layouts/layout.xml +++ b/resources/layouts/layout.xml @@ -19,6 +19,7 @@ 76 88 + 160 176 192 208 diff --git a/source/DataArea.mc b/source/DataArea.mc index fd9daaa0..edd8b82f 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -9,6 +9,7 @@ using Toybox.Application.Properties; class DataArea extends Ui.Drawable { + private var mRowMY; private var mRow0Y; private var mRow1Y; private var mRow2Y; @@ -32,6 +33,7 @@ class DataArea extends Ui.Drawable { function initialize(params) { Drawable.initialize(params); + mRowMY = params[:rowMY]; mRow0Y = params[:row0Y]; mRow1Y = params[:row1Y]; mRow2Y = params[:row2Y]; @@ -79,33 +81,33 @@ class DataArea extends Ui.Drawable { var view = App.getApp().getView(); var city = view.mWeatherStationName; + var linePos = [ mRowMY, mRow0Y, mRow1Y, mRow2Y ]; + var linePosIndex = 0; + var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); + + if (moveBarStyle != 2) { + linePosIndex++; + } + var showWeatherCityName = false; if (view.mShowWeatherStationName && city != null && city.length() > 0) { + showWeatherCityName = true; dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); dc.drawText( locX + (width / 2), - mRow0Y, + linePos[linePosIndex], gNormalFont, // Limit string length. city.substring(0, 16), Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER ); + + linePosIndex++; } // #78 Setting with value of empty string may cause corresponding property to be null. city = view.mLocalCityName; if (city != null && city.length() > 0) { - // Time zone 1 city. - dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); - dc.drawText( - locX + (width / 2), - mRow1Y, - gNormalFont, - // Limit string length. - city.substring(0, 10), - Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER - ); - - // Time zone 1 time. + // Get Time based on Lat/Long var time; if (view.mLocalCityLat != null && view.mLocalCityLat >= -90.0 && view.mLocalCityLat <= 90.0 && view.mLocalCityLon != null && view.mLocalCityLon >= -180.0 && view.mLocalCityLon <= 180.0) { try { @@ -130,20 +132,56 @@ class DataArea extends Ui.Drawable { time = "???"; } - dc.setColor(gMonoLightColour, Gfx.COLOR_TRANSPARENT); - dc.drawText( - locX + (width / 2), - mRow2Y, - gNormalFont, - time, - Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER - ); - } - else { - drawGoalValues(dc, locX, mLeftGoalCurrent, mLeftGoalMax, Graphics.TEXT_JUSTIFY_LEFT); - drawGoalValues(dc, locX + width, mRightGoalCurrent, mRightGoalMax, Graphics.TEXT_JUSTIFY_RIGHT); + if (showWeatherCityName && moveBarStyle != 2 || !showWeatherCityName && moveBarStyle == 2) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there + dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + locX + (width / 2), + linePos[linePosIndex], + gNormalFont, + // Limit string length. + city.substring(0, 10), + Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER + ); + + dc.setColor(gMonoLightColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + locX + (width / 2), + linePos[linePosIndex + 1], + gNormalFont, + time, + Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER + ); + } + else { // Have both name and time on same line, just below move bar + var cityName = city.substring(0, 10) + " "; + var line = cityName + time; + var sizeFull = dc.getTextWidthInPixels(line, gNormalFont); + var sizeName = dc.getTextWidthInPixels(cityName, gNormalFont); + var pos1 = locX + (width / 2) - (sizeFull / 2); + var pos2 = pos1 + sizeName; + + dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + pos1, + linePos[linePosIndex], + gNormalFont, + cityName, + Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER + ); + dc.setColor(gMonoLightColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + pos2, + linePos[linePosIndex], + gNormalFont, + time, + Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER + ); + } } + drawGoalValues(dc, locX, mLeftGoalCurrent, mLeftGoalMax, Graphics.TEXT_JUSTIFY_LEFT); + drawGoalValues(dc, locX + width, mRightGoalCurrent, mRightGoalMax, Graphics.TEXT_JUSTIFY_RIGHT); + /*var spacingX = Sys.getDeviceSettings().screenWidth / 11; var spacingY = Sys.getDeviceSettings().screenHeight / 6; From c828403c50a41981bfedefe86bbf1eaf73b145fa Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 2 Aug 2024 00:07:15 -0400 Subject: [PATCH 190/220] Updated readme --- README.md | 1 + resources/strings/strings.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5856081e..778958ea 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Reviews: - Compiled with CIQ 6.4.2 as 7.x currently breaks custom complications (used by Tesla-Info). - Updated the Tesla status when the car is asleep to match the returned data from the new version of Tesla-Link app. - Fixes the 412 error introduced by Tesla with the change to the API +- Weather city name and "local time in city" locations are dependant on what's showing in the data area - Added Active calories as a data fiel and goal. This value is calculated and not provided by Garmin so it might be off to what Garmin is showing. On Complication enabled watches, since it shows only Active calories, the calculated rested calories are added to the Calories fields and goals. To get the previous active calories, select Active Calories field or goal. ### 2.18.13 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 836600cd..d54d9fdf 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0.b7 + Crystal-Tesla V2.19.0.b8 Theme Hours Colour From b5fd71a7d251236968a1e7e905544308ef6c8599 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:55:14 -0400 Subject: [PATCH 191/220] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 778958ea..3158353c 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.19.0 -- Compiled with CIQ 6.4.2 as 7.x currently breaks custom complications (used by Tesla-Info). +- Compiled with CIQ 6.4.2 as 7.x currently breaks custom complications (used by Tesla-Info). Has no impact on features and supported watches. - Updated the Tesla status when the car is asleep to match the returned data from the new version of Tesla-Link app. - Fixes the 412 error introduced by Tesla with the change to the API -- Weather city name and "local time in city" locations are dependant on what's showing in the data area +- Weather city name and "local time in city" locations on screen are dependant on what's showing in the data area - Added Active calories as a data fiel and goal. This value is calculated and not provided by Garmin so it might be off to what Garmin is showing. On Complication enabled watches, since it shows only Active calories, the calculated rested calories are added to the Calories fields and goals. To get the previous active calories, select Active Calories field or goal. ### 2.18.13 From 4a55c1566dd7755ab06ad8e693847498230a1d54 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 4 Sep 2024 21:46:03 -0400 Subject: [PATCH 192/220] Added Enduro3 and new Fenix8 watches. Small code optimisation for Telsa's complications --- manifest.xml | 7 +++++++ monkey.jungle | 3 +++ resources/strings/strings.xml | 2 +- source/CrystalApp.mc | 2 +- source/CrystalView.mc | 2 +- source/DataArea.mc | 2 +- source/Global.mc | 14 +++++++------- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/manifest.xml b/manifest.xml index 45d67388..c2e3aab4 100644 --- a/manifest.xml +++ b/manifest.xml @@ -3,7 +3,14 @@ + + + + + + + diff --git a/monkey.jungle b/monkey.jungle index 01ae348e..6a954f39 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -48,6 +48,9 @@ approachs7047mm.sourcePath = $(approachs7047mm.sourcePath);always-on-source epix2pro42mm.sourcePath = $(epix2pro42mm.sourcePath);always-on-source epix2pro47mm.sourcePath = $(epix2pro47mm.sourcePath);always-on-source epix2pro51mm.sourcePath = $(epix2pro51mm.sourcePath);always-on-source +fenix843mm.sourcePath = $(fenix843mm.sourcePath);always-on-source +fenix847mm.sourcePath = $(fenix847mm.sourcePath);always-on-source +fenixe.sourcePath = $(fenixe.sourcePath);always-on-source vivoactive5.sourcePath = $(vivoactive5.sourcePath);always-on-source descentmk343mm.sourcePath = $(descentmk343mm.sourcePath);always-on-source descentmk351mm.sourcePath = $(descentmk351mm.sourcePath);always-on-source diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index d54d9fdf..d7a1ca45 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.0.b8 + Crystal-Tesla V2.19.1b1 Theme Hours Colour diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 71e5a62a..32756520 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -56,7 +56,7 @@ class CrystalApp extends App.AppBase { // New app settings have been received so trigger a UI update (:background) function getServiceDelegate() { - /*DEBUG*/ logMessage("Getting service delegate"); + //DEBUG*/ logMessage("Getting service delegate"); return [new BackgroundService()]; } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index c0df5ec5..5cc04d20 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -826,7 +826,7 @@ class CrystalView extends Ui.WatchFace { /*DEBUG*/ var complicationLongLabel = complication.longLabel; if (complicationType == Complications.COMPLICATION_TYPE_INVALID) { logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); } if (gTeslaComplication == true && complicationType == Complications.COMPLICATION_TYPE_INVALID) { - if (complicationShortLabel != null && complicationShortLabel.equals("TESLA")) { + if (complicationShortLabel != null && complicationShortLabel.equals("TeslaLink")) { /*DEBUG*/ logMessage("Doing Tesla Complication!"); $.doTeslaComplication(complicationValue); } diff --git a/source/DataArea.mc b/source/DataArea.mc index edd8b82f..d553e1bb 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -129,7 +129,7 @@ class DataArea extends Ui.Drawable { } } else { - time = "???"; + time = "INV"; } if (showWeatherCityName && moveBarStyle != 2 || !showWeatherCityName && moveBarStyle == 2) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there diff --git a/source/Global.mc b/source/Global.mc index 7e48e6e1..d9b4e4f6 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -97,28 +97,28 @@ function writeBatteryLevel(dc, x, y, width, height, type) { gToggleCounter = (gToggleCounter + 1) & 7; // Increase by one, reset to 0 once 8 is reached. Called every second so incremented every second, giving a two second display of each value showMode = gToggleCounter / 2; // 0-1 is battery, 2-3 Sentry, 4-5 preconditionning, 6-7 is inside temp changed to 0 to 3 - /*DEBUG*/ logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); + //DEBUG*/ logMessage("gToggleCounter=" + gToggleCounter + " showMode=" + showMode); var teslaInfo = Storage.getValue("TeslaInfo"); if (teslaInfo != null) { var httpErrorTesla = teslaInfo.get("httpErrorTesla"); var vehicleState = teslaInfo.get("VehicleState"); var vehicleOnline = (vehicleState != null && vehicleState.equals("online") == true); - /*DEBUG*/ logMessage("httpErrorTesla=" + httpErrorTesla + " vehicleState=" + vehicleState + " vehicleOnline=" + vehicleOnline); - /*DEBUG*/ logMessage("TeslaInfo=" + teslaInfo); + //DEBUG*/ logMessage("httpErrorTesla=" + httpErrorTesla + " vehicleState=" + vehicleState + " vehicleOnline=" + vehicleOnline); + //DEBUG*/ logMessage("TeslaInfo=" + teslaInfo); // Only specific error are handled, the others are displayed 'as is' in pink if (httpErrorTesla != null && (httpErrorTesla == 200 || httpErrorTesla == 401 || httpErrorTesla == 408)) { if (!vehicleOnline) { // If not online, only show battery and preconditionning (0 and 2) showMode &= 2; - /*DEBUG*/ logMessage("Not online, showing Bat et P"); + //DEBUG*/ logMessage("Not online, showing Bat et P"); } if (httpErrorTesla == 401) { // No access token, only show the battery (in gray, default above) - /*DEBUG*/ logMessage("401, sticking to Bat"); + //DEBUG*/ logMessage("401, sticking to Bat"); showMode = 0; } else if (!vehicleOnline || httpErrorTesla == 200) { // Vehicle not online (even if we got a 408, we'll add a "?" after the battery level to show this) or we got valid data. If the vehicle is offline, the line will show gray for stale data - /*DEBUG*/ logMessage("Showing in theme color"); + //DEBUG*/ logMessage("Showing in theme color"); textColour = gThemeColour; // Defaults to theme's color } @@ -652,7 +652,7 @@ function getSunTimes(lat, lng, tz, tomorrow) { //DEBUG //(:debug, :background) -//(:background) +(:background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); From 5eef54d0d5a5229a2e3fd089dd08492b2de6f06b Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:29:38 -0500 Subject: [PATCH 193/220] Added Recovery Time as a MoveBar option --- README.md | 7 +++++++ resources/settings/settings.xml | 3 ++- resources/strings/strings.xml | 2 +- source/DataArea.mc | 4 ++-- source/MoveBar.mc | 26 +++++++++++++++++++++++--- 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3158353c..6c370f2e 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,13 @@ Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. ## Below is what has been added by me (SylvainGa). +### 2.20.0 +- Added recovery time as an option to the move bar. Once it's cleared, recovery is done. + +### 2.19.2 +- Compiled with CIQ 7.3.0. Now works with custom complications (used by Tesla-Info) +- Added Enduro3 and new Fenix8 watches (including Fenix E). +- Small code optimisation for Telsa's complications. If you also use Tesla-Link and receive complications from it, update that one too! ### 2.19.0 - Compiled with CIQ 6.4.2 as 7.x currently breaks custom complications (used by Tesla-Info). Has no impact on features and supported watches. diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 8ed2c464..2487f262 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -257,7 +257,8 @@ @Strings.AllSegments @Strings.FilledSegments - @Strings.Hidden + @Strings.RecoveryTime + @Strings.Hidden diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index d7a1ca45..f74c7d94 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.19.1b1 + Crystal-Tesla V2.20.0b1 Theme Hours Colour diff --git a/source/DataArea.mc b/source/DataArea.mc index d553e1bb..913ace8f 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -85,7 +85,7 @@ class DataArea extends Ui.Drawable { var linePosIndex = 0; var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); - if (moveBarStyle != 2) { + if (moveBarStyle != 3) { linePosIndex++; } var showWeatherCityName = false; @@ -132,7 +132,7 @@ class DataArea extends Ui.Drawable { time = "INV"; } - if (showWeatherCityName && moveBarStyle != 2 || !showWeatherCityName && moveBarStyle == 2) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there + if (showWeatherCityName && moveBarStyle != 3 || !showWeatherCityName && moveBarStyle == 3) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); dc.drawText( locX + (width / 2), diff --git a/source/MoveBar.mc b/source/MoveBar.mc index b1c8eab5..4468bee8 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -54,12 +54,32 @@ class MoveBar extends Ui.Drawable { } function draw(dc) { - if ($.getIntProperty("MoveBarStyle", 0) == 2 /* HIDDEN */) { + var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); + if (moveBarStyle == 3 /* HIDDEN */) { return; } + var view = App.getApp().getView(); + var fieldTypes = view.mFieldTypes; + var currentMoveBarLevel; var info = ActivityMonitor.getInfo(); - var currentMoveBarLevel = info.moveBarLevel; + if (moveBarStyle == 2) { /* recovery time */ + var value; + /*if (Toybox has :Complications && view.useComplications()) { + value = fieldTypes[index].get("ComplicationValue"); + } + else {*/ + value = info.timeToRecovery; + //} + + currentMoveBarLevel = ((value == null || value < 0) ? 0 : value) / 10; + if (currentMoveBarLevel > 5) { + currentMoveBarLevel = 5; + } + } + else { + currentMoveBarLevel = info.moveBarLevel; + } // Calculate current width here, now that DC is accessible. // Balance head/tail positions in full width mode. @@ -150,7 +170,7 @@ class MoveBar extends Ui.Drawable { thisBarColour = gThemeColour; // Move bar below this level, so only show if MoveBarStyle setting is ALL_SEGMENTS. - } else if (moveBarStyle == 0 /* ALL_SEGMENTS */) { + } else if (moveBarStyle != 1 /* FILLED_SEGMENTS */) { thisBarColour = gMeterBackgroundColour; // Otherwise, do not show this, or any higher level. From 93a2331f6283cf16aa74acdd19e2ca7b506c7f0c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:51:02 -0500 Subject: [PATCH 194/220] MoveBar Recovery time can be a Complication and launch its widget when pressed --- README.md | 1 + manifest.xml | 7 ---- resources/strings/strings.xml | 2 +- source/CrystalView.mc | 33 +++++++++++++++++- source/MoveBar.mc | 65 +++++++++++++++++++++++++++-------- source/ThickThinTime.mc | 12 +++---- 6 files changed, 90 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 6c370f2e..e7b6036c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.20.0 - Added recovery time as an option to the move bar. Once it's cleared, recovery is done. +- If move bar is showing recovery time and complications are enabled and available, touching that field will launch the recovery time widget ### 2.19.2 - Compiled with CIQ 7.3.0. Now works with custom complications (used by Tesla-Info) diff --git a/manifest.xml b/manifest.xml index c2e3aab4..45d67388 100644 --- a/manifest.xml +++ b/manifest.xml @@ -3,14 +3,7 @@ - - - - - - - diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index f74c7d94..60a14b58 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.20.0b1 + Crystal-Tesla V2.20.0b4 Theme Hours Colour diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 5cc04d20..ef67b388 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -56,7 +56,7 @@ class CrystalView extends Ui.WatchFace { var mFieldTypes = new [3]; var mGoalTypes = new [2]; - + var mMoveBarType; // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; @@ -107,6 +107,8 @@ class CrystalView extends Ui.WatchFace { mGoalTypes[0] = {}; mGoalTypes[1] = {}; + + mMoveBarType = {}; } function burnInProtectionIsOrWasActive() { @@ -165,6 +167,8 @@ class CrystalView extends Ui.WatchFace { mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + mMoveBarType.put("type", $.getIntProperty("MoveBarType", 0)); + // Themes: explicitly set *Colour properties that have no corresponding (user-facing) setting. updateThemeColours(); @@ -201,6 +205,8 @@ class CrystalView extends Ui.WatchFace { mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + mMoveBarType.put("type", $.getIntProperty("MoveBarType", 0)); + // Themes: explicitly set *Colour properties that have no corresponding (user-facing) setting. updateThemeColours(); @@ -854,6 +860,13 @@ class CrystalView extends Ui.WatchFace { if (mGoalTypes[1].get("ComplicationType") == complicationType) { mGoalTypes[1].put("ComplicationValue", complicationValue); } + + // Now do the MoveBar + if ($.getIntProperty("MoveBarStyle", 0) == 2) { + if (mMoveBarType.get("ComplicationType") == complicationType) { + mMoveBarType.put("ComplicationValue", complicationValue); + } + } } function hasField(fieldType) { @@ -1023,6 +1036,24 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { } } + // Check Movebar + if ($.getIntProperty("MoveBarStyle", 0) == 2) { // Only matters if we're showing the recovery time + var x = mView.mDrawables[:MoveBar]; + x = x.mX; + y = mView.mDrawables[:MoveBar].mY; + var width = mView.mDrawables[:MoveBar].width; + var height = mView.mDrawables[:MoveBar].height; + y -= height * 2; + complicationIndex = "Complication_MB" + isWithin(co_ords[0], co_ords[1], x, y, width, height * 4, "1"); + if (complicationIndex.equals("Complication_MB") == false) { + complicationId = Storage.getValue(complicationIndex); + } + + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } + } return null; } diff --git a/source/MoveBar.mc b/source/MoveBar.mc index 4468bee8..4d3a91c5 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -8,7 +8,7 @@ using Toybox.Application.Properties; class MoveBar extends Ui.Drawable { - private var mX, mY, mBaseWidth, mHeight, mSeparator; + /*private*/ var mX, mY, mBaseWidth, mHeight, mSeparator; private var mTailWidth; (:buffered) private var mBuffer; @@ -24,6 +24,8 @@ class MoveBar extends Ui.Drawable { // Either mBaseWidth, or a calculated full width. private var mCurrentWidth; + private var mMoveBarStyle; + // private enum /* MOVE_BAR_STYLE */ { // ALL_SEGMENTS, // FILLED_SEGMENTS, @@ -42,8 +44,30 @@ class MoveBar extends Ui.Drawable { mTailWidth = mHeight / 2; } + (:noComplications) function onSettingsChanged() { mBufferNeedsRecreate = true; + mMoveBarStyle = $.getIntProperty("MoveBarStyle", 0); + } + + (:hasComplications) + function onSettingsChanged() { + mBufferNeedsRecreate = true; + mMoveBarStyle = $.getIntProperty("MoveBarStyle", 0); + + if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (mMoveBarStyle == 2) { + $.updateComplications("", "Complication_MB", 1, Complications.COMPLICATION_TYPE_RECOVERY_TIME); + App.getApp().getView().mMoveBarType.put("ComplicationType", Complications.COMPLICATION_TYPE_RECOVERY_TIME); + } + else { + Storage.deleteValue("Complication_MB1"); + } + } + else { + Storage.deleteValue("Complication_MB1"); + } + } function setFullWidth(fullWidth) { @@ -54,28 +78,42 @@ class MoveBar extends Ui.Drawable { } function draw(dc) { - var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); - if (moveBarStyle == 3 /* HIDDEN */) { + if (mMoveBarStyle == 3 /* HIDDEN */) { return; } var view = App.getApp().getView(); - var fieldTypes = view.mFieldTypes; + var moveBarType = view.mMoveBarType; var currentMoveBarLevel; var info = ActivityMonitor.getInfo(); - if (moveBarStyle == 2) { /* recovery time */ - var value; - /*if (Toybox has :Complications && view.useComplications()) { - value = fieldTypes[index].get("ComplicationValue"); + if (mMoveBarStyle == 2) { /* recovery time */ + var value = null; + if (Toybox has :Complications && view.useComplications()) { + value = moveBarType.get("ComplicationValue"); + if (value != null) { + value /= 60; // Complication Time to Recovery is in minutes + value = value.toNumber(); + } } - else {*/ - value = info.timeToRecovery; - //} - currentMoveBarLevel = ((value == null || value < 0) ? 0 : value) / 10; + if (value == null) { + value = info.timeToRecovery; // Info time to recovery is in hours + } + + //value = 12; + currentMoveBarLevel = ((value == null || value < 0) ? 0 : value) / 12; // Each bar (up to 5 bars) is 12 hours + if (value > 0) { + currentMoveBarLevel++; // So only when the recovery time is zero does it display no move bars. + } if (currentMoveBarLevel > 5) { currentMoveBarLevel = 5; } + // 0 Move bar : Times up! + // 1 Move bar : Between 1 and 11 hours + // 2 Move bar : Between 12 and 23 hours + // 3 Move bar : Between 24 and 35 hours + // 4 Move bar : Between 36 and 47 hours + // 5 Move bar : 48 and more hours } else { currentMoveBarLevel = info.moveBarLevel; @@ -157,7 +195,6 @@ class MoveBar extends Ui.Drawable { var thisBarWidth; var thisBarColour = 0; var barX = x + mTailWidth; - var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); // One-based, to correspond with move bar level (zero means no bars). for (var i = 1; i <= ActivityMonitor.MOVE_BAR_LEVEL_MAX; ++i) { @@ -170,7 +207,7 @@ class MoveBar extends Ui.Drawable { thisBarColour = gThemeColour; // Move bar below this level, so only show if MoveBarStyle setting is ALL_SEGMENTS. - } else if (moveBarStyle != 1 /* FILLED_SEGMENTS */) { + } else if (mMoveBarStyle != 1 /* FILLED_SEGMENTS */) { thisBarColour = gMeterBackgroundColour; // Otherwise, do not show this, or any higher level. diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index 31b8eb7c..3f27afcf 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -72,10 +72,15 @@ class ThickThinTime extends Ui.Drawable { var halfDCWidth = dc.getWidth() / 2; var halfDCHeight = (dc.getHeight() / 2) + mAdjustY; + var addColon = $.getBoolProperty("AddColon", false); + // Centre combined hours and minutes text (not the same as right-aligning hours and left-aligning minutes). // Font has tabular figures (monospaced numbers) even across different weights, so does not matter which of hours or // minutes font is used to calculate total width. var totalWidth = dc.getTextWidthInPixels(hours + minutes, mHoursFont); + if (addColon) { + totalWidth += dc.getTextWidthInPixels(":", mMinutesFont); + } var x = halfDCWidth - (totalWidth / 2); // Draw hours. @@ -89,13 +94,6 @@ class ThickThinTime extends Ui.Drawable { ); x += dc.getTextWidthInPixels(hours, mHoursFont); - var addColon; - try { - addColon = $.getBoolProperty("AddColon", false); - } - catch (e) { - addColon = false; - } if (addColon != null && addColon == true) { dc.drawText( x, From eebfc71515daebd96d95c4cb88cc9b930e092e1e Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:51:02 -0500 Subject: [PATCH 195/220] MoveBar Recovery time can be a Complication and launch its widget when pressed Fixed the centering of the text when the colon between the hours and minutes is showing. --- README.md | 1 + manifest.xml | 7 ---- resources/strings/strings.xml | 2 +- source/CrystalView.mc | 33 +++++++++++++++++- source/MoveBar.mc | 65 +++++++++++++++++++++++++++-------- source/ThickThinTime.mc | 12 +++---- 6 files changed, 90 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 6c370f2e..e7b6036c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.20.0 - Added recovery time as an option to the move bar. Once it's cleared, recovery is done. +- If move bar is showing recovery time and complications are enabled and available, touching that field will launch the recovery time widget ### 2.19.2 - Compiled with CIQ 7.3.0. Now works with custom complications (used by Tesla-Info) diff --git a/manifest.xml b/manifest.xml index c2e3aab4..45d67388 100644 --- a/manifest.xml +++ b/manifest.xml @@ -3,14 +3,7 @@ - - - - - - - diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index f74c7d94..60a14b58 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.20.0b1 + Crystal-Tesla V2.20.0b4 Theme Hours Colour diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 5cc04d20..ef67b388 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -56,7 +56,7 @@ class CrystalView extends Ui.WatchFace { var mFieldTypes = new [3]; var mGoalTypes = new [2]; - + var mMoveBarType; // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; @@ -107,6 +107,8 @@ class CrystalView extends Ui.WatchFace { mGoalTypes[0] = {}; mGoalTypes[1] = {}; + + mMoveBarType = {}; } function burnInProtectionIsOrWasActive() { @@ -165,6 +167,8 @@ class CrystalView extends Ui.WatchFace { mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + mMoveBarType.put("type", $.getIntProperty("MoveBarType", 0)); + // Themes: explicitly set *Colour properties that have no corresponding (user-facing) setting. updateThemeColours(); @@ -201,6 +205,8 @@ class CrystalView extends Ui.WatchFace { mGoalTypes[0].put("type", $.getIntProperty("LeftGoalType", 0)); mGoalTypes[1].put("type", $.getIntProperty("RightGoalType", 0)); + mMoveBarType.put("type", $.getIntProperty("MoveBarType", 0)); + // Themes: explicitly set *Colour properties that have no corresponding (user-facing) setting. updateThemeColours(); @@ -854,6 +860,13 @@ class CrystalView extends Ui.WatchFace { if (mGoalTypes[1].get("ComplicationType") == complicationType) { mGoalTypes[1].put("ComplicationValue", complicationValue); } + + // Now do the MoveBar + if ($.getIntProperty("MoveBarStyle", 0) == 2) { + if (mMoveBarType.get("ComplicationType") == complicationType) { + mMoveBarType.put("ComplicationValue", complicationValue); + } + } } function hasField(fieldType) { @@ -1023,6 +1036,24 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { } } + // Check Movebar + if ($.getIntProperty("MoveBarStyle", 0) == 2) { // Only matters if we're showing the recovery time + var x = mView.mDrawables[:MoveBar]; + x = x.mX; + y = mView.mDrawables[:MoveBar].mY; + var width = mView.mDrawables[:MoveBar].width; + var height = mView.mDrawables[:MoveBar].height; + y -= height * 2; + complicationIndex = "Complication_MB" + isWithin(co_ords[0], co_ords[1], x, y, width, height * 4, "1"); + if (complicationIndex.equals("Complication_MB") == false) { + complicationId = Storage.getValue(complicationIndex); + } + + //DEBUG*/ logMessage(complicationIndex + " = " + complicationId); + if (complicationId != null) { + return complicationId; + } + } return null; } diff --git a/source/MoveBar.mc b/source/MoveBar.mc index 4468bee8..4d3a91c5 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -8,7 +8,7 @@ using Toybox.Application.Properties; class MoveBar extends Ui.Drawable { - private var mX, mY, mBaseWidth, mHeight, mSeparator; + /*private*/ var mX, mY, mBaseWidth, mHeight, mSeparator; private var mTailWidth; (:buffered) private var mBuffer; @@ -24,6 +24,8 @@ class MoveBar extends Ui.Drawable { // Either mBaseWidth, or a calculated full width. private var mCurrentWidth; + private var mMoveBarStyle; + // private enum /* MOVE_BAR_STYLE */ { // ALL_SEGMENTS, // FILLED_SEGMENTS, @@ -42,8 +44,30 @@ class MoveBar extends Ui.Drawable { mTailWidth = mHeight / 2; } + (:noComplications) function onSettingsChanged() { mBufferNeedsRecreate = true; + mMoveBarStyle = $.getIntProperty("MoveBarStyle", 0); + } + + (:hasComplications) + function onSettingsChanged() { + mBufferNeedsRecreate = true; + mMoveBarStyle = $.getIntProperty("MoveBarStyle", 0); + + if (Toybox has :Complications && App.getApp().getView().useComplications()) { + if (mMoveBarStyle == 2) { + $.updateComplications("", "Complication_MB", 1, Complications.COMPLICATION_TYPE_RECOVERY_TIME); + App.getApp().getView().mMoveBarType.put("ComplicationType", Complications.COMPLICATION_TYPE_RECOVERY_TIME); + } + else { + Storage.deleteValue("Complication_MB1"); + } + } + else { + Storage.deleteValue("Complication_MB1"); + } + } function setFullWidth(fullWidth) { @@ -54,28 +78,42 @@ class MoveBar extends Ui.Drawable { } function draw(dc) { - var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); - if (moveBarStyle == 3 /* HIDDEN */) { + if (mMoveBarStyle == 3 /* HIDDEN */) { return; } var view = App.getApp().getView(); - var fieldTypes = view.mFieldTypes; + var moveBarType = view.mMoveBarType; var currentMoveBarLevel; var info = ActivityMonitor.getInfo(); - if (moveBarStyle == 2) { /* recovery time */ - var value; - /*if (Toybox has :Complications && view.useComplications()) { - value = fieldTypes[index].get("ComplicationValue"); + if (mMoveBarStyle == 2) { /* recovery time */ + var value = null; + if (Toybox has :Complications && view.useComplications()) { + value = moveBarType.get("ComplicationValue"); + if (value != null) { + value /= 60; // Complication Time to Recovery is in minutes + value = value.toNumber(); + } } - else {*/ - value = info.timeToRecovery; - //} - currentMoveBarLevel = ((value == null || value < 0) ? 0 : value) / 10; + if (value == null) { + value = info.timeToRecovery; // Info time to recovery is in hours + } + + //value = 12; + currentMoveBarLevel = ((value == null || value < 0) ? 0 : value) / 12; // Each bar (up to 5 bars) is 12 hours + if (value > 0) { + currentMoveBarLevel++; // So only when the recovery time is zero does it display no move bars. + } if (currentMoveBarLevel > 5) { currentMoveBarLevel = 5; } + // 0 Move bar : Times up! + // 1 Move bar : Between 1 and 11 hours + // 2 Move bar : Between 12 and 23 hours + // 3 Move bar : Between 24 and 35 hours + // 4 Move bar : Between 36 and 47 hours + // 5 Move bar : 48 and more hours } else { currentMoveBarLevel = info.moveBarLevel; @@ -157,7 +195,6 @@ class MoveBar extends Ui.Drawable { var thisBarWidth; var thisBarColour = 0; var barX = x + mTailWidth; - var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); // One-based, to correspond with move bar level (zero means no bars). for (var i = 1; i <= ActivityMonitor.MOVE_BAR_LEVEL_MAX; ++i) { @@ -170,7 +207,7 @@ class MoveBar extends Ui.Drawable { thisBarColour = gThemeColour; // Move bar below this level, so only show if MoveBarStyle setting is ALL_SEGMENTS. - } else if (moveBarStyle != 1 /* FILLED_SEGMENTS */) { + } else if (mMoveBarStyle != 1 /* FILLED_SEGMENTS */) { thisBarColour = gMeterBackgroundColour; // Otherwise, do not show this, or any higher level. diff --git a/source/ThickThinTime.mc b/source/ThickThinTime.mc index 31b8eb7c..3f27afcf 100644 --- a/source/ThickThinTime.mc +++ b/source/ThickThinTime.mc @@ -72,10 +72,15 @@ class ThickThinTime extends Ui.Drawable { var halfDCWidth = dc.getWidth() / 2; var halfDCHeight = (dc.getHeight() / 2) + mAdjustY; + var addColon = $.getBoolProperty("AddColon", false); + // Centre combined hours and minutes text (not the same as right-aligning hours and left-aligning minutes). // Font has tabular figures (monospaced numbers) even across different weights, so does not matter which of hours or // minutes font is used to calculate total width. var totalWidth = dc.getTextWidthInPixels(hours + minutes, mHoursFont); + if (addColon) { + totalWidth += dc.getTextWidthInPixels(":", mMinutesFont); + } var x = halfDCWidth - (totalWidth / 2); // Draw hours. @@ -89,13 +94,6 @@ class ThickThinTime extends Ui.Drawable { ); x += dc.getTextWidthInPixels(hours, mHoursFont); - var addColon; - try { - addColon = $.getBoolProperty("AddColon", false); - } - catch (e) { - addColon = false; - } if (addColon != null && addColon == true) { dc.drawText( x, From 5d9a6558a02e50046b16abdc264fd2783a9014f0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:56:07 -0500 Subject: [PATCH 196/220] Doc update --- README.md | 3 ++- resources/strings/strings.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e7b6036c..3cc84108 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,8 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.20.0 - Added recovery time as an option to the move bar. Once it's cleared, recovery is done. -- If move bar is showing recovery time and complications are enabled and available, touching that field will launch the recovery time widget +- If the move bar is showing the recovery time and complications are enabled/available, touching that field will launch the recovery time widget +- Fixed the centering of the time when the AddColon option is active (thanks blueberry-bytes) ### 2.19.2 - Compiled with CIQ 7.3.0. Now works with custom complications (used by Tesla-Info) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 60a14b58..3b1d3248 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.20.0b4 + Crystal-Tesla V2.20.0b5 Theme Hours Colour From 973137ffc10e8b9b724be19fb715b48665747862 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Fri, 29 Nov 2024 15:20:44 -0500 Subject: [PATCH 197/220] Removed weather station name --- README.md | 6 ++++-- resources/settings/properties.xml | 2 -- resources/settings/settings.xml | 4 ---- resources/strings/strings.xml | 2 +- source/CrystalView.mc | 7 ++++--- source/DataArea.mc | 34 ++++++++++++++++--------------- 6 files changed, 27 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 3cc84108..e6a75577 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,11 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.20.0 +- Compiled with CIQ 7.3.1 - Added recovery time as an option to the move bar. Once it's cleared, recovery is done. -- If the move bar is showing the recovery time and complications are enabled/available, touching that field will launch the recovery time widget -- Fixed the centering of the time when the AddColon option is active (thanks blueberry-bytes) +- If the move bar is showing the recovery time and complications are enabled/available, touching that field will launch the recovery time widget. +- Fixed the centering of the time when the AddColon option is active (thanks blueberry-bytes). +- Removed references to weather city name since Garmin disabled that feature in their latest firmware. ### 2.19.2 - Compiled with CIQ 7.3.0. Now works with custom complications (used by Tesla-Info) diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 9b84c73d..285e6fca 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -30,8 +30,6 @@ false 0 - true - 0 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 2487f262..0f0f2b50 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -245,10 +245,6 @@ - - - - diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 3b1d3248..bdd3b69f 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.20.0b5 + Crystal-Tesla V2.20.0b7 Theme Hours Colour diff --git a/source/CrystalView.mc b/source/CrystalView.mc index ef67b388..d57e1fc8 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -60,7 +60,7 @@ class CrystalView extends Ui.WatchFace { // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; - var mWeatherStationName; + //var mWeatherStationName; // Weather Station name removed from firmware var mLocalCityName; var mLocalCityLat; var mLocalCityLon; @@ -290,7 +290,8 @@ class CrystalView extends Ui.WatchFace { humidity = humidity.format(INTEGER_FORMAT) + "%"; } - mWeatherStationName = $.validateString(weather.observationLocationName, null); + // Weather Station name removed from firmware + // mWeatherStationName = $.validateString(weather.observationLocationName, null); var icon = "01"; var day = "d"; @@ -344,7 +345,7 @@ class CrystalView extends Ui.WatchFace { /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; - /*DEBUG*/ logMessage("Weather at " + mWeatherStationName + " is " + result); + /*DEBUG*/ logMessage("Weather is " + result); } else { result = { "cod" => 404 }; diff --git a/source/DataArea.mc b/source/DataArea.mc index 913ace8f..8493b8fe 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -80,7 +80,7 @@ class DataArea extends Ui.Drawable { drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, mRightGoalstaled, Graphics.TEXT_JUSTIFY_RIGHT); var view = App.getApp().getView(); - var city = view.mWeatherStationName; + var city = null; //view.mWeatherStationName; // Weather Station name removed from firmware var linePos = [ mRowMY, mRow0Y, mRow1Y, mRow2Y ]; var linePosIndex = 0; var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); @@ -88,21 +88,23 @@ class DataArea extends Ui.Drawable { if (moveBarStyle != 3) { linePosIndex++; } - var showWeatherCityName = false; - if (view.mShowWeatherStationName && city != null && city.length() > 0) { - showWeatherCityName = true; - dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); - dc.drawText( - locX + (width / 2), - linePos[linePosIndex], - gNormalFont, - // Limit string length. - city.substring(0, 16), - Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER - ); - linePosIndex++; - } + // Weather Station name removed from firmware + // var showWeatherCityName = false; + // if (view.mShowWeatherStationName && city != null && city.length() > 0) { + // showWeatherCityName = true; + // dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); + // dc.drawText( + // locX + (width / 2), + // linePos[linePosIndex], + // gNormalFont, + // // Limit string length. + // city.substring(0, 16), + // Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER + // ); + + // linePosIndex++; + // } // #78 Setting with value of empty string may cause corresponding property to be null. city = view.mLocalCityName; @@ -132,7 +134,7 @@ class DataArea extends Ui.Drawable { time = "INV"; } - if (showWeatherCityName && moveBarStyle != 3 || !showWeatherCityName && moveBarStyle == 3) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there + if (/*showWeatherCityName && moveBarStyle != 3 || !showWeatherCityName &&*/ moveBarStyle == 3) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); dc.drawText( locX + (width / 2), From 9a4ec580cfe6026bc833861d8f2cd7c2811cb0eb Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:10:47 -0500 Subject: [PATCH 198/220] Added back OWM and the queueing of requests. Fixed for -403 error. --- manifest.xml | 2 +- resources/settings/properties.xml | 7 + resources/settings/settings.xml | 16 ++ resources/strings/strings.xml | 4 + source/BackgroundService.mc | 420 ++++++++++++++++++++++++------ source/CrystalApp.mc | 133 +++++++--- source/CrystalView.mc | 358 ++++++++++++++++++------- source/DataArea.mc | 34 +-- source/DataFields.mc | 25 +- 9 files changed, 759 insertions(+), 240 deletions(-) diff --git a/manifest.xml b/manifest.xml index 45d67388..870ccddc 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 285e6fca..2448ef13 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -34,6 +34,13 @@ 0 + + + + true + + 2651f49cb20de925fc57590709b86ce6 + false 1 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 0f0f2b50..f902ff53 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -258,6 +258,22 @@ + + + + + + + + + + + + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index bdd3b69f..3e819802 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -127,4 +127,8 @@ Which vehicle to show? Show weather station name? Complication Long Name + + Latitude + Longitude + OpenWeatherMap API Key Override diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index d5845116..c928fa86 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -12,23 +12,31 @@ class BackgroundService extends Sys.ServiceDelegate { var _token; var _vehicle_id; + var _step; + var _bg_data; (:background) function initialize() { //DEBUG*/ logMessage("In ServiceDelegate"); Sys.ServiceDelegate.initialize(); + _step = 0; +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { /*DEBUG*/ logMessage("returning because Storage.getValue(\"Tesla\") is " + Storage.getValue("Tesla") + " or gTeslaComplication is " + gTeslaComplication); return; } - var teslaInfo = Bg.getBackgroundData(); - if (teslaInfo == null) { - teslaInfo = {}; - } + if (_bg_data == null) { + _bg_data = Bg.getBackgroundData(); + if (_bg_data == null) { + _bg_data = {}; + } + } else { - /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); } var timeNow = Time.now().value(); @@ -36,9 +44,19 @@ class BackgroundService extends Sys.ServiceDelegate { var expiresIn; // Get the unexpired token from the buffer if we have one, otherwise from Properties/Storage - _token = teslaInfo.get("AccessToken"); - createdAt = teslaInfo.get("TokenCreatedAt"); - expiresIn = teslaInfo.get("TokenExpiresIn"); + var teslaInfo = _bg_data.get("TeslaInfo"); + if (teslaInfo != null) { + _token = teslaInfo.get("AccessToken"); + createdAt = teslaInfo.get("TokenCreatedAt"); + expiresIn = teslaInfo.get("TokenExpiresIn"); + + _vehicle_id = teslaInfo.get("VehicleID"); + } + + if (_vehicle_id == null) { + _vehicle_id = Storage.getValue("TeslaVehicleID"); + } + if (_token != null && createdAt != null && expiresIn != null) { if (timeNow > createdAt + expiresIn) { _token = null; @@ -63,7 +81,7 @@ class BackgroundService extends Sys.ServiceDelegate { _token = null; } - if (_token != null && _token.equals("") == false) { + if (_token != null && _token.length() > 0) { //DEBUG*/ var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); _token = "Bearer " + _token; } @@ -71,51 +89,208 @@ class BackgroundService extends Sys.ServiceDelegate { _token = null; } - _vehicle_id = teslaInfo.get("VehicleID"); - if (_vehicle_id == null) { - _vehicle_id = Storage.getValue("TeslaVehicleID"); - } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** } + // Read pending web requests, and call appropriate web request function. + // This function determines priority of web requests, if multiple are pending. + // Pending web request flag will be cleared only once the background data has been successfully received. (:background) function onTemporalEvent() { - if (!Sys.getDeviceSettings().phoneConnected) { - /*DEBUG*/ logMessage("Our phone isn't connected, bailing out"); - Bg.exit(null); + var pendingWebRequests = Storage.getValue("PendingWebRequests"); + /*DEBUG*/ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "' and step is " + _step); + /*DEBUG*/ logMessage("onTemporalEvent:_bg_data is '" + _bg_data); + + if (pendingWebRequests != null) { + + // // 1. City local time. + // if (pendingWebRequests["CityLocalTime"] != null) { + // makeWebRequest( + // "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", + // { + // "city" => $.getStringProperty("LocalTimeInCity","") + // }, + // method(:onReceiveCityLocalTime) + // ); + + // } + + // 2. Weather. + if (_step == 0) { + if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { + var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); + var lat = $.getStringProperty("LastLocationLat",""); + var lon = $.getStringProperty("LastLocationLng",""); + /*DEBUG*/ logMessage("onTemporalEvent:OWM with overide=" + owmKeyOverride + " lat=" + lat + " lon=" + lon); + + if (lat.length() > 0 && lon.length() > 0) { + makeWebRequest( + "https://api.openweathermap.org/data/2.5/weather", + // "https://api.openweathermap.org/data/3.0/onecall", + { + "lat" => lat, + "lon" => lon, + + // Polite request from Vince, developer of the Crystal Watch Face: + // + // Please do not abuse this API key, or else I will be forced to make thousands of users of Crystal + // sign up for their own Open Weather Map free account, and enter their key in settings - a much worse + // user experience for everyone. + // + // Crystal has been registered with OWM on the Open Source Plan, which lifts usage limits for free, so + // that everyone benefits. However, these lifted limits only apply to the Current Weather API, and *not* + // the One Call API. Usage of this key for the One Call API risks blocking the key for everyone. + // + // If you intend to use this key in your own app, especially for the One Call API, please create your own + // OWM account, and own key. You should be able to apply for the Open Source Plan to benefit from the same + // lifted limits as Crystal. Thank you. + "appid" => ((owmKeyOverride == null) || (owmKeyOverride.length() == 0)) ? "2651f49cb20de925fc57590709b86ce6" : owmKeyOverride, + + "units" => "metric" // Celcius. + }, + method(:onReceiveOpenWeatherMapCurrent) + ); + } + } + else { + _step++; + } + } + +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** + // 3. Tesla + else if (_step == 1) { + if (pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null) { + if (!Sys.getDeviceSettings().phoneConnected) { + return; + } + + // if (_vehicle_id) { + // makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); + // } + + if (_token == null) { + /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); + var refreshToken = $.getStringProperty("TeslaRefreshToken",""); + if (refreshToken != null && refreshToken.length() > 0) { + //DEBUG*/ logMessage("onTemporalEvent:Refresh Token is " + refreshToken); + makeWebPost(refreshToken, method(:onReceiveToken)); + } else { + /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); + _bg_data.put({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); + //DEBUG*/ _bg_data.put({ "TeslaInfo" => { "httpErrorTesla" => 200, "httpInternalErrorTesla" => 200, "BatteryLevel" => 70, "ChargingState" => "Charging", "InsideTemp" => 21, "PrecondEnabled" => false, "SentryEnabled" => false, "VehicleID" => "12345678" , "VehicleState" => "online"} }); + /*DEBUG*/ logMessage("onTemporalEvent: Exiting with " + _bg_data); + Bg.exit(_bg_data); + } + return; + } + + if (_vehicle_id == null) { + /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); + return; + } + + //DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", Comms.HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN, method(:onReceiveVehicleData)); + } + else { + _step++; + } + } + else { // Done, send data! + /*DEBUG*/ logMessage("onTemporalEvent: Exiting with " + _bg_data); + Bg.exit(_bg_data); + } + +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** + } else { + /*DEBUG*/ logMessage("onTemporalEvent() called with no pending web requests!"); } + } - if (_token == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); - var refreshToken = $.getStringProperty("TeslaRefreshToken",""); - if (refreshToken != null) { - makeWebPost(refreshToken, method(:onReceiveToken)); + (:background) + function onReceiveOpenWeatherMapCurrent(responseCode, data) + { + var result; + + /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent responseCode: " + responseCode); + //DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent data: " + data); + + // Useful data only available if result was successful. + // Filter and flatten data response for data that we actually need. + // Reduces runtime memory spike in main app. + if (responseCode == 200) { + result = { + "cod" => data["cod"], + "lat" => data["coord"]["lat"], + "lon" => data["coord"]["lon"], + "dt" => data["dt"], + "temp" => data["main"]["temp"], + "humidity" => data["main"]["humidity"], + "icon" => data["weather"][0]["icon"], + "name" => data["name"] + }; + + // HTTP error: do not save. + } + else { + result = Storage.getValue("OpenWeatherMapCurrent"); + if (result) { + result["cod"] = responseCode; } else { - /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); - Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); + result = { + "httpError" => responseCode + }; } - return; } - if (_vehicle_id == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); - makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", null, method(:onReceiveVehicles)); - return; - } + _bg_data.put("OpenWeatherMapCurrent", result); + + /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: result=" + result); - //DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); - makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", null, method(:onReceiveVehicleData)); + _step++; // We've processed Tesla data, do next one + if (_step < 2) { + onTemporalEvent(); // Call back so we get the next steps done right now + } + else { + // Last queue element, exit background process + try { + /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: Exiting with " + _bg_data); + Bg.exit(_bg_data); + } + catch (e) { + /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent exit assertion " + e); + } + } } +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** (:background) function onReceiveToken(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); - var teslaInfo = Bg.getBackgroundData(); + if (_bg_data == null) { + _bg_data = Bg.getBackgroundData(); + if (_bg_data == null) { + _bg_data = {}; + } + } + else { + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveToken: Buffer has keys " + keys); + } + + var teslaInfo = _bg_data.get("TeslaInfo"); if (teslaInfo == null) { teslaInfo = {}; - } - else { - /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveToken: Buffer has keys " + keys); } if (responseCode == 200) { @@ -123,16 +298,30 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("RefreshToken", responseData["refresh_token"]); teslaInfo.put("TokenExpiresIn", responseData["expires_in"]); teslaInfo.put("TokenCreatedAt", Time.now().value()); - } + _bg_data.put("TeslaInfo", teslaInfo); + onTemporalEvent(); // Call back so we get the next steps done right now + return; + } + teslaInfo.put("httpErrorTesla", 401); teslaInfo.put("httpInternalErrorTesla", responseCode); - try { - Bg.exit({ "TeslaInfo" => teslaInfo }); - } - catch (e) { - Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); + _bg_data.put("TeslaInfo", teslaInfo); + + _step++; // We've processed Tesla data and got an error, skip continuing Tesla and move to the next one + if (_step < 2) { + onTemporalEvent(); // Call back so we get the next steps done right now + } + else { + // Last queue element, exit background process + try { + /*DEBUG*/ logMessage("onReceiveToken: Exiting with " + _bg_data); + Bg.exit(_bg_data); + } + catch (e) { + /*DEBUG*/ logMessage("onReceiveToken exit assertion " + e); + } } } @@ -140,12 +329,20 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveVehicles(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); - var teslaInfo = Bg.getBackgroundData(); + if (_bg_data == null) { + _bg_data = Bg.getBackgroundData(); + if (_bg_data == null) { + _bg_data = {}; + } + } + else { + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicles: Buffer has keys " + keys); + } + + + var teslaInfo = _bg_data.get("TeslaInfo"); if (teslaInfo == null) { teslaInfo = {}; - } - else { - /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicles: Buffer has keys " + keys); } if (responseCode == 200) { @@ -179,16 +376,31 @@ class BackgroundService extends Sys.ServiceDelegate { } teslaInfo.put("VehicleID", _vehicle_id); teslaInfo.put("VehicleState",vehice_state); + + _bg_data.put("TeslaInfo", teslaInfo); + _step++; + onTemporalEvent(); // Call back so we get the next steps done right now + return; } teslaInfo.put("httpErrorTesla", (_vehicle_id == null ? 404 : 408)); teslaInfo.put("httpInternalErrorTesla", responseCode); - try { - Bg.exit({ "TeslaInfo" => teslaInfo }); - } - catch (e) { - Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); + _bg_data.put("TeslaInfo", teslaInfo); + + _step++; // We've processed Tesla data, do next one + if (_step < 2) { + onTemporalEvent(); // Call back so we get the next steps done right now + } + else { + // Last queue element, exit background process + try { + /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); + Bg.exit(_bg_data); + } + catch (e) { + /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); + } } } @@ -197,12 +409,19 @@ class BackgroundService extends Sys.ServiceDelegate { /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); - var teslaInfo = Bg.getBackgroundData(); + if (_bg_data == null) { + _bg_data = Bg.getBackgroundData(); + if (_bg_data == null) { + _bg_data = {}; + } + else { + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); + } + } + + var teslaInfo = _bg_data.get("TeslaInfo"); if (teslaInfo == null) { teslaInfo = {}; - } - else { - /*DEBUG*/ var keys = teslaInfo.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); } teslaInfo.put("httpErrorTesla", responseCode); @@ -211,24 +430,35 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.remove("httpInternalErrorTesla"); teslaInfo.put("VehicleState", "online"); - var response = responseData.get("response"); - if (response != null) { - var result = response.get("charge_state"); - if (result != null) { - teslaInfo.put("BatteryLevel", result.get("battery_level")); - teslaInfo.put("ChargingState", result.get("charging_state")); - teslaInfo.put("PrecondEnabled", result.get("preconditioning_enabled")); - } - result = response.get("climate_state"); - if (result != null) { - teslaInfo.put("InsideTemp", result.get("inside_temp")); - } - - result = response.get("vehicle_state"); - if (result != null) { - teslaInfo.put("SentryEnabled", result.get("sentry_mode")); - } - } + var pos = responseData.find("battery_level"); + var str = responseData.substring(pos + 15, pos + 20); + var posEnd = str.find(","); + teslaInfo.put("BatteryLevel", $.validateNumber(str.substring(0, posEnd), 0)); + + pos = responseData.find("charging_state"); + str = responseData.substring(pos + 17, pos + 37); + posEnd = str.find("\""); + teslaInfo.put("ChargingState", $.validateString(str.substring(0, posEnd), "")); + + pos = responseData.find("inside_temp"); + str = responseData.substring(pos + 13, pos + 20); + posEnd = str.find(","); + teslaInfo.put("InsideTemp", $.validateNumber(str.substring(0, posEnd), 0)); + + pos = responseData.find("sentry_mode"); + str = responseData.substring(pos + 13, pos + 20); + posEnd = str.find(","); + teslaInfo.put("SentryEnabled", $.validateString(str.substring(0, posEnd), "").equals("true")); + + pos = responseData.find("preconditioning_enabled"); + str = responseData.substring(pos + 25, pos + 32); + posEnd = str.find(","); + teslaInfo.put("PrecondEnabled", $.validateString(str.substring(0, posEnd), "").equals("true")); + + _bg_data.put("TeslaInfo", teslaInfo); + _step++; + onTemporalEvent(); // Call back so we get the next steps done right now + return; } // If no vehicle (rare) or can't contact (much more frequent) is received, try to get a new vehicle (404) or retrieve its state (408) else if (responseCode == 404 || responseCode == 408) { @@ -237,25 +467,35 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("VehicleID", null); _vehicle_id = null; } - //DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); - makeWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", null, method(:onReceiveVehicles)); + /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); return; } // Our access token has expired, ask for a new one else if (responseCode == 401) { var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { - //DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); + /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); makeWebPost(refreshToken, method(:onReceiveToken)); return; } } - try { - Bg.exit({ "TeslaInfo" => teslaInfo }); - } - catch (e) { - Bg.exit({ "TeslaInfo" => { "httpErrorTesla" => 413, "httpInternalErrorTesla" => 413 } }); + _bg_data.put("TeslaInfo", teslaInfo); + + _step++; // We've processed Tesla data, do next one + if (_step < 2) { + onTemporalEvent(); // Call back so we get the next steps done right now + } + else { + // Last queue element, exit background process + try { + /*DEBUG*/ logMessage("onReceiveVehicleData: Exiting with " + _bg_data); + Bg.exit(_bg_data); + } + catch (e) { + /*DEBUG*/ logMessage("onReceiveVehicleData exit assertion " + e); + } } } @@ -279,17 +519,31 @@ class BackgroundService extends Sys.ServiceDelegate { } (:background) - function makeWebRequest(url, params, callback) { + function makeTeslaWebRequest(url, method, callback) { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, :headers => { "Authorization" => _token, "User-Agent" => "Crystal-Tesla for Garmin", }, - :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON + :responseType => method }; //DEBUG*/ logMessage("makeWebRequest url: '" + url + "'"); //DEBUG*/ logMessage("makeWebRequest options: '" + options + "'"); - Comms.makeWebRequest(url, params, options, callback); + Comms.makeWebRequest(url, null, options, callback); } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** + + (:background) + function makeWebRequest(url, params, callback) { + var options = { + :method => Comms.HTTP_REQUEST_METHOD_GET, + :headers => { + "Content-Type" => Comms.REQUEST_CONTENT_TYPE_URL_ENCODED}, + :responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON + }; + Comms.makeWebRequest(url, params, options, callback); + } } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 32756520..be24e3a1 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -12,6 +12,14 @@ import Toybox.Application; import Toybox.Lang; import Toybox.WatchUi; +// In-memory current location. +// Previously persisted in App.Storage, but now persisted in Object Store due to #86 workaround for App.Storage firmware bug. +// Current location retrieved/saved in checkPendingWebRequests(). +// Persistence allows weather and sunrise/sunset features to be used after watch face restart, even if watch no longer has current +// location available. +var gLocationLat = null; +var gLocationLng = null; + var gTeslaComplication = false; (:background) @@ -83,61 +91,100 @@ class CrystalApp extends App.AppBase { Ui.requestUpdate(); } - // Handle data received from BackgroundService. - // data is Dictionary with single key that indicates the data type received. + (:background) function onBackgroundData(data) { - var teslaInfo = Storage.getValue("TeslaInfo"); // What we have in Storage - if (teslaInfo == null) { - teslaInfo = {}; + /*DEBUG*/ logMessage("onBackgroundData:received '" + data + "'"); + var pendingWebRequests = Storage.getValue("PendingWebRequests"); + if (pendingWebRequests == null) { + pendingWebRequests = {}; } - // Update in TeslaInfo what has been received in receivedData - var receivedData = data["TeslaInfo"]; // What we just received - if (receivedData != null && receivedData instanceof Lang.Dictionary) { + var type = data.keys()[0]; // Type of received data. + var storedData = Storage.getValue(type); + if (storedData == null) { + storedData = {}; + } + var receivedData = data[type]; // The actual data received: strip away type key. + + // Do process the data if what we got was an error + if (receivedData["httpError"] == null) { + // New data received: clear pendingWebRequests flag and overwrite stored data that with what we received, leaving others intact. + // storedData = receivedData; var keys = receivedData.keys(); var values = receivedData.values(); for (var i = 0; i < keys.size(); i++) { - teslaInfo.put(keys[i], values[i]); + storedData.put(keys[i], values[i]); } - } - else { - /*DEBUG*/ logMessage("Unexpected invalid receivedData: " + receivedData); - } + storedData.put("NewData", true); - // Copy into their own name some of the entries in TeslaInfo, then delete from TeslaInfo - var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; - var arrayProp = [true, true, false, false, false ]; - for (var i = 0; i < arrayKey.size(); i++) { - var value = teslaInfo.get(arrayKey[i]); - if (value != null) { - if (arrayProp[i]) { - Properties.setValue("Tesla" + arrayKey[i], value); - } - else { - Storage.setValue("Tesla" + arrayKey[i], value); - } - teslaInfo.remove(arrayKey[i]); - } - } + pendingWebRequests.remove(type); - // Now store our updated copy of TeslaInfo - Storage.setValue("TeslaInfo", teslaInfo); - - // We deal with specific errors here, leaving the good stuff to the battery indicator - var responseCode = teslaInfo["httpErrorTesla"]; - var internalResponseCode = teslaInfo["httpInternalErrorTesla"]; - if (responseCode != null && internalResponseCode != null) { - if (responseCode == 401 && internalResponseCode != 200) { // Our token has expired and we were unable to get one, refresh it - Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID - } else if (responseCode == 404 && internalResponseCode != 200) { // We got a vehicle not found error and we were unable to get one, reset our vehicle ID - Storage.deleteValue("VehicleID"); // Try to get a new vehicleID - } + Storage.setValue("PendingWebRequests", pendingWebRequests); + Storage.setValue(type, storedData); + + // Don't do this now as it adds too much code to the background process + // checkPendingWebRequests(); // We just got new data, process them right away before displaying } - /*DEBUG*/ var nextTime = Time.now().add(new Time.Duration(5 * 60)); var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next event: " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); - Bg.registerForTemporalEvent(new Time.Duration(5 * 60)); // Since onSettingsChanged go for a specific time, go for duration here once we get going, otherwise we'll get background data only once the view is shown - + Storage.setValue("RequestsPending", true); Ui.requestUpdate(); } + // Handle data received from BackgroundService. + // data is Dictionary with single key that indicates the data type received. + // (:background) + // function onBackgroundData(data) { + // var teslaInfo = Storage.getValue("TeslaInfo"); // What we have in Storage + // if (teslaInfo == null) { + // teslaInfo = {}; + // } + + // // Update in TeslaInfo what has been received in receivedData + // var receivedData = data["TeslaInfo"]; // What we just received + // if (receivedData != null && receivedData instanceof Lang.Dictionary) { + // var keys = receivedData.keys(); + // var values = receivedData.values(); + // for (var i = 0; i < keys.size(); i++) { + // teslaInfo.put(keys[i], values[i]); + // } + // } + // else { + // /*DEBUG*/ logMessage("Unexpected invalid receivedData: " + receivedData); + // } + + // // Copy into their own name some of the entries in TeslaInfo, then delete from TeslaInfo + // var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; + // var arrayProp = [true, true, false, false, false ]; + // for (var i = 0; i < arrayKey.size(); i++) { + // var value = teslaInfo.get(arrayKey[i]); + // if (value != null) { + // if (arrayProp[i]) { + // Properties.setValue("Tesla" + arrayKey[i], value); + // } + // else { + // Storage.setValue("Tesla" + arrayKey[i], value); + // } + // teslaInfo.remove(arrayKey[i]); + // } + // } + + // // Now store our updated copy of TeslaInfo + // Storage.setValue("TeslaInfo", teslaInfo); + + // // We deal with specific errors here, leaving the good stuff to the battery indicator + // var responseCode = teslaInfo["httpErrorTesla"]; + // var internalResponseCode = teslaInfo["httpInternalErrorTesla"]; + // if (responseCode != null && internalResponseCode != null) { + // if (responseCode == 401 && internalResponseCode != 200) { // Our token has expired and we were unable to get one, refresh it + // Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID + // } else if (responseCode == 404 && internalResponseCode != 200) { // We got a vehicle not found error and we were unable to get one, reset our vehicle ID + // Storage.deleteValue("VehicleID"); // Try to get a new vehicleID + // } + // } + + // /*DEBUG*/ var nextTime = Time.now().add(new Time.Duration(5 * 60)); var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next event: " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); + // Bg.registerForTemporalEvent(new Time.Duration(5 * 60)); // Since onSettingsChanged go for a specific time, go for duration here once we get going, otherwise we'll get background data only once the view is shown + + // Ui.requestUpdate(); + // } } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index d57e1fc8..3faf820d 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -60,7 +60,7 @@ class CrystalView extends Ui.WatchFace { // Cache references to drawables immediately after layout, to avoid expensive findDrawableById() calls in onUpdate(); var mDrawables = {}; - //var mWeatherStationName; // Weather Station name removed from firmware + var mWeatherStationName; // Weather Station name removed from firmware var mLocalCityName; var mLocalCityLat; var mLocalCityLon; @@ -175,7 +175,8 @@ class CrystalView extends Ui.WatchFace { // Update hours/minutes colours after theme colours have been set. updateHoursMinutesColours(); - ReadWeather(false); + // ReadWeather(false); + checkPendingWebRequests(); // Get our 2nd local time if available var localTimeInCity = $.getStringProperty("LocalTimeInCity", ""); @@ -213,7 +214,8 @@ class CrystalView extends Ui.WatchFace { // Update hours/minutes colours after theme colours have been set. updateHoursMinutesColours(); - ReadWeather(false); + // ReadWeather(false); + checkPendingWebRequests(); // Get our 2nd local time if available var localTimeInCity = $.getStringProperty("LocalTimeInCity", ""); @@ -261,104 +263,274 @@ class CrystalView extends Ui.WatchFace { } } - // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see - function ReadWeather(fromComplication) { - var weather; - var result; - if (fromComplication) { + // Determine if any web requests are needed. + // If so, set approrpiate pendingWebRequests flag for use by BackgroundService, then register for + // temporal event. + // Currently called on layout initialisation, when settings change, and on exiting sleep. + (:background_method) + function checkPendingWebRequests() { + // Attempt to update current location, to be used by Sunrise/Sunset, and Weather. + // If current location available from current activity, save it in case it goes "stale" and can not longer be retrieved. + + var location = Activity.getActivityInfo().currentLocation; + if (location) { + location = location.toDegrees(); // Array of Doubles. + if (location[0] != 0.0 && location[1] != 0.0) { + gLocationLat = location[0]; + gLocationLng = location[1]; + Properties.setValue("LastLocationLat", gLocationLat.format("%0.5f")); + Properties.setValue("LastLocationLng", gLocationLng.format("%0.5f")); + } } - else if (Toybox has :Weather && Toybox.Weather has :getCurrentConditions) { - weather = Weather.getCurrentConditions(); - if (weather != null) { - var temperature = $.validateNumber(weather.temperature, null); // In Celcius - if (temperature == null) { - temperature = "NaN"; - } - else { - if (Sys.getDeviceSettings().temperatureUnits == System.UNIT_STATUTE) { - temperature = (temperature * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. - } + // If current location is not available, read stored value from Object Store, being careful not to overwrite a valid + // in-memory value with an invalid stored one. + else { + var lat = $.getStringProperty("LastLocationLat",""); + if (lat != null) { + gLocationLat = lat.toFloat(); + } - temperature = temperature.format(INTEGER_FORMAT) + "°"; - } + var lng = $.getStringProperty("LastLocationLng",""); + if (lng != null) { + gLocationLng = lng.toFloat(); + } + } + + if (!(Sys has :ServiceDelegate)) { + return; + } + + var pendingWebRequests = Storage.getValue("PendingWebRequests"); + if (pendingWebRequests == null) { + pendingWebRequests = {}; + } + + //// 1. City local time: + //// City has been specified. + //var city = $.getStringProperty("LocalTimeInCity",""); - var humidity = $.validateNumber(weather.relativeHumidity, null); - if (humidity == null) { - humidity = "NaN"; - } - else { - humidity = humidity.format(INTEGER_FORMAT) + "%"; + // #78 Setting with value of empty string may cause corresponding property to be null. + // if ((city != null) && (city.length() > 0)) { + + // var cityLocalTime = Storage.getValue("CityLocalTime"); + + // // No existing data. + // if ((cityLocalTime == null) || + + // // Existing data is old. + // ((cityLocalTime["next"] != null) && (Time.now().value() >= cityLocalTime["next"]["when"]))) { + + // pendingWebRequests["CityLocalTime"] = true; + + // // Existing data not for this city: delete it. + // // Error response from server: contains requestCity. Likely due to unrecognised city. Prevent requesting this + // // city again. + // } else if (!cityLocalTime["requestCity"].equals(city)) { + + // deleteProperty("CityLocalTime"); + // pendingWebRequests["CityLocalTime"] = true; + // } + // } + + // 2. Weather: + // Location must be available, weather or humidity (#113) data field must be shown. + if ((gLocationLat != null) && + (hasField(FIELD_TYPE_WEATHER) || hasField(FIELD_TYPE_HUMIDITY))) { + + var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); + if (owmKeyOverride == null || owmKeyOverride.length() == 0) { + //2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); + } else { + //2022-04-10 logMessage("Using OpenWeatherMap"); + var owmCurrent = Storage.getValue("OpenWeatherMapCurrent"); + + // No existing data. + if (owmCurrent == null) { + pendingWebRequests["OpenWeatherMapCurrent"] = true; + // Successfully received weather data. + } else if (owmCurrent["cod"] == 200) { + if (owmCurrent["NewData"] != null) { // true if we have new data, otherwise null + Storage.setValue("NewWeatherInfo", true); + owmCurrent.remove("NewData"); + Storage.setValue("OpenWeatherMapCurrent", owmCurrent); + mWeatherStationName = owmCurrent["name"]; + } + // Existing data is older than 5 mins. + // TODO: Consider requesting weather at sunrise/sunset to update weather icon. + if ((Time.now().value() > (owmCurrent["dt"] + 300)) || + true || + // Existing data not for this location. + // Not a great test, as a degree of longitude varies betwee 69 (equator) and 0 (pole) miles, but simpler than + // true distance calculation. 0.02 degree of latitude is just over a mile. + (((gLocationLat - owmCurrent["lat"]).abs() > 0.02) || ((gLocationLng - owmCurrent["lon"]).abs() > 0.02))) { + pendingWebRequests["OpenWeatherMapCurrent"] = true; + } + } else { + pendingWebRequests["OpenWeatherMapCurrent"] = true; } + } + } - // Weather Station name removed from firmware - // mWeatherStationName = $.validateString(weather.observationLocationName, null); - - var icon = "01"; - var day = "d"; - var myLocation = weather.observationLocationPosition; - var now = Time.now(); - if (myLocation != null) { - if (Toybox.Weather has :getSunrise) { - var sunrise = Weather.getSunrise(myLocation, now); - var sunset = Weather.getSunset(myLocation, now); - - if (sunrise != null and sunset != null) { - var sinceSunrise = sunrise.compare(now); - var sinceSunset = now.compare(sunset); - if (sinceSunrise >= 0 || sinceSunset >= 0) { - day = "n"; - } +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** + // 3. Tesla: + if (Storage.getValue("Tesla") != null) { + var teslaInfo = Storage.getValue("TeslaInfo"); + if (teslaInfo != null) { // We got Tesla data, process it + var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; + var arrayProp = [true, true, false, false, false ]; + for (var i = 0; i < arrayKey.size(); i++) { + var value = teslaInfo.get(arrayKey[i]); + if (value != null) { + if (arrayProp[i]) { + Properties.setValue("Tesla" + arrayKey[i], value); } - } - else { - //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); - var myLocationArray = myLocation.toDegrees(); - now = Gregorian.info(now, Time.FORMAT_SHORT); - - // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at - // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). - now = now.hour + ((now.min + 1) / 60.0); - //logMessage(now); - - // Get today's sunrise/sunset times in current time zone. - var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); - //logMessage(sunTimes); - //logMessage("now=" + now); - //logMessage("sunTimes=" + sunTimes); - // If sunrise/sunset happens today. - var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); - if (sunriseSunsetToday) { - if (now < sunTimes[0] || now > sunTimes[1]) { - day = "n"; - } + else { + Storage.setValue("Tesla" + arrayKey[i], value); } + teslaInfo.remove(arrayKey[i]); } } - var condition = $.validateNumber(weather.condition, null); - if (condition != null && condition < 53) { - icon = (mGarminToOWM[condition]).format("%02d") + day; - //logMessage("icon=" + icon); - } - else { - icon = icon + day; - /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); + // Now store our updated copy of TeslaInfo + Storage.setValue("TeslaInfo", teslaInfo); + + // We deal with specific errors here, leaving the good stuff to the battery indicator + var responseCode = teslaInfo["httpErrorTesla"]; + var internalResponseCode = teslaInfo["httpInternalErrorTesla"]; + if (responseCode != null && internalResponseCode != null) { + if (responseCode == 401 && internalResponseCode != 200) { // Our token has expired and we were unable to get one, refresh it + Properties.setValue("TeslaAccessToken", null); // Try to get a new vehicleID + } else if (responseCode == 404 && internalResponseCode != 200) { // We got a vehicle not found error and we were unable to get one, reset our vehicle ID + Storage.deleteValue("VehicleID"); // Try to get a new vehicleID + } } - result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; - /*DEBUG*/ logMessage("Weather is " + result); - } - else { - result = { "cod" => 404 }; - /*DEBUG*/ logMessage("No weather data, returning cod = 404"); + } + pendingWebRequests["TeslaInfo"] = true; } else { - result = { "cod" => 400 }; - /*DEBUG*/ logMessage("No weather data, returning cod = 400"); + pendingWebRequests.remove("TeslaInfo"); + } +//**************************************************************** +//******************** END OF REMVOVED SECTION ******************* +//**************************************************************** + + // If there are any pending requests and we can do background process + if (Toybox.System has :ServiceDelegate && pendingWebRequests.keys().size() > 0) { + // Register for background temporal event as soon as possible. + var lastTime = Bg.getLastTemporalEventTime(); + if (lastTime) { + // Events scheduled for a time in the past trigger immediately. + var nextTime = lastTime.add(new Time.Duration(5 * 60)); + Bg.registerForTemporalEvent(nextTime); + } else { + Bg.registerForTemporalEvent(Time.now()); + } } - Storage.setValue("WeatherInfo", result); - Storage.setValue("NewWeatherInfo", true); - } + + Storage.setValue("PendingWebRequests", pendingWebRequests); + } + + // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see + // function ReadWeather(fromComplication) { + // var weather; + // var result; + // if (fromComplication) { + // } + // else if (Toybox has :Weather && Toybox.Weather has :getCurrentConditions) { + // weather = Weather.getCurrentConditions(); + // if (weather != null) { + // var temperature = $.validateNumber(weather.temperature, null); // In Celcius + // if (temperature == null) { + // temperature = "NaN"; + // } + // else { + // // if (Sys.getDeviceSettings().temperatureUnits == System.UNIT_STATUTE) { + // // temperature = (temperature * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + // // } + + // // temperature = temperature.format(INTEGER_FORMAT) + "°"; + // } + + // var humidity = $.validateNumber(weather.relativeHumidity, null); + // if (humidity == null) { + // humidity = "NaN"; + // } + // else { + // humidity = humidity.format(INTEGER_FORMAT) + "%"; + // } + + // // Weather Station name removed from firmware + // // mWeatherStationName = $.validateString(weather.observationLocationName, null); + + // var icon = "01"; + // var day = "d"; + // var myLocation = weather.observationLocationPosition; + // var now = Time.now(); + // if (myLocation != null) { + // if (Toybox.Weather has :getSunrise) { + // var sunrise = Weather.getSunrise(myLocation, now); + // var sunset = Weather.getSunset(myLocation, now); + + // if (sunrise != null and sunset != null) { + // var sinceSunrise = sunrise.compare(now); + // var sinceSunset = now.compare(sunset); + // if (sinceSunrise >= 0 || sinceSunset >= 0) { + // day = "n"; + // } + // } + // } + // else { + // //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); + // var myLocationArray = myLocation.toDegrees(); + // now = Gregorian.info(now, Time.FORMAT_SHORT); + + // // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at + // // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). + // now = now.hour + ((now.min + 1) / 60.0); + // //logMessage(now); + + // // Get today's sunrise/sunset times in current time zone. + // var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); + // //logMessage(sunTimes); + // //logMessage("now=" + now); + // //logMessage("sunTimes=" + sunTimes); + // // If sunrise/sunset happens today. + // var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); + // if (sunriseSunsetToday) { + // if (now < sunTimes[0] || now > sunTimes[1]) { + // day = "n"; + // } + // } + // } + // } + + // var condition = $.validateNumber(weather.condition, null); + // if (condition != null && condition < 53) { + // icon = (mGarminToOWM[condition]).format("%02d") + day; + // //logMessage("icon=" + icon); + // } + // else { + // icon = icon + day; + // /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); + // } + // result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; + // /*DEBUG*/ logMessage("Weather is " + result); + // } + // else { + // result = { "cod" => 404 }; + // /*DEBUG*/ logMessage("No weather data, returning cod = 404"); + // } + // } + // else { + // result = { "cod" => 400 }; + // /*DEBUG*/ logMessage("No weather data, returning cod = 400"); + // } + // Storage.setValue("OpenWeatherMapCurrent", result); + // Storage.setValue("NewWeatherInfo", true); + // } function updateThemeColours() { @@ -368,7 +540,7 @@ class CrystalView extends Ui.WatchFace { var themeOverride = $.getStringProperty("ThemeOverride",""); gThemeColour = null; // Will still be null if our override is invalid - if (themeOverride.equals("") == false) { + if (themeOverride.length() > 0) { try { gThemeColour = themeOverride.toNumberWithBase(16); } @@ -496,6 +668,13 @@ class CrystalView extends Ui.WatchFace { onSettingsChangedSinceLastDraw(); } + // Do we have requests pending? + var requestsPending = Storage.getValue("RequestsPending"); + if (requestsPending != null) { + Storage.deleteValue("RequestsPending"); + checkPendingWebRequests(); + } + // Clear any partial update clipping. if (dc has :clearClip) { dc.clearClip(); @@ -717,7 +896,7 @@ class CrystalView extends Ui.WatchFace { // crash in GoalMeter.getSegmentScale(). // Sanity check. I've seen weird Invalid Value and "System Error" in DataArea.setGoalValues:48 and :61. Make sure the data is valid if (values[:isValid] && (!(values[:max] instanceof Lang.Number || values[:max] instanceof Lang.Float) || values[:max] < 1)) { - /*DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); + //DEBUG*/ logMessage("values[:max] is invalid=" + values[:max]); values[:max] = 1; values[:isValid] = false; } @@ -760,7 +939,8 @@ class CrystalView extends Ui.WatchFace { setHideSeconds(false); } - ReadWeather(false); + // ReadWeather(false); + checkPendingWebRequests(); // If watch requires burn-in protection, set flag to false when entering sleep. var settings = Sys.getDeviceSettings(); diff --git a/source/DataArea.mc b/source/DataArea.mc index 8493b8fe..5ca7d516 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -80,7 +80,7 @@ class DataArea extends Ui.Drawable { drawGoalIcon(dc, mGoalIconRightX, mRightGoalType, mRightGoalIsValid, mRightGoalstaled, Graphics.TEXT_JUSTIFY_RIGHT); var view = App.getApp().getView(); - var city = null; //view.mWeatherStationName; // Weather Station name removed from firmware + var city = view.mWeatherStationName; var linePos = [ mRowMY, mRow0Y, mRow1Y, mRow2Y ]; var linePosIndex = 0; var moveBarStyle = $.getIntProperty("MoveBarStyle", 0); @@ -90,21 +90,21 @@ class DataArea extends Ui.Drawable { } // Weather Station name removed from firmware - // var showWeatherCityName = false; - // if (view.mShowWeatherStationName && city != null && city.length() > 0) { - // showWeatherCityName = true; - // dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); - // dc.drawText( - // locX + (width / 2), - // linePos[linePosIndex], - // gNormalFont, - // // Limit string length. - // city.substring(0, 16), - // Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER - // ); - - // linePosIndex++; - // } + var showWeatherCityName = false; + if (view.mShowWeatherStationName && city != null && city.length() > 0) { + showWeatherCityName = true; + dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); + dc.drawText( + locX + (width / 2), + linePos[linePosIndex], + gNormalFont, + // Limit string length. + city.substring(0, 16), + Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER + ); + + linePosIndex++; + } // #78 Setting with value of empty string may cause corresponding property to be null. city = view.mLocalCityName; @@ -134,7 +134,7 @@ class DataArea extends Ui.Drawable { time = "INV"; } - if (/*showWeatherCityName && moveBarStyle != 3 || !showWeatherCityName &&*/ moveBarStyle == 3) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there + if (showWeatherCityName && moveBarStyle != 3 || !showWeatherCityName && moveBarStyle == 3) { // Need to do two lines since we'll overflow too much on our goals' value or use two lines if it's only us drawing there dc.setColor(gMonoDarkColour, Gfx.COLOR_TRANSPARENT); dc.drawText( locX + (width / 2), diff --git a/source/DataFields.mc b/source/DataFields.mc index e1be09ed..d6325dc8 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -463,7 +463,7 @@ class DataFields extends Ui.Drawable { } } info = ActivityMonitor.getInfo(); - if (value.equals("") == true && (info has :timeToRecovery)) { + if (value.length() == 0 && (info has :timeToRecovery)) { var recoveryTyime = info.timeToRecovery; if (recoveryTyime != null) { value = recoveryTyime.format(INTEGER_FORMAT); @@ -478,7 +478,7 @@ class DataFields extends Ui.Drawable { value = tmpValue.toString(); } } - if (value.equals("") == true && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { + if (value.length() == 0 && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) { var bodyBattery = Toybox.SensorHistory.getBodyBatteryHistory({:period=>1}); if (bodyBattery != null) { bodyBattery = bodyBattery.next(); @@ -499,7 +499,7 @@ class DataFields extends Ui.Drawable { value = tmpValue.toString(); } } - if (value.equals("") == true && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { + if (value.length() == 0 && (Toybox has :SensorHistory) && (Toybox.SensorHistory has :getStressHistory)) { var stressLevel = Toybox.SensorHistory.getStressHistory({:period=>1}); if (stressLevel != null) { stressLevel = stressLevel.next(); @@ -541,7 +541,7 @@ class DataFields extends Ui.Drawable { value = tmpValue.toString() + "%"; } } - if (value.equals("") == true) { + if (value.length() == 0) { activityInfo = Activity.getActivityInfo(); sample = activityInfo != null and activityInfo has :currentOxygenSaturation ? activityInfo.currentOxygenSaturation : null; if (sample != null) { @@ -559,7 +559,7 @@ class DataFields extends Ui.Drawable { // Yes, no break. We flow through in case with don't have Complication. FIELD_TYPE_HEART_RATE and FIELD_TYPE_HR_LIVE_5S were doing the same thing case FIELD_TYPE_HR_LIVE_5S: // #34 Try to retrieve live HR from Activity::Info, before falling back to historical HR from ActivityMonitor. - if (value.equals("") == true) { + if (value.length() == 0) { activityInfo = Activity.getActivityInfo(); sample = activityInfo.currentHeartRate; if (sample != null) { @@ -810,8 +810,8 @@ class DataFields extends Ui.Drawable { // Only read that dictionnary from Storage if it has changed (or we don't have a local copy), otherwise read our stored weather data if (mWeather == null || Storage.getValue("NewWeatherInfo") != null) { - mWeather = Storage.getValue("WeatherInfo"); - Storage.setValue("NewWeatherInfo", null); + mWeather = Storage.getValue("OpenWeatherMapCurrent"); + Storage.deleteValue("NewWeatherInfo"); } // Stored weather data available. @@ -819,6 +819,17 @@ class DataFields extends Ui.Drawable { // FIELD_TYPE_WEATHER. if (type == FIELD_TYPE_WEATHER) { value = mWeather["temp"]; + try { + if (settings.temperatureUnits == System.UNIT_STATUTE) { + value = (value * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. + } + + value = value.format(INTEGER_FORMAT) + "°"; + } + catch (e) { + /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); + value = "???"; + } result["weatherIcon"] = mWeather["icon"]; // FIELD_TYPE_HUMIDITY. From 8e929b6f7200a004d728b28482103bc1a56a0c4c Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 4 Dec 2024 00:40:35 -0500 Subject: [PATCH 199/220] Previous code was working on the simulator but not a real device :-< --- README.md | 3 + manifest.xml | 2 +- resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 384 ++++++++++++++-------------------- source/CrystalApp.mc | 1 + source/CrystalView.mc | 237 +++++++++------------ source/DataFields.mc | 1 + 7 files changed, 272 insertions(+), 358 deletions(-) diff --git a/README.md b/README.md index e6a75577..1b081d9a 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,9 @@ Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. ## Below is what has been added by me (SylvainGa). +### 2.21.0 +- Added back OpenWeatherMap as a weather service + ### 2.20.0 - Compiled with CIQ 7.3.1 - Added recovery time as an option to the move bar. Once it's cleared, recovery is done. diff --git a/manifest.xml b/manifest.xml index 870ccddc..b1a629ef 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 3e819802..99a18062 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.20.0b7 + Crystal-Tesla V2.21.0.b9 Theme Hours Colour diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index c928fa86..82aac272 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -12,22 +12,14 @@ class BackgroundService extends Sys.ServiceDelegate { var _token; var _vehicle_id; - var _step; + var _stop; var _bg_data; + var _pendingWebRequests; (:background) function initialize() { - //DEBUG*/ logMessage("In ServiceDelegate"); + /*DEBUG*/ logMessage("In ServiceDelegate"); Sys.ServiceDelegate.initialize(); - _step = 0; - -//**************************************************************** -//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** -//**************************************************************** - if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { - /*DEBUG*/ logMessage("returning because Storage.getValue(\"Tesla\") is " + Storage.getValue("Tesla") + " or gTeslaComplication is " + gTeslaComplication); - return; - } if (_bg_data == null) { _bg_data = Bg.getBackgroundData(); @@ -36,20 +28,23 @@ class BackgroundService extends Sys.ServiceDelegate { } } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("initialize: _bg_data has keys " + keys); } - var timeNow = Time.now().value(); - var createdAt; - var expiresIn; + _stop = false; + +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** + if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { + /*DEBUG*/ logMessage("returning because Storage.getValue(\"Tesla\") is " + Storage.getValue("Tesla") + " or gTeslaComplication is " + gTeslaComplication); + return; + } // Get the unexpired token from the buffer if we have one, otherwise from Properties/Storage var teslaInfo = _bg_data.get("TeslaInfo"); if (teslaInfo != null) { _token = teslaInfo.get("AccessToken"); - createdAt = teslaInfo.get("TokenCreatedAt"); - expiresIn = teslaInfo.get("TokenExpiresIn"); - _vehicle_id = teslaInfo.get("VehicleID"); } @@ -57,35 +52,11 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = Storage.getValue("TeslaVehicleID"); } - if (_token != null && createdAt != null && expiresIn != null) { - if (timeNow > createdAt + expiresIn) { - _token = null; - } - } - else { - _token = null; - } - if (_token == null) { - _token = $.getStringProperty("TeslaAccessToken",""); - createdAt = Storage.getValue("TeslaTokenCreatedAt"); - expiresIn = Storage.getValue("TeslaTokenExpiresIn"); + _token = $.getStringProperty("TeslaAccessToken", null); } - if (_token != null && createdAt != null && expiresIn != null) { - if (timeNow > createdAt + expiresIn) { - _token = null; - } - } - else { - _token = null; - } - - if (_token != null && _token.length() > 0) { - //DEBUG*/ var expireAt = new Time.Moment(createdAt + expiresIn); var clockTime = Gregorian.info(expireAt, Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); logMessage("initialize:Using token '" + _token.substring(0,10) + "...' which expires at " + dateStr); - _token = "Bearer " + _token; - } - else { + if (_token != null && _token.length() == 0) { _token = null; } @@ -99,118 +70,62 @@ class BackgroundService extends Sys.ServiceDelegate { // Pending web request flag will be cleared only once the background data has been successfully received. (:background) function onTemporalEvent() { - var pendingWebRequests = Storage.getValue("PendingWebRequests"); - /*DEBUG*/ logMessage("onTemporalEvent:PendingWebRequests is '" + pendingWebRequests + "' and step is " + _step); - /*DEBUG*/ logMessage("onTemporalEvent:_bg_data is '" + _bg_data); - - if (pendingWebRequests != null) { - - // // 1. City local time. - // if (pendingWebRequests["CityLocalTime"] != null) { - // makeWebRequest( - // "https://script.google.com/macros/s/AKfycbwPas8x0JMVWRhLaraJSJUcTkdznRifXPDovVZh8mviaf8cTw/exec", - // { - // "city" => $.getStringProperty("LocalTimeInCity","") - // }, - // method(:onReceiveCityLocalTime) - // ); - - // } - - // 2. Weather. - if (_step == 0) { - if (pendingWebRequests["OpenWeatherMapCurrent"] != null) { - var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); - var lat = $.getStringProperty("LastLocationLat",""); - var lon = $.getStringProperty("LastLocationLng",""); - /*DEBUG*/ logMessage("onTemporalEvent:OWM with overide=" + owmKeyOverride + " lat=" + lat + " lon=" + lon); - - if (lat.length() > 0 && lon.length() > 0) { - makeWebRequest( - "https://api.openweathermap.org/data/2.5/weather", - // "https://api.openweathermap.org/data/3.0/onecall", - { - "lat" => lat, - "lon" => lon, - - // Polite request from Vince, developer of the Crystal Watch Face: - // - // Please do not abuse this API key, or else I will be forced to make thousands of users of Crystal - // sign up for their own Open Weather Map free account, and enter their key in settings - a much worse - // user experience for everyone. - // - // Crystal has been registered with OWM on the Open Source Plan, which lifts usage limits for free, so - // that everyone benefits. However, these lifted limits only apply to the Current Weather API, and *not* - // the One Call API. Usage of this key for the One Call API risks blocking the key for everyone. - // - // If you intend to use this key in your own app, especially for the One Call API, please create your own - // OWM account, and own key. You should be able to apply for the Open Source Plan to benefit from the same - // lifted limits as Crystal. Thank you. - "appid" => ((owmKeyOverride == null) || (owmKeyOverride.length() == 0)) ? "2651f49cb20de925fc57590709b86ce6" : owmKeyOverride, - - "units" => "metric" // Celcius. - }, - method(:onReceiveOpenWeatherMapCurrent) - ); - } - } - else { - _step++; + _pendingWebRequests = Storage.getValue("PendingWebRequests"); + + /*DEBUG*/ logMessage("onTemporalEvent:_pendingWebRequests is '" + _pendingWebRequests + "'"); + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onTemporalEvent:_bg_data has '" + keys); + /*DEBUG*/ if (_token != null) { logMessage("onTemporalEvent:Using token '" + _token.substring(0,20) + "...'"); } else { logMessage("onTemporalEvent:No token");} + + if (_pendingWebRequests != null) { + if (_pendingWebRequests["OpenWeatherMapCurrent"] != null) { + var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); + var lat = $.getStringProperty("LastLocationLat",""); + var lon = $.getStringProperty("LastLocationLng",""); + /*DEBUG*/ logMessage("onTemporalEvent:OWM with overide=" + owmKeyOverride + " lat=" + lat + " lon=" + lon); + + if (lat.length() > 0 && lon.length() > 0) { + makeWebRequest( + "https://api.openweathermap.org/data/2.5/weather", +// "https://api.openweathermap.org/data/3.0/onecall", + { + "lat" => lat, + "lon" => lon, + + // Polite request from Vince, developer of the Crystal Watch Face: + // + // Please do not abuse this API key, or else I will be forced to make thousands of users of Crystal + // sign up for their own Open Weather Map free account, and enter their key in settings - a much worse + // user experience for everyone. + // + // Crystal has been registered with OWM on the Open Source Plan, which lifts usage limits for free, so + // that everyone benefits. However, these lifted limits only apply to the Current Weather API, and *not* + // the One Call API. Usage of this key for the One Call API risks blocking the key for everyone. + // + // If you intend to use this key in your own app, especially for the One Call API, please create your own + // OWM account, and own key. You should be able to apply for the Open Source Plan to benefit from the same + // lifted limits as Crystal. Thank you. + "appid" => ((owmKeyOverride == null) || (owmKeyOverride.length() == 0)) ? "2651f49cb20de925fc57590709b86ce6" : owmKeyOverride, + + "units" => "metric" // Celcius. + }, + method(:onReceiveOpenWeatherMapCurrent) + ); } - } - //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - // 3. Tesla - else if (_step == 1) { - if (pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null) { - if (!Sys.getDeviceSettings().phoneConnected) { - return; - } - - // if (_vehicle_id) { - // makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id.toString() + "/vehicle_data", null, method(:onReceiveVehicleData)); - // } - - if (_token == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Generating Access Token"); - var refreshToken = $.getStringProperty("TeslaRefreshToken",""); - if (refreshToken != null && refreshToken.length() > 0) { - //DEBUG*/ logMessage("onTemporalEvent:Refresh Token is " + refreshToken); - makeWebPost(refreshToken, method(:onReceiveToken)); - } else { - /*DEBUG*/ logMessage("onTemporalEvent:No refresh token!"); - _bg_data.put({ "TeslaInfo" => { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } }); - //DEBUG*/ _bg_data.put({ "TeslaInfo" => { "httpErrorTesla" => 200, "httpInternalErrorTesla" => 200, "BatteryLevel" => 70, "ChargingState" => "Charging", "InsideTemp" => 21, "PrecondEnabled" => false, "SentryEnabled" => false, "VehicleID" => "12345678" , "VehicleState" => "online"} }); - /*DEBUG*/ logMessage("onTemporalEvent: Exiting with " + _bg_data); - Bg.exit(_bg_data); - } - return; - } - - if (_vehicle_id == null) { - /*DEBUG*/ logMessage("onTemporalEvent:Getting vehicles"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); - return; - } - - //DEBUG*/ logMessage("onTemporalEvent: Getting vehicle data"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", Comms.HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN, method(:onReceiveVehicleData)); - } else { - _step++; + doTesla(); } } - else { // Done, send data! - /*DEBUG*/ logMessage("onTemporalEvent: Exiting with " + _bg_data); - Bg.exit(_bg_data); + else { + doTesla(); } - //**************************************************************** //******************** END OF REMVOVED SECTION ******************* //**************************************************************** - } else { + } + else { /*DEBUG*/ logMessage("onTemporalEvent() called with no pending web requests!"); } } @@ -254,26 +169,67 @@ class BackgroundService extends Sys.ServiceDelegate { _bg_data.put("OpenWeatherMapCurrent", result); /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: result=" + result); +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** + doTesla(); // Call back so we get the next steps done right now +//**************************************************************** +//******** DO THIS INSTEAD ******** +//**************************************************************** + // try { + // /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); + // Bg.exit(_bg_data); + // } + // catch (e) { + // /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); + // } - _step++; // We've processed Tesla data, do next one - if (_step < 2) { - onTemporalEvent(); // Call back so we get the next steps done right now - } - else { - // Last queue element, exit background process - try { - /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: Exiting with " + _bg_data); - Bg.exit(_bg_data); + } + +//**************************************************************** +//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//**************************************************************** + (:background) + function doTesla() + { + if (_pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null) { + if (_token == null) { + /*DEBUG*/ logMessage("doTesla:Generating Access Token"); + var refreshToken = $.getStringProperty("TeslaRefreshToken",""); + if (refreshToken != null && refreshToken.length() > 0) { + /*DEBUG*/ logMessage("doTesla:Get new Access token with Refresh token at '" + refreshToken.substring(0, 20) + "'..."); + makeTeslaWebPost(refreshToken, method(:onReceiveToken)); + return; + } else { + /*DEBUG*/ logMessage("doTesla:No refresh token!"); + _bg_data.put("TeslaInfo", { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } ); + //DEBUG*/ _bg_data.put({ "TeslaInfo" => { "httpErrorTesla" => 200, "httpInternalErrorTesla" => 200, "BatteryLevel" => 70, "ChargingState" => "Charging", "InsideTemp" => 21, "PrecondEnabled" => false, "SentryEnabled" => false, "VehicleID" => "12345678" , "VehicleState" => "online"} }); + } } - catch (e) { - /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent exit assertion " + e); + else if (_vehicle_id == null) { + /*DEBUG*/ logMessage("doTesla:Getting vehicles"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); + return; + } + else { + //DEBUG*/ logMessage("doTesla: Getting vehicle data"); + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/vehicles/" + _vehicle_id + "/vehicle_data", Comms.HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN, method(:onReceiveVehicleData)); + return; } } - } + try { + /*DEBUG*/ logMessage("doTesla: Exiting with " + _bg_data); + Bg.exit(_bg_data); + } + catch (e) { + /*DEBUG*/ logMessage("doTesla exit assertion " + e); + } + } //**************************************************************** -//******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** +//******************** END OF REMVOVED SECTION ******************* //**************************************************************** + (:background) function onReceiveToken(responseCode, responseData) { /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); @@ -285,7 +241,7 @@ class BackgroundService extends Sys.ServiceDelegate { } } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveToken: Buffer has keys " + keys); + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveToken: _bg_data has keys " + keys); } var teslaInfo = _bg_data.get("TeslaInfo"); @@ -294,33 +250,24 @@ class BackgroundService extends Sys.ServiceDelegate { } if (responseCode == 200) { - teslaInfo.put("AccessToken", responseData["access_token"]); + _token = responseData["access_token"]; + /*DEBUG*/ logMessage("onReceiveToken:Has token '" + _token.substring(0,20) + "...', calling back doTesla"); + teslaInfo.put("AccessToken", _token); teslaInfo.put("RefreshToken", responseData["refresh_token"]); teslaInfo.put("TokenExpiresIn", responseData["expires_in"]); teslaInfo.put("TokenCreatedAt", Time.now().value()); _bg_data.put("TeslaInfo", teslaInfo); - onTemporalEvent(); // Call back so we get the next steps done right now - return; + doTesla(); } - - teslaInfo.put("httpErrorTesla", 401); - teslaInfo.put("httpInternalErrorTesla", responseCode); - - _bg_data.put("TeslaInfo", teslaInfo); - - _step++; // We've processed Tesla data and got an error, skip continuing Tesla and move to the next one - if (_step < 2) { - onTemporalEvent(); // Call back so we get the next steps done right now - } else { - // Last queue element, exit background process + _bg_data.put("TeslaInfo", { "httpErrorTesla" => 401, "httpInternalErrorTesla" => responseCode } ); try { - /*DEBUG*/ logMessage("onReceiveToken: Exiting with " + _bg_data); + /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); Bg.exit(_bg_data); } catch (e) { - /*DEBUG*/ logMessage("onReceiveToken exit assertion " + e); + /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); } } } @@ -336,10 +283,9 @@ class BackgroundService extends Sys.ServiceDelegate { } } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicles: Buffer has keys " + keys); + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicles: _bg_data has keys " + keys); } - var teslaInfo = _bg_data.get("TeslaInfo"); if (teslaInfo == null) { teslaInfo = {}; @@ -365,7 +311,8 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = null; vehice_state = "VehicleNotFound"; } - } else { + } + else { _vehicle_id = null; vehice_state = "NoVehicles"; } @@ -378,29 +325,23 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("VehicleState",vehice_state); _bg_data.put("TeslaInfo", teslaInfo); - _step++; - onTemporalEvent(); // Call back so we get the next steps done right now - return; - } - teslaInfo.put("httpErrorTesla", (_vehicle_id == null ? 404 : 408)); - teslaInfo.put("httpInternalErrorTesla", responseCode); + /*DEBUG*/ logMessage("onReceiveVehicles:vehice_state=" + vehice_state); - _bg_data.put("TeslaInfo", teslaInfo); + if (_vehicle_id != null) { + doTesla(); + return; + } + } - _step++; // We've processed Tesla data, do next one - if (_step < 2) { - onTemporalEvent(); // Call back so we get the next steps done right now + _bg_data.put("TeslaInfo", { "httpErrorTesla" => (_vehicle_id == null ? 404 : 408), "httpInternalErrorTesla" => responseCode } ); + + try { + /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); + Bg.exit(_bg_data); } - else { - // Last queue element, exit background process - try { - /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); - Bg.exit(_bg_data); - } - catch (e) { - /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); - } + catch (e) { + /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); } } @@ -415,7 +356,7 @@ class BackgroundService extends Sys.ServiceDelegate { _bg_data = {}; } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicleData: Buffer has keys " + keys); + /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicleData: _bg_data has keys " + keys); } } @@ -456,51 +397,50 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("PrecondEnabled", $.validateString(str.substring(0, posEnd), "").equals("true")); _bg_data.put("TeslaInfo", teslaInfo); - _step++; - onTemporalEvent(); // Call back so we get the next steps done right now - return; } // If no vehicle (rare) or can't contact (much more frequent) is received, try to get a new vehicle (404) or retrieve its state (408) else if (responseCode == 404 || responseCode == 408) { // If Tesla can't find our vehicle by its ID, reset it and maybe we'll have better luck next time if (responseCode == 404) { - teslaInfo.put("VehicleID", null); _vehicle_id = null; + _bg_data.put("TeslaInfo", { "httpErrorTesla" => 404, "httpInternalErrorTesla" => responseCode, "VehicleID" => null } ); + } + /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData with _stop at " + _stop); + if (_stop == false) { // We we're true, we already came back here for the next lines so don't get into an infinite loop + _stop = true; // Don't get vehicle_data anymore if we fail again + makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); + return; } - /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData"); - makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); - return; } // Our access token has expired, ask for a new one else if (responseCode == 401) { var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { - /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData"); - makeWebPost(refreshToken, method(:onReceiveToken)); - return; + /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData with _stop at " + _stop); + if (_stop == false) { // We we're true, we already came back here for the next lines so don't get into an infinite loop + _stop = true; // Don't get vehicle_data anymore if we fail again + makeTeslaWebPost(refreshToken, method(:onReceiveToken)); + return; + } + else { + _bg_data.put("TeslaInfo", { "httpErrorTesla" => 401, "httpInternalErrorTesla" => responseCode } ); + } } } _bg_data.put("TeslaInfo", teslaInfo); - _step++; // We've processed Tesla data, do next one - if (_step < 2) { - onTemporalEvent(); // Call back so we get the next steps done right now + try { + /*DEBUG*/ logMessage("onReceiveVehicleData: Exiting with " + _bg_data); + Bg.exit(_bg_data); } - else { - // Last queue element, exit background process - try { - /*DEBUG*/ logMessage("onReceiveVehicleData: Exiting with " + _bg_data); - Bg.exit(_bg_data); - } - catch (e) { - /*DEBUG*/ logMessage("onReceiveVehicleData exit assertion " + e); - } + catch (e) { + /*DEBUG*/ logMessage("onReceiveVehicleData exit assertion " + e); } } (:background) - function makeWebPost(token, notify) { + function makeTeslaWebPost(token, notify) { var url = "https://" + $.getStringProperty("TeslaServerAUTHLocation","") + "/oauth2/v3/token"; Comms.makeWebRequest( url, @@ -523,7 +463,7 @@ class BackgroundService extends Sys.ServiceDelegate { var options = { :method => Comms.HTTP_REQUEST_METHOD_GET, :headers => { - "Authorization" => _token, + "Authorization" => "Bearer " + _token, "User-Agent" => "Crystal-Tesla for Garmin", }, :responseType => method diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index be24e3a1..bede47b4 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -127,6 +127,7 @@ class CrystalApp extends App.AppBase { // checkPendingWebRequests(); // We just got new data, process them right away before displaying } + /*DEBUG*/ logMessage("onBackgroundData:Flag requests are pending"); Storage.setValue("RequestsPending", true); Ui.requestUpdate(); } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 3faf820d..dec388b5 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -175,7 +175,7 @@ class CrystalView extends Ui.WatchFace { // Update hours/minutes colours after theme colours have been set. updateHoursMinutesColours(); - // ReadWeather(false); + ReadWeather(false); checkPendingWebRequests(); // Get our 2nd local time if available @@ -214,7 +214,7 @@ class CrystalView extends Ui.WatchFace { // Update hours/minutes colours after theme colours have been set. updateHoursMinutesColours(); - // ReadWeather(false); + ReadWeather(false); checkPendingWebRequests(); // Get our 2nd local time if available @@ -304,46 +304,19 @@ class CrystalView extends Ui.WatchFace { if (pendingWebRequests == null) { pendingWebRequests = {}; } - - //// 1. City local time: - //// City has been specified. - //var city = $.getStringProperty("LocalTimeInCity",""); - - // #78 Setting with value of empty string may cause corresponding property to be null. - // if ((city != null) && (city.length() > 0)) { - - // var cityLocalTime = Storage.getValue("CityLocalTime"); - - // // No existing data. - // if ((cityLocalTime == null) || - - // // Existing data is old. - // ((cityLocalTime["next"] != null) && (Time.now().value() >= cityLocalTime["next"]["when"]))) { - - // pendingWebRequests["CityLocalTime"] = true; - - // // Existing data not for this city: delete it. - // // Error response from server: contains requestCity. Likely due to unrecognised city. Prevent requesting this - // // city again. - // } else if (!cityLocalTime["requestCity"].equals(city)) { - - // deleteProperty("CityLocalTime"); - // pendingWebRequests["CityLocalTime"] = true; - // } - // } - - // 2. Weather: + /*DEBUG*/ logMessage("checkPendingWebRequests: pendingWebRequest=" + pendingWebRequests); + // 1. Weather: // Location must be available, weather or humidity (#113) data field must be shown. if ((gLocationLat != null) && (hasField(FIELD_TYPE_WEATHER) || hasField(FIELD_TYPE_HUMIDITY))) { var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { - //2022-04-10 logMessage("Using Garmin Weather so skipping OWM code"); + /*DEBUG*/ logMessage("checkPendingWebRequests:Using Garmin Weather so skipping OWM code"); } else { //2022-04-10 logMessage("Using OpenWeatherMap"); var owmCurrent = Storage.getValue("OpenWeatherMapCurrent"); - + /*DEBUG*/ logMessage("checkPendingWebRequests:owmCurrent=" + owmCurrent); // No existing data. if (owmCurrent == null) { pendingWebRequests["OpenWeatherMapCurrent"] = true; @@ -358,7 +331,7 @@ class CrystalView extends Ui.WatchFace { // Existing data is older than 5 mins. // TODO: Consider requesting weather at sunrise/sunset to update weather icon. if ((Time.now().value() > (owmCurrent["dt"] + 300)) || - true || + true || //TODO Remove // Existing data not for this location. // Not a great test, as a degree of longitude varies betwee 69 (equator) and 0 (pole) miles, but simpler than // true distance calculation. 0.02 degree of latitude is just over a mile. @@ -374,9 +347,10 @@ class CrystalView extends Ui.WatchFace { //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** - // 3. Tesla: + // 2. Tesla: if (Storage.getValue("Tesla") != null) { var teslaInfo = Storage.getValue("TeslaInfo"); + /*DEBUG*/ logMessage("checkPendingWebRequests:teslaInfo=" + teslaInfo); if (teslaInfo != null) { // We got Tesla data, process it var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; var arrayProp = [true, true, false, false, false ]; @@ -434,103 +408,98 @@ class CrystalView extends Ui.WatchFace { } // Read the weather from the Garmin API and store it into the same format OpenWeatherMap expects to see - // function ReadWeather(fromComplication) { - // var weather; - // var result; - // if (fromComplication) { - // } - // else if (Toybox has :Weather && Toybox.Weather has :getCurrentConditions) { - // weather = Weather.getCurrentConditions(); - // if (weather != null) { - // var temperature = $.validateNumber(weather.temperature, null); // In Celcius - // if (temperature == null) { - // temperature = "NaN"; - // } - // else { - // // if (Sys.getDeviceSettings().temperatureUnits == System.UNIT_STATUTE) { - // // temperature = (temperature * (9.0 / 5)) + 32; // Convert to Farenheit: ensure floating point division. - // // } - - // // temperature = temperature.format(INTEGER_FORMAT) + "°"; - // } + function ReadWeather(fromComplication) { + var weather; + var result; + if (fromComplication) { + } + else if (Toybox has :Weather && Toybox.Weather has :getCurrentConditions) { + var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); + if (owmKeyOverride != null && owmKeyOverride.length() > 0) { + return; // We have an OWM API key, this means we're going to use OWM and not Garmin weather, so skip function. + } + + weather = Weather.getCurrentConditions(); + if (weather != null) { + var temperature = $.validateNumber(weather.temperature, null); // In Celcius + if (temperature == null) { + temperature = "NaN"; + } - // var humidity = $.validateNumber(weather.relativeHumidity, null); - // if (humidity == null) { - // humidity = "NaN"; - // } - // else { - // humidity = humidity.format(INTEGER_FORMAT) + "%"; - // } - - // // Weather Station name removed from firmware - // // mWeatherStationName = $.validateString(weather.observationLocationName, null); - - // var icon = "01"; - // var day = "d"; - // var myLocation = weather.observationLocationPosition; - // var now = Time.now(); - // if (myLocation != null) { - // if (Toybox.Weather has :getSunrise) { - // var sunrise = Weather.getSunrise(myLocation, now); - // var sunset = Weather.getSunset(myLocation, now); - - // if (sunrise != null and sunset != null) { - // var sinceSunrise = sunrise.compare(now); - // var sinceSunset = now.compare(sunset); - // if (sinceSunrise >= 0 || sinceSunset >= 0) { - // day = "n"; - // } - // } - // } - // else { - // //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); - // var myLocationArray = myLocation.toDegrees(); - // now = Gregorian.info(now, Time.FORMAT_SHORT); - - // // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at - // // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). - // now = now.hour + ((now.min + 1) / 60.0); - // //logMessage(now); - - // // Get today's sunrise/sunset times in current time zone. - // var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); - // //logMessage(sunTimes); - // //logMessage("now=" + now); - // //logMessage("sunTimes=" + sunTimes); - // // If sunrise/sunset happens today. - // var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); - // if (sunriseSunsetToday) { - // if (now < sunTimes[0] || now > sunTimes[1]) { - // day = "n"; - // } - // } - // } - // } - - // var condition = $.validateNumber(weather.condition, null); - // if (condition != null && condition < 53) { - // icon = (mGarminToOWM[condition]).format("%02d") + day; - // //logMessage("icon=" + icon); - // } - // else { - // icon = icon + day; - // /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); - // } - // result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; - // /*DEBUG*/ logMessage("Weather is " + result); - // } - // else { - // result = { "cod" => 404 }; - // /*DEBUG*/ logMessage("No weather data, returning cod = 404"); - // } - // } - // else { - // result = { "cod" => 400 }; - // /*DEBUG*/ logMessage("No weather data, returning cod = 400"); - // } - // Storage.setValue("OpenWeatherMapCurrent", result); - // Storage.setValue("NewWeatherInfo", true); - // } + var humidity = $.validateNumber(weather.relativeHumidity, null); + if (humidity == null) { + humidity = "NaN"; + } + + // Weather Station name removed from firmware + // mWeatherStationName = $.validateString(weather.observationLocationName, null); + + var icon = "01"; + var day = "d"; + var myLocation = weather.observationLocationPosition; + var now = Time.now(); + if (myLocation != null) { + if (Toybox.Weather has :getSunrise) { + var sunrise = Weather.getSunrise(myLocation, now); + var sunset = Weather.getSunset(myLocation, now); + + if (sunrise != null and sunset != null) { + var sinceSunrise = sunrise.compare(now); + var sinceSunset = now.compare(sunset); + if (sinceSunrise >= 0 || sinceSunset >= 0) { + day = "n"; + } + } + } + else { + //logMessage("Sucks, We DON'T have sunrise and sunset routines, do it the old way then"); + var myLocationArray = myLocation.toDegrees(); + now = Gregorian.info(now, Time.FORMAT_SHORT); + + // Convert to same format as sunTimes, for easier comparison. Add a minute, so that e.g. if sun rises at + // 07:38:17, then 07:38 is already consided daytime (seconds not shown to user). + now = now.hour + ((now.min + 1) / 60.0); + //logMessage(now); + + // Get today's sunrise/sunset times in current time zone. + var sunTimes = getSunTimes(myLocationArray[0], myLocationArray[1], null, /* tomorrow */ false); + //logMessage(sunTimes); + //logMessage("now=" + now); + //logMessage("sunTimes=" + sunTimes); + // If sunrise/sunset happens today. + var sunriseSunsetToday = ((sunTimes[0] != null) && (sunTimes[1] != null)); + if (sunriseSunsetToday) { + if (now < sunTimes[0] || now > sunTimes[1]) { + day = "n"; + } + } + } + } + + var condition = $.validateNumber(weather.condition, null); + if (condition != null && condition < 53) { + icon = (mGarminToOWM[condition]).format("%02d") + day; + //logMessage("icon=" + icon); + } + else { + icon = icon + day; + /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); + } + result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; + /*DEBUG*/ logMessage("Weather is " + result); + } + else { + result = { "cod" => 404 }; + /*DEBUG*/ logMessage("No weather data, returning cod = 404"); + } + } + else { + result = { "cod" => 400 }; + /*DEBUG*/ logMessage("No weather data, returning cod = 400"); + } + Storage.setValue("OpenWeatherMapCurrent", result); + Storage.setValue("NewWeatherInfo", true); + } function updateThemeColours() { @@ -671,6 +640,7 @@ class CrystalView extends Ui.WatchFace { // Do we have requests pending? var requestsPending = Storage.getValue("RequestsPending"); if (requestsPending != null) { + /*DEBUG*/ logMessage("onUpdate:Requests are pending"); Storage.deleteValue("RequestsPending"); checkPendingWebRequests(); } @@ -930,8 +900,6 @@ class CrystalView extends Ui.WatchFace { function onExitSleep() { mIsSleeping = false; - //Sys.println("onExitSleep()"); - // If watch does not support per-second updates, AND HideSeconds property is false, // show seconds, and make move bar original width. var hideSeconds = $.getIntProperty("HideSeconds", 0); @@ -939,7 +907,8 @@ class CrystalView extends Ui.WatchFace { setHideSeconds(false); } - // ReadWeather(false); + ReadWeather(false); + /*DEBUG*/ logMessage("onExitSleep:Checking pending requests"); checkPendingWebRequests(); // If watch requires burn-in protection, set flag to false when entering sleep. diff --git a/source/DataFields.mc b/source/DataFields.mc index d6325dc8..c9ce682a 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -835,6 +835,7 @@ class DataFields extends Ui.Drawable { // FIELD_TYPE_HUMIDITY. } else { value = mWeather["humidity"]; + value = value.format(INTEGER_FORMAT) + "%"; } } // Didn't receive weather from Garmin From d3d384b2955bb28fa850970f91b7cd2fa7c70a6d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 14 Dec 2024 15:34:40 -0500 Subject: [PATCH 200/220] Show 200 for httpInternalErrorTesla when all is fine --- source/BackgroundService.mc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 82aac272..46a11135 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -368,7 +368,7 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("httpErrorTesla", responseCode); if (responseCode == 200) { - teslaInfo.remove("httpInternalErrorTesla"); + teslaInfo.put("httpInternalErrorTesla", 200); teslaInfo.put("VehicleState", "online"); var pos = responseData.find("battery_level"); @@ -427,6 +427,9 @@ class BackgroundService extends Sys.ServiceDelegate { } } } + else { + _bg_data.put("TeslaInfo", { "httpErrorTesla" => responseCode, "httpInternalErrorTesla" => responseCode } ); + } _bg_data.put("TeslaInfo", teslaInfo); From 53e0dde0a36c6d5af7ba5c557f9e613298d25cee Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 15 Dec 2024 23:49:05 -0500 Subject: [PATCH 201/220] No changes but compiled with CIQ 7.4.3 --- README.md | 1 + resources/strings/strings.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b081d9a..f6ed8245 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.21.0 +- Compiled with CIQ 7.4.3 - Added back OpenWeatherMap as a weather service ### 2.20.0 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 99a18062..c132a975 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.21.0.b9 + Crystal-Tesla V2.21.0.b10 Theme Hours Colour From 75c5fe7bcc96f8c6b134f62d54d03e766142516d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sun, 15 Dec 2024 23:49:29 -0500 Subject: [PATCH 202/220] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f6ed8245..9f57e1d3 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Reviews: ### 2.21.0 - Compiled with CIQ 7.4.3 - Added back OpenWeatherMap as a weather service +- Readded Fenix 8 and E ### 2.20.0 - Compiled with CIQ 7.3.1 From 703d4cffaf5521de7ef1d38532218b1606633cf5 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:33:10 -0500 Subject: [PATCH 203/220] Duplicated 2.20.2 changes --- source/DataFields.mc | 3 ++- source/MoveBar.mc | 56 +++++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/source/DataFields.mc b/source/DataFields.mc index c9ce682a..26f8d9da 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -463,7 +463,8 @@ class DataFields extends Ui.Drawable { } } info = ActivityMonitor.getInfo(); - if (value.length() == 0 && (info has :timeToRecovery)) { + var t = (info has :timeToRecovery); + if (value.length() == 0 && && t == true) { var recoveryTyime = info.timeToRecovery; if (recoveryTyime != null) { value = recoveryTyime.format(INTEGER_FORMAT); diff --git a/source/MoveBar.mc b/source/MoveBar.mc index 4d3a91c5..205a02bf 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -96,42 +96,50 @@ class MoveBar extends Ui.Drawable { } } - if (value == null) { + var t = (info has :timeToRecovery); + if (value == null && t == true) { value = info.timeToRecovery; // Info time to recovery is in hours } - //value = 12; - currentMoveBarLevel = ((value == null || value < 0) ? 0 : value) / 12; // Each bar (up to 5 bars) is 12 hours - if (value > 0) { - currentMoveBarLevel++; // So only when the recovery time is zero does it display no move bars. + if (value != null) { + //value = 12; + currentMoveBarLevel = ((value == null || value < 0) ? 0 : value) / 12; // Each bar (up to 5 bars) is 12 hours + if (value > 0) { + currentMoveBarLevel++; // So only when the recovery time is zero does it display no move bars. + } + if (currentMoveBarLevel > 5) { + currentMoveBarLevel = 5; + } + // 0 Move bar : Times up! + // 1 Move bar : Between 1 and 11 hours + // 2 Move bar : Between 12 and 23 hours + // 3 Move bar : Between 24 and 35 hours + // 4 Move bar : Between 36 and 47 hours + // 5 Move bar : 48 and more hours } - if (currentMoveBarLevel > 5) { - currentMoveBarLevel = 5; + else { + currentMoveBarLevel = null; } - // 0 Move bar : Times up! - // 1 Move bar : Between 1 and 11 hours - // 2 Move bar : Between 12 and 23 hours - // 3 Move bar : Between 24 and 35 hours - // 4 Move bar : Between 36 and 47 hours - // 5 Move bar : 48 and more hours } else { currentMoveBarLevel = info.moveBarLevel; } - // Calculate current width here, now that DC is accessible. - // Balance head/tail positions in full width mode. - mCurrentWidth = mIsFullWidth ? (dc.getWidth() - (2 * mX) + mTailWidth) : mBaseWidth; + if (currentMoveBarLevel != null) { + // Calculate current width here, now that DC is accessible. + // Balance head/tail positions in full width mode. + mCurrentWidth = mIsFullWidth ? (dc.getWidth() - (2 * mX) + mTailWidth) : mBaseWidth; - // #21 Force unbuffered drawing on fr735xt (CIQ 2.x) to reduce memory usage. - if ((Graphics has :BufferedBitmap) && (Sys.getDeviceSettings().screenShape != Sys.SCREEN_SHAPE_SEMI_ROUND)) { - drawBuffered(dc, currentMoveBarLevel); - } else { - //drawUnbuffered(dc, currentMoveBarLevel); + // #21 Force unbuffered drawing on fr735xt (CIQ 2.x) to reduce memory usage. + if ((Graphics has :BufferedBitmap) && (Sys.getDeviceSettings().screenShape != Sys.SCREEN_SHAPE_SEMI_ROUND)) { + drawBuffered(dc, currentMoveBarLevel); + } else { + //drawUnbuffered(dc, currentMoveBarLevel); - // Draw bars vertically centred on mY. - drawBars(dc, mX, mY - (mHeight / 2), currentMoveBarLevel); - } + // Draw bars vertically centred on mY. + drawBars(dc, mX, mY - (mHeight / 2), currentMoveBarLevel); + } + } } (:buffered) From c1b0fbeca026fff746f721e0b83919628cff82b4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:38:10 -0500 Subject: [PATCH 204/220] Syntax error --- resources/strings/strings.xml | 2 +- source/DataFields.mc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index c132a975..64cb7854 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.21.0.b10 + Crystal-Tesla V2.21.0.b11 Theme Hours Colour diff --git a/source/DataFields.mc b/source/DataFields.mc index 26f8d9da..1701a2b2 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -464,7 +464,7 @@ class DataFields extends Ui.Drawable { } info = ActivityMonitor.getInfo(); var t = (info has :timeToRecovery); - if (value.length() == 0 && && t == true) { + if (value.length() == 0 && t == true) { var recoveryTyime = info.timeToRecovery; if (recoveryTyime != null) { value = recoveryTyime.format(INTEGER_FORMAT); From ae6d890a6bdc50387e65e3d16fbf7930e3fad584 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:20:26 -0500 Subject: [PATCH 205/220] Testing for empty data --- source/CrystalApp.mc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index bede47b4..a627217b 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -100,6 +100,12 @@ class CrystalApp extends App.AppBase { pendingWebRequests = {}; } + var str = data.toString(); + + if (data.isEmpty()) { + /*DEBUG*/ logMessage("onBackgroundData:Empty data"); + return; + } var type = data.keys()[0]; // Type of received data. var storedData = Storage.getValue(type); if (storedData == null) { From 73bd9f717a7de4f2720a6d21910c8333e49cf809 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:59:22 -0500 Subject: [PATCH 206/220] Bug fix when Tesla data is a dict instead of a string. Enumerate data in onBackgroundData instead of looking only at the first one. Tesla background code not ran when reading from complication --- README.md | 3 +- resources/strings/strings.xml | 2 +- source/BackgroundService.mc | 67 ++++++++++++++++++++--------------- source/CrystalApp.mc | 52 ++++++++++++++------------- source/CrystalView.mc | 2 +- source/DataFields.mc | 3 ++ source/Global.mc | 2 +- 7 files changed, 74 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 9f57e1d3..0c768bb4 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.21.0 - Compiled with CIQ 7.4.3 -- Added back OpenWeatherMap as a weather service +- Added back OpenWeatherMap as a weather service. This service, unlike Garmin, can display the weather station but relies on the last activity with GPS or default latitude/longitude entered in the app parameters for location. - Readded Fenix 8 and E +- Fixed a crash when the Tesla data is returned as a dictionary instead of a string, although I requested it to be a string ### 2.20.0 - Compiled with CIQ 7.3.1 diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 64cb7854..193f8374 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.21.0.b11 + Crystal-Tesla V2.21.0.b14 Theme Hours Colour diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 46a11135..9e560a74 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -37,7 +37,7 @@ class BackgroundService extends Sys.ServiceDelegate { //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { - /*DEBUG*/ logMessage("returning because Storage.getValue(\"Tesla\") is " + Storage.getValue("Tesla") + " or gTeslaComplication is " + gTeslaComplication); + /*DEBUG*/ logMessage("initialize:Not doing Tesla because Storage.getValue(\"Tesla\") is null (it's " + Storage.getValue("Tesla") + ") or gTeslaComplication is true (it's " + gTeslaComplication + ")"); return; } @@ -134,7 +134,7 @@ class BackgroundService extends Sys.ServiceDelegate { function onReceiveOpenWeatherMapCurrent(responseCode, data) { var result; - + /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent responseCode: " + responseCode); //DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent data: " + data); @@ -192,7 +192,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background) function doTesla() { - if (_pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null) { + if (_pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null && gTeslaComplication != true) { if (_token == null) { /*DEBUG*/ logMessage("doTesla:Generating Access Token"); var refreshToken = $.getStringProperty("TeslaRefreshToken",""); @@ -217,6 +217,9 @@ class BackgroundService extends Sys.ServiceDelegate { return; } } + else { + /*DEBUG*/ logMessage("doTesla:Not doing Tesla because _pendingWebRequests[\"TeslaInfo\"] is null (it's " + _pendingWebRequests["TeslaInfo"] + ") Storage.getValue(\"Tesla\") is null (it's " + Storage.getValue("Tesla") + ") or gTeslaComplication is true (it's " + gTeslaComplication + ")"); + } try { /*DEBUG*/ logMessage("doTesla: Exiting with " + _bg_data); @@ -371,31 +374,39 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("httpInternalErrorTesla", 200); teslaInfo.put("VehicleState", "online"); - var pos = responseData.find("battery_level"); - var str = responseData.substring(pos + 15, pos + 20); - var posEnd = str.find(","); - teslaInfo.put("BatteryLevel", $.validateNumber(str.substring(0, posEnd), 0)); - - pos = responseData.find("charging_state"); - str = responseData.substring(pos + 17, pos + 37); - posEnd = str.find("\""); - teslaInfo.put("ChargingState", $.validateString(str.substring(0, posEnd), "")); - - pos = responseData.find("inside_temp"); - str = responseData.substring(pos + 13, pos + 20); - posEnd = str.find(","); - teslaInfo.put("InsideTemp", $.validateNumber(str.substring(0, posEnd), 0)); - - pos = responseData.find("sentry_mode"); - str = responseData.substring(pos + 13, pos + 20); - posEnd = str.find(","); - teslaInfo.put("SentryEnabled", $.validateString(str.substring(0, posEnd), "").equals("true")); - - pos = responseData.find("preconditioning_enabled"); - str = responseData.substring(pos + 25, pos + 32); - posEnd = str.find(","); - teslaInfo.put("PrecondEnabled", $.validateString(str.substring(0, posEnd), "").equals("true")); - + if (responseData instanceof Lang.Dictionary) { + teslaInfo.put("BatteryLevel", $.validateNumber(response.get("charge_state").get("battery_level"), 0)); + teslaInfo.put("ChargingState", $.validateString(response.get("charge_state").get("charging_state"), "")); + teslaInfo.put("PrecondEnabled", $.validateBoolean(response.get("charge_state").get("preconditioning_enabled"), false)); + teslaInfo.put("InsideTemp", $.validateNumber(response.get("climate_state").get("inside_temp"), 0)); + teslaInfo.put("SentryEnabled", $.validateBoolean(response.get("vehicle_state").get("sentry_mode"), false)); + } + else if (responseData instanceof Lang.String) { + var pos = responseData.find("battery_level"); + var str = responseData.substring(pos + 15, pos + 20); + var posEnd = str.find(","); + teslaInfo.put("BatteryLevel", $.validateNumber(str.substring(0, posEnd), 0)); + + pos = responseData.find("charging_state"); + str = responseData.substring(pos + 17, pos + 37); + posEnd = str.find("\""); + teslaInfo.put("ChargingState", $.validateString(str.substring(0, posEnd), "")); + + pos = responseData.find("inside_temp"); + str = responseData.substring(pos + 13, pos + 20); + posEnd = str.find(","); + teslaInfo.put("InsideTemp", $.validateNumber(str.substring(0, posEnd), 0)); + + pos = responseData.find("sentry_mode"); + str = responseData.substring(pos + 13, pos + 20); + posEnd = str.find(","); + teslaInfo.put("SentryEnabled", $.validateString(str.substring(0, posEnd), "").equals("true")); + + pos = responseData.find("preconditioning_enabled"); + str = responseData.substring(pos + 25, pos + 32); + posEnd = str.find(","); + teslaInfo.put("PrecondEnabled", $.validateString(str.substring(0, posEnd), "").equals("true")); + } _bg_data.put("TeslaInfo", teslaInfo); } // If no vehicle (rare) or can't contact (much more frequent) is received, try to get a new vehicle (404) or retrieve its state (408) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index a627217b..4310c756 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -100,40 +100,42 @@ class CrystalApp extends App.AppBase { pendingWebRequests = {}; } - var str = data.toString(); - if (data.isEmpty()) { /*DEBUG*/ logMessage("onBackgroundData:Empty data"); return; } - var type = data.keys()[0]; // Type of received data. - var storedData = Storage.getValue(type); - if (storedData == null) { - storedData = {}; - } - var receivedData = data[type]; // The actual data received: strip away type key. - - // Do process the data if what we got was an error - if (receivedData["httpError"] == null) { - // New data received: clear pendingWebRequests flag and overwrite stored data that with what we received, leaving others intact. - // storedData = receivedData; - var keys = receivedData.keys(); - var values = receivedData.values(); - for (var i = 0; i < keys.size(); i++) { - storedData.put(keys[i], values[i]); - } - storedData.put("NewData", true); - pendingWebRequests.remove(type); + for (var keyIndex = 0; keyIndex < data.size(); keyIndex++) { + var type = data.keys()[keyIndex]; // Type of received data. + var storedData = Storage.getValue(type); + if (storedData == null) { + storedData = {}; + } + var receivedData = data[type]; // The actual data received: strip away type key. + + // Do process the data if what we got was an error + if (receivedData["httpError"] == null) { + // New data received: clear pendingWebRequests flag and overwrite stored data that with what we received, leaving others intact. + // storedData = receivedData; + var keys = receivedData.keys(); + var values = receivedData.values(); + for (var i = 0; i < keys.size(); i++) { + storedData.put(keys[i], values[i]); + } + + storedData.put("NewData", true); + Storage.setValue(type, storedData); + + pendingWebRequests.remove(type); + } - Storage.setValue("PendingWebRequests", pendingWebRequests); - Storage.setValue(type, storedData); - - // Don't do this now as it adds too much code to the background process + // No benifit of doing this now as it adds code to the background process that can be done in the main view instead // checkPendingWebRequests(); // We just got new data, process them right away before displaying } - /*DEBUG*/ logMessage("onBackgroundData:Flag requests are pending"); + Storage.setValue("PendingWebRequests", pendingWebRequests); + + /*DEBUG*/ logMessage("onBackgroundData:Flag that requests are pending"); Storage.setValue("RequestsPending", true); Ui.requestUpdate(); } diff --git a/source/CrystalView.mc b/source/CrystalView.mc index dec388b5..3c9a2217 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -331,7 +331,7 @@ class CrystalView extends Ui.WatchFace { // Existing data is older than 5 mins. // TODO: Consider requesting weather at sunrise/sunset to update weather icon. if ((Time.now().value() > (owmCurrent["dt"] + 300)) || - true || //TODO Remove + //true || //TODO Remove // Existing data not for this location. // Not a great test, as a degree of longitude varies betwee 69 (equator) and 0 (pole) miles, but simpler than // true distance calculation. 0.02 degree of latitude is just over a mile. diff --git a/source/DataFields.mc b/source/DataFields.mc index 1701a2b2..4dd9d126 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -813,6 +813,7 @@ class DataFields extends Ui.Drawable { if (mWeather == null || Storage.getValue("NewWeatherInfo") != null) { mWeather = Storage.getValue("OpenWeatherMapCurrent"); Storage.deleteValue("NewWeatherInfo"); + /*DEBUG*/ logMessage("getValueForFieldType:new weather data: " + mWeather); } // Stored weather data available. @@ -847,6 +848,8 @@ class DataFields extends Ui.Drawable { stale = true; } } + + /*DEBUG*/ logMessage("getValueForFieldType:Weather value is " + value + " stale is " + stale); break; case FIELD_TYPE_PRESSURE: diff --git a/source/Global.mc b/source/Global.mc index d9b4e4f6..c2bd3f8d 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -531,7 +531,7 @@ function doTeslaComplication(complicationValue) { teslaInfo.put("SentryEnabled", $.validateBoolean(arrayInfo[4], "")); // Yes, putting an empty string instead of a Boolean. The writeBatteryLevel will know it means I don't have one teslaInfo.put("PrecondEnabled", $.validateBoolean(arrayInfo[5], "")); // Yes, putting an empty string instead of a Boolean. The writeBatteryLevel will know it means I don't have one teslaInfo.put("VehicleState", $.validateString(arrayInfo[6], "")); - + teslaInfo.put("NewData", true); Storage.setValue("TeslaInfo", teslaInfo); } } From f9fed049925bf7d776e2cfcbb8cbcebe2c300d9a Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:09:01 -0500 Subject: [PATCH 207/220] Bug fix --- manifest.xml | 1 + source/BackgroundService.mc | 10 +++++----- source/CrystalView.mc | 2 ++ source/MoveBar.mc | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/manifest.xml b/manifest.xml index b1a629ef..c29ef774 100644 --- a/manifest.xml +++ b/manifest.xml @@ -4,6 +4,7 @@ + diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 9e560a74..513240da 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -375,11 +375,11 @@ class BackgroundService extends Sys.ServiceDelegate { teslaInfo.put("VehicleState", "online"); if (responseData instanceof Lang.Dictionary) { - teslaInfo.put("BatteryLevel", $.validateNumber(response.get("charge_state").get("battery_level"), 0)); - teslaInfo.put("ChargingState", $.validateString(response.get("charge_state").get("charging_state"), "")); - teslaInfo.put("PrecondEnabled", $.validateBoolean(response.get("charge_state").get("preconditioning_enabled"), false)); - teslaInfo.put("InsideTemp", $.validateNumber(response.get("climate_state").get("inside_temp"), 0)); - teslaInfo.put("SentryEnabled", $.validateBoolean(response.get("vehicle_state").get("sentry_mode"), false)); + teslaInfo.put("BatteryLevel", $.validateNumber(responseData.get("response").get("charge_state").get("battery_level"), 0)); + teslaInfo.put("ChargingState", $.validateString(responseData.get("response").get("charge_state").get("charging_state"), "")); + teslaInfo.put("PrecondEnabled", $.validateBoolean(responseData.get("response").get("charge_state").get("preconditioning_enabled"), false)); + teslaInfo.put("InsideTemp", $.validateNumber(responseData.get("response").get("climate_state").get("inside_temp"), 0)); + teslaInfo.put("SentryEnabled", $.validateBoolean(responseData.get("response").get("vehicle_state").get("sentry_mode"), false)); } else if (responseData instanceof Lang.String) { var pos = responseData.find("battery_level"); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index 3c9a2217..d7014662 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -109,6 +109,8 @@ class CrystalView extends Ui.WatchFace { mGoalTypes[1] = {}; mMoveBarType = {}; + + /*DEBUG*/ logMessage("View:Initialize"); } function burnInProtectionIsOrWasActive() { diff --git a/source/MoveBar.mc b/source/MoveBar.mc index 205a02bf..1ac548c4 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -96,8 +96,8 @@ class MoveBar extends Ui.Drawable { } } - var t = (info has :timeToRecovery); - if (value == null && t == true) { + //var t = (info has :timeToRecovery); + if (value == null && (info has :timeToRecovery)) { value = info.timeToRecovery; // Info time to recovery is in hours } From 4a0a491155b29f68daf3216370c71c6d15df5e59 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:43:08 -0500 Subject: [PATCH 208/220] Fail safe in case background data returns null --- source/CrystalApp.mc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 4310c756..620aab47 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -100,6 +100,11 @@ class CrystalApp extends App.AppBase { pendingWebRequests = {}; } + if (data == null) { + /*DEBUG*/ logMessage("onBackgroundData:data is null"); + return; + } + if (data.isEmpty()) { /*DEBUG*/ logMessage("onBackgroundData:Empty data"); return; From e2668a654438a66d3ab7ae711a286aa8aaaa32b4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 2 Jan 2025 00:03:36 -0500 Subject: [PATCH 209/220] Fixed the MoveBar to not stay hidden when coming back from AOD --- README.md | 10 ++++++++-- manifest.xml | 1 + source/DataFields.mc | 3 +-- source/MoveBar.mc | 3 +-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0c768bb4..6780e3cf 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,15 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.21.0 - Compiled with CIQ 7.4.3 -- Added back OpenWeatherMap as a weather service. This service, unlike Garmin, can display the weather station but relies on the last activity with GPS or default latitude/longitude entered in the app parameters for location. -- Readded Fenix 8 and E +- By requests, added back OpenWeatherMap as a weather service. This service, unlike Garmin, can display the weather station but relies on the last activity with GPS or default latitude/longitude entered in the app parameters for location (fallback in case there is no activity with GPS). Clear the "OpenWeatherMap API Key Override" field in the Settings to revert to Garmin Weather - Fixed a crash when the Tesla data is returned as a dictionary instead of a string, although I requested it to be a string +- Fixed moveBar to no stay hidden after coming back from AOD. + +### 2.20.2 +- Fixed what seems a compiler error when timeToRecovery isn't available and yet, the compiler says it is and causes a crash because of that + +### 2.20.1 +- No code changes. Only added back Enduro3 and new Fenix8 watches (including Fenix E). ### 2.20.0 - Compiled with CIQ 7.3.1 diff --git a/manifest.xml b/manifest.xml index c29ef774..5174b50e 100644 --- a/manifest.xml +++ b/manifest.xml @@ -6,6 +6,7 @@ + diff --git a/source/DataFields.mc b/source/DataFields.mc index 4dd9d126..05dc5ffa 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -463,8 +463,7 @@ class DataFields extends Ui.Drawable { } } info = ActivityMonitor.getInfo(); - var t = (info has :timeToRecovery); - if (value.length() == 0 && t == true) { + if (value.length() == 0 && info has :timeToRecovery) { var recoveryTyime = info.timeToRecovery; if (recoveryTyime != null) { value = recoveryTyime.format(INTEGER_FORMAT); diff --git a/source/MoveBar.mc b/source/MoveBar.mc index 1ac548c4..46cb4a2c 100644 --- a/source/MoveBar.mc +++ b/source/MoveBar.mc @@ -24,7 +24,7 @@ class MoveBar extends Ui.Drawable { // Either mBaseWidth, or a calculated full width. private var mCurrentWidth; - private var mMoveBarStyle; + private var mMoveBarStyle = $.getIntProperty("MoveBarStyle", 0); // private enum /* MOVE_BAR_STYLE */ { // ALL_SEGMENTS, @@ -96,7 +96,6 @@ class MoveBar extends Ui.Drawable { } } - //var t = (info has :timeToRecovery); if (value == null && (info has :timeToRecovery)) { value = info.timeToRecovery; // Info time to recovery is in hours } From 9e7a2c6f9b64d5caade20d3325de867ee65a35df Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Thu, 2 Jan 2025 00:16:51 -0500 Subject: [PATCH 210/220] Update manifest.xml.prd --- manifest.xml.prd | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/manifest.xml.prd b/manifest.xml.prd index 77d6803f..2c2fa6fd 100644 --- a/manifest.xml.prd +++ b/manifest.xml.prd @@ -12,6 +12,7 @@ + @@ -30,6 +31,11 @@ + + + + + From 5de2a308f10f9a733a3362c1280c8c61d1228d66 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 4 Jan 2025 21:04:49 -0500 Subject: [PATCH 211/220] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6780e3cf..7f3b5edd 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). ### 2.21.0 - Compiled with CIQ 7.4.3 -- By requests, added back OpenWeatherMap as a weather service. This service, unlike Garmin, can display the weather station but relies on the last activity with GPS or default latitude/longitude entered in the app parameters for location (fallback in case there is no activity with GPS). Clear the "OpenWeatherMap API Key Override" field in the Settings to revert to Garmin Weather +- By requests, OpenWeatherMap IS BACK! (as a weather service). This service, unlike Garmin, can display the weather station but relies on the last activity with GPS or default latitude/longitude entered in the app parameters for location (fallback in case there is no activity with GPS). Clear the "OpenWeatherMap API Key Override" field in the Settings to revert to Garmin Weather (the default is back to OWM). Like before, this weather data is pulled at intervals (5 minutes). - Fixed a crash when the Tesla data is returned as a dictionary instead of a string, although I requested it to be a string -- Fixed moveBar to no stay hidden after coming back from AOD. +- Fixed moveBar to not stay hidden after coming back from AOD. ### 2.20.2 - Fixed what seems a compiler error when timeToRecovery isn't available and yet, the compiler says it is and causes a crash because of that From 5a045ebaf53a19d84f4381ba366590fc05948e05 Mon Sep 17 00:00:00 2001 From: flowstatedev <29851637+flowstatedev@users.noreply.github.com> Date: Wed, 16 Apr 2025 19:15:29 -0400 Subject: [PATCH 212/220] Support long press of live HR field to open HR glance --- source/DataFields.mc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/DataFields.mc b/source/DataFields.mc index 05dc5ffa..86b58890 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -117,6 +117,7 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_FLOOR_CLIMBED, "complicationType" => Complications.COMPLICATION_TYPE_FLOORS_CLIMBED}, {"type" => FIELD_TYPE_PULSE_OX, "complicationType" => Complications.COMPLICATION_TYPE_PULSE_OX}, {"type" => FIELD_TYPE_HEART_RATE, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE}, + {"type" => FIELD_TYPE_HR_LIVE_5S, "complicationType" => Complications.COMPLICATION_TYPE_HEART_RATE}, {"type" => FIELD_RECOVERY_TIME, "complicationType" => Complications.COMPLICATION_TYPE_RECOVERY_TIME}, {"type" => FIELD_TYPE_ALTITUDE, "complicationType" => Complications.COMPLICATION_TYPE_ALTITUDE}, {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_WEATHER}, // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain From c18d5e62e2882b1cc7866fc9f1a4791809332010 Mon Sep 17 00:00:00 2001 From: flowstatedev <29851637+flowstatedev@users.noreply.github.com> Date: Wed, 16 Apr 2025 19:17:53 -0400 Subject: [PATCH 213/220] Fix build by removing BOM from resource xml files --- resources-nob/strings/strings.xml | 2 +- resources-slo/strings/strings.xml | 2 +- resources-slv/strings/strings.xml | 2 +- resources-spa/strings/strings.xml | 2 +- resources-zhs/strings/strings.xml | 2 +- resources-zht/strings/strings.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 6ac7d306..36c366a8 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -1,4 +1,4 @@ - + Crystal diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index a3c78eff..784f5dd8 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -1,4 +1,4 @@ - + Crystal diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 477bb599..c65eecb4 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -1,4 +1,4 @@ - + Crystal diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 501b0c34..2778658c 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -1,4 +1,4 @@ - + Crystal diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 9f573a17..78e3fc86 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -1,4 +1,4 @@ - + Crystal diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index b35350f7..c6a46641 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -1,4 +1,4 @@ - + Crystal From a2227f3be444d469b511464ca3541224df9fed46 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 24 May 2025 14:37:44 -0400 Subject: [PATCH 214/220] Added new devices Approach50, Descent G2, Forerunner 570s/970 and VivoActive 6 --- README.md | 6 ++++++ manifest.xml | 2 +- manifest.xml.prd | 10 +++++++++- monkey.jungle | 7 +++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7f3b5edd..7947e499 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ Reviews: - Video review in Spanish, by Sergio: https://www.youtube.com/watch?v=TZFhnm_y1MM. ## Below is what has been added by me (SylvainGa). + +### 2.21.1 +- Compiled with CIQ 8.1.1 +- Added new devices: Approach50, Descent G2, Forerunner 570s/970 and VivoActive6 +- Added changes from flowstatedev - Support long press of live HR field to open HR glance and fixed some strings file that got daved in UTF8-BOM instead of plain UTF8 somehow + ### 2.21.0 - Compiled with CIQ 7.4.3 - By requests, OpenWeatherMap IS BACK! (as a weather service). This service, unlike Garmin, can display the weather station but relies on the last activity with GPS or default latitude/longitude entered in the app parameters for location (fallback in case there is no activity with GPS). Clear the "OpenWeatherMap API Key Override" field in the Settings to revert to Garmin Weather (the default is back to OWM). Like before, this weather data is pulled at intervals (5 minutes). diff --git a/manifest.xml b/manifest.xml index 5174b50e..a06b1f9c 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + diff --git a/manifest.xml.prd b/manifest.xml.prd index 2c2fa6fd..5d83b42d 100644 --- a/manifest.xml.prd +++ b/manifest.xml.prd @@ -1,12 +1,14 @@ - + + + @@ -27,10 +29,12 @@ + + @@ -47,11 +51,14 @@ + + + @@ -79,6 +86,7 @@ + diff --git a/monkey.jungle b/monkey.jungle index 6a954f39..2472dcfd 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -54,6 +54,13 @@ fenixe.sourcePath = $(fenixe.sourcePath);always-on-source vivoactive5.sourcePath = $(vivoactive5.sourcePath);always-on-source descentmk343mm.sourcePath = $(descentmk343mm.sourcePath);always-on-source descentmk351mm.sourcePath = $(descentmk351mm.sourcePath);always-on-source +approachs50.sourcePath = $(approachs50.sourcePath);always-on-source +descentg2.sourcePath = $(descentg2.sourcePath);always-on-source +fr57042mm.sourcePath = $(fr57042mm.sourcePath);always-on-source +fr57047mm.sourcePath = $(fr57047mm.sourcePath);always-on-source +fr970.sourcePath = $(fr970.sourcePath);always-on-source +vivoactive6.sourcePath = $(vivoactive6.sourcePath);always-on-source + base.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;noComplications descentmk2.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications From 4a618500d3f49a5a8bc153cd97db876a516cf29d Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 24 May 2025 14:38:13 -0400 Subject: [PATCH 215/220] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7947e499..43533927 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Reviews: ### 2.21.1 - Compiled with CIQ 8.1.1 -- Added new devices: Approach50, Descent G2, Forerunner 570s/970 and VivoActive6 +- Added new devices: Approach50, Descent G2, Forerunner 570s/970 and VivoActive 6 - Added changes from flowstatedev - Support long press of live HR field to open HR glance and fixed some strings file that got daved in UTF8-BOM instead of plain UTF8 somehow ### 2.21.0 From a0e98869ac0dc6d0a807c5ee6ddb63e5b6a8e540 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Sat, 24 May 2025 14:44:43 -0400 Subject: [PATCH 216/220] Redid changes made in --- resources/strings/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 193f8374..62682482 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.21.0.b14 + Crystal-Tesla V2.21.1.b0 Theme Hours Colour From cad2b527895aaa7b4184067233da573198c8acb4 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 9 Jun 2025 21:41:23 -0400 Subject: [PATCH 217/220] 2.22.0 - At request, there is now an option to have the date format to have a leading zero when there is only one digit. --- README.md | 3 ++ manifest.xml | 2 +- resources-ces/strings/strings.xml | 1 + resources-dan/strings/strings.xml | 1 + resources-deu/strings/strings.xml | 1 + resources-dut/strings/strings.xml | 1 + resources-fin/strings/strings.xml | 1 + resources-fre/strings/strings.xml | 1 + resources-hrv/strings/strings.xml | 1 + resources-hun/strings/strings.xml | 1 + resources-ita/strings/strings.xml | 1 + resources-kor/strings/strings.xml | 1 + resources-nob/strings/strings.xml | 1 + resources-pol/strings/strings.xml | 1 + resources-por/strings/strings.xml | 1 + resources-rus/strings/strings.xml | 1 + resources-slo/strings/strings.xml | 1 + resources-slv/strings/strings.xml | 1 + resources-spa/strings/strings.xml | 1 + resources-swe/strings/strings.xml | 1 + resources-zhs/strings/strings.xml | 1 + resources-zht/strings/strings.xml | 1 + resources/settings/properties.xml | 1 + resources/settings/settings.xml | 4 ++ resources/strings/strings.xml | 3 +- source/BackgroundService.mc | 72 +++++++++++++++---------------- source/CrystalApp.mc | 18 ++++---- source/CrystalView.mc | 36 ++++++++-------- source/DataArea.mc | 4 +- source/DataFields.mc | 8 ++-- source/DateLine.mc | 3 +- source/Global.mc | 17 ++++---- 32 files changed, 110 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 43533927..dd7a0f73 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.22.0 +- At request, there is now an option to have the date format to have a leading zero when there is only one digit. + ### 2.21.1 - Compiled with CIQ 8.1.1 - Added new devices: Approach50, Descent G2, Forerunner 570s/970 and VivoActive 6 diff --git a/manifest.xml b/manifest.xml index a06b1f9c..f2440154 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,7 +1,7 @@ - + diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index f87a65de..0846ca8c 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index 0852199f..da54b227 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index a904449e..3081249f 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -17,6 +17,7 @@ Hide seconds when inactive Always hide seconds Führende Nullen ausblenden + Hide Day Leading Zero Add colon between hours and minutes Anzahl der Datenfelder diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index 6797f396..a42277ed 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -17,6 +17,7 @@ Hide seconds when inactive Always hide seconds Verberg Eerste Nul Bij Uren + Hide Day Leading Zero Add colon between hours and minutes Hoeveelheid Datavelden diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index dcbe52a9..36ca083d 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index e102a706..2014daf0 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -17,6 +17,7 @@ Afficher sauf quand inactif Toujours cacher Masquer le zéro avant l'heure + Masquer le zéro avant la date Ajouter un deux-points entre les heures et minutes Nombre de champs de données diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index ceba2ec6..bde2ca2a 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index d3d6e6cc..9b02da81 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index 5b4bf17e..de473e95 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 4e880431..b56e4981 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 36c366a8..533f1bbb 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index cdcbe962..448fa36c 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -17,6 +17,7 @@ Hide seconds when inactive Always hide seconds Ukryj Zero Poprzedzające Godzinę + Hide Day Leading Zero Add colon between hours and minutes Liczba Pól z Danymi diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index ce5de5ab..7ba5fcef 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 001a2a00..7831cedd 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -17,6 +17,7 @@ Hide seconds when inactive Always hide seconds Скрывать нули перед часами + Hide Day Leading Zero Add colon between hours and minutes Количество полей данных diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 784f5dd8..2dd55815 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index c65eecb4..aa750181 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 2778658c..28dc08b4 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index d8899599..f9318866 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -17,6 +17,7 @@ Hide seconds when inactive Always hide seconds Dölj inledande nollor + Hide Day Leading Zero Add colon between hours and minutes Antal datafält diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 78e3fc86..735f7a5a 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index c6a46641..04c11c73 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -18,6 +18,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 2448ef13..e77c63d9 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -27,6 +27,7 @@ 0 0 true + true false 0 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index f902ff53..16b313c4 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -233,6 +233,10 @@ + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 62682482..57330c6e 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.21.1.b0 + Crystal-Tesla V2.22.0.b0 Theme Hours Colour @@ -17,6 +17,7 @@ Hide seconds when inactive Always hide seconds Hide Hours Leading Zero + Hide Day Leading Zero Add colon between hours and minutes Number Of Data Fields diff --git a/source/BackgroundService.mc b/source/BackgroundService.mc index 513240da..958ce2ed 100644 --- a/source/BackgroundService.mc +++ b/source/BackgroundService.mc @@ -18,7 +18,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background) function initialize() { - /*DEBUG*/ logMessage("In ServiceDelegate"); + //DEBUG*/ logMessage("In ServiceDelegate"); Sys.ServiceDelegate.initialize(); if (_bg_data == null) { @@ -28,7 +28,7 @@ class BackgroundService extends Sys.ServiceDelegate { } } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("initialize: _bg_data has keys " + keys); + //DEBUG*/ var keys = _bg_data.keys(); logMessage("initialize: _bg_data has keys " + keys); } _stop = false; @@ -37,7 +37,7 @@ class BackgroundService extends Sys.ServiceDelegate { //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** if (Storage.getValue("Tesla") == null || gTeslaComplication == true) { - /*DEBUG*/ logMessage("initialize:Not doing Tesla because Storage.getValue(\"Tesla\") is null (it's " + Storage.getValue("Tesla") + ") or gTeslaComplication is true (it's " + gTeslaComplication + ")"); + //DEBUG*/ logMessage("initialize:Not doing Tesla because Storage.getValue(\"Tesla\") is null (it's " + Storage.getValue("Tesla") + ") or gTeslaComplication is true (it's " + gTeslaComplication + ")"); return; } @@ -72,16 +72,16 @@ class BackgroundService extends Sys.ServiceDelegate { function onTemporalEvent() { _pendingWebRequests = Storage.getValue("PendingWebRequests"); - /*DEBUG*/ logMessage("onTemporalEvent:_pendingWebRequests is '" + _pendingWebRequests + "'"); - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onTemporalEvent:_bg_data has '" + keys); - /*DEBUG*/ if (_token != null) { logMessage("onTemporalEvent:Using token '" + _token.substring(0,20) + "...'"); } else { logMessage("onTemporalEvent:No token");} + //DEBUG*/ logMessage("onTemporalEvent:_pendingWebRequests is '" + _pendingWebRequests + "'"); + //DEBUG*/ var keys = _bg_data.keys(); logMessage("onTemporalEvent:_bg_data has '" + keys); + //DEBUG*/ if (_token != null) { logMessage("onTemporalEvent:Using token '" + _token.substring(0,20) + "...'"); } else { logMessage("onTemporalEvent:No token");} if (_pendingWebRequests != null) { if (_pendingWebRequests["OpenWeatherMapCurrent"] != null) { var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); var lat = $.getStringProperty("LastLocationLat",""); var lon = $.getStringProperty("LastLocationLng",""); - /*DEBUG*/ logMessage("onTemporalEvent:OWM with overide=" + owmKeyOverride + " lat=" + lat + " lon=" + lon); + //DEBUG*/ logMessage("onTemporalEvent:OWM with overide=" + owmKeyOverride + " lat=" + lat + " lon=" + lon); if (lat.length() > 0 && lon.length() > 0) { makeWebRequest( @@ -126,7 +126,7 @@ class BackgroundService extends Sys.ServiceDelegate { //**************************************************************** } else { - /*DEBUG*/ logMessage("onTemporalEvent() called with no pending web requests!"); + //DEBUG*/ logMessage("onTemporalEvent() called with no pending web requests!"); } } @@ -135,7 +135,7 @@ class BackgroundService extends Sys.ServiceDelegate { { var result; - /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent responseCode: " + responseCode); + //DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent responseCode: " + responseCode); //DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent data: " + data); // Useful data only available if result was successful. @@ -168,7 +168,7 @@ class BackgroundService extends Sys.ServiceDelegate { _bg_data.put("OpenWeatherMapCurrent", result); - /*DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: result=" + result); + //DEBUG*/ logMessage("onReceiveOpenWeatherMapCurrent: result=" + result); //**************************************************************** //******** REMVOVED THIS SECTION IF TESLA CODE NOT WANTED ******** //**************************************************************** @@ -177,11 +177,11 @@ class BackgroundService extends Sys.ServiceDelegate { //******** DO THIS INSTEAD ******** //**************************************************************** // try { - // /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); + // //DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); // Bg.exit(_bg_data); // } // catch (e) { - // /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); + // //DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); // } } @@ -194,20 +194,20 @@ class BackgroundService extends Sys.ServiceDelegate { { if (_pendingWebRequests["TeslaInfo"] != null && Storage.getValue("Tesla") != null && gTeslaComplication != true) { if (_token == null) { - /*DEBUG*/ logMessage("doTesla:Generating Access Token"); + //DEBUG*/ logMessage("doTesla:Generating Access Token"); var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null && refreshToken.length() > 0) { - /*DEBUG*/ logMessage("doTesla:Get new Access token with Refresh token at '" + refreshToken.substring(0, 20) + "'..."); + //DEBUG*/ logMessage("doTesla:Get new Access token with Refresh token at '" + refreshToken.substring(0, 20) + "'..."); makeTeslaWebPost(refreshToken, method(:onReceiveToken)); return; } else { - /*DEBUG*/ logMessage("doTesla:No refresh token!"); + //DEBUG*/ logMessage("doTesla:No refresh token!"); _bg_data.put("TeslaInfo", { "httpErrorTesla" => 401, "httpInternalErrorTesla" => 401 } ); //DEBUG*/ _bg_data.put({ "TeslaInfo" => { "httpErrorTesla" => 200, "httpInternalErrorTesla" => 200, "BatteryLevel" => 70, "ChargingState" => "Charging", "InsideTemp" => 21, "PrecondEnabled" => false, "SentryEnabled" => false, "VehicleID" => "12345678" , "VehicleState" => "online"} }); } } else if (_vehicle_id == null) { - /*DEBUG*/ logMessage("doTesla:Getting vehicles"); + //DEBUG*/ logMessage("doTesla:Getting vehicles"); makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); return; } @@ -218,15 +218,15 @@ class BackgroundService extends Sys.ServiceDelegate { } } else { - /*DEBUG*/ logMessage("doTesla:Not doing Tesla because _pendingWebRequests[\"TeslaInfo\"] is null (it's " + _pendingWebRequests["TeslaInfo"] + ") Storage.getValue(\"Tesla\") is null (it's " + Storage.getValue("Tesla") + ") or gTeslaComplication is true (it's " + gTeslaComplication + ")"); + //DEBUG*/ logMessage("doTesla:Not doing Tesla because _pendingWebRequests[\"TeslaInfo\"] is null (it's " + _pendingWebRequests["TeslaInfo"] + ") Storage.getValue(\"Tesla\") is null (it's " + Storage.getValue("Tesla") + ") or gTeslaComplication is true (it's " + gTeslaComplication + ")"); } try { - /*DEBUG*/ logMessage("doTesla: Exiting with " + _bg_data); + //DEBUG*/ logMessage("doTesla: Exiting with " + _bg_data); Bg.exit(_bg_data); } catch (e) { - /*DEBUG*/ logMessage("doTesla exit assertion " + e); + //DEBUG*/ logMessage("doTesla exit assertion " + e); } } //**************************************************************** @@ -235,7 +235,7 @@ class BackgroundService extends Sys.ServiceDelegate { (:background) function onReceiveToken(responseCode, responseData) { - /*DEBUG*/ logMessage("onReceiveToken: " + responseCode); + //DEBUG*/ logMessage("onReceiveToken: " + responseCode); if (_bg_data == null) { _bg_data = Bg.getBackgroundData(); @@ -244,7 +244,7 @@ class BackgroundService extends Sys.ServiceDelegate { } } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveToken: _bg_data has keys " + keys); + //DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveToken: _bg_data has keys " + keys); } var teslaInfo = _bg_data.get("TeslaInfo"); @@ -254,7 +254,7 @@ class BackgroundService extends Sys.ServiceDelegate { if (responseCode == 200) { _token = responseData["access_token"]; - /*DEBUG*/ logMessage("onReceiveToken:Has token '" + _token.substring(0,20) + "...', calling back doTesla"); + //DEBUG*/ logMessage("onReceiveToken:Has token '" + _token.substring(0,20) + "...', calling back doTesla"); teslaInfo.put("AccessToken", _token); teslaInfo.put("RefreshToken", responseData["refresh_token"]); teslaInfo.put("TokenExpiresIn", responseData["expires_in"]); @@ -266,18 +266,18 @@ class BackgroundService extends Sys.ServiceDelegate { else { _bg_data.put("TeslaInfo", { "httpErrorTesla" => 401, "httpInternalErrorTesla" => responseCode } ); try { - /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); + //DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); Bg.exit(_bg_data); } catch (e) { - /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); + //DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); } } } (:background) function onReceiveVehicles(responseCode, responseData) { - /*DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); + //DEBUG*/ logMessage("onReceiveVehicles: " + responseCode); if (_bg_data == null) { _bg_data = Bg.getBackgroundData(); @@ -286,7 +286,7 @@ class BackgroundService extends Sys.ServiceDelegate { } } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicles: _bg_data has keys " + keys); + //DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicles: _bg_data has keys " + keys); } var teslaInfo = _bg_data.get("TeslaInfo"); @@ -329,7 +329,7 @@ class BackgroundService extends Sys.ServiceDelegate { _bg_data.put("TeslaInfo", teslaInfo); - /*DEBUG*/ logMessage("onReceiveVehicles:vehice_state=" + vehice_state); + //DEBUG*/ logMessage("onReceiveVehicles:vehice_state=" + vehice_state); if (_vehicle_id != null) { doTesla(); @@ -340,18 +340,18 @@ class BackgroundService extends Sys.ServiceDelegate { _bg_data.put("TeslaInfo", { "httpErrorTesla" => (_vehicle_id == null ? 404 : 408), "httpInternalErrorTesla" => responseCode } ); try { - /*DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); + //DEBUG*/ logMessage("onReceiveVehicles: Exiting with " + _bg_data); Bg.exit(_bg_data); } catch (e) { - /*DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); + //DEBUG*/ logMessage("onReceiveVehicles exit assertion " + e); } } (:background) function onReceiveVehicleData(responseCode, responseData) { - /*DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); - /*DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); + //DEBUG*/ logMessage("onReceiveVehicleData: " + responseCode); + //DEBUG*/ var myStats = Sys.getSystemStats(); logMessage("Total memory: " + myStats.totalMemory + " Used memory: " + myStats.usedMemory + " Free memory: " + myStats.freeMemory); if (_bg_data == null) { _bg_data = Bg.getBackgroundData(); @@ -359,7 +359,7 @@ class BackgroundService extends Sys.ServiceDelegate { _bg_data = {}; } else { - /*DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicleData: _bg_data has keys " + keys); + //DEBUG*/ var keys = _bg_data.keys(); logMessage("onReceiveVehicleData: _bg_data has keys " + keys); } } @@ -416,7 +416,7 @@ class BackgroundService extends Sys.ServiceDelegate { _vehicle_id = null; _bg_data.put("TeslaInfo", { "httpErrorTesla" => 404, "httpInternalErrorTesla" => responseCode, "VehicleID" => null } ); } - /*DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData with _stop at " + _stop); + //DEBUG*/ logMessage("Requesting vehicles from onReceiveVehicleData with _stop at " + _stop); if (_stop == false) { // We we're true, we already came back here for the next lines so don't get into an infinite loop _stop = true; // Don't get vehicle_data anymore if we fail again makeTeslaWebRequest("https://" + $.getStringProperty("TeslaServerAPILocation","") + "/api/1/products?orders=true", Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON, method(:onReceiveVehicles)); @@ -427,7 +427,7 @@ class BackgroundService extends Sys.ServiceDelegate { else if (responseCode == 401) { var refreshToken = $.getStringProperty("TeslaRefreshToken",""); if (refreshToken != null) { - /*DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData with _stop at " + _stop); + //DEBUG*/ logMessage("Requesting access token from onReceiveVehicleData with _stop at " + _stop); if (_stop == false) { // We we're true, we already came back here for the next lines so don't get into an infinite loop _stop = true; // Don't get vehicle_data anymore if we fail again makeTeslaWebPost(refreshToken, method(:onReceiveToken)); @@ -445,11 +445,11 @@ class BackgroundService extends Sys.ServiceDelegate { _bg_data.put("TeslaInfo", teslaInfo); try { - /*DEBUG*/ logMessage("onReceiveVehicleData: Exiting with " + _bg_data); + //DEBUG*/ logMessage("onReceiveVehicleData: Exiting with " + _bg_data); Bg.exit(_bg_data); } catch (e) { - /*DEBUG*/ logMessage("onReceiveVehicleData exit assertion " + e); + //DEBUG*/ logMessage("onReceiveVehicleData exit assertion " + e); } } diff --git a/source/CrystalApp.mc b/source/CrystalApp.mc index 620aab47..783e7beb 100644 --- a/source/CrystalApp.mc +++ b/source/CrystalApp.mc @@ -33,16 +33,16 @@ class CrystalApp extends App.AppBase { } // function onStart(state) { - // /*DEBUG*/ logMessage("App starting"); + // //DEBUG*/ logMessage("App starting"); // } // function onStop(state) { - // /*DEBUG*/ logMessage("App stopping"); + // //DEBUG*/ logMessage("App stopping"); // } // Return the initial view of your application here function getInitialView() { - /*DEBUG*/ logMessage("Getting initial view"); + //DEBUG*/ logMessage("Getting initial view"); if (WatchUi has :WatchFaceDelegate) { mView = new CrystalView(); @@ -94,19 +94,19 @@ class CrystalApp extends App.AppBase { (:background) function onBackgroundData(data) { - /*DEBUG*/ logMessage("onBackgroundData:received '" + data + "'"); + //DEBUG*/ logMessage("onBackgroundData:received '" + data + "'"); var pendingWebRequests = Storage.getValue("PendingWebRequests"); if (pendingWebRequests == null) { pendingWebRequests = {}; } if (data == null) { - /*DEBUG*/ logMessage("onBackgroundData:data is null"); + //DEBUG*/ logMessage("onBackgroundData:data is null"); return; } if (data.isEmpty()) { - /*DEBUG*/ logMessage("onBackgroundData:Empty data"); + //DEBUG*/ logMessage("onBackgroundData:Empty data"); return; } @@ -140,7 +140,7 @@ class CrystalApp extends App.AppBase { Storage.setValue("PendingWebRequests", pendingWebRequests); - /*DEBUG*/ logMessage("onBackgroundData:Flag that requests are pending"); + //DEBUG*/ logMessage("onBackgroundData:Flag that requests are pending"); Storage.setValue("RequestsPending", true); Ui.requestUpdate(); } @@ -163,7 +163,7 @@ class CrystalApp extends App.AppBase { // } // } // else { - // /*DEBUG*/ logMessage("Unexpected invalid receivedData: " + receivedData); + // //DEBUG*/ logMessage("Unexpected invalid receivedData: " + receivedData); // } // // Copy into their own name some of the entries in TeslaInfo, then delete from TeslaInfo @@ -196,7 +196,7 @@ class CrystalApp extends App.AppBase { // } // } - // /*DEBUG*/ var nextTime = Time.now().add(new Time.Duration(5 * 60)); var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next event: " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); + // //DEBUG*/ var nextTime = Time.now().add(new Time.Duration(5 * 60)); var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next event: " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); // Bg.registerForTemporalEvent(new Time.Duration(5 * 60)); // Since onSettingsChanged go for a specific time, go for duration here once we get going, otherwise we'll get background data only once the view is shown // Ui.requestUpdate(); diff --git a/source/CrystalView.mc b/source/CrystalView.mc index d7014662..e828968a 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -110,7 +110,7 @@ class CrystalView extends Ui.WatchFace { mMoveBarType = {}; - /*DEBUG*/ logMessage("View:Initialize"); + //DEBUG*/ logMessage("View:Initialize"); } function burnInProtectionIsOrWasActive() { @@ -151,7 +151,7 @@ class CrystalView extends Ui.WatchFace { // the state of this View and prepare it to be shown. This includes // loading resources into memory. */ function onShow() { - /*DEBUG*/ logMessage("View showing"); + //DEBUG*/ logMessage("View showing"); } // Set flag to respond to settings change on next full draw (onUpdate()), as we may be in 1Hz (lower power) mode, and cannot @@ -245,10 +245,10 @@ class CrystalView extends Ui.WatchFace { // Events scheduled for a time in the past trigger immediately. var nextTime = lastTime.add(new Time.Duration(5 * 60)); - /*DEBUG*/ var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next temporal event at " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); + //DEBUG*/ var local = Gregorian.info(nextTime, Time.FORMAT_SHORT); var time = $.getFormattedTime(local.hour, local.min, local.sec); logMessage("Next temporal event at " + time[:hour] + ":" + time[:min] + ":" + time[:sec] + time[:amPm]); Bg.registerForTemporalEvent(nextTime); } else { - /*DEBUG*/ logMessage("Next Temporal Events should happen NOW"); + //DEBUG*/ logMessage("Next Temporal Events should happen NOW"); Bg.registerForTemporalEvent(Time.now()); } } @@ -306,7 +306,7 @@ class CrystalView extends Ui.WatchFace { if (pendingWebRequests == null) { pendingWebRequests = {}; } - /*DEBUG*/ logMessage("checkPendingWebRequests: pendingWebRequest=" + pendingWebRequests); + //DEBUG*/ logMessage("checkPendingWebRequests: pendingWebRequest=" + pendingWebRequests); // 1. Weather: // Location must be available, weather or humidity (#113) data field must be shown. if ((gLocationLat != null) && @@ -314,11 +314,11 @@ class CrystalView extends Ui.WatchFace { var owmKeyOverride = $.getStringProperty("OWMKeyOverride",""); if (owmKeyOverride == null || owmKeyOverride.length() == 0) { - /*DEBUG*/ logMessage("checkPendingWebRequests:Using Garmin Weather so skipping OWM code"); + //DEBUG*/ logMessage("checkPendingWebRequests:Using Garmin Weather so skipping OWM code"); } else { //2022-04-10 logMessage("Using OpenWeatherMap"); var owmCurrent = Storage.getValue("OpenWeatherMapCurrent"); - /*DEBUG*/ logMessage("checkPendingWebRequests:owmCurrent=" + owmCurrent); + //DEBUG*/ logMessage("checkPendingWebRequests:owmCurrent=" + owmCurrent); // No existing data. if (owmCurrent == null) { pendingWebRequests["OpenWeatherMapCurrent"] = true; @@ -352,7 +352,7 @@ class CrystalView extends Ui.WatchFace { // 2. Tesla: if (Storage.getValue("Tesla") != null) { var teslaInfo = Storage.getValue("TeslaInfo"); - /*DEBUG*/ logMessage("checkPendingWebRequests:teslaInfo=" + teslaInfo); + //DEBUG*/ logMessage("checkPendingWebRequests:teslaInfo=" + teslaInfo); if (teslaInfo != null) { // We got Tesla data, process it var arrayKey = ["RefreshToken", "AccessToken", "TokenCreatedAt", "TokenExpiresIn", "VehicleID"]; var arrayProp = [true, true, false, false, false ]; @@ -485,19 +485,19 @@ class CrystalView extends Ui.WatchFace { } else { icon = icon + day; - /*DEBUG*/ logMessage("Icon index " + condition + " is invalid"); + //DEBUG*/ logMessage("Icon index " + condition + " is invalid"); } result = { "cod" => 200, "temp" => temperature, "humidity" => humidity, "icon" => icon }; - /*DEBUG*/ logMessage("Weather is " + result); + //DEBUG*/ logMessage("Weather is " + result); } else { result = { "cod" => 404 }; - /*DEBUG*/ logMessage("No weather data, returning cod = 404"); + //DEBUG*/ logMessage("No weather data, returning cod = 404"); } } else { result = { "cod" => 400 }; - /*DEBUG*/ logMessage("No weather data, returning cod = 400"); + //DEBUG*/ logMessage("No weather data, returning cod = 400"); } Storage.setValue("OpenWeatherMapCurrent", result); Storage.setValue("NewWeatherInfo", true); @@ -642,7 +642,7 @@ class CrystalView extends Ui.WatchFace { // Do we have requests pending? var requestsPending = Storage.getValue("RequestsPending"); if (requestsPending != null) { - /*DEBUG*/ logMessage("onUpdate:Requests are pending"); + //DEBUG*/ logMessage("onUpdate:Requests are pending"); Storage.deleteValue("RequestsPending"); checkPendingWebRequests(); } @@ -873,7 +873,7 @@ class CrystalView extends Ui.WatchFace { values[:isValid] = false; } if (values[:isValid] && (!(values[:current] instanceof Lang.Number || values[:current] instanceof Lang.Float))) { - /*DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); + //DEBUG*/ logMessage("values[:current] is invalid=" + values[:current]); values[:current] = 0; values[:isValid] = false; } @@ -895,7 +895,7 @@ class CrystalView extends Ui.WatchFace { // state of this View here. This includes freeing resources from // memory */ function onHide() { - /*DEBUG*/ logMessage("View hidding"); + //DEBUG*/ logMessage("View hidding"); } // The user has just looked at their watch. Timers and animations may be started here. @@ -910,7 +910,7 @@ class CrystalView extends Ui.WatchFace { } ReadWeather(false); - /*DEBUG*/ logMessage("onExitSleep:Checking pending requests"); + //DEBUG*/ logMessage("onExitSleep:Checking pending requests"); checkPendingWebRequests(); // If watch requires burn-in protection, set flag to false when entering sleep. @@ -981,11 +981,11 @@ class CrystalView extends Ui.WatchFace { var complicationShortLabel = complication.shortLabel; var complicationValue = complication.value; - /*DEBUG*/ var complicationLongLabel = complication.longLabel; if (complicationType == Complications.COMPLICATION_TYPE_INVALID) { logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); } + //DEBUG*/ var complicationLongLabel = complication.longLabel; if (complicationType == Complications.COMPLICATION_TYPE_INVALID) { logMessage("Type: " + complicationType + " short label: " + complicationShortLabel + " long label: " + complicationLongLabel + " Value:" + complicationValue); } if (gTeslaComplication == true && complicationType == Complications.COMPLICATION_TYPE_INVALID) { if (complicationShortLabel != null && complicationShortLabel.equals("TeslaLink")) { - /*DEBUG*/ logMessage("Doing Tesla Complication!"); + //DEBUG*/ logMessage("Doing Tesla Complication!"); $.doTeslaComplication(complicationValue); } } diff --git a/source/DataArea.mc b/source/DataArea.mc index 5ca7d516..5f456c8e 100644 --- a/source/DataArea.mc +++ b/source/DataArea.mc @@ -53,7 +53,7 @@ class DataArea extends Ui.Drawable { mLeftGoalMax = (mLeftGoalType == GOAL_TYPE_BATTERY || mLeftGoalType == GOAL_TYPE_BODY_BATTERY || mLeftGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : leftValues[:max].format(INTEGER_FORMAT); } else { if (leftValues[:isValid]) { - /*DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); + //DEBUG*/ logMessage("Should have been screened, why invalid? " + leftValues[:current] + " - " + leftValues[:max]); } mLeftGoalCurrent = null; mLeftGoalMax = null; @@ -68,7 +68,7 @@ class DataArea extends Ui.Drawable { mRightGoalMax = (mRightGoalType == GOAL_TYPE_BATTERY || mRightGoalType == GOAL_TYPE_BODY_BATTERY || mRightGoalType == GOAL_TYPE_STRESS_LEVEL) ? "%" : rightValues[:max].format(INTEGER_FORMAT); } else { if (rightValues[:isValid]) { - /*DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); + //DEBUG*/ logMessage("Should have been screened, why invalid? " + rightValues[:current] + " - " + rightValues[:max]); } mRightGoalCurrent = null; mRightGoalMax = null; diff --git a/source/DataFields.mc b/source/DataFields.mc index 86b58890..4dede389 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -158,7 +158,7 @@ class DataFields extends Ui.Drawable { update(dc, /* isPartialUpdate */ false); } else { - /*DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); + //DEBUG*/ logMessage("datafields draw Skipping because of burning protections"); } } @@ -813,7 +813,7 @@ class DataFields extends Ui.Drawable { if (mWeather == null || Storage.getValue("NewWeatherInfo") != null) { mWeather = Storage.getValue("OpenWeatherMapCurrent"); Storage.deleteValue("NewWeatherInfo"); - /*DEBUG*/ logMessage("getValueForFieldType:new weather data: " + mWeather); + //DEBUG*/ logMessage("getValueForFieldType:new weather data: " + mWeather); } // Stored weather data available. @@ -829,7 +829,7 @@ class DataFields extends Ui.Drawable { value = value.format(INTEGER_FORMAT) + "°"; } catch (e) { - /*DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); + //DEBUG*/ logMessage("getValueForFieldType: Caught exception " + e); value = "???"; } result["weatherIcon"] = mWeather["icon"]; @@ -849,7 +849,7 @@ class DataFields extends Ui.Drawable { } } - /*DEBUG*/ logMessage("getValueForFieldType:Weather value is " + value + " stale is " + stale); + //DEBUG*/ logMessage("getValueForFieldType:Weather value is " + value + " stale is " + stale); break; case FIELD_TYPE_PRESSURE: diff --git a/source/DateLine.mc b/source/DateLine.mc index 55400b44..afa0ff9f 100644 --- a/source/DateLine.mc +++ b/source/DateLine.mc @@ -87,7 +87,8 @@ class DateLine extends Ui.Drawable { mMonthString = Ui.loadResource(resourceArray[mMonth - 1]).toUpper(); } - var day = now.day.format(INTEGER_FORMAT); + var day = now.day.format($.getBoolProperty("HideDayLeadingZero", true) ? INTEGER_FORMAT : "%02d"); + if (mYLine2 != null) { drawDoubleLine(dc, day); } else { diff --git a/source/Global.mc b/source/Global.mc index c2bd3f8d..526bba94 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -227,12 +227,12 @@ function updateComplications(complicationName, storageName, index, complicationT // DEBUG */ if (type == Complications.COMPLICATION_TYPE_HIGH_LOW_TEMPERATURE) { logMessage("Last one before us"); } if (type == complicationType && type != Complications.COMPLICATION_TYPE_INVALID) { - /*DEBUG*/logMessage(complicationId.longLabel.toString() + " available"); + //DEBUG*/logMessage(complicationId.longLabel.toString() + " available"); complicationId = new Complications.Id(complicationType); break; } else if (type == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(complicationName)) { - /*DEBUG*/logMessage(complicationId.longLabel.toString() + " available"); + //DEBUG*/logMessage(complicationId.longLabel.toString() + " available"); complicationId = complicationId.complicationId; break; } @@ -246,7 +246,7 @@ function updateComplications(complicationName, storageName, index, complicationT Complications.subscribeToUpdates(complicationId); } catch (e) { - /*DEBUG*/ logMessage("Error subscribing to complication " + complicationName); + //DEBUG*/ logMessage("Error subscribing to complication " + complicationName); } } } @@ -517,7 +517,7 @@ function doTeslaComplication(complicationValue) { (:hasComplications) function doTeslaComplication(complicationValue) { - /*DEBUG*/ logMessage("Complication read: " + complicationValue); + //DEBUG*/ logMessage("Complication read: " + complicationValue); if (complicationValue instanceof Lang.String) { // Only handle the enhance data sent, not just the battery SoC (a Number) var teslaInfo = Storage.getValue("TeslaInfo"); if (teslaInfo == null){ @@ -651,8 +651,7 @@ function getSunTimes(lat, lng, tz, tomorrow) { } //DEBUG -//(:debug, :background) -(:background) +(:debug, :background) function logMessage(message) { var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); @@ -660,9 +659,9 @@ function logMessage(message) { } //DEBUG*/ -// (:release, :background) -// function logMessage(message) { -// } +(:release, :background) +function logMessage(message) { +} /* function type_name(obj) { From 2f7ee116551f3f00290ea750fed0574e3fce27a0 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:03:01 -0400 Subject: [PATCH 218/220] Added Venu X1 device --- README.md | 4 + manifest.xml.prd | 3 +- monkey.jungle | 1 + resources-rectangle-448x486/fonts/fonts.xml | 35 + .../fonts/namum-gothic-kor-42.bmfc | 55 ++ .../fonts/namum-gothic-kor-42.fnt | 24 + .../fonts/namum-gothic-kor-42_0.png | Bin 0 -> 4436 bytes .../fonts/noto-sans-cjk-sc-medium-42.bmfc | 56 ++ .../fonts/noto-sans-cjk-sc-medium-42.fnt | 30 + .../fonts/noto-sans-cjk-sc-medium-42_0.png | Bin 0 -> 5951 bytes .../fonts/noto-sans-cjk-tc-medium-42.bmfc | 56 ++ .../fonts/noto-sans-cjk-tc-medium-42.fnt | 30 + .../fonts/noto-sans-cjk-tc-medium-42_0.png | Bin 0 -> 5929 bytes .../fonts/noto-sans-rus-bold-42.bmfc | 55 ++ .../fonts/noto-sans-rus-bold-42.fnt | 47 ++ .../fonts/noto-sans-rus-bold-42_0.png | Bin 0 -> 9285 bytes .../fonts/titillium-web-bold-128-tall.bmfc | 59 ++ .../fonts/titillium-web-bold-128-tall.fnt | 15 + .../fonts/titillium-web-bold-128-tall_0.png | Bin 0 -> 3645 bytes .../fonts/titillium-web-bold-128-tall_1.png | Bin 0 -> 855 bytes .../fonts/titillium-web-bold-85-tall.bmfc | 55 ++ .../fonts/titillium-web-bold-85-tall.fnt | 14 + .../fonts/titillium-web-bold-85-tall_0.png | Bin 0 -> 3976 bytes .../fonts/titillium-web-light-128-tall.bmfc | 59 ++ .../fonts/titillium-web-light-128-tall.fnt | 16 + .../fonts/titillium-web-light-128-tall_0.png | Bin 0 -> 3915 bytes .../fonts/titillium-web-light-128-tall_1.png | Bin 0 -> 592 bytes .../fonts/titillium-web-light-85-tall.bmfc | 55 ++ .../fonts/titillium-web-light-85-tall.fnt | 15 + .../fonts/titillium-web-light-85-tall_0.png | Bin 0 -> 4089 bytes .../fonts/titillium-web-semibold-30.bmfc | 57 ++ .../fonts/titillium-web-semibold-30.fnt | 555 ++++++++++++++ .../fonts/titillium-web-semibold-30_0.png | Bin 0 -> 12388 bytes .../fonts/titillium-web-semibold-45.bmfc | 61 ++ .../fonts/titillium-web-semibold-45.fnt | 688 ++++++++++++++++++ .../fonts/titillium-web-semibold-45_0.png | Bin 0 -> 13774 bytes .../fonts/titillium-web-semibold-45_1.png | Bin 0 -> 12058 bytes .../layouts/layout.xml | 80 ++ 38 files changed, 2124 insertions(+), 1 deletion(-) create mode 100644 resources-rectangle-448x486/fonts/fonts.xml create mode 100644 resources-rectangle-448x486/fonts/namum-gothic-kor-42.bmfc create mode 100644 resources-rectangle-448x486/fonts/namum-gothic-kor-42.fnt create mode 100644 resources-rectangle-448x486/fonts/namum-gothic-kor-42_0.png create mode 100644 resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.bmfc create mode 100644 resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.fnt create mode 100644 resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42_0.png create mode 100644 resources-rectangle-448x486/fonts/noto-sans-cjk-tc-medium-42.bmfc create mode 100644 resources-rectangle-448x486/fonts/noto-sans-cjk-tc-medium-42.fnt create mode 100644 resources-rectangle-448x486/fonts/noto-sans-cjk-tc-medium-42_0.png create mode 100644 resources-rectangle-448x486/fonts/noto-sans-rus-bold-42.bmfc create mode 100644 resources-rectangle-448x486/fonts/noto-sans-rus-bold-42.fnt create mode 100644 resources-rectangle-448x486/fonts/noto-sans-rus-bold-42_0.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-bold-128-tall.bmfc create mode 100644 resources-rectangle-448x486/fonts/titillium-web-bold-128-tall.fnt create mode 100644 resources-rectangle-448x486/fonts/titillium-web-bold-128-tall_0.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-bold-128-tall_1.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.bmfc create mode 100644 resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.fnt create mode 100644 resources-rectangle-448x486/fonts/titillium-web-bold-85-tall_0.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-light-128-tall.bmfc create mode 100644 resources-rectangle-448x486/fonts/titillium-web-light-128-tall.fnt create mode 100644 resources-rectangle-448x486/fonts/titillium-web-light-128-tall_0.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-light-128-tall_1.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-light-85-tall.bmfc create mode 100644 resources-rectangle-448x486/fonts/titillium-web-light-85-tall.fnt create mode 100644 resources-rectangle-448x486/fonts/titillium-web-light-85-tall_0.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-semibold-30.bmfc create mode 100644 resources-rectangle-448x486/fonts/titillium-web-semibold-30.fnt create mode 100644 resources-rectangle-448x486/fonts/titillium-web-semibold-30_0.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-semibold-45.bmfc create mode 100644 resources-rectangle-448x486/fonts/titillium-web-semibold-45.fnt create mode 100644 resources-rectangle-448x486/fonts/titillium-web-semibold-45_0.png create mode 100644 resources-rectangle-448x486/fonts/titillium-web-semibold-45_1.png create mode 100644 resources-rectangle-448x486/layouts/layout.xml diff --git a/README.md b/README.md index dd7a0f73..bff21332 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.22.1 +- Compiled with CIQ 8.2.1 +- Added new device: Venu X1 + ### 2.22.0 - At request, there is now an option to have the date format to have a leading zero when there is only one digit. diff --git a/manifest.xml.prd b/manifest.xml.prd index 5d83b42d..c1752c17 100644 --- a/manifest.xml.prd +++ b/manifest.xml.prd @@ -1,7 +1,7 @@ - + @@ -83,6 +83,7 @@ + diff --git a/monkey.jungle b/monkey.jungle index 2472dcfd..b8aa3c67 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -32,6 +32,7 @@ venusq.sourcePath = $(venusq.sourcePath);always-on-source venusqm.sourcePath = $(venusqm.sourcePath);always-on-source venu3.sourcePath = $(venu3.sourcePath);always-on-source venu3s.sourcePath = $(venu3s.sourcePath);always-on-source +venux1.sourcePath = $(venux1.sourcePath);always-on-source d2air.sourcePath = $(d2air.sourcePath);always-on-source d2mach1.sourcePath = $(d2mach1.sourcePath);always-on-source d2airx10.sourcePath = $(d2airx10.sourcePath);always-on-source diff --git a/resources-rectangle-448x486/fonts/fonts.xml b/resources-rectangle-448x486/fonts/fonts.xml new file mode 100644 index 00000000..d651fc57 --- /dev/null +++ b/resources-rectangle-448x486/fonts/fonts.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources-rectangle-448x486/fonts/namum-gothic-kor-42.bmfc b/resources-rectangle-448x486/fonts/namum-gothic-kor-42.bmfc new file mode 100644 index 00000000..aca274c2 --- /dev/null +++ b/resources-rectangle-448x486/fonts/namum-gothic-kor-42.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=NanumGothicExtraBold +fontFile= +charSet=0 +fontSize=42 +aa=2 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=32,40-41,48-57,44552,47785,49688,50900,51068,53664,54868 + +# imported icon images diff --git a/resources-rectangle-448x486/fonts/namum-gothic-kor-42.fnt b/resources-rectangle-448x486/fonts/namum-gothic-kor-42.fnt new file mode 100644 index 00000000..97fe239c --- /dev/null +++ b/resources-rectangle-448x486/fonts/namum-gothic-kor-42.fnt @@ -0,0 +1,24 @@ +info face="NanumGothicExtraBold" size=42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=42 base=34 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="namum-gothic-kor-42_0.png" +chars count=20 +char id=32 x=191 y=35 width=2 height=1 xoffset=0 yoffset=41 xadvance=10 page=0 chnl=15 +char id=40 x=31 y=0 width=11 height=35 xoffset=2 yoffset=5 xadvance=13 page=0 chnl=15 +char id=41 x=43 y=0 width=11 height=35 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 +char id=48 x=22 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=49 x=243 y=0 width=11 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 +char id=50 x=82 y=35 width=18 height=27 xoffset=1 yoffset=8 xadvance=22 page=0 chnl=15 +char id=51 x=101 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=52 x=0 y=36 width=21 height=27 xoffset=0 yoffset=8 xadvance=22 page=0 chnl=15 +char id=53 x=139 y=35 width=17 height=27 xoffset=3 yoffset=8 xadvance=22 page=0 chnl=15 +char id=54 x=42 y=36 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=55 x=120 y=35 width=18 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=56 x=222 y=0 width=20 height=30 xoffset=1 yoffset=7 xadvance=22 page=0 chnl=15 +char id=57 x=62 y=35 width=19 height=27 xoffset=2 yoffset=8 xadvance=22 page=0 chnl=15 +char id=44552 x=90 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=47785 x=124 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=49688 x=158 y=0 width=33 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 +char id=50900 x=0 y=0 width=30 height=35 xoffset=1 yoffset=4 xadvance=34 page=0 chnl=15 +char id=51068 x=192 y=0 width=29 height=34 xoffset=2 yoffset=5 xadvance=34 page=0 chnl=15 +char id=53664 x=157 y=35 width=33 height=26 xoffset=0 yoffset=7 xadvance=34 page=0 chnl=15 +char id=54868 x=55 y=0 width=34 height=34 xoffset=0 yoffset=5 xadvance=34 page=0 chnl=15 diff --git a/resources-rectangle-448x486/fonts/namum-gothic-kor-42_0.png b/resources-rectangle-448x486/fonts/namum-gothic-kor-42_0.png new file mode 100644 index 0000000000000000000000000000000000000000..5f09960b2eee7c8e792ceedb44c37edcd8cb7301 GIT binary patch literal 4436 zcmd6rhd0}c!-v0#YKU2T&uGP-wH2iVRkLcRy|x;yTA{>NS|ir2J)%Zylr%O$%T<)3 zw-iB9J5g$f{ODP)f9y6r-C+}2rY3t!!RKl4wt;bbMkvHxjpZR7*(J0Nl-<~K$~F30_~ zn0EoE>62M}4M$9h?;uKIOO4xDO|iHY=9AF5>GJ-joPRx^9gnFM&U~`^(&foosD1EC zi$qC{1*S+h^`_a@h#n$j+2BzvS0gjxQ90~wC5H&pTv{qlb?XBghNB$a|8*qP@TPXA3;Osyh4zc0&-5r92|Od%Xqr{7Mwe=ME0s<6Q_I+?6$Y z{_&h83l=hlSzOpyH?{SIm(Bef^nSc!U8hUUmFZM(lM-k71Y&Xi=pl;sLZ0S2n4L;T z^J|n|Xw@O)%w@TKhu{tuS zUDmRQPiZ$?CxqI5UciCYdEV&1xJ)NMi+O~wf|^@RX6dAOU#2j~=`OmRfS zR&+?sTaaa5B_!v1cVoDH$H_y)WD@-S8Uj(kkbokvW2R?lBvE!4KHz#Mh9Wv4;!`Lc zkd1Zk00&^Ou>fOsk$?M)ytv`Q@mq9mL&2Mphdu}c>!)ld7bs)_m``Gp4@l*c@X2gc zsz!Hl@o#_Nnb}|}sdb|X1LHFO37;U2fIkDFtx`UG_ewV8pugPs*xWK%M!RT{%dY^n zMCIZ|=96FafbV@k0HPd9Q`*iEK`0>noHl|knO`FU6 zGP^T^lBCUZ&Lh(%-pOF-Kzhua_?T9Jwd2ytw&4~dWG19fpUkP}dg@>=8^XeTHT?U+ z<88X#{#iT?j(iT)`#lW2BDCB(9}Zd8Hy%d{WpVU=isV;QIXANo$;3Hg&fYX1@e8KC z;^k0>)Hi|nB{oN=pZmS(lM{wiF5X4bFSe~#OSSNPEqbGeDHWM4_@9R}!4L736P|0X9q2_3pf5YKy@-FlW zE|{c_1bRe>5A<&s0>v3_i1}0D=G_4{Y41<;xVZd4IVz6@;}O=4BC`<~+-xUl)91l#3K_B2b^MHc_@TWp+x%{u;Rw1MgX^I~YheC_7l0p#BF>tRZ7|r5 z3Uk`kjI9lv{pdql2$|ZYhWmahXV;icV2*j&=hyk8Z@KvG@LnmDKLQh!-vZvyuKFyNh~BZ5fJ2v}hZ(jd%mnwceY{1`Xq*hEEs zxm&cUZV=>D;N$`<$VDgZPA}wTCbp{lkFCgk6j+ zZyl;*wSB)ER$CryDjiSP$o!~14+M9t0!X=R@`uB0%HCa0uS4fJd|Qt%AJQsJ3oD{z za&&mWzlD>r+a<8~e&gx8PPg_X*5lSCPokKE*n$`dH;5F=C%1wggo+>2whB>B=XcT> z#!tA@Eck;%AVAM+<@cJ(4!>`&(|#96x#3g}A}+s@Dk%EM1w)Z6VHA;h@&bPcjYObQ zj)TPsrEe+YtQMOd|l0!dikv;&O zu_%l**Af|)L+|}O6$X9+f5n8rf+!#4s1p7$-Q6shxIFftvSVfKN09o{G~I8`^m{K_ z)k3GLm$(Di_l(NyF@R; z=yYl%q(`n7TVVy?itOr#TnK>X#@m{7fLa9Ks)8LD=;aV`BX7zsFfT;E= zrOT*okOrkvQ4o1A;l^m!h?X&LOPFKb;QP|^?q(ZXH}9v)#HyD42Y<##%w~dr^{2SU zke%&6*!emi21$mlr26pl<<2|jYTnsV4wz-GeR4Ok5WcOnJNAHR!p#__QJQA#*tWbA ztQnY_V_xhSQd{F^UD2SVbG?#^Q`N#6Ui|0{ADYg;TG;$M(iu~TzcM!evv`&0T=rk zGzgzdZy(g1exOc@3-3#D)uUyT2lBRBq2oG2lHr}Wf;sEChdLubUDrw6bab*)>n~7L z_HK0V_g`TP3@-DQ!8%JIglV+Exg;Esf$I0_mT!AzDuYMfehMqe#(Dv+na-3^ONml> z&<0mNc9YN?US&_}-Zz5lW?>tPrgGNSbIdlY|6b%Sm3)WBv|&G1=^bB3+?7}ob5|MR z?W{0p)5pw%{XW1BA*p#Mk>1%7@@H?y)lybNXe*qYm>;>#0U2(; zbP$JhT7m(Kn?(yu8|IDT=;F;I=~s6|8fA9sjzBdm(o0)@qMX6B3T()~Sar02W>S9n zOB2_U`)%}o(-26PaPDqK&gDrgEAFE2+N{0G0$FHukFJT$wqt^c-;F&idx)X*Ri<$$4gAy6aIQkC3j- z!Kz&ZC48$|5^&_!n{rq-U+Tv=2ayTWdoI_6)@@*LD@NX)uQ#GAg!}23gF>(zmNyXH z3oA;9AB4$g(i~)F+XR^yk2l~hhpCXaefmAdQ(Hti1o4GONAO0V8x?>`&WpjV`0ndH zpFwdWth;;L*{LE&&hapR*&`Y|D$P=ZdlJ}m1(Opb{X!2UUo9)EEfE2E%WtO~fK*J( zAJ5|`GRY&G6$+0r4j&vol?3jAh!9i@k7Prhc1D>22B&@BVTCAfsh8DCJm?KW$Z)-N z&dSUw;^YI{VQ^nMNqn{&iRzJGlQrJx%l_~pFRE=Gzt4-*>xQX@zanEYr|B-CQbv1h z#Gg0CU-qmT!Bcz(j=?Qqvv|ZLE8*2R-O)nL1NlH8fwRf#a}y}!ah|mz#ty?UTCyb% zp*lg^)s-a>OcL&U39xR`qK*vWcmJp%QIzt4tm(IoER_-|tsMevlq|UUMO7;~fgS8} zP}%2USJG7hCWXiQ{{&}9&75wEM@GknVSv4V)_}2f_lvBb1tXezJi-XU&AdOZiR1^a2}~6XlcK?frRg!;`#07>r|i}k{ici7 zgJ{~4_4sXia?`4cl0o~_c#d%#S?8!rhXpyP-h6uPiqOd+ApOhZ#u+aG|M;}$hWweg zHxr?8VN9aLT@jmp%S>c|pFf(z@)lFsTp=w`%A6|I!QQ5D)6@bIt|0a`0`PxnaFREg z(IoHWV&2-CF8g?2CfW=BfrnxW9kRULdS}>ZEI0g#{7v7Ps6diC8=0`+hc2oiCeV_~c&Cde;6Qm5fS_Hg%&i&;?Sbp0s15eY_ z#wmHWk_9+@v5?&v6w(^6rxW6#ZJIeB_$-2+ZvQiVOgwHjKMO;5E}!ktRZ5T3EvT%i z*96d$PU>=KPhyvmuwt~jE6Kl2X7ra9au4Wl&^MR^r>)x$<6X!XhfL2U92XZ4@FF2o2l=e&ZgPCvYNILids=&|kZ6S4m zK5*DP*B~;E_@~zz!zTPu*X(L`MEL5vW6jV(5}xD0IR%|0vCXa1m9+}FcFRQ4 z$AT8y9^Qzmzy!IYLab1gD>g;9*vruqx1@8TzK+Efvs+80WZ;_kkGUr{dcP%YQFJ*8 z&lW$KU5&|?r8lr=57@XbGdB-Y^?%1F_;=UmQP1>v(G2-Hf&7A-^1SRPN#d~Kup%He zps1(L)%0-#-$GrC2|4oe9pMknv*P>Tv4#sT_xAl~lAWqf3XEHvod*;c|3B?zuhXS4 XH4*=sxsk{2|Lzimk%eJ{0W$7?Yj=5c literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.bmfc b/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.bmfc new file mode 100644 index 00000000..9b85ec32 --- /dev/null +++ b/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.bmfc @@ -0,0 +1,56 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Noto Sans CJK SC Medium +fontFile= +charSet=0 +fontSize=-42 +aa=2 +scaleH=100 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=10,32,48-57,19968,19971,19977,20061,20108,20116,20843,20845,21313,22235,26085,26143,26376,26399 + + +# imported icon images diff --git a/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.fnt b/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.fnt new file mode 100644 index 00000000..ee5e7127 --- /dev/null +++ b/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42.fnt @@ -0,0 +1,30 @@ +info face="Noto Sans CJK SC Medium" size=-42 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=62 base=49 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="noto-sans-cjk-sc-medium-42_0.png" +chars count=26 +char id=10 x=242 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 +char id=32 x=245 y=33 width=2 height=1 xoffset=0 yoffset=61 xadvance=9 page=0 chnl=15 +char id=48 x=66 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=49 x=236 y=0 width=18 height=32 xoffset=3 yoffset=17 xadvance=24 page=0 chnl=15 +char id=50 x=0 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=51 x=22 y=78 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=52 x=219 y=38 width=22 height=32 xoffset=0 yoffset=17 xadvance=24 page=0 chnl=15 +char id=53 x=44 y=77 width=21 height=32 xoffset=1 yoffset=17 xadvance=24 page=0 chnl=15 +char id=54 x=87 y=77 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=55 x=108 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=56 x=129 y=76 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=57 x=150 y=74 width=20 height=32 xoffset=2 yoffset=17 xadvance=24 page=0 chnl=15 +char id=19968 x=209 y=71 width=39 height=5 xoffset=2 yoffset=30 xadvance=42 page=0 chnl=15 +char id=19971 x=157 y=0 width=39 height=37 xoffset=1 yoffset=14 xadvance=42 page=0 chnl=15 +char id=19977 x=181 y=38 width=37 height=32 xoffset=3 yoffset=17 xadvance=42 page=0 chnl=15 +char id=20061 x=0 y=0 width=39 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 +char id=20108 x=171 y=74 width=37 height=29 xoffset=2 yoffset=19 xadvance=42 page=0 chnl=15 +char id=20116 x=142 y=40 width=38 height=33 xoffset=2 yoffset=17 xadvance=42 page=0 chnl=15 +char id=20843 x=35 y=40 width=40 height=36 xoffset=1 yoffset=16 xadvance=42 page=0 chnl=15 +char id=20845 x=40 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 +char id=21313 x=79 y=0 width=38 height=39 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=15 +char id=22235 x=106 y=40 width=35 height=35 xoffset=3 yoffset=16 xadvance=42 page=0 chnl=15 +char id=26085 x=76 y=40 width=29 height=36 xoffset=7 yoffset=16 xadvance=42 page=0 chnl=15 +char id=26143 x=197 y=0 width=38 height=37 xoffset=2 yoffset=14 xadvance=42 page=0 chnl=15 +char id=26376 x=0 y=40 width=34 height=37 xoffset=1 yoffset=15 xadvance=42 page=0 chnl=15 +char id=26399 x=118 y=0 width=38 height=39 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=15 diff --git a/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42_0.png b/resources-rectangle-448x486/fonts/noto-sans-cjk-sc-medium-42_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f10704df52d54dfa7443b3ac8251b24312bc3a6a GIT binary patch literal 5951 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 literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/fonts/titillium-web-bold-128-tall_1.png b/resources-rectangle-448x486/fonts/titillium-web-bold-128-tall_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c57427ff59c344115157acd66b54383cb15d4e09 GIT binary patch literal 855 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5890C>L#5>RT?`D&a-J@ZAr*7p-U%#vtiaQd zxOVw>qiUng>c*Cl-xUjQDOfrfB|HA9*PqLHSc6IMc&2tz#6Hv4yOuvQot>CD?-9r3 zs}d!_IddyKkLfHnFgtL^tU2mmUipFP7t>s3>G^Ix_i|~1O@yjIX>iu8lHA>U%sH*6=sAO1AxbuzpLp!_!aYyO}pR8?4}d^!el4 z{!><;BbeTb2E2H8KbfiNmA)-kSG8=_Dmzi(0Ezm}wBlcvzwxXU_WmrW@oeqm?>Sq) zS8~|BX;`o;xsuH`+Cczhh4oOV^3D9M_JYX1~d3AGf~Y z^^HGYc_%f@=XZAedh}JKp68^&7H>x^>JJ^`;nMX4%diAqBLndz5t?GZ*x;LlaFYWns)ZmdKI;Vst07E)* AlmGw# literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.bmfc b/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.bmfc new file mode 100644 index 00000000..9b48b734 --- /dev/null +++ b/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web +fontFile= +charSet=0 +fontSize=-85 +aa=1 +scaleH=105 +useSmoothing=1 +isBold=1 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.fnt b/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.fnt new file mode 100644 index 00000000..8f6efb2e --- /dev/null +++ b/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall.fnt @@ -0,0 +1,14 @@ +info face="Titillium Web" size=-85 bold=1 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=136 base=101 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-bold-85-tall_0.png" +chars count=10 +char id=48 x=0 y=0 width=44 height=61 xoffset=2 yoffset=41 xadvance=48 page=0 chnl=15 +char id=49 x=122 y=62 width=30 height=59 xoffset=6 yoffset=42 xadvance=48 page=0 chnl=15 +char id=50 x=217 y=0 width=37 height=60 xoffset=5 yoffset=41 xadvance=48 page=0 chnl=15 +char id=51 x=177 y=0 width=39 height=61 xoffset=4 yoffset=41 xadvance=48 page=0 chnl=15 +char id=52 x=79 y=62 width=42 height=59 xoffset=3 yoffset=42 xadvance=48 page=0 chnl=15 +char id=53 x=0 y=62 width=40 height=60 xoffset=4 yoffset=42 xadvance=48 page=0 chnl=15 +char id=54 x=134 y=0 width=42 height=61 xoffset=3 yoffset=41 xadvance=48 page=0 chnl=15 +char id=55 x=41 y=62 width=37 height=60 xoffset=5 yoffset=42 xadvance=48 page=0 chnl=15 +char id=56 x=45 y=0 width=44 height=61 xoffset=2 yoffset=41 xadvance=48 page=0 chnl=15 +char id=57 x=90 y=0 width=43 height=61 xoffset=2 yoffset=41 xadvance=48 page=0 chnl=15 diff --git a/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall_0.png b/resources-rectangle-448x486/fonts/titillium-web-bold-85-tall_0.png new file mode 100644 index 0000000000000000000000000000000000000000..4a14baf89231656821b650cf758b991ea3e0c461 GIT binary patch literal 3976 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 literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/fonts/titillium-web-light-128-tall.bmfc b/resources-rectangle-448x486/fonts/titillium-web-light-128-tall.bmfc new file mode 100644 index 00000000..fbeca927 --- /dev/null +++ b/resources-rectangle-448x486/fonts/titillium-web-light-128-tall.bmfc @@ -0,0 +1,59 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web Light +fontFile= +charSet=0 +fontSize=-128 +aa=2 +scaleH=105 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 +widthPaddingFactor=0.00 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-58 + +# imported icon images diff --git a/resources-rectangle-448x486/fonts/titillium-web-light-128-tall.fnt b/resources-rectangle-448x486/fonts/titillium-web-light-128-tall.fnt new file mode 100644 index 00000000..6e215bd0 --- /dev/null +++ b/resources-rectangle-448x486/fonts/titillium-web-light-128-tall.fnt @@ -0,0 +1,16 @@ +info face="Titillium Web Light" size=-128 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=2 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=205 base=153 scaleW=256 scaleH=256 pages=2 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-light-128-tall_0.png" +page id=1 file="titillium-web-light-128-tall_1.png" +chars count=11 +char id=48 x=64 y=0 width=61 height=92 xoffset=6 yoffset=62 xadvance=71 page=0 chnl=15 +char id=49 x=221 y=93 width=34 height=89 xoffset=15 yoffset=64 xadvance=71 page=0 chnl=15 +char id=50 x=56 y=93 width=54 height=91 xoffset=9 yoffset=62 xadvance=71 page=0 chnl=15 +char id=51 x=0 y=93 width=55 height=92 xoffset=8 yoffset=62 xadvance=71 page=0 chnl=15 +char id=52 x=0 y=0 width=62 height=89 xoffset=5 yoffset=64 xadvance=71 page=1 chnl=15 +char id=53 x=111 y=93 width=56 height=90 xoffset=9 yoffset=64 xadvance=71 page=0 chnl=15 +char id=54 x=126 y=0 width=59 height=92 xoffset=7 yoffset=62 xadvance=71 page=0 chnl=15 +char id=55 x=168 y=93 width=52 height=90 xoffset=10 yoffset=64 xadvance=71 page=0 chnl=15 +char id=56 x=0 y=0 width=63 height=92 xoffset=4 yoffset=62 xadvance=71 page=0 chnl=15 +char id=57 x=186 y=0 width=59 height=92 xoffset=6 yoffset=62 xadvance=71 page=0 chnl=15 +char id=58 x=246 y=0 width=9 height=59 xoffset=9 yoffset=94 xadvance=26 page=0 chnl=15 diff --git a/resources-rectangle-448x486/fonts/titillium-web-light-128-tall_0.png b/resources-rectangle-448x486/fonts/titillium-web-light-128-tall_0.png new file mode 100644 index 0000000000000000000000000000000000000000..18af974317889a72df074e5da135e138fa3dfaac GIT binary patch literal 3915 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 literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/fonts/titillium-web-light-128-tall_1.png b/resources-rectangle-448x486/fonts/titillium-web-light-128-tall_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e44170509469abdc7a85b8c977e3917e21b3c55e GIT binary patch literal 592 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5890C>L#5>RT?`CN;+`&!Ar*7p-gcaH%RqoN zp!HGQi?knU7V65~Cs;gsrh4_>&fL3w`+x88?>oFxS6RWzW6INi>w)68PKi|9`MxK(Z}CpvOH9|@4lLa^xpKV>d+}8! z_nD0KW`DFUC?!mBJ;0?~@IkENBGXw0-3tsCnA|fP_rGO(UG%B;y3Fx~tbEs)?k{)9 zJzjZVqVOKqgTM=Q4b10qC7X5=5q(!F5Jfd z>&NR_=eHTFS)b_~xGb{btp)25i>9;gjyK&Ma@}xEM&Ot zf4I1>!S%SEMmeL^H^-IS1uu8(zQVd=>+IiOG&D*Xw?!wsV=CElU=8b!oqQ|aUKSBm zj_~L9v1Q8oZP0#{igu!a%2(!c>rxw?_xdwH>OEckT-G@yGywp4XZL*o literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/fonts/titillium-web-light-85-tall.bmfc b/resources-rectangle-448x486/fonts/titillium-web-light-85-tall.bmfc new file mode 100644 index 00000000..07f5271e --- /dev/null +++ b/resources-rectangle-448x486/fonts/titillium-web-light-85-tall.bmfc @@ -0,0 +1,55 @@ +# AngelCode Bitmap Font Generator configuration file +fileVersion=1 + +# font settings +fontName=Titillium Web Light +fontFile= +charSet=0 +fontSize=-85 +aa=1 +scaleH=105 +useSmoothing=1 +isBold=0 +isItalic=0 +useUnicode=1 +disableBoxChars=1 +outputInvalidCharGlyph=0 +dontIncludeKerningPairs=0 +useHinting=1 +renderFromOutline=0 +useClearType=0 + +# character alignment +paddingDown=0 +paddingUp=0 +paddingRight=0 +paddingLeft=0 +spacingHoriz=1 +spacingVert=1 +useFixedHeight=0 +forceZero=0 + +# output file +outWidth=256 +outHeight=256 +outBitDepth=8 +fontDescFormat=0 +fourChnlPacked=0 +textureFormat=png +textureCompression=0 +alphaChnl=1 +redChnl=0 +greenChnl=0 +blueChnl=0 +invA=0 +invR=0 +invG=0 +invB=0 + +# outline +outlineThickness=0 + +# selected chars +chars=48-57 + +# imported icon images diff --git a/resources-rectangle-448x486/fonts/titillium-web-light-85-tall.fnt b/resources-rectangle-448x486/fonts/titillium-web-light-85-tall.fnt new file mode 100644 index 00000000..4a1645c7 --- /dev/null +++ b/resources-rectangle-448x486/fonts/titillium-web-light-85-tall.fnt @@ -0,0 +1,15 @@ +info face="Titillium Web Light" size=-85 bold=0 italic=0 charset="" unicode=1 stretchH=105 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=136 base=101 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 +page id=0 file="titillium-web-light-85-tall_0.png" +chars count=10 +char id=48 x=44 y=0 width=41 height=61 xoffset=3 yoffset=41 xadvance=48 page=0 chnl=15 +char id=49 x=117 y=62 width=23 height=59 xoffset=10 yoffset=42 xadvance=48 page=0 chnl=15 +char id=50 x=0 y=62 width=36 height=60 xoffset=6 yoffset=41 xadvance=48 page=0 chnl=15 +char id=51 x=168 y=0 width=37 height=61 xoffset=5 yoffset=41 xadvance=48 page=0 chnl=15 +char id=52 x=74 y=62 width=42 height=59 xoffset=3 yoffset=42 xadvance=48 page=0 chnl=15 +char id=53 x=206 y=0 width=38 height=60 xoffset=5 yoffset=42 xadvance=48 page=0 chnl=15 +char id=54 x=86 y=0 width=40 height=61 xoffset=4 yoffset=41 xadvance=48 page=0 chnl=15 +char id=55 x=37 y=62 width=36 height=60 xoffset=6 yoffset=42 xadvance=48 page=0 chnl=15 +char id=56 x=0 y=0 width=43 height=61 xoffset=2 yoffset=41 xadvance=48 page=0 chnl=15 +char id=57 x=127 y=0 width=40 height=61 xoffset=3 yoffset=41 xadvance=48 page=0 chnl=15 +char id=58 x=145 y=62 width=12 height=61 xoffset=3 yoffset=41 xadvance=12 page=0 chnl=15 diff --git a/resources-rectangle-448x486/fonts/titillium-web-light-85-tall_0.png b/resources-rectangle-448x486/fonts/titillium-web-light-85-tall_0.png new file mode 100644 index 0000000000000000000000000000000000000000..14126c87a9bc2581386cded84ac23f761487bdcf GIT binary patch literal 4089 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 literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/fonts/titillium-web-semibold-45_1.png b/resources-rectangle-448x486/fonts/titillium-web-semibold-45_1.png new file mode 100644 index 0000000000000000000000000000000000000000..96a819a1ddd605b6667d514fdfe299e9de6c5c28 GIT binary patch literal 12058 zcma)iRaYEL)9ncEK>|S&Gzsny2oMM|A;Db-cXuBi++lEc3+@g>aCdiy;O_9{UFQ#+ zzUZ!tUbVWbYE^ab+97f>lGqre7ytkO8zS{x0RRC06M+D1@C-EA`f@E!p9{!Pg> z?Ks^dji@L2r6cX9ME5tTaFo9NB8KpH1|l@oOy)V&`dV0@b>4iV%|ZWMez>hREko4ebFdPoERKwqP)0&Z)D`fX<8rMmys^ z5G6e+m}OIw7pU{SJZYcm#yom@nK+37B8w-KYvSkM1D{Rms6g@23tbNSa%2TDPqX7d z9CM$kLauk0yWph7@p)CFG}no={4Q2)k;!l+?KjPRDZj5sAu0G?>6XBxhGdh~jwaR# zMi6j($=Gc=R(=0@C9j0;00h%vh8qX1u6fq4bC@m6+T)BA*p;h+#l}Ko2Ry)#f|;ivl6dkOb_y4WqhbdL*cBmLAQ85QvD^jjTOjR#(^} zBk)d%{v$P6dmVMl7FgYAUoaSbRRyWpHE~+&)mI@^e3ZRblU1Vy zslDe^4}SQ%ie`6X{z%zrx-kw)o7HxeJ|Qh;mS3jr(aDJj(KdLO_(Evaf_yVlncq$n z-4hSXl_+R^rR0h2wSs@f!$m{qlJaDJ<(!f`o&Kg6doXG>eO7g3VbKr9NRP_!D2&Q? z`szag;m+C)Yx3%eG4iOlvQ}4Ao4KQwuLanfDWMmU3RI>(FV%Zr8*tY+Y(M{zueKj+ z+@5d0`{;b*6d#Wq?mTKZ7u0QLTu~J3)P_q>Ji2vmG01SWOg{OR=KeQI7B{j?({1M_+ho*qM z&A$IKANQ18Z3nq}eof2{7JAR^-qroolyk=n(A;g+YKUKHIa+P<$n5DMuEvzVSft#Q zE$s3wvzgyU-Zg=L6+9kSfR&igMl{;$N~!N((md{MwgH3$^S>Pa2g%Mw?x8<%yh@}k z97AUeJ?M~vTeFJfBSEWa4?t?Pkcjw=8aq|Om?X!~j6J`k+)qG{uoNF%6k83wrh|J< zSRWPa6eyVV{QNqXwJvi;4|~QK7HlD$cO@cMMLE+tAG;37h5}mw(SLR2Rt0c?i!3@o zGguja-x%vVWK4vkk5Pc(*G+twdK6d}tfu>9;AQtw3-=@WSRA0F9Hj)~c@0m56gGmq z-RdHoWi@UNGr(*!O*EkJSH4>Tl41~x2*a$9)leR^&}`={I<;1HFA5bA)e|z4q4VL9pU$_a-e#&Xt&(DpD-)?fE0A29pupiD;N@givgKyp z%ImAAcesmH-TLR`A_IyH?z#pl{D}VqK_tfBgUvb`IF)89<--6hA!6uX__61(c2K@_ z3GBq?#aIVB?$y-O1vdQE4e3l|zsPF(uV({97FmtMx+T+LPH%oq5up>y;Ij(Th1n6qxP;!OKCg7?KW|9)yf*8NUr&-2KzU;O%w zNXEc8GCVKrzgPmg18nL$4tg;}KtwjNc@ssby#Gs_52daf1A;SBiwxKr+n3CJX;NH9C+frC@LcY0o1CM86C)nhH4kt3WuI zA5Y;*Fl8_((f6#>K$1q&iIUX!pbF>N{sChV5ZEPYEG^{_GWW<|FE zfFdp&gcNA)gAUr6_P?oXz(DpYx@H_X_lH;zPRI=7AGl%L>N_kV=fm{IJdMLLR8p_oL3CL_D$ZHC?YgbW zF%92Q#_!llPn}GbR6j|POrg6gT}}=r0TQ)&V!i=h``P<8%kGmz^xMvI6T|F8w&COS z&fz4EbqTZxRtGpj(Oum3p+{;a;N3TOJo-e;;O;qCK4e~SNjxCgdZ9-jsNa0v}dSjqesz#qKY$+}zmr zu=ZUCzp5Xo2BceKHWVKHFPWVuCjhCy)6C!$L0}r%S;^l)2e#>c06$h|J=%P0xUKLN z`#7M|?491&xREeRK+FQDe@A$QkbkvxSXyghp&c7gRUm0vj#}?7iR$4q>Ufz)XGT#e zqj1Rb7b#r-i>5+Yo0!t`>O^$|Y60#YFKo~Ec3~zR!6`EEuH^!!rxR`66sGFS5Ae!O zo;1O3vD~hVbs5B_T1I+uEF`QWs8ZlaXz^Z1K_F1)7Gmm}+?OM-*6LGMY5tWHZeP0O zpY)uA18$=9u>*uNT%i`AEzabh#;y0dAh{~4Xg8p%-c&}VuG>2B_fwb1tB={OrjJ*^ zp>*&RRbeIy7sbI{bl^{9lC3gRcYE4A?;~^fo)}q&PhNVoyUS&mzzuw;KW#FdN`>^K z-0M%-)5FK4g9PGS;Ty~NJk9i_E#LR-WI8oHEf{sz~5Wc5HJ)dv%LQ0rDB(O&(VcL6T==HS*e;RbQ^ zddzu4`Wv5@RswRUfbZZXfalf&yQp~Mwq_Lhi_X@VlKypH{uC>SrG4fGQ~-LKY%;n= zRkrQzxzA+w^~6B`q01EYp2q}4^8RLLJQV*0)(xwx_>ZfQKc; zI#B{4rA-7+I#4N>tdVnKutUAVQykm-%oD9RXbZqb>o-aTfz&DPSzfHizy;XXpdd9@ z#77WC;rWSwx{UZ3-AGjjy&g4*j6S^7dl%~?>^s4KvO>RlZ!XXVHFx;G0#az};=ovm zpv$UGC5VPKuCdglky=eq?)&hVyg++s@V3C@f290c@Ic}jq?72pSLW}Oe_qmPPb0!^*P`6vL^1X4QHQNj*VVIcQT0M5N51C0@x zCu_&+9nO5MSZBHw$P+X^z~!RqgLLCCy=?)cU!;Ue-*7qM*c!5%*NF+O3`p_kw);`} z5{V>{nvq_9_*cn$MHGIy;`3X*tDGZI1nT!+$b$35uRtvS(=L7wWFJ6{1M8xiqUWbd zvSC1TUV-ChKdguZc!hG!w0Zx?_cq+B>~>|gn`lZ z=PLTPw@HM>iWppMz0tCm3{ks7>iR;oT)?6h?wW4recGE_JGL;K!>F&p(x9(Q?24T4_fF(t!_+m$odvuO*9nT7P2zIVK-ndsCXs3-PH{yO`$(%+W629%%l+ ztPK|*C=~f`^0rSd0a8J~=O||n_}GFfMiJA+1Yh}?T4c7>O&80sCv9YKPw zIF)Xs=W6G>9rS4->;HWN7*MbDOay3aiHuI)U!BzeAnJ0#MIP{aq^D>AM;2K8yA~6)aJx+z$ef8(<lI*mEUSq?ZcQ=lm-c6y#q-_i!j=I9}limjGTY07-nJ@>GuBaoENtlFbo9$pR_)Xd>Q^T9Whhb@^@CTqTx6#A96<>o5NL#pzv zrqfc18$t?1SVGKg1&taY@ZYd(_S4gpSWJ9`DdaaZ+%rWMKts!|ygPh=@m>?Ry?~~a z+kIlW#<#kd*dyIzO&XZM5r#4c{v%6z9C z(y%t`w(HBcUo_Ltl7nEL4+h>(1cu@A0O zx2J$*+n3(6g}z_X5mQv1*;Is~bS9z`+f!Oa=bPTgifS*Gz~y^b@&zS2qO_}A>m>8x zX+m*~gNQNcMUAh%Ji~2uqo6hU>r0pVDCcD`#aX8AO~(DRhTg(fFgz%|n(Ws#)jhMI z*VUXrq3L4l-%rBQ4xef%$p2-<}Fk|Bjq#PT8ARIqC57 z?Gq`_OBub-sPjCj+?$Lfo9hI$zRK@3;W9ydDK9T4+NmjX&#FgOG9Rnn$aG1eu_wr! zwq<`IQMi;i{i4^4j)|oov&Bo{c4y`%HHgUAv?I--x_FrUV+D-B&1~pYyINx98B(m1A z)03&PG(IrF1}8XG+`|~=1o_@;tlwZ}T@=gdi_H_w&xJWH;F(Xkd^aX|9cD2%s_+B_ zFW-+qFT5dQ`#))Tgi8DtVn7X=fF?8A18Aptnq&@Z0YnUze{ar3fAHb1_2+@I|M@>DCb zpeFvTNn6}mD4#UQ+a=r~r-6+4GGJ1!#RT~s=^VxkSF#$3Hm;jlC;x@GO5k0Z?i_(n zr}T~%rgmL_2@l>JNqSRlHU_-y8TY$?yLIH`;&EMyKojVxitWilD1FmT&0FI zk2kMrI!r~6#uDnhRJN&o3dr%BQiO9Y3ka5qD;N|&6l!d)Or!H!a>Zw)6xMUz8PFxu z0xk&}Ng_mgHO_m>aGgIuzAR*7{v2{`92$xl=ylx-cbOw0MMto&ZnPZw%4mN99kxY& z5b9RD_XYTzM`c=rzhDnuQUm?Eie#*K{?q&xxUI5AX&XxAJvoO9?^16ziA0_!twwq_ zBE$(8{XpP+IgEV%p*K~i}!l89!zmzYrDD}oSz&Q z{yT!h&1ju7wpk?3$x;8E4=1#sUPPv=*XQX<0MR75G7r*iD@8@@>LnnmU(IV8>xN#w zO8k0h>MK7qbKJ3(&~y`AujrMhJcg2iZ-151ijK!5f$oO8Rkk924pUJING}+I zbM0MPkI6i)GtG-j8!x84zJf;eL#CnYZw!@kp?0IpacKu2TjdO)bzFE}odj{KY5rX0D=ABx zz8~Su0wURg7BZq-fU=z>xGT=MofY$az`vfL$T#WSO342!w}(ih7<#TJ7a~aV9e!^c z>eIXRVc%8|UTarq>YqM9RHhwRsRbHQa{ACvJa2#SFFgjQx_)T(HTv?Bv3&RTOzaIdSLZ^KP7+5bs z6#f;U0ihE%(sR|v{66dRB;XoWPVhFDX&!4L5X^*f*W}}hg7{6k3gR1#IgbZWjU$aS zf24b+fYFm(&{zJ@L7KQHO-O_0*;g34vI4f~%s$hWc6ADGQ82;tup@6=b7{qBs$H%`Z;`53lC`_vDrW1Ej01$%@OQTe~++@Elm}_GN!AJ(n1vC;%~^1ZPL%; z;CTVS|3ciQ0DIE#-TSiMBXuLexE5r`*bpoMI~T7krO z`9ZO|Y6~m=ziZPt*f zZg@WMxBq4bt11F+e>^T-v?k=Du zacEf~wy$|wFvb!Dd)&-!mpv(DQUhQWO-A$ky&merjl%N!f<*pXN~N-r4jY* zII$ct7iz9l>p3Q2hQBcWML>5RM0%pG=mXP$AxCnj_2Au4`q*S#=MWdgkB{#gWJ9p` zY`?4U1@$QOlPB8@{G1T%qQiYcn)kU-lTr&;a6h4e5WAd!{5>yPoH~CWv)1NkZNY>E z7#M*n?%Lx04SJ`|cU2Cs%+-U2$`3){RIT4i96RgbNJ z>JI`%@zlQ4^eEu&AD{F++_f*RFf2#v&Ma!xhp0TymEqecmXKqv!Q7x3)juYx-cjk_ z>9N?TsKZ7XfvZ=MTDakB%G1j@Y}2Wbh|hhRYc}%uw{c>=*&R#meg3GCk1Z35_Dm8X zT|3&?=Z9P_#cOteN7=l4`nS(WL%MbQ4JP|2=Nkxb_ENIAWvD1`{2HJ(U~ZjPQs8q( z$>Jz|68^^=>rlH7J~hcM1M#Z zKwp`b%C7?>H4{43iID$xf$#&c+?b(|&mgPqdbqV*IcWAA=-4Mk5rzHx=e*+IjYgst zUZb=}7@+a<1$D@Sf^gl?%1_ajDH@XWE9n?`hHv&m(d(A;CFWfd2xtYCIM@i}f?}@Q zX@8+<#4RDA-W7MbHr3Zd;D6I>`Rd4Mi?i#U(Qn8EIyDG?9}a9FD5KpbGs@tzy{+D3 zw`t8cN?#HI%Z7}w4Y-92-%Nr-TBg2>@a^fk21B0!==~U*>Dv69hlCX6YbX=$&uHvP zY&h3s5^j!|9L58S{jU@-v607w{U#BNqr>Lnh5Ro=+VHaQ0I5{oGc*j&9bK5pP|3D}G1a|L z*QQp~QI&9I#4d*bY%Bdd#V~V`keqi#z(pV3cE%|{0_zBM347-Oqu}`_-IhA>;rY-g}5mVg_+n871$T@*c^b;qa^L?1HBZ z`6cL*t)aVTHYs52ikUzn^_p^&zl|*w^;64?xvNo$c_p#%8|2Dw_x1SaShTT105thf z5|R(a*J_{Cg#Y>Kxx3}cd|<)RC^wHc1noVU_g7tp`$vOtmz@l9oMFVUJa-^do(v%A zI3l8iLG-ElWjZ+Tu9{VJ94Qh>$jgX%mTD_qeci~LU>(haEsIeud}G56(1pHB9_$RX z+dyFPq!v}%N#7jfZDhADC}lR{+R1xjvtfo>opvZqV(G-pv{|MW^>sK#{O4=iN~`=< z9xNfPvn_eK-ma3k?ORoeB31IH<>M#tTvwy}PDA##tJvr2l3B$znNu`dMbN$deYS{= zLl@YW*Yz)n&)^i9XkJ^Pgs6*!B?*veOkp^oneqAt*Nt`$OcG|=!2xY^vCFW<@nf># zyY6qO$!PB(?&!pVG=I)P%g>D6w&3KMr~tYoOCx@N0}nIs;Z!n3S)5xSnhM^-Lf=9N zf@fjh#nJADUylsvOw_G%PFHORh2j1NweBQeokZ(D?fUg4C1~yn-OIHbC*ySON!l2*k!nRoa z{9XLyH=OG=@|F524M0eCV#LKu58PTdbHsNZ=f+TXqwpa@AE>?u+ zs^G+x!}@+gto8{#Q=4E3pISZ)`0aQ(^3+OZkm{NRd$R^^@JXv6?#E*rVt2ZN z0Eyug9)N@eH2y#Q0Le65%M3%f&-thEPXg___epbebyC=`X|^fsXH3H!!Ip7(9D@LM>HCuyRudawpBo+X^A5CV$1)WCDWOCn;I-ap#xnnQ(2#^2bScbjKfz1U{!1|2hFo~TkQyN1IUS>vds?QgO!I>P`wva;^K z14PtQPDD~;CZz#=so&OZVwQc7+b2#9F|_6h0|}J+6UD1h>AjHspFFyjV1CwE_|-^q z=tA*pqXUNtDPG@S}G zs0mHZw>Vu~bSmTHV!L7#Su5rMN}`p@cwo}4*nAWvA^~~g=(21y#>i{fIpulLX}g)- zEQRba!_A^SmaAohPx)hO4nJY6Hv2&Uk6D??3yYFTvoE#HPev;_CWnJ z$~VB;*P*7;F+hxpOuUcPHG#Cm(z}u zST-K009>^j$aagHj6FQd+J^piE@A8ZV#%&cjQk`Khk{_k+1V|&T;j$s!v?bA39{<9 z8BZ8c>7#m@{M*(y%2z+wQln5Tgz9fD3-{5jjNz9Zt7yiHomP}{UPly>#>ZjkoeF3<0{xyYBU-3j+#MI)xgK@kBKkkO@^bjmr+K{RltyY5O zFD#vJ{w`mI&E2qdq~ioZVY*Q7R-N;?gHH@#3Rc|H>``tyM7?IKSO)=xU>hMPa@2aH z4+_)ptWky;ZFZGO-S4UeH)qNmy_;NIWkv{N*Fhk`rQFY(Av%csmT!q>P#iV5Xdl)&DQ<+Kq>(3Yl1~vjv zE=MxdRuM-n1tY6!F>PNQvaXgJ>SI3=1r}FiOL3UQ$H)PX{#02_Og{;TA*-2cw7r&X z^58P(q4Z1K%}Ufq&F;Jsy|A35hjKQVehXfi0}zD7!?6E%>%ooI)I+=L{G!^YbSEe1iSr7>kGz@YksHdljfLS6N|84;@6p zicF?*91PGXAM&1}A6un^q?n$~k=9fXMci#e%M9;mW)vpbQs`huBVx}T5vS4^)E|xG zxj3GBmzZJZK}}rNN0lE`e_;F;xvN(m`@yl|!6Wfw(p?iM_(x6%n8xI`F_8meb6wi9 zF^uQ>4*ze2xElFvDFBn0MXON_-r#zD&Ib$+ORx$5rhML@{RuK=826_ z*_yELj15nTGBPl2odp-1zRvIP;*{5dg$T+2zhHZ$BZ<%nU zU(s#dxb7c#vbLK`kKEYDOPa`@LiAL^IMGr7rvpql7=LYTa(8)xxMA88NW&T)Q|K)R z4z$JjCd*c=AuSPm?>L--^8Ovej`-}_AaL|ODoDbn_Wee3o|1Z>$;IG zdq@n)5K|zHC$x4%*NJ^ z5#&ss2erFt|Sg@zaFI6eFVa`09J zuXvI9i6++q)uQC>8ht3#^qSQ;h}R$4zns>;i&w9iqaYNiN(~|n{|pSaOCk&j0?LeC zTvuOI=Hk$jg&JXP)teg` z^pYAv+`weUAo@P+Vm<4rM*-^W*x0^)^A$LlH79L^8F}f2xWswpK9|^JveYHW(wMBi zJE#HCTyMkVjZEfPy>zV-5q z)}z2ncRyT5X)-3NfsLhgu=v6p+om1Cdgbc6OYA$(FLImSaX+_GeICQOgS9e@teXF# z@Alyx>l{*DYTGm)7@7EL%+-uh+8>NUjg`_+@KOMCTF-^TQDH1?nq1x81C33vQz|0w zDK5^2CgH;xEJkxwgpY*6?;!(g6-(?!tw9`LsEOEz`s@g0;_ul%zpGG*ypqkd=#A?5IQk$gJkOyH!|%Vp1cD%KFLpBHj|)L z`5{ApoypEXU6{1r>O$|of?@R`tnEq|M5C?mDK}<$ioS6Gk<522F$tpv;CYz#A5Y#& zXr@I=_uQWSrd>&iuF`>z0(=gUiFK&tFJd(A7001Lp6biGlHDT%bGI)N?_a4fj8qS&~swl$ah_ z8CbOt)`$P4JPc?ZBD`my0K!kKr96gk-(?&X8Mv zA}h<58JxIEAPNvFnn10DQn?V#rb;sDlIZuaDtMa`-M+FX3Twf*wE8IxzQept&!DR& zI_3s+$bQ`U36n{XeEbD#BVNQa7w|7C)#YVAHWVLUCp{mWYt|J}5Rob^D|5Pq00ZlP z@Pz8tj-T;96>rA~>6?pq!s7eyH!Vc2R08<~W*w0~lt!E+Et2aS(zhp|Us|c)?Tp@6 zZ3jHuUm%^8($=YH0J&In?=HGKQsq2wn&uqM8v;V5+?i|GEyc#3_=BW`jBbbU5ob}f z5TBrnjX9QcUXJ!MW%$!OIJ(ZOb7Qdo++VZR4%L^mRvL&)k6?V~5R1A=87=qB>=)!C zIR;Y`DxT)8*)Y9pNAE)u(z$C<=vpne)$@x5A|Y6D@&i7ffTYq0E0`xJd_B@{bOsOA z8`q^u@vUfVZ&;P-UJE+J9s~ z{@V&zmru;zX->=-qMCFQh?)6K8q~dQj`dg7DA$n33Ww;8s`CtK!^_^F8TLyVS7y*ya;_Dp~1|Mk)TaavgBQPomyM6GSLF=03T+>X!V>d*V zS21KLfbh>yFYTUI>Q&*dXz=(f(aJUo(MXMV2unu?>VFJiLZiiQVm``kr2A& z(=JeXJrOH|0nhl^epJe_UXvE*s~zAUW#6+Il8Ak%3mmseQIF(AiZo3~d+*#7+W)&d zhAu;|G(L~f<{T_;)Zco`0Fyj kacn9n@c$#ee!Zh&_f1eiUHqf@KhiryT;_YZDD=Po1E9rJl>h($ literal 0 HcmV?d00001 diff --git a/resources-rectangle-448x486/layouts/layout.xml b/resources-rectangle-448x486/layouts/layout.xml new file mode 100644 index 00000000..744ee6a7 --- /dev/null +++ b/resources-rectangle-448x486/layouts/layout.xml @@ -0,0 +1,80 @@ + + + + + + :left + 12 + 486 + 3 + + + + :right + 12 + 486 + 3 + + + + 91 + 265 + 352 + 385 + 417 + 450 + 409 + 41 + 407 + + + + 122 + 328 + 41 + 72 + 52 + + + + + + 45 + 255 + 65 + 38 + + + + 3 + 345 + 276 + 11 + + + + 74 + 356 + 290 + 23 + 6 + + + + + + + [-77, -39, 39, 77] + -3 + 207 + 270 + + 302 + + 304 + 91 + + + From 7e938d33e24b2298bb38fa10f26c04e7e031ba56 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 1 Jul 2025 21:19:42 -0400 Subject: [PATCH 219/220] Enable custon complication to be called from the battery data field and indicator --- README.md | 3 ++ manifest.xml | 4 +-- resources/settings/properties.xml | 3 +- resources/settings/settings.xml | 6 +++- resources/strings/strings.xml | 5 +-- source/CrystalView.mc | 54 +++++++++++++++++-------------- source/DataFields.mc | 3 +- source/Global.mc | 3 ++ 8 files changed, 49 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index bff21332..293e7440 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Reviews: ## Below is what has been added by me (SylvainGa). +### 2.23.0 +- Option to lauch a battery widget when the battery icon is held on Complication enabled devices + ### 2.22.1 - Compiled with CIQ 8.2.1 - Added new device: Venu X1 diff --git a/manifest.xml b/manifest.xml index f2440154..5823b313 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,12 +1,10 @@ - + - - diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index e77c63d9..ba673f3b 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -6,7 +6,8 @@ false false - Flashlight + + 0 1 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 16b313c4..2d8783f2 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -34,7 +34,11 @@ - + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 57330c6e..575ca5ea 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,6 +1,6 @@ Crystal - Crystal-Tesla V2.22.0.b0 + Crystal-Tesla V2.23.0.b1 Theme Hours Colour @@ -127,7 +127,8 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name Latitude Longitude diff --git a/source/CrystalView.mc b/source/CrystalView.mc index e828968a..1d63ee59 100644 --- a/source/CrystalView.mc +++ b/source/CrystalView.mc @@ -1048,43 +1048,49 @@ class CrystalDelegate extends Ui.WatchFaceDelegate { public function onPress(clickEvent as Ui.ClickEvent) as Lang.Boolean { var co_ords = clickEvent.getCoordinates(); - //DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); + /*DEBUG*/ logMessage("onPress called with x:" + co_ords[0] + ", y:" + co_ords[1]); // returns the complicationId within the boundingBoxes if (Toybox has :Complications && App.getApp().getView().useComplications()) { if (mView != null && mView.mDrawables != null && mView.mDataFields != null) { // Saw an unexpected error because one of these were null, although it shouldn't have happened - var defComplicationName = $.getStringProperty("ComplicationName", ""); var complicationId = checkBoundingBoxes(co_ords); - if (complicationId != null) { + if (complicationId != null && complicationId.getType() != Complications.COMPLICATION_TYPE_BATTERY) { + /*DEBUG*/ logMessage("Launching built-in complication"); try { Complications.exitTo(complicationId); } catch (e) {} } - else if (defComplicationName.length() > 0 ) { - // We're outside our hotspots, see if we can launch our Flashlight - var iter = Complications.getComplications(); - if (iter == null) { - return; - } - complicationId = iter.next(); - - while (complicationId != null) { - //logMessage(complicationId.longLabel.toString()); - if ((complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(defComplicationName))) { - //DEBUG*/ logMessage("Found our flashlight complication"); - complicationId = complicationId.complicationId; - //DEBUG*/ logMessage("complicationId is '" + complicationId + "'"); - if (complicationId != null) { // Got a crash caused by a null complicationId (while holding over 'Steps' while in a indoor walk activity) - try { - Complications.exitTo(complicationId); - } - catch (e) {} + else { + var complicationName = (complicationId != null ? $.getStringProperty("BatteryComplicationName", "") : $.getStringProperty("DefComplicationName", "")); + if (complicationName.length() > 0 ) { + // See if we should launch our external complications (default hotspot or battery widget) + var iter = Complications.getComplications(); + if (iter == null) { + return; + } + complicationId = iter.next(); - return; + while (complicationId != null) { + //DEBUG*/ logMessage(complicationId.longLabel.toString()); + if ((complicationId.getType() == Complications.COMPLICATION_TYPE_INVALID && complicationId.longLabel != null && complicationId.longLabel.equals(complicationName))) { + /*DEBUG*/ logMessage("Found our " + complicationName + " complication"); + complicationId = complicationId.complicationId; + /*DEBUG*/ logMessage("complicationId is '" + complicationId + "'"); + if (complicationId != null) { // Got a crash caused by a null complicationId (while holding over 'Steps' while in a indoor walk activity) + try { + /*DEBUG*/ logMessage("Launching " + complicationName + " complication"); + Complications.exitTo(complicationId); + } + catch (e) { + /*DEBUG*/ logMessage("Failed to launch the " + complicationName + " complication, assertion is " + e); + } + + return; + } } + complicationId = iter.next(); } - complicationId = iter.next(); } } } diff --git a/source/DataFields.mc b/source/DataFields.mc index 4dede389..83147466 100644 --- a/source/DataFields.mc +++ b/source/DataFields.mc @@ -123,7 +123,8 @@ class DataFields extends Ui.Drawable { {"type" => FIELD_TYPE_WEATHER, "complicationType" => Complications.COMPLICATION_TYPE_CURRENT_WEATHER}, // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain {"type" => FIELD_TYPE_SUNRISE_SUNSET, "complicationType" => Complications.COMPLICATION_TYPE_SUNRISE}, // Only for onPress. We do nothing with what is returned since it's missing the temperature. Adding it would require a too big change and extra space in App class for basically no gain {"type" => FIELD_TYPE_CALORIES, "complicationType" => Complications.COMPLICATION_TYPE_CALORIES}, - {"type" => FIELD_TYPE_ACTIVE_CALORIES, "complicationType" => Complications.COMPLICATION_TYPE_CALORIES} + {"type" => FIELD_TYPE_ACTIVE_CALORIES, "complicationType" => Complications.COMPLICATION_TYPE_CALORIES}, + {"type" => FIELD_TYPE_BATTERY, "complicationType" => Complications.COMPLICATION_TYPE_BATTERY} ]; var fieldTypes = view.mFieldTypes; diff --git a/source/Global.mc b/source/Global.mc index 526bba94..88d40b76 100644 --- a/source/Global.mc +++ b/source/Global.mc @@ -661,6 +661,9 @@ function logMessage(message) { (:release, :background) function logMessage(message) { + var clockTime = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM); + var dateStr = clockTime.hour + ":" + clockTime.min.format("%02d") + ":" + clockTime.sec.format("%02d"); + Sys.println(dateStr + " : " + message); } /* From 65ba26c9cccb66f848a6f353a234be290b2c736e Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Tue, 1 Jul 2025 21:40:26 -0400 Subject: [PATCH 220/220] Added the new batterie complication setting string to all strings files --- resources-ces/strings/strings.xml | 3 ++- resources-dan/strings/strings.xml | 3 ++- resources-deu/strings/strings.xml | 3 ++- resources-dut/strings/strings.xml | 3 ++- resources-fin/strings/strings.xml | 3 ++- resources-fre/strings/strings.xml | 3 ++- resources-hrv/strings/strings.xml | 3 ++- resources-hun/strings/strings.xml | 3 ++- resources-ita/strings/strings.xml | 3 ++- resources-kor/strings/strings.xml | 3 ++- resources-nob/strings/strings.xml | 3 ++- resources-pol/strings/strings.xml | 3 ++- resources-por/strings/strings.xml | 3 ++- resources-rus/strings/strings.xml | 3 ++- resources-slo/strings/strings.xml | 3 ++- resources-slv/strings/strings.xml | 3 ++- resources-spa/strings/strings.xml | 3 ++- resources-swe/strings/strings.xml | 3 ++- resources-zhs/strings/strings.xml | 3 ++- resources-zht/strings/strings.xml | 3 ++- 20 files changed, 40 insertions(+), 20 deletions(-) diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 0846ca8c..bfb7aa00 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index da54b227..ba79299a 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 3081249f..7ace5c3a 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index a42277ed..2b2513e9 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index 36ca083d..0d97cc49 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 2014daf0..75750ba2 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -127,5 +127,6 @@ Utilisez les Complications de Tesla-Link pour l'info Tesla Quel véhicle afficher? Montrer le nom de la station météo? - Long nom de la complication + Long nom de la complication par défaut + Long nom de la complication de la Battery diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index bde2ca2a..00284274 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 9b02da81..904a8083 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index de473e95..dc413616 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index b56e4981..f5db64eb 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 533f1bbb..e0acc9f0 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index 448fa36c..6c0659ea 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index 7ba5fcef..58821cf4 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-rus/strings/strings.xml b/resources-rus/strings/strings.xml index 7831cedd..b509513c 100644 --- a/resources-rus/strings/strings.xml +++ b/resources-rus/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 2dd55815..0b62b621 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index aa750181..f0c224f3 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index 28dc08b4..5e34afd6 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index f9318866..2b214904 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index 735f7a5a..d290cc52 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index 04c11c73..96788c57 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -128,5 +128,6 @@ Get Tesla info from Tesla-Link Complications Which vehicle to show? Show weather station name? - Complication Long Name + Default Complication Long Name + Battery Complication Long Name

xa{owRCn!aRBf)VUPaD= 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 literal 12228 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 diff --git a/resources-round-390x390/fonts/fonts.xml b/resources-round-390x390/fonts/fonts.xml index 15334f53..eba366a3 100644 --- a/resources-round-390x390/fonts/fonts.xml +++ b/resources-round-390x390/fonts/fonts.xml @@ -30,5 +30,5 @@ - + diff --git a/resources-small-icons/fonts/crystal-icons-small.fnt b/resources-small-icons/fonts/crystal-icons-small.fnt index 148876d9..4f86e59c 100644 --- a/resources-small-icons/fonts/crystal-icons-small.fnt +++ b/resources-small-icons/fonts/crystal-icons-small.fnt @@ -18,4 +18,6 @@ char id=61 x=250 y=0 width=6 height=6 xoffset=0 yoffset=7 char id=62 x=0 y=21 width=23 height=20 xoffset=0 yoffset=0 xadvance=23 page=0 chnl=15 char id=63 x=24 y=21 width=23 height=20 xoffset=0 yoffset=0 xadvance=23 page=0 chnl=15 char id=64 x=48 y=21 width=17 height=20 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 -char id=65 x=66 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 \ No newline at end of file +char id=65 x=66 y=21 width=14 height=20 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 +char id=66 x=80 y=21 width=26 height=22 xoffset=0 yoffset=0 xadvance=26 page=0 chnl=15 +char id=67 x=106 y=21 width=24 height=20 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file diff --git a/resources-small-icons/fonts/crystal-icons-small.png b/resources-small-icons/fonts/crystal-icons-small.png index 351e80c2572b910dc6f4c1038391ed00a0f23c50..c171b8f5f28488920146d6759a3db0ed2880140c 100644 GIT binary patch literal 5079 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 diff --git a/resources/fonts/crystal-icons.fnt b/resources/fonts/crystal-icons.fnt index 2b32067c..c05a9bcf 100644 --- a/resources/fonts/crystal-icons.fnt +++ b/resources/fonts/crystal-icons.fnt @@ -19,4 +19,5 @@ char id=62 x=47 y=25 width=28 height=24 xoffset=0 yoffset=0 char id=63 x=76 y=25 width=28 height=24 xoffset=0 yoffset=0 xadvance=28 page=0 chnl=15 char id=64 x=105 y=25 width=20 height=24 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 char id=65 x=126 y=25 width=17 height=24 xoffset=0 yoffset=0 xadvance=17 page=0 chnl=15 -char id=66 x=145 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file +char id=66 x=145 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 +char id=67 x=169 y=27 width=24 height=22 xoffset=0 yoffset=0 xadvance=24 page=0 chnl=15 \ No newline at end of file diff --git a/resources/fonts/crystal-icons.png b/resources/fonts/crystal-icons.png index 2dbdfae931d1c7c41a9c67de900cca8fa8ed1cc9..d0472ad87d91c0a78810486928c32ef6d6d530af 100644 GIT binary patch delta 4376 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.Battery @Strings.BatteryNumeric @Strings.Tesla + @Strings.DND @@ -160,6 +161,7 @@ @Strings.Battery @Strings.BatteryNumeric @Strings.Tesla + @Strings.DND @@ -172,6 +174,7 @@ @Strings.Battery @Strings.BatteryNumeric @Strings.Tesla + @Strings.DND diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index c91175be..181343fe 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -108,5 +108,6 @@ Tesla Info Tesla Access Token Tesla Refresh Token + Do Not Disturb diff --git a/source/Indicators.mc b/source/Indicators.mc index 38afe004..e10e91eb 100644 --- a/source/Indicators.mc +++ b/source/Indicators.mc @@ -117,6 +117,7 @@ class Indicators extends Ui.Drawable { writeBatteryLevel(dc, x, y, mBatteryWidth, mBatteryWidth / 2, 1); return; } + //**************************************************************** //******************** END OF REMVOVED SECTION ******************* //**************************************************************** @@ -130,12 +131,16 @@ class Indicators extends Ui.Drawable { indicatorType = 0; // INDICATOR_TYPE_BLUETOOTH } } + else if (indicatorType == 7) { + indicatorType = 3; + } // Get value for indicator type. var value = [ /* INDICATOR_TYPE_BLUETOOTH */ settings.phoneConnected, /* INDICATOR_TYPE_ALARMS */ settings.alarmCount > 0, - /* INDICATOR_TYPE_NOTIFICATIONS */ settings.notificationCount > 0 + /* INDICATOR_TYPE_NOTIFICATIONS */ settings.notificationCount > 0, + /* Do Not Disturb */ settings has :doNotDisturb && settings.doNotDisturb ][indicatorType]; dc.setColor(value ? gThemeColour : gMeterBackgroundColour, Graphics.COLOR_TRANSPARENT); @@ -145,7 +150,7 @@ class Indicators extends Ui.Drawable { x, y, gIconsFont, - ["8", ":", "5"][indicatorType], // Get icon font char for indicator type. + ["8", ":", "5", "C"][indicatorType], // Get icon font char for indicator type. Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER ); } From 4caf6c346b08a4f4a40374df43a19bd2fa4150cf Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 9 May 2022 22:09:11 -0400 Subject: [PATCH 047/220] AOD Shows Tesla's battery level --- always-on-source/AlwaysOnDisplay.mc | 78 ++- resources-rectangle-240x240/fonts/fonts.xml | 2 +- resources-round-360x360/fonts/fonts.xml | 2 +- resources-round-390x390/fonts/fonts.xml | 2 +- resources-round-416x416/fonts/fonts.xml | 2 +- .../fonts/titillium-web-semibold-24.bmfc | 6 +- resources/fonts/titillium-web-semibold-24.fnt | 474 ++++++++++++++---- .../fonts/titillium-web-semibold-24_0.png | Bin 13395 -> 13404 bytes 8 files changed, 440 insertions(+), 126 deletions(-) diff --git a/always-on-source/AlwaysOnDisplay.mc b/always-on-source/AlwaysOnDisplay.mc index f946bfe0..dd66c1b1 100644 --- a/always-on-source/AlwaysOnDisplay.mc +++ b/always-on-source/AlwaysOnDisplay.mc @@ -192,22 +192,68 @@ class AlwaysOnDisplay extends Ui.Drawable { // Date. y = mDataY + burnInYOffset; - dc.drawText( - mDataLeft, - y, - mDateFont, - Lang.format("$1$ $2$ $3$", [mDayOfWeekString, day, mMonthString]), - Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER - ); + if (App.getApp().getProperty("Tesla") != null) { + dc.drawText( + mDataLeft, + y, + mDateFont, + Lang.format("$1$ $2$", [day, mMonthString]), + Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER + ); - // Battery. - var battery = Math.floor(Sys.getSystemStats().battery); - dc.drawText( - dc.getWidth() - mDataLeft, - y, - mBatteryFont, - battery.format(INTEGER_FORMAT) + "%", - Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER - ); + // Batteries. + var battery = Math.floor(Sys.getSystemStats().battery); + var batteryStale = App.getApp().getProperty("TeslaBatterieStale"); + var chargingState = App.getApp().getProperty("TeslaChargingState"); + var error = App.getApp().getProperty("TeslaError"); + var teslaBat = null; + + if (chargingState != null) { + if (chargingState.equals("Charging")) { + chargingState = 1; + } else if (chargingState.equals("Sleeping")) { + chargingState = 2; + } else { + chargingState = 0; + } + } else { + chargingState = 0; + } + + var value = App.getApp().getProperty("TeslaBatterieLevel"); + if (error != null) { + value = error.toNumber().format(INTEGER_FORMAT); + } else if (value == null) { + value = "???"; + } else { + value = value.toNumber().format(INTEGER_FORMAT) + "%" + (chargingState == 1 ? "+" : (chargingState == 2 ? "s" : "")); + } + + dc.drawText( + dc.getWidth() - mDataLeft, + y, + mBatteryFont, + "T" + value + " " + battery.format(INTEGER_FORMAT) + "%", + Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER + ); + } else { + dc.drawText( + mDataLeft, + y, + mDateFont, + Lang.format("$1$ $2$ $3$", [mDayOfWeekString, day, mMonthString]), + Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER + ); + + // Battery. + var battery = Math.floor(Sys.getSystemStats().battery); + dc.drawText( + dc.getWidth() - mDataLeft, + y, + mBatteryFont, + battery.format(INTEGER_FORMAT) + "%", + Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER + ); + } } } \ No newline at end of file diff --git a/resources-rectangle-240x240/fonts/fonts.xml b/resources-rectangle-240x240/fonts/fonts.xml index aee5a84d..14f817ec 100644 --- a/resources-rectangle-240x240/fonts/fonts.xml +++ b/resources-rectangle-240x240/fonts/fonts.xml @@ -20,5 +20,5 @@ - + diff --git a/resources-round-360x360/fonts/fonts.xml b/resources-round-360x360/fonts/fonts.xml index 6487c4a1..c8943de4 100644 --- a/resources-round-360x360/fonts/fonts.xml +++ b/resources-round-360x360/fonts/fonts.xml @@ -32,5 +32,5 @@ - + diff --git a/resources-round-390x390/fonts/fonts.xml b/resources-round-390x390/fonts/fonts.xml index eba366a3..519ed596 100644 --- a/resources-round-390x390/fonts/fonts.xml +++ b/resources-round-390x390/fonts/fonts.xml @@ -30,5 +30,5 @@ - + diff --git a/resources-round-416x416/fonts/fonts.xml b/resources-round-416x416/fonts/fonts.xml index 5401a717..d90b563b 100644 --- a/resources-round-416x416/fonts/fonts.xml +++ b/resources-round-416x416/fonts/fonts.xml @@ -31,5 +31,5 @@ - + diff --git a/resources/fonts/titillium-web-semibold-24.bmfc b/resources/fonts/titillium-web-semibold-24.bmfc index d2b2de57..f98fa303 100644 --- a/resources/fonts/titillium-web-semibold-24.bmfc +++ b/resources/fonts/titillium-web-semibold-24.bmfc @@ -18,6 +18,9 @@ dontIncludeKerningPairs=0 useHinting=1 renderFromOutline=0 useClearType=1 +autoFitNumPages=0 +autoFitFontSizeMin=0 +autoFitFontSizeMax=0 # character alignment paddingDown=0 @@ -28,6 +31,7 @@ spacingHoriz=1 spacingVert=1 useFixedHeight=0 forceZero=0 +widthPaddingFactor=0.00 # output file outWidth=256 @@ -50,7 +54,7 @@ invB=0 outlineThickness=0 # selected chars -chars=32-33,37,39,44-46,48-58,63,65-90,97-122,176,192-223,225,227-230,232-233,237,240-241,243-244,246 +chars=32-33,37,39,43-46,48-58,63,65-90,97-122,176,192-223,225,227-230,232-233,237,240-241,243-244,246 chars=248,251-252,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296 chars=298,300,302,304,308,310,313,315,317,321,323,325,327,330,332,334,336,338,340,342,344,346,348,350 chars=352,356,358,360,362,364,366,368,370,372,374,376-377,379,381-382 diff --git a/resources/fonts/titillium-web-semibold-24.fnt b/resources/fonts/titillium-web-semibold-24.fnt index b5f857e1..85ff9df6 100644 --- a/resources/fonts/titillium-web-semibold-24.fnt +++ b/resources/fonts/titillium-web-semibold-24.fnt @@ -1,125 +1,126 @@ info face="Titillium Web SemiBold" size=-24 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=36 base=27 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0 page id=0 file="titillium-web-semibold-24_0.png" -chars count=181 +chars count=182 char id=32 x=102 y=137 width=3 height=1 xoffset=-1 yoffset=35 xadvance=5 page=0 chnl=15 -char id=33 x=97 y=176 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 -char id=37 x=141 y=116 width=14 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 -char id=39 x=100 y=194 width=4 height=7 xoffset=1 yoffset=10 xadvance=5 page=0 chnl=15 -char id=44 x=105 y=193 width=5 height=6 xoffset=0 yoffset=24 xadvance=6 page=0 chnl=15 -char id=45 x=116 y=193 width=8 height=3 xoffset=1 yoffset=19 xadvance=10 page=0 chnl=15 -char id=46 x=111 y=193 width=4 height=4 xoffset=1 yoffset=23 xadvance=6 page=0 chnl=15 -char id=48 x=186 y=115 width=13 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=33 x=87 y=177 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 +char id=37 x=171 y=116 width=14 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=39 x=114 y=193 width=4 height=7 xoffset=1 yoffset=10 xadvance=5 page=0 chnl=15 +char id=43 x=40 y=195 width=13 height=12 xoffset=0 yoffset=15 xadvance=13 page=0 chnl=15 +char id=44 x=119 y=193 width=5 height=6 xoffset=0 yoffset=24 xadvance=6 page=0 chnl=15 +char id=45 x=130 y=190 width=8 height=3 xoffset=1 yoffset=19 xadvance=10 page=0 chnl=15 +char id=46 x=125 y=193 width=4 height=4 xoffset=1 yoffset=23 xadvance=6 page=0 chnl=15 +char id=48 x=228 y=115 width=13 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 char id=49 x=128 y=173 width=9 height=16 xoffset=1 yoffset=11 xadvance=13 page=0 chnl=15 -char id=50 x=228 y=152 width=12 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 -char id=51 x=26 y=140 width=12 height=18 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=50 x=241 y=152 width=12 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=51 x=13 y=140 width=12 height=18 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 char id=52 x=102 y=176 width=13 height=16 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 -char id=53 x=0 y=177 width=12 height=17 xoffset=1 yoffset=11 xadvance=13 page=0 chnl=15 +char id=53 x=228 y=152 width=12 height=17 xoffset=1 yoffset=11 xadvance=13 page=0 chnl=15 char id=54 x=200 y=115 width=13 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 char id=55 x=116 y=176 width=11 height=16 xoffset=1 yoffset=11 xadvance=13 page=0 chnl=15 char id=56 x=214 y=115 width=13 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 -char id=57 x=117 y=155 width=13 height=17 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 +char id=57 x=173 y=153 width=13 height=17 xoffset=0 yoffset=11 xadvance=13 page=0 chnl=15 char id=58 x=251 y=170 width=4 height=11 xoffset=1 yoffset=16 xadvance=6 page=0 chnl=15 char id=63 x=61 y=177 width=10 height=17 xoffset=0 yoffset=10 xadvance=11 page=0 chnl=15 -char id=65 x=190 y=134 width=15 height=17 xoffset=0 yoffset=10 xadvance=14 page=0 chnl=15 -char id=66 x=89 y=158 width=13 height=17 xoffset=1 yoffset=10 xadvance=15 page=0 chnl=15 -char id=67 x=52 y=140 width=12 height=18 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 -char id=68 x=15 y=159 width=14 height=17 xoffset=1 yoffset=10 xadvance=15 page=0 chnl=15 -char id=69 x=241 y=152 width=12 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 -char id=70 x=215 y=152 width=12 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 -char id=71 x=171 y=116 width=14 height=18 xoffset=0 yoffset=10 xadvance=15 page=0 chnl=15 -char id=72 x=0 y=159 width=14 height=17 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 -char id=73 x=87 y=177 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 +char id=65 x=222 y=134 width=15 height=17 xoffset=0 yoffset=10 xadvance=14 page=0 chnl=15 +char id=66 x=131 y=155 width=13 height=17 xoffset=1 yoffset=10 xadvance=15 page=0 chnl=15 +char id=67 x=0 y=140 width=12 height=18 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=68 x=45 y=159 width=14 height=17 xoffset=1 yoffset=10 xadvance=15 page=0 chnl=15 +char id=69 x=215 y=152 width=12 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=70 x=0 y=177 width=12 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=71 x=141 y=116 width=14 height=18 xoffset=0 yoffset=10 xadvance=15 page=0 chnl=15 +char id=72 x=30 y=159 width=14 height=17 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 +char id=73 x=97 y=176 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 char id=74 x=248 y=95 width=6 height=19 xoffset=0 yoffset=10 xadvance=7 page=0 chnl=15 -char id=75 x=187 y=153 width=13 height=17 xoffset=1 yoffset=10 xadvance=14 page=0 chnl=15 -char id=76 x=25 y=177 width=11 height=17 xoffset=1 yoffset=10 xadvance=11 page=0 chnl=15 +char id=75 x=145 y=155 width=13 height=17 xoffset=1 yoffset=10 xadvance=14 page=0 chnl=15 +char id=76 x=49 y=177 width=11 height=17 xoffset=1 yoffset=10 xadvance=11 page=0 chnl=15 char id=77 x=153 y=135 width=18 height=17 xoffset=1 yoffset=10 xadvance=20 page=0 chnl=15 -char id=78 x=238 y=134 width=14 height=17 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 +char id=78 x=15 y=159 width=14 height=17 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 char id=79 x=125 y=118 width=15 height=18 xoffset=0 yoffset=10 xadvance=16 page=0 chnl=15 -char id=80 x=173 y=153 width=13 height=17 xoffset=1 yoffset=10 xadvance=14 page=0 chnl=15 +char id=80 x=201 y=152 width=13 height=17 xoffset=1 yoffset=10 xadvance=14 page=0 chnl=15 char id=81 x=70 y=97 width=15 height=21 xoffset=0 yoffset=10 xadvance=16 page=0 chnl=15 -char id=82 x=201 y=152 width=13 height=17 xoffset=1 yoffset=10 xadvance=15 page=0 chnl=15 -char id=83 x=228 y=115 width=13 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 -char id=84 x=159 y=153 width=13 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=82 x=187 y=153 width=13 height=17 xoffset=1 yoffset=10 xadvance=15 page=0 chnl=15 +char id=83 x=186 y=115 width=13 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=84 x=117 y=155 width=13 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 char id=85 x=156 y=116 width=14 height=18 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 -char id=86 x=60 y=159 width=14 height=17 xoffset=0 yoffset=10 xadvance=14 page=0 chnl=15 +char id=86 x=0 y=159 width=14 height=17 xoffset=0 yoffset=10 xadvance=14 page=0 chnl=15 char id=87 x=108 y=137 width=22 height=17 xoffset=0 yoffset=10 xadvance=22 page=0 chnl=15 -char id=88 x=45 y=159 width=14 height=17 xoffset=0 yoffset=10 xadvance=14 page=0 chnl=15 -char id=89 x=30 y=159 width=14 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 -char id=90 x=131 y=155 width=13 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 -char id=97 x=184 y=171 width=12 height=14 xoffset=0 yoffset=14 xadvance=12 page=0 chnl=15 -char id=98 x=39 y=140 width=12 height=18 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=88 x=238 y=134 width=14 height=17 xoffset=0 yoffset=10 xadvance=14 page=0 chnl=15 +char id=89 x=60 y=159 width=14 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=90 x=89 y=158 width=13 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=97 x=171 y=171 width=12 height=14 xoffset=0 yoffset=14 xadvance=12 page=0 chnl=15 +char id=98 x=242 y=115 width=12 height=18 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 char id=99 x=209 y=170 width=10 height=14 xoffset=0 yoffset=14 xadvance=11 page=0 chnl=15 -char id=100 x=13 y=140 width=12 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 -char id=101 x=171 y=171 width=12 height=14 xoffset=0 yoffset=14 xadvance=12 page=0 chnl=15 +char id=100 x=39 y=140 width=12 height=18 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=101 x=158 y=173 width=12 height=14 xoffset=0 yoffset=14 xadvance=12 page=0 chnl=15 char id=102 x=89 y=139 width=9 height=18 xoffset=0 yoffset=9 xadvance=8 page=0 chnl=15 char id=103 x=155 y=96 width=13 height=19 xoffset=0 yoffset=14 xadvance=13 page=0 chnl=15 -char id=104 x=13 y=177 width=11 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 -char id=105 x=92 y=176 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 -char id=106 x=247 y=0 width=7 height=23 xoffset=-2 yoffset=10 xadvance=6 page=0 chnl=15 -char id=107 x=49 y=177 width=11 height=17 xoffset=1 yoffset=10 xadvance=12 page=0 chnl=15 -char id=108 x=82 y=177 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 +char id=104 x=25 y=177 width=11 height=17 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=105 x=82 y=177 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 +char id=106 x=171 y=49 width=7 height=23 xoffset=-2 yoffset=10 xadvance=6 page=0 chnl=15 +char id=107 x=13 y=177 width=11 height=17 xoffset=1 yoffset=10 xadvance=12 page=0 chnl=15 +char id=108 x=92 y=176 width=4 height=17 xoffset=1 yoffset=10 xadvance=6 page=0 chnl=15 char id=109 x=220 y=170 width=18 height=13 xoffset=1 yoffset=14 xadvance=20 page=0 chnl=15 char id=110 x=239 y=170 width=11 height=13 xoffset=1 yoffset=14 xadvance=13 page=0 chnl=15 -char id=111 x=158 y=173 width=12 height=14 xoffset=0 yoffset=14 xadvance=13 page=0 chnl=15 -char id=112 x=39 y=120 width=12 height=19 xoffset=1 yoffset=14 xadvance=13 page=0 chnl=15 -char id=113 x=52 y=120 width=12 height=19 xoffset=0 yoffset=14 xadvance=13 page=0 chnl=15 +char id=111 x=184 y=171 width=12 height=14 xoffset=0 yoffset=14 xadvance=13 page=0 chnl=15 +char id=112 x=52 y=120 width=12 height=19 xoffset=1 yoffset=14 xadvance=13 page=0 chnl=15 +char id=113 x=65 y=120 width=12 height=19 xoffset=0 yoffset=14 xadvance=13 page=0 chnl=15 char id=114 x=12 y=195 width=8 height=13 xoffset=1 yoffset=14 xadvance=9 page=0 chnl=15 char id=115 x=197 y=171 width=11 height=14 xoffset=0 yoffset=14 xadvance=11 page=0 chnl=15 char id=116 x=72 y=177 width=9 height=17 xoffset=0 yoffset=11 xadvance=9 page=0 chnl=15 char id=117 x=0 y=195 width=11 height=13 xoffset=1 yoffset=15 xadvance=13 page=0 chnl=15 -char id=118 x=40 y=195 width=12 height=12 xoffset=0 yoffset=15 xadvance=12 page=0 chnl=15 +char id=118 x=54 y=195 width=12 height=12 xoffset=0 yoffset=15 xadvance=12 page=0 chnl=15 char id=119 x=21 y=195 width=18 height=12 xoffset=0 yoffset=15 xadvance=18 page=0 chnl=15 -char id=120 x=53 y=195 width=11 height=12 xoffset=0 yoffset=15 xadvance=11 page=0 chnl=15 -char id=121 x=242 y=115 width=12 height=18 xoffset=0 yoffset=15 xadvance=12 page=0 chnl=15 -char id=122 x=65 y=195 width=11 height=12 xoffset=0 yoffset=15 xadvance=11 page=0 chnl=15 -char id=176 x=90 y=195 width=9 height=8 xoffset=2 yoffset=10 xadvance=13 page=0 chnl=15 -char id=192 x=0 y=26 width=15 height=23 xoffset=0 yoffset=4 xadvance=14 page=0 chnl=15 -char id=193 x=96 y=25 width=15 height=23 xoffset=0 yoffset=4 xadvance=14 page=0 chnl=15 +char id=120 x=67 y=195 width=11 height=12 xoffset=0 yoffset=15 xadvance=11 page=0 chnl=15 +char id=121 x=52 y=140 width=12 height=18 xoffset=0 yoffset=15 xadvance=12 page=0 chnl=15 +char id=122 x=79 y=195 width=11 height=12 xoffset=0 yoffset=15 xadvance=11 page=0 chnl=15 +char id=176 x=104 y=193 width=9 height=8 xoffset=2 yoffset=10 xadvance=13 page=0 chnl=15 +char id=192 x=16 y=26 width=15 height=23 xoffset=0 yoffset=4 xadvance=14 page=0 chnl=15 +char id=193 x=0 y=26 width=15 height=23 xoffset=0 yoffset=4 xadvance=14 page=0 chnl=15 char id=194 x=202 y=49 width=15 height=22 xoffset=0 yoffset=5 xadvance=14 page=0 chnl=15 -char id=195 x=80 y=25 width=15 height=23 xoffset=0 yoffset=4 xadvance=14 page=0 chnl=15 -char id=196 x=0 y=74 width=15 height=22 xoffset=0 yoffset=5 xadvance=14 page=0 chnl=15 +char id=195 x=96 y=25 width=15 height=23 xoffset=0 yoffset=4 xadvance=14 page=0 chnl=15 +char id=196 x=16 y=74 width=15 height=22 xoffset=0 yoffset=5 xadvance=14 page=0 chnl=15 char id=197 x=86 y=97 width=15 height=21 xoffset=0 yoffset=6 xadvance=14 page=0 chnl=15 char id=198 x=131 y=137 width=21 height=17 xoffset=0 yoffset=10 xadvance=21 page=0 chnl=15 -char id=199 x=135 y=49 width=12 height=23 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 -char id=200 x=109 y=49 width=12 height=23 xoffset=1 yoffset=4 xadvance=13 page=0 chnl=15 -char id=201 x=122 y=49 width=12 height=23 xoffset=1 yoffset=4 xadvance=13 page=0 chnl=15 -char id=202 x=26 y=97 width=12 height=22 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 -char id=203 x=234 y=72 width=12 height=22 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 -char id=204 x=247 y=24 width=7 height=23 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15 -char id=205 x=171 y=49 width=7 height=23 xoffset=0 yoffset=4 xadvance=6 page=0 chnl=15 +char id=199 x=109 y=49 width=12 height=23 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 +char id=200 x=122 y=49 width=12 height=23 xoffset=1 yoffset=4 xadvance=13 page=0 chnl=15 +char id=201 x=135 y=49 width=12 height=23 xoffset=1 yoffset=4 xadvance=13 page=0 chnl=15 +char id=202 x=234 y=72 width=12 height=22 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 +char id=203 x=26 y=97 width=12 height=22 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 +char id=204 x=247 y=0 width=7 height=23 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15 +char id=205 x=247 y=24 width=7 height=23 xoffset=0 yoffset=4 xadvance=6 page=0 chnl=15 char id=206 x=39 y=97 width=10 height=22 xoffset=-2 yoffset=5 xadvance=6 page=0 chnl=15 char id=207 x=60 y=97 width=9 height=22 xoffset=-1 yoffset=5 xadvance=6 page=0 chnl=15 char id=208 x=206 y=134 width=15 height=17 xoffset=0 yoffset=10 xadvance=15 page=0 chnl=15 -char id=209 x=202 y=25 width=14 height=23 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 -char id=210 x=70 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 -char id=211 x=118 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 -char id=212 x=48 y=26 width=15 height=23 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 -char id=213 x=102 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 -char id=214 x=64 y=26 width=15 height=23 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 -char id=215 x=77 y=195 width=12 height=10 xoffset=1 yoffset=16 xadvance=13 page=0 chnl=15 +char id=209 x=172 y=25 width=14 height=23 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 +char id=210 x=118 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 +char id=211 x=102 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 +char id=212 x=80 y=25 width=15 height=23 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=213 x=86 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 +char id=214 x=48 y=26 width=15 height=23 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=215 x=91 y=195 width=12 height=10 xoffset=1 yoffset=16 xadvance=13 page=0 chnl=15 char id=216 x=32 y=26 width=15 height=23 xoffset=0 yoffset=7 xadvance=16 page=0 chnl=15 -char id=217 x=164 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 -char id=218 x=179 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 +char id=217 x=194 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 +char id=218 x=134 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 char id=219 x=142 y=25 width=14 height=23 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 char id=220 x=157 y=25 width=14 height=23 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=221 x=187 y=25 width=14 height=23 xoffset=0 yoffset=4 xadvance=13 page=0 chnl=15 +char id=221 x=127 y=25 width=14 height=23 xoffset=0 yoffset=4 xadvance=13 page=0 chnl=15 char id=222 x=75 y=159 width=13 height=17 xoffset=1 yoffset=10 xadvance=14 page=0 chnl=15 char id=223 x=169 y=96 width=13 height=19 xoffset=1 yoffset=9 xadvance=14 page=0 chnl=15 -char id=225 x=26 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 -char id=227 x=13 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 -char id=228 x=0 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 -char id=229 x=235 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 +char id=225 x=39 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 +char id=227 x=26 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 +char id=228 x=13 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 +char id=229 x=0 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 char id=230 x=138 y=173 width=19 height=14 xoffset=0 yoffset=14 xadvance=19 page=0 chnl=15 char id=232 x=222 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 -char id=233 x=196 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 +char id=233 x=209 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=12 page=0 chnl=15 char id=237 x=99 y=139 width=8 height=18 xoffset=0 yoffset=9 xadvance=6 page=0 chnl=15 char id=240 x=141 y=96 width=13 height=19 xoffset=0 yoffset=9 xadvance=13 page=0 chnl=15 -char id=241 x=65 y=140 width=11 height=18 xoffset=1 yoffset=9 xadvance=13 page=0 chnl=15 -char id=243 x=183 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=13 page=0 chnl=15 -char id=244 x=65 y=120 width=12 height=19 xoffset=0 yoffset=9 xadvance=13 page=0 chnl=15 -char id=246 x=209 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=13 page=0 chnl=15 -char id=248 x=0 y=140 width=12 height=18 xoffset=0 yoffset=12 xadvance=13 page=0 chnl=15 +char id=241 x=77 y=140 width=11 height=18 xoffset=1 yoffset=9 xadvance=13 page=0 chnl=15 +char id=243 x=196 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=13 page=0 chnl=15 +char id=244 x=183 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=13 page=0 chnl=15 +char id=246 x=235 y=95 width=12 height=19 xoffset=0 yoffset=9 xadvance=13 page=0 chnl=15 +char id=248 x=26 y=140 width=12 height=18 xoffset=0 yoffset=12 xadvance=13 page=0 chnl=15 char id=251 x=78 y=119 width=11 height=19 xoffset=1 yoffset=9 xadvance=13 page=0 chnl=15 char id=252 x=90 y=119 width=11 height=19 xoffset=1 yoffset=9 xadvance=13 page=0 chnl=15 char id=256 x=102 y=96 width=15 height=21 xoffset=0 yoffset=6 xadvance=14 page=0 chnl=15 @@ -129,18 +130,18 @@ char id=262 x=223 y=0 width=12 height=24 xoffset=1 yoffset=4 char id=264 x=96 y=49 width=12 height=23 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 char id=266 x=83 y=49 width=12 height=23 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 char id=268 x=70 y=50 width=12 height=23 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 -char id=270 x=32 y=74 width=14 height=22 xoffset=1 yoffset=5 xadvance=15 page=0 chnl=15 -char id=272 x=222 y=134 width=15 height=17 xoffset=0 yoffset=10 xadvance=15 page=0 chnl=15 +char id=270 x=62 y=74 width=14 height=22 xoffset=1 yoffset=5 xadvance=15 page=0 chnl=15 +char id=272 x=190 y=134 width=15 height=17 xoffset=0 yoffset=10 xadvance=15 page=0 chnl=15 char id=274 x=118 y=96 width=12 height=21 xoffset=1 yoffset=6 xadvance=13 page=0 chnl=15 char id=276 x=208 y=72 width=12 height=22 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 char id=278 x=221 y=72 width=12 height=22 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 char id=280 x=0 y=97 width=12 height=22 xoffset=1 yoffset=10 xadvance=13 page=0 chnl=15 char id=282 x=13 y=97 width=12 height=22 xoffset=1 yoffset=5 xadvance=13 page=0 chnl=15 -char id=284 x=217 y=25 width=14 height=23 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15 -char id=286 x=112 y=25 width=14 height=23 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15 -char id=288 x=127 y=25 width=14 height=23 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15 -char id=290 x=0 y=0 width=14 height=25 xoffset=0 yoffset=10 xadvance=15 page=0 chnl=15 -char id=292 x=62 y=74 width=14 height=22 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=284 x=112 y=25 width=14 height=23 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15 +char id=286 x=232 y=25 width=14 height=23 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15 +char id=288 x=217 y=25 width=14 height=23 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15 +char id=290 x=15 y=0 width=14 height=25 xoffset=0 yoffset=10 xadvance=15 page=0 chnl=15 +char id=292 x=47 y=74 width=14 height=22 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 char id=294 x=172 y=135 width=17 height=17 xoffset=0 yoffset=10 xadvance=16 page=0 chnl=15 char id=296 x=160 y=49 width=10 height=23 xoffset=-2 yoffset=4 xadvance=6 page=0 chnl=15 char id=298 x=131 y=96 width=9 height=21 xoffset=-1 yoffset=6 xadvance=6 page=0 chnl=15 @@ -152,38 +153,301 @@ char id=310 x=44 y=0 width=13 height=25 xoffset=1 yoffset=10 char id=313 x=148 y=49 width=11 height=23 xoffset=1 yoffset=4 xadvance=11 page=0 chnl=15 char id=315 x=58 y=0 width=11 height=25 xoffset=1 yoffset=10 xadvance=11 page=0 chnl=15 char id=317 x=37 y=177 width=11 height=17 xoffset=1 yoffset=10 xadvance=12 page=0 chnl=15 -char id=321 x=103 y=158 width=13 height=17 xoffset=-1 yoffset=10 xadvance=12 page=0 chnl=15 -char id=323 x=232 y=25 width=14 height=23 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 -char id=325 x=15 y=0 width=14 height=25 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 +char id=321 x=159 y=153 width=13 height=17 xoffset=-1 yoffset=10 xadvance=12 page=0 chnl=15 +char id=323 x=202 y=25 width=14 height=23 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 +char id=325 x=0 y=0 width=14 height=25 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 char id=327 x=77 y=74 width=14 height=22 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 char id=330 x=92 y=73 width=14 height=22 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 -char id=332 x=16 y=74 width=15 height=22 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 -char id=334 x=16 y=26 width=15 height=23 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 -char id=336 x=86 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 +char id=332 x=0 y=74 width=15 height=22 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15 +char id=334 x=64 y=26 width=15 height=23 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=336 x=70 y=0 width=15 height=24 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 char id=338 x=102 y=118 width=22 height=18 xoffset=0 yoffset=10 xadvance=22 page=0 chnl=15 -char id=340 x=28 y=50 width=13 height=23 xoffset=1 yoffset=4 xadvance=15 page=0 chnl=15 +char id=340 x=42 y=50 width=13 height=23 xoffset=1 yoffset=4 xadvance=15 page=0 chnl=15 char id=342 x=30 y=0 width=13 height=25 xoffset=1 yoffset=10 xadvance=15 page=0 chnl=15 char id=344 x=166 y=73 width=13 height=22 xoffset=1 yoffset=5 xadvance=15 page=0 chnl=15 char id=346 x=209 y=0 width=13 height=24 xoffset=0 yoffset=4 xadvance=13 page=0 chnl=15 -char id=348 x=14 y=50 width=13 height=23 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 -char id=350 x=0 y=50 width=13 height=23 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 -char id=352 x=56 y=50 width=13 height=23 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 +char id=348 x=28 y=50 width=13 height=23 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 +char id=350 x=14 y=50 width=13 height=23 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=352 x=0 y=50 width=13 height=23 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 char id=356 x=152 y=73 width=13 height=22 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 -char id=358 x=145 y=155 width=13 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 +char id=358 x=103 y=158 width=13 height=17 xoffset=0 yoffset=10 xadvance=13 page=0 chnl=15 char id=360 x=149 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 -char id=362 x=47 y=74 width=14 height=22 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 -char id=364 x=172 y=25 width=14 height=23 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 -char id=366 x=194 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 -char id=368 x=134 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 +char id=362 x=32 y=74 width=14 height=22 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15 +char id=364 x=187 y=25 width=14 height=23 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=366 x=179 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 +char id=368 x=164 y=0 width=14 height=24 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 char id=370 x=107 y=73 width=14 height=22 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15 char id=372 x=179 y=49 width=22 height=22 xoffset=0 yoffset=5 xadvance=22 page=0 chnl=15 char id=374 x=122 y=73 width=14 height=22 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 char id=376 x=137 y=73 width=14 height=22 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 -char id=377 x=42 y=50 width=13 height=23 xoffset=0 yoffset=4 xadvance=13 page=0 chnl=15 +char id=377 x=56 y=50 width=13 height=23 xoffset=0 yoffset=4 xadvance=13 page=0 chnl=15 char id=379 x=194 y=72 width=13 height=22 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 char id=381 x=180 y=72 width=13 height=22 xoffset=0 yoffset=5 xadvance=13 page=0 chnl=15 -char id=382 x=77 y=140 width=11 height=18 xoffset=0 yoffset=9 xadvance=11 page=0 chnl=15 -kernings count=980 +char id=382 x=65 y=140 width=11 height=18 xoffset=0 yoffset=9 xadvance=11 page=0 chnl=15 +kernings count=1243 +kerning first=39 second=198 amount=-1 +kerning first=44 second=86 amount=-1 +kerning first=44 second=118 amount=-1 +kerning first=45 second=86 amount=-1 +kerning first=45 second=88 amount=-1 +kerning first=45 second=120 amount=-1 +kerning first=46 second=86 amount=-1 +kerning first=46 second=118 amount=-1 +kerning first=65 second=86 amount=-1 +kerning first=66 second=89 amount=-1 +kerning first=66 second=221 amount=-1 +kerning first=66 second=374 amount=-1 +kerning first=66 second=376 amount=-1 +kerning first=70 second=44 amount=-1 +kerning first=70 second=46 amount=-1 +kerning first=70 second=65 amount=-1 +kerning first=70 second=97 amount=-1 +kerning first=70 second=192 amount=-1 +kerning first=70 second=193 amount=-1 +kerning first=70 second=194 amount=-1 +kerning first=70 second=195 amount=-1 +kerning first=70 second=196 amount=-1 +kerning first=70 second=197 amount=-1 +kerning first=70 second=198 amount=-1 +kerning first=70 second=225 amount=-1 +kerning first=70 second=227 amount=-1 +kerning first=70 second=228 amount=-1 +kerning first=70 second=229 amount=-1 +kerning first=70 second=230 amount=-1 +kerning first=70 second=256 amount=-1 +kerning first=70 second=258 amount=-1 +kerning first=70 second=260 amount=-1 +kerning first=76 second=86 amount=-1 +kerning first=76 second=118 amount=-1 +kerning first=80 second=44 amount=-2 +kerning first=80 second=46 amount=-2 +kerning first=80 second=65 amount=-1 +kerning first=80 second=192 amount=-1 +kerning first=80 second=193 amount=-1 +kerning first=80 second=194 amount=-1 +kerning first=80 second=195 amount=-1 +kerning first=80 second=196 amount=-1 +kerning first=80 second=197 amount=-1 +kerning first=80 second=198 amount=-1 +kerning first=80 second=256 amount=-1 +kerning first=80 second=258 amount=-1 +kerning first=80 second=260 amount=-1 +kerning first=84 second=118 amount=-1 +kerning first=84 second=120 amount=-1 +kerning first=84 second=198 amount=-1 +kerning first=84 second=227 amount=-1 +kerning first=84 second=228 amount=-2 +kerning first=84 second=240 amount=-1 +kerning first=86 second=44 amount=-1 +kerning first=86 second=45 amount=-1 +kerning first=86 second=46 amount=-1 +kerning first=86 second=65 amount=-1 +kerning first=86 second=97 amount=-1 +kerning first=86 second=99 amount=-1 +kerning first=86 second=100 amount=-1 +kerning first=86 second=101 amount=-1 +kerning first=86 second=103 amount=-1 +kerning first=86 second=109 amount=-1 +kerning first=86 second=110 amount=-1 +kerning first=86 second=111 amount=-1 +kerning first=86 second=112 amount=-1 +kerning first=86 second=113 amount=-1 +kerning first=86 second=114 amount=-1 +kerning first=86 second=115 amount=-1 +kerning first=86 second=192 amount=-1 +kerning first=86 second=193 amount=-1 +kerning first=86 second=194 amount=-1 +kerning first=86 second=195 amount=-1 +kerning first=86 second=196 amount=-1 +kerning first=86 second=197 amount=-1 +kerning first=86 second=198 amount=-1 +kerning first=86 second=225 amount=-1 +kerning first=86 second=227 amount=-1 +kerning first=86 second=228 amount=-1 +kerning first=86 second=229 amount=-1 +kerning first=86 second=230 amount=-1 +kerning first=86 second=232 amount=-1 +kerning first=86 second=233 amount=-1 +kerning first=86 second=240 amount=-1 +kerning first=86 second=241 amount=-1 +kerning first=86 second=243 amount=-1 +kerning first=86 second=244 amount=-1 +kerning first=86 second=246 amount=-1 +kerning first=86 second=248 amount=-1 +kerning first=86 second=256 amount=-1 +kerning first=86 second=258 amount=-1 +kerning first=86 second=260 amount=-1 +kerning first=87 second=198 amount=-1 +kerning first=88 second=45 amount=-1 +kerning first=88 second=99 amount=-1 +kerning first=88 second=101 amount=-1 +kerning first=88 second=111 amount=-1 +kerning first=88 second=118 amount=-1 +kerning first=88 second=119 amount=-1 +kerning first=88 second=121 amount=-1 +kerning first=88 second=232 amount=-1 +kerning first=88 second=233 amount=-1 +kerning first=88 second=243 amount=-1 +kerning first=88 second=244 amount=-1 +kerning first=88 second=246 amount=-1 +kerning first=88 second=248 amount=-1 +kerning first=89 second=118 amount=-1 +kerning first=89 second=120 amount=-1 +kerning first=89 second=198 amount=-1 +kerning first=89 second=227 amount=-1 +kerning first=89 second=228 amount=-1 +kerning first=89 second=240 amount=-1 +kerning first=97 second=86 amount=-1 +kerning first=98 second=86 amount=-1 +kerning first=101 second=86 amount=-1 +kerning first=102 second=44 amount=-1 +kerning first=102 second=45 amount=-1 +kerning first=102 second=46 amount=-1 +kerning first=102 second=65 amount=-1 +kerning first=102 second=192 amount=-1 +kerning first=102 second=193 amount=-1 +kerning first=102 second=194 amount=-1 +kerning first=102 second=195 amount=-1 +kerning first=102 second=196 amount=-1 +kerning first=102 second=197 amount=-1 +kerning first=102 second=198 amount=-1 +kerning first=102 second=240 amount=-1 +kerning first=102 second=256 amount=-1 +kerning first=102 second=258 amount=-1 +kerning first=102 second=260 amount=-1 +kerning first=103 second=106 amount=1 +kerning first=104 second=86 amount=-1 +kerning first=109 second=86 amount=-1 +kerning first=110 second=86 amount=-1 +kerning first=111 second=86 amount=-1 +kerning first=111 second=88 amount=-1 +kerning first=112 second=86 amount=-1 +kerning first=113 second=86 amount=-1 +kerning first=114 second=88 amount=-1 +kerning first=114 second=198 amount=-1 +kerning first=114 second=240 amount=-1 +kerning first=117 second=86 amount=-1 +kerning first=118 second=44 amount=-1 +kerning first=118 second=46 amount=-1 +kerning first=118 second=84 amount=-1 +kerning first=118 second=88 amount=-1 +kerning first=118 second=89 amount=-1 +kerning first=118 second=221 amount=-1 +kerning first=118 second=356 amount=-1 +kerning first=118 second=358 amount=-1 +kerning first=118 second=374 amount=-1 +kerning first=118 second=376 amount=-1 +kerning first=119 second=88 amount=-1 +kerning first=120 second=45 amount=-1 +kerning first=120 second=84 amount=-1 +kerning first=120 second=89 amount=-1 +kerning first=120 second=221 amount=-1 +kerning first=120 second=356 amount=-1 +kerning first=120 second=358 amount=-1 +kerning first=120 second=374 amount=-1 +kerning first=120 second=376 amount=-1 +kerning first=121 second=88 amount=-1 +kerning first=192 second=86 amount=-1 +kerning first=193 second=86 amount=-1 +kerning first=194 second=86 amount=-1 +kerning first=195 second=86 amount=-1 +kerning first=196 second=86 amount=-1 +kerning first=197 second=86 amount=-1 +kerning first=221 second=118 amount=-1 +kerning first=221 second=120 amount=-1 +kerning first=221 second=198 amount=-1 +kerning first=221 second=227 amount=-1 +kerning first=221 second=228 amount=-1 +kerning first=221 second=240 amount=-1 +kerning first=222 second=44 amount=-1 +kerning first=222 second=46 amount=-1 +kerning first=222 second=84 amount=-1 +kerning first=222 second=88 amount=-1 +kerning first=222 second=89 amount=-1 +kerning first=222 second=221 amount=-1 +kerning first=222 second=356 amount=-1 +kerning first=222 second=358 amount=-1 +kerning first=222 second=374 amount=-1 +kerning first=222 second=376 amount=-1 +kerning first=223 second=84 amount=-1 +kerning first=223 second=86 amount=-1 +kerning first=223 second=89 amount=-1 +kerning first=223 second=221 amount=-1 +kerning first=223 second=356 amount=-1 +kerning first=223 second=358 amount=-1 +kerning first=223 second=374 amount=-1 +kerning first=223 second=376 amount=-1 +kerning first=225 second=86 amount=-1 +kerning first=227 second=86 amount=-1 +kerning first=228 second=86 amount=-1 +kerning first=229 second=86 amount=-1 +kerning first=230 second=86 amount=-1 +kerning first=232 second=86 amount=-1 +kerning first=233 second=86 amount=-1 +kerning first=237 second=39 amount=1 +kerning first=237 second=63 amount=1 +kerning first=240 second=84 amount=-1 +kerning first=240 second=88 amount=-1 +kerning first=240 second=89 amount=-1 +kerning first=240 second=221 amount=-1 +kerning first=240 second=356 amount=-1 +kerning first=240 second=358 amount=-1 +kerning first=240 second=374 amount=-1 +kerning first=240 second=376 amount=-1 +kerning first=241 second=86 amount=-1 +kerning first=243 second=86 amount=-1 +kerning first=243 second=88 amount=-1 +kerning first=244 second=86 amount=-1 +kerning first=244 second=88 amount=-1 +kerning first=246 second=86 amount=-1 +kerning first=246 second=88 amount=-1 +kerning first=248 second=86 amount=-1 +kerning first=248 second=88 amount=-1 +kerning first=251 second=86 amount=-1 +kerning first=252 second=86 amount=-1 +kerning first=256 second=86 amount=-1 +kerning first=258 second=86 amount=-1 +kerning first=260 second=86 amount=-1 +kerning first=260 second=106 amount=1 +kerning first=313 second=86 amount=-1 +kerning first=313 second=118 amount=-1 +kerning first=315 second=86 amount=-1 +kerning first=315 second=118 amount=-1 +kerning first=317 second=39 amount=-2 +kerning first=317 second=84 amount=-1 +kerning first=317 second=86 amount=-1 +kerning first=317 second=87 amount=-1 +kerning first=317 second=118 amount=-1 +kerning first=317 second=356 amount=-1 +kerning first=317 second=358 amount=-1 +kerning first=317 second=372 amount=-1 +kerning first=321 second=86 amount=-1 +kerning first=321 second=118 amount=-1 +kerning first=356 second=118 amount=-1 +kerning first=356 second=120 amount=-1 +kerning first=356 second=198 amount=-1 +kerning first=356 second=227 amount=-1 +kerning first=356 second=228 amount=-2 +kerning first=356 second=240 amount=-1 +kerning first=358 second=118 amount=-1 +kerning first=358 second=120 amount=-1 +kerning first=358 second=198 amount=-1 +kerning first=358 second=227 amount=-1 +kerning first=358 second=228 amount=-2 +kerning first=358 second=240 amount=-1 +kerning first=372 second=198 amount=-1 +kerning first=374 second=118 amount=-1 +kerning first=374 second=120 amount=-1 +kerning first=374 second=198 amount=-1 +kerning first=374 second=227 amount=-1 +kerning first=374 second=228 amount=-1 +kerning first=374 second=240 amount=-1 +kerning first=376 second=118 amount=-1 +kerning first=376 second=120 amount=-1 +kerning first=376 second=198 amount=-1 +kerning first=376 second=227 amount=-1 +kerning first=376 second=228 amount=-1 +kerning first=376 second=240 amount=-1 kerning first=39 second=45 amount=-2 kerning first=39 second=65 amount=-1 kerning first=39 second=192 amount=-1 diff --git a/resources/fonts/titillium-web-semibold-24_0.png b/resources/fonts/titillium-web-semibold-24_0.png index ce5f87775f2c50cca890c933ccdf201130636208..46183d73fc24394ac35e07a9a949c9ac0454c32e 100644 GIT binary patch literal 13404 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 From cd31fc7467835f56e92072b694b21da3fd0f7724 Mon Sep 17 00:00:00 2001 From: SylvainGa <49377866+SylvainGa@users.noreply.github.com> Date: Mon, 9 May 2022 22:32:24 -0400 Subject: [PATCH 048/220] Added images for ConnectIQ --- prototypes/AOD.jpg | Bin 0 -> 37190 bytes prototypes/Crystal-Tesla.jpg | Bin 0 -> 53046 bytes prototypes/Epix2.jpg | Bin 0 -> 42364 bytes prototypes/Fenix7.jpg | Bin 0 -> 39770 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 prototypes/AOD.jpg create mode 100644 prototypes/Crystal-Tesla.jpg create mode 100644 prototypes/Epix2.jpg create mode 100644 prototypes/Fenix7.jpg diff --git a/prototypes/AOD.jpg b/prototypes/AOD.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0cbc933b560c0e9e5c6357acf6f14f4baaccb338 GIT binary patch literal 37190 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