Amazon FreeRTOSはじめました

とうとうAmazon FreeRTOSにも手を出しました。

# 環境

デバイス

* ESP32-DevKitC

開発環境

* Ubuntu 18.04 (on VirtualBox)

# チュートリアルやってみました

基本的にはドキュメントのとおりです。

Getting Started with the Espressif ESP32-DevKitC and the ESP-WROVER-KIT
https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html

## IAMユーザーの準備

手順の途中でIoTのThingを作ったり証明書を作ったりする手順があります。これらの手順は便利ツールが用意されているのでかんたんにできますが、便利ツールの実行に内部ではAWS CLIが使われているため、IAMユーザー（アクセスキー、シークレットアクセスキー）が必要です。必要な権限は

* AmazonFreeRTOSFullAccess
* AWSIoTFullAccess

## 開発環境の準備

### ツールチェインの導入

Linuxの場合はこちらの手順です。

https://docs.espressif.com/projects/esp-idf/en/v3.3/get-started-cmake/linux-setup.html

```
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing cmake ninja-build ccache
```

```
mkdir -p ~/esp
cd ~/esp
tar -xzf ~/Downloads/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
```

パスの設定をする。`~/.profile`に以下を追記

```
export PATH="$HOME/esp/xtensa-esp32-elf/bin:$PATH"
alias get_esp32='export PATH="$HOME/esp/xtensa-esp32-elf/bin:$PATH"'
```

sudoなしで`/dev/ttyUSB0`にアクセスする権限を追加

```
sudo usermod -a -G dialout $USER
```

### CMakeの導入

https://cmake.org/download/ から`cmake-3.16.2-Linux-x86_64.sh`をダウンロードします。
その後インストール。インストール先は`~/cmake-3.16.2-Linux-x86_64`にしました。

```
chmod +x cmake-3.16.2-Linux-x86_64.sh
./cmake-3.16.2-Linux-x86_64.sh
```

パスの設定をする。`~/.profile`に以下を追記

```
export PATH="$HOME/cmake-3.16.2-Linux-x86_64/bin/:$PATH"
```

## Amazon FreeRTOSのダウンロード

`release`ブランチをclone

```
git clone https://github.com/aws/amazon-freertos.git --recurse-submodules -b release
```

## AWS CLIのインストール

pipでインストールできるのは知ってましたが、他のインストール方法もドキュメント上あったのご参考までに。

https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html

```
curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
unzip awscli-bundle.zip
sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws
```

`aws configure`して、アクセスキー、シークレットアクセスキー、リージョンを設定する。

pythonの必要ライブラリーをインストール

```
pip install tornado nose --user
pip install boto3 --user
```

`<amazon-freertos>/tools/aws_config_quick_start/configure.json`に設定を書き込む。
`afr_source_dir`にはデフォルト値が入ってるのでそのまま（相対パス指定）で問題ありませんでした。
その後、以下のコマンド

```
cd <amazon-freertos>/tools/aws_config_quick_start
python SetupAWS.py setup
```

## ビルドしてフラッシュ

さていよいよビルドしてフラッシュです。

ビルド

```
cd <amazon-freertos>
cmake -DVENDOR=espressif -DBOARD=esp32_wrover_kit -DCOMPILER=xtensa-esp32 -S . -B build
```

ドキュメント上、`your-build-directory`とありますが、後続のコメントはこれが`build`である前提で書かれてますのでご注意ください。

```
cd build
make all -j4
```

消して、書いて、モニターする。

```
cd <amazon-freertos>
./vendors/espressif/esp-idf/tools/idf.py erase_flash flash monitor -B build
```

ドキュメント中は`-p /dev/ttyUSB1`とあって、私の環境では、`/dev/ttyUSB0`でした。更にこの`-p`オプションがなかっても検出してくれるようなので、指定なしでも動きました。


めでたしめでたし。

# デモをGreengrass接続のものに変更

ここに書いてある方法でできます。
https://docs.aws.amazon.com/freertos/latest/userguide/gg-demo.html

* AWS IoTのマネジメントコンソール画面で、`モノ`の中にあるFreeRTOSデバイスにアタッチした`証明書`にアタッチしている`ポリシー`の`ポリシードキュメント`に、greengrassへのアクセス許可を追加
* Greengrassグループのロールに`AmazonS3FullAccess `と`AWSIoTFullAccess`を追加。
* FreeRTOSの`モノ`を、Greengrassグループの`デバイス`に追加。
* Greengrassグループの`サブスクリプション`でソースを`FreeRTOS`、ターゲットを`IoT Cloud`にする
* ソースコードの修正

```c:<amazon-freertos>/vendors/espressif/boards/esp32/aws_demos/config_files/aws_demo_config.h
#define CONFIG_MQTT_DEMO_ENABLED
define CONFIG_GREENGRASS_DISCOVERY_DEMO_ENABLED
```

# Greengrass接続のデモを、センサー値収集に変更

鋭意作成中
動作未確認

```diff:demos/greengrass_connectivity/aws_greengrass_discovery_demo.c
+ include "esp_adc_cal.h"

-#define ggdDEMO_MQTT_MSG_DISCOVERY             "{\"message\":\"Hello #%lu from Amazon FreeRTOS to Greengrass Core.\"}"
+#define ggdDEMO_MQTT_MSG_DISCOVERY             "{\"value\":\"%lu\"}"

+        esp_adc_cal_characteristics_t *adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
+        esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, ESP_ADC_CAL_VAL_DEFAULT_VREF, adc_chars);
+
+        uint32_t voltage;
+        IotLogInfo( "%lu", ( long unsigned int )voltage);
+        esp_adc_cal_get_voltage(ADC1_CHANNEL_6, adc_chars, &voltage);


-        xPublishInfo.payloadLength = ( uint32_t ) sprintf( cBuffer, ggdDEMO_MQTT_MSG_DISCOVERY, ( long unsigned int ) ulMessageCounter ); /*lint !e586 sprintf can be used for specific demo. */
+        xPublishInfo.payloadLength = ( uint32_t ) sprintf( cBuffer, ggdDEMO_MQTT_MSG_DISCOVERY, ( long unsigned int ) voltage );
```