summaryrefslogtreecommitdiff
path: root/samples
diff options
context:
space:
mode:
authorFlavio Santes <flavio.santes@intel.com>2016-12-19 12:15:00 -0600
committerJukka Rissanen <jukka.rissanen@linux.intel.com>2017-02-03 15:59:18 +0200
commit59b1384885f775ffd6a5aa5368cfc1ba7f9cbf70 (patch)
tree77619b65d75920e3047def31091f566cb8841473 /samples
parent02bd8411dc07570cdb4971ae7ae42918094d649d (diff)
net/mqtt: Add the MQTT Publisher sample application
This commit adds the MQTT Publisher sample application for Zephyr. The following MQTT API routines are exercised in this sample: - mqtt_init - mqtt_tx_connect - mqtt_tx_pingreq - mqtt_tx_publish - mqtt_tx_disconnect The following MQTT API data structures are used in this application: - struct mqtt_ctx - struct mqtt_connect_msg - struct mqtt_publish_msg This sample application exemplifies how to send MQTT PUBLISH messages with different QoS values. A README file is also included in this patch. Change-Id: I2b41b276d5178a2cd1b07b031c38bff481885fff Signed-off-by: Flavio Santes <flavio.santes@intel.com>
Diffstat (limited to 'samples')
-rw-r--r--samples/net/mqtt_publisher/Makefile14
-rw-r--r--samples/net/mqtt_publisher/README.rst236
-rw-r--r--samples/net/mqtt_publisher/prj_frdm_k64f.conf36
-rw-r--r--samples/net/mqtt_publisher/src/Makefile8
-rw-r--r--samples/net/mqtt_publisher/src/config.h37
-rw-r--r--samples/net/mqtt_publisher/src/main.c410
-rw-r--r--samples/net/mqtt_publisher/testcase.ini4
7 files changed, 745 insertions, 0 deletions
diff --git a/samples/net/mqtt_publisher/Makefile b/samples/net/mqtt_publisher/Makefile
new file mode 100644
index 000000000..e2b27bdfb
--- /dev/null
+++ b/samples/net/mqtt_publisher/Makefile
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2017 Intel Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+BOARD ?= frdm_k64f
+CONF_FILE ?= prj_$(BOARD).conf
+
+include $(ZEPHYR_BASE)/Makefile.inc
+
+ifeq ($(BOARD), qemu_x86)
+ include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack
+endif
diff --git a/samples/net/mqtt_publisher/README.rst b/samples/net/mqtt_publisher/README.rst
new file mode 100644
index 000000000..be597f125
--- /dev/null
+++ b/samples/net/mqtt_publisher/README.rst
@@ -0,0 +1,236 @@
+MQTT Publisher
+##############
+
+Overview
+********
+
+`MQTT <http://mqtt.org/>`_ (MQ Telemetry Transport) is a lightweight
+publish/subscribe messaging protocol optimized for small sensors and
+mobile devices.
+
+The Zephyr MQTT Publisher sample application is a MQTT v3.1.1
+client that sends MQTT PUBLISH messages to a MQTT broker.
+See the `MQTT V3.1.1 spec`_ for more information.
+
+.. _MQTT V3.1.1 spec: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
+
+The source code of this sample application can be found at:
+:file:`samples/net/mqtt_publisher`.
+
+Requirements
+************
+
+- Linux machine
+- Freedom Board (FRDM-K64F)
+- Mosquitto server: any version that supports MQTT v3.1.1. This sample
+ was tested with mosquitto 1.3.4.
+- Mosquitto subscriber
+- LAN for testing purposes (Ethernet)
+
+Build and Running
+*****************
+
+Currently, this sample application only supports static IP addresses.
+Open the :file:`src/config.h` file and set the IP addresses according
+to the LAN environment.
+Alternatively, set the IP addresses in the :file:`prj_frdm_k64f.conf` file.
+
+This file :file:`src/config.h` also contains some variables that may be changed:
+
+MQTT broker TCP port:
+
+.. code-block:: c
+
+ #define SERVER_PORT 1883
+
+Application sleep time:
+
+.. code-block:: c
+
+ #define APP_SLEEP_MSECS 500
+
+Application RX and TX timeout:
+
+.. code-block:: c
+
+ #define APP_TX_RX_TIMEOUT 300
+
+Max number of connection tries:
+
+.. code-block:: c
+
+ #define APP_CONNECT_TRIES 10
+
+Max number of MQTT PUBLISH iterations
+
+.. code-block:: c
+
+ #define APP_MAX_ITERATIONS 5
+
+On your Linux host computer, open a terminal window, locate the source code
+of this sample application (i.e. :file:`samples/net/mqtt_publisher`) and type:
+
+.. code-block:: console
+
+ make BOARD=frdm_k64f
+
+Open another terminal window and type:
+
+.. code-block:: console
+
+ sudo mosquitto -v -p 1883
+
+Open another terminal window and type:
+
+.. code-block:: console
+
+ mosquito_sub -t sensors
+
+Sample output
+=============
+
+This is the output from the FRDM UART console, with:
+
+.. code-block:: c
+
+ #define APP_MAX_ITERATIONS 5
+
+.. code-block:: console
+
+ [dev/eth_mcux] [INF] eth_0_init: Enabled 100M full-duplex mode.
+ [dev/eth_mcux] [DBG] eth_0_init: MAC 00:04:9f:3e:1a:0a
+ [publisher:233] network_setup: 0 <OK>
+ [publisher:258] mqtt_init: 0 <OK>
+ [connect_cb:81] user_data: CONNECTED
+ [try_to_connect:212] mqtt_tx_connect: 0 <OK>
+ [publisher:276] try_to_connect: 0 <OK>
+ [publisher:285] mqtt_tx_pingreq: 0 <OK>
+ [publisher:290] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBACK> packet id: 1888, user_data: PUBLISH
+ [publisher:295] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBREC> packet id: 16356, user_data: PUBLISH
+ [publish_cb:149] <MQTT_PUBCOMP> packet id: 16356, user_data: PUBLISH
+ [publisher:300] mqtt_tx_publish: 0 <OK>
+ [publisher:285] mqtt_tx_pingreq: 0 <OK>
+ [publisher:290] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBACK> packet id: 45861, user_data: PUBLISH
+ [publisher:295] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBREC> packet id: 53870, user_data: PUBLISH
+ [publish_cb:149] <MQTT_PUBCOMP> packet id: 53870, user_data: PUBLISH
+ [publisher:300] mqtt_tx_publish: 0 <OK>
+ [publisher:285] mqtt_tx_pingreq: 0 <OK>
+ [publisher:290] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBACK> packet id: 60144, user_data: PUBLISH
+ [publisher:295] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBREC> packet id: 6561, user_data: PUBLISH
+ [publish_cb:149] <MQTT_PUBCOMP> packet id: 6561, user_data: PUBLISH
+ [publisher:300] mqtt_tx_publish: 0 <OK>
+ [publisher:285] mqtt_tx_pingreq: 0 <OK>
+ [publisher:290] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBACK> packet id: 38355, user_data: PUBLISH
+ [publisher:295] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBREC> packet id: 60656, user_data: PUBLISH
+ [publish_cb:149] <MQTT_PUBCOMP> packet id: 60656, user_data: PUBLISH
+ [publisher:300] mqtt_tx_publish: 0 <OK>
+ [publisher:285] mqtt_tx_pingreq: 0 <OK>
+ [publisher:290] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBACK> packet id: 28420, user_data: PUBLISH
+ [publisher:295] mqtt_tx_publish: 0 <OK>
+ [publish_cb:149] <MQTT_PUBREC> packet id: 49829, user_data: PUBLISH
+ [publish_cb:149] <MQTT_PUBCOMP> packet id: 49829, user_data: PUBLISH
+ [publisher:300] mqtt_tx_publish: 0 <OK>
+ [disconnect_cb:101] user_data: DISCONNECTED
+ [publisher:304] mqtt_tx_disconnect: 0 <OK>
+
+ Bye!
+
+The line:
+
+.. code-block:: console
+
+ [try_to_connect:220] mqtt_connect: -5 <ERROR>
+
+means that an error was detected and a new connect message will be sent.
+
+The MQTT API is asynchronous, so messages are displayed as the callbacks are
+executed.
+
+This is the information that the subscriber will receive:
+
+.. code-block:: console
+
+ mosquitto_sub -t sensors
+ DOORS:OPEN_QoS0
+ DOORS:OPEN_QoS1
+ DOORS:OPEN_QoS2
+ DOORS:OPEN_QoS0
+ DOORS:OPEN_QoS1
+ DOORS:OPEN_QoS2
+ DOORS:OPEN_QoS0
+ DOORS:OPEN_QoS1
+ DOORS:OPEN_QoS2
+ DOORS:OPEN_QoS0
+ DOORS:OPEN_QoS1
+ DOORS:OPEN_QoS2
+ DOORS:OPEN_QoS0
+ DOORS:OPEN_QoS1
+ DOORS:OPEN_QoS2
+
+This is the output from the MQTT broker:
+
+.. code-block:: console
+
+ sudo mosquitto -v
+ 1485663791: mosquitto version 1.3.4 (build date 2014-08-17 00:14:52-0300) starting
+ 1485663791: Using default config.
+ 1485663791: Opening ipv4 listen socket on port 1883.
+ 1485663791: Opening ipv6 listen socket on port 1883.
+ 1485663797: New connection from 192.168.1.101 on port 1883.
+ 1485663797: New client connected from 192.168.1.101 as zephyr_publisher (c1, k0).
+ 1485663797: Sending CONNACK to zephyr_publisher (0)
+ 1485663798: Received PINGREQ from zephyr_publisher
+ 1485663798: Sending PINGRESP to zephyr_publisher
+ 1485663798: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes))
+ 1485663799: Received PUBLISH from zephyr_publisher (d0, q1, r0, m1888, 'sensors', ... (15 bytes))
+ 1485663799: Sending PUBACK to zephyr_publisher (Mid: 1888)
+ 1485663799: Received PUBLISH from zephyr_publisher (d0, q2, r0, m16356, 'sensors', ... (15 bytes))
+ 1485663799: Sending PUBREC to zephyr_publisher (Mid: 16356)
+ 1485663799: Received PUBREL from zephyr_publisher (Mid: 16356)
+ 1485663799: Sending PUBCOMP to zephyr_publisher (Mid: 16356)
+ 1485663800: Received PINGREQ from zephyr_publisher
+ 1485663800: Sending PINGRESP to zephyr_publisher
+ 1485663800: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes))
+ 1485663801: Received PUBLISH from zephyr_publisher (d0, q1, r0, m45861, 'sensors', ... (15 bytes))
+ 1485663801: Sending PUBACK to zephyr_publisher (Mid: 45861)
+ 1485663801: Received PUBLISH from zephyr_publisher (d0, q2, r0, m53870, 'sensors', ... (15 bytes))
+ 1485663801: Sending PUBREC to zephyr_publisher (Mid: 53870)
+ 1485663801: Received PUBREL from zephyr_publisher (Mid: 53870)
+ 1485663801: Sending PUBCOMP to zephyr_publisher (Mid: 53870)
+ 1485663802: Received PINGREQ from zephyr_publisher
+ 1485663802: Sending PINGRESP to zephyr_publisher
+ 1485663802: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes))
+ 1485663803: Received PUBLISH from zephyr_publisher (d0, q1, r0, m60144, 'sensors', ... (15 bytes))
+ 1485663803: Sending PUBACK to zephyr_publisher (Mid: 60144)
+ 1485663803: Received PUBLISH from zephyr_publisher (d0, q2, r0, m6561, 'sensors', ... (15 bytes))
+ 1485663803: Sending PUBREC to zephyr_publisher (Mid: 6561)
+ 1485663803: Received PUBREL from zephyr_publisher (Mid: 6561)
+ 1485663803: Sending PUBCOMP to zephyr_publisher (Mid: 6561)
+ 1485663804: Received PINGREQ from zephyr_publisher
+ 1485663804: Sending PINGRESP to zephyr_publisher
+ 1485663804: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes))
+ 1485663805: Received PUBLISH from zephyr_publisher (d0, q1, r0, m38355, 'sensors', ... (15 bytes))
+ 1485663805: Sending PUBACK to zephyr_publisher (Mid: 38355)
+ 1485663805: Received PUBLISH from zephyr_publisher (d0, q2, r0, m60656, 'sensors', ... (15 bytes))
+ 1485663805: Sending PUBREC to zephyr_publisher (Mid: 60656)
+ 1485663805: Received PUBREL from zephyr_publisher (Mid: 60656)
+ 1485663805: Sending PUBCOMP to zephyr_publisher (Mid: 60656)
+ 1485663806: Received PINGREQ from zephyr_publisher
+ 1485663806: Sending PINGRESP to zephyr_publisher
+ 1485663806: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes))
+ 1485663807: Received PUBLISH from zephyr_publisher (d0, q1, r0, m28420, 'sensors', ... (15 bytes))
+ 1485663807: Sending PUBACK to zephyr_publisher (Mid: 28420)
+ 1485663807: Received PUBLISH from zephyr_publisher (d0, q2, r0, m49829, 'sensors', ... (15 bytes))
+ 1485663807: Sending PUBREC to zephyr_publisher (Mid: 49829)
+ 1485663807: Received PUBREL from zephyr_publisher (Mid: 49829)
+ 1485663807: Sending PUBCOMP to zephyr_publisher (Mid: 49829)
+ 1485663808: Received DISCONNECT from zephyr_publisher
diff --git a/samples/net/mqtt_publisher/prj_frdm_k64f.conf b/samples/net/mqtt_publisher/prj_frdm_k64f.conf
new file mode 100644
index 000000000..2df75a2ba
--- /dev/null
+++ b/samples/net/mqtt_publisher/prj_frdm_k64f.conf
@@ -0,0 +1,36 @@
+CONFIG_NETWORKING=y
+CONFIG_NET_TCP=y
+CONFIG_RANDOM_GENERATOR=y
+CONFIG_NET_ARP=y
+CONFIG_NET_L2_ETHERNET=y
+CONFIG_NET_LOG=y
+CONFIG_INIT_STACKS=y
+
+CONFIG_NET_NBUF_RX_COUNT=16
+CONFIG_NET_NBUF_TX_COUNT=16
+CONFIG_NET_NBUF_DATA_COUNT=16
+
+CONFIG_NET_IPV6_RA_RDNSS=y
+CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
+
+CONFIG_PRINTK=y
+#CONFIG_NET_DEBUG_NET_BUF=y
+
+CONFIG_NET_IPV4=n
+# Enable IPv6 support
+CONFIG_NET_IPV6=y
+
+# Enable the MQTT Lib
+CONFIG_MQTT_LIB=y
+
+CONFIG_NET_SAMPLES_IP_ADDRESSES=y
+CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
+CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
+
+CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.168.1.101"
+CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.168.1.10"
+
+CONFIG_MAIN_STACK_SIZE=2048
+
+# For IPv6
+CONFIG_NET_NBUF_DATA_SIZE=256
diff --git a/samples/net/mqtt_publisher/src/Makefile b/samples/net/mqtt_publisher/src/Makefile
new file mode 100644
index 000000000..9715a81e7
--- /dev/null
+++ b/samples/net/mqtt_publisher/src/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2017 Intel Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+obj-y += main.o
+
diff --git a/samples/net/mqtt_publisher/src/config.h b/samples/net/mqtt_publisher/src/config.h
new file mode 100644
index 000000000..e9e4d3ec0
--- /dev/null
+++ b/samples/net/mqtt_publisher/src/config.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#ifdef CONFIG_NET_SAMPLES_IP_ADDRESSES
+#ifdef CONFIG_NET_IPV6
+#define ZEPHYR_ADDR CONFIG_NET_SAMPLES_MY_IPV6_ADDR
+#define SERVER_ADDR CONFIG_NET_SAMPLES_PEER_IPV6_ADDR
+#else
+#define ZEPHYR_ADDR CONFIG_NET_SAMPLES_MY_IPV4_ADDR
+#define SERVER_ADDR CONFIG_NET_SAMPLES_PEER_IPV4_ADDR
+#endif
+#else
+#ifdef CONFIG_NET_IPV6
+#define ZEPHYR_ADDR "2001:db8::1"
+#define SERVER_ADDR "2001:db8::2"
+#else
+#define ZEPHYR_ADDR "192.168.1.101"
+#define SERVER_ADDR "192.168.1.10"
+#endif
+#endif
+
+#define SERVER_PORT 1883
+
+#define APP_SLEEP_MSECS 500
+#define APP_TX_RX_TIMEOUT 300
+
+#define APP_CONNECT_TRIES 10
+
+#define APP_MAX_ITERATIONS 100
+
+#endif
diff --git a/samples/net/mqtt_publisher/src/main.c b/samples/net/mqtt_publisher/src/main.c
new file mode 100644
index 000000000..909a1d211
--- /dev/null
+++ b/samples/net/mqtt_publisher/src/main.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <net/mqtt.h>
+
+#include <net/net_context.h>
+#include <net/nbuf.h>
+
+#include <misc/printk.h>
+#include <string.h>
+#include <errno.h>
+
+#include "config.h"
+
+/**
+ * @brief mqtt_client_ctx Container of some structures used by the
+ * publisher app.
+ */
+struct mqtt_client_ctx {
+ /**
+ * The connect message structure is only used during the connect
+ * stage. Developers must set some msg properties before calling the
+ * mqtt_tx_connect routine. See below.
+ */
+ struct mqtt_connect_msg connect_msg;
+ /**
+ * This is the message that will be received by the server
+ * (MQTT broker).
+ */
+ struct mqtt_publish_msg pub_msg;
+
+ /**
+ * This is the MQTT application context variable.
+ */
+ struct mqtt_ctx mqtt_ctx;
+
+ /**
+ * This variable will be passed to the connect callback, declared inside
+ * the mqtt context struct. If not used, it could be set to NULL.
+ */
+ void *connect_data;
+
+ /**
+ * This variable will be passed to the disconnect callback, declared
+ * inside the mqtt context struct. If not used, it could be set to NULL.
+ */
+ void *disconnect_data;
+
+ /**
+ * This variable will be passed to the publish_tx callback, declared
+ * inside the mqtt context struct. If not used, it could be set to NULL.
+ */
+ void *publish_data;
+};
+
+/* This is the network context structure. */
+static struct net_context *net_ctx;
+
+/* The mqtt client struct */
+static struct mqtt_client_ctx client_ctx;
+
+/* This routine sets some basic properties for the network context variable */
+static
+int network_setup(struct net_context **net_ctx, const char *local_addr,
+ const char *server_addr, uint16_t server_port);
+
+/* The signature of this routine must match the connect callback declared at
+ * the mqtt.h header.
+ */
+static
+void connect_cb(struct mqtt_ctx *mqtt_ctx)
+{
+ struct mqtt_client_ctx *client_ctx;
+
+ client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
+
+ printk("[%s:%d]", __func__, __LINE__);
+
+ if (client_ctx->connect_data) {
+ printk(" user_data: %s",
+ (const char *)client_ctx->connect_data);
+ }
+
+ printk("\n");
+}
+
+/* The signature of this routine must match the disconnect callback declared at
+ * the mqtt.h header.
+ */
+static
+void disconnect_cb(struct mqtt_ctx *mqtt_ctx)
+{
+ struct mqtt_client_ctx *client_ctx;
+
+ client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
+
+ printk("[%s:%d]", __func__, __LINE__);
+
+ if (client_ctx->disconnect_data) {
+ printk(" user_data: %s",
+ (const char *)client_ctx->disconnect_data);
+ }
+
+ printk("\n");
+}
+
+/**
+ * The signature of this routine must match the publish_tx callback declared at
+ * the mqtt.h header.
+ *
+ * NOTE: we have two callbacks for MQTT Publish related stuff:
+ * - publish_tx, for publishers
+ * - publish_rx, for subscribers
+ *
+ * Applications must keep a "message database" with pkt_id's. So far, this is
+ * not implemented here. For example, if we receive a PUBREC message with an
+ * unknown pkt_id, this routine must return an error, for example -EINVAL or
+ * any negative value.
+ */
+static
+int publish_cb(struct mqtt_ctx *mqtt_ctx, uint16_t pkt_id,
+ enum mqtt_packet type)
+{
+ struct mqtt_client_ctx *client_ctx;
+ const char *str;
+ int rc = 0;
+
+ client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
+
+ switch (type) {
+ case MQTT_PUBACK:
+ str = "MQTT_PUBACK";
+ break;
+ case MQTT_PUBCOMP:
+ str = "MQTT_PUBCOMP";
+ break;
+ case MQTT_PUBREC:
+ str = "MQTT_PUBREC";
+ break;
+ default:
+ rc = -EINVAL;
+ str = "Invalid MQTT packet";
+ }
+
+ printk("[%s:%d] <%s> packet id: %u", __func__, __LINE__, str, pkt_id);
+
+ if (client_ctx->publish_data) {
+ printk(", user_data: %s",
+ (const char *)client_ctx->publish_data);
+ }
+
+ printk("\n");
+
+ return rc;
+}
+
+/**
+ * The signature of this routine must match the malformed callback declared at
+ * the mqtt.h header.
+ */
+static
+void malformed_cb(struct mqtt_ctx *mqtt_ctx, uint16_t pkt_type)
+{
+ printk("[%s:%d] pkt_type: %u\n", __func__, __LINE__, pkt_type);
+}
+
+static const char topic[] = "sensors";
+
+char payload[] = "DOORS:OPEN_QoSx";
+
+static
+void prepare_mqtt_publish_msg(struct mqtt_publish_msg *pub_msg,
+ enum mqtt_qos qos)
+{
+ payload[strlen(payload) - 1] = '0' + qos;
+
+ /* MQTT message payload may be anything, we we use C strings */
+ pub_msg->msg = payload;
+ /* Payload's length */
+ pub_msg->msg_len = strlen(client_ctx.pub_msg.msg);
+ /* MQTT Quality of Service */
+ pub_msg->qos = qos;
+ /* Message's topic */
+ pub_msg->topic = (char *)topic;
+ pub_msg->topic_len = strlen(client_ctx.pub_msg.topic);
+ /* Packet Identifier, always use different values */
+ pub_msg->pkt_id = sys_rand32_get();
+
+}
+
+#define RC_STR(rc) ((rc) == 0 ? "OK" : "ERROR")
+
+#define PRINT_RESULT(func, rc) \
+ printk("[%s:%d] %s: %d <%s>\n", __func__, __LINE__, \
+ (func), rc, RC_STR(rc))
+
+/* In this routine we block until the connected variable is 1 */
+static
+int try_to_connect(struct mqtt_client_ctx *client_ctx)
+{
+ int i = 0;
+
+ while (i++ < APP_CONNECT_TRIES && !client_ctx->mqtt_ctx.connected) {
+ int rc;
+
+ rc = mqtt_tx_connect(&client_ctx->mqtt_ctx,
+ &client_ctx->connect_msg);
+ k_sleep(APP_SLEEP_MSECS);
+ PRINT_RESULT("mqtt_tx_connect", rc);
+ if (rc != 0) {
+ continue;
+ }
+ }
+
+ if (client_ctx->mqtt_ctx.connected) {
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static
+void publisher(void)
+{
+ int i, rc;
+
+ /* The net_ctx variable must be ready BEFORE passing it to the MQTT API.
+ */
+ rc = network_setup(&net_ctx, ZEPHYR_ADDR, SERVER_ADDR, SERVER_PORT);
+ PRINT_RESULT("network_setup", rc);
+ if (rc != 0) {
+ goto exit_app;
+ }
+
+ /* Set everything to 0 and later just assign the required fields. */
+ memset(&client_ctx, 0x00, sizeof(client_ctx));
+
+ /* The network context is the only field that must be set BEFORE
+ * calling the mqtt_init routine.
+ */
+ client_ctx.mqtt_ctx.net_ctx = net_ctx;
+
+ /* connect, disconnect and malformed may be set to NULL */
+ client_ctx.mqtt_ctx.connect = connect_cb;
+
+ client_ctx.mqtt_ctx.disconnect = disconnect_cb;
+ client_ctx.mqtt_ctx.malformed = malformed_cb;
+
+ client_ctx.mqtt_ctx.net_timeout = APP_TX_RX_TIMEOUT;
+
+ /* Publisher apps TX the MQTT PUBLISH msg */
+ client_ctx.mqtt_ctx.publish_tx = publish_cb;
+
+ rc = mqtt_init(&client_ctx.mqtt_ctx, MQTT_APP_PUBLISHER);
+ PRINT_RESULT("mqtt_init", rc);
+ if (rc != 0) {
+ goto exit_app;
+ }
+
+ /* The connect message will be sent to the MQTT server (broker).
+ * If clean_session here is 0, the mqtt_ctx clean_session variable
+ * will be set to 0 also. Please don't do that, set always to 1.
+ * Clean session = 0 is not yet supported.
+ */
+ client_ctx.connect_msg.client_id = "zephyr_publisher";
+ client_ctx.connect_msg.clean_session = 1;
+
+ client_ctx.connect_data = "CONNECTED";
+ client_ctx.disconnect_data = "DISCONNECTED";
+ client_ctx.publish_data = "PUBLISH";
+
+ rc = try_to_connect(&client_ctx);
+ PRINT_RESULT("try_to_connect", rc);
+ if (rc != 0) {
+ goto exit_app;
+ }
+
+ i = 0;
+ while (i++ < APP_MAX_ITERATIONS) {
+ rc = mqtt_tx_pingreq(&client_ctx.mqtt_ctx);
+ k_sleep(APP_SLEEP_MSECS);
+ PRINT_RESULT("mqtt_tx_pingreq", rc);
+
+ prepare_mqtt_publish_msg(&client_ctx.pub_msg, MQTT_QoS0);
+ rc = mqtt_tx_publish(&client_ctx.mqtt_ctx, &client_ctx.pub_msg);
+ k_sleep(APP_SLEEP_MSECS);
+ PRINT_RESULT("mqtt_tx_publish", rc);
+
+ prepare_mqtt_publish_msg(&client_ctx.pub_msg, MQTT_QoS1);
+ rc = mqtt_tx_publish(&client_ctx.mqtt_ctx, &client_ctx.pub_msg);
+ k_sleep(APP_SLEEP_MSECS);
+ PRINT_RESULT("mqtt_tx_publish", rc);
+
+ prepare_mqtt_publish_msg(&client_ctx.pub_msg, MQTT_QoS2);
+ rc = mqtt_tx_publish(&client_ctx.mqtt_ctx, &client_ctx.pub_msg);
+ k_sleep(APP_SLEEP_MSECS);
+ PRINT_RESULT("mqtt_tx_publish", rc);
+ }
+
+ rc = mqtt_tx_disconnect(&client_ctx.mqtt_ctx);
+ PRINT_RESULT("mqtt_tx_disconnect", rc);
+
+exit_app:
+ net_context_put(net_ctx);
+ printk("\nBye!\n");
+}
+
+static
+int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t port)
+{
+ void *ptr;
+ int rc;
+
+#ifdef CONFIG_NET_IPV6
+ net_sin6(sock_addr)->sin6_port = htons(port);
+ sock_addr->family = AF_INET6;
+ ptr = &(net_sin6(sock_addr)->sin6_addr);
+ rc = net_addr_pton(AF_INET6, addr, ptr);
+#else
+ net_sin(sock_addr)->sin_port = htons(port);
+ sock_addr->family = AF_INET;
+ ptr = &(net_sin(sock_addr)->sin_addr);
+ rc = net_addr_pton(AF_INET, addr, ptr);
+#endif
+
+ if (rc) {
+ printk("Invalid IP address: %s\n", addr);
+ }
+
+ return rc;
+}
+
+int network_setup(struct net_context **net_ctx, const char *local_addr,
+ const char *server_addr, uint16_t server_port)
+{
+#ifdef CONFIG_NET_IPV6
+ socklen_t addr_len = sizeof(struct sockaddr_in6);
+ sa_family_t family = AF_INET6;
+
+#else
+ socklen_t addr_len = sizeof(struct sockaddr_in);
+ sa_family_t family = AF_INET;
+#endif
+ struct sockaddr local_sock;
+ struct sockaddr server_sock;
+ void *p;
+ int rc;
+
+ rc = set_addr(&local_sock, local_addr, 0);
+ if (rc) {
+ printk("set_addr (local) error\n");
+ return rc;
+ }
+
+#ifdef CONFIG_NET_IPV6
+ p = net_if_ipv6_addr_add(net_if_get_default(),
+ &net_sin6(&local_sock)->sin6_addr,
+ NET_ADDR_MANUAL, 0);
+#else
+ p = net_if_ipv4_addr_add(net_if_get_default(),
+ &net_sin(&local_sock)->sin_addr,
+ NET_ADDR_MANUAL, 0);
+#endif
+
+ if (!p) {
+ return -EINVAL;
+ }
+
+ rc = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, net_ctx);
+ if (rc) {
+ printk("net_context_get error\n");
+ return rc;
+ }
+
+ rc = net_context_bind(*net_ctx, &local_sock, addr_len);
+ if (rc) {
+ printk("net_context_bind error\n");
+ goto lb_exit;
+ }
+
+ rc = set_addr(&server_sock, server_addr, server_port);
+ if (rc) {
+ printk("set_addr (server) error\n");
+ goto lb_exit;
+ }
+
+ rc = net_context_connect(*net_ctx, &server_sock, addr_len, NULL,
+ APP_SLEEP_MSECS, NULL);
+ if (rc) {
+ printk("net_context_connect error\n"
+ "Is the server (broker) up and running?\n");
+ goto lb_exit;
+ }
+
+ return 0;
+
+lb_exit:
+ net_context_put(*net_ctx);
+
+ return rc;
+}
+
+void main(void)
+{
+ publisher();
+}
diff --git a/samples/net/mqtt_publisher/testcase.ini b/samples/net/mqtt_publisher/testcase.ini
new file mode 100644
index 000000000..16ecfdae3
--- /dev/null
+++ b/samples/net/mqtt_publisher/testcase.ini
@@ -0,0 +1,4 @@
+[test]
+tags = net mqtt
+build_only = true
+platform_whitelist = frdm_k64f