mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 17:20:30 +08:00
moved wol to gpio
This commit is contained in:
parent
688ddca549
commit
0c500aa0c9
@ -79,7 +79,6 @@ from ..validators.os import valid_options
|
||||
from ..validators.os import valid_command
|
||||
|
||||
from ..validators.net import valid_ip_or_host
|
||||
from ..validators.net import valid_ip
|
||||
from ..validators.net import valid_net
|
||||
from ..validators.net import valid_port
|
||||
from ..validators.net import valid_ports_list
|
||||
@ -183,7 +182,7 @@ def _init_config(config_path: str, override_options: List[str], **load_flags: bo
|
||||
raise SystemExit(f"ConfigError: {err}")
|
||||
|
||||
|
||||
def _patch_raw(raw_config: Dict) -> None:
|
||||
def _patch_raw(raw_config: Dict) -> None: # pylint: disable=too-many-branches
|
||||
if isinstance(raw_config.get("otg"), dict):
|
||||
for (old, new) in [
|
||||
("msd", "msd"),
|
||||
@ -195,6 +194,23 @@ def _patch_raw(raw_config: Dict) -> None:
|
||||
raw_config["otg"]["devices"] = {}
|
||||
raw_config["otg"]["devices"][new] = raw_config["otg"].pop(old)
|
||||
|
||||
if isinstance(raw_config.get("kvmd"), dict) and isinstance(raw_config["kvmd"].get("wol"), dict):
|
||||
if not isinstance(raw_config["kvmd"].get("gpio"), dict):
|
||||
raw_config["kvmd"]["gpio"] = {}
|
||||
for section in ["drivers", "scheme"]:
|
||||
if not isinstance(raw_config["kvmd"]["gpio"].get(section), dict):
|
||||
raw_config["kvmd"]["gpio"][section] = {}
|
||||
raw_config["kvmd"]["gpio"]["drivers"]["__wol__"] = {
|
||||
"type": "wol",
|
||||
**raw_config["kvmd"].pop("wol"),
|
||||
}
|
||||
raw_config["kvmd"]["gpio"]["scheme"]["__wol__"] = {
|
||||
"driver": "__wol__",
|
||||
"pin": 0,
|
||||
"mode": "output",
|
||||
"switch": False,
|
||||
}
|
||||
|
||||
if isinstance(raw_config.get("kvmd"), dict) and isinstance(raw_config["kvmd"].get("streamer"), dict):
|
||||
streamer_config = raw_config["kvmd"]["streamer"]
|
||||
|
||||
@ -359,12 +375,6 @@ def _get_config_scheme() -> Dict:
|
||||
},
|
||||
},
|
||||
|
||||
"wol": {
|
||||
"ip": Option("255.255.255.255", type=functools.partial(valid_ip, v6=False)),
|
||||
"port": Option(9, type=valid_port),
|
||||
"mac": Option("", type=_make_ifarg(valid_mac, "")),
|
||||
},
|
||||
|
||||
"hid": {
|
||||
"type": Option("", type=valid_stripped_string_not_empty),
|
||||
|
||||
|
||||
@ -34,7 +34,6 @@ from .. import init
|
||||
from .auth import AuthManager
|
||||
from .info import InfoManager
|
||||
from .logreader import LogReader
|
||||
from .wol import WakeOnLan
|
||||
from .ugpio import UserGpio
|
||||
from .streamer import Streamer
|
||||
from .snapshoter import Snapshoter
|
||||
@ -86,7 +85,6 @@ def main(argv: Optional[List[str]]=None) -> None:
|
||||
),
|
||||
info_manager=InfoManager(global_config),
|
||||
log_reader=LogReader(),
|
||||
wol=WakeOnLan(**config.wol._unpack()),
|
||||
user_gpio=UserGpio(config.gpio, global_config.otg.udc),
|
||||
|
||||
hid=hid,
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
# ========================================================================== #
|
||||
# #
|
||||
# KVMD - The main Pi-KVM daemon. #
|
||||
# #
|
||||
# Copyright (C) 2018-2021 Maxim Devaev <mdevaev@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# ========================================================================== #
|
||||
|
||||
|
||||
from aiohttp.web import Request
|
||||
from aiohttp.web import Response
|
||||
|
||||
from ..wol import WakeOnLan
|
||||
|
||||
from ..http import exposed_http
|
||||
from ..http import make_json_response
|
||||
|
||||
|
||||
# =====
|
||||
class WolApi:
|
||||
def __init__(self, wol: WakeOnLan) -> None:
|
||||
self.__wol = wol
|
||||
|
||||
# =====
|
||||
|
||||
@exposed_http("GET", "/wol")
|
||||
async def __state_handler(self, _: Request) -> Response:
|
||||
return make_json_response(await self.__wol.get_state())
|
||||
|
||||
@exposed_http("POST", "/wol/wakeup")
|
||||
async def __wakeup_handler(self, _: Request) -> Response:
|
||||
await self.__wol.wakeup()
|
||||
return make_json_response()
|
||||
@ -65,7 +65,6 @@ from ... import aioproc
|
||||
from .auth import AuthManager
|
||||
from .info import InfoManager
|
||||
from .logreader import LogReader
|
||||
from .wol import WakeOnLan
|
||||
from .ugpio import UserGpio
|
||||
from .streamer import Streamer
|
||||
from .snapshoter import Snapshoter
|
||||
@ -85,7 +84,6 @@ from .api.auth import check_request_auth
|
||||
|
||||
from .api.info import InfoApi
|
||||
from .api.log import LogApi
|
||||
from .api.wol import WolApi
|
||||
from .api.ugpio import UserGpioApi
|
||||
from .api.hid import HidApi
|
||||
from .api.atx import AtxApi
|
||||
@ -148,7 +146,6 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
||||
auth_manager: AuthManager,
|
||||
info_manager: InfoManager,
|
||||
log_reader: LogReader,
|
||||
wol: WakeOnLan,
|
||||
user_gpio: UserGpio,
|
||||
|
||||
hid: BaseHid,
|
||||
@ -186,7 +183,6 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
||||
for sub in sorted(info_manager.get_subs())
|
||||
],
|
||||
*[
|
||||
_Component("Wake-on-LAN", "wol_state", wol),
|
||||
_Component("User-GPIO", "gpio_state", user_gpio),
|
||||
_Component("HID", "hid_state", hid),
|
||||
_Component("ATX", "atx_state", atx),
|
||||
@ -201,7 +197,6 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
||||
AuthApi(auth_manager),
|
||||
InfoApi(info_manager),
|
||||
LogApi(log_reader),
|
||||
WolApi(wol),
|
||||
UserGpioApi(user_gpio),
|
||||
self.__hid_api,
|
||||
AtxApi(atx),
|
||||
|
||||
@ -27,46 +27,69 @@ from typing import Optional
|
||||
|
||||
from ...logging import get_logger
|
||||
|
||||
from ...errors import OperationError
|
||||
|
||||
from ... import aiotools
|
||||
|
||||
from ...yamlconf import Option
|
||||
|
||||
# =====
|
||||
class WolDisabledError(OperationError):
|
||||
def __init__(self) -> None:
|
||||
super().__init__("WoL is disabled")
|
||||
from ...validators.net import valid_ip
|
||||
from ...validators.net import valid_port
|
||||
from ...validators.net import valid_mac
|
||||
|
||||
from . import GpioDriverOfflineError
|
||||
from . import BaseUserGpioDriver
|
||||
|
||||
|
||||
# =====
|
||||
class WakeOnLan:
|
||||
def __init__(self, ip: str, port: int, mac: str) -> None:
|
||||
class Plugin(BaseUserGpioDriver): # pylint: disable=too-many-instance-attributes
|
||||
def __init__( # pylint: disable=super-init-not-called
|
||||
self,
|
||||
instance_name: str,
|
||||
notifier: aiotools.AioNotifier,
|
||||
|
||||
ip: str,
|
||||
port: int,
|
||||
mac: str,
|
||||
) -> None:
|
||||
|
||||
super().__init__(instance_name, notifier)
|
||||
|
||||
self.__ip = ip
|
||||
self.__port = port
|
||||
self.__mac = mac
|
||||
self.__magic = b""
|
||||
|
||||
if mac:
|
||||
assert len(mac) == 17, mac
|
||||
self.__magic = bytes.fromhex("FF" * 6 + mac.replace(":", "") * 16)
|
||||
|
||||
async def get_state(self) -> Dict:
|
||||
@classmethod
|
||||
def get_plugin_options(cls) -> Dict:
|
||||
return {
|
||||
"enabled": bool(self.__magic),
|
||||
"target": {
|
||||
"ip": self.__ip,
|
||||
"port": self.__port,
|
||||
"mac": self.__mac,
|
||||
},
|
||||
"ip": Option("255.255.255.255", type=(lambda arg: valid_ip(arg, v6=False))),
|
||||
"port": Option(9, type=valid_port),
|
||||
"mac": Option("", type=(lambda arg: (valid_mac(arg) if arg else ""))),
|
||||
}
|
||||
|
||||
@aiotools.atomic
|
||||
async def wakeup(self) -> None:
|
||||
if not self.__magic:
|
||||
raise WolDisabledError()
|
||||
def register_input(self, pin: int, debounce: float) -> None:
|
||||
_ = pin
|
||||
_ = debounce
|
||||
|
||||
logger = get_logger(0)
|
||||
logger.info("Waking up %s (%s:%s) using Wake-on-LAN ...", self.__mac, self.__ip, self.__port)
|
||||
def register_output(self, pin: int, initial: Optional[bool]) -> None:
|
||||
_ = pin
|
||||
_ = initial
|
||||
|
||||
def prepare(self) -> None:
|
||||
get_logger(0).info("Probing driver %s on MAC %s and %s:%d ...", self, self.__mac, self.__ip, self.__port)
|
||||
|
||||
async def run(self) -> None:
|
||||
await aiotools.wait_infinite()
|
||||
|
||||
async def cleanup(self) -> None:
|
||||
pass
|
||||
|
||||
async def read(self, pin: int) -> bool:
|
||||
_ = pin
|
||||
return False
|
||||
|
||||
async def write(self, pin: int, state: bool) -> None:
|
||||
_ = pin
|
||||
if not state:
|
||||
return
|
||||
|
||||
sock: Optional[socket.socket] = None
|
||||
try:
|
||||
@ -74,14 +97,18 @@ class WakeOnLan:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
sock.connect((self.__ip, self.__port))
|
||||
sock.send(self.__magic)
|
||||
sock.send(bytes.fromhex("FF" * 6 + self.__mac.replace(":", "") * 16))
|
||||
except Exception:
|
||||
logger.exception("Can't send Wake-on-LAN packet")
|
||||
else:
|
||||
logger.info("Wake-on-LAN packet sent")
|
||||
get_logger(0).exception("Can't send Wake-on-LAN packet via %s to %s", self, self.__mac)
|
||||
raise GpioDriverOfflineError(self)
|
||||
finally:
|
||||
if sock:
|
||||
try:
|
||||
sock.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"WakeOnLan({self._instance_name})"
|
||||
|
||||
__repr__ = __str__
|
||||
@ -121,7 +121,7 @@
|
||||
<button class="small" data-force-hide-menu id="open-log-button">• Log</button>
|
||||
</td>
|
||||
<td class="feature-disabled" id="wol">
|
||||
<button class="small" disabled data-force-hide-menu id="wol-wakeup-button">• WoL</button>
|
||||
<button class="gpio-button small" data-force-hide-menu id="gpio-button-__wol__" data-channel="__wol__" data-confirm="Are you sure to send Wake-on-LAN packet to the server?">• WoL</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@ -12,7 +12,9 @@ li(class="right")
|
||||
td(id="webterm" class="feature-disabled") #[button(data-force-hide-menu data-show-window="webterm-window" class="small") • Term]
|
||||
td #[button(data-force-hide-menu data-show-window="about-window" class="small") • About]
|
||||
td #[button(data-force-hide-menu id="open-log-button" class="small") • Log]
|
||||
td(id="wol" class="feature-disabled") #[button(disabled data-force-hide-menu id="wol-wakeup-button" class="small") • WoL]
|
||||
td(id="wol" class="feature-disabled")
|
||||
button(data-force-hide-menu id="gpio-button-__wol__" class="gpio-button small" data-channel="__wol__"
|
||||
data-confirm="Are you sure to send Wake-on-LAN packet to the server?") • WoL
|
||||
hr
|
||||
table(class="kv" style="width: calc(100% - 20px)")
|
||||
tr(id="stream-resolution" class="feature-disabled")
|
||||
|
||||
@ -105,6 +105,7 @@ export function Gpio() {
|
||||
}
|
||||
|
||||
tools.featureSetEnabled($("v3-usb-breaker"), ("__v3_usb_breaker__" in model.scheme.outputs));
|
||||
tools.featureSetEnabled($("wol"), ("__wol__" in model.scheme.outputs));
|
||||
|
||||
self.setState(__state);
|
||||
};
|
||||
|
||||
@ -30,7 +30,6 @@ import {Hid} from "./hid.js";
|
||||
import {Atx} from "./atx.js";
|
||||
import {Msd} from "./msd.js";
|
||||
import {Streamer} from "./stream.js";
|
||||
import {WakeOnLan} from "./wol.js";
|
||||
import {Gpio} from "./gpio.js";
|
||||
|
||||
|
||||
@ -48,7 +47,6 @@ export function Session() {
|
||||
var __hid = new Hid(__streamer.getResolution);
|
||||
var __atx = new Atx();
|
||||
var __msd = new Msd();
|
||||
var __wol = new WakeOnLan();
|
||||
var __gpio = new Gpio();
|
||||
|
||||
var __init__ = function() {
|
||||
@ -243,7 +241,6 @@ export function Session() {
|
||||
case "info_hw_state": __setAboutInfoHw(data.event); break;
|
||||
case "info_system_state": __setAboutInfoSystem(data.event); break;
|
||||
case "info_extras_state": __setExtras(data.event); break;
|
||||
case "wol_state": __wol.setState(data.event); break;
|
||||
case "gpio_model_state": __gpio.setModel(data.event); break;
|
||||
case "gpio_state": __gpio.setState(data.event); break;
|
||||
case "hid_keymaps_state": __hid.setKeymaps(data.event); break;
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
/*****************************************************************************
|
||||
# #
|
||||
# KVMD - The main Pi-KVM daemon. #
|
||||
# #
|
||||
# Copyright (C) 2018-2021 Maxim Devaev <mdevaev@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
import {tools, $} from "../tools.js";
|
||||
import {wm} from "../wm.js";
|
||||
|
||||
|
||||
export function WakeOnLan() {
|
||||
var self = this;
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
var __target = {};
|
||||
|
||||
var __init__ = function() {
|
||||
tools.setOnClick($("wol-wakeup-button"), __clickWakeupButton);
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
self.setState = function(state) {
|
||||
if (state) {
|
||||
tools.featureSetEnabled($("wol"), state.enabled);
|
||||
__target = state.target;
|
||||
}
|
||||
wm.setElementEnabled($("wol-wakeup-button"), (state && state.enabled));
|
||||
};
|
||||
|
||||
var __clickWakeupButton = function() {
|
||||
let msg = `
|
||||
Are you sure to send Wake-on-LAN packet to the server?<br>
|
||||
Target: <b>${__target.mac}</b> (${__target.ip}:${__target.port})?
|
||||
`;
|
||||
wm.confirm(msg).then(function(ok) {
|
||||
if (ok) {
|
||||
let http = tools.makeRequest("POST", "/api/wol/wakeup", function() {
|
||||
if (http.readyState === 4) {
|
||||
if (http.status !== 200) {
|
||||
wm.error("Wakeup error:<br>", http.responseText);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
__init__();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user