Threadは、UDPを介したユニキャストおよびマルチキャスト伝送を使用して、アプリケーションフレームワークの実装に必要な基本サービスを提供します。
スレッドの仕様は、ネットワーク層にのみ焦点を当てています。多くのアプリケーション層は、アプリケーション層に依存しないため、問題なく実行するように設計できます。
このラボでは、Threadスタックがマルチホップネットワーク管理およびコミッショニングメッセージのほとんどにCoAPを使用するため、ユーザーはこのアプリケーション層のConstrain Application Protocol(CoAP)を使用します。
制約付きアプリケーションプロトコル(CoAP)は、モノのインターネット(Internet of Thing)の制約付きノードと制約付きネットワークで使用する専用のWeb転送プロトコルです。これは、4つのメソッドを持つバイナリRESTfulプロトコルを使用します
CoAP は ACK 応答も使用します。CONfirmable (ACK が要求されました) メッセージと NONconfirmable メッセージ。
Thread スタックは、マルチホップ ネットワーク管理およびコミッショニング メッセージの大部分に CoAP を使用します
このラボを通じて、ユーザーはファームウェアを変更して次のリストを実現します。
ラボが望ましい行動をとるプロセスを図1に示します。
図1 実験室の望ましい行動を示す図
設定
次のリストでは、ダッシュ (—) の付いたコンポーネントが、このラボの作成に使用されるコンポーネントです。
— 牧師 ある
— Thread Router Eligible Device プロジェクト
— テラターム
図2 FRDM-KW41Z
router_eligible_device_app.c ファイル では、次の変更が加えられます 。
1. シェルでリソースにアクセスするために使用する URI パス名を定義します。
#define APP_RESOURCE1_URI_PATH "/resource1"
#define APP_RESOURCE2_URI_PATH "/resource2"
2. URI リソースを coapUriPath_t で宣言します。この構造体を使用する場合、ユーザーは URI パスの長さと、最後の手順で作成したパスを入力する必要があります。
定数 coapUriPath_t gAPP_RESOURCE1_URI_PATH = {SizeOfString(APP_RESOURCE1_URI_PATH), APP_RESOURCE1_URI_PATH};
定数 coapUriPath_t gAPP_RESOURCE2_URI_PATH = {SizeOfString(APP_RESOURCE2_URI_PATH), APP_RESOURCE2_URI_PATH};
3. リソースのコールバックを作成します。このコールバックは、受信したパケットを処理し、受信したCOAPメソッドのタイプに応じて必要なアクションを実行します。
static void APP_CoapResource1Cb(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);
static void APP_CoapResource2Cb(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);
4.受信したパケットのコールバックハンドラを追加すると、この関数では、受信したCOAPメソッドのタイプに応じて実行されるアクションが定義されます。
static void APP_CoapResource1Cb(coapSessionStatus_t sessionStatus,void *pData,coapSession_t *pSession,uint32_t dataLen){ static uint8_t pMySessionPayload[3]={0x31,0x32,0x33}; 静的uint32_t pMyPayloadSize=3; coapSession_t *pMySession = NULL; pMySession = COAP_OpenSession(mAppCoapInstId); COAP_AddOptionToList(pMySession,COAP_URI_PATH_OPTION, APP_RESOURCE2_URI_PATH,SizeOfString(APP_RESOURCE2_URI_PATH)); if (gCoapConfirmable_c == pSession->msgType) { if (gCoapGET_c == pSession->code) { shell_write("'CON' パケットはペイロードと共に 'GET' を受け取りました: "); } if (gCoapPOST_c == pSession->code) { shell_write("'CON' パケットはペイロードと共に 'POST' を受信しました: "); } if (gCoapPUT_c == pSession->コード) { shell_write("'CON'パケットはペイロードを含む'PUT'を受信しました:"); } if (gCoapFailure_c!=sessionStatus) { COAP_Send(pSession, gCoapMsgTypeAckSuccessChanged_c, pMySessionPayload, pMyPayloadSize); } } else if(gCoapNonConfirmable_c == pSession->msgType) { if (gCoapGET_c == pSession->code) { shell_write("'NON' パケットはペイロードと共に 'GET' を受け取りました: "); } if (gCoapPOST_c == pSession->code) { shell_write("'NON' パケットはペイロードと共に 'POST' を受信しました: "); } if (gCoapPUT_c == pSession->code) { shell_write("'NON' パケットはペイロードと共に 'PUT' を受信しました: "); } } shell_writeN (pData, dataLen); shell_write("\r\n"); pMySession -> msgType=gCoapNonConfirmable_c; pMySession -> コード = gCoapPOST_c; pMySession -> pCallback =NULL; FLib_MemCpy(&pMySession->remoteAddr,&gCoapDestAddress,sizeof(ipAddr_t)); COAP_SendMsg(pMySession, pMySessionPayload, pMyPayloadSize); shell_write("'NON'パケットはペイロード付きで'POST'を送信しました: "); shell_writeN((char*) pMySessionPayload, pMyPayloadSize); shell_write("\r\n"); } |
アプリケーションが 1 つのポートのみを使用する場合は、UDP ポートごとに 1 つの COAP インスタンスが存在する可能性があります。
インスタンスごとに複数の COAP セッションが存在する可能性があり、COAP セッションはパケット/トランザクションごとです。この場合、ACK の応答が異なることが望ましい結果であったため、新しいリソースを使用して新しいセッションを作成する必要があります。
static void APP_CoapResource2Cb(coapSessionStatus_t sessionStatus,void *pData,coapSession_t *pSession,uint32_t dataLen){ if (gCoapNonConfirmable_c == pSession->msgType) { shell_write("'NON' パケットは 'POST' をペイロードと共に受信しました: "); shell_writeN(pData, dataLen); shell_write("\r\n"); } } |
5. コールバックを作成した後 、コールバックは関数 APP_InitCoapDemo(void) の CoAP コールバック配列に登録する必要があります
{APP_CoapResource1Cb, (coapUriPath_t*)&gAPP_RESOURCE1_URI_PATH},
{APP_CoapResource2Cb, (coapUriPath_t*)&gAPP_RESOURCE2_URI_PATH},
CoAPライブラリの使用については、このラボでは使用されなかったが、他のタイプのアプリケーションに役立つ可能性のある点がいくつかあります。
COAP_SendMsg() を使用すると 、 pSession->autoClose の使用方法で示されない限り、セッションはデフォルトで自動的に閉じ ます。
メッセージの送信には、次の 2 つのオプションがあります。
確認可能(CON):ACKの応答を待ち、メッセージを受け取るまでセッションを閉じるか、再送信が使い果たされたときにセッションを閉じます。
確認不可 (NON
メッセージが送信され、応答がなかった場合、再送信はCOAP_ACK_TIMEOUTごとに(ミリ秒単位)送信され、再送信は指数関数的に送信されます:最初はランダム(2、3)秒後、次にタイムアウトを2倍にするなど、COAP_MAX_RETRANSMITに達するまで続きます。
再送信が停止すると、セッションは自動的に閉じられ、アプリケーションにエラーが通知され、ステータス gCoapFailure_c でアプリケーションコールバックが呼び出されます。
コールバックが呼び出されても、現在のセッションはまだ有効ですが、CoAP セッションは関数の終了後にコールバックを閉じます。これには2つの異なる作業があります。
新しいセッションを作成する必要があります
auto>Close が FALSE に設定されている場合は、アプリケーションからセッションを閉じることを忘れないでください。COAP_CloseSession() を使用して、アプリケーションからセッションを閉じることを忘れないでください 。
1. 変更したファームウェアをボードにダウンロードします
2. 各ボードのシリアル端子をボーレート 115200 で開きます
図3 シリアル端末とその構成
3. ボードの端末タイプ「thr create」の1つでは、このボードがリーダーになります。
図 4 ボード 1 とコマンド "thr create"
図 5 ボード 1 のコマンド「thr create」の後
4.ネットワークが作成されたら 、2番目のボードの端末に 「thrjoin」 と入力します。
図 6 「thr join」コマンドが設定されたボード 2
図 7 ボード 2 のコマンド "thr join" の後
5. 両方のシリアル端末で、コマンド「ifconfig」を入力します。このコマンドは、ボードのすべてのアドレスを表示します。
図 8 ボード 1 のコマンド "ifconfig" の後
図 9 ボード 2 のコマンド "ifconfig" の後
6. 作成されたコールバックをテストするには、CoAP メッセージを送信する必要があります。次のコマンドを入力する必要があります。
coap
|
coap CON POST fe80::5df0:2bf0:d69b:1b3c /resource1 hello
|
図 10 送信する CoAP コマンド
7. 送信の結果は、次のようになる必要があります。
― ボード1
ボード 1 は、ボード 2 にリソース1を要求します
図 11 CoAP コマンドを送信する前のボード 1
コード化されたとおりに、他のボードはACKを送信し、メッセージを印刷します。
図 12 CoAP コマンドを送信した後のボード 1
— ボード2
図 13 CoAP コマンドを受信した後のボード 2
CON メッセージを使用する場合、リクエスターボードは応答を受け取りますが、メッセージが NON T ype の場合、応答はありません。
このタイプのメッセージをパッケージタイプとは無関係に使用すると、メッセージの送信時に新しいセッションがオープンされ、NON タイプのメッセージが送信されます。