Logging network status

I’ve had a request to log network status from FactorySQL to be used in FactoryPMI reports. Sounds like a reasonable request. Realtime status is totally taken care of with the SQLTags component overlay system. Historical network status?

My gut feeling is: use Microsoft/3rd party tools. I know of a lot of these for realtime status, but few that record historical uptime to a database.

My idea is to log data based changes of the OPC quality code of the PLC.

Any ideas on the best way to do accomplish this task?

I don’t know exactly what you mean by network status, but you might want to take a look at Kepware’s iSNMP product

Coincidentally, I was going to ask the same question today. Maybe it’s related to what you are talking about.

I will have 13 devices on my network, and I need to have a screen to display the network status (i.e. are they ping-able or not). Is there somethng in FactoryPMI that handles this already? I will have a table with a list of devices and their IP addresses and status.

Hmm, I wouldn’t use FactoryPMI for that, it should definately be in FactorySQL. This is because you care that the machine that FactorySQL is running on has comm to the device, not the machine that the FactoryPMI client is on.

The easiest thing to do is simply use the quality of a tag that is coming from that device. If the quality goes bad - you know there is a comm issue. The tag could even be a heartbeat for double-safety.

There is probably something we could do to actually use the ping protocol, I’d have to think about it… but it might not be worth it, if the tag quality idea is sufficient.

But, these devices have no tags. They are ethernet-to-serial converters that are connected to my PLC. They are on the same network that FactorySQL and my clients will be on, and I will want to display their connection status so the techs can easily tell if one of the devices is unplugged or powered off. I just assumed that since these had nothing to do with the OPC Server or any groups in FactorySQL, there might be a ping function in FactoryPMI.

Ok, I’m a bit hesitant to show you this, because I think it should be done in FactorySQL so that your devices aren’t getting flooded by pings from all of your running clients. (making a plugin for FactorySQL to run a ping would be the best)

In any case, here is how you would do a ping from a script. Its using Java through Jython. Put this script on a button to play with it.

from java.net import InetAddress addr = fpmi.gui.inputBox("Ping what IP Address?", "") try: device = InetAddress.getByName(addr) test = device.isReachable(5000) if test: fpmi.gui.messageBox("Ping successful for %s"%addr) else: fpmi.gui.messageBox("Ping failed for %s"%addr) except IOError, (errmsg): fpmi.gui.errorBox("I/O Error pinging %s: %s" % (addr, errmsg))

Hope this helps,

I agree that it should be done in FSQL, and since we’re so darn efficient around here, here’s a plugin to do it:
inductiveautomation.com/file … Plugin.zip

This fsql plugin exposes a ping function that takes an address and timeout, and returns true or false as to whether it’s available. I’d say run it every minute or so and store the result to a status table.

Let me know what you think or if there are any problems.

That was my first thought (the “what do you mean” and using SNMP). From FSQL’s perspective the best thing I could come up with was an end to end “if I can talk to the PLC then the network must be up”.

Clearly SNMP is the better route to monitor specific network uptime. Thanks, I didn’t realize Kepware had an SNMP product.

Colby, thanks for the plugin. That may work for his application.

Thanks guys, the plugin works perfectly. I can now throw a fault up on the screen before they even were aware that there was a problem.

I dont know if this is related to what was being looked for but what I have used to determine network status is the _error flag in KepServer. If the device is present and communicating this is set to a zero if the device fails communications this sets to a 1. I origionally used this in an SQL database but have since changed it to SQL tags and when this value changed I have it set to an alarm which pops up on the screen causing the supervisor to be made aware of the issue and have to ack it before hand. This way if communications is lost someone is told. There are also other types of flags in the System of KepServer. Just thought I would add my .02

have a great day.


Thats a great idea, Kepware does have nice diagnostic flags, I didn’t know about this one. Step7’s question had to do with devices that weren’t communicating over OPC, but your is a good tip nonetheless.

Thank you. I do however have a question, is not KepServer an OPC communication tool? Just curious, I am still learning all the terms and such but it appears from Kepwares website that Kepserver is the communications client it lies between the device and FSQL. Step7 might have been talking about loss between the device and the OPC server, or between the OPC server and FSQL. If it was between OPC and FSQL is this something that should be taken into consideration? Like I said I am unsure and I dont want to offend anyone just offer my .02 and try to learn at the same time.


Thats a great idea, Kepware does have nice diagnostic flags, I didn’t know about this one. Step7’s question had to do with devices that weren’t communicating over OPC, but your is a good tip nonetheless.[/quote]

Martin, the devices I am pinging are Ethernet-Serial converters, and reside on my machine control network. They don’t have anything to do with the OPC Server or FactorySQL, but since they can be pinged (pung?) by the PC that is runnning FactorySQL, it made sense to put the diagnostics there.

I could have kluged something together in the PLC using some ethernet handshaking with each device, but PCs are much better at this.

I’m adding the ping to a new project, and am kind of weak with expressions.

I have a table of all of the ping-able devices, but the customer can add more if they wish through a machine config screen in fpmi. How would I loop through all of the rows in my ping table using the expression language? At my other customer site, I just hard coded the ip addresses I cared about.

I took a stab at it by first creating an action item to get all of the devices (Select IP FROM MachineConfig). I can see the first row in the action item result pane, and maybe the others are there but I can’t see them. I tried unspecified, array, and string result types. Where would I go from here? Am I better of using a case statement in SQL?

A shove in the right direction would be appreciated.

I think I figured out a way to do this.

I used a table named DevicesToPing with two columns, Index and Address. You would have to make adjustments/alterations based on your table structure and column names.

Try following these steps:

  1. Create a standard group and set its update rate to the period you desire.

  2. Add action items with the following attributes:

    a. Item: AddressCount, SQL query: SELECT COUNT(*) FROM DevicesToPing, Result Type: Integer
    b. Item: Index, expression: GetVariable(“Index”, 1), Result Type: Integer
    c. Item: IndexInc, expression: StoreVariable(“Index”, If(({Index} + 1) > {AddressCount}, 1, {Index} + 1)), Result Type: Unspecified
    d. Item: AddressQuery, expression: Concat("SELECT Address FROM DevicesToPing WHERE [Index] = ", ToString({Index})), Result Type: String
    e. Item: AddressToPing, expression: ExecuteScalarQuery({AddressQuery}), Result Type: String
    f. Item: AddressPing, expression: Ping({AddressToPing}, 10), Result Type: Boolean

If all goes well, every time FSQL executes the group it will increment Index, construct the SQL query, execute the query to get the address to ping, and ping the address.

Thanks MickeyBob, that worked great. I appreciate what you put into that.

I had to make one change because I can’t always guarantee that the indexes will be consectutive or even start at one (it is an identity column, and I might delete rows during development, or the customer may delete devices). So, I used a CTE to create a temp table of row_numbers and IP addresses, which gave me this query in your AddressQuery:

Concat("WITH IPs(RowNumber, Address) AS (SELECT     ROW_NUMBER() OVER (ORDER BY index) AS r, Address
FROM        DevicesToPing)
    SELECT     Address
     FROM         ips
     WHERE     RowNumber = ", ToString({Index}))

Now, it just loops through all the rows in the table and ignores the index.