Unable to connect with Mqtt using wss protocol - flutter

I want to connect mqtt using wss protocol.
What have I tried ->
import 'dart:async';
import 'dart:io';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
final client = MqttServerClient('wss://myServer.com/mqtt', '');
Future<int> main() async {
client.useWebSocket = true;
client.port = 8083;
client.logging(on: true);
client.keepAlivePeriod = 20;
client.onDisconnected = onDisconnected;
client.onConnected = onConnected;
client.onSubscribed = onSubscribed;
client.pongCallback = pong;
final connMess = MqttConnectMessage()
.withClientIdentifier('Mqtt_MyClientUniqueId')
.keepAliveFor(20)
.withWillTopic('willtopic')
.withWillMessage('My Will message')
.startClean()
.withWillQos(MqttQos.atLeastOnce);
print('EXAMPLE::Mosquitto client connecting....');
client.connectionMessage = connMess;
try {
await client.connect();
} on NoConnectionException catch (e) {
print('EXAMPLE::client exception - $e');
client.disconnect();
} on SocketException catch (e) {
print('EXAMPLE::socket exception - $e');
client.disconnect();
}
/// Check we are connected
if (client.connectionStatus.state == MqttConnectionState.connected) {
print('EXAMPLE::Mosquitto client connected');
} else {
print(
'EXAMPLE::ERROR Mosquitto client connection failed - disconnecting, status is
${client.connectionStatus}');
client.disconnect();
exit(-1);
}
print('EXAMPLE::Subscribing to the test/lol topic');
const topic = 'test/lol';
client.subscribe(topic, MqttQos.atMostOnce);
client.updates.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final MqttPublishMessage recMess = c[0].payload;
final pt =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
print(
'EXAMPLE::Change notification:: topic is <${c[0].topic}>, payload is <-- $pt -->');
print('');
});
client.published.listen((MqttPublishMessage message) {
print(
'EXAMPLE::Published notification:: topic is ${message.variableHeader.topicName}, with Qos ${message.header.qos}');
});
const pubTopic = 'Dart/Mqtt_client/testtopic';
final builder = MqttClientPayloadBuilder();
builder.addString('Hello from mqtt_client');
print('EXAMPLE::Subscribing to the Dart/Mqtt_client/testtopic topic');
client.subscribe(pubTopic, MqttQos.exactlyOnce);
print('EXAMPLE::Publishing our topic');
client.publishMessage(pubTopic, MqttQos.exactlyOnce, builder.payload);
print('EXAMPLE::Sleeping....');
await MqttUtilities.asyncSleep(120);
print('EXAMPLE::Unsubscribing');
client.unsubscribe(topic);
await MqttUtilities.asyncSleep(2);
print('EXAMPLE::Disconnecting');
client.disconnect();
return 0;
}
void onSubscribed(String topic) {
print('EXAMPLE::Subscription confirmed for topic $topic');
}
void onDisconnected() {
print('EXAMPLE::OnDisconnected client callback - Client disconnection');
if (client.connectionStatus.disconnectionOrigin ==
MqttDisconnectionOrigin.solicited) {
print('EXAMPLE::OnDisconnected callback is solicited, this is correct');
}
exit(-1);
}
void onConnected() {
print(
'EXAMPLE::OnConnected client callback - Client connection was sucessful');
}
void pong() {
print('EXAMPLE::Ping response client callback invoked');
}
and I get below response in logs
EXAMPLE::Mosquitto client connecting....
I/flutter (17123): 1-2021-01-27 15:15:27.085221 -- MqttConnectionHandlerBase::connect - server wss://myServer.com/mqtt, port 1883
I/flutter (17123): 1-2021-01-27 15:15:27.103638 -- SynchronousMqttServerConnectionHandler::internalConnect entered
I/flutter (17123): 1-2021-01-27 15:15:27.104865 -- SynchronousMqttServerConnectionHandler::internalConnect - initiating connection try 0, auto reconnect in progress false
I/flutter (17123): 1-2021-01-27 15:15:27.107198 -- SynchronousMqttServerConnectionHandler::internalConnect - websocket selected
I/flutter (17123): 1-2021-01-27 15:15:27.110498 -- SynchronousMqttServerConnectionHandler::internalConnect - calling connect
I/flutter (17123): 1-2021-01-27 15:15:27.117350 -- MqttWsConnection::connect - entered
I/flutter (17123): 1-2021-01-27 15:15:27.168054 -- MqttWsConnection::connect - WS URL is wss://myServer.com:1883/mqtt, protocols are [mqtt, mqttv3.1, mqttv3.11]
I/flutter (17123): 1-2021-01-27 15:17:37.221102 -- MqttConnectionBase::_onError - calling disconnected callback
I/flutter (17123): EXAMPLE::socket exception - SocketException: OS Error: Connection timed out, errno = 110, address = myServer.com, port = 32892
I/flutter (17123): 1-2021-01-27 15:17:37.243831 -- MqttConnectionHandlerBase::disconnect - entered
I/flutter (17123): 1-2021-01-27 15:17:37.245454 -- MqttConnectionHandlerBase::_performConnectionDisconnect entered
I/flutter (17123): EXAMPLE::OnDisconnected client callback - Client disconnection

