XscarfX

System Monitor 1.0

Dec 16th, 2024
23
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.25 KB | None | 0 0
  1. import socketio
  2. import statistics
  3. import asyncio
  4. import sys
  5. import json
  6. import time
  7. import serial
  8.  
  9. class ZalMonitor:
  10. def __init__(self, host='192.168.1.45', port=4920):
  11. """Initialize the Zal monitor with host and port."""
  12. self.sio = socketio.AsyncClient(logger=False)
  13. self.host = host
  14. self.port = port
  15. self.current_pid = None
  16. self.running = True
  17. self.current_usage = None
  18. self.current_fps = None
  19. self.last_print_time = 0
  20. self.last_metrics = {
  21. 'cpu_temp': None,
  22. 'gpu_temp': None,
  23. 'gpu': None,
  24. 'fps': None,
  25. 'ram': None
  26. }
  27.  
  28. # Initialize serial connection
  29. try:
  30. self.serial = serial.Serial('COM4', 115200)
  31. print(f"Connected to serial port COM4")
  32. except Exception as e:
  33. print(f"Failed to connect to serial port: {e}")
  34. self.serial = None
  35.  
  36. @self.sio.on('connect')
  37. async def on_connect():
  38. print("Successfully connected to Zal server!")
  39. await self.sio.emit('get_gpu_processes')
  40. # Request hardware info
  41. await self.sio.emit('get_hardware_info')
  42.  
  43. @self.sio.on('connect_error')
  44. def on_connect_error(data):
  45. print(f"Connection failed! Error: {data}")
  46.  
  47. @self.sio.on('disconnect')
  48. def on_disconnect():
  49. print("Disconnected from Zal server!")
  50.  
  51. @self.sio.on('hardware_info')
  52. def on_hardware_info(data):
  53. """Handle hardware information from Zal."""
  54. try:
  55. if isinstance(data, str):
  56. data = json.loads(data)
  57.  
  58. if data:
  59. # Update hardware metrics
  60. self.last_metrics['cpu_temp'] = data.get('cpu_temperature', 0)
  61. self.last_metrics['gpu_temp'] = data.get('gpu_temperature', 0)
  62. self.last_metrics['ram'] = data.get('ram_usage', 0)
  63. self._update_display()
  64. except Exception as e:
  65. print(f"\nError processing hardware data: {e}")
  66.  
  67. @self.sio.on('gpu_processes')
  68. async def on_gpu_processes(data):
  69. """Handle incoming GPU processes data."""
  70. try:
  71. # Handle string data
  72. if isinstance(data, str):
  73. try:
  74. data = json.loads(data)
  75. except json.JSONDecodeError:
  76. return
  77.  
  78. if not data:
  79. return
  80.  
  81. # Extract game info from the data
  82. if isinstance(data, list) and len(data) > 0:
  83. process_data = data[0]
  84. else:
  85. process_data = data
  86.  
  87. if isinstance(process_data, dict):
  88. game_name = list(process_data.keys())[0]
  89. game_info = process_data[game_name]
  90.  
  91. pid = game_info['pid']
  92. usage = game_info['usage']
  93.  
  94. # Start FPS monitoring if we haven't already
  95. if self.current_pid != pid:
  96. self.current_pid = pid
  97. print(f"\nStarting FPS monitoring for {game_name} (PID: {pid})")
  98. await self.sio.emit('start_fps', pid)
  99.  
  100. # Update GPU usage
  101. self.last_metrics['gpu'] = usage
  102. self._update_display()
  103.  
  104. except Exception as e:
  105. print(f"\nError processing GPU data: {e}")
  106.  
  107. @self.sio.on('fps_data')
  108. def on_fps_data(data):
  109. """Handle incoming FPS data."""
  110. try:
  111. if isinstance(data, str):
  112. data = json.loads(data)
  113.  
  114. if isinstance(data, list) and len(data) > 0:
  115. avg_fps = statistics.mean(data)
  116. self.last_metrics['fps'] = avg_fps
  117. self._update_display()
  118. except Exception as e:
  119. print(f"\nError processing FPS data: {e}")
  120.  
  121. def _update_display(self):
  122. """Update both console and TFT display."""
  123. current_time = time.time()
  124. # Only update display every 0.5 seconds to reduce flicker
  125. if current_time - self.last_print_time >= 0.5:
  126. # Update console display
  127. display = "\r"
  128. metrics_available = False
  129.  
  130. if self.last_metrics['cpu_temp'] is not None:
  131. display += f"CPU: {self.last_metrics['cpu_temp']:5.1f}°C | "
  132. metrics_available = True
  133. if self.last_metrics['gpu_temp'] is not None:
  134. display += f"GPU: {self.last_metrics['gpu_temp']:5.1f}°C | "
  135. metrics_available = True
  136. if self.last_metrics['ram'] is not None:
  137. display += f"RAM: {self.last_metrics['ram']:5.1f}GB | "
  138. metrics_available = True
  139. if self.last_metrics['gpu'] is not None:
  140. display += f"GPU Load: {self.last_metrics['gpu']:5.1f}%"
  141. metrics_available = True
  142. if self.last_metrics['fps'] is not None:
  143. if metrics_available:
  144. display += " | "
  145. display += f"FPS: {self.last_metrics['fps']:5.1f}"
  146.  
  147. print(display, end="", flush=True)
  148.  
  149. # Send data to TFT display if available
  150. if self.serial:
  151. # Format: cpu_temp,gpu_temp,ram_usage,gpu_usage,fps,
  152. data_string = (
  153. f"{self.last_metrics['cpu_temp'] if self.last_metrics['cpu_temp'] is not None else 0.0:.1f},"
  154. f"{self.last_metrics['gpu_temp'] if self.last_metrics['gpu_temp'] is not None else 0.0:.1f},"
  155. f"{self.last_metrics['ram'] if self.last_metrics['ram'] is not None else 0.0:.1f},"
  156. f"{self.last_metrics['gpu'] if self.last_metrics['gpu'] is not None else 0.0:.1f},"
  157. f"{self.last_metrics['fps'] if self.last_metrics['fps'] is not None else 0.0:.1f},\n"
  158. )
  159. try:
  160. self.serial.write(data_string.encode())
  161. except Exception as e:
  162. print(f"\nError writing to serial: {e}")
  163.  
  164. self.last_print_time = current_time
  165.  
  166. async def start_monitoring(self):
  167. """Start monitoring FPS data."""
  168. try:
  169. url = f'http://{self.host}:{self.port}'
  170. print(f"Attempting to connect to Zal at {url}")
  171. await self.sio.connect(url, transports=['websocket'])
  172.  
  173. print("Connected and monitoring...")
  174. print("\033[?25l", end="") # Hide cursor
  175. while self.running:
  176. await self.sio.emit('get_gpu_processes')
  177. await self.sio.emit('get_hardware_info') # Regularly request hardware info
  178. await asyncio.sleep(1)
  179.  
  180. except Exception as e:
  181. print(f"Error: {e}")
  182. finally:
  183. print("\033[?25h", end="") # Show cursor
  184. if self.sio.connected:
  185. await self.sio.disconnect()
  186. if self.serial:
  187. self.serial.close()
  188.  
  189. def main():
  190. """Main function to run the monitor."""
  191. if sys.platform == 'win32':
  192. asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
  193.  
  194. loop = asyncio.new_event_loop()
  195. asyncio.set_event_loop(loop)
  196.  
  197. monitor = ZalMonitor()
  198.  
  199. try:
  200. loop.run_until_complete(monitor.start_monitoring())
  201. except KeyboardInterrupt:
  202. print("\nShutting down...")
  203. finally:
  204. try:
  205. pending = asyncio.all_tasks(loop)
  206. for task in pending:
  207. task.cancel()
  208. loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
  209. finally:
  210. loop.close()
  211.  
  212. if __name__ == "__main__":
  213. main()
Advertisement
Add Comment
Please, Sign In to add comment