用Arduino Ethernet远程唤醒电脑

Home / 博客 / 用Arduino Ethernet远程唤醒电脑

译自:http://ricardo-dias.com/2010/11/20/arduino-wakes-my-pc/

DSCN1658.JPG

我一直梦想着通过网络控制我房间里的一些物件。在电脑上看IPTV,开/关灯,遥控P2P下载…完成这些,我需要一个服务器– 我的旧台式机倒是可以做到。当然,我不是故意晾着它 整天/周/月的…^^

我需要在任何想要用的时候,找到复活它的办法。所以我想我可以用一个Arduino和以太网插板来发送 局域网唤醒包(来实现远程服务器开机)。

 

这个UdpRaw库可允许发送原始数据包,所以我要做的只是执行以下这个“魔法包(Magic Packet)” – 它由 6个0xFF及紧跟的16个目标MAC地址 组成。

byte wolMac[] = { 0x00,0x00,0x00,0x36,0x45,0xC1 };

现在,我所需要的是在6*0xFF后复制MAC地址16次。我是这么做的:

byte all[102];
int i,c1,j=0;

for(i = 0; i < 6; i++,j++){
  all[j] = 0xFF;
}
for(i = 0; i < 16; i++){
  for( c1 = 0; c1 < 6; c1++,j++)
    all[j] = wolMac[c1];
}

运行这些代码之后,所有的这些阵列将获得完整的魔法包,预备发送:

UdpRaw.sendPacket(all,102,targetIp,targetPort);

所以测试的话,我琢磨出了一个简单的程序,当按下一个按钮时,包就发送了。然后呢,我在pin 2上用了一个中断。Arduino基本能保持对那个引脚的侦听,无论从低到高,都将执行特定功能。

DSCN1656.JPG

搞定上面之后,我计划用Arduino来侦听网络端口,当它接收到一个指定的包序列后,就唤醒电脑。这样就能在世界的任何有角落叫启动我的服务器了! :D

 

这是全部的Arduino 代码:

/*
* Arduino WakeMyPc
 * Ricardo Dias
 * http://ricardo-dias.com/
 *
 * This sketch sends the "magic packet" to wake up
 * a PC on Local Area Network when a push-button
 * is pressed.
 */

#include <Ethernet.h>
#include <UdpRaw.h>

// ARDUINO CONFIG
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Arduino MAC
byte ip[] = { 192, 168, 1, 112 }; // Arduino IP
byte gw[] = { 192, 168, 1, 254 }; // Gateway IP address
int localPort = 8888; //local port to listen on

// THE TARGET
byte targetIp[] = { 192, 168, 1, 255 };
int targetPort = 5456;
byte wolMac[] = { 0x00,0x00,0x00,0x36,0x45,0xC1 }; // The target PC Mac Address

void setup() {
  Ethernet.begin(mac,ip,gw);
  UdpRaw.begin(localPort);

  // Will run the sendPkt() function when a button wired to
  // pin 2 is pressed
  attachInterrupt(0, sendPkt, RISING);
}

void loop() {
  delay(1);
}

void sendPkt(){
  // The 'magic packet' consists of 6 times 0xFF followed by 16 times
  // the hardware address (MAC).

  byte all[102];
  int i,c1,j=0;

  for(i = 0; i < 6; i++,j++){
    all[j] = 0xFF;
  }
  for(i = 0; i < 16; i++){
    for( c1 = 0; c1 < 6; c1++,j++)
      all[j] = wolMac[c1];
  }

  UdpRaw.sendPacket(all,102,targetIp,targetPort);
}

PS:你可能在想“见鬼为什么它不能直接把这些包发送到电脑上?”

可以这样解释:我的ISP喜欢在每天夜里2点重启路由器。那么路由器重启,服务器就down掉,它不知道服务器连着的是哪个以太网端口。为解决此问题,这些包需要发送到广播IP。然而,在局域网中才行。