samples: net: mqtt: Add a sample to connect to Azure
This samples demonstrates how to connect to Azure Cloud IoT hub which is based on MQTT protocol. User has to create an account in Azure Cloud and provide those details using Kconfig options. This sample first acquires DHCPv4 address and opens a secure connection with Azure cloud. Then opens a MQTT connection and publish messages randomly. Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
This commit is contained in:
parent
50631d66b9
commit
f1a1e5382e
10 changed files with 800 additions and 0 deletions
9
samples/net/mqtt_azure/CMakeLists.txt
Normal file
9
samples/net/mqtt_azure/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13.1)
|
||||||
|
|
||||||
|
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||||
|
project(mqtt-azure)
|
||||||
|
|
||||||
|
FILE(GLOB app_sources src/*.c)
|
||||||
|
target_sources(app PRIVATE ${app_sources})
|
56
samples/net/mqtt_azure/Kconfig
Normal file
56
samples/net/mqtt_azure/Kconfig
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# Kconfig - Private config options for mqtt-azure sample app
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2019 Intel Corporation
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
mainmenu "Networking mqtt-azure sample application"
|
||||||
|
|
||||||
|
config SAMPLE_CLOUD_AZURE_USERNAME
|
||||||
|
string "Azure cloud username"
|
||||||
|
help
|
||||||
|
Username of your Azure account.
|
||||||
|
|
||||||
|
config SAMPLE_CLOUD_AZURE_PASSWORD
|
||||||
|
string "Azure cloud password"
|
||||||
|
help
|
||||||
|
Password of your Azure account.
|
||||||
|
|
||||||
|
config SAMPLE_CLOUD_AZURE_CLIENT_ID
|
||||||
|
string "Azure cloud IoT hub MQTT client ID"
|
||||||
|
help
|
||||||
|
Device ID which you have setup in IoT hub account.
|
||||||
|
|
||||||
|
config SAMPLE_CLOUD_AZURE_HOSTNAME
|
||||||
|
string "Azure cloud IoT hub hostname"
|
||||||
|
help
|
||||||
|
Hostname of your Azure cloud IoT hub.
|
||||||
|
|
||||||
|
config SAMPLE_CLOUD_AZURE_SERVER_ADDR
|
||||||
|
string "Azure cloud server address"
|
||||||
|
help
|
||||||
|
Azure cloud server address.
|
||||||
|
|
||||||
|
config SAMPLE_CLOUD_AZURE_SERVER_PORT
|
||||||
|
int "Azure cloud server port number"
|
||||||
|
default 8883
|
||||||
|
help
|
||||||
|
Azure cloud server port number.
|
||||||
|
|
||||||
|
config SAMPLE_SOCKS_ADDR
|
||||||
|
string "Proxy address"
|
||||||
|
depends on SOCKS
|
||||||
|
help
|
||||||
|
Provide proxy address if you are running this application
|
||||||
|
behind proxy.
|
||||||
|
|
||||||
|
config SAMPLE_SOCKS_PORT
|
||||||
|
int "Proxy port"
|
||||||
|
depends on SOCKS
|
||||||
|
help
|
||||||
|
Provide proxy port if you are running this application
|
||||||
|
behind proxy.
|
||||||
|
|
||||||
|
source "Kconfig.zephyr"
|
115
samples/net/mqtt_azure/README.rst
Normal file
115
samples/net/mqtt_azure/README.rst
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
.. _mqtt-azure-sample:
|
||||||
|
|
||||||
|
MQTT Azure Sample
|
||||||
|
#################
|
||||||
|
|
||||||
|
Overview
|
||||||
|
********
|
||||||
|
|
||||||
|
This sample application demonstrates how an MQTT client
|
||||||
|
can publish messages to an Azure Cloud IoT hub based on MQTT protocol.
|
||||||
|
|
||||||
|
- Acquire a DHCPv4 lease
|
||||||
|
- Establish a TLS connection with Azure Cloud IoT hub
|
||||||
|
- Publish data to the Azure cloud
|
||||||
|
- SOCKS5 supported
|
||||||
|
- DNS supported
|
||||||
|
|
||||||
|
The source code of this sample application can be found at:
|
||||||
|
:zephyr_file:`samples/net/mqtt_azure`.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
************
|
||||||
|
|
||||||
|
- Azure Cloud account
|
||||||
|
- Azure IOT Cloud credentials and required information
|
||||||
|
- Freedom Board (FRDM-K64F)
|
||||||
|
- Network connectivity
|
||||||
|
|
||||||
|
Building and Running
|
||||||
|
********************
|
||||||
|
|
||||||
|
This application has been built and tested on the NXP FRDMK64F.
|
||||||
|
Certs are required to authenticate to the Azure Cloud IoT hub.
|
||||||
|
Current certs in :zephyr_file:`samples/net/mqtt_azure/src/digicert.cer` are
|
||||||
|
copied from `<https://github.com/Azure/azure-iot-sdk-c/blob/master/certs/certs.c>`_
|
||||||
|
|
||||||
|
Configure the following Kconfig options based on your Azure Cloud IoT Hub
|
||||||
|
in your own overlay config file:
|
||||||
|
|
||||||
|
- SAMPLE_CLOUD_AZURE_USERNAME - Username field use::
|
||||||
|
|
||||||
|
{iothubhostname}/{device_id}/?api-version=2018-06-30,
|
||||||
|
|
||||||
|
where ``{iothubhostname}`` is the full CName of the IoT hub.
|
||||||
|
|
||||||
|
- SAMPLE_CLOUD_AZURE_PASSWORD - Password field, use an SAS token.
|
||||||
|
- SAMPLE_CLOUD_AZURE_CLIENT_ID - ClientId field, use the deviceId.
|
||||||
|
- SAMPLE_CLOUD_AZURE_HOSTNAME - IoT hub hostname
|
||||||
|
- SAMPLE_CLOUD_AZURE_SERVER_ADDR - IP address of the Azure MQTT broker
|
||||||
|
- SAMPLE_CLOUD_AZURE_SERVER_PORT - Port number of the Azure MQTT broker
|
||||||
|
|
||||||
|
You'll also need to set these Kconfig options if you're running
|
||||||
|
the sample behind a proxy:
|
||||||
|
|
||||||
|
- SAMPLE_SOCKS_ADDR - IP address of SOCKS5 Proxy server
|
||||||
|
- SAMPLE_SOCKS_PORT - Port number of SOCKS5 Proxy server
|
||||||
|
|
||||||
|
On your Linux host computer, open a terminal window, locate the source code
|
||||||
|
of this sample application (i.e., :zephyr_file:`samples/net/mqtt_azure`) and type:
|
||||||
|
|
||||||
|
.. zephyr-app-commands::
|
||||||
|
:zephyr-app: samples/net/mqtt_azure
|
||||||
|
:board: frdm_k64f
|
||||||
|
:conf: "prj.conf <overlay.conf>"
|
||||||
|
:goals: build flash
|
||||||
|
:compact:
|
||||||
|
|
||||||
|
Also this application can be tested with QEMU. This is described in
|
||||||
|
:ref:`networking_with_qemu`. Set up Zephyr and NAT/masquerading on host
|
||||||
|
to access Internet and use :file:`overlay-qemu_x86.conf`.
|
||||||
|
DHCP support is not enabled with QEMU. It uses static IP addresses.
|
||||||
|
|
||||||
|
Sample overlay file
|
||||||
|
===================
|
||||||
|
|
||||||
|
This is the overlay template for Azure IoT hub and other details:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_USERNAME="<username>"
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_PASSWORD="<SAS token>"
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_CLIENT_ID="<device id>"
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_HOSTNAME="<IoT hub hostname>"
|
||||||
|
CONFIG_SAMPLE_SOCKS_ADDR="<proxy addr>"
|
||||||
|
CONFIG_SAMPLE_SOCKS_PORT=<proxy port>
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_SERVER_ADDR="<server ip addr, if DNS disabled set this>"
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_SERVER_PORT=<server port, if DNS disabled set this>
|
||||||
|
|
||||||
|
Sample output
|
||||||
|
=============
|
||||||
|
|
||||||
|
This is the output from the FRDM UART console, with:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
[00:00:03.001,000] <inf> eth_mcux: Enabled 100M full-duplex mode.
|
||||||
|
[00:00:03.010,000] <dbg> mqtt_azure.main: Waiting for network to setup...
|
||||||
|
[00:00:03.115,000] <inf> net_dhcpv4: Received: 10.0.0.2
|
||||||
|
[00:00:03.124,000] <inf> net_config: IPv4 address: 10.0.0.2
|
||||||
|
[00:00:03.132,000] <inf> net_config: Lease time: 43200 seconds
|
||||||
|
[00:00:03.140,000] <inf> net_config: Subnet: 255.255.255.0
|
||||||
|
[00:00:03.149,000] <inf> net_config: Router: 10.0.0.10
|
||||||
|
[00:00:06.157,000] <dbg> mqtt_azure.try_to_connect: attempting to connect...
|
||||||
|
[00:00:06.167,000] <dbg> net_sock_tls.tls_alloc: (0x200024f8): Allocated TLS context, 0x20001110
|
||||||
|
[00:00:19.412,000] <dbg> mqtt_azure.mqtt_event_handler: MQTT client connected!
|
||||||
|
[00:00:19.424,000] <dbg> mqtt_azure.publish_message: mqtt_publish OK
|
||||||
|
[00:00:19.830,000] <dbg> mqtt_azure.mqtt_event_handler: PUBACK packet id: 63387
|
||||||
|
[00:00:31.842,000] <dbg> mqtt_azure.publish_message: mqtt_publish OK
|
||||||
|
[00:00:51.852,000] <dbg> mqtt_azure.publish_message: mqtt_publish OK
|
||||||
|
[00:00:51.861,000] <dbg> mqtt_azure.mqtt_event_handler: PUBACK packet id: 38106
|
||||||
|
|
||||||
|
You can also check events or messages information on Azure Portal.
|
||||||
|
|
||||||
|
See `Azure Cloud MQTT Documentation
|
||||||
|
<https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-mqtt-support>`_.
|
10
samples/net/mqtt_azure/overlay-qemu_x86.conf
Normal file
10
samples/net/mqtt_azure/overlay-qemu_x86.conf
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
# Disable DHCPv4 and use static address
|
||||||
|
CONFIG_NET_DHCPV4=n
|
||||||
|
|
||||||
|
# Use local DNS server on host
|
||||||
|
CONFIG_DNS_SERVER1="192.0.2.2"
|
||||||
|
|
||||||
|
# Configure static addresses
|
||||||
|
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
|
||||||
|
CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"
|
71
samples/net/mqtt_azure/prj.conf
Normal file
71
samples/net/mqtt_azure/prj.conf
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
CONFIG_NETWORKING=y
|
||||||
|
|
||||||
|
# Disable IPv6 support
|
||||||
|
CONFIG_NET_IPV6=n
|
||||||
|
|
||||||
|
# Enable IPv4 support
|
||||||
|
CONFIG_NET_IPV4=y
|
||||||
|
CONFIG_NET_IF_MAX_IPV4_COUNT=2
|
||||||
|
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
|
||||||
|
|
||||||
|
# Enable TCP support
|
||||||
|
CONFIG_NET_TCP=y
|
||||||
|
|
||||||
|
# Enable Sockets support
|
||||||
|
CONFIG_NET_SOCKETS=y
|
||||||
|
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
|
||||||
|
|
||||||
|
# Enable DHCPv4 support
|
||||||
|
CONFIG_NET_DHCPV4=y
|
||||||
|
|
||||||
|
# Enable SOCKS5 proxy support
|
||||||
|
CONFIG_SOCKS=n
|
||||||
|
|
||||||
|
# Enable MQTT Lib support
|
||||||
|
CONFIG_MQTT_LIB=y
|
||||||
|
CONFIG_MQTT_LIB_TLS=y
|
||||||
|
|
||||||
|
# Enable Mbed TLS configuration
|
||||||
|
CONFIG_MBEDTLS=y
|
||||||
|
CONFIG_MBEDTLS_BUILTIN=y
|
||||||
|
CONFIG_MBEDTLS_ENABLE_HEAP=y
|
||||||
|
CONFIG_MBEDTLS_HEAP_SIZE=100000
|
||||||
|
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=10240
|
||||||
|
CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y
|
||||||
|
|
||||||
|
# Network configuration
|
||||||
|
CONFIG_NET_CONFIG_SETTINGS=y
|
||||||
|
|
||||||
|
# Network connection manager
|
||||||
|
CONFIG_NET_CONNECTION_MANAGER=y
|
||||||
|
|
||||||
|
CONFIG_NET_MGMT_EVENT_STACK_SIZE=1024
|
||||||
|
CONFIG_NET_MGMT_EVENT_QUEUE_SIZE=5
|
||||||
|
CONFIG_NET_MGMT_EVENT_LOG_LEVEL_DBG=n
|
||||||
|
|
||||||
|
CONFIG_DNS_RESOLVER=y
|
||||||
|
CONFIG_DNS_SERVER_IP_ADDRESSES=y
|
||||||
|
CONFIG_DNS_SERVER1="8.8.8.8"
|
||||||
|
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=2
|
||||||
|
CONFIG_NEWLIB_LIBC=y
|
||||||
|
|
||||||
|
CONFIG_INIT_STACKS=y
|
||||||
|
CONFIG_NET_SHELL=y
|
||||||
|
|
||||||
|
CONFIG_MAIN_STACK_SIZE=4096
|
||||||
|
|
||||||
|
# Enable Logging support
|
||||||
|
CONFIG_LOG_IMMEDIATE=y
|
||||||
|
CONFIG_NET_LOG=y
|
||||||
|
CONFIG_NET_TCP_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_MQTT_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_NET_DHCPV4_LOG_LEVEL_INF=n
|
||||||
|
CONFIG_NET_IF_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_MBEDTLS_DEBUG=n
|
||||||
|
#CONFIG_MBEDTLS_DEBUG_LEVEL=4
|
||||||
|
CONFIG_SOCKS_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_NET_CONFIG_LOG_LEVEL_DBG=y
|
||||||
|
CONFIG_NET_CONNECTION_MANAGER_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_DNS_RESOLVER_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_NET_CONTEXT_LOG_LEVEL_DBG=n
|
8
samples/net/mqtt_azure/sample.yaml
Normal file
8
samples/net/mqtt_azure/sample.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
sample:
|
||||||
|
description: MQTT sample app to Azure cloud
|
||||||
|
name: mqtt-azure
|
||||||
|
tests:
|
||||||
|
sample.net.mqtt_azure:
|
||||||
|
harness: net
|
||||||
|
platform_whitelist: sam_e70_xplained frdm_k64f qemu_x86
|
||||||
|
tags: net mqtt cloud
|
24
samples/net/mqtt_azure/src/config.h
Normal file
24
samples/net/mqtt_azure/src/config.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CONFIG_H__
|
||||||
|
#define __CONFIG_H__
|
||||||
|
|
||||||
|
#define SERVER_ADDR CONFIG_SAMPLE_CLOUD_AZURE_SERVER_ADDR
|
||||||
|
#define SERVER_PORT CONFIG_SAMPLE_CLOUD_AZURE_SERVER_PORT
|
||||||
|
|
||||||
|
#if defined(CONFIG_SOCKS)
|
||||||
|
#define SOCKS5_PROXY_ADDR CONFIG_SAMPLE_SOCKS_ADDR
|
||||||
|
#define SOCKS5_PROXY_PORT CONFIG_SAMPLE_SOCKS_PORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MQTT_CLIENTID CONFIG_SAMPLE_CLOUD_AZURE_CLIENT_ID
|
||||||
|
|
||||||
|
#define APP_SLEEP_MSECS 8000
|
||||||
|
|
||||||
|
#define APP_MQTT_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
#endif /* __CONFIG_H__ */
|
21
samples/net/mqtt_azure/src/digicert.cer
Normal file
21
samples/net/mqtt_azure/src/digicert.cer
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
"-----BEGIN CERTIFICATE-----\r\n"
|
||||||
|
"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\r\n"
|
||||||
|
"RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\r\n"
|
||||||
|
"VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\r\n"
|
||||||
|
"DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\r\n"
|
||||||
|
"ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\r\n"
|
||||||
|
"VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\r\n"
|
||||||
|
"mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\r\n"
|
||||||
|
"IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\r\n"
|
||||||
|
"mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\r\n"
|
||||||
|
"XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\r\n"
|
||||||
|
"dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\r\n"
|
||||||
|
"jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\r\n"
|
||||||
|
"BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\r\n"
|
||||||
|
"DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\r\n"
|
||||||
|
"9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\r\n"
|
||||||
|
"jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\r\n"
|
||||||
|
"Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\r\n"
|
||||||
|
"ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\r\n"
|
||||||
|
"R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\r\n"
|
||||||
|
"-----END CERTIFICATE-----\r\n"
|
472
samples/net/mqtt_azure/src/main.c
Normal file
472
samples/net/mqtt_azure/src/main.c
Normal file
|
@ -0,0 +1,472 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(mqtt_azure, LOG_LEVEL_DBG);
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <net/socket.h>
|
||||||
|
#include <net/mqtt.h>
|
||||||
|
|
||||||
|
#include <sys/printk.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "test_certs.h"
|
||||||
|
|
||||||
|
/* Buffers for MQTT client. */
|
||||||
|
static u8_t rx_buffer[APP_MQTT_BUFFER_SIZE];
|
||||||
|
static u8_t tx_buffer[APP_MQTT_BUFFER_SIZE];
|
||||||
|
|
||||||
|
/* The mqtt client struct */
|
||||||
|
static struct mqtt_client client_ctx;
|
||||||
|
|
||||||
|
/* MQTT Broker details. */
|
||||||
|
static struct sockaddr_storage broker;
|
||||||
|
|
||||||
|
#if defined(CONFIG_SOCKS)
|
||||||
|
static struct sockaddr socks5_proxy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Socket Poll */
|
||||||
|
static struct pollfd fds[1];
|
||||||
|
static int nfds;
|
||||||
|
|
||||||
|
static bool mqtt_connected;
|
||||||
|
|
||||||
|
static struct k_delayed_work pub_message;
|
||||||
|
#if defined(CONFIG_NET_DHCPV4)
|
||||||
|
static struct k_delayed_work check_network_conn;
|
||||||
|
|
||||||
|
/* Network Management events */
|
||||||
|
#define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
|
||||||
|
|
||||||
|
static struct net_mgmt_event_callback l4_mgmt_cb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_DNS_RESOLVER)
|
||||||
|
static struct addrinfo hints;
|
||||||
|
static struct addrinfo *haddr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static K_SEM_DEFINE(mqtt_start, 0, 1);
|
||||||
|
static K_SEM_DEFINE(publish_msg, 0, 1);
|
||||||
|
|
||||||
|
/* Application TLS configuration details */
|
||||||
|
#define TLS_SNI_HOSTNAME CONFIG_SAMPLE_CLOUD_AZURE_HOSTNAME
|
||||||
|
#define APP_CA_CERT_TAG 1
|
||||||
|
|
||||||
|
static sec_tag_t m_sec_tags[] = {
|
||||||
|
APP_CA_CERT_TAG,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mqtt_event_handler(struct mqtt_client *const client,
|
||||||
|
const struct mqtt_evt *evt);
|
||||||
|
|
||||||
|
static int tls_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = tls_credential_add(APP_CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
|
||||||
|
ca_certificate, sizeof(ca_certificate));
|
||||||
|
if (err < 0) {
|
||||||
|
LOG_ERR("Failed to register public certificate: %d", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prepare_fds(struct mqtt_client *client)
|
||||||
|
{
|
||||||
|
if (client->transport.type == MQTT_TRANSPORT_SECURE) {
|
||||||
|
fds[0].fd = client->transport.tls.sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
fds[0].events = ZSOCK_POLLIN;
|
||||||
|
nfds = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_fds(void)
|
||||||
|
{
|
||||||
|
nfds = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait(int timeout)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (nfds <= 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = poll(fds, nfds, timeout);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("poll error: %d", errno);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void broker_init(void)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *broker4 = (struct sockaddr_in *)&broker;
|
||||||
|
|
||||||
|
broker4->sin_family = AF_INET;
|
||||||
|
broker4->sin_port = htons(SERVER_PORT);
|
||||||
|
|
||||||
|
#if defined(CONFIG_DNS_RESOLVER)
|
||||||
|
net_ipaddr_copy(&broker4->sin_addr,
|
||||||
|
&net_sin(haddr->ai_addr)->sin_addr);
|
||||||
|
#else
|
||||||
|
inet_pton(AF_INET, SERVER_ADDR, &broker4->sin_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_SOCKS)
|
||||||
|
struct sockaddr_in *proxy4 = (struct sockaddr_in *)&socks5_proxy;
|
||||||
|
|
||||||
|
proxy4->sin_family = AF_INET;
|
||||||
|
proxy4->sin_port = htons(SOCKS5_PROXY_PORT);
|
||||||
|
inet_pton(AF_INET, SOCKS5_PROXY_ADDR, &proxy4->sin_addr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_init(struct mqtt_client *client)
|
||||||
|
{
|
||||||
|
static struct mqtt_utf8 password;
|
||||||
|
static struct mqtt_utf8 username;
|
||||||
|
struct mqtt_sec_config *tls_config;
|
||||||
|
|
||||||
|
mqtt_client_init(client);
|
||||||
|
|
||||||
|
broker_init();
|
||||||
|
|
||||||
|
/* MQTT client configuration */
|
||||||
|
client->broker = &broker;
|
||||||
|
client->evt_cb = mqtt_event_handler;
|
||||||
|
|
||||||
|
client->client_id.utf8 = (u8_t *)MQTT_CLIENTID;
|
||||||
|
client->client_id.size = strlen(MQTT_CLIENTID);
|
||||||
|
|
||||||
|
password.utf8 = (u8_t *)CONFIG_SAMPLE_CLOUD_AZURE_PASSWORD;
|
||||||
|
password.size = strlen(CONFIG_SAMPLE_CLOUD_AZURE_PASSWORD);
|
||||||
|
|
||||||
|
client->password = &password;
|
||||||
|
|
||||||
|
username.utf8 = (u8_t *)CONFIG_SAMPLE_CLOUD_AZURE_USERNAME;
|
||||||
|
username.size = strlen(CONFIG_SAMPLE_CLOUD_AZURE_USERNAME);
|
||||||
|
|
||||||
|
client->user_name = &username;
|
||||||
|
|
||||||
|
client->protocol_version = MQTT_VERSION_3_1_1;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
tls_config = &client->transport.tls.config;
|
||||||
|
|
||||||
|
tls_config->peer_verify = 2;
|
||||||
|
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;
|
||||||
|
|
||||||
|
#if defined(CONFIG_SOCKS)
|
||||||
|
mqtt_client_set_proxy(client, &socks5_proxy,
|
||||||
|
socks5_proxy.sa_family == AF_INET ?
|
||||||
|
sizeof(struct sockaddr_in) :
|
||||||
|
sizeof(struct sockaddr_in6));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqtt_event_handler(struct mqtt_client *const client,
|
||||||
|
const struct mqtt_evt *evt)
|
||||||
|
{
|
||||||
|
switch (evt->type) {
|
||||||
|
case MQTT_EVT_CONNACK:
|
||||||
|
if (evt->result) {
|
||||||
|
LOG_ERR("MQTT connect failed %d", evt->result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mqtt_connected = true;
|
||||||
|
LOG_DBG("MQTT client connected!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MQTT_EVT_DISCONNECT:
|
||||||
|
LOG_DBG("MQTT client disconnected %d", evt->result);
|
||||||
|
|
||||||
|
mqtt_connected = false;
|
||||||
|
clear_fds();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MQTT_EVT_PUBACK:
|
||||||
|
if (evt->result) {
|
||||||
|
LOG_ERR("MQTT PUBACK error %d", evt->result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("PUBACK packet id: %u\n", evt->param.puback.message_id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOG_DBG("Unhandled MQTT event %d", evt->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int publish(struct mqtt_client *client, enum mqtt_qos qos)
|
||||||
|
{
|
||||||
|
char payload[] = "{id=123}";
|
||||||
|
char topic[] = "devices/" MQTT_CLIENTID "/messages/events/";
|
||||||
|
u8_t len = strlen(topic);
|
||||||
|
struct mqtt_publish_param param;
|
||||||
|
|
||||||
|
param.message.topic.qos = qos;
|
||||||
|
param.message.topic.topic.utf8 = (u8_t *)topic;
|
||||||
|
param.message.topic.topic.size = len;
|
||||||
|
param.message.payload.data = payload;
|
||||||
|
param.message.payload.len = strlen(payload);
|
||||||
|
param.message_id = sys_rand32_get();
|
||||||
|
param.dup_flag = 0U;
|
||||||
|
param.retain_flag = 0U;
|
||||||
|
|
||||||
|
return mqtt_publish(client, ¶m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Random time between 10 - 15 seconds
|
||||||
|
* If you prefer to have this value more than CONFIG_MQTT_KEEPALIVE,
|
||||||
|
* then keep the application connection live by calling mqtt_live()
|
||||||
|
* in regular intervals.
|
||||||
|
*/
|
||||||
|
static u8_t timeout_for_publish(void)
|
||||||
|
{
|
||||||
|
return (10 + sys_rand32_get() % 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void publish_timeout(struct k_work *work)
|
||||||
|
{
|
||||||
|
k_sem_give(&publish_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void publish_message(void)
|
||||||
|
{
|
||||||
|
while (mqtt_connected) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = publish(&client_ctx, MQTT_QOS_1_AT_LEAST_ONCE);
|
||||||
|
if (rc) {
|
||||||
|
LOG_ERR("mqtt_publish ERROR");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("mqtt_publish OK");
|
||||||
|
|
||||||
|
rc = wait(APP_SLEEP_MSECS);
|
||||||
|
if (rc <= 0) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
mqtt_input(&client_ctx);
|
||||||
|
|
||||||
|
end:
|
||||||
|
k_delayed_work_submit(&pub_message,
|
||||||
|
MSEC_PER_SEC * timeout_for_publish());
|
||||||
|
k_sem_take(&publish_msg, K_FOREVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int try_to_connect(struct mqtt_client *client)
|
||||||
|
{
|
||||||
|
u8_t retries = 3U;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
LOG_DBG("attempting to connect...");
|
||||||
|
|
||||||
|
while (retries--) {
|
||||||
|
client_init(client);
|
||||||
|
|
||||||
|
rc = mqtt_connect(client);
|
||||||
|
if (rc) {
|
||||||
|
LOG_ERR("mqtt_connect failed %d", rc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_fds(client);
|
||||||
|
|
||||||
|
rc = wait(APP_SLEEP_MSECS);
|
||||||
|
if (rc < 0) {
|
||||||
|
mqtt_abort(client);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
mqtt_input(client);
|
||||||
|
|
||||||
|
if (mqtt_connected) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mqtt_abort(client);
|
||||||
|
|
||||||
|
wait(10 * MSEC_PER_SEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_DNS_RESOLVER)
|
||||||
|
static int get_mqtt_broker_addrinfo(void)
|
||||||
|
{
|
||||||
|
int retries = 3;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
while (retries--) {
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
|
||||||
|
rc = getaddrinfo(CONFIG_SAMPLE_CLOUD_AZURE_HOSTNAME, "8883",
|
||||||
|
&hints, &haddr);
|
||||||
|
if (rc == 0) {
|
||||||
|
LOG_INF("DNS resolved for %s:%d",
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_HOSTNAME,
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_SERVER_PORT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_ERR("DNS not resolved for %s:%d, retrying",
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_HOSTNAME,
|
||||||
|
CONFIG_SAMPLE_CLOUD_AZURE_SERVER_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void connect_to_cloud_and_publish(void)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_DHCPV4)
|
||||||
|
while (true) {
|
||||||
|
k_sem_take(&mqtt_start, K_FOREVER);
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_DNS_RESOLVER)
|
||||||
|
rc = get_mqtt_broker_addrinfo();
|
||||||
|
if (rc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
rc = try_to_connect(&client_ctx);
|
||||||
|
if (rc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
publish_message();
|
||||||
|
#if defined(CONFIG_NET_DHCPV4)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DHCP tries to renew the address after interface is down and up.
|
||||||
|
* If DHCPv4 address renewal is success, then it doesn't generate
|
||||||
|
* any event. We have to monitor this way.
|
||||||
|
* If DHCPv4 attempts exceeds maximum number, it will delete iface
|
||||||
|
* address and attempts for new request. In this case we can rely
|
||||||
|
* on IPV4_ADDR_ADD event.
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_NET_DHCPV4)
|
||||||
|
static void check_network_connection(struct k_work *work)
|
||||||
|
{
|
||||||
|
struct net_if *iface;
|
||||||
|
|
||||||
|
if (mqtt_connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = net_if_get_default();
|
||||||
|
if (!iface) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iface->config.dhcpv4.state == NET_DHCPV4_BOUND) {
|
||||||
|
k_sem_give(&mqtt_start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("waiting for DHCP to acquire addr");
|
||||||
|
|
||||||
|
end:
|
||||||
|
k_delayed_work_submit(&check_network_conn, 3 * MSEC_PER_SEC);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_DHCPV4)
|
||||||
|
static void abort_mqtt_connection(void)
|
||||||
|
{
|
||||||
|
if (mqtt_connected) {
|
||||||
|
mqtt_connected = false;
|
||||||
|
mqtt_abort(&client_ctx);
|
||||||
|
k_delayed_work_cancel(&pub_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void l4_event_handler(struct net_mgmt_event_callback *cb,
|
||||||
|
u32_t mgmt_event, struct net_if *iface)
|
||||||
|
{
|
||||||
|
if ((mgmt_event & L4_EVENT_MASK) != mgmt_event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mgmt_event == NET_EVENT_L4_CONNECTED) {
|
||||||
|
/* Wait for DHCP to be back in BOUND state */
|
||||||
|
k_delayed_work_submit(&check_network_conn, 3 * MSEC_PER_SEC);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
|
||||||
|
k_sem_give(&publish_msg);
|
||||||
|
abort_mqtt_connection();
|
||||||
|
k_delayed_work_cancel(&check_network_conn);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
LOG_DBG("Waiting for network to setup...");
|
||||||
|
|
||||||
|
rc = tls_init();
|
||||||
|
if (rc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_delayed_work_init(&pub_message, publish_timeout);
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_DHCPV4)
|
||||||
|
k_delayed_work_init(&check_network_conn, check_network_connection);
|
||||||
|
|
||||||
|
net_mgmt_init_event_callback(&l4_mgmt_cb, l4_event_handler,
|
||||||
|
L4_EVENT_MASK);
|
||||||
|
net_mgmt_add_event_callback(&l4_mgmt_cb);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
connect_to_cloud_and_publish();
|
||||||
|
}
|
14
samples/net/mqtt_azure/src/test_certs.h
Normal file
14
samples/net/mqtt_azure/src/test_certs.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TEST_CERTS_H__
|
||||||
|
#define __TEST_CERTS_H__
|
||||||
|
|
||||||
|
static const unsigned char ca_certificate[] = {
|
||||||
|
#include "digicert.cer"
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __TEST_CERTS_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue