add launcher

This commit is contained in:
flandre 2025-04-12 01:29:38 +08:00
parent 6e8988c988
commit cf72cde59f
15 changed files with 138 additions and 89 deletions

4
.gitignore vendored
View File

@ -3,4 +3,6 @@
bak bak
__pycache__ __pycache__
@DS @DS
*.whl gui.toml
*.log
doc

1
config/imaging/asd.json Normal file
View File

@ -0,0 +1 @@
{"t_start": 21, "t_end": 838}

View File

@ -0,0 +1 @@
{"t_start": 0, "t_end": 1499}

View File

@ -1,5 +1,5 @@
from pathlib import Path from pathlib import Path
MODULE_FOLDER = Path(__file__) MODULE_FOLDER = Path(__file__).parent
ASSETS = MODULE_FOLDER / 'assets' ASSETS = MODULE_FOLDER / 'assets'
DEV_PROJECT_FOLDER = MODULE_FOLDER.parent.parent DEV_PROJECT_FOLDER = MODULE_FOLDER.parent

View File

@ -21,9 +21,9 @@ SWITCH1_TOKEN = '7ad51e0016e7a9d22f753d5110f76c7d'
SWITCH2_IP = 'c2' SWITCH2_IP = 'c2'
SWITCH2_TOKEN = 'bf5a7b77a1ba3761ea63fafd8427b7d6' SWITCH2_TOKEN = 'bf5a7b77a1ba3761ea63fafd8427b7d6'
CONFIG_FOLDER = platformdirs.user_config_path('Flandre', 'Scarlet')
if ISDEV: if ISDEV:
CONFIG_FOLDER = platformdirs.user_config_path('Flandre', 'Scarlet')
else:
CONFIG_FOLDER = DEV_PROJECT_FOLDER / 'config' CONFIG_FOLDER = DEV_PROJECT_FOLDER / 'config'
DS = DEV_PROJECT_FOLDER / '@DS' DS = DEV_PROJECT_FOLDER / '@DS'
@ -42,6 +42,12 @@ class SoftwareConfig:
p.mkdir(exist_ok=True, parents=True) p.mkdir(exist_ok=True, parents=True)
return p return p
@property
def device_config_folder(self):
p = CONFIG_FOLDER / 'device'
p.mkdir(exist_ok=True, parents=True)
return p
video_height: int = 1920 video_height: int = 1920
video_width: int = 1080 video_width: int = 1080
@ -57,6 +63,10 @@ class SoftwareConfig:
def live_rep_socket(self): def live_rep_socket(self):
return f'tcp://{self.live_ip}:{self.live_rep_port}' return f'tcp://{self.live_ip}:{self.live_rep_port}'
@property
def live_rep_socket_http(self):
return f'http://{self.live_ip}:{self.live_rep_port}'
@staticmethod @staticmethod
def read_config(path: Path): def read_config(path: Path):
j = json.loads(path.read_text(encoding='utf-8')) j = json.loads(path.read_text(encoding='utf-8'))

View File

@ -0,0 +1,24 @@
import logging
import os
import subprocess
from pathlib import Path
from PyQt6 import QtWidgets
import flandre
from flandre.nodes.MainUI import MainUI
def kde_pyqt6_mainui():
subprocess.run(['python', __file__],
env=dict(XDG_CURRENT_DESKTOP="KDE",
XDG_RUNTIME_DIR="/run/user/1000",
XDG_SESSION_TYPE="wayland",
PYTHONPATH=os.environ.get('PYTHONPATH', flandre.MODULE_FOLDER.parent), )
)
if __name__ == '__main__':
print(QtWidgets.QStyleFactory.keys())
logging.basicConfig(level=logging.INFO)
MainUI()()

74
flandre/launcher.py Normal file
View File

