ESP32でネットワークから操作可能な赤外線リモコンを作った

概要

ESP32で赤外線リモコンを作ります。前作ったラズパイリモコンから部品は全て流用しました。

プログラム

ESP32

赤外線のコード自体はESP32に保存せず、POSTリクエストでESP32に送りつける感じにします。
これで新しいコードを追加するごとに書き込まなくて済みます。

#include <Arduino.h>
#include <WiFi.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <WebServer.h>
#include <ArduinoJson.h>

// WiFi credentials
const char* ssid = "SSID";  // Replace with your SSID
const char* password = "Pass";  // Replace with your Password
const IPAddress ip(192, 168, 100, 51); // 好きなIPに変えて
const IPAddress gateway(192, 168, 100, 1);
const IPAddress subnet(255, 255, 255, 0);
const IPAddress dns1(192, 168, 100, 1);

// Webserver
WebServer server(80);

// LED
const uint16_t kIrLed = 4; // LEDを刺したピン
IRsend irsend(kIrLed);

// コード受け取って発信
void sendIrCode(JsonArray rawData) {
  uint16_t rawArray[rawData.size()];
  for (size_t i = 0; i < rawData.size(); i++) {
    rawArray[i] = rawData[i];
  }
  Serial.println("Sending IR code...");
  irsend.sendRaw(rawArray, rawData.size(), 38);  // 38kHzで送信
}

// POSTで送られてきたIRコードを処理
void handleSendIR() {
  if (server.hasArg("plain")) {
    String jsonString = server.arg("plain");

    // JSONパース
    DynamicJsonDocument doc(1024);
    DeserializationError error = deserializeJson(doc, jsonString);

    if (error) {
      server.sendHeader("Access-Control-Allow-Origin", "*"); // CORS対応
      server.send(400, "application/json", "{\"error\":\"Invalid JSON\"}");
      return;
    }

    // JSONからデータを取得
    JsonArray rawData = doc["code"];
    sendIrCode(rawData);

    server.sendHeader("Access-Control-Allow-Origin", "*"); // CORS対応 ここらへんがないとHTMLでPOSTできない(CURLからはなくてもできた)
    server.send(200, "application/json", "{\"status\":\"IR code sent\"}");
  } else {
    server.sendHeader("Access-Control-Allow-Origin", "*"); // CORS対応
    server.send(400, "application/json", "{\"error\":\"No data provided\"}");
  }
}

// CORS対応のプリフライトリクエスト(OPTIONS)ハンドラ
void handleOptions() {
  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.sendHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
  server.sendHeader("Access-Control-Allow-Headers", "Content-Type");
  server.send(204);
}

void setup() {

  // Connect to WiFi
  if (!WiFi.config(ip,gateway,subnet,dns1)){
    Serial.println("Failed to configure!");
  }
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // IR init
  irsend.begin();

  // POSTでJSONデータを受け取るエンドポイントを設定
  server.on("/send_ir", HTTP_POST, handleSendIR);

  // CORS対応のプリフライトリクエスト(OPTIONS)を処理
  server.on("/send_ir", HTTP_OPTIONS, handleOptions);

  // サーバーを開始
  server.begin();
  Serial.println("Server started");

}

void loop() {
  server.handleClient();

  delay(100); //最低限のdelayを入れたほうがいい
}

クライアント側(リモコン)

RawDataをjson形式でPOSTすれば発信してくれます。

$ curl -X POST http://192.168.100.51/send_ir -H "Content-Type: application/json" -d '{"code":[3499, 1736, 447, 424, 447, 424, 447, 1303, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447]}'

HTMLでPOSTするなら次のような感じ。フォームに出てきた[]内にRawData書いて送信します。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>IR Code Sender</title>
</head>
<body>
  <h1>Send IR Code to ESP32</h1>

  <form id="irForm">
    <label for="irCode">Enter IR Code (JSON format):</label><br>
    <textarea id="irCode" rows="10" cols="50">
{"code":[]}
    </textarea><br><br>
    <button type="submit">Send IR Code</button>
  </form>

  <p id="response"></p>

  <script>
    document.getElementById('irForm').addEventListener('submit', function(event) {
      event.preventDefault();

      const irCode = document.getElementById('irCode').value;
      const url = 'http://192.168.100.51/send_ir';  // ESP32のIPアドレスに変更してください

      fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: irCode,
      })
      .then(response => response.json())
      .then(data => {
        document.getElementById('response').innerText = 'Response: ' + JSON.stringify(data);
      })
      .catch(error => {
        document.getElementById('response').innerText = 'Error: ' + error;
      });
    });
  </script>
</body>
</html>

即時に実行して自動でページ閉じてほしいならこっち

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ESP32 IR Sender</title>
</head>
<body>
    <h1>Sending IR Code...</h1>

    <script>
        // ページを開いた時にすぐに実行される
        window.onload = function() {
            // 送信するIRコード
            const irCode = [3499, 1736, 447, 424, 447, 424, 447, 1303, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 30170, 3499, 1736, 447, 424, 447, 424, 447, 1303, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447, 424, 447, 424, 447, 424, 447, 424, 447, 424, 447, 1303, 447];

            // ESP32にPOSTリクエストを送る
            fetch('http://192.168.100.51/send_ir', {  // ESP32のIPアドレスに置き換えてください
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    code: irCode
                })
            })
            .then(response => {
                if (response.ok) {
                    return response.json();
                } else {
                    throw new Error('Network response was not ok.');
                }
            })
            .then(data => {
                console.log("IR code sent successfully:", data);
                // 成功したらページを閉じる
                window.close();
            })
            .catch(error => {
                console.error("There was a problem with the fetch operation:", error);
                // エラーがあってもページを閉じる
                window.close();
            });
        };
    </script>
</body>
</html>

GPT-4o ありがとう🥰

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Index