AzeoTech Posted September 30, 2015 Share Posted September 30, 2015 Sometimes it can be hard to tell if a failure to communicate with a device is caused by a networking issue (cut cable, no power to remote device) or something else (protocol error, etc.) In these cases, the first thing we tend to do is ping the device. A successful ping at least tells us that the device is powered up and the IP is accessible from this computer. It doesn't tell us if the device will allow us to connect to it, a firewall is blocking the desired ports (say 502 for Modbus), or other issues, but it does eliminate some possible problems. There are many times when we wish to do this automatically. So, here is a simple script we'd like to share that you can use to ping a device from script: function checkPing(string ip, string path) system.ShellExecute("cmd","","/C ping " + ip + " > " + path, "", "hide") delay(5) private h = file.Open(path,1,0,0,0) private string data = file.Read(h, file.GetLength(h)) file.Close(h) return(find(data,"TTL=",0) != -1) It does this by triggering the command line ping, just like you would type it, and then piping the result to a file. Then it opens the file and looks for "TTL=" which really only appears if a ping is successful. The delay(5) is to give the ping command time to execute as there is no way us to know. ShellExecute() is a non-blocking function, meaning it will trigger the command but then immediately return. Because we are using command line piping we have to have shellExecute() run "CMD" not "Ping" directly. We pass the /C flag to CMD to tell it to run the Ping command then quit. The design of this function is to allow you to, in script, check the network status on many devices. Simply call this function with the ip and a path to the file you'd like ping to create with the result. You'll want to make sure if you are calling this function from multiple threads for multiple IPs that you pass a different path. Note also that this function will take at least 5 seconds to run, so don't call it from the command line or a button press. Make sure and call it from a sequence running in a background thread. Quote Link to comment Share on other sites More sharing options...
svego Posted December 20, 2017 Share Posted December 20, 2017 Hi, To check if all devices work OK I'm using expression ( systime() - temp_gorice.time[0] > 5 )..Now I need to check other IP devices eg. TCP/RS232, access points, IP printers , IP cams that is not modbus so only solution is to ping them. so here I need to make sequence like this... function checkPing(string ip, string path) system.ShellExecute("cmd","","/C ping " + ip + " > " + path, "", "hide") delay(5) private h = file.Open(path,1,0,0,0) private string data = file.Read(h, file.GetLength(h)) file.Close(h) return(find(data,"TTL=",0) != -1) I want to show for every device on network their TTL time like... node 12 ( Lexmark printer, room 12) : 12ms node 15 ( IP cam, room 14): 10ms etc... please see screen, is that OK ? DF freezes.. what should be there ... string path --> path to txt file with ping results... ?? Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted December 20, 2017 Author Share Posted December 20, 2017 You can't put something in the Expression field of any screen control that isn't really fast. Your code will take a minimum of 5 seconds to run given the delay(5) and so will flat out hang the user interface. You will need to put the checkPing() function calls in a Sequence that runs in the background and updates some global variable that you can then reference from your screen control. Quote Link to comment Share on other sites More sharing options...
svego Posted December 20, 2017 Share Posted December 20, 2017 can you give me example ? Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted December 20, 2017 Author Share Posted December 20, 2017 Sure. There are lots of ways of doing this. I don't see why you need a separate file for each location since they'll be ping sequentially though, so: global pingIPs = {"192.168.1.1", "192.168.1.2", "192.168.1.34"} global pingState = fill(0, numrows(pingIPs)) while(1) try for (private i = 0, i < numrows(pingIPs), i++) pingState[i] = checkPing(pingIps[i], "d:\razno\probe2") delay(0.1) endfor catch() ? strLastError delay(0.1) endcatch endwhile Run that in the background, then have your screen control use the pingState global to display the status. Note also that your screenshot is invalid. The first parameter is a string. 192.168.1.1 on it's own doesn't exist in DAQFactory and will be translated to simply 192 (or maybe it's 1, I don't know and there's no reason to know since it's just wrong). So, in your example, it will ping the address 192. You need to put the IP address in quotes. Quote Link to comment Share on other sites More sharing options...
svego Posted December 20, 2017 Share Posted December 20, 2017 but DF did not created file probe2 ?? "d:\razno\probe2"), now I have result 0.000, 0.000, 0.000 ( variable value component ) there is no error but ping is still not working...what I missed ? Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted December 20, 2017 Author Share Posted December 20, 2017 Something with your shellExecute(). DAQFactory was never going to create the probe2 file. That is handled by the > in your command line. You should probably ? the result of the string concatenation of the shellExecute() then try it from an actual command line. Yes, you can do cmd /C from the command line. It will just open another command shell. My guess is that you need quotes for everything after the /c, so the result is something like: cmd /C "ping 192.168.1.1 > d:\razno\probe2" Note that you'll need to use single quotes then in DAQFactory so you can put double quotes inside: '/C "ping ' + etc.. Quote Link to comment Share on other sites More sharing options...
svego Posted December 21, 2017 Share Posted December 21, 2017 hi, I found somewhere bat file that runs ping test from txt file.. Results are saved in separate txt file like here, IP address and ping result has" ;" delimiter 192.168.1.1; is OK 192.168.1.3; is NOT OK google.com; is OK jadrtovac.dyndns.info; is OK hans.dyndns.info; is OK 192.168.1.11; is NOT OK jutarnji.hr; is OK So, here in attachement is sample of code My plan is to make map with devices and change colour depending of ping result. I created sequence to activate bat file and save results in file pingresults.txt in format IP address, ping result. system.ShellExecute("D:\razno\ping_test_boje_ver3.bat","open","D:\razno","hide") --> runs BAT file but I can't hide it from main screen ?? How to read results from file pingresults.txt and store results in array ?? what do you suggest ? ping_test_boje_ver3.bat servers.txt Quote Link to comment Share on other sites More sharing options...
Daggos Posted November 27, 2019 Share Posted November 27, 2019 Pinging 192.0.0.168 with 32 bytes of data: Request timed out. Request timed out. Request timed out. That's all i get in the file Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted November 27, 2019 Author Share Posted November 27, 2019 192.0.0.168 is an unusual IP address. Usually local addresses start with 192.168, so maybe 192.168.0.1? Quote Link to comment Share on other sites More sharing options...
Daggos Posted November 27, 2019 Share Posted November 27, 2019 Thanks for reply but these are my sequences below function checkPing(string ip, string path) system.ShellExecute("cmd","",'/C "ping ' + ip + " > " + path, "", "hide") delay(5) private h = file.Open(path,1,0,0,0) private string data = file.Read(h, file.GetLength(h)) file.Close(h) return(find(data,"TTL=",0) != -1) global pingIPs = {'192.168.141.50', '192.168.141.55', '192.168.141.94'} global pingState = fill(0, numrows(pingIPs)) while(1) try for (private i = 0, i < numrows(pingIPs), i++) pingState = checkPing(pingIps, "d:\DAQFACTORY\probe2") delay(0.1) endfor catch() ? strLastError delay(0.1) endcatch endwhile Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted November 27, 2019 Author Share Posted November 27, 2019 OK, is there an issue? One thing I will point out is that in newer releases of DAQFactory, the C:\DAQFactory installation folder is read-only when DAQFactory is run in normal mode. This is for security reasons. That means that your code might not be able to write the text to D:\DAQFactory\probe2. Check the security settings on the folder, or better yet, create a new folder for this file. Quote Link to comment Share on other sites More sharing options...
Daggos Posted November 27, 2019 Share Posted November 27, 2019 Thanks for that but the folder isn't the DAQ install folder i just created that folder for this script. the file is being created as intended but all that shows up is. Pinging 192.0.0.168 with 32 bytes of data: Request timed out. Request timed out. Request timed out. The problem is as you can see from my sequence that isn't the ip i have listed global pingIPs = {'192.168.141.50', '192.168.141.55', '192.168.141.94'} Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted November 27, 2019 Author Share Posted November 27, 2019 Right. Sorry didn't look carefully and missed your typo. Look in the calling function. You have pingIPs declared as a number, not a string. You then define it as an array of strings, but the variable is still declared as a number, so DAQFactory is converting all it to an array of 192.168's and the rest is thrown away because it is not a valid number. DAQFactory will convert string numbers to actual numbers up to the point where it is invalid, or if the first character is invalid it will convert it to NaN. So, "192.168.141.50" becomes 192.168, and "ab192" becomes NaN, and "192ab" becomes 192. If you go to a command prompt and type: ping 192.168 you'll see that it will actually try and ping 192.0.0.168. That's being done by the ping executable. Quote Link to comment Share on other sites More sharing options...
Daggos Posted November 27, 2019 Share Posted November 27, 2019 Still struggling. I have changed the line to global string pingIPs = {"192.168.141.50", "192.168.141.55", "192.168.141.94"} changed the single quotes to double. still getting 192.0.0.168 Thanks for your help Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted November 27, 2019 Author Share Posted November 27, 2019 That's because you already declared pingIPs as a number. Declaring a global variable after it is already declared doesn't change the type. You need to either save and restart, or enter ClearGlobals() at the command / alert window to clear out all existing globals so that pingIPs can be redeclared as a string. I recommend the restart option so your auto-start sequence runs (if any) otherwise you end up with other problems (other global variables that have now been "undeclared") Quote Link to comment Share on other sites More sharing options...
Daggos Posted November 27, 2019 Share Posted November 27, 2019 LOL should have tried the old off and on again cheers mate. Works fine now Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.