x046866x Posted July 14, 2022 Posted July 14, 2022 (edited) I had an interesting epiphany the other day that has helped my way of looking at programming on the ISY994. I have been programming since the early 1980's so I'm familiar with most of paradigm's. When working with programming on the ISY994 it was always referred to as "Event based", which it is, but the trap I kept falling down was that I would apply a server-based view of "Event based", where an action is triggered by an Event but then the subsequent coding is (generally speaking) procedural. What was happening was I was expecting the subsequent flow to adhere to traditional procedural pattern....and it doesn't. Calls to programs are not procedurally nested (synchronous) and, in some cases, I would trigger other events incidentally (which would really confuse things). I came to this realization when I read a comment from someone (I will look for their name for proper credit) who said something to the effect of "...every time an Event is triggered all programs are searched for whether they may have interest in the Event, if so the program is executed, otherwise ignored...". The epiphany I had was that the ISY behaves far more like a State machine than a traditional server. Managing behaviors by controlling the internal state, State variables being key (of course). I have found that treating it this way has allowed me to reduce the code I'm using while increasing the reliability. What were unexplained behaviors before are now all explained. This helped me. Dunno if it may help others. P.S.: Like many Epiphany's, once my eyes are opened I am like "Duh....I'm an idiot". I am kicking myself for taking this long to come to this realization, especially considering how long I've been working on this platform. Edited July 14, 2022 by x046866x 2
DCardellini01 Posted September 23, 2022 Posted September 23, 2022 Long time control system programmer, and developer of embedded controls using real-time operating systems. I have always tried to fit most control programs into a State Machine model, and rigorously use the Mealy State Model in my many years. Therefore, I only "do something" on state transitions (never on state). And I always start with a State Diagram. The ISY programming construct is pretty simple for simple things, but it is easy to get into trouble for more complex programs, and becomes impossible to read a year later when you have many "programs" interacting with each other. There are quite a few idiosyncrasies in the programming model, and there does not appear to be any document that warns you of these things situations and how to avoid problems. As such, I only use IF and THEN (not else). I NEVER use WAIT or REPEAT in the state machine. I have a timer service folder that services each timer with a decrementing WAIT (by the second, minute or hour). The instant that I set a Timer in the State Machine, that service program decrements the timer to zero, and there is usually another state transition in my machine that checks for TIMER_1 = 0 in a condition. ****************************** In any event, I struggle to see that the event-based paradigm of the ISY programming is "state-like." All control programing is about "controlling the internal state," whether linear, procedural, object-oriented, or in this unusual paradigm for event-driven. The ISY event-driven model, is, as you point out, a change-in-state model. Internally, the ISY is creating an interrupt for each and every change of status of every device/statevariable in the system, and allowing YOU to create an interrupt service routine for that individual generated interrupt (that is what a singular program is...and interrupt service routine). That paradigm is fine for a smaller system. But when you have many hundredor thousands of devices in larger systems, it becomes very inefficient and very confusing. Better to snapshot the entry state of all devices, run your logic, modifying variables and device state in as output. Traditionally, for control systems, interrupts can cause lots of unforeseen problems, and you use them sparingly for only those things that need incredibly fast response time. And you severely limit the the length of code behind the interrupt service routine. I think the ISY, and now the Polisy, are fantastic, incredibly robust products. The event-driven paradigm works well for the intended target audience. ********************* Back to the State Machine Model for programming ISY: The beauty of sticking to one State-Machine model (I prefer Mealy), is you can implement your State Machine model on ANY programming environment, and spend 90% of your time on a scrap of paper working through your State Diagram. Converting that to code can be done by someone else. And a year later, you simply look at your diagram to dig into any required changes.
larryllix Posted September 23, 2022 Posted September 23, 2022 (edited) Nice! I use integer variables profusely for constants with labels and my only records are imbedded comments and ISY element names. eg. $cTRUE $cFALSE Element names are always positive logic and try not to be ambiguous. eg. Program: deviceName.batt.ok All just good programming practices from inline code habits learned the hard way. I avoid hidden and obscure things like using program state logic etc. Sent from my SM-G781W using Tapatalk Edited September 23, 2022 by larryllix 1
oskrypuch Posted September 23, 2022 Posted September 23, 2022 (edited) For most ISY programming, I just sit down and do it, as the inputs and outputs for many things are pretty trivial. But, that said, even some code that controls several lights based on motion, time of day, and perhaps some other factors, may be difficult to juggle clearly in your head. Some time ago I programmed control of the many zones in the house using a rigorous machine state approach, integrating prioritization, outside weather, time of day, season, location, manual requests for increased heat/cool, etc. And yes, you start on paper (virtual or otherwise), but then the implementation is dog simple, robust and understandable years later -- when you need to inevitably come back and make changes. * Orest Edited September 23, 2022 by oskrypuch 1
DCardellini01 Posted September 23, 2022 Posted September 23, 2022 (edited) Yeah, Larry. In my world, these options here do not exist in ANY program: You are making a more complex program almost impossible to understand a year later, likely making troubleshooting in development far more painful, and in general, adding another confusing layer on top of confusion. Rarely in the controls world is the quickest, easiest program change, the proper change. Those that do not understand that will spend most of their time in frustration with troubleshooting, and use trial and error to fix problems. (which inevitably results in the dreaded "spaghetti code.") Edited September 23, 2022 by dcard
larryllix Posted September 23, 2022 Posted September 23, 2022 (edited) 2 hours ago, dcard said: Yeah, Larry. In my world, these options here do not exist in ANY program: You are making a more complex program almost impossible to understand a year later, likely making troubleshooting in development far more painful, and in general, adding another confusing layer on top of confusion. Rarely in the controls world is the quickest, easiest program change, the proper change. Those that do not understand that will spend most of their time in frustration with troubleshooting, and use trial and error to fix problems. (which inevitably results in the dreaded "spaghetti code.") Yeah, Spaghetti code can't really exist in ISY event programming. Although you can make some very interdependent event driven code that can oscillate. Been there, done that. BTW: I use the Repeat While construct as an inline If/Then/Else construct. Since ISY doesn't offer much in the way of inline conditionals, it makes and avenue to get things done. I don't like it but the whole thing would be much better if I could change the names of the construct to suit better. Good inline commenting and labeling helps the confusion a lot. It can get complicated when you write ISY code to average multiple sensor inputs and discard outliers but it works well for analogue inputs to be reliable in the event of a sensor malfunction and I always like to not use sensor analogues directly from input devices. Passing them through a stats variable has allowed me to swap input devices, change scaling and otherwise massage data that would mean modifying many programs using that data. When I half moved my programs fro ISY to polisy it took one program to synchronise sensor data between devices. Some see that as too complicated and some see it as simplified at the cost of a few more bytes of code. At least ISY offers many ways to do things and we all have our druthers. This is about the 5th system style I have worked with that used event driven code. If you lived on VB, using their "objects", for a length of time, you would fall right into this style. Edited September 23, 2022 by larryllix
DCardellini01 Posted September 23, 2022 Posted September 23, 2022 3 hours ago, larryllix said: BTW: I use the Repeat While construct as an inline If/Then/Else construc Wow. Great idea! My only concern is what I understand to be the open door when a REPEAT (or WAIT) is invoked, That open door to allow other programs to run (interrupt is now available), and the fact that if original top conditional changes, the remaining code under your REPEAT may not execute. Do I have this right???
MrBill Posted September 24, 2022 Posted September 24, 2022 (edited) 15 hours ago, dcard said: Wow. Great idea! My only concern is what I understand to be the open door when a REPEAT (or WAIT) is invoked, That open door to allow other programs to run (interrupt is now available), and the fact that if original top conditional changes, the remaining code under your REPEAT may not execute. Do I have this right??? Once the state of the IF changes, execution is interrupted at the next break (wait and possibly repeat). There are many possible constructs to avoid the issue. I'll write an imaginary abstract example with probably little real world value to illustrate: Program FanCycle.on If Temp > 80.0 then Run Program FanCycle.loop (then) else (blank) Program FanCycle.loop If (blank) then Disable Program FanCycle.on Enable Program FanCycle.off Repeat every 10 minutes Turn on Fan wait 5 minutes Turn off Fan else (blank) Program FanCycle.off If Temp < 75.0 then Stop Program FanCycle.loop Turn Fan off enable Program FanCycle.on disable Program FanCycle.off *// Note: since this program is disabling itself this MUST BE last. //*Program FanCycle.startup (Run at Startup) If (blank) then Turn Fan off Enable Program FanCycle.on Disable Program FanCycle.off else (blank) Program FanCycle.on watches for the temp to exceed 80, when it does it runs Program FanCycle.loop which immediately disables Program 1 and enables Program 3. Program 2 then cycles a Fan on and off for 5 of every 10 minutes. Program FanCycle.off get us out of the loop when the temp drops below 75 Program FanCycle.loop insures that the devices and programs are returned to known states when the ISY is rebooted. If the power to the ISY (or the house) was interrupted while the loop was running, if we didn't have program 4 when power was restored the fan might be on or off (insteon returns to it's last state) and Program FanCycle.on would be disabled which would mean the loop would never begin again. If we don't write these programs as segments like this, the problem is that as the temperature bounces around unanticipated things happen... for example consider this: Program FanCycle If Temp > 80.0 then Repeat every 10 minutes Turn on Fan wait 5 minutes Turn off Fan else Turn Off Fan here are some of the unintended things that happen: If the temp is rising, the loop will first execute at 80.1 or above, if the next temp change is 80.5 the current Then block will stop running, and a new Identical Then block will start running with timers reset. if the temp is wavering around 80 like 80.1, 79.9, 80.5, 79.0, etc the fan will stop and start everytime the temp updates if the temp is falling and had dropped below 80 this program will create ALOT of unneeded insteon traffic, because each time the temperature update the ISY will send the command to the switch to Turn Off. In conclusion: ISY program is a different beast. While you might be able to use some constructs from other languages/styles one must also consider what's happening under the hood (example: it doesn't make sense to turn the fan off everytime the temp changes by .1 degree all WINTER long. Edited September 24, 2022 by MrBill 2
larryllix Posted September 24, 2022 Posted September 24, 2022 (edited) 19 hours ago, dcard said: Wow. Great idea! My only concern is what I understand to be the open door when a REPEAT (or WAIT) is invoked, That open door to allow other programs to run (interrupt is now available), and the fact that if original top conditional changes, the remaining code under your REPEAT may not execute. Do I have this right??? Yes. IIRC this is only event driven system I have worked with, that can have processes stopped and restarted. I would guess in the beginning UDI had to decide what to do when a new event happens that is the same as one already being processed. Continue like nothing happened and ignore the new event Continue like nothing happened and stack the new event for sequential operation Stop the current process and handle the new even like the previous process wasn't happening. The choice they made provides a lot of strange happenings in even processing and program writing. It definitely puts a hiccough in the logical thinking of experienced inline code writers. Now I would like UDI to add a program disable command that allows a program to finish what it started. Currently the Disable program command line also stops the affected program. "They just have no self-control..." Edited September 24, 2022 by larryllix
larryllix Posted September 24, 2022 Posted September 24, 2022 (edited) 3 hours ago, MrBill said: Once the state of the IF changes, execution is interrupted at the next break (wait and possibly repeat). There are many possible constructs to avoid the issue. I'll write an imaginary abstract example with probably little real world value to illustrate: <snipped> In conclusion: ISY program is a different beast. While you might be able to use some constructs from other languages/styles one must also consider what's happening under the hood (example: it doesn't make sense to turn the fan off everytime the temp changes by .1 degree all WINTER long. I can see you are a man of experience. Not many would even realise these quirks without sweating through it themselves. Still have any hair left? Edited September 24, 2022 by larryllix 1
MrBill Posted September 24, 2022 Posted September 24, 2022 1 hour ago, larryllix said: I can see you are a man of experience. Not many would even realise these quirks without sweating through it themselves. Still have any hair left? I dyed it purple for halloween! 2
asbril Posted September 24, 2022 Posted September 24, 2022 9 minutes ago, MrBill said: I dyed it purple for halloween! The yellow (see your avatar) looked nice. 3
larryllix Posted September 24, 2022 Posted September 24, 2022 (edited) 7 hours ago, asbril said: The yellow (see your avatar) looked nice. He couldn't live up to the blonde image giving good advice like that. Sent from my SM-G781W using Tapatalk Edited September 25, 2022 by larryllix 1
asbril Posted September 24, 2022 Posted September 24, 2022 5 minutes ago, larryllix said: He couldn't live up to the blonde image giving ood advice like that. Sent from my SM-G781W using Tapatalk BTW I was in Ontario this Summer and tried to find " Northern SouthWestern Ontario " on the map, but I could not 1
larryllix Posted September 25, 2022 Posted September 25, 2022 4 hours ago, asbril said: BTW I was in Ontario this Summer and tried to find " Northern SouthWestern Ontario " on the map, but I could not I heard you were coming and moved. Here is a map of southern Ontario. See the braying elephant? I lived in a**hole. 1
asbril Posted September 25, 2022 Posted September 25, 2022 5 minutes ago, larryllix said: I heard you were coming and moved. That makes sense......... I noticed how quiet and peaceful Ontario was 😀 2
apostolakisl Posted September 25, 2022 Posted September 25, 2022 (edited) On 9/23/2022 at 5:32 PM, dcard said: Wow. Great idea! My only concern is what I understand to be the open door when a REPEAT (or WAIT) is invoked, That open door to allow other programs to run (interrupt is now available), and the fact that if original top conditional changes, the remaining code under your REPEAT may not execute. Do I have this right??? Yes, and often times that ability to be interrupted is a useful tool. If you intend to have a wait or repeat always execute to completion, you need to have a separate programs for trigger and execution. If whatever you want Then Run then program 2 If blank Then disable program 1 do something wait do something wati etc. enable program 1 I use interruptible waits all the time as a hysteresis type mechanism. My dryer has a wrinkle protector that turns it on every few minutes. And using the notation option in an ISY program you save yourself confusion when a year or two or whatever later you can't remember. The notes included below are in the program, not added by me to this post. This sort of explanation in your programs is invaluable. Master Drier Copy - [ID 0163][Parent 00F7] If 'WebControl8 / Input8' Status is 0 Then Wait 5 minutes Enable Program 'Master Drier' Else - No Actions - (To add one, press 'Action') Input 8 is 1 when drier off. When air vent flapper opens input becomes 0. If the drier is on for 5 continuous minutes, master drier is enabled. At this point, the next time the flap closes (or in other words when it shuts off), it will send a notification and disable itself. It will not send a notification again until it the drier has run for 5 continuous minutes. Master Drier - [ID 00C6][Parent 00F7][Not Enabled][Run At Startup] If 'WebControl8 / Input8' Status is 1 Then Send Notification to 'lou text' content 'Master Dryer Done' Wait 1 second Disable Program 'Master Drier' Else - No Actions - (To add one, press 'Action') Edited September 25, 2022 by apostolakisl
larryllix Posted September 25, 2022 Posted September 25, 2022 2 hours ago, apostolakisl said: Yes, and often times that ability to be interrupted is a useful tool. If you intend to have a wait or repeat always execute to completion, you need to have a separate programs for trigger and execution. If whatever you want Then Run then program 2 If blank Then disable program 1 do something wait do something wati etc. enable program 1 I use interruptible waits all the time as a hysteresis type mechanism. My dryer has a wrinkle protector that turns it on every few minutes. And using the notation option in an ISY program you save yourself confusion when a year or two or whatever later you can't remember. The notes included below are in the program, not added by me to this post. This sort of explanation in your programs is invaluable. Master Drier Copy - [ID 0163][Parent 00F7] If 'WebControl8 / Input8' Status is 0 Then Wait 5 minutes Enable Program 'Master Drier' Else - No Actions - (To add one, press 'Action') Input 8 is 1 when drier off. When air vent flapper opens input becomes 0. If the drier is on for 5 continuous minutes, master drier is enabled. At this point, the next time the flap closes (or in other words when it shuts off), it will send a notification and disable itself. It will not send a notification again until it the drier has run for 5 continuous minutes. Master Drier - [ID 00C6][Parent 00F7][Not Enabled][Run At Startup] If 'WebControl8 / Input8' Status is 1 Then Send Notification to 'lou text' content 'Master Dryer Done' Wait 1 second Disable Program 'Master Drier' Else - No Actions - (To add one, press 'Action') Here is what I would like to see... Program 1 If condition = True Then deTrigger Program 1 <------ disable If section without stopping it do something wait 5 seconds do something else enable Program 1 <----- enable If section Else ----
apostolakisl Posted September 26, 2022 Posted September 26, 2022 18 hours ago, larryllix said: Here is what I would like to see... Program 1 If condition = True Then deTrigger Program 1 <------ disable If section without stopping it do something wait 5 seconds do something else enable Program 1 <----- enable If section Else ---- Being able to disable a program (either from within the program or from another program) without terminating it would be nice. But since you can accomplish the same goal by just separating the trigger and execution into two programs, I really doubt UD would put such a wish on the short list of things to do. 1
larryllix Posted September 26, 2022 Posted September 26, 2022 4 hours ago, apostolakisl said: Being able to disable a program (either from within the program or from another program) without terminating it would be nice. But since you can accomplish the same goal by just separating the trigger and execution into two programs, I really doubt UD would put such a wish on the short list of things to do. Yeah, It seems like it would be so easy to add another pulldown option in the menu, and add the same code without the "program Stop"
apostolakisl Posted September 26, 2022 Posted September 26, 2022 42 minutes ago, larryllix said: Yeah, It seems like it would be so easy to add another pulldown option in the menu, and add the same code without the "program Stop" Two "disable" options would do it. Easy enough to add it to a drop down menu, not sure how hard it would be to add it to the back end. "disable" "disable auto-triggering" 1
Recommended Posts