main commit

This commit is contained in:
2025-10-06 09:40:51 +09:00
parent b1de55d253
commit 79256cd9fc
2375 changed files with 370050 additions and 4033 deletions

350
godeye_server.py Normal file
View File

@@ -0,0 +1,350 @@
#!/usr/bin/env python3
"""
Простой веб-сервер для панели оператора GodEye
Обслуживает WebRTC интерфейс и Socket.IO соединения
"""
import socketio
import eventlet
import eventlet.wsgi
from flask import Flask, send_file
import json
import uuid
from datetime import datetime
import os
# Создаем Flask приложение
app = Flask(__name__)
# Создаем Socket.IO сервер
sio = socketio.Server(cors_allowed_origins="*")
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
# Хранилище подключенных устройств и операторов
connected_devices = {}
connected_operators = {}
active_sessions = {}
@app.route('/')
def serve_interface():
"""Обслуживает панель оператора"""
return send_file('operator-interface.html')
@sio.event
def connect(sid, environ):
"""Обработка подключения клиента"""
print(f"[{datetime.now().strftime('%H:%M:%S')}] 🔗 Клиент подключился: {sid}")
@sio.event
def disconnect(sid):
"""Обработка отключения клиента"""
print(f"[{datetime.now().strftime('%H:%M:%S')}] ❌ Клиент отключился: {sid}")
# Удаляем из устройств
if sid in connected_devices:
device_data = connected_devices[sid]
del connected_devices[sid]
sio.emit('device_disconnected', {
'deviceId': device_data['deviceId'],
'deviceName': device_data['deviceName']
})
print(f"[{datetime.now().strftime('%H:%M:%S')}] 📱 Устройство отключилось: {device_data['deviceName']}")
# Удаляем из операторов
if sid in connected_operators:
del connected_operators[sid]
print(f"[{datetime.now().strftime('%H:%M:%S')}] 👨‍💼 Оператор отключился")
@sio.event
def device_register(sid, data):
"""Регистрация Android устройства"""
device_id = data.get('deviceId')
device_name = data.get('deviceName', 'Unknown Device')
connected_devices[sid] = {
'deviceId': device_id,
'deviceName': device_name,
'connectedAt': datetime.now().isoformat()
}
print(f"[{datetime.now().strftime('%H:%M:%S')}] 📱 Устройство зарегистрировано: {device_name} ({device_id})")
# Уведомляем всех операторов о новом устройстве
sio.emit('device_connected', {
'deviceId': device_id,
'deviceName': device_name
})
# Отправляем подтверждение устройству
sio.emit('registration_confirmed', {
'status': 'success',
'message': 'Устройство успешно зарегистрировано'
}, room=sid)
@sio.event
def operator_register(sid, data):
"""Регистрация оператора"""
operator_id = data.get('operatorId', f'operator_{uuid.uuid4().hex[:8]}')
connected_operators[sid] = {
'operatorId': operator_id,
'connectedAt': datetime.now().isoformat()
}
print(f"[{datetime.now().strftime('%H:%M:%S')}] 👨‍💼 Оператор зарегистрирован: {operator_id}")
# Отправляем список подключенных устройств
devices_list = []
for device_sid, device_data in connected_devices.items():
devices_list.append({
'deviceId': device_data['deviceId'],
'deviceName': device_data['deviceName']
})
sio.emit('devices_list', {'devices': devices_list}, room=sid)
@sio.event
def request_camera(sid, data):
"""Запрос камеры от оператора"""
device_id = data.get('deviceId')
operator_id = data.get('operatorId')
camera_type = data.get('cameraType', 'back') # Убеждаемся что есть значение по умолчанию
print(f"[{datetime.now().strftime('%H:%M:%S')}] 📹 Запрос камеры от {operator_id} для устройства {device_id}, тип камеры: {camera_type}")
# Находим устройство по ID
target_device_sid = None
for device_sid, device_data in connected_devices.items():
if device_data['deviceId'] == device_id:
target_device_sid = device_sid
break
if target_device_sid:
session_id = str(uuid.uuid4())
# Сохраняем сессию с правильными данными
active_sessions[session_id] = {
'deviceSid': target_device_sid,
'operatorSid': sid,
'deviceId': device_id,
'operatorId': operator_id,
'cameraType': camera_type, # Явно сохраняем тип камеры
'status': 'pending', # Добавляем статус
'startedAt': datetime.now().isoformat()
}
# Отправляем запрос устройству с полными данными
sio.emit('camera_request', {
'sessionId': session_id,
'operatorId': operator_id,
'cameraType': camera_type,
'deviceId': device_id, # Добавляем deviceId
'message': f'Оператор {operator_id} запрашивает доступ к камере'
}, room=target_device_sid)
# Уведомляем оператора о создании сессии
sio.emit('session_created', {
'sessionId': session_id,
'deviceId': device_id,
'cameraType': camera_type,
'status': 'pending'
}, room=sid)
print(f"[{datetime.now().strftime('%H:%M:%S')}] 📤 Запрос отправлен устройству, сессия: {session_id}, камера: {camera_type}")
else:
sio.emit('error', {
'message': f'Устройство {device_id} не найдено'
}, room=sid)
@sio.event
def camera_approved(sid, data):
"""Подтверждение доступа к камере от устройства"""
session_id = data.get('sessionId')
if session_id in active_sessions:
session = active_sessions[session_id]
operator_sid = session['operatorSid']
# Обновляем статус сессии
active_sessions[session_id]['status'] = 'approved'
print(f"[{datetime.now().strftime('%H:%M:%S')}] ✅ Доступ к камере подтвержден для сессии: {session_id}")
# Уведомляем оператора с полными данными
sio.emit('camera_approved', {
'sessionId': session_id,
'deviceId': session['deviceId'],
'cameraType': session['cameraType'],
'status': 'approved'
}, room=operator_sid)
@sio.event
def camera_rejected(sid, data):
"""Отклонение доступа к камере от устройства"""
session_id = data.get('sessionId')
reason = data.get('reason', 'Отклонено пользователем')
if session_id in active_sessions:
session = active_sessions[session_id]
operator_sid = session['operatorSid']
print(f"[{datetime.now().strftime('%H:%M:%S')}] ❌ Доступ к камере отклонен для сессии: {session_id}, причина: {reason}")
# Уведомляем оператора об отклонении
sio.emit('camera_rejected', {
'sessionId': session_id,
'deviceId': session['deviceId'],
'reason': reason
}, room=operator_sid)
# Удаляем сессию, так как она отклонена
del active_sessions[session_id]
@sio.event
def camera_started(sid, data):
"""Уведомление о запуске камеры"""
session_id = data.get('sessionId')
if session_id in active_sessions:
session = active_sessions[session_id]
operator_sid = session['operatorSid']
# Обновляем статус сессии на активный
active_sessions[session_id]['status'] = 'active'
active_sessions[session_id]['actualStartedAt'] = datetime.now().isoformat()
print(f"[{datetime.now().strftime('%H:%M:%S')}] 📹 Камера запущена для сессии: {session_id}")
# Уведомляем оператора с обновленным статусом
sio.emit('camera_started', {
'sessionId': session_id,
'deviceId': session['deviceId'],
'cameraType': session['cameraType'],
'status': 'active'
}, room=operator_sid)
# Также отправляем обновление статуса сессии
sio.emit('session_status_update', {
'sessionId': session_id,
'status': 'active',
'cameraType': session['cameraType']
}, room=operator_sid)
@sio.event
def webrtc_offer(sid, data):
"""Пересылка WebRTC offer от устройства к оператору"""
session_id = data.get('sessionId')
offer = data.get('offer')
if session_id in active_sessions:
session = active_sessions[session_id]
operator_sid = session['operatorSid']
print(f"[{datetime.now().strftime('%H:%M:%S')}] 📡 Пересылка WebRTC offer для сессии: {session_id}")
# Пересылаем offer оператору
sio.emit('webrtc_offer', {
'sessionId': session_id,
'offer': offer
}, room=operator_sid)
@sio.event
def webrtc_answer(sid, data):
"""Пересылка WebRTC answer от оператора к устройству"""
session_id = data.get('sessionId')
answer = data.get('answer')
if session_id in active_sessions:
session = active_sessions[session_id]
device_sid = session['deviceSid']
print(f"[{datetime.now().strftime('%H:%M:%S')}] 📡 Пересылка WebRTC answer для сессии: {session_id}")
# Пересылаем answer устройству
sio.emit('webrtc_answer', {
'sessionId': session_id,
'answer': answer
}, room=device_sid)
@sio.event
def webrtc_ice_candidate(sid, data):
"""Пересылка ICE candidates между устройством и оператором"""
session_id = data.get('sessionId')
candidate = data.get('candidate')
if session_id in active_sessions:
session = active_sessions[session_id]
# Определяем куда пересылать (от устройства к оператору или наоборот)
if sid == session['deviceSid']:
# От устройства к оператору
target_sid = session['operatorSid']
else:
# От оператора к устройству
target_sid = session['deviceSid']
print(f"[{datetime.now().strftime('%H:%M:%S')}] 🧊 Пересылка ICE candidate для сессии: {session_id}")
sio.emit('webrtc_ice_candidate', {
'sessionId': session_id,
'candidate': candidate
}, room=target_sid)
@sio.event
def switch_camera(sid, data):
"""Переключение камеры"""
session_id = data.get('sessionId')
if session_id in active_sessions:
session = active_sessions[session_id]
device_sid = session['deviceSid']
print(f"[{datetime.now().strftime('%H:%M:%S')}] 🔄 Переключение камеры для сессии: {session_id}")
# Отправляем команду устройству
sio.emit('switch_camera', {
'sessionId': session_id
}, room=device_sid)
@sio.event
def stop_camera(sid, data):
"""Остановка камеры"""
session_id = data.get('sessionId')
if session_id in active_sessions:
session = active_sessions[session_id]
device_sid = session['deviceSid']
operator_sid = session['operatorSid']
print(f"[{datetime.now().strftime('%H:%M:%S')}] 🛑 Остановка камеры для сессии: {session_id}")
# Отправляем команду устройству
sio.emit('stop_camera', {
'sessionId': session_id
}, room=device_sid)
# Уведомляем оператора
sio.emit('camera_stopped', {
'sessionId': session_id
}, room=operator_sid)
# Удаляем сессию
del active_sessions[session_id]
if __name__ == '__main__':
# ИСПРАВЛЕНО: Используем localhost для локального тестирования
host = '0.0.0.0' # Слушаем на всех интерфейсах
port = 3001
print("🚀 Запуск GodEye сервера...")
print(f"🌐 Веб-интерфейс: http://localhost:{port}")
print(f"🔌 Socket.IO endpoint: http://localhost:{port}/socket.io/")
print("📱 Настройте Android приложение на адрес вашего компьютера")
print("-" * 50)
try:
eventlet.wsgi.server(eventlet.listen((host, port)), app)
except KeyboardInterrupt:
print("\n🛑 Сервер остановлен")
except Exception as e:
print(f"❌ Ошибка сервера: {e}")