Raspberry Pico Wireless MQTT
This guide provides a simple approach to establishing an MQTT connection with lwIP library based on the lwIP MQTT client.
LwIP stands for Lightweight IP, and it is an open-source TCP/IP stack designed to be used in embedded systems with limited resources such as memory, processing power, and storage. LwIP provides a range of networking protocols and features that enable communication over the internet or other networks.
LwIP is commonly used in many embedded systems, such as network routers, industrial automation, IoT devices, and other similar applications. It is lightweight, efficient, and can be easily customized for specific applications.
Let’s get started !
An instance of MQTT client is instantiated, which is associated with the data structure MQTT_CLIENT_DATA_T.
mqtt=(MQTT_CLIENT_DATA_T*)calloc(1, sizeof(MQTT_CLIENT_DATA_T));typedef struct MQTT_CLIENT_DATA_T {
mqtt_client_t *mqtt_client_inst;
struct mqtt_connect_client_info_t mqtt_client_info;
uint8_t data[MQTT_OUTPUT_RINGBUF_SIZE];
uint8_t topic[100];
uint32_t len;
} MQTT_CLIENT_DATA_T;struct mqtt_connect_client_info_t mqtt_client_info =
{
“picow”,
“mqtt_user”, /* user */
“mqtt_password”, /* pass */
0, /* keep alive */
NULL, /* will_topic */
NULL, /* will_msg */
0, /* will_qos */
0 /* will_retain */
#if LWIP_ALTCP && LWIP_ALTCP_TLS
, NULL
#endif
};To establish a connection to the Wi-Fi network, we initialize the cyw43_driver code and set up the lwIP stack.
if (cyw43_arch_init())
{
printf(“failed to initialise\n”);
return 1;
}Next, we activate the Wi-Fi STA (Station) mode, which allows the device to connect to Wi-Fi Access Points.
cyw43_arch_enable_sta_mode();Attempt to establish a connection to the Wi-Fi access point using the provided parameters for the Wi-Fi SSID, password, and authorization type.
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000))
{
printf(“failed to connect\n”);
return 1;
}Additionally, validate whether the provided IP address is a valid ASCII representation of an internet address and convert it to a binary address.
ip_addr_t addr;
if (!ip4addr_aton(“XX.XX”, &addr)) {
printf(“ip error\n”);
return 0;
}Create a new MQTT client instance.
mqtt->mqtt_client_inst = mqtt_client_new();Set callback to handle incoming publish requests from server.
mqtt_set_inpub_callback(mqtt->mqtt_client_inst, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, mqtt);The mqtt_incoming_publish_cb function is called whenever an incoming publish message is received by the MQTT client, while the mqtt_incoming_data_cb function is called when data related to the publish message is received.
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) {
MQTT_CLIENT_DATA_T* mqtt_client = (MQTT_CLIENT_DATA_T*)arg;
strcpy((char*)mqtt_client->topic, (char*)topic);
if (strcmp((const char*)mqtt->topic, "stop") == 0) {
printf("STOP\n");
}
if (strcmp((const char*)mqtt->topic, "start") == 0) {
printf("START\n");
}
}static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) {
printf("mqtt_incoming_data_cb\n");
MQTT_CLIENT_DATA_T* mqtt_client = (MQTT_CLIENT_DATA_T*)arg;
LWIP_UNUSED_ARG(data);
strncpy((char*)mqtt_client->data, (char*)data, len);
}Subsequently, to establish a connection to the MQTT server.
err_t err = mqtt_client_connect(mqtt->mqtt_client_inst, &addr, MQTT_PORT, &mqtt_connection_cb, mqtt, &mqtt->mqtt_client_info);
if (err != ERR_OK) {
printf(“connect error\n”);
return 0;
}Furthermore, an attempt is made to publish the message to the pub_topic topic.
err_t do_publish(mqtt_client_t *client, void *arg)
{
const char *pub_payload= “Picow MQTT”;
err_t err;
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
u8_t retain = 0; /* No don’t retain such crappy payload… */
cyw43_arch_lwip_begin();
err = mqtt_publish(client, “pub_topic”, pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
cyw43_arch_lwip_end();
if(err != ERR_OK) {
printf(“Publish err: %d\n”, err);
}
return err;
}Follow these steps to subscribe to topics:
mqtt_sub_unsub(client, “start”, 0, mqtt_request_cb, arg, 1);
mqtt_sub_unsub(client, “stop”, 0, mqtt_request_cb, arg, 1);Build the program using CMake.
cmake ..
make -j4Then, copy the UF2 file to the Pico and let’s test it with Home Assistant.
The full code is provided below.





