Example #1
0
    def __proc_command(self):
        """
        Called when it is time to execute another command. This function
        simply returns if the queue is empty. Otherwise it pops the next
        command, executes that command, and then sets a Timer to go off the
        given number of milliseconds and call __proc_command again to process
        the next command.
        """
        # No more commands
        if self.commands.empty():
            self.timer = None
            return

        # Pop the next command and run it
        cmd = self.commands.get()
        funct = cmd[1]
        before = DateTime.now().millis
        funct()
        after = DateTime.now().millis

        # Calculate how long to sleep
        delta = after - before
        pause = to_datetime(cmd[0])
        trigger_time = to_datetime(cmd[0]).minusMillis(delta)

        # Create/reschedule the Timer
        if not self.timer:
            self.timer = ScriptExecution.createTimer(trigger_time,
                                                     self.__proc_command)
        else:
            self.timer.reschedule(trigger_time)
def defer(target, value, when, log, is_command=True):
    """
    Use this function to schedule a command to be sent to an Item at the
    specified time or after the speficied delay. If the passed in time or delay
    ends up in the past, the command is sent immediately.
    Arguments:
        - target: Item name to send the command to
        - value: the command to send the Item
        - when: at what time to delay to action until, see to_datetime in the timer_utils library
        - is_command: whether to send value to target as an update or command,
        defaults to True
        - log: logger passed in from the Rule
    """

    trigger_time = to_datetime(when, log)

    if not trigger_time:
        log.error(
            "Cannot schedule a deferred action, {} is not a valid date time or duration"
            .format(when))

    # If trigger_time is in the past, schedule for now
    if trigger_time.isBefore(DateTime.now()):
        trigger_time = DateTime.now()

    # Schedule the timer
    func = lambda: timer_body(target, value, is_command, when, log)
    flap = lambda: log.debug(
        "there is already a timer set for {}, rescheduling".format(target))
    timers.check(target,
                 trigger_time,
                 function=func,
                 flapping_function=flap,
                 reschedule=True)
    def __expired(self):
        """Called when the timer expired, reschedules if necessary"""

        when = self.function()
        if when:
            dt = to_datetime(when)
            self.timer = ScriptExecution.createTimer(dt, self.__expired)
