connection fixes
This commit is contained in:
@@ -61,40 +61,6 @@ function initializeSocket() {
|
||||
socket.on('device:disconnected', (data) => {
|
||||
logMessage('warn', `Устройство отключено: ${data.deviceId}`);
|
||||
});
|
||||
|
||||
// Обработчики событий сессий
|
||||
socket.on('session:created', (data) => {
|
||||
logMessage('info', `Сессия создана: ${data.sessionId} для устройства ${data.deviceId}`);
|
||||
updateOperatorSessions();
|
||||
});
|
||||
|
||||
socket.on('session:accepted', (data) => {
|
||||
logMessage('info', `Сессия принята: ${data.sessionId}`);
|
||||
currentSessionId = data.sessionId;
|
||||
document.getElementById('current-session-id').value = currentSessionId;
|
||||
|
||||
// Показываем кнопку веб-камеры для оператора
|
||||
showOperatorWebcamButton();
|
||||
|
||||
updateOperatorSessions();
|
||||
showAlert('Сессия принята! Можно начинать WebRTC соединение.', 'success');
|
||||
});
|
||||
|
||||
socket.on('session:rejected', (data) => {
|
||||
logMessage('warn', `Сессия отклонена: ${data.sessionId} - ${data.error}`);
|
||||
updateOperatorSessions();
|
||||
showAlert(`Сессия отклонена: ${data.error}`, 'warning');
|
||||
});
|
||||
|
||||
socket.on('session:ended', (data) => {
|
||||
logMessage('info', `Сессия завершена: ${data.sessionId}`);
|
||||
updateOperatorSessions();
|
||||
|
||||
// Скрываем элементы веб-камеры
|
||||
hideOperatorWebcamButton();
|
||||
const webcamVideo = document.getElementById('operatorWebcam');
|
||||
if (webcamVideo) webcamVideo.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// Обновление статуса подключения
|
||||
@@ -181,6 +147,8 @@ function connectAndroid() {
|
||||
});
|
||||
|
||||
androidSocket.on('camera:request', (data) => {
|
||||
console.log('🎥 ПОЛУЧЕН ЗАПРОС КАМЕРЫ:', data);
|
||||
logMessage('info', `🎥 Получен запрос камеры: ${JSON.stringify(data)}`);
|
||||
showCameraRequest(data);
|
||||
});
|
||||
|
||||
@@ -213,6 +181,7 @@ function disconnectAndroid() {
|
||||
}
|
||||
|
||||
function showCameraRequest(data) {
|
||||
console.log('📱 ПОКАЗЫВАЕМ ЗАПРОС КАМЕРЫ:', data);
|
||||
const container = document.getElementById('android-requests');
|
||||
const requestDiv = document.createElement('div');
|
||||
requestDiv.className = 'session-card session-pending';
|
||||
@@ -227,19 +196,30 @@ function showCameraRequest(data) {
|
||||
|
||||
container.appendChild(requestDiv);
|
||||
logMessage('info', `Получен запрос камеры от ${data.operatorId}`);
|
||||
|
||||
// Автоматически принимаем запрос через 1 секунду для удобства тестирования
|
||||
console.log('⏰ ЗАПЛАНИРОВАНО АВТОПРИНЯТИЕ ЧЕРЕЗ 1 СЕКУНДУ');
|
||||
setTimeout(() => {
|
||||
console.log('⏰ ВЫПОЛНЯЕМ АВТОПРИНЯТИЕ');
|
||||
acceptCameraRequest(data.sessionId);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function acceptCameraRequest(sessionId) {
|
||||
console.log('✅ ПРИНЯТИЕ ЗАПРОСА КАМЕРЫ:', sessionId);
|
||||
if (androidSocket) {
|
||||
androidSocket.emit('camera:response', {
|
||||
sessionId,
|
||||
accepted: true,
|
||||
streamUrl: 'webrtc'
|
||||
});
|
||||
console.log('✅ ОТПРАВЛЕНО camera:response с accepted=true');
|
||||
|
||||
// Перемещаем в активные сессии
|
||||
moveToActiveSessions(sessionId, 'active');
|
||||
logMessage('info', `Запрос камеры принят: ${sessionId}`);
|
||||
} else {
|
||||
console.error('❌ androidSocket НЕ ПОДКЛЮЧЕН!');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,14 +314,6 @@ function connectOperator() {
|
||||
document.getElementById('operator-disconnect').disabled = false;
|
||||
|
||||
showAvailableDevices(data.availableDevices || []);
|
||||
updateOperatorSessions(); // Обновляем список сессий после подключения
|
||||
|
||||
// Автоматическое обновление сессий каждые 3 секунды
|
||||
setInterval(() => {
|
||||
if (operatorSocket && operatorSocket.connected) {
|
||||
updateOperatorSessions();
|
||||
}
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
operatorSocket.on('device:connected', (data) => {
|
||||
@@ -352,12 +324,6 @@ function connectOperator() {
|
||||
operatorSocket.on('camera:stream-ready', (data) => {
|
||||
logMessage('info', `Камера готова: ${data.sessionId}`);
|
||||
showOperatorSession(data.sessionId, 'active');
|
||||
updateOperatorSessions();
|
||||
});
|
||||
|
||||
operatorSocket.on('camera:request-sent', (data) => {
|
||||
logMessage('info', `Запрос отправлен: ${data.sessionId}`);
|
||||
updateOperatorSessions();
|
||||
});
|
||||
|
||||
operatorSocket.on('camera:denied', (data) => {
|
||||
@@ -545,7 +511,26 @@ async function endOperatorSession(sessionId) {
|
||||
}
|
||||
|
||||
async function refreshSessions() {
|
||||
updateOperatorSessions();
|
||||
const operatorId = document.getElementById('operator-id').value;
|
||||
if (!operatorId) return;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/operators/sessions', {
|
||||
headers: { 'X-Operator-Id': operatorId }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const container = document.getElementById('operator-sessions');
|
||||
container.innerHTML = '';
|
||||
|
||||
data.sessions.forEach(session => {
|
||||
showOperatorSession(session.sessionId, session.status);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logMessage('error', 'Ошибка загрузки сессий: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// === ADMIN FUNCTIONS ===
|
||||
@@ -679,9 +664,11 @@ function setupAndroidWebRTC() {
|
||||
|
||||
androidSocket.on('webrtc:ice-candidate', async (data) => {
|
||||
try {
|
||||
logMessage('info', `📡 Получен ICE candidate: ${JSON.stringify(data.candidate)}`);
|
||||
const pc = getOrCreatePeerConnection();
|
||||
const candidate = JSON.parse(data.candidate);
|
||||
const candidate = data.candidate;
|
||||
await pc.addIceCandidate(new RTCIceCandidate(candidate));
|
||||
logMessage('success', '✅ ICE candidate добавлен успешно');
|
||||
} catch (error) {
|
||||
logMessage('error', 'ICE candidate ошибка: ' + error.message);
|
||||
}
|
||||
@@ -706,9 +693,11 @@ function setupOperatorWebRTC() {
|
||||
|
||||
operatorSocket.on('webrtc:ice-candidate', async (data) => {
|
||||
try {
|
||||
logMessage('info', `📡 Получен ICE candidate: ${JSON.stringify(data.candidate)}`);
|
||||
const pc = getOrCreatePeerConnection();
|
||||
const candidate = JSON.parse(data.candidate);
|
||||
const candidate = data.candidate;
|
||||
await pc.addIceCandidate(new RTCIceCandidate(candidate));
|
||||
logMessage('success', '✅ ICE candidate добавлен успешно');
|
||||
} catch (error) {
|
||||
logMessage('error', 'ICE candidate ошибка: ' + error.message);
|
||||
}
|
||||
@@ -721,11 +710,13 @@ function getOrCreatePeerConnection() {
|
||||
|
||||
peerConnection.onicecandidate = (event) => {
|
||||
if (event.candidate) {
|
||||
const candidateData = JSON.stringify({
|
||||
const candidateData = {
|
||||
candidate: event.candidate.candidate,
|
||||
sdpMid: event.candidate.sdpMid,
|
||||
sdpMLineIndex: event.candidate.sdpMLineIndex
|
||||
});
|
||||
};
|
||||
|
||||
logMessage('info', `📤 Отправляем ICE candidate: ${JSON.stringify(candidateData)}`);
|
||||
|
||||
if (androidSocket) {
|
||||
androidSocket.emit('webrtc:ice-candidate', {
|
||||
@@ -809,95 +800,9 @@ function stopLocalVideo() {
|
||||
}
|
||||
}
|
||||
|
||||
// Обновление списка сессий оператора
|
||||
function updateOperatorSessions() {
|
||||
console.log('updateOperatorSessions called, operatorSocket:', operatorSocket);
|
||||
|
||||
if (!operatorSocket) {
|
||||
console.log('No operatorSocket, returning');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!operatorSocket.connected) {
|
||||
console.log('operatorSocket not connected, returning');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Requesting sessions list...');
|
||||
operatorSocket.emit('sessions:list', {}, (sessions) => {
|
||||
console.log('Received sessions:', sessions);
|
||||
|
||||
const container = document.getElementById('operator-sessions');
|
||||
if (!container) {
|
||||
console.log('No operator-sessions container found');
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = '';
|
||||
|
||||
if (!sessions || sessions.length === 0) {
|
||||
container.innerHTML = '<p>Нет активных сессий</p>';
|
||||
console.log('No sessions to display');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Displaying', sessions.length, 'sessions');
|
||||
sessions.forEach(session => {
|
||||
const sessionCard = document.createElement('div');
|
||||
sessionCard.className = `session-card session-${session.status}`;
|
||||
|
||||
const statusText = {
|
||||
'pending': 'Ожидание',
|
||||
'active': 'Активна',
|
||||
'rejected': 'Отклонена',
|
||||
'ended': 'Завершена'
|
||||
};
|
||||
|
||||
sessionCard.innerHTML = `
|
||||
<h4>Сессия: ${session.sessionId ? session.sessionId.substr(0, 8) : session.id ? session.id.substr(0, 8) : 'N/A'}...</h4>
|
||||
<p><strong>Устройство:</strong> ${session.deviceId}</p>
|
||||
<p><strong>Камера:</strong> ${session.cameraType}</p>
|
||||
<p><strong>Статус:</strong> ${statusText[session.status] || session.status}</p>
|
||||
<p><strong>Создана:</strong> ${new Date(session.createdAt).toLocaleString()}</p>
|
||||
${session.status === 'active' ? `
|
||||
<button class="btn" onclick="switchCamera('${session.sessionId || session.id}', 'front')">Фронтальная</button>
|
||||
<button class="btn" onclick="switchCamera('${session.sessionId || session.id}', 'back')">Основная</button>
|
||||
<button class="btn btn-danger" onclick="endSession('${session.sessionId || session.id}')">Завершить</button>
|
||||
` : ''}
|
||||
`;
|
||||
|
||||
container.appendChild(sessionCard);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Завершение сессии
|
||||
function endSession(sessionId) {
|
||||
if (!operatorSocket) {
|
||||
showAlert('Не подключен как оператор', 'danger');
|
||||
return;
|
||||
}
|
||||
|
||||
operatorSocket.emit('session:end', { sessionId });
|
||||
logMessage('info', `Завершаем сессию: ${sessionId}`);
|
||||
}
|
||||
|
||||
// Переключение камеры
|
||||
function switchCamera(sessionId, cameraType) {
|
||||
if (!operatorSocket) {
|
||||
showAlert('Не подключен как оператор', 'danger');
|
||||
return;
|
||||
}
|
||||
|
||||
operatorSocket.emit('camera:switch', {
|
||||
sessionId,
|
||||
cameraType
|
||||
});
|
||||
logMessage('info', `Переключаем камеру: ${sessionId} на ${cameraType}`);
|
||||
}
|
||||
|
||||
// Показ уведомления
|
||||
function showAlert(message, type) {
|
||||
// Вспомогательная функция для показа уведомлений
|
||||
function showAlert(type, message) {
|
||||
// Создаем временное уведомление
|
||||
const alert = document.createElement('div');
|
||||
alert.className = `alert alert-${type}`;
|
||||
alert.textContent = message;
|
||||
@@ -909,66 +814,10 @@ function showAlert(message, type) {
|
||||
|
||||
document.body.appendChild(alert);
|
||||
|
||||
// Удаляем через 5 секунд
|
||||
setTimeout(() => {
|
||||
if (document.body.contains(alert)) {
|
||||
document.body.removeChild(alert);
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// === ОПЕРАТОР: Веб-камера и WebRTC ===
|
||||
function showOperatorWebcamButton() {
|
||||
const btn = document.getElementById('startOperatorWebcam');
|
||||
if (btn) btn.style.display = '';
|
||||
}
|
||||
function hideOperatorWebcamButton() {
|
||||
const btn = document.getElementById('startOperatorWebcam');
|
||||
if (btn) btn.style.display = 'none';
|
||||
}
|
||||
function startOperatorWebcam() {
|
||||
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
|
||||
.then(stream => {
|
||||
operatorWebcamStream = stream;
|
||||
const video = document.getElementById('operatorWebcam');
|
||||
if (video) {
|
||||
video.srcObject = stream;
|
||||
video.style.display = '';
|
||||
}
|
||||
startOperatorWebRTC(stream);
|
||||
})
|
||||
.catch(err => {
|
||||
showAlert('danger', 'Ошибка доступа к веб-камере: ' + err);
|
||||
});
|
||||
}
|
||||
function startOperatorWebRTC(stream) {
|
||||
operatorWebcamPeer = new RTCPeerConnection(rtcConfig);
|
||||
stream.getTracks().forEach(track => operatorWebcamPeer.addTrack(track, stream));
|
||||
operatorWebcamPeer.onicecandidate = e => {
|
||||
if (e.candidate) {
|
||||
socket.emit('webrtc:ice-candidate', { candidate: e.candidate });
|
||||
}
|
||||
};
|
||||
operatorWebcamPeer.createOffer().then(offer => {
|
||||
return operatorWebcamPeer.setLocalDescription(offer);
|
||||
}).then(() => {
|
||||
socket.emit('webrtc:offer', { offer: operatorWebcamPeer.localDescription });
|
||||
});
|
||||
}
|
||||
socket.on('webrtc:answer', data => {
|
||||
if (operatorWebcamPeer) {
|
||||
operatorWebcamPeer.setRemoteDescription(new RTCSessionDescription(data.answer));
|
||||
}
|
||||
});
|
||||
socket.on('webrtc:ice-candidate', data => {
|
||||
if (operatorWebcamPeer && data.candidate) {
|
||||
operatorWebcamPeer.addIceCandidate(new RTCIceCandidate(data.candidate));
|
||||
}
|
||||
});
|
||||
// Показывать кнопку веб-камеры при принятии сессии
|
||||
socket.on('camera:response', data => {
|
||||
if (data.accepted) {
|
||||
showOperatorWebcamButton();
|
||||
} else {
|
||||
hideOperatorWebcamButton();
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user