# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

POWERFUN Settings App - A React Native application for managing POWERFUN fitness devices (power meters, paddle sensors, T5 trainers) via Bluetooth LE. Supports device scanning, information reading, calibration, firmware updates (DFU), and spindown calibration.

## Build Commands

```sh
yarn start          # Start Metro bundler
yarn android        # Run on Android
yarn ios            # Run on iOS
yarn build-a        # Android release build (set NODE_OPTIONS=--openssl-legacy-provider)
yarn lint           # Run ESLint
yarn test           # Run Jest tests
yarn clean-a        # Clean Android build (cd android && gradlew clean)
```

## Architecture

### Navigation Structure
- React Navigation Native Stack Navigator
- Entry: SplashScreen → HomeScreen
- Three device paths from HomeScreen: Power Meter, Paddle, T5 Trainer
- Each path: ScanScreen → InfoScreen → DfuScreen
- T5 has additional: SpindownScreen
- Global: SettingScreen, PrivacyScreen

### Screen to File Mapping
| Screen | File | Purpose |
|--------|------|---------|
| HomeScreen | src/HomeScreen.tsx | Device type selection (3 buttons) |
| ScanScreen | src/ScanScreen.tsx | Power meter BLE scanning |
| ScanScreen2 | src/ScanScreen2.tsx | Paddle BLE scanning |
| ScanScreen3 | src/ScanScreen3.tsx | T5 trainer BLE scanning |
| InfoScreen | src/InfoScreen.tsx | Power meter info, real-time data, calibration, power trim |
| InfoScreen2 | src/InfoScreen2.tsx | Paddle boat type settings |
| InfoScreen3 | src/InfoScreen3.tsx | T5 trainer weight, bike type, ERG smoothing |
| DfuScreen | src/DfuScreen.tsx | Nordic DFU firmware upgrade |
| SpindownScreen | src/SpindownScreen.tsx | T5 trainer spindown calibration |
| SettingScreen | src/SettingScreen.tsx | Language, privacy policy |
| PrivacyScreen | src/PrivacyScreen.tsx | Privacy policy content |

### Bluetooth LE Architecture
- Library: `@systemic-games/react-native-bluetooth-le`
- Central API for scanning, connecting, reading/writing characteristics, subscribing to notifications
- Device name prefixes for filtering:
  - Power meters: `PF-PM5-` or `POWERFUN-`
  - Paddles: `PF-STK-` or `POWERFUN-`
  - T5 trainers: `PF-T5-` or `POWERFUN-`
- RSSI filtering: devices below -90 dBm are filtered out

### BLE Service/Characteristic UUIDs
| Service | Characteristic | Purpose |
|---------|----------------|---------|
| fff1 | fff2 (write) | Custom power meter commands |
| fff1 | fff3 (notify) | Custom power meter responses |
| 180a | 2a25 | Serial number |
| 180a | 2a28 | Firmware version |
| 180a | 2a27 | Hardware version |
| 180f | 2a19 | Battery level |
| 1818 | 2a63 | Cycling power measurement (real-time) |

### DFU Architecture
- Library: `@systemic-games/react-native-nordic-nrf5-dfu`
- Firmware manifest: `https://powerfun.oss-cn-shanghai.aliyuncs.com/yecongdfu/latest.json`
- Firmware versions parsed as `hardware.iteration.build` (e.g., "1.23.456")
- Upgrade only allowed when server iteration > device iteration
- Downloads firmware zip to cache, then initiates DFU

### i18n Architecture
- Library: i18next with react-i18next
- Languages: Chinese (zh) and English (en)
- Storage key: `@app_language` in AsyncStorage
- Translation files: `src/i18n/locales/zh.json`, `src/i18n/locales/en.json`

## Key Implementation Notes

### Bluetooth Connection Lifecycle
- InfoScreens connect to device on mount, disconnect on navigation away (except when going to DfuScreen)
- Connection status listener: `Central.addListener("peripheralConnectionStatus", handler)`
- Device ready state: `connectionStatus === "ready"`

### Real-time Data Parsing (Power Meter - 2A63)
- Byte 2-3: Power value (little-endian)
- Byte 4: Left balance (0.5% units)
- Byte 5-6: Cadence revolution count (little-endian)
- Byte 7-8: Cadence timestamp (1/1024 second units)
- Cadence RPM = (revolution_diff / time_in_seconds) * 60

### Power Trim
- Range: 50-200 (represents 50%-200%)
- Stored as: value * 100, sent as 2-byte little-endian
- Protocol: Write [0x02, low, high] to FFF2, then write [0x04] to trigger update

### Calibration
- Command: Write 0x05 to FFF2
- Response: Read from FFF3 notify (0x05 + 2-byte value in 0.1 units)
- Timeout: 5 seconds

### Firmware Version Comparison
```typescript
// Version format: "hardware.iteration.build" (e.g., "1.23.456")
// Only iteration is compared for upgrade decision
// hardware mismatch → cannot upgrade
// server iteration <= device iteration → no upgrade needed
```
