はじめに
LINE Beaconが気になりつつも触れていなかったので、opnizというIoTフレームワークでコントールできるか試してみました。
opnizでコントロールできるとどんなことができるかというと、ビーコンのstartやstopをNode.jsから任意のタイミングで切り替えたり、device message
というビーコンから送れる任意のメッセージを動的に変更できたりします。
それができることで何がうれしいかというと今のところパッと浮かばないのですが、何かできそうなポテンシャルはそこはかとなく感じているので、選択肢のひとつとして頭の片隅においておくといいことがあるかもしれません。
LINE Beacon実装にあたり参考にした記事
- LINE Beaconの擬似無限プッシュでLINE公式アカウント無料枠の制限に立ち向かう話 #linedc #iotlt
- 【ESP32 × LINE】たった2行でLINEビーコンが作れるライブラリをリリースしたよ
- Green Beacon ESP32 Library
LINE Beaconの実装は上記の記事を参考にGreen BeaconというLINE Simple BeaconのArduinoライブラリを使用させていただきました。
少ないコードでLINE Beaconが実装できてとても便利です!作者さまありがとうございます!
環境情報
-
デバイス:M5Stamp Pico
- M5Stack Japan Creativity Contest 2022の参加賞でゲットしたやつ
- M5ATOM Liteでも動作確認しています
-
開発環境
- OS:Windows10
- IDE:VS Code & PlatformIO
- Node.js:v16
ソースコード
Node.js(opniz & LINE Bot)
Node.jsのコードはopniz Node.js SDKをGreenBeacon用に拡張して制御するコードと、LINE BeaconからのWebhookを受けるBotサーバー用のコードの2つがあります。
Botサーバーのコードはopniz Node.js SDKのコードでimportして同時に動かしています。
{
"name": "opniz-line-beacon",
"version": "0.0.1",
"main": "index.mjs",
"type": "module",
"dependencies": {
"@line/bot-sdk": "^7.5.2",
"express": "^4.18.2",
"opniz": "^0.2.4"
}
}
import { Opniz } from "opniz"
import { LINEBot } from "./linebot.mjs"
const config = {
channelAccessToken: "<Channel Access Token>", // 書き換える
channelSecret: "<Channel Secret>", // 書き換える
}
const botPort = 3000 // 任意のポート番号でOK
const opnizPort = 3001 // 任意のポート番号でOK
const lineBot = new LINEBot({ config, port: botPort })
// GreenBeacon用opniz拡張クラス
class GreenBeacon extends Opniz.Esp32 {
async startBeacon(message = "") {
return Boolean(await this.exec("startBeacon", message))
}
async stopBeacon() {
return Boolean(await this.exec("stopBeacon"))
}
async setMessage(message = "") {
return Boolean(await this.exec("setMessage", message))
}
}
const opniz = new GreenBeacon({ port: opnizPort })
const main = async () => {
while (!(await opniz.connectWait({ timeout: 5000 }))) { console.log("connect..."); await opniz.sleep(100) }
console.log("[connected]")
try {
await opniz.startBeacon("test!") // LINE Beacon開始
// await opniz.stopBeacon() // LINE Beacon停止
// 動作テストとして1秒おきにデバイスのヒープメモリサイズを取得
for (;;) {
console.log(await opniz.getFreeHeap())
await opniz.sleep(1000)
}
} catch(e) {
console.log("[error]", e.message)
await main()
}
}
main()
// LINE BeaconからのWebhookを受けるBotサーバー
import express from "express"
import { Client, middleware } from "@line/bot-sdk"
export class LINEBot {
#bot
#app
constructor({ config, port }) {
this.#bot = new Client(config)
this.#app = express()
this.#app.post("/", middleware(config), this.#handleWebhook)
this.#app.listen(port)
}
#handleWebhook = (req, res) => {
const events = req.body.events
console.log(events)
events.forEach(this.handleEvent)
res.status(200).send("OK")
}
handleEvent = (event) => {
switch (event.type) {
case "message": this.handleMessage(event); break
case "beacon": this.handleBeacon(event); break
}
}
handleMessage = (event) => {
this.#bot.replyMessage(event.replyToken, {
type: "text",
text: event.message.text,
})
}
handleBeacon = (event) => {
const message = Buffer.from(event.beacon.dm, "hex").toString("utf-8")
this.#bot.replyMessage(event.replyToken, {
type: "text",
text: message,
})
}
}
M5Stamp Pico(PlatformIO)
$ cd lib
$ git clone https://github.com/miso-develop/opniz-arduino-esp32
$ git clone https://github.com/ukkz/green-beacon-esp32
[env:m5stack-atom]
platform = espressif32
board = m5stack-atom
framework = arduino
lib_deps =
links2004/WebSockets@^2.3.7
bblanchon/ArduinoJson@^6.19.4
monitor_speed = 115200
board_build.partitions = huge_app.csv
#include <OpnizEsp32.h>
#include <lib/WiFiConnector.h>
const char* ssid = "<Wi-Fi SSID>"; // 書き換える
const char* password = "<Wi-Fi Password>"; // 書き換える
const char* address = "<IP Address>"; // Node.js SDKを実行するマシンのIPアドレスへ書き換える
const uint16_t port = 3001; // 任意のポート番号でOK(Node.js SDKと合わせる)
const String hwid = "<Hardware ID>"; // LINE Official Account Managerのビーコンページで取得したハードウェアIDに書き換える
WiFiConnector wifiConnector(ssid, password);
Opniz::Esp32* opniz = new Opniz::Esp32(address, port);
#include "GreenBeacon.h"
GreenBeacon beacon;
// GreenBeacon関数用ハンドラ定義
class startBeaconHandler : public BaseHandler {
public:
String name() override { return "startBeacon"; };
String procedure(JsonArray params) override {
Serial.println("startBeacon");
String message = params[0];
Serial.println(message);
beacon.start(message);
return "true";
}
};
class stopBeaconHandler : public BaseHandler {
public:
String name() override { return "stopBeacon"; };
String procedure(JsonArray params) override {
Serial.println("stopBeacon");
beacon.stop();
return "true";
}
};
class setMessageHandler : public BaseHandler {
public:
String name() override { return "setMessage"; };
String procedure(JsonArray params) override {
Serial.println("setMessage");
String message = params[0];
Serial.println(message);
beacon.setMessage(message);
return "true";
}
};
void setup() {
Serial.begin(115200);
wifiConnector.connect();
beacon = GreenBeacon(hwid);
opniz->addHandler({
new startBeaconHandler,
new stopBeaconHandler,
new setMessageHandler,
});
opniz->connect();
}
void loop() {
opniz->loop();
wifiConnector.watch();
}
ハマったポイントと解決策
PlatformIOでGreenBeaconをインストールしたらバージョンが古かった
- PlatformIOでGreenBeaconをインストールしたあと、【ESP32 × LINE】たった2行でLINEビーコンが作れるライブラリをリリースしたよを参考に2行のコードを書いてみたけどエラー
- バージョンがv0.1.0だった(最新はv0.2.0)
- libディレクトリにGitHubリポジトリをcloneして最新版を使用して解決
- バージョンがv0.1.0だった(最新はv0.2.0)
書き込みサイズオーバー
- コンパイル後、書き込みしようとしたらサイズオーバーでエラー
- とりあえずググってみたらパーティションサイズを変更できるっぽい
- 参考
- テンプレートがいくつか用意されてる
-
huge_app.csv
という大容量アプリ向けのでいけそう
-
- platformio.iniに
board_build.partitions = huge_app.csv
と追記して書き込みで解決
- とりあえずググってみたらパーティションサイズを変更できるっぽい
メモリ不足
- 当初M5ATOM Liteで実装していたのですがパニックで再起動を繰り返す状況に
おわりに
ROM不足にRAM不足と普段なかなか経験しないようなマイコンならではのエラーに悩まされて楽しかったです。
無事opnizからLINE Beaconをコントロールできるようになったので、何かいい感じに使えたらまた記事にしてみたいと思います。