From e1b942f20131550b4bf08631bcce86026a857b95 Mon Sep 17 00:00:00 2001 From: dudewheresmycode Date: Tue, 14 Oct 2025 10:15:06 -0600 Subject: [PATCH 1/5] Add option for connecting to OpenGolfSim --- src/MainWindow.py | 22 ++-- src/MainWindow.ui | 2 +- src/MainWindow_ui.py | 2 +- src/SettingsForm.py | 25 ++++- src/SettingsForm.ui | 120 ++++++++++++++++++++-- src/SettingsForm_ui.py | 104 +++++++++++++++---- src/ball_data.py | 23 +++++ src/custom_exception.py | 8 +- src/gspro_connect.py | 12 +-- src/log_message.py | 1 + src/ogs_connect.py | 91 +++++++++++++++++ src/ogs_connection.py | 203 +++++++++++++++++++++++++++++++++++++ src/settings.py | 13 ++- src/worker_ogs.py | 27 +++++ src/worker_ogs_messages.py | 56 ++++++++++ 15 files changed, 658 insertions(+), 51 deletions(-) create mode 100644 src/ogs_connect.py create mode 100644 src/ogs_connection.py create mode 100644 src/worker_ogs.py create mode 100644 src/worker_ogs_messages.py diff --git a/src/MainWindow.py b/src/MainWindow.py index 681e55b..c68df5a 100644 --- a/src/MainWindow.py +++ b/src/MainWindow.py @@ -16,9 +16,10 @@ from src.devices import Devices from src.log_message import LogMessage, LogMessageSystems, LogMessageTypes from src.putting_settings import PuttingSettings -from src.settings import Settings, LaunchMonitor +from src.settings import Settings, LaunchMonitor, Simulator from src.PuttingForm import PuttingForm from src.gspro_connection import GSProConnection +from src.ogs_connection import OpenGolfSimConnection from src.device_launch_monitor_screenshot import DeviceLaunchMonitorScreenshot from src.putting import Putting @@ -49,6 +50,7 @@ def __init__(self, app): self.__setup_logging() self.settings = Settings(self.app_paths) self.gspro_connection = GSProConnection(self) + self.ogs_connection = OpenGolfSimConnection(self) self.settings_form = SettingsForm(settings=self.settings, app_paths=self.app_paths) self.putting_settings = PuttingSettings(self.app_paths) self.putting_settings_form = PuttingForm(main_window=self) @@ -125,7 +127,7 @@ def __setup_ui(self): def __auto_start(self): if self.settings.auto_start_all_apps == 'Yes': - if len(self.settings.gspro_path) > 0 and len(self.settings.grspo_window_name) and os.path.exists(self.settings.gspro_path): + if self.settings.simulator_api == Simulator.GSPRO and len(self.settings.gspro_path) > 0 and len(self.settings.grspo_window_name) and os.path.exists(self.settings.gspro_path): self.log_message(LogMessageTypes.LOG_WINDOW, LogMessageSystems.CONNECTOR, f'Starting GSPro') self.gspro_connection.gspro_start(self.settings, True) if self.settings.device_id != LaunchMonitor.RELAY_SERVER and \ @@ -206,10 +208,18 @@ def __shop(self): webbrowser.open(url, new=2) # 2 = open in new tab def __gspro_connect(self): - if self.gspro_connection.connected: - self.gspro_connection.disconnect_from_gspro() - else: - self.gspro_connection.connect_to_gspro() + if self.settings.simulator_api == Simulator.GSPRO: + if self.gspro_connection.connected: + self.gspro_connection.disconnect_from_gspro() + else: + self.gspro_connection.connect_to_gspro() + elif self.settings.simulator_api == Simulator.OPENGOLFSIM: + logging.debug(f'{MainWindow.app_name} Connecting to OpenGolfSim API...') + if self.ogs_connection.connected: + self.ogs_connection.disconnect_from_ogs() + else: + self.ogs_connection.connect_to_ogs() + def __about(self): QMessageBox.information(self, "About", f"{MainWindow.app_name}\nVersion: {MainWindow.version}") diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 2dfd103..160a815 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -48,7 +48,7 @@ - GSPro Connection + Simulator Connection diff --git a/src/MainWindow_ui.py b/src/MainWindow_ui.py index 32e219a..2efd193 100644 --- a/src/MainWindow_ui.py +++ b/src/MainWindow_ui.py @@ -691,7 +691,7 @@ def retranslateUi(self, MainWindow): #if QT_CONFIG(tooltip) self.connector_tab.setToolTip("") #endif // QT_CONFIG(tooltip) - self.groupBox.setTitle(QCoreApplication.translate("MainWindow", u"GSPro Connection", None)) + self.groupBox.setTitle(QCoreApplication.translate("MainWindow", u"Simulator Connection", None)) self.gspro_connect_button.setText(QCoreApplication.translate("MainWindow", u"Connect", None)) self.gspro_status_label.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) self.club_selection.setText("") diff --git a/src/SettingsForm.py b/src/SettingsForm.py index 0ce27d3..15c0cda 100644 --- a/src/SettingsForm.py +++ b/src/SettingsForm.py @@ -5,7 +5,7 @@ from src.SettingsForm_ui import Ui_SettingsForm from src.appdata import AppDataPaths from src.devices import Devices -from src.settings import Settings, LaunchMonitor +from src.settings import Settings, LaunchMonitor, Simulator class SettingsForm(QWidget, Ui_SettingsForm): @@ -26,6 +26,13 @@ def __init__(self, settings: Settings, app_paths: AppDataPaths): self.mevo_offline_mode_combo.addItems(['Yes', 'No']) self.launch_monitor_combo.clear() self.launch_monitor_combo.addItems(SettingsForm.launchmonitor_as_list()) + + self.simulator_combo.clear() + self.simulator_combo.addItems(SettingsForm.simulator_as_list()) + + # self.ogs_settings_groupbox + # self.gspro_settings_groupbox + self.close_button.clicked.connect(self.__close) self.save_button.clicked.connect(self.__save) self.file_browse_button.clicked.connect(self.__file_dialog) @@ -39,6 +46,14 @@ def showEvent(self, event: QShowEvent) -> None: def __close(self): self.close() + @staticmethod + def simulator_as_list(): + keys = [] + for key in Simulator.__dict__: + if key != '__' not in key: + keys.append(getattr(Simulator, key)) + return keys + @staticmethod def launchmonitor_as_list(): keys = [] @@ -49,11 +64,14 @@ def launchmonitor_as_list(): def __save(self): if self.__valid(): + self.settings.simulator_api = self.simulator_combo.currentText() self.settings.ip_address = self.ipaddress_edit.toPlainText() self.settings.port = int(self.port_edit.toPlainText()) self.settings.gspro_path = self.gspro_path_edit.toPlainText() self.settings.grspo_window_name = self.gspro_window_name.toPlainText() self.settings.gspro_api_window_name = self.gspro_api_window_name.toPlainText() + self.settings.ogs_ip_address = self.ogs_ipaddress.toPlainText() + self.settings.ogs_port = int(self.ogs_port.toPlainText()) self.settings.device_id = self.launch_monitor_combo.currentText() self.settings.default_device = self.default_device_combo.currentText() self.settings.relay_server_ip_address = self.relay_server_ip_edit.toPlainText() @@ -89,11 +107,16 @@ def __valid(self): return error def __load_values(self): + self.simulator_combo.setCurrentText(self.settings.simulator_api) self.ipaddress_edit.setPlainText(self.settings.ip_address) self.port_edit.setPlainText(str(self.settings.port)) self.gspro_path_edit.setPlainText(str(self.settings.gspro_path)) self.gspro_window_name.setPlainText(str(self.settings.grspo_window_name)) self.gspro_api_window_name.setPlainText(str(self.settings.gspro_api_window_name)) + + self.ogs_ipaddress.setPlainText(self.settings.ogs_ip_address) + self.ogs_port.setPlainText(str(self.settings.ogs_port)) + self.launch_monitor_combo.setCurrentText(self.settings.device_id) device = 'None' if hasattr(self.settings, 'default_device') and self.settings.default_device != '': diff --git a/src/SettingsForm.ui b/src/SettingsForm.ui index 9a68679..a8c34c2 100644 --- a/src/SettingsForm.ui +++ b/src/SettingsForm.ui @@ -3,7 +3,7 @@ SettingsForm - Qt::ApplicationModal + Qt::WindowModality::ApplicationModal @@ -22,7 +22,32 @@ - + + + Simulator + + + + + + Simulator API + + + + + + + + None + + + + + + + + + GSPro @@ -48,7 +73,7 @@ - Qt::PreventContextMenu + Qt::ContextMenuPolicy::PreventContextMenu GSPro IP Address @@ -177,7 +202,7 @@ Application Path(Opyional) - QPlainTextEdit::WidgetWidth + QPlainTextEdit::LineWrapMode::WidgetWidth GSPro Path @@ -196,10 +221,87 @@ + + + + OpenGolfSim + + + + + + + 0 + 0 + + + + + 0 + 31 + + + + + 16777215 + 31 + + + + Qt::ContextMenuPolicy::PreventContextMenu + + + <html><head/><body><p>The IP address of the computer running OpenGolfSim</p></body></html> + + + true + + + OpenGolfSim IP Address + + + + + + + true + + + + 0 + 0 + + + + + 0 + 31 + + + + + 16777215 + 31 + + + + <html><head/><body><p>The port of the OpenGolfSim API</p></body></html> + + + true + + + OpenGolfSim Port + + + + + + - Qt::Vertical + Qt::Orientation::Vertical @@ -574,7 +676,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -593,7 +695,7 @@ - QLayout::SetMinimumSize + QLayout::SizeConstraint::SetMinimumSize @@ -731,7 +833,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -746,7 +848,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal diff --git a/src/SettingsForm_ui.py b/src/SettingsForm_ui.py index 1ee7167..d132e7c 100644 --- a/src/SettingsForm_ui.py +++ b/src/SettingsForm_ui.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'SettingsForm.ui' ## -## Created by: Qt User Interface Compiler version 6.5.2 +## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -23,7 +23,7 @@ class Ui_SettingsForm(object): def setupUi(self, SettingsForm): if not SettingsForm.objectName(): SettingsForm.setObjectName(u"SettingsForm") - SettingsForm.setWindowModality(Qt.ApplicationModal) + SettingsForm.setWindowModality(Qt.WindowModality.ApplicationModal) SettingsForm.resize(981, 510) self.horizontalLayout_7 = QHBoxLayout(SettingsForm) self.horizontalLayout_7.setObjectName(u"horizontalLayout_7") @@ -31,25 +31,43 @@ def setupUi(self, SettingsForm): self.horizontalLayout_6.setObjectName(u"horizontalLayout_6") self.verticalLayout_8 = QVBoxLayout() self.verticalLayout_8.setObjectName(u"verticalLayout_8") - self.r10_settings_groupbox_2 = QGroupBox(SettingsForm) - self.r10_settings_groupbox_2.setObjectName(u"r10_settings_groupbox_2") - self.verticalLayout_7 = QVBoxLayout(self.r10_settings_groupbox_2) + self.groupBox_3 = QGroupBox(SettingsForm) + self.groupBox_3.setObjectName(u"groupBox_3") + self.horizontalLayout_18 = QHBoxLayout(self.groupBox_3) + self.horizontalLayout_18.setObjectName(u"horizontalLayout_18") + self.simulator_label = QLabel(self.groupBox_3) + self.simulator_label.setObjectName(u"simulator_label") + + self.horizontalLayout_18.addWidget(self.simulator_label) + + self.simulator_combo = QComboBox(self.groupBox_3) + self.simulator_combo.addItem("") + self.simulator_combo.setObjectName(u"simulator_combo") + + self.horizontalLayout_18.addWidget(self.simulator_combo) + + + self.verticalLayout_8.addWidget(self.groupBox_3) + + self.gspro_settings_groupbox = QGroupBox(SettingsForm) + self.gspro_settings_groupbox.setObjectName(u"gspro_settings_groupbox") + self.verticalLayout_7 = QVBoxLayout(self.gspro_settings_groupbox) self.verticalLayout_7.setObjectName(u"verticalLayout_7") - self.ipaddress_edit = QPlainTextEdit(self.r10_settings_groupbox_2) + self.ipaddress_edit = QPlainTextEdit(self.gspro_settings_groupbox) self.ipaddress_edit.setObjectName(u"ipaddress_edit") - sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.ipaddress_edit.sizePolicy().hasHeightForWidth()) self.ipaddress_edit.setSizePolicy(sizePolicy) self.ipaddress_edit.setMinimumSize(QSize(0, 31)) self.ipaddress_edit.setMaximumSize(QSize(16777215, 31)) - self.ipaddress_edit.setContextMenuPolicy(Qt.PreventContextMenu) + self.ipaddress_edit.setContextMenuPolicy(Qt.ContextMenuPolicy.PreventContextMenu) self.ipaddress_edit.setTabChangesFocus(True) self.verticalLayout_7.addWidget(self.ipaddress_edit) - self.gspro_window_name = QPlainTextEdit(self.r10_settings_groupbox_2) + self.gspro_window_name = QPlainTextEdit(self.gspro_settings_groupbox) self.gspro_window_name.setObjectName(u"gspro_window_name") sizePolicy.setHeightForWidth(self.gspro_window_name.sizePolicy().hasHeightForWidth()) self.gspro_window_name.setSizePolicy(sizePolicy) @@ -58,10 +76,10 @@ def setupUi(self, SettingsForm): self.verticalLayout_7.addWidget(self.gspro_window_name) - self.port_edit = QPlainTextEdit(self.r10_settings_groupbox_2) + self.port_edit = QPlainTextEdit(self.gspro_settings_groupbox) self.port_edit.setObjectName(u"port_edit") self.port_edit.setEnabled(True) - sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.port_edit.sizePolicy().hasHeightForWidth()) @@ -72,7 +90,7 @@ def setupUi(self, SettingsForm): self.verticalLayout_7.addWidget(self.port_edit) - self.gspro_api_window_name = QPlainTextEdit(self.r10_settings_groupbox_2) + self.gspro_api_window_name = QPlainTextEdit(self.gspro_settings_groupbox) self.gspro_api_window_name.setObjectName(u"gspro_api_window_name") sizePolicy.setHeightForWidth(self.gspro_api_window_name.sizePolicy().hasHeightForWidth()) self.gspro_api_window_name.setSizePolicy(sizePolicy) @@ -83,17 +101,17 @@ def setupUi(self, SettingsForm): self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") - self.gspro_path_edit = QPlainTextEdit(self.r10_settings_groupbox_2) + self.gspro_path_edit = QPlainTextEdit(self.gspro_settings_groupbox) self.gspro_path_edit.setObjectName(u"gspro_path_edit") sizePolicy.setHeightForWidth(self.gspro_path_edit.sizePolicy().hasHeightForWidth()) self.gspro_path_edit.setSizePolicy(sizePolicy) self.gspro_path_edit.setMinimumSize(QSize(300, 0)) self.gspro_path_edit.setMaximumSize(QSize(16777215, 31)) - self.gspro_path_edit.setLineWrapMode(QPlainTextEdit.WidgetWidth) + self.gspro_path_edit.setLineWrapMode(QPlainTextEdit.LineWrapMode.WidgetWidth) self.horizontalLayout_2.addWidget(self.gspro_path_edit) - self.file_browse_button = QPushButton(self.r10_settings_groupbox_2) + self.file_browse_button = QPushButton(self.gspro_settings_groupbox) self.file_browse_button.setObjectName(u"file_browse_button") self.horizontalLayout_2.addWidget(self.file_browse_button) @@ -102,9 +120,38 @@ def setupUi(self, SettingsForm): self.verticalLayout_7.addLayout(self.horizontalLayout_2) - self.verticalLayout_8.addWidget(self.r10_settings_groupbox_2) + self.verticalLayout_8.addWidget(self.gspro_settings_groupbox) + + self.ogs_settings_groupbox = QGroupBox(SettingsForm) + self.ogs_settings_groupbox.setObjectName(u"ogs_settings_groupbox") + self.verticalLayout_11 = QVBoxLayout(self.ogs_settings_groupbox) + self.verticalLayout_11.setObjectName(u"verticalLayout_11") + self.ogs_ipaddress = QPlainTextEdit(self.ogs_settings_groupbox) + self.ogs_ipaddress.setObjectName(u"ogs_ipaddress") + sizePolicy.setHeightForWidth(self.ogs_ipaddress.sizePolicy().hasHeightForWidth()) + self.ogs_ipaddress.setSizePolicy(sizePolicy) + self.ogs_ipaddress.setMinimumSize(QSize(0, 31)) + self.ogs_ipaddress.setMaximumSize(QSize(16777215, 31)) + self.ogs_ipaddress.setContextMenuPolicy(Qt.ContextMenuPolicy.PreventContextMenu) + self.ogs_ipaddress.setTabChangesFocus(True) + + self.verticalLayout_11.addWidget(self.ogs_ipaddress) + + self.ogs_port = QPlainTextEdit(self.ogs_settings_groupbox) + self.ogs_port.setObjectName(u"ogs_port") + self.ogs_port.setEnabled(True) + sizePolicy1.setHeightForWidth(self.ogs_port.sizePolicy().hasHeightForWidth()) + self.ogs_port.setSizePolicy(sizePolicy1) + self.ogs_port.setMinimumSize(QSize(0, 31)) + self.ogs_port.setMaximumSize(QSize(16777215, 31)) + self.ogs_port.setTabChangesFocus(True) - self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalLayout_11.addWidget(self.ogs_port) + + + self.verticalLayout_8.addWidget(self.ogs_settings_groupbox) + + self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_8.addItem(self.verticalSpacer_2) @@ -266,7 +313,7 @@ def setupUi(self, SettingsForm): self.verticalLayout_5.addWidget(self.groupBox_2) - self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_5.addItem(self.verticalSpacer_3) @@ -279,7 +326,7 @@ def setupUi(self, SettingsForm): self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout_3 = QVBoxLayout() self.verticalLayout_3.setObjectName(u"verticalLayout_3") - self.verticalLayout_3.setSizeConstraint(QLayout.SetMinimumSize) + self.verticalLayout_3.setSizeConstraint(QLayout.SizeConstraint.SetMinimumSize) self.horizontalLayout_9 = QHBoxLayout() self.horizontalLayout_9.setObjectName(u"horizontalLayout_9") self.label_7 = QLabel(SettingsForm) @@ -346,13 +393,13 @@ def setupUi(self, SettingsForm): self.verticalLayout_2.addLayout(self.horizontalLayout_15) - self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_2.addItem(self.verticalSpacer) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName(u"horizontalLayout") - self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.horizontalLayout.addItem(self.horizontalSpacer) @@ -383,7 +430,11 @@ def setupUi(self, SettingsForm): def retranslateUi(self, SettingsForm): SettingsForm.setWindowTitle(QCoreApplication.translate("SettingsForm", u"Settings", None)) - self.r10_settings_groupbox_2.setTitle(QCoreApplication.translate("SettingsForm", u"GSPro", None)) + self.groupBox_3.setTitle(QCoreApplication.translate("SettingsForm", u"Simulator", None)) + self.simulator_label.setText(QCoreApplication.translate("SettingsForm", u"Simulator API", None)) + self.simulator_combo.setItemText(0, QCoreApplication.translate("SettingsForm", u"None", None)) + + self.gspro_settings_groupbox.setTitle(QCoreApplication.translate("SettingsForm", u"GSPro", None)) #if QT_CONFIG(tooltip) self.ipaddress_edit.setToolTip(QCoreApplication.translate("SettingsForm", u"GSPro IP Address", None)) #endif // QT_CONFIG(tooltip) @@ -405,6 +456,15 @@ def retranslateUi(self, SettingsForm): #endif // QT_CONFIG(tooltip) self.gspro_path_edit.setPlaceholderText(QCoreApplication.translate("SettingsForm", u"GSPro Path", None)) self.file_browse_button.setText(QCoreApplication.translate("SettingsForm", u"Browse", None)) + self.ogs_settings_groupbox.setTitle(QCoreApplication.translate("SettingsForm", u"OpenGolfSim", None)) +#if QT_CONFIG(tooltip) + self.ogs_ipaddress.setToolTip(QCoreApplication.translate("SettingsForm", u"

