Jump to content

Logic is not working (or my logic is off)


CPrince

Recommended Posts

This is a 2 part program.  The first part is to turn lights on shortly before sunrise but not before a certain time.  This parts works (thanks @MrBill)  The second part is the days I do not want it to run.  I have predefined variables for the days I do not want the lights to come on using Julian dates. IToday is the current day.  I have a program to increment the date at midnight.  I will pull from the Node Server ISY time data soon.   

I have upgraded to 5.3.0 and pulled and deactivated the Zwave module.

image.png.f114aa05c718f9be14c9748fd6ee217c.png

Atrium Lights On AM - [ID 005D][Parent 0063]

If
        (
             On Mon, Tue, Wed, Thu, Fri
             From    Sunrise - 45 minutes
             For      2 hours and 30 minutes 
         And On Mon, Tue, Wed, Thu, Fri
             From     6:45:00AM
             For      2 hours and 30 minutes 
        )
    And (
             $iToday is not $iNewYear
          Or $iToday is not $iMemorial
          Or $iToday is not $iJuly4
          Or $iToday is not $iLaborDay
          Or $iToday is not $iThanksgiving
          Or $iToday is not $iChristmas
          Or $iToday is not $iFloat
        )
 
Then
        Set 'Atrium / Atrium Lights' On
 
Else
   - No Actions - (To add one, press 'Action')
 

 

I am probably missing something stupid like set of (), but I can't find it.

 

Link to comment

I think you want these to be joined with AND

   $iToday is not $iNewYear
          Or $iToday is not $iMemorial
          Or $iToday is not $iJuly4
          Or $iToday is not $iLaborDay
          Or $iToday is not $iThanksgiving
          Or $iToday is not $iChristmas
          Or $iToday is not $iFloat

lets assume $iToday = 329 (i.e. thanksgiving) if we make a truth table out of the statement above it is

   (True

or True

Or True

or True

or False

or True

or True)

which results in True

on the other hand, joined with AND you would get a false on thankgiving which would result in the ( False) for the overall statement.  On a day not listed all would be True. 

-----

All that said... I'm going to suggest a better approach....

Add this program from @kclenden...

-- then since you're wanting to use dates as filters you would want to use the $i____ version of the variables in your If statement.  Use the $s... version of the variables when you want to Trigger the IF statement, use the $i.. version of the variables when you want to filter of stop the running of an IF statement.

Note: thanksgiving is the 4th Thursday of November or when ($iISY.MonthOfYear = 11 AND $iISY.WeekOfMonth = 4 AND $iISY.DayOfWeek = 4 )

----

Actually I'm going to repaste @kclenden's program with a minor change:
 

Set Date Variables - [ID 0104][Parent 0126]

If
        Time is 12:00:00AM
 
Then
        
        // Determine Day of Week
 
        $sISY.DayOfWeek  = [Current Day of Week]
        $sISY.DayOfWeek Init To $sISY.DayOfWeek
        $iISY.DayOfWeek  = $sISY.DayOfWeek
        $iISY.DayOfWeek Init To $sISY.DayOfWeek
        
        // Determine the Month
        //
 
        $sISY.DayOfMonth  = [Current Day of Month]
        $sISY.DayOfMonth Init To $sISY.DayOfMonth
        $iISY.DayOfMonth  = $sISY.DayOfMonth
        $iISY.DayOfMonth Init To $sISY.DayOfMonth
        
        // Determine the Month of the Year
        //
 
        $sISY.MonthOfYear  = [Current Month (Jan=1, Feb=2, etc.)]
        $sISY.MonthOfYear Init To $sISY.MonthOfYear
        $iISY.MonthOfYear  = $sISY.MonthOfYear
        $iISY.MonthOfYear Init To $sISY.MonthOfYear
        
        // Determine the Week of the Month
 
        $iISY.WeekOfMonth  = $sISY.DayOfMonth
        $iISY.WeekOfMonth -= 1
        $iISY.WeekOfMonth /= 7
        $iISY.WeekOfMonth += 1
        $iISY.WeekOfMonth Init To $iISY.WeekOfMonth
        $sISY.WeekOfMonth  = $iISY.WeekOfMonth
        $sISY.WeekOfMonth Init To $iISY.WeekOfMonth
        
        // Create Month.Day Combo
 
        $iISY.Date_Scratchpad  = $iISY.DayOfMonth
        $iISY.Date_Scratchpad /= 100
        $iISY.Date_Scratchpad += $iISY.MonthOfYear
        $iISY.MMDD  = $iISY.Date_Scratchpad
        $iISY.MMDD Init To $iISY.Date_Scratchpad
        $sISY.MMDD  = $iISY.Date_Scratchpad
        $sISY.MMDD Init To $iISY.Date_Scratchpad
 
Else
   - No Actions - (To add one, press 'Action')

