It is currently October 27th, 2020, 3:04 am

Help with variables

Help with creating, editing & fixing problems with skins
User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Help with variables

Post by Codger »

First, I've only been working in RainMeter for a few weeks. Second I'm fairly old and while I did a fair amount of coding in the distant past things come to me much slower now. Third, I'm wordy, please bear with me.

There is much in RM that I find confusing but am slowly wrapping my mind around. However I think I have made a fundamental confusion with variables early on.

I get that most variables in RM are static variables. I am have trouble with the scope of the dynamic ones.

The documentation seems to suggest that the scope is the measure or meter involved This leaves me with the question of initial initialization.

Let's use my current problem as an example. I have a setup where my external IP changes at random intervals 3 to 5 times an hour. So I've been working on a skin that measured my ping, external ip and the location of that IP. It took over a week to learn RM well enough to get that done. Now I'm trying to clean it up, cover more exceptional situations, timeout, errors, etc.

Currently I call the location website every 20 minutes. Ideally I'd like to call it only when the IP address changes (which I check every 90 seconds - eventually I will be able to figure out a way to detect the change over period and only call then.)

So:

Code: Select all

[MeasureExtIP]
Measure=Plugin
Plugin=WebParser
Url=http://icanhazip.com 
RegExp="(?siU)^(.*)$"
StringIndex=1
UpdateRate=90
FinishAction=[!UpdateMeter "MeterExtIP"]
IfCondition=MeasureExtIP<>IPLast
IfTrueAction=[!SetVariable IPLast MeasureExtIP][!UpdateMeasure "MeasureWebParseLocation"]
DynamicVariables=1
So my question (finally) is how do I set an initial value and existence of IPLast that runs only the first time the skin is loaded?
[hr][/hr][hr][/hr]
"If you are the smartest one in the room, you are in the wrong room."
User avatar
balala
Rainmeter Sage
Posts: 11634
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Help with variables

Post by balala »

Codger wrote:So my question (finally) is how do I set an initial value and existence of IPLast that runs only the first time the skin is loaded?
Adding it to the [Variables] section:

Code: Select all

[Variables]
IPLast=Its initial value
User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Re: Help with variables

Post by Codger »

The documentation lead me to believe that putting it in the variables section would make it a static variable.
And when I tried it anyway it failed. But perhaps I did something wrong and will go try again in that vein.
Thank you for your time and swift response.
[hr][/hr][hr][/hr]
"If you are the smartest one in the room, you are in the wrong room."
User avatar
jsmorley
Developer
Posts: 21435
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with variables

Post by jsmorley »

1) Variables are always "global" in the context of a skin.
2) Variables are initialized in a [Variables] section in the skin.
3) Variables are "used" (resolved for the value) by enclosing the variable name in # symbols. If you are changing the value of a variable, you must use DynamicVariables=1 where it is "used".
4) The value of a measure is used with as a section variable by enclosing the measure name in [] square brackets.

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[Variables]
IPlast=XXX.XXX.XXX.XXX

[MeasureExtIP]
Measure=Plugin
Plugin=WebParser
Url=http://icanhazip.com 
RegExp="(?siU)^(.*)$"
UpdateRate=90
FinishAction=[!EnableMeasure MeasureCheck][!UpdateMeasure MeasureCheck]

[MeasureCheck]
Measure=Plugin
Plugin=WebParser
Url=[MeasureExtIP]
StringIndex=1
IfMatch=#IPLast#
IfNotMatchAction=[!SetVariable IPLast "[MeasureCheck]"][!WriteKeyValue Variables IPLast "[MeasureCheck]"]
DynamicVariables=1
Disabled=1

[MeterExtIP]
Meter=String
MeasureName=MeasureCheck
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
So what this does is:

1) Initialize the variable IPLast to XXX.XXX.XXX.XXX the first time the skin is run.
2) Go out and get the actual IP address from icanhazip.
3) Enable and update a child measure that will be used to get the value from StringIndex 1 of the parent.
4) Use IfMatch to test if the value is the same as the #IPLast# variable.
Note that an IP address is not a "number" but a "string", and you can't test it with IFCondition. You must use IFMatch.
5) If the value is different, if the string match is "not true", then set the value of the variable IPLast to the new value.
6) Also if it is different, then physically "write" the value to the IPLast variable in the [Variables] section of the skin .ini file.
This is to ensure that if you refresh the skin, or when you restart Rainmeter or your computer, the value you obtained is "persistent".

Let me know if you have questions.
User avatar
balala
Rainmeter Sage
Posts: 11634
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Help with variables

Post by balala »

Sorry jsmorley, I've started to write my reply, when you've posted yours...
Codger wrote:The documentation lead me to believe that putting it in the variables section would make it a static variable.
And when I tried it anyway it failed. But perhaps I did something wrong and will go try again in that vein.
Thank you for your time and swift response.
A very important thing is that you have to add a DynamicVariables=1 option to the measure or meter which uses the dynamically set variable (in your case to the measure or meter, which has the #IPLast# expression). This is very important, without this option, the according measure or meter won't be able to use the new value of the variable. Because for example the [Rainmeter] section doesn't support the dynamic variables, you can't use them there.
User avatar
jsmorley
Developer
Posts: 21435
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with variables

Post by jsmorley »

One other clarification on DynamicVariables=1.

If you use a #VariableName# or [MeasureName] in any "option" of a measure or meter, anything that is SomeOption=SomeValue, and that variable or measure value is going to "change", that measure or meter must have DynamicVariables=1 on it so it will know that it needs to get the current value of the variable or measure.

This is done so we can save a CPU cycle or two on any measures or meters that are using a #Variable# or [MeasureName] in a "static" way. For instance:

[Variables]
MyColor=255,255,255,255

[MeterName]
FontColor=#MyColor#

There is no reason in that case to be constantly checking and resolving the value of #MyColor# on every skin update, it's not going to change. If it IS going to change, then you need to tell it to do the tiny bit of extra work.


However, when you use either in the context of a "!bang", anything that is SomeAction=[!SomeBangName "SomeBangParameters"] you don't need DynamicVariables. Anything inside a [!SomeBangName] is always treated as dynamic and will use the current value of the variable or measure.

That is why we needed DynamicVariables=1 to support the changing #VariableName# in:

IfMatch=#IPLast#

But to be clear we didn't need it to support the [MeasureName] in:

IfNotMatchAction=[!SetVariable IPLast "[MeasureCheck]"][!WriteKeyValue Variables IPLast "[MeasureCheck]"]
User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Re: Help with variables

Post by Codger »

Thank you all for your kindness. I've been on many coding forums in the past most ranging from condescending to dismissive. There is a very welcoming supportive community vibe here of which I am appreciative.

I gained a lot of understanding in the examples provided. The 'Disabled' command alone made me very happy as that was a problem fixed for part I haven't written yet.

That said, I'd like to be lazy now. I'm tired of staring at this problem and would like to just post the whole code and have you show me what I am doing wrong. I'm not asking to have the whole thing transformed. There is much wrong, much not finished and much more that can be streamlined and improved. But I look forward to doing all that myself.

I just want this one little part to work. I think at this point I can learn more from the correction than by fighting (randomly making changes) for it.

When I run it, it shows the Ext IP and after 5 seconds the Location. So the location display code (very bottom of the skin) still works. If the IP changes, less than 90 seconds later the IP display updates. But the location display does not. I can see your part work but the part I had to add clearly does not.

I took the timer off the location so that it would only be called when needed. That is probably where I messed up but I can't see it.

Again, please resist the urge to tidy and improve. I'd appreciate as little as humanly possible be changed to make the location measure update when the ip changes. I look forward to fixing the rest as I learn.

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1

[Metadata]
Name=Traffic
Author=Codger
Information=My second widget
Version=0.1.2
License=Free to all to do with as they like

 
;	Notes: This widget makes use of three websites:
;
;	http://www.Bing.com is called every 3 seconds to test Ping.
;	http://icanhazip.com is called every 90 seconds to determine External IP
;	http://ipinfo.io/ is called every 20 minutes to determine location 
;		(eventually this will be tried to change in External IP)
;

[Variables]
; Static Variables
BackPadding=15
BarWidth=330
;tied to PingBar.png

PureBlue=0,0,255
PureRed=255,0,0
PureGreen=0,255,0
PureYellow=255,255,0
PureWhite=255,255,255
BurntOrange=153,76,0
MediumOrange=255,128,0
RedOrange=255,51,51
DarkGreen=0,102,0

BarBackColor=60,60,60,200
BarTextColor=#PureWhite#,255
DownloadColor=#DarkGreen#,255
UploadColor=#BurntOrange#,255
OverloadColor=#PureRed#,255
PingColor=#PureBlue#,255
PingHighColor=#RedOrange#,255
PingOverloadColor=#PureRed#,255
OfflineColor=255,0,0,255

PingSite="www.bing.com"
HighestLikelyTraffic=2750000
HighestPing=300

IPlast=196.52.48.67


[Background]
Meter=Image
W=(#BarWidth# + (#BackPadding#*2))
H=216
SolidColor=30,30,30,200
BevelType=1
UpdateDivider=-1

;
; PIA Status
; Just displays a logo at the moment. 
;Future spot for PIA and LeapIP status indication
;
[PIAStatus]
Meter=Image
ImageName=@Resources\PIAGreen.png
W=32
H=32
Y=5r
X=(((#BarWidth#/2) + #BackPadding#/2)-8)

;
; Ext IP

[MeasureExtIP]
Measure=Plugin
Plugin=WebParser
Url=http://icanhazip.com 
RegExp="(?siU)^(.*)$"
StringIndex=1
UpdateRate=90
FinishAction=[!EnableMeasure MeasureCheck][!UpdateMeasure MeasureCheck]

[MeasureCheck]
Measure=Plugin
Plugin=WebParser
Url=[MeasureExtIP]
StringIndex=1
IfMatch=#IPLast#
IfNotMatchAction=[!SetVariable IPLast "[MeasureCheck]"][!WriteKeyValue Variables IPLast "[MeasureCheck]"][!UpdateMeasure "MeasureWebParseLocation"]
IfMatchMode=1
DynamicVariables=1
Disabled=1

[MeterExtIP]
Meter=String
MeasureName=MeasureExtIP
X=#BackPadding#
Y=15r
FontSize=10
StringStyle=Bold
FontColor=#PureYellow#,255
Text="Ext IP: %1"

;
; Online

[Internet]
Measure=Plugin
Plugin=SysInfo
SysInfoType=INTERNET_CONNECTIVITY
SysInfoData=Best
UpdateDivider=-1

[InternetStatus]
Measure=String
String=Status: [Internet]
Substitute="-1":"Offline", "1":"Online"
DynamicVariables=1
UpdateDivider=1

[MeterInternetStatus]
Meter=String
MeasureName=InternetStatus
X=(#BarWidth#+#BackPadding#)
Y=r
FontSize=10
StringStyle=Bold
StringAlign=Right
FontColor=150,150,150,255
InlineSetting=Color | #OfflineColor#
InlinePattern=Offline
DynamicVariables=1
;!Redraw

; 1st
; Ping

[MeasurePing]
Measure=Plugin
Plugin=PingPlugin
DestAddress=#PingSite#
Timeout=3000
UpdateRate=3
FinishAction=[!UpdateMeter "MeterPingBar"][!UpdateMeter "MeterPing"]
TimeoutAction=[!UpdateMeter "MeterPingBar"][!UpdateMeter "MeterPing"]

[BoundPing]
Measure=Calc
MinValue=0
MaxValue=#HighestPing#
Formula=MeasurePing
;IfEqualValue=30000
;IfEqualAction=
; Internet Offline ^

[FormatPing]
Measure=String
MeasureName=Internet
Substitute "-1" : "Offline", "1" : "Ping: %1ms"

[MeterPingBar]
Meter=BAR
MeasureName=BoundPing
X=#BackPadding#
Y=20r
W=#BarWidth#
H=21
; if H is changed dimensions of PingBar.png must changed as well.
;BarColor=#PingColor#
SolidColor=#BarBackColor#
BarImage=@Resources\PingBar.png
BarOrientation=Horizontal
BevelType=1
UpdateDivider=-1

[MeterPing]
Meter=String
MeasureName=BoundPing
X=4r
Y=3r
FontSize=10
StringStyle=Bold
FontColor=#BarTextColor#
Text =  "Ping: %1ms"
UpdateDivider=-1

; 2nd
; Current Upload Traffic

[MeasureUploadTraffic]
Measure=NetOut
Interface=Best
AutoScale=2

[BoundUploadTraffic]
Measure=Calc
MinValue=0
MaxValue=#HighestLikelyTraffic#
Formula=MeasureUploadTraffic

[MeterUploadBar]
Meter=BAR
MeasureName=BoundUploadTraffic
X=-4r
Y=25r
W=#BarWidth#
H=21
MinValue=0
MaxValue=#HighestLikelyTraffic#
BarColor=#UploadColor#
SolidColor=#BarBackColor#
BarOrientation=Horizontal
BevelType=1

[MeterUploadText]
Meter=String
MeasureName=MeasureUploadTraffic
X=4r
Y=3r
FontSize=10
StringStyle=Bold
FontColor=#BarTextColor#
AutoScale=1
NumOfDecimals=1
Text="Upload: %1"

; 3rd
; Current Download Traffic

[MeasureDownloadTraffic]
Measure=NetIn
Interface=Best
AutoScale=2

[BoundDownloadTraffic]
Measure=Calc
MinValue=0
MaxValue=#HighestLikelyTraffic#
Formula=MeasureDownloadTraffic
Percentual=1

[MeterDownloadBar]
Meter=BAR
MeasureName=BoundDownloadTraffic
X=-4r
Y=25r
W=#BarWidth#
H=21
MinValue=0
MaxValue=#HighestLikelyTraffic#
BarColor=#DownloadColor#
SolidColor=#BarBackColor#
BarOrientation=Horizontal
BevelType=1

[MeterDownloadText]
Meter=String
MeasureName=MeasureDownloadTraffic
X=4r
Y=3r
FontSize=10
StringStyle=Bold
FontColor=#BarTextColor#
AutoScale=1
NumOfDecimals=1
Text="Download: %1"

;
; Network Traffic Histograph

[MeterUploadHistogram]
Meter=Histogram
MeasureName=BoundUploadTraffic
Flip=1
X=-4r
Y=59r
W=#BarWidth#
H=30
PrimaryColor=#UploadColor#
SolidColor=#BarBackColor#
BevelType=1
AntiAlias=1

[MeterDownloadHistogram]
Meter=Histogram
MeasureName=BoundDownloadTraffic
X=r
Y=-34r
W=#BarWidth#
H=32
PrimaryColor=#DownloadColor#
SolidColor=#BarBackColor#
BevelType=1
AntiAlias=1

; Location
;

[MeasureWebParseLocation]
Measure=Plugin
Plugin=WebParser
URL=http://ipinfo.io/
RegExp=(?siU)<a class="flag .*</a>\n(.*)</td>
UpdateDivider=-1

[MeasureLocation]
Measure=Plugin
Plugin=WebParser
URL=[MeasureWebParseLocation]
StringIndex=1
DecodeCharacterReference=1
RegExpSubstitute=1
Substitute="^\s+":"","<!\[CDATA\[":"","\]\]>":"","!\[CDATA\[":"","\]\]":""

[MeterLocation]
Meter=String
MeasureName=MeasureLocation
X=2r
Y=69r
FontSize=11
StringStyle=Bold
FontColor=#PureYellow#,255
Text="@ %1"
DynamicVariables=1
UpdateDivider=5


;[Initialize]
;!UpdateMeasure "MeasurePing"
;!UpdateMeter "MeterExtIP"
;UpdateDivider=-1

However if you want to show me how to merge [MeasureWebParseLocation] and [MeasureLocation] into the one measure I think they want to be I would be happy as I am completely lost how the second one strips off leading spaces and tabs. If not the other is all that is really important at this juncture.

Oh, one thing confuses me on the previous example. If IfMatch works in a RegExp manner, why do the periods in the IP address not mess things up? What makes it literal?

Please let me know if I become annoying.
[hr][/hr][hr][/hr]
"If you are the smartest one in the room, you are in the wrong room."
User avatar
jsmorley
Developer
Posts: 21435
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with variables

Post by jsmorley »

A little hard for me to test, as my IP doesn't ever change, but I would think that using:

Code: Select all

[MeasureExtIP]
Measure=Plugin
Plugin=WebParser
Url=http://icanhazip.com 
RegExp="(?siU)^(.*)$"
StringIndex=1
UpdateRate=90
FinishAction=[!EnableMeasure MeasureCheck][!UpdateMeasure MeasureCheck][!CommandMeasure MeasureWebParseLocation "Update"]
And removing UpdateDivider=-1 from [MeaasureWebParseLocation]

Should do the trick.

That !CommandMeasure is needed since that [MeasureWebParseLocation] measure will have the default UpdateRate of 300 (10 minutes) and you want to override that and force a full "go out to the web" update when [MeasureEXtIP] finishes.
User avatar
jsmorley
Developer
Posts: 21435
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with variables

Post by jsmorley »

Codger wrote: Oh, one thing confuses me on the previous example. If IfMatch works in a RegExp manner, why do the periods in the IP address not mess things up? What makes it literal?
Well, in this case the period means one of any character, and "." is a character isn't it... ;-)
User avatar
jsmorley
Developer
Posts: 21435
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with variables

Post by jsmorley »

Codger wrote:Thank you all for your kindness. I've been on many coding forums in the past most ranging from condescending to dismissive. There is a very welcoming supportive community vibe here of which I am appreciative.
Glad to help. We really don't allow "condescending" or "dismissive" here. That's just narcissistic and helps nobody. Not what we are about...