为什么 MQTT Broker 会忘记 SIM800 模块的连接?

物联网 MQTT 蚊子
2021-05-29 09:52:42

我正在研究 SIM800 模块和 MQTT 代理(Mosquitto)来设计一种物联网设备。当我尝试MQTT服务器时,我遇到了这个问题。SIM800 通过 TCP 连接连接 MQTT 服务器。关于SIM800 TCP连接,你可以看到下面的代码:

SIM800_Status_t SIM800_InitTCP(void)
{
  uint8_t count;            //trying counter
    for(count = 0; count < TRYING_LIMIT; count++)
    { 
        HAL_Delay(250);
        /*Functionality = 1 - 10 sec*/
        if(SIM800_SendCommand((uint8_t*)"AT+CFUN=1\n", 10,        (uint8_t*)"AT+CFUN=1\r\nOK\r\n", 15, 10000) != SIM800_OK)
            continue;
        /*Dont sleep - 100 ms*/
        if(SIM800_SendCommand((uint8_t*)"AT+CSCLK=0\n", 11,        (uint8_t*)"AT+CSCLK=0\r\nOK\r\n", 16, 100) != SIM800_OK)
            continue;
        /*Is the SIM Card OK? - 5 sec*/
        if(SIM800_SendCommand((uint8_t*)"AT+CPIN?\n", 9,        (uint8_t*)"AT+CPIN?\r\n+CPIN: READY\r\n\r\nOK\r\n", 30, 5000) != SIM800_OK)
        continue;
        /*Is the SIM Card Registered?*/
        if(SIM800_SendCommand((uint8_t*)"AT+CREG?\n", 9,        (uint8_t*)"AT+CREG?\r\n+CREG: 0,1\r\n\r\nOK\r\n", 28, 100) != SIM800_OK)
        continue;

        /*GPRS Status- 75 sec*/
        if(SIM800_SendCommand((uint8_t*)"AT+CGATT?\n", 10,      (uint8_t*)"AT+CGATT?\r\n+CGATT: 1\r\n\r\nOK\r\n", 28, 75000) != SIM800_OK)
        continue;

        /*If there is PDP context, close it- 65sec*/
        if(SIM800_SendCommand((uint8_t*)"AT+CIPSHUT\n", 11,     (uint8_t*)"AT+CIPSHUT\r\nSHUT OK\r\n", 21, 65000) != SIM800_OK)
        continue;

        /*Status*/
        if(SIM800_SendCommand((uint8_t*)"AT+CIPSTATUS\n", 13,   (uint8_t*)"AT+CIPSTATUS\r\nOK\r\n\r\nSTATE: IP INITIAL\r\n", 39, 100) != SIM800_OK)
        continue;

        /*Single server connection*/
        if(SIM800_SendCommand((uint8_t*)"AT+CIPMUX=0\n", 12,    (uint8_t*)"AT+CIPMUX=0\r\nOK\r\n", 17, 100) != SIM800_OK)
        continue;

        /*Transparent mode*/
        if(SIM800_SendCommand((uint8_t*)"AT+CIPMODE=1\n", 13,   (uint8_t*)"AT+CIPMODE=1\r\nOK\r\n", 18, 100) != SIM800_OK)
        continue;

        /*APN settings*/
        if(SIM800_SendCommand((uint8_t*)"AT+CSTT=\"\",\"\",\"\"\n", 17, (uint8_t*)"AT+CSTT=\"\",\"\",\"\"\r\nOK\r\n", 22, 100) != SIM800_OK)
        continue;

        /*GPRS enable(85 sec)*/
        if(SIM800_SendCommand((uint8_t*)"AT+CIICR\n", 9,        (uint8_t*)"AT+CIICR\r\nOK\r\n", 14, 85000) != SIM800_OK)
        continue;

        /*Did IP address get?*/
        if(SIM800_SendCommand((uint8_t*)"AT+CIFSR\n", 9,        (uint8_t*)"AT+CIFSR\r\n", 10, 100) != SIM800_OK)
        continue;

        HAL_Delay(100); 

        if(SIM800_SendCommand((uint8_t*)"AT+CIPSTART=\"TCP\",\"123.456.78.90\",\"1883\"\n", 28 + 14, (uint8_t*)"AT+CIPSTART=\"TCP\",\"123.456.78.90\",\"1883\"\r\nOK\r\n\r\nCONNECT\r\n", 44 + 14, 160000) != SIM800_OK)
                continue;
        else
                return SIM800_OK;
    }
    return SIM800_ERROR;
}

IP 地址具有代表性。“SIM800_SendCommand”函数参数为:

SIM800_SendCommand(uint8_t* AT_Command, uint8_t AT_Command_Len, uint8_t* Response, uint8_t Response_Len, uint32_t Timeout),

设备使用此代码成功连接到 MQTT Broker。与 TCP 连接后,设备立即向 MQTT 服务器发送“连接请求”。服务器成功返回“CONN ACK”响应。

MQTT 连接后,设备向 MQTT 服务器发送“订阅请求”以订阅“主题 A”。服务器返回“SUB ACK”响应。

在这之后问题就开始了。

我正在使用我的手机(一个 android 应用程序)或 PC 上的“MQTTBox”应用程序向“主题 A”发布一些消息。

当我每 15 秒或每 1 分钟将消息发布到“主题 A”时,没有问题。一切正常。但是,当我在上次发布后等待 2 分钟后将消息发布到“主题 A”时,此后不会将任何消息发送到 SIM800 模块(设备)。

您可以在下面看到问题图:

画画

我怀疑问题出在 SIM800 模块上,但是当我尝试使用相同场景的不同简单服务器应用程序仅使用 TCP 连接的模块时,没有问题。一切正常。

但是当我用 MQTT 尝试相同的场景时,服务器忘记了设备并且不会在 TCP 上发送任何数据。甚至 TCP 连接关闭消息(空消息)。

我非常感谢您帮助解决问题。

1个回答

mosquitto 的默认 keepalive 是 60 秒,这意味着如果您不至少每 90 (1.5 * keepalive) 秒向代理发送 MQTT 数据包,则代理将假定客户端已死并断开连接。

在评论中,您说您已禁用内置的 keepalive 处理,因此这就是如果您尝试在消息之间保留 120 秒,代理会终止连接的原因。

最好的办法不是设置零值,而是设置一个与消息发布频率一致的值,以免浪费带宽而不得不发送 ping 以保持连接活动。