WSS over Wi-Fi on Amazon FreeRTOS
The document explains how to build and run Wi-Fi Simple Setup over Wi-Fi on Amazon FreeRTOS (WSSoWiFi on A:FreeRTOS). Although these instructions are based on the Esp32 Dev Kit and ESP32-WROOM-32D + ESP-32S development board, most of the package is based on A:FreeRTOS APIs and is platform agnostic. See "Platform" for information on making platform specific changes to the example.
Prerequisite
- ESP32-WROOM-32D + ESP-32S development board
- Amazon FreeRTOS 202002.00
- Wi-Fi Radio
- C development environment
- Minimum 128KB of RAM available
- Minimum 1MB of flash memory available
- Support for mbedTLS https://tls.mbed.org
- A 1P Wi-Fi provisioner. 3P provisioner is not supported yet. An Echo device is a 1P provisioner.
Setting up Environment and Run Demo
This section provides guidance on downloading and building the dependencies. It then describes how to configure, build, flash and run the WSSoWiFi A:FreeRTOS program on your Esp32 development board.
Tools required
- cmake
- python 3.7
If you do not have any of the tools mentioned above installed, install them before proceeding.
Download ESP-IDF Toolchain
Follow the ESP-IDF installation instructions.
Download FFS C packages
Download the ffs-provisionee-sdk-master package from the
developer.amazon.com.
The WSSoWiFi on A:FreeRTOS code is under the ffs_amazon_freertos
folder.
cd ffs-provisionee-sdk-master/ffs_amazon_freertos
Set The Device Configuration and Credentials
Device Configurations
Open the file ffs_amazon_freertos/espressif_app/wifi_provisionee/ffs_amazon_freertos_device_configuration.c
and set the following constants to values appropriate for you device:
const char *const FFS_DEVICE_MANUFACTURER_NAME = "Manufacturer Name";
const char *const FFS_DEVICE_MODEL_NUMBER = "Model Number";
const char *const FFS_DEVICE_SERIAL_NUMBER = "Device Serial Number";
const char *const FFS_DEVICE_PIN = "Device PIN";
const char *const FFS_DEVICE_HARDWARE_REVISION = "Hardware Revision";
const char *const FFS_DEVICE_FIRMWARE_REVISION = "Firmware Revision";
const char *const FFS_DEVICE_CPU_ID = "CPU ID";
const char *const FFS_DEVICE_DEVICE_NAME = "Device Name";
const char *const FFS_DEVICE_PRODUCT_INDEX = "Product Index";
This information is used during Wi-Fi simple setup and allows Amazon to identify your device properly.
Set Credentials
The FFS Simple Setup SDK needs to authenticate with the Amazon cloud. For development and testing, you should use device DHA material signed by a development DAK. Request a development DAK from the Amazon Frustration Free Simple Setup Developer Portal.
Please review Provisionee Manufactoring guideline for DHA process.
Once you have received your generated DHA material, open the file
ffs_amazon_freertos/espressif_app/configs/ffs_amazon_freertos_credentials.h
and paste your keys and certificate as cstrings:
#define DEVICE_PRIVATE_KEY "Paste Device DHA Private Key here"
#define DEVICE_TYPE_PUBLIC_KEY "Paste Device Type Public Key here"
#define DEVICE_PUBLIC_KEY "Paste Device DHA Public Key here"
#define DEVICE_CERTIFICATE "Paste Device DHA Certificate here"
Download and Build Amazon FreeRTOS
The reference package is based on version 202002.00 of Amazon FreeRTOS. Download this version of FreeRTOS using the following command:
git clone --branch 202002.00 https://github.com/aws/amazon-freertos.git --recurse-submodules freertos
Create build files for Amazon FreeRTOS using the following command:
cmake -S . -B build
Build the Demo and Flash Your Device
Setup the PATH
and IDF_PATH
environment variables:
export PATH=$PATH:<workspace>/ffs_amazon_freertos/freertos/vendors/espressif/esp-idf/tools
export IDF_PATH=<workspace>/ffs_amazon_freertos/freertos/vendors/espressif/esp-idf
Build the binary:
cmake --build build -j4
Build and flash the binary (This will generate the build to flash on your Espressif device):
cmake --build build -j4 --target flash
To only flash what has been built:
`idf.py flash`
If you run into a problem with the default port number used to flash to your device, you can override the default port number by using the -p port_number
command line argument. For example:
idf.py -p *your_port* flash
Refer to ESP-IDF Programming Guide to determine the port number used to flash your device.
Open the Monitor
Use the following command to reboot the board and connect to the board monitor. After reboot the FFS Wi-Fi Simple Setup process will start running. The system will print log messages to the shell.
idf.py monitor
Type ctrl+]
to quit the monitor.
Examining the Result
Review the output. If FFS Wi-Fi simple setup was successful, the system will print the following message
Ffs Wi-Fi provisionee task reached terminal state
End Ffs Wi-Fi provisionee task
Provisioning was successful.
This indicates that FFS Wi-Fi simple setup was successfully and the board is connected to the Wi-Fi network.
If the message Provisioning was successful
does not appear, FFS Wi-Fi simple setup was not successful.
In this case, example the log for the following pattern:
Response body: {"canProceed":true,"nextProvisioningState":<*NEXT_STEP*>,"nonce": ...
The log entry will indicate the provisioning step that failed.
Development
Platforms
This example and instruction are based on Esp32 Dev Kit. Running it on other platforms requires further changes.
Directed scan
The Amazon Free RTOS Wi-Fi module does not provide a mechanism for directed scans. The example implements this functional specifically for the Esp32 Dev Kit in function ffsDirectedScan
specifically for Esp32 Dev Kit. For other platforms, a new implementation of this function is necessary.
The implementation is found in libffs/src/ffs/amazon_freertos/ffs_amazon_freertos_directed_scan.c
:
#define FFS_DIRECTED_SCANNING_PLATFORM_IN_USE FFS_PLATFORM_NO_PLATFORM // -1 represents no platform
#ifdef FFS_DIRECTED_SCANNING_PLATFORM
#define FFS_DIRECTED_SCANNING_PLATFORM_IN_USE FFS_DIRECTED_SCANNING_PLATFORM
#endif
...
FFS_RESULT ffsDirectedScan(const FfsUserContext_t *userContext, const char *ssid, bool *const found)
{
#if FFS_DIRECTED_SCANNING_PLATFORM_IN_USE == FFS_PLATFORM_ESP32
return ffsDirectedScanEsp32 (userContext, ssid, found);
#else
ffsLogWarning("Unsupported directed scanning platform. Encoded SSID will not work.");
return FFS_NOT_IMPLEMENTED;
#endif
}
You can add your platform in libffs/include/ffs/amazon_freertos/ffs_amazon_freertos_platforms.h
#define FFS_PLATFORM_NO_PLATFORM -1
#define FFS_PLATFORM_ESP32 1
// Define a new platform macro with another integer here.
**#define <*your_platform*> <*number*>**
Then, add the implementation of your device to libffs/src/ffs/amazon_freertos/ffs_amazon_freertos_directed_scan.c
:
#define FFS_DIRECTED_SCANNING_PLATFORM_IN_USE FFS_PLATFORM_NO_PLATFORM // -1 represents no platform
#ifdef FFS_DIRECTED_SCANNING_PLATFORM
#define FFS_DIRECTED_SCANNING_PLATFORM_IN_USE FFS_DIRECTED_SCANNING_PLATFORM
#endif
...
FFS_RESULT ffsDirectedScan(const FfsUserContext_t *userContext, const char *ssid, bool *const found)
{
#if FFS_DIRECTED_SCANNING_PLATFORM_IN_USE == FFS_PLATFORM_ESP32
return ffsDirectedScanEsp32 (userContext, ssid, found);
**#elif FFS_DIRECTED_SCANNING_PLATFORM_IN_USE == <*your_platform*>
<*your_implementation*>**
#else
ffsLogWarning("Unsupported directed scanning platform. Encoded SSID will not work.");
return FFS_NOT_IMPLEMENTED;
#endif
}
Finally, define FFS_DIRECTED_SCANNING_PLATFORM
as <*your_platform*>
macro by editing ffs_amazon_freertos/CMakefile.txt
:
...
message(INFO "Creating build files for Wifi Provisionee Application")
### Edit here
# Specify platform. This macro is used in ffsDirectedScan. For the meaning of the values, refer to libffs/include/ffs_amazon_freertos_platforms.h
**add_definitions( -DFFS_DIRECTED_SCANNING_PLATFORM=<*your_platform*> )**
# Add wifi provisionee cmake subdirectory
add_subdirectory(espressif_app/wifi_provisionee)
...
File Structures
The libffs
folder, excluding the ffsDirectedScan
function, is expected to be portable over Amazon FreeRTOS platforms.
However, all the files not inside the libffs folder can differ from one platform to the other. The way Amazon FreeRTOS
boots on a platform is different. Therefore, if you are trying to use a different platform with this reference implementation,
keep in mind it will require changes to the ffsDirectedScan
files and require you to create application files that work with your
platform. For application files that work with espressif Esp32, look inside the espressif_app folder.
Main Function
The main function app_main()
is located at ffs_amazon_freertos/espressif_app/wifi_provisionee/main.c
.
int app_main( void )
{
// Initialize ESP board and FreeRTOS system.
...
// Run runFrustrationFreeSetup
**xTaskCreate****(runFrustrationFreeSetup, "FrustrationFreeSetup", FFS_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, &ffsTaskHandle);**
// Process the result of runFrustrationFreeSetup
xEventGroupWaitBits(ffsProvisioningResultEventGroup, FFS_PROVISIONING_RESULT_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
xSemaphoreTake(ffsProvisioningResultSemaphore, portMAX_DELAY);
FFS_PROVISIONING_RESULT result = ffsProvisioningResult;
xSemaphoreGive(ffsProvisioningResultSemaphore);
vEventGroupDelete(ffsProvisioningResultEventGroup);
vSemaphoreDelete(ffsProvisioningResultSemaphore);
if (result == FFS_PROVISIONING_RESULT_PROVISIONED)
{
ffsLogInfo("Provisioning was successful.");
}
else
{
ffsLogInfo("Provisioning was not successful.");
// Here, you should add a manual method to provision the device.
}
return 0;
}
The function runFrustrationFreeSetup
drives the FFS Wi-Fi Simple Setup process by calling ffsProvisionDevice(&provisioningArguments)
.
Parameters like DEVICE_PRIVATE_KEY
were set at above (see Set Credentials).
You can override these parameters by using pointers to your secure storage rather than the constants.
static void runFrustrationFreeSetup(void *args) {
FfsProvisioningArguments_t provisioningArguments = {
.privateKey = DEVICE_PRIVATE_KEY,
.privateKeySize = sizeof(DEVICE_PRIVATE_KEY),
.privateKeyType = FFS_KEY_TYPE_PEM,
.publicKey = DEVICE_PUBLIC_KEY,
.publicKeySize = sizeof(DEVICE_PUBLIC_KEY),
.publicKeyType = FFS_KEY_TYPE_PEM,
.deviceTypePublicKey = DEVICE_TYPE_PUBLIC_KEY,
.deviceTypePublicKeySize = sizeof(DEVICE_TYPE_PUBLIC_KEY),
.deviceTypePublicKeyType = FFS_KEY_TYPE_PEM,
.certificate = DEVICE_CERTIFICATE,
.certificateSize = sizeof(DEVICE_CERTIFICATE),
.certificateType = FFS_KEY_TYPE_PEM,
};
FFS_PROVISIONING_RESULT result = ffsProvisionDevice(&provisioningArguments);
// Send the result
xSemaphoreTake(ffsProvisioningResultSemaphore, portMAX_DELAY);
ffsProvisioningResult = result;
xSemaphoreGive(ffsProvisioningResultSemaphore);
xEventGroupSetBits(ffsProvisioningResultEventGroup, FFS_PROVISIONING_RESULT_BIT);
vTaskDelete(ffsTaskHandle);
}
If you need to do anything after the FFS process, you can add code to the end of the app_main()
function.
New Files
If you want to create any new file under espressif_app/wifi_provisionee
, make sure the source files are under espressif_app/wifi_provisionee/src
and the header files are under espressif_app/wifi_provisionee/include
. Otherwise, espressif_app/wifi_provisionee/CMakeLists.txt
needs modification.
Document History
Version | Date | Author | Description |
---|---|---|---|
1.02 | July 30, 2020. | Amazon. | General Availability |
Last updated: Nov 04, 2020