小安派CAM-U---mqtt连接本地服务器并增加断线重连

3 篇文章 0 订阅

1.在已实现连接WiFi得情况下,进行mqtt连接服务器

小安派CAM-U--从helloword工程从零开始搭建连接wifi-CSDN博客

2.找例程(无论博流还是安信可,提供得例程都很多问题,无力吐槽)

艰难地在组件components文件夹中找到MQTT-C得例程,首先移植简单地mqtt连接例程

3.添加mqtt任务到工程

        添加如下代码,创建任务启动即可连接服务器,但是有几个缺点:无法断线重连,连接服务器时即使密码错误也没任何提示

void User_Mqtt_Task(void)
{
    const char* port;
    const char* topic;

    int ret = 0;
    addr = "192.168.3.20";
    port = "1883";
    topic = "bl618";

#if 1
    //等待配网成功,后续可使用信号量或者事件
    EventBits_t r_event; /*  定义一个事件接收变量 */
    r_event = xEventGroupWaitBits(Event_Handle, /*	事件对象句柄 */
                                  WIFI_EVENT,/* 接收 任务 感兴趣的事件 */
                                  pdTRUE, /*  退出时清除事件位 */
                                  pdTRUE, /*  满足感兴趣的所有事件 */
                                  portMAX_DELAY);/*  指定超时事件, 一直等 */

    if (r_event & WIFI_EVENT )
    {
        /*	如果接收完成并且正确 */
        //printf ( "KEY1 与 与 KEY2  都按下\n");
        xEventGroupClearBits( Event_Handle, WIFI_EVENT );
    }
#endif /* 0 */


    /* open the non-blocking TCP socket (connecting to the broker) */
    test_sockfd = open_nb_socket(addr, port);

    if (test_sockfd < 0)
    {
        printf("Failed to open socket: %d\r\n", test_sockfd);
        closesocket(test_sockfd);
        vTaskDelete(client_daemon); //删除 AppTaskCreate 任务

    }

    /* setup a client */
    struct mqtt_client client;

    mqtt_init(&client, test_sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback_1);
    /* Create an anonymous session */
    const char* client_id = NULL;
    /* Ensure we have a clean session */
    uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION;
    /* Send connection request to the broker. */
    ret = mqtt_connect(&client, "phh", NULL, NULL, 0, "phh", "12345678", connect_flags, 400);
    if (ret != MQTT_OK)
    {
        printf("mqtt_connect fail \r\n");
    }
    else
    {
        ret =mqtt_sync(&client);
        if ( MQTT_OK != ret)
        {
            printf("mqtt_connect fail \r\n");
        }
        else
        {
            printf("mqtt_connect  success\r\n");
        }
    }

    /* check that we don't have any errors */
    if (client.error != MQTT_OK)
    {
        printf("error: %s\r\n", mqtt_error_str(client.error));
        closesocket(test_sockfd);
        vTaskDelete(client_daemon); //删除 AppTaskCreate 任务
    }

    /* start a thread to refresh the client (handle egress and ingree client traffic) */
    xTaskCreate(client_refresher, (char*)"client_ref", 1024,  &client, 10, &client_daemon);

    /* subscribe */
    if ( MQTT_OK!= mqtt_subscribe(&client, topic, 0))
    {
        printf("mqtt_subscribe fail \r\n");
    }
    /* start publishing the time */
    printf("listening for '%s' messages.\r\n",  topic);
    printf("Press CTRL-C to exit.\r\n");

    /* block wait CTRL-C exit */
    while(1)
    {
        /* publish the time */
        mqtt_publish(&client, topic, "hello", 5, MQTT_PUBLISH_QOS_0);
        vTaskDelay(1000);
    }



}

4.移植断线重连的例程,并做修改(从例程修改为如下,痛苦,还是esp32的例程做得好)

        PS:说明一下大概流程,注册一个重连回调函数,当连接发生错误时,会自动进入到回调函数,在回调函数中进行重连操作,另外需要自己创建mqtt的发送/接收函数做数据处理

