Add setup workflow controls to web UI
This commit is contained in:
@@ -169,6 +169,50 @@ input{width:100%;border:1px solid var(--line);border-radius:12px;padding:12px;ba
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">Device Config</div>
|
||||
<div class="list">
|
||||
<input id="deviceNameInput" placeholder="Device name">
|
||||
<button onclick="saveDeviceConfig()">Save Device Name</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">BMS Config</div>
|
||||
<div class="sub">Use this for initial setup, bench mode, or replacing the battery/BMS.</div>
|
||||
<div class="list">
|
||||
<input id="bmsNameInput" placeholder="BMS name">
|
||||
<input id="bmsAddressInput" placeholder="BMS BLE address">
|
||||
<input id="bmsAddressTypeInput" placeholder="Address type: public or random">
|
||||
<div class="btnrow">
|
||||
<button onclick="saveBmsFullConfig()">Save BMS</button>
|
||||
<button class="off" onclick="setBmsEnabled(false)">Disable BMS</button>
|
||||
</div>
|
||||
<div class="btnrow">
|
||||
<button onclick="setBmsEnabled(true)">Enable BMS</button>
|
||||
<button onclick="reconnectBms()">Reconnect BMS</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">Temperature Assignment</div>
|
||||
<div class="sub">Scan probes, then assign a discovered sensor to a configured temp slot.</div>
|
||||
<div class="list">
|
||||
<button onclick="scanTemps()">Scan Temp Probes</button>
|
||||
<div id="tempScanResults" class="list"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">System Actions</div>
|
||||
<div class="sub">Use carefully. Factory reset clears install-specific configuration.</div>
|
||||
<div class="btnrow">
|
||||
<button onclick="restartController()">Restart</button>
|
||||
<button class="off" onclick="factoryReset()">Factory Reset</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">System</div>
|
||||
<div class="row"><span class="muted">Firmware</span><span class="v" id="fw">--</span></div>
|
||||
@@ -215,6 +259,7 @@ async function relay(id,on){
|
||||
await load();
|
||||
}
|
||||
function render(data){
|
||||
window.lastStatus=data;
|
||||
$("conn").textContent="Live";
|
||||
$("conn").className="pill good";
|
||||
$("device").textContent=data.config?.device_name||"Overland Controller";
|
||||
@@ -274,6 +319,123 @@ function render(data){
|
||||
$("fw").textContent=(s.firmware_name||"--")+" "+(s.firmware_version||"");
|
||||
$("uptime").textContent=(s.uptime_seconds||0)+" sec";
|
||||
renderConfigControls(data);
|
||||
populateSetupFields(data);
|
||||
}
|
||||
|
||||
|
||||
function populateSetupFields(data){
|
||||
const cfg=data.config||{};
|
||||
if($("deviceNameInput")) $("deviceNameInput").value=cfg.device_name||"";
|
||||
|
||||
const bms=cfg.bms||{};
|
||||
if($("bmsNameInput")) $("bmsNameInput").value=bms.name||"";
|
||||
if($("bmsAddressInput")) $("bmsAddressInput").value=bms.address||"";
|
||||
if($("bmsAddressTypeInput")) $("bmsAddressTypeInput").value=bms.address_type||"public";
|
||||
}
|
||||
|
||||
async function saveDeviceConfig(){
|
||||
const name=$("deviceNameInput")?.value.trim();
|
||||
if(!name){ alert("Device name is required"); return; }
|
||||
|
||||
await fetch("/config/device",{
|
||||
method:"POST",
|
||||
headers:{"Content-Type":"application/json"},
|
||||
body:JSON.stringify({device_name:name})
|
||||
});
|
||||
|
||||
await fetch("/config/save",{method:"POST"});
|
||||
await load();
|
||||
alert("Device name saved");
|
||||
}
|
||||
|
||||
async function saveBmsFullConfig(){
|
||||
const name=$("bmsNameInput")?.value.trim()||"BMS";
|
||||
const address=$("bmsAddressInput")?.value.trim()||"";
|
||||
let address_type=($("bmsAddressTypeInput")?.value.trim()||"public").toLowerCase();
|
||||
|
||||
if(address_type!=="public" && address_type!=="random"){
|
||||
alert("Address type must be public or random");
|
||||
return;
|
||||
}
|
||||
|
||||
await fetch("/config/bms",{
|
||||
method:"POST",
|
||||
headers:{"Content-Type":"application/json"},
|
||||
body:JSON.stringify({
|
||||
enabled:true,
|
||||
name:name,
|
||||
address:address,
|
||||
address_type:address_type
|
||||
})
|
||||
});
|
||||
|
||||
await fetch("/config/save",{method:"POST"});
|
||||
await reconnectBms(false);
|
||||
await load();
|
||||
alert("BMS config saved");
|
||||
}
|
||||
|
||||
async function reconnectBms(showAlert=true){
|
||||
await fetch("/bms/reconnect",{method:"POST"});
|
||||
if(showAlert) alert("BMS reconnect requested");
|
||||
}
|
||||
|
||||
async function scanTemps(){
|
||||
const box=$("tempScanResults");
|
||||
if(box) box.innerHTML=`<div class="item"><span>Scanning...</span><strong class="muted">wait</strong></div>`;
|
||||
|
||||
const r=await fetch("/temps/scan",{method:"POST"});
|
||||
const d=await r.json();
|
||||
const devices=d.devices||[];
|
||||
|
||||
if(!box) return;
|
||||
|
||||
if(!devices.length){
|
||||
box.innerHTML=`<div class="item"><span>No probes found</span><strong class="bad">0</strong></div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
const cfg=window.lastStatus?.config||{};
|
||||
const temps=cfg.temperature_sensors||[];
|
||||
|
||||
box.innerHTML=devices.map(dev=>`
|
||||
<div class="item" style="display:block">
|
||||
<div style="display:flex;justify-content:space-between;gap:8px">
|
||||
<span>${dev.address}</span>
|
||||
<strong>#${dev.index}</strong>
|
||||
</div>
|
||||
<div class="btnrow">
|
||||
${temps.slice(0,4).map((t,i)=>`
|
||||
<button onclick="assignTemp('${t.id}',${dev.index})">${t.name||t.id}</button>
|
||||
`).join("")}
|
||||
</div>
|
||||
</div>`).join("");
|
||||
}
|
||||
|
||||
async function assignTemp(id,index){
|
||||
await fetch("/temps/assign",{
|
||||
method:"POST",
|
||||
headers:{"Content-Type":"application/json"},
|
||||
body:JSON.stringify({id:id,index:index})
|
||||
});
|
||||
|
||||
await fetch("/config/save",{method:"POST"});
|
||||
await load();
|
||||
alert("Temp probe assigned to "+id);
|
||||
}
|
||||
|
||||
async function restartController(){
|
||||
if(!confirm("Restart the controller now?")) return;
|
||||
await fetch("/system/restart",{method:"POST"});
|
||||
alert("Restart requested");
|
||||
}
|
||||
|
||||
async function factoryReset(){
|
||||
if(!confirm("Factory reset all controller configuration?")) return;
|
||||
if(!confirm("This clears WiFi/BMS/relay/temp config. Continue?")) return;
|
||||
|
||||
await fetch("/config/factory-reset",{method:"POST"});
|
||||
alert("Factory reset requested. Reconnect to the controller AP if needed.");
|
||||
}
|
||||
|
||||
function renderConfigControls(data){
|
||||
|
||||
Reference in New Issue
Block a user