Openwrt 安装 Wake on Lan 唤醒PC

内容目录

2025.04.15更新

新版的Openwrt不再使用 /usr/lib/lua/luci/model/cbi/wol.lua 而是使用 /www/luci-static/resources/view/wol.js 这个js文件控制。

让 Deepseek 修改这个js文件。修改后结果如下。

'use strict';
'require view';
'require dom';
'require uci';
'require fs';
'require ui';
'require rpc';
'require form';
'require tools.widgets as widgets';

return view.extend({
    formdata: { wol: {} },
    callHostHints: rpc.declare({
        object: 'luci-rpc',
        method: 'getHostHints',
        expect: { '': {} }
    }),
    load: function() {
        return Promise.all([
            L.resolveDefault(fs.stat('/usr/bin/etherwake')),
            L.resolveDefault(fs.stat('/usr/bin/wol')),
            this.callHostHints(),
            uci.load('etherwake')
        ]);
    },
    render: function(data) {
        var has_ewk = data[0],
            has_wol = data[1],
            m, s, o;

        this.formdata.has_ewk = has_ewk;
        this.formdata.has_wol = has_wol;

        m = new form.JSONMap(this.formdata, _('Wake on LAN'), _('Wake on LAN is a mechanism to remotely boot computers in the local network.'));
        s = m.section(form.NamedSection, 'wol');

        if (has_ewk && has_wol) {
            o = s.option(form.ListValue, 'executable', _('WoL program'), _('Sometimes only one of the two tools works. If one fails, try the other one'));
            o.value('/usr/bin/etherwake', 'Etherwake');
            o.value('/usr/bin/wol', 'WoL');
        }

        if (has_ewk) {
            o = s.option(widgets.DeviceSelect, 'iface', _('Network interface to use'), _('Specifies the interface the WoL packet is sent on'));
            o.default = uci.get('etherwake', 'setup', 'interface');
            o.rmempty = false;
            o.noaliases = true;
            o.noinactive = true;
            if (has_wol)
                o.depends('executable', '/usr/bin/etherwake');
        }

        o = s.option(form.Value, 'mac', _('Host to wake up'), _('Choose the host to wake up or enter a custom MAC address to use'));
        o.rmempty = false;

        // Only predefined MAC addresses
        var predefinedMacs = {
            '00:11:22:33:44:55': 'Device 1',
            '66:77:88:99:AA:BB': 'Device 2',
            'CC:DD:EE:FF:00:11': 'Device 3'
        };

        // Add only predefined MACs to the dropdown
        Object.keys(predefinedMacs).forEach(function(mac) {
            o.value(mac, E([], [mac, ' (', E('strong', [predefinedMacs[mac]]), ')']));
        });

        if (has_ewk) {
            o = s.option(form.Flag, 'broadcast', _('Send to broadcast address'));
            if (has_wol)
                o.depends('executable', '/usr/bin/etherwake');
        }

        return m.render();
    },
    handleWakeup: function(ev) {
        var map = document.querySelector('#maincontent .cbi-map'),
            data = this.formdata;

        return dom.callClassMethod(map, 'save').then(function() {
            if (!data.wol.mac)
                return alert(_('No target host specified!'));

            var bin = data.executable || (data.has_ewk ? '/usr/bin/etherwake' : '/usr/bin/wol'),
                args = [];

            if (bin == '/usr/bin/etherwake') {
                args.push('-D', '-i', data.wol.iface);
                if (data.wol.broadcast == '1')
                    args.push('-b');
                args.push(data.wol.mac);
            } else {
                args.push('-v', data.wol.mac);
            }

            ui.showModal(_('Waking host'), [
                E('p', { 'class': 'spinning' }, [_('Starting WoL utility…')])
            ]);

            return fs.exec(bin, args).then(function(res) {
                ui.showModal(_('Waking host'), [
                    res.stderr ? E('p', [res.stdout]) : '',
                    res.stderr ? E('pre', [res.stderr]) : '',
                    E('div', { 'class': 'right' }, [
                        E('button', { 'class': 'cbi-button cbi-button-primary', 'click': ui.hideModal }, [_('Dismiss')])
                    ])
                ]);
            }).catch(function(err) {
                ui.hideModal();
                ui.addNotification(null, [E('p', [_('Waking host failed: '), err])]);
            });
        });
    },
    addFooter: function() {
        return E('div', { 'class': 'cbi-page-actions' }, [
            E('button', { 'class': 'cbi-button cbi-button-save', 'click': L.ui.createHandlerFn(this, 'handleWakeup') }, [_('Wake up host')])
        ]);
    }
});

var predefinedMacs 这行下面的Mac地址(大概65到67行)替换成自己需要添加的 Mac地址和主机名即可。

然后ssh 登陆路由器,将 /www/luci-static/resources/view/wol.js 这个js修改成上述文件即可。

效果如下:


Openwrt 默认不带 Wake on Lan 程序,需要我们自己安装。下面是安装的步骤。

  1. 安装 luci-app-wol 软件包

    1. 通过管理界面安装

      1. 打开openwrt管理界面
      2. 点击 “系统” ->"软件包"
      3. 在过滤器里面输入:“wol”
      4. 在可用软件包里点击 “luci-app-wol” “wol”左边的“安装”
    2. ssh到openwrt系统安装,假设openwrt的IP地址是192.168.1.1:

      1. ssh root@192.168.1.1
        opkg update
        opkg install luci-app-wol wol
    3. 配置软件包

      1. luci-app-wol软件包目前不支持在界面上添加预定义的主机,需要修改脚本文件。

      2. ssh root@192.168.1.1

      3. 编辑 /usr/lib/lua/luci/model/cbi/wol.lua

        1. vi /usr/lib/lua/luci/model/cbi/wol.lua
      4. 在大概49行 (sys.net.mac_hints(function(mac, name) 这一行之前) 添加需要唤醒的机器列表,例如:

        1. host:value("94:C6:91:A3:F6:F2", "94:C6:91:A3:F6:F2 (ZGT)")
          sys.net.mac_hints(function(mac, name)
              host:value(mac, "%s (%s)" %{ mac, name })
          end)
    4. 测试和Bugfix

      1. 查看一下是否可以找到 “网络”->"Wake on Lan"。

      2. 如果没有可以试试清除 Luci 缓存:

        1. rm /tmp/luci-indexcache
      3. 然后刷新管理界面,就可以在网络下面看到 "Wake on Lan"了。选区_008

      4. 测试,可以选择通过etherwake或者wol两种方式唤醒PC选区_009 选区_010