Beginner questions on IF expressions and wildcard usage in function node

Actually that gives a linting error "The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)" because it does not know that javascript can subtract dates. I believe that js just calls getTime() to convert them to ms then subtracts, so the expression is functionally identical to

(new Date('2023-09-06 11:30:00').getTime() - new Date('2023-09-06 10:30:00').getTime())/60000

I don't think that is correct. getTime() returns the time since 1970 in ms.

@Colin: do you see an issue here then also that would explain the NaN?

Or does the function have a problem with the T in "Time":"2023-09-06T21:40:52" ?

Feed the message you are feeding into the node into a debug node, set to Output Complete Message. and show us what you see.

Another option is to break down your code so you can see where it goes wrong

const debugMe = {
    msgTime: msg.Time,
    msgTimeType: typeof msg.Time,
    msgTimeAsDate: new Date(msg.Time),
    msgTimeAsDateToTime: new Date(msg.Time).getTime(),
}
node.warn(debugMe)

const debugMe2 = {
    msgTopicPlusTime: msg.topic + '_Time',
    msgTopicPlusTimeAsDate: new Date(msg.topic + '_Time'),
    msgTopicPlusTimeAsDateToTime: new Date(msg.topic + '_Time').getTime()
}
node.warn(debugMe2)

mTime = 
msg.TimeDelta = ((new Date(msg.Time).getTime()) - (new Date(msg.topic + '_Time').getTime())) / 1000;
1 Like

Yes that is a good way. I would like to know what is in msg.topic that with '_Time' on the end gives a valid input to new Date()

indeed & why i asked for:

in particular.

@Colin:
flow.set(msg.topic + '_Time', msg.Time)
It is at the end of the function so whenever the if condition is true the current time is written to that message property to create "previous time".
Example
tele/xiaomi/ATC4e211d_Time "2023-09-06T22:17:40"

@Steve-Mcl
I will test as soon as my alarm clock forces me to get back out of bed :slight_smile:

By the way, all my debug nodes are always complete message :wink:
I will post the input into the function tomorrow. But the previous time is not fed into the node. It is a flow context. Only msg.Time is fed into the function and is the same format.

I will post tomorrow morning :slight_smile:

Perhaps you meant
new Date(flow.get(msg.topic + '_Time'))
You currently have
new Date("tele/xiaomi/ATC4e211d_Time")
which is meaningless

1 Like

Oh my! Oh my oh my oh my....
I think you might be right!

If my wife wasn't asleep next to me I would run to my computer to test!!!!!!!!
I think I totally messed that one up and simply forgot to get to treat it correctly as a flow context :man_facepalming: :man_facepalming: :man_facepalming:

Yes, from MDN:

Subtracting two subsequent getTime() calls on newly generated Date objects, give the time span between these two calls.

Yes, there are some pretty bad errors in the linting in Monaco/VScode. Thankfully, not too many.

You can always use the toValue function if you want to avoid the warning.

Looks like you are correct. I think I read the wrong web answer. :frowning:

See this:

Returns NaN if the date is invalid.

1 Like

IT really was the forgotten flow.get() -.-

But here the promised additional info (numbered debugs seen here are of course just for this feedback)

raw_data:
{"topic":"raw_data/tasmota_D2EE70/SENSOR","payload":{"Time":"2023-09-07T06:37:42","ATC8f1b4f":{"mac":"a4c1388f1b4f","Temperature":21.6,"Humidity":59.2,"DewPoint":13.2,"Btn":0,"Battery":69,"RSSI":-56},"ATC801437":{"mac":"a4c138801437","Temperature":22.9,"Humidity":76.2,"DewPoint":18.4,"Btn":0,"Battery":47,"RSSI":-79},"TempUnit":"C"},"qos":0,"retain":false,"_msgid":"c2e9ee8679d60286"}

debug 332:
{"topic":"tele/xiaomi/ATC801437","payload":{"mac":"a4c138801437","Temperature":22.9,"Humidity":76.2,"DewPoint":18.4,"Btn":0,"Battery":47,"RSSI":-79},"Time":"2023-09-07T06:37:42","_msgid":"c2e9ee8679d60286"}

debug 333:
{"topic":"tele/xiaomi/ATC801437","payload":{"mac":"a4c138801437","Temperature":22.9,"Humidity":76.2,"DewPoint":18.4,"Btn":0,"Battery":47,"RSSI":-79},"Time":"2023-09-07T06:37:42","_msgid":"c2e9ee8679d60286","Temperature":22.9}

