Avance.Lab

実験

第6回 IoTを活用した社内備品管理システムを作る / マイコンから重量データを送信してみる

公開日:2024.09.27 更新日:2024.09.27

tag: IoTクラウド組み込み

こんにちは。Matsuです。
社内備品管理システム、前回までにマイコンやサーバ側APIなどの仕様を整理しました。
今回は、マイコンで測った重量をサーバに送信してみます。備品管理システムのコアになる機能のひとつですね。


マイコンをWiFiに接続する

過去の記事で、重量の測定を実際に試してみて、重量の送受信を含んだ仕様を検討してきました。

第3回 IoTを活用した社内備品管理システムを作る / 実際に重量測定してみる

第5回 IoTを活用した社内備品管理システムを作る / 仕様を検討する その2

これを踏まえて、計測した重量をWi-Fiで送信し、サーバで受信できるところを動かしてみます。
まずは、M5Stack Core2を使って社内のWi-Fiに接続してみます。
下記にWiFi接続箇所のコード抜粋を示します。

#include <Arduino.h>
#include <M5Unified.h>
#include <WiFi.h>
#include "esp_wifi.h"

//WiFi設定
const char* ssid = "xxxxxxxxxxx";
const char* pass = "xxxxxxxxxxx";

setup()
{

// 省略 //


// WiFi 接続開始
  Serial.printf("Connecting to %s\n", ssid);
  WiFi.disconnect(true, true);
  WiFi.mode(WIFI_STA);
  wifi_country_t country = {
    .cc = "JP",
    .schan = 1,
    .nchan = 14,
    .policy = WIFI_COUNTRY_POLICY_MANUAL,
  };
  esp_wifi_set_country(&country);
  WiFi.begin(ssid, pass);
  wl_status_t status = WiFi.begin(ssid, pass);
  display.setCursor(0,0);
  display.print("WiFi接続中");
  while (status != WL_CONNECTED) {
    status = WiFi.status();
    if (status == WL_NO_SSID_AVAIL) {
        WiFi.disconnect(true, true);
        WiFi.begin(ssid, pass);
        ESP.restart();
    }
    delay(500);
    display.print(".");
  }
  Serial.println("Connected.");

// 省略 //

}

処理の流れを説明します…

 WiFi.disconnect(true, true);

まず念の為、一旦切断する処理を呼びます。

WiFi.mode(WIFI_STA);

ステーションモード(M5Stackをクライアント側にしてルータへ接続しにいく)に設定します。

  wifi_country_t country =… esp_wifi_set_country(&country);

これはとりあえず置いておきます(次の章で解説します)。

WiFi.begin(ssid, pass);

指定のSSID、パスワードで接続します。

その後は、WiFi.status(); が WL_CONNECTED(接続済み)になるまで待ったり、駄目なときは再起動したりする処理が入っています。


社内のWi-Fiに接続できない!

実は最初、社内のWi-Fiだけどうやっても接続できないという問題がありました。
試しに別のルータに接続したり、家のWi-Fiに接続したりしてみましたが、そちらは問題なし。なんで~~!? となっていましたが、いろいろ切り分けていった結果…

・ ステルスSSID
 かつ
・ 13ch を使っている

の条件のときに接続できないということが分かりました。
この問題(仕様)については、ESPRESSIF(M5Stackで使っているマイコン ESP32のメーカ)の公式フォーラムに記載がありました。
Can’t connect to hidden network

一体どういうことかというと…

まず前提として、国ごとにWi-Fiに許可されているチャンネルの範囲に違いがあります。
(Wi-Fiには2.4GHz帯と5GHz帯がありますが、M5Stackでは2.4GHz帯しか使えませんので、すべて2.4GHz帯でのお話です)

出典:総務省資料「無線LANの現状」(PDF) より抜粋

上の総務省資料によると、2.4GHz帯において、次のチャンネルが許可されています。
(※資料では米国:5GHz帯…等とありますが、資料のページ自体が2.4GHz帯についての記載のため、5GHz帯というのは誤りのようです)
 米国:ch1~11
 日本:ch1~14

