1.CControlJob和CProcessJob的序列化和反序列化;
| | |
| | | #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); }; |
| | |
| | | } |
| | | |
| | | namespace SERVO { |
| | | CControlJob::CControlJob() |
| | | { |
| | | |
| | | } |
| | | |
| | | CControlJob::CControlJob(std::string cjId) |
| | | : m_cjId(trimCopy(std::move(cjId))) |
| | | { |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | /// CControlJobï¼Control Job 管çç±» |
| | | class CControlJob { |
| | | public: |
| | | CControlJob(); |
| | | explicit CControlJob(std::string cjId); |
| | | explicit CControlJob(CControlJob& src); |
| | | |
| | |
| | | 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 }; // 缺çä¼å
级ï¼èªå®ï¼ |
| | |
| | | #include <future> |
| | | #include <vector> |
| | | #include "RecipeManager.h" |
| | | #include <fstream> |
| | | #include "SerializeUtil.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | } |
| | | |
| | | m_processJobs = temp; |
| | | this->saveState(); |
| | | |
| | | return m_processJobs.size(); |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | m_pControlJob->setPJs(temps); |
| | | this->saveState(); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | | |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | 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); } |
| | |
| | | bool m_bEnableAlarmReport; |
| | | SERVO::CControlJob* m_pControlJob; |
| | | std::vector<SERVO::CProcessJob*> m_processJobs; |
| | | std::string m_strStatePath; |
| | | }; |
| | | } |
| | | |
| | |
| | | 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]; |
| | |
| | | #include "stdafx.h" |
| | | #include "ProcessJob.h" |
| | | #include <cctype> |
| | | #include <fstream> |
| | | #include "SerializeUtil.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | | static inline std::string trimCopy(std::string s) { |
| | |
| | | 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) |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | class CProcessJob { |
| | | public: |
| | | // ââ æé / åºæ¬è®¾ç½® ââ |
| | | CProcessJob(); |
| | | explicit CProcessJob(std::string pjId); |
| | | |
| | | const std::string& id() const noexcept { return m_pjId; } |
| | |
| | | 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(); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #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; |
| | | } |
| | | } |
| | |
| | | <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" /> |
| | |
| | | <ClInclude Include="CPageCollectionEvent.h" /> |
| | | <ClInclude Include="ProcessJob.h" /> |
| | | <ClInclude Include="CControlJob.h" /> |
| | | <ClInclude Include="SerializeUtil.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="Servo.rc" /> |