Full Code of espressif/esp-azure for AI

master 15ef01eed284 cached
48 files
134.4 KB
35.9k tokens
74 symbols
1 requests
Download .txt
Repository: espressif/esp-azure
Branch: master
Commit: 15ef01eed284
Files: 48
Total size: 134.4 KB

Directory structure:
gitextract_6f4ybc5i/

├── .github/
│   └── workflows/
│       ├── issue_comment.yml
│       ├── new_issues.yml
│       └── new_prs.yml
├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── README.md
├── component.mk
├── doc/
│   └── azure_cli_iot_hub.md
├── examples/
│   ├── iothub_client_sample_mqtt/
│   │   ├── CMakeLists.txt
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── main/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── Kconfig.projbuild
│   │   │   ├── azure_main.c
│   │   │   ├── component.mk
│   │   │   ├── iothub_client_sample_mqtt.c
│   │   │   └── iothub_client_sample_mqtt.h
│   │   └── sdkconfig.defaults
│   ├── iothub_devicetwin_samples_and_methods/
│   │   ├── CMakeLists.txt
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── main/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── Kconfig.projbuild
│   │   │   ├── azure_main.c
│   │   │   ├── component.mk
│   │   │   └── iothub_client_device_twin_and_methods_sample.c
│   │   └── sdkconfig.defaults
│   └── prov_dev_client_ll_sample/
│       ├── CMakeLists.txt
│       ├── Makefile
│       ├── README.md
│       ├── main/
│       │   ├── CMakeLists.txt
│       │   ├── Kconfig.projbuild
│       │   ├── azure_main.c
│       │   ├── certs/
│       │   │   └── .dummy
│       │   ├── component.mk
│       │   ├── custom_hsm_x509.c
│       │   └── prov_dev_client_ll_sample.c
│       └── sdkconfig.defaults
└── port/
    ├── CMakeLists.txt
    ├── inc/
    │   ├── certs.h
    │   ├── sntp_os.h
    │   ├── socket_async_os.h
    │   └── tlsio_pal.h
    └── src/
        ├── agenttime_esp.c
        ├── certs.c
        ├── platform_esp.c
        └── tlsio_esp_tls.c

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/issue_comment.yml
================================================
name: Sync issue comments to JIRA

# This workflow will be triggered when new issue comment is created (including PR comments)
on: issue_comment

jobs:
  sync_issue_comments_to_jira:
    name: Sync Issue Comments to Jira
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Sync issue comments to JIRA
        uses: espressif/github-actions/sync_issues_to_jira@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          JIRA_PASS: ${{ secrets.JIRA_PASS }}
          JIRA_PROJECT: CA
          JIRA_URL: ${{ secrets.JIRA_URL }}
          JIRA_USER: ${{ secrets.JIRA_USER }}


================================================
FILE: .github/workflows/new_issues.yml
================================================
name: Sync issues to Jira

# This workflow will be triggered when a new issue is opened
on: issues

jobs:
  sync_issues_to_jira:
    name: Sync issues to Jira
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Sync GitHub issues to Jira project
        uses: espressif/github-actions/sync_issues_to_jira@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          JIRA_PASS: ${{ secrets.JIRA_PASS }}
          JIRA_PROJECT: CA
          JIRA_URL: ${{ secrets.JIRA_URL }}
          JIRA_USER: ${{ secrets.JIRA_USER }}


================================================
FILE: .github/workflows/new_prs.yml
================================================
name: Sync remain PRs to Jira

# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project
# Note that, PRs can also get synced when new PR comment is created
on:
  schedule:
    - cron: "0 * * * *"

jobs:
  sync_prs_to_jira:
    name: Sync PRs to Jira
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Sync PRs to Jira project
        uses: espressif/github-actions/sync_issues_to_jira@master
        with:
          cron_job: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          JIRA_PASS: ${{ secrets.JIRA_PASS }}
          JIRA_PROJECT: CA
          JIRA_URL: ${{ secrets.JIRA_URL }}
          JIRA_USER: ${{ secrets.JIRA_USER }}


================================================
FILE: .gitignore
================================================
.settings
.project
.cproject
.vscode/

build
sdkconfig
sdkconfig.old


================================================
FILE: .gitlab-ci.yml
================================================
stages:
  - build_esp32
  - build_esp8266

variables:
  BATCH_BUILD: "1"
  V: "0"
  MAKEFLAGS: "-j5 --no-keep-going"
  IDF_PATH: "$CI_PROJECT_DIR/esp-idf"
  IDF_CI_BUILD: "1"

build_esp32_demo:
  stage: build_esp32
  image: $CI_DOCKER_REGISTRY/esp32-ci-env
  tags:
    - build
  script:
    # add gitlab ssh key
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
    - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
    - git --version
    - git submodule update --init --recursive
    - git clone --recursive --depth 1 $GITLAB_SSH_SERVER/idf/esp-idf.git
    - export PATH="$IDF_PATH/tools:$PATH"
    - cd esp-idf
    - ./install.sh
    - . export.sh
    - cd ..
    - cd examples/iothub_client_sample_mqtt
    - make defconfig && make -j5
    - make clean && rm sdkconfig && rm -r build
    - echo "CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y" >> sdkconfig.defaults
    - make defconfig && make -j5
    - make clean && rm sdkconfig && rm -r build
    - idf.py build
    - cd ../../
    - cd examples/prov_dev_client_ll_sample
    - make defconfig && make -j5
    - make clean && rm sdkconfig && rm -r build
    - echo "CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y" >> sdkconfig.defaults
    - make defconfig && make -j5
    - make clean && rm sdkconfig && rm -r build
    - idf.py build

build_esp8266_demo:
  stage: build_esp8266
  image: $CI_DOCKER_REGISTRY/esp8266-ci-env-new 
  tags:
    - build
  script:
    # add gitlab ssh key
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
    - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
    - git --version
    - git clone -b v3.3 --recursive --depth 1 $GITLAB_SSH_SERVER/sdk/ESP8266_RTOS_SDK.git
    - cd ESP8266_RTOS_SDK
    - source tools/ci/configure_ci_environment.sh
    - cd ..
    - git submodule update --init --recursive
    - export IDF_PATH=$CI_PROJECT_DIR/ESP8266_RTOS_SDK
    - cd examples/iothub_client_sample_mqtt
    - make defconfig
    - make
    - cd ../../
    - cd examples/prov_dev_client_ll_sample
    - make defconfig
    - make


================================================
FILE: .gitmodules
================================================
[submodule "azure-iot-sdk-c"]
	path = azure-iot-sdk-c
	url = https://github.com/Azure/azure-iot-sdk-c.git


================================================
FILE: README.md
================================================
# ESP Azure IoT SDK

## Table of Contents

