ib: jig `.data_reset_hack()` with vnc-client failover
Since apparently porting to the new docker container enforces using a vnc password and `asyncvnc` seems to have a bug/mis-config whenever i've tried a pw over a wg tunnel..? Soo, this tries out the old `i3ipc`-win-focus + `xdo` click hack when the above fails. Deats, - add a mod-level `try_xdo_manual()` to wrap calling `i3ipc_xdotool_manual_click_hack()` with an oserr handler, ensure we don't bother trying if `i3ipc` import fails beforehand tho. - call ^ from both the orig case block and the failover from the vnc-client case. - factor the `+no_setup_msg: str` out to mod level and expect it to be `.format()`-ed. - refresh todo around `asyncvnc` pw ish.. - add a new `i3ipc_fin_wins_titled()` window-title scanner which predicates input `titles` and delivers any matches alongside the orig focused win at call time. - tweak `i3ipc_xdotool_manual_click_hack()` to call ^ and remove prior unfactored window scanning logic.alt_tpts_for_perf
parent
f7caa75228
commit
9df1988aa6
|
@ -34,6 +34,7 @@ from piker.brokers._util import get_logger
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .api import Client
|
from .api import Client
|
||||||
from ib_insync import IB
|
from ib_insync import IB
|
||||||
|
import i3ipc
|
||||||
|
|
||||||
log = get_logger('piker.brokers.ib')
|
log = get_logger('piker.brokers.ib')
|
||||||
|
|
||||||
|
@ -48,6 +49,37 @@ _reset_tech: Literal[
|
||||||
] = 'vnc'
|
] = 'vnc'
|
||||||
|
|
||||||
|
|
||||||
|
no_setup_msg:str = (
|
||||||
|
'No data reset hack test setup for {vnc_sockaddr}!\n'
|
||||||
|
'See config setup tips @\n'
|
||||||
|
'https://github.com/pikers/piker/tree/master/piker/brokers/ib'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def try_xdo_manual(
|
||||||
|
vnc_sockaddr: str,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Do the "manual" `xdo`-based screen switch + click
|
||||||
|
combo since apparently the `asyncvnc` client ain't workin..
|
||||||
|
|
||||||
|
Note this is only meant as a backup method for Xorg users,
|
||||||
|
ideally you can use a real vnc client and the `vnc_click_hack()`
|
||||||
|
impl!
|
||||||
|
|
||||||
|
'''
|
||||||
|
global _reset_tech
|
||||||
|
try:
|
||||||
|
i3ipc_xdotool_manual_click_hack()
|
||||||
|
_reset_tech = 'i3ipc_xdotool'
|
||||||
|
return True
|
||||||
|
except OSError:
|
||||||
|
log.exception(
|
||||||
|
no_setup_msg.format(vnc_sockaddr)
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def data_reset_hack(
|
async def data_reset_hack(
|
||||||
# vnc_host: str,
|
# vnc_host: str,
|
||||||
client: Client,
|
client: Client,
|
||||||
|
@ -90,15 +122,9 @@ async def data_reset_hack(
|
||||||
vnc_port: int
|
vnc_port: int
|
||||||
vnc_sockaddr: tuple[str] | None = client.conf.get('vnc_addrs')
|
vnc_sockaddr: tuple[str] | None = client.conf.get('vnc_addrs')
|
||||||
|
|
||||||
no_setup_msg:str = (
|
|
||||||
f'No data reset hack test setup for {vnc_sockaddr}!\n'
|
|
||||||
'See config setup tips @\n'
|
|
||||||
'https://github.com/pikers/piker/tree/master/piker/brokers/ib'
|
|
||||||
)
|
|
||||||
|
|
||||||
if not vnc_sockaddr:
|
if not vnc_sockaddr:
|
||||||
log.warning(
|
log.warning(
|
||||||
no_setup_msg
|
no_setup_msg.format(vnc_sockaddr)
|
||||||
+
|
+
|
||||||
'REQUIRES A `vnc_addrs: array` ENTRY'
|
'REQUIRES A `vnc_addrs: array` ENTRY'
|
||||||
)
|
)
|
||||||
|
@ -119,27 +145,38 @@ async def data_reset_hack(
|
||||||
port=vnc_port,
|
port=vnc_port,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except OSError:
|
except (
|
||||||
if vnc_host != 'localhost':
|
OSError, # no VNC server avail..
|
||||||
log.warning(no_setup_msg)
|
PermissionError, # asyncvnc pw fail..
|
||||||
return False
|
):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import i3ipc # noqa (since a deps dynamic check)
|
import i3ipc # noqa (since a deps dynamic check)
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
log.warning(no_setup_msg)
|
log.warning(
|
||||||
|
no_setup_msg.format(vnc_sockaddr)
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
if vnc_host not in {
|
||||||
i3ipc_xdotool_manual_click_hack()
|
'localhost',
|
||||||
_reset_tech = 'i3ipc_xdotool'
|
'127.0.0.1',
|
||||||
return True
|
}:
|
||||||
except OSError:
|
focussed, matches = i3ipc_fin_wins_titled()
|
||||||
log.exception(no_setup_msg)
|
if not matches:
|
||||||
|
log.warning(
|
||||||
|
no_setup_msg.format(vnc_sockaddr)
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
else:
|
||||||
|
try_xdo_manual(vnc_sockaddr)
|
||||||
|
|
||||||
|
# localhost but no vnc-client or it borked..
|
||||||
|
else:
|
||||||
|
try_xdo_manual(vnc_sockaddr)
|
||||||
|
|
||||||
case 'i3ipc_xdotool':
|
case 'i3ipc_xdotool':
|
||||||
i3ipc_xdotool_manual_click_hack()
|
try_xdo_manual(vnc_sockaddr)
|
||||||
|
# i3ipc_xdotool_manual_click_hack()
|
||||||
|
|
||||||
case _ as tech:
|
case _ as tech:
|
||||||
raise RuntimeError(f'{tech} is not supported for reset tech!?')
|
raise RuntimeError(f'{tech} is not supported for reset tech!?')
|
||||||
|
@ -178,9 +215,9 @@ async def vnc_click_hack(
|
||||||
host,
|
host,
|
||||||
port=port,
|
port=port,
|
||||||
|
|
||||||
# TODO: doesn't work see:
|
# TODO: doesn't work?
|
||||||
# https://github.com/barneygale/asyncvnc/issues/7
|
# see, https://github.com/barneygale/asyncvnc/issues/7
|
||||||
# password='ibcansmbz',
|
password='doggy',
|
||||||
|
|
||||||
) as client:
|
) as client:
|
||||||
|
|
||||||
|
@ -194,34 +231,67 @@ async def vnc_click_hack(
|
||||||
client.keyboard.press('Ctrl', 'Alt', key) # keys are stacked
|
client.keyboard.press('Ctrl', 'Alt', key) # keys are stacked
|
||||||
|
|
||||||
|
|
||||||
|
def i3ipc_fin_wins_titled(
|
||||||
|
titles: list[str] = [
|
||||||
|
'Interactive Brokers', # tws running in i3
|
||||||
|
'IB Gateway', # gw running in i3
|
||||||
|
# 'IB', # gw running in i3 (newer version?)
|
||||||
|
|
||||||
|
# !TODO, remote vnc instance
|
||||||
|
# -[ ] something in title (or other Con-props) that indicates
|
||||||
|
# this is explicitly for ibrk sw?
|
||||||
|
# |_[ ] !can use modden spawn eventually!
|
||||||
|
'TigerVNC',
|
||||||
|
# 'vncviewer', # the terminal..
|
||||||
|
],
|
||||||
|
) -> tuple[
|
||||||
|
i3ipc.Con, # orig focussed win
|
||||||
|
list[tuple[str, i3ipc.Con]], # matching wins by title
|
||||||
|
]:
|
||||||
|
'''
|
||||||
|
Attempt to find a local-DE window titled with an entry in
|
||||||
|
`titles`.
|
||||||
|
|
||||||
|
If found deliver the current focussed window and all matching
|
||||||
|
`i3ipc.Con`s in a list.
|
||||||
|
|
||||||
|
'''
|
||||||
|
import i3ipc
|
||||||
|
ipc = i3ipc.Connection()
|
||||||
|
|
||||||
|
# TODO: might be worth offering some kinda api for grabbing
|
||||||
|
# the window id from the pid?
|
||||||
|
# https://stackoverflow.com/a/2250879
|
||||||
|
tree = ipc.get_tree()
|
||||||
|
focussed: i3ipc.Con = tree.find_focused()
|
||||||
|
|
||||||
|
matches: list[i3ipc.Con] = []
|
||||||
|
for name in titles:
|
||||||
|
results = tree.find_titled(name)
|
||||||
|
print(f'results for {name}: {results}')
|
||||||
|
if results:
|
||||||
|
con = results[0]
|
||||||
|
matches.append((
|
||||||
|
name,
|
||||||
|
con,
|
||||||
|
))
|
||||||
|
|
||||||
|
return (
|
||||||
|
focussed,
|
||||||
|
matches,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def i3ipc_xdotool_manual_click_hack() -> None:
|
def i3ipc_xdotool_manual_click_hack() -> None:
|
||||||
'''
|
'''
|
||||||
Do the data reset hack but expecting a local X-window using `xdotool`.
|
Do the data reset hack but expecting a local X-window using `xdotool`.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import i3ipc
|
focussed, matches = i3ipc_fin_wins_titled()
|
||||||
i3 = i3ipc.Connection()
|
orig_win_id = focussed.window
|
||||||
|
|
||||||
# TODO: might be worth offering some kinda api for grabbing
|
|
||||||
# the window id from the pid?
|
|
||||||
# https://stackoverflow.com/a/2250879
|
|
||||||
t = i3.get_tree()
|
|
||||||
|
|
||||||
orig_win_id = t.find_focused().window
|
|
||||||
|
|
||||||
# for tws
|
|
||||||
win_names: list[str] = [
|
|
||||||
'Interactive Brokers', # tws running in i3
|
|
||||||
'IB Gateway', # gw running in i3
|
|
||||||
# 'IB', # gw running in i3 (newer version?)
|
|
||||||
]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for name in win_names:
|
for name, con in matches:
|
||||||
results = t.find_titled(name)
|
|
||||||
print(f'results for {name}: {results}')
|
|
||||||
if results:
|
|
||||||
con = results[0]
|
|
||||||
print(f'Resetting data feed for {name}')
|
print(f'Resetting data feed for {name}')
|
||||||
win_id = str(con.window)
|
win_id = str(con.window)
|
||||||
w, h = con.rect.width, con.rect.height
|
w, h = con.rect.width, con.rect.height
|
||||||
|
|
Loading…
Reference in New Issue