It is currently March 28th, 2024, 10:53 am

Tiny Weather Animated

Weather skins
Post Reply
User avatar
xenium
Posts: 841
Joined: January 4th, 2018, 9:52 pm

Tiny Weather Animated

Post by xenium »

TinyW2022-2.PNG
Version 2022



.....more details on the download page





Download: https://www.deviantart.com/xenium-art/art/Tiny-Weather-Animated-939250053
Last edited by xenium on November 30th, 2022, 10:10 pm, edited 1 time in total.
User avatar
xenium
Posts: 841
Joined: January 4th, 2018, 9:52 pm

Re: Tiny Weather Animated

Post by xenium »

30-NOV-2022
The skin has been updated
User avatar
xenium
Posts: 841
Joined: January 4th, 2018, 9:52 pm

Re: Tiny Weather Animated

Post by xenium »

1-SEP-2023
The skin has been updated
User avatar
nek
Posts: 105
Joined: November 3rd, 2019, 12:00 am
Contact:

Re: Tiny Weather Animated

Post by nek »

First of all, sorry for disturbing the topic, but I have something to share I have learnt before.



1. m/s (meters per second) for WIND SPEED

(1) Units for Wind Speed
wind_speed_europe.png
Image file from: Units for wind speed in Europe (reddit.com)

m/s for wind speed is used in Japan (ja-JP), Taiwan (zh-TW) and China (zh-CN).



(2) Weather.com api request parameter and response

Weather.com api support m/s for wind speed with http request query parameter units=s
twc_api_res.png
@see
International System of Units (Wikipedia)


Announcement wrote:
Skin Authors: openstreetmap usage

Too many http requests to nominatim.openstreetmap.org from Rainmeter skins, need to be fixed.



The below is for optimizing the skin code.
package: tiny_weather_animated__updated_1_sep_2023__by_xenium_art_dfj7dz9.rmskin




2. WebParser RegExp option

(1) Better syntax of regular expression

TinyWeather\@Resources\Measures.inc

Code: Select all

[WEATHER.COMSuperParent]
Measure=WebParser
; RegExp=(?siU)^(.*)$
RegExp=(?s)^(.*)$
RegExp=(?s)^(.*)$ is much better for getting a whole string. (?siU) is used when you need to get a part of contents.

(?siU)^(.*)$ 35857 steps (regex101.com)
(?s)^(.*)$ 7 steps (regex101.com)

@description Regular expression
^ Beginning of string
$ End of string

@description about (?siU)
s modifier: single line. Dot . matches newline characters
i modifier: insensitive. Case insensitive match (ignores case of [a-zA-Z])
U modifier: Ungreedy. The match becomes lazy by default. Now a ? following a quantifier makes it greedy

.* and (?U).*? are greedy, .*? and (?U).* are ungreedy (lazy).
greedy-ungreedy.gif
Tips: regex101 settings for WebParser measure RegExp option
FLAVOR: PCRE (PHP <7.3), FUNCTION: Match, REGEX FLAGS: none | https://regex101.com/r/AZUNvH/4
regex101.webparser.regexp.png
Tips: We can see a regular expression parsing process step by step.
TOOLS > 🐞Regex Debugger (bottom left of the page on the regex101.com)

@see
WebParser RegExp, PCRE Regex Cheatsheet (debuggex.com), PCRE Syntax (rexegg.com)
3. Regular Expression Flags (?i)

TinyWeather\TinyWeather.ini

Code: Select all

[MeasureSetCounter]
Measure=String
IfMatch=(?i)0
...
i modifier: insensitive. Case insensitive match (ignores case of [a-zA-Z])

Not for a number.
4. Measure IfMatch option

(1) Usage of IfMatch option

TinyWeather\TinyWeather.ini

Code: Select all

[MeasureSetCounter]
Measure=String
String=[MeasureIcon]
IfMatch=(?i)0
IfMatchAction=[...]
IfMatch2=(?i)1
IfMatchAction2=[...]
IfMatch3=(?i)2
IfMatchAction3=[...]
IfMatch4=(?i)3
IfMatchAction4=[...]
IfMatch5=(?i)4
IfMatchAction5=[...]
IfMatch6=(?i)5
IfMatchAction6=[...]
...
IfMatch48=(?i)47
IfMatchAction48=[...]
IfMatch option behaves different from if ... elseif ... elseif ... elseif ... end,
It is something like if ... end. if ... end. if ... end. if ... end. ...
For instance, if the string value is 15, it matches 1 and IfMatchAction2 will be performed, then it matches 5 and IfMatchAction6 will be performed. Finally it will match 15.


