SORACOM GPSマルチユニットをAWS IoT Coreに接続して、バッテリー低残量の通知を受け取る

SORACOM GPSマルチユニットのバッテリーが低残量になったとき、メールでお知らせする仕組みを作ってみました。
2021.02.25

GPSマルチユニットSORACOM Editionをバッテリー駆動で使っているのですが、バッテリー残量が気になるのです。

SORACOM Lagoonを使えばバッテリー残量のアラート通知ができますが、せっかくなのでAWS IoT Coreに接続して、バッテリーの低残量を通知する仕組みを作ってみました。

おすすめの方

  • GPSマルチユニットSORACOM Editionのバッテリー低残量を通知したい方
  • SORACOM FunnelでAWS IoT Coreにデータを送信したい方
  • AWS IoT Eventsについて知りたい方
  • AWS IoT EventsをCloudFormationで作成したい方

SORACOM Funnel用のIAMユーザを発行する

CloudFormationテンプレート(IAMユーザ)

特定のトピックに対して、iot:Publishできる権限のみを付与しています。

iam_user.yml

AWSTemplateFormatVersion: 2010-09-09
Description: IAM User for SORACOM Funnel

Resources:
  # SORACOM Funnel用のIAMユーザ
  SoracomFunnelUser:
    Type: AWS::IAM::User
    Properties:
      UserName: "soracom-funnel-user"

  # IAMユーザに付与するIAMポリシー
  SoracomFunnelUserPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: "soracom-funnel-user-policy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Action: "iot:Publish"
            Resource: !Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/soracom/gps-multiunit/*"
      Users:
        - !Ref SoracomFunnelUser

デプロイ

aws cloudformation deploy \
	--template-file iam_user.yml \
	--stack-name SORACOM-Funnel-IAM-User-Stack \
	--capabilities CAPABILITY_NAMED_IAM \
	--no-fail-on-empty-changeset

アクセスキーを取得

aws iam create-access-key \
    --user-name soracom-funnel-user

SORACOM Funnelを設定してAWS IoT Coreにデータ送信する

SORACOMにAWS認証情報を登録

SORACOM Webコンソールにアクセスし、右上のメニューにある「セキュリティ」を選択します。

セキュリティを選択

続いて、「認証情報ストア」にある「認証情報を登録」を選択します。

認証情報を登録する

種別は「AWS認証情報」を選択し、さきほど取得したアクセスキーを貼り付けて登録します。

AWSアクセス情報を登録する

AWS IoT Coreエンドポイント取得

下記コマンドで取得できます。

aws iot describe-endpoint \
    --endpoint-type iot:Data-ATS

SORACOM Funnelの設定入力

メニューの「SIMグループ」からGPSマルチユニットのSIMグループを選択します。

SIMグループを選択する

SORACOM Funnelの設定を行います。

項目 内容
転送先サービス AWS IoT
転送先URL xxxxx.iot.ap-northeast-1.amazonaws.com/soracom/gps-multiunit/#{imsi}
認証情報 さきほど登録した認証情報
送信データ形式 JSON

SORACOM Funnelを設定する

AWSs IoT Coreでテスト

IoT Coreの「テスト」にアクセスして、下記トピックをサブスクライブします。

  • soracom/gps-multiunit/+

AWS IoT Coreでトピックをサブスクライブする

しばらく待つとデータが送信されてきました!!!

AWS IoT Coreに来たデータ

JSON内容は下記です(一部マスクしています)

{
  "operatorId": "xxx",
  "timestamp": 1612846193590,
  "destination": {
    "resourceUrl": "xxx.iot.ap-northeast-1.amazonaws.com/soracom/gps-multiunit/#{imsi}",
    "service": "aws-iot",
    "provider": "aws"
  },
  "credentialsId": "funnel-aws-iot-core",
  "payloads": {
    "bat": 3,
    "temp": 25.3,
    "rs": 0,
    "lon": 135,
    "y": null,
    "humi": 25.2,
    "lat": 45,
    "x": null,
    "z": null,
    "type": 1
  },
  "sourceProtocol": "udp",
  "imsi": "111111111111111"
}

ここのbatを監視し、必要に応じて通知すればOKですね。 なお、ペイロードの詳細はこちらに記載があります。

GPSマルチユニットの低残量を通知する

バッテリー残量による状態遷移

batの範囲は「-1,1〜3(-1は充電中)」です。今回は、bat=1がバッテリー低残量とみなして通知する仕組みを作成します。

状態 遷移条件
BatteryHigh bat==3
BatteryLow bat==1

状態管理はAWS IoT Eventsで行います。

CloudFormationテンプレート

  • メール通知用のSNSトピック
  • IoTルール
  • IoTルール用のIAMロール
  • IoT Eventsの入力情報
  • IoT Eventsの探知器モデル
  • IoT Eventsの探知器モデル用のIAMロール
  • IoT Eventsの探知器モデル用のCloudWatchロググループ

notify_soracom_gps_multiunit_battery_low.yml

AWSTemplateFormatVersion: 2010-09-09
Description: IoT Events for SORACOM GPS Multiunit Notify Battery Low

Resources:
  SoracomGpsMultiunitTopicRule:
    Type: AWS::IoT::TopicRule
    Properties:
      RuleName: soracom_gps_multiunit_topic_rule
      TopicRulePayload:
        AwsIotSqlVersion: "2016-03-23"
        RuleDisabled: false
        Sql: >-
          SELECT
            topic(3) as imsi, payloads.bat
          FROM
            'soracom/gps-multiunit/+'
          WHERE
            payloads.type <> -1
        Actions:
          - IotEvents:
              InputName: !Ref SoracomGpsMultiunitEventsInput
              RoleArn: !GetAtt SoracomGpsMultiunitTopicRuleRole.Arn

  SoracomGpsMultiunitNotifyBatteryTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: sample@example.com
          Protocol: email

  SoracomGpsMultiunitTopicRuleRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: soracom-gps-multiunit-topic-rule-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: iot.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSIoTEventsFullAccess

  SoracomGpsMultiunitEventsInput:
    Type: AWS::IoTEvents::Input
    Properties:
      InputName: SoracomGpsMultiunitInputData
      InputDefinition:
        Attributes:
          - JsonPath: imsi
          - JsonPath: bat

  SoracomGpsMultiunitBatteryDetectorModel:
    Type: AWS::IoTEvents::DetectorModel
    Properties:
      DetectorModelName: soracom-gps-multiunit-battery-detector-model
      Key: imsi
      EvaluationMethod: BATCH
      RoleArn: !GetAtt SoracomGpsMultiunitBatteryDetectorModelRole.Arn
      DetectorModelDefinition:
        InitialStateName: BatteryHigh
        States:
          - StateName: BatteryHigh
            OnInput:
              TransitionEvents:
                - EventName: to_battery_low
                  NextState: BatteryLow
                  Condition: $input.SoracomGpsMultiunitInputData.bat == 1
          - StateName: BatteryLow
            OnEnter:
              Events:
                - EventName: send-mail-to-battery-low
                  Actions:
                    - Sns:
                        TargetArn: !Ref SoracomGpsMultiunitNotifyBatteryTopic
                        Payload:
                          Type: STRING
                          ContentExpression: "'バッテリーが低残量になりました。対象デバイス: ${$input.SoracomGpsMultiunitInputData.imsi}'"
            OnInput:
              TransitionEvents:
                - EventName: to_battery_high
                  NextState: BatteryHigh
                  Condition: $input.SoracomGpsMultiunitInputData.bat == 3
            OnExit:
              Events:
                - EventName: send-mail-to-battery-high
                  Actions:
                    - Sns:
                        TargetArn: !Ref SoracomGpsMultiunitNotifyBatteryTopic
                        Payload:
                          Type: STRING
                          ContentExpression: "'バッテリー残量が復旧しました。。対象デバイス: ${$input.SoracomGpsMultiunitInputData.imsi}'"

  SoracomGpsMultiunitBatteryDetectorModelRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: soracom-gps-multiunit-battery-detector-model-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: iotevents.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess

デプロイ

aws cloudformation deploy \
  --template-file notify_soracom_gps_multiunit_battery_low.yml \
  --stack-name Notify-SORACOM-GPS-Multiunit-Battery-Low-Stack \
  --capabilities CAPABILITY_NAMED_IAM \
  --no-fail-on-empty-changeset

デプロイされた探知器モデルを確認する

無事にできました!

AWS IoT Eventsの様子

動作確認

BatteryHighになっている

さっそくディテクターの様子を見てみると、BatteryHigh状態になっていました。

BatteryHigh状態

バッテリー低残量が通知された

しばらく放置していると、バッテリー低残量が通知されました。

バッテリー低残量のメール

ディテクターの状態もBatteryLowになっています。

BatteryLow状態

充電すると、バッテリー残量の復旧通知がきた

充電してしばらく待つと、バッテリー残量の復旧通知がきました。

バッテリー残量復旧のメール

ディテクターの状態もBatteryHighに戻りました。

BatteryHigh状態

おまけ

SORACOM Harvestでbatを確認すると、下記のような状態でした。(送信間隔は5分)

SORACOM Harvestの様子

bat 時間
2 約1時間半
1 約4時間半

今回はbat==1で低残量を通知しましたが、あまり差がないので、bat==2で通知しても良さそうですね。

さいごに

参考