Wake on Lan on MicroPython
近来搞电脑的远程启动搞上瘾了。使用网络启动(Wake on Lan),确实带来很多玩法。为了进一步降低电费,减少电脑非使用时段(例如晚上睡觉时段)待机而产生的功耗,采用ESP32C3(刷上MicroPython)来作为远程开机设备。即:
- 普通x86电脑,在晚上或无需使用的时间正常关机,并开启网络启动功能。
- ESP32C3开发板保持24小时开机并联网,可在需要时远程启动所需x86电脑。
于是找了下,在MicroPython上发送Wake on Lan的实现代码。参考了以下文章:
整理出可用代码,保存为文件wol.py
,如下:
"""
Small module for use with the wake on lan protocol.
Reference:
- https://pypi.org/project/wakeonlan/
- https://www.cnblogs.com/Yogile/p/16488281.html
"""
import socket
import ubinascii
BROADCAST_IP = "255.255.255.255"
DEFAULT_PORT = 9
SO_BROADCAST = 20
def create_magic_packet(macaddress: str) -> bytes:
"""
Create a magic packet.
A magic packet is a packet that can be used with the for wake on lan
protocol to wake up a computer. The packet is constructed from the
mac address given as a parameter.
Args:
macaddress: the mac address that should be parsed into a magic packet.
"""
if len(macaddress) == 17:
sep = macaddress[2]
macaddress = macaddress.replace(sep, "")
elif len(macaddress) == 14:
sep = macaddress[4]
macaddress = macaddress.replace(sep, "")
if len(macaddress) != 12:
raise ValueError("Incorrect MAC address format")
#return bytes.fromhex("F" * 12 + macaddress * 16)
return ubinascii.unhexlify("F" * 12 + macaddress * 16)
def send_magic_packet(
*macs: str,
ip_address: str = BROADCAST_IP,
port: int = DEFAULT_PORT,
interface: str = None
) -> None:
"""
Wake up computers having any of the given mac addresses.
Wake on lan must be enabled on the host device.
Args:
macs: One or more macaddresses of machines to wake.
Keyword Args:
ip_address: the ip address of the host to send the magic packet to.
port: the port of the host to send the magic packet to.
interface: the ip address of the network adapter to route the magic packet through.
"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 1)
if interface is not None:
sock.bind((interface, 0))
sock.setsockopt(socket.SOL_SOCKET, SO_BROADCAST, 1)
sock.connect((ip_address, port))
for mac in macs:
packet = create_magic_packet(mac)
sock.send(packet)
print("send magic packet to MAC [%s]" % (mac))
except:
print('send magic packet failed')
pass
finally:
sock.close()
使用示例:
import wol
mac = '12:ab:12:ab:12:ab' # 必填参数。要启动电脑的网卡MAC
broadcastIp = '192.168.0.255' # 可选参数。广播的地址,一般填对应网段的255地址
wol.send_magic_packet(mac, ip_address=broadcastIp)