Jump to content

How to Synchronize Program Execution to the Hour


Jimini

Recommended Posts

This question may be answered in some Forum thread but I have tried several ways to ask the question without finding ti covered anywhere.  

I want an ISY program to execute every hour on the hour, or at least approximately on the hour. I currently have a way of doing this but I have found it is not sufficiently bullet proof. Our neighborhood recently experienced a power outage for 52 hours.  When power was restored, all of my programs with starts based upon time of day, restarted.  My program to loop every hour was waiting for the time of day of the original start, which was some 16 hours later.  In similar situations, I would want my program to restart at the next whole hour. 

My existing program looks like this:

if 
    (
      time is 8:00:00AM  // This was just an aribtrary time to start program at an hour boundary
    and ProgRunning is 0
    ) 
  or (
      time is Last Run Time for 'Prog Init' + 1 hour
    and ProgRunning > 0
    )

then 
    ProgRunning += 1
    execute stuff

The problem occurred, I believe, because once ISY rebooted after the power outage, the flag variable ProgRunning was re-initialized to 0 and possibly the Last Run Time may also have been cleared.  I don't know about that.  

I am thinking there is likely an easier and more robust way to do this.  Am I correct in that?

Link to comment

Seems like your program runs the way you want it to once it's started, so all you need is an automated startup.  To do that you could create a simple program that uses the Current Minute in some way to signal that your existing program should start.  So how about:

StartHourlyProg Init - [ID 00B4][Parent 0001][Run At Startup]

If
        $iProgRunning is 0
 
Then
        Run Program 'Prog Init' (If)
 
Else
        Wait  60 seconds
        $iProgRunning  = [Current Minute ]
        $iProgRunning *= -1
        Run Program 'StartHourlyProg Init' (If)

with a slight modification to your existing program:

Prog Init - [ID 00A2][Parent 0001]

If
        (
             $iProgRunning is 0
        )
     Or (
             Time is Last Run Time for 'Prog Init' +  1 hour 
         And $iProgRunning > 0
        )
 
Then
        $iProgRunning += 1
        
        // Execute Stuff
 
 
Else
   - No Actions - (To add one, press 'Action')

These two programs depend on your ProgRunning variable (my $iProgRunning variable) being an integer variable (or more specifically not a state variable), and you having its INIT value set to -1 so that when your ISY reboots the variable is initialized to a -1 (or more specifically not 0).  It also depends on the "StartHourlyProg Init" program being set to run at startup.

image.thumb.png.d804513b5a1e9bca0fb0a145482681e8.png

image.png.15d6231e2c26a65dc1a321fb68b9df8d.png

When your ISY reboots, "StartHourlyProg Init" will run and with $iProgRunning being initialized to -1 it will run its ELSE.  That will set $iProgRunning to the current minute times -1.  This will result in a value from 0 to -59.  As a final step, "StartHourlyProg Init" will run its own IF.  This continues until the current minute is 0 at which point the THEN will be run which executes the IF of "Prog Init" and then ceases execution of "StartHourlyProg Init".  The "Wait 60 seconds" is in the ELSE so that the program doesn't take over your ISY, starving other programs of time, until the current minute is 0.

Link to comment

I would prefer to create a stable system clock, independent of any other hardware or systems, that could be used in many programs. Automatic startup is always a problem in ISY and it typically takes an extra program as kclenden demonstrated above. No flagging variable is needed, only one to keep the current system minute clock.

This program needs to have "Run at startup" enabled.
 

Reboot and Initialise - [ID 0040][Parent 0006][Run At Startup]

If
        // Enabled to Run at Startup only
Then
        Wait  2 seconds
        Run Program 'Set hh.mm' (Then Path)
        Wait  1 second
        Run Program 'Set MM.DD' (Then Path)
        ...
        Send Notification to 'Text  Larry' content 'ISY Rebooted'
Else
   - No Actions - (To add one, press 'Action')
 

 

Then a program to keep system clock variables. I generate a combo variable $sISY.hh.mm also.
Note the extra trigger times are for those times that you stall the process editing the program etc.. and no reboot is taking place. They can kickstart the program again.
Note: The usage of State variables where triggers are needed ie: $sISY.minute and $sISY.hh.mm 