Example #4
0
    def check(self,
              key,
              when,
              function=None,
              flapping_function=None,
              reschedule=False):
        """Call to check whether a key has a Timer. If no Timer exists, creates
        a new timer to run the passed in function. If a Timer exists, reschedule
        it if reschedule is True and if a flapping_function was passed, run it.
        Arguments:
            - key: The key to set a Timer for.
            - when: The time for when the timer should go off. Supports:
                - DateTime objects
                - ISO 8601 formatted Strings
                - Python int, treated as number of seconds into the future
                - DecimalType, PercentType, or QuantityType (intValue() is
                called), treated as number of seconds into the future
                - Duration string of the format Xd Xh Xm Xs where:
                    - d: days
                    - h: hours
                    - m: minutes
                    - s: seconds
                    - X: integer or floating point number for the amount
                e.g. 1h3s represents one hour and three seconds
            - function: Optional function to call when the Timer expires
            - flapping_function: Optional function to call if the key already
            has a Timer running. Defaults to None.
            - reschedule: Optional flag that causes the Timer to be rescheduled
            when the key already has a Timer. Defaults to False.
        """

        timeout = to_datetime(when)
        TimerMgr_logger.debug("timeout is: " + str(timeout))
        # Timer exists: if the reschedule flag is set, reschedule it, otherwise
        # cancel it. If a flapping function was passed to us, call the flapping
        # function.
        if key in self.timers:
            if reschedule:
                self.timers[key]['timer'].reschedule(timeout)
                TimerMgr_logger.debug("rescheduling timer for: " + str(key))
            else:
                self.cancel(key)
                TimerMgr_logger.debug("Timer cancelled for: " + str(key))
            if flapping_function:
                flapping_function()
                TimerMgr_logger.debug("Running flapping function for: " +
                                      str(key))

        # No timer exists, create the Timer
        else:
            TimerMgr_logger.debug("Creating timer for: " + str(key))
            timer = ScriptExecution.createTimer(
                timeout, lambda: self.__not_flapping(key))
            self.timers[key] = {
                'timer': timer,
                'flapping': flapping_function,
                'not_flapping': function if function else self.__noop
            }
            TimerMgr_logger.debug("Timer created: " + str(self.timers[key]))
    def run(self, func, when):
        """If it has been long enough since the last time that run was called,
        execute the passed in func. Otherwise ignore the call.
        Arguments:
            - func: The lambda or function to call if allowed.
            - when: When the rate limit will expire. Can be a DateTime type
            object, a number which is treated as seconds, or a duration string
            (e.g. 5m 2.5s), or an ISO 8601 formatted date string. See time_utils
            for details
        """

        now = DateTime().now()
        if now.isAfter(self.until):
            self.until = to_datetime(when)
            func()
    def __init__(self, function, when=None):
        """Initializes and kicks off the looping timer.

        Arguments:
            - function: The function to call when the timer goes off. The
            function must return the time for the next time the timer should run
            (see when below). If None is returned the timer will not be
            rescheduled.
            - when: Optional time when to kick off the first call to function.
            It can be any of the forms supported by to_datetime in time_utils
            (e.g. "1s"). If None is passed the lambda will be called immediately.
        """

        self.function = function
        self.timer = None

        if not when:
            self.__expired()
        else:
            self.timer = ScriptExecution.createTimer(to_datetime(when),
                                                     self.__expired)
Example #7
0
    def __init__(self, log, time, func, count_item):
        """Initializes the CountdownTimer Object and starts the Timer running.
        Arguments:
            - log: The logger from the Rule that created the Timer.
            - time: The DateTime when the Timer should expire.
            - func: The function or lambda to call when the Timer expires.
            - count_item: The name of the Item to update with the amount of time
            until the Timer expires.
        """
        self.log = log
        self.func = func
        self.count_item = count_item
        self.timer = None
        self.start = to_python_datetime(DateTime().now())

        try:
            self.end_time = to_python_datetime(to_datetime(time))
        except TypeError:
            self.log.error("Time is not a recognized DateTime type")
            return

        self.time_left = self.end_time - self.start
        self.__iterate__()
                    str(today_ZonedDateTime.toLocalTime()))

    #Test other format
    test_dict = {
        'integer: ': int(5000),
        'duration: ': "5s",
        'Decimal type: ': DecimalType(5000),
        #'Percent type: ': PercentType(100),
        'Quantity Type: ': QuantityType('5000ms'),
        'ISO 8601 format': DateTime().now().plusSeconds(5).toString()
    }
    #Test other format to Joda
    for keys in test_dict:
        log.info("Checking " + keys + " to Joda DateTime")
        assert abs(seconds_between(ZonedDateTime.now().plus(5000, ChronoUnit.MILLIS),
                               to_datetime(test_dict[keys], log = log))) < 1, \
                               "failed to return a datetime with offset of {} from {}" \
                               .format(str(test_dict[keys]),str(keys))

    #Test other format to python
    test_dict['ISO 8601 format'] = DateTime().now().plusSeconds(5).toString()
    for keys in test_dict:
        log.info("Checking " + keys + " to Python datetime")
        assert abs(seconds_between(ZonedDateTime.now().plus(5000, ChronoUnit.MILLIS),
                               to_datetime(test_dict[keys], output='Python', log = log))) < 1, \
                               "failed to return a datetime with offset of {} from {}" \
                               .format(str(test_dict[keys]),str(keys))

    #Test other format to Java
    test_dict['ISO 8601 format'] = DateTime().now().plusSeconds(5).toString()
    for keys in test_dict: