Skip to content

Commit

Permalink
Better payload viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
Darkness4 committed Feb 20, 2021
1 parent 96815b0 commit 43e4b14
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 159 deletions.
32 changes: 9 additions & 23 deletions csgo_gsi_arduino_lcd/data/csgo_request_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
import socketserver
from functools import partial
from http.server import BaseHTTPRequestHandler
from typing import Any, Dict, Tuple
from typing import Any, Dict, Optional, Tuple

from csgo_gsi_arduino_lcd.data.arduino_mediator import ArduinoMediator
from csgo_gsi_arduino_lcd.debug.payload_viewer_thread import (
PayloadViewerThread,
)
from csgo_gsi_arduino_lcd.data.data_store import DataStore
from csgo_gsi_arduino_lcd.entities.state import State
from csgo_gsi_arduino_lcd.entities.status import Status

Expand All @@ -17,25 +15,17 @@ class CsgoRequestHandler(BaseHTTPRequestHandler):
"""CSGO's requests handler."""

is_waiting: bool = False
payload_viewer: PayloadViewerThread
arduino: ArduinoMediator
data_store: DataStore
last_data: Optional[Dict[str, Any]] = None

@classmethod
def create(
cls,
arduino_mediator: ArduinoMediator,
payload_viewer: PayloadViewerThread,
):
return partial(
cls,
arduino_mediator,
payload_viewer,
)
def create(cls, arduino_mediator: ArduinoMediator, data_store: DataStore):
return partial(cls, arduino_mediator, data_store)

