家の外からESPr Developerを操作

これまでの電子工作では、ESPr Developer からWebサーバに、なんらかのセンサデータを送信するものばかりを作ってきました。

今回は逆に、家の外からESPr Developerに、なんらかの指示を与えるようなものを作ってみようと思います。

具体的な処理としては、以下のようなものを考えました。

  • Webサーバ上に「btn_state.txt」というテキストファイルを置いておく。
  • Webサーバ上に「write_text.php」というPHPプログラムを準備し、スマホからこのプログラムにアクセスすることにとり、「btn_state.txt」の内容を書き換えることができるようにする。
  • Webサーバ上に「read_text.php」というPHPプログラムを準備し、ESPr Developerからこのプログラムにアクセスすることにとり、「btn_state.txt」の内容を読むことができるようにする。
  • ESPr Developerに、一定の時間毎に「read_text.php」にアクセスするスケッチを準備し、「btn_state.txt」の内容に応じて何らかの処理を行えるようにする。

これにより、家の外から、スマホで「btn_state.txt」の内容を書き換えることにより、家の中にあるESPr Developerに、その内容に応じた処理をさせることができます。

実際には、簡単にするために、以下のようなものを作ることにしました。

  • 「btn_state.txt」には、「0」または「1」の1文字だけを格納する。
  • 「write_text.php」にはボタンをひとつだけ準備し、ボタンを押すたびに「btn_state.txt」の内容を「0」⇔「1」に書き換える。
  • ESPr DeveloperにはLEDを接続する。スケッチでは、一定時間毎に「read_text.php」にアクセスして「btn_state.txt」の内容を読み込み、「1」であればLEDを点灯、「0」なら消灯させる。

「write_text.php」の内容は以下のとおりです。formでボタンを準備し、タップするたびに、色が「灰色」⇔「赤」と切り替わるようにしました。

<?php
// ファイル書き込み(ボタンが押された時)
if(isset( $_POST['button1'] )) {
  $f_button1 = $_POST['f_button1'];
  $fp = fopen("./btn_state.txt", "w");
  fwrite($fp, $f_button1);
  fclose($fp);
}

// ファイル読み出し
$fp = fopen("./btn_state.txt", "r");
$f_button1 = fgetc($fp);
fclose($fp);

// フォーム作成
if($f_button1==1) {
  $color = "red";
  $f_button1 = 0;
} else {
  $color = "gray";
  $f_button1 = 1;
}
$res  = "<form action=\"\" method=\"post\">\n";
$res .= "<input type=\"hidden\" name=\"f_button1\" value=" .$f_button1 .">\n";
$res .= "<button type=\"submit\" name=\"button1\" style=\"background-color:" .$color .";\" class=\"hw\">ESPr Developer 1</button>\n";
$res .= "</form>\n";

?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=320" >
<title>Control Window</title>
<style type="text/css">
<!--
body{ font-family: sans-serif; }
.hw { width:280px; height:40px; font-size:1.5em; color:white; border-style:none; }
-->
</style>
</head>
<body>

<?php echo $res; ?>

</body>
</html>

「read_text.php」の内容は以下のとおりです。ファイルから最初の1文字を読み出すだけです。

<?php
$fp = fopen("./btn_state.txt", "r");
print(fgetc($fp));
fclose($fp);
?>

「btn_state.txt」には「0」という1文字だけを書いておき、全ユーザに対するwrite権を付けておきます。
Webサーバに「study_html」というディレクトリを準備し、これら3つのデータを置きます。

ESPr Developerでは、12番ピンとGNDピンの間に、LEDと330Ωの抵抗を、直列に繋げます。

ESPr Developerのスケッチは以下のとおりです。setup()では、WiFi接続を行います。loop()では、1秒毎にGETで「read_text.php」にアクセス、取ってきた値に基づいてLEDのHIGH、LOWを切り替えます。

#include <ESP8266WiFi.h>
const char* ssid     = "XXXXXXXX";
const char* password = "XXXXXXXX";
const char* host     = "XXXXXXXX";

#define LED1 12

void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println();
  Serial.print("Connecting ");

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");

  pinMode(LED1, OUTPUT);
  digitalWrite(LED1, LOW);
}

void loop() {
  delay(1000);

  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  client.print(String("GET ") + "/study_html/read_text.php HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

  String line;
  while(client.available()){
    line = client.readStringUntil('\r');
  }

  char c = line.charAt(1);
  Serial.println(c);
  if(c=='1') {
    digitalWrite(LED1, HIGH);
  } else {
    digitalWrite(LED1, LOW);
  }
}

結果は以下のとおりです。ESPr DeveloperがWiFiにアクセスするのに数秒かかりますので、結構遅れますが、スマホでの操作に基づいて、LEDのON、OFFが切り替わることが確認できました。