it made me tired but this code is working
please don't 'secure = true'
this is set to 'web socket base'
class MqttConnection {
static MqttConnection? _mqttConnection;
static MqttServerClient? _mqttClient;
MqttConnection._() {
_mqttClient =
MqttServerClient("wss://your domain/", "flutter_client");
_mqttClient!.port = 9001;
_mqttClient!.keepAlivePeriod = 20;
_mqttClient!.autoReconnect = true;
_mqttClient!.onConnected = _mqttConnected;
_mqttClient!.onDisconnected = _mqttDisconnected;
_mqttClient!.useWebSocket = true;
_mqttClient!.logging(on: true);
}
static MqttConnection getInstanse() {
if (_mqttConnection != null) return _mqttConnection!;
if (_mqttConnection == null) _mqttConnection = MqttConnection._();
return _mqttConnection!;
}
Future connectMqtt() async {
final MqttConnectMessage connMess = MqttConnectMessage()
.authenticateAs(ApiConstant.mqttUser, ApiConstant.mqttPassword)
.withClientIdentifier((await _getDeviceId())!)
.withWillQos(MqttQos.atLeastOnce)
.startClean();
_mqttClient!.connectionMessage = connMess;
_mqttClient!.securityContext.setTrustedCertificatesBytes(
(await rootBundle.load("assets/cert/bundle.crt")).buffer.asUint8List());
var connection = await _mqttClient!.connect();
isConnect = connection!.state == MqttConnectionState.connected;
_mqttClient!.updates!.listen(mqttEventRecived);
}
Function? callback;
bool isConnect = false;
bool tryToConnect = true;
void stopMqtt() {
tryToConnect = false;
_mqttClient!.disconnect();
isConnect = false;
}
subscribeTopics(List<String> topics) async {
if (!isConnect) {
await connectMqtt();
}
for (var topic in topics) {
_mqttClient!.subscribe(topic, MqttQos.atLeastOnce);
}
}
unSubscribeTopics(List<String> topics) {
for (var topic in topics) {
_mqttClient!.unsubscribe(topic);
}
}
void _mqttConnected() {
print("connected");
isConnect = true;
}
void _mqttDisconnected() {
isConnect = false;
}
Future<void> mqttEventRecived(event) async {
if (callback != null) {
}
}
}

Related

How to show Unhandled Exception message to View FLUTTER

How to show this message to view? so that the user knows that the connection cannot connect to the server
this my socket connection code :
Socket.connect(pIp, port, timeout: const Duration(seconds: 5))
.then((socket) {
_channel = socket;
_isOn = true;
if (pWithdata.isNotEmpty) {
if (_channel != null) {
send(pWithdata);
// submitMessage("LOGIN#xXYjY`#Uf]bXcMM#FFHE#V30#V901");
}
}
socket.listen(
(onData) {
_isOn = true;
_listeners.forEach((Function callback) {
// callback(onData);
callback(String.fromCharCodes(onData).trim());
});
},
onDone: onDone,
onError: onError,
);
});

Flutter: Unhandled Exception: SocketException: Connection reset by peer (OS Error: Connection reset by peer, errno = 104), address = xxxxx, port = xxx

I'm trying to load messages every 2 second, it works but it's returning Unhandled Exception: SocketException: Connection reset by peer (OS Error: Connection reset by peer, errno = 104), address = xxxxx, port = xxx, after a while. thinking the error is from my hosting but in my digital Ocean dashboard I have not exceeded 15% RAM, 3% CPU.
void refresh() async {
isOnline = userOnline(widget.user.lastVisit);
const onesec = Duration(seconds: 2);
timer = Timer.periodic(onesec, (timer) {
loadMessages();
});
}
loadMessages() async {
getMessages().then((messages) async {
_messageController.add(messages);
return messages;
});
}
Future<List<dynamic>> getMessages() async {
List<dynamic> messages = [];
ApiResponse response = await chatRepo.getChats(id: chatId!);
if (response.error == null) {
messages = response.data as List<dynamic>;
}
return messages;
}
class ChatRepo {
Future<ApiResponse> getChats({required int id}) async {
ApiResponse apiResponse = ApiResponse();
try {
final response =
await http.get(Uri.parse(chatUrl + "/$apiKey/$id"), headers: {
'Accept': 'application/json',
});
switch (response.statusCode) {
case 200:
apiResponse.data = jsonDecode(response.body)['chats']
.map((p) => ChatMessageTile.fromJson(p))
.toList();
apiResponse.data as List<dynamic>;
break;
case 401:
apiResponse.error = unauthorized;
break;
default:
apiResponse.error = somethingWentWrong;
break;
}
} catch (e) {
apiResponse.error = serverError;
debugPrint(e.toString());
}
return apiResponse;
}
}

I'm having trouble connecting to mqtt in flutter?

I'm having trouble connecting to mqtt in flutter. I can't connect. The code I am using is as follows.
import 'package:mqtt_client/mqtt_server_client.dart';
late MqttServerClient client;
// ignore: camel_case_types
class mqttconnect {
Future<MqttServerClient> connect() async {
try {
client =
MqttServerClient.withPort('broker.emqx.io', 'flutter_client', 1883);
client.logging(on: true);
client.onConnected = onConnected;
client.onDisconnected = onDisconnected;
} catch (e) {
print(e.toString());
}
try {
await client.connect();
} catch (e) {
print('Exception: $e');
client.disconnect();
}
return client;
}
void onConnected() {
print('object');
}
void onDisconnected() {}
}
While trying to connect to mqtt, I get an error as above in the console. How can I fix.
import 'dart:convert';
import 'dart:developer';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
late MqttServerClient client;
mqttSubscribe() async {
client = MqttServerClient.withPort("broker.emqx.io", "daly", 1883);
client.keepAlivePeriod = 30;
client.autoReconnect = true;
await client.connect().onError((error, stackTrace) {
log("error -> " + error.toString());
});
client.onConnected = () {
log('MQTT connected');
};
client.onDisconnected = () {
log('MQTT disconnected');
};
client.onSubscribed = (String topic) {
log('MQTT subscribed to $topic');
};
if (client.connectionStatus!.state == MqttConnectionState.connected) {
client.subscribe("battery", MqttQos.atMostOnce);
client.updates!.listen((List<MqttReceivedMessage<MqttMessage?>>? c) {
final recMess = c![0].payload as MqttPublishMessage;
final pt = MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
log("message payload => " + pt);
});
}
}
import 'dart:async';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
class MqttService{
MqttService._();
/// Our mqtt client object.
static late MqttClient client;
// for listen from other pages.
// and can close listen mqtt.
static StreamSubscription? mqttListen;
static void initMqtt(){
/// Initialize Mqtt and connect.
client = MqttServerClient(/* Your mqtt host address */)
..logging(on: false)
..port = MqttConstants.mqttPort
..keepAlivePeriod = 20
..onDisconnected = _onDisconnected
..onSubscribed = _onSubscribed
..onConnected = _onConnected
..onUnsubscribed = _onUnsubscribed
..onSubscribeFail = _onSubscribeFail;
/// If the mqtt connection lost
/// MqttBroker publish this message on this topic.
final mqttMsg = MqttConnectMessage()
.withWillMessage('connection-failed')
.withWillTopic('willTopic')
.startClean()
.withWillQos(MqttQos.atLeastOnce)
.withWillTopic('failed');
client.connectionMessage = mqttMsg;
await _connectMqtt();
}
/// Mqtt server connected.
void _onConnected() {
log('Connected');
_listenMqtt();
}
/// Mqtt server disconnected
void _onDisconnected() {
log('Disconnected');
}
/// Mqtt server subscribed
void _onSubscribed(String? topic) {
log('Subscribed topic is : $topic');
}
void _onUnsubscribed(String? topic) {
log('Unsubscribed topic is : $topic');
}
void _onSubscribeFail(String? topic) {
log('Failed subscribe topic : $topic');
}
/// Connection MQTT Server.
Future<void> _connectMqtt() async {
if (client.connectionStatus!.state != MqttConnectionState.connected) {
try {
await client.connect();
} catch (e) {
log('Connection failed' + e.toString());
}
} else {
log('MQTT Server already connected ');
}
}
/// Diconnection MQTT Server.
static Future<void> disconnectMqtt() async {
if (client.connectionStatus!.state == MqttConnectionState.connected) {
try {
client.disconnect();
} catch (e) {
log('Disconnection Failed ' + e.toString());
}
} else {
log('MQTT Server already disconnected ');
}
}
/// Subscribe a topic
static void subscribeTopic(String topic) {
final state = client.connectionStatus?.state;
if (state != null) {
if (state == MqttConnectionState.connected) {
client.subscribe(topic + "/data", MqttQos.atLeastOnce);
}
}
}
/// Publish a message to topic
/// [reatain] means last message save the broker.
static void publish(String topic, String message, {bool retain = true}) {
final builder = MqttClientPayloadBuilder();
builder.addString(message);
client.publishMessage(
topic,
MqttQos.atLeastOnce,
builder.payload!,
retain: retain,
);
builder.clear();
}
static void unSubscribeTopic(String topic) {
final state = client.connectionStatus?.state;
if (state != null) {
if (state == MqttConnectionState.connected) {
client.unsubscribe(topic + "/data");
}
}
}
static void onClose(){
mqttListen?.close();
disconnectMqtt();
}
void _listenMqtt() {
mqttListen = client.updates!.listen((dynamic t) {
MqttPublishMessage recMessage = t[0].payload;
final message =
MqttPublishPayload.bytesToStringAsString(recMessage.payload.message);
/*
Listen subscribe topic.
*/
log(message);
});
}
}
I have created a nice format for MQTT and I wanted to share with you through this question.
Package: mqtt_client

Client only listens to server when sends a message