@ -0,0 +1,74 @@
import logging
import multiprocessing
import os
import tomllib
from enum import Enum
from pathlib import Path
from flandre.BusClient import BusClient
from flandre.kde_pyqt6_mainui import kde_pyqt6_mainui
from flandre.nodes.Beamformer import Beamformer
from flandre.nodes.Broker import Broker
from flandre.nodes.Device import Device
from flandre.nodes.ImageCV import ImageCV
from flandre.nodes.Loader import Loader
from flandre.nodes.MainUI import MainUI
from flandre.nodes.Muxer import Muxer
from flandre.nodes.Robot import Robot
from flandre.nodes.ImageFFMPEG import ImageFFMPEG
from flandre.utils.Msg import KillMsg
from flandre.config import CONFIG_FOLDER
class LaunchComponent(Enum):
MainUI = MainUI
ImageCV = ImageCV
Muxer = Muxer
Robot = Robot
Loader = Loader
Device = Device
Beamformer = Beamformer
ImageFFMPEG = ImageFFMPEG
def launch(arg: dict[LaunchComponent, dict]):
ps = [
Broker()
]
for k, v in arg.items():
if k == LaunchComponent.MainUI and os.environ.get('XDG_CURRENT_DESKTOP', None) == 'KDE':
ps.append(kde_pyqt6_mainui)
continue
ps.append(k.value(**v))
logging.basicConfig(level=logging.INFO)
multiprocessing.set_start_method('spawn')
multiprocessing.Pool()
pps = []
for p in ps:
pps.append(multiprocessing.Process(target=p))
for p in pps:
p.start()
c = BusClient(KillMsg)
while True:
x: KillMsg = c.recv()
if x.name == '':
break
for p in pps:
p.kill()
def launch_from_file(file: Path):
if not file.exists():
file.parent.mkdir(parents=True, exist_ok=True)
file.write_text('[MainUI]\n')
r = tomllib.loads(file.read_text())
arg_d = dict()
for k, v in r.items():
arg_d[LaunchComponent[k]] = v
launch(arg_d)
if __name__ == '__main__':
launch_from_file(CONFIG_FOLDER / 'gui.toml')

View File

@ -1,43 +0,0 @@
import logging
import multiprocessing
from BusClient import BusClient
from nodes.Beamformer import Beamformer
from nodes.Broker import Broker
from nodes.Device import Device
from nodes.ImageCV import ImageCV
from nodes.Loader import Loader
from nodes.MainUI import MainUI
from nodes.Muxer import Receiver
from nodes.Robot import Robot
from nodes.WebRTC import WebRTC
from utils.Msg import KillMsg
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
multiprocessing.set_start_method('spawn')
multiprocessing.Pool()
pps = []
ps = [
Broker(),
WebRTC(),
MainUI(),
Device(level=logging.DEBUG),
ImageCV(),
Beamformer(),
Loader(),
Receiver(),
Robot(),
]
for p in ps:
pps.append(multiprocessing.Process(target=p))
for p in pps:
p.start()
c = BusClient(KillMsg)
while True:
x: KillMsg = c.recv()
if x.name == '':
break
for p in pps:
p.kill()

View File

@ -5,7 +5,7 @@ import cupy as cp
import cv2 import cv2
import zmq import zmq
from flandre.config import C.video_width, C.video_height from flandre.config import C
from flandre.nodes.Node import Node from flandre.nodes.Node import Node
from flandre.utils.Msg import BMMsg, ImageArgMsg, SetSeqMetaMsg, Msg, RfFrameWithMetaMsg, BeamformerMsg, RequestRfFrameMsg, \ from flandre.utils.Msg import BMMsg, ImageArgMsg, SetSeqMetaMsg, Msg, RfFrameWithMetaMsg, BeamformerMsg, RequestRfFrameMsg, \
SeqMetaMsg SeqMetaMsg

View File

