OptimizerProtocol::getPlanParams(SurplusContext, ContexteFil) rend les params d'une requête GetPlan. Fonction pure, compilée dans le plugin mais appelée par personne : sans endpoint, rien ne change. - La prévision voyage À CÔTÉ du contexte (§11) : ContexteFil::prevision porte la sortie de EnergyArbitrator::instantanePrevision(), l'assemblage partagé avec GetForecastSnapshot. forecastDepuisInstantane() la pose sur la grille §5.2 : Wh par pas → p50W moyens (Wh × 3600 / resolutionS), case sans point = null, pv null sans courbe, weather null. - ContexteFil porte aussi trigger (sa source viendra en T3), meter.source, la PV instantanée, la limite de phase, la réserve, le domaine et la mesure par charge. - Inconnu = null ou absent, jamais 0 : contractedPowerW, pv.currentW, capacité et puissances batterie, tarif → null ; learned, comfort, group, champs réservés, force, powerLevels → absents ; borne configurée sans appareil → ni déclaration ni verrous. - meter.exportW brut (règle 8). Champs 1.0 conservés ; energyTargets dérivés par resolveDeadline (installer) et de la dérogation à cible (user-intent). Tests (loadmodel, logique pure) : 4 goldens dans data/optimizer (site sans PV ; PV + ECS relay-router + borne + SG-Ready ; prévision absente ; charge available=false figée), régénérables sous ETM_REGENERER_GOLDEN=1, plus 3 tests d'assertion. Contre-épreuves : contractedPowerW à 0, Wh non convertis, exportW net → chacune fait échouer au moins un test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
214 lines
5.8 KiB
JSON
214 lines
5.8 KiB
JSON
{
|
|
"battery": {
|
|
"capacityWh": null,
|
|
"maxChargeW": null,
|
|
"maxDischargeW": null,
|
|
"powerW": -800,
|
|
"present": true,
|
|
"reserveSocPercent": 15,
|
|
"socPercent": 62
|
|
},
|
|
"forecast": {
|
|
"baseload": {
|
|
"model": "profile",
|
|
"p50W": [
|
|
420,
|
|
380,
|
|
395,
|
|
450,
|
|
610,
|
|
720
|
|
],
|
|
"quality": {
|
|
"commandedMinutes": 0,
|
|
"computedAt": "2026-10-12T03:00:00Z",
|
|
"daysCovered": {
|
|
"weekend": 6,
|
|
"workday": 14
|
|
},
|
|
"incompleteMinutes": 12,
|
|
"loads": [
|
|
{
|
|
"constantMeasurement": false,
|
|
"loadId": "{0d4c6a7e-2222-4c1a-9a01-000000000002}",
|
|
"minutesBySource": {
|
|
"meter": 28800
|
|
},
|
|
"source": "meter"
|
|
}
|
|
],
|
|
"minDays": 7,
|
|
"minutes": 28800,
|
|
"negativeMinutes": 0,
|
|
"resolutionS": 3600,
|
|
"windowDays": 28
|
|
}
|
|
},
|
|
"price": null,
|
|
"pv": {
|
|
"acLimitW": 8000,
|
|
"contentChangedAt": "2026-10-12T10:07:00Z",
|
|
"conversion": "physics",
|
|
"corrections": [
|
|
"temperature",
|
|
"ac-limit"
|
|
],
|
|
"issuedAt": "2026-10-12T09:00:00Z",
|
|
"p50W": [
|
|
5200,
|
|
4800,
|
|
3900,
|
|
null,
|
|
1500,
|
|
300
|
|
],
|
|
"perField": [
|
|
{
|
|
"corrections": [
|
|
"temperature"
|
|
],
|
|
"id": "{0d4c6a7e-6666-4c1a-9a01-000000000006}"
|
|
}
|
|
],
|
|
"weatherModel": "meteofrance_seamless"
|
|
},
|
|
"resolutionS": 3600,
|
|
"start": "2026-10-12T12:00:00Z",
|
|
"steps": 6,
|
|
"weather": null
|
|
},
|
|
"loads": [
|
|
{
|
|
"adapter": "evcharger",
|
|
"declared": {
|
|
"maxA": 16,
|
|
"maxPowerW": 11040,
|
|
"minA": 6,
|
|
"minPowerW": 4140,
|
|
"phases": 3
|
|
},
|
|
"domain": "ev",
|
|
"id": "{0d4c6a7e-3333-4c1a-9a01-000000000003}",
|
|
"label": "Borne garage",
|
|
"limits": {
|
|
"chargingEnabledLockS": 300,
|
|
"currentChangeLockS": 60
|
|
},
|
|
"needs": {
|
|
"deadline": "2026-10-13T07:00:00+02:00",
|
|
"targetSocPercent": 80
|
|
},
|
|
"priority": 1,
|
|
"telemetry": {
|
|
"available": true,
|
|
"charging": true,
|
|
"currentPowerW": 4100,
|
|
"measurement": {
|
|
"powerW": 4100,
|
|
"source": "device"
|
|
},
|
|
"pluggedIn": true,
|
|
"sessionWh": 5200
|
|
}
|
|
},
|
|
{
|
|
"adapter": "relay-router",
|
|
"declared": {
|
|
"maxPowerW": 2400,
|
|
"minPowerW": 800
|
|
},
|
|
"domain": "ecs",
|
|
"id": "{0d4c6a7e-2222-4c1a-9a01-000000000002}",
|
|
"label": "Chauffe-eau",
|
|
"limits": {
|
|
"minOffS": 300,
|
|
"minOnS": 300
|
|
},
|
|
"needs": {
|
|
"dailyDeadline": "18:00",
|
|
"energyTargets": [
|
|
{
|
|
"by": "2026-10-12T18:00:00+02:00",
|
|
"minWh": 4000,
|
|
"source": "installer"
|
|
},
|
|
{
|
|
"by": "2026-10-12T13:00:00Z",
|
|
"minWh": 3000,
|
|
"source": "user-intent"
|
|
}
|
|
],
|
|
"minEnergyWhPerDay": 4000
|
|
},
|
|
"priority": 2,
|
|
"telemetry": {
|
|
"available": true,
|
|
"currentPowerW": 1600,
|
|
"lockMaxPowerW": -1,
|
|
"lockMinPowerW": 1600,
|
|
"measurement": {
|
|
"powerW": 1580,
|
|
"source": "meter"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"adapter": "sg-ready",
|
|
"declared": {
|
|
"estimatedPowerW": {
|
|
"3": 1800,
|
|
"4": 2600
|
|
},
|
|
"states": [
|
|
1,
|
|
2,
|
|
3,
|
|
4
|
|
]
|
|
},
|
|
"domain": "heating",
|
|
"id": "{0d4c6a7e-4444-4c1a-9a01-000000000004}",
|
|
"label": "PAC",
|
|
"limits": {
|
|
"minStateHoldS": 900
|
|
},
|
|
"priority": 3,
|
|
"telemetry": {
|
|
"available": true,
|
|
"currentPowerW": 0,
|
|
"maxState": 4,
|
|
"measurement": {
|
|
"source": "none"
|
|
},
|
|
"minState": 2,
|
|
"state": 2
|
|
}
|
|
}
|
|
],
|
|
"meter": {
|
|
"exportW": 2310,
|
|
"importW": 0,
|
|
"perPhaseA": [
|
|
3.2,
|
|
4.1,
|
|
2.8
|
|
],
|
|
"source": "{0d4c6a7e-1111-4c1a-9a01-000000000001}"
|
|
},
|
|
"pv": {
|
|
"currentW": 3400
|
|
},
|
|
"site": {
|
|
"contractedPowerW": null,
|
|
"gridCapW": null,
|
|
"phaseLimitA": [
|
|
63,
|
|
63,
|
|
63
|
|
]
|
|
},
|
|
"tariff": null,
|
|
"timestamp": "2026-10-12T13:42:00+02:00",
|
|
"trigger": "load-change"
|
|
}
|