Monitoring IoT by Ping

Question - anyone know if we can determine OS in a flow?

I'd make this demo universal if I could.

It might be better to use node-red-node-ping which would presumably cope with such differences.

Colin, if i'm not mistaken, node-red-node-ping node doesn't accept input - OP needs a list to process.

I am aware there is another ping node that accepts input but, I wanted to make it operate without additional external nodes to simplify things - plug and play for any user - however, in hindsight... :confused:

Yes, you are correct, I missed that.

lsb_release -a
will tell you which linux you are using
On Raspbian:

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

That will presumably give you something different on Windows, or error, so you could use that. There may well be a nicer way though.

I am currently porting ICMP from names as a set of tools for Node-Red , you should be able to listen for pings/messages , i will post an announcement rely soon(probably today) , but there should be some things that will be needed fixing.

Well in node.js - require('os').platform(); is probably the most useful.

Yeah cheers Dave, was aware of that however that would require a user to modify settings.js in node-red world right?

Was just wondering if there were a specific env var that we could query on a standard flow that reliably identified the breed (windows/*nix) for this kind of situation?

In a Function node, I wonder does the node object hold any environment clues? :thinking:

@Steve-Mcl You uncomment it in settings.js

    // The following property can be used to seed Global Context with predefined
    // values. This allows extra node modules to be made available with the
    // Function node.
    // For example,
    //    functionGlobalContext: { os:require('os') }
    // can be accessed in a function block as:
    //    global.get("os")
    functionGlobalContext: {
		os:require('os'),

Then in a function node you can use something like

var os = global.get("os");
node.warn(os.platform())

which on my mac returns:

3/31/2020, 8:14:21 AMnode: 46eaf429.ea9bf4
function : (warn)
"darwin"
1 Like

Yeah, as I suspected - however thats not really quick and "handy" for a demo (asking folks to modify settings.js)

Was just curious if an ENV var could identify windows/nix to simplify areas where we might use an EXEC node to do some dirty work and be compatible (as best as possible) with other OSs

Hindsight glasses on...
I think for these cases, It would be useful for the flow to know its host (e.g. if(node.platform == "win32") kinda thing)

I would have to disagree - while "useful", I think it only encourages people to write platform specific code which we don't really want in function nodes etc. At least inside a node you can hope that a developer does the right thing and handles the multiple cases.

@Steve-Mcl
Good Morning. I changed the command and now it worked (this is listing which rasp is on or not)
Thanks a lot for the help

Hi Dave.

I personally think there are valid reasons for a flow to know it's host OS. This is but one case where there is not really a need to develop a node (it's perfectly achievable pretty much out of the box using exec node which is part of the standard install - so I don't get why we would have to jump through hoops to know the host OS)

But I don't disagree with your stand point either - as most here know, you have far more insight on the inner workings and forward vision of node red & I respect your opinion.

Thanks for taking the time to respond.

Hi Steve, no problem. Same way we really don't want to add anything browser specific in if we can help it - we would rather tings work all over the place if possible,

I'm also happy to look at pull requests for the Ping node - There are known techniques to make an input optional, and there's nothing to stop the input being a csv list or array for example.

1 Like

Pretty sure you showed by how to do that on my cron+ node :slight_smile:

I might take a look :+1:

Hello
Great what developed from my request. I am happy to read this process. Thanks to all of you. :blush:

@ dceejay
You are writing the there are known techniques to make an input optional. Can a beginner do that or do they refer more to pure programming?

@Steve-Mcl
I have a question about:

//store ping item
pingResults[thisPing.name] = thisPing;

//save pingResults in flow context
flow.set("pingResults",pingResults);
I have to watch my limited space on store and save. I only have a few MB left on my SD card of my PI. Or does all of this take place in the temporary memory

It's in memory only (as long as you haven't setup file based context storage). If you don't know what I mean then it's very likely it's in memory only.

Dave is referring to node development (a somewhat separate issue to your requirements)

I thank you and everyone else who helps me
Node Red makes me really fun to learn something new.
:grinning: THX Marc (EDSTOBI)

We can now with the updated version of node-red-node-ping

It now has 2 modes: Timed [original mode] or Triggered [new mode] & also accepts a CSV list of IPs or an array of objects - greatly simplifying pinging multiple devices.

Simplified flow screen shot

Simplified flow...

[{"id":"51f7207a.baa53","type":"inject","z":"a878aaaa.79a018","name":"*** Setup devices to ping here ***","topic":"","payload":"[{\"name\":\"router\",\"host\":\"192.168.1.1\"},{\"name\":\"tv\",\"host\":\"192.168.1.51\"},{\"name\":\"smart speaker\",\"host\":\"192.168.1.52\"},{\"name\":\"bad device\",\"host\":\"192.168.2.99\"}]","payloadType":"json","repeat":"20","crontab":"","once":false,"onceDelay":0.1,"x":320,"y":260,"wires":[["cf66e372.27656"]]},{"id":"99c8413.a9a79c","type":"template","z":"a878aaaa.79a018","name":"build html table","field":"html","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"\n<table width=\"100%\">\n  <tr>\n    <th>Name</th>\n    <th>Host</th> \n    <th>Status</th> \n  </tr>\n  {{#tableData}}\n  <tr class='{{rowclass}}'>\n    <td>{{{name}}}</td>\n    <td>{{host}}</td> \n    <td>{{{stateInfo}}}</i></td> \n  </tr>\n  {{/tableData}}\n</table>","x":660,"y":320,"wires":[["c9452322.9411d","90592906.29a578"]]},{"id":"c9452322.9411d","type":"debug","z":"a878aaaa.79a018","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":830,"y":360,"wires":[]},{"id":"3988b1f3.69647e","type":"inject","z":"a878aaaa.79a018","name":"","topic":"","payload":"[{\"name\":\"router\",\"ip\":\"192.168.0.1\"},{\"name\":\"tv\",\"ip\":\"192.168.0.51\"},{\"name\":\"smart speaker\",\"ip\":\"192.168.0.52\"},{\"name\":\"bad device\",\"ip\":\"192.168.1.99\"}]","payloadType":"json","repeat":"30","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":320,"wires":[["4e150f7e.63b67"]]},{"id":"4e150f7e.63b67","type":"function","z":"a878aaaa.79a018","name":"convert pingResults to array","func":"let pingResults = flow.get(\"pingResults\") || {}\nlet now = new Date();\n\nlet tableData = [];\nfor (let k in pingResults) {\n    let r = pingResults[k];\n    r.age = now - r.timestamp\n    if(r.age > 18000){\n        r.state = \"old\"\n    }\n    if(r.state == \"ok\"){\n        r.rowclass = \"good\";\n        r.stateInfo = '<i class=\"fa fa-thumbs-up\" aria-hidden=\"true\"></i> OK'\n    } else if(r.state == \"ng\") {\n         r.rowclass = \"bad\";\n        r.stateInfo = '<i class=\"fa fa-thumbs-down\" aria-hidden=\"true\"></i> NG'\n    } else {\n        r.rowclass = \"unknown\";\n        r.stateInfo = '<i class=\"fa question\" aria-hidden=\"true\"></i> ' + r.state\n    }\n  tableData.push(r);\n}\n\nmsg.tableData = tableData\n\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":320,"wires":[["99c8413.a9a79c","71f260f1.aacbf"]]},{"id":"cf66e372.27656","type":"ping","z":"a878aaaa.79a018","mode":"triggered","name":"","host":"","timer":"20","inputs":1,"x":530,"y":260,"wires":[["ddef4dbb.e8897"]]},{"id":"cf6a929c.6311a","type":"debug","z":"a878aaaa.79a018","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":830,"y":260,"wires":[]},{"id":"ddef4dbb.e8897","type":"function","z":"a878aaaa.79a018","name":"Store Results","func":"let pingResults = flow.get(\"pingResults\") || {}\nlet thisPing = pingResults[msg.topic] || {};\nlet success = msg.payload !== false && msg.payload >= 0;\n\nthisPing.name = msg.ping.name;\nthisPing.host = msg.ping.host;\nthisPing.timestamp = new Date();\nthisPing.responseTime = success ? msg.payload : null;\nthisPing.state = success ? \"ok\" : \"ng\" ;\n\npingResults[msg.topic] = thisPing;//store ping obj in pingResults\nflow.set(\"pingResults\",pingResults);//save pingResults in flow context\n\nmsg.payload = thisPing;\nreturn msg;","outputs":1,"noerr":0,"x":680,"y":260,"wires":[["cf6a929c.6311a"]]},{"id":"90592906.29a578","type":"ui_template","z":"a878aaaa.79a018","group":"3dc35e31.466292","name":"","order":3,"width":"6","height":"5","format":"<style>\ntable {\n    color: #333;\n    font-family: Helvetica, Arial, sans-serif;\n    width: 100%;\n    border-collapse: collapse;\n    border-spacing: 0;\n}\ntd, th {\n    border: 1px solid transparent;\n    /* No more visible border */\n    height: 30px;\n    transition: all 0.3s;\n    /* Simple transition for hover effect */\n}\nth {\n    background: #DFDFDF;\n    /* Darken header a bit */\n    font-weight: bold;\n}\ntd {\n    background: #FAFAFA;\n    text-align: center;\n}\n\n/* Cells in even rows (2,4,6...) are one color */\n\ntr:nth-child(even) td {\n    background: #F1F1F1;\n}\n\n/* Cells in odd rows (1,3,5...) are another (excludes header cells)  */\n\ntr:nth-child(odd) td {\n    background: #FEFEFE;\n}\ntr td:hover {\n    background: #666;\n    color: #FFF;\n}\n\n/* Hover cell effect! */    \n\ntr.good {\n    color: green;\n}\n\ntr.bad {\n    color: red;\n}\n\ntr.unknown {\n    color: orange;\n}\n\n    \n</style>\n<div ng-bind-html=\"msg.html\"></div>\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":840,"y":320,"wires":[[]]},{"id":"71f260f1.aacbf","type":"debug","z":"a878aaaa.79a018","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":590,"y":400,"wires":[]},{"id":"3dc35e31.466292","type":"ui_group","z":"","name":"Default","tab":"5132060d.4cde48","order":1,"disp":true,"width":"6","collapse":false},{"id":"5132060d.4cde48","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

Result...
image

2 Likes

Check out the new node i just built!
image

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.