# Check current dynamic IP then store it if it's new or update timestamp if it's not

**URL:** <https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902>\
**Category:** General\
**Created:** [18 June 2018 23:37 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902 "2018-06-18T23:37:10Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Noh](https://avatars.discourse-cdn.com/v4/letter/n/46a35a/32.png) [@Noh](https://discourse.nodered.org/u/Noh)\
**Post date:** [18 June 2018 23:37 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/1 "2018-06-18T23:37:10Z")

</div>

My in-laws are on DHCP, with their ISP but they occasionally need me to administer their OpenSuse desktop (yes, they’re on Linux). It takes several tens of minutes, every time to get them to find and reveal their WAN IP. As a result, I’m using a Raspberry Pi zero W, piggbacking their router, powered by its USB. Currently I’ve got a shell script run by cron every 5 minutes. It works but I’m using mailx to send me the IP, if it’s updated but Google have made life much more difficult, so I’m trying Node-Red & MQTT to try and achieve similar results but more efficiently.

So far I’ve used `curl 'http://api.ipify.org/'` in an exec node to periodically return my WAN IP and store it. Now I want to compare it to a file (csv, json, text?), to see if this IP is the same as the one on the last line. If it is, then I want to update the timestamp (first seen & last seen) on the last line of the file. If it’s not, I want to append the IP & timestamp to the file. Finally, I’ll use mqtt to also log the IP with the time it was first seen and the time it was last seen on my server.

I can’t see a Node-Red way to check the last row of the file and compare it to the msg.payload of my IP check, then take one of the two actions accordingly (update timestamp or append a new line)

Can anyone suggest a good pattern to follow with Node-Red?

---

<div class="post-metadata">

**Author:** ![cflurin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/cflurin/32/29_2.png) [@cflurin](https://discourse.nodered.org/u/cflurin)\
**Post date:** [19 June 2018 00:26 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/2 "2018-06-19T00:26:30Z")

</div>

To get the ip you could also use the `http request` node:

```auto
[{"id":"df8b7ad8.2a01c8","type":"http request","z":"cf6706ec.415a58","name":"","method":"GET","ret":"txt","url":"","tls":"","x":510,"y":1040,"wires":[["95331697.0175f8"]]},{"id":"95331697.0175f8","type":"debug","z":"cf6706ec.415a58","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":1040,"wires":[]},{"id":"46f1b0ad.fbc45","type":"change","z":"cf6706ec.415a58","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":1040,"wires":[["df8b7ad8.2a01c8"]]},{"id":"a150a92a.c7f9d8","type":"inject","z":"cf6706ec.415a58","name":"http://api.ipify.org/","topic":"http://api.ipify.org/","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":1040,"wires":[["46f1b0ad.fbc45"]]}]

```

To store and compare the ip you might use a flow/global variable and the `contrib-persist` node:

> **[node-red-contrib-persist](https://flows.nodered.org/node/node-red-contrib-persist)**
>
> A node-red node to persist data between Node Red deploys and restarts.

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [19 June 2018 10:04 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/3 "2018-06-19T10:04:20Z")

</div>

Why not set them up with a bookmark to go to [ipchicken.com](http://ipchicken.com)? Or that ‘_that_’ bad with computers (I had an aunt who, when I told her to enter aomething in the address bar, would open up google and enter it into the search field and swear that is whaat I showed her to do)

---

<div class="post-metadata">

**Author:** ![nodecentral](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nodecentral/32/10432_2.png) [@nodecentral](https://discourse.nodered.org/u/nodecentral)\
**Post date:** [23 October 2018 08:50 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/4 "2018-10-23T08:50:29Z")

</div>

Hi,

I’ve loaded in the flow and also installed the persistent node, but I can’t work out how to make it all work together so it automatically checks is the new ip is different to the old one ?

Do you have an example you could share ?

---

<div class="post-metadata">

**Author:** ![cflurin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/cflurin/32/29_2.png) [@cflurin](https://discourse.nodered.org/u/cflurin)\
**Post date:** [23 October 2018 09:00 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/5 "2018-10-23T09:00:12Z")

</div>

That is an old/obsolete post!

I'm now using a dsm-node to check the ip:

```auto
[{"id":"b57294a9.594a58","type":"dsm","z":"85cbcdb3.ef251","name":"read ip","sm_config":"{\n \"currentState\": \"idle\",\n \"states\": {\n \"idle\": {\n \"read\": \"reading\"\n },\n \"reading\": {\n \"evaluade\": \"idle\"\n }\n },\n \"data\": {\n \"url\": \"http://api.ipify.org/\",\n \"ip\": null\n },\n \"methods\": {\n\t\t\"init\": [\n\t\t \"sm.request = require('request');\"\n\t\t],\n \"read\": [\n \"sm.request.get({url: sm.data.url}, function(error, response, body) {\",\n \" if (!error && response.statusCode == 200) {\",\n \" sm.data.current_ip = body;\",\n \" resume('evaluade', msg);\",\n \" } else {\",\n \" node.warn(error);\",\n \" sm.text = error.message;\",\n \" sm.fill = 'red';\",\n \" }\",\n \"});\",\n \"sm.text = 'reading';\",\n \"output = false;\"\n],\n \"evaluade\": [\n \"if (sm.data.current_ip !== sm.data.ip) {\",\n \" sm.data.ip = sm.data.current_ip;\",\n \" msg.payload = sm.data.ip;\",\n \" node.send(msg);\",\n \" sm.text = 'new ip='+sm.data.ip;\",\n \" sm.fill = 'yellow';\",\n \"} else {\",\n \" sm.text = 'unchanged ip='+sm.data.ip;\",\n \" sm.fill = 'green';\",\n \"}\",\n \"output = false;\"\n],\n \"status\": {\n \"fill\": {\n \"get\": \"sm.fill || 'blue';\"\n },\n \"shape\": \"dot\",\n \"text\": {\n \"get\": \"sm.text || 'dummy';\"\n }\n }\n }\n}\n","x":240,"y":1800,"wires":[["7027ffea.5623a"]]},{"id":"7027ffea.5623a","type":"debug","z":"85cbcdb3.ef251","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":430,"y":1800,"wires":[]},{"id":"534650cf.6a398","type":"inject","z":"85cbcdb3.ef251","name":"","topic":"read","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":1800,"wires":[["b57294a9.594a58"]]}]

```

---

<div class="post-metadata">

**Author:** ![nodecentral](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nodecentral/32/10432_2.png) [@nodecentral](https://discourse.nodered.org/u/nodecentral)\
**Post date:** [23 October 2018 09:51 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/7 "2018-10-23T09:51:55Z")

</div>

Thanks @cflurin

I’ve just imported your flow but when I click to inject I receive the following error?

```
23/10/2018, 10:48:46 node: read ip
msg : error
"TypeError: Cannot read property 'get' of undefined"

```

Any ideas ?

---

<div class="post-metadata">

**Author:** ![cflurin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/cflurin/32/29_2.png) [@cflurin](https://discourse.nodered.org/u/cflurin)\
**Post date:** [23 October 2018 09:57 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/8 "2018-10-23T09:57:04Z")

</div>

Which versions are you using?

node-red  
node.js  
node-red-contrib-dsm

operating system: raspbian or ?

---

<div class="post-metadata">

**Author:** ![nodecentral](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nodecentral/32/10432_2.png) [@nodecentral](https://discourse.nodered.org/u/nodecentral)\
**Post date:** [23 October 2018 10:14 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/9 "2018-10-23T10:14:34Z")

</div>

It’s a docker so not sure of all the specifics, or node.js part; as for the others - here you go..

Node red v 0.19.2  
node-red-contrib-dsm v0.11.0 (there does look to be a newer version available)?

Other dsm seem to be working fine, if that helps ?

---

<div class="post-metadata">

**Author:** ![cflurin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/cflurin/32/29_2.png) [@cflurin](https://discourse.nodered.org/u/cflurin)\
**Post date:** [23 October 2018 11:03 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/10 "2018-10-23T11:03:17Z")

</div>

> [@nodecentral](#):
>
> It’s a docker so not sure of all the specifics, or node.js part; as for the others - here you go..
> 
> Node red v 0.19.2  
> node-red-contrib-dsm v0.11.0 (there does look to be a newer version available)?
> 
> Other dsm seem to be working fine, if that helps ?

Install the latest `node-red-contrib-dsm` version, 0.12.2

---

<div class="post-metadata">

**Author:** ![nodecentral](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nodecentral/32/10432_2.png) [@nodecentral](https://discourse.nodered.org/u/nodecentral)\
**Post date:** [23 October 2018 11:16 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/11 "2018-10-23T11:16:23Z")

</div>

Ok, that seems to have done the trick - thanks @cflurin

---

<div class="post-metadata">

**Author:** ![janvda](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/janvda/32/234_2.png) [@janvda](https://discourse.nodered.org/u/janvda)\
**Post date:** [23 October 2018 11:21 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/12 "2018-10-23T11:21:57Z")

</div>

You can also consider using dynamic DNS so that you can access OpenSuse desktop from the internet using a hostname instead of an IP address.

For this you need to register the hostname with a dynamic DNS provider (some are free).

Some internet routers are able to automatically update the IP address linked to your hostname through the dynamic DNS providers API. If your router is not able to do this then you can create simple node-red flow running on OpenSuse desktop that does this (or I can share it if you want).

---

<div class="post-metadata">

**Author:** ![Noh](https://avatars.discourse-cdn.com/v4/letter/n/46a35a/32.png) [@Noh](https://discourse.nodered.org/u/Noh)\
**Post date:** [23 October 2018 14:42 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/13 "2018-10-23T14:42:26Z")

</div>

It would be interesting to see it but I want to run it on a pi zero, powered from the router's USB, so that it's always on, not just when the olds power up their desktop.

---

<div class="post-metadata">

**Author:** ![janvda](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/janvda/32/234_2.png) [@janvda](https://discourse.nodered.org/u/janvda)\
**Post date:** [23 October 2018 20:34 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/14 "2018-10-23T20:34:50Z")

</div>

Of course you can also run the node-red flow on a pi zero.

Here below the flow I am using that checks my public IP address and if it has changed then it will update it (I am using [changeip.com](http://changeip.com) as DDNS provider).

```
[{"id":"4579ebe6.c7c454","type":"inject","z":"8a9419fa.8029f8","name":"Get IP","topic":"ip","payload":"","payloadType":"str","repeat":"21600","crontab":"","once":true,"onceDelay":"5","x":120,"y":260,"wires":[["91eb23ac.09af1"]]},{"id":"91eb23ac.09af1","type":"exec","z":"8a9419fa.8029f8","command":"wget -qO- http://ipv4bot.whatismyipaddress.com/ ; echo","addpay":false,"append":"","useSpawn":"","timer":"","oldrc":false,"name":"Call IP - whatismyipaddress.com","x":343,"y":259.5,"wires":[["a8fa9540.151a28","dcaf176b.4ff1e8"],["362d622c.c0556e"],["90de538b.37c7d"]]},{"id":"a8fa9540.151a28","type":"switch","z":"8a9419fa.8029f8","name":"Integrity check","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b","vt":"str","case":false},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":620,"y":220,"wires":[["cbbbb8d6.385c08","2bca8b86.a2ac04"],[]]},{"id":"dcaf176b.4ff1e8","type":"debug","z":"8a9419fa.8029f8","name":"call ip : stdout","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":620,"y":180,"wires":[]},{"id":"3c25c3e5.9d336c","type":"comment","z":"8a9419fa.8029f8","name":"Flow Documentation","info":"The first part of the flow is based on : https://flows.nodered.org/flow/9559f217b08913702c38\nFor more information about the service used see: https://whatismyipaddress.com/api\n\nThe second part of the flow will update the IP address if changed.\nSee also https://discourse.nodered.org/t/how-to-change-dynamic-ip-address-changip-com-using-node-red/4164/2","x":110,"y":40,"wires":[]},{"id":"362d622c.c0556e","type":"debug","z":"8a9419fa.8029f8","name":"call ip - stderr","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":620,"y":280,"wires":[]},{"id":"90de538b.37c7d","type":"debug","z":"8a9419fa.8029f8","name":"call ip - return code","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":630,"y":340,"wires":[]},{"id":"cbbbb8d6.385c08","type":"debug","z":"8a9419fa.8029f8","name":"my public ip address","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":880,"y":220,"wires":[]},{"id":"eb78fdb1.d7aa5","type":"http request","z":"8a9419fa.8029f8","name":"","method":"GET","ret":"txt","url":"","tls":"","x":550,"y":520,"wires":[["76ea2460.c2552c","60e58409.43daac"]]},{"id":"76ea2460.c2552c","type":"debug","z":"8a9419fa.8029f8","name":"http change ip address response","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":790,"y":520,"wires":[]},{"id":"1612e69b.6d5af9","type":"switch","z":"8a9419fa.8029f8","name":"flow.public_ip != msg.payload ?","property":"payload","propertyType":"msg","rules":[{"t":"neq","v":"public_ip","vt":"flow"}],"checkall":"true","repair":false,"outputs":1,"x":910,"y":380,"wires":[["5a4d1631.39cee8"]]},{"id":"7a98abc4.d1f654","type":"change","z":"8a9419fa.8029f8","name":"flow.public_ip = msg.payload","rules":[{"t":"set","p":"public_ip","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":440,"wires":[["3c7c8a4f.611bf6","c2d5215e.3d9ee"]]},{"id":"3c7c8a4f.611bf6","type":"debug","z":"8a9419fa.8029f8","name":"new public IP address","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1180,"y":440,"wires":[]},{"id":"5f11d6ed.ab5d48","type":"inject","z":"8a9419fa.8029f8","name":"On Start","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":120,"y":100,"wires":[["29093c22.2201a4"]]},{"id":"c2d5215e.3d9ee","type":"change","z":"8a9419fa.8029f8","name":"set msg.url for changeip","rules":[{"t":"set","p":"url","pt":"msg","to":"$flowContext(\"changeip_url\") & \"&myip=\" & $flowContext(\"public_ip\") & \"&\" & $flowContext(\"changeip_url_credentials\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":520,"wires":[["eb78fdb1.d7aa5"]]},{"id":"2bca8b86.a2ac04","type":"change","z":"8a9419fa.8029f8","name":"remove last char","rules":[{"t":"set","p":"payload","pt":"msg","to":"$substring(payload, 0, $length(payload)-1)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":320,"wires":[["1612e69b.6d5af9"]]},{"id":"24e1af82.6d37","type":"inject","z":"8a9419fa.8029f8","name":"set test ip address","topic":"","payload":"9.9.9.9","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":600,"wires":[["8601775f.9f4518"]]},{"id":"8601775f.9f4518","type":"change","z":"8a9419fa.8029f8","name":"flow.public_p = msg.payload","rules":[{"t":"set","p":"public_ip","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":600,"wires":[[]]},{"id":"5a4d1631.39cee8","type":"change","z":"8a9419fa.8029f8","name":"set tweet msg","rules":[{"t":"set","p":"tweet","pt":"msg","to":"\"old public IP=\" & $flowContext(\"public_ip\")\t& \", new public IP=\" & payload &\t\"\\n changing public IP address ...\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1160,"y":360,"wires":[["7a98abc4.d1f654","4dd4e24b.4618cc"]]},{"id":"c069b3e7.42cd8","type":"change","z":"8a9419fa.8029f8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"\"public IP address successfully changed\"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":560,"wires":[["d4a77d7d.0c103"]]},{"id":"60e58409.43daac","type":"switch","z":"8a9419fa.8029f8","name":"statusCode ?","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"200","vt":"num"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":710,"y":580,"wires":[["c069b3e7.42cd8"],["a7baeff0.4920b"]]},{"id":"a7baeff0.4920b","type":"change","z":"8a9419fa.8029f8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"\"Failed to change public IP address (StatusCode = \" &\tpayload & \")\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":600,"wires":[["d4a77d7d.0c103"]]},{"id":"4dd4e24b.4618cc","type":"change","z":"8a9419fa.8029f8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"tweet","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1160,"y":520,"wires":[["d4a77d7d.0c103"]]},{"id":"29093c22.2201a4","type":"credentials","z":"8a9419fa.8029f8","name":"set changeip credentials in flow context","props":[{"value":"changeip_url_credentials","type":"flow"},{"value":"changeip_url","type":"flow"}],"x":400,"y":100,"wires":[[]]},{"id":"d4a77d7d.0c103","type":"debug","z":"8a9419fa.8029f8","name":"Output Message","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1220,"y":600,"wires":[]}]

```

Note that the 2 credentials in the credential node are set as follows:

- **_changeip\_url\_credentials_** = `u=XXXX&p=YYYY`
- **_changeip\_url_** = `https://nic.changeip.com/nic/update?hostname=bXXXXX.onmypc.org`

---

<div class="post-metadata">

**Author:** ![Noh](https://avatars.discourse-cdn.com/v4/letter/n/46a35a/32.png) [@Noh](https://discourse.nodered.org/u/Noh)\
**Post date:** [26 November 2018 11:36 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/15 "2018-11-26T11:36:41Z")

</div>

Here's the solution I came up with:

- It runs on a pi zero W, powered by the router's USB port.
- Wireless IP is set to dynamic
- I have MQTT (Mosquitto) running on an always on pi that is accessible through my firewall
- Every five minutes it checks the WAN IP. If it's new, it appends a row to an sqlite3 DB and MQTT publishes the IP & Time to topic IP/HOSTNAME on the MQTT server. It also writes the IP & human readable date to a 4 line LCD
- I haven't yet tried getting an MQTT client on my Android phone, subscribing to the topic IP/HOSTNAME, but it works when I run a client on my desktop/laptop.

`[{"id":"aa0f87db.45865","type":"inject","z":"1853a7d0.062638","name":"","topic":"","payload":"","payloadType":"date","repeat":"300","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":160,"wires":[["e755640a.6d17d","f1ffdff2.696fc"]]},{"id":"365ac05a.a28b3","type":"http request","z":"1853a7d0.062638","name":"Get current WAN IP","method":"GET","ret":"txt","url":"http://api.ipify.org/","tls":"","x":330,"y":220,"wires":[["29f04258.fed3e6","9ae8d51c.424a8"]]},{"id":"9ae8d51c.424a8","type":"function","z":"1853a7d0.062638","name":"Store IP in flow variable","func":"//store IP in a flow scoped variable\nvar flowIP;\n\nflow.set(\"flowIP\", msg.payload);\n\nmsg.ip = msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":280,"wires":[["dec2afa5.4d27","f2bac181.2a91d","395f8fcf.dbabd8"]]},{"id":"e755640a.6d17d","type":"function","z":"1853a7d0.062638","name":"Get current time","func":"//store now-time in a flow scoped variable\nvar justSeen, justSeenUTC;\n\nflow.set(\"now_time\", msg.payload);\n\nmsg.justSeen = msg.payload;\n\n//return msg;\n\n\n\n var date = new Date(msg.justSeen);\n msg.justSeenUTC = date.toUTCString();\n return msg;\n\n\n\n//msg.justSeen = msg.payload;\n//return msg;","outputs":1,"noerr":0,"x":320,"y":180,"wires":[["a6539c2.5b98b6","365ac05a.a28b3"]]},{"id":"dec2afa5.4d27","type":"debug","z":"1853a7d0.062638","name":"IP","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":570,"y":240,"wires":[]},{"id":"f1ffdff2.696fc","type":"sqlite","z":"1853a7d0.062638","mydb":"7331442a.3f9e44","sqlquery":"fixed","sql":"CREATE TABLE IF NOT EXISTS IPlog (\n ID INTEGER PRIMARY KEY AUTOINCREMENT,\n currentIP TEXT,\n lastSeen TEXT,\n firstSeen TEXT\n);\n","name":"IPmonLog","x":310,"y":120,"wires":[["a77a977d.13d05"]],"outputLabels":["Table created?"]},{"id":"de03078c.76de5","type":"sqlite","z":"1853a7d0.062638","mydb":"7331442a.3f9e44","sqlquery":"msg.topic","sql":"\n\n","name":"Insert or update IP","x":770,"y":440,"wires":[["3ad79da0.9e81aa","d52074d4.e6d8d8"]]},{"id":"f2bac181.2a91d","type":"sqlite","z":"1853a7d0.062638","mydb":"7331442a.3f9e44","sqlquery":"fixed","sql":"SELECT currentIP as lastRecordedIP from IPlog WHERE ID = (SELECT MAX(ID) FROM IPlog);","name":"Query content","x":320,"y":340,"wires":[["5b9458c5.c189b","a46b38d0.9c6e9"]]},{"id":"5b9458c5.c189b","type":"debug","z":"1853a7d0.062638","name":"Get last row currentIP","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":620,"y":340,"wires":[]},{"id":"29f04258.fed3e6","type":"debug","z":"1853a7d0.062638","name":"WAN-IP","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":740,"y":220,"wires":[]},{"id":"a77a977d.13d05","type":"debug","z":"1853a7d0.062638","name":"Create table","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":590,"y":120,"wires":[]},{"id":"a46b38d0.9c6e9","type":"function","z":"1853a7d0.062638","name":"SQL to Insert or update a row","func":"var lastRecordedIP = \"0.0.0.0\";\nif (msg.payload.length !== 0) { \n lastRecordedIP = msg.payload[0].lastRecordedIP;\n}\n//msg.ip = msg.payload[0].lastRecordedIP;\nif (lastRecordedIP == msg.ip) {\n msg.topic = \"UPDATE IPlog \" +\n \"SET lastSeen = \" + msg.justSeen +\n \" WHERE ID = (SELECT MAX(ID) FROM IPlog);\"\n return [msg,null];\n} else {\n msg.topic = \"INSERT INTO IPlog (currentIP, firstSeen, lastSeen) \" + \n \"VALUES ('\" + msg.ip + \"','\" + msg.justSeen + \"','\" + msg.justSeen + \"') ;\";\n mqttMessage = \"'\" + msg.ip + \"','\" + msg.justSeen + \"','\" + msg.justSeen + \"'\";\n msg.payload = { mqttMessage };\n return [msg, {payload:msg.justSeen}];\n //return [msg, msg];\n}\nreturn null;\n//return [msg, {payload:msg.justSeen}];","outputs":2,"noerr":0,"x":370,"y":400,"wires":[["de03078c.76de5","2a091618.2c6caa"],["48de3bfc.cac084","58c28bf2.4ac2cc"]]},{"id":"3ad79da0.9e81aa","type":"sqlite","z":"1853a7d0.062638","mydb":"7331442a.3f9e44","sqlquery":"fixed","sql":"SELECT * from IPlog ;","name":"Query ALL content","x":770,"y":500,"wires":[["1d19f479.5960e4"]]},{"id":"1d19f479.5960e4","type":"debug","z":"1853a7d0.062638","name":"Get last row currentIP","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1000,"y":500,"wires":[]},{"id":"d52074d4.e6d8d8","type":"debug","z":"1853a7d0.062638","name":"SQL summary","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":980,"y":440,"wires":[]},{"id":"e4a6e881.f197e8","type":"comment","z":"1853a7d0.062638","name":"SQLite IPmonLog schema","info":"CREATE TABLE IPlog (\nID INTEGER PRIMARY KEY AUTOINCREMENT,\ncurrentIP TEXT,\nlastSeen TEXT,\nfirstSeen TEXT\n);","x":350,"y":60,"wires":[]},{"id":"69785ef5.bf0e5","type":"mqtt out","z":"1853a7d0.062638","name":"Publish new IP","topic":"IP/INDIAN","qos":"0","retain":"false","broker":"9a1f4bd8.e4b938","x":320,"y":580,"wires":[]},{"id":"48de3bfc.cac084","type":"debug","z":"1853a7d0.062638","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":570,"y":460,"wires":[]},{"id":"a6539c2.5b98b6","type":"debug","z":"1853a7d0.062638","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":570,"y":180,"wires":[]},{"id":"a9f70c33.1d0f58","type":"debug","z":"1853a7d0.062638","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":570,"y":540,"wires":[]},{"id":"7d60391b.c4eba","type":"function","z":"1853a7d0.062638","name":"Date object to string","func":"msg.justSeenString = msg.justSeen.toISOString();\n/* msg.justSeen.years.toString() + \"-\" +\n msg.justSeen.months.toString() + \"-\" + \n msg.justSeen.date.toString() + \"_\" + \n msg.justSeen.hours.toString() + \":\" + \n msg.justSeen.minutes.toString() + \":\" +\n msg.justSeen.seconds.toString() + \".\" + \n msg.justSeen.milliseconds.toString();\n*/ \nreturn msg;","outputs":1,"noerr":0,"x":620,"y":60,"wires":[[]]},{"id":"bac5770e.fd6a08","type":"function","z":"1853a7d0.062638","name":"Add IP to report string","func":"msg.mqttString = flow.get(\"flowIP\") + \" - First detected: \" + msg.payload;\nmsg.payload = msg.mqttString;\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":520,"wires":[["a9f70c33.1d0f58","69785ef5.bf0e5"]]},{"id":"2a091618.2c6caa","type":"debug","z":"1853a7d0.062638","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":730,"y":380,"wires":[]},{"id":"824480a1.3ec35","type":"debug","z":"1853a7d0.062638","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":570,"y":500,"wires":[]},{"id":"58c28bf2.4ac2cc","type":"moment","z":"1853a7d0.062638","name":"","topic":"","input":"payload","format":"YYYY-MM-DD HH:mm:ss","locale":"en_GB","output":"payload","x":340,"y":460,"wires":[["bac5770e.fd6a08","824480a1.3ec35"]]},{"id":"395f8fcf.dbabd8","type":"moment","z":"1853a7d0.062638","name":"","topic":"","input":"justSeenUTC","format":"DD/MM/YY HH:mm","locale":"en_GB","output":"payload","fakeUTC":false,"x":620,"y":280,"wires":[["fd1fd35b.f9f02","d5b042ad.00327"]]},{"id":"cf2067f8.51fc78","type":"rpi-lcd","z":"1853a7d0.062638","name":"Current IP -line 1","pins":"37,35,33,31,29,22","x":1090,"y":280,"wires":[]},{"id":"fd1fd35b.f9f02","type":"function","z":"1853a7d0.062638","name":"Display IP","func":"var displayString;\ndisplayString2 = flow.get(\"flowIP\");\nmsg.payload = displayString2;\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":280,"wires":[["cf2067f8.51fc78","2878b2bf.68c4c6"]]},{"id":"2878b2bf.68c4c6","type":"debug","z":"1853a7d0.062638","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1070,"y":240,"wires":[]},{"id":"d5b042ad.00327","type":"function","z":"1853a7d0.062638","name":"Display just seen","func":"msg.payload = \"2:\" + msg.payload\nreturn msg;","outputs":1,"noerr":0,"x":870,"y":320,"wires":[["cf2067f8.51fc78"]]},{"id":"7331442a.3f9e44","type":"sqlitedb","z":"","db":"/home/pi/IPmonLog.db","mode":"RWC"},{"id":"9a1f4bd8.e4b938","type":"mqtt-broker","z":"","name":"DriveCam","broker":"212.159.76.88","port":"11883","tls":"","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]`

You'd need to:

Install SQLite3 and create a DB, called IPmonLog.db  
Install the Node-Red SQLite node in the palette  
If you want the LCD, install the Node-Red GPIO and LCD nodes into the palette

I have a monitor that subscribes to my Mum's WAN IP and another subscription for my in-law's WAN IP

The audio is optional, obvs.  
`[{"id":"e49d3f3a.bfccb8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"cd19e722.e299a8","type":"mqtt in","z":"e49d3f3a.bfccb8","name":"","topic":"IP/INDIAN","qos":"2","broker":"90ae653c.70b1b8","x":320,"y":100,"wires":[["16c1e9e0.49959e","221658d3.fe90f8","98c1607.04bed2"]]},{"id":"16c1e9e0.49959e","type":"debug","z":"e49d3f3a.bfccb8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":550,"y":100,"wires":[]},{"id":"28c3e2dc.6464fe","type":"mqtt in","z":"e49d3f3a.bfccb8","name":"","topic":"IP/ARCTIC","qos":"2","broker":"90ae653c.70b1b8","x":320,"y":240,"wires":[["eceb9588.c4a96","71995d30.3dcf7c","f0f1bcf4.43db88"]]},{"id":"eceb9588.c4a96","type":"debug","z":"e49d3f3a.bfccb8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":550,"y":240,"wires":[]},{"id":"221658d3.fe90f8","type":"play audio","z":"e49d3f3a.bfccb8","name":"","voice":"0","x":550,"y":140,"wires":[]},{"id":"71995d30.3dcf7c","type":"play audio","z":"e49d3f3a.bfccb8","name":"","voice":"1","x":550,"y":280,"wires":[]},{"id":"98c1607.04bed2","type":"function","z":"e49d3f3a.bfccb8","name":"e-mail INDIAN ","func":"msg.payload = \"INDIAN - \" + msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":560,"y":180,"wires":[["e602b4e9.5026e8"]]},{"id":"f0f1bcf4.43db88","type":"function","z":"e49d3f3a.bfccb8","name":"e-mail ARCTIC ","func":"msg.payload = \"ARCTIC - \" + msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":560,"y":320,"wires":[["e602b4e9.5026e8"]]},{"id":"e602b4e9.5026e8","type":"e-mail","z":"e49d3f3a.bfccb8","server":"smtp.gmail.com","port":"465","secure":true,"name":"","dname":"e-mail to me","x":850,"y":240,"wires":[]},{"id":"90ae653c.70b1b8","type":"mqtt-broker","z":"","name":"DriveCam","broker":"212.159.76.88","port":"11883","tls":"","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]`

---

<div class="post-metadata">

**Author:** ![Noh](https://avatars.discourse-cdn.com/v4/letter/n/46a35a/32.png) [@Noh](https://discourse.nodered.org/u/Noh)\
**Post date:** [26 November 2018 11:40 UTC](https://discourse.nodered.org/t/check-current-dynamic-ip-then-store-it-if-its-new-or-update-timestamp-if-its-not/902/16 "2018-11-26T11:40:45Z")

</div>

Last thought. The code is pretty messy and I'm sure there are inconsistent methods for passing variables down the flow. Please feel free to respond with mods to tighten it up.
