M5stackからUDPでラズパイにメッセージ送信

M5stackをIoT端末として使うときにサーバー(この場合はラズパイ)にメッセージを送る必要がありますが、Wi-Fiが一番汎用性がありそう。

というわけで、UDP使ってメッセージを送ってみます。ラズパイ側はサーバーにNode.js使うので同じくNode.jsスタイルで記述します。

<M5stack側>

NTPサーバー使って現在時刻の取得、mDNS機能を使ってラズパイのアドレスを検索しています。参考サイトは、以下の通りです。

・タイムサーバーの使い方

https://kuracux.hatenablog.jp/entry/2018/10/08/160000

・IPアドレスを4オクテット記法に変換する

https://qiita.com/dojyorin/items/ac56a1c2c620782d90a6

#include <m5stack.h>
#include <WiFi.h>
#include <wifiudp.h>
#include <espmdns.h>


// Wi-Fi connection info.
const char* ssid     = "your said";
const char* password = "your pw";
const int port = 3002;

String string_buf = "message from M5stack";

//ntp server and time info
const char* ntpServer =  "ntp.nict.jp";
const long  gmtOffset_sec = 9 * 3600;
const int   daylightOffset_sec = 0;
struct tm timeinfo;

// The udp library class
WiFiUDP udp;

// mDNS target & M5stack
const String target_dev = "raspberrypi";
IPAddress ip;         // IPAdress of the target device
String ip_addr = "";  // 4 octet style target address
const char *mdns_name = "m5stick";  //M5stack mDNS name

// convert IP address to 4 octet style
String ipToString(uint32_t ip){
  String result = "";

  result += String((ip & 0xFF), 10);    // base number : 10
  result += ".";
  result += String((ip & 0xFF00) >> 8, 10);
  result += ".";
  result += String((ip & 0xFF0000) >> 16, 10);
  result += ".";
  result += String((ip & 0xFF000000) >> 24, 10);

  return result;
}

void mdns(){
  mdns_init();
  ip = MDNS.queryHost(target_dev);
  // target dev IP
  Serial.println("");
  Serial.print(target_dev + " : ");
  Serial.println(ip);
  // M5 self IP
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  ip_addr = ipToString(ip);
  // register mDNS name
  if (MDNS.begin(mdns_name)) {
    Serial.println("MDNS responder started");
  }
}

void print_wifi_state(){
	M5.Lcd.clear(BLACK);  // clear LCD
  M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.setCursor(3, 3);
	M5.Lcd.println("");
	M5.Lcd.println("WiFi connected.");
	M5.Lcd.print("IP address: ");
	M5.Lcd.println(WiFi.localIP());
	M5.Lcd.print("Port: ");
	M5.Lcd.println(port);
}

void setup_wifi(){
	M5.Lcd.setTextColor(RED);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(3, 10);
  M5.Lcd.print("Connecting to ");
  M5.Lcd.println(ssid);

	// setup wifi
  WiFi.mode(WIFI_STA);  // WIFI_AP, WIFI_STA, WIFI_AP_STA or WIFI_OFF
  WiFi.begin(ssid, password);
	// WiFi.begin();

	// Connecting ..
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    M5.Lcd.print(".");
  }

	// print state
  print_wifi_state();
  udp.begin(port);
  
  // mDNS
  mdns();
}

void setup() {
	M5.begin();
  Serial.begin(115200);
	// setup wifi
	setup_wifi();
    //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
}

void loop(){
    // get current rime
    if (!getLocalTime(&timeinfo)) {
      Serial.println("Failed to obtain time");
    return;
    }
    String cur_time = String(timeinfo.tm_year + 1900) 
      + "/" + String(timeinfo.tm_mon) 
      + "/" + String(timeinfo.tm_mday) 
      + " " + String(timeinfo.tm_hour) 
      + ":" + String(timeinfo.tm_min) 
      + " " + String(timeinfo.tm_sec) + " ";
    Serial.println(cur_time);

    //udp send
    const char *ipadr = ip_addr.c_str();
    udp.beginPacket(ipadr, port);
    // current time
    int i = 0;
    while( cur_time.length() > i){
      char tmp = cur_time.charAt(i);
      udp.write(tmp);
      i++;
    }
    // contents
    i = 0;
    while( string_buf.length() > i){
      char tmp = string_buf.charAt(i);
      udp.write(tmp);
      i++;
    }
    udp.endPacket();
    delay(1000);
}

 

<ラズパイ側>

Node.js配下のスクリプトです。

const dgram = require('dgram');
const port = 3002;
const client ='0.0.0.0';

const socket = dgram.createSocket('udp4');

socket.bind(port, client);

socket.on('message', (message, remote) => {
    console.log(remote.address + ':' + remote.port +' - ' + message);
});

参考サイトは、

・ラズパイのavahiユティリティのインストールと使い方

$ sudo apt-get install avahi-utils

Wi-Fi内のデバイスリスト

$ avahi-browse -at

・Node.jsのUDP通信ドキュメント

https://runebook.dev/ja/docs/node/dgram

・what’s socket.io

https://socket.io/docs/v4/

ラズパイ側の出力、

 

admin