(2) An example code of [MeasureSetCounter]

TinyWeather\TinyWeather.ini

Code: Select all

[MeasureSetCounter]
Measure=String
Group=Counters
String=[MeasureIcon]
DynamicVariables=1
Disabled=1
UpdateDivider=-1
IfMatchMode=1
IfMatch=^
IfMatchAction=[!SetOption MeasureCounter Formula "Counter % 28"]
IfMatch2=^(?:19|20|21|22)$
IfMatchAction2=[!SetOption MeasureCounter Formula "Counter % 90"]
IfMatch3=^26$
IfMatchAction3=[!SetOption MeasureCounter Formula "Counter % 46"]
IfMatch4=^44$
IfMatchAction4=[!SetOption MeasureCounter Formula "Counter % 1"]
IfMatch=^ always return true, even if the string value is blank (empty string).
IfMatchAction will be performed first, then evaluate the IfMatch2=, IfMatch3=, IfMatch4= on the [MeasureSetCounter] measure updating.

@description Regular expression
^ Beginning of string
$ End of string
(?:...) non-capturing group. (?:AB|CD|EF) AB or CD or EF

@see
Measure IfMatch, Measure IfMatchMode, PCRE Regex Cheatsheet (debuggex.com), PCRE Syntax (rexegg.com)
5. [Rainmeter] DefaultUpdateDivider=-1 option
nek wrote:
Purpose of this chapter
◾ Learn what UpdateDivider and DefaultUpdateDivider are. (Refer to the description below)
◾ Learn what steps are taken during the Update cycle of a skin in Rainmeter. (⭐ How a skin is updated)
◾ Minimize the number of measures/meters those are updating in the skin update cycle, to reduce a Rainmeter.exe 's workload.


core_measure_ud.png
Left side: Normal Rainmeter skin.
Right side: Optimized Rainmeter Date and Time skin. Set DefaultUpdateDivider=-1 on the [Rainmeter] and set UpdateDivider=1 on the Core Measure.


skin_type_core_measure.png
For Tiny Weather Animated skin, Core Measure are WebParser measure (weather data) and Calc:Counter measure (animation).

Rainmeter Documentation wrote:
UpdateDivider (default: 1) - Measure and Meter option
Frequency at which the measure/meter is updated. The Update option in the [Rainmeter] section of the skin is multiplied by the specified value to determine how often the measure/meter is updated.
Example: If Update=1000 (in the [Rainmeter] section) and UpdateDivider=30, the measure/meter is updated every 30 seconds.
If UpdateDivider=-1 or any negative number, then the measure/meter is only updated once when the skin is loaded or refreshed.

DefaultUpdateDivider (default: 1) - [Rainmeter] section option
This option is designed to set a default UpdateDivider for all measures and meters in the skin. It can be overridden by setting UpdateDivider on individual measures or meters.


(1) Set DefaultUpdateDivider=-1 option on the [Rainmeter]

TinyWeather\TinyWeather.ini

Code: Select all

[Rainmeter]
Update=60
BackgroundMode=2
SolidColor=0,0,0,1

; DynamicWindowSize=1
DefaultUpdateDivider=-1
Update=60 option is set for the Animation (16 fps) of the weather icon.
Using DefaultUpdateDivider=-1 option on the [Rainmeter] section is recommended.

@see
[Rainmeter] DynamicWindowSize, [Rainmeter] DefaultUpdateDivider, Measure UpdateDivider


nek wrote:
Off Topic An example code for a normal weather skin as a first step.

Code: Select all

[Rainmeter]
Update=60000
DefaultUpdateDivider=-1
AccurateText=1
MouseActionCursor=0

[sWebParser]
Measure=WebParser
URL=...
RegExp=...
UpdateDivider=1
UpdateRate=15
Flags=Resync | NoCookies
Header=Connection: close
Header2=DNT: 1
Header3=Sec-GPC: 1
UserAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/120.0
FinishAction=...[!UpdateMeter *][!Redraw]
The WebParser accesses and parses the remote resource every 15 minutes.

