如何避免订阅同一主题并在HiveMQ Android客户端中多次触发回调? 预期行为
我想有一个回拨,以听取我订阅的每一个主题,每发送一封邮件只有一次。我的意思是,我想订阅一个主题1000次,但当收到一条消息时,我只想听一次 IDK如果有什么我做错了(我猜) 实际行为如何避免订阅同一主题并在HiveMQ Android客户端中多次触发回调? 预期行为,android,kotlin,mqtt,hivemq,Android,Kotlin,Mqtt,Hivemq,我想有一个回拨,以听取我订阅的每一个主题,每发送一封邮件只有一次。我的意思是,我想订阅一个主题1000次,但当收到一条消息时,我只想听一次 IDK如果有什么我做错了(我猜) 实际行为 我正在开发一个家庭安全摄像头应用程序 我有一张我自己的相机清单 对于列表中的每一台相机,我都订阅一个主题 每隔30秒,我会更新屏幕,然后再次为每台相机订阅一个主题。这意味着一个主题可以订阅多次 每次我收到一条关于某个主题的消息时,回调都会触发关于同一主题被订阅多少次的消息 复制 台阶 有一个主题摄像头/123
- 我正在开发一个家庭安全摄像头应用程序
- 我有一张我自己的相机清单
- 对于列表中的每一台相机,我都订阅一个主题
- 每隔30秒,我会更新屏幕,然后再次为每台相机订阅一个主题。这意味着一个主题可以订阅多次
- 每次我收到一条关于某个主题的消息时,回调都会触发关于同一主题被订阅多少次的消息
private var mqtt: Mqtt5AsyncClient? = null
private var username: String? = null
private var password: String? = null
private val serverHost: String,
private val serverPort: Int = 1883
构建MQTT
private fun build() {
if (mqtt != null) return
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { Timber.d("On Connected") }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
}
fun connect(username: String, password: String) {
build()
this.username = username
this.password = password
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username("abc")
?.password("123".toByteArray())
?.applySimpleAuth()
?.send()
}
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { onMQTTConnected(it) }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
mqtt?.publishes(MqttGlobalPublishFilter.SUBSCRIBED) { onConsumingTopic(it) }
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username(context.getString(R.string.mqtt_user))
?.password(context.getString(R.string.mqtt_pw).toByteArray())
?.applySimpleAuth()
?.send()
连接MQTT
private fun build() {
if (mqtt != null) return
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { Timber.d("On Connected") }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
}
fun connect(username: String, password: String) {
build()
this.username = username
this.password = password
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username("abc")
?.password("123".toByteArray())
?.applySimpleAuth()
?.send()
}
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { onMQTTConnected(it) }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
mqtt?.publishes(MqttGlobalPublishFilter.SUBSCRIBED) { onConsumingTopic(it) }
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username(context.getString(R.string.mqtt_user))
?.password(context.getString(R.string.mqtt_pw).toByteArray())
?.applySimpleAuth()
?.send()
然后订阅一个主题
每次我订阅一个主题,我都会使用这些有趣的方法
fun subscribeWith(topic: String) {
mqtt?.subscribeWith()
?.topicFilter(topic)
?.qos(MqttQos.AT_MOST_ONCE)
?.callback { t -> onConsumingTopic(t) } <- I THINK THIS IS THE IMPORTANT THING
?.send()
?.whenComplete { ack, error -> onTopicConnected(ack, error, topic) }
}
fun subscribeth(主题:字符串){
mqtt?.subscribowith()
?主题过滤器(主题)
?qos(MqttQos.最多一次)
?回调{t->onConsumingTopic(t)}onTopicConnected(ack,error,topic)}
}
如评论中所述,目前唯一的解决方案是在MQTT客户端库之外保留已订阅主题的列表,并在订阅新主题之前进行检查。如评论中所述,目前唯一的解决方案是在MQTT客户机库之外保留一个订阅主题列表,并在订阅新主题之前进行检查。我找到了正确答案
无需为每个订阅调用注册回调,也无需使用全局数组处理注册的主题,如下所示:
mqtt?.subscribeWith()
?.callback { t -> onConsumingTopic(t) } <- This is not needed
然后您就可以订阅,而无需提供回调
client.subscribeWith().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).send();
完整示例:
构建MQTT
private fun build() {
if (mqtt != null) return
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { Timber.d("On Connected") }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
}
fun connect(username: String, password: String) {
build()
this.username = username
this.password = password
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username("abc")
?.password("123".toByteArray())
?.applySimpleAuth()
?.send()
}
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { onMQTTConnected(it) }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
mqtt?.publishes(MqttGlobalPublishFilter.SUBSCRIBED) { onConsumingTopic(it) }
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username(context.getString(R.string.mqtt_user))
?.password(context.getString(R.string.mqtt_pw).toByteArray())
?.applySimpleAuth()
?.send()
连接MQTT
private fun build() {
if (mqtt != null) return
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { Timber.d("On Connected") }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
}
fun connect(username: String, password: String) {
build()
this.username = username
this.password = password
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username("abc")
?.password("123".toByteArray())
?.applySimpleAuth()
?.send()
}
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { onMQTTConnected(it) }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
mqtt?.publishes(MqttGlobalPublishFilter.SUBSCRIBED) { onConsumingTopic(it) }
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username(context.getString(R.string.mqtt_user))
?.password(context.getString(R.string.mqtt_pw).toByteArray())
?.applySimpleAuth()
?.send()
订阅主题
mqtt?.subscribeWith()
?.topicFilter(topic)
?.qos(MqttQos.AT_LEAST_ONCE)
?.send()
?.whenComplete { ack, error -> onTopicSubscribed(ack, error, topic) }
我找到了正确的答案 无需为每个订阅调用注册回调,也无需使用全局数组处理注册的主题,如下所示:
mqtt?.subscribeWith()
?.callback { t -> onConsumingTopic(t) } <- This is not needed
然后您就可以订阅,而无需提供回调
client.subscribeWith().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).send();
完整示例:
构建MQTT
private fun build() {
if (mqtt != null) return
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { Timber.d("On Connected") }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
}
fun connect(username: String, password: String) {
build()
this.username = username
this.password = password
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username("abc")
?.password("123".toByteArray())
?.applySimpleAuth()
?.send()
}
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { onMQTTConnected(it) }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
mqtt?.publishes(MqttGlobalPublishFilter.SUBSCRIBED) { onConsumingTopic(it) }
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username(context.getString(R.string.mqtt_user))
?.password(context.getString(R.string.mqtt_pw).toByteArray())
?.applySimpleAuth()
?.send()
连接MQTT
private fun build() {
if (mqtt != null) return
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { Timber.d("On Connected") }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
}
fun connect(username: String, password: String) {
build()
this.username = username
this.password = password
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username("abc")
?.password("123".toByteArray())
?.applySimpleAuth()
?.send()
}
mqtt = Mqtt5Client.builder()
.identifier(identifier())
.serverHost(serverHost)
.serverPort(serverPort)
.automaticReconnect()
.applyAutomaticReconnect()
.addConnectedListener { onMQTTConnected(it) }
.addDisconnectedListener { onMQTTDisconnected(it) }
.buildAsync()
mqtt?.publishes(MqttGlobalPublishFilter.SUBSCRIBED) { onConsumingTopic(it) }
mqtt?.connectWith()
?.keepAlive(30)
?.sessionExpiryInterval(7200)
?.cleanStart(false)
?.simpleAuth()
?.username(context.getString(R.string.mqtt_user))
?.password(context.getString(R.string.mqtt_pw).toByteArray())
?.applySimpleAuth()
?.send()
订阅主题
mqtt?.subscribeWith()
?.topicFilter(topic)
?.qos(MqttQos.AT_LEAST_ONCE)
?.send()
?.whenComplete { ack, error -> onTopicSubscribed(ack, error, topic) }
多次订阅一个主题有什么意义?您需要保留一个已订阅主题的列表。在添加新主题之前,请检查列表。完全如我所说。多次订阅。想象一下这个。当我们有一个主题a和MQTT,并且您执行MQTT.subscribe(主题=a)MQTT.subscribe(主题=a)MQTT.subscribe(主题=a)时,当接收到消息时,主题会触发3次@Odysseus@hardillb我想了想,但我认为这只是一个解决办法,而不是真正的行为。MQTT说,订阅同一主题意味着替换,而不是重复。谢谢,我认为这不会发生在代理上,而是在客户端添加额外的匹配回调。多次订阅主题有什么意义?您需要保留一个已订阅主题的列表。在添加新主题之前,请检查列表。完全如我所说。多次订阅。想象一下这个。当我们有一个主题a和MQTT,并且您执行MQTT.subscribe(主题=a)MQTT.subscribe(主题=a)MQTT.subscribe(主题=a)时,当接收到消息时,主题会触发3次@Odysseus@hardillb我想了想,但我认为这只是一个解决办法,而不是真正的行为。MQTT说,订阅同一主题意味着替换,而不是重复。谢谢,我认为这不会发生在代理上,而是在客户端添加额外的匹配回调。