Set hh.mm - [ID 00FC][Parent 0006]

If
        Time is 12:00:05AM
     Or Time is  8:00:05AM
     Or Time is 12:00:05PM
     Or Time is  8:00:05PM
 
Then
        Repeat Every  20 seconds
           $sISY.minute = [Current Minute]
           $ISY.date.scratchpad  = [Current Minute]
           $ISY.date.scratchpad /= 100
           $ISY.date.scratchpad += [Current Hour]
           $sISY.hh.mm  = $ISY.date.scratchpad
           $sISY.hh.mm Init To $ISY.date.scratchpad
 
Else
   - No Actions - (To add one, press 'Action')
 


Now all any program needs to trigger on the hour would be to watch the system clock based variable. No looping or self starting programs, keeping it simple.

Run every hour on the hour - []

If
    $sISY.minute = 0
Then
     execute stuff
Else
    ---

 

 

Link to comment

I would prefer avoiding having programs that automatically run every 20 seconds unless I had a functional reason to justify it (which I do not).  My temptation would be to keep it simple, even if a little inelegant.

if

time is 12am

time is 1am

or time it 2am

or time is 3am

etc....

or time is 11pm

then

do stuff

Link to comment
6 minutes ago, oberkc said:

I would prefer avoiding having programs that automatically run every 20 seconds unless I had a functional reason to justify it (which I do not).  My temptation would be to keep it simple, even if a little inelegant.

if

time is 12am

time is 1am

or time it 2am

or time is 3am

etc....

or time is 11pm

then

do stuff

I have to agree with that logic. I used a previous system which limited the number of timers available while ISY doesn't, and I suspect too many may bog some processes down. This is one reason to create a central time keeper and have all other programs use it.

However, causing ISY to have to check  each of 24  time triggers, every system minute change,  in a program, may have more detriments to the CPU schedule, anyway. With down to one second resolution, ISY Wait timers may get checked every second? hmmmmmm….

I see the need for the Polisy CPU speed increase coming. Looks to be about 40 times the processing speed.

Link to comment
32 minutes ago, larryllix said:

However, causing ISY to have to check  each of 24  time triggers, every system minute change,  in a program, may have more detriments to the CPU schedule, anyway.

I am sure you have a better sense of all this than I.  I admit that I don't understand the frequency that programs are checked, the impact of having 24 conditions versus a few, nor the load on the CPU of checking programs versus running programs.  

In a practical sense, I would actually be surprised if it was noticeable either way.  I just thought about throwing out an idea for a completely different view on this problem for consideration.

Link to comment

Thank you all for the many suggestions.  The discussion has been interesting.  I know very little about the hardware resources within ISY so it is difficult to judge he "efficiency" of the various suggestions.  In addition to the perhaps inelegance of the 24 clause of an IF statement is whether that would set up 24 separate tiggers to be installed perpetually.  

Questions about larryllix's suggestion: Is the intent that the "REPEAT every 20 seconds" runs for ever or just at the 4 times per day of the IF statement?  I think it runs continuously for ever.  If so, then what is the purpose of the 4 times in the IF statement?  Also, what does the INIT TO action do?  I am not familiar with that action.  

Certainly, Bumbershoot's suggestion would be the most elegant if there is a simple way to increment a state variable at the beginning of each hour, but to do that isn't a loop similar to larryllix's 20-second repeat loop required?  A condition similar to "IF [current minute] is 0" which which set up some sort of trigger would do that but I don't think something like that is possible.  

Possibly a pair of programs such as:

    Program SetTopOfHour
        REPEAT every 20 seconds
            CurrentMinutes = [current minutes]
            RUN PROGRAM 'check minutes'

    Program check minutes
        IF
            CurrentMinutes = 0
        THEN
            TopOfHour *= -TopOfHour        // State variable initialized to -1
                                                                  // Flipping sign for perpetual changes

Perhaps these are so short as to not create too much overhead executing every 20 seconds?  

Link to comment
26 minutes ago, Jimini said:

Certainly, Bumbershoot's suggestion would be the most elegant if there is a simple way to increment a state variable at the beginning of each hour, but to do that isn't a loop similar to larryllix's 20-second repeat loop required?  A condition similar to "IF [current minute] is 0" which which set up some sort of trigger would do that but I don't think something like that is possible.  