- [Introduction](#introduction)
- [Getting Started](#get-started)
- [Creating an Azure IoT Device](#create-device)
- [Monitoring Results](#monitoring)
- [Troubleshooting](#troubleshooting)

## 2021 Update

<a name="2021 update"></a>

Since this library has been published, Microsoft has created newer versions of the Azure SDK for usage with the Espressif ESP32. This new library is better suited for microcontrollers, great for composition with your own network stack and officially supported by Microsoft. 

The first one, [Azure IoT middleware for FreeRTOS](https://github.com/Azure/azure-iot-middleware-freertos), is based on ESP-IDF and FreeRTOS and it has [samples](https://github.com/Azure-Samples/iot-middleware-freertos-samples) for IoT Hub and IoT Central using the device provisioning service (DPS).

The second one is based on [Azure IoT for C library for Arduino](https://github.com/Azure/azure-sdk-for-c-arduino) and also has samples for IoT Hub. 

If you can, **avoid using this library for any new projects**.  

## Introduction

<a name="introduction"></a>

The ESP Azure IoT SDK is based on [Azure IoT C SDK](https://github.com/Azure/azure-iot-sdk-c) and enables users to connect their ESP32 based devices to the Azure IoT hub. It provides some examples which can help understand most common use cases.

## Getting Started

<a name="get-started"></a>

### Hardware

You will basically just need a development host and an [ESP32 development board](https://www.espressif.com/en/products/hardware/development-boards) to get started.

### Development Host Setup

This project is to be used with Espressif's IoT Development Framework, [ESP IDF](https://github.com/espressif/esp-idf). Follow these steps to get started:

- Setup ESP IDF development environment by following the steps [here](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html).
- In a separate folder, clone the esp-azure project as follows (please note the --recursive option, which is required to clone the various git submodules required by esp-azure)

``` bash
$ git clone --recursive https://github.com/espressif/esp-azure.git
```

> Note that if you ever change the branch or the git head of either esp-idf or esp-azure, ensure that all the submodules of the git repo are in sync by executing `git submodule update --init --recursive`

##

### Setting up Azure IoT Hub

- Create an Azure IoT Hub by following the documentation [here](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal).

> **Note: When selecting the "Pricing and scale tier", there is also an option to select , F1: Free tier, which should be sufficient for basic evaluation.**

- Copy the IoT Hub `Connection string - primary key` from the Azure IoT Hub. This will be required later. The screenshot below will help you locate it.
![](doc/_static/connection_string.png)
- Connection string - primary key sample:

```
HostName=<azure-iot-hub-name>.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=<base64-encoded-access-key>
```

### Setting up Azure CLI

- Install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
- From your terminal, execute the `az` command to verify that the installation was successful. Output will be like this:

```
$ az

Welcome to Azure CLI!
---------------------
Use `az -h` to see available commands or go to https://aka.ms/cli.
...
```

- Install the Azure IoT CLI extension using

`$ az extension add --name azure-cli-iot-ext`

After that, you should be able to use azure CLI to manage your iot-device. A list of useful Azure CLIs can be found [here](doc/azure_cli_iot_hub.md) 

## Creating an Azure IoT Device

<a name="create-device"></a>

- Login to Azure CLI using `$ az login`
- Create a new device using `$ az iot hub device-identity create -n [IoTHub Name] -d [Device ID]`
- Get connection string for your device using `$ az iot hub device-identity show-connection-string -n [IoTHub Name] -d [Device ID]`
- Device connection string sample:

```
HostName=<azure-iot-hub-name>.azure-devices.net;DeviceId=<azure-iot-device-id>;SharedAccessKey=<base64-encoded-shared-access-key>
```

- This will be required in the examples



## Monitoring Results

<a name="monitoring"></a>

To see various events and the data being exchanged between the device and IoT hub from your command line, run the following command:

 `$ az iot hub monitor-events -n [IoTHub Name] --login '[Connection string - primary key]'`
 
 > Note the single quotes for the connection string. Without them, the command wont work as desired.
 
To monitor activity on your ESP device, run:

 `$ make monitor`

## Troubleshooting
<a name="troubleshooting"></a>

1. Some common problems can be fixed by disabling the firewall.

2. You can try with the followings, if your build fails:
	- `$ git submodule update --init --recursive`
	- Check the compiler version and verify that it is the correct one for your ESP IDF version.
	- Check if the IDF_PATH is set correctly
	- Clean the project with `make clean` and if required, using `rm -rf build sdkconfig sdkconfig.old`
	
3. Ensure that the device connection string received from Azure IoT Hub are correct.


================================================
FILE: component.mk
================================================
#
# Component Makefile
#
 
# Component configuration in preprocessor defines
CFLAGS += -DUSE_LWIP_SOCKET_FOR_AZURE_IOT

COMPONENT_ADD_INCLUDEDIRS := \
azure-iot-sdk-c/c-utility/inc \
azure-iot-sdk-c/c-utility/deps/azure-macro-utils-c/inc \
azure-iot-sdk-c/c-utility/deps/umock-c/inc \
azure-iot-sdk-c/iothub_client/inc \
azure-iot-sdk-c/serializer/inc \
azure-iot-sdk-c/umqtt/inc \
azure-iot-sdk-c/umqtt/inc/azure_umqtt_c \
azure-iot-sdk-c/deps/parson \
azure-iot-sdk-c/provisioning_client/inc \
azure-iot-sdk-c/provisioning_client/adapters \
azure-iot-sdk-c/provisioning_client/deps/utpm/inc \

COMPONENT_PRIV_INCLUDEDIRS := \
port/inc \
azure-iot-sdk-c/c-utility/pal/inc \
azure-iot-sdk-c/c-utility/pal/freertos \
azure-iot-sdk-c/c-utility/pal/generic \

ifndef CONFIG_TARGET_PLATFORM_ESP8266
COMPONENT_ADD_INCLUDEDIRS += azure-iot-sdk-c/certs
endif
 
COMPONENT_OBJS = \
azure-iot-sdk-c/c-utility/pal/freertos/lock.o \
azure-iot-sdk-c/c-utility/pal/socket_async.o \
azure-iot-sdk-c/c-utility/pal/freertos/threadapi.o \
azure-iot-sdk-c/c-utility/pal/freertos/tickcounter.o \
azure-iot-sdk-c/c-utility/pal/tlsio_options.o \
\
port/src/agenttime_esp.o \
port/src/platform_esp.o \
port/src/tlsio_esp_tls.o \
\
azure-iot-sdk-c/c-utility/src/xlogging.o \
azure-iot-sdk-c/c-utility/src/singlylinkedlist.o \
azure-iot-sdk-c/c-utility/src/buffer.o \
azure-iot-sdk-c/c-utility/src/consolelogger.o \
azure-iot-sdk-c/c-utility/src/constbuffer.o \
azure-iot-sdk-c/c-utility/src/constmap.o \
azure-iot-sdk-c/c-utility/src/crt_abstractions.o \
azure-iot-sdk-c/c-utility/src/doublylinkedlist.o \
azure-iot-sdk-c/c-utility/src/gballoc.o \
azure-iot-sdk-c/c-utility/src/gb_stdio.o \
azure-iot-sdk-c/c-utility/src/gb_time.o \
azure-iot-sdk-c/c-utility/src/hmac.o \
azure-iot-sdk-c/c-utility/src/hmacsha256.o \
azure-iot-sdk-c/c-utility/src/httpapiex.o \
azure-iot-sdk-c/c-utility/src/httpapiexsas.o \
azure-iot-sdk-c/c-utility/src/httpheaders.o \
azure-iot-sdk-c/c-utility/src/map.o \
azure-iot-sdk-c/c-utility/src/optionhandler.o \
azure-iot-sdk-c/c-utility/src/sastoken.o \
azure-iot-sdk-c/c-utility/src/sha1.o \
azure-iot-sdk-c/c-utility/src/sha224.o \
azure-iot-sdk-c/c-utility/src/sha384-512.o \
azure-iot-sdk-c/c-utility/src/strings.o \
azure-iot-sdk-c/c-utility/src/string_tokenizer.o \
azure-iot-sdk-c/c-utility/src/urlencode.o \
azure-iot-sdk-c/c-utility/src/usha.o \
azure-iot-sdk-c/c-utility/src/vector.o \
azure-iot-sdk-c/c-utility/src/xio.o \
azure-iot-sdk-c/c-utility/src/azure_base64.o \
\
\
azure-iot-sdk-c/iothub_client/src/iothub_device_client_ll.o \
azure-iot-sdk-c/iothub_client/src/iothub_client_ll.o \
azure-iot-sdk-c/iothub_client/src/iothub_client_core_ll.o \
azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.o \
azure-iot-sdk-c/iothub_client/src/iothub_client_authorization.o \
azure-iot-sdk-c/iothub_client/src/iothub_client_retry_control.o \
azure-iot-sdk-c/iothub_client/src/iothub_client_diagnostic.o \
azure-iot-sdk-c/iothub_client/src/iothub_message.o \
azure-iot-sdk-c/iothub_client/src/iothubtransport.o \
azure-iot-sdk-c/iothub_client/src/iothubtransportmqtt.o \
azure-iot-sdk-c/iothub_client/src/iothubtransport_mqtt_common.o \
azure-iot-sdk-c/iothub_client/src/iothub_transport_ll_private.o \
azure-iot-sdk-c/iothub_client/src/version.o \
\
\
azure-iot-sdk-c/umqtt/src/mqtt_client.o \
azure-iot-sdk-c/umqtt/src/mqtt_codec.o \
azure-iot-sdk-c/umqtt/src/mqtt_message.o \
\
\
azure-iot-sdk-c/deps/parson/parson.o \
\
azure-iot-sdk-c/serializer/src/codefirst.o \
azure-iot-sdk-c/serializer/src/agenttypesystem.o \
azure-iot-sdk-c/serializer/src/commanddecoder.o \
azure-iot-sdk-c/serializer/src/datamarshaller.o \
azure-iot-sdk-c/serializer/src/datapublisher.o \
azure-iot-sdk-c/serializer/src/dataserializer.o \
azure-iot-sdk-c/serializer/src/iotdevice.o \
azure-iot-sdk-c/serializer/src/jsondecoder.o \
azure-iot-sdk-c/serializer/src/jsonencoder.o \
azure-iot-sdk-c/serializer/src/methodreturn.o \
azure-iot-sdk-c/serializer/src/multitree.o \
azure-iot-sdk-c/serializer/src/schema.o \
azure-iot-sdk-c/serializer/src/schemalib.o \
azure-iot-sdk-c/serializer/src/schemaserializer.o \
\
\
azure-iot-sdk-c/provisioning_client/src/prov_device_client.o \
azure-iot-sdk-c/provisioning_client/src/prov_transport_mqtt_client.o \
azure-iot-sdk-c/provisioning_client/src/prov_transport_mqtt_common.o \
azure-iot-sdk-c/provisioning_client/src/prov_security_factory.o \
azure-iot-sdk-c/provisioning_client/src/prov_device_ll_client.o \
azure-iot-sdk-c/provisioning_client/src/iothub_security_factory.o \
azure-iot-sdk-c/provisioning_client/adapters/hsm_client_data.o \
azure-iot-sdk-c/provisioning_client/adapters/hsm_client_tpm.o \
azure-iot-sdk-c/provisioning_client/src/prov_auth_client.o \
azure-iot-sdk-c/provisioning_client/deps/utpm/src/tpm_codec.o \
azure-iot-sdk-c/provisioning_client/deps/utpm/src/Marshal.o \
azure-iot-sdk-c/provisioning_client/deps/utpm/src/tpm_comm_emulator.o \
azure-iot-sdk-c/provisioning_client/deps/utpm/src/Memory.o \
azure-iot-sdk-c/provisioning_client/deps/utpm/src/tpm_socket_comm.o \
azure-iot-sdk-c/iothub_client/src/iothub.o \
azure-iot-sdk-c/c-utility/src/http_proxy_io.o \
azure-iot-sdk-c/c-utility/src/azure_base32.o \

ifdef CONFIG_DEVICE_COMMON_NAME
COMPONENT_OBJS += azure-iot-sdk-c/provisioning_client/src/iothub_auth_client.o
endif

ifdef CONFIG_TARGET_PLATFORM_ESP8266
COMPONENT_OBJS += port/src/certs.o
endif

ifndef CONFIG_TARGET_PLATFORM_ESP8266
COMPONENT_OBJS += azure-iot-sdk-c/certs/certs.o
endif

COMPONENT_SRCDIRS := \
port/src \
azure-iot-sdk-c/c-utility/pal \
azure-iot-sdk-c/c-utility/pal/freertos \
azure-iot-sdk-c/c-utility/pal/lwip \
azure-iot-sdk-c/c-utility/src \
azure-iot-sdk-c/c-utility/adapters \
azure-iot-sdk-c/umqtt/src \
azure-iot-sdk-c/iothub_client/src \
azure-iot-sdk-c/serializer/src \
azure-iot-sdk-c/deps/parson \
azure-iot-sdk-c/prov_device_client/src \
azure-iot-sdk-c/iothub_client_mqtt_transport \
azure-iot-sdk-c/iothub_client_amqp_transport \
azure-iot-sdk-c/provisioning_client/src \
azure-iot-sdk-c/provisioning_client/adapters \
azure-iot-sdk-c/provisioning_client/deps/utpm/src \

ifndef CONFIG_TARGET_PLATFORM_ESP8266
COMPONENT_SRCDIRS += azure-iot-sdk-c/certs
endif

CFLAGS += -Wno-unused-function -Wno-missing-braces -Wno-missing-field-initializers -DHSM_TYPE_X509 -DHSM_TYPE_SAS_TOKEN -Wno-unknown-pragmas

ifdef CONFIG_DEVICE_COMMON_NAME
CFLAGS += -DUSE_PROV_MODULE
endif

azure-iot-sdk-c/iothub_client/src/iothubtransport_mqtt_common.o: CFLAGS+=-Wno-maybe-uninitialized


================================================
FILE: doc/azure_cli_iot_hub.md
================================================
# Azure CLI usage

## Login	[Required for using any of the other commands]
```
az login
```

## Create a device
```
az iot hub device-identity create -n [IoTHub Name] -d [Device ID]
```

## List all devices
```
az iot hub device-identity list --hub-name [IoTHub Name]
```

## Get device connection string
```
az iot hub device-identity show-connection-string -n [IoTHub Name] -d [Device ID]
```

## Send message to device
```
az iot device c2d-message send -d [Device Id] -n [IoTHub Name] --data [Data_to_Send]
```

## Delete a device
```
az iot hub device-identity delete -n [IoTHub Name] -d [Device ID]
```

## Monitor events
```
az iot hub monitor-events -n [IoTHub Name] --login 'HostName=myhub.azuredevices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=12345'
```

## Additional Information


Additional information for Azure IoT CLI can be found [here](https://docs.microsoft.com/en-us/cli/azure/ext/azure-cli-iot-ext/iot?view=azure-cli-latest)

================================================
FILE: examples/iothub_client_sample_mqtt/CMakeLists.txt
================================================
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set (EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_BINARY_DIR}/../../../port")
project(iothub_client_sample_mqtt)


================================================
FILE: examples/iothub_client_sample_mqtt/Makefile
================================================
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#

PROJECT_NAME := iothub_client_sample_mqtt

EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../esp-azure

include $(IDF_PATH)/make/project.mk


================================================
FILE: examples/iothub_client_sample_mqtt/README.md
================================================
# IoT HUB MQTT Client

This demonstrates MQTT send received using Azure IoT.

## Device Configuration
- For this demo we will use the same Azure IoT device created using the steps defined in top level [README](../../README.md#creating-an-azure-iot-device). Copy the connection string for the device from the output of this command:

``` bash
$ az iot hub device-identity show-connection-string -n [IoTHub Name] -d [Device ID]
```

Sample output:
```
{
  "connectionString": "HostName=<azure-iot-hub-name>.azure-devices.net;DeviceId=<azure-iot-device-id>;SharedAccessKey=<base64-encoded-shared-access-key>"
}
```
> Note that the double quotes at both the ends of the string are not part of the connection string. So, for the above, just copy `HostName=<azure-iot-hub-name>.azure-devices.net;DeviceId=<azure-iot-device-id>;SharedAccessKey=<base64-encoded-shared-access-key>`
> While changing the value, please ensure that you have completely cleared the older value, before pasting the new one. If you face any run time connection issues, double check this value.


- Execute `make menuconfig`. In the menu, go to `Example Configuration` and configure `WiFi SSID` and `WiFi Password` so that the device can connect to the appropriate Wi-Fi network on boot up. Set `IOT Hub Device Connection String` with the string copied above

## Trying out the example

- Run the following command to flash the example and monitor the output

``` bash
$ make -j8 flash monitor
```

- In a separate window, monitor the Azure IoT events using the following:

```
$ az iot hub monitor-events -n [IoTHub Name] --login '[Connection string - primary key]'
```

- Once the device connects to the Wi-Fi network, it starts publishing MQTT messages. The Azure IoT monitor will show these messages like below:

```
{
    "event": {
        "origin": "<azure-iot-device-id>",
        "payload": "{\"deviceId\":\"myFirstDevice\",\"windSpeed\":13.00,\"temperature\":22.00,\"humidity\":67.00}"
    }
}
```

- You can also send MQTT messages to your device by using the following command:

```
$ az iot device c2d-message send -d [Device Id] -n [IoTHub Name] --data [Data_to_Send]
```
The `make monitor` output will print the received messages like below:

```
Received Message [1]
 Message ID: 635fd5a9-70a4-422f-9394-4cda9026c2e1
 Correlation ID: <null>
 Data: <<<Hello World>>> & Size=18
```




================================================
FILE: examples/iothub_client_sample_mqtt/main/CMakeLists.txt
================================================
set(COMPONENT_SRCS "iothub_client_sample_mqtt.c"
			"azure_main.c"
			)
set(COMPONENT_ADD_INCLUDEDIRS ".")

register_component()

component_compile_definitions(SET_TRUSTED_CERT_IN_SAMPLES)


================================================
FILE: examples/iothub_client_sample_mqtt/main/Kconfig.projbuild
================================================
menu "Example Configuration"

config WIFI_SSID
    string "WiFi SSID"
	default "myssid"
	help
		SSID (network name) for the example to connect to.

config WIFI_PASSWORD
    string "WiFi Password"
	default "myssid"
	help
		WiFi password (WPA or WPA2) for the example to use.

		Can be left blank if the network has no security set.

config IOTHUB_CONNECTION_STRING
    string "IOT Hub Device Connection String"
	default ""
	help
		String containing Hostname, Device Id & Device Key in the format:
		HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>
		You can get this from the Azure IoT CLI or the Azure Portal.

config MESSAGE_INTERVAL_TIME
    int "Time delay in Milliseconds between two consecutive messages"
    default 100
    help
        Set time delay between two consecutive message sent to the cloud

config MESSAGE_COUNT
    int "Total number of messages to be sent to the cloud"
    default 50
    help
        This example will terminate after sending these many
        messages. If the message count is set as 0 then this example
        will send indefinite messages to the cloud.

endmenu


================================================
FILE: examples/iothub_client_sample_mqtt/main/azure_main.c
================================================
/* esp-azure example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "esp_system.h"
#include "esp_system.h"
#include "esp_wifi.h"
#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
#include "esp_event_loop.h"
#else
#include "esp_event.h"
#endif
#include "esp_log.h"

#include "nvs_flash.h"
#include "iothub_client_sample_mqtt.h"

#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD

EventGroupHandle_t wifi_event_group;

#ifndef BIT0
#define BIT0 (0x1 << 0)
#endif
/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
const int CONNECTED_BIT = BIT0;

static const char *TAG = "azure";

#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        /* This is a workaround as ESP platform WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;
    default:
        break;
    }
    return ESP_OK;
}
#else
static void event_handler(void* arg, esp_event_base_t event_base,
                          int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        /* This is a workaround as ESP platform WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
    }
}
#endif

static void initialise_wifi(void)
{
#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
#else
    ESP_ERROR_CHECK( esp_netif_init() );
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_create_default() );
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);
#endif

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_WIFI_SSID,
            .password = EXAMPLE_WIFI_PASS,
        },
    };
    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);

#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
#else
    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
#endif

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}

void azure_task(void *pvParameter)
{
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                        false, true, portMAX_DELAY);
    ESP_LOGI(TAG, "Connected to AP success!");

    iothub_client_sample_mqtt_run();

    vTaskDelete(NULL);
}

void app_main()
{
    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret );

    initialise_wifi();

    if ( xTaskCreate(&azure_task, "azure_task", 1024 * 5, NULL, 5, NULL) != pdPASS ) {
        printf("create azure task failed\r\n");
    }

}


================================================
FILE: examples/iothub_client_sample_mqtt/main/component.mk
================================================
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

CFLAGS += -DSET_TRUSTED_CERT_IN_SAMPLES


================================================
FILE: examples/iothub_client_sample_mqtt/main/iothub_client_sample_mqtt.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdio.h>
#include <stdlib.h>

#include "iothub_client.h"
#include "iothub_device_client_ll.h"
#include "iothub_client_options.h"
#include "iothub_message.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/crt_abstractions.h"
#include "azure_c_shared_utility/platform.h"
#include "azure_c_shared_utility/shared_util_options.h"
#include "iothubtransportmqtt.h"
#include "iothub_client_options.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#ifdef MBED_BUILD_TIMESTAMP
    #define SET_TRUSTED_CERT_IN_SAMPLES
#endif // MBED_BUILD_TIMESTAMP

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
    #include "certs.h"
#endif // SET_TRUSTED_CERT_IN_SAMPLES

/*String containing Hostname, Device Id & Device Key in the format:                         */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"                */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>"    */
#define EXAMPLE_IOTHUB_CONNECTION_STRING CONFIG_IOTHUB_CONNECTION_STRING
static const char* connectionString = EXAMPLE_IOTHUB_CONNECTION_STRING;

static int callbackCounter;
static char msgText[1024];
static char propText[1024];
static bool g_continueRunning;
#define MESSAGE_COUNT CONFIG_MESSAGE_COUNT
#define DOWORK_LOOP_NUM     3

typedef struct EVENT_INSTANCE_TAG
{
    IOTHUB_MESSAGE_HANDLE messageHandle;
    size_t messageTrackingId;  // For tracking the messages within the user callback.
} EVENT_INSTANCE;

static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
    int* counter = (int*)userContextCallback;
    const char* buffer;
    size_t size;
    MAP_HANDLE mapProperties;
    const char* messageId;
    const char* correlationId;

    // Message properties
    if ((messageId = IoTHubMessage_GetMessageId(message)) == NULL)
    {
        messageId = "<null>";
    }

    if ((correlationId = IoTHubMessage_GetCorrelationId(message)) == NULL)
    {
        correlationId = "<null>";
    }

    // Message content
    if (IoTHubMessage_GetByteArray(message, (const unsigned char**)&buffer, &size) != IOTHUB_MESSAGE_OK)
    {
        (void)printf("unable to retrieve the message data\r\n");
    }
    else
    {
        (void)printf("Received Message [%d]\r\n Message ID: %s\r\n Correlation ID: %s\r\n Data: <<<%.*s>>> & Size=%d\r\n", *counter, messageId, correlationId, (int)size, buffer, (int)size);
        // If we receive the work 'quit' then we stop running
        if (size == (strlen("quit") * sizeof(char)) && memcmp(buffer, "quit", size) == 0)
        {
            g_continueRunning = false;
        }
    }

    // Retrieve properties from the message
    mapProperties = IoTHubMessage_Properties(message);
    if (mapProperties != NULL)
    {
        const char*const* keys;
        const char*const* values;
        size_t propertyCount = 0;
        if (Map_GetInternals(mapProperties, &keys, &values, &propertyCount) == MAP_OK)
        {
            if (propertyCount > 0)
            {
                size_t index;

                printf(" Message Properties:\r\n");
                for (index = 0; index < propertyCount; index++)
                {
                    (void)printf("\tKey: %s Value: %s\r\n", keys[index], values[index]);
                }
                (void)printf("\r\n");
            }
        }
    }

    /* Some device specific action code goes here... */
    (*counter)++;
    return IOTHUBMESSAGE_ACCEPTED;
}

static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
    EVENT_INSTANCE* eventInstance = (EVENT_INSTANCE*)userContextCallback;
    size_t id = eventInstance->messageTrackingId;

    if (result == IOTHUB_CLIENT_CONFIRMATION_OK) {
        (void)printf("Confirmation[%d] received for message tracking id = %d with result = %s\r\n", callbackCounter, (int)id, MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result));
        /* Some device specific action code goes here... */
        callbackCounter++;
    }
    IoTHubMessage_Destroy(eventInstance->messageHandle);
}

void connection_status_callback(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* userContextCallback)
{
    (void)printf("\n\nConnection Status result:%s, Connection Status reason: %s\n\n", MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONNECTION_STATUS, result),
                 MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONNECTION_STATUS_REASON, reason));
}

void iothub_client_sample_mqtt_run(void)
{
    IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle;

    EVENT_INSTANCE message;

    g_continueRunning = true;
    srand((unsigned int)time(NULL));
    double avgWindSpeed = 10.0;
    double minTemperature = 20.0;
    double minHumidity = 60.0;

    callbackCounter = 0;
    int receiveContext = 0;

    if (platform_init() != 0)
    {
        (void)printf("Failed to initialize the platform.\r\n");
    }
    else
    {
        if ((iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, MQTT_Protocol)) == NULL)
        {
            (void)printf("ERROR: iotHubClientHandle is NULL!\r\n");
        }
        else
        {
            bool traceOn = true;
            IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_LOG_TRACE, &traceOn);

            IoTHubClient_LL_SetConnectionStatusCallback(iotHubClientHandle, connection_status_callback, NULL);
            // Setting the Trusted Certificate.  This is only necessary on system with without
            // built in certificate stores.
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
            IoTHubDeviceClient_LL_SetOption(iotHubClientHandle, OPTION_TRUSTED_CERT, certificates);
#endif // SET_TRUSTED_CERT_IN_SAMPLES

            /* Setting Message call back, so we can receive Commands. */
            if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext) != IOTHUB_CLIENT_OK)
            {
                (void)printf("ERROR: IoTHubClient_LL_SetMessageCallback..........FAILED!\r\n");
            }
            else
            {
                (void)printf("IoTHubClient_LL_SetMessageCallback...successful.\r\n");

                /* Now that we are ready to receive commands, let's send some messages */
                int iterator = 0;
                double temperature = 0;
                double humidity = 0;
                time_t sent_time = 0;
                time_t current_time = 0;
                do
                {
                    //(void)printf("iterator: [%d], callbackCounter: [%d]. \r\n", iterator, callbackCounter);
                    time(&current_time);
                    if ((MESSAGE_COUNT == 0 || iterator < MESSAGE_COUNT)
                        && iterator <= callbackCounter
                        && (difftime(current_time, sent_time) > ((CONFIG_MESSAGE_INTERVAL_TIME) / 1000)))
                    {
                        temperature = minTemperature + (rand() % 10);
                        humidity = minHumidity +  (rand() % 20);
                        sprintf_s(msgText, sizeof(msgText), "{\"deviceId\":\"myFirstDevice\",\"windSpeed\":%.2f,\"temperature\":%.2f,\"humidity\":%.2f}", avgWindSpeed + (rand() % 4 + 2), temperature, humidity);
                        if ((message.messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, strlen(msgText))) == NULL)
                        {
                            (void)printf("ERROR: iotHubMessageHandle is NULL!\r\n");
                        }
                        else
                        {
                            message.messageTrackingId = iterator;
                            MAP_HANDLE propMap = IoTHubMessage_Properties(message.messageHandle);
                            (void)sprintf_s(propText, sizeof(propText), temperature > 28 ? "true" : "false");
                            if (Map_AddOrUpdate(propMap, "temperatureAlert", propText) != MAP_OK)
                            {
                                (void)printf("ERROR: Map_AddOrUpdate Failed!\r\n");
                            }

                            if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, message.messageHandle, SendConfirmationCallback, &message) != IOTHUB_CLIENT_OK)
                            {
                                (void)printf("ERROR: IoTHubClient_LL_SendEventAsync..........FAILED!\r\n");
                            }
                            else
                            {
                                time(&sent_time);
                                (void)printf("IoTHubClient_LL_SendEventAsync accepted message [%d] for transmission to IoT Hub.\r\n", (int)iterator);
                            }
                        }
                        iterator++;
                    }
                    IoTHubClient_LL_DoWork(iotHubClientHandle);
                    ThreadAPI_Sleep(10);

                    if (MESSAGE_COUNT != 0 && callbackCounter >= MESSAGE_COUNT)
                    {
                        printf("exit\n");
                        break;
                    }
                } while (g_continueRunning);

                (void)printf("iothub_client_sample_mqtt has gotten quit message, call DoWork %d more time to complete final sending...\r\n", DOWORK_LOOP_NUM);
                size_t index = 0;
                for (index = 0; index < DOWORK_LOOP_NUM; index++)
                {
                    IoTHubClient_LL_DoWork(iotHubClientHandle);
                    ThreadAPI_Sleep(1);
                }
            }
            IoTHubClient_LL_Destroy(iotHubClientHandle);
        }
        platform_deinit();
    }
}

int main(void)
{
    iothub_client_sample_mqtt_run();
    return 0;
}


================================================
FILE: examples/iothub_client_sample_mqtt/main/iothub_client_sample_mqtt.h
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef IOTHUB_CLIENT_SAMPLE_MQTT_H
#define IOTHUB_CLIENT_SAMPLE_MQTT_H

#ifdef __cplusplus
extern "C" {
#endif

#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"

/* FreeRTOS event group to signal when we are connected & ready to make a request */
extern EventGroupHandle_t wifi_event_group;
extern const int CONNECTED_BIT;

void iothub_client_sample_mqtt_run(void);

#ifdef __cplusplus
}
#endif

#endif /* IOTHUB_CLIENT_SAMPLE_MQTT_H */


================================================
FILE: examples/iothub_client_sample_mqtt/sdkconfig.defaults
================================================
# newlib for ESP32 and ESP8266 platform

CONFIG_NEWLIB_ENABLE=y
CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y
CONFIG_NEWLIB_NANO_FORMAT=
CONFIG_SSL_USING_MBEDTLS=y
CONFIG_LWIP_IPV6=y



