月別: 2020年1月

AWS IoT Core にRaspberry Piから赤外線モーションセンサのログを送る

クラウド事業部エンジニアの川勝です。

わけあって人感センサで在室確認したいという要望がありまして、やってみることになりました。
ちょっとIoTブームが個人的にきているのもあってAWS IoT Coreをつかってやってみたいと思います。

今回はAWS IoTに送信までやってみます。
使うのサービスとモノは以下。

● AWS IoT
https://aws.amazon.com/jp/iot-core/

AWS IoT Core は、インターネットに接続されたデバイスから、クラウドアプリケーションやその他のデバイスに簡単かつ安全に通信するためのマネージド型クラウドサービスです。

簡単とうたうだけあってチュートリアルのnode.jsとかpythonのデバイス用sdkを使ったものでmacでも簡単に接続まで試すことができました。

● Raspberry Pi
会社に眠っていたもの。多分Raspberry Pi Type B 

● 赤外線モーションセンサ
ググってでてきたRsbeeの3個セットのもの。安い。
Raspberry Piと接続するのにジャンパーワイヤーもいります。

●言語
チュートリアルはnode.jsでやったのですがgoで実装していきます。

Rasberry Pi と モーションセンサ

Raspberry Piのセットアップ

microSD

Raspberry Piを触るのは初めてだったのですが、microSDにosをインストールして使用します。眠っていた機器にもともと8GBのmicroSDは刺さっていたのですが、ちょっと怪しそうだったので家にあった東芝の16GBのものを使いました。
最低8GBは必要みたいです。

OS

CLIでしか操作しなにのでこちらからRaspbian Buster LiteをDLして使用しました。Ubuntu CoreっていうのもIoT向けで良さそうだったのですが今回使うRaspberry Piだと型が古くて対応外みたいでした…残念。

インストール

公式サイトにインストール方法あります。
今回はmac上でフォーマット、OSインストールした後にSSHできるようにします。(Raspberry Piにつなぐようのディスプレイが手元になかったので…)

microSDを接続したら以下コマンドで確認。

$ diskutil list

/dev/disk0 とか /dev/disk1 とかでてくるので要確認。間違うとmac本体がやられます。自分の環境では /dev/disk2 でした。

/dev/disk2 (external, physical):
#: TYPE NAME SIZE IDENTIFIER
0: FDisk_partition_scheme *7.9 GB disk2
1: Windows_FAT_32 boot 58.7 MB disk2s1
2: Linux 7.9 GB disk2s2

確認できたらフォーマット。

$ diskutil eraseDisk MS-DOS RPI disk2

フォーマットが完了したら一旦アンマウントして…

$ diskutil unmountDisk /dev/disk2DLしたOSのイメージを書き込みます。sudo dd bs=1m if=path_of_your_image.img of=/dev/rdisk2 conv=sync

終わったら、sshできるようにもうひと手間かけます。
もしbootディレクトリがでてこなかったら一度SDカードを取り出して入れるとでてきました。

$ touch /Volumes/boot/ssh

ちなみに Raspberry PiがWifiモデルだったらwifiの設定ファイルを用意しておくと有線で繋がなくても接続できるようです。
wpa_supplicant.confというファイルで以下のような内容をboot以下に保存します。

country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="hoge"
    psk="fuga"
}

mac上でここまでできたらSDカードを取り出してRaspberry Piにセットします。

Raspberry Pi へSSH

Raspberry PiはmicroUSB端子の電源アダプタでつなぐと起動します。
が、電源アダプタがなかったのでAmazon Echoの電源で起動しました。
とりあえず動きはするみたい。
ちなみにRaspberry Pi 4では5V 3Aが推奨のようです。
モニターもないのでLANケーブルもつないで電源ライトの赤と緑のランプが付けばOKとしてmacからsshします。
portがわからないので調べます。

$ arp -a
? (192.168.3.1) at 30:::::** on en0 ifscope [ethernet]
? (192.168.3.3) at ac:::::** on en0 ifscope [ethernet]
? (192.168.3.6) at fc:::::** on en0 ifscope [ethernet]
? (192.168.3.8) at 14:::::** on en0 ifscope [ethernet]
? (224.0.0.251) at 1:::::** on en0 ifscope permanent [ethernet]
? (239.255.255.250) at 1:::::** on en0 ifscope permanent [ethernet]

