Spaces:
Running
Running
fix(console): adapt same-origin harvest/posture schema + raise feed timeouts (real grid data paints)
Browse filesHARDEN-DEEP gap-closer. Same-origin posture returns operator-native shape; added adapter mapping REAL measured readings into rendered fields (no fabrication). Raised posture timeout 2000->8000ms, thermal 1500->6000ms. Byte-identical to GitHub blob fa837d37822d796f83d7d04ee782bdbf9f8f6eab. Sign-off Stephen Lutar <stephenlutar2@gmail.com>
- pages/console.html +27 -2
pages/console.html
CHANGED
|
@@ -14512,7 +14512,7 @@ window.warboard_init=warboard_init; window.warboard_all=warboard_all;
|
|
| 14512 |
async function ehThermalPanel(){
|
| 14513 |
var deployed=false, status='in-deployment', detail='';
|
| 14514 |
try{
|
| 14515 |
-
var _c=new AbortController(); var _t=setTimeout(function(){try{_c.abort();}catch(e){}},
|
| 14516 |
var r=await fetch(EH_API.replace(/\/harvest$/,'')+"/pinn/thermal",{cache:"no-store",signal:_c.signal}).finally(function(){clearTimeout(_t);});
|
| 14517 |
if(r&&r.ok){ deployed=true; status='live'; try{var j=await r.json(); if(j&&j.modeled_not_measured!=null) detail='endpoint reports modeled_not_measured='+esc(j.modeled_not_measured);}catch(e){} }
|
| 14518 |
}catch(e){ /* endpoint not deployed yet — honest degradation, no fabrication */ }
|
|
@@ -14543,10 +14543,35 @@ window.warboard_init=warboard_init; window.warboard_all=warboard_all;
|
|
| 14543 |
the tab — it degrades to an honest "unavailable" state, never fabricated. */
|
| 14544 |
c.innerHTML='<div class="card">'+(window.skelRows?window.skelRows(4):'<div class="dim">reading live grid feeds…</div>')+'</div>';
|
| 14545 |
try{
|
| 14546 |
-
var _ctl=new AbortController(); var _t=setTimeout(function(){try{_ctl.abort();}catch(e){}},
|
| 14547 |
var r=await fetch(EH_API+"/posture",{cache:"no-store",signal:_ctl.signal}).finally(function(){clearTimeout(_t);});
|
| 14548 |
if(!r.ok) throw new Error("HTTP "+r.status);
|
| 14549 |
var d=await r.json();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14550 |
var p=EH_POS[d.grid_price_posture]||EH_POS.unknown;
|
| 14551 |
var soak=d.wasted_energy_available;
|
| 14552 |
var h='';
|
|
|
|
| 14512 |
async function ehThermalPanel(){
|
| 14513 |
var deployed=false, status='in-deployment', detail='';
|
| 14514 |
try{
|
| 14515 |
+
var _c=new AbortController(); var _t=setTimeout(function(){try{_c.abort();}catch(e){}},6000);
|
| 14516 |
var r=await fetch(EH_API.replace(/\/harvest$/,'')+"/pinn/thermal",{cache:"no-store",signal:_c.signal}).finally(function(){clearTimeout(_t);});
|
| 14517 |
if(r&&r.ok){ deployed=true; status='live'; try{var j=await r.json(); if(j&&j.modeled_not_measured!=null) detail='endpoint reports modeled_not_measured='+esc(j.modeled_not_measured);}catch(e){} }
|
| 14518 |
}catch(e){ /* endpoint not deployed yet — honest degradation, no fabrication */ }
|
|
|
|
| 14543 |
the tab — it degrades to an honest "unavailable" state, never fabricated. */
|
| 14544 |
c.innerHTML='<div class="card">'+(window.skelRows?window.skelRows(4):'<div class="dim">reading live grid feeds…</div>')+'</div>';
|
| 14545 |
try{
|
| 14546 |
+
var _ctl=new AbortController(); var _t=setTimeout(function(){try{_ctl.abort();}catch(e){}},8000);
|
| 14547 |
var r=await fetch(EH_API+"/posture",{cache:"no-store",signal:_ctl.signal}).finally(function(){clearTimeout(_t);});
|
| 14548 |
if(!r.ok) throw new Error("HTTP "+r.status);
|
| 14549 |
var d=await r.json();
|
| 14550 |
+
/* same-origin-schema-adapter: the same-origin /api/a11oy/v1/harvest/posture returns
|
| 14551 |
+
the operator-native shape (posture/readings[]/drivers[]) rather than the legacy
|
| 14552 |
+
grid_price_posture shape. Normalize it into the fields this panel renders using
|
| 14553 |
+
ONLY the REAL measured readings (no fabrication). If the response already carries
|
| 14554 |
+
grid_price_posture (legacy shape) this block is a no-op. */
|
| 14555 |
+
if(d&&d.grid_price_posture==null&&Array.isArray(d.readings)){
|
| 14556 |
+
var _find=function(f){for(var i=0;i<d.readings.length;i++){if(d.readings[i].feed===f)return d.readings[i];}return null;};
|
| 14557 |
+
var _aw=_find('awattar_de'), _ren=_find('energy_charts_ren_share'), _uk=_find('uk_carbon_intensity');
|
| 14558 |
+
var _live=0,_tot=0; d.readings.forEach(function(x){_tot++; if(x.reachable&&x.measured)_live++;});
|
| 14559 |
+
var _minNext=null,_negWin=null;
|
| 14560 |
+
if(_aw&&_aw.note){ var m1=/min_next=(-?[0-9.]+)/.exec(_aw.note); if(m1)_minNext=parseFloat(m1[1]); var m2=/neg_windows=([0-9]+)\/[0-9]+/.exec(_aw.note); if(m2)_negWin=parseInt(m2[1],10); }
|
| 14561 |
+
var _ukIdx=null; if(_uk&&_uk.note){ var m3=/index=([a-z]+)/i.exec(_uk.note); if(m3)_ukIdx=m3[1]; }
|
| 14562 |
+
d.grid_price_posture=d.posture||'unknown';
|
| 14563 |
+
d.price_now_eur_mwh=(_aw&&_aw.value!=null)?_aw.value:null;
|
| 14564 |
+
d.next_min_eur_mwh=_minNext;
|
| 14565 |
+
d.next_negative_windows=_negWin;
|
| 14566 |
+
d.next_window_negative=(_negWin!=null&&_negWin>0);
|
| 14567 |
+
d.renewable_share_pct=(_ren&&_ren.value!=null)?_ren.value:null;
|
| 14568 |
+
d.uk_gco2_per_kwh=(_uk&&_uk.value!=null)?_uk.value:null;
|
| 14569 |
+
d.uk_carbon_index=_ukIdx;
|
| 14570 |
+
d.feeds_live=_live; d.feeds_total=_tot;
|
| 14571 |
+
if(d.ts==null&&d.timestamp_utc){ var _t2=Date.parse(d.timestamp_utc); if(!isNaN(_t2)) d.ts=_t2/1000; }
|
| 14572 |
+
if(d.cached==null) d.cached=false;
|
| 14573 |
+
if(!d.honesty) d.honesty=(d.doctrine||'')+(d.citation?(' Source: '+d.citation):'');
|
| 14574 |
+
}
|
| 14575 |
var p=EH_POS[d.grid_price_posture]||EH_POS.unknown;
|
| 14576 |
var soak=d.wasted_energy_available;
|
| 14577 |
var h='';
|