# Timestamp subtraction from msg objects

**URL:** https://discourse.nodered.org/t/timestamp-subtraction-from-msg-objects/76133
**Category:** General
**Created:** [5 March 2023 13:09 UTC](https://discourse.nodered.org/t/timestamp-subtraction-from-msg-objects/76133 "2023-03-05T13:09:59Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Aaroneisele55](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/aaroneisele55/32/65335_2.png) [@Aaroneisele55](https://discourse.nodered.org/u/Aaroneisele55)
#### Post date: [5 March 2023 13:09 UTC](https://discourse.nodered.org/t/timestamp-subtraction-from-msg-objects/76133/1 "2023-03-05T13:09:59Z")

</div>

Hello,  
I have the following problem:  
I have another flow created which returns JSON like this:

```auto
{"payload":195,"topic":"/lights/Aaron/cmd","timestamp":1676613795211}

```

With `timestamp` being the time in milliseconds since 1970 and `payload` and `topic` being irrelevant for this task.  
These msg objects come in dynamic intervals and at very different times.

I now want to subtract the last `timestamp` value from the current one and output it (for demo purpose using a debug node, later into a file)

How can I do this?

Best Regards  
Aaron

---

<div class="post-metadata">

### Author: ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)
#### Post date: [5 March 2023 13:28 UTC](https://discourse.nodered.org/t/timestamp-subtraction-from-msg-objects/76133/2 "2023-03-05T13:28:17Z")

</div>

Maybe this example will help you. It could be simpler but i thought i would show how to store previous timestamps and relate them to the topic.

```auto
[{"id":"1cde623e449fc25f","type":"inject","z":"65617ffeb779f51c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"lights/Aaron/cmd","payload":"195","payloadType":"num","x":160,"y":60,"wires":[["bd7250df945b177b"]]},{"id":"bd7250df945b177b","type":"change","z":"65617ffeb779f51c","name":"","rules":[{"t":"set","p":"previous_timestamp","pt":"msg","to":"previous_timestamps[msg.topic]","tot":"flow"},{"t":"set","p":"time_diff","pt":"msg","to":"$$.timestamp - $$.previous_timestamp","tot":"jsonata"},{"t":"set","p":"previous_timestamps[msg.topic]","pt":"flow","to":"timestamp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":60,"wires":[["a2c6b2a0fe0b68a2"]]},{"id":"a2c6b2a0fe0b68a2","type":"debug","z":"65617ffeb779f51c","name":"debug 238","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"time_diff","statusType":"msg","x":570,"y":120,"wires":[]}]

```

Hope it helps

---

<div class="post-metadata">

### Author: ![Aaroneisele55](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/aaroneisele55/32/65335_2.png) [@Aaroneisele55](https://discourse.nodered.org/u/Aaroneisele55)
#### Post date: [5 March 2023 14:38 UTC](https://discourse.nodered.org/t/timestamp-subtraction-from-msg-objects/76133/3 "2023-03-05T14:38:52Z")

</div>

@E1cid: Thank you very much 😀😀 for your help.  
I've integrated this to the place where I needed it and (after some editing because I actually needed a bit less of functionality - I didn't want the "one value per topic" thing so just edited that out) it just works!

> **My usecase**
>
> I use it as part of my custom solution for some kind of "light show recording system" which I built myself. This works in a way that when I play a song on my phone, the phone sends a MQTT message with information about the song (the title, album, artist and more) to NR. If there is a lightshow configured for that song, the corresponding flow gets started. Such a flow looks like a sequence of delay-,change-,delay-,change-node and so forth, which contains the commands that my lights should get, and also the delays between them.  
> For creating these flows, I have an [M5STACK Core2 device](https://shop.m5stack.com/products/m5stack-core2-esp32-iot-development-kit) (which is essentially an ESP32 with a battery a touchscreen, 3 (touch-)buttons and even more) where I have some buttons on the touchscreen that trigger events in NR.  
> When I create a lightshow, I press these buttons in a way that my lights do what I want (brightness, color change, or even a strobe or a "round-blinking effect"). Then, these events are recorded by this flow:
> 
> ````auto
> [
> {
> "id": "5295a3249041ba5a",
> "type": "tab",
> "label": "MQTT Recorder",
> "disabled": false,
> "info": "",
> "env": []
> },
> {
> "id": "d2b9a29ebdf2f3bc",
> "type": "mqtt in",
> "z": "5295a3249041ba5a",
> "name": "",
> "topic": "/m5Core2/states/touch",
> "qos": "0",
> "datatype": "auto-detect",
> "broker": "bc93d299d4d38301",
> "nl": false,
> "rap": true,
> "rh": 0,
> "inputs": 0,
> "x": 120,
> "y": 40,
> "wires": [
> [
> "75ba668ace844414"
> ]
> ]
> },
> {
> "id": "7f5d414d485637d9",
> "type": "function",
> "z": "5295a3249041ba5a",
> "name": "function 60",
> "func": "msg.payload = {\"payload\":msg.payload,\"topic\":msg.topic,\"timestamp\":new Date().getTime(),\"lastDelay\":msg.tsdiff};\nreturn msg;",
> "outputs": 1,
> "noerr": 0,
> "initialize": "",
> "finalize": "",
> "libs": [],
> "x": 610,
> "y": 40,
> "wires": [
> [
> "4a4c18a859fbc7db"
> ]
> ]
> },
> {
> "id": "75ba668ace844414",
> "type": "switch",
> "z": "5295a3249041ba5a",
> "name": "",
> "property": "recordBPs",
> "propertyType": "global",
> "rules": [
> {
> "t": "true"
> }
> ],
> "checkall": "true",
> "repair": false,
> "outputs": 1,
> "x": 290,
> "y": 40,
> "wires": [
> [
> "adfb6fc471e8d51d"
> ]
> ]
> },
> {
> "id": "4a4c18a859fbc7db",
> "type": "file",
> "z": "5295a3249041ba5a",
> "name": "",
> "filename": "/home/pi/.sys/recordLog",
> "filenameType": "str",
> "appendNewline": true,
> "createDir": false,
> "overwriteFile": "false",
> "encoding": "none",
> "x": 810,
> "y": 40,
> "wires": [
> []
> ]
> },
> {
> "id": "3646f14a448dd7b7",
> "type": "inject",
> "z": "5295a3249041ba5a",
> "name": "",
> "props": [
> {
> "p": "payload"
> }
> ],
> "repeat": "1",
> "crontab": "",
> "once": true,
> "onceDelay": 0.1,
> "topic": "",
> "payload": "recordBPs",
> "payloadType": "global",
> "x": 130,
> "y": 250,
> "wires": [
> [
> "6b48905ab72ece93"
> ]
> ]
> },
> {
> "id": "6b48905ab72ece93",
> "type": "switch",
> "z": "5295a3249041ba5a",
> "name": "",
> "property": "payload",
> "propertyType": "msg",
> "rules": [
> {
> "t": "neq",
> "v": "",
> "vt": "prev"
> }
> ],
> "checkall": "true",
> "repair": false,
> "outputs": 1,
> "x": 290,
> "y": 250,
> "wires": [
> [
> "76ba2c4dfc946496",
> "4f765a38e81ce414"
> ]
> ]
> },
> {
> "id": "76ba2c4dfc946496",
> "type": "switch",
> "z": "5295a3249041ba5a",
> "name": "",
> "property": "recordBPs",
> "propertyType": "global",
> "rules": [
> {
> "t": "true"
> }
> ],
> "checkall": "true",
> "repair": false,
> "outputs": 1,
> "x": 410,
> "y": 250,
> "wires": [
> [
> "5e04c572227e0b21"
> ]
> ]
> },
> {
> "id": "20c0b68cae269ae5",
> "type": "file",
> "z": "5295a3249041ba5a",
> "name": "",
> "filename": "/home/pi/.sys/recordLog",
> "filenameType": "str",
> "appendNewline": false,
> "createDir": false,
> "overwriteFile": "delete",
> "encoding": "none",
> "x": 810,
> "y": 250,
> "wires": [
> [
> "eccc5c89920d4490"
> ]
> ]
> },
> {
> "id": "5e04c572227e0b21",
> "type": "change",
> "z": "5295a3249041ba5a",
> "name": "",
> "rules": [
> {
> "t": "set",
> "p": "payload",
> "pt": "msg",
> "to": "",
> "tot": "str"
> },
> {
> "t": "delete",
> "p": "#:(file)::previous_timestamps",
> "pt": "flow"
> }
> ],
> "action": "",
> "property": "",
> "from": "",
> "to": "",
> "reg": false,
> "x": 570,
> "y": 250,
> "wires": [
> [
> "20c0b68cae269ae5"
> ]
> ]
> },
> {
> "id": "4f765a38e81ce414",
> "type": "ui_switch",
> "z": "5295a3249041ba5a",
> "name": "",
> "label": "MQTT Steuerungsbefehle aufzeichen",
> "tooltip": "",
> "group": "17d51addf9f44c6c",
> "order": 4,
> "width": 0,
> "height": 0,
> "passthru": true,
> "decouple": "false",
> "topic": "topic",
> "topicType": "msg",
> "style": "",
> "onvalue": "true",
> "onvalueType": "bool",
> "onicon": "",
> "oncolor": "",
> "offvalue": "false",
> "offvalueType": "bool",
> "officon": "",
> "offcolor": "",
> "animate": false,
> "className": "",
> "x": 190,
> "y": 310,
> "wires": [
> [
> "d3b7991120e64152"
> ]
> ]
> },
> {
> "id": "d3b7991120e64152",
> "type": "change",
> "z": "5295a3249041ba5a",
> "name": "",
> "rules": [
> {
> "t": "set",
> "p": "recordBPs",
> "pt": "global",
> "to": "payload",
> "tot": "msg",
> "dc": true
> },
> {
> "t": "set",
> "p": "isLSrunning",
> "pt": "global",
> "to": "payload",
> "tot": "msg",
> "dc": true
> }
> ],
> "action": "",
> "property": "",
> "from": "",
> "to": "",
> "reg": false,
> "x": 450,
> "y": 310,
> "wires": [
> []
> ]
> },
> {
> "id": "fa1be33f27cb769a",
> "type": "mqtt in",
> "z": "5295a3249041ba5a",
> "name": "",
> "topic": "/lights/Aaron/cmd",
> "qos": "0",
> "datatype": "auto-detect",
> "broker": "bc93d299d4d38301",
> "nl": false,
> "rap": true,
> "rh": 0,
> "inputs": 0,
> "x": 100,
> "y": 80,
> "wires": [
> [
> "75ba668ace844414"
> ]
> ]
> },
> {
> "id": "e7646f323d55d8a4",
> "type": "mqtt in",
> "z": "5295a3249041ba5a",
> "name": "",
> "topic": "/sys/auto/cmd",
> "qos": "0",
> "datatype": "auto-detect",
> "broker": "bc93d299d4d38301",
> "nl": false,
> "rap": true,
> "rh": 0,
> "inputs": 0,
> "x": 90,
> "y": 120,
> "wires": [
> [
> "75ba668ace844414"
> ]
> ]
> },
> {
> "id": "eccc5c89920d4490",
> "type": "function",
> "z": "5295a3249041ba5a",
> "name": "function 68",
> "func": "msg.payload = {\"event\":\"START\",\"timestamp\":new Date().getTime(),\"auto\":global.get(\"auto\",\"file\"),\"motion\":global.get(\"motion\",\"file\")}\nreturn msg;",
> "outputs": 1,
> "noerr": 0,
> "initialize": "",
> "finalize": "",
> "libs": [],
> "x": 1035,
> "y": 250,
> "wires": [
> [
> "4a4c18a859fbc7db"
> ]
> ]
> },
> {
> "id": "a25fedc1256f763e",
> "type": "mqtt in",
> "z": "5295a3249041ba5a",
> "name": "",
> "topic": "/sys/music/phone/title",
> "qos": "0",
> "datatype": "auto-detect",
> "broker": "bc93d299d4d38301",
> "nl": false,
> "rap": true,
> "rh": 0,
> "inputs": 0,
> "x": 120,
> "y": 165,
> "wires": [
> [
> "75ba668ace844414"
> ]
> ]
> },
> {
> "id": "adfb6fc471e8d51d",
> "type": "change",
> "z": "5295a3249041ba5a",
> "name": "",
> "rules": [
> {
> "t": "set",
> "p": "timestamp",
> "pt": "msg",
> "to": "",
> "tot": "date"
> },
> {
> "t": "set",
> "p": "previous_timestamp",
> "pt": "msg",
> "to": "#:(file)::previous_timestamps[0]",
> "tot": "flow"
> },
> {
> "t": "set",
> "p": "tsdiff",
> "pt": "msg",
> "to": "$$.timestamp- $$.previous_timestamp",
> "tot": "jsonata"
> },
> {
> "t": "set",
> "p": "#:(file)::previous_timestamps[0]",
> "pt": "flow",
> "to": "timestamp",
> "tot": "msg"
> }
> ],
> "action": "",
> "property": "",
> "from": "",
> "to": "",
> "reg": false,
> "x": 440,
> "y": 40,
> "wires": [
> [
> "7f5d414d485637d9"
> ]
> ]
> },
> {
> "id": "bc93d299d4d38301",
> "type": "mqtt-broker",
> "name": "",
> "broker": "localhost",
> "port": "1883",
> "clientid": "NodeRed",
> "autoConnect": true,
> "usetls": false,
> "protocolVersion": "4",
> "keepalive": "59",
> "cleansession": true,
> "birthTopic": "/status/rpi4",
> "birthQos": "0",
> "birthRetain": "false",
> "birthPayload": "CONNECTED",
> "birthMsg": {},
> "closeTopic": "/status/rpi4",
> "closeQos": "0",
> "closeRetain": "false",
> "closePayload": "DISCONNECTED",
> "closeMsg": {},
> "willTopic": "/status/rpi4",
> "willQos": "0",
> "willRetain": "false",
> "willPayload": "C_ERROR",
> "willMsg": {},
> "userProps": "",
> "sessionExpiry": ""
> },
> {
> "id": "17d51addf9f44c6c",
> "type": "ui_group",
> "name": "Default",
> "tab": "e186d7d116ed422a",
> "order": 1,
> "disp": false,
> "width": "6",
> "collapse": false,
> "className": ""
> },
> {
> "id": "e186d7d116ed422a",
> "type": "ui_tab",
> "name": "LightRecorder",
> "icon": "dashboard",
> "order": 7,
> "disabled": false,
> "hidden": false
> }
> ]
> ```, which prints them to a file where the MQTT topic, the value, and the timestamp with the amount of time since the last command. I then proccess the delays and the other data to a flow that looks like I described above, link them to the song (update a big switch node which starts the flow for every song), and then these commands get run every time I play that song. I integrated your flow into the "recorder" part of the system so I won't have to subtract the timestamps after recording it.
> 
> ````

Thanks for your help  
Aaron

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [19 March 2023 14:39 UTC](https://discourse.nodered.org/t/timestamp-subtraction-from-msg-objects/76133/4 "2023-03-19T14:39:26Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
