Zilverdael
Zilverdael

Reputation: 21

C# Serial connection waitfor string

I am trying to operate a device over serial connection. I have it working up to the part where i want to program to wait for certain response received over the rx line. (for example the ready for login prompt) Receive data is on another thread and happens in the background.

When I implement a while loop waiting for the data received with a sleep, the program freezes. No new data is shown, even when received. Even worse, i do not see code executed before the wait.

serialPort1.WriteLine("login");
serialPort1.WriteLine("admin");
waitfor("complete!");

It does not even write the 'login' ... Or at least, i can not see it nor get any response. When i comment out the waitfor line, the line is sent. However i need to catch errors, responses etc. etc. So this 'waitfor' is critical for the program to work. When the 'timout' counter expires, the in and output is spammed on the terminal screen.

public Thread ReadSerialDataThread;
public string readSerialValue;
public string waitValue = "complete!";          // Added value to test and it shows expected response during ReadSerial
public bool waitFound = false;

private void but1_Click(object sender, EventArgs e)
{
    if (!serialPort1.IsOpen) {
        try
        {
            serialPort1.PortName = txtComPort.Text;
            serialPort1.Open();
            but1.Text = "Disconnect";
            txtSend.Enabled = true;
            butSend.Enabled = true;
            txtComPort.Enabled = false;
            ReadSerialData();
            LogSerialData("Port opened");
        }
        catch (Exception ex) {
            MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    else {
        try {
            serialPort1.Close();
            but1.Text = "Connect";
            txtSend.Enabled = false;
            butSend.Enabled = false;
            txtComPort.Enabled = true;
            LogSerialData("Port closed");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

private void ReadSerialData()
{
    try
    {
        ReadSerialDataThread = new Thread(ReadSerial);
        ReadSerialDataThread.Start();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private void ReadSerial()
{
    while (serialPort1.IsOpen)
    {
        readSerialValue = serialPort1.ReadExisting();
        if (readSerialValue.Contains(waitValue)) 
        {
            LogSerialData("\r\nFound: " + waitValue + "\r\n"); 
            waitFound = true; 
        }
        LogSerialData(readSerialValue);
    }
}


private void waitfor(string wait)
{
    waitValue = wait;                   // global waitValue is checked in the threaded read method
    int i = 0;                          // timeout counter (which currently also fails)
    waitFound = false;                  // will be set true by the read method 
    LogSerialData(".");                 // console output to check if there's actually something happening 
    while (!waitFound && i <= 10)       // While one of the conditions is not met, keep on looping
    {
        LogSerialData(".");             // Another output check
        Thread.Sleep(100);              // Wait 100ms
        i++;                            // Increase fail counter
    }
}

Anyone able to give me a little push in the right direction in to solving this issue? The expected behaviour would be: send login text waitfor password request send password text waitfor login success / motd send serial request text waitfor serial#

etc. etc. etc.

Upvotes: 1

Views: 86

Answers (1)

Zilverdael
Zilverdael

Reputation: 21

Thanks to Mong Zhu I was able to find the awnser in async tasks.

    private async Task Waitfor(string wait)
    {
        waitValue = wait;                   // global waitValue is checked in the threaded read method
        waitFound = false;
        while (!waitFound)
        {
            await Task.Delay(50);
        }
        LogDataToLogBox("Wait successfull: " + readSerialValue);
    }

and to call it

serialPort1.WriteLine("login");
serialPort1.WriteLine("admin");
await Waitfor("complete!");

Thanks for the push in the right direction

Upvotes: 1

Related Questions