Home AMX User Forum AMX General Discussion

Wake up alarm

I'm sure a few people came up with solutions to provide users with a Wake up alarm instead of the regular iphone, clock alarm.
What is your choice of implementation between a full home grown solution and using i!Scheduler?
My main question is how to get a portion of code executing at the time entered by the user...
Besides i!Scheduler, is there any trick to compare against current system time?

Thanks a bunch!

Comments

  • ericmedleyericmedley Posts: 4,177
    I've had a whole host of alarm clock, timers and reminder notices for some time. But I must say I've pretty much turned them off on wireless touch panels. They are just not reliable for this kind of thing.

    I have set them up to do more than just beep to wake you up. You can set up a whole scene of lights coming on, TVs turning on, music, etc.

    And for what it's worth, my wife and I have our own NXT-CV10s that have been our alarm clocks for over 10 years very reliably.
  • Pep_SDPep_SD Posts: 106
    Eric,

    That is exactly what I want to do, turning music or tv on with your favorite channel, lights, shades etc.
    I would use the TP just to select the time and actions to perform, not to actually wake up.
    My question is around the mechanism to use to fire these actions.
    Do you use i!Scheduler or something else of your own?

    My main chalenge is to monitor the time and check it against what. The user selected as a time to wake up.
    I tought about mainline or timeline and did some test with mainline but cannot get the event firing exactly at the second - it reacts kind of wierd... Any recommendation you can share?
  • DHawthorneDHawthorne Posts: 4,584
    You're never going to get exact, to-the-second timing. NetLinx is single-threaded, and interpreted, to boot, and if another process takes a tad too long, it will delay a timer interrupt by that amount. To-the-minute is a more reasonable expectation, but a really busy system can throw it off even that much, though it's rare if the code is reasonably streamlined.

    Having said that, I used to include i-Schedule in every project, but found it so clunky to use and so resource intensive, I gave up on it. I wound up writing my own, and the gist of it is a once-a-second timeline that checks the current date and time on each iteration. I then run that through my list of events, and fire them off according to whatever criteria I coded in, which includes one-time events, once-a day events, etc., and the appropriate resets (for example, clearing a "triggered" flag when the date changes if it's a daily event).

    Some of the things I've done with timed events are thermostat setbacks, panel pop-ups, and wake-up calls via a modem on the phone system. But I am finding the need for this kind of thing less and less prevalent, as people have so many other apps and options.
  • ericmedleyericmedley Posts: 4,177
    Pep_SD wrote: »
    Eric,

    That is exactly what I want to do, turning music or tv on with your favorite channel, lights, shades etc.
    I would use the TP just to select the time and actions to perform, not to actually wake up.
    My question is around the mechanism to use to fire these actions.
    Do you use i!Scheduler or something else of your own?

    My main chalenge is to monitor the time and check it against what. The user selected as a time to wake up.
    I tought about mainline or timeline and did some test with mainline but cannot get the event firing exactly at the second - it reacts kind of wierd... Any recommendation you can share?

    I wrote myown. I convert time to digital. Basically seconds since Jan 1. 2000. Then each event is time stamped. From there it's pretty easy to check and see if you need to do something. I will tell you my time stamp checker only checks for minutes first. Then when it hits on something in a minute it granulated to seconds. Thant way I'm not checking every second. In theory, the processor can easily do seconds but I still like to keep things running efficiently as I can.
  • GregGGregG Posts: 251
    I rolled my own "TimedPresets" module generic for use under the alarm clock module and the HVAC presets module, etc.

    I didn't even try to do anything accurate to the second, in fact, the module does time checks with a 20 second repeating timeline (checks at least 2 times a minute) and is only settable for day, hour, and minute on the triggers.
    DEFINE_VARIABLE
    
    Volatile Long lTimes[1]
    Volatile Integer nPresetTriggered
    
    DEFINE_START
    
    lTimes[1] = 20000
    Timeline_Create(TL_CHECK,lTimes,1,Timeline_Relative,Timeline_Repeat)
    
    DEFINE_EVENT
    
    Timeline_Event[TL_CHECK]
    {
    Stack_Var Integer nPulseTime
    Stack_Var Sinteger snToday,snThisHour,snThisMinute       
    
      // To ensure this event only happens one time during the minute
      If(!nPresetTriggered)
      {
        nPulseTime = GET_PULSE_TIME
        Set_Pulse_Time(600)
        Pulse[nPresetTriggered]
        Set_Pulse_Time(nPulseTime)
      
        //... do stuff here with the time information
        snToday = Day_Of_Week(LDATE)
        snThisHour = Time_to_Hour(TIME)
        snThisMinute = Time_to_Minute(TIME)
        If((snThisHour=8) AND (snThisMinute=0) AND (snToday = 2))
        {
          // trigger 8am alarm actions for Monday
        }
      }
    }
    

    And I definitely concur with Eric's suggestion that wifi panels not be used as alarm output (like beeping the panel or something). It's ok to have the UI for setting the alarm on a wifi panel as long as it is doing something else like house audio for the waking sounds.
  • JasonSJasonS Posts: 229
    DHawthorne wrote:
    You're never going to get exact, to-the-second timing. NetLinx is single-threaded, and interpreted, to boot, and if another process takes a tad too long, it will delay a timer interrupt by that amount. To-the-minute is a more reasonable expectation, but a really busy system can throw it off even that much, though it's rare if the code is reasonably streamlined.

    I'm sorry but I utterly disagree with this statement. To the second timing is easy if you use Mainline. Mainline runs hundreds to thousands of times a second, there was a thread about this awhile back. I use mainline for scheduled events whenever I need to do them, it works great. Here is a pseudo code example of how I do it.
    DEFINE_PROGRAM
    
        if (Scheduled_Events_Enabled)
        {
            WAIT 3
            {
                Check_Second = TIME_TO_SECOND(TIME)
                if (Current_Second <> Check_Second)
                {
                    Current_Second = Check_Second
                    Check_Minute = TIME_TO_MINUTE(TIME)
                    if (Current_Minute <> Check_Minute)
                    {
                        Current_Minute == Check_Minute
                        //and so on
                    }
                }
                //Check for Scheduled events Here using Current_Second, Current_Minute, etc.
            }
        }
    //END of Mainline
    

    This code will execute approx. 3 times a second, and it will only check against the schedule once a second. There are no guarantees but in my experience it has never failed to run very accurately. I have used this code on many projects including extremely large projects with very demanding clients.

    I have had issues with long running timelines in the past, and they don't work exactly the way they should. In particular I am referring to the inability to use arrays of timelines in the timeline event, the fact that timeline events have to be the last code in your DEFINE_EVENTS section or none of the code after them runs, and the erratic behavior when using variables for TIMELINE_IDs. I will use them on occasion but only when they don't run for extended amounts of time or they are re-created every time they need to be used. I much prefer using GET_TIMER, adding an offset in 1/10 seconds and checking against it in mainline, much more accurate and reliable in my experience than timelines.
  • the8thstthe8thst Posts: 470
    I've had good luck with using compare_string() instead of if(time == time) in timed events. This example is only to the minute, but would be very easy to change to check by the second.
    DEFINE_VARIABLE
    
    	volatile char cVstatReInitTime[8] = '03:23:0?'
    DEFINE_PROGRAM
    
    	wait 45 'vstat_time_compare_wait' {
    		IF (compare_string(time, cVstatReInitTime)) {
    			CANCEL_WAIT 'REINIT VSTATS'
    			
    			WAIT 50 'REINIT VSTATS' {
    				HVAC_Auto_Refresh()
    			}
    		}
    	}
    
  • GregGGregG Posts: 251
    JasonS wrote: »
    I have had issues with long running timelines in the past, and they don't work exactly the way they should. In particular I am referring to the inability to use arrays of timelines in the timeline event, the fact that timeline events have to be the last code in your DEFINE_EVENTS section or none of the code after them runs

    I don't use mainline, all my code is event driven. So if long running timeline events didn't work in a predictable manner, then my way of doing feedback could not have served me very well for the past 10 or so years. I use a permanently running timeline for feedback, and add another copy of the timeline event directly after every button event that needs feedback.
    DEFINE_START
    
    lTimes[1]=200
    TImeline_Start(TL_FEEDBACK,lTimes,1,TIMELINE_RELATIVE,TIMELINE_REPEAT)
    
    DEFINE_EVENT
    
    Button_Event[tvTP,1]
    {
      Push: nVal1=!nVal1
    }
    Timeline_Event[TL_FEEDBACK]
    {
      [tvTP,1] = nVal1
    }
    
    Button_Event[tvTP,2]
    {
      Push: nVal2=!nVal2
    }
    Timeline_Event[TL_FEEDBACK]
    {
      [tvTP,2] = nVal2
    }
    

    I'm not happy about the arrays of timelines thing, but either sequential constants or an indexing array lookup can work around that.
  • ericmedleyericmedley Posts: 4,177
    I think the whole mainline debate finally came around full-circle last year. For years we were told to avoid mainline and go totally event-driven. Then last year AMX engineering (or someone ) came out on the forum explaining that there really was no big problem using mainline for feedback and whatnot. I'd look up the thread but I don't have the time or patience to suffer through the forum's search abilities. (or lack thereof)

    I personally don't use it and prefer event driven programming. I use timelines all the time, both long running, repeating, etc... And have never had an issue with them. For the most part if I find an issue it ends up being in the handling of them which is not an issue of the timelines themselves. I would also note that I usually don't use the timeline event handlers and prefer to do that kind of thing myself. ( things like timeline.sequence and so forth). I find that if I just use a timeline to count time I avoid a lot f the strangeness we see sometimes.

    Even though there's nothing 'wrong' with mainline I don't think it's necessary to check the time or some condition 5000+ times a second to see if I can do something. If you're going to do that then why not just run a timeline checking twice or three times a second. You'll get the granularity you need to stay right on the second tick without a whole lot of overhead.

    But like I said, there is nothing really wrong with it.
  • JasonSJasonS Posts: 229
    ericmedley wrote:
    Even though there's nothing 'wrong' with mainline I don't think it's necessary to check the time or some condition 5000+ times a second to see if I can do something.

    If you actually look at the code you will see that it only checks if the second value has changed 3 times a second. Time comparisons only happen once a second. Not to mention that this is a purely hypothetical instance where Pep_SD asked about the possibility of second accuracy, which is clearly not only possible but easy to accomplish in several ways. Except for a rare exception I don't see the need to schedule anything to second accuracy.
    ericmedley wrote:
    I personally don't use it and prefer event driven programming. I use timelines all the time, both long running, repeating, etc... And have never had an issue with them. For the most part if I find an issue it ends up being in the handling of them which is not an issue of the timelines themselves.
    Different strokes for different folks. The way I code for AMX is based on an extensive amount of experimentation and experience. I use what I've found to work well. I was on the "Event driven" thing for awhile, but personally I felt it was limiting.

    The point is that we have presented several different options for Pep_SD to try, and he can pick what he likes best, or come up with his own way to do it.
  • ericmedleyericmedley Posts: 4,177
    JasonS wrote: »
    If you actually look at the code you will see that it only checks if the second value has changed 3 times a second. Time comparisons only happen once a second. Not to mention that this is a purely hypothetical instance where Pep_SD asked about the possibility of second accuracy, which is clearly not only possible but easy to accomplish in several ways. Except for a rare exception I don't see the need to schedule anything to second accuracy.


    Different strokes for different folks. The way I code for AMX is based on an extensive amount of experimentation and experience. I use what I've found to work well. I was on the "Event driven" thing for awhile, but personally I felt it was limiting.

    The point is that we have presented several different options for Pep_SD to try, and he can pick what he likes best, or come up with his own way to do it.

    well, I actually did look at the code.
    DEFINE_PROGRAM
    
        if (Scheduled_Events_Enabled)
        {
            WAIT 3
            {
    

    it checks for the value of Scheduled_Events_Enabled every pass through mainline. Then it checks to see of the wait is done. That's two things to check each pass. It's the stuff inside the barces that enclose the code within the wait that don't fire each pass.
  • JasonSJasonS Posts: 229
    Yes, you are correct it will compare the if and the wait everytime mainline executes, so what?
    If you manage to write a DEFINE_PROGRAM section that takes more than one whole second to run (> 400,000,000 machine instructions on a current master) then you can actually stop processing any events.
    Granted there is some overhead associated with the OS using some of those instructions, but the processor is not doing anything most of the time. The amount of time it takes to compare an if and a wait is insignificant, plus mainline does not interfere with event processing unless it is very poorly coded, ie. loops in mainline that change a varaible outside the context of a wait.
    The event processing that previously could occur only through mainline code can now be handled through code in the DEFINE_EVENT section. This provides a more efficient mechanism for processing events in that mainline does not have to be traversed to process a single I/O request. A handler can be defined for processing device-specific events as well as providing feedback for the device initiating the event notification. If a handler is present, mainline will not be called to process the event; the handler is called instead. Once the handler completes its execution, the system is ready to process the next input message. When no more messages are pending, mainline is run. In effect, mainline becomes an idle time process.

    I use this code regularly, it has no significant effect on execution speed. There are many correct ways to do the same thing. Use timelines if that is what you like, it won't bother me. I personally use a different method. There is no harm in keeping an open mind and exploring other solutions, if you feel that your AMX processor is to important to be bothered with checking the state of a variable or two when it has nothing else to do, so be it.
  • ericmedleyericmedley Posts: 4,177
    JasonS wrote: »
    Yes, you are correct it will compare the if and the wait everytime mainline executes, so what?

    Granted there is some overhead associated with the OS using some of those instructions, but the processor is not doing anything most of the time. The amount of time it takes to compare an if and a wait is insignificant, plus mainline does not interfere with event processing unless it is very poorly coded, ie. loops in mainline that change a varaible outside the context of a wait.



    I use this code regularly, it has no significant effect on execution speed. There are many correct ways to do the same thing. Use timelines if that is what you like, it won't bother me. I personally use a different method. There is no harm in keeping an open mind and exploring other solutions, if you feel that your AMX processor is to important to be bothered with checking the state of a variable or two when it has nothing else to do, so be it.

    I'm not calling your method into question. I believe you'll see that I made the very point you're clearly being so defensive about. There's nothing wrong with your methhod. Have a nice time on the forum.
  • JasonSJasonS Posts: 229
    Please excuse me for expressing my opinion, with an attempt at light hearted humor, it won't happen again sir.
Sign In or Register to comment.