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);
}