From a056810ab4c5fa63777f6fdddfeb190bbd9a6f54 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期一, 08 九月 2025 14:05:25 +0800
Subject: [PATCH] Merge branch 'liuyang'
---
SourceCode/Bond/Servo/GlassJson.cpp | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 334 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/Servo/GlassJson.cpp b/SourceCode/Bond/Servo/GlassJson.cpp
new file mode 100644
index 0000000..c16be0b
--- /dev/null
+++ b/SourceCode/Bond/Servo/GlassJson.cpp
@@ -0,0 +1,334 @@
+#include "stdafx.h"
+#include "GlassJson.h"
+
+#include <chrono>
+#include <optional>
+#include <sstream>
+#include <limits>
+#include <cstdlib>
+
+#include "CGlass.h"
+#include "CParam.h"
+#include "CJobDataS.h"
+#include "CPath.h"
+
+using namespace SERVO;
+
+// ==================== 小工具(兼容老 JsonCpp) ====================
+
+// 将 optional<time_point> 转毫秒(int64),再以字符串写入 JSON
+static std::string tp_to_ms_str(std::optional<std::chrono::system_clock::time_point> tp) {
+ if (!tp) return std::string(); // 空串表示无
+ using namespace std::chrono;
+ long long ms = duration_cast<milliseconds>(tp->time_since_epoch()).count();
+ return std::to_string(ms);
+}
+
+// 从 JSON 的字符串/数字容忍式读取 64 位,优先 string
+static bool get_ll_from_json(const Json::Value& v, const char* key, long long& out) {
+ if (!v.isMember(key)) return false;
+ const Json::Value& x = v[key];
+ if (x.isString()) {
+ const std::string s = x.asString();
+ if (s.empty()) return false;
+ char* endp = nullptr;
+ errno = 0;
+#if defined(_MSC_VER)
+ long long val = _strtoi64(s.c_str(), &endp, 10);
+#else
+ long long val = std::strtoll(s.c_str(), &endp, 10);
+#endif
+ if (endp && *endp == '\0' && errno == 0) { out = val; return true; }
+ // 容错:如果其实是数字字符串(带空格),再试一次
+ try { out = std::stoll(s); return true; }
+ catch (...) {}
+ return false;
+ }
+ if (x.isInt()) { out = static_cast<long long>(x.asInt()); return true; }
+ if (x.isUInt()) { out = static_cast<long long>(x.asUInt()); return true; }
+ if (x.isDouble()) { out = static_cast<long long>(x.asDouble()); return true; }
+ return false;
+}
+
+// 写 64 位为字符串(跨版本/跨语言更稳)
+static void put_ull_as_str(Json::Value& obj, const char* key, unsigned long long v) {
+ obj[key] = Json::Value(std::to_string(v));
+}
+static void put_ll_as_str(Json::Value& obj, const char* key, long long v) {
+ obj[key] = Json::Value(std::to_string(v));
+}
+
+// 简化读取(带默认)
+static int JInt(const Json::Value& v, const char* k, int d = 0)
+{
+ return v.isMember(k) ? v[k].asInt() : d;
+}
+static unsigned JUInt(const Json::Value& v, const char* k, unsigned d = 0)
+{
+ return v.isMember(k) ? v[k].asUInt() : d;
+}
+static bool JBool(const Json::Value& v, const char* k, bool d = false)
+{
+ return v.isMember(k) ? v[k].asBool() : d;
+}
+static std::string JStr(const Json::Value& v, const char* k, const std::string& d = "")
+{
+ return v.isMember(k) ? v[k].asString() : d;
+}
+static double JDouble(const Json::Value& v, const char* k, double d = 0.0)
+{
+ return v.isMember(k) ? v[k].asDouble() : d;
+}
+
+// ==================== CGlass -> JSON ====================
+
+Json::Value GlassJson::ToJson(const CGlass& gConst) {
+ CGlass& g = const_cast<CGlass&>(gConst); // 许多 getter 不是 const
+ Json::Value root(Json::objectValue);
+
+ // 基本
+ root["id"] = g.getID();
+ root["materials"] = static_cast<int>(g.getType()); // 0/1/2/3
+ root["buddy_id"] = g.getBuddyId();
+ root["has_buddy"] = (g.getBuddy() != nullptr);
+
+ int port = 0, slot = 0;
+ g.getOrginPort(port, slot);
+ root["origin_port"] = port;
+ root["origin_slot"] = slot;
+
+ root["scheduled"] = g.isScheduledForProcessing() ? true : false;
+ root["state"] = static_cast<int>(g.state()); // GlsState -> int
+ root["fail_reason"] = g.m_failReason;
+
+ // 时间戳:以字符串写
+ root["t_queued_ms"] = tp_to_ms_str(g.tQueued());
+ root["t_start_ms"] = tp_to_ms_str(g.tStart());
+ root["t_end_ms"] = tp_to_ms_str(g.tEnd());
+
+ // params: vector<CParam>
+ {
+ Json::Value arr(Json::arrayValue);
+ for (auto& p : g.getParams()) {
+ Json::Value jp(Json::objectValue);
+ jp["id"] = p.getId();
+ jp["name"] = p.getName();
+ jp["unit"] = p.getUnit();
+ int vt = p.getValueType(); // PVT_INT=0, PVT_DOUBLE=1
+ jp["vtype"] = vt;
+ if (vt == PVT_INT) jp["iv"] = p.getIntValue();
+ else jp["fv"] = p.getDoubleValue();
+ arr.append(std::move(jp));
+ }
+ root["params"] = std::move(arr);
+ }
+
+ // JobDataS
+ {
+ CJobDataS& s = *g.getJobDataS();
+ Json::Value js(Json::objectValue);
+ js["cassette_seq_no"] = s.getCassetteSequenceNo();
+ js["job_seq_no"] = s.getJobSequenceNo();
+ js["lot_id"] = s.getLotId();
+ js["product_id"] = s.getProductId();
+ js["operation_id"] = s.getOperationId();
+ js["glass1_id"] = s.getGlass1Id();
+ js["glass2_id"] = s.getGlass2Id();
+
+ js["job_type"] = s.getJobType();
+ js["materials_type"] = s.getMaterialsType();
+ js["product_type"] = s.getProductType();
+ js["dummy_type"] = s.getDummyType();
+ js["skip_flag"] = s.getSkipFlag();
+ js["process_flag"] = s.getProcessFlag();
+ js["process_reason"] = s.getProcessResonCode();
+ js["last_glass_flag"] = s.getLastGlassFlag();
+ js["first_glass_flag"] = s.getFirstGlassFlag();
+
+ Json::Value q(Json::arrayValue);
+ for (int i = 0; i < 3; i++) q.append(s.getQTime(i));
+ js["qtime"] = std::move(q);
+ js["qtime_over_flag"] = s.getQTimeOverFlag();
+
+ js["master_recipe"] = s.getMasterRecipe();
+ Json::Value rids(Json::arrayValue);
+ for (int i = 0; i < DEVICE_COUNT; i++) rids.append(s.getDeviceRecipeId(i));
+ js["device_recipe_ids"] = std::move(rids);
+
+ js["panel_measure"] = s.getPanelMeasure();
+ js["mode"] = s.getMode();
+ js["slot_unit_select_flag"] = s.getSlotUnitSelectFlag();
+
+ js["source_port_no"] = s.getSourcePortNo();
+ js["source_slot_no"] = s.getSourceSlotNo();
+ js["target_port_no"] = s.getTargetPortNo();
+ js["target_slot_no"] = s.getTargetSlotNo();
+
+ js["product_judge"] = s.getProductJudge();
+
+ root["job_data_s"] = std::move(js);
+ }
+
+ // path(链表 → 数组;时间字段以字符串存)
+ {
+ Json::Value arr(Json::arrayValue);
+ if (auto head = g.getPath()) {
+ CPath* p = head->getHeadPath();
+ while (p) {
+ Json::Value n(Json::objectValue);
+ n["eq_id"] = p->getEqID();
+ n["unit"] = p->getUnit();
+ put_ull_as_str(n, "time_in", static_cast<unsigned long long>(p->getInTime()));
+ put_ull_as_str(n, "time_out", static_cast<unsigned long long>(p->getOutTime()));
+ n["processed"] = p->isProcessEnd() ? true : false;
+ n["insp_result"] = static_cast<int>(p->getInspResult()); // 0:not,1:pass,2:fail
+ arr.append(std::move(n));
+ p = p->getNext();
+ }
+ }
+ root["path"] = std::move(arr);
+ }
+
+ root["payload_version"] = 1;
+ return root;
+}
+
+// ==================== JSON -> CGlass ====================
+
+void GlassJson::FromJson(const Json::Value& root, CGlass& g) {
+ // 基本
+ g.setID(JStr(root, "id").c_str());
+ g.setType(static_cast<MaterialsType>(JInt(root, "materials", 0)));
+ g.getBuddyId() = JStr(root, "buddy_id");
+ g.setScheduledForProcessing(JBool(root, "scheduled") ? TRUE : FALSE);
+ g.m_failReason = JStr(root, "fail_reason");
+ g.setOriginPort(JInt(root, "origin_port", 0), JInt(root, "origin_slot", 0));
+
+ // 状态与时间(时间从字符串/数字容错解析)
+ g.m_state = static_cast<GlsState>(JInt(root, "state", 0));
+ long long ms = 0;
+ if (get_ll_from_json(root, "t_queued_ms", ms)) g.m_tQueued = std::chrono::system_clock::time_point(std::chrono::milliseconds(ms)); else g.m_tQueued = std::nullopt;
+ if (get_ll_from_json(root, "t_start_ms", ms)) g.m_tStart = std::chrono::system_clock::time_point(std::chrono::milliseconds(ms)); else g.m_tStart = std::nullopt;
+ if (get_ll_from_json(root, "t_end_ms", ms)) g.m_tEnd = std::chrono::system_clock::time_point(std::chrono::milliseconds(ms)); else g.m_tEnd = std::nullopt;
+
+ // params
+ g.getParams().clear();
+ if (root.isMember("params") && root["params"].isArray()) {
+ for (const auto& jp : root["params"]) {
+ const int vt = JInt(jp, "vtype", 0); // 0=int,1=double
+ const std::string name = JStr(jp, "name");
+ const std::string id = JStr(jp, "id");
+ const std::string unit = JStr(jp, "unit");
+ if (vt == PVT_INT) {
+ CParam p(name.c_str(), id.c_str(), unit.c_str(), JInt(jp, "iv", 0));
+ g.getParams().push_back(std::move(p));
+ }
+ else {
+ CParam p(name.c_str(), id.c_str(), unit.c_str(), JDouble(jp, "fv", 0.0));
+ g.getParams().push_back(std::move(p));
+ }
+ }
+ }
+
+ // JobDataS
+ if (root.isMember("job_data_s") && root["job_data_s"].isObject()) {
+ const auto& js = root["job_data_s"];
+ CJobDataS* s = g.getJobDataS();
+
+ s->setCassetteSequenceNo(JInt(js, "cassette_seq_no", 0));
+ s->setJobSequenceNo(JInt(js, "job_seq_no", 0));
+
+ s->setLotId(JStr(js, "lot_id").c_str());
+ s->setProductId(JStr(js, "product_id").c_str());
+ s->setOperationId(JStr(js, "operation_id").c_str());
+ s->setGlass1Id(JStr(js, "glass1_id").c_str());
+ s->setGlass2Id(JStr(js, "glass2_id").c_str());
+
+ s->setJobType(JInt(js, "job_type", 0));
+ s->setMaterialsType(JInt(js, "materials_type", 0));
+ s->setProductType(JInt(js, "product_type", 0));
+ s->setDummyType(JInt(js, "dummy_type", 0));
+ s->setSkipFlag(JInt(js, "skip_flag", 0));
+ s->setProcessFlag(JInt(js, "process_flag", 0));
+ s->setProcessResonCode(JInt(js, "process_reason", 0));
+ s->setLastGlassFlag(JInt(js, "last_glass_flag", 0));
+ s->setFirstGlassFlag(JInt(js, "first_glass_flag", 0));
+
+ if (js.isMember("qtime") && js["qtime"].isArray()) {
+ for (int i = 0; i < 3; i++) {
+ int v = (i < (int)js["qtime"].size()) ? js["qtime"][i].asInt() : 0;
+ s->setQTime(i, v);
+ }
+ }
+ else {
+ for (int i = 0; i < 3; i++) s->setQTime(i, 0);
+ }
+ s->setQTimeOverFlag(JInt(js, "qtime_over_flag", 0));
+
+ s->setMasterRecipe(JInt(js, "master_recipe", 0));
+ if (js.isMember("device_recipe_ids") && js["device_recipe_ids"].isArray()) {
+ for (int i = 0; i < DEVICE_COUNT; i++) {
+ int v = (i < (int)js["device_recipe_ids"].size()) ? js["device_recipe_ids"][i].asInt() : 0;
+ s->setDeviceRecipeId(i, static_cast<short>(v));
+ }
+ }
+ else {
+ for (int i = 0; i < DEVICE_COUNT; i++) s->setDeviceRecipeId(i, 0);
+ }
+
+ s->setPanelMeasure(JStr(js, "panel_measure").c_str());
+ s->setMode(JInt(js, "mode", 0));
+ s->setSlotUnitSelectFlag(JInt(js, "slot_unit_select_flag", 0));
+
+ s->setSourcePortNo(JInt(js, "source_port_no", 0));
+ s->setSourceSlotNo(JInt(js, "source_slot_no", 0));
+ s->setTargetPortNo(JInt(js, "target_port_no", 0));
+ s->setTargetSlotNo(JInt(js, "target_slot_no", 0));
+
+ s->setProductJudge(static_cast<short>(JInt(js, "product_judge", 0)));
+ }
+
+ // path:顺序重建链(时间字段以字符串读回)
+ if (root.isMember("path") && root["path"].isArray()) {
+ for (const auto& n : root["path"]) {
+ unsigned eq = JUInt(n, "eq_id", 0);
+ unsigned unit = JUInt(n, "unit", 0);
+ g.addPath(eq, unit);
+
+ CPath* tail = nullptr;
+ if (auto head = g.getPath()) tail = head->getTailPath();
+ if (!tail) continue;
+
+ long long tin = 0, tout = 0;
+ if (get_ll_from_json(n, "time_in", tin)) tail->setInTime(static_cast<ULONGLONG>(tin));
+ if (get_ll_from_json(n, "time_out", tout)) tail->setOutTime(static_cast<ULONGLONG>(tout));
+ tail->setInspResult(static_cast<InspResult>(JInt(n, "insp_result", 0)));
+ if (JBool(n, "processed", false)) tail->processEnd();
+ }
+ }
+}
+
+// ==================== 便捷封装 ====================
+
+std::string GlassJson::ToString(const CGlass& g) {
+ Json::FastWriter w; // 旧版:紧凑,无格式
+ // w.omitEndingLineFeed(); // 去掉末尾换行(如果你的 JsonCpp 版本支持)
+ return w.write(ToJson(g));
+}
+
+std::string GlassJson::ToPrettyString(const CGlass& g) {
+ Json::StyledWriter w; // 旧版:美化输出
+ return w.write(ToJson(g));
+}
+
+bool GlassJson::FromString(const std::string& text, CGlass& g, std::string* err) {
+ Json::Reader reader; // 旧版解析器
+ Json::Value j;
+ bool ok = reader.parse(text, j, /*collectComments*/ false);
+ if (!ok) {
+ if (err) *err = reader.getFormatedErrorMessages();
+ return false;
+ }
+ FromJson(j, g);
+ return true;
+}
--
Gitblit v1.9.3