Default Subscriptions


#1

1) Give a description of the problem
I’ve searched the forums on “subscriptions” but I’m not quite clear on something. I’m sure this has been discussed elsewhere (I did see the Conditions and Triggers topic) so please forgive me, but just looking for a simple explanation of what the intent is here.

2) What is the expected behaviour?
I expect the “if” statement to evaluate an expression that returns a boolean result, and branch accordingly. In this particular case, I expect that

if Backyard East Light's switch is off

compiles to something like

if ( getStatusOfDevice("Backyard East Light", "switch") == "off" ) { … }
else { … }

3) What is happening/not happening?
WC creates a subscription for the Backyard East Light switch (switch 2 in the snapshot). While it doesn’t hurt anything, it seems completely pointless and illogical. The piston is only interested in the state of the switch at the instant the if statement’s condition is evaluated. If I wanted to do something based on an event from the light switch, I would have added it in the on events from section.

I’m coming at this from the perspective of a C++/C# programmer, which is probably part of the problem. I realize I can override the auto behavior and turn off that subscription, but why is it created in the first place?

**4) Post a Green Snapshot of the piston![image|45x37]

5) Attach logs after turning logging level to Full
1/9/2020, 12:43:49 PM +194ms
+12ms ╔Subscribing to devices…
+15ms ║Using Attribute subscription
+72ms ║Device missing from piston. Loading all from parent (56ms)
+77ms ║Subscribing to Backyard Lights Button.pushed…
+85ms ║Subscribing to Backyard East Light.switch…
+92ms ║Piston controls Back Yard Camera…
+107ms ╚Finished subscribing (98ms)
+121ms ║Comparison (enum) off is (string) off = true (1ms)
+123ms ║Cancelling condition #4’s schedules…
+124ms ║Cancelling condition #3’s schedules…
+133ms ╔Starting piston… (v0.3.110.20201015_HE)
+134ms ╚Piston successfully started (127ms)


#2

Quick answer:

If a piston has no triggers, then all conditions are treated as triggers.
(as seen by the two lightning bolts)

If you turn line 18 into a real trigger, then line 22 will loose the lightning bolt, and return to a normal condition.


IE

ϟ IF Unknown device is pushed  <-- Trigger
  Then
      IF Switch 2 is off       <-- Condition
          Then do cool stuff
          Else do boring stuff
      END IF
  END IF

#3

‘on events from’ is not a trigger??? What else could an “event” possibly be?

If ‘if’ statements can be triggers (again seems illogical) then what purpose does the ‘on events from’ statement serve?

I would still expect that IF Unknown device is pushed to evaluate its condition at the time of execution, and that there would be no trigger for this piston to fire (except manually or via another piston).


#4

Personally, I look at conditions as being generic / vague… and triggers as specific / precise…
(and of course, ‘on events from’ is as vague as they come, so it kind of fits here)


Specifically, triggers are created when creating IFs… Every device is different, but triggers are always listed below conditions in the drop down menu.


Note: As you discovered, triggers are not the only thing that warrants a subscription.
(but they are the “normal” way to make conditions act like conditions)


#5

RIght. But the argument to the if statement IS a condition and clearly listed as such, yet its treated as a trigger. So if statements compile differently depending on context?

If that’s the case, then in my piston the if statement is nested inside a trigger (on events IS a trigger, right?) so it should be clear to the code generator that it is a condition, not a trigger.

Just trying to understand the logic behind this. If I want an if statement to always behave as a traditional if statement, is there a way to globally turn off the “feature” that treats conditions as triggers?

Let me put it a different way. I understand triggers to be events that cause a piston to run. If that’s correct, then a trigger declaration would only make sense at the top of the code, right? You can’t have events (triggers) that jump into the middle of the piston’s code. Or can you?

Again, I’m looking at this as a C++/C# programmer so my expectations are probably wrong. But whoever designed the UI made it look like C++/C#/java code which I suppose reinforces my incorrect expectations.


#6

From what I have seen, the entire concept of SmartHome programming is based on context.
(very few questions have a quick answer)


Triggers are everything listed under “Triggers” as seen in my last picture.
(although that list changes depending on device)

Perhaps we are mixing up triggers and subscriptions?
(All triggers are subscribed to, but not all subscriptions are triggers)


It can be done on a piston-by-piston case, (or a line by line case) but that is a core concept of webCoRE. Of course, there are workaround for everything, but personally, I believe that it is better to code with understanding, that to try to force webCoRE into any pre-conceived notions.


TL;DR:

Every lightning bolt (no matter how it got there) will trigger the piston, and run thru the code top to bottom… Executing anything not blocked by conditions. (or ELSE blocks, if it is)


#7

The ‘on events from’ block is meant to be processed outside the normal flow of the piston. It is the device events equivalent of the ‘every’ block. I’m not sure what the subscription in question is doing there either as it doesn’t achieve anything. It might just be a minor bug. It certainly doesn’t represent mainstream webCoRE behaviour.

‘Triggers’ are how you explicitly state that you are interested in certain events. The piston will suscribe to those events. If you don’t have explicit triggers the piston will look for the events that you have implicitly expressed an interest.


#8

Ah, ok! I was looking at the lightning bolt as the entry point for the subscription’s event as well as the statement that caused the subscription to be created.

So, activating switch 2 triggers an action to run the piston. In that case, the on event from button 1 statement is acting as a conditional statement, and since the button is not pushed at that point in time, the piston does nothing.

This would explain the weird logs such as:

|+8ms|╔Received event [Backyard East Light].switch = on with a delay of 70ms, canQueue: true, calledMyself: false|
|---|---|
|+40ms|║RunTime initialize > 39 LockT > 2ms > rtDT > 21ms > pistonT > 20ms (first state access 16 10 29)|
|+44ms|║Runtime (5507 bytes) successfully initialized in 21ms (v0.3.110.20201015_HE)|
|+46ms|║╔Execution stage started|
|+53ms|║╚Execution stage complete. (7ms)|
|+56ms|╚Event processed successfully (55ms)|

I couldn’t figure out where these were coming from, but if I turn switch 2 on (the one with the unwanted subscription), I get this log entry. Now it makes sense.

I don’t really get the intent behind this whole behavior, but at least now I understand what’s going on.

Thanks!


#9

Also explains some other wierdness I see. When the button is pushed, it turns lights 1 and 2 on. The unwanted subscription on light 2 causes the piston to be fired again.

I guess if it wasn’t for the on events statement, this would have ended up in an infinite loop where the light would repeatedly turn on and off, until a black hole developed around my house.


#10

Ok. I guess that’s why the switch 2 events don’t do anything. It’s not that the on event statement is acting as a conditional that evaluates to false on switch 2 events, it’s that the on event block only executes on a button push event.

That would explain why there’s no entries at all between the execution stage started and complete lines.


#11

It may be that the On Events should be marked as a trigger (and therefore stop the promotion of conditions to triggers.


#12

Well, technically it does run thru the code top to bottom at each event.
(meaning if there was another block in that piston, it could very well execute)


#13

I have made some changes to latest HE webCoRE if you want to have a look in regards to default subscriptions