WellNuo/PRD-SENSORS.md
Sergei 9f9124fdab feat(sensors): Batch sensor setup with progress UI and error handling
- Add updateDeviceMetadata and attachDeviceToDeployment API methods
- Device Settings: editable location/description fields with save
- Equipment screen: location placeholder and quick navigation to settings
- Add Sensor: multi-select with checkboxes, select all/deselect all
- Setup WiFi: batch processing of multiple sensors sequentially
- BatchSetupProgress: animated progress bar, step indicators, auto-scroll
- SetupResultsScreen: success/failed/skipped summary with retry options
- Error handling: modal with Retry/Skip/Cancel All buttons
- Documentation: SENSORS_SYSTEM.md with full BLE protocol and flows

Implemented via Ralphy CLI autonomous agent in ~43 minutes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-19 23:24:22 -08:00

356 lines
9.8 KiB
Markdown

# PRD: Sensors Management System
## Context
WellNuo app for elderly care. BLE/WiFi sensors monitor beneficiaries (elderly people) at home.
Each user can have multiple beneficiaries. Each beneficiary has one deployment (household) with up to 5 sensors.
**Architecture:**
- User → Beneficiary (WellNuo API) → deploymentId → Deployment (Legacy API) → Devices
- BLE for sensor setup, WiFi for data transmission
- Legacy API at `https://eluxnetworks.net/function/well-api/api` (external, read-only code access)
**Documentation:** `docs/SENSORS_SYSTEM.md`
**Feature Spec:** `specs/wellnuo/FEATURE-SENSORS-SYSTEM.md`
---
## Tasks
### Phase 1: API Layer
- [x] **TASK-1.1: Add updateDeviceMetadata method to api.ts**
File: `services/api.ts`
Add method to update device location and description via Legacy API.
```typescript
async updateDeviceMetadata(
wellId: number,
mac: string,
deploymentId: number,
location: string,
description: string
): Promise<boolean>
```
Implementation:
1. Get Legacy API credentials via `getLegacyCredentials()`
2. Build form data with: `function=device_form`, `user_name`, `token`, `well_id`, `device_mac`, `location`, `description`, `deployment_id`
3. POST to `https://eluxnetworks.net/function/well-api/api`
4. Return true on success, false on error
Reference: `docs/SENSORS_SYSTEM.md` lines 266-280 for API format.
---
### Phase 2: Device Settings UI
- [x] **TASK-2.1: Add location/description editing to Device Settings screen**
File: `app/(tabs)/beneficiaries/[id]/device-settings/[deviceId].tsx`
Add editable fields for sensor location and description:
1. Add state variables: `location`, `description`, `isSaving`
2. Add two TextInput fields below device info section
3. Add "Save" button that calls `api.updateDeviceMetadata()`
4. Show loading indicator during save
5. Show success/error toast after save
6. Pre-fill fields with current values from device data
UI requirements:
- TextInput for location (placeholder: "e.g., Bedroom, near bed")
- TextInput for description (placeholder: "e.g., Main activity sensor")
- Button: "Save Changes" (disabled when no changes or saving)
- Toast: "Settings saved" on success
---
### Phase 3: Equipment Screen Improvements
- [x] **TASK-3.1: Show placeholder for empty location in Equipment screen**
File: `app/(tabs)/beneficiaries/[id]/equipment.tsx`
Find the sensor list rendering (around line 454) and update:
Before:
```tsx
{sensor.location && (
<Text style={styles.deviceLocation}>{sensor.location}</Text>
)}
```
After:
```tsx
<Text style={[styles.deviceLocation, !sensor.location && styles.deviceLocationEmpty]}>
{sensor.location || 'Tap to set location'}
</Text>
```
Add style `deviceLocationEmpty` with `opacity: 0.5, fontStyle: 'italic'`
- [x] **TASK-3.2: Add quick navigation to Device Settings from Equipment screen**
File: `app/(tabs)/beneficiaries/[id]/equipment.tsx`
Make the location text tappable to navigate to Device Settings:
1. Wrap location Text in TouchableOpacity
2. onPress: navigate to `/beneficiaries/${id}/device-settings/${device.id}`
3. Import `useRouter` from `expo-router` if not already imported
---
### Phase 4: Batch Sensor Setup - Selection UI
- [x] **TASK-4.1: Add checkbox selection to Add Sensor screen**
File: `app/(tabs)/beneficiaries/[id]/add-sensor.tsx`
After BLE scan, show checkboxes for selecting multiple sensors:
1. Add state: `selectedDevices: Set<string>` (device IDs)
2. After scan, select ALL devices by default
3. Render each device with checkbox (use Checkbox from react-native or custom)
4. Add "Select All" / "Deselect All" toggle at top
5. Show count: "3 of 5 selected"
6. Change button from "Connect" to "Setup Selected (N)"
7. Pass selected devices to Setup WiFi screen via route params
UI layout:
```
[ ] Select All
[x] WP_497_81a14c -55 dBm ✓
[x] WP_498_82b25d -62 dBm ✓
[ ] WP_499_83c36e -78 dBm
[Setup Selected (2)]
```
- [x] **TASK-4.2: Update navigation to pass selected devices**
File: `app/(tabs)/beneficiaries/[id]/add-sensor.tsx`
When navigating to setup-wifi screen, pass selected devices:
```typescript
router.push({
pathname: `/(tabs)/beneficiaries/${id}/setup-wifi`,
params: {
devices: JSON.stringify(selectedDevicesArray),
beneficiaryId: id
}
});
```
---
### Phase 5: Batch Sensor Setup - WiFi Configuration
- [x] **TASK-5.1: Refactor Setup WiFi screen for batch processing**
File: `app/(tabs)/beneficiaries/[id]/setup-wifi.tsx`
Update to handle multiple devices:
1. Parse `devices` from route params (JSON array of WPDevice objects)
2. Get WiFi list from FIRST device only (all sensors at same location = same WiFi)
3. After user enters password, process ALL devices sequentially
4. Add state for batch progress tracking
New state:
```typescript
interface DeviceSetupState {
deviceId: string;
deviceName: string;
status: 'pending' | 'connecting' | 'unlocking' | 'setting_wifi' | 'attaching' | 'rebooting' | 'success' | 'error';
error?: string;
}
const [setupStates, setSetupStates] = useState<DeviceSetupState[]>([]);
```
- [x] **TASK-5.2: Implement batch setup processing logic**
File: `app/(tabs)/beneficiaries/[id]/setup-wifi.tsx`
Create `processBatchSetup` function:
```typescript
async function processBatchSetup(ssid: string, password: string) {
for (const device of devices) {
updateStatus(device.id, 'connecting');
// 1. Connect BLE
const connected = await bleManager.connectDevice(device.id);
if (!connected) {
updateStatus(device.id, 'error', 'Could not connect');
continue; // Skip to next device
}
// 2. Unlock with PIN
updateStatus(device.id, 'unlocking');
await bleManager.sendCommand(device.id, 'pin|7856');
// 3. Set WiFi
updateStatus(device.id, 'setting_wifi');
await bleManager.setWiFi(device.id, ssid, password);
// 4. Attach to deployment via Legacy API
updateStatus(device.id, 'attaching');
await api.attachDeviceToDeployment(device.wellId, device.mac, deploymentId);
// 5. Reboot
updateStatus(device.id, 'rebooting');
await bleManager.rebootDevice(device.id);
updateStatus(device.id, 'success');
}
}
```
- [x] **TASK-5.3: Add progress UI for batch setup**
File: `app/(tabs)/beneficiaries/[id]/setup-wifi.tsx`
Show progress for each device:
```
Connecting to "Home_Network"...
WP_497_81a14c
✓ Connected
✓ Unlocked
✓ WiFi configured
● Attaching to Maria...
WP_498_82b25d
✓ Connected
○ Waiting...
WP_499_83c36e
○ Pending
```
Use icons: ✓ (success), ● (in progress), ○ (pending), ✗ (error)
---
### Phase 6: Error Handling
- [x] **TASK-6.1: Add error handling UI with retry/skip options**
File: `app/(tabs)/beneficiaries/[id]/setup-wifi.tsx`
When a device fails:
1. Pause batch processing
2. Show error message with device name
3. Show three buttons: [Retry] [Skip] [Cancel All]
4. On Retry: try this device again
5. On Skip: mark as skipped, continue to next device
6. On Cancel All: abort entire process, show results
```tsx
{currentError && (
<View style={styles.errorContainer}>
<Text style={styles.errorTitle}>
Failed: {currentError.deviceName}
</Text>
<Text style={styles.errorMessage}>
{currentError.message}
</Text>
<View style={styles.errorButtons}>
<Button title="Retry" onPress={handleRetry} />
<Button title="Skip" onPress={handleSkip} />
<Button title="Cancel All" onPress={handleCancelAll} />
</View>
</View>
)}
```
- [x] **TASK-6.2: Add results screen after batch setup**
File: `app/(tabs)/beneficiaries/[id]/setup-wifi.tsx`
After all devices processed, show summary:
```
Setup Complete
Successfully connected:
✓ WP_497_81a14c
✓ WP_498_82b25d
Failed:
✗ WP_499_83c36e - Connection timeout
[Retry This Sensor]
Skipped:
⊘ WP_500_84d47f
[Done]
```
"Done" button navigates back to Equipment screen.
---
### Phase 7: API Method for Device Attachment
- [x] **TASK-7.1: Add attachDeviceToDeployment method to api.ts**
File: `services/api.ts`
Add method to register a new device with Legacy API:
```typescript
async attachDeviceToDeployment(
wellId: number,
mac: string,
deploymentId: number,
location?: string,
description?: string
): Promise<{ success: boolean; deviceId?: number; error?: string }>
```
Implementation:
1. Call Legacy API `device_form` with deployment_id set
2. Return device ID from response on success
3. Return error message on failure
This is used during batch setup to link each sensor to the beneficiary's deployment.
---
## Verification Checklist
After all tasks complete, verify:
- [x] Can view sensors list for any beneficiary
- [x] Can scan and find WP_* sensors via BLE
- [x] Can select multiple sensors with checkboxes
- [x] Can configure WiFi for all selected sensors
- [x] Progress UI shows status for each device
- [x] Errors show retry/skip options
- [x] Results screen shows success/failure summary
- [x] Can edit sensor location in Device Settings
- [x] Location placeholder shows in Equipment screen
- [x] Can tap location to go to Device Settings
- [x] Mock BLE works in iOS Simulator
---
## Notes for AI Agent
1. **Read documentation first**: `docs/SENSORS_SYSTEM.md` has full context
2. **Check existing code**: Files may already have partial implementations
3. **BLE Manager**: Use `services/ble/BLEManager.ts` for real device, `MockBLEManager.ts` for simulator
4. **Legacy API auth**: Use `getLegacyCredentials()` method in api.ts
5. **Error handling**: Always wrap BLE operations in try/catch
6. **TypeScript**: Project uses strict TypeScript, ensure proper types
7. **Testing**: Use iOS Simulator with Mock BLE for testing