MuaazH / ZKTeco_PULLSDK_Wrapper

A wrapper for ZKTeco's pullsdk & ZKFinger
51 stars 31 forks source link

I have a problem when using the code for the problem of opening the door multiple times #7

Closed haisaco closed 1 month ago

haisaco commented 2 months ago

After a while of using the library, I'm encountering some problems. Below is my code:

public void btn_conectar_Click(object sender, EventArgs e)
{
    if (btn_Connect.Text == "Connect")
    {
        foreach (var item in _currentSettings)
        {
            item.AccessPanelData = new AccessPanel();
            // connect
            if (!item.AccessPanelData.Connect(item.IP, item.Port.Value, 0, item.TimeOuts.Value))
            {
                logger.Information("Cannot connect:" + item.IP);
                MessageBox.Show("Cannot connect this ip " + item.IP + ". Error", "Infomation", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                logger.Information("Start with IP:" + item.IP);
               //call function run backgroud
                Task.Run(() => BackgroundTask(item));
            }
        }
        btn_Connect.Text = "Disconnect";
    }
    else
    {
        foreach (var item in _currentSettings)
        {
            item.AccessPanelData.Disconnect();
        }
        listBoxActive.Items.Clear();
        btn_Connect.Text = "Connect";
    }
}

//Create thread run backgroud
async Task BackgroundTask(Settings setting)
{
    while (setting.IsActive)
    {
        await Task.Delay(1000);
        var listLog = csetting.AccessPanelData.GetEventLog();
        if (listLog != null && listLog.Events != null)
        {
            var list = listLog.Events;
            foreach (var item in list)
            {
                if (list_log1.Items.Count > 20)
                {
                    list_log1.Invoke(new MethodInvoker(() => list_log1.Items.Clear()));
                }

                list_log1.Invoke(new MethodInvoker(() =>
                {
                    list_log1.Items.Add(setting.IP);
                    var index = list_log1.Items.Count - 1;
                    list_log1.Items[index].SubItems.Add(item.Time);
                    list_log1.Items[index].SubItems.Add(item.Pin);
                    list_log1.Items[index].SubItems.Add(item.inputString);
                    list_log1.Items[index].SubItems.Add(item.Door);
                    list_log1.Items[index].SubItems.Add(item.EventType.ToString());
                    list_log1.Items[index].SubItems.Add(item.InOrOut.ToString());
                    list_log1.Items[index].SubItems.Add("");
                    list_log1.Items[index].SubItems.Add("");
                }));
               //item.inputString is code I will check to access open door
                if (item.inputString.Length > 5 && setting.intPtr != IntPtr.Zero)
                {
                  // call function check true false can access open door
                    var ticket = await ServiceConnection.CheckTicketAsync(item.inputString, setting.IP);
                    if (CheckCong(item.inputString, setting.IP) && ticket.ActiveID != null)
                    {
                            //create another thread to open Door
                           var task = Task.Run(async () =>
                            {
                              //NumberOfOpenDoor > 1 Open the door multiple times, each time 3 seconds apart 
                                for (int k = 0; k < ticket.NumberOfOpenDoor; k++)
                                {
                                    setting.AccessPanelData.OpenDoor(1, 1);
                                   //wait 3s
                                    await Task.Delay(3000);
                                }
                            });
                            await task;
                    }
                }
            }
        }
    }
}

The above code works normally, but there is a problem that when used to open the door multiple times, the next time will have to wait the entire time of the first time. For example, code 1234 opens the door 10 times after opening the door 3 seconds apart as set. When using code 1235, you will have to wait 10*3=30 seconds for the system to continue opening. i think the problem is await Task.Delay(3000); must not be removed. Do you have any way to optimize this problem? Solve the problem of opening the door multiple times when using 1 code.

MuaazH commented 2 months ago

Your code is too long and deeply nested, with few comments.

  1. Are you opening the door to let people in based on events? You are not supposed to do that. If you have registered the user correctly the door should be open by the device, not from your code.

  2. Are you checking what the return value of openDoor is? In this wrapper, if an operation fails, a counter is incremented and after a certain number the connection is dropped. This sort of used as a recovery procedure to detect and correct connection loss and device freezes (blame ZKTeco for that).

  3. Are you calling IsConnected to reconnect when the connection is dropped?

  4. However, I agree that openDoor should not lag if you spam call it. Sadly this is only a wrapper and I don't think there is a bug in these few lines of code.

haisaco commented 2 months ago
  1. Yes. I am opening the door based on events from logevent. The use of user registration is that I need to use Zkteco's default program?
  2. I don't check the error value when opening the door, just call openDoor
  3. The connection loss condition does not occur and with this code I cannot check that condition either
  4. I think the problem with this line of code lies in the fact that I use data to open the port with logevent and not having control over the threads. But I'm looking forward to an optimal solution for this. For my problem, I use a QR code reader integrated into Zkteco. 1 code can open the door many times with 1 scan. Do you have any solution?
MuaazH commented 2 months ago

I never had a device to test with, but I think QR is handled as the user password. I'm not sure what the content of the QR code are either. So:

  1. WRONG, that's what the controller is for. And you don't need ZKTeco's crap software. First setup a timezone (use id 1 for the default timezone), see the docs here. You just need to create a new User, set the doors the user can access (See User.Doors and User.SetDoorsByFlag, you can do usr.SetDoorsByFlag(255) to give the user access to all doors) The doors should open now without your code

  2. You must check the result, that method may fail for any reason. (Door already open, door is blocked, power loss, bad sensor, ...)

  3. Any code must cover all the possibilities. You can't code and hope.

  4. If you want extra control you can change your code to only write/delete users who gain/lose accesss. But don't open the door yourself. If you want to open the door yourself, then you don't need the "Access Panel". You just need the QR reader and the door lock, find how you can link them to the computer (i.e. drivers & adapters) and write your own software to replace the controller's logic.