/* ============================================================================ GC · INSTÄLLNINGAR — driftrattarna, hans kortform ---------------------------------------------------------------------------- RÄTTELSE 2026-08-16: den första versionen påstod att alla fyra rattar i hans InstallningarView saknade backend-fält. Fel — tre av fyra finns, under andra namn, och gamla designen har justerat dem sedan 30/7 (settings-mode.jsx): hans "Lägsta säljpris för sol" → sellsolar_min_price_ore (styr även den automatiska solladdningen av bilen — hans fjärde ratt behövs därför inte) hans "Undvik nätköp" → maxprofit_import_aversion_kr (kr; UI öre) hans "Handelsmarginal" → cycle_cost_ore/cycle_cost_kwh, vår "Batterislitage": HEMS handlar bara när vinsten överstiger slitaget per kWh hans "Prisgräns för solladdning" → finns inte som fält, och ska enligt backend 16/8 INTE byggas: säljgolvet ovan styr samma sak i dag. Produkt- beslut hos André. Dessutom har vi två rattar han inte har: "Fyll batteriet tidigt" och "Morgonbuffert". Spann bekräftade av backend 16/8: sellsolar 0–500 öre, maxprofit 0–0,5 kr (visas som 0–50 öre), cycle_cost 0–100 öre default 10. 0 = AV, null = flottans värde — två skilda saker. Prisgränsen för solladdning byggs INTE som egen ratt (André 16/8): säljgolvet ovan styr redan samma sak — under det priset säljs inte solen, den används. Två rattar för ett beslut vore två sanningar. REGLERNA ÄR SPEC_GRAVIO_USER_MODE_UI §3.3 och de är hårda: - null = OJUSTERAD, inte 0. En ojusterad ratt visar flottans värde som ghost och skickas ALDRIG i payloaden. - En ratt som VAR satt och återställs skickas som explicit null. - Master-gaten raderar inga värden när den slås av — backend ignorerar dem. - Batterislitaget är INTE gate-styrt: det gäller alltid. Sparvägen är gcSaveSettings (gc-core): hela dokumentet, settings_rev med, en omläsning vid 409. PATCH /api/settings tar bara ev_session. ========================================================================== */ /* Flottans kalibrerade värden — visas som ghost, skickas aldrig. Samma tal som settings-mode.jsx FLEET_DEFAULTS; ändras de där ska de ändras här. maxprofit visas i öre (backend bär kr). */ const GCI_FLEET = { traj_premie_ore_per_kwh_h: 3, sellsolar_min_price_ore: 30, maxprofit_import_aversion_kr: 25, soc_planning_buffer_pct: 2, soc_buffer_release_ore: 30, }; const GCI_KNOBS = [ { field:'traj_premie_ore_per_kwh_h', label:'Fyll batteriet tidigt', min:0, max:15, step:1, unit:'', gated:true, desc:'Högre värde = batteriet laddas fullt tidigare på dagen som säkerhet mot prognosfel. Lägre = ren prisoptimering, som kan vänta till de billigaste timmarna.' }, { field:'sellsolar_min_price_ore', label:'Lägsta säljpris för sol', min:0, max:500, step:5, unit:'öre', gated:true, desc:'Under detta pris säljs solen aldrig — den går till huset och batteriet i stället. Ratten styr också den automatiska solladdningen av bilen: under gränsen får bilen ta det överskott batteriet inte hinner ta, över den säljs solen. Planerad laddning påverkas inte — har du satt mål och avresa laddas bilen oavsett pris. 0 stänger av automatiken.' }, { field:'maxprofit_import_aversion_kr', label:'Undvik nätköp', min:0, max:50, step:1, unit:'öre', factor:100, gated:true, desc:'Högre värde = batteriet täcker huset i stället för att köpa el, även när en liten handelsvinst går förlorad. Vid höga värden avstår systemet också billiga nattladdningar med liten marginal.' }, { field:'soc_planning_buffer_pct', label:'Morgonbuffert', min:0, max:20, step:1, unit:'%', gated:true, desc:'Extra reserv ovanpå din lägsta batterinivå som kvällens planering sparar till morgonen. Vid midnatt släpps spärren. Är kvällen tydligt dyrare än morgonen kan bufferten släppas redan på kvällen, se Släpp morgonbufferten vid.' }, { field:'soc_buffer_release_ore', label:'Släpp morgonbufferten vid', min:0, max:500, step:1, unit:'öre', gated:true, desc:'Så mycket dyrare kvällen (kl 18–24) måste vara än morgonen därpå (kl 00–09, eller tills solen täcker) för att HEMS ska få använda morgonbufferten redan på kvällen. Avgörs när morgondagens priser kommit, runt kl 13. Nås inte skillnaden hålls bufferten till midnatt som vanligt. Standard 30 öre. Högre värde = bufferten hålls oftare, 0 = släpps så fort kvällen är dyrare.' }, ]; const GCI_ALWAYS = { field:'cycle_cost_ore', label:'Batterislitage', min:0, max:100, step:1, unit:'öre', desc:'Slitage per omsatt kWh. Högre värde gör HEMS mer sparsam med laddcyklerna — den handlar bara när vinsten överstiger slitaget. Det är den ratt som i hans prototyp heter Handelsmarginal.' }; /* Läser backendens settings-dokument. null/saknad = ojusterad. */ function gciRead(s){ const d = s || {}; const num = (v) => (v === null || v === undefined || v === '') ? null : Number(v); const out = { traj_premie_ore_per_kwh_h: num(d.traj_premie_ore_per_kwh_h), sellsolar_min_price_ore: num(d.sellsolar_min_price_ore), maxprofit_import_aversion_kr: d.maxprofit_import_aversion_kr == null ? null : Math.round(Number(d.maxprofit_import_aversion_kr)*100), soc_planning_buffer_pct: num(d.soc_planning_buffer_pct), soc_buffer_release_ore: num(d.soc_buffer_release_ore), cycle_cost_ore: d.cycle_cost_kwh ?? d.cycle_cost_ore ?? 10, }; out.user_mode_enabled = (d.user_mode_enabled === true || d.user_mode_enabled === false) ? d.user_mode_enabled : GCI_KNOBS.some(k => out[k.field] != null); return out; } function GciKnob({ k, value, fleet, onChange, disabled }){ const set = value != null; const shown = set ? value : fleet; return (
{k.desc}
{set && ( )}Värdena styr hur HEMS prioriterar mellan att lagra, sälja och köpa. Gravios standardvärden passar de flesta anläggningar — rör ratten bara om du vill styra åt ett särskilt håll.
HEMS kör flottans inställningar. Dina egna värden ligger kvar och används igen när du byter tillbaka.
)}