文档中心 物联网通信 常见问题 设备接入和上报问题

设备接入和上报问题

最近更新时间:2019-09-10 15:43:00

设备连接物联网平台失败一般有哪几类原因?

设备连接失败有多种原因,例如设备与云端网络连接不通,设备鉴权失败,无线网络信号问题导致超时等等,可根据设备连接过程 SDK 的错误日志类型来区分处理,一般处理步骤如下:

  1. 首先需要检查设备端本地网络与物联网通信平台的连接情况,例如,对于 MQTT 连接,可以按以下步骤检查网络连接情况:
    • ping iotcloud-mqtt.gz.tencentdevices.com 检测主机是否可达情况。
    • telnet iotcloud-mqtt.gz.tencentdevices.com 8883 (TLS) 或 1883 (NOTLS)检测端口连接情况。
    • 如果执行上面命令的结果都是正常的,那可能还需要检查本地防火墙策略。
  2. 在无线网络环境,如果由于信号质量和环境干扰问题,导致连接超时,则可以修改 SDK 的可变参数里面的超时设置,如下是 C-SDK 代码 qcloud_iot_export.h 里的配置:
    /* MQTT 阻塞调用(包括连接, 订阅, 发布等)的超时时间, 单位:ms 建议5000ms */
    #define QCLOUD_IOT_MQTT_COMMAND_TIMEOUT                             (5 * 1000)
    /* 接收到 MQTT 包头以后,接收剩余长度及剩余包,最大延迟等待时延 */
    #define QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS                                 (2000)
    /* TLS连接握手超时时间, 单位:ms */
    #define QCLOUD_IOT_TLS_HANDSHAKE_TIMEOUT                            (5 * 1000)
  3. 如果网络连接均无问题,设备鉴权错误也会导致连接失败,需要检查以下设置:
    • 检查使用的设备信息参数是否正确。常见的错误是设备信息或密钥多输了空格,设备信息与密钥信息不一致,或者证书文件名与代码中书写的文件名不一致等细微错误。
    • 证书类连接,如果本地时间错误,也会导致 TLS 连接失败。需要本地安装 ntp client 软件进行对时。
  4. 使用 Android SDK 进行 MQTT 连接时,提示“错误的用户名或者密码”。
    如果确认设备参数(ProductId、DeviceName、DevPsk)都配置正确的话,即可检查一下测试设备的系统时间是否正确,例如,使用 adb shell date 查看 Android 设备的系统时间。

设备为何一直上下线?

物联网接入层有设备互踢的逻辑,如果是用同一个设备 ID 在不同地方登录,会导致其中一方被另一方踢下线。因此发现设备一直上下线时,需要确认是否有不同的人或者多线程在使用同一个设备 ID 执行登录操作。

设备发送或者接收消息失败是什么原因?要如何解决?

一般有几类原因:

  1. 发送消息的 Topic 不存在或者没有发布权限,接收消息的 Topic 不存在或者没有订阅权限。物联网通信的 Topic 需要先在控制台创建并设置权限,去控制台查看设备的权限列表,确认对应的 Topic 是否有发布或者接收权限。
    注意:

    SDK 的 sample 代码使用的 data Topic 也需要先去控制台手动添加并设置发布和订阅权限,才能成功发布和接收消息。

  2. Topic 书写有误。确认代码中书写的 Topic 没有包含多余字符或者漏写了字符,例如多输入了空格或者‘/’,或者某个单词少写了字母等。
  3. 连接断开或者网络通讯故障。MQTT 消息基于 TCP 传输,如果网络出现故障中间路由器断开了,则由于 TCP 的重传机制,会需要较长时间才能检测到连接异常。
  4. 当使用设备端 C-SDK 进行 MQTT 订阅主题操作或者以 QoS1 级别发布消息,如果因为 Topic 不存在或权限不对,又或者网络故障超时,SDK 会在 sample 的事件回调函数中提示收到 NACK 或者 TIMEOUT 事件,可供排查定位问题。

设备端在连接断开后会进行自动重连吗?

使用设备端 SDK 建立 MQTT 连接时。如果初始化参数开启了自动重连(默认开启),那么会进行自动重连的操作。在 SDK 的 Yield 函数中,会根据报文收发以及心跳包行为是否正常来判断网络连接状况,如果出现连接断开情况,会自动进行重连。同时为了避免在网络故障情况下频繁进行重连,SDK 的重连间隔是动态变化的,从最小值开始,如果重连失败,重连间隔就会翻倍增长,如果重连间隔达到最大值后仍然还是连接失败则返回重连超时错误。
如果是用户手动断开连接的情况,如主动调用 Destroy 函数,则不会进行自动重连。

Android SDK 集成到工程中编译出错该怎么办?

采用远程依赖的方式编译出错的话,可能会由于远程库更新不及时导致编译出错。可以在gradle文件中将依赖方式修改成本地库依赖:

  • compile project(':iot_core')
  • compile project(':iot_service')

设备端 C-SDK 对软件运行环境的要求是什么?