In my version "Week of the Month" does the inline scrathpad calculations using the $i or interger version of the variable.  In the original version the scratchpad calculations were done with the $s or state variable.  Since anytime a state variable changes it will run IF statements the original resulted in a weird occurrence that was related to thanksgiving.  (I'd actually made two mistakes but discovered the improvement documented here while tracking the cause down.)


 

 

 

Link to comment

@MrBillThank you.  It took a lot to digest your suggestion.  That in turn made me think more.  Plus the fact that I unplugged an Insteon module that crumbled in my hand and trying to find a replacement.  Not easy.  So now I have a logical calendar in the ISY.  We have fixed holidays (1/1. 7/4, 12/25) and we have calculated holidays (Thanksgiving, Labor day and Memorial Day).  So why not create a new program with a new variable $iException right after we run the program "Set Date Valuables"  Then instead of calculating this in every sub-program that depends on special days, I could just check $iException.  This is much easier.  Now I have to clean up all the old code.

Link to comment
54 minutes ago, CPrince said:

So why not create a new program with a new variable $iException right after we run the program "Set Date Valuables"  Then instead of calculating this in every sub-program that depends on special days, I could just check $iException.  This is much easier.  Now I have to clean up all the old code.

Sounds like you already have it done, but if you need help or suggestions just post what you're working on.

Of course you can name a variable anything you want, but I might call it $iHoliday instead of $iException.   If you haven't discovered it yet, the ISY is pretty cool when it comes to renaming a variable... All you have to do is rename it, the ISY changes its everywhere it's used.

Link to comment
On 11/30/2021 at 12:49 PM, MrBill said:

So why not create a new program with a new variable $iException right after we run the program

Oh yea, that was easy. I wrote a routine last night and it failed miserably this morning.  This morning plus 5 hours later I think I got it!  I did not want to ask the forum as I need to learn this logic better.   I chose Exception over Holiday as Holiday is too cliche.  Plus I am retired and everyday is a holiday.  Note, 11.01 is my test date.  Maybe I overdid it with ()'s, but it seems to work.

Set Exception Variable - [ID 006A][Parent 0001]

If
        Time is 12:03:00AM
    And (
             $iISY.MonthOfYear is not 11
          Or $iISY.WeekOfMonth is not 4
          Or $iISY.DayOfWeek is not 4
        )
    And (
             $iISY.MonthOfYear is not 9
          Or $iISY.WeekOfMonth is not 1
          Or $iISY.DayOfWeek is not 1
        )
    And (
             $iISY.MonthOfYear is not 5
          Or $iISY.WeekOfMonth is not 5
          Or $iISY.DayOfWeek is not 1
        )
    And (
             $iISY.MMDD is not 1.01
        )
    And (
             $iISY.MMDD is not 7.04
        )
    And (
             $iISY.MMDD is not 12.25
        )
    And (
             $iISY.MMDD is not 11.01
        )
 
Then
        $iException Init To 0
        $iException  = 0
 
Else
        $iException Init To 1
        $iException  = 1
 

 

Link to comment
Oh yea, that was easy. I wrote a routine last night and it failed miserably this morning.  This morning plus 5 hours later I think I got it!  I did not want to ask the forum as I need to learn this logic better.   I chose Exception over Holiday as Holiday is too cliche.  Plus I am retired and everyday is a holiday.  Note, 11.01 is my test date.  Maybe I overdid it with ()'s, but it seems to work.
Set Exception Variable - [iD 006A][Parent 0001]
If
        Time is 12:03:00AM
    And (
             $iISY.MonthOfYear is not 11
          Or $iISY.WeekOfMonth is not 4
          Or $iISY.DayOfWeek is not 4
        )
    And (
             $iISY.MonthOfYear is not 9
          Or $iISY.WeekOfMonth is not 1
          Or $iISY.DayOfWeek is not 1
        )
    And (
             $iISY.MonthOfYear is not 5
          Or $iISY.WeekOfMonth is not 5
          Or $iISY.DayOfWeek is not 1
        )
    And (
             $iISY.MMDD is not 1.01
        )
    And (
             $iISY.MMDD is not 7.04
        )
    And (
             $iISY.MMDD is not 12.25
        )
    And (
             $iISY.MMDD is not 11.01
        )
 
Then
        $iException Init To 0
        $iException  = 0
 
Else
        $iException Init To 1
        $iException  = 1
 
 
Looks like you have a good grip on D'Morgan's theory but the reverse logic appears to make it appear more complicated.

Good usage of parenthesis IMHO as they are also for readability, not just the Boolean arithmetic.

Sent from my SM-G781W using Tapatalk

Link to comment

At first I didn't think your method would work... but after trying values in my head for awhile, it might actually.... 

I'd write it with positive rather than Not (or negative) logic tho...

If
        (
             $iISY.MonthOfYear is 11
          And $iISY.WeekOfMonth is 4
          And $iISY.DayOfWeek is 4
        )
    Or (
             $iISY.MonthOfYear is 9
          And $iISY.WeekOfMonth is 1
          And $iISY.DayOfWeek is 1
        )
    Or (
             $iISY.MonthOfYear is 5
          And $iISY.WeekOfMonth is 5
          And $iISY.DayOfWeek is 1
        )
    OR (
             $iISY.MMDD is 1.01
        )
    Or (
             $iISY.MMDD is 7.04
        )
    Or (
             $iISY.MMDD is 12.25
        )
    Or (
             $iISY.MMDD is 11.01
        )
 
Then
        $iException Init To 1
        $iException  = 1
 
Else
        $iException Init To 0
        $iException  = 0

Note that I also removed the Time the program runs from the top of the If statement, that's because we don't actually need it.  (being able to remove it make the parenthesis easier too, which is how you likely got caught up in using negative logic.

So how do we get the program to Run?  Two options to choose from:

  1. Run it as the last statement of the Set Date Variable program  --or--
  2. Note that the last variable set in the Set Date Variable setting program is $sISY.MMDD = $iISY.Date_Scratchpad which is a State variable.  (since it's the LAST state variable set by the program, the change to the value indicates to the ISY that all the other values above it have already been set for today.  We would only want to use this method if the last thing the program did was set a State variable AND the value of that variable state changed (each time the program ran).

Either of these are great options.

So to talk thru the first option, we would probably Disable the Date Exception program, although since it's all integer variables, it would never run on its own.  The key to "disabling a program" is that it only disables the IF statement from automatically triggering the program.... A disabled program will still run if it's called by another program...

So to implement this we would add the statement:

       Run Program 'Exception Checker' (if)

as the last line to the Set Date Variables program.   Then we would right click and the Exception Checker in the tree and select Disable.  It will still run everyday because it's being called as the last thing done by Set Date Variables.

 

Talking thru the second option.

Lets make one tiny change to the exception checker:

If
        (
             $iISY.MonthOfYear is 11
          And $iISY.WeekOfMonth is 4
          And $iISY.DayOfWeek is 4
        )
    Or (
             $iISY.MonthOfYear is 9
          And $iISY.WeekOfMonth is 1
          And $iISY.DayOfWeek is 1
        )
    Or (
             $iISY.MonthOfYear is 5
          And $iISY.WeekOfMonth is 5
          And $iISY.DayOfWeek is 1
        )
    OR (
             $sISY.MMDD is 1.01
        )
    Or (
             $iISY.MMDD is 7.04
        )
    Or (
             $iISY.MMDD is 12.25
        )
    Or (
             $iISY.MMDD is not 11.01
        )
 
Then
        $iException Init To 1
        $iException  = 1
 
Else
        $iException Init To 0
        $iException  = 0

Note the RED line, it's the ONLY thing I changed from above.

Since I changed one single variable to the State Variable this program will now run EVERYTIME that value Changes.  So everytime the Set Date Variables program changes that value, which is a value that does change daily, it will cause this program to fire and the entire IF will be evaluated, even tho all the other variables are integer.

What would I do?

If I used the second method I would reorder the OR's to chronological as the "exceptions" occur during the year.  That readability change would put $sISY.MMDD is 1.01 at the top, and it's easy to spot the "trigger" variable. 

What I would actually do tho is use the first method, disable the Exception Checker program, add a comment to it that it's "run by Set Date Variables" and then add

       Run Program 'Exception Checker' (if)

to the end of the Set Date Variables program.

I only included option 2 as a teaching tool about state variables, but it is a valid option.

-----

A note on disabling programs:  As you learn more about writing ISY programs you will find many uses for disabled programs.  Disabled is actually a tool for when programs run, it's not just a feature that was included for testing.  Another user or two were having trouble with disabled programs becoming enabled tho, so i took that as a queue....

I now have a program called "Disabled-intentionally"  that has the run as startup attribute set

Disabled-Intentionally - [ID 013A][Parent 0001][Run At Startup]

If
   - No Conditions - (To add one, press 'Schedule' or 'Condition')
 
Then
        Disable Program 'SetpointAdjust-DNchevron'
        Disable Program 'SetpointAdjust-UPchevron'

            (abridged for posting..... every program intentionally disabled is listed)
 
Else
   - No Actions - (To add one, press 'Action')

So every time the ISY is rebooted this program runs and makes certain things that are supposed to be disabled actually are disabled.

Link to comment
14 minutes ago, larryllix said:

To further simplify, many of the Or brackets can now be removed and the multiple condition date logics use the same technique as the single line filters to end up with a 7 or 8 line program.

Yea, I left them for clarity (and because I'm lazy and didn't want to redo them all---it's easier to just copy and paste ?)  Like you tho, I would remove them.

Link to comment

Archived

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


  • Recently Browsing

    • No registered users viewing this page.
  • Forum Statistics

    • Total Topics
      36.9k
    • Total Posts
      370.2k
×
×
  • Create New...