edufolly / flutter_bluetooth_serial

A basic Flutter Bluetooth Serial
MIT License
477 stars 457 forks source link

Allow user to choose between normal and broadcast StreamController #74

Open FilippoZazzeroni opened 5 years ago

FilippoZazzeroni commented 5 years ago

I had to enter a page and opening a stream more times but i always got the error of bad state. I know that there are different ways to solve this issue, by either close the stream or make a broadcast controller. I actually solved the problem by modifying flutter ble serial library and change the controller they provided by a broadcast one. So i ask edufolly if it's possible for users to choose between those two configurations and if he might want to explain how to close correctly the stream, cause i tried and failed. Thank you all in advance for the help.

Steps to reproduce

if you want to add a broadcast controller to the library, you open the bluetooth connection sheet and modify the controller by adding the broadcast method.

AgainPsychoX commented 5 years ago

If you need to multiple listen, there is asBroadcastStream in core Dart Stream. Be aware, that these don't buffer - adding another listen allow to listen only further incoming data, not the whole that already were received before listening.

Please, tell me if it fit your needs.

By the way, the situation, when you need to multiple listen on some raw data stream might be app design flaw. I think you might want to have some shared object to manage "resource" like the remote device you are connecting to.

AgainPsychoX commented 5 years ago

@FilippoZazzeroni, please take a look and tell me if using asBroadcastStream fit your needs. If you need further help (including incorporating the solution), also feel free to ask.

FilippoZazzeroni commented 5 years ago

@PsychoXIVI sorry for the delayed answer. Btw i just solved the problem before posting here, by using as you suggested broadcast stream controller. My question was directed to @edufolly, if he could modify the library to allow users, to choose between normal or broadcast controller. my problem was solved by modifying edu's package so i asked.

AgainPsychoX commented 5 years ago

I don't quite understand why would you need to modify the library itself, since asBroadcastStream can be used directly on input.

I imagine example case like you described: there is app with 3 screens:

In such app, there can not be multiple listens to the raw connection input - it would cause bad state, because of re-listening to non-broadcast stream. In such case, there must be asBroadcastStream applied, as I mentioned. To solve the problem, in the main page there should be separate Stream broadcastDataStream field initialized after connection using broadcastDataStream = _connection.input.asBroadcastStream(). Then it should be passed to to both hex and decimal reader pages while entering these, where listening to this broadcasting stream is required.

Please note, that this is only simple example, and in more advanced applications even better solution might be to have separated and shared between pages model for all Bluetooth communications.

Ideal design would be not over-implementing extension, which is easily implementable if there is additional cost for default thing. On other hand, it might be somewhat easier to just have even simpler way of doing this 🤔 And whole Dart isn't "ideal" also at all...

FilippoZazzeroni commented 5 years ago

thank you @PsychoXIVI. I actually tried your way before but i might did it in the wrong way. i'm in accord with you that dart could be easier than it is and some time more clear.

FilippoZazzeroni commented 5 years ago

ah @PsychoXIVI sorry for disturbing you, but i got other question. i really didn't get it how to close stream properly. in my case i'm sending credentials to arduino with a button and after i open stream to read the connection status from the board. the problem is to close the connection every time i 've done the check.

AgainPsychoX commented 5 years ago

You can close connection by either:

Also, please note, that you should invoke connection.dispose() on disposal (like on exiting the page which contains the connection object, or exiting whole app if there is global model which contains the connection object). This method is intended to make sure that all resources are freed.

If you want notify remote device that you are disconnecting, I think you might also send some specific data just before disconnection too. If you are using something like HC-05 Bluetooth for Arduino module, which works like serial port, you might be unable to tell otherwise is device disconnected, since (as far I know) HC-05 cannot notify your board that it was disconnected (well there is LED which blinks fast if you are disconnected, but it might be unreliable).

For future, please feel free to open another issue even for such question.

FilippoZazzeroni commented 5 years ago

Thank you so much @PsychoXIVI, i actually used connection.close() it worked perfectly for closing bluetooth connection, but the connection.output.close() didn't work, the stream is always on read and as i try this method nothing happen, it continue to read untill i close bluetooth connection.

AgainPsychoX commented 5 years ago

but the connection.output.close() didn't work

That could be because of your modification (broadcasted streams are not likely to be closed that way afik).

FilippoZazzeroni commented 5 years ago

ah ok I'll try to restore it, and let you know