diff --git a/.gitignore b/.gitignore index dd5c1b4..7a40350 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ bak __pycache__ @DS -*.whl \ No newline at end of file +gui.toml +*.log +doc \ No newline at end of file diff --git a/config/imaging/asd.json b/config/imaging/asd.json new file mode 100644 index 0000000..78eaa8f --- /dev/null +++ b/config/imaging/asd.json @@ -0,0 +1 @@ +{"t_start": 21, "t_end": 838} \ No newline at end of file diff --git a/config/imaging/asdads.json b/config/imaging/asdads.json new file mode 100644 index 0000000..3cab43d --- /dev/null +++ b/config/imaging/asdads.json @@ -0,0 +1 @@ +{"t_start": 0, "t_end": 1499} \ No newline at end of file diff --git a/flandre/__init__.py b/flandre/__init__.py index 67e3530..e6f7b26 100644 --- a/flandre/__init__.py +++ b/flandre/__init__.py @@ -1,5 +1,5 @@ from pathlib import Path -MODULE_FOLDER = Path(__file__) +MODULE_FOLDER = Path(__file__).parent ASSETS = MODULE_FOLDER / 'assets' -DEV_PROJECT_FOLDER = MODULE_FOLDER.parent.parent \ No newline at end of file +DEV_PROJECT_FOLDER = MODULE_FOLDER.parent \ No newline at end of file diff --git a/flandre/config.py b/flandre/config.py index 1c7c77f..8eb1691 100644 --- a/flandre/config.py +++ b/flandre/config.py @@ -21,9 +21,9 @@ SWITCH1_TOKEN = '7ad51e0016e7a9d22f753d5110f76c7d' SWITCH2_IP = 'c2' SWITCH2_TOKEN = 'bf5a7b77a1ba3761ea63fafd8427b7d6' +CONFIG_FOLDER = platformdirs.user_config_path('Flandre', 'Scarlet') + if ISDEV: - CONFIG_FOLDER = platformdirs.user_config_path('Flandre', 'Scarlet') -else: CONFIG_FOLDER = DEV_PROJECT_FOLDER / 'config' DS = DEV_PROJECT_FOLDER / '@DS' @@ -42,6 +42,12 @@ class SoftwareConfig: p.mkdir(exist_ok=True, parents=True) 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_width: int = 1080 @@ -57,6 +63,10 @@ class SoftwareConfig: def live_rep_socket(self): 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 def read_config(path: Path): j = json.loads(path.read_text(encoding='utf-8')) diff --git a/flandre/kde_pyqt6_mainui.py b/flandre/kde_pyqt6_mainui.py new file mode 100644 index 0000000..8bc09cb --- /dev/null +++ b/flandre/kde_pyqt6_mainui.py @@ -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()() diff --git a/flandre/launcher.py b/flandre/launcher.py new file mode 100644 index 0000000..563eba5 --- /dev/null +++ b/flandre/launcher.py @@ -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') diff --git a/flandre/main.py b/flandre/main.py deleted file mode 100644 index 6c7f7a7..0000000 --- a/flandre/main.py +++ /dev/null @@ -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() diff --git a/flandre/nodes/Beamformer.py b/flandre/nodes/Beamformer.py index a6d1901..cf82f66 100644 --- a/flandre/nodes/Beamformer.py +++ b/flandre/nodes/Beamformer.py @@ -5,7 +5,7 @@ import cupy as cp import cv2 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.utils.Msg import BMMsg, ImageArgMsg, SetSeqMetaMsg, Msg, RfFrameWithMetaMsg, BeamformerMsg, RequestRfFrameMsg, \ SeqMetaMsg diff --git a/flandre/nodes/Device.py b/flandre/nodes/Device.py index 3d9f142..36d567c 100644 --- a/flandre/nodes/Device.py +++ b/flandre/nodes/Device.py @@ -8,7 +8,7 @@ from threading import Thread import zmq 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.utils.Msg import ImageArgMsg, KillMsg, SetDeviceConnectedMsg, SetDeviceEnabledMsg, DeviceEnabledMsg, \ DeviceConnectedMsg, SetDeviceConfigMsg, DeviceOnlineMsg, DeviceConfigListMsg, RequestRfFrameMsg, RfFrameWithMetaMsg, \ @@ -81,7 +81,7 @@ class Device(Node): self.context.term() self.context = zmq.Context() 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): self.switch = False logger.warning(f"interrupt connecting") @@ -89,7 +89,7 @@ class Device(Node): self.context.term() self.context = zmq.Context() 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): self.device_cmd(DeviceCmd.SetConnectionOff) @@ -120,7 +120,7 @@ class Device(Node): return False 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 logger.debug(f'detect curl code: {code}') match code: @@ -198,7 +198,7 @@ class Device(Node): self.c.poller.register(self.rep_socket, zmq.POLLIN) 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.start() @@ -209,7 +209,7 @@ class Device(Node): self.get_connection() self.get_enable() 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())) self.send(DeviceConfigListMsg(arr)) # if arr.__len__() > 0: diff --git a/flandre/nodes/ImageFFMPEG.py b/flandre/nodes/ImageFFMPEG.py index c12f39c..edd3f74 100644 --- a/flandre/nodes/ImageFFMPEG.py +++ b/flandre/nodes/ImageFFMPEG.py @@ -6,7 +6,7 @@ import numpy as np import zmq 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.utils.Msg import BMMsg, SetWindowVisibleMsg, Msg diff --git a/flandre/nodes/Muxer.py b/flandre/nodes/Muxer.py index 4ae4705..9bca775 100644 --- a/flandre/nodes/Muxer.py +++ b/flandre/nodes/Muxer.py @@ -4,7 +4,7 @@ import time import zmq -from config import IMAGING_CONFIG +from flandre.config import C from flandre.nodes.Node import Node from flandre.utils.Msg import ImageArgMsg, KillMsg, SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, \ ImagingConfigNameListMsg, RfFrameWithMetaMsg, BeamformerMsg, RobotRtsiMsg, SeqMetaMsg @@ -86,7 +86,7 @@ class Muxer(Node): self.arg = ImageArgMsg('', t_start=0, t_end=1499) self.c.poller.register(device_socket, zmq.POLLIN) 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: socks = dict(self.c.poller.poll()) for k in socks: diff --git a/flandre/utils/rtsi/rtsi.py b/flandre/utils/rtsi/rtsi.py index 7df8d6f..ad19442 100644 --- a/flandre/utils/rtsi/rtsi.py +++ b/flandre/utils/rtsi/rtsi.py @@ -4,7 +4,7 @@ import select import sys import logging -import utils.rtsi.serialize as serialize +import flandre.utils.rtsi.serialize as serialize DEFAULT_TIMEOUT = 10.0 diff --git a/gui.py b/gui.py index 9c00655..5b6b337 100644 --- a/gui.py +++ b/gui.py @@ -1,31 +1,6 @@ -import logging -import multiprocessing +from pathlib import Path -from flandre.BusClient import BusClient - -from flandre.nodes.MainUI import MainUI -from flandre.utils.Msg import KillMsg +from flandre.launcher import launch_from_file if __name__ == '__main__': - logging.basicConfig(level=logging.INFO) - 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 + launch_from_file(Path(__file__).parent / 'gui.toml') diff --git a/test/testpy.py b/test/testpy.py index cf26d2a..5262b96 100644 --- a/test/testpy.py +++ b/test/testpy.py @@ -1,5 +1,6 @@ import dataclasses import inspect +from enum import Enum @dataclasses.dataclass @@ -12,11 +13,15 @@ class ASD: def b(self): return self.aaa +class EE(Enum): + asd = ASD + x=1 if __name__ == '__main__': # print(dir(ASD())) # print(ASD.__dict__) # print(inspect.getmembers(ASD)) # print(inspect.getmembers(ASD)) - for f in dataclasses.fields(ASD): - print(f.name, f.type) + # for f in dataclasses.fields(ASD): + # print(f.name, f.type) + print(EE.asd.value()) \ No newline at end of file