I'm implementing socket.
Two clients connect to the server with no problem, when client1 sends a message to the server, the server publishes it to every other client (which in this case is client2). but client2 won't get the message unless it sends a message. It seems the listener of the client doesn't work. Obviously, I want client2 to get the message from client1 instantly.
here is my sever code:
import 'dart:io';
import 'dart:typed_data';
void main() async {
// bind the socket server to an address and port
MySocket mySocket = MySocket();
await mySocket.init();
}
class MySocket {
ServerSocket? server;
List<Socket> clients = [];
//initialize the socket
init() async {
server = await ServerSocket.bind("192.168.0.112", 4000);
// listen for client connections to the server
server!.listen((client) {
handleConnection(client);
addClient(client);
});
}
void handleConnection(Socket client) async {
print('Connection from'
' ${client.remoteAddress.address}:${client.remotePort}');
// listen for events from the client
client.listen(
// handle data from the client
(Uint8List data) async {
await Future.delayed(Duration(seconds: 1));
final message = String.fromCharCodes(data);
print(message);
publish(message, client);
},
// handle errors
onError: (error) {
print(error);
client.close();
},
// handle the client closing the connection
onDone: () {
print('Client left');
client.close();
},
);
}
void addClient(Socket client) {
//if client doesn't already exist add it to the list of clients
if (!clients.any((element) =>
'${client.remoteAddress.address}:${client.remotePort}' ==
'${element.remoteAddress.address}:${element.remotePort}')) {
clients.add(client);
}
}
void publish(String message, Socket client) {
//write the message to every client except the author of it
clients.forEach((element) async {
if ('${client.remoteAddress.address}:${client.remotePort}' !=
'${element.remoteAddress.address}:${element.remotePort}') {
element.write(message);
}
});
}
}
here is my client-side code:
import 'dart:io';
import 'dart:typed_data';
void main() async {
//gets the username
String name = '';
while (name.isEmpty) {
print('Enter your name: ');
name = stdin.readLineSync() ?? '';
}
// connect to the socket server
final socket = await Socket.connect("192.168.0.112", 4000);
print('Connected to: ${socket.remoteAddress.address}:${socket.remotePort}');
// listen for responses from the server
socket.listen(
// handle data from the server
(Uint8List data) {
final serverResponse = String.fromCharCodes(data);
print('$serverResponse');
},
// handle errors
onError: (error) {
print(error);
socket.destroy();
},
// handle server ending connection
onDone: () {
print('Left server.');
socket.destroy();
},
);
// sending messages to the server
String message = "";
while (message != "exit") {
message = stdin.readLineSync() ?? '';
await sendMessage(socket, name, message);
}
socket.close();
}
Future<void> sendMessage(Socket socket, String name, String message) async {
socket.write('$name: $message');
await Future.delayed(Duration(seconds: 2));
}
Thank you in advance.
The issue is because stdin.readLineSync() in your client blocks the current thread. You can get around this by spawning an isolate to handle that portion of the code, so that it does not block the socket.listen from printing out the responses from the server.
See updated client code below:
import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
void main() async {
//gets the username
String name = '';
while (name.isEmpty) {
print('Enter your name: ');
name = stdin.readLineSync() ?? '';
}
// connect to the socket server
final socket = await Socket.connect("192.168.0.112", 4000);
print('Connected to: ${socket.remoteAddress.address}:${socket.remotePort}');
// listen for responses from the server
socket.listen(
// handle data from the server
(Uint8List data) {
final serverResponse = String.fromCharCodes(data);
print('$serverResponse');
},
// handle errors
onError: (dynamic error) {
print(error);
socket.destroy();
},
// handle server ending connection
onDone: () {
print('Left server.');
socket.destroy();
},
);
final receive = ReceivePort();
final isolate = await Isolate.spawn(readMessages, receive.sendPort);
await for (final message in receive) {
if (message == 'exit') break;
await sendMessage(socket, name, message as String);
}
socket.close();
}
void readMessages(SendPort port) {
String message = '';
while (message != 'exit') {
message = stdin.readLineSync() ?? '';
port.send(message);
}
Isolate.exit(port);
}
Future<void> sendMessage(Socket socket, String name, String message) async {
socket.write('$name: $message');
await Future<void>.delayed(Duration(seconds: 2));
}

mqtt_client cant emit messages on subscribe flutter