I would just increment the STATE variable +1 at the top of each hour. 

New Program - [ID 010D][Parent 00A7]

If
        Time is  1:00:00AM
     Or Time is  2:00:00AM
     Or Time is  3:00:00AM
     Or ...
 
Then
        $s.HourlyIncrement += 1
 
Else
   - No Actions - (To add one, press 'Action')

The second program could have a simple IF statement (which will only run when the variable changes):

If 
	$s.HourlyIncrement > 0

Then
	Run Stuff

You could just let the variable increment forever.  We'll never live long enough for that value to get too large.  I have a variable set to Unix epoch time, currently sitting on 1581696060.

Link to comment
6 hours ago, Jimini said:

Thank you all for the many suggestions.  The discussion has been interesting.  I know very little about the hardware resources within ISY so it is difficult to judge he "efficiency" of the various suggestions.  In addition to the perhaps inelegance of the 24 clause of an IF statement is whether that would set up 24 separate tiggers to be installed perpetually.  

Questions about larryllix's suggestion: Is the intent that the "REPEAT every 20 seconds" runs for ever or just at the 4 times per day of the IF statement?  I think it runs continuously for ever.  If so, then what is the purpose of the 4 times in the IF statement?  Also, what does the INIT TO action do?  I am not familiar with that action.  

Certainly, Bumbershoot's suggestion would be the most elegant if there is a simple way to increment a state variable at the beginning of each hour, but to do that isn't a loop similar to larryllix's 20-second repeat loop required?  A condition similar to "IF [current minute] is 0" which which set up some sort of trigger would do that but I don't think something like that is possible.  

Possibly a pair of programs such as:

    Program SetTopOfHour
        REPEAT every 20 seconds
            CurrentMinutes = [current minutes]
            RUN PROGRAM 'check minutes'

    Program check minutes
        IF
            CurrentMinutes = 0
        THEN
            TopOfHour *= -TopOfHour        // State variable initialized to -1
                                                                  // Flipping sign for perpetual changes

Perhaps these are so short as to not create too much overhead executing every 20 seconds?  The four time triggers are for ME editing and forgetting to restart the program. When you edit a program it stalls. There may be other reasons for it to stall. I have had stalled programs many times :( but likely always my fault :( 

For inefficiency and CPU cycle wasting...I doubt you would have to worry about it with ISY and when it comes time, you will have a Polisy running about 40 times the processor speed, with hardware clock and hardware buffered I/O etc..

The repeat every 20 seconds...Correct, runs forever. 

Init to is a variable assignment statement that programs a ROM copy of the variable for boot up, initial value. One of the first things ISY does is to copy all the "init to" ROM variable values over to the RAM copies of the same name.

Link to comment
5 hours ago, Bumbershoot said:

I would just increment the STATE variable +1 at the top of each hour. 


New Program - [ID 010D][Parent 00A7]

If
        Time is  1:00:00AM
     Or Time is  2:00:00AM
     Or Time is  3:00:00AM
     Or ...
 
Then
        $s.HourlyIncrement += 1
 
Else
   - No Actions - (To add one, press 'Action')

The second program could have a simple IF statement (which will only run when the variable changes):


If 
	$s.HourlyIncrement > 0

Then
	Run Stuff

You could just let the variable increment forever.  We'll never live long enough for that value to get too large.  I have a variable set to Unix epoch time, currently sitting on 1581696060.

Nice! With this technique it would be simple for newbie ISY programmers and result in a state variable containing the current system hour, usable elsewhere and never have to be used again. To keep the hour under 24 hours the second program could look like this.

If
     $sHourlyIncrement >= 23
Then
    $sHourlyIncrement = -1
    Run 'Program ThisOne (Else)'
Else
    $sHourlyIncrement += 1
    Run stuff

The two programs could be combined into one with a more compound If section logic but I would likely separate it into two programs by logical function. One for e the clock setting the variable, and one for the slave function at each hour top. Just the way I tend to think.
 

Link to comment
9 hours ago, oberkc said:

I am sure you have a better sense of all this than I.  I admit that I don't understand the frequency that programs are checked, the impact of having 24 conditions versus a few, nor the load on the CPU of checking programs versus running programs.  

In a practical sense, I would actually be surprised if it was noticeable either way.  I just thought about throwing out an idea for a completely different view on this problem for consideration.

I have no special ISY inside information, but MY logic tells me, based on best resolution of each program element...
- Wait lines would need an low-level ISY algorithm that checks for the end timeout  every second.
-Time trigger lines would have to have an low-level ISY  algorithm that checks all time triggers every 60 seconds.

Without knowing exact processing times one check every second vs. 24 checks every 60 seconds..... looks like you won! :) 

Link to comment
2 hours ago, oberkc said:

I am not sure what this means to "install" a trigger.

My understanding is when the program is installed, each line is compiled into ISY isms, and triggers are installed into a table or list for the processor to check every X CPU clicks, or whatever time base ISY uses internally. This would avoid the ISY engine from having to "dig" through all the programs looking for what needs doing...for CPU speed and efficiency. Of course this is all conjecture on my part, from writing machine level code with less than 400 bytes of memory and a 1MHz CPU  in 1971. :) 

 