上みたいにIPアドレスとMACアドレスがでてきます。b8:27:e1 から始まるMACアドレスがRaspberry Piらしいのででてくるまで arp -a を連打しましたw
IPアドレスがわかったらSSHします。

$ ssh pi@192.168.xx.xx

初期ユーザはpiでパスワードはraspberryでSSHできます。
パスワードはログイン後に変更しておきましょう。
その他いろいろ設定したほうがよさそうですが、ひとまず接続できたのでAWSの設定と実行プログラムを設置していきます。

AWS IoT

AWSコンソールから作成していきます。

AWS IoTの 管理 > モノ からデバイスの作成をします。

単一のAWS IoT モノの登録を選択します。

Things Registryにデバイスを追加
とりあえず名前だけつけて次へ

証明書を作成します。

ボタンをクリックするだけで新規に証明書が作成されました。
忘れずに証明書、プライベートキー、パブリックキーをダウンロードしましょう。またAWS IoT のルートCAも必要ですのでリンク先からダウンロードします。
ダウンロードしたら証明書を有効化します。
ポリシーをアタッチは先にポリシーを作成しておく必要がありますのでここでは一旦完了します。

モノの一覧にもどるとTestDeviceが作成されていますね!

続いて 安全性 > ポリシー からポリシーの作成をします。

アクションは iot:* としておきます。リソースARNは画像はデフォルトで挿入されている値ですが、接続確認だけなら * にしておいてもよいです。

ポリシーを作成したら 安全性 > 証明書 から証明書にポリシーをアタッチします。

最後に モノ詳細画面からHTTPSエンドポイントを確認しておきます。

センサ接続

ちょっと見にくいですが以下のPINに接続しています。
接続は電源を入れる前に。
1ピン  :5V電源(Power)
6ピン  :0Vアース(GND)
12ピン:GPIO18  (Output)

実行プログラム

ソースはこちら。
goのライブラリでgobotというのを使いました。使いやすくてよかったです。

● Raspberry Pi 用のdriver
https://gobot.io/documentation/platforms/raspi/
● モーションセンサ用
https://gobot.io/documentation/drivers/pir-motion-sensor/

大体そのまま使っています。
モーションセンサで使っているドライバーはRaspberry Pi用のものじゃなくて最初ちょっとハマりました…
あとモーションセンサをつないだpin番号が最初謎でした…
物理ピン番号とGPIOのBCMピン番号があるのですが、物理ピン番号を設定するようです。
Raspberry Piの設定は以下の様になりました。

func newRobot(c MQTT.Client) *gobot.Robot {
// raspiと接続するアダプター
r := raspi.NewAdptor()
// モーションセンサ。pin番号はgpioのpin番号ではない
sensor := gpio.NewPIRMotionDriver(r, pirMotionDriverPin)

// センサの振る舞い
work := func() {
// センサONになったら
sensor.On(gpio.MotionDetected, func(data interface{}) {
fmt.Println(gpio.MotionDetected)
token := c.Publish(fmt.Sprintf(shadowUpdateEndpoint), 0, false, sensorOnMessage)
if token.Wait() && token.Error() != nil {
fmt.Printf("error: %+v", token.Error())
} else {
fmt.Print("Message Publish Success\n")
}
})
// センサOffになったら
sensor.On(gpio.MotionStopped, func(data interface{}) {
fmt.Println(gpio.MotionStopped)
token := c.Publish(shadowUpdateEndpoint, 0, false, sensorOffMessage)
if token.Wait() && token.Error() != nil {
fmt.Printf("error: %+v", token.Error())
} else {
fmt.Print("Message Publish Success\n")
}
})
}

return gobot.NewRobot("motionBot",
[]gobot.Connection{r},
[]gobot.Device{sensor},
work,
)
}

センサのON/OFF時にAWS IoTにMTQQでメッセージを送信します。
あとからきづいたのですがgobotにもMTQQのクライアントがありましたが( https://gobot.io/documentation/platforms/mqtt/ )、違うパッケージを使用しています。
https://github.com/eclipse/paho.mqtt.golang
プログラムでいうと以下あたり

func newTLSConfig() (*tls.Config, error) {
certpool := x509.NewCertPool()
// AWS IoTのルートCA
pemCerts, err := ioutil.ReadFile(caCertificate)
if err == nil {
certpool.AppendCertsFromPEM(pemCerts)
}
// ダウンロードした証明書とプライベートキーのチェック
cert, err := tls.LoadX509KeyPair(clientCertificate, privateKey)
if err != nil {
log.Printf("error: cert file mismatch. clientCertificate: %s, privateKey: %s\n", clientCertificate, privateKey)
return nil, err
}

cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
if err != nil {
log.Print("error: parse certificate.\n")
return nil, err
}

return &tls.Config{
RootCAs: certpool,
ClientAuth: tls.NoClientCert,
ClientCAs: nil,
InsecureSkipVerify: true,
Certificates: []tls.Certificate{cert},
}, nil
}

var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
fmt.Printf("TOPIC: %s\n", msg.Topic())
fmt.Printf("MSG: %s\n", msg.Payload())
}

