一、准备工作
1. 硬件准备
- esp8266-01s
- 继电器
- esp8266-01s下载器
- 电脑开机一分二的杜邦线,用于并联原机箱上的开关
2. 编程的软件环境
- arduino IDE, 对于下载地址:https://www.arduino.cc/en/software/#ide
- 开发板环境配置
打开首选项,在附加开发版管理网址填写
http://arduino.esp8266.com/stable/package_esp8266com_index.json
接着,在工具-> 开发版 -> 开发版管理器-> 搜索eps8266,点击下载即可(网速有点慢,一天的不同时间段多重试几次)。
- 编程语言:LUA 或者 C 都可
3. 网络环境
公网可访问的环境,可以是ipv4公网端口;也可以是frp经过公网服务器转发;也可以是公网mqtt服务透传
- 本文网络环境是基于公网frp服务器做端口转发
二、整体架构和网络链路
- 控制电脑开机链路: 公司电脑 -> 家里nas -> esp8266控制家里Windows电脑开机
- 访问: 公司电脑 -> 公网服务器(frps) -> 家里Windows电脑
- 补充说明:家里nas 和 公网服务器不是必须的,可以用公网ipv4 或者 ipv6替代
三、代码
代码思路
- 查询文档确定定义的GPIO引脚(默认给高电平1),控制继电器(低电平激活);注意初始化电平(继电器常开)
- 连接路由器的WiFi
- 网络具备后,监听80端口
- 获取接口参数,如
${authCode}
=[预设值]
则闭合继电器,${delay}
毫秒(默认500ms)
控制链路
- 访问url : http://192.168.1.2/relay?authCode=yours-auth-code
- 可以在终端使用如下命令 或者 浏览器上访问该地址
$ curl http://192.168..1.2
# 上述命令的响应: this works as well
$ curl http://192.168..1.2/relay?authCode=yours-auth-code
# 上述命令的正确响应: 返回html页面
- 说明:
将IP地址(192.168.1.2)换成你自己的esp8266的ip
authCode是预设的授权口令
代码清单
- 购买的esp8266商家有提供一份lua代码,习惯性用c,这里放一份我用的代码
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
//#include <ESP8266mDNS.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#ifndef STASSID
#define STASSID "wifi-name"
#define STAPSK "wifi-password"
#endif
const char *ssid = STASSID;
const char *password = STAPSK;
ESP8266WebServer server(80);
// ntp
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp1.aliyun.com", 60*60*8, 30*60*1000);
// pinRelay
const int pinRelay = 0; // GPIO0
const String AUTH_CODE = "yours-auth-code";
void handleRoot() {
String url = server.uri(); // 获取完整的URL
Serial.println("handleRoot url:");
Serial.println(url);
if (server.hasArg("authCode")) {
String paramAuthCode = server.arg("authCode");
Serial.println("param-authCode:");
Serial.println(paramAuthCode);
if(AUTH_CODE != paramAuthCode){
String errMsg = "auth code is not exist!";
server.send(200, "text/html", errMsg);
Serial.println(errMsg);
return;
}
} else {
server.send(200, "text/html", "not found authCode");
return;
}
String paramAuthCode = server.arg("authCode");
int delayTime = 500; // default delay 500ms
if (server.hasArg("delay")) {
String paramDelay = server.arg("delay");
delayTime = paramDelay.toInt();
}
if(delayTime < 100 ){
String errMsg = "delay is too small!";
server.send(200, "text/html", errMsg);
Serial.println(errMsg);
return;
}
if(delayTime > 5000 ){
String errMsg = "delay is too large!";
server.send(200, "text/html", errMsg);
Serial.println(errMsg);
return;
}
digitalWrite(pinRelay, LOW);
delay(delayTime);
digitalWrite(pinRelay, HIGH);
Serial.println("exec delay finish!");
char temp[600];
snprintf(temp, 600,
"<!DOCTYPE>\
<html>\
<head>\
<meta charset='UTF-8'/>\
<title>ESP8266 Replay</title>\
<style>\
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
</style>\
</head>\
<body>\
<h1>Hello from ESP8266!</h1>\
<p>Uptime: %s</p>\
<p>GPIO: %d 端口</p>\
<p>Delay: %d ms</p>\
</body>\
</html>", timeClient.getFormattedTime()
, pinRelay
, delayTime);
server.send(200, "text/html", temp);
Serial.println("");
}
void handleNotFound() {
server.send(404, "text/html", "notfound this path");
Serial.println("");
}
void setup(void) {
// 设置GPIO0输出 && 高电平
pinMode(pinRelay, OUTPUT);
digitalWrite(pinRelay, HIGH);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on("/relay", handleRoot);
server.on("/", []() {
server.send(200, "text/plain", "this works as well");
});
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
timeClient.begin();
Serial.println(timeClient.getFormattedTime());
timeClient.update();
Serial.println(timeClient.getFormattedTime());
}
void loop(void) {
server.handleClient();
}
四、说说遇到的坑
1. 供电问题:
由于继电器模组需要5v-12v电源,临时采用了一款锂电池供电,调试时电压在3.9v左右,工作正常;装机后发现无法正常触发继电器;后来将电池充满后解决。
优化方案:可以从主板的usb口取电,但需要电脑主板支持关机充电功能;或者可以像我这样外挂锂电池并从usb口做充电。
2. 其他方案:
如果电脑是有线连接的路由器,可以尝试简单的网络唤醒方案(Wake On LAN);PS:当然如果只有wifi连接的也可以尝试,虽然我没尝试成功。
3. 我为什么需要远程唤醒电脑
- 【主要原因】由于公司和工作原因(公司配发的电脑不方便传输和处理私人文件),有时候需要处理下个人文件(比如学校突然要填个表并外发)
- 【次要原因】上次家里要打印一个文件,我让
某人
帮我把电脑开机,然后回复我电脑开不了机,我电脑是不是坏了?我给电脑做了一个延长线开关(就像网吧的那种)并放在 显示器开关 旁边,这样某人
就不会找不到了。