LAPTOP-SNT8I5JK\Boounion
2025-08-19 0569c29b19e4d23f055845a167c706f11590fa2a
1.CControlJob和CProcessJob的序列化和反序列化;
已添加1个文件
已修改9个文件
393 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CControlJob.cpp 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CControlJob.h 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ProcessJob.cpp 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ProcessJob.h 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/SerializeUtil.h 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CControlJob.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "CControlJob.h"
#include <cctype>
#include "SerializeUtil.h"
static inline std::string trimCopy(std::string s) {
    auto notspace = [](int ch) { return !std::isspace(ch); };
@@ -10,6 +11,11 @@
}
namespace SERVO {
    CControlJob::CControlJob()
    {
    }
    CControlJob::CControlJob(std::string cjId)
        : m_cjId(trimCopy(std::move(cjId)))
    {
@@ -221,4 +227,78 @@
            return c >= 0x20 && c <= 0x7E;
            });
    }
    void CControlJob::serialize(std::ostream& os) const {
        write_pod(os, CJ_MAGIC);
        write_pod(os, CJ_VERSION);
        // æ ‡è¯†/优先级/状态/失败原因
        write_string(os, id());                             // æˆ– m_cjId
        write_pod<uint8_t>(os, priority());                 // æˆ– m_priority
        write_pod<uint8_t>(os, static_cast<uint8_t>(state())); // æˆ– m_state
        write_string(os, failReason());                     // æˆ– m_failReason
        // æ—¶é—´æˆ³
        write_opt_time(os, tQueued());
        write_opt_time(os, tStart());
        write_opt_time(os, tEnd());
        // å…³è” PJ åˆ—表
        write_vec_str(os, pjIds());                         // æˆ– m_pjIds
    }
    bool CControlJob::deserialize(std::istream& is, CControlJob& out, std::string* err) {
        auto fail = [&](const char* msg) { if (err) *err = msg; return false; };
        uint32_t magic = 0; if (!read_pod(is, magic)) return fail("read CJ magic");
        if (magic != CJ_MAGIC) return fail("bad CJ magic");
        uint16_t ver = 0; if (!read_pod(is, ver)) return fail("read CJ version");
        if (ver != CJ_VERSION) return fail("unsupported CJ version");
        std::string cjId;
        if (!read_string(is, cjId)) return fail("read CJID");
        uint8_t prio = 0;
        if (!read_pod(is, prio)) return fail("read Priority");
        uint8_t st = 0;
        if (!read_pod(is, st))   return fail("read State");
        std::string failText;
        if (!read_string(is, failText)) return fail("read failReason");
        std::optional<std::chrono::system_clock::time_point> tQ, tS, tE;
        if (!read_opt_time(is, tQ)) return fail("read tQueued");
        if (!read_opt_time(is, tS)) return fail("read tStart");
        if (!read_opt_time(is, tE)) return fail("read tEnd");
        std::vector<std::string> pjIds;
        if (!read_vec_str(is, pjIds)) return fail("read PJIDs");
        // â€”— å†™å›žå¯¹è±¡ï¼ˆç›´æŽ¥æ”¹æˆå‘˜ï¼Œæˆ–通过 setter)——
        // è‹¥ä½ æœ‰ setter:out.setId(...)/setPriority(...)/setState(...)/setFailReason(...)
        out = CControlJob(cjId);
        out.setPriority(prio);
        // ç›´æŽ¥æ¢å¤å†…部状态(若你要求走状态机,可在这里按合法过渡调用 queue()/start()/...)
        // ç®€åŒ–:直接赋值(你在 CControlJob.cpp å†…部,可访问私有成员)
        struct Access : CControlJob {
            using CControlJob::m_state;
            using CControlJob::m_failReason;
            using CControlJob::m_tQueued;
            using CControlJob::m_tStart;
            using CControlJob::m_tEnd;
            using CControlJob::m_pjIds;
        };
        auto& a = reinterpret_cast<Access&>(out);
        a.m_state = static_cast<CJState>(st);
        a.m_failReason = std::move(failText);
        a.m_tQueued = std::move(tQ);
        a.m_tStart = std::move(tS);
        a.m_tEnd = std::move(tE);
        a.m_pjIds = std::move(pjIds);
        return true;
    }
}
SourceCode/Bond/Servo/CControlJob.h
@@ -36,6 +36,7 @@
    /// CControlJob:Control Job ç®¡ç†ç±»
    class CControlJob {
    public:
        CControlJob();
        explicit CControlJob(std::string cjId);
        explicit CControlJob(CControlJob& src);
@@ -111,12 +112,18 @@
        static void clampString(std::string& s, size_t maxLen);
        static bool asciiPrintable(const std::string& s);
        static constexpr uint32_t CJ_MAGIC = 0x434A5031; // "CJP1"
        static constexpr uint16_t CJ_VERSION = 0x0001;
        void serialize(std::ostream& os) const;
        static bool deserialize(std::istream& is, CControlJob& out, std::string* err = nullptr);
    private:
        void markQueued();
        void markStart();
        void markEnd();
    private:
    protected:
        // â€”— æ ‡è¯† & é…ç½® â€”— //
        std::string m_cjId;
        uint8_t     m_priority{ 5 }; // ç¼ºçœä¼˜å…ˆçº§ï¼ˆè‡ªå®šï¼‰
SourceCode/Bond/Servo/CMaster.cpp
@@ -4,6 +4,8 @@
#include <future>
#include <vector>
#include "RecipeManager.h"
#include <fstream>
#include "SerializeUtil.h"
namespace SERVO {
@@ -1864,6 +1866,8 @@
        }
        m_processJobs = temp;
        this->saveState();
        return m_processJobs.size();
    }
