Update 2017-05-01: Added JavaScript transformation to test for valid IP.
Most Internet Service Providers (ISP) provide you with a dynamic WAN IP address. This address may change over time. If you rely on this address, for example for accessing a computer inside your home network, you might want to monitor changes to the address. Websites like icanhazip and WhatIsMyIP return your public IP address as plain text.
This solution grabs that address and stores it in an item. A rule monitors changes to the item and acts on it.
This solution requires that you have the HTTP Binding installed.
Note: Please be nice to the websites you ping. Don’t increase the interval above once per minute.
valid_ip.js
// return valid IP or '-'
(function(ip) {
// remove blanks first
ip = ip.replace(/\s/g, '');
// http://stackoverflow.com/a/26445549
var rx=/^(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|$)){4}$/;
if (rx.test(ip)) {
return (ip);
}
else {
return "-";
}
})(input)
// input variable contains data passed by openhab
demo.items
// check for WAN IP address changes every 10 mins
String Network_WAN_IP "WAN IP address [%s]" <network> (Network) { http="<[http://icanhazip.com:600000:JS(valid_ip.js)]" }
demo.rules
rule "Monitor WAN IP"
when
Item Network_WAN_IP changes
then
// perform any action needed
val currentState = Network_WAN_IP.state
if (currentState == "-") {
logError("MonitorWANIP", "Unable to get WAN IP")
} else {
logInfo("MonitorWANIP", "WAN IP changed to: " + currentState)
}
end
demo.sitemap
sitemap demo label="Demo" {
Frame {
Text item=Network_WAN_IP
}
}
I have already added this solution to a wiki page:
Dynamic DNS services are very handy and many routers have included support to send updates to them.
I am using no-ip.com, which is fine but asks for reactivation once a month. Other solutions are available. Random comparison article:
Background:
I have openhab on 1 computer in one VLAN , ex 192.168.1.x with a normal WAN IP.
However, I would like to check if the WAN IP changes on another VLAN ex 192.168.2.x.
Reason, this WAN IP is always on an VPN.
I can access the second VLAN from my openhab.
Would it be possible somehow to make openhab ask VLAN ‘2’ for its WAN IP adress just for this instance?
I would like top check if it goes down and reveals my “real WAN IP”.
You can do this by setting a host route in your openHAB system. I.e. if you’re using the solution from above, you just have to add this route (Linux in this case):
ip route add 45.76.25.15/32 via 192.168.2.254
where 45.76.25.15 is the IP of icanhazip.com and 192.168.2.254 is your router in VLAN 2.
Obviously I’m a dumbnut, but could not get it to work via adding the routes normally.
Fortunately, there was a another routing setting in my router so I could set the destination IP to go via VPN instead which worked as expected.
Thank you for the help!
Thanks for the tipp.
I am using icanhazip.com successfully, but have one issue:
Sometimes it does not work and the entire html response wll flood my log file.
So I would like to check whether the returned String is shorter than 17 digits.
Any suggestion how I could do this within OH (without an external script)?
Thanks in advance.
That’s exactly the problem I encountered, but I hoped it was just a temporary issue.
Obviously it’s not…
Fritzbox wanip (with Fritzbox TR064 binding) is not working either…
The original example used the default REGEX transformation to just return the output of the web request. I have modified the example to use a JavaScript transformation that tests for a valid IP address. Please see above.
Cookie messages are gone, but as far as I have noticed the icanhazip service kept working as expected.
One question:
When starting in openhab.log I get the error message:
2017-09-09 15:59:59.444 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model ‘wanip.rules’ has errors, therefore ignoring it: [3,5]: no viable alternative at input ‘changes’
2017-09-09 16:00:05.296 [ERROR] [ab.binding.http.internal.HttpBinding] - Transformation ‘JS(valid_ip.js)’ threw an exception. [response=xx.xx.xx.xx
]
org.openhab.core.transform.TransformationException: An error occurred while loading script.
at org.openhab.core.transform.TransformationHelper$TransformationServiceDelegate.transform(TransformationHelper.java:62)[189:org.openhab.core.compat1x:2.1.0]
at org.openhab.binding.http.internal.HttpBinding.execute(HttpBinding.java:189)[188:org.openhab.binding.http:1.10.0]
at org.openhab.core.binding.AbstractActiveBinding$BindingActiveService.execute(AbstractActiveBinding.java:157)[189:org.openhab.core.compat1x:2.1.0]
at org.openhab.core.service.AbstractActiveService$RefreshThread.run(AbstractActiveService.java:169)[189:org.openhab.core.compat1x:2.1.0]
Do you know something about it?
My *.rules file:
rule "Monitor WAN IP"
when
Item Network_WAN_IP changes
then
// perform any action needed
val currentState = Network_WAN_IP.state
if (currentState == “-”) {
logError(“MonitorWANIP”, “Unable to get WAN IP”)
} else {
logInfo(“MonitorWANIP”, "WAN IP changed to: " + currentState)
}
end
Hello Robert, thanks for your fast reply. Yes, I am using OH2. As written in the link I created the getValue.js file in /etc/openhab2/transform folder:
2017-09-10 17:42:19.171 [ERROR] [ab.binding.http.internal.HttpBinding] - Transformation ‘JS(valid_ip.js)’ threw an exception. [response=91.240.65.131
]
org.openhab.core.transform.TransformationException: An error occurred while loading script.
at org.openhab.core.transform.TransformationHelper$TransformationServiceDelegate.transform(TransformationHelper.java:62)[189:org.openhab.core.compat1x:2.1.0]
at org.openhab.binding.http.internal.HttpBinding.execute(HttpBinding.java:189)[188:org.openhab.binding.http:1.10.0]
at org.openhab.core.binding.AbstractActiveBinding$BindingActiveService.execute(AbstractActiveBinding.java:157)[189:org.openhab.core.compat1x:2.1.0]
at org.openhab.core.service.AbstractActiveService$RefreshThread.run(AbstractActiveService.java:169)[189:org.openhab.core.compat1x:2.1.0]
every ten minutes.
My valid_ip.js
// return valid IP or '-'
(function(ip) {
// remove blanks first
ip = ip.replace(/\s/g, '');
// http://stackoverflow.com/a/26445549
var rx=/^(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|$)){4}$/;