🐝

ESP32でDiscord Webhookを使ってみる

に公開

はじめに

ESP32から簡単にメッセージを送れるLINE Notifyのサービスがが2025年3月31日に終了しました。
この記事では、LINE Notifyの代替として、Micropythonを使ってDiscordのWebhookサービスにESP32からアクセスしてメッセージを送る方法について解説します。

チャンネルの連携サービスでWebhook用のURLを設定する方法についてはこの記事では触れませんので、他の記事を参考にして下さい。

からあげさんのDiscordにPythonで投稿する方法(bot/Webhook)などの記事が参考になると思います。

DiscordのWebhookについて

DiscordのWebhook(ウェブフック)は、外部サービスからDiscordの特定のチャンネルにメッセージを自動的に送信するための便利な機能です。Webhookを利用することで、特定のイベントが発生した際にリアルタイムで情報を共有することが可能になります。

自分が所属するチャンネルの連携サービスでWebhookが有効になっており、そのURLを知っていればWebhookの機能を使用することができます。

例えば、ESP32開発キットに接続されているセンサのデータをWebhookを使ってDIscordに送信することができます。

WebhookとBotの違い

DiscordのサービスにはWebhookの他にBotというのもあります。
Botはユーザーのように振る舞い、メッセージの送信、役割の変更、サーバーの管理など、さまざまな機能を提供します。

Webhook

外部サービスからDiscordへの一方向の通信に特化しており、シンプルな通知に最適です。
Discord Webhookの詳細については以下のドキュメント(英語)を参照して下さい。

https://discord.com/developers/docs/resources/webhook#webhook-object-webhook-types

Bot

Discordと双方向に通信し、より複雑な処理を実行できます。Botはインタラクティブな機能が必要な場合に適しています。

テキストを送信する

次のサンプルコードはテキストを送信するものです。

discord_text.py
# Apr. 29th 2025

import requests
import network
import json
from time import sleep

WIFI_SSID = 'WiFIのSSID'
WIFI_PASS = 'WiFiのパスワード'

# DiscordのチャンネルURL
url = 'ここにURLを入力'

# 送信するメッセージとユーザ名をセット
MESSAGE = "みなさん、こんにちは。山田太郎です。ESP32からメッセージを送っています。"
USER = 'AA0101 山田太郎'

# WiFi接続関数
def connect_wifi():
    wifi = network.WLAN(network.STA_IF) 
    wifi.active(True)
    sleep(0.5)
    
    while not wifi.isconnected():
        print("Connecting to WiFi", end="")
        wifi.connect(WIFI_SSID, WIFI_PASS)
        sleep(1)
        while not wifi.isconnected():
            print(".", end="")
            sleep(1)
            pass
       
    ip = wifi.ifconfig()[0]
    rssi = wifi.status('rssi')
    return ip, rssi

# Discordメッセージ送信関数
def discord_send(message, user):
    # 辞書型データ作成
    data = {
        'content': message,  # メッセージ内容
        'username': user
    }

    # 辞書型のdataをJSON形式の文字列に変換し、UTF-8にエンコーディング
    json_data = json.dumps(data).encode("utf-8")

    # ヘッダー作成
    header = {
        "content-type": "application/json; charset=utf-8"
    }

    print(json_data)

    # DiscordのWebhookに送信
    response = requests.post(url,  data=json_data, headers=header)

    if response.status_code == 204:
        print("メッセージが送信されました。")
    else:
        print(f"エラーが発生しました: {response.status_code}")
        print(response.text)


# ここからメイン
if __name__ == '__main__':
    # WiFi接続
    ip, rssi = connect_wifi()
    print("IP:", ip, "RSSI:", str(rssi))

    # Discordメッセージ送信
    discord_send(MESSAGE, USER)


response.statusで返されるステータスコードの種類

  • 204 No Content: メッセージが正常に送信されたことを示します。この場合、レスポンスボディは空です。

  • 400 Bad Request: リクエストに問題がある場合に返されます。例えば、contentフィールドが空である場合や、JSONの形式が正しくない場合に発生します。

  • 401 Unauthorized: Webhook URLが無効であるか、アクセス権がない場合に返されます。URLを再確認する必要があります。

  • 403 Forbidden: Webhookの使用が禁止されている場合に返されます。サーバーの設定を確認する必要があります。

  • 404 Not Found: 指定したWebhook URLが存在しない場合に返されます。URLが正しいか確認してください。

  • 429 Too Many Requests: 短時間に多くのリクエストを送信した場合に返されます。この場合、リクエストを一時的に制限されることがあります。

  • 500 Internal Server Error: Discordのサーバー側でエラーが発生した場合に返されます。この場合、しばらく待ってから再試行することが推奨されます。

参考: 辞書型とJSON型の違い

以下は生成AI(felo.ai)の回答です。

辞書型(dict型)

データ構造:

Pythonの辞書型は、キーと値のペアを持つ可変(mutable)なデータ構造です。辞書は順序を持たず、キーはハッシュ可能なオブジェクトであれば何でも使用できます。
例:

my_dict = {
    'name': 'Alice',
    'age': 30,
    'is_student': False
}

アクセス方法:

辞書の値には、キーを使ってアクセスします。

print(my_dict['name'])  # 出力: Alice

JSON(JavaScript Object Notation)

データフォーマット: JSONはデータ交換のための軽量なフォーマットで、主にテキスト形式でデータを表現します。JSONは言語に依存せず、さまざまなプログラミング言語で使用できます。
構文: JSONでは、キーは必ず文字列でなければならず、値は文字列、数値、配列、オブジェクト、真偽値、またはnullのいずれかです。
例:

{
    "name": "Alice",
    "age": 30,
    "is_student": false
}

主な違い

データ型:

辞書型はPythonのデータ型であり、プログラム内で直接操作できます。
JSONは文字列として表現され、データ交換のためのフォーマットです。

キーの制約:

辞書型のキーは任意のハッシュ可能なオブジェクト(例えば、数値やタプルなど)を使用できます。
JSONのキーは必ず文字列でなければなりません。

使用目的:

辞書型はPythonプログラム内でデータを管理するために使用されます。
JSONはデータを他のシステムや言語と交換するために使用されます。

変換:

Pythonのjsonモジュールを使用して、辞書型とJSON形式の相互変換が可能です。
例えば、json.dumps() を使って辞書をJSON文字列に変換し、json.loads() を使ってJSON文字列を辞書に変換します。
例: 辞書型からJSONへの変換

import json

my_dict = {'name': 'Alice', 'age': 30}
json_string = json.dumps(my_dict)  # 辞書をJSON文字列に変換
print(json_string)  # 出力: {"name": "Alice", "age": 30}

例: JSONから辞書型への変換

json_string = '{"name": "Alice", "age": 30}'
my_dict = json.loads(json_string)  # JSON文字列を辞書に変換
print(my_dict['name'])  # 出力: Alice

このように、辞書型とJSON型は似た構造を持っていますが、用途や特性が異なります。

Discussion