7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

M5StackでSymbolリスナーを作ってみた

Posted at

はじめに

Twitterでスタックチャンを見かけるようになり、M5Stack-core2を衝動買いしました。
有志の方の助けを借りてChatGPTとGoogleTTSで喋るスタックチャンは開発できました!

しかし、M5Stackで何が出来るのか全くわかっていない状態なので基礎的な部分を
学んだついでにSymbolブロックチェーンを監視するための簡単な仕組みを作ってみました。

Symbolブロックチェーンってなんぞやという方はこちらを参照してください。
コミュニティの方がドキュメントをまとめてくださっています。

スタックチャンとはなんぞやという方はこちらを参照してください。

記事は読まなくていいからコードはよ!というかたはこちら。

目次

  1. 動かした時の画像
  2. 環境構築
  3. 使っている機能
  4. 参考文献

動かした時の画像

image.png
image.png
image.png

環境構築

  1. vscodeのインストール
  2. vscode拡張機能PlatformIO IDEをインストール
  3. M5Stack-Symobl-Listenerをクローン
  4. ビルド&書き込み

問題なく実機に書き込みまでできればSDカードからwifi接続情報を読取り、
wifi接続が行われます。

そもそもM5Stack使ったことない人はUSBシリアルドライバが必要なので参考文献の「M5Stack の開発環境を準備する」
からドライバインストールしておいてください。

使っている機能

1. SDカード読込

SDカードの読み書きはよく使うので覚えておきましょう!

  // SDカード読込
  File f = SD.open("/wifi.txt", FILE_READ);
  
  // SDカードが読み込めたかどうか
  if (f) {
    M5.Lcd.println("open SD");
    String line;

    // ファイルのサイズを取得
    size_t sz = f.size();
    
    // ファイルの内容を格納するバッファを確保
    char buf[sz + 1];

    // ファイルの内容を読み込む
    f.read((uint8_t*)buf, sz);
    
    // バッファの終端にヌル文字を追加
    buf[sz] = 0;
    
    // ファイルを閉じる
    f.close();

    int y = 0;
    for(int x = 0; x < sz; x++) {
      if(buf[x] == 0x0a || buf[x] == 0x0d)
        buf[x] = 0;
      else if (!y && x > 0 && !buf[x - 1] && buf[x])
        y = x;
    }
    M5.Lcd.print(line);
  } else {
    M5.Lcd.print("Failed to open file for reading");
  }

2. wifi接続

使う場合はタイムアウトを設定してください!

    // WiFi接続
    WiFi.begin(buf, &buf[y]);
    
    // WiFi接続待ち
    while (WiFi.status() != WL_CONNECTED) {
      //M5.Lcd.println("wifi no connected");
      delay(500);
      M5.Lcd.print(".");
    }

    M5.Lcd.println("wifi connected");
    M5.Lcd.println(WiFi.localIP());

3. websocket client

symbolノードにwebsocket接続する場合はwss://NODE:3001/wsとなるので
beginSSLで接続します。ws://の場合はbeginでOK!

    // server address, port and URL
    webSocket.beginSSL("mikun-testnet.tk", 3001, "/ws");

    // event handler
    webSocket.onEvent(webSocketEvent);

    // try ever 5000 again if connection has failed
    webSocket.setReconnectInterval(5000);

/**
 * @brief WebSocketイベント
*/
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {

  // 画面初期化
  initScreen();

  switch(type) {
		case WStype_DISCONNECTED:
      M5.Lcd.print("[WSc] Disconnected!\n");
			break;
		case WStype_CONNECTED:
      M5.Lcd.printf("[WSc] Connected to url: %s\n", payload);
			break;
		case WStype_TEXT:
        {
          DynamicJsonDocument json_payload(1024);
          DeserializationError error = deserializeJson(json_payload, (const char*)payload);
          if (error) {
            M5.Lcd.print(F("deserializeJson() failed: "));
            M5.Lcd.println(error.c_str());
            uid = "";
          }else{
            if(json_payload.containsKey("uid")) {
              uid = json_payload["uid"].as<String>();
          
              // uncomfirmedを購読
              subscribeUncomfirmed(uid);
              // comfirmedを購読
              subscribeComfirmed(uid);

            } else{
              M5.Lcd.println(json_payload["topic"].as<String>());
              M5.Lcd.println(json_payload["data"]["meta"]["hash"].as<String>());
            }
        
          }
    			break;
        }

		case WStype_BIN:
			M5.Lcd.printf("[WSc] get binary length: %u\n", length);
			hexdump(payload, length);
			break;
		case WStype_ERROR:
          M5.Lcd.printf("[WSc] get error: %s\n", payload);
          break;
		case WStype_FRAGMENT_TEXT_START:
          M5.Lcd.print("WStype_FRAGMENT_TEXT_START");
          break;
        case WStype_FRAGMENT_BIN_START:
          M5.Lcd.print("WStype_FRAGMENT_BIN_START");
          break;
		case WStype_FRAGMENT:
          M5.Lcd.print("WStype_FRAGMENT");
          break;
		case WStype_FRAGMENT_FIN:
          M5.Lcd.print("WStype_FRAGMENT_FIN");
			break;
	}
}

4. symbol

symbolノードにwebsocket接続をリクエストした場合、はじめにUIDが返却されます。
そのUIDをもとにunconfirmed,confirmedを購読するリクエストを投げて始めて監視が出来るようになります。
他にもblockを購読することもできます。(※blockについては記載していません。)

購読部分はこんな感じ

/**
 * @brief Uncomfirmed
*/
void subscribeUncomfirmed(String uid){
  String message = "{\"uid\":\"" + uid + "\", \"subscribe\":\"unconfirmedAdded/" + ADDRESS + "\"}";
  webSocket.sendTXT(message);
  M5.Lcd.println("subscribe unconfirmedAdded");
}

/**
 * @brief Comfirmed
*/
void subscribeComfirmed(String uid){
  String message = "{\"uid\":\"" + uid + "\", \"subscribe\":\"confirmedAdded/" + ADDRESS + "\"}";
  webSocket.sendTXT(message);
  M5.Lcd.println("subscribe confirmedAdded");
}

最後に

ADDRESSはできればSDカードに格納し、複数のアドレスを関し出来る状態にしたほう
が良かったかなと思います。

今後はSDカードから画像や音声ファイルを読み出し、
トランザクションを検知したタイミングでスタックチャンに喋ってもらう!
とかやってみたいですね。c++ムズカシイィィ!ではまた!

参考文献

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?