Jump to content

Program execution order in IoX


Recommended Posts

Posted

Just to deepen my understanding of how IoX works, I thought I'd look into the order that IoX executes programs, especially when they interact with each other through variables as flags. I started by searching the wiki, which does have a section on evaluation precedence within a program, but as for the order of execution of programs themselves, came across this ominous statement: "In all cases, the order in which the programs run is determined by ISY's internal algorithms, and is not user predictable". Whoa...that's not the language of a control system! It might also explain many of the glitches that people come across in getting unexplained behavior.

I thought I'd start off with a few experiments, using a Polisy that I have as a test system. I started off with a blank system, no programs. To keep things simple, I use an old X10 minicrontroller to generate events (no need to set up links, etc). I defined two state variables (test_1 and test2), then I created two programs. I use the same trigger for each program to keep them all becoming true at the same time. Program AAA is:

    IF X10 A/1 On is received

       THEN $test_1 += 1

 

and Program BBB is:

    IF X10 A/1 On is received

       THEN $test_2 += 1

as expected, both variables increment by 1 with each received X10 command

Second test: modify AAA to add a statement: 

    IF X10 A/1 On is received

       THEN $test_1 += 1

       THEN$test_2 = 0

so now if Program AAA executes before BBB, test_1 should increment with every X10 command, but test_2 should always end up with a value of 1 (Program AAA sets it to zero, and BBB then increments it by 1). But that's not what happens...test_2 is always at zero! So it would appear that BBB gets executed before AAA, even though it was created after. Just for fun I tried having it set test_2 to other values (eg: 42, the meaning of life, the universe, everything...) and sure enough, it always ends up with 42, so program AAA is always getting the last word. Execution is in reverse creation order? Well, what's "order" anyways...there is no clear indication of the order of a program in relation to other programs in the program editor, and copying, deleting programs will make you lose track of "creation order" quickly enough, as will the automatic listing of programs in ASCII name order. Start looking around... Ahh, when you click on "Summary" you get a list of programs, and the last field is an ID field! So programs do have ID's, like everything else in IoX. The first program you create gets ID 0002, and then IDs increment with new programs. So AAA is ID 0002 and BBB is ID 0003. You need to click on the ID heading to have them sorted by increasing ID.

Ok test 3 to see if the reverse order thing seems to be true: add Program CCC

    IF X10 A/1 On is received

       THEN $test_1 = 13

As expected, program CCC gets ID 0004, and sure enough, test_1 ends up with a value of 14 (initiated to 13 by CCC and incremented by one by AAA), and test_2 keeps the final value that AAA sets it to, unaltered by BBB.

Am I on to something? A lot more tests would need to be done to know for sure. The rules really needs to be clear for the controller to be reliable.

Posted

Would th number of lines also have an impact? All the programs should have the same number of lines, even if that means adding another $test_X = 0 at the top. 

This would be to test if both programs start at the same time in your test 1, but program one has an extra line to process and hence turns the test_2 to 0. 

 

Posted

The number of lines doesn't really have to anything to do with it. No two programs can ever be executed "at the same time". A program like IoX loops through the conditional statements at high speed, looking for any tests that are true to execute the Then statements, or false to execute the Else portion. This type of program model is often called a state machine and is used in PLCs (Programmable Logic Controllers). The main characteristic is that it can never stop and spend any time in a particular routine. All actions are usually put in output queues and dealt out as part of the entire scanning routine. ie: sending an Insteon command looks for the PLM to be idle, initiates sending the command, and sets a flag that looks for the PLM to have completed sending the command, but otherwise keeps looping the program.  Same with input conditions. Similarly, a Wait statement will set a flag to look for the system clock to have reached the time for the wait to have elapsed, and immediately gets back to the rest of the loop. The closest you can get two programs to seeing something happening seemingly simultaneously is when you can get them to test true in the same evaluation loop, which is what I was testing here by having them all look for the same X10 command.

The two main characteristics of a looping program controller are usually the known execution order, and timing of any triggering events in relation to the loop. That's how full predictability is achieved. For example, the good ole Ocelot home automation controller would queue incoming events, and a new event would be read off the queue and always become testable between two program scan loops. That, and programs would all be written as continuous series of If/Then lines, each one with line numbers. It would loop by starting at line 0 and loop through consecutive incrementing line numbers. That way, you were certain that program segments at lower line numbers would always be the first to see and test a new input condition. Without knowing that, how can you write program segments that reliably communicate with each other through variables?

Here is what my three test programs would look like in the Ocelot:

0    IF X10 A/1 On is received

1       THEN $test_1 += 1

2   IF X10 A/1 On is received

3       THEN $test_2 += 1

 

4   IF X10 A/1 On is received

5        THEN $test_1 = 13

 

You can have up to 2048 lines. Now no matter when the X10 A/1 On was actually received while the loop was executing, it would become available for testing just before executing line 0 of the following pass and be true for one full pass through the loop. Now I was certain that the Then statement at line 1 would be executed before line 3, and that before line 5.
 