次に、M5Stackに使っているマイコンは、デフォルトでは米国の設定で動いています。つまり、2.4GHz帯はch1~11のみ許可されています

wifi_country_t config = {
    .cc = "01",
    .schan = 1,
    .nchan = 11,
    .policy = WIFI_COUNTRY_POLICY_AUTO,
};

ここで、さらにSSIDがステルスの場合、M5Stackから電波を発して探しに行く形になります(アクティブスキャン)。これが、デフォルトの国情報(米国)では nchan + 1 つまり12chまでしかアクティブスキャンしてくれないという仕様になっているそうです。(実は、13chであってもステルスSSIDでなければ、ルータ側からの信号を受けて米国の設定でも接続ができるようです)

ESP-IDF Programming GuideLogo » API Guides » Wi-Fi Driver

そのため、日本の情報(1~14chを許可するよ)を次のように設定してあげる必要があります。

wifi_country_t country = {
.cc = "JP",
.schan = 1,
.nchan = 14,
.policy = WIFI_COUNTRY_POLICY_MANUAL,
};
esp_wifi_set_country(&country);

これでようやく、社内のWi-Fiに接続することができました。よかった。


重量の送信

やっと社内Wi-Fiに接続することができたので、次は測定した重量をサーバに送信します。
サーバ担当の方に用意してもらったAPIにM5Stackからアクセスし、JSON形式でpostを送信します。

APIの仕様は、第5回の内容から「組み込みAPI仕様」の内容を再掲しておきます。

第5回 IoTを活用した社内備品管理システムを作る / 仕様を検討する その2

プロトコルPOST
パス/weights/
レスポンス正常:HTTP 204
異常:HTTP 400

リクエストボディ

{
	"scale_id": "String"	// 重量計ID
	"weight": 0.0		// 現在の重量(グラム)
}

このAPIにアクセスして重量を送信します。そのために、リクエストボディに使うJSONデータを作る必要があります。

JSONデータを作ってpostするためのコード抜粋を示します。

#include <Arduino.h>
#include <M5Unified.h>
#include <WiFi.h>
#include "esp_wifi.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "M5UnitWeightI2C.h"

const char *host = "xxxxxxxx.local";
JsonDocument doc;
char buffer[255];
char macAdr[24];
 // MACアドレス(コード例には無いが別途取得して格納している)

setup()
{
// 省略 //
}

loop()
{
// 省略 //
  post(weight); // 実際は測定した重量がweightに入ります。
}

// postで重量をサーバに送信
int post(float weight){
  doc["scale_id"] = macAdr;
  doc["weight"] = weight;
  serializeJson(doc, buffer, sizeof(buffer));

  HTTPClient http;
  http.begin(host, 8080, "/weights/");
  http.addHeader("Content-Type", "application/json");

  int status_code = http.POST((uint8_t*)buffer, strlen(buffer));
  http.end();
  return status_code;
}

JSON形式のデータの取り扱いには、ArduinoJsonライブラリを使っています。

https://github.com/bblanchon/ArduinoJson

  doc["scale_id"] = macAdr;
  doc["weight"] = weight;
  serializeJson(doc, buffer, sizeof(buffer));

上のようにJSONデータを作成します。

  HTTPClient http;
  http.begin(host, 8080, "/weights/");
  http.addHeader("Content-Type", "application/json");

ここで接続しにいくurlとportを設定します。

  int status_code = http.POST((uint8_t*)buffer, strlen(buffer));

設定した接続先に、JSONデータをpostします。
これで無事に重量の送信ができました。

受信の確認

M5Stackから重量の送信ができましたので、サーバ側で受信したデータを確認してみましょう。
担当者に受信データの表示機能を確認用に作ってもらったので、さっそく確認してみます。

無事、サーバ側で受け取れていることが確認できましたね!

次回は、サーバ側の実装などについてお話できればと思います。

Matsu

最近ガレージをつくってDIYにハマってしまう。
無限に欲しくなる電動工具が怖い。

関連記事