Link to comment
10 hours ago, larryllix said:

I suspect too many may bog some processes down.

That's why I wrote the program the way I did.  You only have a repeating counter for at most the first 60 minutes of ISY uptime.  After that the repeating counter stops and you're left with the next program that only triggers once an hour.

54 minutes ago, larryllix said:

I have no special ISY inside information, but MY logic tells me, based on best resolution of each program element...
- Wait lines would need an low-level ISY algorithm that checks for the end timeout  every second.
-Time trigger lines would have to have an low-level ISY  algorithm that checks all time triggers every 60 seconds.

I'm guessing that it's way more efficient than that.  There's probably a sorted time queue that any program in a WAIT state, or with a TIME trigger gets put on.  That way, only the very first program has to be checked every second.  If it's not time to trigger the first program then you know it's not time to trigger any program with a later time.

Link to comment
1 hour ago, kclenden said:

That's why I wrote the program the way I did.  You only have a repeating counter for at most the first 60 minutes of ISY uptime.  After that the repeating counter stops and you're left with the next program that only triggers once an hour.

I'm guessing that it's way more efficient than that.  There's probably a sorted time queue that any program in a WAIT state, or with a TIME trigger gets put on.  That way, only the very first program has to be checked every second.  If it's not time to trigger the first program then you know it's not time to trigger any program with a later time.

Awesome concept! I like it!

I am not sure UDI has gone that far for process control yet though. OTOH they did make some basic engine changes on or about v5.0.4 that apparently sped up processing. Who knows? M. told me there was no list, at one time.

Link to comment

I really appreciate all the discussion.  I guess we all our at the point of guessing how the internals of ISY work.  I don't remember seeing how many bits are allocated for integer variables hence my concern about incrementing every hour  Thanks to Bumershoot for alleviating that concern.  And as for the triggers or timing conditions, I wasn't sure if this was accomplished by software loops or hardware timers.  The suggestion that software loops are likely used would make sense for a system with limited hardware but an unknown number of triggers desired by the users.  I was happy to see larryllix is an old time machine code programmer from the 1970s.  I spent the better part of two years writing the real time data acquisition software for my thesis experiment in the 1970s on a 1.25MHz computer.  Some 25 years ago, I demonstrated that I knew some electronics and could manage projects and I never wrote another line of code.  It's been much fun to play with ISY programs and Google Scripts.  It would be interesting to learn a bit more about the ISY hardware.  

Perhaps I can get a couple more questions answered.  For those two little program fragments that I included earlier, the first had no IF clause, only a THEN which should start each time ISY rebutted.  Is that correct?  It can exist without an IF clause?  

Secondly, when kclenden pointed out the need to specify that his program should auto start at startup, that was yet another ISY feature that I did not recall.  In fact, I have four other programs that each start with an IF based upon time of day.  After this recent extended power outage, these four programs restarted as desired and have been running correctly but those four programs do not have that autostart ON set.  Is it understandable why they all restarted?

I think I have enough information to setup my program to operate as I want.  I guess to really test it, I will have to manually reboot my ISY to see how the programs behave.  