@@ -1919,6 +1923,9 @@
            }
        }
        m_pControlJob->setPJs(temps);
        this->saveState();
        return 0;
    }
@@ -1967,4 +1974,82 @@
        return true;
    }
    bool CMaster::saveState() const
    {
        std::ofstream ofs(m_strStatePath, std::ios::binary);
        if (!ofs) return false;
        // æ–‡ä»¶å¤´
        uint32_t magic = 0x4D415354; // 'MAST'
        uint16_t version = 1;
        ofs.write(reinterpret_cast<const char*>(&magic), sizeof(magic));
        ofs.write(reinterpret_cast<const char*>(&version), sizeof(version));
        // ä¿å­˜ ControlJob
        bool hasCJ = (m_pControlJob != nullptr);
        ofs.write(reinterpret_cast<const char*>(&hasCJ), sizeof(hasCJ));
        if (hasCJ) {
            m_pControlJob->serialize(ofs);
        }
        // ä¿å­˜ ProcessJob åˆ—表
        uint32_t count = static_cast<uint32_t>(m_processJobs.size());
        ofs.write(reinterpret_cast<const char*>(&count), sizeof(count));
        for (const auto& job : m_processJobs) {
            job->serialize(ofs);
        }
        // ä»¥åŽå¯ä»¥åœ¨è¿™é‡Œè¿½åŠ æ–°å­—æ®µ
        return true;
    }
    bool CMaster::loadState(const std::string& path)
    {
        // ä¿å­˜æ–‡ä»¶è·¯å¾„
        m_strStatePath = path;
        std::ifstream ifs(path, std::ios::binary);
        if (!ifs) return false;
        // æ–‡ä»¶å¤´
        uint32_t magic = 0;
        uint16_t version = 0;
        ifs.read(reinterpret_cast<char*>(&magic), sizeof(magic));
        ifs.read(reinterpret_cast<char*>(&version), sizeof(version));
        if (magic != 0x4D415354) {
            // æ–‡ä»¶ä¸åˆæ³•
            return false;
        }
        if (m_pControlJob != nullptr) {
            delete m_pControlJob;
            m_pControlJob = nullptr;
        }
        // è¯»å– ControlJob
        bool hasCJ = false;
        ifs.read(reinterpret_cast<char*>(&hasCJ), sizeof(hasCJ));
        if (hasCJ) {
            m_pControlJob = new CControlJob();
            if (!CControlJob::deserialize(ifs, *m_pControlJob)) return false;
        }
        // è¯»å– ProcessJob åˆ—表
        uint32_t count = 0;
        ifs.read(reinterpret_cast<char*>(&count), sizeof(count));
        m_processJobs.clear();
        for (uint32_t i = 0; i < count; i++) {
            CProcessJob* pProcessJob = new CProcessJob();
            if (!CProcessJob::deserialize(ifs, *pProcessJob)) return false;
            m_processJobs.push_back(pProcessJob);
        }
        // å¦‚果版本升级,可在这里判断 version æ¥åŠ è½½æ–°å­—æ®µ
        return true;
    }
}
SourceCode/Bond/Servo/CMaster.h
@@ -111,6 +111,8 @@
        CProcessJob* getProcessJob(const std::string& id);
        int setControlJob(CControlJob& controlJob);
        CLoadPort* getPortWithCarrierId(const std::string& carrierId) const;
        bool saveState() const;
        bool loadState(const std::string& path);
    private:
        inline void lock() { EnterCriticalSection(&m_criticalSection); }
@@ -196,6 +198,7 @@
        bool m_bEnableAlarmReport;
        SERVO::CControlJob* m_pControlJob;
        std::vector<SERVO::CProcessJob*> m_processJobs;
        std::string m_strStatePath;
    };
}
SourceCode/Bond/Servo/Model.cpp
@@ -397,6 +397,14 @@
    m_master.setCacheFilepath((LPTSTR)(LPCTSTR)strMasterDataFile);
    m_master.setCompareMapsBeforeProceeding(m_configuration.isCompareMapsBeforeProceeding());
    // åŠ æˆªJob
    strMasterDataFile.Format(_T("%s\\MasterState.dat"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    std::string strPath = std::string((LPTSTR)(LPCTSTR)strMasterDataFile);
    if (!m_master.loadState(strPath)) {
        LOGE("<Master>加载MasterState.dat文件失败.");
    }
    // åŠ è½½è­¦å‘Šä¿¡æ¯
    AlarmManager& alarmManager = AlarmManager::getInstance();
    char szBuffer[MAX_PATH];
SourceCode/Bond/Servo/ProcessJob.cpp
@@ -1,6 +1,9 @@
#include "stdafx.h"
#include "ProcessJob.h"
#include <cctype>
#include <fstream>
#include "SerializeUtil.h"
namespace SERVO {
    static inline std::string trimCopy(std::string s) {
@@ -8,6 +11,11 @@
        s.erase(s.begin(), std::find_if(s.begin(), s.end(), notspace));
        s.erase(std::find_if(s.rbegin(), s.rend(), notspace).base(), s.end());
        return s;
    }
    CProcessJob::CProcessJob()
    {
    }
    CProcessJob::CProcessJob(std::string pjId)
@@ -257,4 +265,120 @@
            m_carriers.emplace_back(std::move(cs));
        }
    }
    // --------- æ ¸å¿ƒï¼šserialize/deserialize ---------
    void CProcessJob::serialize(std::ostream& os) const {
        // Í·
        write_pod(os, PJ_FILE_MAGIC);
        write_pod(os, PJ_FILE_VERSION);
        // åŸºæœ¬
        write_string(os, m_pjId);
        write_string(os, m_parentCjId);
        // é…æ–¹
        uint8_t recipeType = static_cast<uint8_t>(m_recipeMethod);
        write_pod(os, m_recipeMethod);
        write_string(os, m_recipeSpec);
        // ç‰©æ–™ï¼ˆå¤š Carrier & Slot)
        {
            uint32_t n = static_cast<uint32_t>(m_carriers.size());
            write_pod(os, n);
            for (const auto& cs : m_carriers) {
                write_string(os, cs.carrierId);
                write_vec<uint8_t>(os, cs.slots);
            }
        }
        // å‚æ•°
        {
            uint32_t n = static_cast<uint32_t>(m_params.size());
            write_pod(os, n);
            for (const auto& p : m_params) {
                write_string(os, p.name);
                write_string(os, p.value);
            }
        }
        // æš‚停事件
        write_vec<uint32_t>(os, m_pauseEvents);
        // å¯åŠ¨ç­–ç•¥ & çŠ¶æ€
        uint8_t startPolicy = static_cast<uint8_t>(m_startPolicy);
        uint8_t st = static_cast<uint8_t>(m_state);
        write_pod(os, startPolicy);
        write_pod(os, st);
        // å¤±è´¥åŽŸå› 
        write_string(os, m_failReason);
        // æ—¶é—´æˆ³
        write_opt_time(os, m_tQueued);
        write_opt_time(os, m_tStart);
        write_opt_time(os, m_tEnd);
    }
    bool CProcessJob::deserialize(std::istream& is, CProcessJob& out, std::string* err) {
        auto fail = [&](const char* msg) { if (err) *err = msg; return false; };
        uint32_t magic = 0; if (!read_pod(is, magic)) return fail("read magic failed");
        if (magic != PJ_FILE_MAGIC) return fail("bad magic");
        uint16_t ver = 0; if (!read_pod(is, ver)) return fail("read version failed");
        if (ver != PJ_FILE_VERSION) return fail("unsupported version");
        // åŸºæœ¬
        if (!read_string(is, out.m_pjId))        return fail("read pjId");
        if (!read_string(is, out.m_parentCjId))  return fail("read parentCjId");
        // é…æ–¹
        uint8_t recipeType = 0; if (!read_pod(is, recipeType)) return fail("read recipeType");
        out.m_recipeMethod = static_cast<RecipeMethod>(recipeType);
        if (!read_string(is, out.m_recipeSpec)) return fail("read recipeSpec");
        // ç‰©æ–™
        {
            uint32_t n = 0; if (!read_pod(is, n)) return fail("read carriers count");
            out.m_carriers.clear(); out.m_carriers.reserve(n);
            for (uint32_t i = 0; i < n; ++i) {
                CarrierSlotInfo cs;
                if (!read_string(is, cs.carrierId)) return fail("read carrierId");
                if (!read_vec<uint8_t>(is, cs.slots)) return fail("read slots");
                out.m_carriers.emplace_back(std::move(cs));
            }
        }
        // å‚æ•°
        {
            uint32_t n = 0; if (!read_pod(is, n)) return fail("read params count");
            out.m_params.clear(); out.m_params.reserve(n);
            for (uint32_t i = 0; i < n; ++i) {
                PJParam p;
                if (!read_string(is, p.name))  return fail("read param name");
                if (!read_string(is, p.value)) return fail("read param value");
                out.m_params.emplace_back(std::move(p));
            }
        }
        // æš‚停事件
        if (!read_vec<uint32_t>(is, out.m_pauseEvents)) return fail("read pauseEvents");
        // å¯åŠ¨ç­–ç•¥ & çŠ¶æ€
        uint8_t startPolicy = 0, st = 0;
        if (!read_pod(is, startPolicy)) return fail("read startPolicy");
        if (!read_pod(is, st))          return fail("read state");
        out.m_startPolicy = static_cast<StartPolicy>(startPolicy);
        out.m_state = static_cast<PJState>(st);
        // å¤±è´¥åŽŸå› 
        if (!read_string(is, out.m_failReason)) return fail("read failReason");
        // æ—¶é—´æˆ³
        if (!read_opt_time(is, out.m_tQueued)) return fail("read tQueued");
        if (!read_opt_time(is, out.m_tStart))  return fail("read tStart");
        if (!read_opt_time(is, out.m_tEnd))    return fail("read tEnd");
        return true;
    }
}
SourceCode/Bond/Servo/ProcessJob.h
@@ -85,6 +85,7 @@
    class CProcessJob {
    public:
        // â€”— æž„造 / åŸºæœ¬è®¾ç½® â€”—
        CProcessJob();
        explicit CProcessJob(std::string pjId);
        const std::string& id() const noexcept { return m_pjId; }
@@ -157,6 +158,15 @@
        bool usesCarrierSlots() const noexcept { return !m_carriers.empty(); }
    public:
        // ====== ç‰ˆæœ¬å¤´å¸¸é‡ï¼ˆå»ºè®®ä¿ç•™ï¼Œä¾¿äºŽå…¼å®¹ï¼‰======
        static constexpr uint32_t PJ_FILE_MAGIC = 0x504A4A31; // "PJJ1"
        static constexpr uint16_t PJ_FILE_VERSION = 0x0001;
        // ====== æµå¼åºåˆ—化接口 ======
        void serialize(std::ostream& os) const;
        static bool deserialize(std::istream& is, CProcessJob& out, std::string* err = nullptr);
    private:
        // å†…部状态转移帮助
        void markQueued();
SourceCode/Bond/Servo/SerializeUtil.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
#pragma once
#include <fstream>
// --------- ç§æœ‰/内部:读写工具 ---------
namespace SERVO {
    template<typename T>
    inline void write_pod(std::ostream& os, const T& v) {
        os.write(reinterpret_cast<const char*>(&v), sizeof(T));
    }
    template<typename T>
    inline bool read_pod(std::istream& is, T& v) {
        return bool(is.read(reinterpret_cast<char*>(&v), sizeof(T)));
    }
    inline void write_string(std::ostream& os, const std::string& s) {
        uint32_t n = static_cast<uint32_t>(s.size());
        write_pod(os, n);
        if (n) os.write(s.data(), n);
    }
    inline bool read_string(std::istream& is, std::string& s) {
        uint32_t n = 0; if (!read_pod(is, n)) return false;
        s.resize(n);
        if (n) return bool(is.read(&s[0], n));
        return true;
    }
    template<typename T>
    inline void write_vec(std::ostream& os, const std::vector<T>& v) {
        uint32_t n = static_cast<uint32_t>(v.size());
        write_pod(os, n);
        if (n) os.write(reinterpret_cast<const char*>(v.data()), sizeof(T) * n);
    }
    template<typename T>
    inline bool read_vec(std::istream& is, std::vector<T>& v) {
        uint32_t n = 0; if (!read_pod(is, n)) return false;
        v.resize(n);
        if (n) return bool(is.read(reinterpret_cast<char*>(v.data()), sizeof(T) * n));
        return true;
    }
    // vector<string> ç‰¹åŒ–写读
    inline void write_vec_str(std::ostream& os, const std::vector<std::string>& v) {
        uint32_t n = static_cast<uint32_t>(v.size());
        write_pod(os, n);
        for (const auto& s : v) write_string(os, s);
    }
    inline bool read_vec_str(std::istream& is, std::vector<std::string>& v) {
        uint32_t n = 0; if (!read_pod(is, n)) return false;
        v.clear(); v.reserve(n);
        for (uint32_t i = 0; i < n; ++i) { std::string s; if (!read_string(is, s)) return false; v.emplace_back(std::move(s)); }
        return true;
    }
    // optional<time_point> â†’ bool + int64 (ms since epoch)
    inline void write_opt_time(std::ostream& os, const std::optional<std::chrono::system_clock::time_point>& tp) {
        uint8_t has = tp.has_value() ? 1 : 0;
        write_pod(os, has);
        if (has) {
            auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp->time_since_epoch()).count();
            int64_t v = static_cast<int64_t>(ms);
            write_pod(os, v);
        }
    }
    inline bool read_opt_time(std::istream& is, std::optional<std::chrono::system_clock::time_point>& tp) {
        uint8_t has = 0; if (!read_pod(is, has)) return false;
        if (!has) { tp.reset(); return true; }
        int64_t v = 0; if (!read_pod(is, v)) return false;
        tp = std::chrono::system_clock::time_point(std::chrono::milliseconds(v));
        return true;
    }
}
SourceCode/Bond/Servo/Servo.vcxproj
@@ -333,6 +333,7 @@
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SECSRuntimeManager.h" />
    <ClInclude Include="SecsTestDlg.h" />
    <ClInclude Include="SerializeUtil.h" />
    <ClInclude Include="Servo.h" />
    <ClInclude Include="ServoCommo.h" />
    <ClInclude Include="ServoDlg.h" />
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -361,6 +361,7 @@
    <ClInclude Include="CPageCollectionEvent.h" />
    <ClInclude Include="ProcessJob.h" />
    <ClInclude Include="CControlJob.h" />
    <ClInclude Include="SerializeUtil.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />