esp32/网络开机/远程开机/WOL-Arduino中文社区 - Powered by Discuz! Archiver

吹向陆地的风 发表于 2020-3-20 10:39

esp32/网络开机/远程开机/WOL

本帖最后由 吹向陆地的风 于 2020-3-20 10:46 编辑

最近看到好几个人想用Blinker做远程开机,但都因为种种原因放弃了,网上也没人分享代码,所以花了一晚上用ESP32做了个开机棒。



原理就是广播一个特殊的数据包给目的主机,前提是目的主机的主板支持wake on lan并在BIOS里已经设置好,还有就是要知道目的主机的MAC地址。这个特殊的数据包叫做magic packet,它由102个字节组成,最前面六个字节为0xFF,其他字节为目的主机的MAC地址(6个字节为一组,共16组),如下图所示:



(z这一段是复制大佬介绍的,地址https://blog.csdn.net/dyllove98/article/details/9002969)
知道这个原理之后,只要向目的地址发送一个指定格式的magic packet就可以实现远程开机了。如果家里有公网ip的话下面的步骤都不需要了,找一个网络唤醒的程序直接使用就好,但大部分人家里都没有公网ip,无法从外网连接。
远程开机的思路是利用Blinker的Button组件,控制esp32发送开机数据,解决了没有公网ip不能通信的问题。
void wol()//开机代码部分
{
int i, k, j = 0;
udp.beginPacket(udpAddress, udpPort);//准备发送,设置地址和端口
//下面构建magic packet
for (i = 0; i < 6; i++, j++)
{
    package = 0xFF;
}
for (i = 0; i < 16; i++) {
    for ( k = 0; k < 6; k++, j++)
      package = MAC;
}
udp.write((byte*)package, 102);//将数组package放入缓冲区,准备发送
udp.endPacket();//发送

Blinker.delay(1000);
}
这个是远程开机的核心代码,先构建magic packet数组,然后将该数组以udp方式发送出去,其中MAC数组为你要开机目标的MAc号,端口不重要,只要是合法的都可以,package为被构建的数组,用于存储magic packet,之后发送出去,完成开机操作。




下面是全部代码
#define BLINKER_WIFI
#include <Blinker.h>
#include <WiFi.h>
#include <WiFiUdp.h>
//引用各类库

char auth[] = "auth";
char ssid[] = "ssid";
char pswd[] = "key";
//Blinker常规操作
#define BUTTON_1 "WOL"//定义按键
BlinkerButton Button1(BUTTON_1);

void button1_callback(const String & state)//回调函数
{
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
BLINKER_LOG("get button state: ", state);

if(state == BLINKER_CMD_ON) {
    BLINKER_LOG("Toggle on!");
    wol();
    Button1.print("on");
    Blinker.delay(2000);
    Button1.print("off");//返回关闭状态,方便下一次使用。
}

}
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);

    Blinker.vibrate();
   
    uint32_t BlinkerTime = millis();
   
    Blinker.print("millis", BlinkerTime);
}

const char * udpAddress = "192.168.0.255";//udp接收地址,我这里是使用的广播
const int udpPort = 2333;//udp端口
byte MAC = {0x00, 0x10, 0x12, 0xD0, 0x9C, 0x6D};//MAC号
byte package;

//The udp library class
WiFiUDP udp;

void setup() {
   //WiFi.begin(ssid,pswd);
Blinker.begin(auth,ssid,pswd);

Blinker.attachData(dataRead);
Button1.attach(button1_callback);//注册回调函数
}
void loop() {
Blinker.run();
}

void wol()//开机代码部分
{
int i, k, j = 0;
udp.beginPacket(udpAddress, udpPort);//准备发送,设置地址和端口
//下面构建magic packet
for (i = 0; i < 6; i++, j++)
{
    package = 0xFF;
}
for (i = 0; i < 16; i++) {
    for ( k = 0; k < 6; k++, j++)
      package = MAC;
}
udp.write((byte*)package, 102);//将数组package放入缓冲区,准备发送
udp.endPacket();//发送

Blinker.delay(1000);
}
在Blinker中新建一个WOL的按键,类型设置为开关。
这里udp发送的是广播,所以不用在路由器设置ip与mac绑定,只需要知道mac号就可以了,自己只需要修改mac和udpAddress,记得分192.168.0和192.168.1的区别。
由于我只有一个手机,无法拍摄开机过程视频,就不放了,本人亲测可以成功开机,前提是主板支持网络唤醒并正确配置,具体配置方法可以根据主板类型自行百度,这里就不做赘述。


吹向陆地的风 发表于 2020-3-27 08:48

n1001 发表于 2020-3-26 16:38
我直接塞机箱里,拉个天线出来。如果是笔记本电脑等,楼主的方法显然更好 ...

然而笔记本大部分都不支持wol,即使支持也要插电源插网线,和台式机没什么区别了,wol不需要拆机箱也算好处:lol。

cdb 发表于 2020-3-26 16:15

还能实现关机,需要找我

n1001 发表于 2020-3-26 16:38

我直接塞机箱里,拉个天线出来。如果是笔记本电脑等,楼主的方法显然更好

吹向陆地的风 发表于 2020-3-27 08:44

cdb 发表于 2020-3-26 16:15
还能实现关机,需要找我

除了remote desktop和ssh还有啥方法能实现远程关机,求教,之前没找到方案。

n1001 发表于 2020-3-27 09:11

吹向陆地的风 发表于 2020-3-27 08:48
然而笔记本大部分都不支持wol,即使支持也要插电源插网线,和台式机没什么区别了,wol不需要拆机箱也算好 ...

对于不方便拆开的电脑WOL优势挺大的:lol

cdb 发表于 2020-3-27 09:49

吹向陆地的风 发表于 2020-3-27 08:44
除了remote desktop和ssh还有啥方法能实现远程关机,求教,之前没找到方案。

在电脑上安装关机服务程序,通过接口触发关机指令。周末我发个教程吧

794736229 发表于 2020-5-1 17:54

你好,复制程序到ide编译显示错误,可以发个可用的ino文件吗?谢谢了

吹向陆地的风 发表于 2020-5-3 22:08

794736229 发表于 2020-5-1 17:54
你好,复制程序到ide编译显示错误,可以发个可用的ino文件吗?谢谢了

文件已上传

794736229 发表于 2020-5-4 18:49

吹向陆地的风 发表于 2020-5-3 22:08
文件已上传

收到了,谢谢!变编译还是出错,可能是以为我用8266的原因吧?有没有办法适配8266呢
页: [1] 2
查看完整版本: esp32/网络开机/远程开机/WOL