- Fix saveWiFiPassword to use encrypted passwords map instead of decrypted - Fix getWiFiPassword to decrypt from encrypted storage - Fix test expectations for migration and encryption functions - Remove unused error variables to fix linting warnings - All 27 tests now passing with proper encryption/decryption flow The WiFi credentials cache feature was already implemented but had bugs where encrypted and decrypted password maps were being mixed. This commit ensures proper encryption is maintained throughout the storage lifecycle.
37 KiB
37 KiB
PRD — WellNuo Web
Overview
Полноценная веб-версия WellNuo для настройки и мониторинга BLE-сенсоров с ноутбука/десктопа.
Ключевое преимущество: Удобная настройка сенсоров с большого экрана, полная клавиатура для ввода WiFi паролей.
Browser Compatibility
Поддерживаемые браузеры (Web Bluetooth API)
| Браузер | Платформа | Статус |
|---|---|---|
| Chrome 70+ | Windows 10+, macOS | ✅ Полная поддержка |
| Edge 79+ | Windows 10+ | ✅ Полная поддержка |
| Opera 57+ | Windows, macOS | ✅ Полная поддержка |
НЕ поддерживаемые
| Браузер | Причина |
|---|---|
| Safari | Apple не реализовали Web Bluetooth |
| Firefox | Mozilla отказались по privacy concerns |
| Chrome iOS | iOS блокирует Web Bluetooth |
| Любой браузер на iOS | iOS ограничения |
Browser Check Flow
┌─────────────────────────────────────────────────────────────┐
│ Пользователь заходит │
└─────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────┐
│ navigator.bluetooth exists? │
└───────────────────────────────┘
│ │
YES NO
│ │
▼ ▼
┌─────────────┐ ┌─────────────────────────────┐
│ Продолжить │ │ Показать Unsupported Page │
│ в приложение│ │ + ссылки на Chrome/Edge │
└─────────────┘ │ + ссылка на мобильное app │
└─────────────────────────────┘
Tech Stack
| Компонент | Технология | Почему |
|---|---|---|
| Framework | Next.js 14 (App Router) | Похож на Expo Router, SSR, API routes |
| Styling | Tailwind CSS | Быстрая разработка, responsive |
| State | Zustand | Легковесный, как в мобилке |
| API Client | Fetch + custom hooks | Переиспользуем логику из мобилки |
| BLE | Web Bluetooth API | Нативный браузерный API |
| Auth | JWT (тот же что в мобилке) | Один backend |
| Deployment | Vercel | One-click deploy |
Backend Integration
КРИТИЧЕСКИ ВАЖНО: Используем СУЩЕСТВУЮЩИЙ backend!
┌─────────────────────────────────────────────────────────────────┐
│ WellNuo Web │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────┐ ┌────────────────────────┐ │
│ │ WellNuo API │ │ Legacy API │ │
│ │ wellnuo.smartlaunch│ │ eluxnetworks.net │ │
│ │ hub.com/api │ │ /function/well-api │ │
│ ├────────────────────┤ ├────────────────────────┤ │
│ │ • Auth (OTP) │ │ • device_form │ │
│ │ • /me/beneficiaries│ │ • device_list │ │
│ │ • /auth/profile │ │ • sensor data │ │
│ │ • Subscriptions │ │ • deployments │ │
│ └────────────────────┘ └────────────────────────┘ │
│ │
│ ТОТ ЖЕ КОД ИЗ services/api.ts — АДАПТИРУЕМ ДЛЯ ВЕБА │
└─────────────────────────────────────────────────────────────────┘
Screens & Features
1. Browser Check Page (entry point)
URL: / (redirect logic)
┌─────────────────────────────────────────────────────────────┐
│ │
│ Поддерживаемый браузер? │
│ │ │
│ ├─ YES → redirect to /login или /dashboard (if logged) │
│ │ │
│ └─ NO → показать /unsupported │
│ │
└─────────────────────────────────────────────────────────────┘
2. Unsupported Browser Page
URL: /unsupported
┌─────────────────────────────────────────────────────────────┐
│ │
│ ⚠️ Браузер не поддерживается │
│ │
│ Для работы с Bluetooth-сенсорами используйте: │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Chrome │ │ Edge │ │ Opera │ │
│ │ [Скачать] │ │ [Скачать] │ │ [Скачать] │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ────────────────── или ────────────────── │
│ │
│ Используйте мобильное приложение: │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ App Store │ │ Google Play │ │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
3. Auth Flow
URLs: /login, /verify-otp, /enter-name, /add-loved-one
Полностью повторяет мобильное приложение:
/login
┌─────────────────────────────────────────┐
│ │
│ WellNuo │
│ │
│ ┌───────────────────────────────────┐ │
│ │ Email │ │
│ └───────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────┐ │
│ │ Получить код │ │
│ └───────────────────────────────────┘ │
│ │
└─────────────────────────────────────────┘
/verify-otp
┌─────────────────────────────────────────┐
│ │
│ Введите код из письма │
│ │
│ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │
│ │ _ │ │ _ │ │ _ │ │ _ │ │ _ │ │ _ │ │
│ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ │
│ │
│ Отправить повторно (59 сек) │
│ │
└─────────────────────────────────────────┘
4. Dashboard
URL: /dashboard
┌─────────────────────────────────────────────────────────────────┐
│ WellNuo [Profile Icon] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Добро пожаловать, {firstName}! │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 👵 Мама │ │
│ │ ────────────────────────────────────────────────────── │ │
│ │ Сенсоры: 3 активных │ │
│ │ Последняя активность: 5 минут назад │ │
│ │ │ │
│ │ [Открыть] [Настройки] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 👴 Папа │ │
│ │ ────────────────────────────────────────────────────── │ │
│ │ Сенсоры: 2 активных │ │
│ │ Последняя активность: 1 час назад │ │
│ │ │ │
│ │ [Открыть] [Настройки] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ + Добавить близкого │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
5. Beneficiary Detail
URL: /beneficiaries/[id]
┌─────────────────────────────────────────────────────────────────┐
│ ← Назад 👵 Мама │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Обзор │ │ Сенсоры │ │ История │ │ Настройки│ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ═══════════════════════════════════════════════════════════ │
│ │
│ Сенсоры (3) [+ Добавить] │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🟢 WP_523_81A14C │ │
│ │ Кухня • Онлайн • Последнее: 2 мин назад │ │
│ │ [Настройки] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🟡 WP_524_92B25D │ │
│ │ Спальня • Онлайн • Последнее: 15 мин назад │ │
│ │ [Настройки] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🔴 WP_525_A3C36E │ │
│ │ Гостиная • Оффлайн • Последнее: 2 часа назад │ │
│ │ [Настройки] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
6. Add Sensor (BLE Scan)
URL: /beneficiaries/[id]/add-sensor
┌─────────────────────────────────────────────────────────────────┐
│ ← Назад Добавить сенсор │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. Включите сенсор (зажмите кнопку на 3 сек) │ │
│ │ 2. Убедитесь что Bluetooth включён на компьютере │ │
│ │ 3. Нажмите "Начать поиск" │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🔍 Начать поиск │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ Найденные устройства: │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 📶 WP_526_B4D47F Сигнал: ████░░ -65dBm │
│ │ [Подключить]│ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 📶 WP_527_C5E58G Сигнал: ██░░░░ -78dBm │
│ │ [Подключить]│ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
7. WiFi Setup
URL: /beneficiaries/[id]/setup-wifi
┌─────────────────────────────────────────────────────────────────┐
│ ← Назад Настройка WiFi │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Подключено к: WP_526_B4D47F │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ Шаг 2 из 4: Настройка WiFi │
│ ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 50% │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ Доступные сети: │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 📶 Home_WiFi_5G ████░░ -45dBm │ │
│ │ 🔒 Защищённая [Выбрать] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 📶 Home_WiFi ███░░░ -58dBm │ │
│ │ 🔒 Защищённая [Выбрать] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ Или введите вручную: │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Название сети (SSID) │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Пароль 👁️ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Подключить сенсор │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
8. Profile / Settings
URL: /profile
┌─────────────────────────────────────────────────────────────────┐
│ ← Назад Профиль │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 👤 │ │
│ │ John Doe │ │
│ │ john@example.com │ │
│ │ [Изменить] │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ Настройки │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 🌙 Тёмная тема [OFF] │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 🔔 Уведомления [ON] │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Выйти │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Error Handling
BLE Errors
| Ошибка | Сообщение | Действие |
|---|---|---|
| Bluetooth disabled | "Bluetooth выключен на вашем устройстве" | Инструкция как включить |
| Permission denied | "Доступ к Bluetooth запрещён" | Кнопка "Разрешить" + инструкция |
| Device not found | "Сенсор не найден. Убедитесь что он включён" | Кнопка "Повторить поиск" |
| Connection lost | "Соединение потеряно. Переподключение..." | Auto-retry 3 раза |
| GATT error | "Ошибка связи с сенсором" | Кнопка "Попробовать снова" |
Network Errors
| Ошибка | Сообщение | Действие |
|---|---|---|
| No internet | "Нет подключения к интернету" | Retry button |
| API timeout | "Сервер не отвечает" | Retry button |
| 401 Unauthorized | Redirect to /login | Clear token |
| 500 Server Error | "Ошибка сервера, попробуйте позже" | Retry button |
WiFi Setup Errors
| Ошибка | Сообщение | Действие |
|---|---|---|
| Wrong password | "Неверный пароль WiFi" | Показать поле ввода снова |
| Network not found | "Сеть не найдена" | Кнопка "Обновить список" |
| Connection timeout | "Сенсор не смог подключиться к WiFi" | Инструкция + retry |
Web Bluetooth Implementation
Service UUIDs (из мобильного приложения)
const BLE_CONFIG = {
// WP Sensor Service
SERVICE_UUID: 'xxxx-xxxx-xxxx-xxxx', // TODO: взять из BLEManager.ts
// Characteristics
WIFI_SSID_UUID: 'xxxx',
WIFI_PASSWORD_UUID: 'xxxx',
COMMAND_UUID: 'xxxx',
STATUS_UUID: 'xxxx',
};
Web Bluetooth API vs React Native BLE
| Операция | React Native (текущий) | Web Bluetooth |
|---|---|---|
| Scan | bleManager.startDeviceScan() |
navigator.bluetooth.requestDevice() |
| Connect | device.connect() |
device.gatt.connect() |
| Read | characteristic.read() |
characteristic.readValue() |
| Write | characteristic.writeWithResponse() |
characteristic.writeValue() |
| Subscribe | characteristic.monitor() |
characteristic.startNotifications() |
Project Structure
wellnuo-web/
├── app/
│ ├── (auth)/
│ │ ├── login/page.tsx
│ │ ├── verify-otp/page.tsx
│ │ ├── enter-name/page.tsx
│ │ └── add-loved-one/page.tsx
│ ├── (main)/
│ │ ├── dashboard/page.tsx
│ │ ├── beneficiaries/[id]/
│ │ │ ├── page.tsx
│ │ │ ├── add-sensor/page.tsx
│ │ │ ├── setup-wifi/page.tsx
│ │ │ └── device-settings/[deviceId]/page.tsx
│ │ └── profile/page.tsx
│ ├── unsupported/page.tsx
│ ├── layout.tsx
│ └── page.tsx (redirect logic)
├── components/
│ ├── ui/ (buttons, inputs, cards)
│ ├── BrowserCheck.tsx
│ ├── BLEScanner.tsx
│ ├── WiFiSetup.tsx
│ └── SensorCard.tsx
├── services/
│ ├── api.ts (адаптированный из мобилки)
│ ├── webBluetooth.ts (новый, Web Bluetooth API)
│ └── auth.ts
├── hooks/
│ ├── useBLE.ts
│ ├── useAuth.ts
│ └── useBeneficiaries.ts
├── stores/
│ └── authStore.ts (Zustand)
├── lib/
│ └── browserCheck.ts
└── types/
└── index.ts
Implementation Phases
Phase 1: Foundation (Week 1)
- Next.js project setup + Tailwind
- Browser compatibility check
- Unsupported browser page
- Basic layout + navigation
Phase 2: Auth (Week 1-2)
- Login page (email input)
- OTP verification
- Enter name (new users)
- JWT token management
- Protected routes
Phase 3: Dashboard & Beneficiaries (Week 2)
- Dashboard with beneficiary cards
- Beneficiary detail page
- Add beneficiary flow
- API integration (reuse from mobile)
Phase 4: BLE Integration (Week 2-3)
- Web Bluetooth service
- BLE scan page
- Device connection
- WiFi setup flow
- Sensor attachment to API
Phase 5: Polish (Week 3)
- Error handling (all cases)
- Loading states
- Responsive design
- Dark mode (optional)
- PWA setup (optional)
Success Criteria
- Работает в Chrome/Edge/Opera на Windows и macOS
- Показывает понятную ошибку в Safari/Firefox
- Auth flow идентичен мобилке
- BLE сканирование находит WP сенсоры
- WiFi setup работает полностью
- Сенсоры успешно attach'атся к beneficiary
- Все ошибки обрабатываются с понятными сообщениями
- Responsive дизайн (laptop + большой монитор)
Questions to Clarify
❓ Вопрос 1: BLE UUIDs
Нужно взять Service UUID и Characteristic UUIDs из services/ble/BLEManager.ts. Это критично для Web Bluetooth.
❓ Вопрос 2: Домен
Где будет хоститься? Варианты:
web.wellnuo.comapp.wellnuo.comwellnuo.smartlaunchhub.com(поддомен)
❓ Вопрос 3: PWA
Делать как PWA (можно "установить" на рабочий стол)? Это добавит ~1 день работы.
Notes
- Backend остаётся ТОТ ЖЕ — никаких изменений на сервере
- Код API вызовов переиспользуем из
services/api.ts - BLE логику пишем заново на Web Bluetooth API
- UI пишем на React + Tailwind (не React Native)