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

6.6 KiB

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 :

npx tsc --noEmit

2. Build et relance Docker

docker compose build app
docker compose up -d app

Attendre que l'app soit healthy :

docker compose logs app --tail 5

3. Supprimer le device Sagemcom de l'ACS

curl -s -X DELETE http://localhost:8080/api/v1/devices/2e933565b8fc09f34f42531e

4. Supprimer le device du simulateur (home-device-simulator)

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

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 :

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

sleep 30

Vérifier la classification :

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

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 :

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) :

docker compose --profile test up -d genieacs-sim

Le container fait un Inform automatiquement au démarrage vers http://app:8080/cwmp10.

Vérifier :

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.