Pythonを勉強しよう! 変数名の命名規則
Python初心者の備忘録.....
今回は、自身スキル不足で命名規則を詳しく知らなかった....情けない。 プログラミング言語では下記の命名規則が広く使われているみたいです。
命名規則
記法 | 規則説明 | 記述例 |
---|---|---|
キャメル記法 | 複数の単語を連結。先頭文字は小文字。後に続く単語の先頭は大文字で記述。単語と単語の間に空白や連結記号は使わない。 | serverData, faceDetect |
パスカル記法 | 数の単語を連結。すべての単語の先頭文字を大文字で記述。単語と単語の間に空白や連結記号は使わない。 | ServerData,, FaceDetect |
スネーク記法 | 複数の単語を連結。単語すべて小文字で記述し、単語の間に「_」アンダーバーを記述 | server_data,, face_detect |
感想
いろいろソースコードを掲載したが、筆者自身どの記法にも合わない。まー、全く意識していないから仕方ないか。。。。
今度からは意識して見やすいコードを書くことを心がけることにします。
Pythonを勉強しよう! シングル/ダブル/トリプルクォーテーションについて
Python初心者の備忘録.....
今回は文字型には、「シングルクォーテーション」、「ダブルクォーテーション」、「トリプルクォーテーション」があり、このあたり勉強してします。
シングルクォーテーション/ダブルクォーテーション
「’」:シングルクォーテーション、「"」ダブルクォーテーションのどちらを使っても良いです。
文字列にしたい先頭と最後に記述します。
以下のケースでは「Atom」まで文字列になってしまうため、ダブルクォーテーションを使用する。
全文文字列にならない
name = 'Atom's tech blog'
全文文字列にする
name = "Atom's tech blog"
参考
ダブルクォーテーションが内側にある場合は、シングルクォーテーション、ダブルクォーテーションで囲む。
print('<a href="http://www.example.com"></a>') print("<a href=\"http://www.example.com\"></a>") # <a href="http://www.example.com"></a> # <a href="http://www.example.com"></a>
トリプルクォーテーション
下記のように文字列が継続して改行している場合でも、文字列の続きとして扱われます。
改行している文字列自体もそのままの状態で扱われるため、複数行として表示します。
name ='''Atom's tech blog test proglam''' print(name) # Atom's tech blog # test # proglam
Pythonを勉強しよう! 文字列から数値への変換
Python初心者の備忘録.....
今回は数値の文字列から数値へ変換することを勉強してみます。
数字の文字列を整数(int)、浮動小数点(floar)へ変換
Pythonで数字の文字列を整数値にはint()、小数点ありの数字文字列を浮動小数点に変換するにはfloat()を使用します。
Pythonは整数値と文字列の数字は直接演算できません。
そこで文字列の数字を整数値に変換することで演算が可能となります。
print(int('500')) print(float('100.1')) print(float('500')) # 500 # 100.1 #500.0
エラーになるケース
文字列に小数点がある場合
print(int('500.1')) #raceback (most recent call last): # File "<stdin>", line 1, in <module> #ValueError: invalid literal for int() with base 10: '500.1'
文字列のため、数字間に「,」(カンマ)が入るケースがあるので、これもエラーとなる
print(int('50,010')) #raceback (most recent call last): # File "<stdin>", line 1, in <module> #ValueError: invalid literal for int() with base 10: '50,010'
回避するには文字列から「,」カンマを削除しよう。 replace()メソッドで削除(空に置換)変換可能です。
print(int('50,010'.replace(',', ''))) #50010
2、8、10、16進数文字列を10進数に変換
前回も説明を書いていたが再度。こちらもint()を使用することで可能です。
第一パラメータには2、8、10、16進数の文字列。第二パラメータには基数「2、8、10、16」
# 変数xに文字列の代入 x = '100' # 2進数に変換し、結果を出力 print(int(x,2)) # 8進数に変換し、結果を出力 print(int(x,8)) # 10進数に変換し、結果を出力 print(int(x,10)) # 16進数に変換し、結果を出力 print(int(x,16)) #4 #64 #100 #256
下記の16進数の文字列の場合は、大文字、小文字どちらでも変換可能で、「0x」の文字列でも問題なし。
# 変数に文字列の代入 big = 'FF' small ='ff' str_hex = '0xff' # 16進数に変換し、結果を出力 print(int(big,16)) print(int(small,16)) print(int(str_hex,16)) print(int(str_hex,0)) # 255 # 255 # 255 # 255
数字の文字列を変換して演算
演算するときに数値と数値の演算は可能ですが、数値と文字列の演算はできません。
よく使われるケースは、ログに出力した結果が数値の文字列の場合があり、そのままの取得したデータで演算するとエラーが発生します。
その場合は、文字列を数値に変換して演算を行います。
下記サンプルソースはlog_valueが文字列のため、int()で10進数の整数に変換し、forでループして演算しています。
log_value = '1' for count in range(5): print( count + int(log_value,10)) #1 #2 #3 #4 #5
Pythonを勉強しよう! 扱うデータの種類とn進数の変換
Python初心者の備忘録.....
今回はPythonで扱う基本データ型とn進数の変換について勉強してみます。
Pythonで扱う基本データ型
データの種類型 | 型 | 値の例 | 説明 |
---|---|---|---|
整数型 | int型 | 123 , 3 , -8 | intとはinteger(整数)として、小数点を含まないものを示す |
整数型 | float型 | 3.14159, -0.34 | floatとは浮動小数点数として、小数点を含むものを示す |
文字列型 | str型 | ポイント, point | 文字列は「'」(シングルクォーテーション )、「"」(ダブルクォーテーション)で囲んだ文字列 |
論理型 | bool型 | True,False | 真を示すときは「True」偽を示すときは「False」の2つ値を使う |
上記のint型の値の例は、10進数で表しています。数字の前に「-」(マイナス)を入れることで負の値として扱われます。
プログラミングでは10進数だけではなく、2進数、8進数、16進数をよく使用します。
次は2進数、8進数、16進数の書き方を説明します。
2進数、8進数、16進数の書き方
進数 | 表記例 | 説明 |
---|---|---|
2進数 | 0b100,0B111000 | 先頭に「0b」または「0B」をつけます |
8進数 | 0o100,0O111000 | 先頭に「0o」または「0O」をつけます |
16進数 | 0x6,0x1f | 先頭に「0x」または「0X」をつけます |
書き方はわかったが、よく使いたくなるのが10進数で表した数値を「2進数、8進数、16進数」に変換する方法です。
2進数、8進数、16進数へ変換
bin(),oct(),hex()を使用
10進数の整数値を、2進数、8進数、16進数へ変換します。
変換する進数 | 関数 | 入力パラメータ説明 | 出力型 |
---|---|---|---|
2進数 | bin() | bin関数のパラメータ値に10進数 | 文字列型 |
8進数 | oct() | oct関数のパラメータ値に10進数 | 文字列型 |
16進数 | hex() | hex関数のパラメータ値に10進数 | 文字列型 |
# 変数xに10(10進数)を代入 x = 10 # 2進数に変換し、結果を出力 print(bin(x)) # 8進数に変換し、結果を出力 print(oct(x)) # 16進数に変換し、結果を出力 print(hex(x)) # 0b1010 # 0o12 # 0xa
format()を使用
10進数の整数値を、2進数、8進数、16進数へ変換します。
変換する進数 | 関数 | 入力パラメータ説明 | 出力型 |
---|---|---|---|
2進数 | format() | format関数の第一パラメータ1に10進数の数値、第二パラメータに'b' | 文字列型 |
8進数 | format() | format関数の第一パラメータ1に10進数の数値、第二パラメータに'o' | 文字列型 |
16進数 | format() | format関数の第一パラメータ1に10進数の数値、第二パラメータに'x' | 文字列型 |
# 変数xに10(10進数)を代入 x = 10 # 2進数に変換し、結果を出力 print(format(x,'b')) # 8進数に変換し、結果を出力 print(format(x,'o')) # 16進数に変換し、結果を出力 print(format(x,'x')) # 1010 # 12 # a
10進数へ変換
int()を使用
文字列の2,8,10,16進数を10進数に変換します。
変換する進数 | 関数 | 入力パラメータ説明 | 出力型 |
---|---|---|---|
2進数 | int() | format関数の第一パラメータに文字列の2進数の数字、第二パラメータに2 | 整数型 |
8進数 | int() | format関数の第一パラメータに文字列の8進数の数字、第二パラメータに6 | 整数型 |
10進数 | int() | format関数の第一パラメータに文字列の10進数の数字、第二パラメータに10 | 整数型 |
16進数 | int() | format関数の第一パラメータに文字列の16進数の数字、第二パラメータに16 | 整数型 |
# 変数xに文字列の代入 x = '100' # 2進数に変換し、結果を出力 print(int(x,2)) # 8進数に変換し、結果を出力 print(int(x,8)) # 10進数に変換し、結果を出力 print(int(x,10)) # 16進数に変換し、結果を出力 print(int(x,16)) # 4 # 64 # 100 # 256
小数点を含む場合は、小数点以下が切り捨てられる
print(int( 3.1415)) #3
AWS IoT Device Shadowを使ってみた!(Part4)
本記事は、最終目標である遠隔からDevice Shadow機能を使ってIoT Device制御をまとめたものです。 なお、4つの記事の中で今回は 下記の「 Part4 」です
主な全体記事の流れです。
■ Part1 : API Gatewayから起動するLambda関数の作成
■ Part3 : AWS IoT Deviceとshadow作成
■ Part4 : iPhoneアプリ作成 と 遠隔Camera起動確認
- 注意
- AWS構成図
- Appプロジェクト環境
- Alamofireインストール
- アプリソースコード
- App起動
- App → IoT Core Shadow 動作
- IoT Device shadow起動とiOS App制御
- 最後に
iPhoneアプリも初心者で......。
プロジェクトの作り方や、viewイメージで作成したボタンをソースコード接続や、ボタンをタップしたメソッド生成方法..... などは割愛します。
注意
2020/12/17からboto3でIoT CoreのDevice ShadowにアクセスするとSSLエラーが発生する事象が出ています。
AWSのcertifiライブラリが「2020.12.5」にバージョンアップされたことが原因らしく、下記サイトを参考に応急処置を行い、問題なく動作できることを確認しました。
その時のエラーメッセージです。
{"errorMessage": "SSL validation failed for https://data.iot.ap-northeast-1.amazonaws.com/things/RaspberryPi_Camera/shadow [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
応急処置方法のサイトをリンク貼り付けます。
certifiライブラリ「2020.11.8」版をMACで作成し、その「 layer.zip 」ファイルをAWS Lambdaコンソールから「 レイヤー追加 」、対象となるLambda関数に適用でいけました。
正式にはIoT CoreのATSエンドポイント指定することで対応可能なようです。 すみません。自分は確認していません。ご了承ください。
AWS構成図
赤点線で囲んだ箇所を今回作成します。
Appプロジェクト環境
使用するinterfaceは「 Storyboard 」、言語(Language)は「 Swift 」を使用します。
Alamofireインストール
Alamofireとは
AlamofireはiOSアプリでネットワーク通信(HTTP、REST APIなど)を簡単に使うことができるライブラリです。ネイティブのネットワーク通信のライブラリを使用するより簡単に実装ができるようです。
アプリ作成初心者にはおすすめらしいので「 Alamofire 」を使用します。
インストール
いろいろなサイトでインストール方法が掲載されていますが、一番簡単な方法でやります。
Xcodeの「 File 」 -> 「 Swift Packages 」 -> 「 Add Package Dependency.... 」を選択します。
Alamofireのgitリポジトリアドレスを入力 「 https://github.com/Alamofire/Alamofire 」を入力し、「 Next 」ボタンをクリックします。
「 Branch 」のラジオボタンで選択し、「 Next 」ボタンをクリックします。
Alamofireのチェックボックスにチェックを入れて、「 Next 」ボタンをクリックします。
Alamofireが表示されている状態を確認します。
これでAlamofireがインストールできました。
アプリソースコード
冒頭でも説明しましたが、viewイメージで作成したボタンをソースコード接続や、ボタンをタップなどのメソッド生成方法の図解は割愛します。
Main.storyboardファイルにボタン、テキストをGUI上で配置しておいてください。
ソースファイルのコピペだけではエラーとなりますので、ご注意ください。
ViewController.swift
単純な「ON」と「OFF」ボタンを配置し、タップ動作を入れているだけのシンプル? な初心者作成ソースコードです。
import UIKit import Alamofire class ViewController: UIViewController { @IBOutlet weak var buttonON: UIButton! @IBOutlet weak var buttonOff: UIButton! // AWS API Gateywayで設定し生成されたCamera ONのPOST URL // ■ xxxxxxxxxxxは各自の環境に合わせてください。 var awsApiGatewayURLOn = "https://xxxxxxxxxx.execute-api.xxxxxxxxxxxxxxx.amazonaws.com/development/test?camera=1" // AWS API Gateywayで設定し生成されたCamera OFF POST URL // ■ xxxxxxxxxxxは各自の環境に合わせてください。 var awsApiGatewayURLOff = "https://xxxxxxxxxxxxx.execute-api.ap-xxxxxxxxxxxx.amazonaws.com/development/test?camera=0" // AWS API Gateywayで生成したAPIキー // ■ xxxxxxxxxxxは各自の環境に合わせてください。 var awsApiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" override func viewDidLoad() { super.viewDidLoad() } override func viewDidAppear(_ animated: Bool) { // ボタンONの形を変える buttonON.frame = CGRect(x:25,y:131,width:330,height:150) buttonON.layer.masksToBounds = false buttonON.layer.cornerRadius = 10.0 // ボタンの影 buttonON.layer.shadowOffset = CGSize(width: 3, height: 3)// 影の方向 buttonON.layer.shadowOpacity = 0.4 // 影の濃さ buttonON.layer.shadowRadius = 7 // 影のぼかし量 // ボタンOFFの形を変える buttonOff.frame = CGRect(x:25,y:300,width:330,height:150) buttonOff.layer.masksToBounds = false buttonOff.layer.cornerRadius = 10.0 // ボタンの影 buttonOff.layer.shadowOffset = CGSize(width: 3, height: 3) buttonOff.layer.shadowOpacity = 0.4 buttonOff.layer.shadowRadius = 7 } // ONボタンを押した状態の時に起動 @IBAction func buttonON_touchdown(_ sender: UIButton) { // 色をsystemGray3に変える buttonON.backgroundColor = UIColor.systemGray3 } // OFFボタンを押して離した時に起動 @IBAction func buttonON_touchUp(_ sender: UIButton) { // 色をsystemYellowに変える buttonON.backgroundColor = UIColor.systemYellow // AWS Gatewayアクセス CameraON URL AF.request(awsApiGatewayURLOn,method: .post,headers: ["X-API-KEY":awsApiKey]).response { response in debugPrint(response)} } // OFFボタンを押した状態の時に起動 @IBAction func buttonOFF_touchdown(_ sender: UIButton) { // 色をsystemGray3に変える buttonOff.backgroundColor = UIColor.systemGray3 } // OFFボタンを押して離した時に起動 @IBAction func buttonOFF_touchUp(_ sender: UIButton) { // 色をsystemTealに変える buttonOff.backgroundColor = UIColor.systemTeal // AWS Gatewayアクセス CameraOFF URL AF.request(awsApiGatewayURLOff,method: .post,headers: ["X-API-KEY":awsApiKey]).response { response in debugPrint(response)} } }
App起動
Xcodeでビルドし、起動するとON/OFFの2つのボタンを表示します。
下記イメージはMAC上で表示したSimulatorです。
実際に動作させるときは、iphoneにAppを転送しています。
AWS設定やIoT Deviceソースコード、Lambda関数ソースコード、iOS Appソースコードの説明は以上です。
これでiPhoneからIoT Deviceに接続しているカメラを起動する準備ができました。
それでは実際に試してみます。
App → IoT Core Shadow 動作
Appから「 ON 」ボタンを押してIoT CoreのShadowテーブルが更新することを確認します。 イメージは赤点線で囲んだ箇所のルートです。
IoT CoreのShadowの状態確認
IoT Coreコンソールにアクセスします。
コンソール画面の「 管理 」-> 「 モノ」-> 「 RaspberryPi_Camera 」-> 「 シャドウ 」-> 「 classic shadow 」をクリックします。
"camera" : "0"はカメラ停止 、 "camera" : "1"はカメラ起動 です。
Shadow状態確認
iOS Appから「 ON 」ボタンをクリックします。
Appから送信された「 camera=1 」のREST APIが、最終的にIoT Core Shadowに到達し、「 desired 」の「 "camera" : "1" 」に変化したことが確認できます。
更に「 desired 」と「 reported 」のcamera変数の値が異なることをAWS shadowが検出し、「 delta 」で値をステータスとして表示しています。
このステータスの確認は、一回ブラウザの更新ボタンで画面更新で表示されます。
次にiOS Appからの指示とIoT Deviceの連携を一連の動作で見たいので、一旦OFFボタンをタップして、「 desired 」の「 "camera" : "0" 」にします。
REST API制御
iOS Appを使用しなくても、直接REST APIを呼び出して制御することもできます。
x-api-key、httpsアドレスの 「xxxxxxxxxxxxxxxxxxxx」は各自の環境に合わせてください。
また「ap-northeast-1」.は、API Gatewayで作成したリージョン(今回は東京)です。
ON/OFFの違いは「 camera=0 」と 「 camera=1 」のみです。
Camera ONのAPI
curl -X POST --header "x-api-key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/"test?camera=0"
Camera OFFのAPI
curl -X POST --header "x-api-key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/"test?camera=1"
IoT Device shadow起動とiOS App制御
IoT DeviceがAWS IoT CoreにShadowにアクセスし、「 desired 」の「 "camera" : "1" 」に変化したことを検出し、「reported 」の「 "camera" : "1" 」に変化させ、更にIoT Deviceのカメラが起動していることを確認します。
赤点線部分の確認です。
Pythonスクリプト実行
IoT Device(RaspberryPi)にアクセスし、shadow起動のPythonスクリプトを起動します。
$ python3 shadow_camera_test.py
起動後、標準出力で表示ログを出力します。
下記の表示イメージは、全て「AWSIoTPythonSDK.MQTTLib」ライブラリで出力しています。
2020-12-17 10:01:55,642 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Initializing MQTT layer... 2020-12-17 10:01:55,644 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Registering internal event callbacks to MQTT layer... 2020-12-17 10:01:55,644 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - MqttCore initialized 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Client id: RaspberryPi 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Protocol version: MQTTv3.1.1 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Authentication type: TLSv1.2 certificate based Mutual Auth. 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queueing: max queue size: 0 2020-12-17 10:01:55,646 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queue draining interval: 0.100000 sec 2020-12-17 10:01:55,646 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring endpoint... 2020-12-17 10:01:55,647 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring certificates... 2020-12-17 10:01:55,647 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring reconnect back off timing... 2020-12-17 10:01:55,648 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Base quiet time: 1.000000 sec 2020-12-17 10:01:55,648 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Max quiet time: 32.000000 sec 2020-12-17 10:01:55,648 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Stable connection time: 20.000000 sec 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring connect/disconnect time out: 10.000000 sec 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring MQTT operation time out: 5.000000 sec 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync connect... 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing async connect... 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Keep-alive: 600.000000 sec 2020-12-17 10:01:55,650 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Event consuming thread started 2020-12-17 10:01:55,651 - AWSIoTPythonSDK.core.protocol.mqtt_core - DEBUG - Passing in general notification callbacks to internal client... 2020-12-17 10:01:55,651 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in fixed event callbacks: CONNACK,DISCONNECT,MESSAGE 2020-12-17 10:01:55,774 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Starting network I/O thread... 2020-12-17 10:01:55,848 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [connack] event 2020-12-17 10:01:55,849 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [connack] event 2020-12-17 10:01:55,850 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - No need for recovery 2020-12-17 10:01:55,851 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback... 2020-12-17 10:01:55,852 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync subscribe... 2020-12-17 10:01:55,852 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Adding a new subscription record:$aws/things/RaspberryPi_Camera/shadow/update/delta qos: 0 2020-12-17 10:01:55,853 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom suback event callback... 2020-12-17 10:01:55,907 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [suback] event 2020-12-17 10:01:55,908 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [suback] event 2020-12-17 10:01:55,908 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback... 2020-12-17 10:01:55,909 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing itafter invocation... 2020-12-17 10:01:57,912 - AWSIoTPythonSDK.core.shadow.deviceShadow - INFO - Subscribed to delta topic for deviceShadow:RaspberryPi_Camera 2020-12-17 10:02:01,042 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [message] event 2020-12-17 10:02:01,042 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [message] eventdelta/RaspberryPi_Camera
ASW IoT Coreコンソールからshadow状態の確認します。
まだカメラ停止状態です。
iOS Appから「 ON 」ボタンをタップすると、「 desired 」の「 "camera" : "1" 」に変化したことを検出し、「reported 」の「 "camera" : "1" 」になりました。
Iot Device(RaspberryPi)のshadow変化検出ログイメージです。
++++++++DELTA++++++++++ camera: 1 version: 12 +++++++++++++++++++++++ updating...
最後にカメラが起動した時の画像です。
時間がIoT Core コンソールのShadowステータスと異なりますが、ご了承ください。
最後に
途中AWSアップデートで動作しない時もありましたが、目標としているAWS Iot Device Shadow機能を使って遠隔操作を確認することができました。
この方法は見守りカメラなどでも使用されているようですね。ご参考にしていただければと思います。
AWS IoT Device Shadowを使ってみた!(Part3)
本記事は、最終目標である遠隔からDevice Shadow機能を使ってIoT Device制御をまとめたものです。 なお、4つの記事の中で今回は 下記の「 Part3 」です
主な全体記事の流れです。
■ Part1 : API Gatewayから起動するLambda関数の作成
■ Part3 : AWS IoT Deviceとshadow作成
■ Part4 : iPhoneアプリ作成 と 遠隔Camera起動確認
AWS構成図
赤点線で囲んだ箇所を今回作成します。
AWS IoTアクセス
AWS IoTコンソールにアクセスします。
IoTポリシーの作成
AWS IoTのコンソールの左メニュの「 安全性」-> 「 ポリシー 」をクリックします。
ポリシー登録画面に遷移し、ポリシーを登録します。「作成 」ボタンをクリックし、ポリシーの作成画面に遷移します。
「 名前 」、「 アクション」、「リソースARN」、「 効果 ]を入力&選択します。今回は名前は「 RaspberryPi_Camera-Policy 」にしています。
モノの作成
AWS IoTのコンソールの左メニュの「 管理 」-> 「 モノ 」をクリックします。
モノの登録画面遷移し、IoT Deviceを登録します。「 作成ボタン 」をクリックします。
単一のAWS IoTモノを作成します。「 単一のモノを作成する 」ボタンをクリックします。
「 名前 」、「 Thing Shadow 」を入力します。今回はIoT Deviceは「Raspberry Pi」を使用するため「RaspberryPi_Camera」としています。
「Thing Shadow」はすでに設定内容が 「 "Welcome...... "」となっていますが、下記のように書き換えます。
最後に「 次へ 」ボタンをクリックします。
画像が見えないので「Thing Shadow」は下記をご参考にしてください。
{ "desired": { "camera": "0" }, "reported": { "camera": "0" },
証明書を作成します。「 __ 証明書を作成」ボタンをクリックします。
証明書、キーが発行されますので、ダウンロードしておきます。この証明書は、RaspberryPiにコピーして使用します。
ルートCAファイルは、別途RaspberryPiからダウンロードするため、ここではダウンロードはしません。
証明書、キーファイルのダウンロード完了後に「 有効化 」ボタンをクリックし、証明書を有効にします。
最後に「 ポリシーをアタッチ 」ボタンをクリックします。
最初に作成した「 ポリシー 」を選択し、「 モノの登録 」ボタンをクリックします。
以上で IoT CoreにIoT Deviceの登録が完了しました。
次はIoT Device(Raspberry Pi)で動作する、IoT Device Shadowのプログラムです。
ルートCAファイルのダウンロード
Raspberry PiにSSH接続してログインします。
$ ssh pi@192.168.10.10
保存するディレクトに移動し、ルートCAファイルダウンロードします。
$ cd /home/pi/Documents/testShadow/cert $ sudo wget -O root.ca.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
Raspberry Pi環境
certディレクトリ配下にはルートCA、証明書、キー情報ファイルを配置しますので、 本記事箇所でダウンロードした証明書、キー情報ファイルはコピーしてください。
imageディレクトリは、カメラ起動中にキャプチャした画像を保存する場所です。
testShadow/ | |--- shadow_camera_test.py | |--- cert/ | |--- root.ca.pem # ルートファイル | |--- xxxxxxxxxxx.cert.pem" #証明書ファイル | |--- xxxxxxxxxxx.private.key" #privateキーファイル | |--- image/
ソースコード
「OpenCV」、「AWSIoTPythonSDK.MQTTLib」はインストールしておいてください。
ソースコードは、「AWSIoTPythonSDK」の「sample」ディレクトリにあるソースファイルを参考にしました。
AWSIoTPythonSDK
updateState()、customShadowCallback_Delta()、54行目〜77行目も一部変更していますが、ほぼ流用です。
カメラ起動中は1秒周期でキャプチャーした画像を保存します。
ソースコード内の「 ■ 」コメントがある箇所は自分の環境に合わせて修正してください。
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient import logging import time import json import argparse import cv2 import datetime # VideoCapture用インスタンス生成 cap = cv2.VideoCapture(0) # バッファサイズ1に変更 cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # カメラ状態保存処理 def cameraStatusSet(onoff): global cameraState # カメラ起動指示有無確認 if onoff == "1" : cameraState = 'on' else: cameraState = 'off' # IoT Device Shadow "reported" UpDate処理 def updateState(newState): JSONPayload = '{"state":{"reported":{"camera":' + str(newState) +'}}}' print("updating...\n") print(JSONPayload) deviceShadowHandler.shadowUpdate(JSONPayload, None, 5) cameraStatusSet(newState) # Custom Shadow callback def customShadowCallback_Delta(payload, responseStatus, token): print(responseStatus) payloadDict = json.loads(payload) print("++++++++DELTA++++++++++") print("camera: " + str(payloadDict["state"]["camera"])) print("version: " + str(payloadDict["version"])) print("+++++++++++++++++++++++\n\n") # reported Update newState = json.dumps(payloadDict["state"]["camera"]) updateState(newState) host = "xxxxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com" # ■自環境に合わせて設定 port = 8883 # MQTT clientId = "RaspberryPi" # ■ ClientidはthingNameと同じにするとIoT Coreの # ■ shadow変換が見えなくなるので、違う名前にした thingName = "RaspberryPi_Camera"# ■AWS IoT Coreで「モノの作成」で生成した名前 rootCAPath = "./cert/root.ca.pem" certificatePath = "./cert/xxxxxxxxxxxx-certificate.pem.crt" # ■ 自環境に合わせて設定 privateKeyPath = "./cert/xxxxxxxxxxxx-private.pem.key" # ■ 自環境に合わせて設定 # Configure logging logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) logger.addHandler(streamHandler) # Init AWSIoTMQTTShadowClient myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient(clientId) myAWSIoTMQTTShadowClient.configureEndpoint(host, port) myAWSIoTMQTTShadowClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath) # AWSIoTMQTTShadowClient configuration myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20) myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec # Connect to AWS IoT myAWSIoTMQTTShadowClient.connect() # Create a deviceShadow with persistent subscription deviceShadowHandler = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(thingName, True) # Listen on deltas deviceShadowHandler.shadowRegisterDeltaCallback(customShadowCallback_Delta) # カメラON/OFF状態を初期化 cameraState = 'off' # Loop forever while True: # カメラOPEN状態 while(cap.isOpened()): # カメラ起動状態指示 ? if cameraState == 'on': # カメラで顔データを取得する ret, img = cap.read() # 日時取得 dt_now = datetime.datetime.now() dateStr = dt_now.strftime('%Y%m%d_%H%M%S_%f') dateStr1 = dt_now.strftime('%Y/%m/%d %H:%M:%S') # 画像内に日時を書き込み cv2.putText(img, dateStr1 ,(20,450), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA) # 画像ファイル保存 cv2.imwrite('./image/image_'+ dateStr + '.jpg',img) time.sleep(1)
IoT Device shadow起動
$ python3 shadow_camera_test.py
起動すると、標準出力で表示ログを出力します。
下記の表示イメージは、全て「AWSIoTPythonSDK.MQTTLib」ライブラリで出力しています。
2020-12-17 10:01:55,642 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Initializing MQTT layer... 2020-12-17 10:01:55,644 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Registering internal event callbacks to MQTT layer... 2020-12-17 10:01:55,644 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - MqttCore initialized 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Client id: RaspberryPi 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Protocol version: MQTTv3.1.1 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Authentication type: TLSv1.2 certificate based Mutual Auth. 2020-12-17 10:01:55,645 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queueing: max queue size: 0 2020-12-17 10:01:55,646 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queue draining interval: 0.100000 sec 2020-12-17 10:01:55,646 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring endpoint... 2020-12-17 10:01:55,647 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring certificates... 2020-12-17 10:01:55,647 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring reconnect back off timing... 2020-12-17 10:01:55,648 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Base quiet time: 1.000000 sec 2020-12-17 10:01:55,648 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Max quiet time: 32.000000 sec 2020-12-17 10:01:55,648 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Stable connection time: 20.000000 sec 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring connect/disconnect time out: 10.000000 sec 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring MQTT operation time out: 5.000000 sec 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync connect... 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing async connect... 2020-12-17 10:01:55,649 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Keep-alive: 600.000000 sec 2020-12-17 10:01:55,650 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Event consuming thread started 2020-12-17 10:01:55,651 - AWSIoTPythonSDK.core.protocol.mqtt_core - DEBUG - Passing in general notification callbacks to internal client... 2020-12-17 10:01:55,651 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in fixed event callbacks: CONNACK,DISCONNECT,MESSAGE 2020-12-17 10:01:55,774 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Starting network I/O thread... 2020-12-17 10:01:55,848 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [connack] event 2020-12-17 10:01:55,849 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [connack] event 2020-12-17 10:01:55,850 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - No need for recovery 2020-12-17 10:01:55,851 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback... 2020-12-17 10:01:55,852 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync subscribe... 2020-12-17 10:01:55,852 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Adding a new subscription record:$aws/things/RaspberryPi_Camera/shadow/update/delta qos: 0 2020-12-17 10:01:55,853 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom suback event callback... 2020-12-17 10:01:55,907 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [suback] event 2020-12-17 10:01:55,908 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [suback] event 2020-12-17 10:01:55,908 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback... 2020-12-17 10:01:55,909 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing itafter invocation... 2020-12-17 10:01:57,912 - AWSIoTPythonSDK.core.shadow.deviceShadow - INFO - Subscribed to delta topic for deviceShadow:RaspberryPi_Camera 2020-12-17 10:02:01,042 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [message] event 2020-12-17 10:02:01,042 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [message] eventdelta/RaspberryPi_Camera
参考までに、shadow差分を検知すると以下の画面ログが出力されます。
++++++++DELTA++++++++++ camera: 1 version: 12 +++++++++++++++++++++++ updating...
AWSとIoT Deviceの設定が全て終わりました。
遠隔から指示する場合、iphoneだけではなくPCからも制御可能です。 コマンドイメージはPart4の方で。
AWS IoT Device Shadowを使ってみた!(Part2)
本記事は、最終目標である遠隔からDevice Shadow機能を使ってIoT Device制御をまとめたものです。 なお、4つの記事の中で今回は 下記の「 Part2 」です
主な全体記事の流れです。
■ Part1 : API Gatewayから起動するLambda関数の作成
■ Part3 : AWS IoT Deviceとshadow作成
■ Part4 : iPhoneアプリ作成 と 遠隔Camera起動確認
AWS構成図
赤点線で囲んだ箇所を今回作成します。
API の作成
「 APIを作成 」ボタンをクリックします。
APIタイプを「 REST API」の「 構築 」ボタンをクリックします。
「 API名 」入力、「 エンドポイントタイプ」を選択します。ここではAPI名は「cameraAPITest」、「リージョン」を指定し、「 APIの作成 」ボタンをクリックします。
エンドポイントにリージョンを選択すると、外部から指定するURLに「リージョン名」を付与しているアドレスになるイメージです。
下記のリージョン名は、「ap-northeast-1」です。尚、リージョン名は「メソッド作成」箇所で選択します。 (https:xxxxxxxxxxxxxxxxxxxx.ap-northeast-1.amazonaws.com/xxxxxxxxxxxxxx)
リソースの作成
「 アクション 」ボタンをクリックし「 リソースの作成 」を選択します。
「 リソース名 」を入力し、「 リソースの作成 」をクリックし、リソースを作成します。
「リソース名」は「リソースパス」欄に自動挿入されます。
「リソースパス」とは、外部から指定するURL(https:................/test )のアドレスとして扱われます。ここでは「リソース名」を「test」としているため、パスにtestが入ります。
メソッドの作成
「 アクションボタン 」をクリックし、「 メソッドの作成 」を選択します。
「メソッド」とは、HTTPメソッドのことです。 HTTPメソッドとは、リソースに対して実行したいアクションを示すもので、メソッドには「GET」、「POST」、「PUT」などがあり、HTTPサーバー(今回はAWSがサーバー)へ指定する時に使用します。
AWS API Gatewayは、一つのメソッドに一つのLambda functionを登録できますので、メソッド毎にLambda functionを登録し、別の処理を行うことができます。
プルダウンリストからHTTPリクエストメソッド「 POST 」を選択します。選択完了後は、「 チェックマーク 」をクリックします。
Lambda関数の登録
左側のツリー表示から「POST」を選択し、POSTのセットアップをします。 統合タイプは「 Lambda関数 」のラジオボタンで選択、「 Lambdaリージョン 」を選択します。最後に「 Lambda関数 」に関数名を入力&選択し、「 保存 」ボタンをクリックします。
Lambda関数名は、「Part1」で作成した「」です。キーボードで登録したい関数名を入力すると、作成済みのLambda関数が表示されますので、対象の関数があったらそれを選択しましょう。
「 Lambda関数に権限を追加する 」のダイアログが表示されます。「 OK 」ボタンをクリックします。
APIキーの作成
ここからが「 外部からアクセスするためにURLを公開」する登録です。
ただし、APIをデプロイした時点で外部に公開され、誰でもアクセスできてしまいます。 Webブラウザからアクセスするブログなどのサイトではないので、誰からもアクセスできないようAPIキーを使用して認証を行うようにします。
先にAPIキーを作成し、APIリクエスト時に認証を行うようにします。
左メニューから「 APIキー 」を選択。「 アクションボタン 」をクリックし、「 APIキーの作成 」を選択します。
「 名前 」を入力し、「 APIキー 」は自動生成とし、「 保存ボタン 」をクリックします。
作成が完了すると、APIキーが生成されます。このAPIキーは、外部からアクセスするときに使用します。「 表示 」をクリックでキー情報を確認できます。
APIキーをメソッドと関連付けさせます。左ツリー表示の「 POST 」を選択し、右画面の「 メソッドリクエスト 」をクリックします。
「 APIキーの必要性 」が「 false 」になっていますので、プルダウンで「 true 」を選択し、「 チェックボタン 」をクリックします。
マッピングプレートの作成
URLでパラメータ取得のための「 マッピングプレート 」の登録をします。
POSTメソッドの「 統合リクエスト 」をクリックします。
「 マッピングプレート 」をクリックします。
「 テンプレートが定義されていない場合(推奨)」を選択し、Content-Typeに「 application/json 」を入力し、チェックボタンをクリックします。
チェックボタンクリック後、画面下に「 設定欄 」が表示されますのでイメージのように入力し「 保存」ボタンをクリックし保存します。
設定欄の入力イメージです。
{ "camera": "$input.params('camera')" }
これでURLでパラメータ取得の設定が終わりました。
APIのデプロイ
「 アクションボタン 」をクリックし、「 APIのデプロイ 」を選択します。
デプロイ後に各種設定変更した場合は、同様に再デプロイすることで設定が反映されます。
APIのステージを登録します。
このステージは、実際の使用する時エンドポイントを分けて使用することができます。例えば開発用、評価が終わって正式公開用などのようにもできます。
今回はお試しなので「 デプロイされるステージ 」を「新しいステージ」、「 ステージ名 」を「development」とし、「 デプロイ 」ボタンをクリックし、デプロイします。
このステージ名がURL(https:xxxxxxxxxxxxx/development/test)に割り当てられます。
「 デプロイ 」が完了するとステージまでのURLアドレスが表示されます。これに「 リソース名」(今回はtest)が追加されたアドレスがアクセスアドレスになります。
使用量プランの作成
使用量プランを設定します。作成したAPIの使用量を測定することに使用されます。 左メニュー画面から「 使用プラン 」を選択し、「 作成 」ボタンをクリックします。
プラン「 名前 」を入力し、「 スロットリングの有効化 」「 クォータを有効する 」のチェックボックスのチェックを外して、「 次へ 」のボタンをクリックします。
APIステージと使用プランを関連付けます。下記画像の「 APIステージの追加 」ボタンが非Active化(グレー表示)なっていますが、実際はボタンはActive化状態となっていますので、ご了承ください。
「 APIステージの追加 」ボタンをクリックし、「 API 」、「 ステージ 」を選択し、「 チェックマーク 」をクリックします。
完了すると、「 次へ 」ボタンがActive化されますので、ボタンをクリックします。
APIキーと使用プランを関連付けします。下記画像の「 APIキーを使用プランに追加 」ボタンが非Active化(グレー表示)なっていますが、実際はボタンはActive化状態となっていますので、ご了承ください。
「 名前のテキストボッククス 」に、APIキー名を入力すると選択表示が出ますので選択します。
「 チェックマーク 」をクリックします。
完了すると、「 完了 」ボタンがActive化されますので、ボタンをクリックします。
これで外部からAPIキーを使用したURLアクセスができるようになりました。
次はPart3のAWS IoT Deviceとshadow作成です。