Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/200.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何避免订阅同一主题并在HiveMQ Android客户端中多次触发回调? 预期行为_Android_Kotlin_Mqtt_Hivemq - Fatal编程技术网

如何避免订阅同一主题并在HiveMQ Android客户端中多次触发回调? 预期行为

如何避免订阅同一主题并在HiveMQ Android客户端中多次触发回调? 预期行为,android,kotlin,mqtt,hivemq,Android,Kotlin,Mqtt,Hivemq,我想有一个回拨,以听取我订阅的每一个主题,每发送一封邮件只有一次。我的意思是,我想订阅一个主题1000次,但当收到一条消息时,我只想听一次 IDK如果有什么我做错了(我猜) 实际行为 我正在开发一个家庭安全摄像头应用程序 我有一张我自己的相机清单 对于列表中的每一台相机,我都订阅一个主题 每隔30秒,我会更新屏幕,然后再次为每台相机订阅一个主题。这意味着一个主题可以订阅多次 每次我收到一条关于某个主题的消息时,回调都会触发关于同一主题被订阅多少次的消息 复制 台阶 有一个主题摄像头/123

我想有一个回拨,以听取我订阅的每一个主题,每发送一封邮件只有一次。我的意思是,我想订阅一个主题1000次,但当收到一条消息时,我只想听一次

IDK如果有什么我做错了(我猜)

实际行为
  • 我正在开发一个家庭安全摄像头应用程序
  • 我有一张我自己的相机清单
  • 对于列表中的每一台相机,我都订阅一个主题
  • 每隔30秒,我会更新屏幕,然后再次为每台相机订阅一个主题。这意味着一个主题可以订阅多次
  • 每次我收到一条关于某个主题的消息时,回调都会触发关于同一主题被订阅多少次的消息
复制 台阶
  • 有一个主题摄像头/123
  • 使用以下名为subscribeWith的方法订阅主题N次
  • 通过摄像头/123发送信息
  • 您将收到N次消息,因为您订阅了N次主题
  • 复制器代码 只是变量

    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说,订阅同一主题意味着替换,而不是重复。谢谢,我认为这不会发生在代理上,而是在客户端添加额外的匹配回调。