func mqttClient() (MQTT.Client, error) {
// 証明書の読み込み
tlsconfig, err := newTLSConfig()
if err != nil {
log.Print("error: newTLSConfig error.\n")
return nil, err
}
// AddBrokerでAWS IoTのエンドポイント設定
opts := MQTT.NewClientOptions().
AddBroker(fmt.Sprintf(awsIotHostName, hostName)).
SetClientID(clientID).
SetTLSConfig(tlsconfig).
SetDefaultPublishHandler(f)

return MQTT.NewClient(opts), nil
}

プログラムのbuildはmac上でしてscpでRaspberry Piに転送して動かしました。
実行時のコマンド

./build/deploy/cmd/${PROJECT_NAME} \
-host-name xxxxxxxx.iot.ap-northeast-1.amazonaws.com \
-client-id testDevice-1 \
-client-certificate certificate.pem.crt \
-ca-certificate root-CA.crt \
-private-key private.pem.key \
-thing-name testDevice

引数で証明書のパスとかを指定します。センサのPIN番号も引数にしてもいいかもですね。

このあたりのコマンドはMakefile用意しておいて実行できるようにしています。(引数わすれるので。)
https://github.com/kawakattsun/iot-motion-sensor-go/blob/master/Makefile_go

動かしてみた

(圧縮したので見づらい…)

左がRaspberry Piにsshしてターミナルからコマンド実行した画面。
右はAWS IoTの 管理 > モノ からシャドウという項目をみています。
ちょっと見にくいですが連動して更新されていますね!

ターミナルの表示は
●センサが検知
motion-detected
Message Publish Success

●検知後
motion-stopped
Message Publish Success

どうも検知したあと一定時間で必ずstoppedになるようですね…

この後

次はシャドウの更新をさらにAWS上のサービスに流せるので最終的にLambdaで状態判定して在室検知判定しようと思います。
当初AWS IoTからLambda直で流す予定でしたが、On Offが必ずセットでくるのでkinesis にデータを流して一定期間のレコードからLambdaで判定にしようかな、と思案中。

続きは次回ブログで公開したいと思います。
乞うご期待!

Amazon Comprehend を使って様々な文章を感情分析してみました

CTOの原口です。
Amazon Comprehend が昨年の11月に日本語にも対応した、という事で少し触ってみました。

Amazon Comprehendとは?

Amazon Comprehendとは 機械学習を使用してテキスト内でインサイトや関係性を検出する自然言語処理 (NLP) サービス です。
機械学習の知識なく使えるサービスで文章を投げると 「エンティティ分析」「キーフレーズ分析」「感情分析」の結果が返ってくるというお手軽なサービスになります。

今回、この中でも特に面白そうだな、と思った感情分析でいろいろな文章の感情分析を行ってみました。

Amazon Comprehend で 文章の感情分析

Amazon Comprehendは現在(2020/01/22)は以下のリージョンでしか提供されておらず、残念ながら東京リージョンでの提供はされておりませんので以下のリージョンで試してみます

EU (ロンドン)
EU (アイルランド)
アジアパシフィック (シンガポール)
アジアパシフィック (シドニー)
EU (フランクフルト)
米国東部 (バージニア北部)
米国東部 (オハイオ)
カナダ (中部)
米国西部 (オレゴン)

とりあえず試してみる…というのはすごく簡単で、 Amazon Comprehend のサービストップに移動して「Real-time analysis」をクリックし、解析したい文章を入力し、「Analyze」をクリックするだけで結果が出てきます

Amazon Comprehend の公式ページの文章を解析してみました
大枠として4つの感情に分類されて分析されるようです
Neutral ,Positive ,Negative,Mixed とありますがMixedだけどういうものかよくわかりません…

・Neutral -> ニュートラル(感情→)
・Positive -> ポジティブ (感情↑)
・Negative -> ネガティブ (感情↓)
・Mixed -> 上記が混じった文章?