Q. What is Connection header for?
A. The Connection general header controls whether the network connection stays open after the current transaction finishes. If the value sent is keep-alive, the connection is persistent and not closed, allowing for subsequent requests to the same server to be done. (MDN Web Docs)

Q. Why should it be set Connection: close header? (WebParser: parser mode)
A. Setting header Connection: close on a WebParser measure is nice to HTTP/1.1 server and client.
If Connection: close header is NOT set on the WebParser measure, Connection: keep-alive mode is adopted by default.
The network connection (TCP) will be kept 60 - 100 seconds from the last transaction. Connection: keep-alive mode is designed for a web browser.


@see
WebParser measure
HTTP header Connection (MDN Web Docs), Latest Web Browser User Agents (whatismybrowser.com)


(2) Set UpdateDivider=1 option on the [MeasureCounter] (Calc: Counter)

TinyWeather\TinyWeather.ini

Code: Select all

[MeasureCounter]
Measure=Calc
Group=Counters
Disabled=1

UpdateDivider=1
OnChangeAction=[!UpdateMeter MeterIcon]
Added [!UpdateMeter MeterIcon] OnChangeAction for animation.

@see
Measure UpdateDivider, Measure OnChangeAction, Calc measure Counter



(3) Set UpdateDivider=1 option on the [WEATHER.COMSuperParent] (WebParser)

TinyWeather\@Resources\Measures.inc

Code: Select all

[WEATHER.COMSuperParent]
Measure=WebParser
URL=#URL#
UpdateRate=10000
Flags=Resync | NoCookies
DecodeCharacterReference=1
LogSubstringErrors=0
StringIndex=1

Header=Connection: close
UpdateDivider=1
; RegExp=(?siU)^(.*)$
RegExp=(?s)^(.*)$
; UserAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
UserAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/120.0
; FinishAction=[!EnableMeasureGroup Parents]
FinishAction=[!EnableMeasureGroup Parents][!UpdateMeter *][!Redraw]
Added [!UpdateMeter *][!Redraw] on the FinishAction option.

Accesses and parses the remote resource every 10 minutes. (= 600 seconds = 600000 milliseconds)
[Rainmeter] Update=60 * [WEATHER.COMSuperParent] UpdateDivider=1 * UpdateRate=10000

@see
WebParser FinishAction, WebParser: How UpdateRate Works
HTTP header Connection (MDN Web Docs), Latest Web Browser User Agents (whatismybrowser.com)



(4) Append [MeasureToggleAtNight] measure

TinyWeather\@Resources\Measures.inc

Code: Select all

[MeasureToggleAtNight]
Measure=String
String=[MeasureDailyPrecipDay1]
DynamicVariables=1
IfMatchMode=1
IfMatch=^$
IfMatchAction=[!UpdateMeasure MeasureDailyPrecipDay1]
Disabled=1
Dealing with empty data of the day. If [MeasureDailyPrecipDay1] value is empty, [MeasureDailyPrecipNight1] value will be used.

Code: Select all

[WEATHER.COMSuperParent]
; FinishAction=[!EnableMeasureGroup Parents]
; FinishAction=[!EnableMeasureGroup Parents][!UpdateMeter *][!Redraw]
FinishAction=[!EnableMeasureGroup Parents][!EnableMeasure MeasureToggleAtNight][!UpdateMeasure MeasureToggleAtNight][!UpdateMeter *][!Redraw]

nek wrote:
Off Topic
All measure and meter have some tasks during updating itself. (⭐ How a skin is updated)
We can see how often the measures/meters are updating for debugging purpose.
Adding the following code and save then refresh the skin, open About Rainmeter window > Log tab

Code: Select all

[MeasureName/MeterName]
UpdateDivider=1
OnUpdateAction=[!Log "#CURRENTSECTION# | Update" warning]

@see
How a skin is updated by Brian and jsmorley
💡 Reducing a cpu and memory usage of a skin by nek



The below is additional optimization.
If you would like to keep compatibility with jsmorley's WeatherComJSON package, these might not nesessary.




6. Weather.com api request query parameters

