reconnect with server each 5 seconds by dart - flutter

i try to reconnect with the server , the connection established very well and it work every 5 sec very well also , but when i put a condiotn to control the conection it not working and still get new conection added , new connection added
how can i implement this by dart
var nbmer = 0;
var channel;
Timer? timer;
connect() {
Socket.connect(IP, PORT).then((Socket sock) async {
channel = sock;
sock.write('hello world'
);
});
}
try {
if (nbmer == 0) {
timer = Timer.periodic(Duration(seconds: 5), (Timer t) => connect());
}
} catch (e) {
print(e.toString());
}
nbmer += 1;

You should put your condition in the connect() function, because Timer.periodic will be periodically executed and not check your condition (if (nbmer == 0)).
Solution
Your code should look something like this:
var nbmer = 0;
var channel;
Timer? timer;
connect() {
if (nbmer == 0) {
nbmer += 1;
Socket.connect(IP, PORT).then((Socket sock) async {
channel = sock;
sock.write('hello world');
});
}
}
try {
timer = Timer.periodic(Duration(seconds: 5), (Timer t) => connect());
} catch(e) {
print(e.toString());
}

Related

flutter_libserialport write OK but read unhandled exception

I'm trying to implement a simple at cmd application.
I modified the flutter_libserialport example.
https://pub.dev/packages/flutter_libserialport
simply,
replace the floatButton action to my own reTest() function
floatingActionButton: FloatingActionButton(
child: Icon(Icons.refresh),
// onPressed: initPorts,
onPressed: rwTest,
),
and my rwTest below,
Future<void> rwTest() async {
for (var p in availablePorts) {
if (p == 'COM115') {
print(p);
List<int> d = [65, 84, 13];
Uint8List bytes = Uint8List.fromList(d);
SerialPort port = SerialPort(p);
SerialPortReader reader = SerialPortReader(port, timeout: 10000);
try {
port.openReadWrite();
print(port.write(bytes));
await reader.stream.listen((data) {
print('received : $data');
});
port.close();
} on SerialPortError catch (_, err) {
if (port.isOpen) {
port.close();
print('serial port error');
}
}
}
}
}
my device is shown as COM115 so I put the fixed value.
and the "write" operation was success
but when I use "reader.stream.listen()"
SerialPortError occurs as below
flutter: COM115
flutter: 3
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: SerialPortError: ÀÛ¾÷À» ¿Ï·áÇß½À´Ï´Ù., errno = 0
I guess the usage of "listen" was wrong, but I don't know how to fix it.
anyone can help me to fix it?
You just need to remove the port.close() in try{} ... and I think you should also set the timeout = 1,
Also, it is better to set a configuration before using the port
Note: you can just access the port through name, without looping over all the available ports.
Future<void> rwTest() async {
List<int> d = [65, 84, 13];
Uint8List bytes = Uint8List.fromList(d);
SerialPort port = SerialPort('COM115');
// configuration
final configu = SerialPortConfig();
configu.baudRate = 9600;
configu.bits = 8;
configu.parity = 0;
port.config = configu;
SerialPortReader reader = SerialPortReader(port, timeout: 10);
try {
port.openReadWrite();
print(port.write(bytes));
await reader.stream.listen((data) {
print('received : $data');
});
} on SerialPortError catch (_, err) {
if (port.isOpen) {
port.close();
print('serial port error');
}
}
}
The serial port need to open as far as the communication is active to send and receive data
Remove the port close method call
try {
port.openReadWrite();
print(port.write(bytes));
await reader.stream.listen((data) {
print('received : $data');
});
//port.close(); --> remove this line
}
On exit close the reader stream and then close the port

Flutter: Timer timer cannot end previous session with timer.cancel()?

when I call timer.cancel (), the clock stops working. But when calling back to start a new session, I discover that the _u variable in the old session still counts from itself and parallel with new one.
Please help !
startTime(60);
timer.cancel();# It worked.
timer = null;
startTime(60);# but when recall. It working with 2 session. (old and new)
//Call timer.cancel() _u variable stop at 40.
//Recall startTime() _u variable counts with 2 session (40) and (60)
startTime(reset){
int _u = reset;
const oneSec = const Duration(seconds: 1);
timer = Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (_u < 1) {
timer.cancel();
// call my handle
} else {
_u = _u -1;
if(_u <0){
timer?.cancel();
}
}
},
),
);
Cancel the timer if it is not null. The code below was tested
void startTime(reset) {
int _u = reset;
const oneSec = const Duration(seconds: 1);
if (timer != null) {
timer.cancel();
}
timer = Timer.periodic(oneSec, (Timer t) {
if (_u < 1) {
t.cancel();
// call my handle
} else {
_u = _u - 1;
print(_u);
if (_u < 0) {
t?.cancel();
}
}
});
}

Flutter audioplayers triggers onComplete event before the track is actually completed

