altera2015 / usbserial

Flutter Android USB Serial plugin
BSD 3-Clause "New" or "Revised" License
121 stars 83 forks source link

Data still present in stream after transaction done and disposed #39

Closed EParisot closed 3 years ago

EParisot commented 3 years ago

Hi, I faced a very anoying issue I can't figure out :

my code goes goes like :

// we are in a statefull widget

bool listening;

@override
void initState() {
    super.initState();
    listening= false;
}

Transaction<Uint8List> transaction_0;

Future<void> startStop() async {
  if (listening) {

      // stop listening
      transaction_0.dispose();

      // send the stop command to usb device (no answer to wait)
      Transaction<String> transaction_1 = Transaction.stringTerminated(
            usbPort.inputStream, Uint8List.fromList([13, 10]));
       await transaction_1.transaction(
            usbPort,
            Uint8List.fromList(("stop").codeUnits + [13, 10]),
            Duration(seconds: 1));
        // end this transaction_1
        transaction_1.dispose();

        listening= false;

  } else {

      // send some config commands to usb device witch will answer with confirmation
      Transaction<String> transaction_1 = Transaction.stringTerminated(
            usbPort.inputStream, Uint8List.fromList([13, 10])); // note the ending condition
       String response = transaction_1.transaction(
            usbPort,
            Uint8List.fromList(("config bla bla").codeUnits + [13, 10]),
            Duration(seconds: 1));
        // little check here, always returns the good value
        print(response);
        // end this transaction_1
        transaction_1.dispose();

        -------------> HERE I need to completely clear the data

      // start listening from  the device (terminated needed here because of the "<END>" termination)
      transaction_0= Transaction.terminated(
              usbPort.inputStream, Uint8List.fromList("<END>".codeUnits)); // this ending condition
      transaction_0.stream.listen((Uint8List data) {
            // do stuff like writing the data from usb to a file... HERE the problem append to be visible with previous data leaked to the file
      });

      // send the start command to usb device (no answer, just run...)
      await usbPort.write(Uint8List.fromList(("start").codeUnits + [13, 10]));

      listening= true;
  }
}

It all works great, ... on the first run... but if I stop the listening (from a button -> onTap: StartStop) and then restarts a new one, data leaks from the config response of transaction_1 to the transaction_0 and finish in my file where I write the return of transaction_0 ... but only after a first, clean run...

I tried flushing, disposing stream... nothing seems to prevent the data from being still disponible to transaction_0, after, transaction_1 already handled it... My guess is that the transaction_0 stream is never ended at all and just listen to every data disponible on the port...

How to dispatch, successively, data from a transaction (temporary) to another one (witch is more persistent) ?

EDIT: as a workaroud, I close the port and re-execute the connexion routine but this feels wrong...

altera2015 commented 3 years ago

That was a fun bug. I did find it and had to make a signature change to the Transaction and Transformation classes to fix. Please check the new test case for your issue:

https://github.com/altera2015/usbserial/blob/EmbeddingV2/test/transaction_test.dart#L65

EParisot commented 3 years ago

Hey thanks, I'll look at it ! Do you plan to update the package ?

altera2015 commented 3 years ago

The package was updated yesterday!

EParisot commented 3 years ago

That's a great new, I'll try it tomorrow !