These notes are believed to be accurate, but are still undergoing revisions based on feedback from ISY staff.
Programs are not executed in any particular sequence; the ISY controller runs them in whatever order it sees fit. If you want to guarantee the order of execution, then you can achieve this through the use of schedules, or use a series of program flags to maintain state.
When your program runs, it is guaranteed to complete the sequence of statements "atomically" which simply means that the sequence will run without interruption. This means that you are assured that no other program will run while your program is executing statements, which further means that you don't have to worry about two programs trying to modify things at the same time.
There are two exceptions to the rule that a program runs without interruption.
Exception 1: The Wait and Repeat statements provide an opportunity for other programs to be run; when these statements are encountered, the ISY might run other programs, if/as other programs are eligible for execution.
Exception 2: The Wait and Repeat statements can cause the program to run differently; read the section titled How Programs are Scheduled for Execution for more information.
If you are like most people, any programming you are familiar with is within the tidy confines of a computer. Most things you need access to are always available, or the operating system makes it look that way for you. For example, you don't really have to worry about whether the printer is ready to print -- you just submit the job to the print queue, and the job prints whenever it happens. Similarly, reading a file happens "instantly" -- no need to worry about how long it takes. The only interaction for which you expect delays is waiting for user input.
When working with Insteon devices and other real-world pieces of gear, you can't assume that everything happens "instantly". If you send a command to a device to turn on a light, and you have some other program that checks the status of the light, you have to allow time for the light to change.
************** Question for ISY **************
How are delays actually handled by the ISY?
Suppose program ABC executes a statement to turn LampPatio off,
and this lamp takes 2 seconds to actually turn off
(perhaps due to Insteon network delays).
Further suppose that program XYZ is configured to run when LampPatio
turns on.
Does program XYZ run "immediately" after program ABC attempts
to turn on LampPatio, or does the ISY instead leave the status of
LampPatio as off until the device has actually turned on,
and thus program XYZ only runs after the two second delay?
While the command might take effect almost instantaneously when you are testing your programs, next week there will be a transmission hiccup in your house wiring, and the Insteon command will take a second or two to complete. If your program doesn't gracefully accommodate such a delay, then it will not work as expected.
Because of points 1, 2, and 3, you need to be careful in
how you program, and you need to program "defensively"
so that your logic will work regardless of the Insteon command
delays and retries, the order of execution of your programs, etc.
Point 4 is the trick that you will need to help your program take Actions
only when things have reached a steady-state.
If your program is assessing a possibly dynamic situation, then you should probably put a Wait statement before performing any Action statements. This is a good way to be sure that the situation has reached steady-state.
A detailed example of this principle is described in the notes on the scheme where a KeyPadLinc button is used to both monitor and control basement lights.
You will also want to read and understand the section titled How Programs are Scheduled for Execution.
In ISY, programs are either running, or waiting to run. When a program is "waiting" to run, this means that it is waiting for a "trigger event" to happen. Trigger events include each and every element in the If expression, as well as other conditions that might apply (for example, at a specific time-of-day, or perhaps after so-many seconds or minutes).
Sometimes people like to think of this as a program "waking up" when something happens; this is the same idea as the "trigger". The important thing to remember is that the program will not run until something triggers it. As an aside, note that a program can be explicitly set to run at Start-Up; this is just a special form of a trigger.
The use of triggers allows the ISY to be quite efficient: instead of constantly running programs, always re-evaluating the If expression, the ISY can simply keep track of what nodes trigger your program (recall that a node is a device, scene status, another program status, etc.). This means that your program only needs to be run when one of the nodes changes state. When a node changes state, this triggers execution of your program; the If expression is evaluated, and either the Then or the Else portion executes. After execution, your program again "goes to sleep", waiting for another trigger.
When a Wait statement is encountered, the program "goes to sleep", but has one more additional trigger that can wake it up. This additional trigger is the timer, which is set to go off at the end of the wait period. But remember, any of the other triggers can still wake up your program! So, your program will wake up in one of the 2 following ways:
There are a couple of "race conditions" which can arise in the above
scenario:
1. When an If element changes state, and thus makes the program
eligible for execution, what happens if that element changes state
back to the previous state?
The ISY handles this in a simple way: if any node in the If changes state,
then either the Then or the Else portion will execute.
2. What if an If element changes state, and the Wait trigger fires,
both before the program gets a chance to run.
What takes precedence -- the Wait trigger, or the other trigger(s)?
I don't know for sure, but I think that the ISY determines this in a
way that is beyond your control.
When a Repeat statement is encountered, the program takes a moment to check the status of the triggers. If one has fired, then the If expression is evaluated, and execution proceeds with either the Then or Else part -- starting with the first statement in the Then or Else. If no trigger has fired, then the program proceeds with the next iteration in the loop.
This behavior allows the program to be "interrupted" periodically while looping, which is important because ISY programs run without fear of interruption.
If you want to test if a light is illuminated at all, then you want to test for 'Not Off'. Performing a test for 'On' actually is testing for the light to be at 100%, which is probably not what you want.
This is just a bit of a quirk, and is no big deal as long as you know it. You can query the button directly by referencing the device, but to turn a button on or off you must use a Scene. All this means is that you create a scene that consists of just this one button, then your program turns the scene on and off.
Scenes are a great way to organize collections of devices. You probably already use Scenes to create lighting scenarios, and to create "virtual circuits" for multi-way lighting.
What you might not realize is that Scenes minimize Insteon network traffic. Basically, instead of communicating with individual devices, the ISY can send one command to multiple devices at once (the exact protocol details are a little more complicated, but this is the general idea).
Another benefit of Scenes is that your programming will be simplified. If your program manages a Scene, then you can change the devices contained in that Scene without changing the program.
Some readers of this section will recall a recommendation that programs should only take action on a Scene which contains only Responders. This is not correct; any and all Scenes can and should be referenced by programs.
These final few points don't typically affect your programs, but are worth knowing.
When you check the status of a device, you are actually testing the value of what ISY thinks is the current status. With any luck, ISY will indeed know the correct and current state, and thus your program will work correctly. You can programmatically cause the ISY to perform a query, which will go out "over the wire" and get the current status of device. This might be useful in certain circumstances -- for instance, if it is important to be certain of a particular status.
Using an internal state is a feature and is by design. As you might imagine, by maintaining its own idea of the status of each device, the ISY can execute programs much more quickly, as it doesn't have to constantly flood the network asking for device statuses.
For those of you familiar with modern programming languages, you probably expect If clauses to be evaluated left-to-right (well, top-to-bottom in the ISY GUI), and of course you expect parentheses to be honored. When evaluating left-to-right, many/most languages stop the evaluation as soon as the result is determined. For example, if you AND two tests, then the right-most test won't be evaluated if the left-most expression is false.
What might surprise you is to learn that the entire If clause is always processed -- even when further evaluation is not needed. This should not introduce any side-effects, but does mean that you don't need to bother and try to be "efficient" when constructing a bulky expression. Better to make it as readable as possible, instead of trying to be clever and "efficient" by constructing a contorted expression.
A Wait will not execute if an Action does not follow it.
You might think that ending your program with a Wait will ensure
that your program will keep running until things have reached a
steady-state.
This notion is flawed for at least two reasons:
1. As soon as your program does the Wait, then other programs are
eligible to run anyway.
Other programs are not respecting your program's Wait!
2. Your program might not wait as long as you expect, because
your program might be triggered by any number of events,
and thus end the Wait prematurely.
Read the How Programs are Scheduled for Execution section for more.
Last updated November 17, 2010
Updated 22 Nov to clarify wording in point #7.
Updated 30 Nov to add section "B" re program execution model, etc.
Copyright (c) 2010 John R. Adams jra@adamsj.com