Link to comment
5 hours ago, Jimini said:

For those two little program fragments that I included earlier, the first had no IF clause, only a THEN which should start each time ISY rebutted.  Is that correct?  It can exist without an IF clause?  

No.  A program can exist without an IF clause, but it won't start unless you manually start it, another program starts it, or you have it set to "run at startup" and the ISY starts up (i.e. is rebooted).  To start by itself, a program must have a trigger in its IF clause.  Pretty much anything you can put in the IF clause will be a trigger with the exception of integer variables.  When you put a state variable in an IF clause, it will only act as a trigger when its value changes.  So for example if you had a program like "IF ProgRunning is 0 Then do stuff", that program would only run when ProgRunning was some other value and then became 0.  So if ProgRunning is set to 0 at startup, that program wouldn't run at startup because the value was already 0. 

5 hours ago, Jimini said:

 In fact, I have four other programs that each start with an IF based upon time of day.  After this recent extended power outage, these four programs restarted as desired

Those program restarted themselves because Time Of Day is a trigger.  So when when the ISY rebooted, it watched those programs until the specified time of day arrived and the ISY started the program.  The existing program that you displayed in your original post would also have eventually restarted itself after the power failure, but not until 8:00 AM.  Your question was how to make the top of the hour a trigger, which if used in your original program, would have restarted it at the next top of the hour instead of waiting until the next 8:00 AM to roll around.

Link to comment

Got it, kclenden.  Thanks for the delineation of what would cause a program to restart.  It is very helpful to get these little details understood.  If this is written in the manual somewhere I missed it.  

I've put together what I think will be my final set of programs for this adventure unless others point out a problem or a more efficient way to accomplishing the goal.  I realize that efficiency of execution or of memory space may not be terribly important for ISY programming but I still don't have a feel for how tight either may be.

I have noticed one thing that may be relevant to that.  When I only had my four little programs that each activated once a day to control lights and wrote no reports to an ISY webpage or email back to me, the dark blue or purple light on my ISY glowed very steady and bright.  Since adding my temperature controlling programs that only operate once per hour, that ISY light flickers a lot pulsing as in time with some data transfers.  I may have left some program artifacts running that I cannot see, but otherwise, it seems odd for this light to be flickering so nearly always.  

In any case, I decided to combine much of what I learned from the above thread and put together a sort of hybrid of several ideas.  The resultant code is here:

Start Top of Hour Clock - [ID 000A][Parent 000D]

If
        
        // No need for an IF clause, the THEN clause must be set to 
        // auto start on startup of ISY, i.e. reboot.
 
 
Then
        
        // Notification for courtesy that ISY has rebooted
        // Then start a loop in 'Find First Top of Hour' program to 
        // find when minutes are zero
 
        Send Notification to 'MY_GROUP' content 'ISY_REBOOTED.NTF'
        $Minutes_of_Hour  = [Current Minute ]
        Run Program 'Find First Top of Hour' (If)
 
Else
   - No Actions - (To add one, press 'Action')
 

Find First Top of Hour - [ID 000C][Parent 000D]

If
        
        // With the ELSE clause, this forms a loop until the first 
        // Top of Hour is found after an ISY reboot.
 
        $Minutes_of_Hour is 0
 
Then
        
        // The first Top of Hour is found
        // Trigger that with an increment to .Top_of_Hour
 
        $.Top_of_Hour += 1
 
Else
        
        // Wait 10 seconds between each test of the minutes on the clock
 
        Wait  20 seconds
        $Minutes_of_Hour  = [Current Minute ]
        Run Program 'Find First Top of Hour' (If)
 

Note Top of Hour - [ID 000B][Parent 000D]

If
        
        // The increment of state variable .Top_of_Hour by 
        // the program 'Find First Top of Hour' or by the 
        // THEN clause below will trigger this program to run.
        // Any change to the state variable will cause this program 
        // to run, but an initial value of zero or greater will insure 
        // that the IF statement passes control to the THEN clause.  
        // Initializing it to 0, will allow it to mark the number of hours 
        // since reboot.
 
        $.Top_of_Hour > 0
 
