ok maybe
This commit is contained in:
1 parent
ea73e91aa4
commit
a5b3135396
4 files changed
+154
-1
No files matched your search
@@ -0,0 +1,137 @@
|
||||
# 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. 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)
|
||||
"
|
||||
```
|
||||
|
||||
### 7. Regarder les logs de reclassification
|
||||
|
||||
```bash
|
||||
docker compose logs app --tail 50 2>&1 | grep -i "reclassify\|Reclassify"
|
||||
```
|
||||
|
||||
## Résultat attendu
|
||||
|
||||
```
|
||||
gpnStatus: unsupported
|
||||
Dans properties (MAUVAIS): []
|
||||
Dans parameters (BON): ['Device.ManagementServer.PeriodicInformInterval', 'Device.DeviceInfo.ProvisioningCode']
|
||||
```
|
||||
|
||||
## 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 |
|
||||
|
||||
## API du simulateur
|
||||
|
||||
- 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`.
|
||||
@@ -108,7 +108,8 @@ export class ConfigurationEvaluationState {
|
||||
)
|
||||
return { response }
|
||||
} else if (this.inventoryQueue.length > 0) {
|
||||
// GPN unsupported — clear inventory queue and skip to next phase
|
||||
// GPN unsupported — skip inventory (GPV on object paths also fails on most simulators)
|
||||
// Parameters will be discovered via Inform values and SPV responses
|
||||
logger.debug({ identifier: context.device.identifier, skipped: this.inventoryQueue.length }, '[ConfigEval] Skipping inventory (GPN unsupported)')
|
||||
this.inventoryQueue = []
|
||||
}
|
||||
|
||||
@@ -98,6 +98,9 @@ export class DeviceActionExecutor {
|
||||
const list = resp?.ParameterList?.ParameterValueStruct
|
||||
if (Array.isArray(list) && list.length > 0) {
|
||||
device.updateFromValues(list)
|
||||
if (device.gpnStatus === 'unsupported') {
|
||||
reclassifyDeviceFromCatalog(device)
|
||||
}
|
||||
await this.persistDevice(device)
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -235,6 +238,9 @@ export class DeviceActionExecutor {
|
||||
async (result: TaskResult) => {
|
||||
if (result.status === ResultStatus.Success) {
|
||||
device.updateFromValues(pvStructs as any)
|
||||
if (device.gpnStatus === 'unsupported') {
|
||||
reclassifyDeviceFromCatalog(device)
|
||||
}
|
||||
await this.persistDevice(device)
|
||||
return await callback(true)
|
||||
}
|
||||
@@ -396,6 +402,9 @@ export class DeviceActionExecutor {
|
||||
async (result: TaskResult) => {
|
||||
if (result.status === ResultStatus.Success) {
|
||||
device.updateFromValues(pvStructs as any)
|
||||
if (device.gpnStatus === 'unsupported') {
|
||||
reclassifyDeviceFromCatalog(device)
|
||||
}
|
||||
await this.persistDevice(device)
|
||||
device.tmpPC = ''
|
||||
return await callback(true)
|
||||
|
||||
@@ -8,6 +8,7 @@ import CommandModel from '../../models/command.js'
|
||||
import { ModeType } from '../../domain/shared/mode.js'
|
||||
import logger from '@adonisjs/core/services/logger'
|
||||
import { ConfigurationEvaluationState } from './configuration_evaluation_state.js'
|
||||
import { reclassifyDeviceFromCatalog } from '../parameter_writability.js'
|
||||
|
||||
// ─── Interfaces ────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -277,6 +278,11 @@ class CompletedState extends DeviceState {
|
||||
name = 'completed'
|
||||
|
||||
async handle(context: DeviceContext): Promise<DeviceStateResult> {
|
||||
// Reclassify properties → parameters if GPN is unsupported
|
||||
if (context.device.gpnStatus === 'unsupported') {
|
||||
reclassifyDeviceFromCatalog(context.device)
|
||||
}
|
||||
|
||||
// Persist device on completion
|
||||
try {
|
||||
const snapshot = context.device.toSnapshot()
|
||||
|
||||
Reference in new issue
Block a user