Line Notifyのサービス終了に伴う代替手段としてのDiscord導入について
Line Notifyは、IoTデバイスや各種サービスから通知を受け取る手軽な手段として利用されてきました。しかし、サービス終了により、新たな通知手段の確立が求められる状況となりました。この状況に対応するため、本コードでは、Line Notifyの代替サービスとしてDiscordのWebHook機能を利用し、通知メッセージを送信する仕組みを実装しました。
Discordを選んだ理由
- 無料で利用可能
Discordは基本的な利用が無料で提供されており、通知機能を含む多くの機能をコストゼロで利用できます。 - WebHook機能の柔軟性
DiscordのWebHook機能は、HTTPリクエストを通じて簡単にメッセージを送信できるため、既存のIoTデバイスやプログラムとの統合が容易です。 - リッチな通知
Discordでは、単なるテキストメッセージだけでなく、埋め込みメッセージやファイル添付も可能なため、通知内容を柔軟に拡張できます。 - 信頼性とサポート
世界中で広く利用されているプラットフォームであるため、安定した通知サービスとして期待できます。
本コードの概要
このコードでは、温度センサー(DS18B20)を使用して取得したデータをDiscordのWebHookを通じて通知します。また、データはAmbientにも送信されるため、履歴管理や可視化も可能です。
具体的な機能は以下の通りです:
- 温度データの取得
- DS18B20センサーを使用して温度データを読み取ります。
- センサーの省電力運用のため、必要なタイミングでセンサーの電源をオン・オフします。
- 異常値検知
- 温度が特定の閾値(例: 28°C以上またはエラー値)を超える場合に、通知を送信します。
- 通知の送信
- DiscordのWebHookを使用して、温度データやアラートをテキストメッセージとして送信します。
- 通知内容には、デバイスIDや具体的な測定値が含まれます。
- 省電力設計
- 温度測定後、デバイスを一定時間ディープスリープ状態にすることで、電力消費を最小限に抑えます。
DiscordのWebHook機能の仕組み
DiscordのWebHookは、特定のチャネルにデータを投稿するためのエンドポイント(URL)を提供します。このエンドポイントに対してHTTPリクエストを送信するだけで、メッセージを簡単に投稿できます。本コードでは、この仕組みを利用して、温度センサーから取得したデータや警告メッセージをリアルタイムで送信します。
実装のポイント
- WebHookの設定
- DiscordでWebHookを作成し、エンドポイントURLを取得します。このURLは本コード内で
DISCORD_WEBHOOK
として指定します。
- DiscordでWebHookを作成し、エンドポイントURLを取得します。このURLは本コード内で
- センサーの省電力制御
- センサーの電源を操作するピンを設定し、必要なときだけセンサーを有効化します。
- エラーハンドリング
- センサーのデータ読み取りが失敗した場合や、通信が失敗した場合にも、適切にエラーメッセージを送信します。
- ディープスリープの活用
- デバイスを測定後にスリープさせることで、バッテリー駆動時の運用効率を向上させています。
動作概要
このプログラムは、DS18B20温度センサーを使用して温度データを読み取り、それをDiscordとAmbientに送信します。電源効率のため、センサーの電源は必要な時のみオンにし、使用後にオフにします。また、デバイスはデータ送信後にディープスリープ状態に入り、5分後に再起動します。
/*
DS18B20センサーの値をDiscordおよびAmbientにWebHookを使用して送信します。
OneWire、DallasTemperature、Ambientライブラリが必要です。
*/
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Discord_WebHook.h>
#include <Ambient.h>
#include <WiFiClient.h>
#include <esp_wifi.h>
#include <esp_sleep.h>
Discord_Webhook discord;
Ambient ambient;
WiFiClient client;
// 個体ごとのID
const char* kotaiID = "1";
// Discord Webhook URL
String DISCORD_WEBHOOK = "https://discord.com/api/webhooks/";
// **電源制御ピン (XIAO ESP32C3: GPIO20 = D7)**
const int SENSOR_POWER_PIN = 20;
// **DS18B20 のデータ線 (XIAO ESP32C3: GPIO4 = D2)**
const int ONE_WIRE_PIN = 4;
// Deep Sleep 時間(5分)
const uint64_t SLEEP_DURATION_US = 5 * 60 * 1000000ULL;
// OneWire & DS18B20
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
// WiFi設定
const char* WIFI_SSID = "SSID";
const char* WIFI_PASSWORD = "PASS";
// Ambient設定
const char* userKey = "ユーザーキー";
char devKey[20];
unsigned int channelId;
char writeKey[20];
void setup() {
Serial.begin(115200);
// **GPIO 初期化**
pinMode(SENSOR_POWER_PIN, OUTPUT);
digitalWrite(SENSOR_POWER_PIN, LOW);
pinMode(ONE_WIRE_PIN, INPUT_PULLUP);
// **WiFiはDeep Sleep後オフの状態に**
WiFi.mode(WIFI_OFF);
esp_wifi_stop();
// **MACアドレス取得**
uint8_t mac[6];
esp_read_mac(mac, ESP_MAC_WIFI_STA);
sprintf(devKey, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
// **センサーの電源ON**
digitalWrite(SENSOR_POWER_PIN, HIGH);
delay(500);
sensors.begin();
// **温度測定(リトライ付き)**
float temperature = -127.0;
int retries = 3;
for (int i = 0; i < retries && temperature == -127.0; i++) {
sensors.requestTemperatures();
delay(1000);
temperature = sensors.getTempCByIndex(0);
}
Serial.print("Temperature: ");
Serial.println(temperature);
// **Discord 送信判定**
bool sendToDiscord = false;
String discordMessage = "";
if (temperature == -127.0) {
discordMessage = "⚠️ DS18B20 read failed. Temp: -127.0°C. Check sensor connection!";
sendToDiscord = true;
} else if (temperature > 28.0) {
discordMessage = "🔥 異常温度検出: " + String(temperature) + "°C. ID: " + String(kotaiID);
sendToDiscord = true;
}
// **WiFi接続(温度が取得できた場合のみ)**
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
unsigned long startAttemptTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
delay(100);
}
if (WiFi.status() == WL_CONNECTED) {
// Serial.println("WiFi Connected, IP: " + WiFi.localIP().toString());
// **Discord通知**
if (sendToDiscord) {
discord.begin(DISCORD_WEBHOOK);
discord.send(discordMessage);
}
// **Ambient初期化**
if (!ambient.getchannel(userKey, devKey, channelId, writeKey, sizeof(writeKey), &client)) {
Serial.println("Failed to get Ambient channel!");
} else {
// **writeKey の終端を正しく設定(`}` や `"` が余分についていた場合、削除)**
for (int i = 0; i < sizeof(writeKey); i++) {
if (writeKey[i] == '}' || writeKey[i] == '"') {
writeKey[i] = '\0';
break;
}
}
// Serial.printf("channelId: %d, writeKey: %s\r\n", channelId, writeKey);
// Serial.print("Corrected WriteKey: ");
// Serial.println(writeKey);
// **Ambientへ温度送信**
ambient.begin(channelId, writeKey, &client);
ambient.set(1, temperature);
// Serial.print("Sending to Ambient - d1: ");
if (ambient.send()) {
Serial.println("Ambient send OK");
delay(2000); // WiFi切断前に2秒待機(確実に送信完了するため)
} else {
Serial.println("Failed to send data to Ambient");
}
}
} else {
Serial.println("WiFi connection failed!");
}
// **WiFi OFF**
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
esp_wifi_stop();
// **センサー電源OFF**
digitalWrite(SENSOR_POWER_PIN, LOW);
// **UART OFF(省電力化)**
Serial.end();
// **Deep Sleep**
esp_sleep_enable_timer_wakeup(SLEEP_DURATION_US);
esp_deep_sleep_start();
}
void loop() {
// Deep Sleep後は setup() が再実行されるため、loop() は不要
}
コードの詳細な説明:
- ライブラリのインクルード
以下のライブラリを使用しています:OneWire
: センサーとの通信をサポート。DallasTemperature
: DS18B20センサーの温度読み取りに使用。Discord_WebHook
: Discord WebHookでデータを送信。Ambient
: Ambientプラットフォームにデータを送信。WiFiClient
: Wi-Fi通信のため。
- 設定項目
kotaiID
: デバイスの個体識別用ID。DISCORD_WEBHOOK
: Discord WebHookのURLSENSOR_POWER_PIN
: センサーの電源制御ピン(GPIO7)。ONE_WIRE_PIN
: OneWire通信用ピン(GPIO6)。userKey
: Ambientユーザキー。
📌 処理の流れ 1️⃣ 初期設定 SENSOR_POWER_PIN (GPIO7) を 温度センサーの電源制御用 に設定し、最初は OFF にする ONE_WIRE_PIN (GPIO6) を DS18B20 のデータ通信ピン として設定 WiFi を OFF にして、無駄な電力を消費しないようにする 2️⃣ 温度測定 センサーの電源を ON (digitalWrite(SENSOR_POWER_PIN, HIGH)) 750ms 以上の待機時間 を確保し、センサーの起動を待つ 温度を取得 (sensors.getTempCByIndex(0)) 3回までリトライ可能(最初の測定で失敗することがあるため) 3️⃣ Discord への通知 センサーが測定に失敗した(-127.0℃)場合 Discord に「⚠️ DS18B20 read failed.」を通知 温度が 28.0℃ 以上の場合 Discord に「🔥 異常温度検出: 〇〇°C.」を通知 4️⃣ WiFi接続 Discord へ通知または Ambient へ送信が必要な場合のみ WiFi を ON にして接続 WiFi 接続を最大 10秒間待機(失敗時はスキップ) 5️⃣ Ambient へ温度データを送信 Ambient に接続し、温度データを送信 WiFi 切断前に 2秒待機して、送信を確実に完了させる 6️⃣ 電力を節約するための処理 WiFi を OFF(WiFi.disconnect(true); & esp_wifi_stop();) 温度センサーの電源を OFF(digitalWrite(SENSOR_POWER_PIN, LOW);) シリアル通信(UART)を OFF(Serial.end();) ESP32-C3 を Deep Sleep(スリープモード)にする(esp_deep_sleep_start();) 5分後に再起動し、再び温度測定を開始 📌 このコードの特徴 ✅ バッテリー駆動向けに省電力最適化 ✅ 温度異常時のみ Discord に通知し、無駄なアラートを削減 ✅ WiFi の使用時間を最小限にし、不要な接続を防ぐ ✅ Deep Sleep を活用して動作間隔を 5分ごとに設定 ✅ 温度測定のリトライ処理を実装し、信頼性向上
専用基板
DS18B20を2本実装可能 その他BME280搭載 温湿度・気圧センサモジュール用ピン、バッテリー電圧監視用ピンを取り出した。


Discordの画面

今後の展望
DiscordのWebHook機能を使用した通知システムは柔軟性が高いため、将来的には以下のような拡張も可能です:
- 複数のデータフィールドやセンサーを統合して、より詳細な通知を実現。
- データの可視化や分析のために、他のクラウドサービスと連携。
- 通知内容の多言語化やカスタマイズ。
Line Notifyからの移行に伴い、今回のコードは代替手段として適切な機能を提供するものです。Discordを活用することで、今後も信頼性の高い通知システムを維持することが期待されます。
- 参考URL
- Discordでメッセージを送信
- https://projecthub.arduino.cc/usini/send-a-message-on-discord-9d87d3
- 複数台のIoT端末を同一プログラムで動かす
- https://ambidata.io/docs/getchannel/
コメント
この記事へのトラックバックはありません。
この記事へのコメントはありません。