Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import socketio
- import statistics
- import asyncio
- import sys
- import json
- import time
- import serial
- class ZalMonitor:
- def __init__(self, host='192.168.1.45', port=4920):
- """Initialize the Zal monitor with host and port."""
- self.sio = socketio.AsyncClient(logger=False)
- self.host = host
- self.port = port
- self.current_pid = None
- self.running = True
- self.current_usage = None
- self.current_fps = None
- self.last_print_time = 0
- self.last_metrics = {
- 'cpu_temp': None,
- 'gpu_temp': None,
- 'gpu': None,
- 'fps': None,
- 'ram': None
- }
- # Initialize serial connection
- try:
- self.serial = serial.Serial('COM4', 115200)
- print(f"Connected to serial port COM4")
- except Exception as e:
- print(f"Failed to connect to serial port: {e}")
- self.serial = None
- @self.sio.on('connect')
- async def on_connect():
- print("Successfully connected to Zal server!")
- await self.sio.emit('get_gpu_processes')
- # Request hardware info
- await self.sio.emit('get_hardware_info')
- @self.sio.on('connect_error')
- def on_connect_error(data):
- print(f"Connection failed! Error: {data}")
- @self.sio.on('disconnect')
- def on_disconnect():
- print("Disconnected from Zal server!")
- @self.sio.on('hardware_info')
- def on_hardware_info(data):
- """Handle hardware information from Zal."""
- try:
- if isinstance(data, str):
- data = json.loads(data)
- if data:
- # Update hardware metrics
- self.last_metrics['cpu_temp'] = data.get('cpu_temperature', 0)
- self.last_metrics['gpu_temp'] = data.get('gpu_temperature', 0)
- self.last_metrics['ram'] = data.get('ram_usage', 0)
- self._update_display()
- except Exception as e:
- print(f"\nError processing hardware data: {e}")
- @self.sio.on('gpu_processes')
- async def on_gpu_processes(data):
- """Handle incoming GPU processes data."""
- try:
- # Handle string data
- if isinstance(data, str):
- try:
- data = json.loads(data)
- except json.JSONDecodeError:
- return
- if not data:
- return
- # Extract game info from the data
- if isinstance(data, list) and len(data) > 0:
- process_data = data[0]
- else:
- process_data = data
- if isinstance(process_data, dict):
- game_name = list(process_data.keys())[0]
- game_info = process_data[game_name]
- pid = game_info['pid']
- usage = game_info['usage']
- # Start FPS monitoring if we haven't already
- if self.current_pid != pid:
- self.current_pid = pid
- print(f"\nStarting FPS monitoring for {game_name} (PID: {pid})")
- await self.sio.emit('start_fps', pid)
- # Update GPU usage
- self.last_metrics['gpu'] = usage
- self._update_display()
- except Exception as e:
- print(f"\nError processing GPU data: {e}")
- @self.sio.on('fps_data')
- def on_fps_data(data):
- """Handle incoming FPS data."""
- try:
- if isinstance(data, str):
- data = json.loads(data)
- if isinstance(data, list) and len(data) > 0:
- avg_fps = statistics.mean(data)
- self.last_metrics['fps'] = avg_fps
- self._update_display()
- except Exception as e:
- print(f"\nError processing FPS data: {e}")
- def _update_display(self):
- """Update both console and TFT display."""
- current_time = time.time()
- # Only update display every 0.5 seconds to reduce flicker
- if current_time - self.last_print_time >= 0.5:
- # Update console display
- display = "\r"
- metrics_available = False
- if self.last_metrics['cpu_temp'] is not None:
- display += f"CPU: {self.last_metrics['cpu_temp']:5.1f}°C | "
- metrics_available = True
- if self.last_metrics['gpu_temp'] is not None:
- display += f"GPU: {self.last_metrics['gpu_temp']:5.1f}°C | "
- metrics_available = True
- if self.last_metrics['ram'] is not None:
- display += f"RAM: {self.last_metrics['ram']:5.1f}GB | "
- metrics_available = True
- if self.last_metrics['gpu'] is not None:
- display += f"GPU Load: {self.last_metrics['gpu']:5.1f}%"
- metrics_available = True
- if self.last_metrics['fps'] is not None:
- if metrics_available:
- display += " | "
- display += f"FPS: {self.last_metrics['fps']:5.1f}"
- print(display, end="", flush=True)
- # Send data to TFT display if available
- if self.serial:
- # Format: cpu_temp,gpu_temp,ram_usage,gpu_usage,fps,
- data_string = (
- f"{self.last_metrics['cpu_temp'] if self.last_metrics['cpu_temp'] is not None else 0.0:.1f},"
- f"{self.last_metrics['gpu_temp'] if self.last_metrics['gpu_temp'] is not None else 0.0:.1f},"
- f"{self.last_metrics['ram'] if self.last_metrics['ram'] is not None else 0.0:.1f},"
- f"{self.last_metrics['gpu'] if self.last_metrics['gpu'] is not None else 0.0:.1f},"
- f"{self.last_metrics['fps'] if self.last_metrics['fps'] is not None else 0.0:.1f},\n"
- )
- try:
- self.serial.write(data_string.encode())
- except Exception as e:
- print(f"\nError writing to serial: {e}")
- self.last_print_time = current_time
- async def start_monitoring(self):
- """Start monitoring FPS data."""
- try:
- url = f'http://{self.host}:{self.port}'
- print(f"Attempting to connect to Zal at {url}")
- await self.sio.connect(url, transports=['websocket'])
- print("Connected and monitoring...")
- print("\033[?25l", end="") # Hide cursor
- while self.running:
- await self.sio.emit('get_gpu_processes')
- await self.sio.emit('get_hardware_info') # Regularly request hardware info
- await asyncio.sleep(1)
- except Exception as e:
- print(f"Error: {e}")
- finally:
- print("\033[?25h", end="") # Show cursor
- if self.sio.connected:
- await self.sio.disconnect()
- if self.serial:
- self.serial.close()
- def main():
- """Main function to run the monitor."""
- if sys.platform == 'win32':
- asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
- monitor = ZalMonitor()
- try:
- loop.run_until_complete(monitor.start_monitoring())
- except KeyboardInterrupt:
- print("\nShutting down...")
- finally:
- try:
- pending = asyncio.all_tasks(loop)
- for task in pending:
- task.cancel()
- loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
- finally:
- loop.close()
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment