これまでつくってきた電子工作は、「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が切り替わることが確認できました。