That's the information we're missing about IoX. 

  • Like 1
Posted

A statement like "the order of execution is not defined" in the documentation of systems is common in event queue implementations (and multi-threaded processing implementations). If the programmer writes a finite state machine (IoX programs basically form a finite state machine) where the same event causes two different outcomes, that state machine is in fact a pseudo-random generator. To make the outcome deterministic, something else (another condition) needs to control the outcome. This additional condition could be specific to the system implementation (and therefore obscure) or explicitly added to the finite state machine by the programmer. Personally, I prefer to have full control over the finite state machine, so that it works independent of any particular implementation.

Posted

There is likely an order to processing and I have good idea what that may be but it could change in any future version so it must be considered undefined.

If a particular order is required then it must be forced by the user using Waits or Repeats and or with semaphore techniques.

Posted

@Guy Lavoie very interesting. Having used the Ocelot and Leopard myself to control my X10 network in the 90s had often made me wonder about IoX's program execution order

Gary

Posted

@Guy Lavoie

I have done a good bit of PLC programming and a ton of ISY programming.  The PLC works quite differently.  PLC clearly loops through the code and executes based on the state of any given line.  ISY does not loop through the "if" statements looking for conditions.  It works on triggers.  Again, I don't know how the actual engine works, but if you think of it this way, it will get your programs to work as expected.

So, here is how I think of it:

Consider that all of the if statements' conditions are indexed.  For every event that ISY encounters (a node value is changed or the clock ticks to the next second), it goes to that index and sees if any program matches that event.  If so, it executes the entirety of the program.  If two(or more)  programs match that event, there is no telling which it will execute first. 

Within a program, I have been told that ISY will not necessarily execute then/else clauses in order.  Meaning if you have 2 or more lines in a then clause, it could execute them in any order.  However, it has always been my experience that the lines in an then/else clause do execute in order.  I have a number of programs that do math where order of operations matter and they always work correctly.

  • Like 1
Posted
59 minutes ago, apostolakisl said:

@Guy Lavoie

ISY does not loop through the "if" statements looking for conditions.  It works on triggers.  Again, I don't know how the actual engine works, but if you think of it this way, it will get your programs to work as expected.

 

Well how do you think it detects triggers? It doesn't have a hardware interrupt for every device and program... It has to look for events by scanning through the programs looking for a condition that warrants executing the IF or ELSE statements. It might be optimized to skip some of the tests that can only test true when something external like an Insteon/X10/Zwave/whatever command or update happens, but for some others like a variable, time of day, etc, it needs to revisit any programs containing tests on those values if one of them changes (and time constantly changes). That might explain the reason why the execution order is deemed unpredictable. Certainly, things can be optimized to skip unneeded tests. That's also very likely the reason why there are "state" variables; because these need to be in a hit list for event testing, but no need to test integer variables.

For sure, the IF/THEN statements within a program will be executed in order. 

Posted (edited)
19 minutes ago, Guy Lavoie said:

Well how do you think it detects triggers? It doesn't have a hardware interrupt for every device and program... It has to look for events by scanning through the programs looking for a condition that warrants executing the IF or ELSE statements. It might be optimized to skip some of the tests that can only test true when something external like an Insteon/X10/Zwave/whatever command or update happens, but for some others like a variable, time of day, etc, it needs to revisit any programs containing tests on those values if one of them changes (and time constantly changes). That might explain the reason why the execution order is deemed unpredictable. Certainly, things can be optimized to skip unneeded tests. That's also very likely the reason why there are "state" variables; because these need to be in a hit list for event testing, but no need to test integer variables.

For sure, the IF/THEN statements within a program will be executed in order. 

As I mentioned, it works like it has indexed all of the events contained in all of the programs.  Should something in the index match a current event (not a condition, but an event, or trigger if you will) then it executes the program(s) that contain the item in question.  

ISY receives an event => Event is checked against the indexed list of events => matches point to program(s) containing event => program evaluates "if". 

 

EDIT: If you think of it as looping through all the programs, you are going to expect it to execute on the status of the conditions instead of only the "event" of the condition.

 

"For sure . . "  Not according to the people at Universal Devices when this was discussed many years ago.  But in my experience, I have never seen a then/else clause not execute in order.  But I have been told it is possible.  Perhaps if the first line is computationally complex and the second line is not, the second line might finish before the first line.  But I haven't seen it. 

Edited by apostolakisl
  • Like 1
Posted (edited)

Each element that can cause triggers likely has a list/stack of other elements to check should the value change.

There is no looping required. IIRC, spread sheets did this looping for value changes.

Of course there may be a background looping algorithm, as we know the code exist anyway,  for power up conditions, where there are no triggers happen to update the database.

Edited by larryllix

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing

    • No registered users viewing this page.
  • Forum Statistics

    • Total Topics
      37k
    • Total Posts
      371.3k
×
×
  • Create New...