터치 패널 PC 버튼 확장 복원
This commit is contained in:
1 parent
637739386e
commit
64ded5e566
2 files changed
+117
-6
No files matched your search
+114
-5
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import time
|
||||
import socket
|
||||
import os
|
||||
import shutil
|
||||
from collections import deque
|
||||
@@ -28,6 +29,8 @@ NET_GROUPS = {
|
||||
"wifi5": ["wlan1"],
|
||||
}
|
||||
|
||||
PC_IP = "192.168.50.73"
|
||||
PC_MAC = "74:56:3C:CD:CD:79"
|
||||
RPI_SERVICE_UNITS = [
|
||||
("rpi_docker", "docker.service"),
|
||||
("rpi_nginx", "nginx.service"),
|
||||
@@ -340,6 +343,21 @@ def disk_io():
|
||||
return reads, writes, not found
|
||||
|
||||
|
||||
def send_magic_packet(mac):
|
||||
clean = mac.replace(":", "").replace("-", "")
|
||||
if len(clean) != 12:
|
||||
return False
|
||||
packet = bytes.fromhex("ff" * 6 + clean * 16)
|
||||
try:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
for target in ["192.168.50.255", "255.255.255.255"]:
|
||||
sock.sendto(packet, (target, 9))
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
class StatusDot(QWidget):
|
||||
def __init__(self, active_color):
|
||||
super().__init__()
|
||||
@@ -462,6 +480,72 @@ class StatusTile(QFrame):
|
||||
self.error_dot.set_steady(error_on)
|
||||
|
||||
|
||||
class PcWakeButton(StatusTile):
|
||||
def __init__(self):
|
||||
super().__init__("PC")
|
||||
self.online = False
|
||||
self.last_wake_at = 0.0
|
||||
self.wait_until = 0.0
|
||||
self.error_until = 0.0
|
||||
self.wait_phase = False
|
||||
self.blink_timer = QTimer(self)
|
||||
self.blink_timer.timeout.connect(self.tick_waiting)
|
||||
self.blink_timer.start(250)
|
||||
|
||||
def set_online(self, online):
|
||||
self.online = online
|
||||
self.read_dot.set_steady(online)
|
||||
now = time.monotonic()
|
||||
self.error_dot.set_steady(now < self.error_until)
|
||||
if online:
|
||||
self.wait_until = 0.0
|
||||
self.wait_phase = False
|
||||
self.write_dot.set_steady(False)
|
||||
self.detail.setText("켜짐")
|
||||
elif now < self.wait_until:
|
||||
remaining = int(self.wait_until - now)
|
||||
self.detail.setText(f"대기 {remaining}s")
|
||||
else:
|
||||
self.write_dot.set_steady(False)
|
||||
self.detail.setText("꺼짐")
|
||||
|
||||
def tick_waiting(self):
|
||||
now = time.monotonic()
|
||||
if not self.online and now < self.wait_until:
|
||||
self.wait_phase = not self.wait_phase
|
||||
self.write_dot.set_steady(self.wait_phase)
|
||||
if not self.online and self.wait_until > 0 and now >= self.wait_until:
|
||||
self.wait_until = 0.0
|
||||
self.wait_phase = False
|
||||
self.write_dot.set_steady(False)
|
||||
self.error_until = now + 60
|
||||
self.error_dot.set_steady(True)
|
||||
self.detail.setText("실패")
|
||||
if self.error_until > 0 and now >= self.error_until:
|
||||
self.error_until = 0.0
|
||||
self.error_dot.set_steady(False)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
now = time.monotonic()
|
||||
if not self.online and now >= self.wait_until:
|
||||
self.last_wake_at = now
|
||||
self.wait_until = now + 60
|
||||
self.wait_phase = True
|
||||
self.write_dot.set_steady(True)
|
||||
self.error_until = 0.0
|
||||
self.error_dot.set_steady(False)
|
||||
self.detail.setText("깨우는 중")
|
||||
if not send_magic_packet(PC_MAC):
|
||||
self.wait_until = 0.0
|
||||
self.error_until = now + 5
|
||||
self.error_dot.set_steady(True)
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def tick(self):
|
||||
self.error_dot.tick()
|
||||
|
||||
|
||||
class Sparkline(QFrame):
|
||||
def __init__(self, title, color="#38bdf8", second_color=None, y_unit="", right_unit="", auto_byte_unit=False, max_points=120):
|
||||
super().__init__()
|
||||
@@ -610,6 +694,12 @@ class TouchPanel(QMainWindow):
|
||||
self.fan_timer.timeout.connect(self.update_fan_status)
|
||||
self.fan_timer.start(FAN_INTERVAL_MS)
|
||||
|
||||
self.pc_ping = QProcess(self)
|
||||
self.pc_ping.finished.connect(self.pc_ping_finished)
|
||||
self.pc_timer = QTimer(self)
|
||||
self.pc_timer.timeout.connect(self.ping_pc)
|
||||
self.pc_timer.start(1000)
|
||||
|
||||
self.disk_temp_timer = QTimer(self)
|
||||
self.disk_temp_timer.timeout.connect(self.update_disk_temp)
|
||||
self.disk_temp_timer.start(DISK_TEMP_INTERVAL_MS)
|
||||
@@ -653,6 +743,7 @@ class TouchPanel(QMainWindow):
|
||||
self.pulse_timer.start(25)
|
||||
self.sample()
|
||||
self.update_fan_status()
|
||||
self.ping_pc()
|
||||
self.update_disk_temp()
|
||||
self.update_rpi_services()
|
||||
self.update_synology_status()
|
||||
@@ -663,9 +754,13 @@ class TouchPanel(QMainWindow):
|
||||
|
||||
def _build_ui(self):
|
||||
root = QWidget()
|
||||
layout = QHBoxLayout(root)
|
||||
layout = QVBoxLayout(root)
|
||||
layout.setContentsMargins(4, 8, 10, 8)
|
||||
layout.setSpacing(8)
|
||||
layout.setSpacing(6)
|
||||
|
||||
panel_layout = QHBoxLayout()
|
||||
panel_layout.setContentsMargins(0, 0, 0, 0)
|
||||
panel_layout.setSpacing(8)
|
||||
|
||||
rpi_rows = [
|
||||
(("io", "SSD I/O"), ("rpi_temp", "TEMP"), ("rpi_fan", "FAN")),
|
||||
@@ -684,7 +779,7 @@ class TouchPanel(QMainWindow):
|
||||
(("synology_sata1", "SATA1 I/O"), ("synology_sata2", "SATA2 I/O"), ("synology_sata4", "SATA4 I/O")),
|
||||
]
|
||||
|
||||
left = self.build_status_panel("RASPBERRY", rpi_rows, fixed_width=398, bottom_blank=True)
|
||||
left = self.build_status_panel("RASPBERRY", rpi_rows, fixed_width=398)
|
||||
right = self.build_status_panel("SYNOLOGY", synology_rows)
|
||||
|
||||
header = QHBoxLayout()
|
||||
@@ -697,8 +792,13 @@ class TouchPanel(QMainWindow):
|
||||
header.addWidget(self.clock)
|
||||
right.layout().insertLayout(1, header)
|
||||
|
||||
layout.addWidget(left)
|
||||
layout.addWidget(right, 1)
|
||||
panel_layout.addWidget(left)
|
||||
panel_layout.addWidget(right, 1)
|
||||
layout.addLayout(panel_layout, 1)
|
||||
|
||||
self.pc_button = PcWakeButton()
|
||||
self.pc_button.setFixedHeight(48)
|
||||
layout.addWidget(self.pc_button)
|
||||
self.setCentralWidget(root)
|
||||
|
||||
def build_status_panel(self, title_text, rows, fixed_width=None, bottom_blank=False):
|
||||
@@ -836,6 +936,15 @@ class TouchPanel(QMainWindow):
|
||||
detail = "OK" if active else state.upper()[:6]
|
||||
self.rows[key].set_state(detail, read_steady=active, write_steady=False, error_steady=not active)
|
||||
|
||||
def ping_pc(self):
|
||||
if self.pc_ping.state() != QProcess.NotRunning:
|
||||
return
|
||||
self.pc_ping.start("/usr/bin/ping", ["-c", "1", "-W", "1", PC_IP])
|
||||
|
||||
def pc_ping_finished(self, exit_code, exit_status):
|
||||
del exit_status
|
||||
self.pc_button.set_online(exit_code == 0)
|
||||
|
||||
def ping_synology(self):
|
||||
if self.synology_ping_proc.state() != QProcess.NotRunning:
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user