mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 01:00:29 +08:00
new ocr event format
This commit is contained in:
parent
a26aee3543
commit
76d70d0838
@ -97,25 +97,6 @@ class StreamerApi:
|
|||||||
self.__streamer.remove_snapshot()
|
self.__streamer.remove_snapshot()
|
||||||
return make_json_response()
|
return make_json_response()
|
||||||
|
|
||||||
# =====
|
|
||||||
|
|
||||||
async def get_ocr(self) -> dict: # XXX: Ugly hack
|
|
||||||
enabled = self.__ocr.is_available()
|
|
||||||
default: list[str] = []
|
|
||||||
available: list[str] = []
|
|
||||||
if enabled:
|
|
||||||
default = self.__ocr.get_default_langs()
|
|
||||||
available = self.__ocr.get_available_langs()
|
|
||||||
return {
|
|
||||||
"ocr": {
|
|
||||||
"enabled": enabled,
|
|
||||||
"langs": {
|
|
||||||
"default": default,
|
|
||||||
"available": available,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
@exposed_http("GET", "/streamer/ocr")
|
@exposed_http("GET", "/streamer/ocr")
|
||||||
async def __ocr_handler(self, _: Request) -> Response:
|
async def __ocr_handler(self, _: Request) -> Response:
|
||||||
return make_json_response(await self.get_ocr())
|
return make_json_response({"ocr": (await self.__ocr.get_state())})
|
||||||
|
|||||||
@ -37,6 +37,7 @@ from ctypes import c_void_p
|
|||||||
from ctypes import c_char
|
from ctypes import c_char
|
||||||
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
from typing import AsyncGenerator
|
||||||
|
|
||||||
from PIL import ImageOps
|
from PIL import ImageOps
|
||||||
from PIL import Image as PilImage
|
from PIL import Image as PilImage
|
||||||
@ -107,9 +108,32 @@ class Ocr:
|
|||||||
def __init__(self, data_dir_path: str, default_langs: list[str]) -> None:
|
def __init__(self, data_dir_path: str, default_langs: list[str]) -> None:
|
||||||
self.__data_dir_path = data_dir_path
|
self.__data_dir_path = data_dir_path
|
||||||
self.__default_langs = default_langs
|
self.__default_langs = default_langs
|
||||||
|
self.__notifier = aiotools.AioNotifier()
|
||||||
|
|
||||||
def is_available(self) -> bool:
|
async def get_state(self) -> dict:
|
||||||
return bool(_libtess)
|
enabled = bool(_libtess)
|
||||||
|
default: list[str] = []
|
||||||
|
available: list[str] = []
|
||||||
|
if enabled:
|
||||||
|
default = self.get_default_langs()
|
||||||
|
available = self.get_available_langs()
|
||||||
|
return {
|
||||||
|
"enabled": enabled,
|
||||||
|
"langs": {
|
||||||
|
"default": default,
|
||||||
|
"available": available,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
async def trigger_state(self) -> None:
|
||||||
|
self.__notifier.notify()
|
||||||
|
|
||||||
|
async def poll_state(self) -> AsyncGenerator[dict, None]:
|
||||||
|
while True:
|
||||||
|
await self.__notifier.wait()
|
||||||
|
yield (await self.get_state())
|
||||||
|
|
||||||
|
# =====
|
||||||
|
|
||||||
def get_default_langs(self) -> list[str]:
|
def get_default_langs(self) -> list[str]:
|
||||||
return list(self.__default_langs)
|
return list(self.__default_langs)
|
||||||
|
|||||||
@ -152,6 +152,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
__EV_GPIO_STATE = "gpio_state"
|
__EV_GPIO_STATE = "gpio_state"
|
||||||
__EV_INFO_STATE = "info_state"
|
__EV_INFO_STATE = "info_state"
|
||||||
__EV_STREAMER_STATE = "streamer_state"
|
__EV_STREAMER_STATE = "streamer_state"
|
||||||
|
__EV_OCR_STATE = "ocr_state"
|
||||||
|
|
||||||
def __init__( # pylint: disable=too-many-arguments,too-many-locals
|
def __init__( # pylint: disable=too-many-arguments,too-many-locals
|
||||||
self,
|
self,
|
||||||
@ -185,7 +186,6 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
self.__stream_forever = stream_forever
|
self.__stream_forever = stream_forever
|
||||||
|
|
||||||
self.__hid_api = HidApi(hid, keymap_path, ignore_keys, mouse_x_range, mouse_y_range) # Ugly hack to get keymaps state
|
self.__hid_api = HidApi(hid, keymap_path, ignore_keys, mouse_x_range, mouse_y_range) # Ugly hack to get keymaps state
|
||||||
self.__streamer_api = StreamerApi(streamer, ocr) # Same hack to get ocr langs state
|
|
||||||
self.__apis: list[object] = [
|
self.__apis: list[object] = [
|
||||||
self,
|
self,
|
||||||
AuthApi(auth_manager),
|
AuthApi(auth_manager),
|
||||||
@ -195,7 +195,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
self.__hid_api,
|
self.__hid_api,
|
||||||
AtxApi(atx),
|
AtxApi(atx),
|
||||||
MsdApi(msd),
|
MsdApi(msd),
|
||||||
self.__streamer_api,
|
StreamerApi(streamer, ocr),
|
||||||
ExportApi(info_manager, atx, user_gpio),
|
ExportApi(info_manager, atx, user_gpio),
|
||||||
RedfishApi(info_manager, atx),
|
RedfishApi(info_manager, atx),
|
||||||
]
|
]
|
||||||
@ -206,7 +206,8 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
_Subsystem.make(hid, "HID", "hid_state").add_source("hid_keymaps_state", self.__hid_api.get_keymaps, None, None),
|
_Subsystem.make(hid, "HID", "hid_state").add_source("hid_keymaps_state", self.__hid_api.get_keymaps, None, None),
|
||||||
_Subsystem.make(atx, "ATX", "atx_state"),
|
_Subsystem.make(atx, "ATX", "atx_state"),
|
||||||
_Subsystem.make(msd, "MSD", "msd_state"),
|
_Subsystem.make(msd, "MSD", "msd_state"),
|
||||||
_Subsystem.make(streamer, "Streamer", "streamer_state").add_source("streamer_ocr_state", self.__streamer_api.get_ocr, None, None),
|
_Subsystem.make(streamer, "Streamer", self.__EV_STREAMER_STATE),
|
||||||
|
_Subsystem.make(ocr, "OCR", self.__EV_OCR_STATE),
|
||||||
_Subsystem.make(info_manager, "Info manager", self.__EV_INFO_STATE),
|
_Subsystem.make(info_manager, "Info manager", self.__EV_INFO_STATE),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -370,6 +371,8 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
await self.__poll_info_state(poller)
|
await self.__poll_info_state(poller)
|
||||||
case self.__EV_STREAMER_STATE:
|
case self.__EV_STREAMER_STATE:
|
||||||
await self.__poll_streamer_state(poller)
|
await self.__poll_streamer_state(poller)
|
||||||
|
case self.__EV_OCR_STATE:
|
||||||
|
await self.__poll_ocr_state(poller)
|
||||||
case _:
|
case _:
|
||||||
async for state in poller:
|
async for state in poller:
|
||||||
await self._broadcast_ws_event(event_type, state)
|
await self._broadcast_ws_event(event_type, state)
|
||||||
@ -399,3 +402,8 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
prev.update(state)
|
prev.update(state)
|
||||||
if "features" in prev: # Complete/Full
|
if "features" in prev: # Complete/Full
|
||||||
await self._broadcast_ws_event(self.__EV_STREAMER_STATE, prev, legacy=True)
|
await self._broadcast_ws_event(self.__EV_STREAMER_STATE, prev, legacy=True)
|
||||||
|
|
||||||
|
async def __poll_ocr_state(self, poller: AsyncGenerator[dict, None]) -> None:
|
||||||
|
async for state in poller:
|
||||||
|
await self._broadcast_ws_event(self.__EV_OCR_STATE, state, legacy=False)
|
||||||
|
await self._broadcast_ws_event("streamer_ocr_state", {"ocr": state}, legacy=True)
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export function Ocr(__getGeometry) {
|
|||||||
|
|
||||||
var __start_pos = null;
|
var __start_pos = null;
|
||||||
var __end_pos = null;
|
var __end_pos = null;
|
||||||
var __selection = null;
|
var __sel = null;
|
||||||
|
|
||||||
var __init__ = function() {
|
var __init__ = function() {
|
||||||
tools.el.setOnClick($("stream-ocr-button"), function() {
|
tools.el.setOnClick($("stream-ocr-button"), function() {
|
||||||
@ -54,7 +54,7 @@ export function Ocr(__getGeometry) {
|
|||||||
$("stream-ocr-window").onkeyup = function(event) {
|
$("stream-ocr-window").onkeyup = function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.code === "Enter") {
|
if (event.code === "Enter") {
|
||||||
if (__selection) {
|
if (__sel) {
|
||||||
__recognizeSelection();
|
__recognizeSelection();
|
||||||
wm.closeWindow($("stream-ocr-window"));
|
wm.closeWindow($("stream-ocr-window"));
|
||||||
}
|
}
|
||||||
@ -71,11 +71,14 @@ export function Ocr(__getGeometry) {
|
|||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
self.setState = function(state) {
|
self.setState = function(state) {
|
||||||
let enabled = (state && state.ocr.enabled && !tools.browser.is_mobile);
|
let enabled = (state && state.enabled && !tools.browser.is_mobile);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
let el = $("stream-ocr-lang-selector");
|
let el = $("stream-ocr-lang-selector");
|
||||||
tools.selector.setValues(el, state.ocr.langs.available);
|
el.options.length = 0;
|
||||||
tools.selector.setSelectedValue(el, tools.storage.get("stream.ocr.lang", state.ocr.langs["default"]));
|
for (let lang of state.langs.available) {
|
||||||
|
tools.selector.addOption(el, lang, lang);
|
||||||
|
}
|
||||||
|
el.value = tools.storage.get("stream.ocr.lang", state.langs["default"]);
|
||||||
}
|
}
|
||||||
tools.feature.setEnabled($("stream-ocr"), enabled);
|
tools.feature.setEnabled($("stream-ocr"), enabled);
|
||||||
$("stream-ocr-led").className = (enabled ? "led-gray" : "hidden");
|
$("stream-ocr-led").className = (enabled ? "led-gray" : "hidden");
|
||||||
@ -94,23 +97,23 @@ export function Ocr(__getGeometry) {
|
|||||||
__end_pos = __getGlobalPosition(event);
|
__end_pos = __getGlobalPosition(event);
|
||||||
let width = Math.abs(__start_pos.x - __end_pos.x);
|
let width = Math.abs(__start_pos.x - __end_pos.x);
|
||||||
let height = Math.abs(__start_pos.y - __end_pos.y);
|
let height = Math.abs(__start_pos.y - __end_pos.y);
|
||||||
let el_selection = $("stream-ocr-selection");
|
let el = $("stream-ocr-selection");
|
||||||
el_selection.style.left = Math.min(__start_pos.x, __end_pos.x) + "px";
|
el.style.left = Math.min(__start_pos.x, __end_pos.x) + "px";
|
||||||
el_selection.style.top = Math.min(__start_pos.y, __end_pos.y) + "px";
|
el.style.top = Math.min(__start_pos.y, __end_pos.y) + "px";
|
||||||
el_selection.style.width = width + "px";
|
el.style.width = width + "px";
|
||||||
el_selection.style.height = height + "px";
|
el.style.height = height + "px";
|
||||||
tools.hidden.setVisible(el_selection, (width > 1 || height > 1));
|
tools.hidden.setVisible(el, (width > 1 || height > 1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var __endSelection = function(event) {
|
var __endSelection = function(event) {
|
||||||
__changeSelection(event);
|
__changeSelection(event);
|
||||||
let el_selection = $("stream-ocr-selection");
|
let el = $("stream-ocr-selection");
|
||||||
let ok = (
|
let ok = (
|
||||||
el_selection.offsetWidth > 1 && el_selection.offsetHeight > 1
|
el.offsetWidth > 1 && el.offsetHeight > 1
|
||||||
&& __start_pos !== null && __end_pos !== null
|
&& __start_pos !== null && __end_pos !== null
|
||||||
);
|
);
|
||||||
tools.hidden.setVisible(el_selection, ok);
|
tools.hidden.setVisible(el, ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
let rect = $("stream-box").getBoundingClientRect();
|
let rect = $("stream-box").getBoundingClientRect();
|
||||||
let rel_left = Math.min(__start_pos.x, __end_pos.x) - rect.left;
|
let rel_left = Math.min(__start_pos.x, __end_pos.x) - rect.left;
|
||||||
@ -119,14 +122,14 @@ export function Ocr(__getGeometry) {
|
|||||||
let rel_top = Math.min(__start_pos.y, __end_pos.y) - rect.top + offset;
|
let rel_top = Math.min(__start_pos.y, __end_pos.y) - rect.top + offset;
|
||||||
let rel_bottom = Math.max(__start_pos.y, __end_pos.y) - rect.top + offset;
|
let rel_bottom = Math.max(__start_pos.y, __end_pos.y) - rect.top + offset;
|
||||||
let geo = __getGeometry();
|
let geo = __getGeometry();
|
||||||
__selection = {
|
__sel = {
|
||||||
"left": tools.remap(rel_left, geo.x, geo.width, 0, geo.real_width),
|
"left": tools.remap(rel_left, geo.x, geo.width, 0, geo.real_width),
|
||||||
"right": tools.remap(rel_right, geo.x, geo.width, 0, geo.real_width),
|
"right": tools.remap(rel_right, geo.x, geo.width, 0, geo.real_width),
|
||||||
"top": tools.remap(rel_top, geo.y, geo.height, 0, geo.real_height),
|
"top": tools.remap(rel_top, geo.y, geo.height, 0, geo.real_height),
|
||||||
"bottom": tools.remap(rel_bottom, geo.y, geo.height, 0, geo.real_height),
|
"bottom": tools.remap(rel_bottom, geo.y, geo.height, 0, geo.real_height),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
__selection = null;
|
__sel = null;
|
||||||
}
|
}
|
||||||
__start_pos = null;
|
__start_pos = null;
|
||||||
__end_pos = null;
|
__end_pos = null;
|
||||||
@ -154,7 +157,7 @@ export function Ocr(__getGeometry) {
|
|||||||
tools.hidden.setVisible($("stream-ocr-selection"), false);
|
tools.hidden.setVisible($("stream-ocr-selection"), false);
|
||||||
__start_pos = null;
|
__start_pos = null;
|
||||||
__end_pos = null;
|
__end_pos = null;
|
||||||
__selection = null;
|
__sel = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
var __recognizeSelection = function() {
|
var __recognizeSelection = function() {
|
||||||
@ -164,10 +167,10 @@ export function Ocr(__getGeometry) {
|
|||||||
let params = {
|
let params = {
|
||||||
"ocr": 1,
|
"ocr": 1,
|
||||||
"ocr_langs": $("stream-ocr-lang-selector").value,
|
"ocr_langs": $("stream-ocr-lang-selector").value,
|
||||||
"ocr_left": __selection.left,
|
"ocr_left": __sel.left,
|
||||||
"ocr_top": __selection.top,
|
"ocr_top": __sel.top,
|
||||||
"ocr_right": __selection.right,
|
"ocr_right": __sel.right,
|
||||||
"orc_bottom": __selection.bottom,
|
"orc_bottom": __sel.bottom,
|
||||||
};
|
};
|
||||||
tools.httpGet("/api/streamer/snapshot", params, function(http) {
|
tools.httpGet("/api/streamer/snapshot", params, function(http) {
|
||||||
if (http.status === 200) {
|
if (http.status === 200) {
|
||||||
|
|||||||
@ -368,7 +368,7 @@ export function Session() {
|
|||||||
case "atx_state": __atx.setState(data.event); break;
|
case "atx_state": __atx.setState(data.event); break;
|
||||||
case "msd_state": __msd.setState(data.event); break;
|
case "msd_state": __msd.setState(data.event); break;
|
||||||
case "streamer_state": __streamer.setState(data.event); break;
|
case "streamer_state": __streamer.setState(data.event); break;
|
||||||
case "streamer_ocr_state": __ocr.setState(data.event); break;
|
case "ocr_state": __ocr.setState(data.event); break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user