7

I have ZKTeco Biometrics device which is connected with a C# windows application using This tutorial (C# ZKTeco Biometric Device Getting Started).

It is working fine but after sometime, my application becoming failed to ping the device. As below code suggested, I am trying to ping the device after every 25 seconds.

  private void TimerCheckPingAndCloseAttendanceForm() {
  timerCheckPingAndCloseAttendanceForm            = new Timer();
  timerCheckPingAndCloseAttendanceForm.Tick       += new EventHandler(CheckPingAndCloseAttendanceForm);
  timerCheckPingAndCloseAttendanceForm.Interval   = 25000;//25 seconds.
  timerCheckPingAndCloseAttendanceForm.Start();
        }


 private void CheckPingAndCloseAttendanceForm(object sender, EventArgs e) {
     string ipAddress = tbxDeviceIP.Text.Trim();
     if (UniversalStatic.PingTheDevice(ipAddress) == false) {
           //CloseAttendaceListForm();
           IsDeviceConnected = false;
           string infoString = "Application started on " + applicationStartDateTime.ToString() + " and ping failed on " + DateTime.Now.ToString() + " then, app closed while device ip is "+ ipAddress;
          File.AppendAllText("ConnectionLog.txt", infoString + Environment.NewLine);
          Application.Exit();
          //timerCheckPingAndCloseAttendanceForm.Tick -= new EventHandler(CheckPingAndCloseAttendanceForm);
            }
        }

And when I am trying to ping the command from cmd the device show destination host is unreachable. But whenever I restart the device, the ping working fine. I don't know where is the problem? Either the network problem or its coding issue?

Note: I am doing a ping on regular time interval, because on Disconnected Event is not working. I am assuming ping failed meaning is the device has disconnected with the application.

Muhammad Faizan Khan
  • 10,013
  • 18
  • 97
  • 186
  • which device in particular are you talking about ? Obvious question: can you telnet to the device when you can't ping ? When I worked with uFace800 I got a series of network issues with it, is this happening with ideal network conditions ? Short cables, good switches etc. – farbiondriven Dec 07 '18 at 14:26
  • I didn't telnet the device yet and it is K20 Model. – Muhammad Faizan Khan Dec 08 '18 at 11:23

6 Answers6

2

First of all : Thank you for going through my article

You are doing it the wrong way.

Trying to ping the device after every 25 seconds is unnecessary.

The only job of the UniversalStatic.PingTheDevice method is to check if the device is presumably active, the first time you connect with the device.

If you want to check the status of the device i.e IsDeviceConnected, All you need to do is register to the device OnDisConnected event provided by the SDK.

It seems the code here at line number 57 has already done the OnDisConnected event registration for you.

All you need to do now is set your IsDeviceConnected to false when the objCZKEM_OnDisConnected method in the ZkemClient.cs class is called upon by the device itself.

Sample snippet : In the ZkemClient.cs class file, between line number 81-84

void objCZKEM_OnDisConnected()
{
     IsDeviceConnected = false;  // <-- Add this line
}

Now, Every time you try to make a call to the device, All you need to do is check for the value of your IsDeviceConnected.