I am unable to get messages on subscribe. what am I doing wrong?
I am able to register a connection to the broker. I just can't emit any thing in client.updates.listen.
also what is the difference between MqttPublishMessage and MqttSubscribeMessage?
import 'dart:async';
import 'dart:io';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
final client = MqttServerClient.withPort('ws://192.168.43.56', 'cliendId', 8080,);
Future<int> main() async {
/// Set logging on if needed, defaults to off
client.logging(on: false);
client.keepAlivePeriod = 20;
client.port = 8080;
client.useWebSocket = true;
client.onDisconnected = onDisconnected;
client.onConnected = onConnected;
client.onSubscribed = onSubscribed;
client.pongCallback = pong;
final connMess = MqttConnectMessage()
.withClientIdentifier('client_id')
.keepAliveFor(60) // Must agree with the keep alive set above or not set
.startClean() // Non persistent session for testing
.withWillQos(MqttQos.atLeastOnce);
print('EXAMPLE::Mosquitto client connecting....');
client.connectionMessage = connMess;
try {
await client.connect();
} on Exception catch (e) {
print('EXAMPLE::client exception - $e');
client.disconnect();
}
/// Check we are connected
if (client.connectionStatus.state == MqttConnectionState.connected) {
print('EXAMPLE::Mosquitto client connected');
} else {
/// Use status here rather than state if you also want the broker return code.
print(
'EXAMPLE::ERROR Mosquitto client connection failed - disconnecting, status is ${client.connectionStatus}');
client.disconnect();
return -1;
}
/// Ok, lets try a subscription
print('EXAMPLE::Subscribing to the test/lol topic');
const topic = '/busline/201'; // Not a wildcard topic
client.subscribe(topic, MqttQos.exactlyOnce);
client.updates.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final MqttPublishMessage recMess = c[0].payload;
final pt = MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
print(
'EXAMPLE::Change notification:: topic is <${c[0].topic}>, payload is <-- $pt -->');
print('');
});
print('EXAMPLE::Sleeping....');
await MqttUtilities.asyncSleep(120);
}
/// The subscribed callback
void onSubscribed(String topic) {
print('EXAMPLE::Subscription confirmed for topic $topic');
}
/// The unsolicited disconnect callback
void onDisconnected() {
print('EXAMPLE::OnDisconnected client callback - Client disconnection');
if (client.connectionStatus.disconnectionOrigin ==
MqttDisconnectionOrigin.solicited) {
print('EXAMPLE::OnDisconnected callback is solicited, this is correct');
}
}
/// The successful connect callback
void onConnected() {
print(
'EXAMPLE::OnConnected client callback - Client connection was sucessful');
}
/// Pong callback
void pong() {
print('EXAMPLE::Ping response client callback invoked');
}
you can do like this
// connection succeeded
void onConnected() {
print('Connected');
}
// unconnected
void onDisconnected() {
print('Disconnected');
}
// subscribe to topic succeeded
void onSubscribed(String topic) {
print('Subscribed topic: $topic');
}
// subscribe to topic failed
void onSubscribeFail(String topic) {
print('Failed to subscribe $topic');
}
// unsubscribe succeeded
void onUnsubscribed(String topic) {
print('Unsubscribed topic: $topic');
}
// PING response received
void pong() {
print('Ping response client callback invoked');
}
var data;
Future<MqttServerClient> connect() async {
MqttServerClient client = MqttServerClient.withPort(
'broker', "client something unique", port);
client.logging(on: false);
client.onConnected = onConnected;
client.onDisconnected = onDisconnected;
// client.onUnsubscribed = onUnsubscribed;
client.onSubscribed = onSubscribed;
client.onSubscribeFail = onSubscribeFail;
client.pongCallback = pong;
final connMessage = MqttConnectMessage()
.authenticateAs('Enter Client Id', 'Enter Password')
.withClientIdentifier("something unique match with client")
.startClean()
// .withWillRetain()
.withWillQos(MqttQos.atLeastOnce);
client.connectionMessage = connMessage;
try {
await client.connect();
// client.unsubscribe('topic/');
client.subscribe('topic/', MqttQos.atLeastOnce);
} catch (e) {
print('Exception: $e');
client.disconnect();
}
client.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final MqttPublishMessage message = c[0].payload as MqttPublishMessage;
final payload =
MqttPublishPayload.bytesToStringAsString(message.payload.message);
data = jsonDecode(payload);
print('Received message:$payload from topic: ${c[0].topic}>');
});
return client;
}