ひとまずこの文章は94%がニュートラルで5%だけのポジティブ要素がある、と分析されてようですね

いろんな文章を感情分析してみる

まずは弊社代表、西垣の「社長ブログ」から分析してみました

社長ブログ – 内定式
https://www.seeds-std.co.jp/blog/24gk/education/376/
Neutral 94% Positive 5%


ほぼニュートラル!後半の懇親会の文章などから数ある記事の中でも結構ポジティブ要素が多いのではないかなー?と思って選んだ記事でしたが、ニュートラルでした

社長ブログ – AWSの盾が届きました
https://www.seeds-std.co.jp/blog/24gk/aws/291/
Neutral 92% Positive 7%

お次は同じく社長ブログからAWSからパートナーの盾が届いたこちらの記事を解析。これも結構喜んでおられたので結構ポジティブがいくか!?と思いましたが多少ポジティブが増えましたがそれでも7%でした。
さすが社長。公平があり感情的に揺さぶられないしっかりとした文章をかかれているようです。(持ち上げ)

広報ブログ 忘年会(2019 ver.)を開催しました
https://www.seeds-std.co.jp/blog/pr/6559/
Neutral 65% Positive 9% Mixed 22%

それでは、今度は比較的くだけた文章も書ける広報ブログの文章を分析してみました。やはりニュートラルが基本になりますね。ですがここで初めて Mixedというよくわからない項目が22%に。
実はこのブログ内容には「各事業部の来年の抱負」という部分があるのですが、この項目は各部長の抱負をベースにした文章がありますので、そういう意味で1/3の純情な感情が入り乱れた結果Mixedとなったのかもしれません。

広報ブログ  社長のHappyBirthday!!
https://www.seeds-std.co.jp/blog/pr/3794/
Neutral 35% Positive 64%

同じく広報ブログより、社長の誕生日を社内でお祝いしたブログ記事です。
これはもうポジティブに振り切れるはずだ!と思ったらやっぱりポジティブに振り切れてました。

“これを納期までにやるにはどうしたらいいのかを考えなさい”
Neutral 33% Negative 64%

ではブログ記事ではなく、もっと短い文章での解析はできるのか、とやってみました。こちらは上司からのお叱り文章という例文があったので解析してみました。
やっぱりネガティブが強く出ますね。

Positive 99%

というわけで短文といえばtwitter。僕の好きな、さしこの適当なツイートを分析してみました。ポジティブ99%!さすがアイドルですね。

“雨と雷やべー。。あと5分帰るの遅かったらヤバかった。。 飛行機心配しましたが明日は普通に大丈夫そうですね”
Neutral 48% Positive 2% Negative48%

短文といえば、Slack!今度は社内のslackでの僕の発言を解析。これはどちらかといえば「よかったー」という意味で書いてたのですが、ネガティブが上がってしまっていますね。
やはりこういった複雑な文章を読むのは苦手なのかもしれないです

どんな事に使えそうだろうか

{
    "Sentiment": {
        "Sentiment": "NEUTRAL",
        "SentimentScore": {
            "Positive": 0.05136203020811081,
            "Negative": 0.000046045330236665905,
            "Neutral": 0.9485709071159363,
            "Mixed": 0.000021009738702559844
        }
    }
}

さて、文章をAPIに投げると実際には上記のようなJSONが返ってきて”Sentiment”の項目に最も高かった感情が返ってきます。
これを踏まえて以下のような事をすると面白いのではないかと思いました

・サポート窓口からのご連絡のお客様の返信を解析
お客様から弊社サポートからのご連絡に対して、お客様からの返信を感情分析する事で、サポート品質向上の一つの指針になるのではないかと思いました。

・slackの過去発言から感情の状態でステータス表示を変える
たとえば自分の過去100メッセージから感情の平均を出して、最も多い環状をslackのステータス部分を絵文字とかで表すと面白いかもw

・twitterなどでいっぱい感情分析してその中でネガティブ値が多いものから単語を抜き出しNGワードを作る
やってみないとわからないですがそれなりの結果が出そうです。

おわりに

かんたんに文章の感情分析ができて面白いサービスでした。
可能であればネガティブ感情は「怒り」「悲しみ」くらいには分かれていると嬉しいですね。
機械学習も作るのではなく利用していくフェーズに入ったのだなーという事を改めて思いました。
時間があれば面白いもののデモを作ってみたいですね。

© SEEDS Co.,Ltd.