用esp8266-01s控制电脑远程启动

一、准备工作

1. 硬件准备

  • esp8266-01s
  • 继电器
  • esp8266-01s下载器
  • 电脑开机一分二的杜邦线,用于并联原机箱上的开关

2. 编程的软件环境

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替代

三、代码

代码思路

  1. 查询文档确定定义的GPIO引脚(默认给高电平1),控制继电器(低电平激活);注意初始化电平(继电器常开)
  2. 连接路由器的WiFi
  3. 网络具备后,监听80端口
  4. 获取接口参数,如${authCode}=[预设值]则闭合继电器,${delay}毫秒(默认500ms)

控制链路

$ 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. 我为什么需要远程唤醒电脑

  • 【主要原因】由于公司和工作原因(公司配发的电脑不方便传输和处理私人文件),有时候需要处理下个人文件(比如学校突然要填个表并外发)
  • 【次要原因】上次家里要打印一个文件,我让某人帮我把电脑开机,然后回复我电脑开不了机,我电脑是不是坏了?我给电脑做了一个延长线开关(就像网吧的那种)并放在 显示器开关 旁边,这样某人就不会找不到了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容