The IP address of the computer running OpenGolfSim

", None)) +#endif // QT_CONFIG(tooltip) + self.ogs_ipaddress.setPlaceholderText(QCoreApplication.translate("SettingsForm", u"OpenGolfSim IP Address", None)) +#if QT_CONFIG(tooltip) + self.ogs_port.setToolTip(QCoreApplication.translate("SettingsForm", u"

The port of the OpenGolfSim API

", None)) +#endif // QT_CONFIG(tooltip) + self.ogs_port.setPlaceholderText(QCoreApplication.translate("SettingsForm", u"OpenGolfSim Port", None)) self.label_6.setText(QCoreApplication.translate("SettingsForm", u"Launch Monitor", None)) self.launch_monitor_combo.setItemText(0, QCoreApplication.translate("SettingsForm", u"None", None)) self.launch_monitor_combo.setItemText(1, QCoreApplication.translate("SettingsForm", u"New Item", None)) diff --git a/src/ball_data.py b/src/ball_data.py index bfdfbeb..0495287 100644 --- a/src/ball_data.py +++ b/src/ball_data.py @@ -163,6 +163,29 @@ def ballcolor_as_list(): keys.append(getattr(BallColor, key)) return keys + def to_opengolfsim(self): + payload = { + "shot": { + "ballSpeed": self.speed, + "spinAxis": self.spin_axis, + "spinSpeed": self.total_spin, + "horizontalLaunchAngle": self.hla, + "verticalLaunchAngle": self.vla + # "Backspin": self.back_spin, + # "SideSpin": self.side_spin, + # "CarryDistance": 0 + }, + "club": { + "angleOfAttack": self.angle_of_attack, + "clubPath": self.path, + "clubSpeed": self.club_speed, + "faceToPath": self.face_to_path, + "faceToTarget": self.face_to_target, + "speedAtImpact": self.speed_at_impact + } + } + return payload + def to_gspro(self): payload = { "BallData": { diff --git a/src/custom_exception.py b/src/custom_exception.py index d183f34..31d804f 100644 --- a/src/custom_exception.py +++ b/src/custom_exception.py @@ -5,19 +5,19 @@ class CameraWindowNotFoundException(Exception): pass -class GSProConnectionTimeout(Exception): +class SimTCPConnectionTimeout(Exception): pass -class GSProConnectionSocketError(Exception): +class SimTCPConnectionSocketError(Exception): pass -class GSProConnectionUknownError(Exception): +class SimTCPConnectionUnknownError(Exception): pass -class GSProConnectionGSProClosedConnection(Exception): +class SimTCPConnectionClientClosedConnection(Exception): pass diff --git a/src/gspro_connect.py b/src/gspro_connect.py index d8b7f89..64a37a5 100644 --- a/src/gspro_connect.py +++ b/src/gspro_connect.py @@ -7,8 +7,8 @@ from PySide6.QtCore import QObject from src.ball_data import BallData -from src.custom_exception import GSProConnectionTimeout, GSProConnectionUknownError, \ - GSProConnectionGSProClosedConnection, GSProConnectionSocketError +from src.custom_exception import SimTCPConnectionTimeout, SimTCPConnectionUnknownError, \ + SimTCPConnectionClientClosedConnection, SimTCPConnectionSocketError class GSProConnect(QObject): @@ -43,22 +43,22 @@ def send_msg(self, payload, attempts=2): except socket.timeout: logging.info('Timed out. Retrying...') if attempt >= attempts-1: - raise GSProConnectionTimeout(f'Failed to send shot to GSPro after {attempts} attempts.') + raise SimTCPConnectionTimeout(f'Failed to send shot to GSPro after {attempts} attempts.') Event().wait(0.5) continue except socket.error as e: msg = f'GSPro Connector socket error when trying to send shot, Exception: {format(e)}' logging.debug(msg) - raise GSProConnectionSocketError(msg) + raise SimTCPConnectionSocketError(msg) except Exception as e: msg = f"GSPro Connector unknown error when trying to send shot, Exception: {format(e)}" logging.debug(msg) - raise GSProConnectionUknownError(msg) + raise SimTCPConnectionUnknownError(msg) else: if len(msg) == 0: msg = f"GSPro closed the connection" logging.debug(msg) - raise GSProConnectionGSProClosedConnection(msg) + raise SimTCPConnectionClientClosedConnection(msg) else: logging.debug(f"Response from GSPro: {msg}") return msg diff --git a/src/log_message.py b/src/log_message.py index 5b456d2..3160180 100644 --- a/src/log_message.py +++ b/src/log_message.py @@ -6,6 +6,7 @@ class LogMessageSystems: CONNECTOR = 'Connector' GSPRO_CONNECT = 'GSProConnect' + OPENGOLFSIM = 'OpenGolfSim' WEBCAM_PUTTING = "Webcam Putting" EXPUTT_PUTTING = "ExPutt" RELAY_SERVER = "Relay Server" diff --git a/src/ogs_connect.py b/src/ogs_connect.py new file mode 100644 index 0000000..e6f712b --- /dev/null +++ b/src/ogs_connect.py @@ -0,0 +1,91 @@ +import socket +import logging +import json +from threading import Event + +import select +from PySide6.QtCore import QObject + +from src.ball_data import BallData +from src.custom_exception import SimTCPConnectionTimeout, SimTCPConnectionUnknownError, \ + SimTCPConnectionClientClosedConnection, SimTCPConnectionSocketError + + +class OpenGolfSimConnect(QObject): + + successful_send = 200 + + def __init__(self, device_id, units, api_version) -> None: + self._socket = None + self._device_id = device_id + self._units = units + self._api_version = api_version + self._shot_number = 1 + self._connected = False + super(OpenGolfSimConnect, self).__init__() + + def init_socket(self, ip_address: str, port: int) -> None: + self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._socket.connect((ip_address, port)) + self._socket.settimeout(2) + self._connected = True + + def connected(self): + return self._connected + + def send_msg(self, payload, attempts=2): + if self._connected: + for attempt in range(attempts): + try: + logging.info(f"Sending to GSPro data: {payload}") + self._socket.sendall(payload) + msg = self._socket.recv(2048) + except socket.timeout: + logging.info('Timed out. Retrying...') + if attempt >= attempts-1: + raise SimTCPConnectionTimeout(f'Failed to send shot to GSPro after {attempts} attempts.') + Event().wait(0.5) + continue + except socket.error as e: + msg = f'OpenGolfSim socket error when trying to send shot, Exception: {format(e)}' + logging.debug(msg) + raise SimTCPConnectionSocketError(msg) + except Exception as e: + msg = f"OpenGolfSim unknown error when trying to send shot, Exception: {format(e)}" + logging.debug(msg) + raise SimTCPConnectionUnknownError(msg) + else: + if len(msg) == 0: + msg = f"OpenGolfSim closed the connection" + logging.debug(msg) + raise SimTCPConnectionClientClosedConnection(msg) + else: + logging.debug(f"Response from OpenGolfSim: {msg}") + return msg + + def launch_ball(self, ball_data: BallData) -> None: + if self._connected: + device = { + "DeviceID": self._device_id, + "Units": self._units, + "ShotNumber": self._shot_number, + "APIversion": self._api_version + } + payload = device | ball_data.to_opengolfsim() + logging.debug(f'Launch Ball payload: {payload} ball_data.to_opengolfsim(): {ball_data.to_opengolfsim()}') + self.send_msg(json.dumps(payload).encode("utf-8")) + self._shot_number += 1 + + def check_for_message(self): + message = bytes(0) + if self._connected: + read_socket, write_socket, error_socket = select.select([self._socket], [], [], 0) + while read_socket: + message = message + self._socket.recv(1024) + read_socket, write_socket, error_socket = select.select([self._socket], [], [], 0) + return message + + def terminate_session(self): + if self._socket: + self._socket.close() + self._connected = False diff --git a/src/ogs_connection.py b/src/ogs_connection.py new file mode 100644 index 0000000..02e3ac7 --- /dev/null +++ b/src/ogs_connection.py @@ -0,0 +1,203 @@ +import logging +import os + +from PySide6.QtCore import QThread, Signal, QObject +from PySide6.QtWidgets import QMessageBox +from src.ctype_screenshot import ScreenMirrorWindow +from src.ogs_connect import OpenGolfSimConnect +from src.worker_ogs_messages import WorkerOpenGolfSimMessages +# from src.worker_gspro_start import WorkerGSProStart +from src.worker_ogs import WorkerOpenGolfSim +from src.log_message import LogMessageSystems, LogMessageTypes +from src.worker_thread import WorkerThread +from PySide6.QtCore import QProcess + +class OpenGolfSimConnection(QObject): + connected_to_ogs = Signal() + disconnected_from_ogs = Signal() + club_selected = Signal(object) + ogs_message = Signal(object) + + def __init__(self, main_window): + super(OpenGolfSimConnection, self).__init__() + self.main_window = main_window + self.current_club = None + self.worker = None + self.thread = None + self.ogs_messages_thread = None + self.ogs_messages_worker = None + self.send_shot_thread = None + self.send_shot_worker = None + self.ogs_start_worker = None + self.ogs_start_thread = None + self.connected = False + self.settings = main_window.settings + self.ogs_connect = OpenGolfSimConnect( + self.settings.device_id, + self.settings.units, + self.settings.api_version + ) + self.__ogs_disconnected() + self.__setup_send_shot_thread() + self.__setup_ogs_messages_thread() + + + def __ogs_disconnected(self): + self.main_window.gspro_connect_button.setEnabled(True) + self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, 'Disconnected from OpenGolfSim') + self.main_window.gspro_connect_button.setText('Connect') + self.main_window.gspro_status_label.setText('Not Connected') + self.main_window.gspro_status_label.setStyleSheet(f"QLabel {{ background-color : red; color : white; }}") + + def __setup_send_shot_thread(self): + self.send_shot_thread = QThread() + self.send_shot_worker = WorkerOpenGolfSim(self.ogs_connect) + self.send_shot_worker.moveToThread(self.send_shot_thread) + self.send_shot_worker.started.connect(self.__sending_shot) + self.send_shot_worker.sent.connect(self.main_window.shot_sent) + self.send_shot_worker.error.connect(self.__send_shot_error) + self.send_shot_thread.started.connect(self.send_shot_worker.run) + self.send_shot_thread.start() + + def __setup_ogs_messages_thread(self): + self.ogs_messages_thread = QThread() + self.ogs_messages_worker = WorkerOpenGolfSimMessages(self.ogs_connect) + self.ogs_messages_worker.moveToThread(self.ogs_messages_thread) + self.ogs_messages_worker.club_selected.connect(self.__club_selected) + self.ogs_messages_worker.error.connect(self.__ogs_messages_error) + self.ogs_messages_worker.ogs_message.connect(self.__ogs_message) + self.ogs_messages_thread.started.connect(self.ogs_messages_worker.run) + self.ogs_messages_thread.start() + + def __ogs_message(self, message): + self.ogs_message.emit(message) + + def __setup_connection_thread(self): + self.thread = QThread() + self.worker = WorkerThread(self.ogs_connect.init_socket, self.settings.ogs_ip_address, self.settings.ogs_port) + self.worker.moveToThread(self.thread) + self.worker.started.connect(self.__in_progress) + self.worker.result.connect(self.__connected) + self.worker.error.connect(self.__error) + # self.worker.finished.connect(self.__finished) + self.thread.started.connect(self.worker.run()) + self.thread.start() + + def __club_selecion_error(self, error): + self.disconnect_from_ogs() + msg = f"Error while trying to check for club selection messages from GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." + self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') + QMessageBox.warning(self.main_window, "GSPro Receive Error", msg) + + def __club_selected(self, club_data): + logging.debug(f"{self.__class__.__name__} Club selected: {club_data['Player']['Club']}") + if club_data['Player']['Club'] == "PT": + self.main_window.club_selection.setText('Putter') + self.main_window.club_selection.setStyleSheet(f"QLabel {{ background-color : green; color : white; }}") + else: + self.main_window.club_selection.setText(club_data['Player']['Club']) + self.main_window.club_selection.setStyleSheet(f"QLabel {{ background-color : orange; color : white; }}") + self.club_selected.emit(club_data) + if self.current_club != club_data['Player']['Club']: + self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.CONNECTOR, f'Club selected: {club_data["Player"]["Club"]}') + self.current_club = club_data['Player']['Club'] + + def __send_shot_error(self, error): + self.disconnect_from_ogs() + msg = f"Error while trying to send shot to GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." + self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') + QMessageBox.warning(self.main_window, "GSPro Send Error", msg) + + def __ogs_messages_error(self, error): + self.disconnect_from_ogs() + msg = f"Error while trying to check for new messages from GSPro.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." + self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') + QMessageBox.warning(self.main_window, "GSPro Message Receive Error", msg) + + def connect_to_ogs(self): + if not self.connected: + # if self.__find_gspro_api_app(): + if self.thread is None: + self.__setup_connection_thread() + else: + if not self.ogs_connect.connected(): + self.worker.run() + if self.ogs_messages_thread is None: + self.__setup_ogs_messages_thread() + self.ogs_messages_worker.start() + if self.send_shot_thread is None: + self.__setup_send_shot_thread() + self.send_shot_worker.start() + # self.__shutdown_ogs_start_thread() + + def disconnect_from_ogs(self): + if self.connected: + self.connected = False + self.__ogs_disconnected() + self.send_shot_worker.stop() + self.ogs_messages_worker.stop() + self.ogs_connect.terminate_session() + self.disconnected_from_ogs.emit() + + def __sending_shot(self): + self.__log_message(LogMessageTypes.ALL, 'Sending shot to GSPro') + + def __in_progress(self): + msg = 'Connecting...' + self.__log_message(LogMessageTypes.ALL, f'Connecting to GSPro...') + self.__log_message(LogMessageTypes.LOGS, f'Connection settings: {self.settings.to_json(True)}') + self.main_window.gspro_status_label.setText(msg) + self.main_window.gspro_status_label.setStyleSheet("QLabel { background-color : orange; color : white; }") + self.main_window.gspro_connect_button.setEnabled(False) + + def __connected(self): + self.connected = True + self.main_window.gspro_connect_button.setEnabled(True) + self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, f'Connected to OpenGolfSim') + self.main_window.gspro_connect_button.setText('Disconnect') + self.main_window.gspro_status_label.setText('Connected') + self.main_window.gspro_status_label.setStyleSheet(f"QLabel {{ background-color : green; color : white; }}") + self.connected_to_ogs.emit() + + def __error(self, error): + self.disconnect_from_ogs() + msg = "Error while trying to connect to OpenGolfSim.\nMake sure OpenGolfSim API Connect is running.\nStart/restart API Connect from OpenGolfSim.\nPress 'Connect' to reconnect to OpenGolfSim." + self.__log_message(LogMessageTypes.LOGS, f'{msg} Exception: {format(error)}') + QMessageBox.warning(self.main_window, "OpenGolfSim Connect Error", msg) + + def shutdown(self): + self.ogs_connect.terminate_session() + self.connected = False + self.__shutdown_threads() + + def __log_message(self, types, message): + self.main_window.log_message(types, LogMessageSystems.OPENGOLFSIM, message) + + def __shutdown_threads(self): + if self.ogs_messages_thread is not None: + self.ogs_messages_worker.shutdown() + self.ogs_messages_thread.quit() + self.ogs_messages_thread.wait() + self.ogs_messages_thread = None + self.ogs_messages_worker = None + if self.send_shot_thread is not None: + self.send_shot_thread.quit() + self.send_shot_thread.wait() + self.send_shot_thread = None + self.send_shot_worker = None + if self.thread is not None: + self.thread.quit() + self.thread.wait() + self.thread = None + self.worker = None + + def __shutdown_ogs_start_thread(self): + logging.debug(f'{self.__class__.__name__} Shutting down threads, ogs_start_thread') + if self.ogs_start_thread is not None: + self.ogs_start_worker.shutdown() + if self.ogs_start_thread.isRunning(): + logging.debug(f'{self.__class__.__name__} Quitting ogs_start_thread') + self.ogs_start_thread.quit() + self.ogs_start_thread.wait() + self.ogs_start_thread = None + self.ogs_start_worker = None diff --git a/src/settings.py b/src/settings.py index c70afc6..f242435 100644 --- a/src/settings.py +++ b/src/settings.py @@ -3,6 +3,11 @@ from src.settings_base import SettingsBase +@dataclass +class Simulator: + GSPRO = "GSPro" + OPENGOLFSIM = 'OpenGolfSim' + @dataclass class LaunchMonitor: MLM2PRO = "Rapsodo MLM2PRO" @@ -30,6 +35,7 @@ def __init__(self, app_paths): name='settings', ext='.json' ), { + "simulator_api": Simulator.GSPRO, "ip_address": "127.0.0.1", "port": 921, "api_version": "1", @@ -47,7 +53,9 @@ def __init__(self, app_paths): "relay_server_ip_address": "127.0.0.1", "relay_server_port": 9234, 'auto_start_all_apps': 'No', - 'keep_log_history': 'No' + 'keep_log_history': 'No', + "ogs_ip_address": "127.0.0.1", + "ogs_port": 3111 } ) # Removed this from the settings file, specifies the @@ -115,6 +123,9 @@ def load(self): "offline_mode": "No" } save = True + if not hasattr(self, 'simulator_api'): + self.simulator_api = Simulator.GSPRO + save = True if save: super().save() diff --git a/src/worker_ogs.py b/src/worker_ogs.py new file mode 100644 index 0000000..87f926c --- /dev/null +++ b/src/worker_ogs.py @@ -0,0 +1,27 @@ +import traceback +from PySide6.QtCore import Signal + +from src.ogs_connect import OpenGolfSimConnect +from src.worker_base import WorkerBase + + +class WorkerOpenGolfSim(WorkerBase): + sent = Signal(object or None) + + def __init__(self, ogs_connection: OpenGolfSimConnect): + super().__init__() + self.ogs_connection = ogs_connection + + def run(self, balldata=None): + if balldata is not None: + try: + self.started.emit() + self.ogs_connection.launch_ball(balldata) + except Exception as e: + traceback.print_exc() + self.error.emit((e, traceback.format_exc())) + else: + self.sent.emit(balldata) # Return the result of the processing + finally: + self.finished.emit() # Done + \ No newline at end of file diff --git a/src/worker_ogs_messages.py b/src/worker_ogs_messages.py new file mode 100644 index 0000000..46f5fc4 --- /dev/null +++ b/src/worker_ogs_messages.py @@ -0,0 +1,56 @@ +import json +import logging +import re +import traceback +from threading import Event +from PySide6.QtCore import Signal +from src.ogs_connect import OpenGolfSimConnect +from src.worker_base import WorkerBase +from src.worker_screenshot_device_base import WorkerScreenshotBase + + +class WorkerOpenGolfSimMessages(WorkerBase): + player_info = 201 + club_selected = Signal(object) + ogs_message = Signal(object) + + def __init__(self, ogs_connection: OpenGolfSimConnect): + super().__init__() + self.ogs_connection = ogs_connection + self.name = 'WorkerOpenGolfSimMessages' + + def run(self): + self.started.emit() + logging.debug(f'{self.name} Started') + # Execute if not shutdown + while not self._shutdown.is_set(): + Event().wait(250/1000) + # When _pause is clear we wait(suspended) if set we process + self._pause.wait() + if not self._shutdown.is_set() and self.ogs_connection is not None and self.ogs_connection.connected(): + try: + message = self.ogs_connection.check_for_message() + if len(message) > 0: + logging.debug(f'{self.name}: Received data: {message}') + self.ogs_message.emit(message) + self.__process_message(message) + except Exception as e: + if not isinstance(e, ValueError): + self.pause() + traceback.print_exc() + logging.debug(f'Error in process {self.name}: {format(e)}, {traceback.format_exc()}') + self.error.emit((e, traceback.format_exc())) + self.finished.emit() + + def __process_message(self, message): + messages = {} + json_messages = re.split(r'(\{.*?})(?= *\{)', message.decode("utf-8")) + for json_message in json_messages: + if len(json_message) > 0: + logging.debug(f'__process_message json_message: {json_message}') + msg = json.loads(json_message) + messages[str(msg['Code'])] = msg + # # Check if club selection message + # if msg['Code'] == WorkerGSProMessages.player_info: + # self.club_selected.emit(msg) + return messages From a21adb946de12b4f13666e16f39ae5e81a99d86b Mon Sep 17 00:00:00 2001 From: dudewheresmycode Date: Tue, 14 Oct 2025 10:15:37 -0600 Subject: [PATCH 2/5] Add workflow build --- .github/workflows/build.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..16d1ec3 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,23 @@ +name: build/python + +on: + push: + branches: + - main + - feat/ogs-beta + ## otherwise we only build when new tags are pushed + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + pyinstaller-build: + runs-on: windows-latest + steps: + - name: Create Executable + uses: sayyid5416/pyinstaller@v1 + with: + python_ver: '3.6' + spec: 'MLM2Pro-GSPro-Connector.spec' + requirements: 'requirements.txt' + upload_exe_with_name: 'MLM2Pro-OGS' + options: --onefile, --name "MLM2Pro OGS", --windowed, \ No newline at end of file From aab573156a52ca14ca1f378ecb6a020fe91504fd Mon Sep 17 00:00:00 2001 From: dudewheresmycode Date: Tue, 14 Oct 2025 10:21:15 -0600 Subject: [PATCH 3/5] Set python version to 3.12 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 16d1ec3..8957eea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: - name: Create Executable uses: sayyid5416/pyinstaller@v1 with: - python_ver: '3.6' + python_ver: '3.12' spec: 'MLM2Pro-GSPro-Connector.spec' requirements: 'requirements.txt' upload_exe_with_name: 'MLM2Pro-OGS' From 6346196e82b74364ddb79f07e0694be30c740bf2 Mon Sep 17 00:00:00 2001 From: dudewheresmycode Date: Tue, 14 Oct 2025 10:27:52 -0600 Subject: [PATCH 4/5] Add and do not ignore missing secret file --- .gitignore | 3 ++- src/bluetooth/mlm2pro_secret.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 src/bluetooth/mlm2pro_secret.py diff --git a/.gitignore b/.gitignore index b1c786d..f613c21 100644 --- a/.gitignore +++ b/.gitignore @@ -165,5 +165,6 @@ train.traineddata.old mlm2pro_bt_app/ r10_bt_app/ -src/bluetooth/mlm2pro_secret.py +# track this file, but use a no-op +# src/bluetooth/mlm2pro_secret.py nuitka-build/ diff --git a/src/bluetooth/mlm2pro_secret.py b/src/bluetooth/mlm2pro_secret.py new file mode 100644 index 0000000..d3366ff --- /dev/null +++ b/src/bluetooth/mlm2pro_secret.py @@ -0,0 +1,5 @@ +class MLM2PROSecret: + + @staticmethod + def decrypt(data: str): + return "" \ No newline at end of file From bd6290d5681e82079067f91b828d52a018fc82b9 Mon Sep 17 00:00:00 2001 From: dudewheresmycode Date: Tue, 14 Oct 2025 17:21:37 -0600 Subject: [PATCH 5/5] major refactor for dual sim connector --- src/MainWindow.py | 39 ++-- src/MainWindow.ui | 94 ++++---- src/MainWindow_ui.py | 140 ++++++------ src/{ogs_connect.py => connect_base.py} | 29 +-- src/{gspro_connect.py => connect_gspro.py} | 5 +- src/connect_ogs.py | 75 +++++++ src/device_base.py | 2 +- src/device_launch_monitor_bluetooth_base.py | 6 +- src/device_launch_monitor_relay_server.py | 22 +- ...device_launch_monitor_relay_server_base.py | 23 +- src/device_launch_monitor_screenshot.py | 16 +- src/device_putting_base.py | 12 +- src/ogs_connection.py | 203 ------------------ ...{gspro_connection.py => sim_connection.py} | 164 ++++++++------ ...rker_device_launch_monitor_relay_server.py | 10 +- src/worker_ogs.py | 27 --- src/worker_ogs_messages.py | 56 ----- src/{worker_gspro.py => worker_sim.py} | 10 +- ...pro_messages.py => worker_sim_messages.py} | 21 +- 19 files changed, 379 insertions(+), 575 deletions(-) rename src/{ogs_connect.py => connect_base.py} (72%) rename src/{gspro_connect.py => connect_gspro.py} (96%) create mode 100644 src/connect_ogs.py delete mode 100644 src/ogs_connection.py rename src/{gspro_connection.py => sim_connection.py} (67%) delete mode 100644 src/worker_ogs.py delete mode 100644 src/worker_ogs_messages.py rename src/{worker_gspro.py => worker_sim.py} (71%) rename src/{worker_gspro_messages.py => worker_sim_messages.py} (71%) diff --git a/src/MainWindow.py b/src/MainWindow.py index c68df5a..d8213f5 100644 --- a/src/MainWindow.py +++ b/src/MainWindow.py @@ -18,8 +18,9 @@ from src.putting_settings import PuttingSettings from src.settings import Settings, LaunchMonitor, Simulator from src.PuttingForm import PuttingForm -from src.gspro_connection import GSProConnection -from src.ogs_connection import OpenGolfSimConnection +from src.sim_connection import SimConnection +# from src.gspro_connection import GSProConnection +# from src.ogs_connection import OpenGolfSimConnection from src.device_launch_monitor_screenshot import DeviceLaunchMonitorScreenshot from src.putting import Putting @@ -32,8 +33,8 @@ class LogTableCols: class MainWindow(QMainWindow, Ui_MainWindow): - version = 'V1.04.22 Beta' - app_name = 'MLM2PRO-GSPro-Connector' + version = 'V2.0.0 Beta' + app_name = 'MLM2PRO-Universal-Connector' good_shot_color = '#62ff00' good_putt_color = '#fbff00' bad_shot_color = '#ff3800' @@ -49,8 +50,7 @@ def __init__(self, app): self.app_paths.setup() self.__setup_logging() self.settings = Settings(self.app_paths) - self.gspro_connection = GSProConnection(self) - self.ogs_connection = OpenGolfSimConnection(self) + self.sim_connection = SimConnection(self, simulator_api=self.settings.simulator_api) self.settings_form = SettingsForm(settings=self.settings, app_paths=self.app_paths) self.putting_settings = PuttingSettings(self.app_paths) self.putting_settings_form = PuttingForm(main_window=self) @@ -88,12 +88,13 @@ def showEvent(self, event: QShowEvent) -> None: def __setup_ui(self): self.__setup_launch_monitor() + self.sim_group_box.setTitle(f"{self.settings.simulator_api} Connection") self.actionExit.triggered.connect(self.__exit) self.actionAbout.triggered.connect(self.__about) self.actionSettings.triggered.connect(self.__settings) self.actionDonate.triggered.connect(self.__donate) self.actionShop.triggered.connect(self.__shop) - self.gspro_connect_button.clicked.connect(self.__gspro_connect) + self.gspro_connect_button.clicked.connect(self.__sim_connect) self.main_tab.setCurrentIndex(0) #self.log_table.horizontalHeader().setStretchLastSection(True) self.log_table.setHorizontalHeaderLabels(['Date', 'Type', 'System', 'Message']) @@ -129,7 +130,8 @@ def __auto_start(self): if self.settings.auto_start_all_apps == 'Yes': if self.settings.simulator_api == Simulator.GSPRO and len(self.settings.gspro_path) > 0 and len(self.settings.grspo_window_name) and os.path.exists(self.settings.gspro_path): self.log_message(LogMessageTypes.LOG_WINDOW, LogMessageSystems.CONNECTOR, f'Starting GSPro') - self.gspro_connection.gspro_start(self.settings, True) + self.sim_connection.gspro_start(self.settings, True) + # self.gspro_connection.gspro_start(self.settings, True) if self.settings.device_id != LaunchMonitor.RELAY_SERVER and \ self.settings.device_id != LaunchMonitor.MLM2PRO_BT and \ self.settings.device_id != LaunchMonitor.R10_BT and \ @@ -189,8 +191,8 @@ def __exit(self): self.close() def closeEvent(self, event: QShowEvent) -> None: - logging.debug(f'{MainWindow.app_name} Closing gspro connection') - self.gspro_connection.shutdown() + logging.debug(f'{MainWindow.app_name} Closing simulator connection') + self.sim_connection.shutdown() logging.debug(f'{MainWindow.app_name} Closing putting') self.putting.shutdown() logging.debug(f'{MainWindow.app_name} Closing launch monitor connection') @@ -207,18 +209,11 @@ def __shop(self): url = "https://cascadia3dpd.com" webbrowser.open(url, new=2) # 2 = open in new tab - def __gspro_connect(self): - if self.settings.simulator_api == Simulator.GSPRO: - if self.gspro_connection.connected: - self.gspro_connection.disconnect_from_gspro() - else: - self.gspro_connection.connect_to_gspro() - elif self.settings.simulator_api == Simulator.OPENGOLFSIM: - logging.debug(f'{MainWindow.app_name} Connecting to OpenGolfSim API...') - if self.ogs_connection.connected: - self.ogs_connection.disconnect_from_ogs() - else: - self.ogs_connection.connect_to_ogs() + def __sim_connect(self): + if self.sim_connection.connected: + self.sim_connection.disconnect_sim() + else: + self.sim_connection.connect_sim() def __about(self): diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 160a815..8091a51 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -38,26 +38,26 @@ - QLayout::SetFixedSize + QLayout::SizeConstraint::SetFixedSize - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint - + Simulator Connection - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint @@ -102,7 +102,7 @@ TextLabel
- Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -133,7 +133,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -143,7 +143,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -165,12 +165,12 @@ - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint @@ -215,7 +215,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -246,7 +246,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -256,7 +256,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -280,13 +280,13 @@ - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint @@ -318,7 +318,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -349,7 +349,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -367,7 +367,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -385,7 +385,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -403,7 +403,7 @@ Mode - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -431,7 +431,7 @@ - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint @@ -463,7 +463,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -494,7 +494,7 @@ TextLabel - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -525,7 +525,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -556,7 +556,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -587,7 +587,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -618,7 +618,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter 5 @@ -631,7 +631,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -640,14 +640,14 @@ - QLayout::SetFixedSize + QLayout::SizeConstraint::SetFixedSize - QLayout::SetFixedSize + QLayout::SizeConstraint::SetFixedSize @@ -660,7 +660,7 @@ Ball Speed - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -675,7 +675,7 @@ Spin Axis - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter
@@ -690,7 +690,7 @@ Spin Rate
- Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter
@@ -705,7 +705,7 @@ Launch Dir (HLA)
- Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter
@@ -720,7 +720,7 @@ Path
- Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter
@@ -735,7 +735,7 @@ Impact Speed - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -744,7 +744,7 @@ - QLayout::SetFixedSize + QLayout::SizeConstraint::SetFixedSize @@ -877,7 +877,7 @@ - QLayout::SetFixedSize + QLayout::SizeConstraint::SetFixedSize @@ -890,7 +890,7 @@ Launch Angle (VLA) - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -905,7 +905,7 @@ Club Speed - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -920,7 +920,7 @@ Back Spin - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -935,7 +935,7 @@ Side Spin - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -950,7 +950,7 @@ Face to Target - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -965,7 +965,7 @@ Angle of Attack - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -974,7 +974,7 @@ - QLayout::SetFixedSize + QLayout::SizeConstraint::SetFixedSize @@ -1136,10 +1136,10 @@ - QAbstractItemView::ScrollPerItem + QAbstractItemView::ScrollMode::ScrollPerItem - QAbstractItemView::ScrollPerItem + QAbstractItemView::ScrollMode::ScrollPerItem false diff --git a/src/MainWindow_ui.py b/src/MainWindow_ui.py index 2efd193..8b070cc 100644 --- a/src/MainWindow_ui.py +++ b/src/MainWindow_ui.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'MainWindow.ui' ## -## Created by: Qt User Interface Compiler version 6.5.2 +## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -29,43 +29,43 @@ def setupUi(self, MainWindow): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(1349, 804) icon = QIcon() - icon.addFile(u":/ico/ico/connect.ico", QSize(), QIcon.Normal, QIcon.Off) + icon.addFile(u":/ico/ico/connect.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) MainWindow.setWindowIcon(icon) MainWindow.setWindowOpacity(6.000000000000000) self.actionExit = QAction(MainWindow) self.actionExit.setObjectName(u"actionExit") icon1 = QIcon() - icon1.addFile(u":/ico/ico/exit.ico", QSize(), QIcon.Normal, QIcon.Off) + icon1.addFile(u":/ico/ico/exit.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.actionExit.setIcon(icon1) self.actionDevices = QAction(MainWindow) self.actionDevices.setObjectName(u"actionDevices") icon2 = QIcon() - icon2.addFile(u":/ico/ico/devices.ico", QSize(), QIcon.Normal, QIcon.Off) + icon2.addFile(u":/ico/ico/devices.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.actionDevices.setIcon(icon2) self.actionSettings = QAction(MainWindow) self.actionSettings.setObjectName(u"actionSettings") icon3 = QIcon() - icon3.addFile(u":/ico/ico/settings.ico", QSize(), QIcon.Normal, QIcon.Off) + icon3.addFile(u":/ico/ico/settings.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.actionSettings.setIcon(icon3) self.actionAbout = QAction(MainWindow) self.actionAbout.setObjectName(u"actionAbout") icon4 = QIcon() - icon4.addFile(u":/ico/ico/about.ico", QSize(), QIcon.Normal, QIcon.Off) + icon4.addFile(u":/ico/ico/about.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.actionAbout.setIcon(icon4) self.actionPuttingSettings = QAction(MainWindow) self.actionPuttingSettings.setObjectName(u"actionPuttingSettings") icon5 = QIcon() - icon5.addFile(u":/ico/ico/Iconsmind-Outline-Golf-2.ico", QSize(), QIcon.Normal, QIcon.Off) + icon5.addFile(u":/ico/ico/Iconsmind-Outline-Golf-2.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.actionPuttingSettings.setIcon(icon5) self.actionDonate = QAction(MainWindow) self.actionDonate.setObjectName(u"actionDonate") icon6 = QIcon() - icon6.addFile(u":/ico/ico/nav-logo-stroke.ico", QSize(), QIcon.Normal, QIcon.Off) + icon6.addFile(u":/ico/ico/nav-logo-stroke.ico", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.actionDonate.setIcon(icon6) self.actionShop = QAction(MainWindow) self.actionShop.setObjectName(u"actionShop") icon7 = QIcon() - icon7.addFile(u":/ico/ico/store_2838968.png", QSize(), QIcon.Normal, QIcon.Off) + icon7.addFile(u":/ico/ico/store_2838968.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) self.actionShop.setIcon(icon7) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") @@ -79,21 +79,21 @@ def setupUi(self, MainWindow): self.verticalLayout_7.setObjectName(u"verticalLayout_7") self.verticalLayout_5 = QVBoxLayout() self.verticalLayout_5.setObjectName(u"verticalLayout_5") - self.verticalLayout_5.setSizeConstraint(QLayout.SetFixedSize) + self.verticalLayout_5.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize) self.horizontalLayout_8 = QHBoxLayout() self.horizontalLayout_8.setObjectName(u"horizontalLayout_8") - self.horizontalLayout_8.setSizeConstraint(QLayout.SetDefaultConstraint) - self.groupBox = QGroupBox(self.connector_tab) - self.groupBox.setObjectName(u"groupBox") - self.horizontalLayout = QHBoxLayout(self.groupBox) + self.horizontalLayout_8.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) + self.sim_group_box = QGroupBox(self.connector_tab) + self.sim_group_box.setObjectName(u"sim_group_box") + self.horizontalLayout = QHBoxLayout(self.sim_group_box) self.horizontalLayout.setObjectName(u"horizontalLayout") - self.horizontalLayout.setSizeConstraint(QLayout.SetDefaultConstraint) + self.horizontalLayout.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) self.verticalLayout = QVBoxLayout() self.verticalLayout.setObjectName(u"verticalLayout") - self.verticalLayout.setSizeConstraint(QLayout.SetDefaultConstraint) - self.gspro_connect_button = QPushButton(self.groupBox) + self.verticalLayout.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) + self.gspro_connect_button = QPushButton(self.sim_group_box) self.gspro_connect_button.setObjectName(u"gspro_connect_button") - sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) + sizePolicy = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.gspro_connect_button.sizePolicy().hasHeightForWidth()) @@ -102,9 +102,9 @@ def setupUi(self, MainWindow): self.verticalLayout.addWidget(self.gspro_connect_button) - self.gspro_status_label = QLabel(self.groupBox) + self.gspro_status_label = QLabel(self.sim_group_box) self.gspro_status_label.setObjectName(u"gspro_status_label") - sizePolicy1 = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Preferred) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.gspro_status_label.sizePolicy().hasHeightForWidth()) @@ -114,23 +114,23 @@ def setupUi(self, MainWindow): font.setPointSize(12) font.setBold(False) self.gspro_status_label.setFont(font) - self.gspro_status_label.setAlignment(Qt.AlignCenter) + self.gspro_status_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.gspro_status_label.setMargin(5) self.verticalLayout.addWidget(self.gspro_status_label) - self.club_selection = QLabel(self.groupBox) + self.club_selection = QLabel(self.sim_group_box) self.club_selection.setObjectName(u"club_selection") sizePolicy1.setHeightForWidth(self.club_selection.sizePolicy().hasHeightForWidth()) self.club_selection.setSizePolicy(sizePolicy1) self.club_selection.setMinimumSize(QSize(120, 0)) self.club_selection.setFont(font) - self.club_selection.setAlignment(Qt.AlignCenter) + self.club_selection.setAlignment(Qt.AlignmentFlag.AlignCenter) self.club_selection.setMargin(5) self.verticalLayout.addWidget(self.club_selection) - self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout.addItem(self.verticalSpacer) @@ -138,16 +138,16 @@ def setupUi(self, MainWindow): self.horizontalLayout.addLayout(self.verticalLayout) - self.horizontalLayout_8.addWidget(self.groupBox) + self.horizontalLayout_8.addWidget(self.sim_group_box) self.groupBox_3 = QGroupBox(self.connector_tab) self.groupBox_3.setObjectName(u"groupBox_3") self.horizontalLayout_3 = QHBoxLayout(self.groupBox_3) self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") - self.horizontalLayout_3.setSizeConstraint(QLayout.SetDefaultConstraint) + self.horizontalLayout_3.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) self.verticalLayout_2 = QVBoxLayout() self.verticalLayout_2.setObjectName(u"verticalLayout_2") - self.verticalLayout_2.setSizeConstraint(QLayout.SetDefaultConstraint) + self.verticalLayout_2.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) self.putting_server_button = QPushButton(self.groupBox_3) self.putting_server_button.setObjectName(u"putting_server_button") sizePolicy.setHeightForWidth(self.putting_server_button.sizePolicy().hasHeightForWidth()) @@ -162,7 +162,7 @@ def setupUi(self, MainWindow): self.putting_system_label.setSizePolicy(sizePolicy1) self.putting_system_label.setMinimumSize(QSize(120, 0)) self.putting_system_label.setFont(font) - self.putting_system_label.setAlignment(Qt.AlignCenter) + self.putting_system_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.putting_system_label.setMargin(5) self.verticalLayout_2.addWidget(self.putting_system_label) @@ -173,12 +173,12 @@ def setupUi(self, MainWindow): self.putting_server_status_label.setSizePolicy(sizePolicy1) self.putting_server_status_label.setMinimumSize(QSize(120, 0)) self.putting_server_status_label.setFont(font) - self.putting_server_status_label.setAlignment(Qt.AlignCenter) + self.putting_server_status_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.putting_server_status_label.setMargin(5) self.verticalLayout_2.addWidget(self.putting_server_status_label) - self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) self.verticalLayout_2.addItem(self.verticalSpacer_2) @@ -194,15 +194,15 @@ def setupUi(self, MainWindow): self.horizontalLayout_13.setObjectName(u"horizontalLayout_13") self.horizontalLayout_12 = QHBoxLayout() self.horizontalLayout_12.setObjectName(u"horizontalLayout_12") - self.horizontalLayout_12.setSizeConstraint(QLayout.SetDefaultConstraint) + self.horizontalLayout_12.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) self.device_control_widget = QWidget(self.launch_monitor_groupbox) self.device_control_widget.setObjectName(u"device_control_widget") self.verticalLayout_8 = QVBoxLayout(self.device_control_widget) self.verticalLayout_8.setObjectName(u"verticalLayout_8") - self.verticalLayout_8.setSizeConstraint(QLayout.SetDefaultConstraint) + self.verticalLayout_8.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) self.select_device_button = QPushButton(self.device_control_widget) self.select_device_button.setObjectName(u"select_device_button") - sizePolicy2 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) + sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) sizePolicy2.setHorizontalStretch(0) sizePolicy2.setVerticalStretch(0) sizePolicy2.setHeightForWidth(self.select_device_button.sizePolicy().hasHeightForWidth()) @@ -216,21 +216,21 @@ def setupUi(self, MainWindow): font1 = QFont() font1.setPointSize(12) self.selected_device.setFont(font1) - self.selected_device.setAlignment(Qt.AlignCenter) + self.selected_device.setAlignment(Qt.AlignmentFlag.AlignCenter) self.selected_device.setMargin(5) self.verticalLayout_8.addWidget(self.selected_device) self.selected_mirror_app = QLabel(self.device_control_widget) self.selected_mirror_app.setObjectName(u"selected_mirror_app") - sizePolicy3 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) + sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) sizePolicy3.setHorizontalStretch(0) sizePolicy3.setVerticalStretch(0) sizePolicy3.setHeightForWidth(self.selected_mirror_app.sizePolicy().hasHeightForWidth()) self.selected_mirror_app.setSizePolicy(sizePolicy3) self.selected_mirror_app.setMinimumSize(QSize(0, 0)) self.selected_mirror_app.setFont(font) - self.selected_mirror_app.setAlignment(Qt.AlignCenter) + self.selected_mirror_app.setAlignment(Qt.AlignmentFlag.AlignCenter) self.selected_mirror_app.setMargin(5) self.verticalLayout_8.addWidget(self.selected_mirror_app) @@ -238,7 +238,7 @@ def setupUi(self, MainWindow): self.connector_status = QLabel(self.device_control_widget) self.connector_status.setObjectName(u"connector_status") self.connector_status.setFont(font1) - self.connector_status.setAlignment(Qt.AlignCenter) + self.connector_status.setAlignment(Qt.AlignmentFlag.AlignCenter) self.connector_status.setMargin(5) self.verticalLayout_8.addWidget(self.connector_status) @@ -246,7 +246,7 @@ def setupUi(self, MainWindow): self.ocr_training_file_label = QLabel(self.device_control_widget) self.ocr_training_file_label.setObjectName(u"ocr_training_file_label") self.ocr_training_file_label.setFont(font1) - self.ocr_training_file_label.setAlignment(Qt.AlignCenter) + self.ocr_training_file_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.ocr_training_file_label.setMargin(5) self.verticalLayout_8.addWidget(self.ocr_training_file_label) @@ -254,7 +254,7 @@ def setupUi(self, MainWindow): self.mode_label = QLabel(self.device_control_widget) self.mode_label.setObjectName(u"mode_label") self.mode_label.setFont(font1) - self.mode_label.setAlignment(Qt.AlignCenter) + self.mode_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.mode_label.setMargin(5) self.verticalLayout_8.addWidget(self.mode_label) @@ -276,7 +276,7 @@ def setupUi(self, MainWindow): self.server_control_widget.setObjectName(u"server_control_widget") self.verticalLayout_12 = QVBoxLayout(self.server_control_widget) self.verticalLayout_12.setObjectName(u"verticalLayout_12") - self.verticalLayout_12.setSizeConstraint(QLayout.SetDefaultConstraint) + self.verticalLayout_12.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) self.start_server_button = QPushButton(self.server_control_widget) self.start_server_button.setObjectName(u"start_server_button") sizePolicy2.setHeightForWidth(self.start_server_button.sizePolicy().hasHeightForWidth()) @@ -288,7 +288,7 @@ def setupUi(self, MainWindow): self.server_status_label = QLabel(self.server_control_widget) self.server_status_label.setObjectName(u"server_status_label") self.server_status_label.setFont(font1) - self.server_status_label.setAlignment(Qt.AlignCenter) + self.server_status_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.server_status_label.setMargin(5) self.verticalLayout_12.addWidget(self.server_status_label) @@ -299,7 +299,7 @@ def setupUi(self, MainWindow): self.server_connection_label.setSizePolicy(sizePolicy3) self.server_connection_label.setMinimumSize(QSize(0, 0)) self.server_connection_label.setFont(font) - self.server_connection_label.setAlignment(Qt.AlignCenter) + self.server_connection_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.server_connection_label.setMargin(5) self.verticalLayout_12.addWidget(self.server_connection_label) @@ -310,7 +310,7 @@ def setupUi(self, MainWindow): self.launch_monitor_rssi_label.setSizePolicy(sizePolicy3) self.launch_monitor_rssi_label.setMinimumSize(QSize(0, 0)) self.launch_monitor_rssi_label.setFont(font) - self.launch_monitor_rssi_label.setAlignment(Qt.AlignCenter) + self.launch_monitor_rssi_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.launch_monitor_rssi_label.setMargin(5) self.verticalLayout_12.addWidget(self.launch_monitor_rssi_label) @@ -321,7 +321,7 @@ def setupUi(self, MainWindow): self.launch_monitor_battery_label.setSizePolicy(sizePolicy3) self.launch_monitor_battery_label.setMinimumSize(QSize(0, 0)) self.launch_monitor_battery_label.setFont(font) - self.launch_monitor_battery_label.setAlignment(Qt.AlignCenter) + self.launch_monitor_battery_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.launch_monitor_battery_label.setMargin(5) self.verticalLayout_12.addWidget(self.launch_monitor_battery_label) @@ -332,7 +332,7 @@ def setupUi(self, MainWindow): self.launch_monitor_event_label.setSizePolicy(sizePolicy3) self.launch_monitor_event_label.setMinimumSize(QSize(0, 0)) self.launch_monitor_event_label.setFont(font) - self.launch_monitor_event_label.setAlignment(Qt.AlignCenter) + self.launch_monitor_event_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.launch_monitor_event_label.setMargin(5) self.verticalLayout_12.addWidget(self.launch_monitor_event_label) @@ -343,7 +343,7 @@ def setupUi(self, MainWindow): self.token_expiry_label.setSizePolicy(sizePolicy3) self.token_expiry_label.setMinimumSize(QSize(0, 0)) self.token_expiry_label.setFont(font) - self.token_expiry_label.setAlignment(Qt.AlignCenter) + self.token_expiry_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.token_expiry_label.setMargin(5) self.verticalLayout_12.addWidget(self.token_expiry_label) @@ -353,8 +353,8 @@ def setupUi(self, MainWindow): self.line = QFrame(self.launch_monitor_groupbox) self.line.setObjectName(u"line") - self.line.setFrameShape(QFrame.VLine) - self.line.setFrameShadow(QFrame.Sunken) + self.line.setFrameShape(QFrame.Shape.VLine) + self.line.setFrameShadow(QFrame.Shadow.Sunken) self.horizontalLayout_12.addWidget(self.line) @@ -362,52 +362,52 @@ def setupUi(self, MainWindow): self.edit_field_layout.setObjectName(u"edit_field_layout") self.horizontalLayout_7 = QHBoxLayout() self.horizontalLayout_7.setObjectName(u"horizontalLayout_7") - self.horizontalLayout_7.setSizeConstraint(QLayout.SetFixedSize) + self.horizontalLayout_7.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize) self.edit_field_layout.addLayout(self.horizontalLayout_7) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") - self.horizontalLayout_2.setSizeConstraint(QLayout.SetFixedSize) + self.horizontalLayout_2.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize) self.label_2 = QLabel(self.launch_monitor_groupbox) self.label_2.setObjectName(u"label_2") self.label_2.setFont(font1) - self.label_2.setAlignment(Qt.AlignCenter) + self.label_2.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_2.addWidget(self.label_2) self.label_3 = QLabel(self.launch_monitor_groupbox) self.label_3.setObjectName(u"label_3") self.label_3.setFont(font1) - self.label_3.setAlignment(Qt.AlignCenter) + self.label_3.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_2.addWidget(self.label_3) self.label = QLabel(self.launch_monitor_groupbox) self.label.setObjectName(u"label") self.label.setFont(font1) - self.label.setAlignment(Qt.AlignCenter) + self.label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_2.addWidget(self.label) self.label_4 = QLabel(self.launch_monitor_groupbox) self.label_4.setObjectName(u"label_4") self.label_4.setFont(font1) - self.label_4.setAlignment(Qt.AlignCenter) + self.label_4.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_2.addWidget(self.label_4) self.label_6 = QLabel(self.launch_monitor_groupbox) self.label_6.setObjectName(u"label_6") self.label_6.setFont(font1) - self.label_6.setAlignment(Qt.AlignCenter) + self.label_6.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_2.addWidget(self.label_6) self.label_9 = QLabel(self.launch_monitor_groupbox) self.label_9.setObjectName(u"label_9") self.label_9.setFont(font1) - self.label_9.setAlignment(Qt.AlignCenter) + self.label_9.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_2.addWidget(self.label_9) @@ -416,10 +416,10 @@ def setupUi(self, MainWindow): self.edit_field_layout1 = QHBoxLayout() self.edit_field_layout1.setObjectName(u"edit_field_layout1") - self.edit_field_layout1.setSizeConstraint(QLayout.SetFixedSize) + self.edit_field_layout1.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize) self.speed_edit = QTextEdit(self.launch_monitor_groupbox) self.speed_edit.setObjectName(u"speed_edit") - sizePolicy4 = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) + sizePolicy4 = QSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Maximum) sizePolicy4.setHorizontalStretch(0) sizePolicy4.setVerticalStretch(0) sizePolicy4.setHeightForWidth(self.speed_edit.sizePolicy().hasHeightForWidth()) @@ -481,46 +481,46 @@ def setupUi(self, MainWindow): self.horizontalLayout_5 = QHBoxLayout() self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") - self.horizontalLayout_5.setSizeConstraint(QLayout.SetFixedSize) + self.horizontalLayout_5.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize) self.label_7 = QLabel(self.launch_monitor_groupbox) self.label_7.setObjectName(u"label_7") self.label_7.setFont(font1) - self.label_7.setAlignment(Qt.AlignCenter) + self.label_7.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_5.addWidget(self.label_7) self.label_8 = QLabel(self.launch_monitor_groupbox) self.label_8.setObjectName(u"label_8") self.label_8.setFont(font1) - self.label_8.setAlignment(Qt.AlignCenter) + self.label_8.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_5.addWidget(self.label_8) self.label_5 = QLabel(self.launch_monitor_groupbox) self.label_5.setObjectName(u"label_5") self.label_5.setFont(font1) - self.label_5.setAlignment(Qt.AlignCenter) + self.label_5.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_5.addWidget(self.label_5) self.SideSpin = QLabel(self.launch_monitor_groupbox) self.SideSpin.setObjectName(u"SideSpin") self.SideSpin.setFont(font1) - self.SideSpin.setAlignment(Qt.AlignCenter) + self.SideSpin.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_5.addWidget(self.SideSpin) self.SideSpin_2 = QLabel(self.launch_monitor_groupbox) self.SideSpin_2.setObjectName(u"SideSpin_2") self.SideSpin_2.setFont(font1) - self.SideSpin_2.setAlignment(Qt.AlignCenter) + self.SideSpin_2.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_5.addWidget(self.SideSpin_2) self.SideSpin_3 = QLabel(self.launch_monitor_groupbox) self.SideSpin_3.setObjectName(u"SideSpin_3") self.SideSpin_3.setFont(font1) - self.SideSpin_3.setAlignment(Qt.AlignCenter) + self.SideSpin_3.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_5.addWidget(self.SideSpin_3) @@ -529,7 +529,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_6 = QHBoxLayout() self.horizontalLayout_6.setObjectName(u"horizontalLayout_6") - self.horizontalLayout_6.setSizeConstraint(QLayout.SetFixedSize) + self.horizontalLayout_6.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize) self.vla_edit = QTextEdit(self.launch_monitor_groupbox) self.vla_edit.setObjectName(u"vla_edit") sizePolicy4.setHeightForWidth(self.vla_edit.sizePolicy().hasHeightForWidth()) @@ -630,8 +630,8 @@ def setupUi(self, MainWindow): __qtablewidgetitem2 = QTableWidgetItem() self.log_table.setHorizontalHeaderItem(2, __qtablewidgetitem2) self.log_table.setObjectName(u"log_table") - self.log_table.setVerticalScrollMode(QAbstractItemView.ScrollPerItem) - self.log_table.setHorizontalScrollMode(QAbstractItemView.ScrollPerItem) + self.log_table.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerItem) + self.log_table.setHorizontalScrollMode(QAbstractItemView.ScrollMode.ScrollPerItem) self.log_table.setWordWrap(False) self.verticalLayout_9.addWidget(self.log_table) @@ -646,7 +646,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusbar) self.toolBar = QToolBar(MainWindow) self.toolBar.setObjectName(u"toolBar") - MainWindow.addToolBar(Qt.TopToolBarArea, self.toolBar) + MainWindow.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.toolBar) self.toolBar.addAction(self.actionExit) self.toolBar.addSeparator() @@ -691,7 +691,7 @@ def retranslateUi(self, MainWindow): #if QT_CONFIG(tooltip) self.connector_tab.setToolTip("") #endif // QT_CONFIG(tooltip) - self.groupBox.setTitle(QCoreApplication.translate("MainWindow", u"Simulator Connection", None)) + self.sim_group_box.setTitle(QCoreApplication.translate("MainWindow", u"Simulator Connection", None)) self.gspro_connect_button.setText(QCoreApplication.translate("MainWindow", u"Connect", None)) self.gspro_status_label.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) self.club_selection.setText("") diff --git a/src/ogs_connect.py b/src/connect_base.py similarity index 72% rename from src/ogs_connect.py rename to src/connect_base.py index e6f712b..960a05c 100644 --- a/src/ogs_connect.py +++ b/src/connect_base.py @@ -11,7 +11,7 @@ SimTCPConnectionClientClosedConnection, SimTCPConnectionSocketError -class OpenGolfSimConnect(QObject): +class ConnectBase(QObject): successful_send = 200 @@ -22,7 +22,7 @@ def __init__(self, device_id, units, api_version) -> None: self._api_version = api_version self._shot_number = 1 self._connected = False - super(OpenGolfSimConnect, self).__init__() + super(ConnectBase, self).__init__() def init_socket(self, ip_address: str, port: int) -> None: self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -43,38 +43,31 @@ def send_msg(self, payload, attempts=2): except socket.timeout: logging.info('Timed out. Retrying...') if attempt >= attempts-1: - raise SimTCPConnectionTimeout(f'Failed to send shot to GSPro after {attempts} attempts.') + raise SimTCPConnectionTimeout(f'Failed to send shot to simulator after {attempts} attempts.') Event().wait(0.5) continue except socket.error as e: - msg = f'OpenGolfSim socket error when trying to send shot, Exception: {format(e)}' + msg = f'Socket error when trying to send shot to simulator, Exception: {format(e)}' logging.debug(msg) raise SimTCPConnectionSocketError(msg) except Exception as e: - msg = f"OpenGolfSim unknown error when trying to send shot, Exception: {format(e)}" + msg = f"Unknown error when trying to send shot to simulator, Exception: {format(e)}" logging.debug(msg) raise SimTCPConnectionUnknownError(msg) else: if len(msg) == 0: - msg = f"OpenGolfSim closed the connection" + msg = f"Simulator closed the connection" logging.debug(msg) raise SimTCPConnectionClientClosedConnection(msg) else: - logging.debug(f"Response from OpenGolfSim: {msg}") + logging.debug(f"Response from simulator: {msg}") return msg def launch_ball(self, ball_data: BallData) -> None: - if self._connected: - device = { - "DeviceID": self._device_id, - "Units": self._units, - "ShotNumber": self._shot_number, - "APIversion": self._api_version - } - payload = device | ball_data.to_opengolfsim() - logging.debug(f'Launch Ball payload: {payload} ball_data.to_opengolfsim(): {ball_data.to_opengolfsim()}') - self.send_msg(json.dumps(payload).encode("utf-8")) - self._shot_number += 1 + # logging.debug(f"---- launch_ball -----") + print("---------base_launch_ball") + logging.debug(ball_data) + return def check_for_message(self): message = bytes(0) diff --git a/src/gspro_connect.py b/src/connect_gspro.py similarity index 96% rename from src/gspro_connect.py rename to src/connect_gspro.py index 64a37a5..ff25a8a 100644 --- a/src/gspro_connect.py +++ b/src/connect_gspro.py @@ -6,12 +6,13 @@ import select from PySide6.QtCore import QObject +from src.connect_base import ConnectBase from src.ball_data import BallData from src.custom_exception import SimTCPConnectionTimeout, SimTCPConnectionUnknownError, \ SimTCPConnectionClientClosedConnection, SimTCPConnectionSocketError -class GSProConnect(QObject): +class GSProConnect(ConnectBase): successful_send = 200 @@ -22,7 +23,7 @@ def __init__(self, device_id, units, api_version) -> None: self._api_version = api_version self._shot_number = 1 self._connected = False - super(GSProConnect, self).__init__() + super(ConnectBase, self).__init__() def init_socket(self, ip_address: str, port: int) -> None: self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/src/connect_ogs.py b/src/connect_ogs.py new file mode 100644 index 0000000..cd05cb3 --- /dev/null +++ b/src/connect_ogs.py @@ -0,0 +1,75 @@ +import socket +import logging +import json +from threading import Event + +import select +from PySide6.QtCore import QObject + +from src.connect_base import ConnectBase +from src.ball_data import BallData +from src.custom_exception import SimTCPConnectionTimeout, SimTCPConnectionUnknownError, \ + SimTCPConnectionClientClosedConnection, SimTCPConnectionSocketError + + +class OpenGolfSimConnect(ConnectBase): + + successful_send = 200 + + def __init__(self) -> None: + self._socket = None + self._shot_number = 1 + self._connected = False + super(ConnectBase, self).__init__() + + def send_msg(self, payload, attempts=2): + if self._connected: + for attempt in range(attempts): + try: + logging.info(f"Sending data: {payload}") + self._socket.sendall(payload) + msg = self._socket.recv(2048) + except socket.timeout: + logging.info('Timed out. Retrying...') + if attempt >= attempts-1: + raise SimTCPConnectionTimeout(f'Failed to send shot to OpenGolfSim after {attempts} attempts.') + Event().wait(0.5) + continue + except socket.error as e: + msg = f'Socket error when trying to send shot to OpenGolfSim, Exception: {format(e)}' + logging.debug(msg) + raise SimTCPConnectionSocketError(msg) + except Exception as e: + msg = f"Unknown error when trying to send shot to OpenGolfSim, Exception: {format(e)}" + logging.debug(msg) + raise SimTCPConnectionUnknownError(msg) + else: + if len(msg) == 0: + msg = f"OpenGolfSim closed the connection" + logging.debug(msg) + raise SimTCPConnectionClientClosedConnection(msg) + else: + logging.debug(f"Response from OpenGolfSim: {msg}") + return msg + + def launch_ball(self, ball_data: BallData) -> None: + if self._connected: + device = { + "shotId": self._shot_number, + "type": "shot" + } + payload = device | ball_data.to_opengolfsim() + logging.debug(f'Launch Ball payload: {payload} ball_data.to_opengolfsim(): {ball_data.to_opengolfsim()}') + self.send_msg(json.dumps(payload).encode("utf-8")) + self._shot_number += 1 + + def check_for_message(self): + message = bytes(0) + if self._connected: + read_socket, write_socket, error_socket = select.select([self._socket], [], [], 0) + while read_socket: + message = message + self._socket.recv(1024) + read_socket, write_socket, error_socket = select.select([self._socket], [], [], 0) + return message + + \ No newline at end of file diff --git a/src/device_base.py b/src/device_base.py index 2aa7cb9..1b3bc7d 100644 --- a/src/device_base.py +++ b/src/device_base.py @@ -13,7 +13,7 @@ def __init__(self, main_window): def resume(self): self.running = True - if self.device_worker is not None and self.running and self.main_window.gspro_connection.connected: + if self.device_worker is not None and self.running and self.main_window.sim_connection.connected: self.device_worker.resume() def pause(self): diff --git a/src/device_launch_monitor_bluetooth_base.py b/src/device_launch_monitor_bluetooth_base.py index 16ab1d4..8f76da3 100644 --- a/src/device_launch_monitor_bluetooth_base.py +++ b/src/device_launch_monitor_bluetooth_base.py @@ -32,7 +32,7 @@ def setup_device_thread(self) -> None: def __setup_signals(self) -> None: self.main_window.start_server_button.clicked.connect(self.server_start_stop) - self.main_window.gspro_connection.club_selected.connect(self.__club_selected) + self.main_window.sim_connection.club_selected.connect(self.__club_selected) # Scanner signals self._scanner.status_update.connect(self.__status_update) self._scanner.device_found.connect(self.device_found) @@ -87,7 +87,7 @@ def _setup_device_signals(self) -> None: self._device.error.connect(self.__device_error) self._device.connected.connect(self.__device_connected) self._device.update_battery.connect(self.__update_battery) - self._device.shot.connect(self.main_window.gspro_connection.send_shot_worker.run) + self._device.shot.connect(self.main_window.sim_connection.send_shot_worker.run) self._device.launch_monitor_event.connect(self.__launch_monitor_event) def __launch_monitor_event(self, event: str) -> None: @@ -96,7 +96,7 @@ def __launch_monitor_event(self, event: str) -> None: def __shot_sent(self, ball_data: BallData) -> None: print(f"Shot sent: {json.dumps(ball_data.to_json())}") - if self.main_window.gspro_connection.connected: + if self.main_window.sim_connection.connected: self.main_window.shot_sent(ball_data) def __update_battery(self, battery: int) -> None: diff --git a/src/device_launch_monitor_relay_server.py b/src/device_launch_monitor_relay_server.py index c56ca59..4c6cd42 100644 --- a/src/device_launch_monitor_relay_server.py +++ b/src/device_launch_monitor_relay_server.py @@ -32,32 +32,32 @@ def setup_device_thread(self): def __setup_signals(self): self.main_window.start_server_button.clicked.connect(self.__server_start_stop) - self.main_window.gspro_connection.club_selected.connect(self.__club_selected) - self.main_window.gspro_connection.disconnected_from_gspro.connect(self.pause) - self.main_window.gspro_connection.connected_to_gspro.connect(self.resume) - self.main_window.gspro_connection.gspro_message.connect(self.__gspro_message) + self.main_window.sim_connection.club_selected.connect(self.__club_selected) + self.main_window.sim_connection.disconnected_from_sim.connect(self.pause) + self.main_window.sim_connection.connected_to_sim.connect(self.resume) + self.main_window.sim_connection.sim_message.connect(self.__sim_message) def __shot_sent(self, shot_data): data = json.loads(shot_data.decode("utf-8")) balldata = BallData() balldata.from_gspro(data) - balldata.club = self.main_window.gspro_connection.current_club - print(f'balldata: {balldata.to_json()} club: {self.main_window.gspro_connection.current_club}') + balldata.club = self.main_window.sim_connection.current_club + print(f'balldata: {balldata.to_json()} club: {self.main_window.sim_connection.current_club}') balldata.good_shot = True if self.prev_shot is None or self.prev_shot.eq(balldata) > 0: self.main_window.shot_sent(balldata) self.prev_shot = balldata - def __gspro_message(self, message): + def __sim_message(self, message): self.device_worker.send_msg(message) def __server_start_stop(self): if self.device_worker is None: #QMessageBox.warning(self.main_window, "Starting ELM connector", 'Before starting the relay server ensure your launch monitor is turned on and ready for connection.') - self.device_worker = WorkerDeviceLaunchMonitorRelayServer(self.main_window.settings, self.main_window.gspro_connection.gspro_connect) + self.device_worker = WorkerDeviceLaunchMonitorRelayServer(self.main_window.settings, self.main_window.sim_connection.sim_connect) self.setup_device_thread() self.device_worker.start() - self.device_worker.club_selected(self.main_window.gspro_connection.current_club) + self.device_worker.club_selected(self.main_window.sim_connection.current_club) #self.__start_app() else: self.device_worker.stop() @@ -86,7 +86,7 @@ def device_worker_paused(self): button = 'Start' if self.is_running(): button = 'Stop' - if self.main_window.gspro_connection.connected: + if self.main_window.sim_connection.connected: color = 'orange' status = 'Paused' else: @@ -103,7 +103,7 @@ def device_worker_resumed(self): self.main_window.start_server_button.setText('Stop') msg = 'Running' color = 'green' - if not self.main_window.gspro_connection.connected: + if not self.main_window.sim_connection.connected: msg = 'Waiting GSPro' color = 'red' self.main_window.server_status_label.setText(msg) diff --git a/src/device_launch_monitor_relay_server_base.py b/src/device_launch_monitor_relay_server_base.py index a559a2e..58d509a 100644 --- a/src/device_launch_monitor_relay_server_base.py +++ b/src/device_launch_monitor_relay_server_base.py @@ -34,32 +34,33 @@ def setup_device_thread(self): def __setup_signals(self): self.main_window.start_server_button.clicked.connect(self.__server_start_stop) - self.main_window.gspro_connection.club_selected.connect(self.__club_selected) - self.main_window.gspro_connection.disconnected_from_gspro.connect(self.pause) - self.main_window.gspro_connection.connected_to_gspro.connect(self.resume) - self.main_window.gspro_connection.gspro_message.connect(self.__gspro_message) + self.main_window.sim_connection.club_selected.connect(self.__club_selected) + self.main_window.sim_connection.disconnected_from_sim.connect(self.pause) + self.main_window.sim_connection.connected_to_sim.connect(self.resume) + self.main_window.sim_connection.sim_message.connect(self.__post_sim_message) def __shot_sent(self, shot_data): data = json.loads(shot_data.decode("utf-8")) balldata = BallData() balldata.from_gspro(data) - balldata.club = self.main_window.gspro_connection.current_club - print(f'balldata: {balldata.to_json()} club: {self.main_window.gspro_connection.current_club}') + balldata.club = self.main_window.sim_connection.current_club + print(f'balldata: {balldata.to_json()} club: {self.main_window.sim_connection.current_club}') balldata.good_shot = True if self.prev_shot is None or self.prev_shot.eq(balldata) > 0: self.main_window.shot_sent(balldata) self.prev_shot = balldata - def __gspro_message(self, message): + def __post_sim_message(self, message): + print(f'__post_sim_message: {message}') self.device_worker.send_msg(message) def __server_start_stop(self): if self.device_worker is None: #QMessageBox.warning(self.main_window, "Starting LM connector", 'Before starting the relay server ensure your launch monitor is turned on and ready for connection.') - self.device_worker = WorkerDeviceLaunchMonitorRelayServer(self.main_window.settings, self.main_window.gspro_connection.gspro_connect) + self.device_worker = WorkerDeviceLaunchMonitorRelayServer(self.main_window.settings, self.main_window.sim_connection.sim_connect) self.setup_device_thread() self.device_worker.start() - self.device_worker.club_selected(self.main_window.gspro_connection.current_club) + self.device_worker.club_selected(self.main_window.sim_connection.current_club) self.__start_app() else: self.device_worker.stop() @@ -111,7 +112,7 @@ def device_worker_paused(self): button = 'Start' if self.is_running(): button = 'Stop' - if self.main_window.gspro_connection.connected: + if self.main_window.sim_connection.connected: color = 'orange' status = 'Paused' else: @@ -128,7 +129,7 @@ def device_worker_resumed(self): self.main_window.start_server_button.setText('Stop') msg = 'Running' color = 'green' - if not self.main_window.gspro_connection.connected: + if not self.main_window.sim_connection.connected: msg = 'Waiting GSPro' color = 'red' self.main_window.server_status_label.setText(msg) diff --git a/src/device_launch_monitor_screenshot.py b/src/device_launch_monitor_screenshot.py index 9b80e32..a96ae03 100644 --- a/src/device_launch_monitor_screenshot.py +++ b/src/device_launch_monitor_screenshot.py @@ -27,7 +27,7 @@ def __init__(self, main_window): def setup_device_thread(self): super().setup_device_thread() - self.device_worker.shot.connect(self.main_window.gspro_connection.send_shot_worker.run) + self.device_worker.shot.connect(self.main_window.sim_connection.send_shot_worker.run) self.device_worker.bad_shot.connect(self.__bad_shot) self.device_worker.too_many_ghost_shots.connect(self.__too_many_ghost_shots) @@ -38,9 +38,9 @@ def __setup_signals(self): self.select_device.selected.connect(self.__device_selected) self.select_device.cancel.connect(self.__device_select_cancelled) self.main_window.select_device_button.clicked.connect(self.__select_device) - self.main_window.gspro_connection.club_selected.connect(self.__club_selected) - self.main_window.gspro_connection.disconnected_from_gspro.connect(self.pause) - self.main_window.gspro_connection.connected_to_gspro.connect(self.resume) + self.main_window.sim_connection.club_selected.connect(self.__club_selected) + self.main_window.sim_connection.disconnected_from_sim.connect(self.pause) + self.main_window.sim_connection.connected_to_sim.connect(self.resume) self.main_window.putting_settings_form.cancel.connect(self.resume) self.main_window.actionPuttingSettings.triggered.connect(self.pause) self.main_window.actionDevices.triggered.connect(self.__devices) @@ -67,7 +67,7 @@ def device_worker_paused(self): color = 'red' restart = False if self.is_running(): - if self.main_window.gspro_connection.connected: + if self.main_window.sim_connection.connected: color = 'orange' status = 'Paused' if self.device_worker.selected_club() != "PT": @@ -126,7 +126,7 @@ def device_worker_resumed(self): color = 'green' restart = False pause = True - if not self.main_window.gspro_connection.connected: + if not self.main_window.sim_connection.connected: msg = 'Waiting GSPro' color = 'red' pause = False @@ -137,7 +137,7 @@ def device_worker_resumed(self): self.main_window.pause_button.setEnabled(pause) def __device_select_cancelled(self): - if not self.current_device is None and self.main_window.gspro_connection.connected: + if not self.current_device is None and self.main_window.sim_connection.connected: self.device_worker.change_device(self.current_device) self.resume() @@ -150,7 +150,7 @@ def __device_selected(self, device): self.resume() else: self.start() - self.device_worker.club_selected(self.main_window.gspro_connection.current_club) + self.device_worker.club_selected(self.main_window.sim_connection.current_club) def __update_selected_mirror_app(self): diff --git a/src/device_putting_base.py b/src/device_putting_base.py index 182e32b..9febca1 100644 --- a/src/device_putting_base.py +++ b/src/device_putting_base.py @@ -20,12 +20,12 @@ def start_app(self): return def setup_signals(self): - self.main_window.gspro_connection.club_selected.connect(self.club_selected) + self.main_window.sim_connection.club_selected.connect(self.club_selected) self.main_window.putting_settings_form.cancel.connect(self.resume) self.main_window.actionPuttingSettings.triggered.connect(self.pause) - self.main_window.gspro_connection.disconnected_from_gspro.connect(self.pause) - self.main_window.gspro_connection.connected_to_gspro.connect(self.resume) - self.device_worker.shot.connect(self.main_window.gspro_connection.send_shot_worker.run) + self.main_window.sim_connection.disconnected_from_sim.connect(self.pause) + self.main_window.sim_connection.connected_to_sim.connect(self.resume) + self.device_worker.shot.connect(self.main_window.sim_connection.send_shot_worker.run) def club_selected(self, club_data): if self.device_worker is not None: @@ -39,7 +39,7 @@ def device_worker_paused(self): enabled = True if self.is_running(): msg = 'Stop' - if self.main_window.gspro_connection.connected: + if self.main_window.sim_connection.connected: color = 'orange' status = 'Paused' else: @@ -56,7 +56,7 @@ def device_worker_resumed(self): self.main_window.putting_server_button.setText('Stop') msg = 'Running' color = 'green' - if not self.main_window.gspro_connection.connected: + if not self.main_window.sim_connection.connected: msg = 'Waiting GSPro' color = 'red' self.main_window.putting_server_status_label.setText(msg) diff --git a/src/ogs_connection.py b/src/ogs_connection.py deleted file mode 100644 index 02e3ac7..0000000 --- a/src/ogs_connection.py +++ /dev/null @@ -1,203 +0,0 @@ -import logging -import os - -from PySide6.QtCore import QThread, Signal, QObject -from PySide6.QtWidgets import QMessageBox -from src.ctype_screenshot import ScreenMirrorWindow -from src.ogs_connect import OpenGolfSimConnect -from src.worker_ogs_messages import WorkerOpenGolfSimMessages -# from src.worker_gspro_start import WorkerGSProStart -from src.worker_ogs import WorkerOpenGolfSim -from src.log_message import LogMessageSystems, LogMessageTypes -from src.worker_thread import WorkerThread -from PySide6.QtCore import QProcess - -class OpenGolfSimConnection(QObject): - connected_to_ogs = Signal() - disconnected_from_ogs = Signal() - club_selected = Signal(object) - ogs_message = Signal(object) - - def __init__(self, main_window): - super(OpenGolfSimConnection, self).__init__() - self.main_window = main_window - self.current_club = None - self.worker = None - self.thread = None - self.ogs_messages_thread = None - self.ogs_messages_worker = None - self.send_shot_thread = None - self.send_shot_worker = None - self.ogs_start_worker = None - self.ogs_start_thread = None - self.connected = False - self.settings = main_window.settings - self.ogs_connect = OpenGolfSimConnect( - self.settings.device_id, - self.settings.units, - self.settings.api_version - ) - self.__ogs_disconnected() - self.__setup_send_shot_thread() - self.__setup_ogs_messages_thread() - - - def __ogs_disconnected(self): - self.main_window.gspro_connect_button.setEnabled(True) - self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, 'Disconnected from OpenGolfSim') - self.main_window.gspro_connect_button.setText('Connect') - self.main_window.gspro_status_label.setText('Not Connected') - self.main_window.gspro_status_label.setStyleSheet(f"QLabel {{ background-color : red; color : white; }}") - - def __setup_send_shot_thread(self): - self.send_shot_thread = QThread() - self.send_shot_worker = WorkerOpenGolfSim(self.ogs_connect) - self.send_shot_worker.moveToThread(self.send_shot_thread) - self.send_shot_worker.started.connect(self.__sending_shot) - self.send_shot_worker.sent.connect(self.main_window.shot_sent) - self.send_shot_worker.error.connect(self.__send_shot_error) - self.send_shot_thread.started.connect(self.send_shot_worker.run) - self.send_shot_thread.start() - - def __setup_ogs_messages_thread(self): - self.ogs_messages_thread = QThread() - self.ogs_messages_worker = WorkerOpenGolfSimMessages(self.ogs_connect) - self.ogs_messages_worker.moveToThread(self.ogs_messages_thread) - self.ogs_messages_worker.club_selected.connect(self.__club_selected) - self.ogs_messages_worker.error.connect(self.__ogs_messages_error) - self.ogs_messages_worker.ogs_message.connect(self.__ogs_message) - self.ogs_messages_thread.started.connect(self.ogs_messages_worker.run) - self.ogs_messages_thread.start() - - def __ogs_message(self, message): - self.ogs_message.emit(message) - - def __setup_connection_thread(self): - self.thread = QThread() - self.worker = WorkerThread(self.ogs_connect.init_socket, self.settings.ogs_ip_address, self.settings.ogs_port) - self.worker.moveToThread(self.thread) - self.worker.started.connect(self.__in_progress) - self.worker.result.connect(self.__connected) - self.worker.error.connect(self.__error) - # self.worker.finished.connect(self.__finished) - self.thread.started.connect(self.worker.run()) - self.thread.start() - - def __club_selecion_error(self, error): - self.disconnect_from_ogs() - msg = f"Error while trying to check for club selection messages from GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." - self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') - QMessageBox.warning(self.main_window, "GSPro Receive Error", msg) - - def __club_selected(self, club_data): - logging.debug(f"{self.__class__.__name__} Club selected: {club_data['Player']['Club']}") - if club_data['Player']['Club'] == "PT": - self.main_window.club_selection.setText('Putter') - self.main_window.club_selection.setStyleSheet(f"QLabel {{ background-color : green; color : white; }}") - else: - self.main_window.club_selection.setText(club_data['Player']['Club']) - self.main_window.club_selection.setStyleSheet(f"QLabel {{ background-color : orange; color : white; }}") - self.club_selected.emit(club_data) - if self.current_club != club_data['Player']['Club']: - self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.CONNECTOR, f'Club selected: {club_data["Player"]["Club"]}') - self.current_club = club_data['Player']['Club'] - - def __send_shot_error(self, error): - self.disconnect_from_ogs() - msg = f"Error while trying to send shot to GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." - self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') - QMessageBox.warning(self.main_window, "GSPro Send Error", msg) - - def __ogs_messages_error(self, error): - self.disconnect_from_ogs() - msg = f"Error while trying to check for new messages from GSPro.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." - self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') - QMessageBox.warning(self.main_window, "GSPro Message Receive Error", msg) - - def connect_to_ogs(self): - if not self.connected: - # if self.__find_gspro_api_app(): - if self.thread is None: - self.__setup_connection_thread() - else: - if not self.ogs_connect.connected(): - self.worker.run() - if self.ogs_messages_thread is None: - self.__setup_ogs_messages_thread() - self.ogs_messages_worker.start() - if self.send_shot_thread is None: - self.__setup_send_shot_thread() - self.send_shot_worker.start() - # self.__shutdown_ogs_start_thread() - - def disconnect_from_ogs(self): - if self.connected: - self.connected = False - self.__ogs_disconnected() - self.send_shot_worker.stop() - self.ogs_messages_worker.stop() - self.ogs_connect.terminate_session() - self.disconnected_from_ogs.emit() - - def __sending_shot(self): - self.__log_message(LogMessageTypes.ALL, 'Sending shot to GSPro') - - def __in_progress(self): - msg = 'Connecting...' - self.__log_message(LogMessageTypes.ALL, f'Connecting to GSPro...') - self.__log_message(LogMessageTypes.LOGS, f'Connection settings: {self.settings.to_json(True)}') - self.main_window.gspro_status_label.setText(msg) - self.main_window.gspro_status_label.setStyleSheet("QLabel { background-color : orange; color : white; }") - self.main_window.gspro_connect_button.setEnabled(False) - - def __connected(self): - self.connected = True - self.main_window.gspro_connect_button.setEnabled(True) - self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, f'Connected to OpenGolfSim') - self.main_window.gspro_connect_button.setText('Disconnect') - self.main_window.gspro_status_label.setText('Connected') - self.main_window.gspro_status_label.setStyleSheet(f"QLabel {{ background-color : green; color : white; }}") - self.connected_to_ogs.emit() - - def __error(self, error): - self.disconnect_from_ogs() - msg = "Error while trying to connect to OpenGolfSim.\nMake sure OpenGolfSim API Connect is running.\nStart/restart API Connect from OpenGolfSim.\nPress 'Connect' to reconnect to OpenGolfSim." - self.__log_message(LogMessageTypes.LOGS, f'{msg} Exception: {format(error)}') - QMessageBox.warning(self.main_window, "OpenGolfSim Connect Error", msg) - - def shutdown(self): - self.ogs_connect.terminate_session() - self.connected = False - self.__shutdown_threads() - - def __log_message(self, types, message): - self.main_window.log_message(types, LogMessageSystems.OPENGOLFSIM, message) - - def __shutdown_threads(self): - if self.ogs_messages_thread is not None: - self.ogs_messages_worker.shutdown() - self.ogs_messages_thread.quit() - self.ogs_messages_thread.wait() - self.ogs_messages_thread = None - self.ogs_messages_worker = None - if self.send_shot_thread is not None: - self.send_shot_thread.quit() - self.send_shot_thread.wait() - self.send_shot_thread = None - self.send_shot_worker = None - if self.thread is not None: - self.thread.quit() - self.thread.wait() - self.thread = None - self.worker = None - - def __shutdown_ogs_start_thread(self): - logging.debug(f'{self.__class__.__name__} Shutting down threads, ogs_start_thread') - if self.ogs_start_thread is not None: - self.ogs_start_worker.shutdown() - if self.ogs_start_thread.isRunning(): - logging.debug(f'{self.__class__.__name__} Quitting ogs_start_thread') - self.ogs_start_thread.quit() - self.ogs_start_thread.wait() - self.ogs_start_thread = None - self.ogs_start_worker = None diff --git a/src/gspro_connection.py b/src/sim_connection.py similarity index 67% rename from src/gspro_connection.py rename to src/sim_connection.py index d73ce0f..c8370ee 100644 --- a/src/gspro_connection.py +++ b/src/sim_connection.py @@ -4,55 +4,69 @@ from PySide6.QtCore import QThread, Signal, QObject from PySide6.QtWidgets import QMessageBox from src.ctype_screenshot import ScreenMirrorWindow -from src.gspro_connect import GSProConnect -from src.worker_gspro_messages import WorkerGSProMessages +from src.settings import Simulator +from src.connect_base import ConnectBase +from src.connect_gspro import GSProConnect +from src.connect_ogs import OpenGolfSimConnect from src.worker_gspro_start import WorkerGSProStart -from src.worker_gspro import WorkerGspro +from src.worker_sim_messages import WorkerSimMessages +from src.worker_sim import WorkerSim from src.log_message import LogMessageSystems, LogMessageTypes from src.worker_thread import WorkerThread from PySide6.QtCore import QProcess -class GSProConnection(QObject): +class SimConnection(QObject): + + # simulator_api = Simulator.GSPRO + disconnected_from_sim = Signal() + connected_to_sim = Signal() - connected_to_gspro = Signal() - disconnected_from_gspro = Signal() club_selected = Signal(object) - gspro_message = Signal(object) + sim_message = Signal(object) + # ogs_message = Signal(object) - def __init__(self, main_window): - super(GSProConnection, self).__init__() + def __init__(self, main_window, simulator_api: Simulator): + super(SimConnection, self).__init__() self.main_window = main_window + # self.simulator_api == Simulator.GSPRO + self.simulator_api = simulator_api self.current_club = None self.worker = None self.thread = None - self.gspro_messages_thread = None - self.gspro_messages_worker = None + self.sim_messages_thread = None + self.sim_messages_worker = None self.send_shot_thread = None self.send_shot_worker = None self.gspro_start_worker = None self.gspro_start_thread = None self.connected = False self.settings = main_window.settings - self.gspro_connect = GSProConnect( - self.settings.device_id, - self.settings.units, - self.settings.api_version - ) - self.__gspro_disconnected() + + + if self.simulator_api == Simulator.OPENGOLFSIM: + self.sim_connect = OpenGolfSimConnect() + else: + self.sim_connect = GSProConnect( + self.settings.device_id, + self.settings.units, + self.settings.api_version + ) + + self.__sim_disconnected() self.__setup_send_shot_thread() - self.__setup_gspro_messages_thread() + self.__setup_sim_messages_thread() - def __gspro_disconnected(self): + def __sim_disconnected(self): self.main_window.gspro_connect_button.setEnabled(True) - self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, 'Disconnected from GSPro') + self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, f'Disconnected from {self.simulator_api}') self.main_window.gspro_connect_button.setText('Connect') self.main_window.gspro_status_label.setText('Not Connected') self.main_window.gspro_status_label.setStyleSheet(f"QLabel {{ background-color : red; color : white; }}") def __setup_send_shot_thread(self): self.send_shot_thread = QThread() - self.send_shot_worker = WorkerGspro(self.gspro_connect) + self.send_shot_worker = WorkerSim(self.sim_connect) self.send_shot_worker.moveToThread(self.send_shot_thread) self.send_shot_worker.started.connect(self.__sending_shot) self.send_shot_worker.sent.connect(self.main_window.shot_sent) @@ -60,23 +74,26 @@ def __setup_send_shot_thread(self): self.send_shot_thread.started.connect(self.send_shot_worker.run) self.send_shot_thread.start() - def __setup_gspro_messages_thread(self): - self.gspro_messages_thread = QThread() - self.gspro_messages_worker = WorkerGSProMessages(self.gspro_connect) - self.gspro_messages_worker.moveToThread(self.gspro_messages_thread) - self.gspro_messages_worker.club_selected.connect(self.__club_selected) - self.gspro_messages_worker.error.connect(self.__gspro_messages_error) - self.gspro_messages_worker.gspro_message.connect(self.__gspro_message) - self.gspro_messages_thread.started.connect(self.gspro_messages_worker.run) - self.gspro_messages_thread.start() + def __setup_sim_messages_thread(self): + self.sim_messages_thread = QThread() + self.sim_messages_worker = WorkerSimMessages(self.sim_connect) + self.sim_messages_worker.moveToThread(self.sim_messages_thread) + self.sim_messages_worker.club_selected.connect(self.__club_selected) + self.sim_messages_worker.error.connect(self.__sim_messages_error) + self.sim_messages_worker.sim_message.connect(self.__sim_message) + self.sim_messages_thread.started.connect(self.sim_messages_worker.run) + self.sim_messages_thread.start() - def __gspro_message(self, message): - self.gspro_message.emit(message) + def __sim_message(self, message): + self.sim_message.emit(message) def __setup_connection_thread(self): self.thread = QThread() - self.worker = WorkerThread( - self.gspro_connect.init_socket, self.settings.ip_address, self.settings.port) + if self.simulator_api == Simulator.OPENGOLFSIM: + self.worker = WorkerThread(self.sim_connect.init_socket, self.settings.ogs_ip_address, self.settings.ogs_port) + else: + self.worker = WorkerThread(self.sim_connect.init_socket, self.settings.ip_address, self.settings.port) + self.worker.moveToThread(self.thread) self.worker.started.connect(self.__in_progress) self.worker.result.connect(self.__connected) @@ -86,10 +103,10 @@ def __setup_connection_thread(self): self.thread.start() def __club_selecion_error(self, error): - self.disconnect_from_gspro() + self.disconnect_sim() msg = f"Error while trying to check for club selection messages from GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') - QMessageBox.warning(self.main_window, "GSPro Receive Error", msg) + QMessageBox.warning(self.main_window, f"{self.simulator_api} Receive Error", msg) def __club_selected(self, club_data): logging.debug(f"{self.__class__.__name__} Club selected: {club_data['Player']['Club']}") @@ -105,48 +122,48 @@ def __club_selected(self, club_data): self.current_club = club_data['Player']['Club'] def __send_shot_error(self, error): - self.disconnect_from_gspro() - msg = f"Error while trying to send shot to GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." + self.disconnect_sim() + msg = f"Error while trying to send shot to {self.simulator_api}" self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') - QMessageBox.warning(self.main_window, "GSPro Send Error", msg) + QMessageBox.warning(self.main_window, f"{self.simulator_api} Send Error", msg) - def __gspro_messages_error(self, error): - self.disconnect_from_gspro() + def __sim_messages_error(self, error): + self.disconnect_sim() msg = f"Error while trying to check for new messages from GSPro.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." self.__log_message(LogMessageTypes.LOGS, f'{msg}\nException: {format(error)}') - QMessageBox.warning(self.main_window, "GSPro Message Receive Error", msg) + QMessageBox.warning(self.main_window, f"{self.simulator_api} Message Receive Error", msg) - def connect_to_gspro(self): + def connect_sim(self): if not self.connected: if self.__find_gspro_api_app(): if self.thread is None: self.__setup_connection_thread() else: - if not self.gspro_connect.connected(): + if not self.sim_connect.connected(): self.worker.run() - if self.gspro_messages_thread is None: - self.__setup_gspro_messages_thread() - self.gspro_messages_worker.start() + if self.sim_messages_thread is None: + self.__setup_sim_messages_thread() + self.sim_messages_worker.start() if self.send_shot_thread is None: self.__setup_send_shot_thread() self.send_shot_worker.start() self.__shutdown_gspro_start_thread() - def disconnect_from_gspro(self): + def disconnect_sim(self): if self.connected: self.connected = False - self.__gspro_disconnected() + self.__sim_disconnected() self.send_shot_worker.stop() - self.gspro_messages_worker.stop() - self.gspro_connect.terminate_session() - self.disconnected_from_gspro.emit() + self.sim_messages_worker.stop() + self.sim_connect.terminate_session() + self.disconnected_from_sim.emit() def __sending_shot(self): - self.__log_message(LogMessageTypes.ALL, 'Sending shot to GSPro') + self.__log_message(LogMessageTypes.ALL, 'Sending shot to {self.simulator_api}') def __in_progress(self): msg = 'Connecting...' - self.__log_message(LogMessageTypes.ALL, f'Connecting to GSPro...') + self.__log_message(LogMessageTypes.ALL, f'Connecting to {self.simulator_api}...') self.__log_message(LogMessageTypes.LOGS, f'Connection settings: {self.settings.to_json(True)}') self.main_window.gspro_status_label.setText(msg) self.main_window.gspro_status_label.setStyleSheet("QLabel { background-color : orange; color : white; }") @@ -155,37 +172,46 @@ def __in_progress(self): def __connected(self): self.connected = True self.main_window.gspro_connect_button.setEnabled(True) - self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, f'Connected to GSPro') + self.main_window.log_message(LogMessageTypes.ALL, LogMessageSystems.GSPRO_CONNECT, f'Connected to {self.simulator_api}') self.main_window.gspro_connect_button.setText('Disconnect') self.main_window.gspro_status_label.setText('Connected') self.main_window.gspro_status_label.setStyleSheet(f"QLabel {{ background-color : green; color : white; }}") - self.connected_to_gspro.emit() + self.connected_to_sim.emit() def __error(self, error): - self.disconnect_from_gspro() - msg = "Error while trying to connect to GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." + self.disconnect_sim() + if self.simulator_api == Simulator.OPENGOLFSIM: + msg = f"Error while trying to connect to {self.simulator_api}" + else: + msg = "Error while trying to connect to GSPro.\nMake sure GSPro API Connect is running.\nStart/restart API Connect from GSPro.\nPress 'Connect' to reconnect to GSPro." self.__log_message(LogMessageTypes.LOGS, f'{msg} Exception: {format(error)}') - QMessageBox.warning(self.main_window, "GSPro Connect Error", msg) + QMessageBox.warning(self.main_window, f"{self.simulator_api} Connect Error", msg) def shutdown(self): - self.gspro_connect.terminate_session() + self.sim_connect.terminate_session() self.connected = False self.__shutdown_threads() def __log_message(self, types, message): self.main_window.log_message(types, LogMessageSystems.GSPRO_CONNECT, message) + def __find_gspro_api_app(self): + # assume opengolfsim is already running + if self.simulator_api == Simulator.OPENGOLFSIM: + running = True + return running + try: if self.settings.local_gspro(): ScreenMirrorWindow.find_window(self.settings.gspro_api_window_name) running = True except Exception: - self.main_window.gspro_connection.disconnect_from_gspro() + self.disconnect_sim() msg = f"GSPro API window '{self.main_window.settings.gspro_api_window_name}' does not seem to be running.\nStart GSPro or reset the API connector.\nPress 'Connect' to reconnect to GSPro." self.main_window.log_message(LogMessageTypes.LOGS, - LogMessageSystems.GSPRO_CONNECT, - msg) + LogMessageSystems.GSPRO_CONNECT, + msg) QMessageBox.warning(self.main_window, "GSPRO API Window Not Found", msg) running = False return running @@ -224,12 +250,12 @@ def __gspro_start_error(self, error): QMessageBox.warning(self.main_window, "GSPro Start Error", msg) def __shutdown_threads(self): - if self.gspro_messages_thread is not None: - self.gspro_messages_worker.shutdown() - self.gspro_messages_thread.quit() - self.gspro_messages_thread.wait() - self.gspro_messages_thread = None - self.gspro_messages_worker = None + if self.sim_messages_thread is not None: + self.sim_messages_worker.shutdown() + self.sim_messages_thread.quit() + self.sim_messages_thread.wait() + self.sim_messages_thread = None + self.sim_messages_worker = None if self.send_shot_thread is not None: self.send_shot_thread.quit() self.send_shot_thread.wait() diff --git a/src/worker_device_launch_monitor_relay_server.py b/src/worker_device_launch_monitor_relay_server.py index 71a9ec3..6f58af6 100644 --- a/src/worker_device_launch_monitor_relay_server.py +++ b/src/worker_device_launch_monitor_relay_server.py @@ -5,7 +5,7 @@ from PySide6.QtCore import Signal -from src.gspro_connect import GSProConnect +from src.connect_base import ConnectBase from src.settings import Settings from src.worker_base import WorkerBase @@ -19,10 +19,10 @@ class WorkerDeviceLaunchMonitorRelayServer(WorkerBase): shot_error = Signal(tuple) disconnected = Signal() - def __init__(self, settings: Settings, gspro_connection: GSProConnect): + def __init__(self, settings: Settings, sim_connect: ConnectBase): WorkerBase.__init__(self) self.settings = settings - self.gspro_connection = gspro_connection + self.sim_connect = sim_connect self.name = 'WorkerDeviceLaunchMonitorRelayServer' self.connection = None self._shutdown = Event() @@ -56,9 +56,9 @@ def run(self) -> None: data = self.connection.recv(1024) if data is not None and len(data) > 0: logging.debug(f'{self.name}: connector received data: {data.decode()}') - if self.gspro_connection.connected(): + if self.sim_connect.connected(): try: - msg = self.gspro_connection.send_msg(data) + msg = self.sim_connect.send_msg(data) self.send_msg(msg) self.relay_server_shot.emit(data) logging.debug(f'{self.name}: connector sent data to GSPro result: {msg.decode()}') diff --git a/src/worker_ogs.py b/src/worker_ogs.py deleted file mode 100644 index 87f926c..0000000 --- a/src/worker_ogs.py +++ /dev/null @@ -1,27 +0,0 @@ -import traceback -from PySide6.QtCore import Signal - -from src.ogs_connect import OpenGolfSimConnect -from src.worker_base import WorkerBase - - -class WorkerOpenGolfSim(WorkerBase): - sent = Signal(object or None) - - def __init__(self, ogs_connection: OpenGolfSimConnect): - super().__init__() - self.ogs_connection = ogs_connection - - def run(self, balldata=None): - if balldata is not None: - try: - self.started.emit() - self.ogs_connection.launch_ball(balldata) - except Exception as e: - traceback.print_exc() - self.error.emit((e, traceback.format_exc())) - else: - self.sent.emit(balldata) # Return the result of the processing - finally: - self.finished.emit() # Done - \ No newline at end of file diff --git a/src/worker_ogs_messages.py b/src/worker_ogs_messages.py deleted file mode 100644 index 46f5fc4..0000000 --- a/src/worker_ogs_messages.py +++ /dev/null @@ -1,56 +0,0 @@ -import json -import logging -import re -import traceback -from threading import Event -from PySide6.QtCore import Signal -from src.ogs_connect import OpenGolfSimConnect -from src.worker_base import WorkerBase -from src.worker_screenshot_device_base import WorkerScreenshotBase - - -class WorkerOpenGolfSimMessages(WorkerBase): - player_info = 201 - club_selected = Signal(object) - ogs_message = Signal(object) - - def __init__(self, ogs_connection: OpenGolfSimConnect): - super().__init__() - self.ogs_connection = ogs_connection - self.name = 'WorkerOpenGolfSimMessages' - - def run(self): - self.started.emit() - logging.debug(f'{self.name} Started') - # Execute if not shutdown - while not self._shutdown.is_set(): - Event().wait(250/1000) - # When _pause is clear we wait(suspended) if set we process - self._pause.wait() - if not self._shutdown.is_set() and self.ogs_connection is not None and self.ogs_connection.connected(): - try: - message = self.ogs_connection.check_for_message() - if len(message) > 0: - logging.debug(f'{self.name}: Received data: {message}') - self.ogs_message.emit(message) - self.__process_message(message) - except Exception as e: - if not isinstance(e, ValueError): - self.pause() - traceback.print_exc() - logging.debug(f'Error in process {self.name}: {format(e)}, {traceback.format_exc()}') - self.error.emit((e, traceback.format_exc())) - self.finished.emit() - - def __process_message(self, message): - messages = {} - json_messages = re.split(r'(\{.*?})(?= *\{)', message.decode("utf-8")) - for json_message in json_messages: - if len(json_message) > 0: - logging.debug(f'__process_message json_message: {json_message}') - msg = json.loads(json_message) - messages[str(msg['Code'])] = msg - # # Check if club selection message - # if msg['Code'] == WorkerGSProMessages.player_info: - # self.club_selected.emit(msg) - return messages diff --git a/src/worker_gspro.py b/src/worker_sim.py similarity index 71% rename from src/worker_gspro.py rename to src/worker_sim.py index 079d247..c07bbe6 100644 --- a/src/worker_gspro.py +++ b/src/worker_sim.py @@ -1,22 +1,22 @@ import traceback from PySide6.QtCore import Signal -from src.gspro_connect import GSProConnect from src.worker_base import WorkerBase -class WorkerGspro(WorkerBase): +class WorkerSim(WorkerBase): sent = Signal(object or None) - def __init__(self, gspro_connection: GSProConnect): + def __init__(self, sim_connect): super().__init__() - self.gspro_connection = gspro_connection + self.sim_connect = sim_connect def run(self, balldata=None): if balldata is not None: try: + print(f'WorkerSim: {balldata.to_json()}') self.started.emit() - self.gspro_connection.launch_ball(balldata) + self.sim_connect.launch_ball(balldata) except Exception as e: traceback.print_exc() self.error.emit((e, traceback.format_exc())) diff --git a/src/worker_gspro_messages.py b/src/worker_sim_messages.py similarity index 71% rename from src/worker_gspro_messages.py rename to src/worker_sim_messages.py index 0dbdc3a..1d13b64 100644 --- a/src/worker_gspro_messages.py +++ b/src/worker_sim_messages.py @@ -4,20 +4,19 @@ import traceback from threading import Event from PySide6.QtCore import Signal -from src.gspro_connect import GSProConnect from src.worker_base import WorkerBase from src.worker_screenshot_device_base import WorkerScreenshotBase -class WorkerGSProMessages(WorkerBase): +class WorkerSimMessages(WorkerBase): player_info = 201 club_selected = Signal(object) - gspro_message = Signal(object) + sim_message = Signal(object) - def __init__(self, gspro_connection: GSProConnect): + def __init__(self, sim_connect): super().__init__() - self.gspro_connection = gspro_connection - self.name = 'WorkerGSProMessages' + self.sim_connect = sim_connect + self.name = 'WorkerSimMessages' def run(self): self.started.emit() @@ -27,12 +26,12 @@ def run(self): Event().wait(250/1000) # When _pause is clear we wait(suspended) if set we process self._pause.wait() - if not self._shutdown.is_set() and self.gspro_connection is not None and self.gspro_connection.connected(): + if not self._shutdown.is_set() and self.sim_connect is not None and self.sim_connect.connected(): try: - message = self.gspro_connection.check_for_message() + message = self.sim_connect.check_for_message() if len(message) > 0: - logging.debug(f'{self.name}: GSPro received data: {message}') - self.gspro_message.emit(message) + logging.debug(f'{self.name}: Received data: {message}') + self.sim_message.emit(message) self.__process_message(message) except Exception as e: if not isinstance(e, ValueError): @@ -51,6 +50,6 @@ def __process_message(self, message): msg = json.loads(json_message) messages[str(msg['Code'])] = msg # Check if club selection message - if msg['Code'] == WorkerGSProMessages.player_info: + if msg['Code'] == WorkerSimMessages.player_info: self.club_selected.emit(msg) return messages