/* ============================================================================ 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, }; 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.' }, ]; 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), 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.
)}