はじめに
今回はAWS IoT Coreの新機能であるAWS IoT Core Device Locationを試してみました。
これを使用すればCK-RX65N with RYZ014Aの大体の位置を緯度経度で知ることができます。
AWS IoT Core Device LocationについてもAWS公式で使い方が公開されています。
今回はこの使い方をベースにデモを実装しました
実装したデモは以下GitHubリポジトリに公開しています。
- nizuki926/iot-reference-rx
- Branch Name : v202210.01-lts-rx-1.1.2-device-location
上記使い方は位置の計測結果をIoTデバイスにPublishしています。
今回は簡易的なデモでCK-RX65Nに接続されたCellular-RYZ014Aモジュールから、IPアドレスとアクセスポイントの情報を取得して、JSON形式でAWSにMQTTメッセージとして送信するだけです。
その後、AWS IoT Coreのマネジメントコンソールから送信されたJSON形式のメッセージを緯度経度に変換するまでを行います。
準備した環境は以下の通りです。
- CK-RX65N (評価ボード)
- e2 studio 2023-10 (統合開発環境)
- CC-RX V3.05.00 (RXマイコン用コンパイラ)
デバイス位置情報取得デモの実装
各デモタスクを起動するメインタスクを変更する
各デモタスクを起動するメインタスクを変更します。
今回はENABLE_DEVICE_LOCATION_DEMO
オプションを新規作成して、このオプションが有効 (1
) な時にPubSub
デモの代わりにデバイス位置情報取得
デモを起動するように変更しました。
if(ApplicationCounter(Time2Wait))
{
/* Remove CLI task before going to demo. */
/* CLI and Log tasks use common resources but are not exclusively controlled. */
/* For this reason, the CLI task must be deleted before executing the Demo. */
vTaskDelete(xCLIHandle);
if( !Connect2AP())
{
configPRINTF( ( "Cellular init failed" ) );
}
else
{
vTaskDelay(300);
configPRINTF( ( "Initialise the RTOS's TCP/IP stack\n" ) );
configPRINTF( ( "---------STARTING DEMO---------\r\n" ) );
#if (ENABLE_FLEET_PROVISIONING_DEMO == 1)
vStartFleetProvisioningDemo();
#else
xSetMQTTAgentState( MQTT_AGENT_STATE_INITIALIZED );
#endif
vStartMQTTAgent (appmainMQTT_AGENT_TASK_STACK_SIZE, appmainMQTT_AGENT_TASK_PRIORITY);
#if (ENABLE_DEVICE_LOCATION_DEMO == 0)
vStartSimplePubSubDemo ();
#else
vStartDeviceLocationDemo ();
#endif
#if (ENABLE_OTA_UPDATE_DEMO == 1)
vStartOtaDemo();
#endif
}
}
while( 1 )
{
vTaskSuspend( NULL );
}
位置解決に必要な情報を取得する関数の実装
main.c
に位置解決に必要な情報を取得する関数を実装します。
なぜmain.c
に実装するのかというと使用する通信I/Fごとに取得できる情報に違いがあるからです。
今回はRYZ014Aを使用したセルラー通信のプロジェクトにデモを実装したので、IPアドレスとアクセスポイントの情報を使用することができます。
これが仮にイーサネット通信のプロジェクトにデモを実装すると、IPアドレスのみを使用できます。
したがって、通信I/Fごとに存在するmain.c
に関数を実装しました。
ちなみに、AWS IoT Core Device Locationで使用できる情報を以下の通りです。
- Wi-Fi ベースのソルバー
- セルラーベースのソルバー
- IP リバースルックアップソルバー
- GNSS ソルバー
IPアドレスとアクセスポイントの情報を取得するためにはRYZ014AドライバのAPI関数を呼び出していますが、セルラーベースで必須情報であるMCC
とMNC
だけは取得することができないようです。
そのため、今回はMCC
とMNC
を固定値にして実装しています。
したがって、本デモの動作を試す場合は使用するSIMカードに応じて、CELLULAR_MCC
とCELLULAR_MNC
の値を変更してください。
int vGetDeviceLocationInfo( char * buffer)
{
e_cellular_err_t cell_ret;
st_cellular_notice_t cellular_notice = {0};
st_cellular_ipaddr_t ip_addr;
cell_ret = R_CELLULAR_GetAPConnectState(&cellular_ctrl, CELLULAR_ENABLE_NETWORK_RESULT_CODE_LEVEL2, &cellular_notice);
if (CELLULAR_SUCCESS != cell_ret)
{
return -1;
}
cell_ret = R_CELLULAR_GetPDPAddress(&cellular_ctrl, &ip_addr);
if (CELLULAR_SUCCESS != cell_ret)
{
return -1;
}
return snprintf(buffer, demoDEVICE_LOCATION_JSON_SIZE, demoDEVICE_LOCATION_JSON, ip_addr.ipv4, CELLULAR_MCC, CELLULAR_MNC, strtol( cellular_notice.cell_id, NULL, 16 ), strtol( cellular_notice.ta_code, NULL, 16 ) );
}
デモタスクの実装
今回実装したデバイス位置情報取得
デモタスクはPubSub
デモを流用しました。
あらかじめ、Cellular-RYZ014AモジュールからIPアドレスとアクセスポイントの情報を取得しておき、一定時間おきにAWSにJSON形式に変換してMQTTメッセージとして送信するだけのデモです。
main.c
側に実装したvGetDeviceLocationInfo
を呼び出して位置解決に必要な情報を取得しています。
if( xStatus == pdTRUE )
{
/* Create a topic name for this task to publish to. */
xOutTopicLength = snprintf( cOutTopicBuf,
mqttexampleOUTPUT_TOPIC_BUFFER_LENGTH,
mqttexampleOUTPUT_TOPIC_FORMAT,
gKeyValueStore.table[KVS_CORE_THING_NAME].value );
/* Assert if the topic buffer is enough to hold the required topic. */
configASSERT( xOutTopicLength <= mqttexampleOUTPUT_TOPIC_BUFFER_LENGTH );
/* Create a payload to send with the publish message. This contains
* the task name and an incrementing number. */
do
{
xPayloadLength = vGetDeviceLocationInfo( cPayloadBuf );
} while (-1 == xPayloadLength);
/* For a finite number of publishes... */
for( ulPublishCount = 0UL; ulPublishCount < mqttexamplePUBLISH_COUNT; ulPublishCount++ )
{
/* Assert if the buffer length is not enough to hold the message.*/
configASSERT( xPayloadLength <= mqttexampleSTRING_BUFFER_LENGTH );
LogInfo( ( "Sending publish request on topic \"%.*s\"", xOutTopicLength, cOutTopicBuf ) );
xMQTTStatus = prvPublishToTopic( xQoS,
cOutTopicBuf,
xOutTopicLength,
( uint8_t * ) cPayloadBuf,
xPayloadLength,
mqttexampleNUM_PUBLISH_RETRIES );
デモの動作確認手順
モノの作成および初回の証明書/秘密鍵のダウンロード
AWSに接続してMQTTメッセージを送るために証明書/秘密鍵をダウンロードします。
下記iot-reference-rx
におけるGetting_Started_Guide.md
のStep 4-1: Run PubSub demo
記載の方法に従って、モノの作成および証明書/秘密鍵をダウンロードしてください。
プログラムの実行
v202210.01-lts-rx-1.1.2-device-location
ブランチからプロジェクトおよびソースコードをクローンしてから、e2 studioにaws_ryz014a_ck_rx65n
をインポートしてください。
使用するSIMカードに応じて、Cellular用の情報を設定してプログラムをビルドします。
その後、プログラムを実行して、下記step-4-1-6-input-via-cli-for-pubsub-demo
に従って、TeraTermでモノの名前
、エンドポイント名
、証明書
、秘密鍵
を入力してリセットします。
リセット後、数秒間経過するとデモが実行されます。
その前に、AWSマネジメントコンソール側のMQTTテストクライアントでCK-RX65Nから送信されたMQTTメッセージを待ち受けましょう。
トピックのフィルターは#
でサブスクライブすれば良いと思います。
最初に入力したモノの名前
、エンドポイント名
、証明書
、秘密鍵
を使用してAWSに接続した後に下記のようなトピックでAWSにMQTTメッセージを送信します。
MQTTテストクライアントを確認するとCK-RX65NからPublishされたメッセージを確認できます。
この情報をコピーしてデバイスの位置情報のペイロードを介して位置を解決する
にこの情報を張り付けて解決を押しましょう。
するとリソースの場所
に以下のような情報が表示されます。
coordinates
に表示されるのが緯度経度の情報です。
この情報をGoogle map
等の地図情報サービスに張り付けることでIoTデバイスの大体の位置情報を知ることができます。
私の場合、誤差500m
でIoTデバイスの大体の位置を取得することができました。
さいごに
今回はAWSの新機能であるAWS IoT Core Device LocationをRXファミリ用のFreeRTOS-LTSで試してみました。
イーサネットプロジェクトでも同じように試すことができると思いますが、家庭のLAN環境だとCK-RX65Nがルーターにぶら下がった状態でありプライベートIPアドレス
が割り当てられるため、AWS IoT Core Device Locationが使用できないと考えて、今回Cellular-RYZ014Aプロジェクトにデモを実装しました。
イーサネットプロジェクトでもグローバルIPアドレス
を知るためのWebサービス等を使用すれば同じようなことが実現可能だと考えます。
またさらに精度を高めるためにはGNSS スキャン結果メッセージ
をAWSに送信して、AWS IoT Core Device Locationの位置解決の情報として使用することができます。