@ -8,7 +8,7 @@ from threading import Thread
import zmq import zmq
from flandre.BusClient import BusClient from flandre.BusClient import BusClient
from config import LIVE_REP_SOCKET, DEVICE_CONFIG from flandre.config import C
from flandre.nodes.Node import Node from flandre.nodes.Node import Node
from flandre.utils.Msg import ImageArgMsg, KillMsg, SetDeviceConnectedMsg, SetDeviceEnabledMsg, DeviceEnabledMsg, \ from flandre.utils.Msg import ImageArgMsg, KillMsg, SetDeviceConnectedMsg, SetDeviceEnabledMsg, DeviceEnabledMsg, \
DeviceConnectedMsg, SetDeviceConfigMsg, DeviceOnlineMsg, DeviceConfigListMsg, RequestRfFrameMsg, RfFrameWithMetaMsg, \ DeviceConnectedMsg, SetDeviceConfigMsg, DeviceOnlineMsg, DeviceConfigListMsg, RequestRfFrameMsg, RfFrameWithMetaMsg, \
@ -81,7 +81,7 @@ class Device(Node):
self.context.term() self.context.term()
self.context = zmq.Context() self.context = zmq.Context()
self.req_driver_socket = self.context.socket(zmq.REQ) self.req_driver_socket = self.context.socket(zmq.REQ)
self.req_driver_socket.connect(f"tcp://{LIVE_REP_SOCKET}") self.req_driver_socket.connect(C.live_rep_socket)
if isinstance(msg, RefreshDeviceMsg): if isinstance(msg, RefreshDeviceMsg):
self.switch = False self.switch = False
logger.warning(f"interrupt connecting") logger.warning(f"interrupt connecting")
@ -89,7 +89,7 @@ class Device(Node):
self.context.term() self.context.term()
self.context = zmq.Context() self.context = zmq.Context()
self.req_driver_socket = self.context.socket(zmq.REQ) self.req_driver_socket = self.context.socket(zmq.REQ)
self.req_driver_socket.connect(f"tcp://{LIVE_REP_SOCKET}") self.req_driver_socket.connect(C.live_rep_socket)
def disconnect(self): def disconnect(self):
self.device_cmd(DeviceCmd.SetConnectionOff) self.device_cmd(DeviceCmd.SetConnectionOff)
@ -120,7 +120,7 @@ class Device(Node):
return False return False
def online(self): def online(self):
code = subprocess.run(['curl', '-m', '1', f'http://{LIVE_REP_SOCKET}'], stderr=subprocess.DEVNULL, code = subprocess.run(['curl', '-m', '1', C.live_rep_socket_http], stderr=subprocess.DEVNULL,
stdout=subprocess.DEVNULL).returncode stdout=subprocess.DEVNULL).returncode
logger.debug(f'detect curl code: {code}') logger.debug(f'detect curl code: {code}')
match code: match code:
@ -198,7 +198,7 @@ class Device(Node):
self.c.poller.register(self.rep_socket, zmq.POLLIN) self.c.poller.register(self.rep_socket, zmq.POLLIN)
self.req_driver_socket = self.context.socket(zmq.REQ) self.req_driver_socket = self.context.socket(zmq.REQ)
self.req_driver_socket.connect(f"tcp://{LIVE_REP_SOCKET}") self.req_driver_socket.connect(C.live_rep_socket)
self.loop2_t = Thread(target=self.loop2) self.loop2_t = Thread(target=self.loop2)
self.loop2_t.start() self.loop2_t.start()
@ -209,7 +209,7 @@ class Device(Node):
self.get_connection() self.get_connection()
self.get_enable() self.get_enable()
self.get_seq_meta_name() self.get_seq_meta_name()
for f in DEVICE_CONFIG.glob('*.txt'): for f in C.device_config_folder.glob('*.txt'):
arr.append((f.stem, f.read_text())) arr.append((f.stem, f.read_text()))
self.send(DeviceConfigListMsg(arr)) self.send(DeviceConfigListMsg(arr))
# if arr.__len__() > 0: # if arr.__len__() > 0:

View File

@ -6,7 +6,7 @@ import numpy as np
import zmq import zmq
from flandre.BusClient import BusClient from flandre.BusClient import BusClient
from flandre.config import C.video_height, C.video_width from flandre.config import C
from flandre.nodes.Node import Node from flandre.nodes.Node import Node
from flandre.utils.Msg import BMMsg, SetWindowVisibleMsg, Msg from flandre.utils.Msg import BMMsg, SetWindowVisibleMsg, Msg

View File

@ -4,7 +4,7 @@ import time
import zmq import zmq
from config import IMAGING_CONFIG from flandre.config import C
from flandre.nodes.Node import Node from flandre.nodes.Node import Node
from flandre.utils.Msg import ImageArgMsg, KillMsg, SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, \ from flandre.utils.Msg import ImageArgMsg, KillMsg, SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, \
ImagingConfigNameListMsg, RfFrameWithMetaMsg, BeamformerMsg, RobotRtsiMsg, SeqMetaMsg ImagingConfigNameListMsg, RfFrameWithMetaMsg, BeamformerMsg, RobotRtsiMsg, SeqMetaMsg
@ -86,7 +86,7 @@ class Muxer(Node):
self.arg = ImageArgMsg('', t_start=0, t_end=1499) self.arg = ImageArgMsg('', t_start=0, t_end=1499)
self.c.poller.register(device_socket, zmq.POLLIN) self.c.poller.register(device_socket, zmq.POLLIN)
time.sleep(1) time.sleep(1)
self.send(ImagingConfigNameListMsg([path.stem for path in IMAGING_CONFIG.glob('*.json')])) self.send(ImagingConfigNameListMsg([path.stem for path in C.imaging_config_folder.glob('*.json')]))
while True: while True:
socks = dict(self.c.poller.poll()) socks = dict(self.c.poller.poll())
for k in socks: for k in socks:

View File

@ -4,7 +4,7 @@ import select
import sys import sys
import logging import logging
import utils.rtsi.serialize as serialize import flandre.utils.rtsi.serialize as serialize
DEFAULT_TIMEOUT = 10.0 DEFAULT_TIMEOUT = 10.0

31
gui.py
View File

@ -1,31 +1,6 @@
import logging from pathlib import Path
import multiprocessing
from flandre.BusClient import BusClient from flandre.launcher import launch_from_file
from flandre.nodes.MainUI import MainUI
from flandre.utils.Msg import KillMsg
if __name__ == '__main__': if __name__ == '__main__':
logging.basicConfig(level=logging.INFO) launch_from_file(Path(__file__).parent / 'gui.toml')
multiprocessing.set_start_method('spawn')
multiprocessing.Pool()
pps = []
ps = [
MainUI(),
]
for p in ps:
pps.append(multiprocessing.Process(target=p))
for p in pps:
p.start()
c = BusClient(KillMsg)
while True:
x: KillMsg = c.recv()
if x.name == '':
break
for p in pps:
p.kill()
if __name__ == '__main__':
pass

View File

@ -1,5 +1,6 @@
import dataclasses import dataclasses
import inspect import inspect
from enum import Enum
@dataclasses.dataclass @dataclasses.dataclass
@ -12,11 +13,15 @@ class ASD:
def b(self): def b(self):
return self.aaa return self.aaa
class EE(Enum):
asd = ASD
x=1
if __name__ == '__main__': if __name__ == '__main__':
# print(dir(ASD())) # print(dir(ASD()))
# print(ASD.__dict__) # print(ASD.__dict__)
# print(inspect.getmembers(ASD)) # print(inspect.getmembers(ASD))
# print(inspect.getmembers(ASD)) # print(inspect.getmembers(ASD))
for f in dataclasses.fields(ASD): # for f in dataclasses.fields(ASD):
print(f.name, f.type) # print(f.name, f.type)
print(EE.asd.value())