(1) Request an only needed data by the skin

TinyWeather\@Resources\Variables.inc

Code: Select all

URL=...
Changed: from v3-wx-forecast-daily-15day to v3-wx-forecast-daily-3day
Removed: v3alertsHeadlines and v3-wx-forecast-hourly-12hour

Response data: json file size: from 17 KB to 6 KB
The weather.com services have millions of api requests per second, I guess. We need to keep skins to be gentle to the servers.


(2) Modify the regular expressions

TinyWeather\@Resources\RegExp.inc

Code: Select all

; DailyForecastTempMax=(?siU)"v3-wx-forecast-daily-15day":.*{.*"temperatureMax":(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),.*
DailyForecastTempMax=(?siU)"v3-wx-forecast-daily-3day":.*{.*"temperatureMax":(.*),

; DailyForecastTempMin=(?siU)"v3-wx-forecast-daily-15day":.*{.*"temperatureMin":(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),.*
DailyForecastTempMin=(?siU)"v3-wx-forecast-daily-3day":.*{.*"temperatureMin":(.*),

; DailyForecastPrecip=(?siU)"v3-wx-forecast-daily-15day":.*{.*"precipChance":(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),.*
DailyForecastPrecip=(?siU)"v3-wx-forecast-daily-3day":.*{.*"precipChance":(.*),(.*),
7. WebParser RegExp option again

(1) Change RegExp= code (non-capturing) and remove StringIndex=1

TinyWeather\@Resources\Measures.inc

Code: Select all

[WEATHER.COMSuperParent]
Measure=WebParser
; RegExp=(?s)^(.*)$
; RegExp=(?s)^.*$
RegExp=\A[\s\S]*\z
; StringIndex=1
When getting a whole string of a remote content, there is no need to capture with (), since the WebParser has already had the whole string data. (About Rainmeter > Skins > TinyWeather > WEATHER.COMSuperParent : String value).
You might use RegExp=\A[\s\S]*\z or RegExp=(?s)^.*$.

@description
(?s) modifier: single line. Dot . matches newline characters
^ Beginning of string
$ End of string
\A Very beginning of string
\z Very end of string
\s Whitespace characters [\r\n\t\f\v ]
\S Non-whitespace characters [^\r\n\t\f\v ]

[\s\S]* is equivalent to (?s).*

@see
PCRE Regex Cheatsheet (debuggex.com), PCRE Syntax (rexegg.com)



(2) Remove StringIndex=1 from [WEATHER.COMSuperParent] 's child measures

TinyWeather\@Resources\Measures.inc

Code: Select all

[MeasureLocation]
Measure=WebParser
Group=Parents
URL=[WEATHER.COMSuperParent]
Disabled=1
; StringIndex=1
RegExp=#Location#
LogSubstringErrors=0
[MeasureCurrentObservations], [MeasureDailyForecastTempMax],
[MeasureDailyForecastTempMin], [MeasureDailyForecastPrecip]

@see
WebParser StringIndex



Final code

📦 TinyWeather.Optimized.2023-11-27.zip (11.3 MB, GitHub.com)

Modified files
TinyWeather\TinyWeather.ini
TinyWeather\@Resources\Measures.inc
TinyWeather\@Resources\RegExp.inc
TinyWeather\@Resources\Variables.inc

Note that this is one of the examples of optimizing Rainmeter skin code.
TinyWeather\Language\Language.ini file is not modified. You might apply units=s (m/s for wind speed) related things if you would like to.

Edited: 2023-12-23
Recommend checking out a new api key.





Announcement wrote:
Skin Authors: openstreetmap usage

Too many http requests to nominatim.openstreetmap.org from Rainmeter skins, need to be fixed.
Last edited by nek on December 23rd, 2023, 12:04 pm, edited 11 times in total.
User avatar
Yincognito
Rainmeter Sage
Posts: 7017
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Tiny Weather Animated

Post by Yincognito »

I won't touch the suggestions above (by the way, I'm one of the first, if not one of the few who, ever since I created my suite, only updated the weather once an hour as it's not changing every minute, and not using nominatim at all since it's no big deal to look for your geocode online on wiki), but just so folks know, that measurement units map linked above is not exactly accurate in practice, things are more consistent over the continent in that regard...
Post Reply