Then
        
        // Wait one hour before retriggering the IF clause above. 
        // Any other program testing the state variable .Top_of_Hour 
        // will also be tiggered at each top of hour.  
 
        Wait  1 hour 
        $.Top_of_Hour += 1
 
Else
   - No Actions - (To add one, press 'Action')
        

I have not tested it by rebooting ISY as yet, but I tested it by manually starting the program 'Start Top of Hour Clock' and this works fine.  

I decided that rather than keep a program looping every 20 seconds to continuously find the next Top of Hour, I would find the first one and then use Wait 1 hour to find each successive one.  I will need to test over some time to see if this eventually looses too much time with respect to the real top of hour.  I am wondering if once I have at least one other program being triggered by the .Top_of_Hour variable, that other program could start execution before this 'Note Top of Hour' program wakes up and initiates its WAIT 1 hour.  This would delay the start of the 1 hour wait.  Likely that will be less than minutes but perhaps a protocol should be established for each such program being triggered by .Top_of_Hour to issue a 'WAIT 1 second' before doing anything else to assure that the 1 hour wait is started.  That may be over kill but any delay in starting the 1 hour wait will be a cumulative offset.  

I don't know if this will be any more efficient in ISY resources than a continuously running 20 second loop, but I thought this way, I am leaving the efficiency question up to the ISY developers for an efficient 1 hour wait.  

Any comments are welcome as usual.

Link to comment
Start Top of Hour Clock - [ID 000A][Parent 000D][Run at Startup] <-------------
If 
Then
        Send Notification to 'MY_GROUP' content 'ISY_REBOOTED.NTF'
        $Minutes_of_Hour  = [Current Minute ]
        Run Program 'Find First Top of Hour' (If)  <---- only ever calls program once upon power up.
Else
   - No Actions - (To add one, press 'Action')



Find First Top of Hour - [ID 000C][Parent 000D]
If
        $Minutes_of_Hour is 0 
Then
        $.Top_of_Hour += 1  <--- is this a State variable? Most here denote State with "s" prefix
Else
        Wait  20 seconds
        $Minutes_of_Hour  = [Current Minute ]
        Run Program 'Find First Top of Hour' (If) 
 

Note Top of Hour - [ID 000B][Parent 000D]
If
        $.Top_of_Hour > 0     <---- must be State variable to trigger program, Self triggering loop?
Then
        Wait  1 hour 
        $.Top_of_Hour += 1 
Else
   - No Actions - (To add one, press 'Action')Note Top of Hour - [ID 000B][Parent 000D]


An alternate consideration
-could use absolute real time hour above (Not +=1) also $.Top_of_Hour = [Current Hour]
Note Top of Hour - [ID 000B][Parent 000D]
If
Then
        Wait 10 seconds   <------ keep away from jitter point
        Repeat every 1 hour
            $.Top_of_Hour = [Current Hour]  <-----create real time hour variable for usage elsewhere.
Else
    -----
 

Very confusing method for me but looks like it should work if a State variable was the intent. You will always need to kickstart it manually after editing it.

Proofing will be the final test.

Link to comment
3 hours ago, Jimini said:

Any comments are welcome as usual.

A couple things...

  • Based on the copy & paste, you haven't yet set "Start Top Of Hour Clock" to "Run At Startup".
  • In the "Note Top Of Hour" program, I would get rid of the "$.Top_of_Hour > 0" condition and simply put a "Run Program "Note Top Of Hour' (Then)" as the last line after "$.Top_of_Hour += 1".  To me that would be more efficient.
  • Your "$.Top_of_Hour" variable not only denotes each new top of hour, but effectively becomes a count of the number of hours your ISY has been continuously running, with the exception that the first hour could have been anywhere from 0-60 minutes.  So you may as well save it's value into static memory and report the value via the email sent out in the "Start Top Of Hour Clock" program.

As far as the efficiency of a "Wait 20 Seconds" versus a "Wait 1 Hour", the real savings comes in the reduction of lines of code that are being run.  There are 180 twenty second intervals in an hour, so by using the "Wait 1 Hour" you're reducing the number of lines of code executed by a factor of 180.

Here are the programs with my suggestions:

Start Top of Hour Clock - [ID 000A][Parent 000D][Run at startup]

