Files
adam-acs/.kiro/steering/debug-reclassification.md
T
Kevin L'Hereec bc9ac4f125 fix: state machine timing + reclassification tests
- Fix state machine start timing: don't call start() in startStateMachine,
  let the CPE's first empty body trigger the state machine via continue().
  This ensures GPN is sent at the correct point in the TR-069 session.
- Add unit tests for reclassifyDeviceFromCatalog (10 tests)
- Add unit tests for MainStateMachine transitions and GPN callbacks (11 tests)
- Test both scenarios: Huawei (GPN supported) and Livebox (GPN unsupported + fallback)
- Fix tr069_trace_service test path assertion (config/ → data/)
- Update steering doc with Livebox bootstrap command
2026-06-01 17:31:33 +02:00

198 lines
6.6 KiB
Markdown

# Debug: Reclassification Properties → Parameters
## Contexte du problème
Les paramètres `Device.ManagementServer.PeriodicInformInterval` et `Device.DeviceInfo.ProvisioningCode` apparaissent comme **properties** (read-only) dans l'interface alors qu'ils devraient être des **parameters** (writable).
Le catalogue `config/tr181-catalog.json` les marque bien comme `writable: true`.
La fonction `reclassifyDeviceFromCatalog()` dans `app/services/parameter_writability.ts` est censée les déplacer de properties vers parameters quand `gpnStatus === 'unsupported'`.
Le dernier log de debug montre : `[Reclassify] properties=9, reclassified=0, catalogSize=2953` — la fonction est appelée mais ne reclassifie rien malgré les paths présents dans le catalogue.
## Fichiers impliqués
- `app/services/parameter_writability.ts` — contient `reclassifyDeviceFromCatalog()` et `normalizePath()`
- `app/services/cwmp/device_action_executor.ts` — appelle la reclassification quand GPN échoue
- `app/services/cwmp/main_state_machine.ts` — `CompletedState` appelle aussi la reclassification
- `app/controllers/cwmp_controller.ts` — `handleInform()` appelle la reclassification si `gpnStatus === 'unsupported'`
- `app/domain/device/device.ts` — `updateFromValues()` stocke les nouveaux params comme properties par défaut
- `config/tr181-catalog.json` — référentiel de writabilité TR-181
## Procédure de test complète
### 1. Faire la modification de code
Modifier le fichier concerné, puis vérifier la compilation :
```bash
npx tsc --noEmit
```
### 2. Build et relance Docker
```bash
docker compose build app
docker compose up -d app
```
Attendre que l'app soit healthy :
```bash
docker compose logs app --tail 5
```
### 3. Supprimer le device Sagemcom de l'ACS
```bash
curl -s -X DELETE http://localhost:8080/api/v1/devices/2e933565b8fc09f34f42531e
```
### 4. Supprimer le device du simulateur (home-device-simulator)
```bash
curl -s -X DELETE "http://localhost:9898/api/v1/device-simulator/delete-devices" \
-H 'Content-Type: application/json' \
-d '["F8:B7:FF:00:11:22"]'
```
### 5. Recréer le device dans le simulateur
```bash
curl -s -X PUT "http://localhost:9898/api/v1/device-simulator/create-devices?noOfDevices=1&autoGenerate=false&ipAddressType=ipv4" \
-H 'Content-Type: application/json' \
-d '{
"manufacturer": "Sagemcom",
"oui": "F8B7FF",
"productClass": "Livebox 4",
"serialNumber": "LB4-TEST-001",
"macaddress": "F8:B7:FF:00:11:22",
"parameters": [
{"type": "Manufacturer", "model": "Device.DeviceInfo.Manufacturer", "value": "Sagemcom"},
{"type": "ManufacturerOUI", "model": "Device.DeviceInfo.ManufacturerOUI", "value": "F8B7FF"},
{"type": "ModelName", "model": "Device.DeviceInfo.ModelName", "value": "Livebox 4"},
{"type": "ProductClass", "model": "Device.DeviceInfo.ProductClass", "value": "Livebox 4"},
{"type": "SerialNumber", "model": "Device.DeviceInfo.SerialNumber", "value": "LB4-TEST-001"},
{"type": "HardwareVersion", "model": "Device.DeviceInfo.HardwareVersion", "value": "SR40_sip-fr-4.62.0"},
{"type": "SoftwareVersion", "model": "Device.DeviceInfo.SoftwareVersion", "value": "SR40_sip-fr-4.62.0"}
]
}'
```
### 6. Déclencher le bootstrap Inform
Le simulateur ne fait PAS d'Inform automatiquement après la création. Il faut le déclencher manuellement :
```bash
sleep 3
curl -s -X POST "http://localhost:9898/api/v1/device-simulator/device-request" \
-H 'Content-Type: application/json' \
-d '{"actions":[{"macaddress":"F8:B7:FF:00:11:22","event":{"0":"BOOTSTRAP"}}]}'
```
### 7. Attendre l'Inform (30s max) puis vérifier
```bash
sleep 30
```
Vérifier la classification :
```bash
curl -s "http://localhost:8080/api/v1/devices/2e933565b8fc09f34f42531e" | \
python3 -c "
import sys,json
d=json.load(sys.stdin)
print('gpnStatus:', d.get('gpnStatus'))
props = [p['name'] for p in d.get('properties',[]) if 'PeriodicInform' in p['name'] or 'ProvisioningCode' in p['name']]
params = [p['name'] for p in d.get('parameters',[]) if 'PeriodicInform' in p['name'] or 'ProvisioningCode' in p['name']]
print('Dans properties (MAUVAIS):', props)
print('Dans parameters (BON):', params)
"
```
### 8. Regarder les logs de reclassification
```bash
docker compose logs app --tail 50 2>&1 | grep -i "reclassify\|Reclassify"
```
## Résultat attendu
**Sagemcom Livebox 4** (GPN unsupported, reclassification via catalogue) :
```
gpnStatus: unsupported
properties: 7
parameters: 2 (PeriodicInformInterval + ProvisioningCode)
```
**Huawei BM632w** (GPN supported, classification via GPN response) :
```
gpnStatus: supported
properties: 16
parameters: 15
compliance: compliant
```
## Identifiants du device de test
| Champ | Valeur |
|-------|--------|
| ACS identifier | `2e933565b8fc09f34f42531e` |
| Manufacturer | Sagemcom |
| OUI | F8B7FF |
| Product Class | Livebox 4 |
| Serial Number | LB4-TEST-001 |
| MAC (simulateur) | F8:B7:FF:00:11:22 |
| Data Model | tr-181 |
## Device Huawei (genieacs-sim)
| Champ | Valeur |
|-------|--------|
| ACS identifier | `f9747826c5545b0e49db7967` |
| Manufacturer | Huawei Technologies Co., Ltd. |
| OUI | 202BC1 |
| Product Class | BM632w |
| Serial Number | 000000 |
| Data Model | tr-098 (InternetGatewayDevice.*) |
| Container | `adam-acs-genieacs-sim-1` |
### Procédure de test Huawei
Le Huawei est simulé par le container `genieacs-sim` (défini dans `docker-compose.yml` avec le profile `test`). Il se crée automatiquement au démarrage du container.
**Supprimer le device :**
```bash
docker stop adam-acs-genieacs-sim-1 && docker rm adam-acs-genieacs-sim-1
curl -s -X DELETE http://localhost:8080/api/v1/devices/f9747826c5545b0e49db7967
```
**Recréer le device (relancer le container) :**
```bash
docker compose --profile test up -d genieacs-sim
```
Le container fait un Inform automatiquement au démarrage vers `http://app:8080/cwmp10`.
**Vérifier :**
```bash
sleep 15
curl -s "http://localhost:8080/api/v1/devices/f9747826c5545b0e49db7967" | python3 -c "
import sys,json
d=json.load(sys.stdin)
print('gpnStatus:', d.get('gpnStatus'))
print('dataModel:', d.get('dataModel'))
print('Properties:', len(d.get('properties',[])))
print('Parameters:', len(d.get('parameters',[])))
"
```
- Base URL : `http://localhost:9898/api/v1/device-simulator`
- Swagger : `http://localhost:9898/swagger/`
- Suppression par MAC : `DELETE /delete-devices` body `["MAC"]`
- Création : `PUT /create-devices?noOfDevices=1&autoGenerate=false&ipAddressType=ipv4`
## Trace TR-069
Le device est déjà dans la config de trace (`data/tr069-trace.json` dans le volume Docker `app_tr069_data`). Les logs SOAP sont visibles sur `http://localhost:8080/tr069-trace`.