ACE Auto Refill toggle feature

This commit is contained in:
Gangoke
2026-05-17 22:36:42 -10:00
parent 8c4bff6b86
commit 70b70b1d98

View File

@@ -453,6 +453,7 @@ class KobraXBridge:
self._ams_loaded_slot: int = -1 # global slot index of currently loaded slot
self._pending_load_slot: int = -1 # global slot index requested via /api/ams/feed type=1
self._ace_box_ids: list[int] = [] # detected ACE unit IDs (0..3)
self._ace_auto_feed: dict[int, int] = {} # per-box auto_feed state (0/1)
self._head_tools_model: int = -1
self._filament_mode: str = "toolhead"
self._last_uploaded_file: str = ""
@@ -821,6 +822,10 @@ class KobraXBridge:
global_slots, global_loaded = self._aggregate_slots(boxes, self._filament_mode)
self._ams_loaded_slot = global_loaded
self._update_ace_drying_state(data, boxes)
for box in boxes:
bid = int(box.get("id", -1))
if 0 <= bid <= 3 and "auto_feed" in box:
self._ace_auto_feed[bid] = int(box["auto_feed"])
if self._pending_load_slot >= 0 and global_loaded == self._pending_load_slot:
self._pending_load_slot = -1
activity_map = self._slot_activity_map(boxes, global_loaded)
@@ -3218,7 +3223,11 @@ function applyState(){
if(!show)continue;
var ud=unitMap[i]||dry;
var refillToggle=document.getElementById('ace-auto-refill-toggle-'+i);
if(refillToggle)refillToggle.checked=_aceAutoRefillGet(i);
var autoFeedMap=s.ace_auto_feed||{};
if(refillToggle&&!_aceAutoFeedPending[i]){
var afVal=autoFeedMap.hasOwnProperty(String(i))?Number(autoFeedMap[String(i)]):(_aceAutoRefillGet(i)?1:0);
refillToggle.checked=afVal===1;
}
var dryToggle=document.getElementById('ace-dry-enable-toggle-'+i);
if(dryToggle)dryToggle.checked=Number(ud.status||0)>0;
var hh=document.getElementById('d-ace-dry-humidity-'+i);
@@ -3755,11 +3764,19 @@ function aceDryStart(aceId){
.catch(function(e){clog('ACE-Fehler: '+e,'msg-err');});
}
var _aceAutoFeedPending={};
function aceAutoRefillToggle(aceId){
aceId=(typeof aceId==='number'&&aceId>=0)?aceId:0;
var on=!!((document.getElementById('ace-auto-refill-toggle-'+aceId)||{}).checked);
_aceAutoRefillSet(aceId,on);
clog('ACE '+(aceId+1)+' - '+(T.ace_dry_auto_refill||'Auto Refill')+': '+(on?'ON':'OFF')+' '+(T.ace_dry_ui_pending||'(UI only, backend next)'),'msg-info');
_aceAutoFeedPending[aceId]=true;
fetch('/api/ace/auto_feed',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({ace_id:aceId,on:on?1:0})})
.then(function(r){return r.json();})
.then(function(d){
delete _aceAutoFeedPending[aceId];
if(d.error){clog('Auto Refill error: '+d.error,'msg-err');var t=document.getElementById('ace-auto-refill-toggle-'+aceId);if(t)t.checked=!on;return;}
clog('ACE '+(aceId+1)+' - '+(T.ace_dry_auto_refill||'Auto Refill')+': '+(on?'ON':'OFF'),'msg-ok');
})
.catch(function(e){delete _aceAutoFeedPending[aceId];clog('Auto Refill error: '+e,'msg-err');var t=document.getElementById('ace-auto-refill-toggle-'+aceId);if(t)t.checked=!on;});
}
function openAceDryDialog(aceId){
@@ -4764,6 +4781,36 @@ function loadPrinterTab(){
await loop.run_in_executor(None, _send)
return web.json_response({"result": "ok"})
async def handle_api_ace_auto_feed(self, request):
try:
body = await request.json()
except Exception:
body = {}
ace_id_raw = body.get("ace_id", None)
on_raw = body.get("on", None)
if ace_id_raw is None or on_raw is None:
return web.json_response({"error": "ace_id and on are required"}, status=400)
try:
ace_id = int(ace_id_raw)
on = int(bool(on_raw))
except Exception:
return web.json_response({"error": "invalid parameters"}, status=400)
if not (0 <= ace_id <= 3):
return web.json_response({"error": "ace_id must be 0-3"}, status=400)
payload = {"multi_color_box": [{"id": ace_id, "auto_feed": on}]}
loop = asyncio.get_event_loop()
# Fire-and-forget: setAutoFeed ACK arrives via multiColorBox/report callback.
# Waiting for a response on that busy push topic causes false "code:0" rejections.
await loop.run_in_executor(
None,
lambda: self.client.publish("multiColorBox", "setAutoFeed", payload, timeout=0)
)
self._ace_auto_feed[ace_id] = on
self._state_dirty = True
return web.json_response({"result": "ok", "ace_id": ace_id, "auto_feed": on})
async def handle_api_ace_dry(self, request):
try:
body = await request.json()
@@ -5087,6 +5134,7 @@ function loadPrinterTab(){
"filament_mode": s.get("filament_mode", self._filament_mode),
"ace_drying": s.get("ace_drying", {"status": 0, "target_temp": 0, "duration": 0, "remain_time": 0, "humidity": None, "current_temp": None}),
"ace_units": list(self._ace_box_ids),
"ace_auto_feed": dict(self._ace_auto_feed),
"ace_dry_presets": self._ace_dry_presets,
"thumbnail": self._thumbnail_b64,
"connection_error": s["connection_error"],
@@ -5822,6 +5870,7 @@ def build_app(bridge: KobraXBridge) -> web.Application:
r.add_post("/api/speed", bridge.handle_api_speed)
r.add_post("/api/ams/feed", bridge.handle_api_ams_feed)
r.add_post("/api/ams/set_slot", bridge.handle_api_ams_set_slot)
r.add_post("/api/ace/auto_feed", bridge.handle_api_ace_auto_feed)
r.add_post("/api/ace/dry", bridge.handle_api_ace_dry)
r.add_post("/api/axis", bridge.handle_api_axis)
r.add_post("/api/temperature", bridge.handle_api_temperature)