21.04 Release (#203)
* Substantially updated Azure IoT sample: * Now supports Azure IoT PnP, and non-blocking provisioning using full Azure IoT C SDK provisioning flow * Clearer, more modular code with separation of business logic, data model, UI, Azure IoT communications and connection setup. * New snippet showing detection and cleanup on memory overuse. * Updated READMEs to bring into line with recommendations for Azure Sample Browser.
This commit is contained in:
Родитель
15bc18a18c
Коммит
43751794a0
|
@ -0,0 +1,50 @@
|
|||
// Code Snippet: Memory Overuse Detection And Cleanup
|
||||
|
||||
// This code snippet demonstrates how to detect and gracefully handle unexpected memory usage,
|
||||
// e.g. due to leak. The code based on this snippet might be called before and/or after memory
|
||||
// allocations, and also regularly on a timer.
|
||||
|
||||
// Because the application will be restarted by the OS if the memory limit was exceeded, its
|
||||
// state may be saved before exiting and recovered afterwards. For illustration of how to save
|
||||
// and recover the state of the application check the MutableStorage and the PowerDown samples:
|
||||
// https://github.com/Azure/azure-sphere-samples/tree/master/Samples/MutableStorage/main.c
|
||||
// https://github.com/Azure/azure-sphere-samples/tree/master/Samples/Powerdown/main.c
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <applibs/log.h>
|
||||
#include <applibs/applications.h>
|
||||
|
||||
// Set this limit based on the expectation of the maximum resources required by the application
|
||||
static const size_t TotalMemoryLimit = <INSERT MEMORY VALUE HERE>; // Change this value according to the app constraints
|
||||
|
||||
static ExitCode CheckTotalMemoryLimit(void)
|
||||
{
|
||||
// Depending on the logic of the application, the call to the
|
||||
// Applications_GetTotalMemoryUsageInKB may be replaced with any of the functions described here
|
||||
// https://docs.microsoft.com/azure-sphere/app-development/application-memory-usage?pivots=visual-studio#determine-run-time-application-ram-usage
|
||||
size_t totalMemoryUsage = Applications_GetTotalMemoryUsageInKB();
|
||||
|
||||
if (totalMemoryUsage == 0) {
|
||||
Log_Debug("ERROR: Applications_GetTotalMemoryUsageInKB failed: %s (%d)\n", strerror(errno),
|
||||
errno);
|
||||
|
||||
// User defined: https://docs.microsoft.com/azure-sphere/app-development/exit-codes
|
||||
return ExitCode_CheckTotalMemoryLimit_GetTotalMemoryUsageInKB_Failed;
|
||||
}
|
||||
|
||||
// To aid debugging, telemetry may be sent to the cloud with the memory usage details from
|
||||
// the memory APIs. For general illustration of how to send telemetry check the AzureIoT sample:
|
||||
// https://github.com/Azure/azure-sphere-samples/blob/master/Samples/AzureIoT/main.c
|
||||
// e.g SendTelemetry("{\"TotalMemoryUsed\" : totalMemoryUsage}");
|
||||
if (totalMemoryUsage >= TotalMemoryLimit) {
|
||||
Log_Debug("ERROR: TotalMemoryUsed reached: %zu KB\n", totalMemoryUsage);
|
||||
|
||||
// User defined: https://docs.microsoft.com/azure-sphere/app-development/exit-codes
|
||||
return ExitCode_CheckTotalMemoryLimit_Overflow;
|
||||
}
|
||||
|
||||
// User defined: https://docs.microsoft.com/azure-sphere/app-development/exit-codes
|
||||
return ExitCode_Success;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
# Snippets: Memory Overuse Detection And Cleanup
|
||||
|
||||
This folder contains one snippet that demonstrates how to detect and handle unexpected memory usage.
|
||||
|
||||
The [Memory Overuse Detection and Cleanup snippet](MemoryOveruseDetectionAndCleanup) demonstrates how to detect and gracefully handle unexpected memory usage. Code based on this snippet can be called before or after memory allocations, or both, and can also be called regularly on a timer.
|
||||
|
||||
The snippet uses the [Applications_GetTotalMemoryUsageInKB()](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-applications/function-applications-gettotalmemoryusageinkb) function. Similar code could use any of the other functions described [here](https://docs.microsoft.com/azure-sphere/app-development/application-memory-usage#determine-run-time-application-ram-usage).
|
||||
|
||||
### Compiling and running the snippet
|
||||
|
||||
In order to successfully compile and run the snippet, you must replace the placeholder '\<INSERT MEMORY VALUE HERE\>' for the total memory usage limit with an integer value. The limit of the total memory usage should be set based on the application logic and on your expectations of the maximum resources required by the application. For more information on memory usage in high-level Azure Sphere applications, see [Memory use in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/application-memory-usage) and [Best practices for managing RAM usage in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/ram-usage-best-practices).
|
||||
|
||||
If the limit is reached, the snippet exits with an [exit code](https://docs.microsoft.com/azure-sphere/app-development/exit-codes) you define. In order to successfully compile and run the snippet, you should declare an ExitCode enum that you can use to define all of your specific exit code values. The ExitCode_Success should always be set to 0, while the ExitCode_CheckTotalMemoryLimit_Overflow and the ExitCode_CheckTotalMemoryLimit_GetTotalMemoryUsageInKB_Failed can be set to any value in the [1, 255] interval.
|
||||
|
||||
### Additional logic
|
||||
|
||||
If the memory limit is exceeded, the application exits and is restarted by the OS. You may want to insert code to save the application state before exiting; you can then recover the saved state after restart. See [the MutableStorage sample](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/MutableStorage) for an example of how to do so. Constantly writing and erasing the flash eventually wears it out and makes it invalid. Consider saving the state of the application to flash only if the state has changed. The [PowerDown](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/Powerdown/main.c) sample provides another example of saving and restoring state.
|
||||
|
||||
To aid debugging, telemetry may be sent to the cloud with the memory usage details from the APIs. Sending telemetry can happen before exiting the application or regularly throughout the application's lifetime. For general illustration of how to send telemetry check the [AzureIoT](https://github.com/Azure/azure-sphere-samples/blob/master/Samples/AzureIoT/main.c) sample.
|
||||
|
||||
### Output
|
||||
|
||||
The memory usage results may vary if the code snippet is run [under the debugger](https://docs.microsoft.com/azure-sphere/app-development/application-memory-usage).
|
||||
|
||||
### Additional resources
|
||||
|
||||
If you want how to detect if an application has a memory leak, you can check the [MemoryUsage tutorial](https://github.com/Azure/azure-sphere-samples/tree/master/Tutorials/MemoryUsage). This tutorial shows how to observe, find, and fix a memory leak using either Visual Studio's [memory usage profiler](https://docs.microsoft.com/azure-sphere/app-development/application-memory-usage?pivots=visual-studio#use-the-visual-studio-performance-profiler) or the Azure Sphere CLI's [**azsphere device app show-memory-stats**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#app-show-memory-stats) command.
|
|
@ -5,28 +5,29 @@ This section provides instructions for connecting the following Ethernet boards
|
|||
- [Connection instructions for the Olimex ENC28J60-H development board](#Connection-instructions-for-the-Olimex-ENC28J60-H-development-board)
|
||||
- [Connection instructions for the MT3620 Ethernet Shield](#Connection-instructions-for-the-MT3620-Ethernet-Shield)
|
||||
|
||||
***
|
||||
## Connection instructions for the Olimex ENC28J60-H development board
|
||||
## Connection instructions for the Olimex ENC28J60-H development board
|
||||
|
||||
The [Olimex ENC28J60-H development board](https://www.olimex.com/Products/Modules/Ethernet/ENC28J60-H/) uses ISU port 0 (ISU0) to communicate with the MT3620 board via SPI.
|
||||
|
||||
Use jumper wires to make the following connections between the ENC28J60-H board and the MT3620 board.
|
||||
Use jumper wires to make the following connections between the ENC28J60-H board and the MT3620 board.
|
||||
|
||||
- ENC28J60-H 3V3: 10 to MT3620 3V3: Header 3 (upper right) Pin 3
|
||||
- ENC28J60-H GND: 9 to MT3620 GND: Header 2 (lower left) Pin 2
|
||||
- ENC28J60-H CS: 7 to MT3620 CSA0: Header 2 (lower left) Pin 1
|
||||
- ENC28J60-H SCK: 1 to MT3620 SCLK0: Header 2 (lower left) Pin 3
|
||||
- ENC28J60-H MOSI: 2 to MT3620 MOSI0: Header 2 (lower left) Pin 5
|
||||
- ENC28J60-H MISO: 3 to MT3620 MISO0 RTS: Header 2 (lower left) Pin 7
|
||||
- ENC28J60-H INT: 5 to MT3620 GPIO5: Header 2 (lower left) Pin 4
|
||||
| ENC28J60-H pin | MT3620 board pin |
|
||||
| -------------- | ---------------- |
|
||||
| 3V3: 10 | 3V3: Header 3 (upper right), Pin 3 |
|
||||
| GND: 9 | GND: Header 2 (lower left), Pin 2 |
|
||||
| CS: 7 | CSA0: Header 2, Pin 5 |
|
||||
| SCK: 1 | SCLK0: Header 2, Pin 3 |
|
||||
| MOSI: 2 | MOSI0: Header 2, Pin 7 |
|
||||
| MISO: 3 | MISO0 RTS: Header 2, Pin 1 |
|
||||
| INT: 5 | GPIO5: Header 2, Pin 4 |
|
||||
|
||||
Refer to the following graphic for details.
|
||||
|
||||
![Connection diagram for ENC28J60-H and MT3620](./Media/ENC28J60Hconnection.jpg)
|
||||
|
||||
***
|
||||
## Connection instructions for the MT3620 Ethernet Shield
|
||||
## Connection instructions for the MT3620 Ethernet Shield
|
||||
|
||||
The [MT3620 Ethernet Shield](https://www.seeedstudio.com/MT3620-Ethernet-Shield-v1-0-p-2917.html) uses the same board configuration package, and is internally wired to the same MT3620 development board GPIO pins as the Olimex ENC28J60-H Development Board.
|
||||
It also uses the same ISU port (ISU0) to communicate with the MT3620 board via SPI. However, you connect the MT3620 Ethernet Shield directly to the interface headers on the MT3620 board.
|
||||
|
||||
|
||||
![MT3620 Ethernet Shield - Seeed Studio](./Media/MT3620EthernetShield.jpg)
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(ADC_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -23,7 +23,7 @@ description: "Demonstrates how to do analog-to-digital conversion on the MT3620
|
|||
|
||||
# Sample: ADC high-level app
|
||||
|
||||
This sample application demonstrates how to do analog-to-digital conversion on the MT3620 high-level core.
|
||||
This sample application demonstrates how to do analog-to-digital conversion in a high-level application.
|
||||
|
||||
The application samples and displays the output from a simple variable voltage source once per second. It uses the MT3620 analog-to-digital converter (ADC) to sample the voltage.
|
||||
|
||||
|
@ -31,21 +31,23 @@ The sample uses the following Azure Sphere libraries.
|
|||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [adc](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-adc/adc-overview) | Manages ADCs |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events |
|
||||
|
||||
|
||||
The [ADC code snippets](https://github.com/Azure/azure-sphere-samples/tree/master/CodeSnippets/Peripherals/ADC) demonstrate how to interact with the ADC peripheral using the simplified functions provided by Azure Sphere or advanced functions using Linux ioctls.
|
||||
|
||||
For more information, see [Use ADCs in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/adc) documentation.
|
||||
| [adc](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-adc/adc-overview) | Manages the analog-to-digital converters (ADCs). |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| ADC_HighLevelApp |Sample source code and project files |
|
||||
| README.md | This readme file |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -57,17 +59,17 @@ The sample requires the following hardware:
|
|||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer, and your computer is connected to the internet.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *ADC_HighLevelApp* sample in the *ADC* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/adc/).
|
||||
|
||||
## Set up the ADC connections
|
||||
### Set up the ADC connections
|
||||
|
||||
1. Connect MT3620 dev board pin H2.2 (GND) to an outer terminal of the potentiometer.
|
||||
1. Connect both pin 1 and pin 2 of jumper J1 to the other outer terminal of the potentiometer. This connects the MT3620 2.5 V output to the ADC VREF pin and to the potentiometer.
|
||||
|
@ -79,10 +81,9 @@ The sample requires the following hardware:
|
|||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
After you have built, deployed, and started the sample the ADC output will be displayed in the output terminal or window.
|
||||
Adjust the potentiometer and observe that the displayed value changes. For example:
|
||||
The ADC output is displayed in the output terminal or **Device Output** window during debugging. Adjust the potentiometer and observe that the displayed value changes, as shown in the following example output.
|
||||
|
||||
```sh
|
||||
Show output from: Device Output
|
||||
|
@ -91,3 +92,10 @@ The out sample value is 2.483 V
|
|||
The out sample value is 2.337 V
|
||||
The out sample value is 2.055 V
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- To learn more about how to interact with an ADC peripheral by using the simplified Azure Sphere functions or the advanced Linux IOCTLs, see the [ADC code snippets](https://github.com/Azure/azure-sphere-samples/tree/master/CodeSnippets/Peripherals/ADC).
|
||||
- For information about using ADCs, see [Use ADCs in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/adc).
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# Ignore output directories
|
||||
/out/
|
||||
/install/
|
||||
out/
|
||||
install/
|
|
@ -5,13 +5,24 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(AzureIoT C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c parson.c)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${AZURE_SPHERE_API_SET_DIR}/usr/include/azureiot
|
||||
${AZURE_SPHERE_API_SET_DIR}/usr/include/azure_prov_client
|
||||
add_executable(${PROJECT_NAME} "")
|
||||
|
||||
add_subdirectory(common)
|
||||
|
||||
# The subdirectory below can be set to one of IoTHub, DPS or IoTEdge, to include the code
|
||||
# particular to that connectivity scenario.
|
||||
add_subdirectory(IoTHub)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_SOURCE_DIR}/common
|
||||
${AZURE_SPHERE_API_SET_DIR}/usr/include/azureiot
|
||||
${AZURE_SPHERE_API_SET_DIR}/usr/include/azure_prov_client
|
||||
${AZURE_SPHERE_API_SET_DIR}/usr/include/azure_c_shared_utility)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Werror)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC AZURE_IOT_HUB_CONFIGURED)
|
||||
target_link_libraries(${PROJECT_NAME} m azureiot applibs gcc_s c)
|
||||
|
||||
|
@ -36,7 +47,10 @@ find_program(POWERSHELL powershell.exe)
|
|||
if (POWERSHELL)
|
||||
# Run validate_manifest script during build
|
||||
add_custom_target(ValidateManifest ALL
|
||||
COMMAND ${POWERSHELL} -ExecutionPolicy Bypass -NoProfile -NonInteractive -File ${CMAKE_SOURCE_DIR}/script/validate_manifest.ps1
|
||||
COMMAND ${POWERSHELL} -ExecutionPolicy Bypass -NoProfile -NonInteractive
|
||||
-File ${CMAKE_SOURCE_DIR}/script/validate_manifest.ps1
|
||||
-Manifest ${CMAKE_SOURCE_DIR}/app_manifest.json
|
||||
-Helper ${MANIFEST_HELPER}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/app_manifest.json)
|
||||
else()
|
||||
# Warn users without PowerShell to update their manifest
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/options_dps.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/connection_dps.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/connection_dps.h
|
||||
)
|
||||
|
||||
set(MANIFEST_HELPER ${CMAKE_CURRENT_LIST_DIR}/manifest_helper.psm1 PARENT_SCOPE)
|
|
@ -0,0 +1,382 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <applibs/application.h>
|
||||
#include <applibs/log.h>
|
||||
#include <applibs/storage.h>
|
||||
#include <applibs/networking.h>
|
||||
|
||||
// Azure IoT SDK
|
||||
#include <iothub_device_client_ll.h>
|
||||
#include <iothub_client_options.h>
|
||||
#include <iothubtransportmqtt.h>
|
||||
#include <azure_prov_client/prov_device_ll_client.h>
|
||||
#include <azure_prov_client/iothub_security_factory.h>
|
||||
#include <azure_prov_client/prov_security_factory.h>
|
||||
#include <azure_prov_client/prov_transport_mqtt_client.h>
|
||||
#include <shared_util_options.h>
|
||||
|
||||
#include <azure_sphere_provisioning.h>
|
||||
|
||||
#include "exitcodes.h"
|
||||
#include "eventloop_timer_utilities.h"
|
||||
#include "connection.h"
|
||||
#include "connection_dps.h"
|
||||
|
||||
static void InitializeProvisioningClient(void);
|
||||
static void CleanupProvisioningClient(void);
|
||||
static bool IsReadyToProvision(void);
|
||||
static void RegisterDeviceCallback(PROV_DEVICE_RESULT registerResult, const char *callbackHubUri,
|
||||
const char *deviceId, void *userContext);
|
||||
static void ProvisioningTimerHandler(EventLoopTimer *timer);
|
||||
static void TimeoutTimerHandler(EventLoopTimer *timer);
|
||||
static void OnRegisterComplete(void);
|
||||
|
||||
static ExitCode_CallbackType failureCallbackFunction = NULL;
|
||||
static Connection_StatusCallbackType connectionStatusCallback = NULL;
|
||||
|
||||
static bool dpsRegisterCompleted = false;
|
||||
static PROV_DEVICE_RESULT dpsRegisterStatus = PROV_DEVICE_RESULT_INVALID_STATE;
|
||||
|
||||
#define MAX_HUB_URI_LENGTH (512)
|
||||
#define MAX_SCOPEID_LENGTH (32)
|
||||
#define MAX_MODELID_LENGTH (512)
|
||||
|
||||
static char iotHubUri[MAX_HUB_URI_LENGTH + 1];
|
||||
static char scopeId[MAX_SCOPEID_LENGTH + 1];
|
||||
static char azureSphereModelId[MAX_MODELID_LENGTH + 1];
|
||||
|
||||
PROV_DEVICE_LL_HANDLE provHandle = NULL;
|
||||
static const char dpsUrl[] = "global.azure-devices-provisioning.net";
|
||||
|
||||
static EventLoopTimer *provisioningTimer = NULL;
|
||||
static EventLoopTimer *timeoutTimer = NULL;
|
||||
|
||||
MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(PROV_DEVICE_RESULT, PROV_DEVICE_RESULT_VALUE);
|
||||
MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUE);
|
||||
|
||||
ExitCode Connection_Initialise(EventLoop *el, Connection_StatusCallbackType statusCallBack,
|
||||
ExitCode_CallbackType failureCallback, const char *modelId,
|
||||
void *context)
|
||||
{
|
||||
failureCallbackFunction = failureCallback;
|
||||
connectionStatusCallback = statusCallBack;
|
||||
|
||||
Connection_Dps_Config *config = context;
|
||||
|
||||
if (NULL == config) {
|
||||
Log_Debug("ERROR: DPS connection context cannot be NULL.\n");
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
|
||||
if (NULL == config->scopeId) {
|
||||
Log_Debug("ERROR: DPS connection config must specify an ID scope.\n");
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
|
||||
if (strnlen(config->scopeId, MAX_SCOPEID_LENGTH) == MAX_SCOPEID_LENGTH) {
|
||||
Log_Debug("ERROR: ID scope length exceed maximum of %d\n", MAX_SCOPEID_LENGTH);
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
strncpy(scopeId, config->scopeId, MAX_SCOPEID_LENGTH);
|
||||
|
||||
if (NULL != modelId) {
|
||||
if (strnlen(modelId, MAX_MODELID_LENGTH) == MAX_MODELID_LENGTH) {
|
||||
Log_Debug("ERROR: Model ID length exceeds maximum of %d\n", MAX_MODELID_LENGTH);
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
strncpy(azureSphereModelId, modelId, MAX_MODELID_LENGTH);
|
||||
} else {
|
||||
azureSphereModelId[0] = '\0';
|
||||
}
|
||||
|
||||
provisioningTimer = CreateEventLoopDisarmedTimer(el, ProvisioningTimerHandler);
|
||||
|
||||
if (provisioningTimer == NULL) {
|
||||
Log_Debug("ERROR: Failed to create provisioning event loop timer: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
return ExitCode_Connection_CreateTimer;
|
||||
}
|
||||
|
||||
timeoutTimer = CreateEventLoopDisarmedTimer(el, TimeoutTimerHandler);
|
||||
|
||||
if (timeoutTimer == NULL) {
|
||||
Log_Debug("ERROR: Failed to create provisioning timeout timer: %s (%d)\n", strerror(errno),
|
||||
errno);
|
||||
return ExitCode_Connection_CreateTimer;
|
||||
}
|
||||
|
||||
return ExitCode_Success;
|
||||
}
|
||||
|
||||
void Connection_Start(void)
|
||||
{
|
||||
static const long timeoutSec = 10;
|
||||
static const long workDelayMs = 25;
|
||||
|
||||
if (!IsReadyToProvision()) {
|
||||
// If we're not ready to provision, indicate that the connection has failed (which will
|
||||
// cause a retry)
|
||||
connectionStatusCallback(Connection_Failed, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeProvisioningClient();
|
||||
if (provHandle == NULL) {
|
||||
Log_Debug("ERROR: Failed to create and initialize device provisioning client\n");
|
||||
failureCallbackFunction(ExitCode_Connection_InitializeClient);
|
||||
return;
|
||||
}
|
||||
|
||||
const struct timespec sleepTime = {.tv_sec = 0, .tv_nsec = workDelayMs * 1000 * 1000};
|
||||
if (SetEventLoopTimerPeriod(provisioningTimer, &sleepTime) == -1) {
|
||||
Log_Debug("ERROR: Failed to start provisioning event loop timer: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
failureCallbackFunction(ExitCode_Connection_TimerStart);
|
||||
return;
|
||||
}
|
||||
|
||||
const struct timespec timeoutTime = {.tv_sec = timeoutSec, .tv_nsec = 0};
|
||||
if (SetEventLoopTimerOneShot(timeoutTimer, &timeoutTime) == -1) {
|
||||
Log_Debug("ERROR: Failed to start provisioning timeout timer: %s (%d)\n", strerror(errno),
|
||||
errno);
|
||||
failureCallbackFunction(ExitCode_Connection_TimerStart);
|
||||
return;
|
||||
}
|
||||
|
||||
connectionStatusCallback(Connection_Started, NULL);
|
||||
}
|
||||
|
||||
static void ProvisioningTimerHandler(EventLoopTimer *timer)
|
||||
{
|
||||
if (ConsumeEventLoopTimerEvent(timer) != 0) {
|
||||
Log_Debug("ERROR: Failed to consume provisioning timer event: %s (%d)\n", strerror(errno),
|
||||
errno);
|
||||
failureCallbackFunction(ExitCode_Connection_TimerConsume);
|
||||
return;
|
||||
}
|
||||
|
||||
if (provHandle != NULL) {
|
||||
Prov_Device_LL_DoWork(provHandle);
|
||||
}
|
||||
|
||||
if (dpsRegisterCompleted) {
|
||||
DisarmEventLoopTimer(timer);
|
||||
DisarmEventLoopTimer(timeoutTimer);
|
||||
OnRegisterComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static void TimeoutTimerHandler(EventLoopTimer *timer)
|
||||
{
|
||||
if (ConsumeEventLoopTimerEvent(timer) != 0) {
|
||||
Log_Debug("ERROR: Failed to consume provisioning timeout timer event: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
failureCallbackFunction(ExitCode_Connection_TimerConsume);
|
||||
return;
|
||||
}
|
||||
|
||||
DisarmEventLoopTimer(timer);
|
||||
DisarmEventLoopTimer(provisioningTimer);
|
||||
CleanupProvisioningClient();
|
||||
|
||||
Log_Debug("ERROR: Timed out waiting for device provisioning service to provision device\n");
|
||||
connectionStatusCallback(Connection_Failed, NULL);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback that gets called on device registration for provisioning
|
||||
/// </summary>
|
||||
static void RegisterDeviceCallback(PROV_DEVICE_RESULT registerResult, const char *callbackHubUri,
|
||||
const char *deviceId, void *userContext)
|
||||
{
|
||||
dpsRegisterCompleted = true;
|
||||
dpsRegisterStatus = registerResult;
|
||||
|
||||
if (registerResult == PROV_DEVICE_RESULT_OK) {
|
||||
|
||||
Log_Debug("INFO: DPS device registration successful\n");
|
||||
|
||||
if (callbackHubUri != NULL) {
|
||||
size_t uriSize = strlen(callbackHubUri);
|
||||
if (uriSize > MAX_HUB_URI_LENGTH) {
|
||||
Log_Debug("ERROR: IoT Hub URI size (%u bytes) exceeds maximum (%u bytes).\n",
|
||||
uriSize, MAX_HUB_URI_LENGTH);
|
||||
return;
|
||||
}
|
||||
strncpy(iotHubUri, callbackHubUri, strlen(callbackHubUri));
|
||||
} else {
|
||||
Log_Debug("ERROR: Device registration did not return an IoT Hub URI\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsReadyToProvision(void)
|
||||
{
|
||||
bool networkingReady = false;
|
||||
|
||||
// Verifies networking on device
|
||||
if (Networking_IsNetworkingReady(&networkingReady) != 0) {
|
||||
Log_Debug("ERROR: Networking_IsNetworkingReady: %d (%s)\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!networkingReady) {
|
||||
Log_Debug("ERROR: DPS connection - networking not ready.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verifies authentication is ready on device
|
||||
bool currentAppDeviceAuthReady = false;
|
||||
if (Application_IsDeviceAuthReady(¤tAppDeviceAuthReady) != 0) {
|
||||
Log_Debug("ERROR: Application_IsDeviceAuthReady: %d (%s)\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!currentAppDeviceAuthReady) {
|
||||
Log_Debug("ERROR: DPS connection - device auth not ready.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void InitializeProvisioningClient(void)
|
||||
{
|
||||
#define MAX_DTDL_BUFFER_SIZE 64
|
||||
static char dtdlBuffer[MAX_DTDL_BUFFER_SIZE];
|
||||
|
||||
int len =
|
||||
snprintf(dtdlBuffer, MAX_DTDL_BUFFER_SIZE, "{\"modelId\":\"%s\"}", azureSphereModelId);
|
||||
if (len < 0 || len >= MAX_DTDL_BUFFER_SIZE) {
|
||||
Log_Debug("ERROR: Cannot write Model ID to buffer.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Initiate security with X509 Certificate
|
||||
if (prov_dev_security_init(SECURE_DEVICE_TYPE_X509) != 0) {
|
||||
Log_Debug("ERROR: Failed to initiate X509 Certificate security\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Create Provisioning Client for communication with DPS
|
||||
// using MQTT protocol
|
||||
provHandle = Prov_Device_LL_Create(dpsUrl, scopeId, Prov_Device_MQTT_Protocol);
|
||||
if (provHandle == NULL) {
|
||||
Log_Debug("ERROR: Failed to create Provisioning Client\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Use DAA cert in provisioning flow - requires the SetDeviceId option to be set on the
|
||||
// provisioning client.
|
||||
static const int deviceIdForDaaCertUsage = 1;
|
||||
PROV_DEVICE_RESULT prov_result =
|
||||
Prov_Device_LL_SetOption(provHandle, "SetDeviceId", &deviceIdForDaaCertUsage);
|
||||
if (prov_result != PROV_DEVICE_RESULT_OK) {
|
||||
Log_Debug("ERROR: Failed to set Device ID in Provisioning Client\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Sets Model ID provisioning data
|
||||
prov_result = Prov_Device_LL_Set_Provisioning_Payload(provHandle, dtdlBuffer);
|
||||
if (prov_result != PROV_DEVICE_RESULT_OK) {
|
||||
Log_Debug("Error: Failed to set Model ID in Provisioning Client\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Sets the callback function for device registration
|
||||
prov_result =
|
||||
Prov_Device_LL_Register_Device(provHandle, RegisterDeviceCallback, NULL, NULL, NULL);
|
||||
if (prov_result != PROV_DEVICE_RESULT_OK) {
|
||||
Log_Debug("ERROR: Failed to set callback function for device registration\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
CleanupProvisioningClient();
|
||||
}
|
||||
|
||||
static void CleanupProvisioningClient()
|
||||
{
|
||||
if (provHandle != NULL) {
|
||||
Prov_Device_LL_Destroy(provHandle);
|
||||
provHandle = NULL;
|
||||
}
|
||||
|
||||
prov_dev_security_deinit();
|
||||
}
|
||||
|
||||
static void OnRegisterComplete(void)
|
||||
{
|
||||
IOTHUB_DEVICE_CLIENT_LL_HANDLE iothubClientHandle = NULL;
|
||||
|
||||
if (dpsRegisterStatus != PROV_DEVICE_RESULT_OK) {
|
||||
Log_Debug("ERROR: Failed to register device with provisioning service: %s\n",
|
||||
PROV_DEVICE_RESULTStrings(dpsRegisterStatus));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (iotHubUri == NULL) {
|
||||
// Use this as a crude failure indicator for the RegisterDeviceCallback
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
iothubClientHandle =
|
||||
IoTHubDeviceClient_LL_CreateWithAzureSphereFromDeviceAuth(iotHubUri, &MQTT_Protocol);
|
||||
|
||||
if (iothubClientHandle == NULL) {
|
||||
Log_Debug("ERROR: Failed to create client IoT Hub Client Handle\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Use DAA cert when connecting - requires the SetDeviceId option to be set on the
|
||||
// IoT Hub client.
|
||||
static const int deviceIdForDaaCertUsage = 1;
|
||||
IOTHUB_CLIENT_RESULT iothubResult = IoTHubDeviceClient_LL_SetOption(
|
||||
iothubClientHandle, "SetDeviceId", &deviceIdForDaaCertUsage);
|
||||
if (iothubResult != IOTHUB_CLIENT_OK) {
|
||||
IoTHubDeviceClient_LL_Destroy(iothubClientHandle);
|
||||
iothubClientHandle = NULL;
|
||||
Log_Debug("ERROR: Failed to set Device ID on IoT Hub Client: %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Sets auto URL encoding on IoT Hub Client
|
||||
static bool urlAutoEncodeDecode = true;
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(
|
||||
iothubClientHandle, OPTION_AUTO_URL_ENCODE_DECODE, &urlAutoEncodeDecode)) !=
|
||||
IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Failed to set auto Url encode option on IoT Hub Client: %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Sets model ID on IoT Hub Client
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(iothubClientHandle, OPTION_MODEL_ID,
|
||||
azureSphereModelId)) != IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Failed to set the Model ID on IoT Hub Client: %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (iothubClientHandle != NULL) {
|
||||
connectionStatusCallback(Connection_Complete, iothubClientHandle);
|
||||
} else {
|
||||
connectionStatusCallback(Connection_Failed, NULL);
|
||||
}
|
||||
|
||||
CleanupProvisioningClient();
|
||||
}
|
||||
|
||||
void Connection_Cleanup(void) {}
|
|
@ -0,0 +1,11 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/// <summary>
|
||||
/// Context data for required for provisioning and connection via DPS.
|
||||
/// </summary>
|
||||
typedef struct {
|
||||
const char *scopeId;
|
||||
} Connection_Dps_Config;
|
|
@ -0,0 +1,45 @@
|
|||
function Test-CmdArgs {
|
||||
param(
|
||||
[Parameter(Mandatory=$True)] $cmdArgs = $null
|
||||
)
|
||||
|
||||
$errors = @()
|
||||
|
||||
if (-not $cmdArgs.Contains("--ScopeID")) {
|
||||
$errors += "Error: The ID scope for your IoT Central app or DPS instance must be set in the 'CmdArgs' field of your app_manifest.json: `"--ScopeID`", `"<id scope>`""
|
||||
}
|
||||
|
||||
return $errors
|
||||
}
|
||||
|
||||
function Test-AllowedConnections {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)] $allowedConnections = $null
|
||||
)
|
||||
|
||||
$dpsEndpoint = "global.azure-devices-provisioning.net"
|
||||
|
||||
if($allowedConnections -eq $null)
|
||||
{
|
||||
$connectionCount = 0
|
||||
} else {
|
||||
$connectionCount = $allowedConnections.Count
|
||||
}
|
||||
|
||||
$errors = @()
|
||||
|
||||
# Check for Azure DPS endpoint address only if ConnectionType is set to DPS.
|
||||
if ($connectionCount -gt 0 -and $allowedConnections.Contains($dpsEndpoint)) {
|
||||
$connectionCount--
|
||||
} else {
|
||||
$errors += "Error: The 'AllowedConnections' field in your app_manifest.json must contain the Azure DPS endpoint address (global.azure-devices-provisioning.net)"
|
||||
}
|
||||
|
||||
if ($connectionCount -eq 0) {
|
||||
$errors += "Error: The 'AllowedConnections' field in your app_manifest.json must contain your IoT Hub or IoT Central application endpoint address(es)"
|
||||
}
|
||||
|
||||
return $errors
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Test-CmdArgs, Test-AllowedConnections
|
|
@ -0,0 +1,72 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <applibs/log.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "exitcodes.h"
|
||||
#include "connection_dps.h"
|
||||
|
||||
static ExitCode ValidateUserConfiguration(void);
|
||||
|
||||
// Usage text for command line arguments in application manifest.
|
||||
static const char *cmdLineArgsUsageText =
|
||||
"The command line arguments for the application shoud be set in app_manifest.json as below:\n"
|
||||
"\" CmdArgs \": [\"--ScopeID\", \"<scope_id>\"]\n";
|
||||
|
||||
static const char *scopeId = NULL;
|
||||
static Connection_Dps_Config config = {.scopeId = NULL};
|
||||
|
||||
ExitCode Options_ParseArgs(int argc, char *argv[])
|
||||
{
|
||||
int option = 0;
|
||||
static const struct option cmdLineOptions[] = {
|
||||
{.name = "ScopeID", .has_arg = required_argument, .flag = NULL, .val = 's'},
|
||||
{.name = NULL, .has_arg = 0, .flag = NULL, .val = 0}};
|
||||
|
||||
// Loop over all of the options.
|
||||
while ((option = getopt_long(argc, argv, "s:", cmdLineOptions, NULL)) != -1) {
|
||||
// Check if arguments are missing. Every option requires an argument.
|
||||
if (optarg != NULL && optarg[0] == '-') {
|
||||
Log_Debug("WARNING: Option %c requires an argument\n", option);
|
||||
continue;
|
||||
}
|
||||
switch (option) {
|
||||
case 's':
|
||||
Log_Debug("ScopeID: %s\n", optarg);
|
||||
scopeId = optarg;
|
||||
break;
|
||||
default:
|
||||
// Unknown options are ignored.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ValidateUserConfiguration();
|
||||
}
|
||||
|
||||
void *Options_GetConnectionContext(void)
|
||||
{
|
||||
return (void *)&config;
|
||||
}
|
||||
|
||||
static ExitCode ValidateUserConfiguration(void)
|
||||
{
|
||||
ExitCode validationExitCode = ExitCode_Success;
|
||||
|
||||
if (scopeId == NULL) {
|
||||
validationExitCode = ExitCode_Validate_ScopeId;
|
||||
} else {
|
||||
Log_Debug("Using DPS Connection: Azure IoT DPS Scope ID %s\n", scopeId);
|
||||
config.scopeId = scopeId;
|
||||
}
|
||||
|
||||
if (validationExitCode != ExitCode_Success) {
|
||||
Log_Debug(cmdLineArgsUsageText);
|
||||
}
|
||||
|
||||
return validationExitCode;
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
# Run the sample with Azure IoT Central
|
||||
|
||||
**IMPORTANT**:
|
||||
- Follow the instructions in the [README.md](./README.md) file before you perform any of the steps described here.
|
||||
- This sample uses the latest IoT Central message syntax and will not work with IoT Central applications created on or before July 7th, 2020. To run this sample with an older IoT Central application, follow the steps in the [Build and run the sample](#build-and-run-the-sample) section.
|
||||
|
||||
To run the sample with Azure IoT Central, you must:
|
||||
|
||||
- Create an Azure IoT Central application.
|
||||
- Configure the Azure IoT Central application.
|
||||
- Set up Azure IoT Central to work with your Azure Sphere tenant.
|
||||
- Configure the sample application to work with your Azure Sphere tenant and devices.
|
||||
|
||||
You can then build and run the application. Later, you can enhance the Azure IoT Central application to support additional features.
|
||||
|
||||
## Create an Azure IoT Central application
|
||||
|
||||
1. Go to [Azure IoT Central](https://apps.azureiotcentral.com/build) in your browser.
|
||||
|
||||
1. Select **Custom apps** and sign in with your Microsoft account, or create a new account.
|
||||
|
||||
1. On the **Build** > **New application–Custom** page, use the default **Application name** and **URL** or modify them, if you prefer.
|
||||
|
||||
1. Under **Application template**, select **Custom application**.
|
||||
|
||||
1. Under **Pricing plan**, select **Free**, or select one of the **Standard** plans and provide your billing information.
|
||||
|
||||
1. Click **Create** at the bottom of the page to complete the operation.
|
||||
|
||||
## Configure your Azure IoT Central application
|
||||
|
||||
1. On the Dashboard for your application, select **Device Templates**.
|
||||
|
||||
![Create Device Templates button](media/CreateDeviceTemplate.png)
|
||||
|
||||
1. On the **Select type** page, select **Azure Sphere Sample Device**. After making your selection, click **Next: Review** > **Create**.
|
||||
|
||||
1. On the device templates page for your Azure Sphere Sample Device, add two views to the sample device: one to send a command to the device, and another to show temperature and button press data.
|
||||
|
||||
- To set up a view to send a command to the device, select **Views** > **Editing device and cloud data**.
|
||||
- Customize the **Form name** with "StatusLED".
|
||||
- Under **Property**, select **Status LED**, then **Add section**, and then click **Save** in the ribbon at the top of the form.
|
||||
|
||||
![Create Edit Device and Cloud Data View](media/FormView.png)
|
||||
|
||||
- To set up a view of temperature and button press telemetry, select **Views** > **Visualizing the device**.
|
||||
- Customize the **View name** with "Temp and button press data".
|
||||
- Under **Telemetry**, use the dropdown menu to select **Temperature**, then **Add tile**.
|
||||
- Under **Telemetry**, use the dropdown menu to select **Button Press**, then **Add tile**.
|
||||
- Click **Save** in the ribbon at the top of the form.
|
||||
|
||||
![Set temperature and button press telemetry](media/iotc-set-temp-and-button-press-telemetry.png)
|
||||
|
||||
1. Click **Publish** from the top menu bar so the device template can be used in the Azure IoT Central application.
|
||||
|
||||
![Publish temperature and button press telemetry](media/iotc-publish-temp-and-button-press-telemetry.png)
|
||||
|
||||
## Set up Azure IoT Central to work with Azure Sphere
|
||||
|
||||
Verify the identity of your Azure Sphere tenant by following the steps in [set up Azure IoT Central](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-central#step-2-download-the-tenant-authentication-ca-certificate). Start at step 2 and perform steps 2-5.
|
||||
|
||||
## Configure the sample application to work with your Azure Sphere tenant and devices
|
||||
|
||||
To configure the sample application, update the following parameters in the app_manifest.json file for AzureIoT:
|
||||
|
||||
- The allowed connections for your Azure Sphere device.
|
||||
- The Scope ID for your Azure IoT Central application.
|
||||
- The Tenant ID for your Azure Sphere device.
|
||||
|
||||
Follow these steps to gather the information and configure the application:
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it.
|
||||
|
||||
1. At the command prompt, run the ShowIoTCentralConfig program from the Windows or Linux folder in the sample repository. For example, on Windows, the path is Samples\AzureIoT\Tools\win-x64\ShowIoTCentralConfig.exe. When running this tool on a Linux machine you may need to explicitly set permissions. For example, from a terminal, run `chmod +x ShowIoTCentralConfig` to set permissions on the tool.
|
||||
|
||||
Now follow the prompts that the tool provides, and copy the information from the output into the app_manifest.json file. The tool will require the following input:
|
||||
|
||||
- The **IoT Central App URL** can be found in your browser address bar; for example, `https://myiotcentralapp.azureiotcentral.com/`.
|
||||
|
||||
- The **API token** can be generated from your IoT Central application. In the Azure IoT Central application, select **Administration** > **API Tokens** > **Generate Token**, and then provide a name for the token; for example, "AzureSphereSample." Select **Administrator** as the role, and then click **Generate**. Copy the token to the clipboard. The token starts with **SharedAccessSignature**.
|
||||
|
||||
- The **ID Scope** is in the Azure IoT Central application. Select **Administration** > **Device Connection** and then copy the **ID Scope**.
|
||||
|
||||
1. At the command prompt, run the following command to get the Tenant ID:
|
||||
|
||||
`azsphere tenant show-selected`
|
||||
|
||||
Paste the GUID for your tenant into the **DeviceAuthentication** field of the app_manifest.json file.
|
||||
|
||||
Your updated app-manifest.json file should look like the following example:
|
||||
|
||||
![Example app_manifest.json file](media/iot-correct-app-manifest-json-file.png)
|
||||
|
||||
1. Save the updated application manifest.
|
||||
|
||||
1. Ensure that the **Auto approve** option is enabled. From the Azure IoT Central Application, click **Administration** > **Device connection**, then on the **Auto approve** option, select **Enabled**.
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
1. If you are using an IoT Central application that was created on or before July 7th, 2020, please make the following updates to the main.c file.
|
||||
- Open main.c and locate lines 751-762:
|
||||
```c
|
||||
int statusLedValue = json_object_dotget_boolean(desiredProperties, "StatusLED");
|
||||
if (statusLedValue != -1) {
|
||||
statusLedOn = statusLedValue == 1;
|
||||
GPIO_SetValue(deviceTwinStatusLedGpioFd, statusLedOn ? GPIO_Value_Low : GPIO_Value_High);
|
||||
}
|
||||
|
||||
// Report current status LED state
|
||||
if (statusLedOn) {
|
||||
TwinReportState("{\"StatusLED\":true}");
|
||||
} else {
|
||||
TwinReportState("{\"StatusLED\":false}");
|
||||
}
|
||||
```
|
||||
- Replace lines 751-762 with the following code:
|
||||
```c
|
||||
JSON_Object *LEDState = json_object_dotget_object(desiredProperties, "StatusLED");
|
||||
if (LEDState != NULL) {
|
||||
// ... with a "value" field which is a Boolean
|
||||
int statusLedValue = json_object_get_boolean(LEDState, "value");
|
||||
if (statusLedValue != -1) {
|
||||
statusLedOn = statusLedValue == 1;
|
||||
GPIO_SetValue(deviceTwinStatusLedGpioFd,
|
||||
statusLedOn ? GPIO_Value_Low : GPIO_Value_High);
|
||||
}
|
||||
}
|
||||
|
||||
// Report current status LED state
|
||||
if (statusLedOn) {
|
||||
TwinReportState("{\"StatusLED\":{\"value\":true}}");
|
||||
} else {
|
||||
TwinReportState("{\"StatusLED\":{\"value\":false}}");
|
||||
}
|
||||
```
|
||||
- The application is now configured to run with the old IoT Central message format. For more information, please see the [IoT Central messaging documentation](https://docs.microsoft.com/azure/iot-central/core/concepts-telemetry-properties-commands).
|
||||
|
||||
1. Ensure that your device is connected to the internet.
|
||||
|
||||
1. Follow the steps in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
1. See [Troubleshooting samples](../troubleshooting.md) if you encounter errors.
|
||||
|
||||
1. When the application starts, you should see output showing that the button and an LED have been opened, and that device authentication returned `AZURE_SPHERE_PROV_RESULT_OK`. The application then starts to send periodic messages with simulated temperatures to IoT Central.
|
||||
|
||||
1. Press button A. Device output shows the following message:
|
||||
|
||||
```
|
||||
Sending Azure IoT Hub telemetry: { "ButtonPress": "True" }
|
||||
INFO: IoTHubClient accepted the telemetry event for delivery
|
||||
```
|
||||
|
||||
## Show your device data in Azure IoT Central
|
||||
|
||||
1. In your Azure IoT Central application, select **Devices** > **All Devices**. You should see your device listed as Unassociated and Unassigned. If you don’t see this, refresh the page.
|
||||
|
||||
1. Select your device and then select **Migrate**. Select the Azure Sphere Sample Device template, and click **Migrate**.
|
||||
|
||||
1. To view output from your Azure Sphere device, select **Devices** > **Azure Sphere Sample Device** and then select your device. You may change the device name at this point by selecting the name, modifying it, and selecting anywhere on the screen to save.
|
||||
|
||||
1. Select **View**, which is on the menu bar just under the device name. Note that the device is sending simulated temperatures at regular intervals. Each time you press button A, an event is added to the button press graph. The graphs show data averaged over 30 seconds and not every individual event will be visible on the graphs. To see the count of button presses, hover the cursor over the chart. Note that you will not see previous data on the Button Press chart initially and will instead see "Waiting for data".
|
||||
|
||||
1. Turn on an LED on your Azure Sphere device from the Azure IoT Central application. Select the **Form** tab, click the **Status LED** checkbox, and then select **Save**. In a few seconds, the LED will light up.
|
||||
|
||||
1. Trigger an alarm from the Azure IoT Central application. Select the **Command** tab and then click **Run**. Select the small history icon in the right corner of the Interface/Trigger Alarm box. This will show you the response to command from your sphere device. The device output will show the following message:
|
||||
|
||||
```
|
||||
----- ALARM TRIGGERED! -----
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. The following message in device output indicates a connection error:
|
||||
|
||||
`IOTHUB_CLIENT_NO_CONNECTION`
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The **AllowedConnections** field has not been properly updated in the application manifest .json file.
|
||||
|
||||
The application may generate output like "IoTHubClient accepted the message for delivery" while telemetry is generated. This indicates that the IoTHubClient has accepted the message for delivery but the data has not yet been sent to the IoT hub.
|
||||
|
||||
1. The following message in device output indicates an authentication error:
|
||||
|
||||
`IoTHubDeviceClient_LL_CreateWithAzureSphereDeviceAuthProvisioning returned 'AZURE_SPHERE_PROV_RESULT_DEVICEAUTH_NOT_READY'.`
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The correct tenant ID is not present in the **DeviceAuthentication** field of the application manifest .json file.
|
||||
- The device has not been claimed.
|
||||
- When using the Azure IoT C SDK to connect to IoT Hub or IoT Central using device provisioning service, you must implement connection retry logic using your application. If you rely on internal retry logic, you may see an authentication error.
|
||||
|
||||
1. The following message in device output indicates a device provisioning error:
|
||||
|
||||
`IoTHubDeviceClient_LL_CreateWithAzureSphereDeviceAuthProvisioning returned 'AZURE_SPHERE_PROV_RESULT_PROV_DEVICE_ERROR'.`
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The [setup for Azure IoT Central](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-central) has not been completed.
|
|
@ -1,160 +0,0 @@
|
|||
# Run the sample with IoT Edge
|
||||
|
||||
**IMPORTANT**: Follow the instructions in the [README.md](./README.md) file before you perform any of the steps described here.
|
||||
|
||||
This sample connects to an IoT Edge device acting as a transparent gateway.
|
||||
|
||||
## Before you begin
|
||||
|
||||
Before you run the sample with IoT Edge, you must:
|
||||
|
||||
- Create an Azure IoT Hub and an Azure IoT Edge device.
|
||||
- Configure the IoT Edge device as a transparent gateway.
|
||||
- Set up your Azure Sphere device in IoT hub and authenticate it.
|
||||
- Configure the sample application with information about your Azure Sphere tenant and your IoT Edge device.
|
||||
|
||||
You can then build the application and, if you want to, use a device twin to support additional features. For more information about device twins, see [Understand and use device twins in IoT hub](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-device-twins).
|
||||
|
||||
## Set up the IoT Edge device as a transparent gateway, Azure IoT Hub and Azure Sphere device in Azure IoT Hub
|
||||
|
||||
Follow the steps in [Set up Azure IoT Edge for Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-edge) to set up your IoT Edge device as a transparent gateway, as well as an Azure IoT Hub, and your Azure Sphere device in Azure IoT Hub. When given the option, follow the Quickstart instructions.
|
||||
|
||||
## Configure the sample application to work with your IoT Edge device
|
||||
|
||||
### Modify the app manifest file of the sample
|
||||
|
||||
To configure the sample to connect to an IoT Edge device, you will need the following information:
|
||||
|
||||
- The Tenant ID for your Azure Sphere device.
|
||||
- The Device ID of your Azure Sphere device.
|
||||
- The Azure IoT Hub server hostname for your IoT hub.
|
||||
- The connection type to use when connecting to your IoT Edge device.
|
||||
|
||||
Follow these steps to gather the information and configure the application:
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it.
|
||||
|
||||
1. Update the **CmdArgs** field of the app_manifest.json file:
|
||||
|
||||
- To configure the sample to connect to your IoT Edge device, copy and paste the following line into the **CmdArgs** field of the app_manifest.json file:
|
||||
|
||||
`"--ConnectionType", "IoTEdge"`
|
||||
|
||||
- Copy the DNS name of your IoT Edge device and paste it into the **CmdArgs** field of the app_manifest.json file as an argument to the Hostname option, as shown below:
|
||||
|
||||
`"--Hostname", "<iotedgedevice_hostname>"`
|
||||
|
||||
If using the virtual machine as your IoT Edge device, log in to the Azure portal. You will find the DNS name on the summary screen at the top right of your virtual machine.
|
||||
|
||||
- Provide the root CA certificate of IoT Edge device to the Azure Sphere device.
|
||||
- Put the trusted root CA certificate of the IoT Edge device in the certs/ folder.
|
||||
- Copy the name of the certificate and paste it into the **CmdArgs** field of the app_manifest.json file as an argument to the IoTEdgeRootCAPath option, as shown below:
|
||||
|
||||
`"--IoTEdgeRootCAPath", "certs/<iotedgedevice_cert_name>"`
|
||||
|
||||
If you used the scripts provided in the IoT Edge git repository to create test certificates, then the root CA certificate is called *azure-iot-test-only.root.ca.cert.pem*
|
||||
|
||||
- Each command line option must be surrounded by double quotes. Separate command line options with a comma.
|
||||
|
||||
- Your **CmdArgs** field should now look like this:
|
||||
|
||||
`"CmdArgs": [ "--ConnectionType", "IoTEdge", "--Hostname", "<iotedgedevice_hostname>", "--IoTEdgeRootCAPath", "certs/<iotedgedevice_cert_name>" ]`
|
||||
|
||||
1. Update the **AllowedConnections** field of the app_manifest.json file.
|
||||
|
||||
- Copy the DNS name of your IoT Edge device used in the **CmdArgs** section and append it to the **AllowedConnections** field of the app_manifest.json file.
|
||||
|
||||
- Each connection must be surrounded by double quotes. Separate connections with a comma.
|
||||
|
||||
- Your **AllowedConnections** field should now look like this:
|
||||
|
||||
`"AllowedConnections": [ "<iot_edge_device>" ]`
|
||||
|
||||
1. Update the **DeviceAuthentication** field of the app_manifest.json file.
|
||||
|
||||
- At the command prompt, run the following command to get the Tenant ID. Use the GUID, not the friendly name, and paste it into the **DeviceAuthentication** field of the app_manifest.json file:
|
||||
|
||||
`azsphere tenant show-selected`
|
||||
|
||||
- Your **DeviceAuthentication** field should now look like this:
|
||||
|
||||
`"DeviceAuthentication": "<GUID>"`
|
||||
|
||||
1. Save the modified app_manifest.json file.
|
||||
|
||||
### Modify the CMakeLists.txt file of the sample
|
||||
|
||||
To include the root CA certificate of your IoT Edge device in the application package, update the
|
||||
|
||||
`azsphere_target_add_image_package` in CMakeLists.txt as shown below:
|
||||
|
||||
`azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/<iotedgedevice_cert_name>")`
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
1. Ensure that your device is connected to the internet.
|
||||
|
||||
1. Follow the steps in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
1. See [Troubleshooting samples](../troubleshooting.md) if you encounter errors.
|
||||
|
||||
1. After a short delay, the sample app will display output messages like:
|
||||
|
||||
**INFO: Azure IoT Hub send telemetry: { "Temperature": "33.85" }**
|
||||
|
||||
1. Press button A on the MT3620 development board to send a button-press notification to the IoT Hub. The sample app will display an output message indicating a button-press:
|
||||
|
||||
**Sending Azure IoT Hub telemetry: { "ButtonPress": "True" }**
|
||||
|
||||
## Edit device twin to change properties
|
||||
|
||||
You can now edit the device twin to change properties. For example, follow these steps to turn LED 1 on or off by changing a property in the device twin:
|
||||
|
||||
1. Log in to the [Azure Portal](https://portal.azure.com) and select your IoT Hub resource.
|
||||
|
||||
1. On the left-side menu under **Explorers**, select **IoT Devices**, and then double-click the Device ID for your device.
|
||||
|
||||
1. On the **Device Details** page, select **Device Twin**.
|
||||
|
||||
1. In the **properties** field, under **"desired"**, add `"StatusLED": true,` as shown below:
|
||||
|
||||
```json
|
||||
"properties": {
|
||||
"desired": {
|
||||
"StatusLED": true,
|
||||
"$metadata": {
|
||||
"$lastUpdated": "2019-01-30T22:18:19.612025Z",
|
||||
```
|
||||
|
||||
1. Click **Save** to update the twin and notify the application.
|
||||
In a few seconds, the LED will light up red.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. The following message in device output indicates a connection error with the IoT Edge device:
|
||||
|
||||
```
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
```
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- Inbound port 8883 has not been opened on the IoT Edge device. For more information, see [Open IoT Edge gateway device ports for communication](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-edge#step-3-open-iot-edge-gateway-device-ports-for-communication).
|
||||
- The sample is using the incorrect/invalid IoT Edge device root CA certificate.
|
||||
- The **edgeAgent** and **edgeHub** modules are not running on the IoT Edge device.
|
||||
|
||||
1. The following message in device output indicates a device provisioning error:
|
||||
|
||||
```
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL
|
||||
```
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The Azure Sphere device is not manually provisioned. For corrective action, follow the steps to [authenticate using a direct connection](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub#authenticate-using-a-direct-connection).
|
|
@ -0,0 +1,8 @@
|
|||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/options_iot_edge.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/connection_iot_edge.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/connection_iot_edge.h
|
||||
)
|
||||
|
||||
set(MANIFEST_HELPER ${CMAKE_CURRENT_LIST_DIR}/manifest_helper.psm1 PARENT_SCOPE)
|
|
@ -0,0 +1,278 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <applibs/application.h>
|
||||
#include <applibs/log.h>
|
||||
#include <applibs/storage.h>
|
||||
#include <applibs/networking.h>
|
||||
|
||||
// Azure IoT SDK
|
||||
#include <iothub_device_client_ll.h>
|
||||
#include <iothub_client_options.h>
|
||||
#include <iothubtransportmqtt.h>
|
||||
#include <azure_sphere_provisioning.h>
|
||||
#include <azure_prov_client/iothub_security_factory.h>
|
||||
#include <shared_util_options.h>
|
||||
|
||||
#include "exitcodes.h"
|
||||
|
||||
#include "connection.h"
|
||||
#include "connection_iot_edge.h"
|
||||
|
||||
#define MAX_ROOT_CA_CERT_CONTENT_SIZE (3 * 1024)
|
||||
#define MAX_HOSTNAME_LENGTH (256)
|
||||
#define MAX_MODELID_LENGTH (512)
|
||||
|
||||
static char hostname[MAX_HOSTNAME_LENGTH + 1];
|
||||
static char iotEdgeRootCACertContent[MAX_ROOT_CA_CERT_CONTENT_SIZE +
|
||||
1]; // Add 1 to account for null terminator.
|
||||
static char azureSphereModelId[MAX_MODELID_LENGTH + 1];
|
||||
|
||||
IOTHUB_DEVICE_CLIENT_LL_HANDLE iothubClientHandle;
|
||||
|
||||
static const int deviceIdForDaaCertUsage = 1; // A constant used to direct the IoT SDK to use
|
||||
// the DAA cert under the hood.
|
||||
|
||||
static Connection_StatusCallbackType connectionStatusCallback = NULL;
|
||||
|
||||
static bool SetUpAzureIoTHubClientWithDaa(void);
|
||||
static ExitCode ReadIoTEdgeCaCertContent(const char *certPath);
|
||||
static bool IsReadyToConnect(void);
|
||||
|
||||
MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUE);
|
||||
|
||||
ExitCode Connection_Initialise(EventLoop *el, Connection_StatusCallbackType statusCallBack,
|
||||
ExitCode_CallbackType failureCallback, const char *modelId,
|
||||
void *context)
|
||||
{
|
||||
(void)failureCallback;
|
||||
connectionStatusCallback = statusCallBack;
|
||||
|
||||
if (NULL != modelId) {
|
||||
if (strnlen(modelId, MAX_MODELID_LENGTH) == MAX_MODELID_LENGTH) {
|
||||
Log_Debug("ERROR: Model ID length exceeds maximum of %d\n", MAX_MODELID_LENGTH);
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
strncpy(azureSphereModelId, modelId, MAX_MODELID_LENGTH);
|
||||
} else {
|
||||
azureSphereModelId[0] = '\0';
|
||||
}
|
||||
|
||||
Connection_IotEdge_Config *config = context;
|
||||
if (NULL == config) {
|
||||
Log_Debug("ERROR: IoT Edge connection context cannot be NULL.\n");
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
|
||||
if (NULL == config->edgeDeviceHostname) {
|
||||
Log_Debug("ERROR: IoT Edge connection config must specify a hostname.\n");
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
|
||||
if (NULL == config->iotEdgeCACertPath) {
|
||||
Log_Debug(
|
||||
"ERROR: IoT Edge connection config must specify a path to a root CA certificate.\n");
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
|
||||
if (strnlen(config->edgeDeviceHostname, MAX_HOSTNAME_LENGTH) == MAX_HOSTNAME_LENGTH) {
|
||||
Log_Debug("ERROR: Specified IoT Edge device hostname exceeds maximum length '%d'.\n",
|
||||
MAX_HOSTNAME_LENGTH);
|
||||
return ExitCode_Validate_Hostname;
|
||||
}
|
||||
|
||||
strncpy(hostname, config->edgeDeviceHostname, MAX_HOSTNAME_LENGTH);
|
||||
|
||||
return ReadIoTEdgeCaCertContent(config->iotEdgeCACertPath);
|
||||
}
|
||||
|
||||
void Connection_Start(void)
|
||||
{
|
||||
connectionStatusCallback(Connection_Started, NULL);
|
||||
|
||||
if (SetUpAzureIoTHubClientWithDaa()) {
|
||||
connectionStatusCallback(Connection_Complete, iothubClientHandle);
|
||||
} else {
|
||||
connectionStatusCallback(Connection_Failed, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void Connection_Cleanup(void) {}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the Azure IoT Hub connection (creates the iothubClientHandle)
|
||||
/// with DAA
|
||||
/// </summary>
|
||||
static bool SetUpAzureIoTHubClientWithDaa(void)
|
||||
{
|
||||
bool retVal = true;
|
||||
|
||||
// If network/DAA are not ready, fail out (which will trigger a retry)
|
||||
if (!IsReadyToConnect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up auth type
|
||||
int retError = iothub_security_init(IOTHUB_SECURITY_TYPE_X509);
|
||||
if (retError != 0) {
|
||||
Log_Debug("ERROR: iothub_security_init failed with error %d.\n", retError);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create Azure Iot Hub client handle
|
||||
iothubClientHandle =
|
||||
IoTHubDeviceClient_LL_CreateWithAzureSphereFromDeviceAuth(hostname, MQTT_Protocol);
|
||||
|
||||
if (iothubClientHandle == NULL) {
|
||||
Log_Debug("IoTHubDeviceClient_LL_CreateFromDeviceAuth returned NULL.\n");
|
||||
retVal = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT iothubResult;
|
||||
// Enable DAA cert usage when x509 is invoked
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(
|
||||
iothubClientHandle, "SetDeviceId", &deviceIdForDaaCertUsage)) != IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Failure setting Azure IoT Hub client option \"SetDeviceId\": %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
retVal = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Provide the Azure IoT device client with the IoT Edge root
|
||||
// X509 CA certificate that was used to setup the IoT Edge runtime.
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(iothubClientHandle, OPTION_TRUSTED_CERT,
|
||||
iotEdgeRootCACertContent)) !=
|
||||
IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Failure setting Azure IoT Hub client option \"TrustedCerts\": %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
retVal = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Set the auto URL Encoder (recommended for MQTT).
|
||||
bool urlEncodeOn = true;
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(
|
||||
iothubClientHandle, OPTION_AUTO_URL_ENCODE_DECODE, &urlEncodeOn)) !=
|
||||
IOTHUB_CLIENT_OK) {
|
||||
Log_Debug(
|
||||
"ERROR: Failure setting Azure IoT Hub client option "
|
||||
"\"OPTION_AUTO_URL_ENCODE_DECODE\": %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
retVal = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Sets model ID on IoT Hub Client
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(iothubClientHandle, OPTION_MODEL_ID,
|
||||
azureSphereModelId)) != IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Failed to set the Model ID on IoT Hub Client: %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
iothub_security_deinit();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check networking and DAA status before connection
|
||||
/// </summary>
|
||||
/// <returns>True if networking and DAA are ready; false otherwise.</returns>
|
||||
static bool IsReadyToConnect(void)
|
||||
{
|
||||
bool networkingReady = false;
|
||||
|
||||
// Verifies networking on device
|
||||
if (Networking_IsNetworkingReady(&networkingReady) != 0) {
|
||||
Log_Debug("ERROR: Networking_IsNetworkingReady: %d (%s)\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!networkingReady) {
|
||||
Log_Debug("ERROR: IoT Edge connection - networking not ready.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verifies authentication is ready on device
|
||||
bool currentAppDeviceAuthReady = false;
|
||||
if (Application_IsDeviceAuthReady(¤tAppDeviceAuthReady) != 0) {
|
||||
Log_Debug("ERROR: Application_IsDeviceAuthReady: %d (%s)\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!currentAppDeviceAuthReady) {
|
||||
Log_Debug("ERROR: IoT Edge connection - device auth not ready.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the certificate file and provide a null terminated string containing the certificate.
|
||||
/// The function logs an error and returns an error code if it cannot allocate enough memory to
|
||||
/// hold the certificate content.
|
||||
/// </summary>
|
||||
/// <returns>ExitCode_Success on success, any other exit code on error</returns>
|
||||
static ExitCode ReadIoTEdgeCaCertContent(const char *iotEdgeRootCAPath)
|
||||
{
|
||||
int certFd = -1;
|
||||
off_t fileSize = 0;
|
||||
|
||||
certFd = Storage_OpenFileInImagePackage(iotEdgeRootCAPath);
|
||||
if (certFd == -1) {
|
||||
Log_Debug("ERROR: Storage_OpenFileInImagePackage failed with error code: %d (%s).\n", errno,
|
||||
strerror(errno));
|
||||
return ExitCode_IoTEdgeRootCa_Open_Failed;
|
||||
}
|
||||
|
||||
// Get the file size.
|
||||
fileSize = lseek(certFd, 0, SEEK_END);
|
||||
if (fileSize == -1) {
|
||||
Log_Debug("ERROR: lseek SEEK_END: %d (%s)\n", errno, strerror(errno));
|
||||
close(certFd);
|
||||
return ExitCode_IoTEdgeRootCa_LSeek_Failed;
|
||||
}
|
||||
|
||||
// Reset the pointer to start of the file.
|
||||
if (lseek(certFd, 0, SEEK_SET) < 0) {
|
||||
Log_Debug("ERROR: lseek SEEK_SET: %d (%s)\n", errno, strerror(errno));
|
||||
close(certFd);
|
||||
return ExitCode_IoTEdgeRootCa_LSeek_Failed;
|
||||
}
|
||||
|
||||
if (fileSize == 0) {
|
||||
Log_Debug("File size invalid for %s\r\n", iotEdgeRootCAPath);
|
||||
close(certFd);
|
||||
return ExitCode_IoTEdgeRootCa_FileSize_Invalid;
|
||||
}
|
||||
|
||||
if (fileSize > MAX_ROOT_CA_CERT_CONTENT_SIZE) {
|
||||
Log_Debug("File size for %s is %lld bytes. Max file size supported is %d bytes.\r\n",
|
||||
iotEdgeRootCAPath, fileSize, MAX_ROOT_CA_CERT_CONTENT_SIZE);
|
||||
close(certFd);
|
||||
return ExitCode_IoTEdgeRootCa_FileSize_TooLarge;
|
||||
}
|
||||
|
||||
// Copy the file into the buffer.
|
||||
ssize_t read_size = read(certFd, &iotEdgeRootCACertContent, (size_t)fileSize);
|
||||
if (read_size != (size_t)fileSize) {
|
||||
Log_Debug("Error reading file %s\r\n", iotEdgeRootCAPath);
|
||||
close(certFd);
|
||||
return ExitCode_IoTEdgeRootCa_FileRead_Failed;
|
||||
}
|
||||
|
||||
// Add the null terminator at the end.
|
||||
iotEdgeRootCACertContent[fileSize] = '\0';
|
||||
|
||||
close(certFd);
|
||||
return ExitCode_Success;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/// <summary>
|
||||
/// Context data required for connecting to an Azure IoT Edge device
|
||||
/// </summary>
|
||||
typedef struct {
|
||||
const char *iotEdgeCACertPath;
|
||||
const char *edgeDeviceHostname;
|
||||
} Connection_IotEdge_Config;
|
|
@ -0,0 +1,33 @@
|
|||
function Test-CmdArgs {
|
||||
param(
|
||||
$cmdArgs
|
||||
)
|
||||
|
||||
$errors = @()
|
||||
|
||||
if (-not $cmdArgs.Contains("--Hostname")) {
|
||||
$errors += "Error: The hostname of your Azure IoT Edge device must be set in the 'CmdArgs' field of your app_manifest.json: `"--Hostname`",`"<hub_hostname>`""
|
||||
}
|
||||
if (-not $cmdArgs.Contains("--IoTEdgeRootCAPath")) {
|
||||
$errors += "Error: The path to the root CA certificate for your IoT Edge device must be set in the 'CmdArgs' field on your app_manifest.json: `"--IoTEdgeRootCAPath`", `"<path to .pem file>`""
|
||||
}
|
||||
|
||||
return $errors
|
||||
}
|
||||
|
||||
function Test-AllowedConnections {
|
||||
param(
|
||||
$allowedConnections
|
||||
)
|
||||
|
||||
$errors = @()
|
||||
|
||||
if (($allowedConnections -eq $null) -or
|
||||
($allowedConnections.Count -eq 0)) {
|
||||
$errors += "Error: The 'AllowedConnections' field of your app_manifest.json must contain your IoT edge device address(es)"
|
||||
}
|
||||
|
||||
return $errors
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Test-CmdArgs, Test-AllowedConnections
|
|
@ -0,0 +1,92 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <applibs/log.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "connection_iot_edge.h"
|
||||
|
||||
// Usage text for command line arguments in application manifest.
|
||||
static const char *cmdLineArgsUsageText =
|
||||
"The command line arguments for the application shoud be set in app_manifest.json as below:\n"
|
||||
"\" CmdArgs \": [\"--Hostname\", \"<iotedgedevice_hostname>\", "
|
||||
"\"--IoTEdgeRootCAPath\", \"certs/<iotedgedevice_cert_name>\"]\n";
|
||||
|
||||
static char *hostname = NULL; // IoT Edge Hostname.
|
||||
static char *iotEdgeRootCAPath = NULL;
|
||||
|
||||
static ExitCode ValidateUserConfiguration(void);
|
||||
|
||||
static Connection_IotEdge_Config config = {.edgeDeviceHostname = NULL, .iotEdgeCACertPath = NULL};
|
||||
|
||||
/// <summary>
|
||||
/// Parse the command line arguments given in the application manifest.
|
||||
/// </summary>
|
||||
ExitCode Options_ParseArgs(int argc, char *argv[])
|
||||
{
|
||||
int option = 0;
|
||||
static const struct option cmdLineOptions[] = {
|
||||
{.name = "Hostname", .has_arg = required_argument, .flag = NULL, .val = 'h'},
|
||||
{.name = "IoTEdgeRootCAPath", .has_arg = required_argument, .flag = NULL, .val = 'i'},
|
||||
{.name = NULL, .has_arg = 0, .flag = NULL, .val = 0}};
|
||||
|
||||
// Loop over all of the options.
|
||||
while ((option = getopt_long(argc, argv, "h:i:", cmdLineOptions, NULL)) != -1) {
|
||||
// Check if arguments are missing. Every option requires an argument.
|
||||
if (optarg != NULL && optarg[0] == '-') {
|
||||
Log_Debug("WARNING: Option %c requires an argument\n", option);
|
||||
continue;
|
||||
}
|
||||
switch (option) {
|
||||
case 'h':
|
||||
Log_Debug("IoT Edge Device Hostname: %s\n", optarg);
|
||||
hostname = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
Log_Debug("IoT Edge Root CA Path: %s\n", optarg);
|
||||
iotEdgeRootCAPath = optarg;
|
||||
break;
|
||||
default:
|
||||
// Unknown options are ignored.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ValidateUserConfiguration();
|
||||
}
|
||||
|
||||
void *Options_GetConnectionContext(void)
|
||||
{
|
||||
return (void *)&config;
|
||||
}
|
||||
|
||||
static ExitCode ValidateUserConfiguration(void)
|
||||
{
|
||||
ExitCode validationExitCode = ExitCode_Success;
|
||||
|
||||
if (hostname == NULL) {
|
||||
validationExitCode = ExitCode_Validate_Hostname;
|
||||
}
|
||||
|
||||
if (iotEdgeRootCAPath == NULL) {
|
||||
validationExitCode = ExitCode_Validate_IoTEdgeCAPath;
|
||||
}
|
||||
|
||||
if (validationExitCode == ExitCode_Success) {
|
||||
Log_Debug(
|
||||
"Using IoT Edge Connection: IoT Edge device Hostname %s, trusted CA cert path %s\n",
|
||||
hostname, iotEdgeRootCAPath);
|
||||
config.edgeDeviceHostname = hostname;
|
||||
config.iotEdgeCACertPath = iotEdgeRootCAPath;
|
||||
}
|
||||
|
||||
if (validationExitCode != ExitCode_Success) {
|
||||
Log_Debug(cmdLineArgsUsageText);
|
||||
}
|
||||
|
||||
return validationExitCode;
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
# Run the sample with an IoT Hub
|
||||
|
||||
**IMPORTANT**: Follow the instructions in the [README.md](./README.md) file before you perform any of the steps described here.
|
||||
|
||||
This sample can connect to the IoT Hub in two ways. It can connect directly to an IoT Hub with a device manually provisioned, or it can connect using the device provisioning service.
|
||||
|
||||
## Before you begin
|
||||
|
||||
Before you run the sample with an IoT Hub:
|
||||
|
||||
- Configure an IoT Hub to work with Azure Sphere based on how you want to connect to your IoT Hub. The device provisioning service is the recommended authentication method.
|
||||
- Configure the sample application with information about your Azure Sphere tenant and your IoT Hub.
|
||||
|
||||
You can then build the application and, if you want to, use a device twin to support additional features. For more information about device twins, see [Understand and use device twins in IoT Hub](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-device-twins).
|
||||
|
||||
## Configure an IoT Hub
|
||||
|
||||
You must set up an IoT Hub for Azure Sphere, if you have not already done so.
|
||||
|
||||
To set up an IoT Hub where the sample application connects to the IoT Hub using the device provisioning service, [use device provisioning service to authenticate.](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub#authenticate-using-the-device-provisioning-service) Note that the device provisioning service is the recommended authentication method.
|
||||
|
||||
To set up an IoT Hub where the sample application connects directly to the IoT Hub, [use a direct connection to authenticate.](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub#authenticate-using-a-direct-connection)
|
||||
|
||||
## Configure the sample application to work with your Azure IoT Hub
|
||||
|
||||
To configure the sample application, you'll need to update some information in the app_manifest.json file for AzureIoT. The type of information depends on the connection type to the IoT Hub.
|
||||
|
||||
### Connect to the IoT Hub using the device provisioning service
|
||||
|
||||
To connect using the device provisioning service, you will need the following information:
|
||||
|
||||
- The Tenant ID for your Azure Sphere device.
|
||||
- The Scope ID for your device provisioning service instance.
|
||||
- The Azure IoT Hub URL for your IoT Hub and the global access link to device provisioning service (global.azure-devices.provisioning.net).
|
||||
- The connection type to use when connecting to the IoT Hub.
|
||||
|
||||
Use the following steps to gather the information and configure the application:
|
||||
|
||||
1. Log in to the [Azure Portal](https://portal.azure.com) and navigate to your device provisioning service. You will need to refer to service details while configuring the application.
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it.
|
||||
|
||||
1. Update the **CmdArgs** field of the app_manifest.json file.
|
||||
- To configure the sample to use the device provisioning service to connect to the Azure IoT Hub, copy and paste the following line into the **CmdArgs** field of the app_manifest.json file:
|
||||
|
||||
`"--ConnectionType", "DPS"`
|
||||
|
||||
- In the Azure portal, on the summary screen at the top right of your device provisioning service, copy the ID Scope value and append it to the **CmdArgs** field of the app_manifest.json file as shown below:
|
||||
|
||||
`"--ScopeID", "<scope_id>"`
|
||||
|
||||
- You can also find the ID Scope value in Visual Studio Cloud Explorer. Expand **IoT Hub Device Provisioning Services** under **Azure Sphere Product Services** in Cloud Explorer, then select your device provisioning service. Click the **Properties** tab in the lower pane of Cloud Explorer and look for ID Scope in the list of properties.
|
||||
|
||||
- Each command line option must be surrounded by double quotes. Separate command line options with a comma.
|
||||
|
||||
- Your **CmdArgs** field should now look like:
|
||||
|
||||
`"CmdArgs": [ "--ConnectionType", "DPS", "--ScopeID", "<scope_id>" ]`
|
||||
1. Update the **AllowedConnections** field of the app_manifest.json file.
|
||||
|
||||
- On the Azure portal, under **Settings** of your device provisioning service, select **Linked IoT Hubs**. Copy the Name values(s) for the Azure IoT Hub(s) and append them to the **AllowedConnections** field of the app_manifest.json file.
|
||||
|
||||
- Make sure that global.azure-devices-provisioning.net remains in the list; this name is required for access to the device provisioning service.
|
||||
|
||||
- Each connection must be surrounded by double quotes. Separate connections with a comma.
|
||||
|
||||
- Your **AllowedConnections** field should now look like:
|
||||
|
||||
`"AllowedConnections": [ "global.azure-devices-provisioning.net", "<linked_iot_hub>" ]`
|
||||
|
||||
1. Update the **DeviceAuthentication** field of the app_manifest.json file.
|
||||
|
||||
- At the command prompt, use the following command to get the Tenant ID. Use the GUID, not the friendly name, and paste it into the **DeviceAuthentication** field of the app_manifest.json file:
|
||||
|
||||
`azsphere tenant show-selected`
|
||||
|
||||
- Your **DeviceAuthentication** field should now look like:
|
||||
|
||||
`"DeviceAuthentication": "<GUID>"`
|
||||
|
||||
1. Save the modified app_manifest.json file.
|
||||
|
||||
### Connect to the IoT Hub directly
|
||||
|
||||
To configure a direct connection to IoT Hub, you will need the following information:
|
||||
|
||||
- The Tenant ID for your Azure Sphere device.
|
||||
- The Device ID of your Azure Sphere device.
|
||||
- The Azure IoT Hub server hostname for your IoT Hub.
|
||||
- The connection type to use when connecting to the IoT Hub.
|
||||
|
||||
Follow these steps to gather the information and configure the application:
|
||||
|
||||
1. Log in to the Azure Portal and navigate to your Azure IoT Hub. You will need to refer to this later while configuring the application.
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it.
|
||||
|
||||
1. Update the **CmdArgs** field of the app_manifest.json file:
|
||||
- To configure the sample to connect directly to the IoT Hub, copy and paste the following line into the **CmdArgs** field of the app_manifest.json file:
|
||||
|
||||
`"--ConnectionType", "Direct"`
|
||||
|
||||
- In the Azure portal, on the summary screen at the top right of your device provisioning service, copy the Hostname of Azure IoT Hub and paste it into the **CmdArgs** field of the app_manifest.json file as an argument to the Hostname option, as shown below:
|
||||
|
||||
`"--Hostname", "<azure_iot_hub_hostname>"`
|
||||
|
||||
- Each command line option must be surrounded by double quotes. Separate command line options with a comma.
|
||||
|
||||
- Your **CmdArgs** field should now look like:
|
||||
|
||||
`"CmdArgs": [ "--ConnectionType", "Direct", "--Hostname", "<azure_iot_hub_hostname>" ]`
|
||||
|
||||
1. Update the **AllowedConnections** field of the app_manifest.json file.
|
||||
|
||||
- Copy the hostname used in the **CmdArgs** section and append it to the **AllowedConnections** field of the app_manifest.json file.
|
||||
|
||||
- Each connection must be surrounded by double quotes. Separate connections with a comma.
|
||||
|
||||
- Your **AllowedConnections** field should now look like:
|
||||
|
||||
`"AllowedConnections": [ "<azure_iot_hub_hostname>" ]`
|
||||
|
||||
1. Update the **DeviceAuthentication** field of the app_manifest.json file.
|
||||
|
||||
- At the command prompt, run the following command to get the Tenant ID. Use the GUID, not the friendly name, and paste it into the **DeviceAuthentication** field of the app_manifest.json file:
|
||||
|
||||
`azsphere tenant show-selected`
|
||||
|
||||
- Your **DeviceAuthentication** field should now look like:
|
||||
|
||||
`"DeviceAuthentication": "<GUID>"`
|
||||
|
||||
1. Save the modified app_manifest.json file.
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
1. Ensure that your device is connected to the internet.
|
||||
|
||||
1. Follow the steps in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
1. See [Troubleshooting samples](../troubleshooting.md) if you encounter errors.
|
||||
|
||||
1. After a short delay, the sample app will display output messages like:
|
||||
|
||||
**INFO: Azure IoT Hub send telemetry: { "Temperature": "33.85" }**
|
||||
|
||||
1. Press button A on the MT3620 development board to send a button-press notification to the IoT Hub. The sample app will display an output message indicating a button-press:
|
||||
|
||||
**Sending Azure IoT Hub telemetry: { "ButtonPress": "True" }**
|
||||
|
||||
## Edit device twin to change properties
|
||||
|
||||
You can now edit the device twin to change properties. For example, follow these steps to turn LED 1 on or off by changing a property in the device twin:
|
||||
|
||||
1. Log in to the [Azure Portal](https://portal.azure.com) and select your IoT Hub resource.
|
||||
|
||||
1. On the left-side menu under **Explorers**, select **IoT Devices**, and then double-click the Device ID for your device.
|
||||
|
||||
1. On the **Device Details** page, select **Device Twin**.
|
||||
|
||||
1. In the **properties** field, under **"desired"**, add `"StatusLED": true,` as shown below:
|
||||
|
||||
```json
|
||||
"properties": {
|
||||
"desired": {
|
||||
"StatusLED": true,
|
||||
"$metadata": {
|
||||
"$lastUpdated": "2019-01-30T22:18:19.612025Z",
|
||||
```
|
||||
|
||||
1. Click **Save** to update the twin and notify the application.
|
||||
In a few seconds, the LED will light up red.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. The following message in device output indicates a connection error:
|
||||
|
||||
`IOTHUB_CLIENT_NO_CONNECTION`
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The **AllowedConnections** field has not been properly updated in the application manifest .json file.
|
||||
|
||||
The application may generate output like "IoTHubClient accepted the message for delivery" while telemetry is generated. This indicates that the IoTHubClient has accepted the message for delivery but the data has not yet been sent to the IoT hub.
|
||||
|
||||
1. The following message in device output indicates an authentication error:
|
||||
|
||||
'IoTHubDeviceClient_LL_CreateWithAzureSphereDeviceAuthProvisioning returned 'AZURE_SPHERE_PROV_RESULT_DEVICEAUTH_NOT_READY'.'
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The correct Tenant ID is not present in the **DeviceAuthentication** field of the application manifest.
|
||||
- The device has not been claimed.
|
||||
- When using the Azure IoT C SDK to connect to IoT Hub or IoT Central using device provisioning service, you must implement connection retry logic using your application. If you rely on internal retry logic, you may see an authentication error.
|
||||
|
||||
1. The following message in device output indicates a device provisioning error:
|
||||
|
||||
'IoTHubDeviceClient_LL_CreateWithAzureSphereDeviceAuthProvisioning returned 'AZURE_SPHERE_PROV_RESULT_PROV_DEVICE_ERROR'.'
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- [Azure IoT Hub](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub) setup has not been completed.
|
|
@ -0,0 +1,8 @@
|
|||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/options_iot_hub.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/connection_iot_hub.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/connection_iot_hub.h
|
||||
)
|
||||
|
||||
set(MANIFEST_HELPER ${CMAKE_CURRENT_LIST_DIR}/manifest_helper.psm1 PARENT_SCOPE)
|
|
@ -0,0 +1,185 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <applibs/application.h>
|
||||
#include <applibs/log.h>
|
||||
#include <applibs/storage.h>
|
||||
#include <applibs/networking.h>
|
||||
|
||||
// Azure IoT SDK
|
||||
#include <iothub_device_client_ll.h>
|
||||
#include <iothub_client_options.h>
|
||||
#include <iothubtransportmqtt.h>
|
||||
#include <azure_sphere_provisioning.h>
|
||||
#include <azure_prov_client/iothub_security_factory.h>
|
||||
#include <shared_util_options.h>
|
||||
|
||||
#include "exitcodes.h"
|
||||
|
||||
#include "connection.h"
|
||||
#include "connection_iot_hub.h"
|
||||
|
||||
#define MAX_HOSTNAME_LENGTH (256)
|
||||
#define MAX_MODELID_LENGTH (512)
|
||||
|
||||
static char hostname[MAX_HOSTNAME_LENGTH + 1];
|
||||
static char azureSphereModelId[MAX_MODELID_LENGTH + 1];
|
||||
|
||||
IOTHUB_DEVICE_CLIENT_LL_HANDLE iothubClientHandle;
|
||||
|
||||
static Connection_StatusCallbackType connectionStatusCallback = NULL;
|
||||
|
||||
static bool SetUpAzureIoTHubClientWithDaa(void);
|
||||
static bool IsReadyToConnect(void);
|
||||
|
||||
MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUE);
|
||||
|
||||
ExitCode Connection_Initialise(EventLoop *el, Connection_StatusCallbackType statusCallBack,
|
||||
ExitCode_CallbackType failureCallback, const char *modelId,
|
||||
void *context)
|
||||
{
|
||||
(void)failureCallback;
|
||||
connectionStatusCallback = statusCallBack;
|
||||
|
||||
if (NULL != modelId) {
|
||||
if (strnlen(modelId, MAX_MODELID_LENGTH) == MAX_MODELID_LENGTH) {
|
||||
Log_Debug("ERROR: Model ID length exceeds maximum of %d\n", MAX_MODELID_LENGTH);
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
strncpy(azureSphereModelId, modelId, MAX_MODELID_LENGTH);
|
||||
} else {
|
||||
azureSphereModelId[0] = '\0';
|
||||
}
|
||||
|
||||
Connection_IotHub_Config *config = context;
|
||||
|
||||
if (NULL == config) {
|
||||
Log_Debug("ERROR: IoT Hub connection context cannot be NULL.\n");
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
|
||||
if (NULL == config->hubHostname) {
|
||||
Log_Debug("ERROR: IoT Hub connection config must specify a hostname.\n");
|
||||
return ExitCode_Validate_ConnectionConfig;
|
||||
}
|
||||
|
||||
if (strnlen(config->hubHostname, MAX_HOSTNAME_LENGTH) == MAX_HOSTNAME_LENGTH) {
|
||||
Log_Debug("ERROR: Specified IoT hub hostname exceeds maximum length '%d'.\n",
|
||||
MAX_HOSTNAME_LENGTH);
|
||||
return ExitCode_Validate_Hostname;
|
||||
}
|
||||
|
||||
strncpy(hostname, config->hubHostname, MAX_HOSTNAME_LENGTH);
|
||||
|
||||
return ExitCode_Success;
|
||||
}
|
||||
|
||||
void Connection_Start(void)
|
||||
{
|
||||
connectionStatusCallback(Connection_Started, NULL);
|
||||
|
||||
if (SetUpAzureIoTHubClientWithDaa()) {
|
||||
connectionStatusCallback(Connection_Complete, iothubClientHandle);
|
||||
} else {
|
||||
connectionStatusCallback(Connection_Failed, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void Connection_Cleanup(void) {}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the Azure IoT Hub connection (creates the iothubClientHandle)
|
||||
/// with DAA
|
||||
/// </summary>
|
||||
static bool SetUpAzureIoTHubClientWithDaa(void)
|
||||
{
|
||||
bool retVal = true;
|
||||
|
||||
// If network/DAA are not ready, fail out (which will trigger a retry)
|
||||
if (!IsReadyToConnect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up auth type
|
||||
int retError = iothub_security_init(IOTHUB_SECURITY_TYPE_X509);
|
||||
if (retError != 0) {
|
||||
Log_Debug("ERROR: iothub_security_init failed with error %d.\n", retError);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create Azure Iot Hub client handle
|
||||
iothubClientHandle =
|
||||
IoTHubDeviceClient_LL_CreateWithAzureSphereFromDeviceAuth(hostname, MQTT_Protocol);
|
||||
|
||||
if (iothubClientHandle == NULL) {
|
||||
Log_Debug("ERROR: IoTHubDeviceClient_LL_CreateFromDeviceAuth returned NULL.\n");
|
||||
retVal = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT iothubResult;
|
||||
|
||||
// Use DAA cert when connecting - requires the SetDeviceId option to be set on the
|
||||
// IoT Hub client.
|
||||
static const int deviceIdForDaaCertUsage = 1;
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(
|
||||
iothubClientHandle, "SetDeviceId", &deviceIdForDaaCertUsage)) != IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Failure setting Azure IoT Hub client option \"SetDeviceId\": %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
retVal = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Sets model ID on IoT Hub Client
|
||||
if ((iothubResult = IoTHubDeviceClient_LL_SetOption(iothubClientHandle, OPTION_MODEL_ID,
|
||||
azureSphereModelId)) != IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Failed to set the Model ID on IoT Hub Client: %s\n",
|
||||
IOTHUB_CLIENT_RESULTStrings(iothubResult));
|
||||
retVal = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
iothub_security_deinit();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check networking and DAA status before connection
|
||||
/// </summary>
|
||||
/// <returns>True if networking and DAA are ready; false otherwise.</returns>
|
||||
static bool IsReadyToConnect(void)
|
||||
{
|
||||
bool networkingReady = false;
|
||||
|
||||
// Verifies networking on device
|
||||
if (Networking_IsNetworkingReady(&networkingReady) != 0) {
|
||||
Log_Debug("ERROR: Networking_IsNetworkingReady: %d (%s)\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!networkingReady) {
|
||||
Log_Debug("ERROR: IoT Hub connection - networking not ready.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verifies authentication is ready on device
|
||||
bool currentAppDeviceAuthReady = false;
|
||||
if (Application_IsDeviceAuthReady(¤tAppDeviceAuthReady) != 0) {
|
||||
Log_Debug("ERROR: Application_IsDeviceAuthReady: %d (%s)\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!currentAppDeviceAuthReady) {
|
||||
Log_Debug("ERROR: IoT Hub connection - device auth not ready.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/// <summary>
|
||||
/// Context data required for connecting directly to an Azure IoT Hub
|
||||
/// </summary>
|
||||
typedef struct {
|
||||
const char *hubHostname;
|
||||
} Connection_IotHub_Config;
|
|
@ -0,0 +1,30 @@
|
|||
function Test-CmdArgs {
|
||||
param(
|
||||
$cmdArgs
|
||||
)
|
||||
|
||||
$errors = @()
|
||||
|
||||
if (-not $cmdArgs.Contains("--Hostname")) {
|
||||
$errors += "Error: The hostname of your Azure IoT Hub must be set in the 'CmdArgs' field of your app_manifest.json: `"--Hostname`",`"<hub_hostname>`""
|
||||
}
|
||||
|
||||
return $errors
|
||||
}
|
||||
|
||||
function Test-AllowedConnections {
|
||||
param(
|
||||
$allowedConnections
|
||||
)
|
||||
|
||||
$errors = @()
|
||||
|
||||
if (($allowedConnections -eq $null) -or
|
||||
($allowedConnections.Count -eq 0)) {
|
||||
$errors += "Error: The 'AllowedConnections' field of your app_manifest.json must contain the address of your Azure IoT Hub"
|
||||
}
|
||||
|
||||
return $errors
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Test-CmdArgs, Test-AllowedConnections
|
|
@ -0,0 +1,73 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <applibs/log.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "connection_iot_hub.h"
|
||||
|
||||
// Usage text for command line arguments in application manifest.
|
||||
static const char *cmdLineArgsUsageText =
|
||||
"The command line arguments for the application shoud be set in app_manifest.json as below:\n"
|
||||
"\" CmdArgs \": [\"--Hostname\", \"<azureiothub_hostname>\"]\n";
|
||||
|
||||
static char *hostname = NULL; // Azure IoT Hub Hostname.
|
||||
|
||||
static ExitCode ValidateUserConfiguration(void);
|
||||
|
||||
static Connection_IotHub_Config config = {.hubHostname = NULL};
|
||||
|
||||
/// <summary>
|
||||
/// Parse the command line arguments given in the application manifest.
|
||||
/// </summary>
|
||||
ExitCode Options_ParseArgs(int argc, char *argv[])
|
||||
{
|
||||
int option = 0;
|
||||
static const struct option cmdLineOptions[] = {
|
||||
{.name = "Hostname", .has_arg = required_argument, .flag = NULL, .val = 'h'},
|
||||
{.name = NULL, .has_arg = 0, .flag = NULL, .val = 0}};
|
||||
|
||||
// Loop over all of the options.
|
||||
while ((option = getopt_long(argc, argv, "h:", cmdLineOptions, NULL)) != -1) {
|
||||
// Check if arguments are missing. Every option requires an argument.
|
||||
if (optarg != NULL && optarg[0] == '-') {
|
||||
Log_Debug("WARNING: Option %c requires an argument\n", option);
|
||||
continue;
|
||||
}
|
||||
switch (option) {
|
||||
case 'h':
|
||||
Log_Debug("Hostname: %s\n", optarg);
|
||||
hostname = optarg;
|
||||
break;
|
||||
default:
|
||||
// Unknown options are ignored.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ValidateUserConfiguration();
|
||||
}
|
||||
|
||||
void *Options_GetConnectionContext(void)
|
||||
{
|
||||
return (void *)&config;
|
||||
}
|
||||
|
||||
static ExitCode ValidateUserConfiguration(void)
|
||||
{
|
||||
ExitCode validationExitCode = ExitCode_Success;
|
||||
|
||||
if (hostname == NULL) {
|
||||
validationExitCode = ExitCode_Validate_Hostname;
|
||||
Log_Debug(cmdLineArgsUsageText);
|
||||
} else {
|
||||
Log_Debug("Using Direct Connection: Azure IoT Hub Hostname %s\n", hostname);
|
||||
config.hubHostname = hostname;
|
||||
}
|
||||
|
||||
return validationExitCode;
|
||||
}
|
|
@ -18,83 +18,95 @@ extendedZipContent:
|
|||
target: SECURITY.md
|
||||
- path: Samples/troubleshooting.md
|
||||
target: troubleshooting.md
|
||||
- path: ethernet-setup-instructions.md
|
||||
target: ethernet-setup-instructions.md
|
||||
description: "Demonstrates how to use the Azure IoT APIs to communicate with Azure IoT Central or Azure IoT Hub."
|
||||
---
|
||||
|
||||
# Sample: Azure IoT
|
||||
|
||||
This sample demonstrates how to use the Azure IoT SDK C APIs in an Azure Sphere application to communicate with Azure IoT Central or Azure IoT Hub. This sample can connect to the IoT hub in two ways. It can connect directly to an IoT hub with a device manually provisioned, or it can connect using the device provisioning service.
|
||||
This sample demonstrates how to use the Azure IoT SDK C APIs in an Azure Sphere application to communicate with [Azure IoT Hub](https://docs.microsoft.com/azure/iot-fundamentals/iot-introduction) or [Azure IoT Central](https://docs.microsoft.com/azure/iot-central/core/overview-iot-central).
|
||||
|
||||
**IMPORTANT**: This sample application requires customization before it will compile and run. Follow the instructions in this README and in IoTCentral.md and/or IoTHub.md and/or IoTEdge.md to perform the necessary steps.
|
||||
**IMPORTANT**: Before you can compile and run the sample, you must configure an Azure IoT Hub application, and customize the sample to connect to it. Carefully follow the instructions in this README and in its linked topics.
|
||||
|
||||
This application does the following:
|
||||
## Overview
|
||||
|
||||
- Sends simulated temperature telemetry data to Azure IoT Central or an Azure IoT hub at regular intervals.
|
||||
- Sends a button-press event to Azure IoT Central or an Azure IoT hub when you press button A on the MT3620 development board.
|
||||
- Sends a simulated orientation state to Azure IoT Central or an Azure IoT hub when you press button B on the MT3620 development board.
|
||||
- Controls one of the LEDs on the MT3620 development board when you change a toggle setting on Azure IoT Central or when you edit the device twin on Azure IoT hub.
|
||||
This sample application implements an example *thermometer* that works with Azure IoT Hub as follows:
|
||||
|
||||
Before you can run the sample, you must configure either an Azure IoT Central application or an Azure IoT Hub, and modify the sample's application manifest to enable it to connect to the Azure IoT resources that you configured.
|
||||
1. Sends simulated *temperature* telemetry data at regular intervals.
|
||||
1. Sends a simulated *thermometer moved* telemetry event when button B is pressed.
|
||||
1. Reports a read-only string *serial number* device twin.
|
||||
1. Synchronizes a read/write boolean *Thermometer Telemetry Upload Enabled* device twin.
|
||||
- This status is reflected by one of the LEDs on the MT3620 development board.
|
||||
- This status can be turned on/off via the cloud or on the device itself by pressing button A.
|
||||
1. Implements a *display alert* direct method. For example, a cloud solution could call this method when it receives a temperature reading that is higher than a given threshold.
|
||||
1. Declares that it implements the *Azure Sphere Example Thermometer* model, consisting of this telemetry, device twin, and direct method by sending its [Azure IoT Plug and Play (PnP)](https://docs.microsoft.com/azure/iot-pnp/overview-iot-plug-and-play) model ID upon connection.
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, make the following changes:
|
||||
## Application libraries
|
||||
|
||||
1. Configure Azure Sphere as described in [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet).
|
||||
1. Add an Ethernet adapter to your hardware. If you are using an MT3620 RDB, see the [wiring instructions](../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
1. Add the following line to the Capabilities section of the app_manifest.json file:
|
||||
|
||||
`"NetworkConfig" : true`
|
||||
|
||||
1. In main.c, ensure that the global constant networkInterface is set to "eth0". In source file AzureIoT/main.c, search for the following line:
|
||||
|
||||
`static const char networkInterface[] = "wlan0";`
|
||||
|
||||
and change it to:
|
||||
|
||||
`static const char networkInterface[] = "eth0";`
|
||||
|
||||
1. In main.c, add the following lines before any other networking calls:
|
||||
|
||||
```c
|
||||
int err = Networking_SetInterfaceState("eth0", true);
|
||||
if (err == -1) {
|
||||
Log_Debug("Error setting interface state %d\n",errno);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
The sample uses the following Azure Sphere application libraries:
|
||||
This sample uses the following Azure Sphere application libraries:
|
||||
|
||||
|Library |Purpose |
|
||||
|---------|---------|
|
||||
|log | Displays messages in the Device Output window during debugging |
|
||||
| networking | Determines whether the device is connected to the internet |
|
||||
| gpio | Manages buttons A and B and LED 4 on the device |
|
||||
| storage | Opens the certificate file that is used to authenticate to the IoT Edge device |
|
||||
|[log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Determines whether the device is connected to the internet |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages buttons A and B and LED 4 on the device |
|
||||
| [storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Opens the certificate file that is used to authenticate to the IoT Edge device |
|
||||
| [EventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events |
|
||||
|
||||
## Contents
|
||||
|
||||
| File | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. | `README.md` | This README file. |
|
||||
| `READMEStartwithIoTCentral.md` | Instructions for customizing the sample to run with Azure IoT Central. |
|
||||
| `READMEAddIoTEdge.md` | Instructions for customizing the sample to run with an Azure IoT Edge device. |
|
||||
| `READMEStartwithIoTHub.md` | Instructions for customizing the sample to run with Azure IoT Hub. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The sample requires the following software:
|
||||
This sample requires the following software and hardware:
|
||||
|
||||
- Azure Sphere SDK version 21.01 or higher. At the command prompt, run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk), if necessary.
|
||||
- An Azure subscription. If your organization does not already have one, you can set up a [free trial subscription](https://azure.microsoft.com/free/?v=17.15).
|
||||
- **Azure Sphere SDK version 21.04 or higher**. At the command prompt, run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) to check your SDK version. Install the latest [Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk), if necessary.
|
||||
- **An Azure subscription**. If your organization does not already have a subscription, you can set up a [free trial subscription](https://azure.microsoft.com/free/?v=17.15).
|
||||
|
||||
**Note**: By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, like the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../HardwareDefinitions/README.md).
|
||||
|
||||
## Preparation
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, like the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../HardwareDefinitions/README.md).
|
||||
Complete the following steps to prepare your environment:
|
||||
|
||||
1. Set up your Azure Sphere device and development environment as described in [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *AzureIoT* sample in the *AzureIoT* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/azureiot/).
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *AzureIoT* sample in the *AzureIoT* folder or download the zip file from the [Microsoft samples browser](/samples/azure/azure-sphere-samples/azureiot/).
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Enable a network interface on your Azure Sphere device and verify that it is connected to the internet.
|
||||
1. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview) and [enable application development](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) on your device if you have not already done so:
|
||||
1. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview) and [enable application development](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) on your device if you have not already done so by entering the following command:
|
||||
|
||||
```
|
||||
azsphere device enable-development
|
||||
```
|
||||
`azsphere device enable-development`
|
||||
|
||||
### Use Ethernet instead of Wi-Fi
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, follow the [Ethernet setup instructions](../../ethernet-setup-instructions.md).
|
||||
|
||||
## Run the sample
|
||||
|
||||
- [Run the sample with Azure IoT Central](./IoTCentral.md)
|
||||
- [Run the sample with an Azure IoT Hub](./IoTHub.md)
|
||||
- [Run the sample with an IoT Edge device](./IoTEdge.md)
|
||||
You can use either Azure IoT Hub or Azure IoT Central to configure the sample:
|
||||
|
||||
1. [Run the sample by connecting to an Azure IoT Hub](./READMEStartWithIoTHub.md).
|
||||
|
||||
- To change your device authentication method to use device provisioning service instead of direct authentication, see [Connect via Azure IoT Hub device provisioning service](./READMEAddDPS.md).
|
||||
- To add an IoT Edge device that provides a filtering and data processing layer between your Azure Sphere device and IoT Hub, see [Connect via Azure IoT Edge](./READMEAddIoTEdge.md).
|
||||
|
||||
1. [Run the sample by connecting to an Azure IoT Central application](./READMEStartWithIoTCentral.md).
|
||||
|
||||
## Next steps
|
||||
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- See the [Azure Sphere Gallery](https://github.com/Azure/azure-sphere-gallery#azure-sphere-gallery), a collection of unmaintained scripts, utilities, and functions.
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
# Add support to the sample for connecting via Azure IoT Hub device provisioning service
|
||||
|
||||
## Step 1. Start with the Azure IoT README topic
|
||||
|
||||
Follow the instructions in the [READMEStartWithHub.md](./READMEStartWithHub.md) file before you perform any of the steps described here.
|
||||
|
||||
## Step 2. Configure the device provisioning service
|
||||
|
||||
You must [set up the device provisioning service to provision your Azure Sphere devices into your IoT Hub(s)](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub?tabs=cliv2beta#authenticate-using-the-device-provisioning-service), if you have not already done so.
|
||||
|
||||
## Step 3. Update the sample application to connect via device provisioning service
|
||||
|
||||
By default, the application's top-level CMakeLists.txt pulls in code to connect directly to an IoT Hub. You'll need to modify this CMakeLists.txt to pull in the code for device provisioning service instead, and change some information in the app_manifest.json file:
|
||||
|
||||
1. Find the CMakeLists.txt file in your sample directory and open it.
|
||||
|
||||
1. Change the *add_subdirectory* CMake function call so that it no longer adds the code in the "IoTHub" directory and instead adds the code in the "DPS" subdirectory. The call should now look like this:
|
||||
|
||||
`add_subdirectory(DPS)`
|
||||
|
||||
1. After making the changes, save the modified CMakeLists.txt file.
|
||||
|
||||
1. Log in to the [Azure Portal](https://portal.azure.com) and navigate to your device provisioning service. You will need to refer to service details while configuring the application.
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it. In the following steps, you'll add the following information to this file:
|
||||
|
||||
- The Scope ID for your device provisioning service.
|
||||
- The allowed connections for your Azure Sphere device.
|
||||
|
||||
1. Update the *CmdArgs* field of the app_manifest.json file.
|
||||
|
||||
- In the Azure portal, on the summary screen at the top right of your device provisioning service, copy the ID Scope value and add it to the *CmdArgs* field of the app_manifest.json file, removing any direct configuration of the Hub hostname, as shown below:
|
||||
|
||||
`"CmdArgs": [ "--ScopeID", "<scope_id>" ]`
|
||||
|
||||
1. Update the *AllowedConnections* field of the app_manifest.json file.
|
||||
|
||||
- Add "global.azure-devices-provisioning.net" to the list of connections in the *AllowedConnections* field.
|
||||
|
||||
- In the Azure portal, under **Settings** of your device provisioning service, click **Linked IoT Hubs**. Copy the Name values for the Azure IoT Hub and append them to the *AllowedConnections* field of the app_manifest.json file, if they are not there already.
|
||||
|
||||
- Each connection must be surrounded by double quotes. Separate connections with a comma.
|
||||
|
||||
- Your *AllowedConnections* field should now look like:
|
||||
|
||||
`"AllowedConnections": [ "global.azure-devices-provisioning.net", "<linked_iot_hub>" ]`
|
||||
|
||||
1. Save the modified app_manifest.json file.
|
||||
|
||||
## Step 4. Re-build and re-run the sample
|
||||
|
||||
Repeat the steps to [build and run the sample](./READMEStartWithIoTHub.md#Step-4.-build-and-run-the-sample).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For common errors and corrective action, see [Troubleshooting](./troubleshooting.md).
|
||||
|
||||
## Next steps
|
||||
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- See the [Azure Sphere Gallery](https://github.com/Azure/azure-sphere-gallery#azure-sphere-gallery), a collection of unmaintained scripts, utilities, and functions.
|
|
@ -0,0 +1,76 @@
|
|||
# Add support to the sample for connecting via Azure IoT Edge
|
||||
|
||||
## Step 1. Start with the Azure IoT README topic
|
||||
|
||||
Follow the instructions in the [READMEStartWithIoTHub.md](./READMEStartWithIoTHub.md) file before you perform any of the steps described here.
|
||||
|
||||
## Step 2. Set up the IoT Edge device as a transparent gateway
|
||||
|
||||
Follow the steps in [Set up Azure IoT Edge for Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-edge) to set up your IoT Edge device as a transparent gateway.
|
||||
|
||||
## Step 3. Update the sample application to connect via your IoT Edge device
|
||||
|
||||
By default, the application's top-level CMakeLists.txt pulls in code to connect directly to an IoT Hub. You'll need to modify this CMakeLists.txt to pull in the code to connect via IoT Edge instead, add the root CA certificate of the IoT Edge device. You'll also need to change some information in the app_manifest.json file:
|
||||
|
||||
1. Put the IoT Edge device's root CA certificate in the certs/ directory of the application. If you used the scripts provided in the IoT Edge git repository to create test certificates, then the root CA certificate is called *azure-iot-test-only.root.ca.cert.pem*.
|
||||
|
||||
1. Find the CMakeLists.txt file in your sample directory and open it.
|
||||
|
||||
1. Change the add_subdirectory CMake function call so that it no longer adds the code in the "IoTHub" directory and instead adds the code in the "IoTEdge" subdirectory. The call should now look like this:
|
||||
|
||||
`add_subdirectory(IoTEdge)`
|
||||
|
||||
1. Include the root CA certificate by updating the CMake function call that creates the application image package.
|
||||
|
||||
`azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/<iotedgedevice_cert_name>")`
|
||||
|
||||
1. Save the modified CMakeLists.txt file.
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it.
|
||||
|
||||
1. Update the *CmdArgs* field of the app_manifest.json file.
|
||||
|
||||
- Copy the DNS name of your IoT Edge device and paste it into the *CmdArgs* field of the app_manifest.json file as an argument to the Hostname option, as shown below:
|
||||
|
||||
`"--Hostname", "<iotedgedevice_hostname>"`
|
||||
|
||||
If using the virtual machine as your IoT Edge device, log in to the Azure portal. You will find the DNS name on the summary screen at the top right of your virtual machine.
|
||||
|
||||
- Provide the root CA certificate of the IoT Edge device to the Azure Sphere device.
|
||||
- Put this certificate in the certs/ directory of the application.
|
||||
- Copy the name of the certificate and paste it into the *CmdArgs* field of the app_manifest.json file as an argument to the IoTEdgeRootCAPath option, as shown below:
|
||||
|
||||
`"--IoTEdgeRootCAPath", "certs/<iotedgedevice_cert_name>"`
|
||||
|
||||
If you used the scripts provided in the IoT Edge git repository to create test certificates, then the root CA certificate is called *azure-iot-test-only.root.ca.cert.pem*.
|
||||
|
||||
- Each command line option must be surrounded by double quotes. Separate command line options with a comma.
|
||||
|
||||
- Your *CmdArgs* field should now look like this:
|
||||
|
||||
`"CmdArgs": [ "--Hostname", "<iotedgedevice_hostname>", "--IoTEdgeRootCAPath", "certs/<iotedgedevice_cert_name>" ]`
|
||||
|
||||
1. Update the *AllowedConnections* field of the app_manifest.json file.
|
||||
|
||||
- Copy the DNS name of your IoT Edge device used in the *CmdArgs* section and append it to the *AllowedConnections* field of the app_manifest.json file:
|
||||
|
||||
`"AllowedConnections": [ "<iot_edge_device>" ]`
|
||||
1. Update the *DeviceAuthentication* field of the app_manifest.json file.
|
||||
|
||||
- At the command prompt, run the following command to get the Tenant ID. Use the GUID, not the friendly name, and paste it into the *DeviceAuthentication* field of the app_manifest.json file:
|
||||
|
||||
`azsphere tenant show-selected`
|
||||
|
||||
- Your *DeviceAuthentication* field should now look like this:
|
||||
|
||||
`"DeviceAuthentication": "<GUID>"`
|
||||
|
||||
1. Save the modified app_manifest.json file.
|
||||
|
||||
## Step 4. Re-build and re-run the sample
|
||||
|
||||
Repeat [the steps to build and run the sample](./READMEStartWithHub.md#Build-and-run-the-sample).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For common errors and corrective action, see [Troubleshooting](./troubleshooting.md).
|
|
@ -0,0 +1,109 @@
|
|||
# Run the sample by connecting to an Azure IoT Central application
|
||||
|
||||
## Step 1. Start with the Azure IoT README topic
|
||||
|
||||
Follow the instructions in the [README](./README.md) topic before you perform any of the steps described here.
|
||||
|
||||
**Note**: This sample uses the latest IoT Central message syntax and will not work with IoT Central applications created on or before July 7th, 2020.
|
||||
|
||||
## Step 2. Configure Azure IoT Central to work with Azure Sphere
|
||||
|
||||
You must [set up Azure IoT Central to work with Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-central), if you have not already done so.
|
||||
|
||||
## Step 3. Enable the Azure IoT Central auto-approve option
|
||||
|
||||
1. Go to [Azure IoT Central](https://apps.azureiotcentral.com/myapps) in your browser.
|
||||
|
||||
1. From the Azure IoT Central Application, click **Administration** > **Device connection**, then on the **Auto approve new devices** option, select **Enabled**.
|
||||
|
||||
## Step 4. Modify the sample app_manifest.json file to connect to your IoT Central application
|
||||
|
||||
An Azure IoT Central application includes underlying Azure IoT Hub and a device provisioning service to provision devices into these hubs. By default, this application's top-level CMakeLists.txt pulls in code to connect directly to an IoT Hub. You'll need to modify this CMakeLists.txt to pull in the code to connect via DPS instead and change some information in the app_manifest.json file:
|
||||
|
||||
1. Find the CMakeLists.txt file in your sample directory and open it.
|
||||
|
||||
1. Change the *add_subdirectory* CMake function call so that it no longer adds the code in the IoTHub directory and instead adds the code in the DPS subdirectory. The call should now look like this:
|
||||
|
||||
`add_subdirectory(DPS)`
|
||||
|
||||
1. Save the modified CMakeLists.txt file.
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it. In the following steps, you'll gather the following information and add it to this file:
|
||||
|
||||
- The Scope ID for your Azure IoT Central application.
|
||||
- The allowed connections for your Azure Sphere device.
|
||||
- The Tenant ID for your Azure Sphere device.
|
||||
|
||||
1. At the command prompt, run the **ShowIoTCentralConfig** program from the Windows or Linux folder in the sample repository. For example, on Windows, the path is ..\Samples\AzureIoT\Tools\win-x64\ShowIoTCentralConfig.exe. When running this tool on a Linux machine you may have to explicitly set permissions. For example, from a terminal, run `chmod +x ShowIoTCentralConfig` to set permissions on the tool.
|
||||
|
||||
**Note**: If you are unable to run the **ShowIoTCentralConfig** program at the command prompt, delete the AppData\Local\Temp\.net\ShowIoTCentralConfig folder, then run the program again.
|
||||
|
||||
Now follow the prompts that the tool provides, and copy the information from the output into the app_manifest.json file. The tool will require the following input:
|
||||
|
||||
- The IoT Central App URL can be found in your browser address bar; for example, `https://myiotcentralapp.azureiotcentral.com/`.
|
||||
|
||||
- The API token can be generated from your IoT Central application. In the Azure IoT Central application, click **Administration** > **API Tokens** > **Generate Token**, then provide a name for the token; for example, "AzureSphereSample." Select **Administrator** as the role. Click **Generate**, and then copy the token to the clipboard. The token starts with **SharedAccessSignature**.
|
||||
|
||||
- The ID Scope is in the Azure IoT Central application. Click **Administration** > **Device Connection**, then copy the **ID Scope**.
|
||||
|
||||
1. At the command prompt, run the following command to get the Tenant ID:
|
||||
|
||||
`azsphere tenant show-selected`
|
||||
|
||||
Paste the GUID for your tenant into the **DeviceAuthentication** field of the app_manifest.json file.
|
||||
|
||||
1. Check that your updated app_manifest.json file has lines that looks like this:
|
||||
|
||||
`"CmdArgs": [ "--ScopeID", "<scope_id>" ]`
|
||||
|
||||
and:
|
||||
|
||||
`"AllowedConnections": [ "global.azure-devices-provisioning.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net","iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net","iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net", "iotc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net" ],`
|
||||
|
||||
and:
|
||||
|
||||
`"DeviceAuthentication": "<GUID>"`
|
||||
|
||||
1. Save the updated application manifest.
|
||||
|
||||
## Step 5. Build and run the sample
|
||||
|
||||
1. Ensure that your device is connected to the internet.
|
||||
|
||||
1. Follow the steps in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
1. See [Troubleshooting samples](../troubleshooting.md) if you encounter errors.
|
||||
|
||||
1. When the app is running, press button A on the MT3620 development board to change the Thermometer Telemetry Upload Enabled status to true. The app will start sending (simulated) temperature telemetry. An LED on the device will light to indicate this status change, and the app will output messages like:
|
||||
|
||||
**INFO: Sending Azure IoT Hub telemetry: {"Temperature":49.700000762939453}.**
|
||||
|
||||
1. Press button A again to change the Thermometer Telemetry Upload Enabled status back to false. The app will stop sending temperature telemetry, and the LED will turn off again.
|
||||
|
||||
1. Press button B to send a telemetry event indicating the thermometer has been moved to a new location. The app will output messages like:
|
||||
|
||||
**INFO: Thermometer Moved**
|
||||
|
||||
## Step 6. View and edit the device data in Azure IoT Central
|
||||
|
||||
1. In your Azure IoT Central application, select your device. Click **Devices** > **All Devices**. You should see your device listed as an "Azure Sphere Example Thermometer". The device is identified in this way because it sends its [Azure IoT Plug and Play (PnP)](https://docs.microsoft.com/azure/iot-pnp/) model ID when it connects.
|
||||
|
||||
1. Select **About** on the menu bar just under the device name. Note that the device has sent its serial number.
|
||||
|
||||
1. Click **Device templates** and select the **Azure Sphere Example Thermometer** template.
|
||||
|
||||
1. Click **Views** > **Editing device and cloud data**. Enter *Enable telemetry* as the Form name value. Select **Thermometer Telemetry Upload Enabled**. Click **Add section** > **Save** > **Publish**.
|
||||
|
||||
1. Go back to your device. Select **Enable telemetry**. Click to open the **Thermometer Telemetry Upload Enabled** dropdown menu, then click **True** > **Save**. In a few seconds, the LED will light up and the app will start sending telemetry.
|
||||
|
||||
1. Select **Overview**. See that the device is sending simulated temperatures at regular intervals. See also that the **Raw Data** will include any Thermometer Moved events when you press button B.
|
||||
|
||||
1. Run a command from the Azure IoT Central application. Click the **Command** tab. In the Alert Message field, enter an example alert message like "Sunny later today. Close your window blinds to lower temperature!". Click **Run**. Click the History icon in the right corner of the Interface/Trigger Alarm box. This will show you the response to the command from your Azure Sphere device. The device itself will also output the following message:
|
||||
|
||||
```
|
||||
ALERT: Sunny later today. Close your window blinds to lower temperature!
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For common errors and corrective action, see [Troubleshooting](./troubleshooting.md).
|
|
@ -0,0 +1,133 @@
|
|||
# Run the sample by connecting to an Azure IoT Hub
|
||||
|
||||
## Step 1. Start with the Azure IoT Readme topic
|
||||
|
||||
Follow the instructions in the [README](./README.md) topic before you perform any of the steps described here.
|
||||
|
||||
## Step 2. Configure an IoT Hub to work with Azure Sphere
|
||||
|
||||
You must [set up an Azure IoT Hub for Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub), if you have not already done so.
|
||||
|
||||
## Step 3. Modify the sample app_manifest.json file to connect to your Azure IoT Hub
|
||||
|
||||
To configure the sample application, you'll update some information in the app_manifest.json file. Follow these steps to gather the information and configure the application:
|
||||
|
||||
1. Log in to the [Azure Portal](https://portal.azure.com) and navigate to your Azure IoT Hub. You will need to refer to this later while configuring the application.
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it. In the following steps, you'll add the following information to this file:
|
||||
|
||||
- The hostname of your Azure IoT Hub.
|
||||
- The allowed connections for your Azure Sphere device.
|
||||
- The Tenant ID for your Azure Sphere device.
|
||||
|
||||
1. Update the *CmdArgs* field of the app_manifest.json file:
|
||||
- In the Azure portal, at the top right of your Hub's Overview screen, copy the Hostname and paste it into the *CmdArgs* field of the app_manifest.json file as an argument to the Hostname option. Your *CmdArgs* field should now look like:
|
||||
|
||||
`"CmdArgs": [ "--Hostname", "<azure_iot_hub_hostname.azure-devices.net>" ]`
|
||||
|
||||
1. Update the *AllowedConnections* field of the app_manifest.json file.
|
||||
|
||||
- Copy the hostname used in the *CmdArgs* section and append it to the *AllowedConnections* field of the app_manifest.json file. The field should now look like:
|
||||
|
||||
`"AllowedConnections": [ "<azure_iot_hub_hostname.azure-devices.net>" ]`
|
||||
|
||||
1. Update the *DeviceAuthentication* field of the app_manifest.json file.
|
||||
|
||||
- At the command prompt, run the following command to get the Tenant ID. Use the GUID, not the friendly name, and paste it into the *DeviceAuthentication* field of the app_manifest.json file:
|
||||
|
||||
`azsphere tenant show-selected`
|
||||
|
||||
- Your *DeviceAuthentication* field should now look like:
|
||||
|
||||
`"DeviceAuthentication": "<GUID>"`
|
||||
|
||||
1. Save the modified app_manifest.json file.
|
||||
|
||||
## Step 4. Build and run the sample
|
||||
|
||||
1. Ensure that your device is connected to the internet.
|
||||
|
||||
1. Follow the steps in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
1. See [Troubleshooting samples](../troubleshooting.md) if you encounter errors.
|
||||
|
||||
1. When the app is running, press button A on the MT3620 development board to change the Thermometer Telemetry Upload Enabled status to true. The app will start sending (simulated) temperature telemetry. An LED on the device will light to indicate this status change, and the app will output messages like:
|
||||
|
||||
**INFO: Sending Azure IoT Hub telemetry: {"Temperature":49.700000762939453}.**
|
||||
|
||||
1. Press button A again to change the Thermometer Telemetry Upload Enabled status back to false. The app will stop sending temperature telemetry, and the LED will turn off again.
|
||||
|
||||
1. Press button B to send a telemetry event indicating the thermometer has been moved to a new location. The app will output messages like:
|
||||
|
||||
**INFO: Thermometer moved**
|
||||
|
||||
## Step 5. View and edit the device data in IoT Hub
|
||||
|
||||
View device in IoT Hub:
|
||||
|
||||
1. Log in to the [Azure Portal](https://portal.azure.com) and select your IoT Hub resource.
|
||||
|
||||
1. On the left-side menu under **Explorers**, click **IoT Devices**, then click the Device ID for your device.
|
||||
|
||||
View and edit the device twin:
|
||||
|
||||
1. Select the **Device Twin** tab.
|
||||
|
||||
1. In the *properties* field, under **reported**, note that the device has reported its serial number.
|
||||
|
||||
1. In the *properties* field, under **desired**, add `"ThermometerTelemetryUploadEnabled": true,` as shown below:
|
||||
|
||||
```json
|
||||
"properties": {
|
||||
"desired": {
|
||||
"ThermometerTelemetryUploadEnabled": true,
|
||||
"$metadata": {
|
||||
"$lastUpdated": "2019-01-30T22:18:19.612025Z",
|
||||
```
|
||||
|
||||
1. Click **Save** to update the twin and notify the application. In a few seconds, the LED will light up and the app will start sending telemetry.
|
||||
|
||||
Execute a direct method:
|
||||
|
||||
1. Click the **Direct Method** tab.
|
||||
|
||||
1. In the *Method Name* field, enter "displayAlert".
|
||||
|
||||
1. In the *Payload* field, enter an example alert message like "Sunny later today. Close your window blinds to lower temperature!".
|
||||
|
||||
1. Click **Invoke Method** to execute the method on the application. In a few seconds, the device will output the following:
|
||||
|
||||
```
|
||||
ALERT: Sunny later today. Close your window blinds to lower temperature!
|
||||
```
|
||||
|
||||
You can view telemetry:
|
||||
|
||||
1. Start the Azure CLI in Cloud Shell. There is a button to launch this shell at the top of the portal.
|
||||
|
||||
1. Install the Azure IoT Hub extension:
|
||||
|
||||
`az extension add --name azure-iot`
|
||||
|
||||
1. Run the following command:
|
||||
|
||||
`az iot hub monitor-events --hub-name <azure_iot_hub_hostname> --output table`
|
||||
|
||||
1. Observe the telemetry arriving, both the regular temperature readings and thermometer-moved events when you press button B.
|
||||
|
||||
## Step 6. Note how the app uses Azure IoT PnP
|
||||
|
||||
The application implements an example [Azure IoT Plug and Play (PnP)](https://docs.microsoft.com/azure/iot-pnp/) model called "Azure Sphere example". It sends this model's ID when it connects to Azure IoT Hub.
|
||||
|
||||
Follow the [IoT Explorer instructions](https://docs.microsoft.com/azure/iot-pnp/howto-use-iot-explorer) to interact and test this feature.
|
||||
|
||||
Note how the Azure IoT Explorer client finds and uses the PnP model to understand the device's data, and you don't need to type the model's parameter names, like ThermometerTelemetryUploadEnabled or DisplayAlert.
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Connect via Azure IoT Hub device provisioning service](./READMEAddDPS.md)
|
||||
- [Connect via Azure IoT Edge](./READMEAddIoTEdge.md)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For common errors and corrective action, see [Troubleshooting](./troubleshooting.md).
|
Двоичные данные
Samples/AzureIoT/Tools/linux-x64/ShowIoTCentralConfig
Двоичные данные
Samples/AzureIoT/Tools/linux-x64/ShowIoTCentralConfig
Двоичный файл не отображается.
|
@ -1,11 +1,11 @@
|
|||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: BSN Pgp v1.0.0.0
|
||||
|
||||
iQEcBAABCAAGBQJfOej7AAoJEOs+lK2+EinPERsH/3uEM7jj8CFF9jHh9T/Ih9VN
|
||||
8gNIt9jmWOJUWFjLI1XqPU6APnU2qv9M2atFlzM9uo3SVKiMTJbP9shyB3tPKaUU
|
||||
WUpt4y54gRyjruSTRWwcCpFDtVZ/JL+U4wUgQF0mct3Ij23BDpUoVWrkBj2mn5FE
|
||||
8ndyVfH/9Sb78iOtVaI+0/TKltnmmfEoq1+lxjytv2Oj/X3WdyhBuzu0p1Z4RnuN
|
||||
ZaWgyNevs50QFNji2UXyIKf5LSXxT/OETFwhaGCwOiyChiz1+0h9k+kNT08VgGHS
|
||||
7ayqRYTwOXbxSTdztQnzdi3rfZ42lFUukHNhIXc4EAIFa5QKrNRRTsTa/5O9zeM=
|
||||
=tdb5
|
||||
iQEcBAABCAAGBQJggNmkAAoJEOs+lK2+EinPy4cIALaiyxwS0aqur+VAbRbZYbYJ
|
||||
kp6YoNw+ycuNU/pF6i+ZkHY8Dj67RxkA2UH6zxEdqlhwl1lkZltXt5HCD+Wx+A4J
|
||||
8unBN+QGWcbwPHBXQZU25mtawRny7ZWpSXd4xWThkaikm5vdLrNldqRUj/pbLW/Y
|
||||
S+nuo3ZiNvwdsAHQWWwwHWEiVzQHqHWjvHVeUMzdF/FzgfSvkhOgn7LjAoTy6tnQ
|
||||
xdMRFTYi5KgGcMYkvat9XWAQER9rs14EpwNJkcsgXqTD5m0A9PUxWxlQGLVy2UKF
|
||||
BL7NMJqZv8BhmkCy02k+mGh54e4eH33ebqatk3GGjMBFxXa1xfhfgKfNOKaVx5g=
|
||||
=M5bv
|
||||
-----END PGP SIGNATURE-----
|
||||
|
|
Двоичные данные
Samples/AzureIoT/Tools/win-x64/ShowIoTCentralConfig.exe
Двоичные данные
Samples/AzureIoT/Tools/win-x64/ShowIoTCentralConfig.exe
Двоичный файл не отображается.
|
@ -0,0 +1,111 @@
|
|||
# Troubleshooting Azure IoT sample apps
|
||||
|
||||
Troubleshooting content in this topic addresses scenarios in [Azure-sphere-samples/Samples/AzureIoT/Readme.md](https://github.com/Azure/azure-sphere-samples/blob/master/Samples/AzureIoT/README.md).
|
||||
|
||||
## All Azure IoT scenarios
|
||||
|
||||
1. The following message in the device output may indicate that device authentication is not ready:
|
||||
|
||||
```
|
||||
ERROR: <connection type> - device auth not ready.
|
||||
```
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The tenant ID specified in the *DeviceAuthentication* field of your app_manifest.json file is incorrect. Verify that it matches the ID of the tenant your device is claimed into.
|
||||
|
||||
- Your device is not claimed into a tenant. Go through the steps to [claim your device](https://docs.microsoft.com/azure-sphere/install/claim-device?tabs=cliv2beta).
|
||||
|
||||
## Azure Sphere device with a direct connection to your Azure IoT hub
|
||||
|
||||
1. The following messages in the device output may indicate a device registration or certificate authority error:
|
||||
|
||||
```
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL
|
||||
```
|
||||
These errors may occur if:
|
||||
|
||||
- The device is not registered with the IoT Hub. Go through the steps to register device with Hub again. See Step 5 in [Set up an Azure IoT Hub to work with Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub#step-5.-create-an-x.509-device-in-your-iot-hub-for-your-azure-sphere-device).
|
||||
|
||||
- Incorrect or no certificate is uploaded to the IoT hub. See Steps 2-4 in [Set up an Azure IoT hub to work with Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub).
|
||||
|
||||
2. The following message in the device output may indicate a problem with the configuration of the Azure IoT hub in your app_manifest.json file:
|
||||
|
||||
```
|
||||
INFO: Azure IoT Hub connection started.
|
||||
INFO: Azure IoT Hub connection complete.
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
```
|
||||
|
||||
This error may occur if:
|
||||
|
||||
- The Azure IoT hub specified in the app_manifest.json doesn't exist. Verify that you've used the fully-qualified hub hostname; for example, contoso-hub-1234.azure-devices.net and not just contoso-hub-1234. Also verify that your hub has been created successfully and that it is deployed.
|
||||
|
||||
- The Azure IoT hub hostname specified in *CmdArgs* does not match that specified in *AllowedConnections*, or vice-versa, or is missing from one of them. Verify that the Azure IoT hub hostname is correctly specified in both the *CmdArgs* and *AllowedConnections* fields of your app_manifest.json file.
|
||||
|
||||
## Azure IoT Central and device provisioning service
|
||||
|
||||
1. The following messages in the device output may indicate a problem in the configuration of your IoT Central application or device provisioning service instance:
|
||||
|
||||
```
|
||||
ERROR: Failed to register device with provisioning service: PROV_DEVICE_RESULT_DISABLED
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
ERROR: Failed to register device with provisioning service: PROV_DEVICE_RESULT_TRANSPORT
|
||||
```
|
||||
|
||||
These errors may occur if:
|
||||
|
||||
- Device enrollment group has not been created or is disabled in the device provisioning service or in IoT Central. Go through the steps to [set up IoT Central](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-central?tabs=cliv2beta) or to [configure the device provisioning service](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub-with-dps?tabs=cliv2beta) again.
|
||||
|
||||
- Incorrect certificate uploaded. Go through the steps to [set up IoT Central](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-central?tabs=cliv2beta) or to [configure device provisioning service](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub-with-dps?tabs=cliv2beta) again.
|
||||
|
||||
2. The following messages in the device output may indicate a misconfiguration of the Azure IoT Hub in your app_manifest.json file:
|
||||
|
||||
```
|
||||
INFO: Azure IoT Hub connection started.
|
||||
INFO: DPS device registration successful
|
||||
INFO: Azure IoT Hub connection complete.
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
```
|
||||
|
||||
These errors may occur if:
|
||||
|
||||
- The hub hostname is missing from, or incorrect in, the *AllowedConnections* field in your app_manifest.json file.
|
||||
- If you are using the device provisioning service, verify that you've used the fully-qualified hub hostname; for example, contoso-hub-1234.azure-devices.net and not just contoso-hub-1234.
|
||||
- Verify that the enrollment group is pointing to the correct hub in the Azure Portal. Review steps to [configure device provisioning service](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub-with-dps?tabs=cliv2beta).
|
||||
- If you are using IoT Central, re-run ShowIoTCentralConfig.exe and make sure you copy the *AllowedConnections* field correctly.
|
||||
|
||||
## Azure IoT Edge
|
||||
|
||||
1. The following messages in the device output may indicate a connection error with the IoT Edge device:
|
||||
|
||||
```
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
```
|
||||
|
||||
These errors may occur if:
|
||||
|
||||
- Inbound port 8883 has not been opened on the IoT Edge device. For more information, see Step 3 in [Open IoT Edge gateway device ports for communication](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-edge?tabs=cliv2beta#step-3-open-iot-edge-gateway-device-ports-for-communication).
|
||||
- The sample is using an incorrect or invalid IoT Edge device root CA certificate.
|
||||
- The *edgeAgent* and *edgeHub* modules are not running on the IoT Edge device.
|
||||
|
||||
1. The following messages in the device output may indicate a device provisioning error:
|
||||
|
||||
```
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_NO_NETWORK
|
||||
Azure IoT connection status: IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL
|
||||
```
|
||||
|
||||
These errors may occur if:
|
||||
|
||||
- The Azure Sphere device is not manually provisioned. Follow the steps to [authenticate using a direct connection](https://docs.microsoft.com/azure-sphere/app-development/setup-iot-hub?tabs=cliv2beta).
|
|
@ -3,10 +3,10 @@
|
|||
"Name": "AzureIoT",
|
||||
"ComponentId": "819255ff-8640-41fd-aea7-f85d34c491d5",
|
||||
"EntryPoint": "/bin/app",
|
||||
"CmdArgs": [],
|
||||
"CmdArgs": [ ],
|
||||
"Capabilities": {
|
||||
"AllowedConnections": [ "global.azure-devices-provisioning.net" ],
|
||||
"Gpio": [ "$SAMPLE_BUTTON_1", "$SAMPLE_LED" ],
|
||||
"AllowedConnections": [],
|
||||
"Gpio": [ "$SAMPLE_BUTTON_1", "$SAMPLE_BUTTON_2", "$SAMPLE_LED" ],
|
||||
"DeviceAuthentication": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
"ApplicationType": "Default"
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/applibs_versions.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/azure_iot.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/azure_iot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/cloud.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/cloud.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/connection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/eventloop_timer_utilities.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/eventloop_timer_utilities.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/exitcodes.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/user_interface.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/user_interface.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/main.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/options.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/parson.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/parson.h
|
||||
)
|
|
@ -0,0 +1,401 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <applibs/eventloop.h>
|
||||
#include <applibs/log.h>
|
||||
#include <applibs/networking.h>
|
||||
|
||||
#include "parson.h"
|
||||
|
||||
#include "azure_iot.h"
|
||||
#include "eventloop_timer_utilities.h"
|
||||
#include "exitcodes.h"
|
||||
#include "connection.h"
|
||||
|
||||
static void AzureTimerEventHandler(EventLoopTimer *timer);
|
||||
static void SetUpAzureIoTHubClient(void);
|
||||
static void ConnectionStatusCallback(IOTHUB_CLIENT_CONNECTION_STATUS result,
|
||||
IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason,
|
||||
void *userContextCallback);
|
||||
static void SendEventCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void *context);
|
||||
static void DeviceTwinCallback(DEVICE_TWIN_UPDATE_STATE updateState, const unsigned char *payload,
|
||||
size_t payloadSize, void *userContextCallback);
|
||||
static void ReportedStateCallback(int result, void *context);
|
||||
static int DeviceMethodCallback(const char *methodName, const unsigned char *payload,
|
||||
size_t payloadSize, unsigned char **response, size_t *responseSize,
|
||||
void *userContextCallback);
|
||||
|
||||
static void ConnectionCallbackHandler(Connection_Status status,
|
||||
IOTHUB_DEVICE_CLIENT_LL_HANDLE clientHandle);
|
||||
static bool IsConnectionReadyToSendTelemetry(void);
|
||||
|
||||
/// <summary>
|
||||
/// Authentication state of the client with respect to the Azure IoT Hub.
|
||||
/// </summary>
|
||||
typedef enum {
|
||||
/// <summary>Client is not authenticated by the Azure IoT Hub.</summary>
|
||||
IoTHubClientAuthenticationState_NotAuthenticated = 0,
|
||||
/// <summary>Client has initiated authentication to the Azure IoT Hub.</summary>
|
||||
IoTHubClientAuthenticationState_AuthenticationInitiated = 1,
|
||||
/// <summary>Client is authenticated by the Azure IoT Hub.</summary>
|
||||
IoTHubClientAuthenticationState_Authenticated = 2
|
||||
} IoTHubClientAuthenticationState;
|
||||
|
||||
static IoTHubClientAuthenticationState iotHubClientAuthenticationState =
|
||||
IoTHubClientAuthenticationState_NotAuthenticated; // Authentication state with respect to the
|
||||
// IoT Hub.
|
||||
|
||||
// Azure IoT poll periods
|
||||
static const int AzureIoTDefaultPollPeriodSeconds = 1; // poll azure iot every second
|
||||
static const int AzureIoTMinReconnectPeriodSeconds = 10; // back off when reconnecting
|
||||
static const int AzureIoTMaxReconnectPeriodSeconds = 10 * 60; // back off limit
|
||||
static int azureIoTPollPeriodSeconds = -1;
|
||||
static EventLoopTimer *azureTimer = NULL;
|
||||
|
||||
static IOTHUB_DEVICE_CLIENT_LL_HANDLE iothubClientHandle = NULL;
|
||||
static ExitCode_CallbackType failureCallbackFunction = NULL;
|
||||
static AzureIoT_Callbacks callbacks;
|
||||
|
||||
static Connection_Status connectionStatus = Connection_NotStarted;
|
||||
|
||||
// Constants
|
||||
#define MAX_DEVICE_TWIN_PAYLOAD_SIZE 512
|
||||
|
||||
static const char networkInterface[] = "wlan0";
|
||||
|
||||
MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_CONNECTION_STATUS_REASON,
|
||||
IOTHUB_CLIENT_CONNECTION_STATUS_REASON_VALUES);
|
||||
|
||||
ExitCode AzureIoT_Initialize(EventLoop *eventLoop, ExitCode_CallbackType failureCallback,
|
||||
const char *modelId, void *connectionContext, AzureIoT_Callbacks cb)
|
||||
{
|
||||
failureCallbackFunction = failureCallback;
|
||||
callbacks = cb;
|
||||
|
||||
ExitCode connectionErrorCode = Connection_Initialise(
|
||||
eventLoop, ConnectionCallbackHandler, failureCallback, modelId, connectionContext);
|
||||
if (connectionErrorCode != ExitCode_Success) {
|
||||
return connectionErrorCode;
|
||||
}
|
||||
|
||||
azureIoTPollPeriodSeconds = AzureIoTDefaultPollPeriodSeconds;
|
||||
struct timespec azureTelemetryPeriod = {.tv_sec = azureIoTPollPeriodSeconds, .tv_nsec = 0};
|
||||
azureTimer =
|
||||
CreateEventLoopPeriodicTimer(eventLoop, &AzureTimerEventHandler, &azureTelemetryPeriod);
|
||||
if (azureTimer == NULL) {
|
||||
return ExitCode_Init_AzureTimer;
|
||||
}
|
||||
|
||||
return ExitCode_Success;
|
||||
}
|
||||
|
||||
void AzureIoT_Cleanup(void)
|
||||
{
|
||||
DisposeEventLoopTimer(azureTimer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the Azure IoT Hub connection code to indicate a change in connection status.
|
||||
/// </summary>
|
||||
/// <param name="status">Connection status.</param>
|
||||
/// <param name="clientHandle">
|
||||
/// If successfully connected to an Azure IoT Hub, this will be
|
||||
/// set to a device client handle for that hub; otherwise, NULL.
|
||||
/// </param>
|
||||
static void ConnectionCallbackHandler(Connection_Status status,
|
||||
IOTHUB_DEVICE_CLIENT_LL_HANDLE clientHandle)
|
||||
{
|
||||
connectionStatus = status;
|
||||
|
||||
switch (status) {
|
||||
case Connection_NotStarted:
|
||||
break;
|
||||
case Connection_Started:
|
||||
Log_Debug("INFO: Azure IoT Hub connection started.\n");
|
||||
break;
|
||||
case Connection_Complete: {
|
||||
Log_Debug("INFO: Azure IoT Hub connection complete.\n");
|
||||
|
||||
iothubClientHandle = clientHandle;
|
||||
|
||||
// Successfully connected, so make sure the polling frequency is back to the default
|
||||
azureIoTPollPeriodSeconds = AzureIoTDefaultPollPeriodSeconds;
|
||||
struct timespec azureTelemetryPeriod = {.tv_sec = azureIoTPollPeriodSeconds, .tv_nsec = 0};
|
||||
SetEventLoopTimerPeriod(azureTimer, &azureTelemetryPeriod);
|
||||
|
||||
// Set client authentication state to initiated. This is done to indicate that
|
||||
// SetUpAzureIoTHubClient() has been called (and so should not be called again) while the
|
||||
// client is waiting for a response via the ConnectionStatusCallback().
|
||||
iotHubClientAuthenticationState = IoTHubClientAuthenticationState_AuthenticationInitiated;
|
||||
|
||||
IoTHubDeviceClient_LL_SetDeviceTwinCallback(iothubClientHandle, DeviceTwinCallback, NULL);
|
||||
IoTHubDeviceClient_LL_SetDeviceMethodCallback(iothubClientHandle, DeviceMethodCallback,
|
||||
NULL);
|
||||
IoTHubDeviceClient_LL_SetConnectionStatusCallback(iothubClientHandle,
|
||||
ConnectionStatusCallback, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
case Connection_Failed: {
|
||||
|
||||
// If we fail to connect, reduce the polling frequency, starting at
|
||||
// AzureIoTMinReconnectPeriodSeconds and with a backoff up to
|
||||
// AzureIoTMaxReconnectPeriodSeconds
|
||||
if (azureIoTPollPeriodSeconds == AzureIoTDefaultPollPeriodSeconds) {
|
||||
azureIoTPollPeriodSeconds = AzureIoTMinReconnectPeriodSeconds;
|
||||
} else {
|
||||
azureIoTPollPeriodSeconds *= 2;
|
||||
if (azureIoTPollPeriodSeconds > AzureIoTMaxReconnectPeriodSeconds) {
|
||||
azureIoTPollPeriodSeconds = AzureIoTMaxReconnectPeriodSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
struct timespec azureTelemetryPeriod = {azureIoTPollPeriodSeconds, 0};
|
||||
SetEventLoopTimerPeriod(azureTimer, &azureTelemetryPeriod);
|
||||
|
||||
Log_Debug("ERROR: Azure IoT Hub connection failed - will retry in %i seconds.\n",
|
||||
azureIoTPollPeriodSeconds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Azure timer event: Check connection status and send telemetry
|
||||
/// </summary>
|
||||
static void AzureTimerEventHandler(EventLoopTimer *timer)
|
||||
{
|
||||
if (ConsumeEventLoopTimerEvent(timer) != 0) {
|
||||
failureCallbackFunction(ExitCode_AzureTimer_Consume);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether the device is connected to the internet.
|
||||
Networking_InterfaceConnectionStatus status;
|
||||
if (Networking_GetInterfaceConnectionStatus(networkInterface, &status) == 0) {
|
||||
if ((status & Networking_InterfaceConnectionStatus_ConnectedToInternet) &&
|
||||
(iotHubClientAuthenticationState == IoTHubClientAuthenticationState_NotAuthenticated)) {
|
||||
SetUpAzureIoTHubClient();
|
||||
}
|
||||
} else {
|
||||
if (errno != EAGAIN) {
|
||||
Log_Debug("ERROR: Networking_GetInterfaceConnectionStatus: %d (%s)\n", errno,
|
||||
strerror(errno));
|
||||
failureCallbackFunction(ExitCode_InterfaceConnectionStatus_Failed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (iothubClientHandle != NULL) {
|
||||
IoTHubDeviceClient_LL_DoWork(iothubClientHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the Azure IoT Hub connection (creates the iothubClientHandle)
|
||||
/// When the SAS Token for a device expires the connection needs to be recreated
|
||||
/// which is why this is not simply a one time call.
|
||||
/// </summary>
|
||||
static void SetUpAzureIoTHubClient(void)
|
||||
{
|
||||
if (iothubClientHandle != NULL) {
|
||||
IoTHubDeviceClient_LL_Destroy(iothubClientHandle);
|
||||
iothubClientHandle = NULL;
|
||||
}
|
||||
|
||||
if (connectionStatus == Connection_NotStarted || connectionStatus == Connection_Failed) {
|
||||
Connection_Start();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the Azure IoT connection state changes.
|
||||
/// This can indicate that a new connection attempt has succeeded or failed.
|
||||
/// It can also indicate than an existing connection has expired due to SAS token expiry.
|
||||
/// </summary>
|
||||
static void ConnectionStatusCallback(IOTHUB_CLIENT_CONNECTION_STATUS result,
|
||||
IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason,
|
||||
void *userContextCallback)
|
||||
{
|
||||
Log_Debug("Azure IoT connection status: %s\n",
|
||||
IOTHUB_CLIENT_CONNECTION_STATUS_REASONStrings(reason));
|
||||
|
||||
iotHubClientAuthenticationState = result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED
|
||||
? IoTHubClientAuthenticationState_Authenticated
|
||||
: IoTHubClientAuthenticationState_NotAuthenticated;
|
||||
|
||||
if (iotHubClientAuthenticationState == IoTHubClientAuthenticationState_NotAuthenticated) {
|
||||
ConnectionCallbackHandler(Connection_NotStarted, NULL);
|
||||
}
|
||||
|
||||
if (callbacks.connectionStatusCallbackFunction != NULL) {
|
||||
callbacks.connectionStatusCallbackFunction(result ==
|
||||
IOTHUB_CLIENT_CONNECTION_AUTHENTICATED);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback invoked when a Device Twin update is received from Azure IoT Hub.
|
||||
/// </summary>
|
||||
static void DeviceTwinCallback(DEVICE_TWIN_UPDATE_STATE updateState, const unsigned char *payload,
|
||||
size_t payloadSize, void *userContextCallback)
|
||||
{
|
||||
// Statically allocate this for more predictable memory use patterns
|
||||
static char nullTerminatedJsonString[MAX_DEVICE_TWIN_PAYLOAD_SIZE + 1];
|
||||
|
||||
if (payloadSize > MAX_DEVICE_TWIN_PAYLOAD_SIZE) {
|
||||
Log_Debug("ERROR: Device twin payload size (%u bytes) exceeds maximum (%u bytes).\n",
|
||||
payloadSize, MAX_DEVICE_TWIN_PAYLOAD_SIZE);
|
||||
|
||||
failureCallbackFunction(ExitCode_PayloadSize_TooLarge);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the payload to local buffer for null-termination.
|
||||
memcpy(nullTerminatedJsonString, payload, payloadSize);
|
||||
|
||||
// Add the null terminator at the end.
|
||||
nullTerminatedJsonString[payloadSize] = 0;
|
||||
|
||||
if (callbacks.deviceTwinReceivedCallbackFunction != NULL) {
|
||||
callbacks.deviceTwinReceivedCallbackFunction(nullTerminatedJsonString);
|
||||
}
|
||||
}
|
||||
|
||||
AzureIoT_Result AzureIoT_SendTelemetry(const char *jsonMessage, void *context)
|
||||
{
|
||||
Log_Debug("Sending Azure IoT Hub telemetry: %s.\n", jsonMessage);
|
||||
|
||||
// Check whether the device is connected to the internet.
|
||||
if (IsConnectionReadyToSendTelemetry() == false) {
|
||||
return AzureIoT_Result_NoNetwork;
|
||||
}
|
||||
|
||||
if (iotHubClientAuthenticationState != IoTHubClientAuthenticationState_Authenticated) {
|
||||
// AzureIoT client is not authenticated. Log a warning and return.
|
||||
Log_Debug("WARNING: Azure IoT Hub is not authenticated. Not sending telemetry.\n");
|
||||
return AzureIoT_Result_OtherFailure;
|
||||
}
|
||||
|
||||
IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromString(jsonMessage);
|
||||
|
||||
if (messageHandle == 0) {
|
||||
Log_Debug("ERROR: unable to create a new IoTHubMessage.\n");
|
||||
return AzureIoT_Result_OtherFailure;
|
||||
}
|
||||
|
||||
AzureIoT_Result result = AzureIoT_Result_OK;
|
||||
|
||||
if (IoTHubDeviceClient_LL_SendEventAsync(iothubClientHandle, messageHandle, SendEventCallback,
|
||||
context) != IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: failure requesting IoTHubClient to send telemetry event.\n");
|
||||
result = AzureIoT_Result_OtherFailure;
|
||||
} else {
|
||||
Log_Debug("INFO: IoTHubClient accepted the telemetry event for delivery.\n");
|
||||
}
|
||||
|
||||
IoTHubMessage_Destroy(messageHandle);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback invoked when the Azure IoT Hub send event request is processed.
|
||||
/// </summary>
|
||||
static void SendEventCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void *context)
|
||||
{
|
||||
Log_Debug("INFO: Azure IoT Hub send telemetry event callback: status code %d.\n", result);
|
||||
|
||||
if (callbacks.sendTelemetryCallbackFunction != NULL) {
|
||||
callbacks.sendTelemetryCallbackFunction(result == IOTHUB_CLIENT_CONFIRMATION_OK, context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a report containing Device Twin reported properties. The report is not sent
|
||||
/// immediately, but it is sent on the next invocation of IoTHubDeviceClient_LL_DoWork().
|
||||
/// </summary>
|
||||
AzureIoT_Result AzureIoT_DeviceTwinReportState(const char *jsonState, void *context)
|
||||
{
|
||||
if (IsConnectionReadyToSendTelemetry() == false) {
|
||||
return AzureIoT_Result_NoNetwork;
|
||||
}
|
||||
|
||||
if (iotHubClientAuthenticationState != IoTHubClientAuthenticationState_Authenticated) {
|
||||
// AzureIoT client is not authenticated. Log a warning and return.
|
||||
Log_Debug("WARNING: Azure IoT Hub is not authenticated. Not sending device twin.\n");
|
||||
return AzureIoT_Result_OtherFailure;
|
||||
}
|
||||
|
||||
if (IoTHubDeviceClient_LL_SendReportedState(
|
||||
iothubClientHandle, (const unsigned char *)jsonState, strlen(jsonState),
|
||||
ReportedStateCallback, context) != IOTHUB_CLIENT_OK) {
|
||||
Log_Debug("ERROR: Azure IoT Hub client error when reporting state '%s'.\n", jsonState);
|
||||
return AzureIoT_Result_OtherFailure;
|
||||
}
|
||||
|
||||
Log_Debug("INFO: Azure IoT Hub client accepted request to report state '%s'.\n", jsonState);
|
||||
return AzureIoT_Result_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback invoked when the Device Twin report state request is processed by Azure IoT Hub
|
||||
/// client.
|
||||
/// </summary>
|
||||
static void ReportedStateCallback(int result, void *context)
|
||||
{
|
||||
Log_Debug("INFO: Azure IoT Hub Device Twin reported state callback: status code %d.\n", result);
|
||||
|
||||
if (callbacks.deviceTwinReportStateAckCallbackTypeFunction != NULL) {
|
||||
callbacks.deviceTwinReportStateAckCallbackTypeFunction(result != 0, context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback invoked when a Direct Method is received from Azure IoT Hub.
|
||||
/// </summary>
|
||||
static int DeviceMethodCallback(const char *methodName, const unsigned char *payload,
|
||||
size_t payloadSize, unsigned char **response, size_t *responseSize,
|
||||
void *userContextCallback)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
Log_Debug("Received Device Method callback: Method name %s.\n", methodName);
|
||||
|
||||
if (callbacks.deviceMethodCallbackFunction != NULL) {
|
||||
result = callbacks.deviceMethodCallbackFunction(methodName, payload, payloadSize, response,
|
||||
responseSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check the network status.
|
||||
/// </summary>
|
||||
static bool IsConnectionReadyToSendTelemetry(void)
|
||||
{
|
||||
Networking_InterfaceConnectionStatus status;
|
||||
if (Networking_GetInterfaceConnectionStatus(networkInterface, &status) != 0) {
|
||||
if (errno != EAGAIN) {
|
||||
Log_Debug("ERROR: Networking_GetInterfaceConnectionStatus: %d (%s)\n", errno,
|
||||
strerror(errno));
|
||||
failureCallbackFunction(ExitCode_InterfaceConnectionStatus_Failed);
|
||||
return false;
|
||||
}
|
||||
Log_Debug(
|
||||
"WARNING: Cannot send Azure IoT Hub telemetry because the networking stack isn't ready "
|
||||
"yet.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((status & Networking_InterfaceConnectionStatus_ConnectedToInternet) == 0) {
|
||||
Log_Debug(
|
||||
"WARNING: Cannot send Azure IoT Hub telemetry because the device is not connected to "
|
||||
"the internet.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <applibs/eventloop.h>
|
||||
#include "exitcodes.h"
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked on IoT Hub connection status change.
|
||||
/// </summary>
|
||||
/// <param name="connected">A boolean indicating connection status.</param>
|
||||
typedef void (*AzureIoT_ConnectionStatusCallbackType)(bool connected);
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when telemetry is sent to the IoT Hub, or when a
|
||||
/// send attempt fails.
|
||||
/// </summary>
|
||||
/// <param name="success">A boolean indicating whether the telemetry was successfully sent.</param>
|
||||
/// <param name="context">The user context supplied when the request to send telemetry was
|
||||
/// queued, if any.</param>
|
||||
typedef void (*AzureIoT_SendTelemetryCallbackType)(bool success, void *context);
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when a device twin message is received.
|
||||
/// </summary>
|
||||
/// <param name="deviceTwinContent">The device twin, as a NULL-terminated JSON string.</param>
|
||||
typedef void (*AzureIoT_DeviceTwinReceivedCallbackType)(const char *deviceTwinContent);
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when a device twin update is sent to the IoT Hub,
|
||||
/// or when a send attempt fails.
|
||||
/// </summary>
|
||||
/// <param name="success">A boolean indicating whether the device twin update was successfully
|
||||
/// sent.</param>
|
||||
/// <param name="context">The user context supplied when the request to send the update was
|
||||
/// queued, if any.</param>
|
||||
typedef void (*AzureIoT_DeviceTwinReportStateAckCallbackType)(bool success, void *context);
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when a request to invoke a device method is
|
||||
/// received from the IoT Hub. The method may return a response by setting
|
||||
/// <paramref name="response" /> and <paramref name="responseSize" />.
|
||||
/// </summary>
|
||||
/// <param name="methodName">Name of the device method to invoke, as a NULL-terminated
|
||||
/// string.</param>
|
||||
/// <param name="payload">Payload for the method invocation, if any.</param>
|
||||
/// <param name="payloadSize">Size of the payload.</param>
|
||||
/// <param name="response">(out) pointer to a buffer containing the response.</param>
|
||||
/// <param name="responseSize">(out) the size of the response buffer, if any.</param>
|
||||
typedef int (*AzureIoT_DeviceMethodCallbackType)(const char *methodName,
|
||||
const unsigned char *payload, size_t payloadSize,
|
||||
unsigned char **response, size_t *responseSize);
|
||||
|
||||
/// <summary>
|
||||
/// Structure holding callback functions for Azure IoT Hub events
|
||||
/// </summary>
|
||||
typedef struct {
|
||||
/// <summary>
|
||||
/// Function called when the Azure IoT Hub connection status changes
|
||||
/// </summary>
|
||||
AzureIoT_ConnectionStatusCallbackType connectionStatusCallbackFunction;
|
||||
/// <summary>
|
||||
/// Function called when a Device Twin message is received from the Azure IoT Hub
|
||||
/// </summary>
|
||||
AzureIoT_DeviceTwinReceivedCallbackType deviceTwinReceivedCallbackFunction;
|
||||
/// <summary>
|
||||
/// Function called when the Azure IoT Hub acknowledges receipt of a Device Twin report
|
||||
/// </summary>
|
||||
AzureIoT_DeviceTwinReportStateAckCallbackType deviceTwinReportStateAckCallbackTypeFunction;
|
||||
/// <summary>
|
||||
/// Function called when a telemetry event is sent to the Azure IoT Hub
|
||||
/// </summary>
|
||||
AzureIoT_SendTelemetryCallbackType sendTelemetryCallbackFunction;
|
||||
/// <summary>
|
||||
/// Function called when the Azure IoT Hub invokes a device method
|
||||
/// </summary>
|
||||
AzureIoT_DeviceMethodCallbackType deviceMethodCallbackFunction;
|
||||
} AzureIoT_Callbacks;
|
||||
|
||||
/// <summary>
|
||||
/// An enum indicating possible result codes when performing Azure IoT-related operations
|
||||
/// </summary>
|
||||
typedef enum {
|
||||
/// <summary>
|
||||
/// The operation succeeded
|
||||
/// </summary>
|
||||
AzureIoT_Result_OK = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The operation could not be performed as no network connection was available
|
||||
/// </summary>
|
||||
AzureIoT_Result_NoNetwork,
|
||||
|
||||
/// <summary>
|
||||
/// The operation failed for another reason not explicitly listed
|
||||
/// </summary>
|
||||
AzureIoT_Result_OtherFailure
|
||||
} AzureIoT_Result;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the Azure IoT Hub connection.
|
||||
/// </summary>
|
||||
/// <param name="el">EventLoop to register timers and events to.</param>
|
||||
/// <param name="failureCallback">Function called on unrecoverable failure.</param>
|
||||
/// <param name="modelId">Azure IoT PnP model ID, if using; NULL otherwise.</param>
|
||||
/// <param name="connectionContext">Implementation-specific context data for connection.</param>
|
||||
/// <param name="callbacks">Structure holding callback functions for Azure IoT Hub events.</param>
|
||||
/// <returns>An <see cref="ExitCode" /> indicating success or failure.</returns>
|
||||
ExitCode AzureIoT_Initialize(EventLoop *el, ExitCode_CallbackType failureCallback,
|
||||
const char *modelId, void *connectionContext,
|
||||
AzureIoT_Callbacks callbacks);
|
||||
|
||||
/// <summary>
|
||||
/// Closes and cleans up the Azure IoT Hub connection
|
||||
/// </summary>
|
||||
void AzureIoT_Cleanup(void);
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue telemetry to send to the Azure IoT Hub. The telemetry is not sent immediately; the
|
||||
/// function will return immediately, and then call the
|
||||
/// <see cref="AzureIoT_SendTelemetryCallbackType" /> (passed to
|
||||
/// <see cref="AzureIoT_Initialize" />) to indicate success or failure.
|
||||
/// </summary>
|
||||
/// <param name="jsonMessage">The telemetry to send, as a JSON string.</param>
|
||||
/// <param name="context">An optional context, which will be passed to the callback.</param>
|
||||
/// <returns>An <see cref="AzureIoT_Result" /> indicating success or failure.</returns>
|
||||
AzureIoT_Result AzureIoT_SendTelemetry(const char *jsonMessage, void *context);
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue a report containing Device Twin properties to send to the Azure IoT Hub. The report
|
||||
/// is not sent immediately; the function will return immediately, and then call the
|
||||
/// <see cref="AzureIoT_DeviceTwinReportStateAckCallbackType" /> (passed to
|
||||
/// <see cref="AzureIoT_Initialize" />) to indicate success or failure.
|
||||
/// </summary>
|
||||
/// <param name="jsonState">A JSON string representing the device twin properties to report.</param>
|
||||
/// <param name="context">An optional context, which will be passed to the callback.</param>
|
||||
/// <returns>An <see cref="AzureIoT_Result" /> indicating success or failure.</returns>
|
||||
AzureIoT_Result AzureIoT_DeviceTwinReportState(const char *jsonState, void *context);
|
|
@ -0,0 +1,260 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <applibs/eventloop.h>
|
||||
#include <applibs/log.h>
|
||||
|
||||
#include "parson.h"
|
||||
|
||||
#include "azure_iot.h"
|
||||
#include "cloud.h"
|
||||
#include "exitcodes.h"
|
||||
|
||||
// This file implements the interface described in cloud.h in terms of an Azure IoT Hub.
|
||||
// Specifically, it translates Azure IoT Hub specific concepts (events, device twin messages, device
|
||||
// methods, etc) into business domain concepts (telemetry, upload enabled, alarm raised)
|
||||
|
||||
static const char azureSphereModelId[] = "dtmi:com:example:azuresphere:thermometer;1";
|
||||
|
||||
// Azure IoT Hub callback handlers
|
||||
static void DeviceTwinCallbackHandler(const char *nullTerminatedJsonString);
|
||||
static int DeviceMethodCallbackHandler(const char *methodName, const unsigned char *payload,
|
||||
size_t payloadSize, unsigned char **response,
|
||||
size_t *responseSize);
|
||||
static void ConnectionChangedCallbackHandler(bool connected);
|
||||
|
||||
// Default handlers for cloud events
|
||||
static void DefaultTelemetryUploadEnabledChangedHandler(bool uploadEnabled);
|
||||
static void DefaultDisplayAlertHandler(const char *alertMessage);
|
||||
static void DefaultConnectionChangedHandler(bool connected);
|
||||
|
||||
// Cloud event callback handlers
|
||||
static Cloud_TelemetryUploadEnabledChangedCallbackType
|
||||
thermometerTelemetryUploadEnabledChangedCallbackFunction =
|
||||
DefaultTelemetryUploadEnabledChangedHandler;
|
||||
static Cloud_DisplayAlertCallbackType displayAlertCallbackFunction = DefaultDisplayAlertHandler;
|
||||
static Cloud_ConnectionChangedCallbackType connectionChangedCallbackFunction =
|
||||
DefaultConnectionChangedHandler;
|
||||
|
||||
// Utility functions
|
||||
static Cloud_Result AzureIoTToCloudResult(AzureIoT_Result result);
|
||||
|
||||
// Constants
|
||||
#define MAX_PAYLOAD_SIZE 512
|
||||
|
||||
unsigned int latestVersion = 1;
|
||||
|
||||
ExitCode Cloud_Initialize(EventLoop *el, void *backendContext,
|
||||
ExitCode_CallbackType failureCallback,
|
||||
Cloud_TelemetryUploadEnabledChangedCallbackType
|
||||
thermometerTelemetryUploadEnabledChangedCallback,
|
||||
Cloud_DisplayAlertCallbackType displayAlertCallback,
|
||||
Cloud_ConnectionChangedCallbackType connectionChangedCallback)
|
||||
{
|
||||
if (thermometerTelemetryUploadEnabledChangedCallback != NULL) {
|
||||
thermometerTelemetryUploadEnabledChangedCallbackFunction =
|
||||
thermometerTelemetryUploadEnabledChangedCallback;
|
||||
}
|
||||
|
||||
if (displayAlertCallback != NULL) {
|
||||
displayAlertCallbackFunction = displayAlertCallback;
|
||||
}
|
||||
|
||||
if (connectionChangedCallback != NULL) {
|
||||
connectionChangedCallbackFunction = connectionChangedCallback;
|
||||
}
|
||||
|
||||
AzureIoT_Callbacks callbacks = {
|
||||
.connectionStatusCallbackFunction = ConnectionChangedCallbackHandler,
|
||||
.deviceTwinReceivedCallbackFunction = DeviceTwinCallbackHandler,
|
||||
.deviceTwinReportStateAckCallbackTypeFunction = NULL,
|
||||
.sendTelemetryCallbackFunction = NULL,
|
||||
.deviceMethodCallbackFunction = DeviceMethodCallbackHandler};
|
||||
|
||||
return AzureIoT_Initialize(el, failureCallback, azureSphereModelId, backendContext, callbacks);
|
||||
}
|
||||
|
||||
void Cloud_Cleanup(void)
|
||||
{
|
||||
AzureIoT_Cleanup();
|
||||
}
|
||||
|
||||
static Cloud_Result AzureIoTToCloudResult(AzureIoT_Result result)
|
||||
{
|
||||
switch (result) {
|
||||
case AzureIoT_Result_OK:
|
||||
return Cloud_Result_OK;
|
||||
case AzureIoT_Result_NoNetwork:
|
||||
return Cloud_Result_NoNetwork;
|
||||
case AzureIoT_Result_OtherFailure:
|
||||
default:
|
||||
return Cloud_Result_OtherFailure;
|
||||
}
|
||||
}
|
||||
|
||||
Cloud_Result Cloud_SendTelemetry(const Cloud_Telemetry *telemetry)
|
||||
{
|
||||
JSON_Value *telemetryValue = json_value_init_object();
|
||||
JSON_Object *telemetryRoot = json_value_get_object(telemetryValue);
|
||||
json_object_dotset_number(telemetryRoot, "temperature", telemetry->temperature);
|
||||
char *serializedTelemetry = json_serialize_to_string(telemetryValue);
|
||||
AzureIoT_Result aziotResult = AzureIoT_SendTelemetry(serializedTelemetry, NULL);
|
||||
Cloud_Result result = AzureIoTToCloudResult(aziotResult);
|
||||
|
||||
json_free_serialized_string(serializedTelemetry);
|
||||
json_value_free(telemetryValue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Cloud_Result Cloud_SendThermometerMovedEvent(void)
|
||||
{
|
||||
JSON_Value *thermometerMovedValue = json_value_init_object();
|
||||
JSON_Object *thermometerMovedRoot = json_value_get_object(thermometerMovedValue);
|
||||
json_object_dotset_boolean(thermometerMovedRoot, "thermometerMoved", 1);
|
||||
char *serializedDeviceMoved = json_serialize_to_string(thermometerMovedValue);
|
||||
AzureIoT_Result aziotResult = AzureIoT_SendTelemetry(serializedDeviceMoved, NULL);
|
||||
Cloud_Result result = AzureIoTToCloudResult(aziotResult);
|
||||
|
||||
json_free_serialized_string(serializedDeviceMoved);
|
||||
json_value_free(thermometerMovedValue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Cloud_Result Cloud_SendThermometerTelemetryUploadEnabledChangedEvent(bool uploadEnabled)
|
||||
{
|
||||
JSON_Value *thermometerTelemetryUploadValue = json_value_init_object();
|
||||
JSON_Object *thermometerTelemetryUploadRoot =
|
||||
json_value_get_object(thermometerTelemetryUploadValue);
|
||||
|
||||
json_object_dotset_boolean(thermometerTelemetryUploadRoot,
|
||||
"thermometerTelemetryUploadEnabled.value", uploadEnabled ? 1 : 0);
|
||||
json_object_dotset_number(thermometerTelemetryUploadRoot,
|
||||
"thermometerTelemetryUploadEnabled.ac", 200);
|
||||
json_object_dotset_number(thermometerTelemetryUploadRoot,
|
||||
"thermometerTelemetryUploadEnabled.av", latestVersion++);
|
||||
json_object_dotset_string(thermometerTelemetryUploadRoot,
|
||||
"thermometerTelemetryUploadEnabled.ad",
|
||||
"Successfully updated thermometerTelemetryUploadEnabled");
|
||||
char *serializedTelemetryUpload = json_serialize_to_string(thermometerTelemetryUploadValue);
|
||||
AzureIoT_Result aziotResult = AzureIoT_DeviceTwinReportState(serializedTelemetryUpload, NULL);
|
||||
Cloud_Result result = AzureIoTToCloudResult(aziotResult);
|
||||
|
||||
json_free_serialized_string(serializedTelemetryUpload);
|
||||
json_value_free(thermometerTelemetryUploadValue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Cloud_Result Cloud_SendDeviceDetails(const char *serialNumber)
|
||||
{
|
||||
// Send static device twin properties when connection is established.
|
||||
JSON_Value *deviceDetailsValue = json_value_init_object();
|
||||
JSON_Object *deviceDetailsRoot = json_value_get_object(deviceDetailsValue);
|
||||
json_object_dotset_string(deviceDetailsRoot, "serialNumber", serialNumber);
|
||||
char *serializedDeviceDetails = json_serialize_to_string(deviceDetailsValue);
|
||||
AzureIoT_Result aziotResult = AzureIoT_DeviceTwinReportState(serializedDeviceDetails, NULL);
|
||||
Cloud_Result result = AzureIoTToCloudResult(aziotResult);
|
||||
|
||||
json_free_serialized_string(serializedDeviceDetails);
|
||||
json_value_free(deviceDetailsValue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DefaultTelemetryUploadEnabledChangedHandler(bool uploadEnabled)
|
||||
{
|
||||
Log_Debug("WARNING: Cloud - no handler registered for TelemetryUploadEnabled - status %s\n",
|
||||
uploadEnabled ? "true" : "false");
|
||||
}
|
||||
|
||||
static void DefaultDisplayAlertHandler(const char *alertMessage)
|
||||
{
|
||||
Log_Debug("WARNING: Cloud - no handler registered for DisplayAlert - message %s\n",
|
||||
alertMessage);
|
||||
}
|
||||
|
||||
static void DefaultConnectionChangedHandler(bool connected)
|
||||
{
|
||||
Log_Debug("WARNING: Cloud - no handler registered for ConnectionChanged - status %s\n",
|
||||
connected ? "true" : "false");
|
||||
}
|
||||
|
||||
static void ConnectionChangedCallbackHandler(bool connected)
|
||||
{
|
||||
connectionChangedCallbackFunction(connected);
|
||||
}
|
||||
|
||||
static void DeviceTwinCallbackHandler(const char *nullTerminatedJsonString)
|
||||
{
|
||||
JSON_Value *rootProperties = NULL;
|
||||
rootProperties = json_parse_string(nullTerminatedJsonString);
|
||||
if (rootProperties == NULL) {
|
||||
Log_Debug("WARNING: Cannot parse the string as JSON content.\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
JSON_Object *rootObject = json_value_get_object(rootProperties);
|
||||
JSON_Object *desiredProperties = json_object_dotget_object(rootObject, "desired");
|
||||
if (desiredProperties == NULL) {
|
||||
desiredProperties = rootObject;
|
||||
}
|
||||
|
||||
// The desired properties should have a "TelemetryUploadEnabled" object
|
||||
int thermometerTelemetryUploadEnabledValue =
|
||||
json_object_dotget_boolean(desiredProperties, "thermometerTelemetryUploadEnabled");
|
||||
|
||||
if (thermometerTelemetryUploadEnabledValue != -1) {
|
||||
unsigned int requestedVersion =
|
||||
(unsigned int)json_object_dotget_number(desiredProperties, "$version");
|
||||
|
||||
if (requestedVersion > latestVersion) {
|
||||
latestVersion = requestedVersion;
|
||||
}
|
||||
|
||||
thermometerTelemetryUploadEnabledChangedCallbackFunction(
|
||||
thermometerTelemetryUploadEnabledValue == 1);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
// Release the allocated memory.
|
||||
json_value_free(rootProperties);
|
||||
}
|
||||
|
||||
static int DeviceMethodCallbackHandler(const char *methodName, const unsigned char *payload,
|
||||
size_t payloadSize, unsigned char **response,
|
||||
size_t *responseSize)
|
||||
{
|
||||
int result;
|
||||
char *responseString;
|
||||
static char nullTerminatedPayload[MAX_PAYLOAD_SIZE + 1];
|
||||
|
||||
size_t actualPayloadSize = payloadSize > MAX_PAYLOAD_SIZE ? MAX_PAYLOAD_SIZE : payloadSize;
|
||||
|
||||
strncpy(nullTerminatedPayload, payload, actualPayloadSize);
|
||||
nullTerminatedPayload[actualPayloadSize] = '\0';
|
||||
|
||||
if (strcmp("displayAlert", methodName) == 0) {
|
||||
|
||||
displayAlertCallbackFunction(nullTerminatedPayload);
|
||||
|
||||
responseString =
|
||||
"\"Alert message displayed successfully.\""; // must be a JSON string (in quotes)
|
||||
result = 200;
|
||||
} else {
|
||||
// All other method names are ignored
|
||||
responseString = "{}";
|
||||
result = -1;
|
||||
}
|
||||
|
||||
// if 'response' is non-NULL, the Azure IoT library frees it after use, so copy it to heap
|
||||
*responseSize = strlen(responseString);
|
||||
*response = malloc(*responseSize);
|
||||
memcpy(*response, responseString, *responseSize);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "exitcodes.h"
|
||||
|
||||
// This header describes a backend-agnostic interface to a cloud platform.
|
||||
// An implementation of this header should implement logic to translate between business domain
|
||||
// concepts and the specifics of the cloud backend.
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when the cloud backend indicates that the
|
||||
/// telemetry upload enabled state has changed.
|
||||
/// </summary>
|
||||
/// <param name="status">A boolean indicating whether telemetry upload should be enabled.</param>
|
||||
typedef void (*Cloud_TelemetryUploadEnabledChangedCallbackType)(bool status);
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when the cloud backend requests and alert be
|
||||
/// displayed.
|
||||
/// </summary>
|
||||
/// <param name="alertMessage">A NULL-terminated string containing the alert message.</param>
|
||||
typedef void (*Cloud_DisplayAlertCallbackType)(const char *alertMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when the cloud backend indicates the connection
|
||||
/// status has changed.
|
||||
/// </summary>
|
||||
/// <param name="connected">A boolean indicating whether the cloud connection is available.</param>
|
||||
typedef void (*Cloud_ConnectionChangedCallbackType)(bool connected);
|
||||
|
||||
/// <summary>
|
||||
/// Telemetry to send to the cloud.
|
||||
/// </summary>
|
||||
typedef struct {
|
||||
float temperature;
|
||||
} Cloud_Telemetry;
|
||||
|
||||
/// <summary>
|
||||
/// An enum indicating possible result codes when performing cloud-related operations
|
||||
/// </summary>
|
||||
typedef enum {
|
||||
/// <summary>
|
||||
/// The operation succeeded
|
||||
/// </summary>
|
||||
Cloud_Result_OK = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The operation could not be performed as no network connection was available
|
||||
/// </summary>
|
||||
Cloud_Result_NoNetwork,
|
||||
|
||||
/// <summary>
|
||||
/// The operation failed for another reason not explicitly listed
|
||||
/// </summary>
|
||||
Cloud_Result_OtherFailure
|
||||
} Cloud_Result;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the cloud connection.
|
||||
/// </summary>
|
||||
/// <param name="el">An EventLoop that events may be registered to.</param>
|
||||
/// <param name="backendContext">
|
||||
/// Backend-specific context to be passed to the backend during initialization.
|
||||
/// </param>
|
||||
/// <param name="failureCallback">Function called on unrecoverable failure.</param>
|
||||
/// <param name="telemetryUploadEnabledChangedCallback">
|
||||
/// Function called by the cloud backend to indicates the telemetry upload enabled status
|
||||
/// has changed.
|
||||
/// </param>
|
||||
/// <param name="displayAlertCallback">
|
||||
/// Function called when the cloud backend requests an alert be displayed.
|
||||
/// </param>
|
||||
/// <param name="connectionChangedCallback">
|
||||
/// Function called when the status of the connection to the cloud backend changes.
|
||||
/// </param>
|
||||
/// <returns>An <see cref="ExitCode" /> indicating success or failure.</returns>
|
||||
ExitCode Cloud_Initialize(
|
||||
EventLoop *el, void *backendContext, ExitCode_CallbackType failureCallback,
|
||||
Cloud_TelemetryUploadEnabledChangedCallbackType telemetryUploadEnabledChangedCallback,
|
||||
Cloud_DisplayAlertCallbackType displayAlertCallback,
|
||||
Cloud_ConnectionChangedCallbackType connectionChangedCallback);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect and cleanup the cloud connection.
|
||||
/// </summary>
|
||||
void Cloud_Cleanup(void);
|
||||
|
||||
/// <summary>
|
||||
/// Queue sending telemtry to the cloud backend.
|
||||
/// </summary>
|
||||
/// <param name="telemetry">A pointer to a <see cref="Cloud_Telemetry" /> structure to send.</param>
|
||||
/// <returns>A <see cref="Cloud_Result" /> indicating success or failure.</returns>
|
||||
Cloud_Result Cloud_SendTelemetry(const Cloud_Telemetry *telemetry);
|
||||
|
||||
/// <summary>
|
||||
/// Queue sending an event to the cloud indicating that the device location has changed.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Cloud_Result" /> indicating success or failure.</returns>
|
||||
Cloud_Result Cloud_SendThermometerMovedEvent(void);
|
||||
|
||||
/// <summary>
|
||||
/// Queue sending device status to the cloud indicating whether telemetry upload is enabled.
|
||||
/// <result>A <see cref="Cloud_Result" /> indicating success or failure.</result>
|
||||
/// </summary>
|
||||
/// <param name="uploadEnabled">true if the telemetry upload is enabled; false otherwise</param>
|
||||
/// <returns>A <see cref="Cloud_Result" /> indicating success or failure.</returns>
|
||||
Cloud_Result Cloud_SendThermometerTelemetryUploadEnabledChangedEvent(bool uploadEnabled);
|
||||
|
||||
/// <summary>
|
||||
/// Queue sending device details to the cloud
|
||||
/// </summary>
|
||||
/// <param name="serialNumber">The device's serial number</param>
|
||||
/// <returns>A <see cref="Cloud_Result" /> indicating success or failure.</returns>
|
||||
Cloud_Result Cloud_SendDeviceDetails(const char *serialNumber);
|
|
@ -0,0 +1,70 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <applibs/eventloop.h>
|
||||
|
||||
#include <azureiot/iothub_device_client_ll.h>
|
||||
|
||||
#include "exitcodes.h"
|
||||
|
||||
// This header defines an interface for establishing a connection to Azure IoT.
|
||||
//
|
||||
// Implementations specific to each connection type (IoTHub, DPS and IoTEdge) can be found
|
||||
// in the corresponding directory.
|
||||
|
||||
/// <summary>
|
||||
/// Status of the connection attempt.
|
||||
/// </summary>
|
||||
typedef enum {
|
||||
Connection_NotStarted,
|
||||
Connection_Started,
|
||||
Connection_Complete,
|
||||
Connection_Failed
|
||||
} Connection_Status;
|
||||
|
||||
/// <summary>
|
||||
/// A callback type for a function to be invoked when connection status changes, following a call
|
||||
/// to <see cref="Connection_Start" />
|
||||
/// </summary>
|
||||
/// <param name="status">Connection status</param>
|
||||
/// <param name="iothubDeviceClientHandle">If <paramref name="status" /> is
|
||||
/// <see cref="Connection_Complete" />, this will contain a valid
|
||||
/// <see cref="IOTHUB_DEVICE_CLIENT_LL_HANDLE" />. Otherwise, NULL.</param>
|
||||
typedef void (*Connection_StatusCallbackType)(
|
||||
Connection_Status status, IOTHUB_DEVICE_CLIENT_LL_HANDLE iothubDeviceClientHandle);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize (but do not start) connection to an Azure IoT Hub. Requires
|
||||
/// implementation-specific context data retrieved from
|
||||
/// <see cref="Options_GetConnectionContext" />.
|
||||
/// </summary>
|
||||
/// <param name="el">Pointer to an EventLoop to which events can be registered.</param>
|
||||
/// <param name="statusCallBack">Function to be called when connection status changes.</param>
|
||||
/// <param name="failureCallback">Function called on unrecoverable failure.</param>
|
||||
/// <param name="modelId">Azure IoT PnP model ID, as a NULL-terminated string.</param>
|
||||
/// <param name="context">Implementation-specific context data required for connection.</param>
|
||||
/// <returns></returns>
|
||||
ExitCode Connection_Initialise(EventLoop *el, Connection_StatusCallbackType statusCallBack,
|
||||
ExitCode_CallbackType failureCallback, const char *modelId,
|
||||
void *context);
|
||||
|
||||
/// <summary>
|
||||
/// Begin connection to an Azure IoT Hub.
|
||||
///
|
||||
/// On successful connection, the status callback passed to
|
||||
/// <see cref="Connection_Initialize" /> will be invoked with an
|
||||
/// <see cref="IOTHUB_DEVICE_CLIENT_LL_HANDLE" /> and the <see cref="Connection_Status" />
|
||||
/// status. On failure, the status callback will be invoked with
|
||||
/// <see cref="Connection_Failed" />.
|
||||
///
|
||||
/// This is an asynchronous operation; it is not guaranteed that this function will return before
|
||||
/// the connection status callback is called.
|
||||
/// </summary>
|
||||
void Connection_Start(void);
|
||||
|
||||
/// <summary>
|
||||
/// Close and cleanup any resources needed by the Azure IoT Hub connection.
|
||||
/// </summary>
|
||||
void Connection_Cleanup(void);
|
|
@ -0,0 +1,61 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/// <summary>
|
||||
/// Exit codes for this application. These are used for the
|
||||
/// application exit code. They must all be between zero and 255,
|
||||
/// where zero is reserved for successful termination.
|
||||
/// </summary>
|
||||
typedef enum {
|
||||
ExitCode_Success = 0,
|
||||
|
||||
ExitCode_TermHandler_SigTerm = 1,
|
||||
|
||||
ExitCode_Main_EventLoopFail = 2,
|
||||
|
||||
ExitCode_ButtonTimer_Consume = 3,
|
||||
|
||||
ExitCode_AzureTimer_Consume = 4,
|
||||
|
||||
ExitCode_Init_EventLoop = 5,
|
||||
ExitCode_Init_Button = 6,
|
||||
/* ExitCode 7 no longer used */
|
||||
ExitCode_Init_Led = 8,
|
||||
ExitCode_Init_ButtonPollTimer = 9,
|
||||
ExitCode_Init_AzureTimer = 10,
|
||||
|
||||
ExitCode_IsButtonPressed_GetValue = 11,
|
||||
|
||||
/* ExitCode 12 no longer user */
|
||||
|
||||
ExitCode_Validate_ScopeId = 13,
|
||||
ExitCode_Validate_Hostname = 14,
|
||||
ExitCode_Validate_IoTEdgeCAPath = 15,
|
||||
|
||||
ExitCode_InterfaceConnectionStatus_Failed = 16,
|
||||
|
||||
ExitCode_IoTEdgeRootCa_Open_Failed = 17,
|
||||
ExitCode_IoTEdgeRootCa_LSeek_Failed = 18,
|
||||
ExitCode_IoTEdgeRootCa_FileSize_Invalid = 19,
|
||||
ExitCode_IoTEdgeRootCa_FileSize_TooLarge = 20,
|
||||
ExitCode_IoTEdgeRootCa_FileRead_Failed = 21,
|
||||
|
||||
ExitCode_PayloadSize_TooLarge = 22,
|
||||
|
||||
ExitCode_Init_TelemetryTimer = 23,
|
||||
ExitCode_TelemetryTimer_Consume = 24,
|
||||
|
||||
ExitCode_Validate_ConnectionConfig = 25,
|
||||
ExitCode_Connection_CreateTimer = 26,
|
||||
ExitCode_Connection_TimerStart = 27,
|
||||
ExitCode_Connection_TimerConsume = 28,
|
||||
ExitCode_Connection_InitializeClient = 29,
|
||||
} ExitCode;
|
||||
|
||||
/// <summary>
|
||||
/// Callback type for a function to be invoked when a fatal error with exit code needs to be raised.
|
||||
/// </summary>
|
||||
/// <param name="exitCode">Exit code representing the failure.</param>
|
||||
typedef void (*ExitCode_CallbackType)(ExitCode exitCode);
|
|
@ -0,0 +1,280 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
// This sample C application demonstrates how to use Azure Sphere devices with Azure IoT
|
||||
// services, using the Azure IoT C SDK.
|
||||
//
|
||||
// It implements a simulated thermometer device, with the following features:
|
||||
// - Telemetry upload (simulated temperature, device moved events) using Azure IoT Hub events.
|
||||
// - Reporting device state (serial number) using device twin/read-only properties.
|
||||
// - Mutable device state (telemetry upload enabled) using device twin/writeable properties.
|
||||
// - Alert messages invoked from the cloud using device methods.
|
||||
//
|
||||
// It can be configured using the top-level CMakeLists.txt to connect either directly to an
|
||||
// Azure IoT Hub, to an Azure IoT Edge device, or to use the Azure Device Provisioning service to
|
||||
// connect to either an Azure IoT Hub, or an Azure IoT Central application. All connection types
|
||||
// make use of the device certificate issued by the Azure Sphere security service to authenticate,
|
||||
// and supply an Azure IoT PnP model ID on connection.
|
||||
//
|
||||
// It uses the following Azure Sphere libraries:
|
||||
// - eventloop (system invokes handlers for timer events)
|
||||
// - gpio (digital input for button, digital output for LED)
|
||||
// - log (displays messages in the Device Output window during debugging)
|
||||
// - networking (network interface connection status)
|
||||
//
|
||||
// You will need to provide information in the application manifest to use this application. Please
|
||||
// see README.md and the other linked documentation for full details.
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// applibs_versions.h defines the API struct versions to use for applibs APIs.
|
||||
#include "applibs_versions.h"
|
||||
#include <applibs/eventloop.h>
|
||||
#include <applibs/networking.h>
|
||||
#include <applibs/log.h>
|
||||
|
||||
#include "eventloop_timer_utilities.h"
|
||||
#include "user_interface.h"
|
||||
#include "exitcodes.h"
|
||||
#include "cloud.h"
|
||||
#include "options.h"
|
||||
#include "connection.h"
|
||||
|
||||
static volatile sig_atomic_t exitCode = ExitCode_Success;
|
||||
|
||||
// Initialization/Cleanup
|
||||
static ExitCode InitPeripheralsAndHandlers(void);
|
||||
static void ClosePeripheralsAndHandlers(void);
|
||||
|
||||
// Interface callbacks
|
||||
static void ExitCodeCallbackHandler(ExitCode ec);
|
||||
static void ButtonPressedCallbackHandler(UserInterface_Button button);
|
||||
|
||||
// Cloud
|
||||
static const char *CloudResultToString(Cloud_Result result);
|
||||
static void ConnectionChangedCallbackHandler(bool connected);
|
||||
static void CloudTelemetryUploadEnabledChangedCallbackHandler(bool status);
|
||||
static void DisplayAlertCallbackHandler(const char *alertMessage);
|
||||
|
||||
// Timer / polling
|
||||
static EventLoop *eventLoop = NULL;
|
||||
static EventLoopTimer *telemetryTimer = NULL;
|
||||
|
||||
static bool isConnected = false;
|
||||
|
||||
// Business logic
|
||||
static void SetThermometerTelemetryUploadEnabled(bool uploadEnabled);
|
||||
static bool telemetryUploadEnabled = false; // False by default - do not send telemetry until told
|
||||
// by the user or the cloud
|
||||
|
||||
static const char *serialNumber = "TEMPMON-01234";
|
||||
|
||||
/// <summary>
|
||||
/// Signal handler for termination requests. This handler must be async-signal-safe.
|
||||
/// </summary>
|
||||
static void TerminationHandler(int signalNumber)
|
||||
{
|
||||
// Don't use Log_Debug here, as it is not guaranteed to be async-signal-safe.
|
||||
exitCode = ExitCode_TermHandler_SigTerm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main entry point for this sample.
|
||||
/// </summary>
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Log_Debug("Azure IoT Application starting.\n");
|
||||
|
||||
bool isNetworkingReady = false;
|
||||
if ((Networking_IsNetworkingReady(&isNetworkingReady) == -1) || !isNetworkingReady) {
|
||||
Log_Debug("WARNING: Network is not ready. Device cannot connect until network is ready.\n");
|
||||
}
|
||||
|
||||
exitCode = Options_ParseArgs(argc, argv);
|
||||
|
||||
if (exitCode != ExitCode_Success) {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
exitCode = InitPeripheralsAndHandlers();
|
||||
|
||||
// Main loop
|
||||
while (exitCode == ExitCode_Success) {
|
||||
EventLoop_Run_Result result = EventLoop_Run(eventLoop, -1, true);
|
||||
// Continue if interrupted by signal, e.g. due to breakpoint being set.
|
||||
if (result == EventLoop_Run_Failed && errno != EINTR) {
|
||||
exitCode = ExitCode_Main_EventLoopFail;
|
||||
}
|
||||
}
|
||||
|
||||
ClosePeripheralsAndHandlers();
|
||||
|
||||
Log_Debug("Application exiting.\n");
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
static void ExitCodeCallbackHandler(ExitCode ec)
|
||||
{
|
||||
exitCode = ec;
|
||||
}
|
||||
|
||||
static const char *CloudResultToString(Cloud_Result result)
|
||||
{
|
||||
switch (result) {
|
||||
case Cloud_Result_OK:
|
||||
return "OK";
|
||||
case Cloud_Result_NoNetwork:
|
||||
return "No network connection available";
|
||||
case Cloud_Result_OtherFailure:
|
||||
return "Other failure";
|
||||
}
|
||||
|
||||
return "Unknown Cloud_Result";
|
||||
}
|
||||
|
||||
static void SetThermometerTelemetryUploadEnabled(bool uploadEnabled)
|
||||
{
|
||||
telemetryUploadEnabled = uploadEnabled;
|
||||
UserInterface_SetStatus(uploadEnabled);
|
||||
|
||||
Cloud_Result result = Cloud_SendThermometerTelemetryUploadEnabledChangedEvent(uploadEnabled);
|
||||
if (result != Cloud_Result_OK) {
|
||||
Log_Debug(
|
||||
"WARNING: Could not send thermometer telemetry upload enabled changed event to cloud: "
|
||||
"%s",
|
||||
CloudResultToString(result));
|
||||
}
|
||||
}
|
||||
|
||||
static void ButtonPressedCallbackHandler(UserInterface_Button button)
|
||||
{
|
||||
if (button == UserInterface_Button_A) {
|
||||
bool newTelemetryUploadEnabled = !telemetryUploadEnabled;
|
||||
Log_Debug("INFO: Telemetry upload enabled state changed (via button press): %s\n",
|
||||
newTelemetryUploadEnabled ? "enabled" : "disabled");
|
||||
SetThermometerTelemetryUploadEnabled(newTelemetryUploadEnabled);
|
||||
} else if (button == UserInterface_Button_B) {
|
||||
Log_Debug("INFO: Device moved.\n");
|
||||
Cloud_Result result = Cloud_SendThermometerMovedEvent();
|
||||
if (result != Cloud_Result_OK) {
|
||||
Log_Debug("WARNING: Could not sent thermometer moved event to cloud: %s\n",
|
||||
CloudResultToString(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CloudTelemetryUploadEnabledChangedCallbackHandler(bool uploadEnabled)
|
||||
{
|
||||
Log_Debug("INFO: Thermometer telemetry upload enabled state changed (via cloud): %s\n",
|
||||
uploadEnabled ? "enabled" : "disabled");
|
||||
SetThermometerTelemetryUploadEnabled(uploadEnabled);
|
||||
}
|
||||
|
||||
static void DisplayAlertCallbackHandler(const char *alertMessage)
|
||||
{
|
||||
Log_Debug("ALERT: %s\n", alertMessage);
|
||||
}
|
||||
|
||||
static void ConnectionChangedCallbackHandler(bool connected)
|
||||
{
|
||||
isConnected = connected;
|
||||
|
||||
if (isConnected) {
|
||||
Cloud_Result result = Cloud_SendDeviceDetails(serialNumber);
|
||||
if (result != Cloud_Result_OK) {
|
||||
Log_Debug("WARNING: Could not send device details to cloud: %s\n",
|
||||
CloudResultToString(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TelemetryTimerCallbackHandler(EventLoopTimer *timer)
|
||||
{
|
||||
static Cloud_Telemetry telemetry = {.temperature = 50.f};
|
||||
|
||||
if (ConsumeEventLoopTimerEvent(timer) != 0) {
|
||||
exitCode = ExitCode_TelemetryTimer_Consume;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isConnected) {
|
||||
if (telemetryUploadEnabled) {
|
||||
// Generate a simulated temperature.
|
||||
float delta = ((float)(rand() % 41)) / 20.0f - 1.0f; // between -1.0 and +1.0
|
||||
telemetry.temperature += delta;
|
||||
|
||||
Cloud_Result result = Cloud_SendTelemetry(&telemetry);
|
||||
if (result != Cloud_Result_OK) {
|
||||
Log_Debug("WARNING: Could not send thermometer telemetry to cloud: %s\n",
|
||||
CloudResultToString(result));
|
||||
}
|
||||
} else {
|
||||
Log_Debug("INFO: Telemetry upload disabled; not sending telemetry.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set up SIGTERM termination handler, initialize peripherals, and set up event handlers.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// ExitCode_Success if all resources were allocated successfully; otherwise another
|
||||
/// ExitCode value which indicates the specific failure.
|
||||
/// </returns>
|
||||
static ExitCode InitPeripheralsAndHandlers(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(struct sigaction));
|
||||
action.sa_handler = TerminationHandler;
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
|
||||
eventLoop = EventLoop_Create();
|
||||
if (eventLoop == NULL) {
|
||||
Log_Debug("Could not create event loop.\n");
|
||||
return ExitCode_Init_EventLoop;
|
||||
}
|
||||
|
||||
struct timespec telemetryPeriod = {.tv_sec = 5, .tv_nsec = 0};
|
||||
telemetryTimer =
|
||||
CreateEventLoopPeriodicTimer(eventLoop, &TelemetryTimerCallbackHandler, &telemetryPeriod);
|
||||
if (telemetryTimer == NULL) {
|
||||
return ExitCode_Init_TelemetryTimer;
|
||||
}
|
||||
|
||||
ExitCode interfaceExitCode =
|
||||
UserInterface_Initialise(eventLoop, ButtonPressedCallbackHandler, ExitCodeCallbackHandler);
|
||||
|
||||
if (interfaceExitCode != ExitCode_Success) {
|
||||
return interfaceExitCode;
|
||||
}
|
||||
|
||||
UserInterface_SetStatus(telemetryUploadEnabled);
|
||||
|
||||
void *connectionContext = Options_GetConnectionContext();
|
||||
|
||||
return Cloud_Initialize(eventLoop, connectionContext, ExitCodeCallbackHandler,
|
||||
CloudTelemetryUploadEnabledChangedCallbackHandler,
|
||||
DisplayAlertCallbackHandler, ConnectionChangedCallbackHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close peripherals and handlers.
|
||||
/// </summary>
|
||||
static void ClosePeripheralsAndHandlers(void)
|
||||
{
|
||||
DisposeEventLoopTimer(telemetryTimer);
|
||||
Cloud_Cleanup();
|
||||
UserInterface_Cleanup();
|
||||
Connection_Cleanup();
|
||||
EventLoop_Close(eventLoop);
|
||||
|
||||
Log_Debug("Closing file descriptors\n");
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include "exitcodes.h"
|
||||
|
||||
// This header defines an interface for options parsing.
|
||||
// Implementations specific to each connection type (IoTHub, DPS and IoTEdge) can be found
|
||||
// in the corresponding directory.
|
||||
|
||||
/// <summary>
|
||||
/// Parse the provided options.
|
||||
/// </summary>
|
||||
/// <param name="argc">Number of arguments.</param>
|
||||
/// <param name="argv">Array of null-terminated strings representing the arguments.</param>
|
||||
/// <returns>An <see cref="ExitCode" /> indicating success or failure.</returns>
|
||||
ExitCode Options_ParseArgs(int argc, char *argv[]);
|
||||
|
||||
/// <summary>
|
||||
/// Get the context required for connection to the cloud as specified by the provided options.
|
||||
///
|
||||
/// The context returned from this function should be passed to
|
||||
/// <see cref="Connection_Initialize" />.
|
||||
/// You must call <see cref="Options_ParseArgs" /> before calling this function.
|
||||
/// </summary>
|
||||
/// <returns>Implementation-specific connection context data.</returns>
|
||||
void *Options_GetConnectionContext(void);
|
|
@ -0,0 +1,162 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <applibs/gpio.h>
|
||||
#include <applibs/log.h>
|
||||
|
||||
#include "user_interface.h"
|
||||
|
||||
// The following #include imports a "sample appliance" definition. This app comes with multiple
|
||||
// implementations of the sample appliance, each in a separate directory, which allow the code to
|
||||
// run on different hardware.
|
||||
//
|
||||
// By default, this app targets hardware that follows the MT3620 Reference Development Board (RDB)
|
||||
// specification, such as the MT3620 Dev Kit from Seeed Studio.
|
||||
//
|
||||
// To target different hardware, you'll need to update CMakeLists.txt. For example, to target the
|
||||
// Avnet MT3620 Starter Kit, change the TARGET_HARDWARE variable to
|
||||
// "avnet_mt3620_sk".
|
||||
//
|
||||
// See https://aka.ms/AzureSphereHardwareDefinitions for more details.
|
||||
#include <hw/sample_appliance.h>
|
||||
|
||||
#include "eventloop_timer_utilities.h"
|
||||
|
||||
static void ButtonPollTimerEventHandler(EventLoopTimer *timer);
|
||||
static bool IsButtonPressed(int fd, GPIO_Value_Type *oldState);
|
||||
static void CloseFdAndPrintError(int fd, const char *fdName);
|
||||
|
||||
// File descriptors - initialized to invalid value
|
||||
static int buttonAGpioFd = -1;
|
||||
static int buttonBGpioFd = -1;
|
||||
static int statusLedGpioFd = -1;
|
||||
|
||||
static EventLoopTimer *buttonPollTimer = NULL;
|
||||
|
||||
static ExitCode_CallbackType failureCallbackFunction = NULL;
|
||||
static UserInterface_ButtonPressedCallbackType buttonPressedCallbackFunction = NULL;
|
||||
|
||||
// State variables
|
||||
static GPIO_Value_Type buttonAState = GPIO_Value_High;
|
||||
static GPIO_Value_Type buttonBState = GPIO_Value_High;
|
||||
|
||||
/// <summary>
|
||||
/// Check whether a given button has just been pressed.
|
||||
/// </summary>
|
||||
/// <param name="fd">The button file descriptor</param>
|
||||
/// <param name="oldState">Old state of the button (pressed or released)</param>
|
||||
/// <returns>true if pressed, false otherwise</returns>
|
||||
static bool IsButtonPressed(int fd, GPIO_Value_Type *oldState)
|
||||
{
|
||||
bool isButtonPressed = false;
|
||||
GPIO_Value_Type newState;
|
||||
int result = GPIO_GetValue(fd, &newState);
|
||||
if (result != 0) {
|
||||
Log_Debug("ERROR: Could not read button GPIO: %s (%d).\n", strerror(errno), errno);
|
||||
failureCallbackFunction(ExitCode_IsButtonPressed_GetValue);
|
||||
} else {
|
||||
// Button is pressed if it is low and different than last known state.
|
||||
isButtonPressed = (newState != *oldState) && (newState == GPIO_Value_Low);
|
||||
*oldState = newState;
|
||||
}
|
||||
|
||||
return isButtonPressed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Button timer event: Check the status of the button
|
||||
/// </summary>
|
||||
static void ButtonPollTimerEventHandler(EventLoopTimer *timer)
|
||||
{
|
||||
if (ConsumeEventLoopTimerEvent(timer) != 0) {
|
||||
failureCallbackFunction(ExitCode_ButtonTimer_Consume);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsButtonPressed(buttonAGpioFd, &buttonAState) && NULL != buttonPressedCallbackFunction) {
|
||||
buttonPressedCallbackFunction(UserInterface_Button_A);
|
||||
}
|
||||
|
||||
if (IsButtonPressed(buttonBGpioFd, &buttonBState) && NULL != buttonPressedCallbackFunction) {
|
||||
buttonPressedCallbackFunction(UserInterface_Button_B);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a file descriptor and prints an error on failure.
|
||||
/// </summary>
|
||||
/// <param name="fd">File descriptor to close</param>
|
||||
/// <param name="fdName">File descriptor name to use in error message</param>
|
||||
static void CloseFdAndPrintError(int fd, const char *fdName)
|
||||
{
|
||||
if (fd >= 0) {
|
||||
int result = close(fd);
|
||||
if (result != 0) {
|
||||
Log_Debug("ERROR: Could not close fd %s: %s (%d).\n", fdName, strerror(errno), errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExitCode UserInterface_Initialise(EventLoop *el,
|
||||
UserInterface_ButtonPressedCallbackType buttonPressedCallback,
|
||||
ExitCode_CallbackType failureCallback)
|
||||
{
|
||||
failureCallbackFunction = failureCallback;
|
||||
buttonPressedCallbackFunction = buttonPressedCallback;
|
||||
|
||||
// Open SAMPLE_BUTTON_1 GPIO as input
|
||||
Log_Debug("Opening SAMPLE_BUTTON_1 as input.\n");
|
||||
buttonAGpioFd = GPIO_OpenAsInput(SAMPLE_BUTTON_1);
|
||||
if (buttonAGpioFd == -1) {
|
||||
Log_Debug("ERROR: Could not open SAMPLE_BUTTON_1: %s (%d).\n", strerror(errno), errno);
|
||||
return ExitCode_Init_Button;
|
||||
}
|
||||
|
||||
// Open SAMPLE_BUTTON_2 GPIO as input
|
||||
Log_Debug("Opening SAMPLE_BUTTON_2 as input.\n");
|
||||
buttonBGpioFd = GPIO_OpenAsInput(SAMPLE_BUTTON_2);
|
||||
if (buttonBGpioFd == -1) {
|
||||
Log_Debug("ERROR: Could not open SAMPLE_BUTTON_2: %s (%d).\n", strerror(errno), errno);
|
||||
return ExitCode_Init_Button;
|
||||
}
|
||||
|
||||
// SAMPLE_LED is used to show state
|
||||
Log_Debug("Opening SAMPLE_LED as output.\n");
|
||||
statusLedGpioFd = GPIO_OpenAsOutput(SAMPLE_LED, GPIO_OutputMode_PushPull, GPIO_Value_High);
|
||||
if (statusLedGpioFd == -1) {
|
||||
Log_Debug("ERROR: Could not open SAMPLE_LED: %s (%d).\n", strerror(errno), errno);
|
||||
return ExitCode_Init_Led;
|
||||
}
|
||||
|
||||
// Set up a timer to poll for button events.
|
||||
static const struct timespec buttonPressCheckPeriod = {.tv_sec = 0, .tv_nsec = 1000 * 1000};
|
||||
buttonPollTimer =
|
||||
CreateEventLoopPeriodicTimer(el, &ButtonPollTimerEventHandler, &buttonPressCheckPeriod);
|
||||
if (buttonPollTimer == NULL) {
|
||||
return ExitCode_Init_ButtonPollTimer;
|
||||
}
|
||||
|
||||
return ExitCode_Success;
|
||||
}
|
||||
|
||||
void UserInterface_Cleanup(void)
|
||||
{
|
||||
DisposeEventLoopTimer(buttonPollTimer);
|
||||
|
||||
// Leave the LEDs off
|
||||
if (statusLedGpioFd >= 0) {
|
||||
GPIO_SetValue(statusLedGpioFd, GPIO_Value_High);
|
||||
}
|
||||
|
||||
CloseFdAndPrintError(buttonAGpioFd, "ButtonA");
|
||||
CloseFdAndPrintError(buttonBGpioFd, "ButtonB");
|
||||
CloseFdAndPrintError(statusLedGpioFd, "StatusLed");
|
||||
}
|
||||
|
||||
void UserInterface_SetStatus(bool status)
|
||||
{
|
||||
GPIO_SetValue(statusLedGpioFd, status ? GPIO_Value_Low : GPIO_Value_High);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License. */
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <applibs/eventloop.h>
|
||||
#include "exitcodes.h"
|
||||
|
||||
typedef enum {
|
||||
UserInterface_Button_A,
|
||||
UserInterface_Button_B,
|
||||
} UserInterface_Button;
|
||||
|
||||
/// <summary>
|
||||
/// Callback for a function to be invoked when a button is pressed.
|
||||
/// </summary>
|
||||
/// <param name="buttonPressed">A <see cref="UserInterface_Button" /> value indicating which
|
||||
/// button was pressed.</param>
|
||||
typedef void (*UserInterface_ButtonPressedCallbackType)(UserInterface_Button buttonPressed);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the user interface.
|
||||
/// </summary>
|
||||
/// <param name="el">Pointer to an EventLoop to which events can be registered.</param>
|
||||
/// <param name="buttonPressed">Function to be called when a button is pressed.</param>
|
||||
/// <param name="failureCallback">Function called on unrecoverable failure.</param>
|
||||
/// <returns>An <see cref="ExitCode" /> indicating success or failure.</returns>
|
||||
ExitCode UserInterface_Initialise(EventLoop *el,
|
||||
UserInterface_ButtonPressedCallbackType buttonPressed,
|
||||
ExitCode_CallbackType failureCallback);
|
||||
|
||||
/// <summary>
|
||||
/// Close and clean up the user interface.
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
void UserInterface_Cleanup(void);
|
||||
|
||||
/// <summary>
|
||||
/// Set the status of the status LED.
|
||||
/// </summary>
|
||||
/// <param name="status">Status LED status.</param>
|
||||
void UserInterface_SetStatus(bool status);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 331 KiB |
|
@ -1,59 +1,56 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
param(
|
||||
[Parameter(Mandatory=$True)][string] $Manifest,
|
||||
[Parameter(Mandatory=$True)][string] $Helper
|
||||
)
|
||||
|
||||
Write-Output "Validating project app_manifest.json"
|
||||
Import-Module -Name $Helper
|
||||
|
||||
$scriptPath =Split-Path $PSCommandPath -Parent
|
||||
$manifestFile = Join-Path $scriptPath "..\app_manifest.json" -Resolve -ErrorAction SilentlyContinue
|
||||
if ($manifestFile -eq $null) {
|
||||
Write-Output "Error: Cannot find the app_manifest.json"
|
||||
Write-Output "Validating project $($Manifest)"
|
||||
|
||||
$manifestPreset = Test-Path $Manifest
|
||||
|
||||
if (-not $manifestPreset) {
|
||||
Write-Output "Error: Cannot find the app_manifest.json at $($Manifest)"
|
||||
return 1
|
||||
}
|
||||
|
||||
$ret=0
|
||||
$deviceAuthPlaceholder="00000000-0000-0000-0000-000000000000"
|
||||
$dpsEndpoint = "global.azure-devices-provisioning.net"
|
||||
|
||||
$json = Get-Content $manifestFile -Raw
|
||||
$json = Get-Content $Manifest -Raw
|
||||
$jsonObj = ConvertFrom-Json -InputObject $json
|
||||
|
||||
$cmdArgs = $jsonobj.CmdArgs
|
||||
Write-Host $cmdArgs
|
||||
if ($cmdArgs -eq $null -or $cmdArgs.Count -eq 0) {
|
||||
Write-Output "Error: The app_manifest.json 'CmdArgs' needs to contain the ConnectionType, Azure IoT Hub hostname and Device ID for Direct Connection, or ConnectionType and Scope ID for DPS connection."
|
||||
Write-Output "Error: The 'CmdArgs' field in your app_manifest.json must be set."
|
||||
$ret=1
|
||||
}
|
||||
|
||||
$allowedConnections=$jsonobj.Capabilities.AllowedConnections
|
||||
if($allowedConnections -eq $null)
|
||||
{
|
||||
$connectionCount = 0
|
||||
} else {
|
||||
$connectionCount = $allowedConnections.Count
|
||||
$cmdArgsErrors = Test-CmdArgs $cmdArgs
|
||||
|
||||
if ($cmdArgsErrors.Count -gt 0) {
|
||||
Write-Output $cmdArgsErrors
|
||||
$ret = 1
|
||||
}
|
||||
|
||||
# Check for Azure DPS endpoint address only if ConnectionType is set to DPS.
|
||||
if ($cmdArgs -contains "--ConnectionType DPS") {
|
||||
if ($connectionCount -gt 0 -and $allowedConnections.Contains($dpsEndpoint)) {
|
||||
$connectionCount--
|
||||
} else {
|
||||
Write-Output "Error: The app_manifest.json 'AllowedConnections' needs to contain the Azure DPS endpoint address (global.azure-devices-provisioning.net)"
|
||||
$ret=1
|
||||
}
|
||||
}
|
||||
$allowedConnectionsErrors = Test-AllowedConnections $jsonobj.Capabilities.AllowedConnections
|
||||
|
||||
if ($connectionCount -eq 0) {
|
||||
Write-Output "Error: The app_manifest.json 'AllowedConnections' needs to contain your IoT Hub/Central application endpoint address(es)"
|
||||
$ret=1
|
||||
if ($allowedConnectionsErrors.Count -gt 0) {
|
||||
Write-Output $allowedConnectionsErrors
|
||||
$ret = 1
|
||||
}
|
||||
|
||||
$deviceAuth=$jsonobj.Capabilities.DeviceAuthentication
|
||||
if ($deviceAuth -eq $null -or $deviceAuth -eq $deviceAuthPlaceholder) {
|
||||
Write-Output "Error: The app_manifest.json 'DeviceAuthentication' needs to contain your Azure Sphere Tenant Id. This can be obtained using the Azure Sphere Developer Command Prompt 'azsphere tenant show-selected'".
|
||||
Write-Output "Error: The 'DeviceAuthentication' field in your app_maifest.json must be set to your Azure Sphere Tenant Id. This can be obtained using the Azure Sphere Developer Command Prompt 'azsphere tenant show-selected'".
|
||||
$ret=1
|
||||
}
|
||||
|
||||
if ($ret -eq 0) {
|
||||
Write-Output "app_manifest.json IoT Hub/Central parameters exist."
|
||||
Write-Output "app_manifest.json parameters exist."
|
||||
}
|
||||
|
||||
exit $ret
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(Cert_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -18,102 +18,97 @@ extendedZipContent:
|
|||
target: SECURITY.md
|
||||
- path: Samples/troubleshooting.md
|
||||
target: troubleshooting.md
|
||||
description: "Shows how to use certificates in an Azure Sphere high-level application."
|
||||
description: "Shows how to use and manage certificates in an Azure Sphere high-level application."
|
||||
---
|
||||
|
||||
# Sample: Certificates high-level app
|
||||
|
||||
This sample shows how to use certificates in an Azure Sphere high-level application.
|
||||
This sample demonstrates how to use and manage certificates in an Azure Sphere high-level application.
|
||||
|
||||
BUTTON_1 cycles through commands on the example certificates in this order:
|
||||
Button A (BUTTON_1) is used by the sample to perform certificate-management operations, such as certificate installation and deletion. Button B (BUTTON_2) displays certificate-related information such as the amount of space that is available on the device for certificate storage. Each button press executes a particular operation on the device.
|
||||
|
||||
1. Installs a client and a root certificate.
|
||||
1. Installs a second root certificate.
|
||||
1. Replaces the first root certificate with the second root certificate.
|
||||
1. Reloads the Wi-Fi network (this step is required for an EAP-TLS network).
|
||||
1. Deletes the certificates.
|
||||
|
||||
BUTTON_2 does the following:
|
||||
|
||||
1. Displays the available space for certificate storage on the device.
|
||||
1. Displays the number of available certificates on the device.
|
||||
1. Lists the certificate identifier, subject name, issuer name, and validity dates for each certificate that is installed on the device.
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [gpio.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) |Contains functions and types that interact with GPIOs. |
|
||||
| [log.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Contains functions that log debug messages. |
|
||||
| [certstore.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-certstore/certstore-overview) | Contains functions and types that interact with certificates. |
|
||||
| [wificonfig.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-wificonfig/wificonfig-overview) | Contains functions and types that interact with networking. |
|
||||
| [certstore](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-certstore/certstore-overview) | Contains functions and types that interact with certificates. |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) |Contains functions and types that interact with GPIOs. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Contains functions that log debug messages. |
|
||||
| [wificonfig](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-wificonfig/wificonfig-overview) | Contains functions and types that interact with networking. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This sample requires the following certificates in either PKCS1 or PKCS8 encoding and PEM format:
|
||||
The sample requires the following items:
|
||||
|
||||
- Two Root CA certificates
|
||||
- A client certificate, a client private key, and the private key password if one exists
|
||||
- An Azure Sphere device
|
||||
|
||||
If you don't already have certificates for testing, follow the instructions in [How to generate certificates for use with samples](get-certificates.md) to create the certificates you'll need.
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
Refer to the following topics for information about how to manage certificates and configure an EAP-TLS network in a high-level Azure Sphere application:
|
||||
- The following certificates in either PKCS1 or PKCS8 encoding and PEM format:
|
||||
|
||||
- [Manage certificates in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/certstore)
|
||||
- [Set up EAP-TLS network in an app](https://docs.microsoft.com/azure-sphere/network/eap-tls-app-setup)
|
||||
- Two Root CA certificates
|
||||
- A client certificate, a client private key, and the private key password if one exists
|
||||
|
||||
The sample requires the following hardware:
|
||||
If you don't already have certificates for testing, follow the instructions in [How to generate certificates for use with samples](get-certificates.md) to create the certificates you'll need.
|
||||
|
||||
- Azure Sphere device
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer and your computer is connected to the internet.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *Cert_HighLevelApp* sample in the *Certificates* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/certificates/).
|
||||
|
||||
## Add your example certificates to the application
|
||||
### Add your example certificates to the application
|
||||
|
||||
**Caution!** Because [Certificate IDs](https://docs.microsoft.com/azure-sphere/app-development/certstore#certificate-ids) are system-wide, an **azsphere** command or a function call that adds a new certificate can overwrite a certificate that was added by an earlier
|
||||
command or function call, potentially causing network connection failures. We strongly recommend that you develop clear certificate update procedures and choose
|
||||
certificate IDs carefully.
|
||||
|
||||
To add your certificates to the application, make the following changes to [main.c](./main.c):
|
||||
To add your certificates to the application, make the following changes in the sample:
|
||||
|
||||
1. Add your root CA certificate:
|
||||
|
||||
1. Open your root CA certificate in a text editor and copy the entire content of the certificate, including the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- tags.
|
||||
1. In main.c, search for the line `static const char *rootCACertContent = "root_ca_cert_content";` and replace `root_ca_cert_content` with the content of your root CA certificate.
|
||||
1. In `main.c`, search for the line `static const char *rootCACertContent = "root_ca_cert_content";` and replace `root_ca_cert_content` with the content of your root CA certificate.
|
||||
|
||||
1. Add your second root CA certificate:
|
||||
|
||||
1. Open your second root CA certificate in a text editor and copy the content of the certificate, including the tags.
|
||||
1. In main.c, search for the line `static const char *newRootCACertContent = "new_root_ca_cert_content";` and replace `new_root_ca_cert_content` with the content of your second root CA certificate.
|
||||
1. In `main.c`, search for the line `static const char *newRootCACertContent = "new_root_ca_cert_content";` and replace `new_root_ca_cert_content` with the content of your second root CA certificate.
|
||||
|
||||
1. Add your client certificate:
|
||||
|
||||
1. Open your client certificate in a text editor and copy the content of the certificate, including the tags.
|
||||
1. In main.c, search for the line `static const char *clientCertContent = "client_cert_content";` and replace `client_cert_content` with the content of your client certificate.
|
||||
1. In `main.c`, search for the line `static const char *clientCertContent = "client_cert_content";` and replace `client_cert_content` with the content of your client certificate.
|
||||
|
||||
1. Add your client private key:
|
||||
|
||||
1. Open your client private key in a text editor and the copy the content of the private key, including the tags. The text of the tags will vary depending on whether the key uses PKCS1 or PKCS8 encryption.
|
||||
|
||||
In addition, if you used PKCS1 encryption or followed the instructions in [How to generate certificates for use with samples](get-certificates.md), you must add a newline character (`\n') at the end of the third line of content. This line starts with "DEK-Info:" and is followed by a hyphenated string that starts with "DES-", a comma, and a 16-character hexadecimal value. Insert '\n' after the hexadecimal value, with no intervening spaces. If the content contains a blank line at this position, delete it.
|
||||
1. In main.c, search for the line `static const char *clientPrivateKeyContent = "client_private_key_content";` and replace `client_private_key_content` with your client private key.
|
||||
1. Add your client key password:
|
||||
1. In main.c, search for the line `static const char *clientPrivateKeyPassword = "client_private_key_password";` and replace `client_private_key_password` with the client private key password.
|
||||
1. In `main.c`, search for the line `static const char *clientPrivateKeyContent = "client_private_key_content";` and replace `client_private_key_content` with your client private key.
|
||||
|
||||
**Note:** If the client key was created without a password, replace `client_private_key_password` with `NULL`.
|
||||
1. Add your client key password: In `main.c`, search for the line `static const char *clientPrivateKeyPassword = "client_private_key_password";` and replace `client_private_key_password` with the client private key password.
|
||||
|
||||
**Note:** If the client key was created without a password, replace `client_private_key_password` with `NULL`.
|
||||
|
||||
**Note:** If your certificate content spans more than one line, add a line continuation character (`\`) at the end of each line. If you added a newline character to the private key content, add the line continuation character after the newline.
|
||||
|
||||
|
@ -121,8 +116,26 @@ To add your certificates to the application, make the following changes to [main
|
|||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
The output will be displayed in the terminal window.
|
||||
The output will be displayed in the terminal window. Use the buttons on the device to cycle through several operations related to certificates. Each button press executes a particular operation on the device.
|
||||
|
||||
Use BUTTON_1 and BUTTON_2 as directed in the sample description, above.
|
||||
Button A (BUTTON_1) performs the following management operations in the order specified:
|
||||
|
||||
1. Installs a client and a root certificate.
|
||||
1. Installs a second root certificate.
|
||||
1. Replaces the first root certificate with the second root certificate.
|
||||
1. Reloads the Wi-Fi network (this step is required for an EAP-TLS network).
|
||||
1. Deletes the certificates.
|
||||
|
||||
Button B (BUTTON_2) performs the following display operations in the order specified:
|
||||
|
||||
1. Displays the space that is available for certificate storage on the device.
|
||||
1. Displays the number of available certificates on the device.
|
||||
1. Lists the certificate identifier, subject name, issuer name, and validity dates for each certificate that is installed on the device.
|
||||
|
||||
## Next steps
|
||||
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For details about how an application can set up an EAP-TLS network, see [Set up EAP-TLS network from an app](https://docs.microsoft.com/azure-sphere/network/eap-tls-app-setup).
|
||||
- To learn more about certificate management, see [Manage certificates in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/certstore).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(CustomNTP_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -18,177 +18,138 @@ extendedZipContent:
|
|||
target: SECURITY.md
|
||||
- path: Samples/troubleshooting.md
|
||||
target: troubleshooting.md
|
||||
- path: ethernet-setup-instructions.md
|
||||
target: ethernet-setup-instructions.md
|
||||
description: "Demonstrates how to configure custom NTP servers on an MT3620 device."
|
||||
---
|
||||
|
||||
# Sample: Custom NTP high-level app
|
||||
|
||||
This sample application demonstrates how to configure custom NTP servers on an MT3620 device. After you configure the sample with your NTP server configuration in the application manifest, you can use the button and status LED on the device as follows:
|
||||
This sample application demonstrates how to configure custom NTP servers on an MT3620 device.
|
||||
|
||||
SAMPLE_BUTTON_1 does the following:
|
||||
- Gets the last time synced information
|
||||
- If the device has not yet successfully time synced, the sample logs a debug message informing the user that the device has not time synced as yet.
|
||||
- If the device has successfully time synced, the sample logs a message displaying the time before the sync, and the new adjusted time after the successful sync.
|
||||
The sample configures the NTP servers according to your configuration in the application manifest file. The last-time-synced information is retrieved when button A is pressed. The color of the LED indicates the time-synced status.
|
||||
|
||||
Status LED indicates the following:
|
||||
- Red - Not time synced. This state is true on reboot till the device successfully time syncs with the NTP server, or when the NTP server config is changed and the device has not yet synced with the NTP server.
|
||||
- Green - The device has time synced successfully to the NTP server. This state is true when the device successfully syncs with the configured NTP server.
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
The sample uses the following Azure Sphere libraries:
|
||||
|
||||
|Library |Purpose |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages button A (SAMPLE_BUTTON_1) and LED 2 on the device |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Networking related API calls |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages button A (SAMPLE_BUTTON_1) and LED 2 on the device. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Manages the network configuration of the device. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/Folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json | Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures Visual Studio to use CMake with the correct command-line options. |
|
||||
| launch.vs.json | Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
| .vscode | Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The sample requires the following hardware:
|
||||
|
||||
1. [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
- [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, make the following changes:
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
1. Configure Azure Sphere as described in [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet).
|
||||
1. Add an Ethernet adapter to your hardware. If you are using an MT3620 RDB, see the [wiring instructions](../../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
1. In CustomNTP_HighLevelApp/main.c, ensure that the global constant `networkInterface` is set to "eth0". In the source file CustomNTP_HighLevelApp/main.c, search for the following line:
|
||||
## Setup
|
||||
|
||||
`static const char networkInterface[] = "wlan0";`
|
||||
|
||||
Change this line to:
|
||||
|
||||
`static const char networkInterface[] = "eth0";`
|
||||
1. In CustomNTP_HighLevelApp/main.c, add a call to `Networking_SetInterfaceState` before any other networking calls:
|
||||
|
||||
```c
|
||||
int err = Networking_SetInterfaceState(networkInterface, true);
|
||||
if (err == -1) {
|
||||
Log_Debug("Error setting interface state %d\n",errno);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
## Prepare the sample
|
||||
Complete the following steps to set up this sample.
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer, and your computer is connected to the internet.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Install the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Install the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *CustomNTP_HighLevelApp* sample in the *CustomNTP* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/customntp/).
|
||||
|
||||
## Configure the sample application to work with your NTP server configuration
|
||||
There are three different types of NTP server configurations possible:
|
||||
1. Configure the sample application to work with your NTP server configuration. There are three different types of NTP server configurations possible:
|
||||
|
||||
1. System default (prod.time.sphere.azure.net)
|
||||
1. DHCP (Automatic) NTP server
|
||||
1. Custom NTP server
|
||||
- System default (`prod.time.sphere.azure.net`) NTP server — See the [System default NTP server configuration](#system-default-ntp-server-configuration) section for setup instructions.
|
||||
- DHCP-assigned (Automatic) NTP server — See the [DHCP-assigned NTP server configuration](#dhcp-assigned-ntp-server-configuration) section for setup instructions.
|
||||
- Custom NTP server — See the [Custom NTP server configuration](#custom-ntp-server-configuration) section for setup instructions.
|
||||
|
||||
The sample can be configured with any one type at a time.
|
||||
The sample can be configured with any one type at a time. For details, see the section [Specifying an NTP Server](https://docs.microsoft.com/azure-sphere/app-development/rtc#specifying-an-ntp-server) in the topic [Manage system time and the RTC in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/rtc).
|
||||
|
||||
For more information, see [Specifying an NTP Server](https://docs.microsoft.com/azure-sphere/app-development/rtc#Specifying-an-NTP-Server).
|
||||
### Use Ethernet instead of Wi-Fi
|
||||
|
||||
### System Default
|
||||
This uses the system default (prod.time.sphere.azure.net) as the time source.
|
||||
To configure the sample to connect to the system default NTP server, copy and paste the following line into the CmdArgs field of the app_manifest.json file:
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, follow the [Ethernet setup instructions](../../../ethernet-setup-instructions.md).
|
||||
|
||||
`"CmdArgs": [ "--TimeSource", "Default" ]`
|
||||
### System default NTP server configuration
|
||||
|
||||
### Automatic NTP server
|
||||
This configures the sample to connect to the NTP servers assigned by DHCP.
|
||||
You will need the following information:
|
||||
- The time source to use
|
||||
- Fallback enabled or disabled
|
||||
In this configuration, the sample connects to the system default (`prod.time.sphere.azure.net`) NTP server.
|
||||
|
||||
Update the CmdArgs field of the app_manifest.json file:
|
||||
- To configure the sample to connect to the DHCP assigned NTP servers, copy and paste the following line into the CmdArgs field of the app_manifest.json file:
|
||||
To configure the sample to connect to the system default NTP server, add `"--TimeSource", "Default"` in the **CmdArgs** field of the `app_manifest.json` file.
|
||||
|
||||
`"--TimeSource", "Automatic"`
|
||||
- Fallback is enabled by default. Configure this option only if you want fallback to be disabled.
|
||||
To disable fallback, set the `DisableFallback` option in the CmdArgs field of the app_manifest.json file, as shown below:
|
||||
The **CmdArgs** field should now look like the following: `"CmdArgs": [ "--TimeSource", "Default" ]`
|
||||
|
||||
`"--DisableFallback"`
|
||||
### DHCP-assigned NTP server configuration
|
||||
|
||||
Note: This option does not have an argument.
|
||||
In this configuration, the sample connects to an NTP server that is assigned by DHCP.
|
||||
|
||||
- Your CmdArgs field should now look like:
|
||||
- With fallback enabled
|
||||
To configure the sample to connect to a DHCP-assigned NTP server, make the following revisions in the `app_manifest.json` file:
|
||||
|
||||
`"CmdArgs": [ "--TimeSource", "Automatic" ]`
|
||||
1. Add `"--TimeSource", "Automatic"` in the **CmdArgs** field.
|
||||
1. Fallback is enabled by default. To disable fallback, add `"--DisableFallback"` in the **CmdArgs** field. Configure this option only if you want fallback to be disabled.
|
||||
|
||||
- With fallback disabled
|
||||
The **CmdArgs** field should now look like the following:
|
||||
|
||||
`"CmdArgs": [ "--TimeSource", "Automatic", "--DisableFallback" ]`
|
||||
- With fallback enabled: `"CmdArgs": [ "--TimeSource", "Automatic" ]`
|
||||
- With fallback disabled: `"CmdArgs": [ "--TimeSource", "Automatic", "--DisableFallback" ]`
|
||||
|
||||
### Custom NTP server configuration
|
||||
|
||||
### Custom NTP servers
|
||||
This configures the sample to connect to up to two user-configured NTP servers. If you do not have access to an NTP server for testing, see https://www.pool.ntp.org/ for a list of NTP servers you could use with the sample.
|
||||
In this configuration, the sample connects to up to two user-configured NTP servers. If you do not have access to an NTP server for testing, see [NTP Pool Project](https://www.pool.ntp.org/) for a list of NTP servers you can use with the sample.
|
||||
|
||||
You will need the following information:
|
||||
- The time source to use
|
||||
- Fallback enabled or disabled
|
||||
- Primary NTP server hostname or IP.
|
||||
- Secondary NTP server hostname or IP. This is optional.
|
||||
To configure the sample to connect to a primary NTP server and, optionally, a secondary NTP server, make the following revisions in the `app_manifest.json` file:
|
||||
|
||||
Update the CmdArgs field of the app_manifest.json file:
|
||||
- To configure the sample to connect to the DHCP assigned NTP servers, copy and paste the following line into the CmdArgs field of the app_manifest.json file:
|
||||
1. Add `"--TimeSource", "Custom"` in the **CmdArgs** field.
|
||||
1. Fallback is enabled by default. To disable fallback, add `"--DisableFallback"` in the **CmdArgs** field. Configure this option only if you want fallback to be disabled.
|
||||
1. Add `"--PrimaryNTPServer", "<hostname_or_ip>"` in the **CmdArgs** field and replace *`<hostname_or_ip>`* with the hostname or IP address of your primary NTP server.
|
||||
1. If you want the sample to connect to a secondary NTP server, add `"--SecondaryNTPServer", "<hostname_or_ip>"` in the **CmdArgs** field and replace *`<hostname_or_ip>`* with the hostname or IP address of your secondary NTP server.
|
||||
|
||||
`"--TimeSource", "Custom"`
|
||||
The **CmdArgs** field should now look the following:
|
||||
|
||||
- Fallback is enabled by default. Configure this option only if you want fallback to be disabled.
|
||||
To disable fallback, set the `DisableFallback` option in the CmdArgs field of the app_manifest.json file, as shown below:
|
||||
- With only a primary NTP server configured:
|
||||
|
||||
`"--DisableFallback"`
|
||||
- With fallback enabled: `"CmdArgs": [ "--TimeSource", "Custom", "--PrimaryNtpServer", "<hostname_or_ip>" ]`
|
||||
- With fallback disabled: `"CmdArgs": [ "--TimeSource", "Custom", "--DisableFallback", "--PrimaryNtpServer", "<hostname_or_ip>" ]`
|
||||
|
||||
Note: This option does not have an argument.
|
||||
|
||||
- Specify the hostname or IP of the primary NTP server in the CmdArgs field of the app_manifest.json file, as shown below:
|
||||
|
||||
`"--PrimaryNTPServer", "<hostname_or_ip>"`
|
||||
|
||||
- Optionally, you can also specify the hostname or IP of the secondary NTP server in the CmdArgs field of the app_manifest.json file, as shown below:
|
||||
|
||||
`"--SecondaryNTPServer", "<hostname_or_ip>"`
|
||||
|
||||
- Your CmdArgs field should now look like:
|
||||
- Without secondary NTP server configured and fallback enabled
|
||||
|
||||
`"CmdArgs": [ "--TimeSource", "Custom", "--PrimaryNtpServer", "<hostname_or_ip>" ]`
|
||||
|
||||
- Without secondary NTP server configured and fallback disabled
|
||||
|
||||
`"CmdArgs": [ "--TimeSource", "Custom", "--DisableFallback", "--PrimaryNtpServer", "<hostname_or_ip>" ]`
|
||||
|
||||
- With secondary NTP server configured and fallback enabled
|
||||
|
||||
`"CmdArgs": [ "--TimeSource", "Custom", "--PrimaryNtpServer", "<hostname_or_ip>", "--SecondaryNtpServer", "<hostname_or_ip>" ]`
|
||||
|
||||
- With secondary NTP server configured and fallback disabled
|
||||
|
||||
`"CmdArgs": [ "--TimeSource", "Custom", "--DisableFallback", "--PrimaryNtpServer", "<hostname_or_ip>", "--SecondaryNtpServer", "<hostname_or_ip>" ]`
|
||||
- With a secondary NTP server configured:
|
||||
|
||||
- With fallback enabled: `"CmdArgs": [ "--TimeSource", "Custom", "--PrimaryNtpServer", "<hostname_or_ip>", "--SecondaryNtpServer", "<hostname_or_ip>" ]`
|
||||
- With fallback disabled: `"CmdArgs": [ "--TimeSource", "Custom", "--DisableFallback", "--PrimaryNtpServer", "<hostname_or_ip>", "--SecondaryNtpServer", "<hostname_or_ip>" ]`
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../..//BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
The output will be displayed in the terminal window. When the sample runs, it will configure the NTP servers as per your configuration in the application manifest file.
|
||||
When the sample runs, it configures the NTP servers according to your configuration in the application manifest file. The output will be displayed in the terminal window. Use button A (SAMPLE_BUTTON_1) and the status LED as described below.
|
||||
|
||||
Use SAMPLE_BUTTON_1 and Status LED as directed in the sample description, above.
|
||||
SAMPLE_BUTTON_1 does the following:
|
||||
|
||||
- Gets the last-time-synced information.
|
||||
- If the device has not yet successfully time-synced, the sample logs a debug message informing the user that the device has not time-synced yet.
|
||||
- If the device has successfully time-synced, the sample logs a message displaying the time before the sync, and the new adjusted time after the successful sync.
|
||||
|
||||
The color of the status LED indicates the following:
|
||||
|
||||
- Red — Not time-synced. This state is true on reboot till the device successfully time-syncs with the NTP server, or when the NTP server config is changed and the device has not yet synced with the NTP server.
|
||||
- Green — The device has time-synced successfully to the NTP server. This state is true when the device successfully syncs with the configured NTP server.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For network troubleshooting, see [Troubleshoot network problems](https://docs.microsoft.com/azure-sphere/network/troubleshoot-network-problems).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(DNSServiceDiscovery C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c dns-sd.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -16,6 +16,8 @@ extendedZipContent:
|
|||
target: SECURITY.md
|
||||
- path: Samples/troubleshooting.md
|
||||
target: troubleshooting.md
|
||||
- path: ethernet-setup-instructions.md
|
||||
target: ethernet-setup-instructions.md
|
||||
description: "Demonstrates how to perform service discovery on the local network by using multicast DNS (mDNS)."
|
||||
---
|
||||
|
||||
|
@ -25,112 +27,98 @@ description: "Demonstrates how to perform service discovery on the local network
|
|||
|
||||
This sample demonstrates how to perform [DNS service discovery](https://docs.microsoft.com/azure-sphere/app-development/service-discovery) by sending DNS-SD queries to the local network using multicast DNS (mDNS).
|
||||
|
||||
The application queries the local network for **PTR** records that identify all instances of the _sample-service._tcp service. The application then queries the network for the **SRV**, **TXT**, and **A** records that contain the DNS details for each service instance.
|
||||
|
||||
After service discovery is performed, the Azure Sphere firewall allows the application to connect to the discovered host names.
|
||||
The application queries the local network for **PTR** records that identify all instances of the _sample-service._tcp service. The application then queries the network for the **SRV**, **TXT**, and **A** records that contain the DNS details for each service instance. After service discovery is performed, the Azure Sphere firewall allows the application to connect to the discovered host names.
|
||||
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [Networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Manages network connectivity |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
| [EventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Manages network connectivity. |
|
||||
|
||||
## Contents
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures Visual Studio to use CMake with the correct command-line options. |
|
||||
|launch.vs.json |Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The sample requires the following hardware:
|
||||
|
||||
* [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
- [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Connect your Azure Sphere device to the same local network as the DNS service.
|
||||
1. Enable application development, if you have not already done so:
|
||||
|
||||
`azsphere device enable-development`
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *DNSServiceDiscovery* sample in the *DNSServiceDiscovery* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/dnsservicediscovery/).
|
||||
|
||||
### Network configuration
|
||||
1. Set up a DNS service. This sample requires that you run a DNS service instance that is discoverable on the same local network as the Azure Sphere device. You can use the dns-sd tool from [Apple Bonjour](https://developer.apple.com/bonjour/) to set up the service.
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, make the following changes:
|
||||
The following **dns-sd** command registers an instance of a DNS responder service with the default service configuration used by the sample:
|
||||
|
||||
1. Configure Azure Sphere as described in [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet).
|
||||
1. Add an Ethernet adapter to your hardware. If you are using an MT3620 RDB, see the [wiring instructions](../../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
1. Add the following line to the Capabilities section of the app_manifest.json file:
|
||||
`Dns-sd -R SampleInstanceName _sample-service._tcp local 1234 SampleTxtData`
|
||||
|
||||
`"NetworkConfig" : true`
|
||||
1. In main.c, ensure that the global constant `NetworkInterface` is set to "eth0". In source file DNSServiceDiscovery/main.c, search for the following line:
|
||||
The command registers a service instance with the following configuration:
|
||||
|
||||
`static const char NetworkInterface[] = "wlan0"`;
|
||||
- service instance name: SampleInstanceName
|
||||
- DNS server type: _sample-service._tcp
|
||||
- DNS server domain: local
|
||||
- port: 1234
|
||||
- TXT record: SampleTxtData
|
||||
|
||||
and change it to:
|
||||
1. You may want to modify the sample to use unicast queries if you don't need to use multicast queries. You can use unicast queries by calling the **res_send** POSIX API to query the DNS server and process the response in a single blocking call. This may simplify the application, especially if it doesn't need to perform other activities while waiting for the response.
|
||||
|
||||
`static const char NetworkInterface[] = "eth0"`;
|
||||
1. In main.c, add a call to `Networking_SetInterfaceState` before any other networking calls:
|
||||
### Use Ethernet instead of Wi-Fi
|
||||
|
||||
```c
|
||||
int err = Networking_SetInterfaceState("eth0", true);
|
||||
if (err == -1) {
|
||||
Log_Debug("Error setting interface state %d\n",errno);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
### DNS service
|
||||
|
||||
This sample requires that you run a DNS service instance that is discoverable on the same local network as the Azure Sphere device. You can use the dns-sd tool from [Apple Bonjour](https://developer.apple.com/bonjour/) to set up the service. This dns-sd command registers an instance of a DNS responder service with the default service configuration used by the sample:
|
||||
|
||||
```
|
||||
Dns-sd -R SampleInstanceName _sample-service._tcp local 1234 SampleTxtData
|
||||
```
|
||||
|
||||
The command registers a service instance with the following configuration:
|
||||
|
||||
- service instance name: SampleInstanceName
|
||||
- DNS server type: _sample-service._tcp
|
||||
- DNS server domain: local
|
||||
- port: 1234
|
||||
- TXT record: SampleTxtData
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, follow the [Ethernet setup instructions](../../ethernet-setup-instructions.md).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
When you run the application, it displays the name, host, IPv4 address, port, and TXT data from the query response. The application should then be able to connect to the host names returned by the response.
|
||||
|
||||
You can verify the connection by setting up a local web server on the same computer as the DNS service, and then making requests to the service from the application.
|
||||
|
||||
To set up a web server using IIS:
|
||||
To set up an Internet Information Services (IIS) web server, complete the following steps:
|
||||
|
||||
1. Install [IIS](https://www.iis.net/) on the same computer as the DNS service.
|
||||
1. If you set up a site binding for a default website with a port other than 80 or 443, you must add an inbound rule that allows the port.
|
||||
|
||||
To send requests to the web server, you can incorporate code from the [HTTPS_Curl_Easy](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/HTTPS/HTTPS_Curl_Easy) sample into the application. Requests to the web server should fail before the DNS-SD responses are received but should succeed afterwards.
|
||||
|
||||
By default, this sample queries the _sample-service._tcp.local DNS server address. To query a different DNS server, make the following changes:
|
||||
## Rebuild the sample to query a different DNS server
|
||||
|
||||
1. Open app_manifest.json.
|
||||
1. Change the value of the `AllowedConnections` field from `"_sample-service._tcp.local"` to the new DNS server address, such as `"_http._tcp.local"`.
|
||||
1. Open main.c.
|
||||
1. Go to the line `static const char DnsServiceDiscoveryServer[] = "_sample-service._tcp.local";"` and replace `_sample-service._tcp.local` with the new DNS server address.
|
||||
By default, this sample queries the _sample-service._tcp.local DNS server address. To rebuild the sample to query a different DNS server, complete the following steps.
|
||||
|
||||
If you don't need to use multicast queries, you can use unicast queries by calling the res_send() POSIX API to query the DNS server and process the response in a single blocking call. This may simplify the application, especially if it doesn't need to perform other activities while waiting for the response.
|
||||
1. Make the following changes in the sample:
|
||||
|
||||
1. In the `app_manifest.json` file, change the value of the **AllowedConnections** field from `"_sample-service._tcp.local"` to the new DNS server address, such as `"_http._tcp.local"`.
|
||||
1. In `main.c`, find the code `static const char DnsServiceDiscoveryServer[] = "_sample-service._tcp.local";"` and replace `_sample-service._tcp.local` with the new DNS server address.
|
||||
|
||||
1. Follow the instructions in the [Build and run the sample](#build-and-run-the-sample) section of this README.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For network troubleshooting, see [Troubleshoot network problems](https://docs.microsoft.com/azure-sphere/network/troubleshoot-network-problems).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(DeferredUpdate C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -34,11 +34,25 @@ The sample uses the following Azure Sphere libraries.
|
|||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [GPIO](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages buttons and LEDs on the device. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Monitors and dispatches events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages buttons and LEDs on the device. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [sysevent](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-sysevent/sysevent-overview) | Interacts with system event notifications. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The sample requires the following hardware:
|
||||
|
@ -47,9 +61,17 @@ The sample requires the following hardware:
|
|||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
- Azure Sphere SDK version 21.01 or above. To check, run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) at the command prompt.
|
||||
- Azure Sphere SDK version 21.04 or above. To check, run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) at the command prompt.
|
||||
|
||||
## Create the Blink application .imagepackage file
|
||||
## Setup
|
||||
|
||||
First, obtain the sample. Next, create the Blink application `.imagepackage` file and prepare the device to receive updates.
|
||||
|
||||
### Obtain the sample
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *DeferredUpdate* sample in the *DeferredUpdate* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/DeferredUpdate/).
|
||||
|
||||
### Create the Blink application .imagepackage file
|
||||
|
||||
1. Connect the Azure Sphere device to your computer through USB and ensure that the device is connected to the internet.
|
||||
|
||||
|
@ -61,25 +83,25 @@ The sample requires the following hardware:
|
|||
|
||||
1. Confirm that the application is deployed and running (LED1 blinks red).
|
||||
|
||||
1. Note the location of the Blink.imagepackage file. For example: `<path to your Blink folder>\Blink\out\ARM-Debug\Blink.imagepackage`.
|
||||
1. Note the location of the `Blink.imagepackage` file. For example: `<path to your Blink folder>\Blink\out\ARM-Debug\Blink.imagepackage`.
|
||||
|
||||
1. Delete the application from the device.
|
||||
|
||||
1. Run [**azsphere device image list-installed**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#image-list-installed) to display the component ID of the application.
|
||||
1. Run the [**azsphere device sideload delete**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#sideload-delete) command to delete the application. For example:
|
||||
|
||||
|
||||
Azure Sphere CLI:
|
||||
|
||||
```
|
||||
azsphere device sideload delete --component-id <blink-component-id>
|
||||
```
|
||||
|
||||
|
||||
Azure Sphere classic CLI:
|
||||
```
|
||||
azsphere device sideload delete --componentid <blink-component-id>
|
||||
```
|
||||
|
||||
## Prepare the device to receive updates
|
||||
### Prepare the device to receive updates
|
||||
|
||||
1. If you haven't already, run **azsphere product create --name MyProduct** at the command prompt. This command [creates a product](https://docs.microsoft.com/azure-sphere/reference/azsphere-product#create) and the [standard device groups](https://docs.microsoft.com/azure-sphere/deployment/deployment-concepts#device-groups).
|
||||
|
||||
|
@ -90,50 +112,71 @@ The sample requires the following hardware:
|
|||
```
|
||||
azsphere device update --device-group "MyProduct/Field Test"
|
||||
```
|
||||
|
||||
|
||||
Azure Sphere classic CLI:
|
||||
|
||||
|
||||
```
|
||||
azsphere device update --productname MyProduct --devicegroupname "Field Test"
|
||||
```
|
||||
|
||||
1. Run the [**azsphere device wifi show-status**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#wifi-show-status) command to verify that the Azure Sphere device is connected to your WiFi network.
|
||||
|
||||
## Build and run the Deferred Update application
|
||||
## Build and run the sample
|
||||
|
||||
To build and run the Deferred Update sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
Perform the following steps to build and run this sample:
|
||||
|
||||
1. [Build and run the Deferred Update application](#build-and-run-the-deferred-update-application).
|
||||
1. [Deploy the Blink.imagepackage file](#deploy-the-blinkimagepackage-file).
|
||||
1. [Update the device](#update-the-device).
|
||||
|
||||
### Build and run the Deferred Update application
|
||||
|
||||
To build and run the Deferred Update application, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
After the application starts up, LED2 will light up green to indicate that the Deferred Update application is running and updates will be deferred.
|
||||
|
||||
## Deploy the Blink.imagepackage file
|
||||
### Deploy the Blink.imagepackage file
|
||||
|
||||
Run the [**azsphere device-group deployment**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device-group#deployment-create) command to create a deployment for the **Field Test** device group. For example:
|
||||
When you deploy the imagepackage file a deployment is created for the **Field Test** device group. For example:
|
||||
|
||||
Azure Sphere CLI:
|
||||
|
||||
```
|
||||
azsphere device-group deployment create --device-group "MyProduct/Field Test" --images <path to your Blink folder>\Blink\out\ARM-Debug\Blink.imagepackage
|
||||
```
|
||||
1. Upload the image package to your Azure Sphere tenant by using [**azsphere image add**](https://docs.microsoft.com/azure-sphere/reference/azsphere-image?tabs=cliv2beta#add).
|
||||
|
||||
```
|
||||
azsphere image add --image <path to your Blink folder>\Blink\out\ARM-Debug\Blink.imagepackage>
|
||||
```
|
||||
|
||||
2. Create a new deployment for a device group for the uploaded images using [**azsphere device-group deployment create**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device-group?tabs=cliv2beta#deployment-create).
|
||||
|
||||
```
|
||||
azsphere device-group deployment create --device-group "MyProduct/Field Test" --images <image-ID>
|
||||
```
|
||||
|
||||
Azure Sphere classic CLI:
|
||||
|
||||
Upload the image package to your Azure Sphere tenant and create a new deployment for a device group for the uploaded images using [**azsphere device-group deployment create**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device-group?tabs=cliv2beta#deployment-create).
|
||||
|
||||
```
|
||||
azsphere device-group deployment create --productname MyProduct --devicegroupname "Field Test" --filepath <path to your Blink folder>\Blink\out\ARM-Debug\Blink.imagepackage>
|
||||
```
|
||||
azsphere device-group deployment create --productname MyProduct --devicegroupname "Field Test" --filepath <path to your Blink folder>\Blink\out\ARM-Debug\Blink.imagepackage
|
||||
```
|
||||
|
||||
## Update the device
|
||||
### Update the device
|
||||
|
||||
An Azure Sphere device is not automatically notified when updates are available. It checks for updates when it first connects to the internet and at regular intervals (currently 24 hours) thereafter.
|
||||
The device will also check for updates when it is restarted.
|
||||
An Azure Sphere device is not automatically notified when updates are available. It checks for updates when it first connects to the internet and at regular intervals (currently 24 hours) thereafter. The device will also check for updates when it is restarted.
|
||||
|
||||
You can update the device with the Deferred Update application running inside or outside the Visual Studio or Visual Studio Code integrated development environment (IDE), continuing with one of the options below. The sample uses the following LEDs.
|
||||
The sample uses the following LEDs:
|
||||
|
||||
| LED | Description |
|
||||
|---------|---------|
|
||||
| LED 3 | Blue if an update was received. |
|
||||
| LED 2 | Green if updates are being deferred, yellow if updates are being accepted. |
|
||||
|
||||
### Outside an IDE
|
||||
You can update the device with the Deferred Update application running inside or outside the Visual Studio or Visual Studio Code integrated development environment (IDE), continuing with one of the options below.
|
||||
|
||||
**Outside an IDE**
|
||||
|
||||
To update the device with the Deferred Update application running outside an IDE:
|
||||
|
||||
1. After you deploy the Blink.imagepackage file, restart the device.
|
||||
|
||||
|
@ -153,7 +196,9 @@ You can update the device with the Deferred Update application running inside or
|
|||
|
||||
1. Run [**azsphere device image list-installed**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#image-list-installed) to verify that the Blink/Hello World application is installed, and the Deferred Update application and GDB server are no longer installed.
|
||||
|
||||
### In an IDE
|
||||
**Inside an IDE**
|
||||
|
||||
To update the device with the Deferred Update application running inside an IDE:
|
||||
|
||||
1. After you deploy the Blink.imagepackage, restart the device.
|
||||
|
||||
|
@ -184,3 +229,7 @@ You can update the device with the Deferred Update application running inside or
|
|||
|
||||
See [Troubleshooting samples](../../troubleshooting.md) if you encounter errors.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(LowPowerMcuToCloud C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.c
|
||||
|
|
|
@ -1,86 +1,11 @@
|
|||
# Build and deploy the External MCU, Low Power reference solution
|
||||
# Build, run, and deploy the External MCU, Low Power reference solution
|
||||
|
||||
**Note:** The [Azure Sphere Hardware Designs repository](https://github.com/Azure/azure-sphere-hardware-designs/tree/master/P-MT3620EXMSTLP-1-0) on GitHub includes a hardware reference design (folder P-MT3620EXMSTLP-1-0) that demonstrates how to integrate MT3620 into a low-power design where the MT3620 achieves its lowest-power mode but wakes to provide cloud-based operations. The design incorporates an external very-low-power microcontroller that can respond to external input such as button presses.
|
||||
Perform the following steps to build, run, and deploy this sample:
|
||||
|
||||
To build and run this application using off-the-shelf hardware you will need to do the following:
|
||||
|
||||
- Wire up the external MCU development board and connect it to an Azure Sphere development board.
|
||||
- Create an IoT Central application and add views.
|
||||
- Build and deploy the external MCU and MT3620 high-level apps.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Set up your device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
|
||||
**Parts list:**
|
||||
|
||||
| Quantity |Item |
|
||||
| ------------- |-------------|
|
||||
| 1|NUCLEO-L031K6 - Dev Board |
|
||||
| 1|RGB LED (common anode)|
|
||||
| 1|USB-Serial interface module (optional) |
|
||||
| 3|330 Ohm Resistor |
|
||||
| 2|4K7 Resistor |
|
||||
| 1|10K Resistor |
|
||||
| 1|10K Potentiometer |
|
||||
| 1| Breadboard and pre cut M-M jumper leads|
|
||||
| 2|Tactile Switch |
|
||||
|1 |150mm F-F jumper leads |
|
||||
|7 |200mm M-F jumper leads |
|
||||
|8 |200mm M-M jumper leads |
|
||||
|
||||
## Wire up the external MCU development board and connect it to an Azure Sphere development board
|
||||
|
||||
**Note:**
|
||||
|
||||
- The connection between MT3620 RDB pins H3.2 and H3.10 is not required for RDB versions 1.6 and later.
|
||||
|
||||
- This sample was updated in 20.11 and the common cathode RGB LED has been replaced by a common anode RGB LED. If you use hardware built for the older version of the sample, the RGB LED polarity will be reversed (turn on when it should turn off, and vice versa). If needed you can modify the following lines of code in the `UpdateLedStatus` function in the file *McuSoda\Core\Src\flavor.c* :
|
||||
|
||||
change
|
||||
|
||||
`static const GPIO_PinState ledOnState = GPIO_PIN_RESET;`
|
||||
|
||||
`static const GPIO_PinState ledOffState = GPIO_PIN_SET;`
|
||||
|
||||
to
|
||||
|
||||
`static const GPIO_PinState ledOffState = GPIO_PIN_RESET;`
|
||||
|
||||
`static const GPIO_PinState ledOnState = GPIO_PIN_SET;`
|
||||
|
||||
![Connection diagram](./media/MCU-to-Cloud-wiring.png)
|
||||
|
||||
Make the following connections between the STM NUCLEO-L031K6 and MT3620 dev boards using the jumper wires:
|
||||
|
||||
- External MCU pin D1 to 10K resistor; 10K resistor to first outer terminal of 10k potentiometer.
|
||||
- External MCU pin D4 to 330 ohm resistor to RGB LED Pin Blue
|
||||
- External MCU pin D5 to 330 ohm resistor to RGB LED Pin Green
|
||||
- External MCU pin D9 to Dispense button
|
||||
- External MCU pin D10 to Refill button
|
||||
- External MCU pin D11 to 330 ohm resistor to RGB LED Pin Red
|
||||
- External MCU pin D12 to MT3620 RDB pin H3.4
|
||||
- Dispense button to 4.7K pull-up resistor; 4.7K pull-up resistor to power strip (+)
|
||||
- Dispense button to ground strip (-)
|
||||
- Refill button to 4.7K pull-up resistor; 4.7K pull-up resistor to power strip (+)
|
||||
- Refill button to circuit ground strip (-)
|
||||
- Second outer terminal of 10K potentiometer to ground strip.
|
||||
- RGB LED common anode pin to power strip (+)
|
||||
- External MCU pin GND to ground strip.
|
||||
- External MCU pin 3.3v to power strip (+)
|
||||
- External MCU pin A2 to MT36220 RDB pin H2.3
|
||||
- External MCU pin A3 to center terminal of 10K potentiometer
|
||||
- External MCU pin A7 to MT3620 RDB pin H2.1
|
||||
- Ground strip to MT3620 RDB pin H1.2 (GND)
|
||||
- MT3620 RDB pin H3.2 to MT3620 RDB pin H3.10.
|
||||
|
||||
### Optional debug UART connections
|
||||
|
||||
Output from Log_Debug can also be seen on the optional debug UART. This can be useful for observing application behavior without a debugger connection. For example, after device shutdown or restart.
|
||||
|
||||
- MT3620 RDB pin H4.2 to USB-Serial Ground pin
|
||||
- MT3620 RDB pin H4.5 to USB-Serial Tx pin
|
||||
- MT3620 RDB pin H4.7 to USB-Serial Rx pin
|
||||
1. [Build and deploy the MCU application](#build-and-deploy-the-mcu-app).
|
||||
1. [Create an IoT Central application and add views](#create-an-iot-central-application-and-add-views).
|
||||
1. [Build and deploy the Azure Sphere MT3620 high-level application](#build-and-deploy-the-azure-sphere-mt3620-high-level-app).
|
||||
1. [Run the solution](#run-the-solution).
|
||||
|
||||
## Build and deploy the MCU app
|
||||
|
||||
|
@ -103,7 +28,7 @@ To build and run the MCU app do the following:
|
|||
|
||||
## Create an IoT Central application and add views
|
||||
|
||||
To create an IoT Central app, see [IOT Central Setup](./IOTCentralSetup.md).
|
||||
To create an IoT Central application and add views, see [IOT Central Setup](./IOTCentralSetup.md).
|
||||
|
||||
## Build and deploy the Azure Sphere MT3620 high-level app
|
||||
|
||||
|
@ -144,17 +69,9 @@ Every 2 minutes, the MT3620 turns on the status LED, wakes up the external MCU,
|
|||
|
||||
## Build your own solution
|
||||
|
||||
To change the following settings, open the configuration.h file (*.../LocalSamples/DeviceToCloud/ExternalMcuLowPower/common/configuration.h*), which is located in the folder and change the value of the corresponding constant.
|
||||
To build your own solution, modify the `configuration.h` file located at `../LocalSamples/DeviceToCloud/ExternalMcuLowPower/common/configuration.h`. Open the file and change the value of the corresponding constant.
|
||||
|
||||
| Setting |Default value | Description |
|
||||
| ------------- |-------------| -----|
|
||||
| MachineCapacity |5 |The capacity (maximum units) of the soda machine |
|
||||
|LowDispenseAlertThreshold|2|The number of remaining units that will initiate a low stock alert.
|
||||
|
||||
## License
|
||||
|
||||
For details on license, see LICENSE.txt in this directory.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
| Setting | Default value | Description |
|
||||
| -------- |----------------| -------------|
|
||||
| MachineCapacity | 5 | The capacity (maximum units) of the soda machine |
|
||||
| LowDispenseAlertThreshold | 2 | The number of remaining units that will initiate a low stock alert |
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
## Create an Azure IoT Central application
|
||||
|
||||
1. Go to [Azure IoT Central](https://apps.azureiotcentral.com/build) in your browser.
|
||||
1. Choose Custom apps and sign in with your Microsoft account, or create a new account.
|
||||
1. Use the default Application name and URL or modify it, if you prefer.
|
||||
1. Under Application template, choose Custom Application.
|
||||
1. Either choose 7 day free trial and provide your contact info, or provide your billing info.
|
||||
1. Choose **Custom apps** and sign in with your Microsoft account, or create a new account.
|
||||
1. Use the default **Application name and URL** or modify it, if you prefer.
|
||||
1. Under **Application template**, choose **Custom Application**.
|
||||
1. Either choose **Free** 7-day trial and provide your contact info, or provide your billing info.
|
||||
1. Click **Create** at the bottom of the page.
|
||||
|
||||
## Configure the Azure IoT Central application
|
||||
|
||||
1. In the left navigation pane on the Home Page, select **Device Templates**
|
||||
1. In the **Device Templates** pane, select **+ (New)**.
|
||||
1. In the **Select Template Type** pane, select **IoT Device > Next: Customize**.
|
||||
1. Fill in the Device template name with any name you choose (for example: Soda Machine) and select **Next: Review > Create**.
|
||||
1. Select **Import capability model** and select the SodaMachineTemplate.json file from the root folder of the reference solution.
|
||||
1. In the left navigation pane on the **Home Page**, select **Device Templates**.
|
||||
1. In the **Device Templates** pane, select **+ New**.
|
||||
1. In the **Select Template Type** pane, select **IoT Device** > **Next: Customize**.
|
||||
1. Fill in the **Device template name** with any name you choose (for example: Soda Machine) and select **Next: Review** > **Create**.
|
||||
1. On the **Create a model** page, select **Import a model** and then select the SodaMachineTemplate.json file from the root folder of the reference solution.
|
||||
|
||||
## Add the views
|
||||
|
||||
|
@ -24,25 +24,25 @@ Add two Views to the Device Template, one to display the soda machine state and
|
|||
|
||||
To display the soda machine state:
|
||||
|
||||
1. Select **Views > Visualizing the device**.
|
||||
1. Customize the **View name** with "Soda Machine State".
|
||||
1. Under **Telemetry**, use the use the dropdown menu to select **Dispenses (since last update)**, then **Add tile**. Use the **Change Visualization** button on the graph to change the view to a KPI. You may also resize the graph using the **Size Available** button to **2x1**.
|
||||
1. Under **Telemetry**, use the dropdown menu to select **Lifetime total dispenses**, then **Add tile**. Select the **Settings** button on the graph and then select the **Settings** button on the **Lifetime total dispenses** telemetry value to change the data aggregation from Average to Sum. Select **Update** to save the graph option.
|
||||
1. Under **Telemetry**, use the dropdown menu to select **Low Soda**, then **Add tile**. Use the **Change Visualization** button on the graph to change the view to the **Last Known Value**. You may also resize the graph using the **Size Available** button to **1x1**.
|
||||
1. Under **Telemetry**, use the dropdown menu to select **Remaining Dispenses**, then **Add tile**. Use the **Change Visualization** button on the graph to change the view to the **Last Known Value**. You may also resize the graph using the **Size Available** button to **1x1**.
|
||||
1. Under **Telmetry**, use the dropdown menu to select **Battery Level (V)**, then **Add tile**. Use the Change Visualization button on the graph to change the view to the **Last Known Value**. You may also resize the graph using the **Size Available** button to **1x1**.
|
||||
1. Under **Property**, use the dropdown menu to select **Name**, then **Add tile**.
|
||||
1. The view should look like the following image. Select **Save**.
|
||||
1. Select **Views** > **Visualizing the device**.
|
||||
1. Customize the **View name** with **Soda Machine State**.
|
||||
1. Under **Telemetry**, use the use the drop-down menu to select **Dispenses (since last update)**, then click **Add tile**. Use the **Change Visualization** button on the graph to change the view to a **KPI**. You may also resize the graph using the **Size Available** button to **2x1**.
|
||||
1. Under **Telemetry**, use the drop-down menu to select **Lifetime total dispenses**, then click **Add tile**. Select the **Configure** button on the graph and then select the **Gear** button on the **Lifetime total dispenses** telemetry value to change the data aggregation from **Average** to **Sum**. Select **Update** to save your changes.
|
||||
1. Under **Telemetry**, use the drop-down menu to select **Low Soda**, then click **Add tile**. Use the **Change Visualization** button on the graph to change the view to the **Last Known Value**. You may also resize the graph using the **Size Available** button to **1x1**.
|
||||
1. Under **Telemetry**, use the drop-down menu to select **Remaining Dispenses**, then click **Add tile**. Use the **Change Visualization** button on the graph to change the view to the **Last Known Value**. You may also resize the graph using the **Size Available** button to **1x1**.
|
||||
1. Under **Telemetry**, use the drop-down menu to select **Battery Level**, then click **Add tile**. Use the Change Visualization button on the graph to change the view to the **Last Known Value**. You may also resize the graph using the **Size Available** button to **1x1**.
|
||||
1. Under **Property**, use the drop-down menu to select **Name**, then **Add tile**.
|
||||
1. The view should look like the following image. You can drag and drop tiles to arrange the view as you wish. When the tiles are arranged to your satisfaction, click **Save**.
|
||||
|
||||
![Display the soda machine state.](./media/IOT1-50.png)
|
||||
|
||||
To select the next flavor:
|
||||
|
||||
1. Select **Views > Editing device and cloud data**
|
||||
1. Customize the **Form name** with "Next Flavor".
|
||||
1. Under **Property**, select **Next Flavor**, then **Add section**.
|
||||
1. Select **Views** > **Editing device and cloud data**.
|
||||
1. Customize the **Form name** with **Next Flavor**.
|
||||
1. Under **Property**, select the check box for **Next Flavor**, then click **Add section**.
|
||||
1. The view should look like the following image. Select **Save**.
|
||||
1. Select **Publish > Publish**.
|
||||
1. Select **Publish** > **Publish**.
|
||||
|
||||
![Edit device and cloud data.](./media/IOT2-50.png)
|
||||
|
||||
|
@ -57,7 +57,7 @@ Add two Views to the Device Template, one to display the soda machine state and
|
|||
- The Tenant ID for your Azure Sphere device
|
||||
- The Scope ID for your Azure IoT Central application
|
||||
- The allowed connections for your Azure Sphere device
|
||||
|
||||
|
||||
Follow these steps to gather the information and configure the application:
|
||||
|
||||
1. Find the app_manifest.json file in your sample directory and open it.
|
||||
|
@ -66,15 +66,14 @@ Add two Views to the Device Template, one to display the soda machine state and
|
|||
|
||||
1. Follow the prompts that the tool provides, and copy the information from the output into the app_manifest.json file. The tool will require the following input:
|
||||
|
||||
*IoT Central App URL* – this can be found in your browser address bar. For Example: http://myiotcentralapp.azureiotcentral.com/. Paste the URL into the **AllowedConnections** field of the app manifest.
|
||||
*IoT Central App URL* – This can be found in your browser address bar. For example: http://myiotcentralapp.azureiotcentral.com/. Paste the URL into the **AllowedConnections** field of the app manifest.
|
||||
|
||||
*API token* – this can be generated from your IoT Central application. In the Azure IoT Central application, select **Administration** > **API Tokens** > **Generate Token**, and then provide a name for the token. For example, "AzureSphereSample" - select **Administrator** as the role, and then click **Generate**. Copy the token to the clipboard. The token starts with **SharedAccessSignature**.
|
||||
*API token* – This can be generated from your IoT Central application. In the Azure IoT Central application, select **Administration** > **API Tokens** > **Generate Token**, and then provide a name for the token. For example, "AzureSphereSample". Select **Administrator** as the role, and then click **Generate**. Copy the token to the clipboard. The token starts with **SharedAccessSignature**.
|
||||
|
||||
*ID Scope* - In the Azure IoT Central application, select **Administration** > **Device Connection** and then copy everything in this section and paste it into the **CmdArgs** field of the app manifest.
|
||||
*ID Scope* - In the Azure IoT Central application, select **Administration** > **Device Connection**. Copy the contents of the **ID scope** field and paste it into the **CmdArgs** field of the app manifest.
|
||||
|
||||
1. At the command prompt, run the [**azsphere tenant show-selected**](https://docs.microsoft.com/azure-sphere/reference/azsphere-tenant?tabs=cliv1#show-selected) command to get the tenant ID (a GUID). In the [app_manifest.json file](https://docs.microsoft.com/azure-sphere/app-development/app-manifest), set the value of the **DeviceAuthentication** capability to your tenant ID.
|
||||
|
||||
1. At the command prompt, run the [**azsphere tenant show-selected**](https://docs.microsoft.com/azure-sphere/reference/azsphere-tenant?tabs=cliv1#show-selected) command to get the tenant ID (a GUID). In the [app_manifest.json file](https://docs.microsoft.com/azure-sphere/app-development/app-manifest), set the value of the **DeviceAuthentication** capability to your tenant ID.
|
||||
|
||||
1. Save the updated application manifest.
|
||||
|
||||
1. Ensure that the **Auto approve** option is enabled. From the Azure IoT Central Application, click **Administration** > **Device connection**, then on the **Auto approve** option, select **Enabled**.
|
||||
|
||||
|
|
|
@ -21,42 +21,123 @@ description: "Demonstrates how you might use an Azure Sphere device as an interf
|
|||
|
||||
# Sample: Device to Cloud - external MCU, low power
|
||||
|
||||
This reference solution demonstrates how you might use an Azure Sphere device as an interface between an external MCU, not connected to the internet, and an IoT application platform such as IoT Central.
|
||||
This sample demonstrates how you might use an Azure Sphere device as an interface between an external MCU, not connected to the internet, and an IoT application platform such as IoT Central. The solution is implemented to optimize for low power by incorporating features such as the Azure Sphere device [Power Down state](https://docs.microsoft.com/azure-sphere/app-development/power-down#power-down-state) when it's not collecting data from the MCU or communicating with IoT Central.
|
||||
|
||||
This solution is implemented to optimize for low power by incorporating features such as the Azure Sphere device [Power Down state](https://docs.microsoft.com/azure-sphere/app-development/power-down) when it's not collecting data from the MCU or communicating with IoT Central.
|
||||
This solution models a soda machine that regularly sends usage data to IoT Central and receives new flavor recipes from IoT Central. An external MCU is used to implement the soda machine model. An Azure Sphere MT3620 provides the communication interface between the MCU and IoT Central. Soda machine managers can use views in IoT Central to see which machines are low on stock and need refills and which machines are used more. They can also use IoT Central to send new flavors to soda machines.
|
||||
|
||||
## Overview
|
||||
When the user initiates an action, the external MCU wakes, increments its usage count, stores the new value, and returns to low power mode. If it detects a low inventory level it informs the Azure Sphere MT3620. The Azure Sphere MT3620, connected to the MCU via UART, periodically collects the data from the MCU and sends it to IoT Central. The Azure Sphere MT3620 also receives, and passes on to the MCU, configuration data from IoT Central.
|
||||
|
||||
This solution models a soda machine that regularly sends usage data to IoT Central and receives new flavor recipes from IoT Central. An external MCU is used to implement the soda machine model. An Azure Sphere MT3620 provides the communication interface between the MCU and IoT Central.
|
||||
**Note:** This README describes how to build, deploy, and run this sample with a breadboard-based hardware design and off-the-shelf hardware. Alternatively, you can use a printed circuit board (PCB) that integrates an MT3620 module and an external MCU. To use the PCB instead of a breadboard with this sample, see the [Azure Sphere PCB hardware design](https://github.com/Azure/azure-sphere-hardware-designs/tree/master/P-MT3620EXMSTLP-1-0/README.md) instructions.
|
||||
|
||||
When the user initiates an action, the external MCU wakes, increments its usage count, stores the new value, and returns to low power mode. If it detects a low inventory level it informs the Azure Sphere MT3620.
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
The Azure Sphere MT3620, connected to the MCU via UART, periodically collects the data from the MCU and sends it to IoT Central. The Azure Sphere MT3620 also receives, and passes on to the MCU, configuration data from IoT Central.
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [application](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Communicates with the real-time capable application running on the external MCU. |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for I/O timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages status LEDs on the Azure Sphere MT3620. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Manages the network configuration of the Azure Sphere MT3620. |
|
||||
| [powermanagement](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-power/power-overview) | Manages the power state of the Azure Sphere MT3620. |
|
||||
| [storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Stores the data collected from the MCU. |
|
||||
| [sysevent](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-sysevent/sysevent-overview) | Registers for system event notifications. |
|
||||
| [uart](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-uart/uart-overview) | Manages communication with the MCU. |
|
||||
|
||||
The [Azure Sphere Hardware Designs repository](https://dev.azure.com/msazuresphere/4x4/_git/cust-Hardware?path=%2FGitHub-Local--azure-sphere-hardware-designs) on GitHub contains a [hardware reference design](https://github.com/Azure/azure-sphere-hardware-designs/tree/master/P-MT3620EXMSTLP-1-0) that demonstrates how to integrate an MT3620 module and an external MCU onto a single Printed Circuit Board (PCB) with a low-power design.
|
||||
## Contents
|
||||
|
||||
See [Build and deploy the External MCU, Low Power reference solution](BuildMcuToCloud.md) to learn how to build, deploy and run this reference solution with a breadboard-based hardware design.
|
||||
| File/folder | Description |
|
||||
|--------------------------|-------------|
|
||||
| `BuildMcuToCloud.md` | Instructions for building, deploying, and running this sample application. |
|
||||
| `IOTCentralSetup.md` | Instructions for creating the IoT Central application. |
|
||||
| `README.md` | This README file. |
|
||||
| `AzureSphere_HighLevelApp` | Folder containing the configuration files, source code files, and other files needed for the high-level application that runs on the Azure Sphere MT3620. |
|
||||
| `common` | Folder containing common header files and source code files. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
| `McuSoda` | Folder containing the configuration files, source code files, and other files needed for the soda machine application that runs on the external MCU. |
|
||||
|
||||
**Note:** You can also build and deploy this solution using the hardware reference design. However, code changes will be required. For more information, see the [README.md file](https://github.com/Azure/azure-sphere-hardware-designs/tree/master/P-MT3620EXMSTLP-1-0/README.md) for the **Device To Cloud - External MCU, Low Power** reference solution.
|
||||
## Prerequisites
|
||||
|
||||
### What's in the solution
|
||||
- Set up your device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
- Insure that you have all of the parts that are listed in the parts list.
|
||||
|
||||
The reference solution contains the following:
|
||||
**Parts list:**
|
||||
|
||||
- The soda machine application running on an external MCU.
|
||||
| Quantity |Item |
|
||||
| ------------- |-------------|
|
||||
| 1 | STM NUCLEO-L031K6 - Dev Board |
|
||||
| 1 | RGB LED (common anode)|
|
||||
| 1 | USB-Serial interface module (optional) |
|
||||
| 3 | 330 Ohm Resistor |
|
||||
| 2 | 4K7 Resistor |
|
||||
| 1 | 10K Resistor |
|
||||
| 1 | 10K Potentiometer |
|
||||
| 1 | Breadboard and pre cut M-M jumper leads|
|
||||
| 2 | Tactile Switch |
|
||||
| 1 | 150mm F-F jumper leads |
|
||||
| 7 | 200mm M-F jumper leads |
|
||||
| 8 | 200mm M-M jumper leads |
|
||||
|
||||
An [STM NUCLEO-L031K6](https://www.st.com/en/evaluation-tools/nucleo-l031k6.html) is used as the low power external MCU but the solution can easily be adapted to run with other external MCUs.
|
||||
|
||||
- The high-level application running on an Azure Sphere MT3620.
|
||||
## Setup
|
||||
|
||||
- The soda machine IoT Central application running in the cloud.
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *DeviceToCloud* sample in the *DeviceToCloud* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/DeviceToCloud/).
|
||||
|
||||
Soda machine managers can use views in IoT Central to see which machines are low on stock and need refills and which machines are used more. They can also use IoT Central to send new flavors to soda machines.
|
||||
1. Make the following connections between the external MCU (STM NUCLEO-L031K6) and Azure Sphere MT3620 development boards using the jumper wires:
|
||||
|
||||
## License
|
||||
For details on license, see LICENSE.txt in this directory.
|
||||
- External MCU pin D1 to 10K resistor; 10K resistor to first outer terminal of 10k potentiometer.
|
||||
- External MCU pin D4 to 330 ohm resistor to RGB LED Pin Blue
|
||||
- External MCU pin D5 to 330 ohm resistor to RGB LED Pin Green
|
||||
- External MCU pin D9 to Dispense button
|
||||
- External MCU pin D10 to Refill button
|
||||
- External MCU pin D11 to 330 ohm resistor to RGB LED Pin Red
|
||||
- External MCU pin D12 to MT3620 RDB pin H3.4
|
||||
- Dispense button to 4.7K pull-up resistor; 4.7K pull-up resistor to power strip (+)
|
||||
- Dispense button to ground strip (-)
|
||||
- Refill button to 4.7K pull-up resistor; 4.7K pull-up resistor to power strip (+)
|
||||
- Refill button to circuit ground strip (-)
|
||||
- Second outer terminal of 10K potentiometer to ground strip.
|
||||
- RGB LED common anode pin to power strip (+)
|
||||
- External MCU pin GND to ground strip.
|
||||
- External MCU pin 3.3v to power strip (+)
|
||||
- External MCU pin A2 to MT36220 RDB pin H2.3
|
||||
- External MCU pin A3 to center terminal of 10K potentiometer
|
||||
- External MCU pin A7 to MT3620 RDB pin H2.1
|
||||
- Ground strip to MT3620 RDB pin H1.2 (GND)
|
||||
- MT3620 RDB pin H3.2 to MT3620 RDB pin H3.10.
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
![Connection diagram](./media/MCU-to-Cloud-wiring.png)
|
||||
|
||||
**Note:**
|
||||
|
||||
- The connection between MT3620 RDB pins H3.2 and H3.10 is not required for RDB versions 1.6 and later.
|
||||
|
||||
- This sample was updated in 20.11 and the common cathode RGB LED has been replaced by a common anode RGB LED. If you use hardware built for the older version of the sample, the RGB LED polarity will be reversed (turn on when it should turn off, and vice versa). If needed you can modify the following lines of code in the `UpdateLedStatus` function in the file `McuSoda\Core\Src\flavor.c`:
|
||||
|
||||
change
|
||||
|
||||
`static const GPIO_PinState ledOnState = GPIO_PIN_RESET;`
|
||||
|
||||
`static const GPIO_PinState ledOffState = GPIO_PIN_SET;`
|
||||
|
||||
to
|
||||
|
||||
`static const GPIO_PinState ledOffState = GPIO_PIN_RESET;`
|
||||
|
||||
`static const GPIO_PinState ledOnState = GPIO_PIN_SET;`
|
||||
|
||||
### Optional debug UART connections
|
||||
|
||||
Output from Log_Debug can also be seen on the optional debug UART. This can be useful for observing application behavior without a debugger connection. For example, after device shutdown or restart.
|
||||
|
||||
- MT3620 RDB pin H4.2 to USB-Serial Ground pin
|
||||
- MT3620 RDB pin H4.5 to USB-Serial Tx pin
|
||||
- MT3620 RDB pin H4.7 to USB-Serial Rx pin
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
Follow the instructions in [BuildMcuToCloud.md](./BuildMcuToCloud.md) to build and run this sample.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- To learn about how to manage power in Azure Sphere devices, see [Manage Power Down state](https://docs.microsoft.com/azure-sphere/app-development/power-down) and [Set power profiles](https://docs.microsoft.com/azure-sphere/app-development/set-power-profiles).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(ExternalMcuUpdateNrf52 C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c file_view.c mem_buf.c eventloop_timer_utilities.c nordic/slip.c nordic/crc.c nordic/dfu_uart_protocol.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -25,13 +25,32 @@ description: "Demonstrates how you might use an Azure Sphere device to deploy an
|
|||
|
||||
Your product may incorporate other MCUs with your Azure Sphere device, and [those other MCUs may require updates](https://docs.microsoft.com/azure-sphere/deployment/external-mcu-update). Assuming the other MCUs permit updates to be loaded over the connection you establish with the Azure Sphere device, for example over UART, you can use the Azure Sphere device to securely deliver those updates.
|
||||
|
||||
This reference solution demonstrates how you might use an Azure Sphere device to deploy an update to an external MCU device. This solution contains an Azure Sphere app that deploys firmware to the Nordic nRF52 Development Kit over UART. This app can itself be updated remotely via [over-the-air updates](https://docs.microsoft.com/azure-sphere/deployment/deployment-overview), ensuring that the software versions of this app and the MCU firmware are always in sync.
|
||||
This reference solution demonstrates how you might use an Azure Sphere device to deploy an update to an external MCU device. This solution contains an Azure Sphere application that deploys firmware to the Nordic nRF52 Development Kit over UART. This application can itself be updated remotely via [over-the-air updates](https://docs.microsoft.com/azure-sphere/deployment/deployment-overview), ensuring that the software versions of this application and the MCU firmware are always in sync.
|
||||
|
||||
## Preparation
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for I/O timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages the buttons and LEDs on the device. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Opens a file in the image package. |
|
||||
| [uart](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-uart/uart-overview) | Manages communication with the Nordic nRF52 Development Kit. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|----------------------------|-------------|
|
||||
| `README.md` | This README file. |
|
||||
| `AzureSphere_HighLevelApp` | Folder containing the configuration files, source code files, hardware definitions, and other files needed for the high-level application. |
|
||||
| `Binaries` | Folder containing the `.hex` bootloader files. |
|
||||
| `Nrf52Bootloader` | Folder containing the configuration files, source code files, and other files needed for building your own bootloader. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This reference solution requires the following:
|
||||
|
||||
- Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Download and install the latest SDK as needed. The [set-up procedures](https://docs.microsoft.com/azure-sphere/install/overview) describe how to choose and install an SDK.
|
||||
- Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Download and install the latest SDK as needed. The [set-up procedures](https://docs.microsoft.com/azure-sphere/install/overview) describe how to choose and install an SDK.
|
||||
- Azure Sphere MT3620 board
|
||||
- Nordic nRF52 BLE development board
|
||||
- Jumper wires to connect the boards
|
||||
|
@ -39,44 +58,51 @@ This reference solution requires the following:
|
|||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../HardwareDefinitions/README.md). You might also need to wire the device differently.
|
||||
|
||||
## Connect Azure Sphere MT3620 to the Nordic nRF52
|
||||
## Setup
|
||||
|
||||
Make the following connections between the nRF52 and MT3620 dev boards using the jumper wires:
|
||||
1. Make the following connections between the Nordic nRF52 and Azure Sphere MT3620 dev boards using the jumper wires:
|
||||
|
||||
- nRF52 RX: P0.11 to MT3620 UART0 TX: Header 2 (lower left) Pin 3
|
||||
- nRF52 TX: P0.12 to MT3620 UART0 RX: Header 2 (lower left) Pin 1
|
||||
- nRF52 CTS: P0.23 to MT3620 UART0 RTS: Header 2 (lower left) Pin 7
|
||||
- nRF52 RTS: P0.22 to MT3620 UART0 CTS: Header 2 (lower left) Pin 5
|
||||
- nRF52 Reset: P0.21 to MT3620 GPIO5: Header 2 (lower left) Pin 4
|
||||
- nRF52 DFU: P0.16 to MT3620 GPIO44: Header 2 (lower left) Pin 14
|
||||
- nRF52 Ground: GND to MT3620 GND: Header 2 (lower left) Pin 2
|
||||
- nRF52 RX: P0.11 to MT3620 UART0 TX: Header 2 (lower left) Pin 3
|
||||
- nRF52 TX: P0.12 to MT3620 UART0 RX: Header 2 (lower left) Pin 1
|
||||
- nRF52 CTS: P0.23 to MT3620 UART0 RTS: Header 2 (lower left) Pin 7
|
||||
- nRF52 RTS: P0.22 to MT3620 UART0 CTS: Header 2 (lower left) Pin 5
|
||||
- nRF52 Reset: P0.21 to MT3620 GPIO5: Header 2 (lower left) Pin 4
|
||||
- nRF52 DFU: P0.16 to MT3620 GPIO44: Header 2 (lower left) Pin 14
|
||||
- nRF52 Ground: GND to MT3620 GND: Header 2 (lower left) Pin 2
|
||||
|
||||
Refer to the following graphic for details.
|
||||
Refer to the following graphic for details.
|
||||
|
||||
![Connection diagram for nRF52 and MT3620](./media/nRF52_MT3620_connection.png)
|
||||
|
||||
## Install bootloader on the nRF52
|
||||
![Connection diagram for nRF52 and MT3620](./media/nRF52_MT3620_connection.png)
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *ExternalMcuUpdate* sample in the *ExternalMcuUpdate* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/externalmcuupdate/).
|
||||
1. Connect the nRF52 developer board to your computer using USB. Once connected, the nRF52 displays a JLINK removable drive in Windows.
|
||||
1. Find softdevice_Bootloader.hex in the ExternalMcuUpdateNrf52\Binaries folder, and copy it to the JLINK drive. The nRF52 restarts automatically and runs the bootloader.
|
||||
1. Observe that LED1 and LED3 are lit on the nRF52 development board, which indicates that the bootloader has started successfully.
|
||||
|
||||
## Build and run the Azure Sphere app that updates the firmware on the nRF52
|
||||
1. Install bootloader on the nRF52.
|
||||
|
||||
Follow the instructions in [Build a sample application](../../BUILD_INSTRUCTIONS.md) to build and run the Azure Sphere app in Visual Studio or Visual Studio Code.
|
||||
1. Connect the nRF52 developer board to your computer using USB. Once connected, the nRF52 displays a JLINK removable drive in Windows.
|
||||
1. Find softdevice_Bootloader.hex in the `ExternalMcuUpdateNrf52\Binaries` folder, and copy it to the JLINK drive. The nRF52 restarts automatically and runs the bootloader.
|
||||
1. Observe that LED1 and LED3 are lit on the nRF52 development board, which indicates that the bootloader has started successfully.
|
||||
|
||||
### Observe the app while it updates the firmware on the nRF52
|
||||
## Build and run the sample
|
||||
|
||||
1. As the app runs, observe the Output window for activity messages. You should see the sample firmware install on the nRF52.
|
||||
Follow the instructions in [Build a sample application](../../BUILD_INSTRUCTIONS.md) to build and run the Azure Sphere application in Visual Studio or Visual Studio Code.
|
||||
|
||||
### Observe the output
|
||||
|
||||
Observe the output while the application updates the firmware on the nRF52.
|
||||
|
||||
1. As the application runs, observe the Output window for activity messages. You should see the sample firmware install on the nRF52.
|
||||
1. Observe that LED2 and LED4 are blinking on the nRF52 development board, which indicates the new firmware is running.
|
||||
1. Press button A to restart the update process. In the Output window, observe that the app determines the nRF52 firmware is already up to date, and does not reinstall it.
|
||||
1. Press button A to restart the update process. In the Output window, observe that the application determines the nRF52 firmware is already up to date, and does not reinstall it.
|
||||
|
||||
## Edit the Azure Sphere app to deploy different firmware to the nRF52
|
||||
## Rebuild the sample to deploy different firmware
|
||||
|
||||
The nRF52 firmware files are included as resources within the Azure Sphere app. The app can easily be rebuilt to include different firmware. For example, to run the BlinkyV2 nRF52 app you replace the BlinkyV1.bin and BlinkyV1.dat files with the corresponding BlinkyV2 files.
|
||||
The nRF52 firmware files are included as resources within the Azure Sphere sample application. The application can easily be revised and rebuilt to include different firmware for deployment to the nRF52. The sample application is currently set up to deploy the Blinkyv1 firmware.
|
||||
|
||||
1. In the [CMakeLists.txt](./AzureSphere_HighLevelApp/CMakeLists.txt) file for this sample edit the azsphere_target_add_image_package command to replace BlinkyV1.bin and BlinkyV1.dat with BlinkyV2.bin and BlinkyV2.dat:
|
||||
### Revise the Azure Sphere sample application
|
||||
|
||||
To include different firmware files as resources, update the resources specified in the sample's `CMakeLists.txt` and `main.c` files. For example, to include the Blinkyv2 instead of the Blinkyv1 firmware files as resources, complete the following steps:
|
||||
|
||||
1. In the [CMakeLists.txt](./AzureSphere_HighLevelApp/CMakeLists.txt) file for this sample, edit the **azsphere_target_add_image_package** command to replace `BlinkyV1.bin` and `BlinkyV1.dat` with `BlinkyV2.bin` and `BlinkyV2.dat` respectively:
|
||||
|
||||
azsphere_target_add_image_package(
|
||||
${PROJECT_NAME}
|
||||
|
@ -86,45 +112,61 @@ The nRF52 firmware files are included as resources within the Azure Sphere app.
|
|||
"ExternalNRF52Firmware/s132_nrf52_6.1.0_softdevice.bin"
|
||||
"ExternalNRF52Firmware/s132_nrf52_6.1.0_softdevice.dat")
|
||||
|
||||
1. Update the filename constants in main.c to point at BlinkyV2 instead of BlinkyV1.
|
||||
1. Update the filename constants in `main.c` to point at BlinkyV2 instead of BlinkyV1.
|
||||
1. Update the accompanying version constant to '2' instead of '1'.
|
||||
1. Ensure the "SoftDevice" BLE stack firmware files (s132_nrf52_6.1.0_softdevice.bin and s132_nrf52_6.1.0_softdevice.dat) are still included as resources. Do not edit the constants that relate to these files.
|
||||
1. Rebuild and run the Azure Sphere app.
|
||||
1. Ensure the "SoftDevice" BLE stack firmware files (`s132_nrf52_6.1.0_softdevice.bin` and `s132_nrf52_6.1.0_softdevice.dat`) are still included as resources. Do not edit the constants that relate to these files.
|
||||
|
||||
### Rebuild and run the sample
|
||||
|
||||
1. Rebuild and run the Azure Sphere application.
|
||||
1. Use the Output window to observe as the BlinkyV2 firmware is installed and run on the nRF52.
|
||||
1. Observe that LED3 and LED4 are now blinking on the nRF52 development board, which indicates that the BlinkyV2 firmware is running.
|
||||
1. Notice that the SoftDevice BLE stack was not updated because it is already at the correct version.
|
||||
|
||||
## Build and deploy your own app firmware for the nRF52
|
||||
## Build and deploy your own nRF52 firmware
|
||||
|
||||
You can adapt this solution to include your own nRF52 app.
|
||||
You can adapt this solution to deploy your own firmware for the nRF52.
|
||||
|
||||
### Create a new 'BlinkyV3' nRF52 app
|
||||
### Create a new BlinkyV3 nRF52 firmware application
|
||||
|
||||
1. Download and install [SEGGER Embedded Studio](https://www.segger.com/downloads/embedded-studio). [Download the 32-bit version](https://www.segger.com/downloads/embedded-studio/EmbeddedStudio_ARM_Win_x86), not the 64-bit version. Ensure that you are licensed to use it for your purposes. In Oct 2018, we were able to [obtain the license for free because we were developing for NRF52](https://www.segger.com/news/segger-embedded-studio-ide-now-free-for-nordic-sdk-users/).
|
||||
1. Download and unzip the [Nordic NRF5 SDK V15.2](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF5-SDK#Downloads).
|
||||
1. Edit Nordic's Blinky sample app so you can build it against your SDK:
|
||||
- Use a text editor to open <NORDIC_SDK_PATH>\examples\peripheral\blinky\pca10040\s132\ses\blinky_pca10040_s132.emProject.
|
||||
- Set the SDK_ROOT variable in this file to point to the root directory your Nordic SDK install. Specifically, replace the words "CHANGE_THIS_TO_YOUR_NORDIC_SDK_PATH" with the correct path, changing any backslashes ("\\") to forward slashes ("/") in the path. For example: macros="SDK_ROOT=C:/Users/ExampleUser/source/nRF5_SDK_15.2.0_9412b96;…"
|
||||
1. Edit Nordic's Blinky sample application so you can build it against your SDK:
|
||||
1. Use a text editor to open `<NORDIC_SDK_PATH>\examples\peripheral\blinky\pca10040\s132\ses\blinky_pca10040_s132.emProject`.
|
||||
1. Set the SDK_ROOT variable in this file to point to the root directory your Nordic SDK install. Specifically, replace the words "CHANGE_THIS_TO_YOUR_NORDIC_SDK_PATH" with the correct path, changing any backslashes ("\\") to forward slashes ("/") in the path. For example: `macros="SDK_ROOT=C:/Users/ExampleUser/source/nRF5_SDK_15.2.0_9412b96;…"`.
|
||||
1. Open this .emProject file in the Segger IDE.
|
||||
1. Build it (**Build->Build Solution**) to generate a .hex file. It is placed in this location: <NORDIC_SDK_PATH>\examples\peripheral\blinky\pca10040\s132\ses\Output\Release\Exe\blinky_pca10040_s132.hex
|
||||
1. Build it (**Build->Build Solution**) to generate a .hex file. It is placed in this location: `<NORDIC_SDK_PATH>\examples\peripheral\blinky\pca10040\s132\ses\Output\Release\Exe\blinky_pca10040_s132.hex`
|
||||
|
||||
### Obtain the BlinkyV3.bin and BlinkyV3.dat app firmware files
|
||||
### Obtain the BlinkyV3.bin and BlinkyV3.dat firmware files
|
||||
|
||||
1. Install [Python](https://www.python.org/downloads/) 2.7.6 (32-bit) or later.
|
||||
|
||||
**Note:** Python 3 won't work but it's fine to have this installed side-by-side.
|
||||
|
||||
1. Install [Python](https://www.python.org/downloads/) 2.7.6 (32-bit) or later. **Note:** Python 3 won't work but it's fine to have this installed side-by-side.
|
||||
1. Install the Nordic [nrfutil](http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.tools%2Fdita%2Ftools%2Fnrfutil%2Fnrfutil_intro.html) CLI.
|
||||
1. Use the **nrfutil** utility to transform the downloaded app .hex file into a firmware update package .zip file. Specify the app version in the command.
|
||||
- Open a command prompt and go to the directory that contains the .hex file generated above.
|
||||
- Run this command:
|
||||
`nrfutil pkg generate --application blinky_pca10040_s132.hex --sd-req "0xA8","0xAF" --application-version 3 --hw-version 52 blinkyV3.zip`
|
||||
- The version specified to pack the application ('3' in this case) must also be specified in the Azure Sphere app when you [deploy the new firmware](#deploy-the-new-firmware).
|
||||
- Note the warning about 'not providing a signature key'. This doesn't stop you from proceeding, but you should consider whether this is acceptable for your production scenario or whether, for example, your product is designed so that only the Azure Sphere chip has the ability to update the nRF52 firmware.
|
||||
- See the [nrfutil documentation](https://libraries.io/pypi/nrfutil) for more details about its command options.
|
||||
1. Use the **nrfutil** utility to transform the downloaded application .hex file into a firmware update package .zip file. Specify the application version in the command.
|
||||
1. Open a command prompt and go to the directory that contains the .hex file generated above.
|
||||
1. Run the following command:
|
||||
|
||||
```
|
||||
nrfutil pkg generate --application blinky_pca10040_s132.hex --sd-req "0xA8","0xAF" --application-version 3 --hw-version 52 blinkyV3.zip
|
||||
```
|
||||
|
||||
See the [nrfutil documentation](https://libraries.io/pypi/nrfutil) for more details about this command's options.
|
||||
|
||||
Note the warning about 'not providing a signature key'. This doesn't stop you from proceeding, but you should consider whether this is acceptable for your production scenario or whether, for example, your product is designed so that only the Azure Sphere chip has the ability to update the nRF52 firmware.
|
||||
|
||||
The version specified to pack the application ('3' in this case) must also be specified in the Azure Sphere application when you [Deploy the BlinkyV3 firmware](#deploy-the-blinkyv3-firmware).
|
||||
|
||||
1. Open the resulting .zip file and extract the .bin and metadata .dat back out from this .zip package.
|
||||
1. Rename these files as desired—for example, BlinkyV3.bin/.dat.
|
||||
|
||||
### Deploy the new firmware
|
||||
### Deploy the BlinkyV3 firmware
|
||||
|
||||
Add BlinkyV3.bin and BlinkyV3.dat as resources in the AzureSphere app by following the steps specified in [Edit the Azure Sphere app to deploy different firmware to the nRF52](#edit-the-azure-sphere-app-to-deploy-different-firmware-to-the-nrf52). Remember to update the filenames and the version to '3' in main.c.
|
||||
To deploy your new firmware to the nRF52, complete the following steps:
|
||||
|
||||
1. Add `BlinkyV3.bin` and `BlinkyV3.dat` as resources in the Azure Sphere application by following the steps specified in [Revise the Azure Sphere sample application](#revise-the-azure-sphere-sample-application). Remember to update the filenames and the version to '3' in `main.c`.
|
||||
1. Rebuild and run the sample by following the steps specified in [Rebuild and run the sample](#rebuild-and-run-the-sample).
|
||||
|
||||
## Combine this solution with the solution for BLE-based Wi-Fi setup
|
||||
|
||||
|
@ -132,23 +174,26 @@ You can combine this solution for external MCU update with the solution for [BLE
|
|||
|
||||
### Create a single Azure Sphere application
|
||||
|
||||
1. Remove the code that uses button A to trigger a firmware update and instead trigger it only when the combined app starts. In particular, remove the DfuTimerEventHandler, dfuButtonTimerEvent, gpioButtonFd, buttonPressCheckPeriod and dfuButtonTimerFd.
|
||||
1. Remove the code that uses button A to trigger a firmware update and instead trigger it only when the combined application starts. In particular, remove the DfuTimerEventHandler, dfuButtonTimerEvent, gpioButtonFd, buttonPressCheckPeriod and dfuButtonTimerFd.
|
||||
1. Combine the initialization and close functions. In particular, the UART, Epoll, and Reset file descriptors are opened and closed by both applications. Make sure you maintain only a single copy of each.
|
||||
1. After the MCU update is complete, make sure to remove any of its UART event handlers from the epoll event loop. This will allow the Wi-Fi setup code to register its own UART event handlers when needed. Failure to do so will result in such registrations returning -1 with errno set to EEXISTS.
|
||||
1. Combine the app manifest. In particular, add the required GPIOs for both applications and set the WifiConfig capability to true.
|
||||
1. Combine the application manifest. In particular, add the required GPIOs for both applications and set the WifiConfig capability to true.
|
||||
|
||||
### Obtain the nRF52 firmware files
|
||||
|
||||
1. Rebuild the nRF52 firmware for the [BLE-based Wi-Fi app](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/WifiSetupAndDeviceControlViaBle#build-your-own-solution). Select **Build->Build Solution** or press F7 to generate a .hex file. The hex file is placed in this location:
|
||||
|
||||
<PATH_TO_DOWNLOADED_SAMPLES>\WifiSetupAndDeviceControlViaBle\Nrf52App\pca10040\s132\ses\Output\Release\Exe\ble_app_uart_pca10040_s132.hex
|
||||
`<PATH_TO_DOWNLOADED_SAMPLES>\WifiSetupAndDeviceControlViaBle\Nrf52App\pca10040\s132\ses\Output\Release\Exe\ble_app_uart_pca10040_s132.hex`
|
||||
|
||||
1. Follow the steps specified in [Obtain the BlinkyV3.bin and BlinkyV3.dat app firmware files](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/ExternalMcuUpdate#obtain-the-blinkyv3bin-and-blinkyv3dat-app-firmware-files) to transform this .hex file into .dat and .bin files.
|
||||
1. Follow the steps specified in [Obtain the BlinkyV3.bin and BlinkyV3.dat firmware files](#obtain-the-blinkyv3bin-and-blinkyv3dat-firmware-files) to transform this .hex file into .dat and .bin files.
|
||||
1. Rename these fields as desired—for example, WifiSetupAndDeviceControlViaBle.bin/.dat
|
||||
|
||||
### Edit the Azure Sphere application to deploy the new nRF52 firmware
|
||||
### Deploy the new firmware
|
||||
|
||||
Add WifiSetupAndDeviceControlViaBle.bin and WifiSetupAndDeviceControlViaBle.dat as resources in the ExternalMcuUpdateNrf52 app by following the steps specified in [Edit the Azure Sphere app to deploy different firmware to the nRF52](#edit-the-azure-sphere-app-to-deploy-different-firmware-to-the-nrf52). Remember to update the filenames and the version in main.c. For example, if you've previously deployed version '3' of the firmware (even if it was just test firmware such as 'Blinky') then the version should now be '4'.
|
||||
To deploy the new firmware to the nRF52, complete the following steps:
|
||||
|
||||
1. Add `WifiSetupAndDeviceControlViaBle.bin` and `WifiSetupAndDeviceControlViaBle.dat` as resources in the **External MCU update** sample application by following the steps specified in [Revise the Azure Sphere sample application](#revise-the-azure-sphere-sample-application). Remember to update the filenames and the version in `main.c`. For example, if you've previously deployed version '3' of the firmware (even if it was just test firmware such as 'Blinky') then the version should now be '4'.
|
||||
|
||||
1. Rebuild and run the sample by following the steps specified in [Rebuild and run the sample](#rebuild-and-run-the-sample).
|
||||
|
||||
## Build your own bootloader
|
||||
|
||||
|
@ -163,14 +208,13 @@ This sample includes a modified version of the example bootloader (secure_bootlo
|
|||
To further edit and deploy this bootloader:
|
||||
|
||||
1. Edit the bootloader sample so you can build it against your SDK:
|
||||
- Use a text editor to open ExternalMcuUpdateNrf52\Nrf52Bootloader\pca10040\s132\ses\bootloader_uart_mbr_pca10040_debug.emProject.
|
||||
- Set the SDK_ROOT variable in this file to point to the root directory your Nordic SDK install. Specifically, replace the words "CHANGE_THIS_TO_YOUR_NORDIC_SDK_PATH" with the correct path, changing the backslashes ("\\") to forward slashes ("/") in the path. For example: macros="SDK_ROOT=C:/Users/ExampleUser/source/nRF5_SDK_15.2.0_9412b96;…"
|
||||
1. Use a text editor to open `ExternalMcuUpdate\Nrf52Bootloader\pca10040\s132\ses\bootloader_uart_mbr_pca10040_debug.emProject`.
|
||||
1. Set the SDK_ROOT variable in this file to point to the root directory your Nordic SDK install. Specifically, replace the words "CHANGE_THIS_TO_YOUR_NORDIC_SDK_PATH" with the correct path, changing the backslashes ("\\") to forward slashes ("/") in the path. For example: `macros="SDK_ROOT=C:/Users/ExampleUser/source/nRF5_SDK_15.2.0_9412b96;…"`.
|
||||
1. Open this .emProject file in the Segger IDE.
|
||||
1. Build it (**Build->Build Solution**) to generate a .hex file. It is placed in this location: ExternalMcuUpdateNrf52\Nrf52Bootloader\pca10040\s132\ses\Output\Release\Exe\bootloader_uart_mbr_pca10040_debug.hex
|
||||
1. Build it (**Build->Build Solution**) to generate a .hex file. It is placed in this location: `ExternalMcuUpdate\Nrf52Bootloader\pca10040\s132\ses\Output\Release\Exe\bootloader_uart_mbr_pca10040_debug.hex`
|
||||
1. Copy this file to the JLINK drive presented by the nRF52. The nRF52 restart automatically and runs the bootloader.
|
||||
|
||||
## License
|
||||
For license details, see LICENSE.txt in each directory.
|
||||
## Next steps
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(GPIO_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -23,38 +23,44 @@ description: "Demonstrates how to use a button to change the blink rate of an LE
|
|||
|
||||
# Sample: GPIO high-level app
|
||||
|
||||
This application does the following:
|
||||
This sample application demonstrates how to use a general-purpose input/output (GPIO) with Azure Sphere in a high-level application.
|
||||
|
||||
- Provides access to one of the LEDs on the MT3620 development board using GPIO
|
||||
- Uses a button to change the blink rate of the LED
|
||||
A GPIO is used to read the state of button A and to change the blink rate of LED 1 in response to a button press. The sample allows three possible blink rates for the LED.
|
||||
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [GPIO](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages button A and LED 1 on the device |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
| [EventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Accesses button A and LED 1 on the device. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| GPIO_HighLevelApp |Sample source code and VS project files |
|
||||
| README.md | This readme file |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The sample requires the following hardware:
|
||||
|
||||
* [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
- [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer, and your computer is connected to the internet.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
|
@ -65,8 +71,13 @@ The sample requires the following hardware:
|
|||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
LED1 on the MT3620 begins blinking red.
|
||||
The output messages are displayed in the **Device Output** window during debugging.
|
||||
|
||||
Press button A repeatedly to cycle through the 3 possible blink rates.
|
||||
LED1 on the MT3620 begins blinking red. Press button A on the MT3620 repeatedly to cycle through the three possible LED blink rates.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(HTTPS_Curl_Easy C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c curl)
|
||||
|
|
|
@ -16,6 +16,8 @@ extendedZipContent:
|
|||
target: SECURITY.md
|
||||
- path: Samples/troubleshooting.md
|
||||
target: troubleshooting.md
|
||||
- path: ethernet-setup-instructions.md
|
||||
target: ethernet-setup-instructions.md
|
||||
description: "Demonstrates how to use the cURL Easy interface with Azure Sphere over a secure HTTPS connection."
|
||||
---
|
||||
|
||||
|
@ -23,36 +25,32 @@ description: "Demonstrates how to use the cURL Easy interface with Azure Sphere
|
|||
|
||||
This sample demonstrates how to use the cURL Easy interface with Azure Sphere over a secure HTTPS connection. For details about using the libcurl library with Azure Sphere, see [Connect to web services using cURL](https://docs.microsoft.com/azure-sphere/app-development/curl).
|
||||
|
||||
The sample periodically downloads the index web page at example.com, by using cURL over a secure HTTPS connection.
|
||||
It uses the cURL Easy interface, which is a synchronous (blocking) API.
|
||||
The sample periodically downloads the index web page at example.com, by using cURL over a secure HTTPS connection. It uses the cURL Easy interface, which is a synchronous (blocking) API.
|
||||
|
||||
The sample logs the downloaded content. If the size of the downloaded content exceeds 2 KiB, the sample pauses the download, prints the content that has been downloaded so far, and then resumes the download. Refer to cURL `curl_easy_pause` API for more information.
|
||||
The sample logs the downloaded content. If the size of the downloaded content exceeds 2 KiB, the sample pauses the download, prints the content that has been downloaded so far, and then resumes the download. Refer to cURL **curl_easy_pause** API for more information.
|
||||
|
||||
You can modify the sample to use mutual authentication if your website is configured to do so. Instructions on how to modify the sample are provided below; however, they require that you already have a website and certificates configured for mutual authentication. See [Connect to web services - mutual authentication](https://docs.microsoft.com/azure-sphere/app-development/curl#mutual-authentication) for information about configuring mutual authentication on Azure Sphere. For information about configuring a website with mutual authentication for testing purposes, you can use [Configure certificate authentication in ASP.NET Core](https://docs.microsoft.com/aspnet/core/security/authentication/certauth?view=aspnetcore-3.0).
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
You can configure a static IP address on an Ethernet or Wi-Fi interface. If you have configured a device with a static IP and require name resolution your application must set a static DNS address. For more information, see the topics *"Static IP address"* and *"Static DNS address"* in [Use network services](https://docs.microsoft.com/azure-sphere/network/use-network-services).
|
||||
|
||||
The sample uses the following Azure Sphere libraries:
|
||||
|
||||
|Library |Purpose |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
|[log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
|[storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Gets the path to the certificate file that is used to authenticate the server |
|
||||
|libcurl | Configures the transfer and downloads the web page |
|
||||
| [EventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Gets and sets network interface configuration |
|
||||
| [curl](https://docs.microsoft.com/azure-sphere/reference/baseapis#curl-library) | Configures the data transfer and downloads the web page over HTTP/HTTPS. |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Gets and sets network interface configuration. |
|
||||
| [storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Gets the path to the certificate file that is used to authenticate the server. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -60,76 +58,78 @@ The sample requires the following hardware:
|
|||
|
||||
* [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, make the following changes:
|
||||
## Setup
|
||||
|
||||
1. Configure Azure Sphere as described in [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet).
|
||||
1. Add an Ethernet adapter to your hardware. If you are using an MT3620 RDB, see the [wiring instructions](../../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
1. Add the following line to the Capabilities section of the app_manifest.json file:
|
||||
|
||||
`"NetworkConfig" : true`
|
||||
1. In HTTPS_Curl_Easy/main.c, ensure that the global constant `networkInterface` is set to "eth0". In source file HTTPS_Curl_Easy/main.c, search for the following line:
|
||||
|
||||
`static const char networkInterface[] = "wlan0";`
|
||||
|
||||
Change this line to:
|
||||
|
||||
`static const char networkInterface[] = "eth0";`
|
||||
1. In HTTPS_Curl_Easy/main.c, add a call to `Networking_SetInterfaceState` before any other networking calls:
|
||||
|
||||
```c
|
||||
int err = Networking_SetInterfaceState(networkInterface, true);
|
||||
if (err == -1) {
|
||||
Log_Debug("Error setting interface state %d\n",errno);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
## Prepare the sample
|
||||
Complete the following steps to set up this sample.
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer, and your computer is connected to the internet.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *HTTPS_Curl_Easy* sample in the *HTTPS* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/https-curl-easy/).
|
||||
|
||||
## Add host names to the application manifest
|
||||
1. Note that the sample can connect only to websites listed in the **AllowedConnections** capability of the [app_manifest.json](https://docs.microsoft.com/azure-sphere/app-development/app-manifest) file. The sample is set up to connect to the website `example.com`:
|
||||
|
||||
The sample can only connect to websites listed in the application manifest. In the "AllowedConnections" section of the [app_manifest.json](https://docs.microsoft.com/azure-sphere/app-development/app-manifest) file, add the host name of each website to which you want the sample to connect. For example, the following adds Contoso.com to the list of allowed websites.
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections": [ "example.com" ],
|
||||
},
|
||||
```
|
||||
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections": [ "www.example.com", "www.Contoso.com"],
|
||||
},
|
||||
```
|
||||
You can revise the sample to connect to a different website for downloading, as described in the [Rebuild the sample to download from a different website](#rebuild-the-sample-to-download-from-a-different-website) section of this README.
|
||||
|
||||
## Downloading from another website
|
||||
### Use Ethernet instead of Wi-Fi
|
||||
|
||||
To download data from a website other than the default website, you'll need to get the root CA certificate from the website, and modify the sample to use the new website and its certificate.
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, follow the [Ethernet setup instructions](../../../ethernet-setup-instructions.md).
|
||||
|
||||
### Configure a static IP address
|
||||
|
||||
You can configure a static IP address on an Ethernet or a Wi-Fi interface. If you have configured a device with a static IP and require name resolution, your application must set a static DNS address. For more information, see the sections *Static IP address* and *Static DNS address* in [Use network services](https://docs.microsoft.com/azure-sphere/network/use-network-services).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
The sample logs the downloaded content. If the size of the downloaded content exceeds 2 KiB, the sample pauses the download, prints the content that has been downloaded so far, and then resumes the download. Refer to cURL **curl_easy_pause** API for more information.
|
||||
|
||||
## Rebuild the sample to download from a different website
|
||||
|
||||
To download data from a website other than the default website, you'll need to get the root CA certificate from the website, modify the sample to use the new website and its certificate, and build and run the modified sample.
|
||||
|
||||
Complete the steps described in the following sections.
|
||||
|
||||
### Download the root CA certificate
|
||||
|
||||
If the website uses SSL, you may need to use a different root CA certificate. To download the certificate from the website, follow these instructions:
|
||||
If the website uses SSL, you may need to use a different root CA certificate. To download the certificate from the website, complete the following steps.
|
||||
|
||||
1. Open the browser and click the Secure icon, which is a padlock in the address bar.
|
||||
1. Select Certificate.
|
||||
1. Open the Certification Path tab.
|
||||
1. Select the top certificate in the hierarchy and then select View Certificate.
|
||||
1. Open the Details tab and select Copy to File.
|
||||
1. In the Certificate Export Wizard, click Next.
|
||||
1. Select the Base-64 encoded X.509 (.CER) format and then click Next.
|
||||
1. Type the file name to which to export the certificate and then click Next.
|
||||
1. Click Finish to complete the wizard.
|
||||
1. Open the browser and click the **Secure** icon, which is a padlock in the address bar.
|
||||
1. Select **Certificate**.
|
||||
1. Open the **Certification Path** tab.
|
||||
1. Select the top certificate in the hierarchy and then select **View Certificate**.
|
||||
1. Open the **Details** tab and select **Copy to File**.
|
||||
1. In the Certificate Export Wizard, click **Next**.
|
||||
1. Select the Base-64 encoded X.509 (.CER) format and then click **Next**.
|
||||
1. Type the file name to which to export the certificate and then click **Next**.
|
||||
1. Click **Finish** to complete the wizard.
|
||||
1. Rename the downloaded certificate file to have the .pem extension.
|
||||
|
||||
### Modify the sample to use the new website
|
||||
|
||||
1. If you haven't already done so, add the hostname to the AllowedConnections capability of the application manifest.
|
||||
Complete the following steps to modify the sample to use the new website.
|
||||
|
||||
1. Open main.c, go to the following statement, and change `example.com` to the URL of the website you want to connect to.
|
||||
1. In the `app_manifest.json` file, add the hostname of the new website to the **AllowedConnections** capability. For example, the following adds `Contoso.com` to the list of allowed websites.
|
||||
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections": [ "example.com", "Contoso.com"],
|
||||
},
|
||||
```
|
||||
|
||||
1. Open `main.c`, go to the following statement, and change `example.com` to the URL of the website you want to connect to.
|
||||
|
||||
```c
|
||||
if ((res = curl_easy_setopt(curlHandle, CURLOPT_URL, "https://example.com")) != CURLE_OK) {
|
||||
|
@ -138,112 +138,120 @@ If the website uses SSL, you may need to use a different root CA certificate. To
|
|||
}
|
||||
```
|
||||
|
||||
1. Update the sample to use a different root CA certificate, if necessary:
|
||||
1. Put the trusted root CA certificate in the certs/ folder (and optionally remove the existing DigiCert Global Root CA certificate).
|
||||
1. Update line 14 of CMakeLists.txt to include the new trusted root CA certificate in the image package, instead of the DigiCert Global Root CA certificate.
|
||||
1. Update line 185 of main.c to point to the new trusted root CA certificate.
|
||||
1. Update the sample to use a different root CA certificate, if necessary:
|
||||
|
||||
## Build and run the sample
|
||||
1. Put the trusted root CA certificate in the `certs/` folder (and optionally remove the existing DigiCert Global Root CA certificate).
|
||||
1. Update line 14 of `CMakeLists.txt` to include the new trusted root CA certificate in the image package, instead of the DigiCert Global Root CA certificate.
|
||||
1. Update line 185 of `main.c` to point to the new trusted root CA certificate.
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
### Build and run the sample modified to use the new website
|
||||
|
||||
## Using the sample with mutual authentication
|
||||
To build and run the modified sample, follow the instructions in the [Build and run the sample](#build-and-run-the-sample) section of this README.
|
||||
|
||||
**Note:**
|
||||
These instructions are for testing purposes only and should not be used in a production environment.
|
||||
## Rebuild the sample to use mutual authentication
|
||||
|
||||
Continue here to modify and run the sample on a website that is configured to require mutual authentication.
|
||||
You can modify the sample to use mutual authentication if your website is configured to do so. The instructions in this section require that you already have a website and certificates configured for mutual authentication. See [Connect to web services - mutual authentication](https://docs.microsoft.com/azure-sphere/app-development/curl#mutual-authentication) for information about configuring mutual authentication on Azure Sphere. For information about configuring a website with mutual authentication for testing purposes, you can use [Configure certificate authentication in ASP.NET Core](https://docs.microsoft.com/aspnet/core/security/authentication/certauth?view=aspnetcore-3.0).
|
||||
|
||||
**Note:** These instructions are for testing purposes only and should not be used in a production environment.
|
||||
|
||||
Complete the steps described in the following sections to rebuild the sample to use mutual authentication on a website that is configured for mutual authentication.
|
||||
|
||||
### Update the application manifest
|
||||
|
||||
Add the following to app_manifest.json.
|
||||
Add the following to the `app_manifest.json` file.
|
||||
|
||||
1. Add the `DeviceAuthentication` capability, and use it to specify your tenant ID.
|
||||
1. Add the **DeviceAuthentication** capability, and use it to specify your tenant ID.
|
||||
|
||||
1. If you haven't already done so, in the `AllowedConnections` capability, add the HTTPS endpoint of the website that has mutual authentication configured.
|
||||
1. In the **AllowedConnections** capability, add the HTTPS endpoint of the website that has mutual authentication configured.
|
||||
|
||||
The following code snippet is an example entry.
|
||||
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections" : [ "www.example.com" ],
|
||||
"AllowedConnections" : [ "example.com" ],
|
||||
"DeviceAuthentication": "77304f1f-9530-4157-8598-30bc1f3d66f0"
|
||||
},
|
||||
```
|
||||
|
||||
### Add the TLS utilities library
|
||||
|
||||
1. Add [tlsutils](https://docs.microsoft.com/azure-sphere/app-development/baseapis#tls-utilities-library) to `target_link_libraries` in CMakeLists.txt.
|
||||
1. Add `tlsutils` to `target_link_libraries` in the `CMakeLists.txt` file, as shown in the following line of code. For information about this library, see [TLS utilities library](https://docs.microsoft.com/azure-sphere/app-development/tlsutils-library) in the Azure Sphere documentation.
|
||||
|
||||
```c
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c curl tlsutils)
|
||||
```
|
||||
`target_link_libraries(${PROJECT_NAME} applibs gcc_s c curl tlsutils)`
|
||||
|
||||
2. Open main.c and add the deviceauth_curl.h header file after curl.h.
|
||||
2. Open `main.c` and add the `deviceauth_curl.h` header file after `curl.h`:
|
||||
|
||||
```c
|
||||
#include <curl/curl.h>
|
||||
#include <tlsutils/deviceauth_curl.h>
|
||||
```
|
||||
```c
|
||||
#include <curl/curl.h>
|
||||
#include <tlsutils/deviceauth_curl.h>
|
||||
```
|
||||
|
||||
### Add TLS utilities functions
|
||||
|
||||
Use the [**DeviceAuth_CurlSslFunc**](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/tlsutils/function-deviceauth-curlsslfunc) function or create a custom authentication function using [**DeviceAuth_SslCtxFunc**](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/tlsutils/function-deviceauth-sslctxfunc). See [Connect to web services - mutual authentication](https://docs.microsoft.com/azure-sphere/app-development/curl#mutual-authentication) for more information about these functions.
|
||||
Use the [**DeviceAuth_CurlSslFunc**](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/tlsutils/function-deviceauth-curlsslfunc) function or create a custom authentication function that calls [**DeviceAuth_SslCtxFunc**](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/tlsutils/function-deviceauth-sslctxfunc) to perform the authentication. See [Connect to web services - mutual authentication](https://docs.microsoft.com/azure-sphere/app-development/curl#mutual-authentication) for more information about these functions.
|
||||
|
||||
#### Use DeviceAuth_CurlSslFunc
|
||||
- To use **DeviceAuth_CurlSslFunc**, revise `main.c` by adding the following code to the **PerformWebPageDownload** function after the **if** statement that sets **CURLOPT_VERBOSE**.
|
||||
|
||||
1. In main.c, add this code to the **PerformWebPageDownload** function after the **if** statement that sets **CURLOPT_VERBOSE**.
|
||||
```c
|
||||
// Configure SSL to use device authentication-provided client certificates
|
||||
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSL_CTX_FUNCTION, DeviceAuth_CurlSslFunc)) !=
|
||||
CURLE_OK) {
|
||||
LogCurlError("curl_easy_setopt CURLOPT_SSL_CTX_FUNCTION", res);
|
||||
goto cleanupLabel;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
// Configure SSL to use device authentication-provided client certificates
|
||||
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSL_CTX_FUNCTION, DeviceAuth_CurlSslFunc)) !=
|
||||
CURLE_OK) {
|
||||
LogCurlError("curl_easy_setopt CURLOPT_SSL_CTX_FUNCTION", res);
|
||||
goto cleanupLabel;
|
||||
}
|
||||
```
|
||||
- To create a custom authentication function that calls **DeviceAuth_SslCtxFunc**, complete the following steps.
|
||||
|
||||
#### Create a custom authentication function using DeviceAuth_SslCtxFunc
|
||||
1. Create your custom callback function. The following code is an example:
|
||||
|
||||
1. Create your custom callback function using **DeviceAuth_SslCtxFunc** to perform the authentication. for example:
|
||||
```c
|
||||
static CURLcode UserSslCtxFunction(CURL* curlHandle, void* sslCtx, void* userCtx)
|
||||
{
|
||||
DeviceAuthSslResult result = DeviceAuth_SslCtxFunc(sslCtx);
|
||||
|
||||
if (result != DeviceAuthSslResult_Success) {
|
||||
Log_Debug("Failed to set up device auth client certificates: %d\n", result);
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
static CURLcode UserSslCtxFunction(CURL* curlHandle, void* sslCtx, void* userCtx)
|
||||
{
|
||||
DeviceAuthSslResult result = DeviceAuth_SslCtxFunc(sslCtx);
|
||||
2. In `main.c`, add your custom function above the **PerformWebPageDownload** function.
|
||||
|
||||
if (result != DeviceAuthSslResult_Success) {
|
||||
Log_Debug("Failed to set up device auth client certificates: %d\n", result);
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
3. Add the following code to the **PerformWebPageDownload** function after the **if** statement that sets **CURLOPT_VERBOSE**.
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
```
|
||||
```c
|
||||
// Configure SSL to use device authentication-provided client certificates
|
||||
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSL_CTX_FUNCTION, UserSslCtxFunction)) !=
|
||||
CURLE_OK) {
|
||||
LogCurlError("curl_easy_setopt CURLOPT_SSL_CTX_FUNCTION", res);
|
||||
goto cleanupLabel;
|
||||
}
|
||||
```
|
||||
|
||||
2. In main.c, add your custom function above the **PerformWebPageDownload** function.
|
||||
### Build and run the sample modified to use mutual authentication
|
||||
|
||||
3. Add the following code to the **PerformWebPageDownload** function after the **if** statement that sets **CURLOPT_VERBOSE**.
|
||||
|
||||
```c
|
||||
// Configure SSL to use device authentication-provided client certificates
|
||||
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSL_CTX_FUNCTION, UserSslCtxFunction)) !=
|
||||
CURLE_OK) {
|
||||
LogCurlError("curl_easy_setopt CURLOPT_SSL_CTX_FUNCTION", res);
|
||||
goto cleanupLabel;
|
||||
}
|
||||
```
|
||||
To build and run the modified sample, follow the instructions in the [Build and run the sample](#build-and-run-the-sample) section of this README.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
The following message in device output may indicate an out of memory issue:
|
||||
The following message in device output may indicate an out of memory issue:
|
||||
|
||||
`Child terminated with signal = 0x9 (SIGKILL)`
|
||||
`Child terminated with signal = 0x9 (SIGKILL)`
|
||||
|
||||
Currently, the Azure Sphere OS has a bug that causes a slow memory leak when using cURL and HTTPS. This slow memory leak can result in your application running out of memory. We plan to fix this bug in an upcoming quality release, and will announce it in the [IoT blog](https://techcommunity.microsoft.com/t5/internet-of-things/bg-p/IoTBlog) when it is available.
|
||||
Currently, the Azure Sphere OS has a bug that causes a slow memory leak when using cURL and HTTPS. This slow memory leak can result in your application running out of memory. We plan to fix this bug in an upcoming quality release, and will announce it in the [IoT blog](https://techcommunity.microsoft.com/t5/internet-of-things/bg-p/IoTBlog) when it is available.
|
||||
|
||||
Until the updated OS is released, you can mitigate this problem. However, the mitigation might degrade performance, so you should remove it as soon as the updated OS is available. To mitigate the problem, disable the CURLOPT_SSL_SESSIONID_CACHE option when you create cURL handles, as shown in the following example:
|
||||
Until the updated OS is released, you can mitigate this problem. However, the mitigation might degrade performance, so you should remove it as soon as the updated OS is available. To mitigate the problem, disable the CURLOPT_SSL_SESSIONID_CACHE option when you create cURL handles, as shown in the following example:
|
||||
|
||||
`curl_easy_setopt(curlHandle, CURLOPT_SSL_SESSIONID_CACHE, 0);`
|
||||
|
||||
For details about how to set this option, see [CURLOPT_SSL_SESSIONID_CACHE explained](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_SESSIONID_CACHE.html) in the cURL documentation.
|
||||
For details about how to set this option, see [CURLOPT_SSL_SESSIONID_CACHE explained](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_SESSIONID_CACHE.html) in the cURL documentation.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For network troubleshooting, see [Troubleshoot network problems](https://docs.microsoft.com/azure-sphere/network/troubleshoot-network-problems).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(HTTPS_Curl_Multi C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c ui.c eventloop_timer_utilities.c web_client.c log_utils.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c curl)
|
||||
|
|
|
@ -18,6 +18,8 @@ extendedZipContent:
|
|||
target: SECURITY.md
|
||||
- path: Samples/troubleshooting.md
|
||||
target: troubleshooting.md
|
||||
- path: ethernet-setup-instructions.md
|
||||
target: ethernet-setup-instructions.md
|
||||
description: "Demonstrates how to use the cURL Multi interface with Azure Sphere over a secure HTTPS connection."
|
||||
---
|
||||
|
||||
|
@ -27,55 +29,30 @@ This sample demonstrates how to use the cURL Multi interface with Azure Sphere o
|
|||
|
||||
The sample downloads multiple web pages concurrently by using the cURL Multi interface. The content is output as soon as it arrives. Pressing button A on the MT3620 development board initiates the web transfers. After the sample validates the server identity, communication occurs over HTTP or HTTPS. At the same time, LED1 blinks at a constant rate, demonstrating that the cURL Multi interface is non-blocking.
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, make the following changes:
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
1. Configure Azure Sphere as described in [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet).
|
||||
1. Add an Ethernet adapter to your hardware. If you are using an MT3620 RDB, see the [wiring instructions](../../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
1. Add the following line to the Capabilities section of the app_manifest.json file:
|
||||
|
||||
`"NetworkConfig" : true`
|
||||
1. In HTTPS_Curl_Multi/main.c, ensure that the global constant `networkInterface` is set to "eth0". In source file HTTPS_Curl_Multi/main.c, search for the following line:
|
||||
|
||||
`const char networkInterface[] = "wlan0";`
|
||||
|
||||
Change this line to:
|
||||
|
||||
`const char networkInterface[] = "eth0";`
|
||||
1. In HTTPS_Curl_Multi/main.c, add a call to `Networking_SetInterfaceState` before any other networking calls:
|
||||
|
||||
```c
|
||||
int err = Networking_SetInterfaceState(networkInterface, true);
|
||||
if (err == -1) {
|
||||
Log_Debug("Error setting interface state %d\n",errno);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
You can also configure a static IP address on an Ethernet or Wi-Fi interface. If you have configured a device with a static IP and require name resolution your application must set a static DNS address. For more information, see the topics *"Static IP address"* and *"Static DNS address"* in [Use network services](https://docs.microsoft.com/azure-sphere/network/use-network-services).
|
||||
|
||||
|
||||
The sample uses the following Azure Sphere libraries:
|
||||
|
||||
|Library |Purpose |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Enables digital input for button A |
|
||||
|[log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
|[storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Gets the path to the certificate file that is used to authenticate the server |
|
||||
|libcurl | Configures the transfer and downloads the web page |
|
||||
|[networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Gets and sets network interface configuration |
|
||||
| [curl](https://docs.microsoft.com/azure-sphere/reference/baseapis#curl-library) | Configures the data transfer and downloads the web page over HTTP/HTTPS. |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Enables digital input for button A. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Gets and sets network interface configuration. |
|
||||
| [storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Gets the path to the certificate file that is used to authenticate the server. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -85,49 +62,76 @@ The sample requires the following hardware:
|
|||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
Complete the following steps to set up this sample.
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer, and your computer is connected to the internet.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *HTTPS_Curl_Multi* sample in the *HTTPS* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/https-curl-multi/).
|
||||
|
||||
## Add host names to the application manifest
|
||||
1. Note that the sample can connect only to websites listed in the **AllowedConnections** capability of the [app_manifest.json](https://docs.microsoft.com/azure-sphere/app-development/app-manifest) file. The sample is set up to connect to the website `httpstat.us`:
|
||||
|
||||
The sample can only connect to websites listed in the application manifest. In the "AllowedConnections" section of the [app_manifest.json](https://docs.microsoft.com/azure-sphere/app-development/app-manifest) file, add the host name of each website to which you want the sample to connect. For example, the following adds Contoso.com to the list of allowed websites.
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections": [ "httpstat.us" ],
|
||||
},
|
||||
```
|
||||
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections": [ "www.example.com", "www.Contoso.com"],
|
||||
},
|
||||
```
|
||||
You can revise the sample to connect to a different website for downloading, as described in the [Rebuild the sample to download from a different website](#rebuild-the-sample-to-download-from-a-different-website) section of this README.
|
||||
|
||||
## Downloading from another website
|
||||
### Use Ethernet instead of Wi-Fi
|
||||
|
||||
To download data from a website other than the default website, you'll need to get the root CA certificate from the website, and modify the sample to use the new website and its certificate.
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, follow the [Ethernet setup instructions](../../../ethernet-setup-instructions.md).
|
||||
|
||||
### Configure a static IP address
|
||||
|
||||
You can configure a static IP address on an Ethernet or a Wi-Fi interface. If you have configured a device with a static IP and require name resolution, your application must set a static DNS address. For more information, see the sections *Static IP address* and *Static DNS address* in [Use network services](https://docs.microsoft.com/azure-sphere/network/use-network-services).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
To start the download, press button A on the board. The sample downloads status information for HTTP statuses 200 (success) and 400 (bad request) from the `httpstat.us` website.
|
||||
|
||||
## Rebuild the sample to download from a different website
|
||||
|
||||
To download data from a website other than the default website, you'll need to get the root CA certificate from the website, modify the sample to use the new website and its certificate, and build and run the modified sample.
|
||||
|
||||
Complete the steps described in the following sections.
|
||||
|
||||
### Download the root CA certificate
|
||||
|
||||
If the website uses SSL, you may need to use a different root CA certificate. To download the certificate from the website, follow these instructions:
|
||||
If the website uses SSL, you may need to use a different root CA certificate. To download the certificate from the website, complete the following steps.
|
||||
|
||||
1. Open the browser and click the Secure icon, which is a padlock in the address bar.
|
||||
1. Select Certificate.
|
||||
1. Open the Certification Path tab.
|
||||
1. Select the top certificate in the hierarchy and then select View Certificate.
|
||||
1. Open the Details tab and select Copy to File.
|
||||
1. In the Certificate Export Wizard, click Next.
|
||||
1. Select the Base-64 encoded X.509 (.CER) format and then click Next.
|
||||
1. Type the file name to which to export the certificate and then click Next.
|
||||
1. Click Finish to complete the wizard.
|
||||
1. Open the browser and click the **Secure** icon, which is a padlock in the address bar.
|
||||
1. Select **Certificate**.
|
||||
1. Open the **Certification Path** tab.
|
||||
1. Select the top certificate in the hierarchy and then select **View Certificate**.
|
||||
1. Open the **Details** tab and select **Copy to File**.
|
||||
1. In the Certificate Export Wizard, click **Next**.
|
||||
1. Select the Base-64 encoded X.509 (.CER) format and then click **Next**.
|
||||
1. Type the file name to which to export the certificate and then click **Next**.
|
||||
1. Click **Finish** to complete the wizard.
|
||||
1. Rename the downloaded certificate file to have the .pem extension.
|
||||
|
||||
### Modify the sample to use the new website
|
||||
|
||||
1. If you haven't already done so, add the hostname to the AllowedConnections capability of the application manifest.
|
||||
1. Open web_client.c, go to the following statement, and change `https://httpstat.us/200?sleep=5000` and `https://httpstat.us/400?sleep=1000` to the URLs of the website you want to connect to.
|
||||
Complete the following steps to modify the sample to use the new website.
|
||||
|
||||
1. In the `app_manifest.json` file, add the hostname of the new website to the **AllowedConnections** capability. For example, the following adds `Contoso.com` to the list of allowed websites.
|
||||
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections": [ "httpstat.us", "Contoso.com"],
|
||||
},
|
||||
```
|
||||
|
||||
1. Open `web_client.c`, go to the following statement, and change `https://httpstat.us/200?sleep=5000` and `https://httpstat.us/400?sleep=1000` to the URLs of the website you want to connect to.
|
||||
|
||||
```c
|
||||
// The web transfers executed with cURL.
|
||||
|
@ -138,41 +142,32 @@ If the website uses SSL, you may need to use a different root CA certificate. To
|
|||
{.url = "https://httpstat.us/400?sleep=1000", .easyHandle = NULL}};
|
||||
```
|
||||
|
||||
1. Update the sample to use a different root CA certificate, if necessary:
|
||||
1. Put the trusted root CA certificate in the certs/ folder (and optionally remove the existing bundle.pem certificate).
|
||||
1. Update line 16 of CMakeLists.txt to include the new trusted root CA certificate in the image package, instead of the bundle.pem certificate.
|
||||
1. Update line 195 of web_client.c to point to the new trusted root CA certificate.
|
||||
1. Update the sample to use a different root CA certificate, if necessary:
|
||||
|
||||
## Build and run the sample
|
||||
1. Put the trusted root CA certificate in the `certs/` folder (and optionally remove the existing `bundle.pem` certificate).
|
||||
1. Update line 16 of `CMakeLists.txt` to include the new trusted root CA certificate in the image package, instead of the `bundle.pem` certificate.
|
||||
1. Update line 195 of `web_client.c` to point to the new trusted root CA certificate.
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
### Build and run the sample modified to use the new website
|
||||
|
||||
## To start the download
|
||||
To build and run the modified sample, follow the instructions in the [Build and run the sample](#build-and-run-the-sample) section of this README.
|
||||
|
||||
1. Press button A on the board to start download.
|
||||
|
||||
The sample downloads status information for HTTP statuses 200 (success) and 400 (bad request) from the httpstat.us website.
|
||||
|
||||
The sample can only connect to websites listed in the application manifest. In the "AllowedConnections" section of the app_manifest.json file, add the host name of each website to which you want the sample to connect. For example, the following adds Contoso.com to the list of allowed websites.
|
||||
|
||||
```json
|
||||
"Capabilities": {
|
||||
"AllowedConnections": ["httpstat.us", "Contoso.com"],
|
||||
.
|
||||
.
|
||||
.
|
||||
}
|
||||
```
|
||||
## Troubleshooting
|
||||
|
||||
The following message in device output may indicate an out of memory issue:
|
||||
|
||||
`Child terminated with signal = 0x9 (SIGKILL)`
|
||||
`Child terminated with signal = 0x9 (SIGKILL)`
|
||||
|
||||
Currently, the Azure Sphere OS has a bug that causes a slow memory leak when using cURL and HTTPS. This slow memory leak can result in your application running out of memory. We plan to fix this bug in an upcoming quality release, and will announce it in the [IoT blog](https://techcommunity.microsoft.com/t5/internet-of-things/bg-p/IoTBlog) when it is available.
|
||||
Currently, the Azure Sphere OS has a bug that causes a slow memory leak when using cURL and HTTPS. This slow memory leak can result in your application running out of memory. We plan to fix this bug in an upcoming quality release, and will announce it in the [IoT blog](https://techcommunity.microsoft.com/t5/internet-of-things/bg-p/IoTBlog) when it is available.
|
||||
|
||||
Until the updated OS is released, you can mitigate this problem. However, the mitigation might degrade performance, so you should remove it as soon as the updated OS is available. To mitigate the problem, disable the CURLOPT_SSL_SESSIONID_CACHE option when you create cURL handles, as shown in the following example:
|
||||
|
||||
`curl_easy_setopt(curlHandle, CURLOPT_SSL_SESSIONID_CACHE, 0);`
|
||||
|
||||
For details about how to set this option, see [CURLOPT_SSL_SESSIONID_CACHE explained](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_SESSIONID_CACHE.html) in the cURL documentation.
|
||||
For details about how to set this option, see [CURLOPT_SSL_SESSIONID_CACHE explained](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_SESSIONID_CACHE.html) in the cURL documentation.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For network troubleshooting, see [Troubleshoot network problems](https://docs.microsoft.com/azure-sphere/network/troubleshoot-network-problems).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(HelloWorld_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
This sample shows how to use CMake to build an Azure Sphere high-level application. It simply blinks an LED, so that you can verify that the Azure Sphere device and tools are installed and set up correctly.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|
@ -10,15 +12,18 @@ The sample uses the following Azure Sphere libraries.
|
|||
| [log.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Contains functions that log debug messages. |
|
||||
|
||||
## Contents
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
|
||||
| File/folder | Description |
|
||||
|---------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -28,10 +33,10 @@ The sample requires the following hardware:
|
|||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer and your computer is connected to the internet.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
|
@ -42,7 +47,7 @@ The sample requires the following hardware:
|
|||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Observe the output
|
||||
### Observe the output
|
||||
|
||||
LED1 on the MT3620 will begin to blink red.
|
||||
|
||||
|
@ -56,9 +61,3 @@ C:\Build>azsphere device app show-status
|
|||
To stop the application enter the command `azsphere device app stop -i <component ID>`.
|
||||
|
||||
To restart the application enter the command `azsphere device app start -i <component ID>`.
|
||||
|
||||
## License
|
||||
For license details, see LICENSE.txt in this directory.
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
|
|
|
@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(HelloWorld_RTApp_MT3620_BareMetal C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c)
|
||||
target_link_libraries(${PROJECT_NAME})
|
||||
|
|
|
@ -4,7 +4,18 @@ This sample demonstrates how to create, deploy, and run [MT3620 real-time capabl
|
|||
|
||||
This sample app for an MT3620 real-time core repeatedly transmits a simple message over a UART. These messages can be read in terminal application on a computer using a USB-to-serial adapter. By default, it uses the real-time core's dedicated UART, but if your hardware doesn't expose this UART's TX pin, then the sample can be altered to use a different UART.
|
||||
|
||||
Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *HelloWorld_RTApp_MT3620_BareMetal* sample in the *HelloWorld* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/helloworld/).
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -12,55 +23,57 @@ Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples)
|
|||
1. A breakout board and USB-to-serial adapter (for example, [FTDI Friend](https://www.digikey.com/catalog/en/partgroup/ftdi-friend/60311)) to connect the real-time core UART to a USB port on your computer.
|
||||
1. A terminal emulator (such as Telnet or [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/) to display the output.
|
||||
|
||||
## Prep your device
|
||||
## Setup
|
||||
|
||||
To prep your device on Windows:
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *HelloWorld_RTApp_MT3620_BareMetal* sample in the *HelloWorld* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/helloworld/).
|
||||
|
||||
1. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview) with administrator privileges.
|
||||
1. Prepare your device on Windows or Linux:
|
||||
|
||||
Administrator privileges are required for enabling real-time core debugging because it installs USB drivers for the debugger.
|
||||
**On Windows:**
|
||||
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command:
|
||||
1. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview) with administrator privileges.
|
||||
|
||||
Azure Sphere CLI:
|
||||
Administrator privileges are required for enabling real-time core debugging because it installs USB drivers for the debugger.
|
||||
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command:
|
||||
|
||||
Azure Sphere classic CLI:
|
||||
Azure Sphere CLI:
|
||||
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
|
||||
1. Close the window after the command completes because administrator privilege is no longer required. As a best practice, you should always use the lowest privilege that can accomplish a task.
|
||||
Azure Sphere classic CLI:
|
||||
|
||||
To prep your device on Linux:
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command:
|
||||
1. Close the window after the command completes because administrator privilege is no longer required. As a best practice, you should always use the lowest privilege that can accomplish a task.
|
||||
|
||||
Azure Sphere CLI:
|
||||
**On Linux:**
|
||||
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command:
|
||||
|
||||
Azure Sphere classic CLI:
|
||||
Azure Sphere CLI:
|
||||
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
|
||||
## Set up hardware to display output
|
||||
Azure Sphere classic CLI:
|
||||
|
||||
To prepare your hardware to display output from the sample, see [Set up hardware to display output](https://docs.microsoft.com/azure-sphere/install/qs-real-time-application#set-up-hardware-to-display-output).
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
|
||||
1. Prepare your hardware to display output from the sample. See [Set up hardware to display output](https://docs.microsoft.com/azure-sphere/install/qs-real-time-application#set-up-hardware-to-display-output) for instructions.
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
See [Tutorial: Build a real-time capable application](https://docs.microsoft.com/azure-sphere/install/qs-real-time-application) to learn how to build and deploy this sample.
|
||||
|
||||
## Test the sample
|
||||
### Observe the output
|
||||
|
||||
The connected terminal emulator should display output from the HelloWorld_RTApp_MT3620_Baremetal program. The program sends the following words at one-second intervals:
|
||||
|
||||
|
|
|
@ -25,7 +25,35 @@ description: "Demonstrates the basic features of Azure Sphere high-level and rea
|
|||
|
||||
The samples in this folder demonstrate the basic features of Azure Sphere high-level and real-time capable applications and provide confirmation that the Azure Sphere hardware, SDK, and other tools are properly installed and configured.
|
||||
|
||||
## Samples
|
||||
The following samples are included:
|
||||
|
||||
* [HelloWorld_HighLevelApp](HelloWorld_HighLevelApp/) - a basic high-level app.
|
||||
* [HelloWorld_RTApp_MT3620_BareMetal](HelloWorld_RTApp_MT3620_BareMetal/) - a basic real-time capable app for the MT3620 running on bare-metal.
|
||||
- [HelloWorld_HighLevelApp](HelloWorld_HighLevelApp/) — A basic high-level application.
|
||||
- [HelloWorld_RTApp_MT3620_BareMetal](HelloWorld_RTApp_MT3620_BareMetal/) — A basic real-time capable application (RTApp) for the MT3620 running on bare-metal.
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------------------------------|-------------|
|
||||
| `README.md` | This README file. |
|
||||
| `HelloWorld_HighLevelApp` | Folder containing the configuration files, source code files, hardware definitions, and other files needed for the high-level application. |
|
||||
| `HelloWorld_RTApp_MT3620_BareMetal` | Folder containing the configuration files, source code files, and other files needed for the real-time capable application (RTApp). |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **High-level application**: See the [high-level app prerequisites](HelloWorld_HighLevelApp/README.md#prerequisites).
|
||||
- **Real-time capable application**: See the [RTApp prerequisites](HelloWorld_RTApp_MT3620_BareMetal/README.md#prerequisites).
|
||||
|
||||
## Setup
|
||||
|
||||
- **High-level application**: See the [high-level app setup](HelloWorld_HighLevelApp/README.md#setup).
|
||||
- **Real-time capable application**: See the [RTApp setup](HelloWorld_RTApp_MT3620_BareMetal/README.md#setup).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
- **High-level application**: See the [high-level app build instructions](HelloWorld_HighLevelApp/README.md#build-and-run-the-sample).
|
||||
- **Real-time capable application**: See the [RTApp build instructions](HelloWorld_RTApp_MT3620_BareMetal/README.md#build-and-run-the-sample).
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(I2C_LSM6DS3_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -25,19 +25,33 @@ description: "Demonstrates how to use the I2C (Inter-Integrated Circuit) interfa
|
|||
|
||||
This sample demonstrates how to use [I2C with Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/i2c) in a high-level application. The sample displays data from an accelerometer connected to an MT3620 development board through I2C (Inter-Integrated Circuit). Once per second the application calls the [Applibs I2C APIs](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-i2c/i2c-overview) to retrieve the accelerometer data. It then calls [Log_Debug](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/function-log-debug) to display the data.
|
||||
|
||||
By default, this sample is configured to use an external accelerometer—the [ST LSM6DS3](https://www.st.com/en/mems-and-sensors/lsm6ds3.html). It is not configured to use the on-board sensors found on some development boards, such as the [ST LSM6DS0](https://www.st.com/resource/en/datasheet/LSM6DSO.pdf) on the Avnet Starter Kit. To run the sample using the Avnet MT3620 Starter Kit and the on-board LSM6DSO accelerometer, see [Changes required to use the Avnet MT3620 Starter Kit and its on-board LSM6SDO accelerometer](#changes-required-to-use-the-avnet-mt3620-starter-kit-and-its-on-board-lsm6sdo-accelerometer).
|
||||
By default, this sample is configured to use an external accelerometer—the [ST LSM6DS3](https://www.st.com/en/mems-and-sensors/lsm6ds3.html). It is not configured to use the on-board sensors found on some development boards, such as the [ST LSM6DS0](https://www.st.com/resource/en/datasheet/LSM6DSO.pdf) on the Avnet Starter Kit. To run the sample using the Avnet MT3620 Starter Kit and the on-board ST LSM6DSO accelerometer, see [Use the Avnet MT3620 Starter Kit and its on-board accelerometer](#use-the-avnet-mt3620-starter-kit-and-its-on-board-accelerometer).
|
||||
|
||||
The sample uses the following Azure Sphere libraries:
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
|Library |Purpose |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
|log | Displays messages in the Device Output window during debugging |
|
||||
|i2c | Manages I2C interfaces |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [i2c](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-i2c/i2c-overview) | Manages Inter-Integrated Circuit (I2C) interfaces. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This sample requires the following hardware:
|
||||
This sample requires the following hardware:
|
||||
|
||||
- Azure Sphere device
|
||||
|
||||
|
@ -48,45 +62,39 @@ The sample uses the following Azure Sphere libraries:
|
|||
- We recommend a breadboard because this sample requires wiring from multiple sources to the same pin and the use of pull-up resistors.
|
||||
- Jumper wires to connect the boards.
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Set up your Azure Sphere device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this setup previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *I2C_LSM6DS3_HighLevelApp* sample in the *I2C* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/i2c/).
|
||||
1. Set up your hardware to display output from the sample. For instructions, see [Set up hardware to display output](https://docs.microsoft.com/azure-sphere/install/qs-multicore-dev#set-up-hardware-to-display-output).
|
||||
1. Make the following connections between the ST LSM6DS3 and MT3620 dev boards. Make sure that power is disconnected while you wire the boards.
|
||||
|
||||
## Set up hardware to display output
|
||||
**Note:** This sample uses ISU2 on the MT3620 board; however, you can use another ISU by adjusting the wiring, the code, and the application manifest.
|
||||
|
||||
To prepare your hardware to display output from the sample, see "Set up hardware to display output" for [Windows](https://docs.microsoft.com/azure-sphere/install/development-environment-windows#set-up-hardware-to-display-output) or [Linux](https://docs.microsoft.com/azure-sphere/install/development-environment-linux#set-up-hardware-to-display-output).
|
||||
![Connection diagram for ST LSM6DS3 and MT3620](./media/i2cwiring.png)
|
||||
|
||||
## Set up the ST LSM6DS3 connections
|
||||
### Use the Avnet MT3620 Starter Kit and its on-board accelerometer
|
||||
|
||||
Make the following connections between the ST LSM6DS3 and MT3620 dev boards. Make sure that power is disconnected while you wire the boards.
|
||||
If you're using the Avnet MT3620 Starter Kit and its on-board ST LSM6DSO accelerometer instead of the ST LSM6DS3 external accelerometer, make the following changes in the sample:
|
||||
|
||||
**Note:** this sample uses ISU2 on the MT3620 board; however, you can use another ISU by adjusting the wiring, the code, and the application manifest.
|
||||
|
||||
![Connection diagram for ST LSM6DS3 and MT3620](./media/i2cwiring.png)
|
||||
|
||||
## Changes required to use the Avnet MT3620 Starter Kit and its on-board LSM6SDO accelerometer
|
||||
|
||||
1. Open main.c
|
||||
1. Search for `static const uint8_t expectedWhoAmI = 0x69;` and replace `0x69` with `0x6C`
|
||||
1. Search for `i2cFd = I2CMaster_Open(SAMPLE_LSM6DS3_I2C);` and replace `SAMPLE_LSM6DS3_I2C` with `SAMPLE_LSM6DSO_I2C`
|
||||
|
||||
1. Open app_manifest.json
|
||||
1. Search for `"I2cMaster": [ "$SAMPLE_LSM6DS3_I2C" ]` and replace `$SAMPLE_LSM6DS3_I2C` with `$SAMPLE_LSM6DSO_I2C`
|
||||
1. Open the `I2C\main.c` source code file:
|
||||
1. Search for the code `static const uint8_t expectedWhoAmI = 0x69;` and replace `0x69` with `0x6C`.
|
||||
1. Search for the code `i2cFd = I2CMaster_Open(SAMPLE_LSM6DS3_I2C);` and replace `SAMPLE_LSM6DS3_I2C` with `SAMPLE_LSM6DSO_I2C`.
|
||||
1. Open the `app_manifest.json` file. Search for `"I2cMaster": [ "$SAMPLE_LSM6DS3_I2C" ]` and replace `$SAMPLE_LSM6DS3_I2C` with `$SAMPLE_LSM6DSO_I2C`.
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
When you run the application, it reads the accelerometer WHO_AM_I register. The returned value (0x69 for the LSM6DS3) is compared with the application's `expectedWhoAmI` constant to verify that the MT3620 can successfully communicate with the accelerometer. If this fails, verify that the devices are wired correctly, and that the application opened the correct I2C interface. For details on the LSM6DS3 registers, see the [ST LSM6DS3 data sheet](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf).
|
||||
When you run the application, it reads the accelerometer WHO_AM_I register. The returned value (0x69 for the LSM6DS3) is compared with the application's **expectedWhoAmI** constant to verify that the MT3620 can successfully communicate with the accelerometer. If this fails, verify that the devices are wired correctly, and that the application opened the correct I2C interface. For details on the LSM6DS3 registers, see the [ST LSM6DS3 data sheet](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf).
|
||||
|
||||
After displaying the initial values, the application configures the accelerometer and then displays the vertical acceleration every second.
|
||||
|
||||
|
@ -95,3 +103,8 @@ To test the accelerometer data:
|
|||
1. Keep the device still and observe the accelerometer output in the **Output Window**. It should indicate a vertical acceleration of approximately +1g. Once the data from the accelerometer CTRL3_C register is displayed, the output should repeat every second.
|
||||
|
||||
1. Turn the accelerometer upside down and observe the updated data in the **Output Window**. The vertical acceleration should change from approximately +1g to approximately -1g.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(IntercoreComms_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(IntercoreComms_RTApp_MT3620_BareMetal C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c logical-intercore.c logical-dpc.c mt3620-intercore.c mt3620-uart-poll.c mt3620-timer.c)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_DEPENDS ${CMAKE_SOURCE_DIR}/linker.ld)
|
||||
|
|
|
@ -25,78 +25,88 @@ This sample demonstrates how to exchange messages between applications running o
|
|||
|
||||
**Note:** Before you run this sample, see [Communicate with a high-level application](https://docs.microsoft.com/azure-sphere/app-development/inter-app-communication). It describes how real-time capable applications communicate with high-level applications on the MT3620.
|
||||
|
||||
Once per second the high-level application (HLApp) sends a message "hl-app-to-rt-app-%d", where %d cycles between 00 and 99.
|
||||
The real-time capable application (RTApp) prints the receieved message.
|
||||
Once per second the RTApp sends a message "rt-app-to-hl-app-%d" to the HLApp, where %d cycles between 00 and 99.
|
||||
The HLApp prints the received message.
|
||||
Once per second the high-level application (HLApp) sends a message "hl-app-to-rt-app-%d", where %d cycles between 00 and 99. The real-time capable application (RTApp) prints the received message. Once per second the RTApp sends a message "rt-app-to-hl-app-%d" to the HLApp, where %d cycles between 00 and 99. The HLApp prints the received message.
|
||||
|
||||
The HLApp uses the following Azure Sphere libraries:
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
|Library |Purpose |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
|[application.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) |Communicates with and controls real-time capable applications |
|
||||
|[log.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) |Displays messages in the Device Output window during debugging |
|
||||
|[eventloop.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) |Invoke handlers for timer events |
|
||||
| [application](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Communicates with and controls the real-time capable application. |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
|
||||
Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *IntercoreComms* sample in the *IntercoreComms* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/intercorecomms/).
|
||||
**Note:** These libraries are used only by the high-level application.
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------------------------|-------------|
|
||||
| `intercore.code-workspace` | A Visual Studio Code workspace file that allows building and debugging the RTApp and the high-level app at the same time. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `README.md` | This README file. |
|
||||
| `IntercoreComms_HighLevelApp` | Folder containing the configuration files, source code files, and other files needed for the high-level application. |
|
||||
| `IntercoreComms_RTApp_MT3620_BareMetal` | Folder containing the configuration files, source code files, and other files needed for the real-time capable application (RTApp). |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
1. A USB-to-serial adapter (for example, [FTDI Friend](https://www.digikey.com/catalog/en/partgroup/ftdi-friend/60311)) to connect the real-time capable core UART to a USB port on your PC.
|
||||
1. A terminal emulator (such as Telnet or [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/.)) to display the output.
|
||||
- [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
- A USB-to-serial adapter (for example, [FTDI Friend](https://www.digikey.com/catalog/en/partgroup/ftdi-friend/60311)) to connect the real-time capable core UART to a USB port on your PC.
|
||||
- A terminal emulator (such as Telnet or [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/.)) to display the output.
|
||||
|
||||
## Prep your device
|
||||
## Setup
|
||||
|
||||
To prep your device on Windows:
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *IntercoreComms* sample in the *IntercoreComms* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/intercorecomms/).
|
||||
|
||||
1. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview) with administrator privileges.
|
||||
1. Prepare your device on Windows or Linux.
|
||||
|
||||
Administrator privileges are required for enabling real-time core debugging because it installs USB drivers for the debugger.
|
||||
**To prepare your device on Windows:**
|
||||
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command as follows:
|
||||
1. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview) with administrator privileges.
|
||||
|
||||
Azure Sphere CLI:
|
||||
Administrator privileges are required for enabling real-time core debugging because it installs USB drivers for the debugger.
|
||||
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command as follows:
|
||||
|
||||
Azure Sphere classic CLI:
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
Azure Sphere CLI:
|
||||
|
||||
1. Close the window after the command completes because administrator privilege is no longer required. As a best practice, you should always use the lowest privilege that can accomplish a task.
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
|
||||
To prep your device on Linux:
|
||||
Azure Sphere classic CLI:
|
||||
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command as follows:
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
|
||||
Azure Sphere CLI:
|
||||
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
1. Close the window after the command completes because administrator privilege is no longer required. As a best practice, you should always use the lowest privilege that can accomplish a task.
|
||||
|
||||
Azure Sphere classic CLI:
|
||||
**To prepare your device on Linux:**
|
||||
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
1. Enter the [**azsphere device enable-development**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#enable-development) command as follows:
|
||||
|
||||
## Set up hardware to display output
|
||||
Azure Sphere CLI:
|
||||
|
||||
To prepare your hardware to display output from the sample, see [Set up hardware to display output](https://docs.microsoft.com/azure-sphere/install/development-environment-windows#set-up-hardware-to-display-output) for Windows or [Set up hardware to display output](https://docs.microsoft.com/azure-sphere/install/development-environment-linux#set-up-hardware-to-display-output) for Linux.
|
||||
```
|
||||
azsphere device enable-development --enable-rt-core-debugging
|
||||
```
|
||||
|
||||
## Build and run the apps
|
||||
Azure Sphere classic CLI:
|
||||
|
||||
```
|
||||
azsphere device enable-development --enablertcoredebugging
|
||||
```
|
||||
|
||||
1. Set up the hardware to display output from the RTApp. For instructions, see [Set up hardware to display output](https://docs.microsoft.com/azure-sphere/install/qs-real-time-application#set-up-hardware-to-display-output).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
The applications in this sample run as partners. Make sure that they're designated as partners, as described in [Mark applications as partners](https://docs.microsoft.com/azure-sphere/app-development/sideload-app#mark-applications-as-partners), so that sideloading one doesn't delete the other.
|
||||
|
||||
If you're using Visual Studio or Visual Studio Code, you will need to deploy and debug both apps simutaneously. See the following instructions for building and running
|
||||
the sample with Visual Studio or Visual Studio Code:
|
||||
If you're using Visual Studio or Visual Studio Code, you will need to deploy and debug both apps simultaneously. See the following instructions for building and running
|
||||
the sample with Visual Studio or Visual Studio Code.
|
||||
|
||||
### Build and run the sample with Visual Studio
|
||||
**To build and run the sample with Visual Studio:**
|
||||
|
||||
1. On the **File** menu, select **Open > Folder**.
|
||||
1. Navigate to your Azure Sphere samples directory, select IntercoreComms, and click **Select Folder**.
|
||||
|
@ -104,10 +114,9 @@ the sample with Visual Studio or Visual Studio Code:
|
|||
1. On the **Build** menu, select **Build All**.
|
||||
1. On the **Debug** menu, select **Start**, or press **F5**.
|
||||
|
||||
### Build and run the sample with Visual Studio Code
|
||||
|
||||
Use the [Visual Studio Code Multi-root Workspaces](https://code.visualstudio.com/docs/editor/multi-root-workspaces) feature to build and debug the RTApp and high-level app at the same time.
|
||||
**To build and run the sample with Visual Studio Code:**
|
||||
|
||||
1. Use the [Visual Studio Code Multi-root Workspaces](https://code.visualstudio.com/docs/editor/multi-root-workspaces) feature to build and debug the RTApp and high-level app at the same time.
|
||||
1. On the **File** menu, **Select Open Workspace**.
|
||||
1. Navigate to the IntercoreComms root directory and select the file *intercore.code-workspace*.
|
||||
1. Click **Open**.
|
||||
|
@ -116,11 +125,9 @@ Use the [Visual Studio Code Multi-root Workspaces](https://code.visualstudio.com
|
|||
1. On the pulldown menu, that appears at the top of the window on the left side of the screen, select **Launch for azure Sphere Applications (gdb)(workspace)**.
|
||||
1. On the **Run** menu, select **Start Debugging**.
|
||||
|
||||
If you're running the sample from the command line you will need to build and run the RTApp before you build and run the high-level app. For more information about building real-time capable
|
||||
and high-level applications from the command line, go to [Build a sample application](../../BUILD_INSTRUCTIONS.md) and click on the links "Tutorial: Build a real-time capable application"
|
||||
and "Build and run a high-level sample with the CLI" respectively.
|
||||
If you're running the sample from the command line you will need to build and run the RTApp before you build and run the high-level app. For more information about building real-time capable and high-level applications from the command line, go to [Build a sample application](../../BUILD_INSTRUCTIONS.md) and click on the links *Tutorial: Build a real-time capable application* and *Build and run a high-level sample with the CLI* respectively.
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
The high-level application output will be displayed in the Output window in Visual Studio or Visual Studio Code.
|
||||
|
||||
|
@ -155,3 +162,9 @@ Text: hl-app-to-rt-app-01
|
|||
```
|
||||
|
||||
Again, the numbers in the messages may start from different places.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn about partner-application development, see [Create partner applications](https://docs.microsoft.com/azure-sphere/app-development/create-partner-apps).
|
||||
- To learn about how a high-level application communicates with an RTApp, see [Communicate with a real-time capable application](https://docs.microsoft.com/azure-sphere/app-development/high-level-inter-app).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(MutableStorage C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -27,32 +27,41 @@ This sample application illustrates how to manage [storage](https://docs.microso
|
|||
|
||||
When you press button A, the sample opens a persistent data file on the device, increments the value in it, and closes the file. When you press button B, the sample deletes the file. The file persists if the application exits or is updated. However, if you delete the application by using the **azsphere device sideload delete** command, the file is deleted as well.
|
||||
|
||||
The sample uses the following Azure Sphere libraries:
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
|Library |Purpose |
|
||||
|---------|---------|
|
||||
|gpio | Enables use of buttons and LEDs |
|
||||
|log | Displays messages in the Device Output window during debugging |
|
||||
|storage | Manages persistent user data |
|
||||
| Library | Purpose |
|
||||
|-----------|----------|
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Enables use of buttons and LEDs. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Manages persistent user data. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Describes how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prepare the sample
|
||||
## Prerequisites
|
||||
|
||||
**Note:**: By default, this sample targets MT3620 reference development board (RDB) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the README file in the HardwareDefinitions folder.
|
||||
The sample requires the following hardware:
|
||||
|
||||
- [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Setup
|
||||
|
||||
1. Set up your Azure Sphere device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
1. Even if you've performed this set up previously, ensure you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Even if you've performed this set up previously, ensure you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *MutableStorage* sample in the *MutableStorage* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/mutablestorage/).
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
@ -63,9 +72,16 @@ The sample uses the following Azure Sphere libraries:
|
|||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
When the application starts:
|
||||
|
||||
1. Press button A to open and write to a file.
|
||||
1. Press the button repeatedly to increment the value in the file.
|
||||
1. Press button B to delete the file.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- To learn more about memory usage by high-level applications, see [Understand memory use](https://docs.microsoft.com/azure-sphere/app-development/application-memory-usage).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(PWM_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -23,9 +23,9 @@ description: "Demonstrates how to use the PWM (pulse-width modulator) interface
|
|||
|
||||
# Sample: PWM high-level app
|
||||
|
||||
This sample demonstrates how to use the PWM (pulse-width modulator) interface in a simple digital-to-analog conversion application on an MT3620 device.
|
||||
This sample demonstrates how to use the pulse-width modulator (PWM) interface in a simple digital-to-analog conversion application on an MT3620 device.
|
||||
|
||||
It varies the brightness of an LED by incrementally varying the duty cycle of the output pulses from the PWM.
|
||||
The sample varies the brightness of an LED by incrementally varying the duty cycle of the output pulses from the PWM.
|
||||
|
||||
**Note:** Minimum and maximum period and duty cycle will vary depending on the hardware you use. For example, The MT3620 reference board's PWM modulators run at 2 MHz with 16 bit on/off compare registers. This imposes a minimum duty cycle of 500 ns, and an effective maximum period of approximately 32.77 ms. Consult the data sheet for your specific device for details.
|
||||
|
||||
|
@ -33,38 +33,53 @@ It varies the brightness of an LED by incrementally varying the duty cycle of th
|
|||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [pwm](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-pwm/pwm-overview) | Manages PWMs |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [pwm](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-pwm/pwm-overview) | Manages the pulse-width modulators (PWMs). |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| `PWM_HighLevelApp` |Sample source code and project files|
|
||||
| `README` | This README file. |
|
||||
| `LICENSE` | The license for the sample. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *PWM_HighLevelApp* sample in the *PWM* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/pwm/).
|
||||
The sample requires the following hardware:
|
||||
|
||||
- [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
|
||||
## Prepare the sample
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studio. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
## Setup
|
||||
|
||||
1. Ensure that your Azure Sphere device is connected to your computer, and your computer is connected to the internet.
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.01 or above. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview), and run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.04 or above. Open the [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview), and run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
```
|
||||
azsphere device enable-development
|
||||
```
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *PWM_HighLevelApp* sample in the *PWM* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/pwm/).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
LED1 (green on the RDB) will gradually increase in brightness until it reaches maximum, after which it will turn off and the cycle will repeat.
|
||||
The output messages are displayed in the **Device Output** window during debugging.
|
||||
|
||||
LED1 (green on the MT3620 RDB) gradually increases in brightness until it reaches maximum, after which it turns off and the cycle repeats.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(PowerDown_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -18,6 +18,8 @@ extendedZipContent:
|
|||
target: SECURITY.md
|
||||
- path: Samples/troubleshooting.md
|
||||
target: troubleshooting.md
|
||||
- path: ethernet-setup-instructions.md
|
||||
target: ethernet-setup-instructions.md
|
||||
description: "Demonstrates how to force an Azure Sphere device into the Power Down state and wake up the device to check for updates."
|
||||
---
|
||||
|
||||
|
@ -25,7 +27,7 @@ description: "Demonstrates how to force an Azure Sphere device into the Power Do
|
|||
|
||||
This sample application demonstrates how to force an Azure Sphere device into the [Power Down](https://docs.microsoft.com/azure-sphere/app-development/power-down) state and wake up the device to check for [OS and app updates](https://docs.microsoft.com/azure-sphere/app-development/power-down#force-power-down-and-updates).
|
||||
|
||||
To ensure that updates have completed before the Power Down state is requested, the sample application makes use of three [system event notifications](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-sysevent/enum-sysevent-events): **SysEvent_Events_NoUpdateAvailable,** **SysEvent_Events_UpdateStarted,** and **SysEvent_Events_UpdateReadyForInstall**. It uses these notifications to find out about the status of downloads and updates.
|
||||
To ensure that updates have completed before the Power Down state is requested, the sample application makes use of three [system event notifications](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-sysevent/enum-sysevent-events): **SysEvent_Events_NoUpdateAvailable**, **SysEvent_Events_UpdateStarted**, and **SysEvent_Events_UpdateReadyForInstall**. It uses these notifications to find out about the status of downloads and updates.
|
||||
|
||||
The sample performs the following cycle of operations:
|
||||
|
||||
|
@ -33,46 +35,29 @@ The sample performs the following cycle of operations:
|
|||
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
|Library |Purpose |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
|[log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
|[gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Used for GPIO (general-purpose input/output) pin communication |
|
||||
|[eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Used for LED blink, Power Down, and other timers |
|
||||
|[sysevent](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-sysevent/sysevent-overview) | Used to register for system event notifications about updates so that the app can make sure update checks have completed before the Power Down state is requested |
|
||||
|[powermanagement](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-power/power-overview) | Used to manage the power state of the device |
|
||||
|[storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Used to keep track of when an update check happened |
|
||||
|[networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Used to check if the device is connected to a network and if the time is synchronized|
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, make the following changes:
|
||||
|
||||
1. Configure Azure Sphere as described in [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet).
|
||||
1. Add an Ethernet adapter to your hardware. If you are using an MT3620 RDB, see the [wiring instructions](../../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
1. Add the following line to the Capabilities section of the app_manifest.json file:
|
||||
|
||||
`"NetworkConfig" : true`
|
||||
1. In Powerdown/Powerdown_HighLevelApp/main.c, ensure that the global constant `networkInterface` is set to "eth0". In source file Powerdown/Powerdown_HighLevelApp/main.c, search for the following line:
|
||||
|
||||
`static const char networkInterface[] = "wlan0";`
|
||||
|
||||
Change this line to:
|
||||
|
||||
`static const char networkInterface[] = "eth0";`
|
||||
1. In Powerdown/Powerdown_HighLevelApp/main.c, add a call to `Networking_SetInterfaceState` before any other networking calls:
|
||||
|
||||
```c
|
||||
int err = Networking_SetInterfaceState(networkInterface, true);
|
||||
if (err == -1) {
|
||||
Log_Debug("Error setting interface state %d\n",errno);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for LED blink, Power Down, and other timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Communicates with general-purpose input/outputs (GPIOs). |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Checks if the device is connected to a network and if the time is synchronized. |
|
||||
| [powermanagement](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-power/power-overview) | Manages the power state of the device. |
|
||||
| [storage](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-storage/storage-overview) | Keeps track of when an update check happened. |
|
||||
| [sysevent](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-sysevent/sysevent-overview) | Registers for system event notifications about updates. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| Powerdown_HighLevelApp | Sample source code and project files |
|
||||
| README.md | This readme file |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -82,7 +67,7 @@ By default, this sample runs over a Wi-Fi connection to the internet. To use Eth
|
|||
|
||||
- CR2032 coin cell battery to power the real-time clock (RTC) (Optional): Insert the battery into the battery holder on the bottom of the RDB as shown in the following image:
|
||||
|
||||
![Connection diagram for pulling PMU_EN low on RDB v1.0](./media/RTC_battery_RDB.png)
|
||||
![Connection diagram for pulling PMU_EN low on RDB v1.0](./media/RTC_battery_RDB.png)
|
||||
|
||||
- Jumper block to set the power source for the RTC:
|
||||
|
||||
|
@ -93,41 +78,45 @@ By default, this sample runs over a Wi-Fi connection to the internet. To use Eth
|
|||
|
||||
- Female-female header (if using RDB v1.0): To determine which version of the RDB you have, see the [MT3620 User Guide](https://docs.microsoft.com/azure-sphere/hardware/mt3620-user-guide#power-down-mode). If you have RDB v1.0, you will need to tie the PMU_EN pin low to enable the MT3620 to Power Down. Connect the female header from pin 10 on H3 (PMU_EN) to pin 2 on H4 (GND), as shown on the right side of the following image:
|
||||
|
||||
![Image showing where to insert the RTC battery on the RDB](./media/PMU_EN_low_RDB.png)
|
||||
![Image showing where to insert the RTC battery on the RDB](./media/PMU_EN_low_RDB.png)
|
||||
|
||||
- In-line USB current meter (optional): You can connect an in-line USB current meter between your RDB and your PC to measure the current consumption of the RDB. This is helpful for validating that the RDB has entered Power Down by observing the decrease in current consumption displayed on the meter.
|
||||
|
||||
**Note:** Although most USB current meters will work, get one with a data passthrough feature so that you can deploy apps and debug while it's connected. One such USB current meter is the [StarTech USB Voltage and Current Tester Kit](https://www.startech.com/Cables/USB-2.0/USB-Adapters/usb-voltage-current-tester-kit~USBAUBSCHM) (pictured below).
|
||||
|
||||
![Image showing USB current meter setup](./media/Current_Meter_Setup.jpg)
|
||||
![Image showing USB current meter setup](./media/Current_Meter_Setup.jpg)
|
||||
|
||||
**Note:** Additional on-board circuitry (the FTDI interface and so forth) is also powered from the main power supply. When the chip is placed in Power Down state, the overall current consumption of the board will not drop to the expected MT3620 Power Down levels because the FTDI consumes between 10-80mA, depending on its connection activity with the USB Host device. As such, the RDB is helpful for validating that software is correctly placing the chip in Power Down state, but is less useful for validating overall power consumption of the hardware design.
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Set up your Azure Sphere device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
1. Even if you've performed this setup previously, ensure you have Azure Sphere SDK version 21.01 or above. Open a [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview), and run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) to check. Install [the Azure Sphere SDK for Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [the Azure Sphere SDK for Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux).
|
||||
1. Even if you've performed this setup previously, ensure you have Azure Sphere SDK version 21.04 or above. Open a [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview), and run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) to check. Install [the Azure Sphere SDK for Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [the Azure Sphere SDK for Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux).
|
||||
1. Connect your Azure Sphere device to your PC by USB.
|
||||
1. Enable application development, if you have not already done so, using this command:
|
||||
|
||||
```
|
||||
azsphere device enable-development
|
||||
```
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *Powerdown_HighLevelApp* sample in the *Powerdown* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/powerdown/).
|
||||
|
||||
### Use Ethernet instead of Wi-Fi
|
||||
|
||||
By default, this sample runs over a Wi-Fi connection to the internet. To use Ethernet instead, follow the [Ethernet setup instructions](../../../ethernet-setup-instructions.md).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
**Note:**
|
||||
To test the sample, follow the instructions in the [Test power down](#test-power-down) and [Test update checks](#test-update-checks) sections below.
|
||||
|
||||
- When the MT3620 is in Power Down state, it will be unresponsive to CLI commands or attempts to deploy a new or updated image from Visual Studio and Visual Studio Code. The reset button on the development board will not work, and recovery will also not work while the board is in this state. Please see the [MT3620 Hardware Notes](https://docs.microsoft.com/azure-sphere/hardware/mt3620-hardware-notes#power-down-considerations) for more information.
|
||||
Note the following:
|
||||
|
||||
- When the MT3620 is in Power Down state, it will be unresponsive to CLI commands or attempts to deploy a new or updated image from Visual Studio and Visual Studio Code. The reset button on the development board will not work, and recovery will also not work while the board is in this state. See the [MT3620 Hardware Notes](https://docs.microsoft.com/azure-sphere/hardware/mt3620-hardware-notes#power-down-considerations) for more information.
|
||||
- After a Power Down/wake cycle, the debugger will no longer be attached to the Azure Sphere device. This means you will also no longer see debug console output after the device wakes up. As a workaround, redeploy the sample app after the device wakes up to restore debugging functionality and debug console output.
|
||||
|
||||
## Test the sample
|
||||
### Test power down
|
||||
|
||||
The device repeatedly cycles through 3 states: Start-up, Update, and Power Down.
|
||||
The device repeatedly cycles through three states: Start-up, Update, and Power Down.
|
||||
|
||||
1. Start-up
|
||||
|
||||
|
@ -143,7 +132,7 @@ The device repeatedly cycles through 3 states: Start-up, Update, and Power Down.
|
|||
- Slow - An update is available and has begun downloading
|
||||
- Steady (on but not blinking) - The download has completed and the device will reboot to apply the download.
|
||||
|
||||
See [Test Update Checks](#test-update-checks) for details.
|
||||
See the [Test update checks](#test-update-checks) section below for details.
|
||||
|
||||
1. Power Down
|
||||
|
||||
|
@ -153,32 +142,26 @@ The device repeatedly cycles through 3 states: Start-up, Update, and Power Down.
|
|||
|
||||
**Note:** The RDB has additional components that will cause it to consume much more current than a production device would when in the Power Down state. This test is only intended for observing the relative current drop to validate that your application is entering Power Down.
|
||||
|
||||
The device will stay in Power Down for `powerdownResidencyTime` seconds (the default is 10 seconds). Change this constant value in the app to configure how long the device stays in Power Down.
|
||||
The device will stay in Power Down for **powerdownResidencyTime** seconds (the default is 10 seconds). Change this constant value in the app to configure how long the device stays in Power Down.
|
||||
|
||||
After `powerdownResidencyTime` seconds, the device will wake up. You should see the reading on the current meter rise back up to approximately 0.15A.
|
||||
After **powerdownResidencyTime** seconds, the device will wake up. You should see the reading on the current meter rise back up to approximately 0.15A.
|
||||
|
||||
### Test update checks
|
||||
|
||||
When checking for updates, the app will wait until one of three events occurs:
|
||||
|
||||
1. The app receives a `SysEvent_Events_NoUpdateAvailable` event notification, indicating the update check has completed and no updates are available. In this case, the device will wait until the end of the 60 second interval and enter Power Down.
|
||||
1. The app receives a **SysEvent_Events_NoUpdateAvailable** event notification, indicating the update check has completed and no updates are available. In this case, the device will wait until the end of the 60 second interval and enter Power Down.
|
||||
|
||||
1. It receives a `SysEvent_Events_UpdateStarted` event. This means an update is available and has begun downloading. The green LED will begin to blink more slowly to indicate an update is downloading. The device will stay awake while the update downloads until one of two things occurs:
|
||||
1. It receives a **SysEvent_Events_UpdateStarted** event. This means an update is available and has begun downloading. The green LED will begin to blink more slowly to indicate an update is downloading. The device will stay awake while the update downloads until one of two things occurs:
|
||||
|
||||
- The update finishes downloading, indicated by the reception of a `SysEvent_Events_UpdateReadyForInstall` event notification. The LED stops blinking but remains on to indicate the download has completed. After approximately 2 seconds, the device will reboot to apply the update.
|
||||
- The update finishes downloading, indicated by the reception of a **SysEvent_Events_UpdateReadyForInstall** event notification. The LED stops blinking but remains on to indicate the download has completed. After approximately 2 seconds, the device will reboot to apply the update.
|
||||
|
||||
- The update has not finished downloading after `waitForUpdatesToDownloadTimerInterval` seconds have elapsed. In this case, the app will Power Down to conserve energy. For example, this might happen if an unreliable network connection is causing the download to take an excessive amount of time. The app will try to resume the download again the next time it wakes up.
|
||||
- The update has not finished downloading after **waitForUpdatesToDownloadTimerInterval** seconds have elapsed. In this case, the app will Power Down to conserve energy. For example, this might happen if an unreliable network connection is causing the download to take an excessive amount of time. The app will try to resume the download again the next time it wakes up.
|
||||
|
||||
1. An update check has not completed. This means that neither of the update event notifications (`SysEvent_Events_NoUpdateAvailable` nor `SysEvent_Events_UpdateStarted`) were received after `businessLogicCompleteTimerInterval` seconds. In this case, the app will Power Down to conserve energy and try to check for updates again the next time it wakes up.
|
||||
1. An update check has not completed. This means that neither of the update event notifications (**SysEvent_Events_NoUpdateAvailable** nor **SysEvent_Events_UpdateStarted**) were received after **businessLogicCompleteTimerInterval** seconds. In this case, the app will Power Down to conserve energy and try to check for updates again the next time it wakes up.
|
||||
|
||||
## Next steps
|
||||
|
||||
- To learn more about power management and the Power Down state on Azure Sphere, see [Manage Power Down state for Azure Sphere devices](https://docs.microsoft.com/azure-sphere/app-development/power-down).
|
||||
- For more details about Power Down that are specific to the RDB, see the [Power Down section of the MT3620 RDB User Guide](https://docs.microsoft.com/azure-sphere/hardware/mt3620-user-guide#power-down-mode).
|
||||
- To learn about hardware considerations to ensure your design can take advantage of Power Down, see [the Power Down considerations section of the MT3620 hardware notes documentation](https://docs.microsoft.com/azure-sphere/hardware/mt3620-hardware-notes#power-down-considerations).
|
||||
|
||||
## License
|
||||
|
||||
For details on license, see LICENSE.txt in this directory.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- To learn about how to use power profiles to adjust the balance between performance and energy savings, see [Set power profiles](https://docs.microsoft.com/azure-sphere/app-development/set-power-profiles).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(PrivateNetworkServices C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c echo_tcp_server.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -23,7 +23,7 @@ description: "Demonstrates how to connect an Azure Sphere device to a private ne
|
|||
|
||||
# Sample: Private network services
|
||||
|
||||
This sample application demonstrates how you can [connect an Azure Sphere device to a private network](https://docs.microsoft.com/azure-sphere/network/connect-ethernet) and [use network services](https://docs.microsoft.com/azure-sphere/network/use-network-services). It configures the Azure Sphere device to run a DHCP server and an SNTP server, and implements a basic TCP server. The steps below show how to verify this functionality by connecting your computer to this private network.
|
||||
This sample application demonstrates how you can [connect an Azure Sphere device to a private network](https://docs.microsoft.com/azure-sphere/network/connect-ethernet) and [use network services](https://docs.microsoft.com/azure-sphere/network/use-network-services). It configures the Azure Sphere device to run a DHCP server and an SNTP server, and implements a basic TCP server.
|
||||
|
||||
The DHCP and SNTP servers are managed by the Azure Sphere OS and configured by the high-level application. The servers start only upon request from the application but continue to run even after the application stops.
|
||||
|
||||
|
@ -31,61 +31,79 @@ The TCP server runs in the application process and stops when the application st
|
|||
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
|Library |Purpose |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
|log | Displays messages in the Device Output window during debugging |
|
||||
|networking | Gets and sets network interface configuration |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Gets and sets network interface configuration. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This sample will run on any supported network interface. However, it is configured by default for a private Ethernet network. If using Ethernet, before you build and run this sample you must connect and configure an Ethernet adapter to your MT3620 development board. See how to [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet) and if using an MT3620 RDB, see [add an Ethernet adapter to your development board](../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
The sample requires the following hardware:
|
||||
|
||||
To run the sample on a different network interface, modify the code that defines the global constant ``NetworkInterface`` which is found in the source file ``\PrivateNetworkServices\PrivateNetworkServices\main.c``. For example, to specify a Wi-Fi network, change the line
|
||||
```c
|
||||
static const char NetworkInterface[] = "eth0";
|
||||
```
|
||||
* [Seeed MT3620 Development Kit](https://aka.ms/azurespheredevkits) or other hardware that implements the [MT3620 Reference Development Board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) design.
|
||||
|
||||
to
|
||||
```c
|
||||
static const char NetworkInterface[] = "wlan0";
|
||||
```
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Set up your Azure Sphere device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
`azsphere device enable-development`
|
||||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *PrivateNetworkServices* sample in the *PrivateNetworkServices* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/privatenetworkservices/).
|
||||
1. Configure the sample for your network interface. This sample will run on any supported network interface. However, it is configured by default for a private Ethernet network.
|
||||
|
||||
- To use Ethernet, you must connect and configure an Ethernet adapter to your MT3620 development board. See [Connect Azure Sphere to Ethernet](https://docs.microsoft.com/azure-sphere/network/connect-ethernet) and [add an Ethernet adapter to your development board](../../HardwareDefinitions/mt3620_rdb/EthernetWiring.md).
|
||||
|
||||
- To use a different network interface, change the value of the global constant **NetworkInterface** in the source file `PrivateNetworkServices\main.c`. For example, to specify a Wi-Fi network, change "eth0" to "wlan0":
|
||||
|
||||
`static const char NetworkInterface[] = "eth0";`
|
||||
|
||||
is changed to
|
||||
|
||||
`static const char NetworkInterface[] = "wlan0";`
|
||||
|
||||
1. If you want the sample to set and retreive the sizes of the socket send/receive buffers, add code that uses the standard **getsockopt** and **setsockopt** functions.
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
Connect your computer to the same private network to which you connected your device. If using an Ethernet private network, attach an Ethernet cable from the Ethernet adapter on the device to the Ethernet connection on your computer.
|
||||
This sample configures the Azure Sphere device to run a DHCP server and an SNTP server, and implements a basic TCP server.
|
||||
|
||||
If your computer is managed by policies that prevent it from being connected to multiple network interfaces at once, you may need to disable other network interfaces while using this sample.
|
||||
Complete the following steps to test this functionality:
|
||||
|
||||
1. Connect your computer to the same private network to which you connected your device. If using an Ethernet private network, attach an Ethernet cable from the Ethernet adapter on the device to the Ethernet connection on your computer.
|
||||
1. If your computer is managed by policies that prevent it from being connected to multiple network interfaces at once, you may need to disable other network interfaces while using this sample.
|
||||
1. Perform the following operations, which are described in the sections below:
|
||||
|
||||
- [Test the device's DHCP server](#test-the-devices-dhcp-server).
|
||||
- [Test the device's SNTP server](#test-the-devices-sntp-server).
|
||||
- [Test the application's TCP server](#test-the-applications-tcp-server).
|
||||
|
||||
**Note:** The sample uses the IP address range 192.168.100.xxx. If you have another network adapter that uses the same range, you will need to either modify the sample or disable the other network adapter temporarily.
|
||||
|
||||
### Test the device's DHCP server
|
||||
#### Test the device's DHCP server
|
||||
|
||||
Open a command prompt on your computer and type `ipconfig`. You should see that the DHCP server has issued an IP address in the 192.168.100.xxx range to your computer for its network connection:
|
||||
|
||||
|
@ -103,14 +121,15 @@ Open a command prompt on your computer and type `ipconfig`. You should see that
|
|||
|
||||
You could also find, download, and use a DHCP client test tool (not provided) on your computer to inspect the DHCP server response in more detail — such as to look at the NTP server address(es) returned.
|
||||
|
||||
### Test the device's SNTP server
|
||||
#### Test the device's SNTP server
|
||||
|
||||
1. Ensure the Azure Sphere device is connected to the internet via a different network interface (for example, Wi-Fi if using private Ethernet), so that it can obtain time settings from a public NTP server. The SNTP server won't respond until it knows the current time.
|
||||
1. Open a command prompt on your computer and type the following command:
|
||||
|
||||
**w32tm /stripchart /computer:192.168.100.10 /dataonly /samples:1**
|
||||
`w32tm /stripchart /computer:192.168.100.10 /dataonly /samples:1`
|
||||
|
||||
This command invokes the [Windows Time tool](https://docs.microsoft.com/windows-server/networking/windows-time-service/windows-time-service-tools-and-settings) to query the device's SNTP server and to display the calculated difference between your computer's time and the device's time:
|
||||
|
||||
```sh
|
||||
Tracking 192.168.100.10 [192.168.100.10:123].
|
||||
Collecting 1 samples.
|
||||
|
@ -119,6 +138,7 @@ You could also find, download, and use a DHCP client test tool (not provided) on
|
|||
```
|
||||
|
||||
1. If the SNTP server doesn't respond, then you may see the following output. Check that the app is running and that the Azure Sphere device is connected to the internet.
|
||||
|
||||
```sh
|
||||
Tracking 192.168.100.10 [192.168.100.10:123].
|
||||
Collecting 1 samples.
|
||||
|
@ -126,7 +146,7 @@ You could also find, download, and use a DHCP client test tool (not provided) on
|
|||
14:16:50, error: 0x800705B4
|
||||
```
|
||||
|
||||
### Test the application's TCP server
|
||||
#### Test the application's TCP server
|
||||
|
||||
Ensure that the sample app is still running on your Azure Sphere device. Then, on your computer, use a terminal application to open a raw TCP connection to the Azure Sphere application's TCP server at 192.168.100.10 port 11000. You can open this connection with a third-party terminal application such as PuTTY (using a "raw" connection type), or with the built-in Telnet client for Windows.
|
||||
|
||||
|
@ -134,17 +154,18 @@ To use the built-in Telnet client for Windows:
|
|||
|
||||
1. Open Control Panel and click **Programs and Features** > **Turn Windows features on or off** to launch the **Windows Features** window.
|
||||
1. Ensure **Telnet Client** is selected and click **OK**.
|
||||
1. Open a command prompt and type **telnet 192.168.100.10 11000**.
|
||||
1. Open a command prompt and type `telnet 192.168.100.10 11000`.
|
||||
|
||||
The characters that you type will appear in the debug console in Visual Studio—either immediately or when you enter a newline—showing that they have been received by the example TCP server on the MT3620. When you enter a newline, the MT3620 sends the following string back to the terminal:
|
||||
|
||||
```sh
|
||||
Received "<last-received-line>"
|
||||
```
|
||||
`Received "<last-received-line>"`
|
||||
|
||||
The sample server can hold 15 characters. If another character arrives before a newline has been received, the existing characters will be discarded and the newly-arrived character will be placed at the start of the buffer. The Output window in Visual Studio will display:
|
||||
|
||||
`Input data overflow. Discarding 15 characters.`
|
||||
|
||||
#### Socket buffer size
|
||||
To retrieve and configure the socket send and receive buffer sizes, use the standard `getsockopt` and `setsockopt` functions.
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For network troubleshooting, see [Troubleshoot network problems](https://docs.microsoft.com/azure-sphere/network/troubleshoot-network-problems).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(SPI_LSM6DS3_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -23,29 +23,45 @@ description: "Demonstrates how to use the SPI (Serial Peripheral Interface) with
|
|||
|
||||
# Sample: SPI high-level app
|
||||
|
||||
This sample demonstrates how to use [SPI with Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/spi) in a high-level application. The sample displays data from an ST LSM6DS3 accelerometer connected to an MT3620 development board through SPI (Serial Peripheral Interface). The accelerometer data is retrieved every second and is displayed by calling the [Applibs SPI APIs](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-spi/spi-overview).
|
||||
This sample demonstrates how to use [SPI with Azure Sphere](https://docs.microsoft.com/azure-sphere/app-development/spi) in a high-level application.
|
||||
|
||||
The sample uses the following Azure Sphere libraries:
|
||||
The sample displays data from an ST LSM6DS3 accelerometer connected to an MT3620 development board through the Serial Peripheral Interface (SPI). The accelerometer data is retrieved every second and is displayed by calling the [Applibs SPI APIs](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-spi/spi-overview).
|
||||
|
||||
|Library |Purpose |
|
||||
|---------|---------|
|
||||
|log | Displays messages in the Device Output window during debugging |
|
||||
|spi | Manages SPI interfaces |
|
||||
| [EventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events |
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|-----------|---------|
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [spi](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-spi/spi-overview) | Manages the Serial Peripheral Interfaces (SPIs). |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This sample requires the following hardware:
|
||||
|
||||
- Azure Sphere MT3620 board.
|
||||
- [ST LSM6DS3](https://www.st.com/en/mems-and-sensors/lsm6ds3.html).
|
||||
- We recommend a breadboard because this sample requires wiring from multiple sources to the same pin.
|
||||
- Jumper wires to connect the boards.
|
||||
- An Azure Sphere MT3620 board
|
||||
- [ST LSM6DS3 inertial measurement unit (IMU)](https://www.st.com/en/mems-and-sensors/lsm6ds3.html)
|
||||
- A breadboard (recommended because this sample requires wiring from multiple sources to the same pin)
|
||||
- Jumper wires to connect the boards
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Set up your Azure Sphere device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
1. Even if you've performed this set up previously, ensure you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Even if you've performed this set up previously, ensure you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Upgrade the Azure Sphere SDK for [Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux) as needed.
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
|
@ -53,11 +69,11 @@ The sample uses the following Azure Sphere libraries:
|
|||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *SPI_LSM6DS3_HighLevelApp* sample in the *SPI* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/spi/).
|
||||
|
||||
## Set up the ST LSM6DS3 connections
|
||||
### Set up the ST LSM6DS3 connections
|
||||
|
||||
Make the following connections between the ST LSM6DS3 and MT3620 dev boards. Make sure that power is disconnected while you wire the boards.
|
||||
|
||||
**Note:** By default, this sample is configured to use an external LSM6DS3, and isn't configured to use the onboard sensors found on some development boards, such as the LSM6DS0 on the Avnet Starter Kit. This sample uses ISU1 on the MT3620 board; however, you can use another ISU by adjusting the wiring, the code, and the application manifest.
|
||||
**Note:** By default, this sample is configured to use an external ST LSM6DS3 and isn't configured to use the onboard sensors found on some development boards, such as the ST LSM6DS0 on the Avnet Starter Kit. This sample uses ISU1 on the MT3620 board; however, you can use another ISU by adjusting the wiring, the code, and the application manifest.
|
||||
|
||||
![Connection diagram for ST LSM6DS3 and MT3620](./media/spiwiring.png)
|
||||
|
||||
|
@ -65,7 +81,7 @@ Make the following connections between the ST LSM6DS3 and MT3620 dev boards. Mak
|
|||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
When you run the application, it reads the WHO_AM_I register from the accelerometer. This should return the known value 0x69, which confirms that the MT3620 can successfully communicate with the accelerometer. If this fails, verify that the devices are wired correctly, and that the application opened the correct SPI interface. For details on the registers, see the [ST LSM6DS3 data sheet](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf).
|
||||
|
||||
|
@ -73,6 +89,11 @@ After displaying the initial values, the application configures the acceleromete
|
|||
|
||||
To test the accelerometer data:
|
||||
|
||||
1. Keep the device still, and observe the accelerometer output in the **Output Window**. Once the data from the CTRL3_C register is displayed, the output should repeat every second.
|
||||
1. Keep the device still, and observe the accelerometer output in the **Device Output** window. Once the data from the CTRL3_C register is displayed, the output should repeat every second.
|
||||
|
||||
1. Turn the accelerometer upside down and observe the updated data in the **Output Window**. The vertical acceleration should change from approximately +1g to approximately -1g.
|
||||
1. Turn the accelerometer upside down and observe the updated data in the **Device Output** window. The vertical acceleration should change from approximately +1g to approximately -1g.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(SystemTime C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -23,59 +23,64 @@ description: "Demonstrates how to manage the system time and the hardware real-t
|
|||
|
||||
# Sample: System time
|
||||
|
||||
This sample application demonstrates how to manage the system time and the hardware [RTC (real time clock)](https://docs.microsoft.com/azure-sphere/app-development/rtc). The system time is changed whenever button A is pressed, and it is synchronized to the hardware RTC whenever button B is pressed.
|
||||
This sample application demonstrates how to manage the system time and the hardware real-time clock (RTC). The system time is changed whenever button A is pressed, and it is synchronized to the hardware RTC whenever button B is pressed.
|
||||
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
|Library |Purpose |
|
||||
|----------|---------|
|
||||
|log | Displays messages in the Device Output window during debugging |
|
||||
|gpio | Digital input for buttons |
|
||||
|rtc | Synchronizes the hardware RTC with the current system time |
|
||||
|networking | Gets and sets network interface configuration |
|
||||
| [EventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for timer events |
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [eventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages digital input for buttons. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Gets and sets the network interface configuration. |
|
||||
| [rtc](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-rtc/rtc-overview) | Synchronizes the hardware real-time clock (RTC) with the current system time. |
|
||||
|
||||
## Contents
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Describes how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This sample requires the following hardware:
|
||||
|
||||
- Azure Sphere MT3620 board
|
||||
- CR2032 coin cell battery
|
||||
- CR2032 coin cell battery (not installed)
|
||||
- J3 jumper is set to the 3v3 position (pins 2 and 3 of J3 are connected)
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../HardwareDefinitions/README.md). Battery support may differ for your hardware; check with the manufacturer for details.
|
||||
|
||||
You must perform these steps before you continue:
|
||||
## Setup
|
||||
|
||||
- Connect your Azure Sphere device to your computer.
|
||||
- Ensure that the coin cell battery is not installed and the J3 jumper is set to the 3v3 position. For more information, see the [MT3620 development board user guide](https://docs.microsoft.com/azure-sphere/hardware/mt3620-user-guide#power-supply).
|
||||
- Complete the steps to [install Azure Sphere](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
- Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
1. Ensure that the coin cell battery is not installed and the J3 jumper is set to the 3v3 position (pins 2 and 3 of J3 are connected). For more information, see the [MT3620 development board user guide](https://docs.microsoft.com/azure-sphere/hardware/mt3620-user-guide#power-supply).
|
||||
1. Set up your Azure Sphere device and development environment as described in the [Azure Sphere documentation](https://docs.microsoft.com/azure-sphere/install/overview).
|
||||
1. Even if you've performed this set up previously, ensure you have Azure Sphere SDK version 21.04 or above. Open a [Azure Sphere command-line tool](https://docs.microsoft.com/azure-sphere/reference/overview), and run [**azsphere show-version**](https://docs.microsoft.com/azure-sphere/reference/azsphere-show-version) to check. Install [the Azure Sphere SDK for Windows](https://docs.microsoft.com/azure-sphere/install/install-sdk) or [the Azure Sphere SDK for Linux](https://docs.microsoft.com/azure-sphere/install/install-sdk-linux).
|
||||
1. Connect your Azure Sphere device to your PC by USB.
|
||||
1. Enable application development, if you have not already done so, using this command:
|
||||
|
||||
`azsphere device enable-development`
|
||||
`azsphere device enable-development`
|
||||
|
||||
## Prepare the sample
|
||||
|
||||
1. Even if you've performed this set up previously, ensure you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *SystemTime* sample in the *SystemTime* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/systemtime/).
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
To test the sample, perform the following operations, which are described in the sections below:
|
||||
|
||||
Perform the following tests to test the sample.
|
||||
- [Change the system time without updating the hardware RTC](#change-the-system-time-without-updating-the-hardware-rtc).
|
||||
- [Change the system time and store it in the hardware RTC](#change-the-system-time-and-store-it-in-the-hardware-rtc).
|
||||
- [Remove power from the hardware RTC](#remove-power-from-the-hardware-rtc).
|
||||
- [Power the hardware RTC from a battery](#power-the-hardware-rtc-from-a-battery).
|
||||
|
||||
### Change the system time without updating the hardware RTC
|
||||
|
||||
|
@ -123,3 +128,9 @@ Perform the following tests to test the sample.
|
|||
1. Wait at least ten seconds and then plug the cable back into the device.
|
||||
1. Wait at least five more seconds and then restart the application.
|
||||
1. Verify that the system time was maintained after power loss.
|
||||
|
||||
## Next steps
|
||||
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- To learn more about the real-time clock (RTC), see [Manage time and use the RTC](https://docs.microsoft.com/azure-sphere/app-development/rtc).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(UART_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -32,43 +32,61 @@ This sample does the following:
|
|||
- Displays the data received from the UART in the Output Window of Visual Studio or Visual Studio Code.
|
||||
- Causes an LED to blink when data is received from the UART.
|
||||
|
||||
This sample uses these Applibs APIs:
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [UART](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-uart/uart-overview) | Manages UART connectivity on the device |
|
||||
| [GPIO](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages button A on the device |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging |
|
||||
| [EventLoop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invoke handlers for IO and timer events |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for I/O and timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages button A on the device. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the Device Output window during debugging. |
|
||||
| [uart](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-uart/uart-overview) | Manages UART connectivity on the device. |
|
||||
|
||||
## Contents
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Describes how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md). You may also have to set the hardware differently.
|
||||
|
||||
This sample requires the following hardware:
|
||||
|
||||
- Azure Sphere MT3620 board
|
||||
- An Azure Sphere MT3620 board
|
||||
|
||||
On header 2 (marked H2) on the lower left side of the board:
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md). You may also have to set the hardware differently.
|
||||
|
||||
- Connect pins 1 and 3 (ISU0 RXD and ISU0 TXD) of H2 with a jumper header. These are the first two pins on the left side of the header, circled in red in the figure.
|
||||
- Make a loopback connection on header 2 (marked H2) on the lower left side of the board by connecting pins 1 and 3 (ISU0 RXD and ISU0 TXD) of H2 with a jumper. Pins 1 and 3 are the first two pins on the left side of the header, circled in red in the image.
|
||||
|
||||
![RDB with header pins circled](./media/MT3620UartJumper.png)
|
||||
|
||||
## Prepare the sample
|
||||
- As an alternative to using the loopback connection, you can connect the UART to an external serial-USB interface board and use a client such as Telnet or Putty to transmit and receive bytes. This solution has been tested using the Adafruit FTDI Friend serial-to-USB adapter with the following wiring connections.
|
||||
|
||||
1. Even if you've performed this setup previously, ensure you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
![Connections for MT3620 and FTDI Friend](./media/MT3620_FTDI-Friend-2.png)
|
||||
|
||||
| FTDI Friend | Azure Sphere MT3620 |
|
||||
| ----------- | ------------------- |
|
||||
| GND | H2 Pin 2 |
|
||||
| TX | H2 Pin 1 |
|
||||
| RX | H2 Pin 3 |
|
||||
| RTS | H2 Pin 5 |
|
||||
| CTS | H2 Pin 7 |
|
||||
|
||||
**Putty settings:**
|
||||
|
||||
- Local echo = force on
|
||||
- Local line editing = force on
|
||||
|
||||
## Setup
|
||||
|
||||
1. Even if you've performed this setup previously, ensure you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) as needed.
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
|
@ -80,53 +98,23 @@ On header 2 (marked H2) on the lower left side of the board:
|
|||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
Press button A on the board. This sends 13 bytes over the UART connection and displays the sent and received text in the Device Output window, if you're using Visual Studio or Visual Studio Code:
|
||||
Press button A on the board. This sends 13 bytes over the UART connection and displays the sent and received text in the **Device Output** window, if you're using Visual Studio or Visual Studio Code:
|
||||
|
||||
`Sent 13 bytes over UART in 1 calls`
|
||||
`UART received 12 bytes: 'Hello world!'`
|
||||
`UART received 1 bytes: '`
|
||||
`'`
|
||||
`Sent 13 bytes over UART in 1 calls.`
|
||||
`UART received 12 bytes: 'Hello world!'.`
|
||||
`UART received 1 bytes: '`
|
||||
`'.`
|
||||
|
||||
All the received text might not appear at once, and it might not appear immediately.
|
||||
The received text might not appear all at the same time and it might not appear immediately.
|
||||
|
||||
The message may contain more bytes than read() can return, depending on the Azure Sphere device (on the MT3620 this is often 12 bytes). The message may need to be assmbled asynchronously over a sequence of read() calls as a result, as illustrated at [this point](https://github.com/Azure/azure-sphere-samples/blob/7232fcb52a493b7def65c50ea93ab9bb73e283c2/Samples/WifiSetupAndDeviceControlViaBle/AzureSphereApp/WifiSetupAndDeviceControlViaBle/message_protocol.c#L214) in the WifiSetupAndDeviceControlViaBle sample.
|
||||
The message may contain more bytes than the **read** function can return, depending on the Azure Sphere device (on the MT3620 this is often 12 bytes). The message may need to be assembled asynchronously over a sequence of **read** calls as a result, as illustrated at [this point](https://github.com/Azure/azure-sphere-samples/blob/7232fcb52a493b7def65c50ea93ab9bb73e283c2/Samples/WifiSetupAndDeviceControlViaBle/AzureSphereApp/WifiSetupAndDeviceControlViaBle/message_protocol.c#L214) in the WifiSetupAndDeviceControlViaBle sample.
|
||||
|
||||
If it is temporarily not possible to send further bytes, such as when transmitting larger buffers, write() may fail with errno of EAGAIN. You can handle this by registering an EPOLLOUT event handler, as illustrated at [this point](https://github.com/Azure/azure-sphere-samples/blob/7232fcb52a493b7def65c50ea93ab9bb73e283c2/Samples/WifiSetupAndDeviceControlViaBle/AzureSphereApp/WifiSetupAndDeviceControlViaBle/message_protocol.c#L276) in the WifiSetupAndDeviceControlViaBle sample.
|
||||
If it is temporarily not possible to send further bytes, such as when transmitting larger buffers, the **write** function may fail with errno of **EAGAIN**. You can handle this by registering an **EPOLLOUT** event handler, as illustrated at [this point](https://github.com/Azure/azure-sphere-samples/blob/7232fcb52a493b7def65c50ea93ab9bb73e283c2/Samples/WifiSetupAndDeviceControlViaBle/AzureSphereApp/WifiSetupAndDeviceControlViaBle/message_protocol.c#L276) in the WifiSetupAndDeviceControlViaBle sample.
|
||||
|
||||
As an alternative to using the loopback connection, you can connect the UART to an external serial-USB interface board, and transmit and receive bytes using a client such as Telnet or Putty. We tested this solution using the Adafruit FTDI Friend serial to USB adapter, with the wiring connections listed below.
|
||||
## Next steps
|
||||
|
||||
![Connections for MT3620 and FTDI Friend](./media/MT3620_FTDI-Friend-2.png)
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>FTDI Friend</th>
|
||||
<th>Azure Sphere MT3620</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GND</td>
|
||||
<td>H2 Pin 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TX</td>
|
||||
<td>H2 Pin 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RX</td>
|
||||
<td>H2 Pin 3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RTS</td>
|
||||
<td>H2 Pin 5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CTS</td>
|
||||
<td>H2 Pin 7</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Putty settings:
|
||||
|
||||
- Local echo = force on
|
||||
- Local line editing = force on
|
||||
- For an overview of Azure Sphere, see [What is Azure Sphere](https://docs.microsoft.com/azure-sphere/product-overview/what-is-azure-sphere).
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For information about how UARTs can be used in high-level applications, see [Use UARTs in high-level applications](https://docs.microsoft.com/azure-sphere/app-development/uart).
|
||||
|
|
|
@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.10)
|
|||
|
||||
project(Wifi_HighLevelApp C)
|
||||
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.01")
|
||||
azsphere_configure_api(TARGET_API_SET "8")
|
||||
azsphere_configure_tools(TOOLS_REVISION "21.04")
|
||||
azsphere_configure_api(TARGET_API_SET "9")
|
||||
|
||||
add_executable(${PROJECT_NAME} main.c eventloop_timer_utilities.c)
|
||||
target_link_libraries(${PROJECT_NAME} applibs gcc_s c)
|
||||
|
|
|
@ -23,69 +23,56 @@ description: "Demonstrates how to connect to a Wi-Fi network and check the netwo
|
|||
|
||||
# Sample: Wi-Fi high-level app
|
||||
|
||||
This sample application demonstrates how to connect to a Wi-Fi network and check the network status on an MT3620 device. After you configure the sample with your Wi-Fi network settings, you can use the buttons on the device to do the following:
|
||||
This sample application demonstrates how to connect to a Wi-Fi network and check the network status on an MT3620 device.
|
||||
|
||||
BUTTON_1 cycles through commands on the example Wi-Fi network in this order:
|
||||
Button A (BUTTON_1) is used by the sample to perform Wi-Fi network-management operations, such as adding and enabling a Wi-Fi network. Button B (BUTTON_2) displays network-related information such as the device's network status. Each button press executes a particular operation on the device.
|
||||
|
||||
1. Adds the network.
|
||||
1. Enables the network.
|
||||
1. Disables the network.
|
||||
1. Duplicates the network.
|
||||
1. Deletes the network.
|
||||
|
||||
BUTTON_2 does the following:
|
||||
|
||||
1. Displays the network status of the device.
|
||||
1. Displays the network diagnostic information.
|
||||
1. Lists the stored Wi-Fi networks on the device.
|
||||
1. Starts a network scan.
|
||||
1. Lists the available Wi-Fi networks.
|
||||
|
||||
The sample displays the stored and scanned networks based on their SSID, security type, and RSSID, and removes duplicates. Therefore, the output of the equivalent CLI commands `azsphere device wifi list`and `azsphere device wifi scan` might be different from the sample's output.
|
||||
The sample displays the stored and scanned networks based on their SSID, security type, and RSSID, and removes duplicates. Therefore, the output of the equivalent CLI commands **azsphere device wifi list** and **azsphere device wifi scan** might be different from the sample's output.
|
||||
|
||||
The sample uses the following Azure Sphere libraries.
|
||||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| [gpio.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages button A and LED 1 on the device. |
|
||||
| [wificonfig.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-wificonfig/wificonfig-overview) | Manages Wi-Fi configuration on the device. |
|
||||
| [networking.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Manages the network configuration of the device. |
|
||||
| [log.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the IDE device output window during debugging.
|
||||
| [eventloop.h](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events |
|
||||
| [eventloop](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-eventloop/eventloop-overview) | Invokes handlers for timer events. |
|
||||
| [gpio](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-gpio/gpio-overview) | Manages button A and LED 1 on the device. |
|
||||
| [log](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-log/log-overview) | Displays messages in the IDE device output window during debugging. |
|
||||
| [networking](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-networking/networking-overview) | Manages the network configuration of the device. |
|
||||
| [wificonfig](https://docs.microsoft.com/azure-sphere/reference/applibs-reference/applibs-wificonfig/wificonfig-overview) | Manages Wi-Fi configuration on the device. |
|
||||
|
||||
## Contents
|
||||
|
||||
| File/folder | Description |
|
||||
|-------------|-------------|
|
||||
| main.c | Sample source file. |
|
||||
| app_manifest.json |Sample manifest file. |
|
||||
| CMakeLists.txt | Contains the project information and produces the build. |
|
||||
| CMakeSettings.json| Configures CMake with the correct command-line options. |
|
||||
|launch.vs.json |Tells Visual Studio how to deploy and debug the application.|
|
||||
| README.md | This readme file. |
|
||||
|.vscode |Contains settings.json that configures Visual Studio Code to use CMake with the correct options, and tells it how to deploy and debug the application. |
|
||||
| File/folder | Description |
|
||||
|-----------------------|-------------|
|
||||
| `app_manifest.json` | Application manifest file, which describes the resources. |
|
||||
| `CMakeLists.txt` | CMake configuration file, which Contains the project information and is required for all builds. |
|
||||
| `CMakeSettings.json` | JSON file for configuring Visual Studio to use CMake with the correct command-line options. |
|
||||
| `launch.vs.json` | JSON file that tells Visual Studio how to deploy and debug the application. |
|
||||
| `LICENSE.txt` | The license for this sample application. |
|
||||
| `main.c` | Main C source code file. |
|
||||
| `README.md` | This README file. |
|
||||
| `.vscode` | Folder containing the JSON files that configure Visual Studio Code for building, debugging, and deploying the application. |
|
||||
| `HardwareDefinitions` | Folder containing the hardware definition files for various Azure Sphere boards. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Access to a WPA2 (Wi-Fi Protected Access II), an open Wi-Fi, or an EAP-TLS network is required.
|
||||
The sample requires the following:
|
||||
|
||||
If the configured network is an EAP-TLS network, make sure that the Root CA certificate, the client certificate, and the private key are already
|
||||
installed on the device before you run the EAP-TLS portion of this sample.
|
||||
- An Azure Sphere device
|
||||
|
||||
If you don't have certificates, follow the steps in [How to generate certificates for testing](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/Certificates/Cert_HighLevelApp/get-certificates.md) to create the certificates. You can install them in either of the following ways:
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
|
||||
- Use the **azsphere device certificate add** command, as described in [Store the certificates using the CLI](https://docs.microsoft.com/azure-sphere/network/eap-tls-cert-acquisition#store-the-certificates-using-the-cli).
|
||||
- Build and run the [Cert_HighLevelApp sample](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/Certificates/Cert_HighLevelApp) but exit before the BUTTON_1 press that deletes the certificates.
|
||||
- Access to a WPA2 (Wi-Fi Protected Access II), an open Wi-Fi, or an EAP-TLS network.
|
||||
|
||||
The sample requires the following hardware:
|
||||
- If the network is an EAP-TLS network, make sure that the Root CA certificate, the client certificate, and the private key are already installed on the device before you set up the sample for EAP-TLS.
|
||||
|
||||
- Azure Sphere device
|
||||
If you don't have certificates, follow the steps in [How to generate certificates for testing](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/Certificates/Cert_HighLevelApp/get-certificates.md) to create the certificates. You can install them in either of the following ways:
|
||||
|
||||
**Note:** By default, this sample targets [MT3620 reference development board (RDB)](https://docs.microsoft.com/azure-sphere/hardware/mt3620-reference-board-design) hardware, such as the MT3620 development kit from Seeed Studios. To build the sample for different Azure Sphere hardware, change the Target Hardware Definition Directory in the CMakeLists.txt file. For detailed instructions, see the [README file in the HardwareDefinitions folder](../../../HardwareDefinitions/README.md).
|
||||
- Use the **azsphere device certificate add** command, as described in [Store the certificates using the CLI](https://docs.microsoft.com/azure-sphere/network/eap-tls-cert-acquisition#store-the-certificates-using-the-cli).
|
||||
- Build and run the [Cert_HighLevelApp sample](https://github.com/Azure/azure-sphere-samples/tree/master/Samples/Certificates/Cert_HighLevelApp) but exit before the BUTTON_1 press that deletes the certificates.
|
||||
|
||||
## Prepare the sample
|
||||
## Setup
|
||||
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.01 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) if needed.
|
||||
1. Even if you've performed this set up previously, ensure that you have Azure Sphere SDK version 21.04 or above. At the command prompt, run **azsphere show-version** to check. Install [the Azure Sphere SDK](https://docs.microsoft.com/azure-sphere/install/install-sdk) if needed.
|
||||
1. Connect your Azure Sphere device to your computer by USB.
|
||||
1. Enable application development, if you have not already done so, by entering the following line at the command prompt:
|
||||
|
||||
|
@ -93,38 +80,61 @@ The sample requires the following hardware:
|
|||
|
||||
1. Clone the [Azure Sphere samples](https://github.com/Azure/azure-sphere-samples) repository and find the *WiFi_HighLevelApp* sample in the *WiFi* folder or download the zip file from the [Microsoft samples browser](https://docs.microsoft.com/samples/azure/azure-sphere-samples/wifi/).
|
||||
|
||||
## Add your network settings
|
||||
### Add your network settings to the sample
|
||||
|
||||
Before you can run the sample, you need to configure the app to use the settings for your network. To add your network settings to the application, make the following changes to [main.c](./main.c):
|
||||
The sample must be configured to use the settings for your network. To add your network settings, complete the following steps:
|
||||
|
||||
1. In `main.c`, search for the line `static const uint8_t sampleNetworkSsid[] = "WIFI_NETWORK_SSID";` and change `WIFI_NETWORK_SSID` to SSID of the Wi-Fi network.
|
||||
1. In `main.c`, search for the line `static const WifiConfig_Security_Type sampleNetworkSecurityType = WifiConfig_Security_Unknown;` and change `WifiConfig_Security_Unknown` to the security type of the Wi-Fi network, as specified in the following steps. For a WPA2-PSK network or an EAP-TLS network, complete additional steps.
|
||||
|
||||
- If the network is an open Wi-Fi network, set the security type to `WifiConfig_Security_Open`.
|
||||
|
||||
1. Search for the line `static const uint8_t sampleNetworkSsid[] = "WIFI_NETWORK_SSID";` and change `WIFI_NETWORK_SSID` to SSID of the Wi-Fi network.
|
||||
1. Search for the line `static const WifiConfig_Security_Type sampleNetworkSecurityType = WifiConfig_Security_Unknown;` and change `WifiConfig_Security_Unknown` to the security type of the Wi-Fi network.
|
||||
- If the network is open:
|
||||
1. Set the security type to `WifiConfig_Security_Open`.
|
||||
- If the network is a WPA2-PSK network:
|
||||
1. Set the security type to `WifiConfig_Security_Wpa2_Psk`
|
||||
|
||||
1. Set the security type to `WifiConfig_Security_Wpa2_Psk`.
|
||||
1. Search for the line `static const char *sampleNetworkPsk = "WIFI_NETWORK_PASSWORD";` and change `WIFI_NETWORK_PASSWORD` to the password of your Wi-Fi network.
|
||||
- If the network is an EAP-TLS network, you'll need an installed root CA certificate and a client certificate, as described in [prerequisites](#prerequisites).
|
||||
|
||||
- If the network is an EAP-TLS network:
|
||||
|
||||
**Note:** A root CA certificate and a client certificate must be installed, as described in [Prerequisites](#prerequisites).
|
||||
|
||||
1. Set the security type to `WifiConfig_Security_Wpa2_EAP_TLS`
|
||||
1. Search for the line `const char *rootCACertStoreIdentifier = "SmplRootCACertId";` and change `SmplRootCACertId` to the identifier of your root CA certificate. You can use the [**azsphere device certificate list**][https://docs.microsoft.com/azure-sphere/reference/azsphere-device#certificate-list] command to see the certificate IDs for all installed certificates.
|
||||
1. Search for the line `const char *rootCACertStoreIdentifier = "SmplRootCACertId";` and change `SmplRootCACertId` to the identifier of your root CA certificate. You can use the [**azsphere device certificate list**](https://docs.microsoft.com/azure-sphere/reference/azsphere-device#certificate-list) command to see the certificate IDs for all installed certificates.
|
||||
1. Search for the line `const char *clientCertStoreIdentifier = "SmplClientCertId";` and change `SmplClientCertId` to the identifier of your client certificate.
|
||||
1. Search for the line `const char *clientIdentity = "SmplClientId";` and change `SmplClientId` to your client identity.
|
||||
|
||||
**Caution:** Because certificate IDs are system-wide, an **azsphere** command or a function call that adds a new certificate can overwrite a certificate that was added by an earlier command or function call, potentially causing network connection failures. We strongly recommend that you develop clear certificate update procedures and choose certificate IDs carefully. See [Certificate IDs](https://docs.microsoft.com/azure-sphere/app-development/certstore#certificate-ids) for more information about how Azure Sphere uses certificate IDs.
|
||||
**Caution:** Because certificate IDs are system-wide, an **azsphere** command or a function call that adds a new certificate can overwrite a certificate that was added by an earlier command or function call, potentially causing network connection failures. We strongly recommend that you develop clear certificate update procedures and choose certificate IDs carefully. See [Certificate IDs](https://docs.microsoft.com/azure-sphere/app-development/certstore#certificate-ids) for more information about how Azure Sphere uses certificate IDs.
|
||||
|
||||
1. Open app_manifest.json.
|
||||
1. If the security type of the configured network is `WifiConfig_Security_Wpa2_EAP_TLS`:
|
||||
1. Add the EnterpriseWifiConfig capability in the app_manifest.json file.
|
||||
1. If you set the security type of the network to `WifiConfig_Security_Wpa2_EAP_TLS`, you must add the **EnterpriseWifiConfig** capability in the `app_manifest.json` file:
|
||||
|
||||
`"EnterpriseWifiConfig": true`
|
||||
`"EnterpriseWifiConfig": true`
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build and run this sample, follow the instructions in [Build a sample application](../../../BUILD_INSTRUCTIONS.md).
|
||||
|
||||
## Test the sample
|
||||
### Test the sample
|
||||
|
||||
The output will be displayed in the terminal window.
|
||||
The output will be displayed in the terminal window. Use the buttons on the device to cycle through several operations related to Wi-Fi networks. Each button press executes a particular operation on the device.
|
||||
|
||||
Use BUTTON_1 and BUTTON_2 as directed in the sample description, above.
|
||||
Button A (BUTTON_1) performs the following management operations in the order specified:
|
||||
|
||||
1. Adds the network.
|
||||
1. Enables the network.
|
||||
1. Disables the network.
|
||||
1. Duplicates the network.
|
||||
1. Deletes the network.
|
||||
|
||||
Button B (BUTTON_2) performs the following display and scan operations in the order specified:
|
||||
|
||||
1. Displays the network status of the device.
|
||||
1. Displays the network diagnostic information.
|
||||
1. Lists the stored Wi-Fi networks on the device.
|
||||
1. Starts a network scan.
|
||||
1. Lists the available Wi-Fi networks.
|
||||
|
||||
## Next steps
|
||||
|
||||
- To learn more about Azure Sphere application development, see [Overview of Azure Sphere applications](https://docs.microsoft.com/azure-sphere/app-development/applications-overview).
|
||||
- For an overview of Wi-Fi network connectivity, see [Networking connectivity overview](https://docs.microsoft.com/azure-sphere/network/wifi-including-ble).
|
||||
- To learn more about EAP-TLS for Wi-Fi networks, see [Use EAP-TLS](https://docs.microsoft.com/azure-sphere/network/eap-tls-overview).
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче