FengChendian / serial_port_win32

A flutter SerialPort library using win32 API.
BSD 3-Clause "New" or "Revised" License
31 stars 9 forks source link

Port opens but can't read data #14

Closed Zopenzop closed 1 year ago

Zopenzop commented 2 years ago

I have confirmed that the connection between my laptop and my serial device is correct and working. But when using this package, I am able to get the port, open it but it never reads data. I have no idea why it is so. The baud rate and everything is just as it should be, and I am using the example project made by you. What could be the reason?

nirmalaranawat commented 2 years ago

I am facing similar issue. I am able to open and write to ports but not able to read the data. Facing the same issue with example code provided.

FengChendian commented 2 years ago

How much data do you read at a time?

Maybe:

  1. I just translated C++ code to dart interface. But win32 package is a little different from Win32 API. The num of read bytes needs to be the same as num of bytes you send. If you send 4 bytes data, but you read 5 bytes. Maybe you can not get data.

  2. ReadIntervalTimeout, ReadTotalTimeoutConstant,ReadTotalTimeoutMultiplier may not be suitable for your project。Please see https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts

    factory SerialPort(
    String portName, {
    // ignore: non_constant_identifier_names
    int BaudRate = CBR_115200,
    // ignore: non_constant_identifier_names
    int Parity = NOPARITY,
    // ignore: non_constant_identifier_names
    int StopBits = ONESTOPBIT,
    // ignore: non_constant_identifier_names
    int ByteSize = 8,
    // ignore: non_constant_identifier_names
    int ReadIntervalTimeout = 10,
    // ignore: non_constant_identifier_names
    int ReadTotalTimeoutConstant = 1,
    // ignore: non_constant_identifier_names
    int ReadTotalTimeoutMultiplier = 0,
    
    /// if you want open port when create instance, set [openNow] true
    bool openNow = true,
    })
  3. I use Duration(milliseconds: 1) to look up for reading data. But I think it should be ok for reading,.

nirmalaranawat commented 2 years ago

Thank you for response. In my application I do not know before hand the number of bytes I will be receiving. I tried sending a fixed length of data and read it on the app, but that did not happen either.

Zopenzop commented 2 years ago

@FengChendian At a time I receive 8-10 bytes of data. Also, if ReadIntervalTimeout, ReadTotalTimeoutConstant or ReadTotalTimeoutMultiplier are not suitable for my project, should I fork this repo and get rid of them?

FengChendian commented 2 years ago

@nirmalaranawat @Zopenzop I can get data correctly even though data size is larger than transmited by MCU. Do you have any small code example?

Now I update all dependcies to lastest version. You can try it again.

image
FengChendian commented 2 years ago

@FengChendian At a time I receive 8-10 bytes of data. Also, if ReadIntervalTimeout, ReadTotalTimeoutConstant or ReadTotalTimeoutMultiplier are not suitable for my project, should I fork this repo and get rid of them?

You can set them when create serial instance. Like

port = SerialPort(ports[0], openNow: false, ReadIntervalTimeout: 1, ReadTotalTimeoutConstant: 2);
wachidsusilo commented 2 years ago

Is there any solution for this? mine won't work either.

lesslefou commented 2 years ago

Is there any solution for this? mine won't work either.

Personnaly I didn't realise to make the code work so I change to the following librairy : flutter_libserialport.

wachidsusilo commented 2 years ago

@lesslefou Does flutter_libserialport works for you? I initially came to that library, but I thought this platform specific lib would be more stable on windows. may be i should go back to the initial plan.

lesslefou commented 2 years ago

Well I succeed to do what I want with this librairy. I just have to read data with a terminal before launching my application. I don't know why if I don't do that I receive strange data.

FengChendian commented 2 years ago

@wachidsusilo @lesslefou Do you have a whole project and I/O data example? I don't know why some people can't read data correctly. And other people can read proper data. It's confusing.

If a terminal can solve it, it may be due to internal typecasting or dart win32 API:

/// Typecasting
var u8l = lpBuffer.cast<Uint8>().asTypedList(_bytesRead.value);
/// -----------------------
/// Read Function of win32
ReadFile(handler!, lpBuffer, bytesSize, _bytesRead, _over);

And read function is so simple that I can't understand why data is wrong.

/// [_read] is a fundamental read function/
  Future<Uint8List> _read(int bytesSize) async {
    final lpBuffer = calloc<Uint16>(bytesSize);
    Uint8List uint8list;

    try {
      readOnBeforeFunction();
      ReadFile(handler!, lpBuffer, bytesSize, _bytesRead, _over);
    } finally {
      /// Uint16 need to be casted for real Uint8 data
      var u8l = lpBuffer.cast<Uint8>().asTypedList(_bytesRead.value);
      uint8list = Uint8List.fromList(u8l);
      free(lpBuffer);
    }

    return uint8list;
  }
wachidsusilo commented 2 years ago

@FengChendian may be the problem was in dart win32 API, as i used flutter_libserialport library and the problem still persist. It's working though, but i need to open the SerialPort on another program first.

Actually, while debugging i found interesting behaviour:

  1. Open Serial -> success
  2. Read Data -> nothing shown
  3. Write Data -> nothing sent
  4. Close Serial -> success
  5. Open Serial on another program -> The previously written data was sent immediately

May be this was due to NON_OVERLAPPED_IO thing? Currently i give up on this. I've changed the source file, so i cannot give you the example.

I create my own DLL using ILCompiler and NativeAOT on C# (DotNet). I wrote my own ffi implementation and it works as expected now.

By the way, you did a great job @FengChendian. The problem was on me. I was doing great on Kotlin, i'm regretting choosing this path (flutter) 😂

FengChendian commented 2 years ago

@wachidsusilo

Maybe due to OVERLAPPED_IO or win32 API.

I use OVERLAPPED_IO to get data in async mode. Otherwise the function WaitForSingleObject will enter blocking mode.Then UI will be freezed.

(⊙︿⊙) And if win32 API causes this problem, I think there is nothing I can do.

Zopenzop commented 2 years ago

@FengChendian I don't think it's the Win32 api. Anyways, I'll be back to working on my project once again and I'll revert back with how it turns out to work.

maiducgiang commented 2 years ago

Hi, I can't read the complete input message, in image first, I read fail, in image second, I read by app other image image

maiducgiang commented 2 years ago

that is my setup, sorry my english is bad image

FengChendian commented 2 years ago

Hi, I can't read the complete input message, in image first, I read fail, in image second, I read by app other image image

Does your message have '\0' ending? According to discussion, '\0' ending is important for message to be truncated by ReadFile Function. Although I don't know why 😢 And readBytesSize == messageSize(include '\0') is better.

maiducgiang commented 2 years ago

what can i do?

FengChendian commented 2 years ago

what can i do?

If you send 10 char, read 10bytes, not 100. And try add '\n' or '\0' in your message. In C

char message[5] = '1234'; // it is actually '1234\0'

uint8_t data[5] = {1, 2, 3, 4, 5}; // not ending with  '\0'

if it doesn't work, please try other package implemented by native C/C++ language. There might also be some bugs that I can't fix.

arcral commented 1 year ago

i also can't read any data. i think the read function has some serious bugs

FengChendian commented 1 year ago

i also can't read any data. i think the read function has some serious bugs

If you use readBytesOnce function, can you read anything? Or do you have any code to reproduce this bug?

There are some reports that the read function doesn't work properly, but I can't reproduce the bug on my computer. The biggest difference between the read and write functions is that read uses async and stream. I don't know if stream is causing this bug or win32 API init failed, or different Windows version.

FengChendian commented 1 year ago

I have confirmed that ClearCommError and PurgeComm causes the read bug. ClearCommError will return wrong cbInQue in some systems if PurgeComm has been executed.

Because PurgeComm may be processed after rx ready due to VM delay. (It should be processed before rx ready, and is ok in C++)

I have removed the stage of purge com in read function and tested it using ESP32. I think I have fixed this bug in version 1.1.0