主要有以下要求:

  1. 需要操作系统或C运行库提供系统调用诸如动态内存分配(malloc/free),定时器和休眠,随机数函数和打印函数等等,在多线程环境还需要临界数据保护如Mutex机制。
  2. 需要 TCP/IP 协议栈,SDK 的 TCP/UDP 实现依赖于 socket 的 send/recv 接口以及 select 等同步I/O机制,如果系统接口不一致需要修改相关的 HAL_TCP/UDP 层实现。
  3. 采用 TLS 加密通讯的场景,需要 SSL/TLS 库的支持,目前物联网通信平台 C-SDK 仅支持 mbedtls,如果采用其他 SSL/TLS 库,需要修改相关的 HAL_TLS/DTLS 层实现。

嵌入式设备资源比较受限,有什么减小 C-SDK 运行内存及库大小的办法吗?

有如下建议:

  1. 首先可以把不需要使用的功能关闭,例如在 make.setting 中把不需要的功能选项置为 n,将 BUILD_TYPE 设置为 release。
  2. 检查 HAL 层的系统调用函数的内存使用情况,例如在某些系统上发现 getaddrinfo 系统函数会分配了较多的内存用于 IPV6。如果 SDK 只用 IPV4,那么可以考虑优化 getaddrinfo 中这个内存分配操作,可以节省运行 RAM。
  3. 设备接入鉴权的方式中,TLS 证书方式需要最多的存储资源和运行内存,安全性也最高。TLS KEY 方式占用资源会少一些,同时保证了安全性。而 NOTLS KEY 方式占用资源最少,不需要 TLS 库,但安全性最低,数据采用明文传输,有被盗取和篡改的风险。用户需要根据设备的资源做取舍和选择。
  4. 在使用 TLS 库的时候,可以根据使用场景对所需的加密算法和密钥交换算法进行裁剪,如 mbedtls 库可对其 config.h里面的特性宏进行定制。

设备端 C-SDK 关于 MQTT 连接的心跳包机制是怎么样的?

MQTT 采用 TCP 长连接,需要心跳包机制来保证连接是活跃的,设备端 C-SDK 按照 MQTT 规范的 Keep Alive 机制,在初始化参数列表里面有一个心跳包发送周期参数:

/* MQTT心跳消息发送周期, 单位:ms */
#define QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL                         (240 * 1000)

在一个心跳发送周期内,如果设备端没有成功发送 MQTT 控制报文(包括 SUB/UNSUB/QoS1 PUB 报文,并收到相应的ACK),则会发送 MQTT PINGREQ 给云端并等待云端回复 PINGRESP 报文,如果在一定时间内没有收到 PINGRESP 报文,则设备端认为连接已断开,会进行自动重连操作。

设备端 C-SDK 对 MQTT QoS 的支持是怎么样的?

目前物联网通信平台支持 MQTT QoS0 和 QoS1,不支持 QoS2。对于 QoS0 的消息,设备端在 Publish 函数调用返回成功之后,即由 TCP/IP 协议栈来保障消息是否送达,SDK 不会做进一步处理。而对于 QoS1 的消息,SDK 会维护一个消息状态队列,并根据 MQTT PUBACK 消息做进一步的跟踪反馈,并在相应的事件回调中通知用户该 QoS1 消息是成功送达或者超时失败,再由用户决定是否进行重发。

设备端 C-SDK 的 Yield 函数是什么作用?

Yield 函数的作用是在当前线程上下文中,进行 MQTT 报文读取,消息处理,超时请求,心跳包及重连状态管理等任务,是设备端进行 MQTT 物联网通信的重要步骤。对于单线程单任务场景,在用户的逻辑代码循环中需要保证对该函数的调用执行。对于多线程多任务场景,可以使用一个单独的线程任务来执行该函数,并且设置一定的线程优先级,避免该线程被长时间挂起。具体使用方法可以参考相应的 sample 代码。

设备端 C-SDK 是否支持多线程?

设备端 C-SDK 支持多线程,对于 MQTT 接口在多线程环境下的使用有如下注意事项,详细代码用例可以参考samples/mqtt/multi_thread_mqtt_sample.c

  1. 不允许多线程调用IOT_MQTT_Yield,IOT_MQTT_Construct以及IOT_MQTT_Destroy。
  2. 可以多线程调用IOT_MQTT_Publish,IOT_MQTT_Subscribe及IOT_MQTT_Unsubscribe。
  3. IOT_MQTT_Yield 作为读取并处理 MQTT 报文以及连接状态的函数,应保证一定的执行时间,避免被长时间挂起或抢占。

设备端 C-SDK 是否支持远程诊断功能?

从版本v2.3.1开始,设备端 C-SDK 增加设备端日志上报功能,可将设备端的运行日志通过 HTTP 上报到云端,并可在控制台展示,方便用户远程诊断及监控设备运行状况。因为日志上报采用了单独的通讯通道,可以在网络通讯正常但 MQTT 连接出现问题时候进行远程诊断。