FengChendian / serial_port_win32

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

Read time too much when scanner scanned a barcode. #20

Closed Abduraimbek closed 10 months ago

Abduraimbek commented 1 year ago

Thanks for great work. I have problem with scanning barcode. When I scan a barcode with scanner, readBytesOnListen fires after 1 to 2 seconds. What should I do? Thanks for solution.

FengChendian commented 1 year ago

What is the size of your data?If data is large, higher baudrate is better.

And async functions may be delayed due to other program.

There some para which you can set: ReadIntervalTimeout, ReadTotalTimeoutConstant,ReadTotalTimeoutMultiplier

Please see https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts

 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 = 10,

    /// if you want open port when create instance, set [openNow] true
    bool openNow = true,
  })

And I use for-loop lookup function to yield data with stream. If I/O Flag is set, WaitForSingleObject will be called up to 500 times with 1ms lookup duration until transmission is done.

I don't know if changing this parameter will solve your problem. But it does take up CPU time.

 /// look up I/O event and read data using stream
  Stream<Uint8List> _lookUpEvent(Duration interval) async* {
    int event = 0;
    Uint8List data;
    PurgeComm(handler!, PURGE_RXCLEAR | PURGE_TXCLEAR);
    while (true) {
      await Future.delayed(interval);
      event = WaitCommEvent(handler!, _dwCommEvent, _over);
      if (event != 0) {
        ClearCommError(handler!, _errors, _status);
        if (_status.ref.cbInQue < _readBytesSize) {
          data = await _read(_status.ref.cbInQue);
        } else {
          data = await _read(_readBytesSize);
        }
        if (data.isNotEmpty) {
          yield data;
        }
      } else {
        if (GetLastError() == ERROR_IO_PENDING) {
          /// For Loop 
          for (int i = 0; i < 500; i++) {
            if (WaitForSingleObject(_over.ref.hEvent, 0) == 0) {
              ClearCommError(handler!, _errors, _status);
              if (_status.ref.cbInQue < _readBytesSize) {
                data = await _read(_status.ref.cbInQue);
              } else {
                data = await _read(_readBytesSize);
              }
              if (data.isNotEmpty) {
                yield data;
              }
              ResetEvent(_over.ref.hEvent);
              break;
            }
            ResetEvent(_over.ref.hEvent);
            await Future.delayed(interval);
          }
        }
      }
    }
  }
Abduraimbek commented 1 year ago

My barcode data as following: AB5229874445395 478999283349943

Thank you for attantion. But I found following in the package:

 SerialPort._internal(
    this.portName,
    this._portNameUtf16, {
    // ignore: non_constant_identifier_names
    required int BaudRate,
    // ignore: non_constant_identifier_names
    required int Parity,
    // ignore: non_constant_identifier_names
    required int StopBits,
    // ignore: non_constant_identifier_names
    required int ByteSize,
    // ignore: non_constant_identifier_names
    required int ReadIntervalTimeout,
    // ignore: non_constant_identifier_names
    required int ReadTotalTimeoutConstant,
    // ignore: non_constant_identifier_names
    required int ReadTotalTimeoutMultiplier,
    required bool openNow,
  }) {
    dcb
      ..ref.BaudRate = BaudRate
      ..ref.Parity = Parity
      ..ref.StopBits = StopBits
      ..ref.ByteSize = ByteSize;
    commTimeouts
      ..ref.ReadIntervalTimeout = 10
      ..ref.ReadTotalTimeoutMultiplier = 10
      ..ref.ReadTotalTimeoutConstant = 1;
    if (openNow) {
      open();
    }
  }

If I set values, it constructs with default values. Or am I thinking wrong?

FengChendian commented 1 year ago

@Abduraimbek I test the barcode data with virtual serial port driver. I send data from COM6. Then I can get data immediately in COM5. The delay is about max 10ms. Are you sure that your device has no hardware delay?

image

About parameters: I mean that you can change the default to other values.

Abduraimbek commented 1 year ago

Thanks for the reply. I will try with other new scanners.

FengChendian commented 10 months ago

I have change code to improve read performance. Now read latency drops.

Updates will be released in version 1.2.0