Le lot plugin B-bis (1.15.2+etm15) est sur .75 et GetLoadConfig/GetLoadTelemetry concordent : les critères 4 à 8 du brief deviennent atteignables. - models/load_telemetry.dart : vue en lecture. timestamp/budget/mechanism/lock/ faultCode nullables — omis porte un sens que zéro ne porterait pas. - services/telemetry_text.dart : rendu français des CODES (19 motifs, 3 défauts, 3 verrous, 4 mécanismes). Repli lisible sur un code inconnu ET sur un code connu privé d'un paramètre : une phrase trouée a l'air d'une donnée, le code brut a l'air de ce qu'il est. - providers/load_telemetry_provider.dart : instantané + LoadTelemetryChanged, fraîcheur à trois signaux (âge du timestamp, silence des trames, timestamp qui cesse d'avancer), machine à états de ClearLoadFault qui ne conclut JAMAIS sur l'acquittement du RPC. - load_config_provider : assignDomain() en brouillon, énumération fermée. - load_order_screen : budget, fraîcheur, mode dégradé, bloc par charge, encart défaut, menu de domaine. - nymea_service : getLoadTelemetry(), clearLoadFault(), aiguillage de la notification. Une box sans la méthode s'annonce comme telle, pas comme en panne. Seuil de fraîcheur à 180 s : le battement de cœur du plugin est de 60 s et le timestamp avance d'un cycle par minute. Un seuil plus court crierait « données anciennes » sur une installation vivante. Fixtures v3 prises sur .75 après déploiement, dont un cycle porteur d'un verrou — « lock » étant optionnel, un dump pris au mauvais moment ne l'éprouverait pas. 57 tests (30 avant), flutter analyze inchangé à 25 issues. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XPUo3RMr8SzK6qbFtfBm8H
153 lines
4.9 KiB
JSON
153 lines
4.9 KiB
JSON
{
|
|
"_source": "JSONRPC.Introspect sur 192.168.1.75, 2026-08-25 — plugin 1.15.2+etm15 (194 méthodes / 101 notifications au total, dont 20/14 pour NymeaEnergy.*).",
|
|
"_note": "nymea rejette toute clé inconnue AVANT le handler (jsonvalidator.cpp:143). Ce que la box déclare fait donc autorité sur ce que l'app a le droit d'envoyer. mechanism, lock, faultCode, budget et timestamp sont OPTIONNELS (o:) — omis, jamais nuls.",
|
|
"GetLoadTelemetry": {
|
|
"description": "Get a snapshot of the arbitration runtime state: surplus budget, per-load allocation, availability, fault code, active lock (seconds remaining), mechanism payload and decision reason. Reason and fault are CODES with numeric params - never human-readable sentences: the client renders them in the user's language. Identical payload to the LoadTelemetryChanged notification. 'timestamp' is the end of the last arbitration cycle and is omitted while no cycle has run yet.",
|
|
"params": {},
|
|
"permissionScope": "PermissionScopeControlThings",
|
|
"returns": {
|
|
"degradedMode": "Bool",
|
|
"loads": [
|
|
{
|
|
"allocatedW": "Double",
|
|
"available": "Bool",
|
|
"decision": {
|
|
"code": "String",
|
|
"params": "Variant"
|
|
},
|
|
"loadId": "String",
|
|
"o:faultCode": "String",
|
|
"o:lock": {
|
|
"kind": "String",
|
|
"remainingS": "Int"
|
|
},
|
|
"o:mechanism": {
|
|
"kind": "String",
|
|
"o:chargingEnabled": "Bool",
|
|
"o:currentA": "Double",
|
|
"o:estimatedPowerW": "Double",
|
|
"o:maxPowerW": "Double",
|
|
"o:maxStageW": "Double",
|
|
"o:percent": "Double",
|
|
"o:phaseCount": "Uint",
|
|
"o:pluggedIn": "Bool",
|
|
"o:setpointW": "Double",
|
|
"o:stageW": "Double",
|
|
"o:state": "Int"
|
|
}
|
|
}
|
|
],
|
|
"o:budget": {
|
|
"allocatedW": "Double",
|
|
"evReservedW": "Double",
|
|
"recreditedW": "Double",
|
|
"remainingW": "Double",
|
|
"surplusW": "Double"
|
|
},
|
|
"o:timestamp": "String"
|
|
}
|
|
},
|
|
"LoadTelemetryChanged": {
|
|
"description": "Emitted whenever the arbitration runtime state changed significantly, and periodically (heartbeat) even when unchanged, so that a frozen arbitrator is detectable by a timestamp that stops advancing. Same payload as GetLoadTelemetry.",
|
|
"params": {
|
|
"degradedMode": "Bool",
|
|
"loads": [
|
|
{
|
|
"allocatedW": "Double",
|
|
"available": "Bool",
|
|
"decision": {
|
|
"code": "String",
|
|
"params": "Variant"
|
|
},
|
|
"loadId": "String",
|
|
"o:faultCode": "String",
|
|
"o:lock": {
|
|
"kind": "String",
|
|
"remainingS": "Int"
|
|
},
|
|
"o:mechanism": {
|
|
"kind": "String",
|
|
"o:chargingEnabled": "Bool",
|
|
"o:currentA": "Double",
|
|
"o:estimatedPowerW": "Double",
|
|
"o:maxPowerW": "Double",
|
|
"o:maxStageW": "Double",
|
|
"o:percent": "Double",
|
|
"o:phaseCount": "Uint",
|
|
"o:pluggedIn": "Bool",
|
|
"o:setpointW": "Double",
|
|
"o:stageW": "Double",
|
|
"o:state": "Int"
|
|
}
|
|
}
|
|
],
|
|
"o:budget": {
|
|
"allocatedW": "Double",
|
|
"evReservedW": "Double",
|
|
"recreditedW": "Double",
|
|
"remainingW": "Double",
|
|
"surplusW": "Double"
|
|
},
|
|
"o:timestamp": "String"
|
|
}
|
|
},
|
|
"ClearLoadFault": {
|
|
"description": "Clear the fault latch of a controllable load (ECS-410). Deliberate operator action: the fault never clears by itself.",
|
|
"params": {
|
|
"loadId": "String"
|
|
},
|
|
"permissionScope": "PermissionScopeControlThings",
|
|
"returns": {
|
|
"energyError": "$ref:EnergyError"
|
|
}
|
|
},
|
|
"SetLoadConfig_params": {
|
|
"loadConfigs": [
|
|
{
|
|
"adapter": "String",
|
|
"enabled": "Bool",
|
|
"id": "String",
|
|
"label": "String",
|
|
"mode": "String",
|
|
"o:domain": "String",
|
|
"o:maxPowerW": "Uint",
|
|
"o:minOffS": "Uint",
|
|
"o:minOnS": "Uint",
|
|
"o:needs": {
|
|
"o:dailyDeadline": "String",
|
|
"o:minEnergyWhPerDay": "Uint"
|
|
},
|
|
"o:powerLevels": [
|
|
"Uint"
|
|
],
|
|
"o:relays": [
|
|
{
|
|
"powerW": "Uint",
|
|
"thingId": "String"
|
|
}
|
|
],
|
|
"o:sgReady": {
|
|
"o:minStateHoldS": "Uint",
|
|
"o:states": [
|
|
{
|
|
"estimatedPowerW": "Double",
|
|
"relays": [
|
|
"String"
|
|
],
|
|
"state": "Uint"
|
|
}
|
|
]
|
|
},
|
|
"priority": "Uint"
|
|
}
|
|
]
|
|
},
|
|
"LoadConfigChanged": {
|
|
"description": "Emitted whenever the controllable load configuration changed.",
|
|
"params": {
|
|
"loadConfigs": [
|
|
"$ref:LoadConfig"
|
|
]
|
|
}
|
|
}
|
|
} |