connect method
void
connect()
Implementation
void connect() async {
// eventbus发送广播,连接中...
bytedeskEventBus
.fire(ConnectionEventBus(BytedeskConstants.USER_STATUS_CONNECTING));
//
currentUid = SpUtil.getString(BytedeskConstants.uid);
client = BytedeskUtils.getClient();
clientId = "$currentUid/$client";
//注意:必须要先判断web,否则在web运行会报错:
// Unsupported operation: Platform._operatingSystem
if (BytedeskUtils.isWeb) {
if (BytedeskConstants.isDebug) {
mqttClient = MqttBrowserClient.withPort(
'ws://127.0.0.1/websocket', clientId!, 3885);
} else {
mqttClient = MqttBrowserClient.withPort(
BytedeskConstants.webSocketWssUrl, clientId!, 443);
}
} else {
if (BytedeskConstants.isWebSocketWss) {
mqttClient =
MqttServerClient(BytedeskConstants.webSocketWssUrl, clientId!);
mqttClient.useWebSocket = true;
mqttClient.port = 443;
/// You can also supply your own websocket protocol list or disable this feature using the websocketProtocols
/// setter, read the API docs for further details here, the vast majority of brokers will support the client default
/// list so in most cases you can ignore this. Mosquito needs the single default setting.
// mqttClient.websocketProtocols = MqttClientConstants.protocolsSingleDefault;
} else {
mqttClient = MqttServerClient(BytedeskConstants.mqttHost, clientId!);
mqttClient.port = BytedeskConstants.mqttPort;
mqttClient.secure = BytedeskConstants.isSecure;
}
}
// 启用3.1.1版本协议,否则clientId限制最大长度为23
mqttClient.setProtocolV311();
/// Set logging on if needed, defaults to off
// mqttClient.logging(on: BytedeskConstants.isDebug);
mqttClient.logging(on: false); // BytedeskConstants.isDebug
/// If you intend to use a keep alive value in your connect message that is not the default(60s)
/// you must set it here
mqttClient.keepAlivePeriod = keepAlivePeriod;
mqttClient.autoReconnect = true; // FIXME:
mqttClient.onAutoReconnect = _onAutoReconnect; // FIXME:
mqttClient.onDisconnected = _onDisconnected;
mqttClient.onConnected = _onConnected;
mqttClient.onSubscribed = _onSubscribed;
mqttClient.onUnsubscribed = _onUnSubscribed;
mqttClient.onSubscribeFail = _onSubscribeFailed;
/// Set a ping received callback if needed, called whenever a ping response(pong) is received from the broker.
mqttClient.pongCallback = _onPong;
/// Create a connection message to use or use the default one. The default one sets the
/// client identifier, any supplied username/password, the default keepalive interval(60s)
/// and clean session, an example of a specific one below.
final MqttConnectMessage connMessage = MqttConnectMessage()
.withClientIdentifier(clientId!)
.authenticateAs('username', 'password'); // TODO: 服务器暂时不需要auth,随便填写
// .keepAliveFor(keepAlivePeriod); // Must agree with the keep alive set above or not set
// 取消客户端设置,直接在服务器端统一内容格式推送
// .withWillTopic('protobuf/lastWill/mqtt') // If you set this you must set a will message
// .withWillMessage('My Will message')
// .startClean() // Non persistent session for testing
// .withWillQos(MqttQos.atLeastOnce);
debugPrint('mqttClient connecting....');
mqttClient.connectionMessage = connMessage;
/// Connect the client, any errors here are communicated by raising of the appropriate exception. Note
/// in some circumstances the broker will just disconnect us, see the spec about this, we however eill
/// never send malformed messages.
try {
await mqttClient.connect();
} on Exception catch (e) {
debugPrint('mqttClient exception - $e');
mqttClient.disconnect();
}
/// Check we are connected
if (mqttClient.connectionStatus.state == MqttConnectionState.connected) {
debugPrint('mqttClient connected');
} else {
/// Use status here rather than state if you also want the broker return code.
debugPrint(
'ERROR mqttClient connection failed - disconnecting, status is ${mqttClient.connectionStatus}');
mqttClient.disconnect();
// exit(-1);
}
/// The client has a change notifier object(see the Observable class) which we then listen to to get
/// notifications of published updates to each subscribed topic.
// mqttClient.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
// final MqttPublishMessage recMess = c[0].payload;
// final String pt =
// MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
// // debugPrint('Change notification:: topic is <${c[0].topic}>, payload is <-- $pt -->');
// });
/// 收到的消息
// if (mqttClient != null && mqttClient.published != null) {
//
mqttClient.published!.listen((MqttPublishMessage messageBinary) {
// debugPrint('Published notification');
//
protomsg.Message messageProto =
protomsg.Message.fromBuffer(messageBinary.payload.message);
// FIXME: 自己发送的消息显示两条?此处根据mid去个重
var mid = messageProto.mid;
// if (midList.contains(mid)) {
// return;
// }
// midList.add(mid);
//
var uid = messageProto.user.uid;
var username = messageProto.user.username;
var nickname = messageProto.user.nickname;
var avatar = messageProto.user.avatar;
//
var content = '';
var type = messageProto.type;
var timestamp = messageProto.timestamp;
var client = messageProto.client;
//
debugPrint(
'bytedesk_mqtt.dart receive type:$type client:$client mid:$mid');
// 非会话消息,如:会议通知等, 另行处理
if (type == BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_NOTICE) {
// TODO: 待处理
return;
}
//
User user = User(
uid: uid, username: username, nickname: nickname, avatar: avatar);
//
Thread thread = Thread(
tid: messageProto.thread.tid,
type: messageProto.thread.type,
// uid: '',
nickname: messageProto.thread.nickname,
avatar: messageProto.thread.avatar,
content: messageProto.thread.content,
timestamp: messageProto.thread.timestamp,
unreadCount: messageProto.thread.unreadCount,
topic: messageProto.thread.topic,
client: client);
Message message = Message(
mid: mid,
content: content,
imageUrl: content,
nickname: nickname,
avatar: avatar,
type: type,
timestamp: timestamp,
status: 'stored',
isSend: uid == currentUid ? 1 : 0,
currentUid: currentUid,
thread: thread,
user: user,
client: client);
// 是否发送消息回执
// var autoReply = false;
var sendReceipt = false;
// var webRTCVideoInvite = false;
// var webRTCAudioInvite = false;
switch (type) {
case BytedeskConstants.MESSAGE_TYPE_TEXT:
{
//
// autoReply = true;
sendReceipt = true;
// TODO: 判断是否加密,暂时不需要
message.content = messageProto.text.content;
// debugPrint('receive text:${message.content!}');
break;
}
case BytedeskConstants.MESSAGE_TYPE_IMAGE:
{
//
// autoReply = true;
sendReceipt = true;
message.imageUrl = messageProto.image.imageUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_VOICE:
{
//
// autoReply = true;
sendReceipt = true;
message.voiceUrl = messageProto.voice.voiceUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_FILE:
{
//
// autoReply = true;
sendReceipt = true;
message.fileUrl = messageProto.file.fileUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_VIDEO:
case BytedeskConstants.MESSAGE_TYPE_SHORT_VIDEO:
{
//
// autoReply = true;
sendReceipt = true;
message.videoUrl = messageProto.video.videoOrShortUrl;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_THREAD:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_THREAD_REENTRY:
case BytedeskConstants.MESSAGE_TYPE_COMMODITY:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_CONNECT:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_DISCONNECT:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_QUEUE:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_QUEUE_ACCEPT:
{
// 替换 'joinQueueThread'
message.content = '接入队列会话'; // TODO: 国际化
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_AGENT_CLOSE:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_VISITOR_CLOSE:
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_AUTO_CLOSE:
{
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TICKET:
{
// TODO: 工单消息
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_FEEDBACK:
{
// TODO: 意见反馈
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_CHANNEL:
{
// TODO: 渠道消息
message.content = messageProto.text.content;
break;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_PREVIEW:
{
// 对方正在输入
String uid = messageProto.user.uid;
String previewContent = messageProto.preview.content;
if (uid != currentUid) {
bytedeskEventBus
.fire(ReceiveMessagePreviewEventBus(previewContent));
}
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECEIPT:
{
// 消息回执
var midR = messageProto.receipt.mid;
var statusR = messageProto.receipt.status;
messageProvider.update(midR, statusR);
// 通知界面更新聊天记录状态
bytedeskEventBus.fire(ReceiveMessageReceiptEventBus(midR, statusR));
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RECALL:
{
// 消息撤回
String mid = messageProto.recall.mid;
bytedeskEventBus.fire(DeleteMessageEventBus(mid));
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_TRANSFER_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_INVITE_RATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_RATE_RESULT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE_VIDEO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_INVITE_AUDIO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CANCEL:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_OFFER_VIDEO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_OFFER_AUDIO:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_ANSWER:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CANDIDATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_READY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_BUSY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_WEBRTC_CLOSE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_CREATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_UPDATE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_ANNOUNCEMENT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_INVITE_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY_APPROVE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_APPLY_DENY:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_KICK:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_MUTE:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER_ACCEPT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_TRANSFER_REJECT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_WITHDRAW:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_NOTIFICATION_GROUP_DISMISS:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_LOCATION:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_LINK:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_EVENT:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_CUSTOM:
{
//
return;
}
case BytedeskConstants.MESSAGE_TYPE_RED_PACKET:
{
//
return;
}
default:
debugPrint('other message type:$type');
}
// 客服端使用
// if (autoReply) {
// //
// }
// 自己发送的消息、智谱AI返回信息不发送回执
if (sendReceipt &&
message.isSend == 0 &&
thread.type != BytedeskConstants.THREAD_TYPE_ZHIPUAI) {
// 发送送达回执
sendReceiptReceivedMessage(mid, thread);
}
//
// final encrypter = Encrypter(AES(key, mode: AESMode.cbc));
// final decrypted = encrypter.decrypt64(messageProto.text.content, iv: iv);
// debugPrint('content: ' + decrypted);
//
// 忽略连接信息
if (message.content == 'visitorConnect' ||
message.content == 'visitorDisconnect') {
return;
}
// 插入本地数据库
// if (messageProvider != null) {
messageProvider.insert(message);
// }
// 通知界面显示聊天记录
bytedeskEventBus.fire(ReceiveMessageEventBus(message));
// 接收消息播放提示音,放到SDK外实现,迁移到demo中
if (BytedeskKefu.getPlayAudioOnReceiveMessage()! && message.isSend == 0) {
// debugPrint('play audio');
SystemSound.play(SystemSoundType.click);
}
// 振动,放到SDK外实现,迁移到demo中
if (BytedeskKefu.getVibrateOnReceiveMessage()! && message.isSend == 0) {
// debugPrint('should vibrate');
vibrate();
}
});
//
// } else {
// debugPrint('mqttClient.published is null');
// }
}