Hi guys,
I have MQTT v5 up and running but I am currently trying to implement one-way TLS then mutual TLS once it's completed. I am not too sure what I am doing wrong but I always seem to get the following error in my serial terminal:
[00:00:00.307,952] <inf> eth_w5500: W5500 Initialized *** Booting nRF Connect SDK v3.1.1-e2a97fe2578a *** *** Using Zephyr OS v4.1.99-ff8f0c579eeb *** [00:00:00.310,180] <inf> app: Waiting for network interface to be up... [00:00:01.808,319] <inf> eth_w5500: ethernet@0: Link up [00:00:01.811,218] <inf> app: Network interface is up; starting DHCPv4... [00:00:09.826,812] <inf> net_dhcpv4: Received: 192.168.50.210 [00:00:11.312,957] <inf> app: IPv4 address: 192.168.50.210 [00:00:11.312,957] <inf> app: Adding CA certificate (size: 1550 bytes) [00:00:11.312,988] <inf> app: Successfully added CA certificate [00:00:11.313,018] <inf> app: tls_init: 0 <OK> [00:00:11.313,018] <inf> app: attempting to connect: [00:00:11.313,110] <inf> app: TLS configuration complete [00:00:11.313,262] <dbg> net_sock_tls: tls_alloc: (main): Allocated TLS context, 0x20002098 [00:00:11.313,720] <dbg> net_sock: zsock_socket_internal: (main): socket: ctx=0x200039e4, fd=4 [00:00:11.397,613] <err> net_sock_tls: Failed to parse CA certificate, err: -0x2180 [00:00:11.397,796] <dbg> net_sock: zsock_close_ctx: (main): close: ctx=0x200039e4, fd=4 [00:00:11.398,742] <inf> app: mqtt_connect: -22 <ERROR> [00:00:11.898,895] <inf> app: TLS configuration complete [00:00:11.899,108] <dbg> net_sock_tls: tls_alloc: (main): Allocated TLS context, 0x20002098 [00:00:11.899,536] <dbg> net_sock: zsock_socket_internal: (main): socket: ctx=0x20003a78, fd=4 [00:00:11.909,423] <err> net_sock_tls: Failed to parse CA certificate, err: -0x2180
The TCP dump output is below and my interpretation of it:
-
TCP connect succeeds.
-
The client app closes the socket before sending any TLS data (no ClientHello seen).
-
The broker, having seen an abrupt close/invalid record boundary, replies with a fatal decode_error alert and closes.
14:54:08.975175 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 44)
192.168.50.210.40075 > 192.168.50.215.8883: Flags [S], cksum 0x3f44 (correct), seq 1483820942, win 2730, options [mss 1460], length 0
0x0000: 4500 002c 0000 0000 4006 93d2 c0a8 32d2 E..,[email protected].
0x0010: c0a8 32d7 9c8b 22b3 5871 4f8e 0000 0000 ..2...".XqO.....
0x0020: 6002 0aaa 3f44 0000 0204 05b4 0000 `...?D........
14:54:08.976186 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
192.168.50.215.8883 > 192.168.50.210.40075: Flags [S.], cksum 0xf3a3 (correct), seq 608907758, ack 1483820943, win 65535, options [mss 1460], length 0
0x0000: 4500 002c 0000 4000 4006 53d2 c0a8 32d7 E..,..@[email protected].
0x0010: c0a8 32d2 22b3 9c8b 244b 31ee 5871 4f8f ..2."...$K1.XqO.
0x0020: 6012 ffff f3a3 0000 0204 05b4 `...........
14:54:08.983478 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 40)
192.168.50.210.40075 > 192.168.50.215.8883: Flags [.], cksum 0x00b7 (correct), seq 1, ack 1, win 2730, length 0
0x0000: 4500 0028 0000 0000 4006 93d6 c0a8 32d2 E..([email protected].
0x0010: c0a8 32d7 9c8b 22b3 5871 4f8f 244b 31ef ..2...".XqO.$K1.
0x0020: 5010 0aaa 00b7 0000 0000 0000 0000 P.............
14:54:08.985019 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 40)
192.168.50.210.40075 > 192.168.50.215.8883: Flags [F.], cksum 0x00b6 (correct), seq 1, ack 1, win 2730, length 0
0x0000: 4500 0028 0000 0000 4006 93d6 c0a8 32d2 E..([email protected].
0x0010: c0a8 32d7 9c8b 22b3 5871 4f8f 244b 31ef ..2...".XqO.$K1.
0x0020: 5011 0aaa 00b6 0000 0000 0000 0000 P.............
14:54:08.985228 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
192.168.50.215.8883 > 192.168.50.210.40075: Flags [.], cksum 0x0b60 (correct), seq 1, ack 2, win 65535, length 0
0x0000: 4500 0028 0000 4000 4006 53d6 c0a8 32d7 E..(..@[email protected].
0x0010: c0a8 32d2 22b3 9c8b 244b 31ef 5871 4f90 ..2."...$K1.XqO.
0x0020: 5010 ffff 0b60 0000 P....`..
14:54:08.987085 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 47)
192.168.50.215.8883 > 192.168.50.210.40075: Flags [P.], cksum 0xbf4b (correct), seq 1:8, ack 2, win 65535, length 7
0x0000: 4500 002f 0000 4000 4006 53cf c0a8 32d7 E../..@[email protected].
0x0010: c0a8 32d2 22b3 9c8b 244b 31ef 5871 4f90 ..2."...$K1.XqO.
0x0020: 5018 ffff bf4b 0000 1503 0300 0202 32 P....K........2
14:54:08.987403 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
192.168.50.215.8883 > 192.168.50.210.40075: Flags [F.], cksum 0x0b58 (correct), seq 8, ack 2, win 65535, length 0
0x0000: 4500 0028 0000 4000 4006 53d6 c0a8 32d7 E..(..@[email protected].
0x0010: c0a8 32d2 22b3 9c8b 244b 31f6 5871 4f90 ..2."...$K1.XqO.
0x0020: 5011 ffff 0b58 0000 P....X..
14:54:08.996072 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 40)
192.168.50.210.40075 > 192.168.50.215.8883: Flags [R], cksum 0x61a6 (correct), seq 1483820944, win 0, length 0
0x0000: 4500 0028 0000 0000 4006 93d6 c0a8 32d2 E..([email protected].
0x0010: c0a8 32d7 9c8b 22b3 5871 4f90 0000 0000 ..2...".XqO.....
0x0020: 5004 0000 61a6 0000 0000 0000 0000 P...a.........
14:54:09.488659 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 44)
192.168.50.210.55445 > 192.168.50.215.8883: Flags [S], cksum 0x6c11 (correct), seq 765989248, win 2730, options [mss 1460], length 0
0x0000: 4500 002c 0000 0000 4006 93d2 c0a8 32d2 E..,[email protected].
0x0010: c0a8 32d7 d895 22b3 2da8 1180 0000 0000 ..2...".-.......
0x0020: 6002 0aaa 6c11 0000 0204 05b4 0000 `...l.........
14:54:09.489540 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
192.168.50.215.8883 > 192.168.50.210.55445: Flags [S.], cksum 0x1db8 (correct), seq 2464269840, ack 765989249, win 65535, options [mss 1460], length 0
0x0000: 4500 002c 0000 4000 4006 53d2 c0a8 32d7 E..,..@[email protected].
0x0010: c0a8 32d2 22b3 d895 92e1 c610 2da8 1181 ..2.".......-...
0x0020: 6012 ffff 1db8 0000 0204 05b4 `...........
14:54:09.496937 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 40)
192.168.50.210.55445 > 192.168.50.215.8883: Flags [.], cksum 0x2acb (correct), seq 1, ack 1, win 2730, length 0
0x0000: 4500 0028 0000 0000 4006 93d6 c0a8 32d2 E..([email protected].
0x0010: c0a8 32d7 d895 22b3 2da8 1181 92e1 c611 ..2...".-.......
0x0020: 5010 0aaa 2acb 0000 0000 0000 0000 P...*.........
14:54:09.498449 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 40)
192.168.50.210.55445 > 192.168.50.215.8883: Flags [F.], cksum 0x2aca (correct), seq 1, ack 1, win 2730, length 0
0x0000: 4500 0028 0000 0000 4006 93d6 c0a8 32d2 E..([email protected].
0x0010: c0a8 32d7 d895 22b3 2da8 1181 92e1 c611 ..2...".-.......
0x0020: 5011 0aaa 2aca 0000 0000 0000 0000 P...*.........
14:54:09.498635 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
192.168.50.215.8883 > 192.168.50.210.55445: Flags [.], cksum 0x3574 (correct), seq 1, ack 2, win 65535, length 0
0x0000: 4500 0028 0000 4000 4006 53d6 c0a8 32d7 E..(..@[email protected].
0x0010: c0a8 32d2 22b3 d895 92e1 c611 2da8 1182 ..2.".......-...
0x0020: 5010 ffff 3574 0000 P...5t..
14:54:09.498784 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 47)
192.168.50.215.8883 > 192.168.50.210.55445: Flags [P.], cksum 0xe95f (correct), seq 1:8, ack 2, win 65535, length 7
0x0000: 4500 002f 0000 4000 4006 53cf c0a8 32d7 E../..@[email protected].
0x0010: c0a8 32d2 22b3 d895 92e1 c611 2da8 1182 ..2.".......-...
0x0020: 5018 ffff e95f 0000 1503 0300 0202 32 P...._........2
14:54:09.498876 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
192.168.50.215.8883 > 192.168.50.210.55445: Flags [F.], cksum 0x356c (correct), seq 8, ack 2, win 65535, length 0
0x0000: 4500 0028 0000 4000 4006 53d6 c0a8 32d7 E..(..@[email protected].
0x0010: c0a8 32d2 22b3 d895 92e1 c618 2da8 1182 ..2.".......-...
0x0020: 5011 ffff 356c 0000 P...5l..
14:54:09.509352 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 40)
192.168.50.210.55445 > 192.168.50.215.8883: Flags [R], cksum 0x8e73 (correct), seq 765989250, win 0, length 0
0x0000: 4500 0028 0000 0000 4006 93d6 c0a8 32d2 E..([email protected].
0x0010: c0a8 32d7 d895 22b3 2da8 1182 0000 0000 ..2...".-.......
0x0020: 5004 0000 8e73 0000 0000 0000 0000 P....s........
I am including my files for your perusal. Most of it I have implemented from the NCS zephyr MQTT publisher example that is provided but using my own certs and the nRF5340DK board along with the W5500 controller board. Any help would be appreciated has I have been suck on this.
7382.certs.h6177.prj.conf2867.nrf5340dk_nrf5340_cpuapp.overlay
/*
* nRF5340 DK + W5500 (SPI) + Zephyr (NCS 3.1.1)
* Ethernet via W5500 (DHCPv4) + MQTT v5.0 over TCP (no TLS)
*/
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/dhcpv4.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/mqtt.h>
#include <zephyr/sys/util.h> /* MIN() */
#include <stdbool.h>
#include <string.h>
#include <zephyr/random/random.h>
#include <zephyr/posix/poll.h>
#include <errno.h>
// Local Project Settings
#include "config.h"
#include "certs.h"
#define APP_BMEM
#define APP_DMEM
LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);
/* Buffers for MQTT client. */
static APP_BMEM uint8_t rx_buffer[APP_MQTT_BUFFER_SIZE];
static APP_BMEM uint8_t tx_buffer[APP_MQTT_BUFFER_SIZE];
/* The mqtt client struct */
static APP_BMEM struct mqtt_client client;
/* MQTT Broker details. */
static APP_BMEM struct sockaddr_storage broker;
static APP_BMEM struct pollfd fds[1];
static APP_BMEM int nfds;
static APP_BMEM bool connected;
/* Whether to include full topic in the publish message, or alias only (MQTT 5). */
static APP_BMEM bool include_topic;
static APP_BMEM bool aliases_enabled;
#define APP_TOPIC_ALIAS 1
#define TLS_SNI_HOSTNAME BROKER_NAME
#define APP_CA_CERT_TAG 1
#define APP_PSK_TAG 2
static APP_DMEM sec_tag_t m_sec_tags[] = {APP_CA_CERT_TAG};
// Initialize TLS credentials
static int tls_init(void)
{
int err;
LOG_INF("Adding CA certificate (size: %d bytes)", sizeof(ca_certificate_pem));
LOG_HEXDUMP_DBG(ca_certificate_pem, sizeof(ca_certificate_pem), "Certificate:");
/* First delete any existing credential */
tls_credential_delete(APP_CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE);
/* Add the CA certificate */
err = tls_credential_add(APP_CA_CERT_TAG,
TLS_CREDENTIAL_CA_CERTIFICATE,
ca_certificate_pem,
sizeof(ca_certificate_pem) - 1); // Subtract 1 to exclude null terminator
if (err < 0) {
LOG_ERR("Failed to register CA certificate: %d (0x%x)", err, -err);
return err;
}
LOG_INF("Successfully added CA certificate");
return 0;
}
// Prepare file descriptors for poll()
static void prepare_fds(struct mqtt_client *client)
{
if (client->transport.type == MQTT_TRANSPORT_NON_SECURE) {
fds[0].fd = client->transport.tcp.sock;
}
else if (client->transport.type == MQTT_TRANSPORT_SECURE) {
fds[0].fd = client->transport.tls.sock;
}
fds[0].events = POLLIN;
nfds = 1;
}
// Clear file descriptors
static void clear_fds(void)
{
nfds = 0;
}
// Wait for socket events with timeout
static int wait(int timeout)
{
int ret = 0;
if (nfds > 0) {
ret = poll(fds, nfds, timeout);
if (ret < 0) {
LOG_ERR("poll error: %d", errno);
}
}
return ret;
}
// MQTT event handler
void mqtt_evt_handler(struct mqtt_client *const client,
const struct mqtt_evt *evt)
{
int err;
switch (evt->type) {
case MQTT_EVT_CONNACK:
// Check if connection was successful
if (evt->result != 0) {
LOG_ERR("MQTT connect failed %d", evt->result);
break;
}
connected = true;
LOG_INF("MQTT client connected!");
// Check if broker supports topic aliases
if (evt->param.connack.prop.rx.has_topic_alias_maximum &&
evt->param.connack.prop.topic_alias_maximum > 0) {
LOG_INF("Topic aliases allowed by the broker, max %u.",
evt->param.connack.prop.topic_alias_maximum);
aliases_enabled = true;
} else {
LOG_INF("Topic aliases disallowed by the broker.");
}
break;
case MQTT_EVT_DISCONNECT:
// Handle disconnection
LOG_INF("MQTT client disconnected %d", evt->result);
connected = false;
clear_fds();
break;
case MQTT_EVT_PUBACK:
// Handle PUBACK for QoS
if (evt->result != 0) {
LOG_ERR("MQTT PUBACK error %d", evt->result);
break;
}
LOG_INF("PUBACK packet id: %u", evt->param.puback.message_id);
break;
case MQTT_EVT_PUBREC:
// Handle PUBREC for QoS
if (evt->result != 0) {
LOG_ERR("MQTT PUBREC error %d", evt->result);
break;
}
LOG_INF("PUBREC packet id: %u", evt->param.pubrec.message_id);
const struct mqtt_pubrel_param rel_param = {
.message_id = evt->param.pubrec.message_id
};
err = mqtt_publish_qos2_release(client, &rel_param);
if (err != 0) {
LOG_ERR("Failed to send MQTT PUBREL: %d", err);
}
break;
case MQTT_EVT_PUBCOMP:
// Handle PUBCOMP for QoS
if (evt->result != 0) {
LOG_ERR("MQTT PUBCOMP error %d", evt->result);
break;
}
LOG_INF("PUBCOMP packet id: %u",
evt->param.pubcomp.message_id);
break;
case MQTT_EVT_PINGRESP:
// Handle PINGRESP
LOG_INF("PINGRESP packet");
break;
default:
break;
}
}
// Generate MQTT payload based on QoS
static char *get_mqtt_payload(enum mqtt_qos qos)
{
static APP_DMEM char payload[] = "DOORS:OPEN_QoSx";
payload[strlen(payload) - 1] = '0' + qos;
return payload;
}
// Generate MQTT topic based on configuration
static char *get_mqtt_topic(void)
{
#if APP_HOSPITAL_TOPIC
return "iot-2/type/"HOSPITAL_DEVTYPE"/id/"HOSPITAL_DEVID
"/evt/"HOSPITAL_EVENT"/fmt/"HOSPITAL_FORMAT;
#else
return "Testing/Zephyr/MQTT";
#endif
}
// Publish MQTT message with given QoS
static int publish(struct mqtt_client *client, enum mqtt_qos qos)
{
struct mqtt_publish_param param = { 0 };
/* Always true for MQTT 3.1.1.
* True only on first publish message for MQTT 5.0 if broker allows aliases.
*/
if (include_topic) {
param.message.topic.topic.utf8 = (uint8_t *)get_mqtt_topic();
param.message.topic.topic.size =
strlen(param.message.topic.topic.utf8);
}
param.message.topic.qos = qos;
param.message.payload.data = get_mqtt_payload(qos);
param.message.payload.len =
strlen(param.message.payload.data);
param.message_id = sys_rand16_get();
param.dup_flag = 0U;
param.retain_flag = 0U;
if (aliases_enabled) {
param.prop.topic_alias = APP_TOPIC_ALIAS;
include_topic = false;
}
return mqtt_publish(client, ¶m);
}
#define RC_STR(rc) ((rc) == 0 ? "OK" : "ERROR")
// Macro to print function results
#define PRINT_RESULT(func, rc) \
LOG_INF("%s: %d <%s>", (func), rc, RC_STR(rc))
// Initialize broker address
static void broker_init(void)
{
struct sockaddr_in *broker4 = (struct sockaddr_in *)&broker;
broker4->sin_family = AF_INET;
broker4->sin_port = htons(BROKER_PORT);
int aerr = net_addr_pton(AF_INET, BROKER_IP, &broker4->sin_addr);
if (aerr) {
LOG_INF("net_addr_pton failed (%d) for %s", aerr, BROKER_IP);
}
}
// Initialize MQTT client
static void client_init(struct mqtt_client *client)
{
mqtt_client_init(client);
broker_init();
/* MQTT client configuration */
client->broker = &broker;
client->evt_cb = mqtt_evt_handler;
client->client_id.utf8 = (uint8_t *)CLIENT_ID;
client->client_id.size = strlen(CLIENT_ID);
client->password = NULL;
client->user_name = NULL;
client->protocol_version = MQTT_VERSION_5_0;
/* MQTT buffers configuration */
client->rx_buf = rx_buffer;
client->rx_buf_size = sizeof(rx_buffer);
client->tx_buf = tx_buffer;
client->tx_buf_size = sizeof(tx_buffer);
/* MQTT transport configuration */
client->transport.type = MQTT_TRANSPORT_SECURE;
struct mqtt_sec_config *tls_config = &client->transport.tls.config;
tls_config->peer_verify = TLS_PEER_VERIFY_REQUIRED;
tls_config->cipher_count = 0; // Let mbedTLS choose ciphers
tls_config->cipher_list = NULL;
tls_config->sec_tag_list = m_sec_tags;
tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags);
tls_config->hostname = TLS_SNI_HOSTNAME; // Must match cert CN
tls_config->cert_nocopy = 0; // Copy certificates
LOG_INF("TLS configuration complete");
}
// Process MQTT events and maintain connection
static int process_mqtt_and_sleep(struct mqtt_client *client, int timeout)
{
int64_t remaining = timeout;
int64_t start_time = k_uptime_get();
int rc;
while (remaining > 0 && connected) {
if (wait(remaining)) {
rc = mqtt_input(client);
if (rc != 0) {
PRINT_RESULT("mqtt_input", rc);
return rc;
}
}
rc = mqtt_live(client);
if (rc != 0 && rc != -EAGAIN) {
PRINT_RESULT("mqtt_live", rc);
return rc;
} else if (rc == 0) {
rc = mqtt_input(client);
if (rc != 0) {
PRINT_RESULT("mqtt_input", rc);
return rc;
}
}
remaining = timeout + start_time - k_uptime_get();
}
return 0;
}
/* In this routine we block until the connected variable is 1 */
static int try_to_connect(struct mqtt_client *client)
{
int rc, i = 0;
while (i++ < APP_CONNECT_TRIES && !connected) {
client_init(client);
rc = mqtt_connect(client);
if (rc != 0) {
PRINT_RESULT("mqtt_connect", rc);
k_sleep(K_MSEC(APP_SLEEP_MSECS));
continue;
}
prepare_fds(client);
if (wait(APP_CONNECT_TIMEOUT_MS)) {
mqtt_input(client);
}
if (!connected) {
mqtt_abort(client);
}
}
if (connected) {
return 0;
}
return -EINVAL;
}
#define SUCCESS_OR_EXIT(rc) { if (rc != 0) { return 1; } }
#define SUCCESS_OR_BREAK(rc) { if (rc != 0) { break; } }
// Main publisher function
static int publisher(void)
{
int i, rc, r = 0;
include_topic = true;
aliases_enabled = false;
LOG_INF("attempting to connect: ");
rc = try_to_connect(&client);
PRINT_RESULT("try_to_connect", rc);
SUCCESS_OR_EXIT(rc);
i = 0;
while (i++ < CONFIG_NET_SAMPLE_APP_MAX_ITERATIONS && connected) {
r = -1;
rc = mqtt_ping(&client);
PRINT_RESULT("mqtt_ping", rc);
SUCCESS_OR_BREAK(rc);
rc = process_mqtt_and_sleep(&client, APP_SLEEP_MSECS);
SUCCESS_OR_BREAK(rc);
rc = publish(&client, MQTT_QOS_0_AT_MOST_ONCE);
PRINT_RESULT("mqtt_publish", rc);
SUCCESS_OR_BREAK(rc);
rc = process_mqtt_and_sleep(&client, APP_SLEEP_MSECS);
SUCCESS_OR_BREAK(rc);
rc = publish(&client, MQTT_QOS_1_AT_LEAST_ONCE);
PRINT_RESULT("mqtt_publish", rc);
SUCCESS_OR_BREAK(rc);
rc = process_mqtt_and_sleep(&client, APP_SLEEP_MSECS);
SUCCESS_OR_BREAK(rc);
rc = publish(&client, MQTT_QOS_2_EXACTLY_ONCE);
PRINT_RESULT("mqtt_publish", rc);
SUCCESS_OR_BREAK(rc);
rc = process_mqtt_and_sleep(&client, APP_SLEEP_MSECS);
SUCCESS_OR_BREAK(rc);
r = 0;
}
rc = mqtt_disconnect(&client, NULL);
PRINT_RESULT("mqtt_disconnect", rc);
LOG_INF("Bye!");
return r;
}
// Start the application
static int start_app(void)
{
int r = 0, i = 0;
while (!CONFIG_NET_SAMPLE_APP_MAX_CONNECTIONS ||
i++ < CONFIG_NET_SAMPLE_APP_MAX_CONNECTIONS) {
r = publisher();
if (!CONFIG_NET_SAMPLE_APP_MAX_CONNECTIONS) {
k_sleep(K_MSEC(5000));
}
}
return r;
}
// Wait for network interface to be up and get IPv4 address
static void wait_for_network(void)
{
struct net_if *iface = net_if_get_default();
int waited_ms = 0;
LOG_INF("Waiting for network interface to be up...");
while (!net_if_is_up(iface)) {
k_sleep(K_MSEC(100));
}
LOG_INF("Network interface is up; starting DHCPv4...");
net_dhcpv4_start(iface);
/* Wait for IPv4 address with longer timeout */
while (net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED) == NULL) {
if (waited_ms >= 30000) { // 30 second timeout
LOG_ERR("Timed out waiting for IPv4 address");
break;
}
k_sleep(K_MSEC(500));
waited_ms += 500;
}
/* Additional wait after IP acquisition */
k_sleep(K_MSEC(1000));
const struct in_addr *addr = net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED);
if (addr) {
char buf[NET_IPV4_ADDR_LEN];
net_addr_ntop(AF_INET, addr, buf, sizeof(buf));
LOG_INF("IPv4 address: %s", buf);
} else {
LOG_ERR("No IPv4 address obtained");
}
}
// Main function
int main(void)
{
wait_for_network();
int rc;
rc = tls_init();
PRINT_RESULT("tls_init", rc);
rc = start_app();
PRINT_RESULT("start_app", rc);
// Loop forever - don't exit
while (1) {
k_sleep(K_SECONDS(1));
}
return 0; // Never reached
}
// /* Flags set by the MQTT event handler */
// static volatile bool g_connack_ok;
// static volatile bool g_suback_ok;
// static void send_test_pub(struct mqtt_client *client);
// /* --- IPv4 helpers --- */
// static const struct in_addr *get_ipv4_addr(struct net_if *iface)
// {
// return net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED);
// }
// static void print_ipv4(struct net_if *iface)
// {
// char buf[NET_IPV4_ADDR_LEN];
// const struct in_addr *addr = get_ipv4_addr(iface);
// if (addr) {
// LOG_INF("IPv4 address: %s", net_addr_ntop(AF_INET, addr, buf, sizeof(buf)));
// } else {
// LOG_INF("No IPv4 address yet");
// }
// }
// static int acquire_dhcp_address(struct net_if *iface, int timeout_ms)
// {
// int waited = 0;
// net_dhcpv4_start(iface);
// while (waited < timeout_ms) {
// if (get_ipv4_addr(iface)) {
// return 0;
// }
// k_sleep(K_MSEC(200));
// waited += 200;
// }
// return -ETIMEDOUT;
// }
// /* --- MQTT event handler (v5) --- */
// static void mqtt_event_handler(struct mqtt_client *const client,
// const struct mqtt_evt *evt)
// {
// switch (evt->type) {
// case MQTT_EVT_CONNACK:
// if (evt->param.connack.return_code == 0) {
// LOG_INF("MQTT v5 connected");
// g_connack_ok = true;
// } else {
// LOG_INF("MQTT CONNACK return_code=%u", evt->param.connack.return_code);
// }
// break;
// case MQTT_EVT_PUBLISH: {
// const struct mqtt_publish_param *p = &evt->param.publish;
// LOG_INF("Message on topic %.*s (QoS %d, id %u)",
// (int)p->message.topic.topic.size,
// (const char *)p->message.topic.topic.utf8,
// p->message.topic.qos,
// p->message_id);
// /* Drain payload fully */
// size_t remaining = p->message.payload.len;
// while (remaining > 0) {
// uint8_t buf[64];
// size_t to_read = MIN(remaining, sizeof(buf));
// int r = mqtt_read_publish_payload(client, buf, to_read);
// if (r < 0) {
// LOG_INF("mqtt_read_publish_payload err %d", r);
// break;
// }
// LOG_INF("Payload chunk (%d/%u): %.*s",
// r, (unsigned)p->message.payload.len, r, (const char *)buf);
// remaining -= (size_t)r;
// }
// /* QoS1 inbound → send PUBACK */
// if (p->message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) {
// struct mqtt_puback_param ack = { .message_id = p->message_id };
// int err = mqtt_publish_qos1_ack(client, &ack);
// if (err) {
// LOG_INF("PUBACK failed (%d)", err);
// }
// }
// break;
// }
// case MQTT_EVT_SUBACK: {
// const struct mqtt_suback_param *sa = &evt->param.suback;
// LOG_INF("SUBACK id=%u count=%u",
// sa->message_id, (unsigned)sa->return_codes.len);
// for (uint16_t i = 0; i < sa->return_codes.len; i++) {
// uint8_t rc = sa->return_codes.data[i];
// LOG_INF(" rc[%u]=%u", (unsigned)i, (unsigned)rc);
// }
// g_suback_ok = true;
// break;
// }
// case MQTT_EVT_DISCONNECT:
// LOG_INF("MQTT disconnected");
// g_connack_ok = false;
// g_suback_ok = false;
// break;
// default:
// break;
// }
// }
// /* --- Configure client for MQTT v5 over TCP --- */
// static void mqtt_setup(struct mqtt_client *client, struct sockaddr_in *broker)
// {
// mqtt_client_init(client);
// memset(broker, 0, sizeof(*broker));
// broker->sin_family = AF_INET;
// broker->sin_port = htons(BROKER_PORT);
// int aerr = net_addr_pton(AF_INET, BROKER_IP, &broker->sin_addr);
// if (aerr) {
// LOG_INF("net_addr_pton failed (%d) for %s", aerr, BROKER_IP);
// }
// static uint8_t rxbuf[1024];
// static uint8_t txbuf[1024];
// client->broker = (struct sockaddr *)broker;
// client->evt_cb = mqtt_event_handler;
// client->client_id = MQTT_UTF8_LITERAL(CLIENT_ID);
// /* v5 protocol + clean start */
// client->protocol_version = MQTT_VERSION_5_0;
// client->clean_session = 1;
// client->keepalive = CONFIG_MQTT_KEEPALIVE;
// client->transport.type = MQTT_TRANSPORT_NON_SECURE;
// client->rx_buf = rxbuf;
// client->rx_buf_size = sizeof(rxbuf);
// client->tx_buf = txbuf;
// client->tx_buf_size = sizeof(txbuf);
// #if defined(CONFIG_MQTT_VERSION_5_0)
// /* Minimal non-empty CONNECT properties */
// client->prop.request_problem_info = 1;
// #endif
// }
// /* Connect → wait CONNACK → subscribe → wait SUBACK */
// static int mqtt_connect_and_sub(struct mqtt_client *client, int timeout_ms)
// {
// g_connack_ok = false;
// g_suback_ok = false;
// int err = mqtt_connect(client);
// if (err) {
// LOG_INF("mqtt_connect failed (%d)", err);
// return err;
// }
// /* Wait for CONNACK */
// int waited = 0;
// while (!g_connack_ok && waited < timeout_ms) {
// err = mqtt_input(client);
// if (err && err != -EAGAIN) {
// int soerr = 0;
// socklen_t slen = sizeof(soerr);
// (void)zsock_getsockopt(client->transport.tcp.sock,
// SOL_SOCKET, SO_ERROR, &soerr, &slen);
// LOG_INF("mqtt_input while waiting CONNACK failed (%d), so_error=%d",
// err, soerr);
// return err;
// }
// (void)mqtt_live(client);
// k_sleep(K_MSEC(50));
// waited += 50;
// }
// if (!g_connack_ok) {
// LOG_INF("Timed out waiting for CONNACK");
// return -ETIMEDOUT;
// }
// /* Subscribe after we are connected */
// struct mqtt_topic topic = {
// .topic = { .utf8 = SUB_TOPIC, .size = sizeof(SUB_TOPIC) - 1 },
// .qos = SUB_QOS,
// };
// const struct mqtt_subscription_list sub = {
// .list = &topic,
// .list_count = 1U,
// .message_id = 1U,
// };
// err = mqtt_subscribe(client, &sub);
// if (err) {
// LOG_INF("mqtt_subscribe failed (%d)", err);
// return err;
// }
// /* Wait for SUBACK */
// waited = 0;
// while (!g_suback_ok && waited < timeout_ms) {
// err = mqtt_input(client);
// if (err && err != -EAGAIN) {
// LOG_INF("mqtt_input while waiting SUBACK failed (%d)", err);
// return err;
// }
// (void)mqtt_live(client);
// k_sleep(K_MSEC(50));
// waited += 50;
// }
// if (!g_suback_ok) {
// LOG_INF("Timed out waiting for SUBACK");
// return -ETIMEDOUT;
// }
// LOG_INF("Subscribed to %s (QoS %d)", SUB_TOPIC, SUB_QOS);
// /* Send a test publish once after we’re subscribed */
// send_test_pub(client);
// return 0;
// }
// /* Regular service loop */
// static void mqtt_service_loop(struct mqtt_client *client)
// {
// int64_t next_ping = k_uptime_get() + 1000;
// for (;;) {
// int err = mqtt_input(client);
// if (err && err != -EAGAIN) {
// LOG_INF("mqtt_input error %d; leaving service loop", err);
// break;
// }
// if (k_uptime_get() >= next_ping) {
// err = mqtt_live(client);
// if (err && err != -EAGAIN) {
// LOG_INF("mqtt_live error %d; leaving service loop", err);
// break;
// }
// next_ping += 1000;
// }
// k_sleep(K_MSEC(50));
// }
// }
// static void send_test_pub(struct mqtt_client *client)
// {
// static uint8_t payload[] = "hi from nrf5340";
// struct mqtt_publish_param pub = {
// .message.topic = {
// .topic = MQTT_UTF8_LITERAL("test/topic"),
// .qos = MQTT_QOS_1_AT_LEAST_ONCE,
// },
// .message.payload = {
// .data = payload,
// .len = sizeof(payload) - 1,
// },
// .message_id = 42,
// .dup_flag = 0,
// .retain_flag = 0,
// };
// int err = mqtt_publish(client, &pub);
// LOG_INF("publish: err=%d", err);
// }
// /* --- main --- */
// void main(void)
// {
// LOG_INF("Booting: Ethernet (W5500) + DHCP + MQTT v5.0");
// struct net_if *iface = net_if_get_default();
// if (!iface) {
// LOG_INF("No default net_if found!");
// return;
// }
// if (acquire_dhcp_address(iface, 20000) == 0) {
// print_ipv4(iface);
// } else {
// LOG_INF("DHCP timeout; check cable/router or try static IP.");
// return;
// }
// struct mqtt_client client;
// struct sockaddr_in broker;
// mqtt_setup(&client, &broker);
// if (mqtt_connect_and_sub(&client, 8000) == 0) {
// mqtt_service_loop(&client);
// (void)mqtt_disconnect(&client, NULL);
// }
// }