Expressions and LuaXP Functions
-
This yanked from the REACTOR.LOG, showing latest attempt:
2021-03-15T00:24:20.517Z <VeraController:null> VeraController#vera enqueue task for Entity#vera>device_97 action x_vera_svc_ecobee_com_Ecobee1.SetClimateHold: task { "HoldClimateRef": "${{houseModeTxt}}", "DeviceNum": "97", "id": "action", "serviceId": "urn:ecobee-com:serviceId:Ecobee1", "action": "SetClimateHold" } 2021-03-15T00:24:21.231Z <VeraController:ERR> [VeraController:performOnEntity] action request failed 2021-03-15T00:24:21.232Z <VeraController:CRIT> Error: Request failed: 501 Error Error: Request failed: 501 Error at /opt/reactor/server/lib/Controller.js:445:37 at runMicrotasks (<anonymous>) at processTicksAndRejections (node:internal/process/task_queues:94:5)
-
OK, but before that.
-
This post is deleted!
-
A one-step play of an action will not do variable substitution. The variable substitution is only done by the Engine when running the full reaction.
-
Ah, I follow you, thanks. Will circle back to this issue (if legit) tomorrow. Was called away for several hours, in which time I've decided this workflow is not worth the complexity. I intend to replace it with simple IF A THEN B logic tomorrow.
-
toggledbitswrote on Mar 15, 2021, 3:21 AM last edited by toggledbits Mar 14, 2021, 11:23 PM
I may have to re-route how that function works. Right now, it sends the request via the websocket to the WSAPI, which asks the entity to perform the action on itself. It will take a bit of plumbing, but I can probably redirect that process to the Engine, where the sub can take place. The trick is rule-based, because they set up context very differently from global, and the rule sets up context for the engine (so if I'm asking the engine to do something for the rule, the context hasn't been established... yeah, going to take some noodling...).
-
◄— this guy effed up
I was entirely mistaken about MSR not substituting variables correctly in my workflow. The problem, alas, was entirely of my own making (e.g. not grasping that running internal portions of a Rule manually would NOT invoke substitution(s) the way I had surmised). Secondly, I had crafted entirely too complex a workflow for a simple task; namely, instructing Vera to match the A/C "Mode" to the current House Mode, and vice versa.My crazy construct involved arrays and indexes (to prevent illegal Mode values), lookup tables (to cross-reference integers (2) with words ("away")), time delays (to ward off bouncing/throttling), Global Expressions (to track device states and act as Triggers), boolean flags (to test parity and serve as a Constraint in Rules), etc., etc.
Think I'll stick with a simpler set of Rules, one for each case (Home on Vera ► Home on A/C; Away on A/C ► Away on Vera, etc.) and be done with it. MSR gives you so much more breathing room than the Vera environment, why not utilize it?
Sorry @rigpapa for the unnecessary back-and-forth above, and for not having the time required for ME to diagnose my own issue(s) last night.
-
Well, I think you hit on an important issue, which is that the "trial run" (of an individual action in a reaction) doesn't run in full context (the trial run of the full reaction, however, does). It may be that it can't (I can't imagine, it's really just a matter of if the squeeze is worth the juice), but I'm completely on board with the idea that it should. So I'll be looking into that today.
-
This post is deleted!
-
I honestly can't wrap my head around what you are telling me. It sounds as if you think the values
home
,away
, etc. are different from the strings "home", "away", etc. and somehow that's a problem, but all parameters in Vera are strings, even the numbers. There is no such construct as a "keyword" and no non-string special values forhome
oraway
etc. If you want to sendaway
to the Ecobee thermostat on the Vera, the only way to do it is by sending it a string.It sounds to me like you need to (a) look at the MSR log to see what MSR is sending to the Vera, and (b) look at the Vera LuaUPnP log to see what is being received and what it's doing with it.
-
This post is deleted!
-
This post is deleted!
-
Eesh, suddenly it is all working fine!! Please let's DELETE this convo and I promise never to mention it again. Something must've been wrong before the lunch break that was mucking up the workflow. SORRY!!
-
No problem at all... but please, do look at the log file on MSR to see what it is sending, because right now, I have ALL actions being logged on all platforms, regardless of log level settings, for just this very reason. If what's being sent makes sense, then just look on the Vera side to see what it is getting, which is hopefully the same, but that is literally looking at one side and the other of one function call (to do the HTTP request), so there should be parity. But, there can always be a case where something about the value isn't kosher... an extra space before or after? Something sneaking in that doesn't immediately jump out. Logs. Always the logs.
-
WILCO, just bear with me while I endure the "two steps back" phase of debugging my workflow, and get back to you.
For the moment, I suspect the problem is me, not MSR. -
@toggledbits I'm noticing that in MSR the following boolean test expressions are equating to FALSE when I naively expect TRUE (at least for the array version):
1 in {one:1}
and1 in [1,2,3]
Also FALSE for:
"one" in keys(testobj)
wheretestobj := {one:1,two:2,three:3}
which MSR sees internally as{"one":1, "two":2, "three":3}
More importantly, despite
in
being declared a reserved keyword in lexpjs, it is not (yet) explicitly included in your docs among the array operations. Should I submit a request for that?Thanks for your insights, as always.
EDIT: Think I found the answer to where "in" belongs in the lexpjs docs... it's intended for the
each..<item>..in..<array>
construct, whereas the docs currently describeeach..<item>..OF..<array>
so please accept this typo submission.I believe this means I should not be attempting to use
in
as I described above, then? And always useindexOf()
instead? -
@librasun said in Expressions and LuaXP Functions:
1 in {one:1}
This is false because 1 is not a key of the object.
1 in [1,2,3]
Is actually true (just tested in lexpjs) because 1 is a key in the object (i.e. the element at array index 1 exists). This is JavaScript semantics.
Also FALSE for: "one" in keys(testobj)
That would be correct because, following those JavaScript semantics,
keys()
returns an array, andone
is not a valid index for any array.Now, we can talk about whether or not the array behavior is expected. The smart folks that came up with JavaScript think so, but that doesn't mean it's the right answer for Reactor. It never occurred to me to use
in
on array in JavaScript, so I've never seen this effect; the "correct" way is (among several)Array.find()
orArray.indexOf()
. There is anindexOf()
function in MSR/lexpjs.On the
1 in { 'one': 1 }
being false, though, this is defensibly correct in both Reactor and JavaScript. If we change the behavior ofin
for arrays, then test (and true result) you want here would be written as1 in values( { 'one': 1 } )
-
I see. I hadn't considered the
.find
method only because it wasn't explicitly mentioned in lexpjs docs, but should have assumed it present from JS by extension.Furthermore, I stand corrected about
1 in [1,2,3]
which I swore (should not!) MSR returned as FALSE on first run of test. My bad.Lastly, where do you stand on
[1,2,3] || [3,4,5]
and[1,2,3] && [3,4,5]
? Former is returning TRUE (sorta expected) and latter is returning[3,4,5]
which I kinda get, but don't? -
toggledbitsreplied to LibraSun on Mar 16, 2021, 6:15 PM last edited by toggledbits Mar 16, 2021, 2:16 PM
@librasun said in Expressions and LuaXP Functions:
I see. I hadn't considered the .find method only because it wasn't explicitly mentioned in lexpjs docs, but should have assumed it present from JS by extension.
[referring to
Array.find()
] That's not a lexpjs function, it's how you do what you are trying to do in JavaScript (find a value in an array). Your Reactor/lexpjs solution isindexOf()
. Also note that dot-function notation is not supported by Reactor/lexpjs -- you can't saysomearrayname.indexOf( lookingfor )
, you have to writeindexof( somearrayname, lookingfor )
.I'm tempted to just leave
in
as-is for arrays, but well-documented, simply because it follows a common-use language pattern, and there is a defined replacement, which happens to be (almost) the same for both.Lastly, where do you stand on [1,2,3] || [3,4,5] and [1,2,3] && [3,4,5]?
That's a bug. The answer for the former should be
[1,2,3]
and for the latter[4,5,6]
. Fixing now. -
MSR SAMPLE EXPRESSIONS: Timestamp
If you want to display a timestamp in a stored variable or an outbound message from MSR, that looks like "
14:24:43 Wed 2021-Mar-17
", allow me to save you some typing. Just include this Expression in your Reaction, and reference${{timeStamp}}
in your workflow.daysList = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], monthsList = ["","Jan","Feb","Mar","Apr","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], timeNow = dateparts(time()), timeStamp = timeNow.hour + ':' + substr('0' + timeNow.minute,-2,2) + ':' + substr('0' + timeNow.second,-2,2) + ' ' + daysList[timeNow.weekday] + ' ' + timeNow.year + '-' + monthsList[timeNow.month] + '-' + substr('0' + timeNow.day,-2,2)
This construct takes advantage of the multi-statement feature built into MSR, which permits you to string together a series of declarations and evaluations within a single Expression. I've also sprinkled in a little formatting spice, so that single-digit
day
,minute
andsecond
fields display with a leading0
.
32/126