为了研究esp8266的继电器控制,编写了一个通用的程序,同时包含服务器端(arduino编写)和客户端(安卓app)。因为买esp01的继电器模块带来的程序根本用不了,随即写了这个大通用版本,可以利用它通过Web方式控制任意IP的任意GPIO,支持各种电平触发模式,绝对好用,给大家免费分享一下。
程序的难点还是在于服务器端对于http的GET请求的处理和返回,服务器端使用Arduino C语言开发,安卓App使用麻省理工的App Inventor2开发。全都开源免费分享给大家,都在CSDN资源包里。
CSDN资源分享https://download.csdn.net/download/safirst/87425099
/************************************************************
通用的远程控制GPIO的Web服务端,配合我开发的安卓APP使用更佳
在ESP8266的esp01s模块和Arduino D1开发板上编写,可以用于
Arduino支持的其他开发板
Safirst C. Ke
zhongjizhuyi@163.com
2023年2月6日 15:56:13
************************************************************/
#include <ESP8266WiFi.h>
#define L false
#define H true
#define TRIGGER(GPIO, LEVEL) \
do { \
digitalWrite(GPIO, LEVEL); \
delay(200); \
digitalWrite(GPIO, !LEVEL); \
} while (0)
const char* ssid = "ESP8266_TEST";
const char* password = "********";
IPAddress local_IP(192, 168, 11, 6);
IPAddress gateway(192, 168, 11, 1);
IPAddress subnet(255, 255, 255, 0);
WiFiServer server(80);
void connectToWiFi() {
Serial.print("\n\nConnecting to ");
Serial.println(ssid);
WiFi.config(local_IP, gateway, subnet); //设置静态IP
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
String parseReq(String s, int* gpio)
{
int posA, posB;
posA = s.indexOf(" ");
posB = s.lastIndexOf(" ");
String cc = s.substring(posA + 2, posB);
if (isDigit(cc.charAt(1))) //直接检验指令第二位是不是数字,干脆利落!
{
*gpio = cc.substring(1).toInt();
return cc.substring(0, 1); //L or H
}
else
{
*gpio = cc.substring(2).toInt();
return cc.substring(0, 2); //LH or HL
}
}
void setup() {
Serial.begin(115200);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
digitalWrite(0, HIGH);
digitalWrite(2, HIGH);
connectToWiFi();
server.begin();
Serial.println("Server started : To control GPIO, use Android APP [WebGPIOControl.apk].");
}
void loop() {
WiFiClient client = server.accept();
if (!client) {
Serial.print("A");
delay(200);
return;
}
Serial.println("\n\n");
Serial.println("Client " + client.remoteIP().toString() + " connected.");
String req;
while (client.connected())
{
Serial.print("C");
delay(100);
if (client.available())
{
Serial.println("\nclient available...");
req = client.readStringUntil('\r');
Serial.println("client request:");
Serial.println(req);
}
while (client.available())
{
// but first, let client finish its request
// that's diplomatic compliance to protocols
// (and otherwise some clients may complain, like curl)
// (that is an example, prefer using a proper webserver library)
client.read();
}
//以下是解析GET请求中的指令
int gpio = 0;
String op = parseReq(req, &gpio);
if (op == "L") {
digitalWrite(gpio, L);
}
else if (op == "H") {
digitalWrite(gpio, H);
}
else if (op == "LH") {
TRIGGER(gpio, L);
}
else if (op == "HL") {
TRIGGER(gpio, H);
}
else
{
Serial.println("invalid request control code, reset...");
client.print("HTTP/1.1 404\r\n");
client.stop();
return;
}
Serial.println("Op is : " + op + " ------ gpio is :" + gpio);
Serial.println("send a standard http response header");
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
Serial.println("send the body");
client.println("<html><body>");
client.println("<h1>Arduino Server</h1>");
client.print("<p>millis=");
client.print(millis());
client.println("</p>");
client.println("</body></html>");
delay(100);
client.stop();
}
Serial.println("\n[Client disonnected]");
}