init
This commit is contained in:
378
INTEGRATION.md
Normal file
378
INTEGRATION.md
Normal file
@@ -0,0 +1,378 @@
|
||||
# 🎬 Интеграция: Мобильное приложение + Сервер KazicCAM
|
||||
|
||||
## 📋 Быстрый старт (5 минут)
|
||||
|
||||
### 1️⃣ Запустить сервер на компьютере
|
||||
|
||||
```bash
|
||||
python server.py
|
||||
```
|
||||
|
||||
Сохраните IP адрес, который будет показан (например: 192.168.1.100)
|
||||
|
||||
### 2️⃣ Создать комнату в веб-интерфейсе
|
||||
|
||||
1. Откройте браузер → `http://192.168.1.100:8000`
|
||||
2. Вход: `admin` / `admin123`
|
||||
3. Нажмите **"Create Room"**
|
||||
4. Заполните форму и сохраните **Room ID** и **пароль**
|
||||
|
||||
### 3️⃣ Подключить приложение на телефоне
|
||||
|
||||
1. Запустите приложение **CamControl** на Android
|
||||
2. Введите:
|
||||
- IP сервера: `192.168.1.100`
|
||||
- Порт: `8000`
|
||||
- Room ID: (из шага 2)
|
||||
- Пароль: (из шага 2)
|
||||
3. Нажмите **"Подключиться"**
|
||||
|
||||
### 4️⃣ Просмотреть трансляцию
|
||||
|
||||
Вернитесь в веб-интерфейс → откройте комнату → нажмите **"View"** на клиенте
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Архитектура приложения
|
||||
|
||||
### Структура слоев
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ UI Layer (Compose) │
|
||||
│ MainActivity, Screens, Components │
|
||||
└────────────┬────────────────────────────┘
|
||||
│
|
||||
┌────────────▼────────────────────────────┐
|
||||
│ ViewModel Layer (StreamViewModel) │
|
||||
│ State Management, Business Logic │
|
||||
└────────────┬────────────────────────────┘
|
||||
│
|
||||
┌────────────▼────────────────────────────┐
|
||||
│ Service Layer │
|
||||
│ WebSocketManager, VideoStreamingMgr │
|
||||
└────────────┬────────────────────────────┘
|
||||
│
|
||||
┌────────────▼────────────────────────────┐
|
||||
│ External Services │
|
||||
│ WebSocket, CameraX, Android APIs │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Основные компоненты
|
||||
|
||||
| Компонент | Назначение |
|
||||
|-----------|-----------|
|
||||
| `MainActivity.kt` | Главный экран приложения |
|
||||
| `StreamViewModel.kt` | Управление состоянием и логикой |
|
||||
| `WebSocketManager.kt` | WebSocket соединение с сервером |
|
||||
| `VideoStreamingManager.kt` | Захват видео с камеры |
|
||||
| `CameraManager.kt` | Управление камерой |
|
||||
| `Models.kt` | Модели данных |
|
||||
|
||||
---
|
||||
|
||||
## 📡 Процесс трансляции видео
|
||||
|
||||
### Диаграмма потока данных
|
||||
|
||||
```
|
||||
Камера телефона
|
||||
↓
|
||||
CameraX (ImageAnalysis)
|
||||
↓
|
||||
VideoStreamingManager (обработка кадров)
|
||||
↓
|
||||
StreamViewModel (отправка на сервер)
|
||||
↓
|
||||
WebSocketManager (WebSocket)
|
||||
↓
|
||||
Сервер KazicCAM
|
||||
↓
|
||||
Веб-интерфейс (просмотр)
|
||||
```
|
||||
|
||||
### Этапы подключения
|
||||
|
||||
```
|
||||
1. Инициализация ViewModel
|
||||
└─ Создание WebSocketManager
|
||||
└─ Создание VideoStreamingManager
|
||||
|
||||
2. Подключение к серверу
|
||||
└─ WebSocket.connect(serverUrl)
|
||||
└─ Ожидание onOpen()
|
||||
|
||||
3. Запуск захвата видео
|
||||
└─ CameraX.startStreaming()
|
||||
└─ onFrameAvailable() callback
|
||||
|
||||
4. Отправка кадров
|
||||
└─ WebSocket.sendBinary(frameData)
|
||||
└─ Повторяется для каждого кадра
|
||||
|
||||
5. Отключение
|
||||
└─ WebSocket.disconnect()
|
||||
└─ CameraX.stopStreaming()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Интеграция с WebSocket
|
||||
|
||||
### Подключение
|
||||
|
||||
```kotlin
|
||||
val wsManager = WebSocketManager(
|
||||
onConnected = { /* уведомление UI */ },
|
||||
onDisconnected = { /* очистка ресурсов */ },
|
||||
onError = { error -> /* обработка ошибок */ },
|
||||
onMessage = { msg -> /* получение команд */ }
|
||||
)
|
||||
|
||||
wsManager.connect("ws://server:8000/ws/client/roomId/password")
|
||||
```
|
||||
|
||||
### Отправка видео
|
||||
|
||||
```kotlin
|
||||
// Отправка байтов кадра
|
||||
wsManager.sendBinary(frameData)
|
||||
|
||||
// Отправка команд JSON
|
||||
wsManager.sendMessage(VideoCommands.rotate(90).toJson())
|
||||
```
|
||||
|
||||
### Получение команд
|
||||
|
||||
```kotlin
|
||||
onMessage = { message ->
|
||||
val command = Gson().fromJson(message, VideoCommand::class.java)
|
||||
// Обработка команды...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Статистика и мониторинг
|
||||
|
||||
### Метрики приложения
|
||||
|
||||
```
|
||||
FPS (Frames Per Second)
|
||||
└─ Обновляется каждую секунду
|
||||
└─ Отправляется в логи
|
||||
|
||||
Объем переданных данных
|
||||
└─ Суммируется размер каждого кадра
|
||||
└─ Отображается в МБ
|
||||
|
||||
Статус подключения
|
||||
└─ Idle → Connecting → Connected → Disconnected/Error
|
||||
└─ Обновляется в реальном времени
|
||||
```
|
||||
|
||||
### Просмотр логов
|
||||
|
||||
```bash
|
||||
# Все логи приложения
|
||||
adb logcat | grep "camControl"
|
||||
|
||||
# Только WebSocket
|
||||
adb logcat | grep "WebSocket"
|
||||
|
||||
# Только видеопоток
|
||||
adb logcat | grep "VideoStreamingManager"
|
||||
|
||||
# Только ViewModel
|
||||
adb logcat | grep "StreamViewModel"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Безопасность соединения
|
||||
|
||||
### Текущая реализация
|
||||
|
||||
- ✅ WebSocket соединение
|
||||
- ✅ Аутентификация по Room ID и пароль
|
||||
- ❌ Шифрование не включено
|
||||
|
||||
### Для продакшена используйте WSS (WebSocket Secure)
|
||||
|
||||
```kotlin
|
||||
// Вместо ws:// используйте wss://
|
||||
wsManager.connect("wss://server:8000/ws/client/roomId/password")
|
||||
```
|
||||
|
||||
Требуется SSL сертификат на сервере.
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Отладка проблем
|
||||
|
||||
### Проблема: Приложение не подключается
|
||||
|
||||
**Логи:**
|
||||
```
|
||||
[WebSocket] Connection error: java.net.ConnectException
|
||||
```
|
||||
|
||||
**Решение:**
|
||||
- Проверьте IP адрес: `ping <server-ip>`
|
||||
- Убедитесь, что сервер запущен
|
||||
- Проверьте firewall: `netstat -an | findstr :8000`
|
||||
|
||||
### Проблема: Видео не передается
|
||||
|
||||
**Логи:**
|
||||
```
|
||||
[VideoStreamingManager] Error processing frame
|
||||
```
|
||||
|
||||
**Решение:**
|
||||
- Проверьте разрешение на камеру
|
||||
- Перезагрузите приложение
|
||||
- Проверьте, что другие приложения не используют камеру
|
||||
|
||||
### Проблема: Приложение крашится
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
# Очистить кэш
|
||||
adb shell pm clear com.example.camcontrol
|
||||
|
||||
# Переустановить
|
||||
./gradlew installDebug
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Оптимизация производительности
|
||||
|
||||
### На стороне приложения
|
||||
|
||||
1. **Качество видео**
|
||||
```kotlin
|
||||
// В ImageAnalysis.Builder()
|
||||
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
|
||||
// Более эффективный формат
|
||||
```
|
||||
|
||||
2. **Частота кадров**
|
||||
```kotlin
|
||||
// Отправлять кадры реже, если нужно
|
||||
if (frameCount % 2 == 0) { // Каждый 2-й кадр
|
||||
wsManager.sendBinary(frameData)
|
||||
}
|
||||
```
|
||||
|
||||
3. **Размер буфера**
|
||||
```kotlin
|
||||
// Сжимать кадры перед отправкой
|
||||
val compressed = compressFrame(frameData)
|
||||
wsManager.sendBinary(compressed)
|
||||
```
|
||||
|
||||
### На стороне сервера
|
||||
|
||||
Отредактируйте `server.py`:
|
||||
|
||||
```python
|
||||
SERVER_CONFIG = {
|
||||
"video_width": 480, # Уменьшить разрешение
|
||||
"video_height": 320,
|
||||
"jpeg_quality": 70, # Уменьшить качество
|
||||
"frame_rate": 15, # Снизить FPS
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Дополнительные примеры
|
||||
|
||||
### Отправка команды с параметром
|
||||
|
||||
```kotlin
|
||||
// Отправить команду яркости
|
||||
val command = VideoCommand(type = "brightness", value = 50)
|
||||
viewModel.sendCommand(command)
|
||||
```
|
||||
|
||||
### Обработка разных типов команд на сервере
|
||||
|
||||
```python
|
||||
if cmd_type == "rotate":
|
||||
angle = command.get("angle", 0)
|
||||
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
|
||||
elif cmd_type == "brightness":
|
||||
value = command.get("value", 0)
|
||||
frame = cv2.convertScaleAbs(frame, alpha=1, beta=value)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Жизненный цикл приложения
|
||||
|
||||
```
|
||||
onCreate()
|
||||
↓
|
||||
Запрос разрешений
|
||||
↓
|
||||
setContent() - Рисование UI
|
||||
↓
|
||||
Ввод параметров подключения
|
||||
↓
|
||||
initializeConnection()
|
||||
↓
|
||||
WebSocket подключение
|
||||
↓
|
||||
CameraX запуск
|
||||
↓
|
||||
Отправка видеокадров
|
||||
↓
|
||||
(пользователь нажимает отключиться)
|
||||
↓
|
||||
disconnect()
|
||||
↓
|
||||
Закрытие WebSocket
|
||||
↓
|
||||
Остановка камеры
|
||||
↓
|
||||
onDestroy()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Советы по использованию
|
||||
|
||||
1. **Используйте кабель USB** для более стабильного соединения при разработке
|
||||
2. **Монитор батареи** - приложение интенсивно использует камеру и сеть
|
||||
3. **Тестируйте на реальном устройстве** - эмулятор может быть медленнее
|
||||
4. **Сохраняйте логи** - полезно для отладки проблем
|
||||
|
||||
---
|
||||
|
||||
## 📝 Контрольный список подготовки к использованию
|
||||
|
||||
- [ ] Сервер запущен и доступен
|
||||
- [ ] Веб-интерфейс работает
|
||||
- [ ] Комната создана в веб-интерфейсе
|
||||
- [ ] Android устройство подключено в ту же сеть
|
||||
- [ ] Приложение установлено на устройстве
|
||||
- [ ] Разрешение на камеру выдано
|
||||
- [ ] IP адрес введен правильно
|
||||
- [ ] Room ID и пароль скопированы корректно
|
||||
|
||||
---
|
||||
|
||||
## 📞 Помощь и поддержка
|
||||
|
||||
Если возникают проблемы:
|
||||
|
||||
1. Проверьте логи Logcat
|
||||
2. Убедитесь, что все требования соблюдены
|
||||
3. Попробуйте переустановить приложение
|
||||
4. Перезагрузите телефон и компьютер
|
||||
|
||||
|
||||
Reference in New Issue
Block a user