void Mqtt_reconnect_Init(void)
{
#if 1
    //等待配网成功,后续可使用信号量或者事件
    EventBits_t r_event; /*  定义一个事件接收变量 */
    r_event = xEventGroupWaitBits(Event_Handle, /*	事件对象句柄 */
                                  WIFI_EVENT,/* 接收 任务 感兴趣的事件 */
                                  pdTRUE, /*  退出时清除事件位 */
                                  pdTRUE, /*  满足感兴趣的所有事件 */
                                  portMAX_DELAY);/*  指定超时事件, 一直等 */

    if (r_event & WIFI_EVENT )
    {
        /*	如果接收完成并且正确 */
        //printf ( "KEY1 与 与 KEY2  都按下\n");
        xEventGroupClearBits( Event_Handle, WIFI_EVENT );
    }
#endif /* 0 */

    const char* addr;
    const char* port;
    const char* topic;
    addr = "192.168.3.20";
    port = "1883";
    topic = "bl618";

    /* build the reconnect_state structure which will be passed to reconnect */
    struct reconnect_state_t reconnect_state;
    reconnect_state.hostname = addr;
    reconnect_state.port = port;
    reconnect_state.topic = topic;

    reconnect_state.sendbuf = sendbuf;
    reconnect_state.sendbufsz = sizeof(sendbuf);
    reconnect_state.recvbuf = recvbuf;
    reconnect_state.recvbufsz = sizeof(recvbuf);
    /* setup a client */
    struct mqtt_client client;


    mqtt_init_reconnect(&client,
                        reconnect_client, &reconnect_state,
                        publish_callback_1
                       );
    /* start a thread to refresh the client (handle egress and ingree client traffic) */
    xTaskCreate(client_refresher, (char*)"client_ref", 1024,  &client, 10, &client_daemon);
	//再创建一个mqtt发送跟接收函数
	
	/* Ensure we have a clean session */
    uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION;
    /* Send connection request to the broker. */
    //mqtt_connect(&client, "phh", NULL, NULL, 0, "phh", "12345678", connect_flags, 400);
    /* start publishing the time */
    printf("listening for '%s' messages.\n", topic);
    printf("Press ENTER to inject an error.\n");
    printf("Press CTRL-D to exit.\n\n");

    /* block */
    //while(1)
    {
        //printf("Injecting error: \"MQTT_ERROR_SOCKET_ERROR\"\n");
        //client.error = MQTT_ERROR_SOCKET_ERROR;
		/* publish the time */
        //mqtt_publish(&client, topic, "hello", 5, MQTT_PUBLISH_QOS_0);
        vTaskDelay(1000);
		printf("\n still running  \n"  );
    }
	vTaskDelay(1000);

	//删除任务
    vTaskDelete(NULL); //删除  任务


}
void reconnect_client(struct mqtt_client* client, void **reconnect_state_vptr)
{
	
    printf("\n reconnect_client start \n");
    struct reconnect_state_t *reconnect_state = *((struct reconnect_state_t**) reconnect_state_vptr);
    /* Close the clients socket if this isn't the initial reconnect call */
    if (client->error != MQTT_ERROR_INITIAL_RECONNECT )
    {
        close(client->socketfd);
    }
    /* Perform error handling here. */
    if (client->error != MQTT_ERROR_INITIAL_RECONNECT)
    {
        printf("reconnect_client: called while client was in error state \"%s\"\n",
               mqtt_error_str(client->error)
              );
    }
	
    /* Open a new socket. */
    int sockfd = open_nb_socket(reconnect_state->hostname, reconnect_state->port);
    if (sockfd == -1)
    {
		printf("\n Failed to open socket:   \n");
        //exit_example(EXIT_FAILURE, sockfd, &client_daemon);
		//vTaskDelete(client_daemon); //删除 AppTaskCreate 任务
    }
	printf("\n open_nb_socket start \n");
    /* Reinitialize the client. */
    mqtt_reinit(client, sockfd,
                reconnect_state->sendbuf, reconnect_state->sendbufsz,
                reconnect_state->recvbuf, reconnect_state->recvbufsz
               );

    /* Send connection request to the broker. */
    mqtt_connect(client, "phh", NULL, NULL, 0, "phh", "12345678", 0, 400);
    /* Subscribe to the topic. */
    mqtt_subscribe(client, reconnect_state->topic, 0);
	
    printf("\n mqtt_subscribe start \n");
	//mqtt_publish(&client, "bl618", "hello", 5, MQTT_PUBLISH_QOS_0);
}

5.烧录后,可看到服务器突然断线的话会不断进入回调函数进行重新连接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值