Node red: how to make inject fire at given seconds

2019-09-15 10:37发布

问题:

Is it possible to make an inject node that fires every 5 seconds, but not depending on deployment, instead in a fixed time grid.

For example, an inject node with a 5 second interval would fire at hh:mm:08, hh:mm:13, hh:mm:18 etc. when deployed at hh:mm:03.

Is there a way to delay it so that messages are sent exactly(*) at hh:mm:05, hh:mm:10, hh:mm:15 no matter in which second it was deployed?

A possible solution would be to set the repeat interval to 1 second, and use a function node to only pass the appropriate messages (i.e. the first message arriving after a multiple-of-5secs-timestamp), but maybe there is a better way to archive that.

(*) within the limits of the machine, of course

回答1:

Not at the moment.

The inject node uses the cron scheduling engine under the covers for the the "Interval between times" mode, but cron only has minute level granularity.

A 1 second inject rate and a filter may be the only option.



回答2:

Eventually, I created a node that does that... I might create a NPM package later, right now here is the source to install it as a local node:

interval-timer.js:

module.exports = function(RED) {
    function IntervalTimerNode(config) {
        RED.nodes.createNode(this,config);
        var node = this;
        var interval = config.interval;
        var timer;

        var timeHandler = function() {
            node.send({payload: config.payload || Date.now()});
            timer = setTimeout(timeHandler, interval - (Date.now() %interval));  // setInterval apparently has a considerable drift, so we use setTimeout to stay within the time grid as much as possible
        };

        timer = setTimeout(timeHandler, interval - (Date.now() %interval));        

        node.on('close', function() {
            clearTimeout(timer);
        });
    }

    RED.nodes.registerType("interval-timer", IntervalTimerNode);
}

interval-timer.html:

<script type="text/javascript">
    RED.nodes.registerType('interval-timer',{
        category: 'input',
        color: '#a6bbcf',
        defaults: {
            interval: {value:5000},
            payload: {value: ""},
            name: {value:""}
        },
        inputs:0,
        outputs:1,
        icon: "timer.png",
        label: function() {
            return this.name||"interval-timer";
        }
    });
</script>

<script type="text/x-red" data-template-name="interval-timer">
    <div class="form-row">
        <label for="node-input-interval"><i class="icon-repeat"></i> Interval [ms]</label>
        <input type="number" id="node-input-interval">
    </div>
    <div class="form-row">
        <label for="node-input-payload"><i class="icon-envelope"></i> Payload (defaults to current timestamp)</label>
        <input type="text" id="node-input-payload" placeholder="Payload">
    </div>
    <div class="form-row">
        <label for="node-input-name"><i class="icon-tag"></i> Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
    </div>
</script>

<script type="text/x-red" data-help-name="interval-timer">
    <p>A interval timer that fires at multiples of the given interval, measured from Jan 1 1970</p>
</script>


标签: node-red