jcurl / RJCP.DLL.SerialPortStream

SerialPortStream is an independent implementation of System.IO.Ports.SerialPort and SerialStream for better reliability and maintainability. Default branch is 2.x and now has support for Mono with help of a C library.
Microsoft Public License
624 stars 197 forks source link

Values written to serial are echoed back? #73

Closed RussellHaley closed 5 years ago

RussellHaley commented 5 years ago

Hi, I'm just reading and writing to serial and my input is being echoed back in my DataReceived delegate. What silly thing have I done wrong? I'm reviewing your test code for examples of using the library. Is there a better source of sample code (e.g for stealing rather than learning. lolz)?

using System;
using System.Text;
using RJCP.IO.Ports;

namespace rs232Testing
{
    class Program
    {
        static void Main(string[] args)
        {
            string com = "COM4";
            //Console.WriteLine("{0}, {1}", args[0], args[1]);
            byte[] readBuffer = new byte[8192];
            byte[] writeBuffer = new byte[8192];

            using (SerialPortStream src = new SerialPortStream(com, 115200))
            {
                bool running = true;
                src.Open();

                int totalBytes = 0;
                src.DataReceived += (s, e) =>
                {

                    int bytes = src.Read(readBuffer, 0, readBuffer.Length);
                    byte[] buf = new byte[bytes];
                    Buffer.BlockCopy(readBuffer, 0, buf, 0, bytes);  
                    totalBytes += bytes;
                    Console.WriteLine(Encoding.ASCII.GetString(buf));
                    //Console.WriteLine("===> EventType: {0}, bytes read = {1}, total read = {2}", e.EventType, bytes, totalBytes);
                    //if (totalBytes >= testTotalBytes) finished.Set();
                };
                src.ErrorReceived += (s, e) =>
                {
                    Console.WriteLine("===> EventType: {0}", e.EventType);
                };

                Console.WriteLine("Hello World!");
                string input;
                while (running)
                {
                    input = Console.ReadLine();
                    if(input != "q")
                    {
                        src.Write(input + "\n");
                    }
                    else
                    {
                        running = false;
                    }
                }

            }
        }
    }
}
jcurl commented 5 years ago

I can confirm that the problem doesn't occur on my development bench. I modified it to run in NUnit, replaced input = Console.ReadLine() with input = "Test String" and delay 500ms before sending. In the test below, we should have see the string 20 times if it was a problem in the implementation of SerialPortStream.

I use COM1, because nothing is attached to that, to ensure no "listening" device is echoing. We see no echo in the output logs.

You can see the write occurring regularly.

Now, you don't say what is on COM4, but if it's a modem, I would expect to see echo. That's how modems are built, until you give ATE0 (or something similar).

------ Discover test started ------
NUnit VS Adapter 2.1.1.0 discovering tests is started
NUnit VS Adapter 2.1.1.0 discovering test is finished
========== Discover test finished: 94 found (0:00:00.1720772) ==========
------ Run test started ------
NUnit VS Adapter 2.1.1.0 executing tests is started
Loading tests from C:\Users\jcurl\Documents\Programming\HELIOS\serialportstream\test\SerialPortStreamTest\bin\Debug\RJCP.SerialPortStreamTest.dll
Run started: C:\Users\jcurl\Documents\Programming\HELIOS\serialportstream\test\SerialPortStreamTest\bin\Debug\RJCP.SerialPortStreamTest.dll
Hello World!
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157352, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157364, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157376, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157388, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157400, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157412, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157424, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157436, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157448, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157460, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157472, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157484, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157496, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157508, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157520, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157532, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157544, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157556, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: DoWriteEvent: WriteFile(2652, 70157568, 12, ...) == False
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: CommEvent: EV_TXEMPTY
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: 12 bytes
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: ProcessWriteEvent: TX-BUFFER empty
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: OverlappedIO: Stopping Thread
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: OverlappedIO: Waiting for Thread
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: SerialThread: Thread closing
IO.Ports.SerialPortStream Verbose: 0 : 
COM1: OverlappedIO: Thread Stopped
NUnit VS Adapter 2.1.1.0 executing tests is finished
========== Run test finished: 1 run (0:00:11.0205821) ==========
RussellHaley commented 5 years ago

Hi there, sorry I dropped the ball on this; I got busy at work and then got distracted. I'm seeing my information echoed back to me when I have a Linux shell at the other end of the serial cable when using an Arm development board. This may be "normal behavior" but I'm just not sure.

Steps: 1) Use putty to open a serial console to my Beagle Bone Black with Arch Linux on it. I log into a shell and then close the console, which leaves the shell open. 2) On my host laptop (Windows), I open my console application that uses SerialPortStream. To call src.write(...) I append the console input with '>'.
3) I have a little lua script on the Linux side that I start. The lua script just reads stdin and the writes "I Got" + input.

Here is an example of what I see. My input is preceded with ">". Note that there is an "echo" every time I send something, even when the lua script is running (which should have no output except "I Got...").

>ls
ls
base64.lua           crc32.lua    msg-test.lua  mylog.log    testing.lua
chirpy-messages.lua  logging.lua  msgs.tar      serpent.lua
[alarm@alarm msg-test]$ >lua testing.lua
lua testing.lua
>This is a message
This is a message
I Got This is a message

The application is here: https://github.com/RussellHaley/NLuaSerialConsole/blob/master/NLuaSerialConsole/LuaConsole.cs

with the relevant pieces here (setting up the event handler): https://github.com/RussellHaley/NLuaSerialConsole/blob/master/NLuaSerialConsole/LuaConsole.cs#L23-L36

and here (writing to the serial port): https://github.com/RussellHaley/NLuaSerialConsole/blob/master/NLuaSerialConsole/LuaConsole.cs#L151-L160

My lua application is just this loop:

local answer = q
repeat
        io.flush()
        msg=io.read()
        if msg == 'q' then return 1 end
        print('I Got ' .. msg)
until answer=="y" or answer=="n"

Any thoughts on what I'm doing wrong? Thanks in advance.

jcurl commented 5 years ago

Sorry for the delay. Are you sure the console on the remote side isn't echoing? For "terminals", I would always expect that characters which are sent are echoed back, except when entering passwords. Perhaps there's a terminal option to turn off the echo from the remote side?

jcurl commented 5 years ago

I looked at Windows documentation (https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_dcb) and there is nothing to enable echo. On Linux, the echo is disabled. That means it is your terminal that you're speaking to (the remote side) that is turning on Echo. If you're using a terminal program, it may be that it's sending some specific commands. You'd have to sniff the serial port to see what the difference is.

RussellHaley commented 5 years ago

Hey thanks for looking at that. I finally got my hands on a null modem cable and there is no echo when I open my application on one end and putty on the other (which means nothing wrong with my code). The serial port I'm using is the root terminal so maybe that's causing it?

I'll carry on because this isn't my main use case. If I find anything definitive I'll post here. I wonder if the wireshark usb plugin would help?

I appreciate your help! Russ

jcurl commented 5 years ago

Hello, what you need is to sniff the protocol over the serial connection. So a WireShark trace is useful if you can extract the content of what is being sent/received. You've confirmed that it is not the software you've written (a null modem shows no echo), so it must be the remote terminal, it may have received a command to enable echo.