#!/usr/bin/env python3 # -*- coding: utf-8 -*- import socket import threading import json from client_info import ClientInfo import os class Server: def __init__(self, host, port, config_file): self.host = host self.port = port self.clients = [] self.load_config(config_file) self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_socket.bind((self.host, self.port)) self.server_socket.listen(5) print(f"Server started on {self.host}:{self.port}") def load_config(self, config_file): with open(config_file, 'r') as f: self.config = json.load(f) self.valid_clients = self.config.get("valid_clients", []) def validate_client(self, client_socket): try: data = client_socket.recv(1024).decode('utf-8') client_info = json.loads(data) for valid_client in self.valid_clients: if (client_info["device_id"] == valid_client["device_id"] and client_info["mac_address"] == valid_client["mac_address"]): return client_info except Exception as e: print(f"Validation error: {e}") return None def connect_audio_streams(self, client_info): try: audio_output_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) audio_output_socket.connect((client_info.ip_address, client_info.audio_output_port)) client_info.audio_output_socket = audio_output_socket audio_input_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) audio_input_socket.connect((client_info.ip_address, client_info.audio_input_port)) client_info.audio_input_socket = audio_input_socket except Exception as e: print(f"Error connecting audio streams: {e}") def send_audio_stream(self, client_socket, file_path): try: with open(file_path, 'rb') as audio_file: while True: data = audio_file.read(1024) if not data: break client_socket.sendall(data) except Exception as e: print(f"Error sending audio stream: {e}") def handle_client(self, client_socket): client_info = self.validate_client(client_socket) if client_info: ip_address = client_socket.getpeername()[0] client = ClientInfo( client_info["device_id"], client_info["mac_address"], client_info["room_name"], ip_address=ip_address, audio_output_port=client_info["audio_output_port"], audio_input_port=client_info["audio_input_port"], command_socket=client_socket ) self.clients.append(client) print(f"Client connected: {client}") client_socket.send("Validation successful".encode('utf-8')) # Connect audio streams self.connect_audio_streams(client) # Handle update requests self.handle_update_requests(client_socket) # Send the audio stream to the client's audio output socket self.send_audio_stream(client.audio_output_socket, "audio/SpeechOn.wav") try: while True: data = client_socket.recv(1024) if not data: break # Handle further communication with the client here except Exception as e: print(f"Error while communicating with client: {e}") finally: print(f"Client disconnected: {client}") self.clients.remove(client) client_socket.close() else: client_socket.send("Validation failed".encode('utf-8')) client_socket.close() def handle_update_requests(self, client_socket): try: while True: request = client_socket.recv(1024).decode('utf-8') if request == "GET_MODEL_INFO": model_info = { "name": self.config["hotword"], "size": os.path.getsize("model/hotword/"+self.config["hotword"]+".keras") } client_socket.send(json.dumps(model_info).encode('utf-8')) elif request == "SEND_MODEL": with open("model/hotword/"+self.config["hotword"]+".keras", 'rb') as model_file: while True: data = model_file.read(1024) if not data: break client_socket.sendall(data) client_socket.send(b"____~EOF____~") break except Exception as e: print(f"Error handling update requests: {e}") def start(self): while True: client_socket, addr = self.server_socket.accept() print(f"Connection from {addr}") client_thread = threading.Thread(target=self.handle_client, args=(client_socket,)) client_thread.start()