mqtt - 如何初始化 LwIP 以使用 MQTT 库
问题描述
我查看并遵循了 LwIP 2.0.2 的文档。我的项目包含 LwIP 2.0.2 中提供的 MQTT 库。我还在https://dzone.com/articles/mqtt-with-lwip-and-the-nxp-frdm-k64f找到了一些帮助。我无法建立连接,我使用了免费的公共 MQTT 代理,但连接没有希望。我可以ping我的设备。难道我做错了什么?
static void mqtt_test(mqtt_client_t *mqtt_client)
if (mqtt_client_is_connected(&mqtt_client) == 1)
{
example_subscribe(&mqtt_client, NULL);
} else {
mqtt_do_connect(&mqtt_client);
}
}
当我调用此方法时,它总是进入 mqtt_do_connect() 从不连接。这是 mqtt_do_connect
static void mqtt_do_connect(mqtt_client_t *mqtt_client)
{
ip4_addr_t broker_ipaddr;
struct mqtt_connect_client_info_t ci;
err_t err;
if (ipaddr_aton("52.58.177.181", &broker_ipaddr))
{
err = ERR_OK;
}
/* Setup an empty client info structure */
memset( & ci, 0, sizeof(ci));
/* Minimal amount of information required is client identifier, so set it here */
ci.client_id = "test";
/* Initiate client and connect to server, if this fails immediately an error code is returned
otherwise mqtt_connection_cb will be called with connection result after attempting
to establish a connection with the server.
For now MQTT version 3.1.1 is always used */
err = mqtt_client_connect(mqtt_client, & broker_ipaddr, 1883, mqtt_connection_cb, 0, & ci);
/* For now just print the result code if something goes wrong */
if (err != ERR_OK) {
printf("mqtt_connect return %d\n", err);
}
}
我还在 mqtt.c 中的 mqtt_client_connect 方法中注意到它存在:
/* Any local address, pick random local port number */
err = tcp_bind(client->conn, IP_ADDR_ANY, 0);
为什么需要这个?如果我将 IP_ADDR_ANY 替换为我的设备静态 IP 的本地地址,它将运行而不会引发错误,但不会调用回调 mqtt_connection_cb。
我还初始化了静态 IP 提到的 TCP/IP 堆栈。我将 NO_SYS 用作 1,但会将其移至 FreeRTOS,但要先迈出第一步。
我在 LwIP 实现中没有找到对 MQTT 的太多支持,我是否遗漏了一些明显的东西,任何帮助将不胜感激。
我已经使用 MQTTfx 在代理上运行了一个或两个测试,响应良好,但我的嵌入式设备 (Atmel SAME54) 没有。
解决方案
我找到了解决方案。我在 FreeRTOS 线程中运行 TCP 设置并打开了一个套接字
static void mqtt_start(void *p)
{
struct sockaddr_in address;
int s_create, new_socket;
int addrlen = sizeof(address);
int opt = 1;
int socket_check;
sys_sem_t sem;
err_t err_sem;
err_sem = sys_sem_new(&sem, 0); /* Create a new semaphore. */
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(&sem); /* Block until the lwIP stack is initialized. */
sys_sem_free(&sem); /* Free the semaphore. */
/*Create a socket*/
s_create = socket(AF_INET, 1, 0);
setsockopt(s_create, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(IPADDR_ANY);
address.sin_port = htons(HTTP_PORT);
/* bind the connection to port */
socket_check = bind(s_create, (struct sockaddr *)&address, sizeof(address));
if (socket_check < 0) {
LWIP_DEBUGF(LWIP_DBG_ON, ("Bind error=%d\n", socket_check));
goto socket_close;
}
/* tell the connection to listen for incoming connection requests */
listen(s_create, 3);
mqtt_connect(&mqtt_client);
for (;;) {
new_socket = accept(s_create, (struct sockaddr *)&address, (socklen_t *)&addrlen);
socket_close:
close(new_socket);
}
}
我的 mqtt 客户端的初始化也有问题,在它上面放了一个手表,发现结构没有初始化。我全局初始化它
mqtt_client_t mqtt_client;
然后稍后在 mqtt_start 中使用它。
推荐阅读
- apache-kafka - Kafka 到 Kafka -> 多次读取源 kafka 主题
- swiftui - 如何在 SwiftUI 中进行类似 Apple Music 的导航?自定义列表和 NavigationView 的突出显示不会消失
- c++ - 将抽象对象从主线程发送到其他线程
- laravel - cross-env:在容器优化操作系统上部署 docker 时权限被拒绝
- c - 什么是名为“sh”的进程
- ruby-on-rails - 在 ActiveModelSerializers 中过滤关联
- node.js - React 组件未在 socket.io 事件上更新
- postgresql - 更改现有表中的主键及其(外部)引用 - Knex.js / Postgres
- vba - MS-Access:使用 vba 移动到 NavigationControl
- spring-boot - 在 Spring Cloud Gateway 预过滤器中获取 SecurityContextHolder