================================================
FILE: examples/iothub_devicetwin_samples_and_methods/CMakeLists.txt
================================================
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set (EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_BINARY_DIR}/../../../port")
project(iothub_devicetwin_samples_and_methods)


================================================
FILE: examples/iothub_devicetwin_samples_and_methods/Makefile
================================================
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#

PROJECT_NAME := iothub_devicetwin_samples_and_methods

EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../esp-azure

include $(IDF_PATH)/make/project.mk


================================================
FILE: examples/iothub_devicetwin_samples_and_methods/README.md
================================================
# Device Twin and Direct Method Example

This example demonstrates Device twin and Direct method features of Azure IoT.


## Device Twin

In this example, we use car object with desired and reported properties as described in the JSON blob below.

```
Car: {
	"lastOilChangeDate": "<value>",            \\ reported property
		"changeOilReminder": "<value>",	           \\ desired property
		"maker": {                                 \\ reported property 
			"makerName": "<value>",
				"style": "<value>",
				"year": <value>
		},
		"state": {                                 \\ reported property
			"reported_maxSpeed": <value>,
			"softwareVersion": <value>,
			"vanityPlate": "<value>"
		},
		"settings": {                              \\ desired property
			"desired_maxSpeed": <value>,
			"location": {
				"longitude": <value>,
				"latitude": <value>
			},
		},
}
```	


### Set Device Twin Desired Properties

