324 lines
9.7 KiB
JavaScript
324 lines
9.7 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* Тестовый скрипт для симуляции подключения Android устройства
|
||
* и тестирования подключения Desktop Operator к телефону
|
||
*/
|
||
|
||
const io = require('socket.io-client');
|
||
const axios = require('axios');
|
||
|
||
const SERVER_URL = 'http://localhost:3001';
|
||
const WS_URL = 'ws://localhost:3001';
|
||
|
||
// Симулируем Android устройство
|
||
class AndroidSimulator {
|
||
constructor(deviceId) {
|
||
this.deviceId = deviceId;
|
||
this.socket = null;
|
||
this.isRegistered = false;
|
||
}
|
||
|
||
async connect() {
|
||
console.log('📱 Подключение Android устройства...');
|
||
|
||
this.socket = io(WS_URL, {
|
||
transports: ['websocket']
|
||
});
|
||
|
||
return new Promise((resolve, reject) => {
|
||
this.socket.on('connect', () => {
|
||
console.log(`✅ Android подключен: ${this.socket.id}`);
|
||
this.register();
|
||
resolve();
|
||
});
|
||
|
||
this.socket.on('connect_error', (error) => {
|
||
console.error('❌ Ошибка подключения Android:', error);
|
||
reject(error);
|
||
});
|
||
|
||
// Обработка запросов подключения
|
||
this.socket.on('connection:request', (data) => {
|
||
console.log('📞 Получен запрос подключения:', data);
|
||
this.handleConnectionRequest(data);
|
||
});
|
||
|
||
// Legacy обработка
|
||
this.socket.on('camera:request', (data) => {
|
||
console.log('📷 Получен запрос камеры (legacy):', data);
|
||
this.handleCameraRequest(data);
|
||
});
|
||
});
|
||
}
|
||
|
||
register() {
|
||
console.log('📝 Регистрация Android устройства...');
|
||
|
||
this.socket.emit('register:android', {
|
||
deviceId: this.deviceId,
|
||
deviceInfo: {
|
||
manufacturer: 'Samsung',
|
||
model: 'Galaxy S21 Test',
|
||
androidVersion: '11',
|
||
availableCameras: ['back', 'front', 'ultra_wide', 'telephoto'],
|
||
appVersion: '1.0.0-test'
|
||
}
|
||
});
|
||
|
||
this.socket.on('register:success', (data) => {
|
||
console.log('✅ Android зарегистрирован:', data);
|
||
this.isRegistered = true;
|
||
});
|
||
}
|
||
|
||
handleConnectionRequest(data) {
|
||
console.log(`
|
||
🔔 ЗАПРОС ПОДКЛЮЧЕНИЯ:
|
||
Connection ID: ${data.connectionId}
|
||
Operator: ${data.operatorInfo?.name || 'Unknown'}
|
||
Camera: ${data.cameraType}
|
||
Expires: ${data.expiresAt}
|
||
`);
|
||
|
||
// Симулируем принятие запроса через 2 секунды
|
||
setTimeout(() => {
|
||
console.log('✅ Принимаем запрос подключения...');
|
||
|
||
this.socket.emit('connection:accept', {
|
||
connectionId: data.connectionId,
|
||
sessionId: data.sessionId,
|
||
cameraType: data.cameraType,
|
||
webrtcInfo: {
|
||
supported: true,
|
||
codecs: ['H264', 'VP8'],
|
||
resolutions: ['720p', '1080p', '4K']
|
||
},
|
||
timestamp: new Date().toISOString()
|
||
});
|
||
}, 2000);
|
||
}
|
||
|
||
handleCameraRequest(data) {
|
||
console.log(`
|
||
📷 LEGACY ЗАПРОС КАМЕРЫ:
|
||
Session ID: ${data.sessionId}
|
||
Operator: ${data.operatorId}
|
||
Camera: ${data.cameraType}
|
||
`);
|
||
|
||
// Симулируем принятие запроса
|
||
setTimeout(() => {
|
||
console.log('✅ Принимаем запрос камеры (legacy)...');
|
||
|
||
this.socket.emit('camera:response', {
|
||
sessionId: data.sessionId,
|
||
accepted: true,
|
||
reason: 'camera_granted',
|
||
cameraType: data.cameraType,
|
||
timestamp: new Date().toISOString()
|
||
});
|
||
}, 1500);
|
||
}
|
||
|
||
disconnect() {
|
||
if (this.socket) {
|
||
this.socket.disconnect();
|
||
console.log('📱 Android отключен');
|
||
}
|
||
}
|
||
}
|
||
|
||
// Симулируем Desktop Operator
|
||
class OperatorSimulator {
|
||
constructor(operatorId) {
|
||
this.operatorId = operatorId;
|
||
this.socket = null;
|
||
this.isRegistered = false;
|
||
}
|
||
|
||
async connect() {
|
||
console.log('💻 Подключение Desktop Operator...');
|
||
|
||
this.socket = io(WS_URL, {
|
||
transports: ['websocket']
|
||
});
|
||
|
||
return new Promise((resolve, reject) => {
|
||
this.socket.on('connect', () => {
|
||
console.log(`✅ Operator подключен: ${this.socket.id}`);
|
||
this.register();
|
||
resolve();
|
||
});
|
||
|
||
this.socket.on('connect_error', (error) => {
|
||
console.error('❌ Ошибка подключения Operator:', error);
|
||
reject(error);
|
||
});
|
||
|
||
// Обработка ответов на подключения
|
||
this.socket.on('connection:accepted', (data) => {
|
||
console.log('🎉 Подключение принято Android:', data);
|
||
});
|
||
|
||
this.socket.on('connection:rejected', (data) => {
|
||
console.log('❌ Подключение отклонено Android:', data);
|
||
});
|
||
|
||
this.socket.on('connection:timeout', (data) => {
|
||
console.log('⏰ Таймаут подключения:', data);
|
||
});
|
||
|
||
// Legacy события
|
||
this.socket.on('camera:accepted', (data) => {
|
||
console.log('📹 Камера принята (legacy):', data);
|
||
});
|
||
});
|
||
}
|
||
|
||
register() {
|
||
console.log('📝 Регистрация Desktop Operator...');
|
||
|
||
this.socket.emit('register:operator', {
|
||
operatorId: this.operatorId,
|
||
operatorInfo: {
|
||
name: 'Тестовый Оператор',
|
||
organization: 'QA Отдел',
|
||
permissions: ['view_cameras', 'request_camera', 'initiate_connection']
|
||
}
|
||
});
|
||
|
||
this.socket.on('register:success', (data) => {
|
||
console.log('✅ Operator зарегистрирован:', data);
|
||
this.isRegistered = true;
|
||
});
|
||
}
|
||
|
||
async getAvailableDevices() {
|
||
try {
|
||
const response = await axios.get(`${SERVER_URL}/api/operators/devices`, {
|
||
headers: {
|
||
'x-operator-id': this.operatorId
|
||
}
|
||
});
|
||
|
||
console.log('📱 Доступные устройства:', response.data);
|
||
return response.data.devices;
|
||
} catch (error) {
|
||
console.error('❌ Ошибка получения устройств:', error.response?.data || error.message);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
async requestConnection(deviceId, cameraType = 'back') {
|
||
try {
|
||
console.log(`🔗 Запрос подключения к ${deviceId} (${cameraType})...`);
|
||
|
||
const response = await axios.post(`${SERVER_URL}/api/operators/connections/request`, {
|
||
deviceId,
|
||
cameraType
|
||
}, {
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'x-operator-id': this.operatorId
|
||
}
|
||
});
|
||
|
||
console.log('✅ Запрос подключения отправлен:', response.data);
|
||
return response.data;
|
||
} catch (error) {
|
||
console.error('❌ Ошибка запроса подключения:', error.response?.data || error.message);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async getConnections() {
|
||
try {
|
||
const response = await axios.get(`${SERVER_URL}/api/operators/connections`, {
|
||
headers: {
|
||
'x-operator-id': this.operatorId
|
||
}
|
||
});
|
||
|
||
console.log('🔗 Активные подключения:', response.data);
|
||
return response.data.connections;
|
||
} catch (error) {
|
||
console.error('❌ Ошибка получения подключений:', error.response?.data || error.message);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
disconnect() {
|
||
if (this.socket) {
|
||
this.socket.disconnect();
|
||
console.log('💻 Operator отключен');
|
||
}
|
||
}
|
||
}
|
||
|
||
// Основная функция тестирования
|
||
async function runTest() {
|
||
console.log('🚀 Запуск тестирования подключения Operator → Android');
|
||
console.log('=' .repeat(60));
|
||
|
||
const deviceId = 'test_android_' + Math.random().toString(36).substr(2, 9);
|
||
const operatorId = 'test_operator_' + Math.random().toString(36).substr(2, 9);
|
||
|
||
const android = new AndroidSimulator(deviceId);
|
||
const operator = new OperatorSimulator(operatorId);
|
||
|
||
try {
|
||
// 1. Подключаем Android
|
||
await android.connect();
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
|
||
// 2. Подключаем Operator
|
||
await operator.connect();
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
|
||
// 3. Проверяем доступные устройства
|
||
console.log('\n📋 Шаг 1: Проверка доступных устройств');
|
||
const devices = await operator.getAvailableDevices();
|
||
|
||
if (devices.length === 0) {
|
||
console.log('❌ Нет доступных устройств');
|
||
return;
|
||
}
|
||
|
||
// 4. Инициируем подключение
|
||
console.log('\n🔗 Шаг 2: Инициация подключения');
|
||
const connectionResult = await operator.requestConnection(deviceId, 'back');
|
||
|
||
if (!connectionResult) {
|
||
console.log('❌ Не удалось создать подключение');
|
||
return;
|
||
}
|
||
|
||
// 5. Ждем обработки подключения
|
||
console.log('\n⏳ Шаг 3: Ожидание ответа Android...');
|
||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||
|
||
// 6. Проверяем статус подключений
|
||
console.log('\n📊 Шаг 4: Проверка статуса подключений');
|
||
await operator.getConnections();
|
||
|
||
console.log('\n✅ Тестирование завершено!');
|
||
|
||
} catch (error) {
|
||
console.error('❌ Ошибка тестирования:', error);
|
||
} finally {
|
||
// Отключаем всех
|
||
setTimeout(() => {
|
||
android.disconnect();
|
||
operator.disconnect();
|
||
process.exit(0);
|
||
}, 2000);
|
||
}
|
||
}
|
||
|
||
// Запуск
|
||
if (require.main === module) {
|
||
runTest();
|
||
}
|
||
|
||
module.exports = { AndroidSimulator, OperatorSimulator }; |