#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();
|
n["slot"] = 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.setBuddyId(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);
|
unsigned slot = JUInt(n, "slot", 0);
|
g.addPath(eq, unit, slot);
|
|
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;
|
}
|