Network status display for 'ping' results

From Vince's ping question I have tested the Python script below and it works well.

import os
print '192.168.1.1 ', os.system("ping -n 1 -w 1000 192.168.3.1") == 0

It's running on a Windows host so

  • "-n 1" limits it to one ping rather than the default of four
  • -w 1000 times it out after 1000 ms in the event of no answer.

Question:
How can I use this to update an indicator status to populate a form with a hundred devices to test?

( ) 10.99.100.1 Good.
(X) 10.99.100.2 No response
( ) 10.99.100.3 Good.
( ) 10.99.100.4 Good.
( ) 10.99.100.5 Good.

Is there a method of incorporating this into a memory or expression tag?

Many thanks.

When I did this, I used two scripts. One was to initialize the contents of a dataset tag with the IP addresses in one column and a ā€˜Neverā€™ status an the second column. I wrote this, because I have 500-ish IPs to keep track of. More on the status in a moment.

The second script reads the tag holding the IP addresses and statuses, iterates and updates rows whose IPs connect with a time stamp, then writes it back to the tag. This keeps track of the last time that a device was seen.

EDIT: Sorry, I didnā€™t provide the quite the correct source code for the ā€˜pingā€™ script. It had a major flaw that didnā€™t create the dataset before trying to write to the tag. Edited to reflect correct code.

Initialization script:

# This script initializes a dataset tag so that all results are 'Never'

# tag to hold results
resultsTag = '[default]Ping/Results'

# initialize dataset
headers = ['ip', 'last_ping']
data = []

#list of IP ranges. More than one range can be specified.
ipList = ['192.168.140', '192.168.141']


for ipRange in ipList:
  for i in range(1,255):
    ip_addr = ipRange + '.' + str(i)
    data.append([ip_addr, 'Never'])
dataOut = system.dataset.toDataSet(headers, data)
system.tag.write(resultsTag, dataOut)

ā€˜Pingā€™ script:

from java.net import InetAddress
from datetime import datetime

resultsTag = '[default]Ping/Results'

dataIn = system.dataset.toPyDataSet(system.tag.read(resultsTag).value)

headers = ['ip', 'last_ping']
data = []


timeout = 200

for row in dataIn:
  ip_addr = row['ip']
  ip = InetAddress.getByName(ip_addr)
  r =  ip.isReachable(timeout)
  if r:
    data.append([row['ip'], str(datetime.now())])
  else:
    data.append(list(row))
  print ip_addr, r
dataOut = system.dataset.toDataSet(headers, data)
system.tag.write(resultsTag, dataOut)

One more thingā€¦ Be sure you are running this in a dedicated thread.

If it runs in a shared thread, anything that relies on that thread comes to a screeching halt. While one may ask how I know that, I refuse to answer. :innocent:

5 Likes

Thank you, Jordan. That was a great help.
I couldnā€™t get the Java InetAddress function to work so I replaced it with an os.system call which works fine on my Windows setup.

For anyone else trying this here are a few more detailed steps to get you going.


###1. Create the dataset tag
In the Tag Browser create a tag for the dataset tag for the ping results. I created the inside a tag folder called PingTest:

  • Name: Results
  • Data Type: DataSet
  • Enabled: Yes
  • Access Rights: Read/Write
  • Scan Class: Default

###2. Create the gateway event script

In the Project Browser | Project | Scripts double-click Gateway Event Scripts.

####2.1 Startup script code
In the Startup script add the code:

# This script initializes a dataset tag so that all results are 'Never'

# tag to hold results
resultsTag = '[default]PingTest/Results'

# initialize dataset
headers = ['ip', 'last_ping']
data = []

#list of IP ranges. More than one range can be specified.
ipList = ['192.168.0', '192.168.1']

for ipRange in ipList:
  for i in range(200,253): # I'm only interested in addresses above 200.
    ip_addr = ipRange + '.' + str(i)
    data.append([ip_addr, 'Never'])
dataOut = system.dataset.toDataSet(headers, data)
system.tag.write(resultsTag, dataOut)

####2.2 The timer event code
Click the Timer icon | New ā€˜+ā€™ button.

  • Give the timer a name.
  • Delay: 30000. (Pings can take a while.)
  • Enabled: True.
  • Delay Type: Fixed delay
  • Threading: Dedicated.

As Jordan has pointed out, you need to set this to ā€œdedicatedā€ thread otherwise all other scripts will pause while this one runs (and many pings can take quite a while).

  • Add the code below.
from datetime import datetime
import os

resultsTag = '[default]PingTest/Results'

dataIn = system.dataset.toPyDataSet(system.tag.read(resultsTag).value)

headers = ['ip', 'last_ping']
data = []

for row in dataIn:
  r = os.system("ping -n 1 -w 1000 " + row['ip']) == 0;
  if r:
    data.append([row['ip'], str(datetime.now())])
  else:
    data.append(list(row))
  print row['ip'], r
dataOut = system.dataset.toDataSet(headers, data)
system.tag.write(resultsTag, dataOut)

###3. Create the display

  • Create a form.
  • Add a table.
  • Drag and drop the Results tag onto the table.
  • Save the project.

The table should update with the results when the last ping is finished.

1 Like

Hi, is this ping script applicable to Linux Ubuntu as well?

Yes, it uses Java libraries, so it should be platform independent.

You may need to modify the os ping call for Linux.

r = os.system("ping -n 1 -w 1000 " + row['ip']) == 0;

to something like

r = os.system("ping -c 1 -w 1000 " + row['ip']) == 0;

Itā€™s ā€˜-nā€™ in Windows and ā€˜-cā€™ in Linux. Check the manual.

You just want it to try once and then give up.