From bc7f1c4e028e69be51079b59dae4ae5c4d43f5bb Mon Sep 17 00:00:00 2001
From: chenluhua1980 <Chenluhua@qq.com>
Date: 星期六, 31 一月 2026 21:54:56 +0800
Subject: [PATCH] 1.状态指示图,目前灰色表示掉线,绿色表示在线。增加Slot的小点表示有没有料,及加工状态 。 2.增加图示
---
SourceCode/Bond/Servo/ProductionStats.cpp | 63 +++++++++++++++++++++++++++++++
1 files changed, 62 insertions(+), 1 deletions(-)
diff --git a/SourceCode/Bond/Servo/ProductionStats.cpp b/SourceCode/Bond/Servo/ProductionStats.cpp
index aff2a74..edf6272 100644
--- a/SourceCode/Bond/Servo/ProductionStats.cpp
+++ b/SourceCode/Bond/Servo/ProductionStats.cpp
@@ -88,7 +88,9 @@
}
const char* sql =
- "SELECT class_id, buddy_id, aoi_result "
+ "SELECT class_id, buddy_id, aoi_result, "
+ "IFNULL(strftime('%Y-%m-%d %H:%M:%S', t_start, 'localtime'), ''),"
+ "IFNULL(strftime('%Y-%m-%d %H:%M:%S', t_end, 'localtime'), '') "
"FROM glass_log "
"WHERE t_end IS NOT NULL AND t_end >= ? AND t_end < ?;";
@@ -105,6 +107,7 @@
bool hasPass = false;
bool hasFail = false;
bool hasNo = false;
+ long long maxTaktSeconds = -1;
};
std::unordered_map<std::string, PairAgg> pairs;
@@ -114,6 +117,8 @@
const char* classId = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
const char* buddyId = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
const int aoi = sqlite3_column_int(stmt, 2);
+ const char* sStart = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
+ const char* sEnd = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4));
const std::string a = classId ? classId : "";
const std::string b = buddyId ? buddyId : "";
@@ -130,6 +135,12 @@
if (aoi == 1) agg.hasPass = true;
else if (aoi == 2) agg.hasFail = true;
else agg.hasNo = true;
+
+ std::chrono::system_clock::time_point tpStart{}, tpEnd{};
+ if (TryParseLocalTime(sStart ? sStart : "", tpStart) && TryParseLocalTime(sEnd ? sEnd : "", tpEnd) && tpEnd > tpStart) {
+ const auto secs = std::chrono::duration_cast<std::chrono::seconds>(tpEnd - tpStart).count();
+ if (secs > agg.maxTaktSeconds) agg.maxTaktSeconds = secs;
+ }
}
else if (rc == SQLITE_DONE) {
break;
@@ -143,14 +154,23 @@
sqlite3_close(db);
out.pairsTotal = static_cast<long long>(pairs.size());
+ long long sumTakt = 0;
+ long long cntTakt = 0;
for (const auto& kv : pairs) {
const auto& agg = kv.second;
if (agg.hasFail) out.pairsFail++;
else if (agg.hasPass) out.pairsPass++;
else out.pairsNoResult++;
+
+ if (agg.maxTaktSeconds >= 0) {
+ sumTakt += agg.maxTaktSeconds;
+ cntTakt += 1;
+ }
}
const long long denom = out.pairsPass + out.pairsFail;
out.yield = (denom > 0) ? (static_cast<double>(out.pairsPass) / static_cast<double>(denom)) : 0.0;
+ out.taktSamplePairs = cntTakt;
+ out.avgTaktSeconds = (cntTakt > 0) ? (static_cast<double>(sumTakt) / static_cast<double>(cntTakt)) : 0.0;
}
static void ComputeAlarmSummaryFromDb(
@@ -359,6 +379,7 @@
LOGI("<ProductionStats>Shift=%s, [%s ~ %s]", shiftName, s.window.startLocal.c_str(), s.window.endLocal.c_str());
LOGI("<ProductionStats>Output(pairs): total=%lld, pass=%lld, fail=%lld, no_result=%lld, yield=%.2f%%",
s.output.pairsTotal, s.output.pairsPass, s.output.pairsFail, s.output.pairsNoResult, s.output.yield * 100.0);
+ LOGI("<ProductionStats>Takt: avg=%.1fs, samples=%lld", s.output.avgTaktSeconds, s.output.taktSamplePairs);
LOGI("<ProductionStats>Alarms: triggered=%d, overlapping=%d, downtime=%.1f min",
s.alarms.alarmsTriggered, s.alarms.alarmsOverlapping, s.alarms.downtimeMinutes);
if (!s.alarms.bySeverity.empty()) {
@@ -375,3 +396,43 @@
LOGI("%s", oss.str().c_str());
}
}
+
+bool ProductionStats::ComputeDayNightSummaries(CConfiguration& config, ProductionShiftSummary& outDay, ProductionShiftSummary& outNight)
+{
+ ProductionShiftSummary cur;
+ if (!ComputeCurrentShiftSummary(config, cur)) return false;
+
+ // Determine previous adjacent window for the other shift.
+ ProductionShiftSummary other = cur;
+ if (cur.window.type == ProductionShiftType::Day) {
+ other.window.type = ProductionShiftType::Night;
+ other.window.end = cur.window.start;
+ other.window.start = cur.window.start - (cur.window.end - cur.window.start);
+ }
+ else {
+ other.window.type = ProductionShiftType::Day;
+ other.window.end = cur.window.start;
+ other.window.start = cur.window.start - (cur.window.end - cur.window.start);
+ }
+ other.window.startLocal = FormatLocal(other.window.start);
+ other.window.endLocal = FormatLocal(other.window.end);
+ other.window.startUtcIso = FormatUtcIso(other.window.start);
+ other.window.endUtcIso = FormatUtcIso(other.window.end);
+
+ other.output = ProductionOutputSummary{};
+ other.alarms = ProductionAlarmSummary{};
+ other.transfers = ProductionTransferSummary{};
+ ComputeOutputFromProcessDb(other.window, other.output);
+ ComputeAlarmSummaryFromDb(other.window, other.alarms);
+ ComputeTransferSummaryFromDb(other.window, other.transfers);
+
+ if (cur.window.type == ProductionShiftType::Day) {
+ outDay = std::move(cur);
+ outNight = std::move(other);
+ }
+ else {
+ outNight = std::move(cur);
+ outDay = std::move(other);
+ }
+ return true;
+}
--
Gitblit v1.9.3