feat: Add VisionData panel, HW error display, and reel handler 3D model
- Add hardware error banner with priority system (motion > i/o > emergency) - Add DIO status to HW status display with backend integration - Remove status text from HW status, keep only LED indicators - Add VisionDataPanel showing real-time recognized data for L/C/R ports - Add GetVisionData API in MachineBridge with batch field support - Add BroadcastVisionData function (250ms interval) - Replace 3D model with detailed reel handler equipment - Use OrthographicCamera with front view for distortion-free display - Fix ProcessedDataPanel layout to avoid right sidebar overlap - Show log viewer filename in error message when file not found 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -277,6 +277,7 @@ namespace Project.Dialog
|
||||
{
|
||||
_hwUpdateCounter = 0;
|
||||
BroadcastHWStatus();
|
||||
BroadcastVisionData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,6 +312,37 @@ namespace Project.Dialog
|
||||
}
|
||||
}
|
||||
|
||||
// Vision Data 브로드캐스트 (listView21과 동일한 데이터)
|
||||
private void BroadcastVisionData()
|
||||
{
|
||||
try
|
||||
{
|
||||
var bridge = new WebUI.MachineBridge(this);
|
||||
string visionDataJson = bridge.GetVisionData();
|
||||
|
||||
var payload = new
|
||||
{
|
||||
type = "VISION_DATA_UPDATE",
|
||||
data = JsonConvert.DeserializeObject(visionDataJson)
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(payload);
|
||||
|
||||
// WebView2로 전송
|
||||
if (webView != null && webView.CoreWebView2 != null)
|
||||
{
|
||||
webView.CoreWebView2.PostWebMessageAsJson(json);
|
||||
}
|
||||
|
||||
// WebSocket으로 전송
|
||||
_wsServer?.Broadcast(json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[fWebView] Vision data broadcast error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private List<object> GetChangedIOs()
|
||||
{
|
||||
var list = new List<object>();
|
||||
|
||||
@@ -1367,7 +1367,7 @@ namespace Project.WebUI
|
||||
var exename = AR.UTIL.MakePath("LogView.exe");
|
||||
if (System.IO.File.Exists(exename) == false)
|
||||
{
|
||||
var response = new { success = false, message = "Log viewer file not found\nPlease contact support" };
|
||||
var response = new { success = false, message = $"Log viewer file not found\n{exename}\nPlease contact support" };
|
||||
return JsonConvert.SerializeObject(response);
|
||||
}
|
||||
|
||||
@@ -2221,7 +2221,15 @@ namespace Project.WebUI
|
||||
hwList.Add(new { name = "PLC", title = "SET", status = 0 });
|
||||
}
|
||||
|
||||
// 9. Motion
|
||||
// 9. DIO (Digital I/O)
|
||||
hwList.Add(new
|
||||
{
|
||||
name = "DIO",
|
||||
title = PUB.dio?.IsInit == true ? "ON" : "OFF",
|
||||
status = PUB.dio?.IsInit == true ? 1 : 3
|
||||
});
|
||||
|
||||
// 10. Motion
|
||||
hwList.Add(new
|
||||
{
|
||||
name = "MOT",
|
||||
@@ -2238,6 +2246,100 @@ namespace Project.WebUI
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 실시간 인식 데이터 조회 (listView21과 동일한 데이터)
|
||||
/// Left/Center/Right 포트의 VisionData 정보
|
||||
/// </summary>
|
||||
public string GetVisionData()
|
||||
{
|
||||
try
|
||||
{
|
||||
var visdataL = PUB.Result.ItemDataL?.VisionData;
|
||||
var visdataC = PUB.Result.ItemDataC?.VisionData;
|
||||
var visdataR = PUB.Result.ItemDataR?.VisionData;
|
||||
|
||||
var result = new
|
||||
{
|
||||
left = new
|
||||
{
|
||||
cartSize = DIO.getCartSize(0).ToString(),
|
||||
enabled = PUB.flag.get(eVarBool.FG_ENABLE_LEFT),
|
||||
rid = visdataL?.RID ?? "",
|
||||
sid = visdataL?.SID ?? "",
|
||||
qty = visdataL?.QTY ?? "",
|
||||
vname = visdataL?.VNAME ?? "",
|
||||
vlot = visdataL?.VLOT ?? "",
|
||||
mfgdate = visdataL?.MFGDATE ?? "",
|
||||
partno = visdataL?.PARTNO ?? "",
|
||||
reelSize = visdataL?.ReelSize.ToString() ?? "--",
|
||||
batch = visdataL?.BATCH ?? "",
|
||||
rid2 = visdataL?.RID2 ?? "",
|
||||
sid2 = visdataL?.SID2 ?? "",
|
||||
qty2 = visdataL?.QTY2 ?? "",
|
||||
vname2 = visdataL?.VNAME2 ?? "",
|
||||
vlot2 = visdataL?.VLOT2 ?? "",
|
||||
mfgdate2 = visdataL?.MFGDATE2 ?? "",
|
||||
partno2 = visdataL?.PARTNO2 ?? ""
|
||||
},
|
||||
center = new
|
||||
{
|
||||
cartSize = DIO.getCartSize(1).ToString(),
|
||||
confirm = visdataC?.Confirm ?? false,
|
||||
rid = visdataC?.RID ?? "",
|
||||
rid_trust = visdataC?.RID_Trust ?? false,
|
||||
rid_new = visdataC?.RIDNew ?? false,
|
||||
sid = visdataC?.SID ?? "",
|
||||
sid0 = visdataC?.SID0 ?? "",
|
||||
sid_trust = visdataC?.SID_Trust ?? false,
|
||||
qty = visdataC?.QTY ?? "",
|
||||
qty_trust = visdataC?.QTY_Trust ?? false,
|
||||
qty_rq = visdataC?.QTYRQ ?? false,
|
||||
vname = visdataC?.VNAME ?? "",
|
||||
vname_trust = visdataC?.VNAME_Trust ?? false,
|
||||
vlot = visdataC?.VLOT ?? "",
|
||||
vlot_trust = visdataC?.VLOT_Trust ?? false,
|
||||
mfgdate = visdataC?.MFGDATE ?? "",
|
||||
mfgdate_trust = visdataC?.MFGDATE_Trust ?? false,
|
||||
partno = visdataC?.PARTNO ?? "",
|
||||
partno_trust = visdataC?.PARTNO_Trust ?? false,
|
||||
reelSize = visdataC?.ReelSize.ToString() ?? "--",
|
||||
batch = visdataC?.BATCH ?? "",
|
||||
qtymax = visdataC?.QTYMAX ?? "",
|
||||
barcodeCount = visdataC?.barcodelist?.Count ?? 0,
|
||||
regexCount = PUB.Result.BCDPattern?.Count ?? 0
|
||||
},
|
||||
right = new
|
||||
{
|
||||
cartSize = DIO.getCartSize(2).ToString(),
|
||||
enabled = PUB.flag.get(eVarBool.FG_ENABLE_RIGHT),
|
||||
rid = visdataR?.RID ?? "",
|
||||
sid = visdataR?.SID ?? "",
|
||||
qty = visdataR?.QTY ?? "",
|
||||
vname = visdataR?.VNAME ?? "",
|
||||
vlot = visdataR?.VLOT ?? "",
|
||||
mfgdate = visdataR?.MFGDATE ?? "",
|
||||
partno = visdataR?.PARTNO ?? "",
|
||||
reelSize = visdataR?.ReelSize.ToString() ?? "--",
|
||||
batch = visdataR?.BATCH ?? "",
|
||||
rid2 = visdataR?.RID2 ?? "",
|
||||
sid2 = visdataR?.SID2 ?? "",
|
||||
qty2 = visdataR?.QTY2 ?? "",
|
||||
vname2 = visdataR?.VNAME2 ?? "",
|
||||
vlot2 = visdataR?.VLOT2 ?? "",
|
||||
mfgdate2 = visdataR?.MFGDATE2 ?? "",
|
||||
partno2 = visdataR?.PARTNO2 ?? ""
|
||||
}
|
||||
};
|
||||
|
||||
return JsonConvert.SerializeObject(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[ERROR] Failed to get vision data: {ex.Message}");
|
||||
return JsonConvert.SerializeObject(new { left = new { }, center = new { }, right = new { } });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인터락 목록 조회 (실시간 값 포함)
|
||||
/// </summary>
|
||||
|
||||
@@ -1651,7 +1651,7 @@ namespace Project
|
||||
var exename = UTIL.MakePath("LogView.exe");
|
||||
if (System.IO.File.Exists(exename) == false)
|
||||
{
|
||||
UTIL.MsgE("Log viewer file not found\nPlease contact support (T8567)");
|
||||
UTIL.MsgE($"Log viewer file not found\n{exename}\nPlease contact support (T8567)");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user