デバイスへudpパケット送信(VPN) (M5Stack)

サンプルソースコード

概要

前回のサンプル 「ラベル機能」を使用することで、サーバからクライアントに向けて指示を出すことができます。しかし、ラベル機能では、クライアント側からサーバにあるラベル(指示内容)を取りに行く必要があり、どうしてもリアルタイム性には欠けます。

今回は、「サーバからクライアントに向けて指示を出す」もう1つの方法である、udpパケット送信APIを利用してみます。
クライアント側でudpのポートを開けて待ち受け状態にしておき、サーバ側からAPIを使用してそこに向けてパケットを送信することで、よりリアルタイム性がある指示を出すことができます。


ソースコード
m5stack_iijiot_vpn_udp.ino
#include <M5Stack.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <WireGuard-ESP32.h>
#include "lwip/dns.h"
 
//--- TODO: WI-Fiルーターの SSIDとパスワードを指定してください
const char* ssid = "YOUR_SSID";
const char* pass = "YOUR_PASSWORD";
//---
 
//--- TODO: 自身のVPNアクセスの設定に書き換えてください。
const IPAddress local_ip(10, 10, 10, 10);               //IPアドレス
const char public_key[] = "YOUR PUBLIC KEY";            //公開鍵
const char private_key[] = "YOUR PRIVATE KEY";          //秘密鍵
const char endpoint_address[] = "vgw001.to.iot.iij.jp"; //接続先アドレス
const int endpoint_port = 9999;                         //接続先ポート番号
//---

const int udpPort = 9999;
 
WiFiUDP udp;
static WireGuard wg;

/*
  setup関数
*/
void setup() {
  //M5Stackを初期化
  M5.begin();
  M5.Power.begin();
 
  //Wi-Fi接続
  WiFi.begin(ssid,pass);
  M5.Lcd.printf("Waiting connect to WiFi: %s ", ssid);
  while(WiFi.status() != WL_CONNECTED) {
    //接続完了まで待つ
    delay(1000);
    M5.Lcd.print(".");
  }
  //接続完了したらIPアドレスとMacアドレスを表示する
  M5.Lcd.println("\nWiFi connected");
  M5.Lcd.print("IP address: ");
  M5.Lcd.println(WiFi.localIP());
  M5.Lcd.print("MAC address:");
  M5.Lcd.println(WiFi.macAddress());
  delay(500);

  //現在時刻をセット
  M5.Lcd.println("Adjusting system time...");
  configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com");
  delay(2000);  

  //WireGuardでVPN接続する
  M5.Lcd.println("Initializing WireGuard...");
  if (wg.begin(
      local_ip,
      private_key,
      endpoint_address,
      public_key,
      endpoint_port)) {

    M5.Lcd.println("VPN connected.");
    //--- DNS参照先をVPN側に向ける
    ip_addr_t dnsserver = IPADDR4_INIT_BYTES(10, 64, 2, 11);
    dns_setserver(0, &dnsserver);
  } else {
    M5.Lcd.println("WireGuard initializing Failed.");
  }
  delay(2000);

  //udp待受開始
  udp.begin(udpPort);
  M5.Lcd.println("Waiting udp packet...");
}
 
/*
  loop関数
*/
void loop() {
  //udpパケットを受信した場合
  if (int len = udp.parsePacket()) {
    //udpパケットを読み込む
    char buff[len + 1];
    memset(buff, '\0', sizeof(buff));
    udp.read((uint8_t*)buff, len);
    //読み込んだudpパケットを表示する
    M5.Lcd.printf("Recieved: %d byte(s)\n", len);
    M5.Lcd.println(buff);
  }
}
実行手順
  1. M5Stackで上記スケッチをビルドし、実行します。
    パケット待受状態の表示になります。
  2. PCから IoTサービスのコントロールパネルにログインします。
  3. メニューの「API」を開き、アクセスキー・シークレットアクセスキーをメモします。
    同様に、メニューの「デバイス」を開き、対象の「VPN」の Device ID をメモします。
  4. IIJ IoTサービス Web API のページを開き、以下のとおり操作します。

    1. 画面上部の "AccessKeyID" "SecretAccessKey" に、メモしておいた アクセスキー・シークレットアクセスキー を入力します。
    2. UDP送信API の欄を開き、画面上の "Try it out" ボタンを押します。
    3. "deviceId" の欄に、メモしておいた Device ID を入力します。

    4. "udpRequest" の欄に、送信先デバイスのポート番号と送信するペイロードをJSON形式で入力します。今回は、M5Stack に対して "udp packet test" という文字列を 9999番ポートに 送信します。

      {
        "port": 9999,
        "payload": "udp packet test"
      }
    5. 画面上の "Execute" ボタンを押すと API実行結果が表示されます。 202のレスポンスが返ってくればOKです。

  5. M5Stackの画面に、送信したパケットが表示されます。


各種情報へのリンク

IIJ IoTサービスマニュアル

M5Stack

WireGuard-ESP32-Arduino