This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CC3220SF-LAUNCHXL:禁用阻止发送时、订阅多个 MQTT 主题失败

Guru**** 2562870 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/wi-fi-group/wifi/f/wi-fi-forum/1011188/cc3220sf-launchxl-subscription-to-multiple-mqtt-topics-fails-when-blocking-send-is-disabled

器件型号:CC3220SF-LAUNCHXL

在 MQTT 客户端示例(SDK 5.10)中、当阻止发送被禁用时、当我们尝试订阅多个主题(超过2个主题)时、订阅将失败、并显示错误代码-5 (MQTT_packet_ERR_PKT_AVL)

我已经尝试使用各种 QoS 级别和保留/不保留消息、结果相同。

此致、

Zac

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您能否发送您正在使用的参考代码?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我 在 SDK 中获取了 MQTT 客户端示例、并启用了安全 MQTT 连接、同时禁用了阻止发送。 有4个主题,每个主题都保留了现有的信息。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    查看代码(特别是 MQTT_if.c 中的第267行)-似乎当前使用示例 AS 时仅 支持阻塞模式。

    MQTT 连接建立后、 应用程序立即尝试发送所有主题订阅。

    您看到的错误是由于模块中的资源有限造成的、因此在第一个订购完成(亚 ACKed)之前发送第二个订购命令将返回您看到的错误。

     如果返回特定错误、您可以尝试重新调用 MQTT_IF_Subscribe (或等待收到亚 ACK、然后再发送下一个订阅)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢 Kobi。 如果这些接口在 SDK 发布之前更完整并经过测试、那将非常有用。 我们 在阻塞发送方面遇到问题、在可用内存有限(7个任务/线程正在运行)时 MQTT 连接卡住、因此测试了非阻塞发送选项。 但是、我们似乎需要进一步分析/了解、以确保系统稳定。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    要添加、我们还发现在 非阻塞发送模式下发布多条消息时错过了一些消息。 我想这会使非阻塞式发送模式完全不可用。 与  阻塞模式相比、添加 ACK 检查似乎没有任何优势。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您是否检查了错过的发布消息的返回值?

    非阻塞在顺序实现中是没有意义的(在这种情况下、对阻塞 I/f 没有优势)。 它在事件驱动(状态机)实现中可能很有用。

    请提供有关原始(阻止)问题的详细信息。 该库在现有应用程序的上下文中进行了测试。 拥有更多线程会影响有限的资源系统。 我们可以查看 MQTT 内部存储器分配、并可以帮助优化以满足您的实施需求。

    BR、

    Kobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在安全服务器和4个主题已订阅的阻塞模式下、MQTT_IF_Connect 方法有时会卡住 、不会返回。 在10个测试中进行2个或3个测试时会发生这种情况、当 少数其他线程被禁用时、相同的工作正常 、这使我相信它与存储器相关。 我们无法调试到确切的步骤中 、因为此问题是随机的、大多数情况下不会在调试会话期间发生。 另一个问题是调用 MQTT_IF_Disconnect 时、 我们经常看到错误[sock event]- Unexpected Event [20x] error。 在示例代码中也是如此、并且仅在运行更多线程时发生。 不确定这是否也与内存有关。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    MQTT 连接期间、其他线程还在做什么?

     MQTT_IF_Subscribe 在 MQTT_IF_Connect 之前或之后是否被调用?  

    您能否提供监听器日志(显示 MQTT 流量)?  该模块可能一直在等待 conn-ack 或 sub-ack、但这不应受到其他线程的影响)?

    请尝试检查 堆状态和线程的堆栈峰值(两者都可以通过 RTOS 对象查看器查看:在 CCS 中、在调试会话期间选中"Tools"->"ROV"->"HeapMem/Task")。

    BR、

    Kobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    • 其他线程包括 WiFi 配置任务、NTP 线程、OTA 任务、调度程序(特定于应用)、GPIO 读/写处理程序和看门狗。
    • MQTT_IF_Subscribe 当前在 MQTT_IF_Connect 之前调用。 我们还在连接后尝试了订阅、它在我们的初始测试中起作用、但这可能需要在重新连接过程中进行额外处理。 另请注意、当我禁用一些其他线程(如调度程序和 OTA)时、代码工作正常
    • 您能帮我从 CCS 获取监听器日志吗? (我正在使用 macOS Big Sur)
    • 线程堆栈峰值在范围内、堆在 ROV 上看起来不错(附加快照)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我不确定调度程序线程是什么、但 OTA 线程是否在 MQTT 操作失败期间实际执行(还是只是挂起/休眠)?

    也许您可以尝试提高 MQTTContextThread 和 MQTTAppThread 的优先级。

    您似乎可以减小多个线程的堆栈大小(例如看门狗和 GPIO)并获得更多的堆空间(尽管我知道堆目前不是问题)。

    CCS 不能用于监听 MQTT 流量。 它应由外部监听器(例如 Wireshark)完成。

    重新连接后、以前的订阅将自动(重新)订阅(在重新连接之后)、因此您认为自动订阅有问题是正确的。 唯一 的解决方法是取消订阅 以响应断开连接、然后在(重新)连接完成后再次订阅。  

      

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    OTA 线程计划以特定的间隔运行、 不应干扰 MQTT。

    我已提升  MQTTContextThread 和 MQTTAppThread 的优先级、但 问题仍然存在。  

    看门狗和 GPIO 堆栈峰值在少数操作时会增加、因此没有 减小堆栈尺寸的余地。

    连接后订阅主题正常、但在断开连接期间取消订阅主题 失败、出现错误"未连接到代理"、模块重置。

    请注意、很少有主题具有多级通配符、大多数主题都保留了消息。   这将导致在订阅时同时接收多条消息。  这可能会导致连接方法卡住。  我们可以禁用自动订阅吗? 或者 ,您是否可以建议一些解决方法?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我想 我发现了这个问题。 这些主题中包含通配符、从而导致10条消息同时发送、但 MQTT_IF.c 中"msgQueue"的最大队列大小仅为10、这似乎在最初阻止了 RECV 事件。 将其大小增加到20似乎到目前为止是可行的。 我将进行进一步测试以确认。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您提供此信息。

      

     您能否在使用时发送一个带有通配符的主题示例(将转换为多个数据包)?

    标准 MQTT 通配符不应产生比非通配符订阅更多的事件(服务器上可能存在待处理的事件)。  

    我仍然不确定事件队列大小如何 导致 MQTT_IF_Connect 卡住 该队列是为了 让应用程序线程处理堆栈事件、我不记得在任何特定事件上应用程序被阻止。

    您能告诉我们 MQTT_IF_Connect 被卡在哪里吗?  例如,通过添加打印稿或在 ROV 中检查线程的状态。

    我认为 这与通配符无关、我想复制它并仔细检查问题。

    谢谢、

    Kobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    MQTT 通配符的一个示例是 /house/room、它具有 /house/room/appliance1、 /house/room/appliance2、 /house/room/appliance3等

    这些主题中的每一个都将保留消息、在订阅 /house/room 时、它将推送所有消息、在我们的案例中、我们将推送12条或更多不同的消息。 请注意、这些只是保留的消息、不是待处理事件(非持续会话)

    到目前为止、我们的测试表明问题出在队列大小。  队列已满时、MQ_send 似乎被阻止。

    此致、

    Zac

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、这更有意义。  但是、即使 MQ_send 卡住、也应在应用程序线程调用 MQ_recv 时释放、因此我仍然无法清除整个死锁。

    我猜 MQTT_IF 在 创建消息队列时可能使用了 O_NONBLOCK 标志(但您可能错过 了一些 消息-因此您的修复效果更好)。