Ozesh
  • 6,536
  • 1
  • 25
  • 23
  • 1
    Thanks for the response, But OnDisconected Event is not firing, when i off the device or unplug network cable. I have already asked this question (3 months ago). https://stackoverflow.com/questions/52090851/zkemkeeper-ondisconnectedevent-is-not-firing-in-c-sharp This is the reason that I am ping the device after 25 second in order to know that devices is still connected or not. – Muhammad Faizan Khan Dec 07 '18 at 10:32
  • Have you tried by registering the OnDisConnected event before the objCZKEM.Connect_Net method gets called in the ZkemClient.cs. In some devices, the code at line 57 needs to be placed before line 49 in the ZkemClient.cs file. – Ozesh Dec 07 '18 at 11:51
  • Just tested upon your suggestion objCZKEM.OnDisConnected += objCZKEM_OnDisConnected; if (objCZKEM.Connect_Net(IPAdd, Port)) but no changed – Muhammad Faizan Khan Dec 07 '18 at 11:55
  • any hint that what i am doing wrong? The work is based on your efforts(as i have mentioned). The device get disconncted and i don't know the reason therefore i am making a ping request. – Muhammad Faizan Khan Dec 08 '18 at 04:07
  • I dont think that you are doing the event registration part wrong. Its just that some devices act differently. The device actually goes to sleep mode. What you can try doing is using the EnableDevice function before making any other call (Read/Write operations) to the device. EnableDevice(machineNumber, false) sets the device to working state and EnableDevice(machineNumber, true) sets the device to the non working state. You can also try using the DisableDeviceWithTimeOut method to set the timeout to be a little longer. – Ozesh Dec 09 '18 at 06:43
  • Thanks i dont know about device sleep mode. Well it is k20 model. Tomorrow innShaaAllah i will try it and let you know the result. By the way what is the default timeout limit? And do you think that when i am getting destination host unreachable message on ping it means device is not enabled? I think that when i am unable to ping then i will be unable to unable it. – Muhammad Faizan Khan Dec 09 '18 at 12:29
  • Actually i am only using `OnAttTransactionEx` currently. At this event i am displaying real time user attendance. – Muhammad Faizan Khan Dec 10 '18 at 06:16
  • I have change my PC, network and increased the ping checking time to 1 minutes. It brought significant good result and now my devices rarely hanged or facing ping failed issue. But now i am getting a weird problem that `OnAttTransactionEx` is not firing and ping is correctly working. – Muhammad Faizan Khan Jan 07 '19 at 05:27
  • Do there anyway available to know that device has disconnected. ? I want constant connection with my device using the windows application. – Muhammad Faizan Khan Jan 07 '19 at 05:28
0

Not having the actual code and the hardware setup, this answer is a bit of a shot in the dark, but here goes …

Since it works initially, this is not a hardware configuration or network configuration issue. Yet it says that after a while the destination (reader) becomes unavailable. This is probably not a network keepalive issue because you are pinging every 25 sec. Looking at the code that you referenced, it shows opening a connection and hooking up callbacks, and making a call to a hardware feature.

My guess would be maybe you are opening the connection each ping and not closing the connection, then after a number of attempts the hardware jams because there are too many open connections. Just a guess. If this is the problem then to fix it, either close the connection or, better, keep the connection open and re-use it.

Alternative possibility would be that the router(s) between your code and the device are detecting too many pings and blocking the connection as a possible DOS attack. If this is the problem then to fix it, configure the router to allow the traffic.

sjb-sjb
  • 1,112
  • 6
  • 14
  • The error being returned has to deal with the networking stack not able to send the IMCP packet to the device because no one knows what machine has it (IE: it is probably not responding it ARP). This should eliminate the # of connections theory. Also DDOS protect will not trigger at intervals of 25 seconds. – Liam Kelly Dec 03 '18 at 14:26
0

This sounds like the device misbehaving. The error "destination host is unreachable" corresponds to an ICMP packet, same type of packet as ping but different job, being sent by your router saying "I have no idea which device has that IP". This normally happens when the device stop responding to ARP, which basically asks "who has this IP?" and expects a machine to respond "I have it" with its MAC address. The router constantly refreshes its ARP table, forgetting old values.

So when you boot the device it is 'happy', responding to ARP and responding to pings; however, something happens and it at least stops responding to ARP (probably something more wrong with it). Depending on its architecture it could be loaded down doing other stuff and unable to respond, or it could just be locked up.

Try slowing down other actions to the device (if your polling it for information other than ping, do it slower) and also see if you can get status from the device via another output (does it have a uart?).

Liam Kelly
  • 3,524
  • 1
  • 17
  • 41
0

OPTION 1

Since that restarting the device fixes your problem for a period of time, check that the IP that you are using is not in use on another device/computer/element_of_the_network.

