ラズパイとAWS IoTを使った見守りシステム自作で学んだこと（7）ラズパイの自動起動の設定

[（５）paho.mqttでセンサーデータをラズパイからAWS IoTにPublish](https://qiita.com/nsaito9628/items/db43b1e854a3cc95df1a)と[（６）ラズパイでイベント録画してS3にupload](https://qiita.com/nsaito9628/items/8126fda477d61d542414)で説明したPython codesをラズパイで自動起動する為の設定です。

ラズパイのコマンドラインからcrontabで環境変数と自動実行スクリプトを書込みます。.profileへは環境変数を直接書き込みます。

## crontabで書込み

起動時に展開する内容をコマンドラインからcron_mod.confファイルにまとめて、crontabで書き込みます。

### ラズパイからAWS IoTへのPublishで使う環境変数
[モノの登録と証明書の発行](https://qiita.com/nsaito9628/items/2ff6ab6d471537270e68#%E3%83%A2%E3%83%8E%E3%81%AE%E7%99%BB%E9%8C%B2%E3%81%A8%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E7%99%BA%E8%A1%8C)で設定したモノの名前、証明書、鍵、エンドポイントを読み込んでcron_mod.confに書き出します。

モノの名前がCatBed1の場合、これらの情報はモノを登録して証明書を作成した際に/home/userに以下のようなファイル名で出力されます。

```sh
/home/user
・
・
┣ /cert
┃ ┣ CatBed1-certificate.pem.crt
┃ ┣ CatBed1-private.pem.key
┃ ┣ AmazonRootCA1.pem
┃ ┣ end_point.json
┃ ┣ create-thing.json
┃ ┣ create-keys-and-certificate.json
┃ ・
```


もう一つ[（２）見守りProjectの設計で出力した./src/cert/iot_prov_config](https://qiita.com/nsaito9628/items/da402829316549853d0f#srccertiot_prov_config)のパラメーターも読み込んでcron_mod.confに書き込みます。

```sh:iot_prov_config
THING_NAME=CatBed1
TOPIC_DETECT=CatBed1/count
S3BUCKET=neko-mimamori
AWS_AccountId=${your AWS account id}  
SENSOR_NO=1
PREFIX_IN=Place1
TRIGGER_SELECT=1
```

#### HOST_ENDPOINT：AWS IoTのエンドポイント
```sh
echo HOST_ENDPOINT=$(jq -r '.endpointAddress' < ./end_point.json) >> cron_mod.conf
```
#### CLIENTCERT：クライアント証明書
```sh
echo CLIENTCERT=./cert/${THING_NAME}-certificate.pem.crt >> cron_mod.conf
```
#### CLIENTKEY：クライアント証明書の秘密鍵
```sh
echo CLIENTKEY=./cert/${THING_NAME}-private.pem.key >> cron_mod.conf
```
#### CACERT：クライアント証明書の作成時に署名した認証局の証明書
```sh
echo CACERT=./cert/AmazonRootCA1.pem >> cron_mod.conf
```
#### TOPIC_DETECT：mqtt topic
```sh
echo TOPIC_DETECT="${THING_NAME}/count" >> cron_mod.conf
```
#### SENSOR_NO：センサータイプ
```sh
echo SENSOR_NO=$(cat ./iot_prov_config | grep SENSOR_NO | awk -F'=' '{print $2}') >> cron_mod.conf
```

### イベント録画してS3にuploadするのに使う環境変数

ラズパイのコマンドラインからaws configureを実行済みの環境では、.awsの下にcredentialsとconfigというdirectoryが作られていて情報が格納されています。

boto3の利用に必要なcredentialはcredentialsに、regionはconfigから読み取ります。

```sh
/home/user
・
・
┣ /.aws
┃ ┣ credentials
┃ ┣ config
┃ ・
```
録画のupload先S3Bucket名は[./src/cert/iot_prov_config](https://qiita.com/nsaito9628/items/da402829316549853d0f#srccertiot_prov_config)から読み取ります。

以下順番にcron_mod.confに書き出します。

#### ACCESS_KEY：IAM userのCredential
```sh
echo ACCESS_KEY=$(cat ../.aws/credentials | grep aws_access_key_id | awk -F'= ' '{print $2}') >> cron_mod.conf
```
#### SECRET_KEY：IAM userのCredential
```sh
echo SECRET_KEY=$(cat ../.aws/credentials | grep aws_secret_access_key | awk -F'= ' '{print $2}') >> cron_mod.conf
```
#### REGION：モノを登録したAWSのregion
```sh
echo REGION=$(cat ../.aws/config | grep region | awk -F'= ' '{print $2}') >> cron_mod.conf
```
#### S3BUCKET：イベント映像upload先のS3Bucket名
```sh
echo S3BUCKET=$(cat ./iot_prov_config | grep S3BUCKET | awk -F'=' '{print $2}') >> cron_mod.conf
```
#### PREFIX_IN：ラズパイ設置場所の番号でPlace1～Place4に固定(修正予定)
```sh
echo PREFIX_IN=$(cat ./iot_prov_config | grep PREFIX_IN | awk -F'=' '{print $2}') >> cron_mod.conf
```
#### SENSOR_NO：センサータイプ
```sh
echo SENSOR_NO=$(cat ./iot_prov_config | grep SENSOR_NO | awk -F'=' '{print $2}') >> cron_mod.conf
```
#### TRIGGER_SELECT：イベント録画のトリガータイプ
```sh
echo TRIGGER_SELECT=$(cat ./iot_prov_config | grep TRIGGER_SELECT | awk -F'=' '{print $2}') >> cron_mod.conf
```



### 自動起動設定
ラズパイ起動時にmain.pyとemr_rec.pyを自動起動させる設定をします。

```sh
echo @reboot python ~/main.py >> cron_mod.conf
echo @reboot python ~/emr_rec.py >> cron_mod.conf
```
もう一つ、コマンドラインから手動実行する為に環境変数のみを.profileに追記したかったので、起動時に.profileを実行させます。開発時に必要だった設定でそのまま残してあります。
```sh
echo @reboot ~/.profile >> cron_mod.conf
```
### crontabで書込み実行
起動時に展開する内容を書き込みます。
```sh
crontab ./cron_mod.conf
```

## .profileへの環境変数の書込み
「@ reboot」で始まる自動起動設定以外の内容をcrontab ./cron_mod.confを実行する前に.profileにも書き込みます。こちらはconf等中間ファイルを介さず直接書込みます。

```sh
echo export HOST_ENDPOINT=$(jq -r '.endpointAddress' < ./end_point.json) >> ../.profile
echo export CACERT=./cert/AmazonRootCA1.pem >> ../.profile
echo export CLIENTCERT=./cert/${THING_NAME}-certificate.pem.crt >> ../.profile
echo export CLIENTKEY=./cert/${THING_NAME}-private.pem.key >> ../.profile
echo export  >> ../.profile
echo export TOPIC_DETECT=$(cat ./iot_prov_config | grep TOPIC_DETECT | awk -F'=' '{print $2}') >> ../.profile
echo export  >> ../.profile
echo export ACCESS_KEY=$(cat ../.aws/credentials | grep aws_access_key_id | awk -F'= ' '{print $2}') >> ../.profile
echo export SECRET_KEY=$(cat ../.aws/credentials | grep aws_secret_access_key | awk -F'= ' '{print $2}') >> ../.profile
echo export REGION=$(cat ../.aws/config | grep region | awk -F'= ' '{print $2}') >> ../.profile
echo export SENSOR_NO=$(cat ./iot_prov_config | grep SENSOR_NO | awk -F'=' '{print $2}') >> ../.profile
echo export S3BUCKET=$(cat ./iot_prov_config | grep S3BUCKET | awk -F'=' '{print $2}') >> ../.profile
echo export PREFIX_IN=$(cat ./iot_prov_config | grep PREFIX_IN | awk -F'=' '{print $2}') >> ../.profile
echo export TRIGGER_SELECT=$(cat ./iot_prov_config | grep TRIGGER_SELECT | awk -F'=' '{print $2}') >> ../.profile
```

## モノの登録から自動起動登録まで一括実行
以上説明した手順は[（４）モノの登録と証明書の発行](https://qiita.com/nsaito9628/items/2ff6ab6d471537270e68#%E3%83%A2%E3%83%8E%E3%81%AE%E7%99%BB%E9%8C%B2%E3%81%A8%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AE%E7%99%BA%E8%A1%8C)で説明したcliコマンドと併せてシェルスクリプト化して/home/user/Monitoring-system-with-Raspberry-Pi-and-AWS/cert/iot_prov.shにまとめてあります。

連続投稿の最後に予定している「（１０） 以上の内容を一部シェルスクリプトにまとめてcliで連続実装」の中で実行します。

```sh:iot_prov.sh
#!/bin/bash

#/home/pi/ --> mkdir cert && cd cert && cp iot_prov.sh
sudo apt install jq -y
sudo apt update -y
sudo apt upgrade -y

#THING NAME (is same as Project Name) and AWS account ID
THING_NAME=$(cat ./iot_prov_config | grep THING_NAME | awk -F'=' '{print $2}')
AccountId=$(cat ./iot_prov_config | grep AWS_AccountId | awk -F'=' '{print $2}')

# create the thing
aws iot create-thing --thing-name ${THING_NAME} | tee create-thing.json
 
# create and download the keys and device certificate
aws iot create-keys-and-certificate --certificate-pem-outfile ${THING_NAME}-certificate.pem.crt --public-key-outfile ${THING_NAME}-public.pem.key --private-key-outfile ${THING_NAME}-private.pem.key --set-as-active | tee create-keys-and-certificate.json  
 
# attach the certificate to the thing
CERT_ARN=$(jq -r '.certificateArn' < create-keys-and-certificate.json)
aws iot attach-thing-principal --thing-name ${THING_NAME} --principal ${CERT_ARN}  

# create the thing policy
policy_stm="\"Statement\": [
      {
        \"Effect\": \"Allow\",
        \"Action\": \"iot:Connect\",
        \"Resource\": \"arn:aws:iot:ap-northeast-1:${AccountId}:client/\${iot:Connection.Thing.ThingName}\",
        \"Condition\": {
          \"Bool\": { \"iot:Connection.Thing.IsAttached\": \"true\" }
        }
      },
      {
        \"Effect\": \"Allow\",
        \"Action\": \"iot:Publish\",
        \"Resource\": \"arn:aws:iot:ap-northeast-1:${AccountId}:topic/\${iot:Connection.Thing.ThingName}/*\"
      },
      {
        \"Effect\": \"Allow\",
        \"Action\": \"iot:Subscribe\",
        \"Resource\": \"arn:aws:iot:ap-northeast-1:${AccountId}:topicfilter/\${iot:Connection.Thing.ThingName}/count\"
      }
    ]"

aws iot create-policy --policy-name "${THING_NAME}_subscribe" --policy-document "{\"Version\": \"2012-10-17\",${policy_stm}}"
 
# attach policy to the certificate
aws iot attach-policy --policy-name ${THING_NAME}_subscribe --target ${CERT_ARN}
 
# download the amazon root ca
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem
 
# find out what endpoint we need to connect to
echo $(aws iot describe-endpoint --endpoint-type iot:Data-ATS --region ap-northeast-1) >> end_point.json

crontab -r

# creating cron_mod.conf
echo HOST_ENDPOINT=$(jq -r '.endpointAddress' < ./end_point.json) >> cron_mod.conf
echo CACERT=./cert/AmazonRootCA1.pem >> cron_mod.conf
echo CLIENTCERT=./cert/${THING_NAME}-certificate.pem.crt >> cron_mod.conf
echo CLIENTKEY=./cert/${THING_NAME}-private.pem.key >> cron_mod.conf
echo >> cron_mod.conf
echo TOPIC_DETECT="${THING_NAME}/count" >> cron_mod.conf
echo >> cron_mod.conf
echo ACCESS_KEY=$(cat ../.aws/credentials | grep aws_access_key_id | awk -F'= ' '{print $2}') >> cron_mod.conf
echo SECRET_KEY=$(cat ../.aws/credentials | grep aws_secret_access_key | awk -F'= ' '{print $2}') >> cron_mod.conf
echo REGION=$(cat ../.aws/config | grep region | awk -F'= ' '{print $2}') >> cron_mod.conf
echo SENSOR_NO=$(cat ./iot_prov_config | grep SENSOR_NO | awk -F'=' '{print $2}') >> cron_mod.conf
echo S3BUCKET=$(cat ./iot_prov_config | grep S3BUCKET | awk -F'=' '{print $2}') >> cron_mod.conf
echo PREFIX_IN=$(cat ./iot_prov_config | grep PREFIX_IN | awk -F'=' '{print $2}') >> cron_mod.conf
echo TRIGGER_SELECT=$(cat ./iot_prov_config | grep TRIGGER_SELECT | awk -F'=' '{print $2}') >> cron_mod.conf

echo >> cron_mod.conf
echo @reboot ~/.profile >> cron_mod.conf
echo @reboot python ~/main.py >> cron_mod.conf
echo @reboot python ~/emr_rec.py >> cron_mod.conf

# adding .profile
echo >> ../.profile
echo export HOST_ENDPOINT=$(jq -r '.endpointAddress' < ./end_point.json) >> ../.profile
echo export CACERT=./cert/AmazonRootCA1.pem >> ../.profile
echo export CLIENTCERT=./cert/${THING_NAME}-certificate.pem.crt >> ../.profile
echo export CLIENTKEY=./cert/${THING_NAME}-private.pem.key >> ../.profile
echo export  >> ../.profile
echo export TOPIC_DETECT=$(cat ./iot_prov_config | grep TOPIC_DETECT | awk -F'=' '{print $2}') >> ../.profile
echo export  >> ../.profile
echo export ACCESS_KEY=$(cat ../.aws/credentials | grep aws_access_key_id | awk -F'= ' '{print $2}') >> ../.profile
echo export SECRET_KEY=$(cat ../.aws/credentials | grep aws_secret_access_key | awk -F'= ' '{print $2}') >> ../.profile
echo export REGION=$(cat ../.aws/config | grep region | awk -F'= ' '{print $2}') >> ../.profile
echo export SENSOR_NO=$(cat ./iot_prov_config | grep SENSOR_NO | awk -F'=' '{print $2}') >> ../.profile
echo export S3BUCKET=$(cat ./iot_prov_config | grep S3BUCKET | awk -F'=' '{print $2}') >> ../.profile
echo export PREFIX_IN=$(cat ./iot_prov_config | grep PREFIX_IN | awk -F'=' '{print $2}') >> ../.profile
echo export TRIGGER_SELECT=$(cat ./iot_prov_config | grep TRIGGER_SELECT | awk -F'=' '{print $2}') >> ../.profile

crontab ./cron_mod.conf
```

## 次回
[(8) template.yamlで定義するAWSリソースの説明とsam deployに続きます。](https://qiita.com/nsaito9628/items/312112486ce61ba396ae)

## 追記

#### 修正　2022.10.25
IoT policyをRegion、AWSアカウント、topicで明示されたResource名で縛られたpolicyに修正しました。