I am trying to achieve a direct task, I want to autoplay the next track after the current track finishes, but sometimes the onComplete event is triggered before even the track is completed which lead to skip one of the tracks
the package I am using is: audioplayers ^0.14.2
the tracks are fetched from the database they are not local tracks
void play(List<SoundTrack> tracks){
audioPlayer.play(tracks[currentIndex].url);
setIsTalking = true;
audioPlayer.onPlayerCompletion.listen((event) {
if(currentIndex < tracks.length-1) {
next(tracks);
} else {
audioPlayer.release();
setIsTalking = false;
setPlayerState = PlayerState.paused;
}
print('completed this track, current index is' + currentIndex.toString());
});
}
void next(List<SoundTrack> tracks){
setCurrentIndex = currentIndex +1;
play(tracks);
}```
Try something like this:
define
int currentIndex = 0;
and
play(List<String> urlList, int currentIndex) async {
int result = await audioPlayer.play(urlList[currentIndex]);
if (result == 1) {
print('Success: is playing');
} else {
print('Error on audio play');
}
audioPlayer.onPlayerCompletion.listen((event) {
if(currentIndex < urlList.length-1){
currentIndex = currentIndex + 1;
nextTrack(urlList, currentIndex);
print("NEXT AUDIO! $currentIndex");
} else {
print("AUDIO COMPLETED PLAYING");
}
});
}
void nextTrack(List<String> urlList, int currentIndex) {
play(urlList, currentIndex);
}
In your play botton you call
nextTrack(urlList, currentIndex)
I tested and for me it is working.

How to use Dart socket onError as inline function?

I have dart socket that gets very long data. Lucky the third party add '\r\n' end of the data, so I can close when I find last data has '\r\n'.
In weeks I am trying to get long data due server problem. Before I used to waiting endlessly to server closes the connection (sometime took me 10 to 12 min)
Now seems everything works but a small problem. I used to get onError and onDone using void function. But I am using aqueduct so I need to return long data after I receive from server as a response.
In my below full code its keep printing "Server_Error". If I comment below data seems everything works. But my problem is that I need to return error data as well.
onError: () {
print("Server_Error");
},
onDone: () {
_socket.destroy();
},
cancelOnError: true);
If I comment above part I can print the long data.
My question is that, based on my scenario how to use Dart socket onError as inline function?
import 'dart:io';
import 'dart:convert';
import 'dart:typed_data';
Socket _socket;
String _reply;
String _testValue = "";
main() async {
String _queryA = “QueryLongData”;
await Socket.connect("192.168.22.120”, 3000).then((Socket sock) {
_socket = sock;
_socket.write('$_queryA\r\n');
_socket.listen((data) {
final List<int> byteArray = data;
_reply = String.fromCharCodes(byteArray);
int dataLen = _reply.length;
int carriageReturnPosition = dataLen - 2;
int newLinePosition = dataLen - 1;
_testValue = _testValue + _reply;
if (_reply.substring(carriageReturnPosition, newLinePosition) == '\r' &&
_reply.substring(newLinePosition, dataLen) == '\n') {
_socket.close();
print("Data: $_testValue"); // means return data
}
}, onError: () {
print("Server_Error");
},
onDone: () {
_socket.destroy();
},
cancelOnError: true);
}).catchError((e) {
print("Server_Error");
});
if(_socket.done == true) {
print("Exiting...");
exit(0);
}
}
<!-- language: dart -->
String _queryA = "QueryLongData";
Socket.connect("192.168.22.120", 3000).then((Socket sock) {
_socket = sock;
_socket.write("$_queryA\r\n");
_socket.listen((data) {
final List<int> byteArray = data;
_reply = String.fromCharCodes(byteArray);
int dataLen = _reply.length;
int carriageReturnPosition = dataLen - 2;
int newLinePosition = dataLen - 1;
_testValue = _testValue + _reply;
if (_reply.substring(carriageReturnPosition, newLinePosition) == "\r" &&
_reply.substring(newLinePosition, dataLen) == "\n") {
_socket.close();
print("Data: $_testValue"); // means return data
}
}, onError: () => print("Server_Error"),
onDone: () => _socket.destroy(),
cancelOnError: true);
}).catchError((e) => print("Server_Error"));
if( ( await _socket.done enter code here) == true) {
print("Exiting...");
exit(0);
}

Dart HTML Server. How do I have the server refuse more than one client connection?

I'm writing a web application that is to be used by only one client and want to accept only one connection to the server. The LAN will be confined to an aircraft. I'm really new to Dart, HTML etc. How can I refuse multiple connections to the server?
Here's my code fir the HTTP server -
class MicroServer {
var address;
var port;
var httpServer; // global
MicroServer(this.address, this.port) {
final HTTP_ROOT_PATH = Platform.script.resolve('../build/web').toFilePath();
final virDir = new VirtualDirectory(HTTP_ROOT_PATH)
..jailRoot = false
..allowDirectoryListing = true;
HttpServer.bind(address, port)
.then((httpserver) {
httpServer = httpserver;
httpserver.listen((request) {
virDir.serveRequest(request);
});
});
}
}
Dart is single-threaded, so you can safely use check a variable to see if there's a current connection:
bool hasClient = false;
HttpServer.bind(address, port)
.then((httpserver) {
httpServer = httpserver;
httpserver.listen((request) {
if (hasClient) {
sendBusyPage(request);
} else {
hasClient = true;
virDir.serveRequest(request);
hasClient = false;
}
});
});
}
I have found that the code below works so far. I could also have taken advantage of
if(request.session.isNew) // then grab the session.id etc.
but it's just as easy to use the session.id variable since I will use it anyway.
class MicroServer {
var address;
var port;
var httpServer;
var sessionID; // null until first request received
MicroServer(this.address, this.port) {
final HTTP_ROOT_PATH = Platform.script.resolve('../build/web').toFilePath();
final virDir = new VirtualDirectory(HTTP_ROOT_PATH)
..jailRoot = false // process links will work
..followLinks = true
..allowDirectoryListing = true;
HttpServer.bind(address, port)
.then((httpserver) {
httpServer = httpserver;
httpserver.idleTimeout = null;
print("micro server started on ${httpserver.address}:${httpserver.port}");
httpserver.listen((request) {
if(sessionID == null) {
sessionID = request.session.id;
virDir.serveRequest(request);
} else if(sessionID == request.session.id){
virDir.serveRequest(request);
} else {
request.response.writeln('ERROR - Connection is in use.');
request.response.close();
request.session.destroy();
}
});
}).catchError((e) => print(e.toString()));
}
}