Node-red-contrib-dsm question


#1

This is an awsome node, i'm really enjoying the contex storage example to monitor some real world machine running time . But pushing things a little bit further i'd like to modify the rising edge counter to be persisent as well. I have a payload from a counter that i would like to persist across restarts. any ideas anyone?


#2

you want to modify the rising edge counter within the node? If that’s the case the best bet as it is a contrib node is to open a discussion with the node author.
The best place for that is usually the nodes github page ( a link is generally avaialable from the nodes page on flows.nodered.org)

If you mean outside of node-red read the blog entry on the latest release about persistent storage.


#3

@jupiter8: There are two ways to do it:

  1. Store the counter in a context variable, see persist across restarts
  2. Set the dsm configuration with an inject node:

counter

Note: The inject node is only used once to define the configuration (or if you need to modify it).

Flow:

[{"id":"f18070e.d1f739","type":"dsm","z":"6ff0723.8c6b78c","name":"rising-edge counter","sm_config":"","x":380,"y":1200,"wires":[["581f1472.02c33c"]]},{"id":"6faa5214.722d9c","type":"inject","z":"6ff0723.8c6b78c","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":1240,"wires":[["f18070e.d1f739"]]},{"id":"581f1472.02c33c","type":"debug","z":"6ff0723.8c6b78c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":570,"y":1200,"wires":[]},{"id":"cf54e77.7332618","type":"inject","z":"6ff0723.8c6b78c","name":"","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":1200,"wires":[["f18070e.d1f739"]]},{"id":"ca10673e.2a1e28","type":"inject","z":"6ff0723.8c6b78c","name":"reset counter","topic":"reset","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":1160,"wires":[["f18070e.d1f739"]]},{"id":"98a31f23.6ae47","type":"inject","z":"6ff0723.8c6b78c","name":"set","topic":"set","payload":"{     \"data\": {         \"counter\": 0     }, \t\"methods\": { \t    \"reset\": \"sm.data.counter = 0;\", \t    \"onTransition\": [ \t        \"if (msg.payload === 1) {\",             \"   sm.data.counter++;\",             \"   msg.payload = sm.data.counter;\",             \"   output = true;\",             \"}\"         ], \t    \"status\": { \t        \"fill\": \"blue\",             \"shape\": \"dot\",             \"text\": {                 \"get\": \"sm.data.counter;\"             }         } \t} }","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":1120,"wires":[["f18070e.d1f739"]]}]

@ukmoose:

This isn't an issue but a question, so here is the right place to ask. You may also open an issue on github if you like, no problems for me.


#4

@cflurin:

Works a treat, thank you very much.


#5

@cflurin

And by the way, how can i format the ouput of the "operating time" flow in hours min sec like a normal hour meter on a machine? I've searched for a javascript function example or node but all are giving Time, it has to be a simple sec to HH:mm:ss function...


#6

Have a look at node-red-contrib-moment


#7

@jupiter8
You can use the node @colin has proposed or use a simple function in the dsm node.

Just copy/past this configuration:

{
    "currentState": "stopped",
    "states": {
        "stopped": {
            "on": "started"
        },
        "started": {
            "inc": "counting",
            "off": "stopped"
        },
        "counting": {
            "inc": "counting",
            "off": "stopped"
        }
    },
    "data": {
        "prev_time": null,
        "time": 0,
        "seconds": 0,
        "interval": 5
    },
    "methods": {
        "init": [
            "sm.calc_time = function () {",
            "   var now = Date.now();",
            "   sm.data.time += now - sm.data.prev_time;",
            "   sm.data.prev_time = now;",
            "   sm.data.seconds = Math.round(sm.data.time / 1000);",
            "};",
            "sm.sec2hhmmss = function(t) {",
            "  var min = t/60;",
            "  var t_h = pad(parseInt(min / 60));",
            "  var t_m = pad(parseInt(min % 60));",
            "  var t_s = pad(Math.round(t % 60));",
            "  return t_h+':'+t_m+':'+t_s;",
            "};"         
        ],
        "on": [
            "if (sm.currentState === 'started') {",
            "   sm.data.prev_time = Date.now();",
            "   resume('inc', msg);",
            "}",
            "output = false;"
        ],
        "inc": [
            "timeout.interval = setTimeout(function() {",
            "   sm.calc_time();",
            "   msg.data = sm.data;",
            "   /* msg.payload = sm.sec2hhmmss(sm.data.seconds);",
            "   node.send(msg); */",
            "   resume('inc', msg);",
            "}, sm.data.interval*1000);",
            "output = false;"
        ],
        "off": [
            "clearTimeout(timeout.interval);",
            "sm.calc_time();",
            "msg.payload = sm.sec2hhmmss(sm.data.seconds);"
        ],
        "reset": [
            "sm.data.time = 0;",
            "sm.data.seconds = 0;"
        ],
        "status": {
            "fill": {
                "get": "sm.currentState === 'counting' ? 'green' : 'grey';"
            },
            "shape": "dot",
            "text": {
                "get": "'time '+ sm.sec2hhmmss(sm.data.seconds);"
            }
        }
    }
}

#8

Exellent! Thanks.