ZKTeco devices come with the IP 192.168.1.201 configured by default. Configure a different static IP and avoid using DHCP (it´s well known that using DHCP in ZKTeco devices isn´t a good choice since they don´t refresh automatically the IP after rebooting the system or any network change).

Make sure that the IP is not in use and that nobody else will use it.

OPTION 2

Another thing that It may be the cause of your problem, is that you are using zkemkeeper in a different part of your application (or into a different application) and you are not closing the oppened connections properly... That may be blocking all network activity from the device. To close the connection just make sure that you call this sdk method after performing all the necessary actions:

sdk.Disconnect();
  • DHCP is good option. If you reset the device or disable/enable the DHCP while change the network, it will pick the right one. If it doesnt pick one, then the given LAN connection might have two networks integrated, in this case, device will not get the internet. So its good for the quick troubleshoot too... – Ravanan Dec 05 '18 at 17:50
  • Generaly DHCP is a good option, but in this case, ZKTeco devices don´t refresh the IP automatically after rebooting the device or after any network change... You must go physically to the device and update it manually by disabling the dhcp through the menu and enabling it again. That´s why in this case I don´t recommend using it. – Roberto Vázquez Dec 06 '18 at 09:38
  • I am using static IP, not using DHCP – Muhammad Faizan Khan Dec 06 '18 at 09:47
0

It looks like a code issue. While investigating UniversalStatic.PingTheDevice(ipAddress), its found that its calling System.Net.NetworkInformation.Ping.Send setting DontFragment = true. Reference: https://github.com/zaagan/BioMetrix/blob/master/BioMetrixCore/Utilities/UniversalStatic.cs#LC51. The timeout for the ping is set to 120 milli seconds. This tries to send 32 bytes of data to the given IP.

Following is the snippet taken from https://learn.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ping.send?view=netframework-4.7.2 would answer the root-cause of your issue

If the DontFragment property is true and the total packet size exceeds the maximum packet size that can be transmitted by one of the routing nodes between the local and remote computers, the ICMP echo request fails. When this happens, the Status is set to PacketTooBig.

So when you restart your device, possibly, the data travelling on the network gets lost. Hence it started working till the packets reaching its limit.

Few suggestions:

  • Try calling System.Net.NetworkInformation.Ping.Dispose in PingTheDevice before returns
  • Increase the timeout from 120 milliseconds to seconds.
  • Increase the timerCheckPingAndCloseAttendanceForm.Interval to 1 min.
  • Check the return code of the System.Net.NetworkInformation.Ping.Send and find the associated failure meaning

Please share your findings if the above suggestions do not help you finding the root-cause.

Ravanan
  • 536
  • 2
  • 13
  • actually if close inspect the pindDevice method the timeout has already set to 120. – Muhammad Faizan Khan Dec 06 '18 at 09:54
  • Ya. i mentioned the same in my answer too. timeout is meant for the return the blocker function. it not necessarily closes the resources to engages. If the function completes is before, before even it reaches the timeout duration, the function will be returned. So you can keep it high to allow ping to complete its full work so that you can quickly ping again. – Ravanan Dec 06 '18 at 17:02
  • Hope, making the above suggestions and testing will not take more than 15 mins.... Please confirm, if the suggestion is helping/not helping by making the changes. Otherwise, we can only share the guesses. – Ravanan Dec 07 '18 at 10:31
0

you try this code for ping the device,

try
        {
            IPAddress ipAddress = IPAddress.Parse(ipAdd);

            Ping pingSender = new Ping();
            PingOptions options = new PingOptions();
            options.DontFragment = true;

            // Create a buffer of 32 bytes of data to be transmitted. 
            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            int timeout = 120;
            PingReply reply = pingSender.Send(ipAddress, timeout, buffer, options);

            if (reply.Status == IPStatus.Success)
                return true;
            else
            {
                return false;
            }
        }
        catch (Exception)
        {
            return false;
        }

Thanks.