If
        
        // No need for an IF clause, the THEN clause must be set to 
        // auto start on startup of ISY, i.e. reboot.
 
 
Then
        
        // Notification for courtesy that ISY has rebooted
        // Then start a loop in 'Find First Top of Hour' program to 
        // find when minutes are zero
 
        Send Notification to 'MY_GROUP' content 'ISY_REBOOTED.NTF'
        $Minutes_of_Hour  = [Current Minute ]

        // Reset Top_of_Hour after reporting it via Email
        // Initializing it to 0, will allow it to mark the number of hours 
        // since reboot.
        $.Top_of_Hour = 0
        // Save Top_of_Hour to permanent memory 
        $.Top_of_Hour Init to $.Top_of_Hour
        Run Program 'Find First Top of Hour' (If)
 
Else
   - No Actions - (To add one, press 'Action')
 

Find First Top of Hour - [ID 000C][Parent 000D]

If
        
        // With the ELSE clause, this forms a loop until the first 
        // Top of Hour is found after an ISY reboot.
 
        $Minutes_of_Hour is 0
 
Then
        
        // The first Top of Hour is found
        // Trigger that with an increment to .Top_of_Hour
 
        $.Top_of_Hour += 1
        Run Program 'Note Top of Hour' (Then)
 
Else
        
        // Wait 20 seconds between each test of the minutes on the clock
 
        Wait  20 seconds
        $Minutes_of_Hour  = [Current Minute ]
        Run Program 'Find First Top of Hour' (If)
 

Note Top of Hour - [ID 000B][Parent 000D]

If
        
 
Then
        
        // Wait one hour before retriggering the THEN clause above. 
        // Other programs testing the state variable .Top_of_Hour 
        // will also be tiggered at each top of hour.  
 
        Wait  1 hour 
        $.Top_of_Hour += 1
        $.Top_of_Hour Init to $.Top_of_Hour
        Run Program 'Note Top Of Hour' (Then)
 
Else
   - No Actions - (To add one, press 'Action')

 

Link to comment

Thank you for your comments and suggestions, larryllix and kclenden.  I did forget to add to my comments that the variable $.Top_of_Hour must be a state variable, but I did include in my opening comment to the program 'Start Top of Hour Clock' that it must be set to auto start at start up.  Other than that comment, I don't know how I should have indicated that in my listing.  

You are correct that as written the "Top of Hour Clock" must either be kick-started by manually starting its THEN clause or reboot ISY.  The point is that once kick-started it will restart when ISY reboots for some reason. 

Making the variable $.Top_of_Hour a state variable and leaving the 'IF $.Top_of_Hour > 0'  in the program 'Note Top of Hour' is so that other programs, in particular my original program that I want to run at each Top of Hour, will do so, which was my original question to start this thread.  I guess that goal was lost along the way.  

I do now see the purpose of the 'Init To' statement in that it preserves the value of a variable across ISY reboots which can be reported in the email message at startup.  That would be useful.  However, the statement setting it to zero after reporting its value will trigger a start of all programs waiting for a 'Top of Hour', which will produce one extra run of each prior to a real top of hour.  I think that statement needs to be left out and $.Top_of_Hour then contains the number of hours integrated over all ISY reboots with the email reports the trail of how that increments.  Or I guess, I could introduce another integer variable to replace what receives the  'Init To' and what is zeroed after reporting its value in the startup program.  

Question: does that statement '$.Top_of_Hour Init to $.Top_of_Hour' create a trigger for programs waiting for a change of that variable if the variable is a state variable?  I would think not, but just asking to be sure.  

Link to comment
19 minutes ago, Jimini said:

<snipped>

Question: does that statement '$.Top_of_Hour Init to $.Top_of_Hour' create a trigger for programs waiting for a change of that variable if the variable is a state variable?  I would think not, but just asking to be sure.  

No. "Init to" does not affect any triggers. The ROM  "init to" value is copied to the RAM copy for program usage before any programs are released into the wild upon boot up of ISY.  It is an attempt to have ISY continue after a power failure/reboot like nothing happened.

Link to comment

Archived

This topic is now archived and is closed to further replies.


×
×
  • Create New...