def __init__(
self,
arduino_mediator: ArduinoMediator,
payload_viewer: PayloadViewerThread,
request: bytes,
client_address: Tuple[str, int],
server: socketserver.BaseServer,
Expand All @@ -44,14 +34,15 @@ def __init__(
request, client_address, server
)
self.arduino = arduino_mediator
self.payload_viewer = payload_viewer

def do_POST(self):
"""Receive CSGO's informations."""
length = int(self.headers["Content-Length"])
body = self.rfile.read(length).decode("utf-8")

self.parse_payload(json.loads(body))
data = json.loads(body)
self.parse_payload(data)
self.data_store.data = data

self.send_header("Content-type", "text/html")
self.send_response(200)
Expand Down Expand Up @@ -92,10 +83,5 @@ def parse_payload(
elif not self.is_waiting:
self.is_waiting = True
self.arduino.status = Status.NONE

# Show payload
if payload != self.payload_viewer.payload:
self.payload_viewer.payload = payload
self.payload_viewer.refresh()
except (KeyError, TypeError):
logging.exception("Parsing incorrect")
9 changes: 9 additions & 0 deletions csgo_gsi_arduino_lcd/data/data_store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from dataclasses import dataclass
from typing import Any, Dict, Optional


@dataclass
class DataStore:
"""Pass data to the ui."""

data: Optional[Dict[str, Any]] = None
14 changes: 5 additions & 9 deletions csgo_gsi_arduino_lcd/data/server_thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,24 @@

import logging
from http.server import HTTPServer
from threading import Thread

from csgo_gsi_arduino_lcd.data.arduino_mediator import ArduinoMediator
from csgo_gsi_arduino_lcd.data.csgo_request_handler import CsgoRequestHandler
from csgo_gsi_arduino_lcd.debug.payload_viewer_thread import (
PayloadViewerThread,
)
from qtpy.QtCore import QThread
from csgo_gsi_arduino_lcd.data.data_store import DataStore
from serial import Serial


class ServerThread(QThread):
class ServerThread(Thread):
"""Server thread."""

payload_viewer = PayloadViewerThread()
arduino_mediator: ArduinoMediator
data_store = DataStore()
server: HTTPServer
ser_arduino: Serial

def __init__(self, com_str: str):
"""Start thread and save the COM port."""
QThread.__init__(self)
self.com_str = com_str
self.ser_arduino = Serial(self.com_str, 9600)
logging.info("Arduino detected")
Expand All @@ -38,8 +35,7 @@ def __init__(self, com_str: str):
logging.info("Arduino Mediator started")

handler = CsgoRequestHandler.create(
self.arduino_mediator,
self.payload_viewer,
self.arduino_mediator, self.data_store
)
self.server = HTTPServer(("localhost", 3000), handler)

Expand Down
Empty file.
67 changes: 0 additions & 67 deletions csgo_gsi_arduino_lcd/debug/payload_viewer_thread.py

This file was deleted.

91 changes: 31 additions & 60 deletions csgo_gsi_arduino_lcd/ui/csgo_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,11 @@
from typing import Optional

from csgo_gsi_arduino_lcd.data.server_thread import ServerThread
from csgo_gsi_arduino_lcd.ui.payload_dialog import PayloadDialog
from qtpy.QtCore import QSize, Qt, Slot
from qtpy.QtGui import QIcon, QCloseEvent
from qtpy.QtWidgets import (
QComboBox,
QHBoxLayout,
QPushButton,
QVBoxLayout,
QWidget,
)
from qtpy.QtGui import QCloseEvent, QIcon
from qtpy.QtWidgets import (QComboBox, QHBoxLayout, QPushButton, QVBoxLayout,
QWidget)
from serial.tools import list_ports


Expand All @@ -35,10 +31,24 @@ class CsgoWindow(QWidget):
refresh_btn: QPushButton
payload_viewer_btn: QPushButton
comcb: QComboBox
payload_dialog: PayloadDialog

def __init__(self):
"""Init UI."""
super(CsgoWindow, self).__init__()
# Icon
app_icon = QIcon()
for i in (16, 20, 24, 32, 48, 64, 128, 256, 512):
app_icon.addFile(
resource_path(f"assets/csgo-{i}.ico"),
QSize(i, i),
)

# Window
self.setWindowIcon(app_icon)
self.setWindowTitle("CSGO GSI on LCD")
self.setWindowFlags(Qt.WindowCloseButtonHint)

# Check ports
list_ports_device = sorted(
map(lambda x: str(x.name), list_ports.comports())
Expand All @@ -58,8 +68,10 @@ def __init__(self):
self.refresh_btn.resize(self.refresh_btn.sizeHint())
self.refresh_btn.clicked.connect(self.refresh)

# Payload Viewer
self.payload_viewer_btn = QPushButton("View payload")
self.payload_viewer_btn.setDisabled(True)
self.payload_viewer_btn.clicked.connect(self.show_last_data)
self.payload_dialog = PayloadDialog(app_icon)

# Container
vbox = QVBoxLayout()
Expand All @@ -72,22 +84,17 @@ def __init__(self):
vbox.addWidget(self.connect_btn)
self.setLayout(vbox)

# Icon
app_icon = QIcon()
for i in (16, 20, 24, 32, 48, 64, 128, 256, 512):
app_icon.addFile(
resource_path(f"assets/csgo-{i}.ico"),
QSize(i, i),
)

# Window
self.setWindowIcon(app_icon)
self.setWindowTitle("CSGO GSI on LCD")
self.setWindowFlags(Qt.WindowCloseButtonHint)

self.show()
self.setFixedSize(self.size())

@Slot()
def show_last_data(self):
data = None
if self.server_thread is not None:
data = self.server_thread.data_store.data
self.payload_dialog.update_text(data)
self.payload_dialog.show()

@Slot()
def refresh(self):
"""Refresh COM ports."""
Expand All @@ -102,7 +109,7 @@ def refresh(self):
self.connect_btn.setDisabled(False)

@Slot()
def connect(self):
def start_server(self):
"""Connect to the server."""
# Disable buttons
self.comcb.setDisabled(True)
Expand All @@ -120,65 +127,29 @@ def connect(self):
self.connect_btn.setDisabled(False)
self.connect_btn.setText("Stop")

# Enable payload_viewer
self.payload_viewer_btn.clicked.connect(self.resume_payload_viewer)
self.payload_viewer_btn.setDisabled(False)

@Slot()
def stop_server(self):
"""Stop the server."""
# Disable buttons
self.payload_viewer_btn.setDisabled(True)

# Kill the messenger and server
if self.server_thread is not None:
self.server_thread.arduino_mediator.shutdown()
self.server_thread.payload_viewer.shutdown()
self.server_thread.server.shutdown()
self.server_thread = None

# Change button function
self.connect_btn.clicked.disconnect()
self.connect_btn.clicked.connect(self.connect)
self.connect_btn.clicked.connect(self.start_server)
self.connect_btn.setText("Connect")
self.payload_viewer_btn.clicked.disconnect()
self.payload_viewer_btn.clicked.connect(self.resume_payload_viewer)
self.payload_viewer_btn.setText("View payload")

# Enable buttons
self.comcb.setDisabled(False)
self.connect_btn.setDisabled(False)
self.refresh_btn.setDisabled(False)

@Slot()
def resume_payload_viewer(self):
"""Start Payload Viewer."""
# Start payload vierwer
if self.server_thread is not None:
self.server_thread.payload_viewer.resume()

# Change button function
self.payload_viewer_btn.clicked.disconnect()
self.payload_viewer_btn.clicked.connect(self.pause_payload_viewer)
self.payload_viewer_btn.setText("Hide payload")

@Slot()
def pause_payload_viewer(self):
"""Stop Payload Viewer."""
# Stop payload viewer
if self.server_thread is not None:
self.server_thread.payload_viewer.pause()

# Change button function
self.payload_viewer_btn.clicked.disconnect()
self.payload_viewer_btn.clicked.connect(self.resume_payload_viewer)
self.payload_viewer_btn.setText("View payload")

def close_all(self, event: QCloseEvent):
"""Close everything before closing app."""
super(CsgoWindow, self).closeEvent(event)
if self.server_thread is not None:
self.server_thread.arduino_mediator.shutdown()
self.server_thread.payload_viewer.shutdown()
self.server_thread.server.shutdown()
self.server_thread = None
39 changes: 39 additions & 0 deletions csgo_gsi_arduino_lcd/ui/payload_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import json
from typing import Any, Dict, Optional

from qtpy.QtCore import Qt
from qtpy.QtGui import QIcon
from qtpy.QtWidgets import QDialog, QFormLayout, QLabel, QScrollArea


class PayloadDialog(QDialog):
label: QLabel

def __init__(self, app_icon: QIcon):
super().__init__(
None, Qt.WindowSystemMenuHint | Qt.WindowCloseButtonHint
)
self.setWindowIcon(app_icon)
self.setWindowTitle("Last Payload")

self.label = QLabel("")
self.label.setTextInteractionFlags(Qt.TextSelectableByMouse)

scrollArea = QScrollArea()
scrollArea.setWidgetResizable(True)

scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scrollArea.setWidget(self.label)
scrollArea.setWidgetResizable(True)

layout = QFormLayout()
layout.addWidget(scrollArea)
self.setLayout(layout)

def update_text(self, data: Optional[Dict[str, Any]]):
self.label.setText(
json.dumps(data, indent=2, sort_keys=True)
if data is not None
else ""
)

0 comments on commit 43e4b14

Please sign in to comment.