基于 MicroPython 的 WOL (远程唤醒)

依赖

Python

MicroPython 是基于 Python 的 WOL 适配移植过来的,原代码在 MicroPython 中不是直接可用的。

源代码请参见:LouisJin / WakeOnLan-Python

MicroPython

Gitee 下载: Yogile / micropython-wol

除了 boot.py 放在根路径下。其他 .py 文件均放在 /lib 文件夹下。

U_WIFI.py

U_WIFI.py 用于连接 WIFI 。

'''
Author: Yogile
Gitee: https://gitee.com/yogile
Date: 2022-07-17 00:41:25
LastEditors: Yogile
LastEditTime: 2022-07-17 10:03:30
Description: 
'''
import network

class WIFI:
    WLAN = None
    IP = None
    SSID = b"[SSID]"
    PASSWORD = b"[PASSWORD]"

def connectWiFi():
    WIFI.WLAN = None
    WIFI.WLAN = network.WLAN(network.STA_IF)
    try:
        if not WIFI.WLAN.isconnected():
            WIFI.WLAN.active(True)
            WIFI.WLAN.connect(WIFI.SSID, WIFI.PASSWORD)
        if WIFI.WLAN.isconnected():
            print('network config:', WIFI.WLAN.ifconfig())
            WIFI.IP = WIFI.WLAN.ifconfig()[0]
    except:
        print('WIFI.WLAN network except')
        WIFI.WLAN.IP = None
    finally:
        print('WIFI.WLAN connectWiFi finish')

使用示例:

import lib as lib
from lib import U_WIFI

def start():
    while(True):
        if U_WIFI.WIFI.WLAN == None:
            print("WIFI Start Connect...")
            U_WIFI.connectWiFi()
        if U_WIFI.WIFI.WLAN.isconnected():
            print("WIFI Connected...")
        else:
            print("WIFI Not Connect...")
            U_WIFI.WIFI.WLAN = None
            utime.sleep(5)

start()

U_STRING.py

U_STRING.py 用于实现 WOL 涉及到的 Python 实现了的——但 MicroPython 未实现的,有关方法。

包含 replace()rindex()join()

方法 参数 说明
replace(string, inStr, chgStr) string:被操作字符串 支持 "xx",不支持 b'xx'b"xx" 格式
inStr:要被替换的单个字符 支持 "x",不支持 b'x'b"x" 格式
chgStr:用于替换的单个字符 支持 "x",不支持 b'x'b"x" 格式
rindex(string, indexStr) string:被查找字符串 支持 "xx",不支持 b'xx'b"xx" 格式
indexStr:用于查找的目标单个字符 支持 "x",不支持 b'x'b"x" 格式
join(string, Dict) string:被操作字符串 支持 "xx",不支持 b'xx'b"xx" 格式
Dict:包含字符串的简单的一元字典 仅支持 ["asd"(, "asd" * 16, ...)] 格式
'''
Author: Yogile
Gitee: https://gitee.com/yogile
Date: 2022-06-28 23:51:30
LastEditors: Yogile
LastEditTime: 2022-07-06 18:33:32
Description: 
'''
import struct

class String():
    def __init__(self, string):
        self.string = string

    def replace(string, inStr, chgStr):
        tempStr = str()
        _chgStr = chgStr
        for i in range(0, len(string)):
            if str(string[i]) == inStr:
                if chgStr == '' or chgStr == "" or chgStr == None:
                    pass
                else:
                    tempStr = tempStr + _chgStr
            else:
                tempStr = tempStr + string[i]
        return tempStr
    
    def rindex(string, indexStr):
        r_index = 0
        for i in range(0, len(string)):
            if string[i] == indexStr:
                if i >= r_index:
                    r_index = i
        return r_index
        
    def join(string, Dict):
        for i in range(0, len(Dict)):
            string = string + Dict[i]
        return string

使用示例:见 U_WOL.py

U_WOL.py

U_WIFI 用于获取本地 IP 。

U_STRING 用于实现字符串操作有关方法。

'''
Author: Yogile
Gitee: https://gitee.com/yogile
Date: 2022-06-28 23:51:30
LastEditors: Yogile
LastEditTime: 2022-07-06 18:33:32
Description: 
'''
import usocket
import struct

import lib as lib
from lib import U_WIFI
from lib import U_STRING

class WOL():
    def __init__(self, IP, MAC_ADDRESS):
        self.IP = IP
        self.MAC_ADDRESS = MAC_ADDRESS
        self.SO_BROADCAST = 32
    
    def do(self):
        # 初始化 IP 和 MAC
        try:
            print('start send magic packet to ', self.MAC_ADDRESS)
            
            host_ip = self.IP
            print("host_ip: ", host_ip)
            
            host = (host_ip[: U_STRING.String.rindex(host_ip, '.') + 1] + '255', 9)
            print("host: ", host)
            
            mac_address = self.MAC_ADDRESS
            mac_address_fmt = U_STRING.String.replace(mac_address, ':', '')
            mac_address_fmt = U_STRING.String.replace(mac_address_fmt, '-', '')
            print("mac_address_fmt: ", mac_address_fmt)
        except:
            print('U_WOL Init error, String except...')
        finally:
            print('U_WOL Init finally')
        # 编写 WOL 协议数据
        try:
            data = U_STRING.String.join('', ['FFFFFFFFFFFF', mac_address_fmt * 16])
            send_data = b''
            for i in range(0, len(data), 2):
                send_data = U_STRING.String.join(b'', [send_data, struct.pack('B', int(data[i: i + 2], 16))])
            print("send_data: ", send_data)
        except:
            print('U_WOL Code error, String except...')
        finally:
            print('U_WOL Code finally')
        # 发送 WOL 魔术包
        try:
            sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, 1)
            sock.setsockopt(usocket.SOL_SOCKET, self.SO_BROADCAST, 1)
            sock.sendto(send_data, host)
        except:
            print('U_WOL Socket error, About SO_BROADCAST except...')
        finally:
            sock.close()
            print('U_WOL Socket finally')

使用示例:

import lib as lib
from lib import U_STRING
from lib import U_WIFI
from lib import U_WOL

import utime

def start():
    print("U_WIFI.WIFI.WLAN is %s" % U_WIFI.WIFI.WLAN)
    while(True):
        if U_WIFI.WIFI.WLAN == None:
            print("WIFI Start Connect...")
            U_WIFI.connectWiFi()
        if U_WIFI.WIFI.WLAN.isconnected():
            print("WIFI Connected...")
        else:
            print("WIFI Not Connect...")
            U_WIFI.WIFI.WLAN = None
            utime.sleep(5)
            continue
            # 跳过本循环后续代码,进行下一循环,直到 WIFI 连接成功
        goalMAC = "xx:xx:xx:xx:xx:xx"
        wol = U_WOL.WOL(U_WIFI.WIFI.IP, goalMAC)
        wol.do()

start()

适配移植

MicroPython 已实现

根据文档 builtins-内置函数和异常 :得知 class str 已实现。

MicroPython 方法缺失

根据文档 MicroPython 内置类型 :没有实现类似 replace() 的功能。

根据 usocket -- socket 模块 :得知未定义常量 usocket.SO_BROADCAST ,其值 usocket.SO_BROADCAST = 32

其他语言

C 语言

参见:GramThanos / WakeOnLAN

更多:Github 搜索结果

posted @ 2022-07-17 20:36  Yogile  阅读(442)  评论(0编辑  收藏  举报