- To execute Device Twin, an IoT device will be required. We will use the same Azure IoT device created using the steps defined in top level [README](../../README.md#creating-an-azure-iot-device).
- Set Device Twin desired properties by navigating to `Azure Portal` -> `your IoT Hub` -> `IoT Devices` -> `your IoT device` -> `Device Twin` and paste the following JSON blob under `desired` property. 

```
    "desired": {
        // paste from here..

		"changeOilReminder": "LOW_FUEL",
			"settings": {
				"desired_maxSpeed": 120,
				"location": {
					"longitude": 71,
					"latitude": 25 
				}
			},

		// desired continues..
```

## Device Configuration
- For this demo we will use the same Azure IoT device created using the steps defined in top level [README](../../README.md#create_device). Copy the connection string for the device from the output of this command:

``` bash
$ az iot hub device-identity show-connection-string -n [IoTHub Name] -d [Device ID]
```

Sample output:
```
{
  "connectionString": "HostName=<azure-iot-hub-name>.azure-devices.net;DeviceId=<azure-iot-device-id>;SharedAccessKey=<base64-encoded-shared-access-key>"
}
```
> Note that the double quotes at both the ends of the string are not part of the connection string. So, for the above, just copy `HostName=<azure-iot-hub-name>.azure-devices.net;DeviceId=<azure-iot-device-id>;SharedAccessKey=<base64-encoded-shared-access-key>`
While changing the value, please ensure that you have completely cleared the older value, before pasting the new one. If you face any run time connection issues, double check this value.

- Execute `make menuconfig`. In the menu, go to `Example Configuration` and configure `WiFi SSID` and `WiFi Password` so that the device can connect to the appropriate Wi-Fi network on boot up. Set `IOT Hub Device Connection String` with the string copied above


## Trying out the example

Run the following command to flash the example and monitor the output
`$ make -j8 flash monitor`

After running the application, you can check updated properties by navigating to `Azure Portal` -> `your IoT Hub` -> `IoT devices` -> `your IoT device` -> `Device Twin`

If you change the above set desired field and click on "Save", they will be mirrored on to your ESP Monitor.

### Direct Method Invocation


Navigate to `Azure Portal` -> `your IoT Hub` -> `IoT devices` -> `your IoT device` -> `Direct Method`

Set the `Method Name` as `getCarVIN` and add some payload. Consider an example payload as below:

```
{ "message": "Hello World" }
```

On invoking the method, the invocation request will be sent to the IoT device, which in turn will respond with a payload like below:

```
{ "Response": "1HGCM82633A004352" }
```






================================================
FILE: examples/iothub_devicetwin_samples_and_methods/main/CMakeLists.txt
================================================
set(COMPONENT_SRCS "azure_main.c"
                "iothub_client_device_twin_and_methods_sample.c"
                )
set(COMPONENT_ADD_INCLUDEDIRS ".")

register_component()

component_compile_definitions(SET_TRUSTED_CERT_IN_SAMPLES)


================================================
FILE: examples/iothub_devicetwin_samples_and_methods/main/Kconfig.projbuild
================================================
menu "Example Configuration"

config WIFI_SSID
    string "WiFi SSID"
	default "myssid"
	help
		SSID (network name) for the example to connect to.

config WIFI_PASSWORD
    string "WiFi Password"
	default "myssid"
	help
		WiFi password (WPA or WPA2) for the example to use.

		Can be left blank if the network has no security set.

config IOTHUB_CONNECTION_STRING
    string "IOT Hub Device Connection String"
	default ""
    help
		String containing Hostname, Device Id & Device Key in the format:
		HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>
		You can get this from the Azure IoT CLI or the Azure Portal.

endmenu


================================================
FILE: examples/iothub_devicetwin_samples_and_methods/main/azure_main.c
================================================
/* esp-azure example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "esp_system.h"
#include "esp_system.h"
#include "esp_wifi.h"
#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
#include "esp_event_loop.h"
#else
#include "esp_event.h"
#endif
#include "esp_log.h"

#include "nvs_flash.h"

#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group;

#ifndef BIT0
#define BIT0 (0x1 << 0)
#endif
/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
const int CONNECTED_BIT = BIT0;

static const char *TAG = "azure";

extern int iothhub_devicetwin_init(void);

#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        /* This is a workaround as ESP platform WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;
    default:
        break;
    }
    return ESP_OK;
}
#else
static void event_handler(void* arg, esp_event_base_t event_base,
                          int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        /* This is a workaround as ESP platform WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
    }
}
#endif

static void initialise_wifi(void)
{
#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
#else
    ESP_ERROR_CHECK( esp_netif_init() );
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_create_default() );
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);
#endif

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_WIFI_SSID,
            .password = EXAMPLE_WIFI_PASS,
        },
    };
    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);

#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
#else
    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
#endif

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}

extern int iothub_client_device_twin_init();
void azure_task(void *pvParameter)
{
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                        false, true, portMAX_DELAY);
    ESP_LOGI(TAG, "Connected to AP success!");

    iothub_client_device_twin_init();

    vTaskDelete(NULL);
}

void app_main()
{
    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret );

    initialise_wifi();

    if ( xTaskCreate(&azure_task, "azure_task", 1024 * 6, NULL, 5, NULL) != pdPASS ) {
        printf("create azure task failed\r\n");
    }
}


================================================
FILE: examples/iothub_devicetwin_samples_and_methods/main/component.mk
================================================
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

CFLAGS += -DSET_TRUSTED_CERT_IN_SAMPLES


================================================
FILE: examples/iothub_devicetwin_samples_and_methods/main/iothub_client_device_twin_and_methods_sample.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// This sample shows how to translate the Device Twin json received from Azure IoT Hub into meaningful data for your application.
// It uses the parson library, a very lightweight json parser.

// There is an analogous sample using the serializer - which is a library provided by this SDK to help parse json - in devicetwin_simplesample.
// Most applications should use this sample, not the serializer.

// WARNING: Check the return of all API calls when developing your solution. Return checks ommited for sample simplification.

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "azure_macro_utils/macro_utils.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/platform.h"
#include "iothub_device_client.h"
#include "iothub_client_options.h"
#include "iothub.h"
#include "iothub_message.h"
#include "parson.h"
#include "sdkconfig.h"

// The protocol you wish to use should be uncommented
//
#define SAMPLE_MQTT
//#define SAMPLE_MQTT_OVER_WEBSOCKETS
//#define SAMPLE_AMQP
//#define SAMPLE_AMQP_OVER_WEBSOCKETS
//#define SAMPLE_HTTP

#ifdef SAMPLE_MQTT
    #include "iothubtransportmqtt.h"
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
    #include "iothubtransportmqtt_websockets.h"
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
    #include "iothubtransportamqp.h"
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
    #include "iothubtransportamqp_websockets.h"
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
    #include "iothubtransporthttp.h"
#endif // SAMPLE_HTTP

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
#include "certs.h"
#endif // SET_TRUSTED_CERT_IN_SAMPLES

/* Paste in the your iothub device connection string  */
static const char* connectionString = CONFIG_IOTHUB_CONNECTION_STRING;

#define DOWORK_LOOP_NUM     3

typedef struct MAKER_TAG
{
    char* makerName;
    char* style;
    int year;
} Maker;

typedef struct GEO_TAG
{
    double longitude;
    double latitude;
} Geo;

typedef struct CAR_STATE_TAG
{
    int32_t softwareVersion;        // reported property
    uint8_t reported_maxSpeed;      // reported property
    char* vanityPlate;              // reported property
} CarState;

typedef struct CAR_SETTINGS_TAG
{
    uint8_t desired_maxSpeed;       // desired property
    Geo location;                   // desired property
} CarSettings;

typedef struct CAR_TAG
{
    char* lastOilChangeDate;        // reported property
    char* changeOilReminder;        // desired property
    Maker maker;                    // reported property
    CarState state;                 // reported property
    CarSettings settings;           // desired property
} Car;

//  Converts the Car object into a JSON blob with reported properties that is ready to be sent across the wire as a twin.
static char* serializeToJson(Car* car)
{
    char* result;

    JSON_Value* root_value = json_value_init_object();
    JSON_Object* root_object = json_value_get_object(root_value);

    // Only reported properties:
    (void)json_object_set_string(root_object, "lastOilChangeDate", car->lastOilChangeDate);
    (void)json_object_dotset_string(root_object, "maker.makerName", car->maker.makerName);
    (void)json_object_dotset_string(root_object, "maker.style", car->maker.style);
    (void)json_object_dotset_number(root_object, "maker.year", car->maker.year);
    (void)json_object_dotset_number(root_object, "state.reported_maxSpeed", car->state.reported_maxSpeed);
    (void)json_object_dotset_number(root_object, "state.softwareVersion", car->state.softwareVersion);
    (void)json_object_dotset_string(root_object, "state.vanityPlate", car->state.vanityPlate);

    result = json_serialize_to_string(root_value);
    json_value_free(root_value);

    return result;
}

//  Converts the desired properties of the Device Twin JSON blob received from IoT Hub into a Car object.
static Car* parseFromJson(const char* json, DEVICE_TWIN_UPDATE_STATE update_state)
{
    Car* car = malloc(sizeof(Car));
    JSON_Value* root_value = NULL;
    JSON_Object* root_object = NULL;

    if (NULL == car)
    {
        (void)printf("ERROR: Failed to allocate memory\r\n");
    }

    else
    {
        (void)memset(car, 0, sizeof(Car));

        root_value = json_parse_string(json);
        root_object = json_value_get_object(root_value);

        // Only desired properties:
        JSON_Value* changeOilReminder;
        JSON_Value* desired_maxSpeed;
        JSON_Value* latitude;
        JSON_Value* longitude;

        if (update_state == DEVICE_TWIN_UPDATE_COMPLETE)
        {
            changeOilReminder = json_object_dotget_value(root_object, "desired.changeOilReminder");
            desired_maxSpeed = json_object_dotget_value(root_object, "desired.settings.desired_maxSpeed");
            latitude = json_object_dotget_value(root_object, "desired.settings.location.latitude");
            longitude = json_object_dotget_value(root_object, "desired.settings.location.longitude");
        }
        else
        {
            changeOilReminder = json_object_dotget_value(root_object, "changeOilReminder");
            desired_maxSpeed = json_object_dotget_value(root_object, "settings.desired_maxSpeed");
            latitude = json_object_dotget_value(root_object, "settings.location.latitude");
            longitude = json_object_dotget_value(root_object, "settings.location.longitude");
        }

        if (changeOilReminder != NULL)
        {
            const char* data = json_value_get_string(changeOilReminder);

            if (data != NULL)
            {
                car->changeOilReminder = malloc(strlen(data) + 1);
                if (NULL != car->changeOilReminder)
                {
                    (void)strcpy(car->changeOilReminder, data);
                }
            }
        }

        if (desired_maxSpeed != NULL)
        {
            car->settings.desired_maxSpeed = (uint8_t)json_value_get_number(desired_maxSpeed);
        }

        if (latitude != NULL)
        {
            car->settings.location.latitude = json_value_get_number(latitude);
        }

        if (longitude != NULL)
        {
            car->settings.location.longitude = json_value_get_number(longitude);
        }
        json_value_free(root_value);
    }

    return car;
}

static int deviceMethodCallback(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* response_size, void* userContextCallback)
{
    (void)userContextCallback;
    (void)payload;
    (void)size;

    printf("Method Name: %s\n", method_name);
    int result;
    if (strcmp("getCarVIN", method_name) == 0)
    {
        const char deviceMethodResponse[] = "{ \"Response\": \"1HGCM82633A004352\" }";
        *response_size = sizeof(deviceMethodResponse)-1;
        *response = malloc(*response_size);
        if (*response != NULL)
        {
            (void)memcpy(*response, deviceMethodResponse, *response_size);
            result = 200;
        }
        else
        {
            result = -1;
        }
    }
    else
    {
        // All other entries are ignored.
        const char deviceMethodResponse[] = "{ }";
        *response_size = sizeof(deviceMethodResponse)-1;
        *response = malloc(*response_size);
        if (*response != NULL) {
            (void)memcpy(*response, deviceMethodResponse, *response_size);
        }
        result = -1;
    }

    return result;
}

static void deviceTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
{
    (void)update_state;
    (void)size;
    Car* oldCar = (Car*)userContextCallback;
    Car* newCar = parseFromJson((const char*)payLoad, update_state);

    if (newCar != NULL)
    {
        if (newCar->changeOilReminder != NULL)
        {
            if ((oldCar->changeOilReminder != NULL) && (strcmp(oldCar->changeOilReminder, newCar->changeOilReminder) != 0))
            {
                free(oldCar->changeOilReminder);
            }

            if (oldCar->changeOilReminder == NULL)
            {
                printf("Received a new changeOilReminder = %s\n", newCar->changeOilReminder);
                if ( NULL != (oldCar->changeOilReminder = malloc(strlen(newCar->changeOilReminder) + 1)))
                {
                    (void)strcpy(oldCar->changeOilReminder, newCar->changeOilReminder);
                    free(newCar->changeOilReminder);
                }
            }
        }

        if (newCar->settings.desired_maxSpeed != 0)
        {
            if (newCar->settings.desired_maxSpeed != oldCar->settings.desired_maxSpeed)
            {
                printf("Received a new desired_maxSpeed = %" PRIu8 "\n", newCar->settings.desired_maxSpeed);
                oldCar->settings.desired_maxSpeed = newCar->settings.desired_maxSpeed;
            }
        }

        if (newCar->settings.location.latitude != 0)
        {
            if (newCar->settings.location.latitude != oldCar->settings.location.latitude)
            {
                printf("Received a new latitude = %f\n", newCar->settings.location.latitude);
                oldCar->settings.location.latitude = newCar->settings.location.latitude;
            }
        }

        if (newCar->settings.location.longitude != 0)
        {
            if (newCar->settings.location.longitude != oldCar->settings.location.longitude)
            {
                printf("Received a new longitude = %f\n", newCar->settings.location.longitude);
                oldCar->settings.location.longitude = newCar->settings.location.longitude;
            }
        }

        free(newCar);
    }
    else
    {
        printf("Error: JSON parsing failed!\r\n");
    }
}

static void reportedStateCallback(int status_code, void* userContextCallback)
{
    (void)userContextCallback;
    printf("Device Twin reported properties update completed with result: %d\r\n", status_code);
}


static void iothub_client_device_twin_and_methods_sample_run(void)
{
    IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
    IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle;

    // Select the Protocol to use with the connection
#ifdef SAMPLE_MQTT
    protocol = MQTT_Protocol;
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
    protocol = MQTT_WebSocket_Protocol;
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
    protocol = AMQP_Protocol;
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
    protocol = AMQP_Protocol_over_WebSocketsTls;
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
    protocol = HTTP_Protocol;
#endif // SAMPLE_HTTP

    if (IoTHub_Init() != 0)
    {
        (void)printf("Failed to initialize the platform.\r\n");
    }
    else
    {
        if ((iotHubClientHandle = IoTHubDeviceClient_LL_CreateFromConnectionString(connectionString, protocol)) == NULL)
        {
            (void)printf("ERROR: iotHubClientHandle is NULL!\r\n");
        }
        else
        {
            // Uncomment the following lines to enable verbose logging (e.g., for debugging).
            //bool traceOn = true;
            //(void)IoTHubDeviceClient_SetOption(iotHubClientHandle, OPTION_LOG_TRACE, &traceOn);

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
            // For mbed add the certificate information
            if (IoTHubDeviceClient_LL_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
            {
                (void)printf("failure to set option \"TrustedCerts\"\r\n");
            }
#endif // SET_TRUSTED_CERT_IN_SAMPLES

            Car car;
            memset(&car, 0, sizeof(Car));
            car.lastOilChangeDate = "2016";
            car.maker.makerName = "Fabrikam";
            car.maker.style = "sedan";
            car.maker.year = 2014;
            car.state.reported_maxSpeed = 100;
            car.state.softwareVersion = 1;
            car.state.vanityPlate = "1I1";

            char* reportedProperties = serializeToJson(&car);
            if (reportedProperties != NULL)
            {
                (void)IoTHubDeviceClient_LL_SendReportedState(iotHubClientHandle, (const unsigned char*)reportedProperties, strlen(reportedProperties), reportedStateCallback, NULL);
                (void)IoTHubDeviceClient_LL_SetDeviceMethodCallback(iotHubClientHandle, deviceMethodCallback, NULL);
                (void)IoTHubDeviceClient_LL_SetDeviceTwinCallback(iotHubClientHandle, deviceTwinCallback, &car);

                while (1) {
                    IoTHubDeviceClient_LL_DoWork(iotHubClientHandle);
                    ThreadAPI_Sleep(10);
                }

                free(reportedProperties);
                free(car.changeOilReminder);
            }
            else
            {
                printf("Error: JSON serialization failed!\r\n");
            }
            IoTHubDeviceClient_LL_Destroy(iotHubClientHandle);
        }

        IoTHub_Deinit();
    }
}

int iothub_client_device_twin_init(void)
{
    iothub_client_device_twin_and_methods_sample_run();
    return 0;
}

================================================
FILE: examples/iothub_devicetwin_samples_and_methods/sdkconfig.defaults
================================================
# newlib for ESP32 and ESP8266 platform

CONFIG_NEWLIB_ENABLE=y
CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y
CONFIG_NEWLIB_NANO_FORMAT=
CONFIG_SSL_USING_MBEDTLS=y
CONFIG_LWIP_IPV6=y



================================================
FILE: examples/prov_dev_client_ll_sample/CMakeLists.txt
================================================
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set (EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_BINARY_DIR}/../../../port")
project(prov_dev_client_ll_sample)


================================================
FILE: examples/prov_dev_client_ll_sample/Makefile
================================================
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#

PROJECT_NAME := prov_dev_client_ll_sample

EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../esp-azure

include $(IDF_PATH)/make/project.mk


================================================
FILE: examples/prov_dev_client_ll_sample/README.md
================================================
# Azure Provisioning Demo

This example demonstrates Device Authentication using X.509 CA Certificates. Refer [this azure documentation](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-x509ca-overview) to learn more about this.

# Provisioning Setup

### Creating a Device

- We will use the same IoT hub that was created as per the steps in the top level [README](../../README.md#setting-up-azure-iot-hub)
- Go to the IoT Hub. Find and click on "IoT devices" under "Explorers" in the menu bar.
- Click on "New".
- Enter name of your IoT Device in "Device ID".
- Select Authentication type as "X.509 CA Signed".
- Click "Save".


### Certificate Generation
<a name="cert-gen"></a>

- Here certificates will be generated with [OpenSSL](https://www.openssl.org/). Other services can also be used to generate certificates.These commands are UNIX/Linux specific. For other system, these commands may not work.
- [Download](https://www.openssl.org/source/) and install openSSL.
- After the installation is complete, use following commands:
	- Generate Root CA private key

	```
	$ openssl genrsa -out rootCA.key 4096
	```
	- Generate Root CA certificate:

	```
	$ openssl req -x509 -new -key rootCA.key -days 1024 -out rootCA.pem
	```
	> You can keep all parameters at defaults (by pressing enter) except Common Name (CN). Give any user friendly common name to your root CA certificate.
	
	- Generate key for device (we will call it a leaf):
	
	```
	$ openssl genrsa -out leaf_private_key.pem 4096
	```
	- Generate Certificate Signing Request for the device:

	```
	$ openssl req -new -key leaf_private_key.pem -out leaf.csr
	```
	> You can keep all parameters at defaults (by pressing enter) excpet Common Name (CN). **Give the name which was registered in IoT Hub ([Device ID](#creating-a-device)) as the CN.**

	- Generate device certificate (leaf certificate):
	```
	$ openssl x509 -req -in leaf.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out leaf_certificate.pem
	```

### CA Certificate Registration

- Go to previously created IoT Hub and navigate to "Certificates" under "Settings" in menu bar.
- Click on "Add".
- Give a User friendly certificate name and add the `rootCA.pem` which was created in the above steps. Click on "Save".
- Status of this certificate will be "Unverified". To verify this click on the certificate name. Click on `Generate Verification Code` at the bottom under `Certificate Details`. A verification code will be generated, copy it.
- In the terminal, navigate to directory where `rootCA.pem` was created and run following command to generate a certificate signing request:

```
	$ openssl req -new -key rootCA.key -out verification.csr
```
> You can keep all parameters at defaults (by pressing enter) except Common Name (CN). **Give the Verification Code copied in previous step as Common Name.**

- Generate Verification Certificate:

```
$ openssl x509 -req -in verification.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out verification_certificate.pem
```
- Upload this certificate on the Azure Portal under `Certificate Details`.

### Device Provisioning Service

- In the upper left-hand corner of the Azure portal, click Create a resource.
- In the Search box, type "device provisioning" and select `IoT Hub Device Provisioning Service` from the suggestions.
- Fill out the IoT Hub Device Provisioning Service form and click "Create" at the bottom.
- Select this newly created resource, select `Linked IoT hubs` under `Settings` and click on `Add`.
- In the Add link to IoT hub page
	- IoT hub: Select the IoT hub that you want to link with this Device Provisioning Service instance.
   - Access Policy: Select `iothubowner`.
- Go to `Manage Enrollments` under `Settings` and click on `Add individual enrollment`.
- Select Mechanism as "X.509".
- Upload device certificate created earlier (`leaf_certificate.pem`) in place of "Primary Certificate". Leave "Secondary Certificate" blank.
- Enter the appropriate IoT Hub Device ID. Mark IoT Edge device as "False".
- Click "Save" at the top.
- Copy device certificate created earlier (`leaf_certificate.pem`) to `main/certs/`.
- Copy private key (`leaf_private_key.pem`) to `main/certs/`.

## Device Configuration

- Execute `make menuconfig`. In the menu, go to `Example Configuration` and configure `WiFi SSID` and `WiFi Password` so that the device can connect to the appropriate Wi-Fi network on boot up.
- Get the IoT Hub connection string using `az iot hub show-connection-string -n <IoT_hub_name>` and paste in `IoT Hub Device Connection String`.

> Note: While changing the value, please ensure that you have completely cleared the older value, before pasting the new one. If you face any run time connection issues, double check this value.

- Enter the `Device leaf certificate common name` which was set during [certificate generation](#certificate-generation)
- Copy the ID Scope of the device provisioning service which you can find on the Azure portal under "Overview" section of the service and paste in `ID Scope` field.
- Save and exit `menuconfig`.

> Note

> In case following error occurs:
> `cp: embed_txt/leaf_private_key
> .pem: Permission denied`
> give apt permissions to `leaf_certificate.pem` 

> eg: `$ cd main/certs/ && chmod 644 leaf_certificate.pem` 

## Trying out the example

- Run the following command to flash the example and monitor the output

``` bash
$ make -j8 flash monitor
```

- In a separate window, monitor the Azure IoT events using the following:

```
$ az iot hub monitor-events -n [IoTHub Name] --login '[Connection string - primary key]'
```

- Once the device connects to the Wi-Fi network, it starts publishing MQTT messages. The Azure IoT monitor will show these messages like below:

```
{
    "event": {
        "origin": "<azure-iot-device-id>",
        "payload": "{ \"message_index\" : \"0\" }"
    }
}
{
    "event": {
        "origin": "<azure-iot-device-id>",
        "payload": "{ \"message_index\" : \"1\" }"
    }
}

```


================================================
FILE: examples/prov_dev_client_ll_sample/main/CMakeLists.txt
================================================
set(COMPONENT_SRCS "azure_main.c"
				"custom_hsm_x509.c"
				"prov_dev_client_ll_sample.c"
				)
set(COMPONENT_ADD_INCLUDEDIRS ".")

set(COMPONENT_EMBED_TXTFILES "certs/leaf_certificate.pem"
                             "certs/leaf_private_key.pem"
                             )

register_component()

component_compile_definitions(SET_TRUSTED_CERT_IN_SAMPLES)


================================================
FILE: examples/prov_dev_client_ll_sample/main/Kconfig.projbuild
================================================
menu "Example Configuration"

config WIFI_SSID
    string "WiFi SSID"
	default "myssid"
	help
		SSID (network name) for the example to connect to.

config WIFI_PASSWORD
    string "WiFi Password"
	default "myssid"
	help
		WiFi password (WPA or WPA2) for the example to use.

		Can be left blank if the network has no security set.

config IOTHUB_CONNECTION_STRING
    string "IOT Hub Connection String"
	default ""
	help
		The IoT Hub Connection string - primary key in the format
		"HostName=<hostname>;SharedAccessKeyName=<shared_access_key_name>;SharedAccessKey=<shared_access_key>."
		You can get this from the Azure IoT CLI or the Azure Portal.

config DEVICE_COMMON_NAME
    string "Device Leaf Certificate Common Name"
    default "mydevice"
    help
        Common name of Leaf Certificate

config DPS_ID_SCOPE
    string "ID Scope of Device provisioning service"
    default "myidscope"
    help
        This is the unique ID scope of Device Provisioning Service (DPS), and can be found under "Overview"
        section of your DPS on azure IoT portal

endmenu


================================================
FILE: examples/prov_dev_client_ll_sample/main/azure_main.c
================================================
/* esp-azure example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "esp_system.h"
#include "esp_system.h"
#include "esp_wifi.h"
#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
#include "esp_event_loop.h"
#else
#include "esp_event.h"
#endif
#include "esp_log.h"

#include "nvs_flash.h"

#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group;

#ifndef BIT0
#define BIT0 (0x1 << 0)
#endif
/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
const int CONNECTED_BIT = BIT0;

static const char *TAG = "azure";

#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        /* This is a workaround as ESP platform WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;
    default:
        break;
    }
    return ESP_OK;
}
#else
static void event_handler(void* arg, esp_event_base_t event_base,
                          int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        /* This is a workaround as ESP platform WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
    }
}
#endif

static void initialise_wifi(void)
{
#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
#else
    ESP_ERROR_CHECK( esp_netif_init() );
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_create_default() );
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);
#endif

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_WIFI_SSID,
            .password = EXAMPLE_WIFI_PASS,
        },
    };
    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);

#ifdef CONFIG_IDF_TARGET_ESP8266 || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0))
#else
    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
#endif

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}

extern int prov_dev_client_ll_sample_run();
void azure_task(void *pvParameter)
{
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                        false, true, portMAX_DELAY);
    ESP_LOGI(TAG, "Connected to AP success!");

    prov_dev_client_ll_sample_run();

    vTaskDelete(NULL);
}

void app_main()
{
    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret );

    initialise_wifi();

    if ( xTaskCreate(&azure_task, "azure_task", 1024 * 5, NULL, 5, NULL) != pdPASS ) {
        printf("create azure task failed\r\n");
    }
}


================================================
FILE: examples/prov_dev_client_ll_sample/main/certs/.dummy
================================================


================================================
FILE: examples/prov_dev_client_ll_sample/main/component.mk
================================================
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the 
# src/ directory, compile them and link them into lib(subdirectory_name).a 
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#
COMPONENT_EMBED_TXTFILES := certs/leaf_private_key.pem certs/leaf_certificate.pem

ifndef IDF_CI_BUILD
# Print an error if the certificate/key files are missing
$(COMPONENT_PATH)/certs/leaf_private_key.pem $(COMPONENT_PATH)/certs/leaf_certificate.pem:
	@echo "Missing PEM file $@. This file identifies the ESP32 to Azure DPS for the example, see README for details."
	exit 1
else  # IDF_CI_BUILD
# this case is for the internal Continuous Integration build which
# compiles all examples. Add some dummy certs so the example can
# compile (even though it won't work)
$(COMPONENT_PATH)/certs/leaf_private_key.pem $(COMPONENT_PATH)/certs/leaf_certificate.pem:
	echo "Dummy certificate data for continuous integration" > $@
endif

CFLAGS += -DSET_TRUSTED_CERT_IN_SAMPLES


================================================
FILE: examples/prov_dev_client_ll_sample/main/custom_hsm_x509.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sdkconfig.h>
#include "hsm_client_data.h"

static const char* const COMMON_NAME = CONFIG_DEVICE_COMMON_NAME;

extern const uint8_t leaf_cert_pem_start[] asm("_binary_leaf_certificate_pem_start");
extern const uint8_t leaf_pv_key_pem_start[] asm("_binary_leaf_private_key_pem_start");

// This sample is provided for sample only.  Please do not use this in production
// For more information please see the devdoc using_custom_hsm.md
static const char* const CERTIFICATE = (char *)leaf_cert_pem_start;
static const char* const PRIVATE_KEY = (char *)leaf_pv_key_pem_start;

// Provided for sample only
static const char* const SYMMETRIC_KEY = "Symmetric Key value";
static const char* const REGISTRATION_NAME = "Registration Name";

// Provided for sample only, canned values
static const unsigned char EK[] = { 0x45, 0x6e, 0x64, 0x6f, 0x72, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x0d, 0x0a };
static const size_t EK_LEN = sizeof(EK)/sizeof(EK[0]);
static const unsigned char SRK[] = { 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x0d, 0x0a };
static const size_t SRK_LEN = sizeof(SRK) / sizeof(SRK[0]);

typedef struct CUSTOM_HSM_SAMPLE_INFO_TAG
{
    const char* certificate;
    const char* common_name;
    const char* key;
    const unsigned char* endorsment_key;
    size_t ek_length;
    const unsigned char* storage_root_key;
    size_t srk_len;
    const char* symm_key;
    const char* registration_name;
} CUSTOM_HSM_SAMPLE_INFO;

int hsm_client_x509_init()
{
    return 0;
}

void hsm_client_x509_deinit()
{
}


HSM_CLIENT_HANDLE custom_hsm_create()
{
    HSM_CLIENT_HANDLE result;
    CUSTOM_HSM_SAMPLE_INFO* hsm_info = malloc(sizeof(CUSTOM_HSM_SAMPLE_INFO));
    if (hsm_info == NULL)
    {
        (void)printf("Failued allocating hsm info\r\n");
        result = NULL;
    }
    else
    {
        // TODO: initialize any variables here
        hsm_info->certificate = CERTIFICATE;
        hsm_info->key = PRIVATE_KEY;
        hsm_info->common_name = COMMON_NAME;
        hsm_info->endorsment_key = EK;
        hsm_info->ek_length = EK_LEN;
        hsm_info->storage_root_key = SRK;
        hsm_info->srk_len = SRK_LEN;
        hsm_info->symm_key = SYMMETRIC_KEY;
        hsm_info->registration_name = REGISTRATION_NAME;
        result = hsm_info;
    }
    return result;
}

void custom_hsm_destroy(HSM_CLIENT_HANDLE handle)
{
    if (handle != NULL)
    {
        CUSTOM_HSM_SAMPLE_INFO* hsm_info = (CUSTOM_HSM_SAMPLE_INFO*)handle;
        // Free anything that has been allocated in this module
        free(hsm_info);
    }
}

char* custom_hsm_get_certificate(HSM_CLIENT_HANDLE handle)
{
    char* result;
    if (handle == NULL)
    {
        (void)printf("Invalid handle value specified\r\n");
        result = NULL;
    }
    else
    {
        // TODO: Malloc the certificate for the iothub sdk to free
        // this value will be sent unmodified to the tlsio
        // layer to be processed
        CUSTOM_HSM_SAMPLE_INFO* hsm_info = (CUSTOM_HSM_SAMPLE_INFO*)handle;
        size_t len = strlen(hsm_info->certificate);
        if ((result = (char*)malloc(len + 1)) == NULL)
        {
            (void)printf("Failure allocating certificate\r\n");
            result = NULL;
        }
        else
        {
            strcpy(result, hsm_info->certificate);
        }
    }
    return result;
}

char* custom_hsm_get_key(HSM_CLIENT_HANDLE handle)
{
    char* result;
    if (handle == NULL)
    {
        (void)printf("Invalid handle value specified\r\n");
        result = NULL;
    }
    else
    {
        // TODO: Malloc the private key for the iothub sdk to free
        // this value will be sent unmodified to the tlsio
        // layer to be processed
        CUSTOM_HSM_SAMPLE_INFO* hsm_info = (CUSTOM_HSM_SAMPLE_INFO*)handle;
        size_t len = strlen(hsm_info->key);
        if ((result = (char*)malloc(len + 1)) == NULL)
        {
            (void)printf("Failure allocating certificate\r\n");
            result = NULL;
        }
        else
        {
            strcpy(result, hsm_info->key);
        }
    }
    return result;
}

char* custom_hsm_get_common_name(HSM_CLIENT_HANDLE handle)
{
    char* result;
    if (handle == NULL)
    {
        (void)printf("Invalid handle value specified\r\n");
        result = NULL;
    }
    else
    {
        // TODO: Malloc the common name for the iothub sdk to free
        // this value will be sent to dps
        CUSTOM_HSM_SAMPLE_INFO* hsm_info = (CUSTOM_HSM_SAMPLE_INFO*)handle;
        size_t len = strlen(hsm_info->common_name);
        if ((result = (char*)malloc(len + 1)) == NULL)
        {
            (void)printf("Failure allocating certificate\r\n");
            result = NULL;
        }
        else
        {
            strcpy(result, hsm_info->common_name);
        }
    }
    return result;
}

// Defining the v-table for the x509 hsm calls
static const HSM_CLIENT_X509_INTERFACE x509_interface =
{
    custom_hsm_create,
    custom_hsm_destroy,
    custom_hsm_get_certificate,
    custom_hsm_get_key,
    custom_hsm_get_common_name
};

const HSM_CLIENT_X509_INTERFACE* hsm_client_x509_interface()
{
    // x509 interface pointer
    return &x509_interface;
}


================================================
FILE: examples/prov_dev_client_ll_sample/main/prov_dev_client_ll_sample.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// CAVEAT: This sample is to demonstrate azure IoT client concepts only and is not a guide design principles or style
// Checking of return codes and error values shall be omitted for brevity.  Please practice sound engineering practices
// when writing production code.
#include <stdio.h>
#include <stdlib.h>

#include "iothub.h"
#include "iothub_message.h"
#include "iothub_client_version.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/tickcounter.h"
#include "azure_c_shared_utility/shared_util_options.h"
#include "azure_c_shared_utility/http_proxy_io.h"

#include "iothub_device_client_ll.h"
#include "iothub_client_options.h"
#include "azure_prov_client/prov_device_ll_client.h"
#include "azure_prov_client/prov_security_factory.h"
#include "sdkconfig.h"
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
#include "certs.h"
#endif // SET_TRUSTED_CERT_IN_SAMPLES

//
// The protocol you wish to use should be uncommented
//
#define SAMPLE_MQTT
//#define SAMPLE_MQTT_OVER_WEBSOCKETS
//#define SAMPLE_AMQP
//#define SAMPLE_AMQP_OVER_WEBSOCKETS
//#define SAMPLE_HTTP

#ifdef SAMPLE_MQTT
#include "iothubtransportmqtt.h"
#include "azure_prov_client/prov_transport_mqtt_client.h"
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
#include "iothubtransportmqtt_websockets.h"
#include "azure_prov_client/prov_transport_mqtt_ws_client.h"
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
#include "iothubtransportamqp.h"
#include "azure_prov_client/prov_transport_amqp_client.h"
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
#include "iothubtransportamqp_websockets.h"
#include "azure_prov_client/prov_transport_amqp_ws_client.h"
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
#include "iothubtransportmqtt.h"
#include "azure_prov_client/prov_transport_http_client.h"
#endif // SAMPLE_HTTP

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
#include "certs.h"
#endif // SET_TRUSTED_CERT_IN_SAMPLES

// This sample is to demostrate iothub reconnection with provisioning and should not
// be confused as production code

MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(PROV_DEVICE_RESULT, PROV_DEVICE_RESULT_VALUE);
MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(PROV_DEVICE_REG_STATUS, PROV_DEVICE_REG_STATUS_VALUES);

static const char* global_prov_uri = "global.azure-devices-provisioning.net";
static const char* id_scope = CONFIG_DPS_ID_SCOPE;

static bool g_use_proxy = false;
static const char* PROXY_ADDRESS = "127.0.0.1";

#define PROXY_PORT                  8888
#define MESSAGES_TO_SEND            2
#define TIME_BETWEEN_MESSAGES       2

typedef struct CLIENT_SAMPLE_INFO_TAG
{
    unsigned int sleep_time;
    char* iothub_uri;
    char* access_key_name;
    char* device_key;
    char* device_id;
    int registration_complete;
} CLIENT_SAMPLE_INFO;

typedef struct IOTHUB_CLIENT_SAMPLE_INFO_TAG
{
    int connected;
    int stop_running;
} IOTHUB_CLIENT_SAMPLE_INFO;

static IOTHUBMESSAGE_DISPOSITION_RESULT receive_msg_callback(IOTHUB_MESSAGE_HANDLE message, void* user_context)
{
    (void)message;
    IOTHUB_CLIENT_SAMPLE_INFO* iothub_info = (IOTHUB_CLIENT_SAMPLE_INFO*)user_context;
    (void)printf("Stop message recieved from IoTHub\r\n");
    iothub_info->stop_running = 1;
    return IOTHUBMESSAGE_ACCEPTED;
}

static void registration_status_callback(PROV_DEVICE_REG_STATUS reg_status, void* user_context)
{
    (void)user_context;
    (void)printf("Provisioning Status: %s\r\n", MU_ENUM_TO_STRING(PROV_DEVICE_REG_STATUS, reg_status));
}

static void iothub_connection_status(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* user_context)
{
    (void)reason;
    if (user_context == NULL)
    {
        printf("iothub_connection_status user_context is NULL\r\n");
    }
    else
    {
        IOTHUB_CLIENT_SAMPLE_INFO* iothub_info = (IOTHUB_CLIENT_SAMPLE_INFO*)user_context;
        if (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED)
        {
            iothub_info->connected = 1;
        }
        else
        {
            iothub_info->connected = 0;
            iothub_info->stop_running = 1;
        }
    }
}

static void register_device_callback(PROV_DEVICE_RESULT register_result, const char* iothub_uri, const char* device_id, void* user_context)
{
    if (user_context == NULL)
    {
        printf("user_context is NULL\r\n");
    }
    else
    {
        CLIENT_SAMPLE_INFO* user_ctx = (CLIENT_SAMPLE_INFO*)user_context;
        if (register_result == PROV_DEVICE_RESULT_OK)
        {
            (void)printf("Registration Information received from service: %s!\r\n", iothub_uri);
            (void)mallocAndStrcpy_s(&user_ctx->iothub_uri, iothub_uri);
            (void)mallocAndStrcpy_s(&user_ctx->device_id, device_id);
            user_ctx->registration_complete = 1;
        }
        else
        {
            (void)printf("Failure encountered on registration %s\r\n", MU_ENUM_TO_STRING(PROV_DEVICE_RESULT, register_result) );
            user_ctx->registration_complete = 2;
        }
    }
}

const IO_INTERFACE_DESCRIPTION* socketio_get_interface_description(void)
{
    return NULL;
}

int prov_dev_client_ll_sample_run()
{
    SECURE_DEVICE_TYPE hsm_type;
    //hsm_type = SECURE_DEVICE_TYPE_TPM;
    hsm_type = SECURE_DEVICE_TYPE_X509;
    //hsm_type = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;

    bool traceOn = false;

    (void)IoTHub_Init();
    (void)prov_dev_security_init(hsm_type);
    // Set the symmetric key if using they auth type
    //prov_dev_set_symmetric_key_info("<symm_registration_id>", "<symmetric_Key>");

    PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION prov_transport;
    HTTP_PROXY_OPTIONS http_proxy;
    CLIENT_SAMPLE_INFO user_ctx;

    memset(&http_proxy, 0, sizeof(HTTP_PROXY_OPTIONS));
    memset(&user_ctx, 0, sizeof(CLIENT_SAMPLE_INFO));

    // Protocol to USE - HTTP, AMQP, AMQP_WS, MQTT, MQTT_WS
#ifdef SAMPLE_MQTT
    prov_transport = Prov_Device_MQTT_Protocol;
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
    prov_transport = Prov_Device_MQTT_WS_Protocol;
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
    prov_transport = Prov_Device_AMQP_Protocol;
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
    prov_transport = Prov_Device_AMQP_WS_Protocol;
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
    prov_transport = Prov_Device_HTTP_Protocol;
#endif // SAMPLE_HTTP

    // Set ini
    user_ctx.registration_complete = 0;
    user_ctx.sleep_time = 10;

    printf("Provisioning API Version: %s\r\n", Prov_Device_LL_GetVersionString());
    printf("Iothub API Version: %s\r\n", IoTHubClient_GetVersionString());

    if (g_use_proxy)
    {
        http_proxy.host_address = PROXY_ADDRESS;
        http_proxy.port = PROXY_PORT;
    }

    PROV_DEVICE_LL_HANDLE handle;
    if ((handle = Prov_Device_LL_Create(global_prov_uri, id_scope, prov_transport)) == NULL)
    {
        (void)printf("failed calling Prov_Device_LL_Create\r\n");
    }
    else
    {
        if (http_proxy.host_address != NULL)
        {
            Prov_Device_LL_SetOption(handle, OPTION_HTTP_PROXY, &http_proxy);
        }

        Prov_Device_LL_SetOption(handle, PROV_OPTION_LOG_TRACE, &traceOn);
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
        // Setting the Trusted Certificate.  This is only necessary on system with without
        // built in certificate stores.
        Prov_Device_LL_SetOption(handle, OPTION_TRUSTED_CERT, certificates);
#endif // SET_TRUSTED_CERT_IN_SAMPLES

        // This option sets the registration ID it overrides the registration ID that is 
        // set within the HSM so be cautious if setting this value
        //Prov_Device_SetOption(prov_device_handle, PROV_REGISTRATION_ID, "[REGISTRATION ID]");

        if (Prov_Device_LL_Register_Device(handle, register_device_callback, &user_ctx, registration_status_callback, &user_ctx) != PROV_DEVICE_RESULT_OK)
        {
            (void)printf("failed calling Prov_Device_LL_Register_Device\r\n");
        }
        else
        {
            do
            {
                Prov_Device_LL_DoWork(handle);
                ThreadAPI_Sleep(user_ctx.sleep_time);
            } while (user_ctx.registration_complete == 0);
        }
        Prov_Device_LL_Destroy(handle);
    }

    if (user_ctx.registration_complete != 1)
    {
        (void)printf("registration failed!\r\n");
    }
    else
    {
        IOTHUB_CLIENT_TRANSPORT_PROVIDER iothub_transport;

        // Protocol to USE - HTTP, AMQP, AMQP_WS, MQTT, MQTT_WS
#if defined(SAMPLE_MQTT) || defined(SAMPLE_HTTP) // HTTP sample will use mqtt protocol
        iothub_transport = MQTT_Protocol;
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
        iothub_transport = MQTT_WebSocket_Protocol;
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
        iothub_transport = AMQP_Protocol;
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
        iothub_transport = AMQP_Protocol_over_WebSocketsTls;
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS

        IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle;

        (void)printf("Creating IoTHub Device handle\r\n");
        if ((device_ll_handle = IoTHubDeviceClient_LL_CreateFromDeviceAuth(user_ctx.iothub_uri, user_ctx.device_id, iothub_transport) ) == NULL)
        {
            (void)printf("failed create IoTHub client from connection string %s!\r\n", user_ctx.iothub_uri);
        }
        else
        {
            IOTHUB_CLIENT_SAMPLE_INFO iothub_info;
            TICK_COUNTER_HANDLE tick_counter_handle = tickcounter_create();
            tickcounter_ms_t current_tick;
            tickcounter_ms_t last_send_time = 0;
            size_t msg_count = 0;
            iothub_info.stop_running = 0;
            iothub_info.connected = 0;

            (void)IoTHubDeviceClient_LL_SetConnectionStatusCallback(device_ll_handle, iothub_connection_status, &iothub_info);

            // Set any option that are neccessary.
            // For available options please see the iothub_sdk_options.md documentation

            IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_LOG_TRACE, &traceOn);

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
            // Setting the Trusted Certificate.  This is only necessary on system with without
            // built in certificate stores.
            IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_TRUSTED_CERT, certificates);
#endif // SET_TRUSTED_CERT_IN_SAMPLES

            (void)IoTHubDeviceClient_LL_SetMessageCallback(device_ll_handle, receive_msg_callback, &iothub_info);

            (void)printf("Sending 1 messages to IoTHub every %d seconds for %d messages (Send any message to stop)\r\n", TIME_BETWEEN_MESSAGES, MESSAGES_TO_SEND);
            do
            {
                if (iothub_info.connected != 0)
                {
                    // Send a message every TIME_BETWEEN_MESSAGES seconds
                    (void)tickcounter_get_current_ms(tick_counter_handle, &current_tick);
                    if ((current_tick - last_send_time) / 1000 > TIME_BETWEEN_MESSAGES)
                    {
                        static char msgText[1024];
                        sprintf_s(msgText, sizeof(msgText), "{ \"message_index\" : \"%zu\" }", msg_count++);

                        IOTHUB_MESSAGE_HANDLE msg_handle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, strlen(msgText));
                        if (msg_handle == NULL)
                        {
                            (void)printf("ERROR: iotHubMessageHandle is NULL!\r\n");
                        }
                        else
                        {
                            if (IoTHubDeviceClient_LL_SendEventAsync(device_ll_handle, msg_handle, NULL, NULL) != IOTHUB_CLIENT_OK)
                            {
                                (void)printf("ERROR: IoTHubClient_LL_SendEventAsync..........FAILED!\r\n");
                            }
                            else
                            {
                                (void)tickcounter_get_current_ms(tick_counter_handle, &last_send_time);
                                (void)printf("IoTHubClient_LL_SendEventAsync accepted message [%zu] for transmission to IoT Hub.\r\n", msg_count);

                            }
                            IoTHubMessage_Destroy(msg_handle);
                        }
                    }
                }
                IoTHubDeviceClient_LL_DoWork(device_ll_handle);
                ThreadAPI_Sleep(1);
            } while (iothub_info.stop_running == 0 && msg_count < MESSAGES_TO_SEND);

            size_t index = 0;
            for (index = 0; index < 10; index++)
            {
                IoTHubDeviceClient_LL_DoWork(device_ll_handle);
                ThreadAPI_Sleep(1);
            }
            tickcounter_destroy(tick_counter_handle);
            // Clean up the iothub sdk handle
            IoTHubDeviceClient_LL_Destroy(device_ll_handle);
        }
    }
    free(user_ctx.iothub_uri);
    free(user_ctx.device_id);
    prov_dev_security_deinit();

    // Free all the sdk subsystem
    IoTHub_Deinit();

    (void)getchar();

    return 0;
}


================================================
FILE: examples/prov_dev_client_ll_sample/sdkconfig.defaults
================================================
# newlib for ESP32 and ESP8266 platform

CONFIG_NEWLIB_ENABLE=y
CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y
CONFIG_NEWLIB_NANO_FORMAT=
CONFIG_SSL_USING_MBEDTLS=y
CONFIG_LWIP_IPV6=y



================================================
FILE: port/CMakeLists.txt
================================================
#
# Component Makefile
#

set (AZURE_IOT_SDK "${CMAKE_CURRENT_LIST_DIR}/../azure-iot-sdk-c")

set (COMPONENT_ADD_INCLUDEDIRS
    "inc"
    "${AZURE_IOT_SDK}/certs"
	"${AZURE_IOT_SDK}/c-utility/inc"
	"${AZURE_IOT_SDK}/c-utility/deps/azure-macro-utils-c/inc"
	"${AZURE_IOT_SDK}/c-utility/deps/umock-c/inc"
	"${AZURE_IOT_SDK}/c-utility/pal/inc"
	"${AZURE_IOT_SDK}/c-utility/pal/freertos"
	"${AZURE_IOT_SDK}/c-utility/pal/generic"
	"${AZURE_IOT_SDK}/iothub_client/inc"
	"${AZURE_IOT_SDK}/serializer/inc"
	"${AZURE_IOT_SDK}/umqtt/inc"
	"${AZURE_IOT_SDK}/umqtt/inc/azure_umqtt_c"
	"${AZURE_IOT_SDK}/deps/parson"
	"${AZURE_IOT_SDK}/provisioning_client/inc"
	"${AZURE_IOT_SDK}/provisioning_client/adapters"
	"${AZURE_IOT_SDK}/provisioning_client/deps/utpm/inc"
	)

set (COMPONENT_SRCS
	"src/agenttime_esp.c"
	"src/platform_esp.c"
	"src/tlsio_esp_tls.c"
	"${AZURE_IOT_SDK}/certs/certs.c"
	"${AZURE_IOT_SDK}/c-utility/pal/freertos/lock.c"
	"${AZURE_IOT_SDK}/c-utility/pal/socket_async.c"
	"${AZURE_IOT_SDK}/c-utility/pal/freertos/threadapi.c"
	"${AZURE_IOT_SDK}/c-utility/pal/freertos/tickcounter.c"
	"${AZURE_IOT_SDK}/c-utility/pal/tlsio_options.c"
	"${AZURE_IOT_SDK}/c-utility/src/xlogging.c"
	"${AZURE_IOT_SDK}/c-utility/src/singlylinkedlist.c"
	"${AZURE_IOT_SDK}/c-utility/src/buffer.c"
	"${AZURE_IOT_SDK}/c-utility/src/consolelogger.c"
	"${AZURE_IOT_SDK}/c-utility/src/constbuffer.c"
	"${AZURE_IOT_SDK}/c-utility/src/constmap.c"
	"${AZURE_IOT_SDK}/c-utility/src/crt_abstractions.c"
	"${AZURE_IOT_SDK}/c-utility/src/doublylinkedlist.c"
	"${AZURE_IOT_SDK}/c-utility/src/gballoc.c"
	"${AZURE_IOT_SDK}/c-utility/src/gb_stdio.c"
	"${AZURE_IOT_SDK}/c-utility/src/gb_time.c"
	"${AZURE_IOT_SDK}/c-utility/src/hmac.c"
	"${AZURE_IOT_SDK}/c-utility/src/hmacsha256.c"
	"${AZURE_IOT_SDK}/c-utility/src/httpapiex.c"
	"${AZURE_IOT_SDK}/c-utility/src/httpapiexsas.c"
	"${AZURE_IOT_SDK}/c-utility/src/httpheaders.c"
	"${AZURE_IOT_SDK}/c-utility/src/map.c"
	"${AZURE_IOT_SDK}/c-utility/src/optionhandler.c"
	"${AZURE_IOT_SDK}/c-utility/src/sastoken.c"
	"${AZURE_IOT_SDK}/c-utility/src/sha1.c"
	"${AZURE_IOT_SDK}/c-utility/src/sha224.c"
	"${AZURE_IOT_SDK}/c-utility/src/sha384-512.c"
	"${AZURE_IOT_SDK}/c-utility/src/strings.c"
	"${AZURE_IOT_SDK}/c-utility/src/string_tokenizer.c"
	"${AZURE_IOT_SDK}/c-utility/src/urlencode.c"
	"${AZURE_IOT_SDK}/c-utility/src/usha.c"
	"${AZURE_IOT_SDK}/c-utility/src/vector.c"
	"${AZURE_IOT_SDK}/c-utility/src/xio.c"
	"${AZURE_IOT_SDK}/c-utility/src/azure_base64.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_device_client_ll.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_client_ll.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_client_core_ll.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_client_ll_uploadtoblob.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_client_authorization.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_client_retry_control.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_client_diagnostic.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_message.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothubtransport.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothubtransportmqtt.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothubtransport_mqtt_common.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub_transport_ll_private.c"
	"${AZURE_IOT_SDK}/iothub_client/src/version.c"
	"${AZURE_IOT_SDK}/umqtt/src/mqtt_client.c"
	"${AZURE_IOT_SDK}/umqtt/src/mqtt_codec.c"
	"${AZURE_IOT_SDK}/umqtt/src/mqtt_message.c"
	"${AZURE_IOT_SDK}/deps/parson/parson.c"
	"${AZURE_IOT_SDK}/serializer/src/codefirst.c"
	"${AZURE_IOT_SDK}/serializer/src/agenttypesystem.c"
	"${AZURE_IOT_SDK}/serializer/src/commanddecoder.c"
	"${AZURE_IOT_SDK}/serializer/src/datamarshaller.c"
	"${AZURE_IOT_SDK}/serializer/src/datapublisher.c"
	"${AZURE_IOT_SDK}/serializer/src/dataserializer.c"
	"${AZURE_IOT_SDK}/serializer/src/iotdevice.c"
	"${AZURE_IOT_SDK}/serializer/src/jsondecoder.c"
	"${AZURE_IOT_SDK}/serializer/src/jsonencoder.c"
	"${AZURE_IOT_SDK}/serializer/src/methodreturn.c"
	"${AZURE_IOT_SDK}/serializer/src/multitree.c"
	"${AZURE_IOT_SDK}/serializer/src/schema.c"
	"${AZURE_IOT_SDK}/serializer/src/schemalib.c"
	"${AZURE_IOT_SDK}/serializer/src/schemaserializer.c"
	"${AZURE_IOT_SDK}/provisioning_client/src/prov_device_client.c"
	"${AZURE_IOT_SDK}/provisioning_client/src/prov_transport_mqtt_client.c"
	"${AZURE_IOT_SDK}/provisioning_client/src/prov_transport_mqtt_common.c"
	"${AZURE_IOT_SDK}/provisioning_client/src/prov_security_factory.c"
	"${AZURE_IOT_SDK}/provisioning_client/src/prov_device_ll_client.c"
	"${AZURE_IOT_SDK}/provisioning_client/src/iothub_security_factory.c"
	"${AZURE_IOT_SDK}/provisioning_client/adapters/hsm_client_data.c"
	"${AZURE_IOT_SDK}/provisioning_client/adapters/hsm_client_tpm.c"
	"${AZURE_IOT_SDK}/provisioning_client/src/prov_auth_client.c"
	"${AZURE_IOT_SDK}/provisioning_client/deps/utpm/src/tpm_codec.c"
	"${AZURE_IOT_SDK}/provisioning_client/deps/utpm/src/Marshal.c"
	"${AZURE_IOT_SDK}/provisioning_client/deps/utpm/src/tpm_comm_emulator.c"
	"${AZURE_IOT_SDK}/provisioning_client/deps/utpm/src/Memory.c"
	"${AZURE_IOT_SDK}/provisioning_client/deps/utpm/src/tpm_socket_comm.c"
	"${AZURE_IOT_SDK}/iothub_client/src/iothub.c"
	"${AZURE_IOT_SDK}/c-utility/src/http_proxy_io.c"
	"${AZURE_IOT_SDK}/c-utility/src/azure_base32.c"
	)

if (CONFIG_DEVICE_COMMON_NAME)
	list (APPEND COMPONENT_SRCS "${AZURE_IOT_SDK}/provisioning_client/src/iothub_auth_client.c")
endif()

set (COMPONENT_SUBMODULES "${AZURE_IOT_SDK}")

set(COMPONENT_PRIV_REQUIRES "mbedtls esp-tls main")

register_component()

set_source_files_properties(
    ${AZURE_IOT_SDK}/iothub_client/src/iothubtransport_mqtt_common.c
    PROPERTIES COMPILE_FLAGS
    -Wno-maybe-uninitialized)

component_compile_options (
	-Wno-unused-function
	-Wno-missing-braces
	-Wno-missing-field-initializers
	-Wno-unknown-pragmas
	)

component_compile_definitions (
    USE_LWIP_SOCKET_FOR_AZURE_IOT
	HSM_TYPE_X509
	HSM_TYPE_SAS_TOKEN
)

if (CONFIG_DEVICE_COMMON_NAME)
	add_definitions(-DUSE_PROV_MODULE)
endif()


================================================
FILE: port/inc/certs.h
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef CERTS_H
#define CERTS_H

#ifdef __cplusplus
extern "C"
{
#endif

    extern const char certificates[];

#ifdef __cplusplus
}
#endif

#endif /* CERTS_H */


================================================
FILE: port/inc/sntp_os.h
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

//This file pulls in OS-specific header files to allow compilation of socket_async.c under
// most OS's except for Windows.

// For ESP platform lwIP systems which use the ESP-IDF's non-standard lwIP include structure
// Tested with:
// ESP platform

#ifndef LWIP_SNTP_OS_H
#define LWIP_SNTP_OS_H

#include "apps/sntp/sntp.h"

#endif // LWIP_SNTP_OS_H


================================================
FILE: port/inc/socket_async_os.h
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

//This file pulls in OS-specific header files to allow compilation of socket_async.c under
// most OS's except for Windows.

// For lwIP systems
// Tested with:
// ESP platform

#ifndef SOCKET_ASYNC_OS_H
#define SOCKET_ASYNC_OS_H

#include "sdkconfig.h"
#include <sys/socket.h>
#include <netdb.h>

#endif // SOCKET_ASYNC_OS_H


================================================
FILE: port/inc/tlsio_pal.h
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef TLSIO_PAL_H
#define TLSIO_PAL_H

#include "azure_c_shared_utility/tlsio.h"
#include "umock_c/umock_c_prod.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, tlsio_pal_get_interface_description);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* TLSIO_PAL_H */


================================================
FILE: port/src/agenttime_esp.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "lwip/apps/sntp.h"

#include "azure_c_shared_utility/agenttime.h"
#include "azure_c_shared_utility/xlogging.h"

void initialize_sntp(void)
{
    printf("Initializing SNTP\n");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_init();
}

static void obtain_time(void)
{
    // wait for time to be set
    time_t now = 0;
    struct tm timeinfo = { 0 };
    int retry = 0;

    while(timeinfo.tm_year < (2016 - 1900) ) {
        printf("Waiting for system time to be set... tm_year:%d[times:%d]\n", timeinfo.tm_year, ++retry);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        time(&now);
        localtime_r(&now, &timeinfo);
    }
}

time_t sntp_get_current_timestamp()
{
    time_t now;
	struct tm timeinfo;
	time(&now);
	localtime_r(&now, &timeinfo);
	// Is time set? If not, tm_year will be (1970 - 1900).
	if (timeinfo.tm_year < (2016 - 1900)) {
		printf("Time is not set yet. Connecting to WiFi and getting time over NTP. timeinfo.tm_year:%d\n",timeinfo.tm_year);
		obtain_time();
		// update 'now' variable with current time
		time(&now);
	}
	localtime_r(&now, &timeinfo);
	return now;
}

time_t get_time(time_t* currentTime)
{
    return sntp_get_current_timestamp();

}

double get_difftime(time_t stopTime, time_t startTime)
{
    return (double)stopTime - (double)startTime;
}

struct tm* get_gmtime(time_t* currentTime)
{
    return NULL;
}

char* get_ctime(time_t* timeToGet)
{
    return NULL;
}


================================================
FILE: port/src/certs.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

/* This file contains minimalistic cert needed to communicate with Azure (IoT) */
/* The cert from this file is used in case of azure connection on esp8266 */

#include "certs.h"

const char certificates[] =
/* DigiCert Baltimore Root */
"-----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";


================================================
FILE: port/src/platform_esp.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdlib.h>
#ifdef _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#include "azure_c_shared_utility/platform.h"
#include "azure_c_shared_utility/xio.h"
#include "azure_c_shared_utility/tlsio_openssl.h"
#include "azure_c_shared_utility/xlogging.h"
#include "esp_log.h"
#include "tlsio_pal.h"

#include "lwip/apps/sntp.h"

static const char* TAG = "platform";

time_t sntp_get_current_timestamp();
void initialize_sntp(void);

int platform_init(void)
{
    initialize_sntp();
    printf("ESP platform sntp inited!\n");
    time_t now = sntp_get_current_timestamp();

    char strftime_buf[64];
    struct tm timeinfo;

    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time is: %s", strftime_buf);

    return 0;
}

const IO_INTERFACE_DESCRIPTION* platform_get_default_tlsio(void)
{
    return tlsio_pal_get_interface_description();
    return NULL;
}

void platform_deinit(void)
{
      sntp_stop();
}

STRING_HANDLE platform_get_platform_info(PLATFORM_INFO_OPTION options)
{
    // Expected format: "(<runtime name>; <operating system name>; <platform>)"

    return STRING_construct("(native; freertos; esp platform)");
}


================================================
FILE: port/src/tlsio_esp_tls.c
================================================
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// This component was written to conform to the tlsio_requirements.md specification located
// in the Azure IoT C Utility: 
// https://github.com/Azure/azure-c-shared-utility/blob/master/devdoc/tlsio_requirements.md
// Comments throughout this code refer to requirements in that spec.

#include <stdlib.h>

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "tlsio_pal.h"
#include "azure_c_shared_utility/optimize_size.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/agenttime.h"
#include "azure_c_shared_utility/singlylinkedlist.h"
#include "azure_c_shared_utility/crt_abstractions.h"
#include "azure_c_shared_utility/tlsio_options.h"

#include "esp_tls.h"

typedef struct
{
    unsigned char* bytes;
    size_t size;
    size_t unsent_size;
    ON_SEND_COMPLETE on_send_complete;
    void* callback_context;
} PENDING_TRANSMISSION;

#define MAX_VALID_PORT 0xffff

// The TLSIO_RECEIVE_BUFFER_SIZE has very little effect on performance, and is kept small
// to minimize memory consumption.
#define TLSIO_RECEIVE_BUFFER_SIZE 64

#define MAX_RCV_COUNT 5

typedef enum TLSIO_STATE_TAG
{
    TLSIO_STATE_CLOSED,
    TLSIO_STATE_INIT,
    TLSIO_STATE_OPEN,
    TLSIO_STATE_ERROR,
} TLSIO_STATE;

bool is_an_opening_state(TLSIO_STATE state)
{
    return state == TLSIO_STATE_INIT;
}

// This structure definition is mirrored in the unit tests, so if you change
typedef struct TLS_IO_INSTANCE_TAG
{
    ON_BYTES_RECEIVED on_bytes_received;
    ON_IO_ERROR on_io_error;
    ON_IO_OPEN_COMPLETE on_open_complete;
    void* on_bytes_received_context;
    void* on_io_error_context;
    void* on_open_complete_context;
    esp_tls_cfg_t esp_tls_cfg;
    esp_tls_t   *esp_tls_handle;
    TLSIO_STATE tlsio_state;
    uint16_t port;
    char* hostname;
    SINGLYLINKEDLIST_HANDLE pending_transmission_list;
    TLSIO_OPTIONS options;
} TLS_IO_INSTANCE;

/* Codes_SRS_TLSIO_30_005: [ The phrase "enter TLSIO_STATE_EXT_ERROR" means the adapter shall call the on_io_error function and pass the on_io_error_context that was supplied in tlsio_open_async. ]*/
static void enter_tlsio_error_state(TLS_IO_INSTANCE* tls_io_instance)
{
    if (tls_io_instance->tlsio_state != TLSIO_STATE_ERROR)
    {
        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
        tls_io_instance->on_io_error(tls_io_instance->on_io_error_context);
    }
}

// Return true if a message was available to remove
static bool process_and_destroy_head_message(TLS_IO_INSTANCE* tls_io_instance, IO_SEND_RESULT send_result)
{
    bool result;
    LIST_ITEM_HANDLE head_pending_io;
    if (send_result == IO_SEND_ERROR)
    {
        /* Codes_SRS_TLSIO_30_095: [ If the send process fails before sending all of the bytes in an enqueued message, the tlsio_dowork shall call the message's on_send_complete along with its associated callback_context and IO_SEND_ERROR. ]*/
        enter_tlsio_error_state(tls_io_instance);
    }
    head_pending_io = singlylinkedlist_get_head_item(tls_io_instance->pending_transmission_list);
    if (head_pending_io != NULL)
    {
        PENDING_TRANSMISSION* head_message = (PENDING_TRANSMISSION*)singlylinkedlist_item_get_value(head_pending_io);
        // Must remove the item from the list before calling the callback because 
        // SRS_TLSIO_30_091: [ If  tlsio_esp_tls_dowork  is able to send all the bytes in an enqueued message, it shall first dequeue the message then call the messages's  on_send_complete  along with its associated  callback_context  and  IO_SEND_OK . ]
        if (singlylinkedlist_remove(tls_io_instance->pending_transmission_list, head_pending_io) != 0)
        {
            // This particular situation is a bizarre and unrecoverable internal error
            /* Codes_SRS_TLSIO_30_094: [ If the send process encounters an internal error or calls on_send_complete with IO_SEND_ERROR due to either failure or timeout, it shall also call on_io_error and pass in the associated on_io_error_context. ]*/
            enter_tlsio_error_state(tls_io_instance);
            LogError("Failed to remove message from list");
        }
        // on_send_complete is checked for NULL during PENDING_TRANSMISSION creation
        /* Codes_SRS_TLSIO_30_095: [ If the send process fails before sending all of the bytes in an enqueued message, the tlsio_dowork shall call the message's on_send_complete along with its associated callback_context and IO_SEND_ERROR. ]*/
        head_message->on_send_complete(head_message->callback_context, send_result);

        free(head_message->bytes);
        free(head_message);
        result = true;
    }
    else
    {
        result = false;
    }
    return result;
}

static void internal_close(TLS_IO_INSTANCE* tls_io_instance)
{
    /* Codes_SRS_TLSIO_30_009: [ The phrase "enter TLSIO_STATE_EXT_CLOSING" means the adapter shall iterate through any unsent messages in the queue and shall delete each message after calling its on_send_complete with the associated callback_context and IO_SEND_CANCELLED. ]*/
    /* Codes_SRS_TLSIO_30_006: [ The phrase "enter TLSIO_STATE_EXT_CLOSED" means the adapter shall forcibly close any existing connections then call the on_io_close_complete function and pass the on_io_close_complete_context that was supplied in tlsio_close_async. ]*/
    /* Codes_SRS_TLSIO_30_051: [ On success, if the underlying TLS does not support asynchronous closing, then the adapter shall enter TLSIO_STATE_EXT_CLOSED immediately after entering TLSIO_STATE_EX_CLOSING. ]*/

    esp_tls_conn_delete(tls_io_instance->esp_tls_handle);
    while (process_and_destroy_head_message(tls_io_instance, IO_SEND_CANCELLED));
    // singlylinkedlist_destroy gets called in the main destroy

    tls_io_instance->on_bytes_received = NULL;
    tls_io_instance->on_io_error = NULL;
    tls_io_instance->on_bytes_received_context = NULL;
    tls_io_instance->on_io_error_context = NULL;
    tls_io_instance->tlsio_state = TLSIO_STATE_CLOSED;
    tls_io_instance->on_open_complete = NULL;
    tls_io_instance->on_open_complete_context = NULL;
}

static void tlsio_esp_tls_destroy(CONCRETE_IO_HANDLE tls_io)
{
    if (tls_io == NULL)
    {
        /* Codes_SRS_TLSIO_30_020: [ If tlsio_handle is NULL, tlsio_destroy shall do nothing. ]*/
        LogError("NULL tlsio");
    }
    else
    {
        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
        if (tls_io_instance->tlsio_state != TLSIO_STATE_CLOSED)
        {
            /* Codes_SRS_TLSIO_30_022: [ If the adapter is in any state other than TLSIO_STATE_EX_CLOSED when tlsio_destroy is called, the adapter shall enter TLSIO_STATE_EX_CLOSING and then enter TLSIO_STATE_EX_CLOSED before completing the destroy process. ]*/
            LogError("tlsio_esp_tls_destroy called while not in TLSIO_STATE_CLOSED.");
            internal_close(tls_io_instance);
        }
        /* Codes_SRS_TLSIO_30_021: [ The tlsio_destroy shall release all allocated resources and then release tlsio_handle. ]*/
        if (tls_io_instance->hostname != NULL)
        {
            free(tls_io_instance->hostname);
        }
        
        tlsio_options_release_resources(&tls_io_instance->options);

        if (tls_io_instance->pending_transmission_list != NULL)
        {
            /* Pending messages were cleared in internal_close */
            singlylinkedlist_destroy(tls_io_instance->pending_transmission_list);
        }
        free(tls_io_instance);
    }
}

/* Codes_SRS_TLSIO_30_010: [ The tlsio_esp_tls_create shall allocate and initialize all necessary resources and return an instance of the tlsio_esp_tls. ]*/
static CONCRETE_IO_HANDLE tlsio_esp_tls_create(void* io_create_parameters)
{
    TLS_IO_INSTANCE* result;

    if (io_create_parameters == NULL)
    {
        /* Codes_SRS_TLSIO_30_013: [ If the io_create_parameters value is NULL, tlsio_create shall log an error and return NULL. ]*/
        LogError("NULL tls_io_config");
        result = NULL;
    }
    else
    {
        /* Codes_SRS_TLSIO_30_012: [ The tlsio_create shall receive the connection configuration as a TLSIO_CONFIG* in io_create_parameters. ]*/
        TLSIO_CONFIG* tls_io_config = (TLSIO_CONFIG*)io_create_parameters;
        if (tls_io_config->hostname == NULL)
        {
            /* Codes_SRS_TLSIO_30_014: [ If the hostname member of io_create_parameters value is NULL, tlsio_create shall log an error and return NULL. ]*/
            LogError("NULL tls_io_config->hostname");
            result = NULL;
        }
        else if (tls_io_config->port < 0 || tls_io_config->port > MAX_VALID_PORT)
        {
            /* Codes_SRS_TLSIO_30_015: [ If the port member of io_create_parameters value is less than 0 or greater than 0xffff, tlsio_esp_tls_create shall log an error and return NULL. ]*/
            LogError("tls_io_config->port out of range");
            result = NULL;
        }
        else
        {
            result = malloc(sizeof(TLS_IO_INSTANCE));
            if (result == NULL)
            {
                /* Codes_SRS_TLSIO_30_011: [ If any resource allocation fails, tlsio_esp_tls_create shall return NULL. ]*/
                LogError("malloc failed");
            }
            else
            {
                int ms_result;
                memset(result, 0, sizeof(TLS_IO_INSTANCE));
                result->port = (uint16_t)tls_io_config->port;
                result->tlsio_state = TLSIO_STATE_CLOSED;
                result->hostname = NULL;

                result->pending_transmission_list = NULL;
                tlsio_options_initialize(&result->options, TLSIO_OPTION_BIT_TRUSTED_CERTS |
                TLSIO_OPTION_BIT_x509_RSA_CERT | TLSIO_OPTION_BIT_x509_ECC_CERT);
                result->esp_tls_handle = calloc(1, sizeof(esp_tls_t));
                if (result->esp_tls_handle == NULL)
                {
                    /* Codes_SRS_TLSIO_30_011: [ If any resource allocation fails, tlsio_create shall return NULL. ]*/
                    LogError("malloc failed");
                    tlsio_esp_tls_destroy(result);
                    result = NULL;
                }

                /* Codes_SRS_TLSIO_30_016: [ tlsio_create shall make a copy of the hostname member of io_create_parameters to allow deletion of hostname immediately after the call. ]*/
                ms_result = mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname);
                if (ms_result != 0)
                {
                    /* Codes_SRS_TLSIO_30_011: [ If any resource allocation fails, tlsio_create shall return NULL. ]*/
                    LogError("malloc failed");
                    tlsio_esp_tls_destroy(result);
                    result = NULL;
                }
                else
                {
                    // Create the message queue
                    result->pending_transmission_list = singlylinkedlist_create();
                    if (result->pending_transmission_list == NULL)
                    {
                        /* Codes_SRS_TLSIO_30_011: [ If any resource allocation fails, tlsio_create shall return NULL. ]*/
                        LogError("Failed singlylinkedlist_create");
                        tlsio_esp_tls_destroy(result);
                        result = NULL;
                    }
                }
            }
        }
    }

    return (CONCRETE_IO_HANDLE)result;
}


static int tlsio_esp_tls_open_async(CONCRETE_IO_HANDLE tls_io,
    ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context,
    ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context,
    ON_IO_ERROR on_io_error, void* on_io_error_context)
{

    int result;
    if (on_io_open_complete == NULL)
    {
        /* Codes_SRS_TLSIO_30_031: [ If the on_io_open_complete parameter is NULL, tlsio_open shall log an error and return FAILURE. ]*/
        LogError("Required parameter on_io_open_complete is NULL");
        result = MU_FAILURE;
    }
    else
    {
        if (tls_io == NULL)
        {
            /* Codes_SRS_TLSIO_30_030: [ If the tlsio_handle parameter is NULL, tlsio_open shall log an error and return FAILURE. ]*/
            result = MU_FAILURE;
            LogError("NULL tlsio");
        }
        else
        {
            if (on_bytes_received == NULL)
            {
                /* Codes_SRS_TLSIO_30_032: [ If the on_bytes_received parameter is NULL, tlsio_open shall log an error and return FAILURE. ]*/
                LogError("Required parameter on_bytes_received is NULL");
                result = MU_FAILURE;
            }
            else
            {
                if (on_io_error == NULL)
                {
                    /* Codes_SRS_TLSIO_30_033: [ If the on_io_error parameter is NULL, tlsio_open shall log an error and return FAILURE. ]*/
                    LogError("Required parameter on_io_error is NULL");
                    result = MU_FAILURE;
                }
                else
                {
                    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;

                    if (tls_io_instance->tlsio_state != TLSIO_STATE_CLOSED)
                    {
                        /* Codes_SRS_TLSIO_30_037: [ If the adapter is in any state other than TLSIO_STATE_EXT_CLOSED when tlsio_open  is called, it shall log an error, and return FAILURE. ]*/
                        LogError("Invalid tlsio_state. Expected state is TLSIO_STATE_CLOSED.");
                        result = MU_FAILURE;
                    }
                    else
                    {

                        /* Codes_SRS_TLSIO_30_034: [ The tlsio_open shall store the provided on_bytes_received, on_bytes_received_context, on_io_error, on_io_error_context, on_io_open_complete, and on_io_open_complete_context parameters for later use as specified and tested per other line entries in this document. ]*/
                        tls_io_instance->on_bytes_received = on_bytes_received;
                        tls_io_instance->on_bytes_received_context = on_bytes_received_context;

                        tls_io_instance->on_io_error = on_io_error;
                        tls_io_instance->on_io_error_context = on_io_error_context;

                        tls_io_instance->on_open_complete = on_io_open_complete;
                        tls_io_instance->on_open_complete_context = on_io_open_complete_context;

                        tls_io_instance->esp_tls_cfg.non_block = true;
                        if (tls_io_instance->options.x509_key != NULL && tls_io_instance->options.x509_cert != NULL) {
                            tls_io_instance->esp_tls_cfg.clientcert_pem_buf = (unsigned char *)tls_io_instance->options.x509_cert;
                            tls_io_instance->esp_tls_cfg.clientcert_pem_bytes = strlen(tls_io_instance->options.x509_cert) + 1;
                            tls_io_instance->esp_tls_cfg.clientkey_pem_buf = (unsigned char *)tls_io_instance->options.x509_key;
                            tls_io_instance->esp_tls_cfg.clientkey_pem_bytes = strlen(tls_io_instance->options.x509_key) + 1;
                        }
                        if (tls_io_instance->options.trusted_certs != NULL) {
                            tls_io_instance->esp_tls_cfg.cacert_pem_buf = (unsigned char *)tls_io_instance->options.trusted_certs;
                            tls_io_instance->esp_tls_cfg.cacert_pem_bytes = strlen(tls_io_instance->options.trusted_certs) + 1;
                        }

                        tls_io_instance->tlsio_state = TLSIO_STATE_INIT;
                        result = 0;
                    }
                }
            }
        }
        /* Codes_SRS_TLSIO_30_039: [ On failure, tlsio_open_async shall not call on_io_open_complete. ]*/
    }

    return result;
}

// This implementation does not have asynchronous close, but uses the _async name for consistency with the spec
static int tlsio_esp_tls_close_async(CONCRETE_IO_HANDLE tls_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
{
    int result;

    if (tls_io == NULL)
    {
        /* Codes_SRS_TLSIO_30_050: [ If the tlsio_handle parameter is NULL, tlsio_esp_tls_close_async shall log an error and return FAILURE. ]*/
        LogError("NULL tlsio");
        result = MU_FAILURE;
    }
    else
    {
        if (on_io_close_complete == NULL)
        {
            /* Codes_SRS_TLSIO_30_055: [ If the on_io_close_complete parameter is NULL, tlsio_esp_tls_close_async shall log an error and return FAILURE. ]*/
            LogError("NULL on_io_close_complete");
            result = MU_FAILURE;
        }
        else
        {
            TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;

            if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN &&
                tls_io_instance->tlsio_state != TLSIO_STATE_ERROR)
            {
                /* Codes_SRS_TLSIO_30_053: [ If the adapter is in any state other than TLSIO_STATE_EXT_OPEN or TLSIO_STATE_EXT_ERROR then tlsio_close_async shall log that tlsio_close_async has been called and then continue normally. ]*/
                // LogInfo rather than LogError because this is an unusual but not erroneous situation
                LogInfo("tlsio_esp_tls_close has been called when in neither TLSIO_STATE_OPEN nor TLSIO_STATE_ERROR.");
            }

            if (is_an_opening_state(tls_io_instance->tlsio_state))
            {
                /* Codes_SRS_TLSIO_30_057: [ On success, if the adapter is in TLSIO_STATE_EXT_OPENING, it shall call on_io_open_complete with the on_io_open_complete_context supplied in tlsio_open_async and IO_OPEN_CANCELLED. This callback shall be made before changing the internal state of the adapter. ]*/
                tls_io_instance->on_open_complete(tls_io_instance->on_open_complete_context, IO_OPEN_CANCELLED);
            }
            // This adapter does not support asynchronous closing
            /* Codes_SRS_TLSIO_30_056: [ On success the adapter shall enter TLSIO_STATE_EX_CLOSING. ]*/
            /* Codes_SRS_TLSIO_30_051: [ On success, if the underlying TLS does not support asynchronous closing, then the adapter shall enter TLSIO_STATE_EX_CLOSED immediately after entering TLSIO_STATE_EX_CLOSING. ]*/
            /* Codes_SRS_TLSIO_30_052: [ On success tlsio_close shall return 0. ]*/
            internal_close(tls_io_instance);
            on_io_close_complete(callback_context);
            result = 0;
        }
    }
    /* Codes_SRS_TLSIO_30_054: [ On failure, the adapter shall not call on_io_close_complete. ]*/
    return result;
}

static int dowork_read(TLS_IO_INSTANCE* tls_io_instance)
{
    // TRANSFER_BUFFER_SIZE is not very important because if the message is bigger
    // then the framework just calls dowork repeatedly until it gets everything. So
    // a bigger buffer would just use memory without buying anything.
    // Putting this buffer in a small function also allows it to exist on the stack
    // rather than adding to heap fragmentation.
    unsigned char buffer[TLSIO_RECEIVE_BUFFER_SIZE];
    int rcv_bytes = 0;
    int rcv_count = 0;

    if (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN)
    {
        rcv_bytes = esp_tls_conn_read(tls_io_instance->esp_tls_handle, buffer, sizeof(buffer));
        while (rcv_bytes > 0)
        {
            // tls_io_instance->on_bytes_received was already checked for NULL
            // in the call to tlsio_esp_tls_open_async
            /* Codes_SRS_TLSIO_30_100: [ As long as the TLS connection is able to provide received data, tlsio_dowork shall repeatedly read this data and call on_bytes_received with the pointer to the buffer containing the data, the number of bytes received, and the on_bytes_received_context. ]*/
            tls_io_instance->on_bytes_received(tls_io_instance->on_bytes_received_context, buffer, rcv_bytes);
            
            if (++rcv_count > MAX_RCV_COUNT)
            {
                // Read no more than "MAX_RCV_COUNT" times to avoid starvation of other processes.
                // LogInfo("Skipping further reading to avoid starvation.");
                break;
            }
            
            rcv_bytes = esp_tls_conn_read(tls_io_instance->esp_tls_handle, buffer, sizeof(buffer));
        }
        /* Codes_SRS_TLSIO_30_102: [ If the TLS connection receives no data then tlsio_dowork shall not call the on_bytes_received callback. ]*/
    }
    return rcv_bytes;
}

static int dowork_send(TLS_IO_INSTANCE* tls_io_instance)
{
    LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(tls_io_instance->pending_transmission_list);
    int write_result = 0;
    if (first_pending_io != NULL)
    {
        PENDING_TRANSMISSION* pending_message = (PENDING_TRANSMISSION*)singlylinkedlist_item_get_value(first_pending_io);
        uint8_t* buffer = ((uint8_t*)pending_message->bytes) +
            pending_message->size - pending_message->unsent_size;
        write_result = esp_tls_conn_write(tls_io_instance->esp_tls_handle, buffer, pending_message->unsent_size);
        if (write_result > 0)
        {
            pending_message->unsent_size -= write_result;
            if (pending_message->unsent_size == 0)
            {
                /* Codes_SRS_TLSIO_30_091: [ If tlsio_esp_tls_dowork is able to send all the bytes in an enqueued message, it shall call the messages's on_send_complete along with its associated callback_context and IO_SEND_OK. ]*/
                // The whole message has been sent successfully
                process_and_destroy_head_message(tls_io_instance, IO_SEND_OK);
            }
            else
            {
                /* Codes_SRS_TLSIO_30_093: [ If the TLS connection was not able to send an entire enqueued message at once, subsequent calls to tlsio_dowork shall continue to send the remaining bytes. ]*/
                // Repeat the send on the next pass with the rest of the message
                // This empty else compiles to nothing but helps readability
            }
        }
        else
        {
            LogInfo("Error from SSL_write: %d", write_result);
        }
    }
    else
    {
        /* Codes_SRS_TLSIO_30_096: [ If there are no enqueued messages available, tlsio_esp_tls_dowork shall do nothing. ]*/
    }
    return write_result;
}

static void tlsio_esp_tls_dowork(CONCRETE_IO_HANDLE tls_io)
{
    if (tls_io == NULL)
    {
        /* Codes_SRS_TLSIO_30_070: [ If the tlsio_handle parameter is NULL, tlsio_dowork shall do nothing except log an error. ]*/
        LogError("NULL tlsio");
    }
    else
    {
        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;

        // This switch statement handles all of the state transitions during the opening process
        switch (tls_io_instance->tlsio_state)
        {
        case TLSIO_STATE_CLOSED:
            /* Codes_SRS_TLSIO_30_075: [ If the adapter is in TLSIO_STATE_EXT_CLOSED then  tlsio_dowork  shall do nothing. ]*/
            // Waiting to be opened, nothing to do
            break;
        case TLSIO_STATE_INIT:
            {
            int result = esp_tls_conn_new_async(tls_io_instance->hostname, strlen(tls_io_instance->hostname), tls_io_instance->port, &tls_io_instance->esp_tls_cfg, tls_io_instance->esp_tls_handle);
            if (result == 1) {
                tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
                tls_io_instance->on_open_complete(tls_io_instance->on_open_complete_context, IO_OPEN_OK);
            } else if (result == -1) {
                tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
            }
            }
            break;
        case TLSIO_STATE_OPEN:
            if (dowork_read(tls_io_instance) < 0 && errno != EAGAIN)
            {
                tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
            }
            if (dowork_send(tls_io_instance) < 0 && errno != EAGAIN)
            {
                tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
            }
            break;
        case TLSIO_STATE_ERROR:
            /* Codes_SRS_TLSIO_30_071: [ If the adapter is in TLSIO_STATE_EXT_ERROR then tlsio_dowork shall do nothing. ]*/
            // There's nothing valid to do here but wait to be retried
            break;
        default:
            LogError("Unexpected internal tlsio state");
            break;
        }
    }
}

static int tlsio_esp_tls_send_async(CONCRETE_IO_HANDLE tls_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
{
    int result;
    if (on_send_complete == NULL)
    {
        /* Codes_SRS_TLSIO_30_062: [ If the on_send_complete is NULL, tlsio_esp_tls_send_async shall log the error and return FAILURE. ]*/
        result = MU_FAILURE;
        LogError("NULL on_send_complete");
    }
    else
    {
        if (tls_io == NULL)
        {
            /* Codes_SRS_TLSIO_30_060: [ If the tlsio_handle parameter is NULL, tlsio_esp_tls_send_async shall log an error and return FAILURE. ]*/
            result = MU_FAILURE;
            LogError("NULL tlsio");
        }
        else
        {
            if (buffer == NULL)
            {
                /* Codes_SRS_TLSIO_30_061: [ If the buffer is NULL, tlsio_esp_tls_send_async shall log the error and return FAILURE. ]*/
                result = MU_FAILURE;
                LogError("NULL buffer");
            }
            else
            {
                if (size == 0)
                {
                    /* Codes_SRS_TLSIO_30_067: [ If the  size  is 0,  tlsio_send  shall log the error and return FAILURE. ]*/
                    result = MU_FAILURE;
                    LogError("0 size");
                }
                else
                {
                    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
                    if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
                    {
                        result = MU_FAILURE;
                        LogError("tlsio_esp_tls_send_async without a prior successful open");
                    }
                    else
                    {
                        PENDING_TRANSMISSION* pending_transmission = (PENDING_TRANSMISSION*)malloc(sizeof(PENDING_TRANSMISSION));
                        if (pending_transmission == NULL)
                        {
                            /* Codes_SRS_TLSIO_30_064: [ If the supplied message cannot be enqueued for transmission, tlsio_esp_tls_send shall log an error and return FAILURE. ]*/
                            result = MU_FAILURE;
                            LogError("malloc failed");
                        }
                        else
                        {
                            /* Codes_SRS_TLSIO_30_063: [ The tlsio_esp_tls_send_async shall enqueue for transmission the on_send_complete, the callback_context, the size, and the contents of buffer. ]*/
                            pending_transmission->bytes = (unsigned char*)malloc(size);

                            if (pending_transmission->bytes == NULL)
                            {
                                /* Codes_SRS_TLSIO_30_064: [ If the supplied message cannot be enqueued for transmission, tlsio_esp_tls_send shall log an error and return FAILURE. ]*/
                                LogError("malloc failed");
                                free(pending_transmission);
                                result = MU_FAILURE;
                            }
                            else
                            {
                                pending_transmission->size = size;
                                pending_transmission->unsent_size = size;
                                pending_transmission->on_send_complete = on_send_complete;
                                pending_transmission->callback_context = callback_context;
                                (void)memcpy(pending_transmission->bytes, buffer, size);

                                if (singlylinkedlist_add(tls_io_instance->pending_transmission_list, pending_transmission) == NULL)
                                {
                                    /* Codes_SRS_TLSIO_30_064: [ If the supplied message cannot be enqueued for transmission, tlsio_esp_tls_send_async shall log an error and return FAILURE. ]*/
                                    LogError("Unable to add socket to pending list.");
                                    free(pending_transmission->bytes);
                                    free(pending_transmission);
                                    result = MU_FAILURE;
                                }
                                else
                                {
                                    /* Codes_SRS_TLSIO_30_063: [ On success, tlsio_esp_tls_send_async shall enqueue for transmission the  on_send_complete , the  callback_context , the  size , and the contents of  buffer  and then return 0. ]*/
                                    dowork_send(tls_io_instance);
                                    result = 0;
                                }
                            }
                        }
                    }
                }
            }
        }
        /* Codes_SRS_TLSIO_30_066: [ On failure, on_send_complete shall not be called. ]*/
    }
    return result;
}

static int tlsio_esp_tls_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
    /* Codes_SRS_TLSIO_30_120: [ If the tlsio_handle parameter is NULL, tlsio_esp_tls_setoption shall do nothing except log an error and return FAILURE. ]*/
    int result;
    if (tls_io_instance == NULL)
    {
        LogError("NULL tlsio");
        result = MU_FAILURE;
    }
    else
    {
        /* Codes_SRS_TLSIO_30_121: [ If the optionName parameter is NULL, tlsio_esp_tls_setoption shall do nothing except log an error and return FAILURE. ]*/
        /* Codes_SRS_TLSIO_30_122: [ If the value parameter is NULL, tlsio_esp_tls_setoption shall do nothing except log an error and return FAILURE. ]*/
        /* Codes_SRS_TLSIO_ESP_TLS_COMPACT_30_520 [ The tlsio_esp_tls_setoption shall do nothing and return FAILURE. ]*/
        TLSIO_OPTIONS_RESULT options_result = tlsio_options_set(&tls_io_instance->options, optionName, value);
        if (options_result != TLSIO_OPTIONS_RESULT_SUCCESS)
        {
            LogError("Failed tlsio_options_set");
            result = MU_FAILURE;
        }
        else
        {
            result = 0;
        }
    }
    return result;
}

/* Codes_SRS_TLSIO_ESP_TLS_COMPACT_30_560: [ The  tlsio_esp_tls_retrieveoptions  shall do nothing and return an empty options handler. ]*/
static OPTIONHANDLER_HANDLE tlsio_esp_tls_retrieveoptions(CONCRETE_IO_HANDLE tls_io)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
    /* Codes_SRS_TLSIO_30_160: [ If the tlsio_handle parameter is NULL, tlsio_esp_tls_retrieveoptions shall do nothing except log an error and return FAILURE. ]*/
    OPTIONHANDLER_HANDLE result;
    if (tls_io_instance == NULL)
    {
        LogError("NULL tlsio");
        result = NULL;
    }
    else
    {
        result = tlsio_options_retrieve_options(&tls_io_instance->options, tlsio_esp_tls_setoption);
    }
    return result;
}

/* Codes_SRS_TLSIO_30_008: [ The tlsio_get_interface_description shall return the VTable IO_INTERFACE_DESCRIPTION. ]*/
static const IO_INTERFACE_DESCRIPTION tlsio_esp_tls_interface_description =
{
    tlsio_esp_tls_retrieveoptions,
    tlsio_esp_tls_create,
    tlsio_esp_tls_destroy,
    tlsio_esp_tls_open_async,
    tlsio_esp_tls_close_async,
    tlsio_esp_tls_send_async,
    tlsio_esp_tls_dowork,
    tlsio_esp_tls_setoption
};

/* Codes_SRS_TLSIO_30_001: [ The tlsio_esp_tls shall implement and export all the Concrete functions in the VTable IO_INTERFACE_DESCRIPTION defined in the xio.h. ]*/
const IO_INTERFACE_DESCRIPTION* tlsio_pal_get_interface_description(void)
{
    return &tlsio_esp_tls_interface_description;
}
Download .txt
gitextract_6f4ybc5i/

├── .github/
│   └── workflows/
│       ├── issue_comment.yml
│       ├── new_issues.yml
│       └── new_prs.yml
├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── README.md
├── component.mk
├── doc/
│   └── azure_cli_iot_hub.md
├── examples/
│   ├── iothub_client_sample_mqtt/
│   │   ├── CMakeLists.txt
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── main/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── Kconfig.projbuild
│   │   │   ├── azure_main.c
│   │   │   ├── component.mk
│   │   │   ├── iothub_client_sample_mqtt.c
│   │   │   └── iothub_client_sample_mqtt.h
│   │   └── sdkconfig.defaults
│   ├── iothub_devicetwin_samples_and_methods/
│   │   ├── CMakeLists.txt
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── main/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── Kconfig.projbuild
│   │   │   ├── azure_main.c
│   │   │   ├── component.mk
│   │   │   └── iothub_client_device_twin_and_methods_sample.c
│   │   └── sdkconfig.defaults
│   └── prov_dev_client_ll_sample/
│       ├── CMakeLists.txt
│       ├── Makefile
│       ├── README.md
│       ├── main/
│       │   ├── CMakeLists.txt
│       │   ├── Kconfig.projbuild
│       │   ├── azure_main.c
│       │   ├── certs/
│       │   │   └── .dummy
│       │   ├── component.mk
│       │   ├── custom_hsm_x509.c
│       │   └── prov_dev_client_ll_sample.c
│       └── sdkconfig.defaults
└── port/
    ├── CMakeLists.txt
    ├── inc/
    │   ├── certs.h
    │   ├── sntp_os.h
    │   ├── socket_async_os.h
    │   └── tlsio_pal.h
    └── src/
        ├── agenttime_esp.c
        ├── certs.c
        ├── platform_esp.c
        └── tlsio_esp_tls.c
Download .txt
SYMBOL INDEX (74 symbols across 10 files)

FILE: examples/iothub_client_sample_mqtt/main/azure_main.c
  function esp_err_t (line 43) | static esp_err_t event_handler(void *ctx, system_event_t *event)
  function event_handler (line 64) | static void event_handler(void* arg, esp_event_base_t event_base,
  function initialise_wifi (line 80) | static void initialise_wifi(void)
  function azure_task (line 116) | void azure_task(void *pvParameter)
  function app_main (line 127) | void app_main()

FILE: examples/iothub_client_sample_mqtt/main/iothub_client_sample_mqtt.c
  type EVENT_INSTANCE (line 42) | typedef struct EVENT_INSTANCE_TAG
  function IOTHUBMESSAGE_DISPOSITION_RESULT (line 48) | static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_ME...
  function SendConfirmationCallback (line 111) | static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT r...
  function connection_status_callback (line 124) | void connection_status_callback(IOTHUB_CLIENT_CONNECTION_STATUS result, ...
  function iothub_client_sample_mqtt_run (line 130) | void iothub_client_sample_mqtt_run(void)
  function main (line 243) | int main(void)

FILE: examples/iothub_devicetwin_samples_and_methods/main/azure_main.c
  function esp_err_t (line 45) | static esp_err_t event_handler(void *ctx, system_event_t *event)
  function event_handler (line 66) | static void event_handler(void* arg, esp_event_base_t event_base,
  function initialise_wifi (line 82) | static void initialise_wifi(void)
  function azure_task (line 119) | void azure_task(void *pvParameter)
  function app_main (line 130) | void app_main()

FILE: examples/iothub_devicetwin_samples_and_methods/main/iothub_client_device_twin_and_methods_sample.c
  type Maker (line 61) | typedef struct MAKER_TAG
  type Geo (line 68) | typedef struct GEO_TAG
  type CarState (line 74) | typedef struct CAR_STATE_TAG
  type CarSettings (line 81) | typedef struct CAR_SETTINGS_TAG
  type Car (line 87) | typedef struct CAR_TAG
  function Car (line 120) | static Car* parseFromJson(const char* json, DEVICE_TWIN_UPDATE_STATE upd...
  function deviceMethodCallback (line 193) | static int deviceMethodCallback(const char* method_name, const unsigned ...
  function deviceTwinCallback (line 231) | static void deviceTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, co...
  function reportedStateCallback (line 293) | static void reportedStateCallback(int status_code, void* userContextCall...
  function iothub_client_device_twin_and_methods_sample_run (line 300) | static void iothub_client_device_twin_and_methods_sample_run(void)
  function iothub_client_device_twin_init (line 382) | int iothub_client_device_twin_init(void)

FILE: examples/prov_dev_client_ll_sample/main/azure_main.c
  function esp_err_t (line 43) | static esp_err_t event_handler(void *ctx, system_event_t *event)
  function event_handler (line 64) | static void event_handler(void* arg, esp_event_base_t event_base,
  function initialise_wifi (line 80) | static void initialise_wifi(void)
  function azure_task (line 117) | void azure_task(void *pvParameter)
  function app_main (line 128) | void app_main()

FILE: examples/prov_dev_client_ll_sample/main/custom_hsm_x509.c
  type CUSTOM_HSM_SAMPLE_INFO (line 30) | typedef struct CUSTOM_HSM_SAMPLE_INFO_TAG
  function hsm_client_x509_init (line 43) | int hsm_client_x509_init()
  function hsm_client_x509_deinit (line 48) | void hsm_client_x509_deinit()
  function HSM_CLIENT_HANDLE (line 53) | HSM_CLIENT_HANDLE custom_hsm_create()
  function custom_hsm_destroy (line 79) | void custom_hsm_destroy(HSM_CLIENT_HANDLE handle)
  function HSM_CLIENT_X509_INTERFACE (line 182) | const HSM_CLIENT_X509_INTERFACE* hsm_client_x509_interface()

FILE: examples/prov_dev_client_ll_sample/main/prov_dev_client_ll_sample.c
  type CLIENT_SAMPLE_INFO (line 77) | typedef struct CLIENT_SAMPLE_INFO_TAG
  type IOTHUB_CLIENT_SAMPLE_INFO (line 87) | typedef struct IOTHUB_CLIENT_SAMPLE_INFO_TAG
  function IOTHUBMESSAGE_DISPOSITION_RESULT (line 93) | static IOTHUBMESSAGE_DISPOSITION_RESULT receive_msg_callback(IOTHUB_MESS...
  function registration_status_callback (line 102) | static void registration_status_callback(PROV_DEVICE_REG_STATUS reg_stat...
  function iothub_connection_status (line 108) | static void iothub_connection_status(IOTHUB_CLIENT_CONNECTION_STATUS res...
  function register_device_callback (line 130) | static void register_device_callback(PROV_DEVICE_RESULT register_result,...
  function IO_INTERFACE_DESCRIPTION (line 154) | const IO_INTERFACE_DESCRIPTION* socketio_get_interface_description(void)
  function prov_dev_client_ll_sample_run (line 159) | int prov_dev_client_ll_sample_run()

FILE: port/src/agenttime_esp.c
  function initialize_sntp (line 13) | void initialize_sntp(void)
  function obtain_time (line 21) | static void obtain_time(void)
  function time_t (line 36) | time_t sntp_get_current_timestamp()
  function time_t (line 53) | time_t get_time(time_t* currentTime)
  function get_difftime (line 59) | double get_difftime(time_t stopTime, time_t startTime)
  type tm (line 64) | struct tm

FILE: port/src/platform_esp.c
  function platform_init (line 22) | int platform_init(void)
  function IO_INTERFACE_DESCRIPTION (line 38) | const IO_INTERFACE_DESCRIPTION* platform_get_default_tlsio(void)
  function platform_deinit (line 44) | void platform_deinit(void)
  function STRING_HANDLE (line 49) | STRING_HANDLE platform_get_platform_info(PLATFORM_INFO_OPTION options)

FILE: port/src/tlsio_esp_tls.c
  type PENDING_TRANSMISSION (line 25) | typedef struct
  type TLSIO_STATE (line 42) | typedef enum TLSIO_STATE_TAG
  function is_an_opening_state (line 50) | bool is_an_opening_state(TLSIO_STATE state)
  type TLS_IO_INSTANCE (line 56) | typedef struct TLS_IO_INSTANCE_TAG
  function enter_tlsio_error_state (line 74) | static void enter_tlsio_error_state(TLS_IO_INSTANCE* tls_io_instance)
  function process_and_destroy_head_message (line 84) | static bool process_and_destroy_head_message(TLS_IO_INSTANCE* tls_io_ins...
  function internal_close (line 121) | static void internal_close(TLS_IO_INSTANCE* tls_io_instance)
  function tlsio_esp_tls_destroy (line 140) | static void tlsio_esp_tls_destroy(CONCRETE_IO_HANDLE tls_io)
  function CONCRETE_IO_HANDLE (line 174) | static CONCRETE_IO_HANDLE tlsio_esp_tls_create(void* io_create_parameters)
  function tlsio_esp_tls_open_async (line 257) | static int tlsio_esp_tls_open_async(CONCRETE_IO_HANDLE tls_io,
  function tlsio_esp_tls_close_async (line 342) | static int tlsio_esp_tls_close_async(CONCRETE_IO_HANDLE tls_io, ON_IO_CL...
  function dowork_read (line 390) | static int dowork_read(TLS_IO_INSTANCE* tls_io_instance)
  function dowork_send (line 425) | static int dowork_send(TLS_IO_INSTANCE* tls_io_instance)
  function tlsio_esp_tls_dowork (line 463) | static void tlsio_esp_tls_dowork(CONCRETE_IO_HANDLE tls_io)
  function tlsio_esp_tls_send_async (line 513) | static int tlsio_esp_tls_send_async(CONCRETE_IO_HANDLE tls_io, const voi...
  function tlsio_esp_tls_setoption (line 608) | static int tlsio_esp_tls_setoption(CONCRETE_IO_HANDLE tls_io, const char...
  function OPTIONHANDLER_HANDLE (line 638) | static OPTIONHANDLER_HANDLE tlsio_esp_tls_retrieveoptions(CONCRETE_IO_HA...
  function IO_INTERFACE_DESCRIPTION (line 669) | const IO_INTERFACE_DESCRIPTION* tlsio_pal_get_interface_description(void)
Condensed preview — 48 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (147K chars).
[
  {
    "path": ".github/workflows/issue_comment.yml",
    "chars": 633,
    "preview": "name: Sync issue comments to JIRA\n\n# This workflow will be triggered when new issue comment is created (including PR com"
  },
  {
    "path": ".github/workflows/new_issues.yml",
    "chars": 578,
    "preview": "name: Sync issues to Jira\n\n# This workflow will be triggered when a new issue is opened\non: issues\n\njobs:\n  sync_issues_"
  },
  {
    "path": ".github/workflows/new_prs.yml",
    "chars": 754,
    "preview": "name: Sync remain PRs to Jira\n\n# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero c"
  },
  {
    "path": ".gitignore",
    "chars": 69,
    "preview": ".settings\n.project\n.cproject\n.vscode/\n\nbuild\nsdkconfig\nsdkconfig.old\n"
  },
  {
    "path": ".gitlab-ci.yml",
    "chars": 2376,
    "preview": "stages:\n  - build_esp32\n  - build_esp8266\n\nvariables:\n  BATCH_BUILD: \"1\"\n  V: \"0\"\n  MAKEFLAGS: \"-j5 --no-keep-going\"\n  I"
  },
  {
    "path": ".gitmodules",
    "chars": 106,
    "preview": "[submodule \"azure-iot-sdk-c\"]\n\tpath = azure-iot-sdk-c\n\turl = https://github.com/Azure/azure-iot-sdk-c.git\n"
  },
  {
    "path": "README.md",
    "chars": 5260,
    "preview": "# ESP Azure IoT SDK\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [Getting Started](#get-started)\n- [Creating"
  },
  {
    "path": "component.mk",
    "chars": 6485,
    "preview": "#\n# Component Makefile\n#\n \n# Component configuration in preprocessor defines\nCFLAGS += -DUSE_LWIP_SOCKET_FOR_AZURE_IOT\n\n"
  },
  {
    "path": "doc/azure_cli_iot_hub.md",
    "chars": 956,
    "preview": "# Azure CLI usage\n\n## Login\t[Required for using any of the other commands]\n```\naz login\n```\n\n## Create a device\n```\naz i"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/CMakeLists.txt",
    "chars": 325,
    "preview": "# The following five lines of boilerplate have to be in your project's\n# CMakeLists in this exact order for cmake to wor"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/Makefile",
    "chars": 256,
    "preview": "#\n# This is a project Makefile. It is assumed the directory this Makefile resides in is a\n# project subdirectory.\n#\n\nPRO"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/README.md",
    "chars": 2365,
    "preview": "# IoT HUB MQTT Client\n\nThis demonstrates MQTT send received using Azure IoT.\n\n## Device Configuration\n- For this demo we"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/main/CMakeLists.txt",
    "chars": 189,
    "preview": "set(COMPONENT_SRCS \"iothub_client_sample_mqtt.c\"\n\t\t\t\"azure_main.c\"\n\t\t\t)\nset(COMPONENT_ADD_INCLUDEDIRS \".\")\n\nregister_com"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/main/Kconfig.projbuild",
    "chars": 1126,
    "preview": "menu \"Example Configuration\"\n\nconfig WIFI_SSID\n    string \"WiFi SSID\"\n\tdefault \"myssid\"\n\thelp\n\t\tSSID (network name) for "
  },
  {
    "path": "examples/iothub_client_sample_mqtt/main/azure_main.c",
    "chars": 4481,
    "preview": "/* esp-azure example\n\n   This example code is in the Public Domain (or CC0 licensed, at your option.)\n\n   Unless require"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/main/component.mk",
    "chars": 186,
    "preview": "#\n# \"main\" pseudo-component makefile.\n#\n# (Uses default behaviour of compiling all source files in directory, adding 'in"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/main/iothub_client_sample_mqtt.c",
    "chars": 9948,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/main/iothub_client_sample_mqtt.h",
    "chars": 607,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "examples/iothub_client_sample_mqtt/sdkconfig.defaults",
    "chars": 175,
    "preview": "# newlib for ESP32 and ESP8266 platform\n\nCONFIG_NEWLIB_ENABLE=y\nCONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y\nCONFIG_NEWLIB_NANO_"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/CMakeLists.txt",
    "chars": 337,
    "preview": "# The following five lines of boilerplate have to be in your project's\n# CMakeLists in this exact order for cmake to wor"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/Makefile",
    "chars": 268,
    "preview": "#\n# This is a project Makefile. It is assumed the directory this Makefile resides in is a\n# project subdirectory.\n#\n\nPRO"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/README.md",
    "chars": 3645,
    "preview": "# Device Twin and Direct Method Example\n\nThis example demonstrates Device twin and Direct method features of Azure IoT.\n"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/main/CMakeLists.txt",
    "chars": 234,
    "preview": "set(COMPONENT_SRCS \"azure_main.c\"\n                \"iothub_client_device_twin_and_methods_sample.c\"\n                )\nset"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/main/Kconfig.projbuild",
    "chars": 644,
    "preview": "menu \"Example Configuration\"\n\nconfig WIFI_SSID\n    string \"WiFi SSID\"\n\tdefault \"myssid\"\n\thelp\n\t\tSSID (network name) for "
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/main/azure_main.c",
    "chars": 4622,
    "preview": "/* esp-azure example\n\n   This example code is in the Public Domain (or CC0 licensed, at your option.)\n\n   Unless require"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/main/component.mk",
    "chars": 186,
    "preview": "#\n# \"main\" pseudo-component makefile.\n#\n# (Uses default behaviour of compiling all source files in directory, adding 'in"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/main/iothub_client_device_twin_and_methods_sample.c",
    "chars": 13245,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "examples/iothub_devicetwin_samples_and_methods/sdkconfig.defaults",
    "chars": 175,
    "preview": "# newlib for ESP32 and ESP8266 platform\n\nCONFIG_NEWLIB_ENABLE=y\nCONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y\nCONFIG_NEWLIB_NANO_"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/CMakeLists.txt",
    "chars": 325,
    "preview": "# The following five lines of boilerplate have to be in your project's\n# CMakeLists in this exact order for cmake to wor"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/Makefile",
    "chars": 256,
    "preview": "#\n# This is a project Makefile. It is assumed the directory this Makefile resides in is a\n# project subdirectory.\n#\n\nPRO"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/README.md",
    "chars": 5998,
    "preview": "# Azure Provisioning Demo\n\nThis example demonstrates Device Authentication using X.509 CA Certificates. Refer [this azur"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/main/CMakeLists.txt",
    "chars": 363,
    "preview": "set(COMPONENT_SRCS \"azure_main.c\"\n\t\t\t\t\"custom_hsm_x509.c\"\n\t\t\t\t\"prov_dev_client_ll_sample.c\"\n\t\t\t\t)\nset(COMPONENT_ADD_INCL"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/main/Kconfig.projbuild",
    "chars": 1070,
    "preview": "menu \"Example Configuration\"\n\nconfig WIFI_SSID\n    string \"WiFi SSID\"\n\tdefault \"myssid\"\n\thelp\n\t\tSSID (network name) for "
  },
  {
    "path": "examples/prov_dev_client_ll_sample/main/azure_main.c",
    "chars": 4577,
    "preview": "/* esp-azure example\n\n   This example code is in the Public Domain (or CC0 licensed, at your option.)\n\n   Unless require"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/main/certs/.dummy",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/prov_dev_client_ll_sample/main/component.mk",
    "chars": 1083,
    "preview": "#\n# Main component makefile.\n#\n# This Makefile can be left empty. By default, it will take the sources in the \n# src/ di"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/main/custom_hsm_x509.c",
    "chars": 5473,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/main/prov_dev_client_ll_sample.c",
    "chars": 13256,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "examples/prov_dev_client_ll_sample/sdkconfig.defaults",
    "chars": 175,
    "preview": "# newlib for ESP32 and ESP8266 platform\n\nCONFIG_NEWLIB_ENABLE=y\nCONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y\nCONFIG_NEWLIB_NANO_"
  },
  {
    "path": "port/CMakeLists.txt",
    "chars": 5977,
    "preview": "#\n# Component Makefile\n#\n\nset (AZURE_IOT_SDK \"${CMAKE_CURRENT_LIST_DIR}/../azure-iot-sdk-c\")\n\nset (COMPONENT_ADD_INCLUDE"
  },
  {
    "path": "port/inc/certs.h",
    "chars": 314,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "port/inc/sntp_os.h",
    "chars": 504,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "port/inc/socket_async_os.h",
    "chars": 478,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "port/inc/tlsio_pal.h",
    "chars": 492,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "port/src/agenttime_esp.c",
    "chars": 1739,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "port/src/certs.c",
    "chars": 1778,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "port/src/platform_esp.c",
    "chars": 1367,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  },
  {
    "path": "port/src/tlsio_esp_tls.c",
    "chars": 32172,
    "preview": "// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root"
  }
]

About this extraction

This page contains the full source code of the espressif/esp-azure GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 48 files (134.4 KB), approximately 35.9k tokens, and a symbol index with 74 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!