m32 ATC*Temperature:
{"topic":"tele/xiaomi/ATC801437","payload":{"mac":"a4c138801437","Temperature":23.5,"Humidity":60.8,"DewPoint":15.5,"Btn":0,"Battery":47,"RSSI":-83},"Time":"2023-09-07T06:38:32","_msgid":"8024b9f1fea9f525","Temperature":23.5,"PowerDelta":0.3999999999999986,"TimeDelta":40}

In case you are wondering:
I am preserving the original message in the payload so I can publish it once I am done with my processing. The added msg properties inbetween are either for better handling or debugging or just out of curiosity :smiling_face:

I think that should be valueOf(). It seems that the spec for valueOf() is identical to getTime().

From mdn web docs:

The valueOf() method of Date instances returns the number of milliseconds for this date since the epoch, which is defined as the midnight at the beginning of January 1, 1970, UTC.

The getTime() method of Date instances returns the number of milliseconds for this date since the epoch, which is defined as the midnight at the beginning of January 1, 1970, UTC.

As Colin says

new Date(msg.topic + '_Time')

is never going to work because you are trying to get a Date object from a non date string

1 Like

See above. I forgot to get the context. It was never sipposed to be a message property but a context named after a message property :wink:

According to a stackoverflow post, getTime() was inteoduced first. Since it is less versatile, valueOf() was introduced but getTime() never removed. Maybe for backwards compatibility, maybe because it feels more elegant :person_shrugging:

This makes sense if we consider that getTime got introduced in JavaScript 1.0 and valueOf was introduced in JavaScript 1.1. My guess is that getTime was kept for backwards compability.

-Attila Kun

Mar 14, 2012 at 21:03

Doh! Shows how tired I was yesterday since I'd only just looked it up!

Personally I think that getTicks() or getms() would have been better. Too late now.

I am still struggling a bit with the details of the matchingKeys.forEach part.
I would like to add the msg.payload.Time to the payload of each element.

My first approach is

const matchingKeys = Object.keys(msg.payload).filter((element) => element.startsWith("ATC"))
matchingKeys.forEach((element) => node.send({
    topic: "tele/xiaomi/" + element,
    payload[element].Time: msg.payload.Time, //error message: No value exists in scope for the shorthand property 'payload'. Either declare one or provide an initializer.(18004)
    payload: msg.payload[element],
}))

I was thinking that I added the sub property to the element's payload and then made the node out payload the extended payload.
I thought that maybe I first have to initialize the message property msg.payload[element].Time because it is not known to the system yet.
So I tried

const matchingKeys = Object.keys(msg.payload).filter((element) => element.startsWith("ATC"))
matchingKeys.forEach((element) => node.send({
    topic: "tele/xiaomi/" + element,
    msg.payload[element].Time = msg.payload.Time,
    payload: msg.payload[element],
}))

This should create a property "Time" in each payload of each element. Well, at least that is what I thought :smiley:
What am I doing wrong? Or where is my mental mistake? I am not altering the original payload, only the element specific one. That should be fine in my books :wink:

I keep seeing a yellow lightbulb or a red triangle but those seem to only say "something is wrong" and are giving absolutely no indication of what. Seems somehow useless to me.
Sometimes I can hover with the mouse over each part of the respective line of code but this time I don't even see anything there.
Obviously the system dislikes something but is not sharing with me what it is :thinking:

You have an assignment as a property of the Object

const matchingKeys = Object.keys(msg.payload).filter((element) => element.startsWith("ATC"))
matchingKeys.forEach((element) => node.send({
    topic: "tele/xiaomi/" + element,
    msg.payload[element].Time = msg.payload.Time,   // try msg.payload[element].Time: msg.payload.Time,
    payload: msg.payload[element],           
}))

Currently msg.payload is just a value (msg.payload[element]). If you want to have a property msg.payload.time then you must make the payload be an object and move the existing value into another property, so something like

matchingKeys.forEach((element) => node.send({
    topic: "tele/xiaomi/" + element,
    payload: {value: msg.payload[element], time: msg.payload.time}
}))

Where you can change value to whatever name you want.
So the line
payload: {value: msg.payload[element], time: msg.payload.time}
says that payload is an object with two properties, value and time, and sets them to those values.