#include "stdafx.h" #include #include "Helper.JSON.hpp" #include "DIOS.Dev.Mech.OTCStitch.hpp" using namespace DIOS::Dev; using namespace DIOS::Dev::Detail::MECH; namespace nsMech = DIOS::Dev::Detail::MECH; //关闭无关警告 #pragma warning (disable:4244) // warning C4244: “初始化”: 从“double”转换到“float”,可能丢失数据 #pragma warning (disable:4305) // warning C4305: “参数”: 从“double”到“float”截断 #pragma warning (disable:4267) // warning C4267 : “初始化”: 从“size_t”转换到“int”,可能丢失数据 #pragma warning (disable:4805) // warning C4805: “!=”: 在操作中将类型“bool”与类型“int”混合不安全 //设置相关常量 #define OTCStitch_TIMEOUTVALUE 100 #define OTCStitch_LoopDefHBTime 1000 #define OTCStitch_LoopExpHBTime 500 static const int msTimeOut_Lock = 200; //通讯接口锁定时间 #define OTCStitch_Com_NormalLen 150 #define OTCStitch_STX 0x02 #define OTCStitch_NAK 0x15 #define OTCStitch_ETX 0x03 Log4CPP::Logger* mLog::gLogger = nullptr; //----------------------------------------------------------------------------- // OTCStitchDevice //----------------------------------------------------------------------------- struct tFrameMapping { static const int MaxLen = 5; // 前缀不能超超过 5 个字符 ! using cbFun = std::function ; char strHead[MaxLen]; int NbOfCharOfHead; cbFun fun; tFrameMapping(char* str, int len, cbFun f) { assert(len < MaxLen); //len最大只能是4 for (int i = 0; i < len; i++) strHead[i] = str[i]; NbOfCharOfHead = len; fun = f; } }; static std::list arFrame; static bool DecodeFrame(const char* strFrame, int length) { auto pr = [strFrame, length](const tFrameMapping& Item) { for (int i = 0; i < Item.NbOfCharOfHead; i++) { if (strFrame[i] != Item.strHead[i]) { return false; } } return true; }; auto found = std::find_if(arFrame.begin(), arFrame.end(), pr);//此处pr,是上面定义的 lambda表达式,用来在list中找到对于的包头。 if (found == arFrame.end()) { return false; } const auto& Item = *found; auto pc = strFrame; char data[100] = { 0 }; memcpy(data, strFrame + Item.NbOfCharOfHead, length - Item.NbOfCharOfHead); Item.fun(data, length - Item.NbOfCharOfHead);//第二个参数 不重要 return true; } nsMech::OTCStitchDevice::OTCStitchDevice(std::shared_ptr center, nsSCF::SCF SCF, string configfile /*= ""*/):super(center, SCF) { string version; if (GetVersion(version, hMyModule)) mLog::Info("\n===============log begin : version:{$} ===================\n", version.c_str()); else mLog::Info("\n===============log begin : version:0.0.0.0 ===================\n"); ResDataObject Conftemp; if (!configfile.empty()) { Conftemp.loadFile(configfile.c_str()); m_GenConfig = Conftemp["CONFIGURATION"]; TransJsonText(m_GenConfig); } //m_MECHUnit.m_ViewID.reset(new VIEWIDMould(0, 0, 10, 1)); //m_MECHUnit.m_GridState.reset(new GRIDSTATEMould(AttrKey::Grid_Noinformation, AttrKey::Grid_Noinformation, AttrKey::Grid_OUT_CHANGE, 1)); //m_MECHUnit.m_GridType.reset(new GRIDTYPEMould(AttrKey::Grid_No, AttrKey::Grid_No, AttrKey::Grid_1500, 1)); //m_MECHUnit.m_GridOrientation.reset(new GRIDORIENTATIONMould(AttrKey::Grid_Vertical, AttrKey::Grid_Vertical, AttrKey::Grid_Horizontal, 1)); //m_MECHUnit.m_TID.reset(new TIDMould(0, 0, 10000, 1)); //m_MECHUnit.m_SOD.reset(new SODMould(0, 0, 10000, 1)); //m_MECHUnit.m_ENTRANCE.reset(new ENTRANCEMould(0, 0, 10000, 1)); m_strcurrentcmd = ""; m_bStitchingInProgress = false; m_nCurrentImage = 0; m_nImageCount = 0; m_MECHUnit.m_StitchingState.reset(new StitchingStateMould(AttrKey::STITCHSTATE_INIT, AttrKey::STITCHSTATE_ERR, AttrKey::STITCHSTATE_RESTART, 1)); m_MECHUnit.m_KV.reset(new KVMould(0.0, 40.0, 120.0, 1.0)); m_MECHUnit.m_MA.reset(new MAMould(0.0, 1.0, 1000.0, 0.1)); m_MECHUnit.m_MS.reset(new MSMould(0.0, 1.0, 10000.0, 0.01)); m_MECHUnit.m_MAS.reset(new MASMould(0.0, 0.5, 1000.0, 0.01)); m_MECHUnit.m_Techmode.reset(new TECHMODEMould(AttrKey::TECHMODE_NOAEC_3P, AttrKey::TECHMODE_NOAEC_3P, AttrKey::TECHMODE_AEC_MAS_MA, 1)); m_MECHUnit.m_WS.reset(new WORKSTATIONMould(1, 0, 5, 1)); m_MECHUnit.m_Focus.reset(new FOCUSMould(AttrKey::FOCUS_TYPE::FOCUS_LARGE, AttrKey::FOCUS_SMALL, AttrKey::FOCUS_LARGE, 1)); m_MECHUnit.m_AECField.reset(new AECFIELDMould(0, 0, 111, 1)); //stitching parameter m_MECHUnit.m_StitchHeight.reset(new StitchHeightMould(0, 0, 1000, 1)); m_MECHUnit.m_StitchLength.reset(new StitchLengthMould(0, 0, 1000, 1)); m_MECHUnit.m_StitchOverLap.reset(new StitchOverLapMould(0, 0, 1000, 1)); m_MECHUnit.m_SID.reset(new SIDMould(0, 0, 10000, 1)); m_MECHUnit.m_StitchPID.reset(new StitchPIDMould(0, 0, 1000, 1)); m_MECHUnit.m_StitchDirection.reset(new StitchDirectionMould(AttrKey::STITCHDIR_TopToBottom, AttrKey::STITCHDIR_TopToBottom, AttrKey::STITCHDIR_RightToLeft, 1)); m_MECHUnit.m_StitchType.reset(new StitchTypeMould(AttrKey::STITCHTYPE_AutomaticTranslation, AttrKey::STITCHTYPE_AutomaticTranslation, AttrKey::STITCHTYPE_ManualAngle, 1)); m_MECHUnit.m_StitchStepLength.reset(new StitchStepLengthMould(0, 0, 1000, 1)); //normal parameter m_MECHUnit.m_FID.reset(new FIDMould(0, 0, 10000, 1)); m_MECHUnit.m_TubeAngle.reset(new TubeAngleMould(0, -180, 180, 1)); m_MECHUnit.m_FPDPosition.reset(new FPDPositionMould(0, 0, 100, 1)); m_MECHUnit.m_PatientSize.reset(new PATIENTSIZEMould(0, 0, 10, 1)); m_MECHUnit.m_PostionNumber.reset(new POSITIONNUMBERMould(0, 0, 10000, 1)); m_Collimator.fHeight = 0; m_Collimator.fWidth = 0; m_MSGUnit.reset(new nsDetail::MSGUnit(center, MechUnitType)); Delivermodule.InitSendModle(this ,&ProcessClientData, WriteLog); Delivermodule.SetPriority(1, false, 150, false); //type=1时,需要等ACK if (m_GenConfig.GetKeyCount("ConvertFlag") > 0) m_ConvertFlag = (int)m_GenConfig["ConvertFlag"]; else m_ConvertFlag = 0; if (m_GenConfig.GetKeyCount("OTCType") > 0) m_strOTCType = (string)m_GenConfig["OTCType"]; else m_strOTCType = ""; //配置响应操作对照表 OnCallBack(); //将机架可以对外提供的指令注册集进行补充 Register(); /*2023 new add:表示初始化完成。*/ string strcommand = "INI"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); } nsMech::OTCStitchDevice::~OTCStitchDevice() { //关闭之前,发送退出指令至机架 mLog::Debug("Send EXIT"); string strcommand = "GEX"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); mLog::Debug(strcommand.c_str()); Sleep(200); Delivermodule.EixtSendModle(); mLog::Info("\n===============log end ===================\n"); } std::string OTCStitchDevice::GetGUID() const { mLog::Debug("\n===============GetGUID : {$} ===================\n", MechUnitType); return MechUnitType; } void nsMech::OTCStitchDevice::Register() { auto Disp = &Dispatch; superMech::RegisterStitchingControl(Disp); Disp->Get.Push(m_MSGUnit->GetKey().c_str(), [this](std::string& out) { out = m_MSGUnit->JSGet(); return RET_STATUS::RET_SUCCEED; }); } int nsMech::OTCStitchDevice::FormatCommand(string& command) { mLog::Debug("FormatCommand:str[{$}]", command.c_str()); int size = command.length(); if (size == 0) //发送命令字节为0 { return -1; } int checknum = 0; for (int i = 0; i < size; i++) { checknum += command[i]; } checknum = checknum + (0x02) + (0x03); char xorResult = checknum & 0xFF; command = char(OTCStitch_STX) + command; command += char(OTCStitch_ETX); command += (char)(xorResult); return static_cast(command.length()); } int nsMech::OTCStitchDevice::FormatCommand(string inuputcommand, char* poutputcommand) { mLog::Debug("FormatCommand:char[{$}]", inuputcommand.c_str()); int size = inuputcommand.length();// command.GetLength(); if (size == 0) //发送命令字节为0 { return -1; } int checknum = 0; for (int i = 0; i < size; i++) { checknum += inuputcommand[i]; } checknum = checknum + (OTCStitch_STX)+(OTCStitch_ETX); char xorResult = checknum & 0xFF; poutputcommand[0] = OTCStitch_STX; for (int i = 1; i < size + 1; i++) { poutputcommand[i] = inuputcommand[i - 1]; } poutputcommand[size + 1] = 3; poutputcommand[size + 2] = xorResult; //return static_cast(strlen(command)); return size + 3; } void nsMech::OTCStitchDevice::FireNotify(std::string key, std::string content) { EventCenter->OnNotify(1, key, content); } void nsMech::OTCStitchDevice::FireNotify(std::string key, int content) { std::string str = std::format("{:d}", content); m_EventCenter->OnNotify(1, key, str); } void nsMech::OTCStitchDevice::FireErrorMessage(const bool Act, const int Code, const char* ResInfo) { string ErrorCode("OTC_ERR_"); ErrorCode += std::to_string(Code); int level = OTC_MG_REGULATION_LEVEL::REG_ERRO; if (Act) { mLog::Error("add {$}:{$}", ErrorCode.c_str(), ResInfo); m_MSGUnit->AddErrorMessage(ErrorCode.c_str(), level, ResInfo); } else { mLog::Error("del {$}:{$}", ErrorCode.c_str(), ResInfo); m_MSGUnit->DelErrorMessage(ErrorCode.c_str(), level, ResInfo); } } void nsMech::OTCStitchDevice::FireWarnMessage(const bool Act, const int Code, const char* ResInfo) { string ErrorCode("OTC_WAR_"); ErrorCode += std::to_string(Code); int level = OTC_MG_REGULATION_LEVEL::REG_WARN; if (Act) { mLog::Error("add {$}:{$}", ErrorCode.c_str(), ResInfo); m_MSGUnit->AddWarnMessage(ErrorCode.c_str(), level, ResInfo); } else { mLog::Error("del {$}:{$}", ErrorCode.c_str(), ResInfo); m_MSGUnit->DelWarnMessage(ErrorCode.c_str(), level, ResInfo); } } void __stdcall nsMech::OTCStitchDevice::ProcessClientData(const char* pData, unsigned long nDataLength, void* lparam) { nsMech::OTCStitchDevice* h = (nsMech::OTCStitchDevice*)lparam; mLog::Debug("==OUT==: [{$}]", pData); if (h->m_SCF) { //此处有一个bug,当校验和是零的时候,转为string,会截断。相当于少发送一位数据。所以此处需要判断,并主动添加。 //0x03结尾的,并且不是0303的(因为0303)很可能时正常数据。很大可能缺少结尾。故主动添加 string strData(pData); if (pData[nDataLength - 1] == 0x03 && pData[nDataLength - 2] != 0x03) { strData[nDataLength] = 0; nDataLength += 1; mLog::Debug("==OUT==:jk++:xoresult is zero,so add zero at the end."); } int retLength; h->m_SCF.Lock(msTimeOut_Lock) .SendPacket(strData.c_str(), strData.length(), OTCStitch_TIMEOUTVALUE, retLength); Sleep(OTCStitch_TIMEOUTVALUE); } } void __stdcall nsMech::OTCStitchDevice::WriteLog(const char* pData, nsSerialGPM::LOG_V2_LEVEL level) { switch (level) { case 0: case 1: mLog::Error(pData); break; case 2: mLog::Warn(pData); break; case 3: mLog::Info(pData); break; default: break; } } void OTCStitchDevice::OnCallBack() { mLog::Info("Enter OnCallBack"); auto HWNotProcess = [](const char* value, int length) -> void { mLog::Warn(" This commands didn't need to process!"); }; auto HWUCS = [this](const char* value, int length) -> void { //assert(value && length >= 3); int ret = atoi(value); if (ret) { m_bStitchingInProgress = false; mLog::Debug("Stitch cancle"); if(m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_CANCEL)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); } else { //是否通知上层报错 mLog::Debug("Stitch cancle failed"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_ERR)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); } }; auto HWUER = [this](const char* value, int length) -> void { //assert(value && length >= 3); int errorcode = atoi(value); FireErrorMessage(true, errorcode, "unknown"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_ERR)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUEX = [this](const char* value, int length) -> void { //assert(value && length >= 3); int ret = atoi(value); if (ret) { mLog::Debug("Extra image number"); } else { //是否通知上层报错 mLog::Debug("Extra image number failed"); } }; auto HWUSA = [this](const char* value, int length) -> void { //assert(value && length >= 3); mLog::Debug("accept this image"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_Accept_Image)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUSC = [this](const char* value, int length) -> void { //assert(value && length >= 3); m_nCurrentImage = atoi(value); mLog::Debug("Current image is [{$}],Total image is [{$}]", m_nCurrentImage, m_nImageCount); FireNotify(AttrKey::CURRENTIMAGENUMBER, m_nCurrentImage); //if (m_nCurrentImage == m_nImageCount) //{ // mLog::Debug("Total image is [{$}]", m_nImageCount); // //EndStitching(); //} }; auto HWUSD = [this](const char* value, int length) -> void { //assert(value && length >= 3); if (UP_TO_DOWN == m_MECHUnit.m_StitchDirection->Get()) { m_MECHUnit.m_StitchDirection->Update(AttrKey::STITCHDIR_TopToBottom); } else if (DOWN_TO_UP == m_MECHUnit.m_StitchDirection->Get()) { if(m_MECHUnit.m_StitchDirection->Update(AttrKey::STITCHDIR_BottomToTop)) FireNotify(AttrKey::STITCHDIRECTION, m_MECHUnit.m_StitchDirection->JSGet()); } else { //default if (m_MECHUnit.m_StitchDirection->Update(AttrKey::STITCHDIR_TopToBottom)) FireNotify(AttrKey::STITCHDIRECTION, m_MECHUnit.m_StitchDirection->JSGet()); } mLog::Debug("stitch direction is[{$}]", m_MECHUnit.m_StitchDirection->Get()); }; auto HWUSE = [this](const char* value, int length) -> void { //assert(value && length >= 3); m_bStitchingInProgress = false; mLog::Debug("stitch end"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_END)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUSJ = [this](const char* value, int length) -> void { //assert(value && length >= 3); mLog::Debug("reject this image"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_Reject_Image)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUSR = [this](const char* value, int length) -> void { //assert(value && length >= 3); mLog::Debug("stitch resart"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_RESTART)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUSM = [this](const char* value, int length) -> void { //assert(value && length >= 3); mLog::Debug("stitch moving"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_MOVING)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUSN = [this](const char* value, int length) -> void { //assert(value && length >= 3); m_nImageCount = atoi(value); mLog::Debug("Total image is [{$}]", m_nImageCount); FireNotify(AttrKey::TOTALIMAGECOUNT, m_nImageCount); }; auto HWUSP = [this](const char* value, int length) -> void { //assert(value && length >= 3); string strReadString = std::format("{:s}", value); m_nImageCount = atoi(strReadString.substr(0, 2).c_str()); //m_nCurrentImage = 1; mLog::Debug("stitch setup"); //if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_STANDBY)) // FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUSS = [this](const char* value, int length) -> void { //assert(value && length >= 3); mLog::Debug("stitch start"); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_START)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); }; auto HWUST = [this](const char* value, int length) -> void { //assert(value && length >= 3); int nTemp = atoi(value); switch (nTemp) { case 1://Stitch Start { if (m_bStitchingInProgress == false) { m_bStitchingInProgress = true; } mLog::Debug("StitchingState:[{$}]->STITCHSTATE_START", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_START)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); break; } case 2://Stitch need to move { if (m_bStitchingInProgress) { mLog::Debug("StitchingState:[{$}]->STITCHSTATE_NEED_MOVE", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_NEED_MOVE)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); if (m_nCurrentImage == m_nImageCount) { EndStitching(); } } break; } case 3://Moving { if (m_bStitchingInProgress) { mLog::Debug("StitchingState:[{$}]->STITCHSTATE_MOVING", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_MOVING)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); if (m_nCurrentImage == 1) { mLog::Debug("First image, Moving to init position"); } else { mLog::Debug("Moving to next position"); } } break; } case 4://Stitch Ready for exposure { if (m_bStitchingInProgress) { mLog::Debug("StitchingState:[{$}]->STITCHSTATE_READY", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_READY)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); mLog::Debug("Ready for exposure"); } break; } case 5://Stitch End { if (m_bStitchingInProgress) { m_bStitchingInProgress = false; mLog::Debug("StitchingState:[{$}]->STITCHSTATE_END", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_END)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); } break; } case 6://Setup Parameter receive { if (m_bStitchingInProgress == false) { m_bStitchingInProgress = true; } mLog::Debug("StitchingState:[{$}]->STITCHSTATE_INIT", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_INIT)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); break; } case 7://Setup stitch ok { if (m_bStitchingInProgress == false) { m_bStitchingInProgress = true; } mLog::Debug("StitchingState:[{$}]->STITCHSTATE_STANDBY", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_STANDBY)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); break; } case 8://Setup stitch fail { mLog::Debug("StitchingState:[{$}]->STITCHSTATE_ERR", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_ERR)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); mLog::Debug("Setup stitch fail"); break; } case 9://Reach to the initial position { if (m_bStitchingInProgress) { mLog::Debug("StitchingState:[{$}]->STITCHSTATE_REACH_INIT", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_REACH_INIT)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); mLog::Debug("Reach to the initial position"); } break; } case 10://Reach to the next position { if (m_bStitchingInProgress) { mLog::Debug("StitchingState:[{$}]->STITCHSTATE_REACH_NEXT", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_REACH_NEXT)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); mLog::Debug("Reach to the next position"); } break; } case 11://Reach to the Extra position { if (m_bStitchingInProgress) { mLog::Debug("StitchingState:[{$}]->STITCHSTATE_REACH_EXTRA", m_MECHUnit.m_StitchingState->Get()); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_REACH_EXTRA)) FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->JSGet()); mLog::Debug("Reach to the Extra position"); } break; } } }; auto HWUWN = [this](const char* value, int length) -> void { //assert(value && length >= 3); int warncode = atoi(value); FireWarnMessage(true, warncode, "unknown"); }; auto HWSID = [this](const char* value, int length) -> void { //assert(value && length >= 3); int nSID = atoi(value); if (m_MECHUnit.m_SID->Get() != nSID) { mLog::Debug("SID:[{$}]->[{$}]", m_MECHUnit.m_SID->Get(), nSID); if(m_MECHUnit.m_SID->Update(nSID)) FireNotify(AttrKey::SID, m_MECHUnit.m_SID->JSGet()); } else { //do nothing. } }; auto HWTAG = [this](const char* value, int length) -> void//球管角度 { //assert(value && length >= 3); int nTubeAngle = atoi(value); mLog::Debug("TubeAngle:[{$}]->[{$}]", m_MECHUnit.m_TubeAngle->Get(), nTubeAngle); if(m_MECHUnit.m_TubeAngle->Update(nTubeAngle)) FireNotify(AttrKey::TUBEANGLE, m_MECHUnit.m_TubeAngle->JSGet()); }; auto HWGPP = [this](const char* value, int length) -> void//位置码 { //assert(value && length >= 3); int nPositionCode = atoi(value); mLog::Debug("PositionNumber:[{$}]->[{$}]", m_MECHUnit.m_PostionNumber->Get(), nPositionCode); m_MECHUnit.m_PostionNumber->Update(nPositionCode); FireNotify(AttrKey::POSITIONNUMBER, m_MECHUnit.m_PostionNumber->JSGet()); }; auto HWFID = [this](const char* value, int length) -> void//床台到地面的距离 { //assert(value && length >= 3); int nFID = atoi(value); mLog::Debug("FID:[{$}]->[{$}]", m_MECHUnit.m_FID->Get(), nFID); m_MECHUnit.m_FID->Update(nFID); FireNotify(AttrKey::FID, m_MECHUnit.m_FID->JSGet()); }; auto HWDTP = [this](const char* value, int length) -> void//探测器位置 { //assert(value && length >= 3); int nDtPosition = atoi(value); mLog::Debug("FPDPosition:[{$}]->[{$}]", m_MECHUnit.m_FPDPosition->Get(), nDtPosition); m_MECHUnit.m_FPDPosition->Update(nDtPosition); FireNotify(AttrKey::FPDPOSITION, m_MECHUnit.m_FPDPosition->JSGet()); }; auto HWGKV = [this](const char* value, int length) -> void//KV { //assert(value && length >= 3); string strReadString = std::format("{:s}", value); if (strReadString.substr(0, 1) == "+") { mLog::Debug("KV:+"); } else if (strReadString.substr(0, 1) == "-") { mLog::Debug("KV:-"); } else { int temp = atoi(value); mLog::Debug("KV:[{$}]->[{$}]", m_MECHUnit.m_KV->Get(),temp); m_MECHUnit.m_KV->Update(temp); } }; auto HWGMA = [this](const char* value, int length) -> void//MA { //assert(value && length >= 3); string strReadString = std::format("{:s}", value); if (strReadString.substr(0, 1) == "+") { mLog::Debug("MA:+"); } else if (strReadString.substr(0, 1) == "-") { mLog::Debug("MA:-"); } else { int temp = atoi(value); float ftemp = (float)temp / 100; mLog::Debug("MA:[{$}]->[{$}]", m_MECHUnit.m_MA->Get(), ftemp); m_MECHUnit.m_MA->Update(ftemp); } }; auto HWGMS = [this](const char* value, int length) -> void//MS { //assert(value && length >= 3); string strReadString = std::format("{:s}", value); if (strReadString.substr(0, 1) == "+") { mLog::Debug("MS:+"); } else if (strReadString.substr(0, 1) == "-") { mLog::Debug("MS:-"); } else { int temp = atoi(value); float ftemp = (float)temp / 10; mLog::Debug("MS:[{$}]->[{$}]", m_MECHUnit.m_MS->Get(), ftemp); m_MECHUnit.m_MS->Update(ftemp); } }; auto HWGMX = [this](const char* value, int length) -> void//MAS { //assert(value && length >= 3); string strReadString = std::format("{:s}", value); if (strReadString.substr(0, 1) == "+") { mLog::Debug("MAS:+"); } else if (strReadString.substr(0, 1) == "-") { mLog::Debug("MAS:-"); } else { int temp = atoi(value); float ftemp = (float)temp / 100; mLog::Debug("MAS:[{$}]->[{$}]", m_MECHUnit.m_MAS->Get(), ftemp); m_MECHUnit.m_MAS->Update(ftemp); } }; auto HWGFI = [this](const char* value, int length) -> void//AEC filed { //assert(value && length >= 3); int temp = atoi(value); mLog::Debug("AEC filed:[{$}]->[{$}]", m_MECHUnit.m_AECField->Get(), temp); m_MECHUnit.m_AECField->Update(temp); }; auto HWGFO = [this](const char* value, int length) -> void//FO { //assert(value && length >= 3); int temp = atoi(value); mLog::Debug("Focus:[{$}]->[{$}]", m_MECHUnit.m_Focus->Get(), temp); m_MECHUnit.m_Focus->Update(temp); }; auto HWGWS = [this](const char* value, int length) -> void//work station { //assert(value && length >= 3); int temp = atoi(value); mLog::Debug("work station:[{$}]->[{$}]", m_MECHUnit.m_WS->Get(), temp); m_MECHUnit.m_WS->Update(temp); }; auto HWGET = [this](const char* value, int length) -> void//tech mode { //assert(value && length >= 3); int temp = atoi(value); mLog::Debug("tech mode:[{$}]->[{$}]", m_MECHUnit.m_Techmode->Get(), temp); m_MECHUnit.m_Techmode->Update(temp); }; auto HWGFN = [this](const char* value, int length) -> void//AEC density { //assert(value && length >= 3); int temp = atoi(value); mLog::Debug("AEC density:[{$}]->[{$}]", m_MECHUnit.m_AECDensity->Get(), temp); m_MECHUnit.m_AECDensity->Update(temp); }; auto HWGCL = [this](const char* value, int length) -> void { //assert(value && length >= 3); string strReadString = std::format("{:s}", value); int nHeight = atoi(strReadString.substr(0, 3).c_str()); int nWidth = atoi(strReadString.substr(3, 3).c_str()); mLog::Debug("Collimator:Height[{$}]->[{$}],Width[{$}]->[{$}]", m_Collimator.fHeight, nHeight, m_Collimator.fWidth, nWidth); m_Collimator.fHeight = nHeight; m_Collimator.fWidth = nWidth; FireNotify("XSize", m_Collimator.fHeight); FireNotify("YSize", m_Collimator.fWidth); }; auto HWGPS = [this](const char* value, int length) -> void { //assert(value && length >= 3); /* if (strPSize.MakeUpper() == "SMALL") { strPS = "2"; } else if (strPSize.MakeUpper() == "MEDIUM") { strPS = "3"; } else if (strPSize.MakeUpper() == "LARGE") { strPS = "4"; } else if (strPSize.MakeUpper() == "PAEDIATRIC") { strPS = "1"; } */ int temp = atoi(value); mLog::Debug("PatientSize:[{$}]->[{$}]", m_MECHUnit.m_PatientSize->Get(), temp); if(m_MECHUnit.m_PatientSize->Update(temp)) FireNotify(AttrKey::PATIENTSIZE, m_MECHUnit.m_PatientSize->JSGet()); }; // 有部分前缀是包含关系, 长的包含短的, 因此长的在前面, 短的在后面 // Device 是个短寿命对象, 而 arFrame 是静态变量 !!! // 因此, 在添加到 arFrame 之前, 务必先清零 !!! arFrame.clear(); arFrame.push_back(tFrameMapping("NULL", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("UCS", 3, HWUCS)); arFrame.push_back(tFrameMapping("UER", 3, HWUER)); arFrame.push_back(tFrameMapping("UEX", 3, HWUEX)); arFrame.push_back(tFrameMapping("USA", 3, HWUSA)); arFrame.push_back(tFrameMapping("USC", 3, HWUSC)); arFrame.push_back(tFrameMapping("USD", 3, HWUSD)); arFrame.push_back(tFrameMapping("USE", 3, HWUSE)); arFrame.push_back(tFrameMapping("USJ", 3, HWUSJ)); arFrame.push_back(tFrameMapping("USR", 3, HWUSR)); arFrame.push_back(tFrameMapping("USM", 3, HWUSM)); arFrame.push_back(tFrameMapping("USN", 3, HWUSN)); arFrame.push_back(tFrameMapping("USP", 3, HWUSP)); arFrame.push_back(tFrameMapping("USS", 3, HWUSS)); arFrame.push_back(tFrameMapping("UST", 3, HWUST)); arFrame.push_back(tFrameMapping("UWN", 3, HWUWN)); arFrame.push_back(tFrameMapping("SID", 3, HWSID)); arFrame.push_back(tFrameMapping("TAG", 3, HWTAG)); arFrame.push_back(tFrameMapping("GPP", 3, HWGPP)); arFrame.push_back(tFrameMapping("FID", 3, HWFID)); arFrame.push_back(tFrameMapping("DTP", 3, HWDTP)); arFrame.push_back(tFrameMapping("GKV", 3, HWGKV)); arFrame.push_back(tFrameMapping("GMA", 3, HWGMA)); arFrame.push_back(tFrameMapping("GMS", 3, HWGMS)); arFrame.push_back(tFrameMapping("GMX", 3, HWGMX)); arFrame.push_back(tFrameMapping("GFI", 3, HWGFI)); arFrame.push_back(tFrameMapping("GFO", 3, HWGFO)); arFrame.push_back(tFrameMapping("GWS", 3, HWGWS)); arFrame.push_back(tFrameMapping("GET", 3, HWGET)); arFrame.push_back(tFrameMapping("GFN", 3, HWGFN)); arFrame.push_back(tFrameMapping("GCL", 3, HWGCL)); arFrame.push_back(tFrameMapping("GPS", 3, HWGPS)); } void nsMech::OTCStitchDevice::Convert(const char* strIn, string& strOut, int sourceCodepage, int targetCodepage) { int len = lstrlen(strIn); int unicodeLen = MultiByteToWideChar(sourceCodepage, 0, strIn, -1, NULL, 0); wchar_t* pUnicode; pUnicode = new wchar_t[unicodeLen + 1]; memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t)); MultiByteToWideChar(sourceCodepage, 0, strIn, -1, (LPWSTR)pUnicode, unicodeLen); BYTE* pTargetData = NULL; int targetLen = WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char*)pTargetData, 0, NULL, NULL); pTargetData = new BYTE[targetLen + 1]; memset(pTargetData, 0, targetLen + 1); WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char*)pTargetData, targetLen, NULL, NULL); strOut = std::format("{:s}", (char*)pTargetData); delete pUnicode; delete pTargetData; } RET_STATUS nsMech::OTCStitchDevice::SetPatientInfo(ResDataObject& pParam) //注册完病人信息后调用 { mLog::Debug("Enter SetPatientInfo"); //m_sPATIENTInfo = sPATIENT; string strcommand{""}; string strPName{ "" }; if (m_ConvertFlag != 1) { Convert(m_sPATIENTInfo.strPatientName.c_str(), strPName, CP_ACP, CP_UTF8); } else { strPName = m_sPATIENTInfo.strPatientName; mLog::Debug("m_ConvertFlag = 1, don't do any code switch"); } if (strPName == "") { strPName = " "; } mLog::Debug("PatientName[{$}]", strPName.c_str()); strcommand = std::format("PIN{:s}", strPName.c_str()); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); string strSex = m_sPATIENTInfo.strSex.substr(0, 1); transform(strSex.begin(), strSex.end(), strSex.begin(), ::toupper); if (strSex == "") { strSex = " "; } mLog::Debug("Sex[{$}]", strSex.c_str()); string strAge{ "" }; int age = 0; if (m_sPATIENTInfo.strAge.find('D',0) != string::npos) { age = atoi(m_sPATIENTInfo.strAge.c_str()) / 365; } else if (m_sPATIENTInfo.strAge.find('M',0) != string::npos) { age = atoi(m_sPATIENTInfo.strAge.c_str()) / 12; } else { age = atoi(m_sPATIENTInfo.strAge.c_str()); } strAge = std::format("{:03d}", age); if (strAge == "") { strAge = " "; } mLog::Debug("Age[{$}]", strAge.c_str()); string strPSize = m_sPATIENTInfo.strPatientSize; //Large\Medium\Small\Paediatric string strPS = "3"; transform(strPSize.begin(), strPSize.end(), strPSize.begin(), ::toupper); if (strPSize == "SMALL") { strPS = "2"; } else if (strPSize == "MEDIUM") { strPS = "3"; } else if (strPSize == "LARGE") { strPS = "4"; } else if (strPSize == "PAEDIATRIC") { strPS = "1"; } if (strPS == "") { strPS = " "; } mLog::Debug("PatientSize[{$}]", strPS.c_str()); strcommand = std::format("PIF{:s}{:s}{:s}", strSex.c_str(), strPS.c_str(), strAge.c_str()); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); string strPID = m_sPATIENTInfo.strPatientID; if (strPID == "") { strPID = " "; } mLog::Debug("PatientID[{$}]", strPID.c_str()); strcommand = std::format("PID{:s}", strPID.c_str()); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); string strViewDescription{ "" }; if (m_ConvertFlag != 1) { Convert(m_sPATIENTInfo.strStudyDescription.c_str(), strViewDescription, CP_ACP, CP_UTF8); } else { strViewDescription = m_sPATIENTInfo.strStudyDescription; } if (strViewDescription == "") { strViewDescription = " "; } mLog::Debug("StudyDescription[{$}]", strViewDescription.c_str()); strcommand = std::format("PSD{:s}", strViewDescription.c_str()); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetViewInfo(ResDataObject& pParam) //假设2个体位View { mLog::Debug("Enter SetViewInfo:ListSize"); m_tempProcedureViewList.clear(); //m_tempProcedureViewList = tempProcedureViewList; string strcommand; strcommand = std::format("VLC{:03d}", m_tempProcedureViewList.size()); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); string strViewDescription; for (int i = 0; i < m_tempProcedureViewList.size(); i++) { //mLog::Debug("ViewDescription[{$}]", m_tempProcedureViewList[i].strViewDescription); strViewDescription.clear(); if (m_ConvertFlag != 1) { Convert(m_tempProcedureViewList[i].strViewDescription.c_str(), strViewDescription, CP_ACP, CP_UTF8); } else { strViewDescription = m_tempProcedureViewList[i].strViewDescription; mLog::Debug("Reserved2 = 1, don't do any code switch"); } mLog::Debug("ViewDescription[{$}]", strViewDescription.c_str()); strcommand = std::format("VLD{:03d}{:s}", i, strViewDescription.c_str()); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetStudyInfo(ResDataObject& pParam) { mLog::Debug("Enter SetStudyInfo"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetSID(float value) { mLog::Debug("Enter SetSID[{$}]", value); string strcommand = std::format("SID{:03d}", value); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::BeginStitching() { mLog::Debug("Enter BeginStitching"); string strcommand = "USS"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::EndStitching() { mLog::Debug("Enter EndStitching"); string strcommand = "USE"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetupStitching(string& value) { ResDataObject json; json.decode(value.c_str()); int nInitHeight = atoi(((string)json[AttrKey::STITCHHEIGHT]).c_str()); int nTargetLength = atoi(((string)json[AttrKey::STITCHLENGTH]).c_str()); int nOverlap = atoi(((string)json[AttrKey::STITCHOVERLAP]).c_str()); int nSID = atoi(((string)json[AttrKey::SID]).c_str()); int nPID = atoi(((string)json[AttrKey::STITCHPID]).c_str()); int nDirection = atoi(((string)json[AttrKey::STITCHDIRECTION]).c_str()); int nStitchType = atoi(((string)json[AttrKey::STITCHTYPE]).c_str()); mLog::Debug("Enter SetupStitching:[InitHeight:{$},TotalLength:{$},Overlap:{$},SID:{$},TID:{$},Direction:{$},StitchType:{$}]", nInitHeight, nTargetLength, nOverlap, nSID, nPID, nDirection, nStitchType); if (nInitHeight <= 0 || nTargetLength <= 0 || nOverlap <= 0 || nSID <= 0) { return RET_STATUS::RET_FAILED; } if (nDirection)//up down, now just support two direction { nDirection = 1; } else { nDirection = 2;//down up } m_MECHUnit.m_StitchDirection->Update(nDirection); if (nStitchType == 0) { nStitchType = 0;//line } else { nStitchType = 1;// Angle } m_MECHUnit.m_StitchType->Update(nStitchType); int nStitchingLength = nTargetLength;//length for stitching int nTID = 10; int nStitchingStepLength = 43 * (nSID - nTID) / nSID - nOverlap; m_MECHUnit.m_StitchHeight->Update(nInitHeight); m_MECHUnit.m_StitchLength->Update(nStitchingLength); m_MECHUnit.m_StitchOverLap->Update(nOverlap); m_MECHUnit.m_StitchStepLength->Update(nStitchingStepLength); mLog::Debug("StitchingStepLength[{$}]cm, StitchingLength[{$}]cm", nStitchingStepLength, nStitchingLength); m_nImageCount = nStitchingLength / nStitchingStepLength; if (m_nImageCount < 2) { m_nImageCount = 2; mLog::Debug("The image count is not correct"); } else if (m_nImageCount > 4) { m_nImageCount = 4; mLog::Debug("The image count is not correct"); } FireNotify(AttrKey::TOTALIMAGECOUNT, m_nImageCount); m_nCurrentImage = 0; FireNotify(AttrKey::CURRENTIMAGENUMBER, m_nCurrentImage); mLog::Debug("Image index[{$}], total images[{$}]", m_nCurrentImage, m_nImageCount); string strcommand = ""; strcommand = std::format("USP{:02d}{:02d}{:d}{:02d}{:03d}{:03d}{:03d}", m_nImageCount, nDirection, nStitchType, nOverlap, nInitHeight, nSID, nTargetLength); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); //strcommand="SS"; //FormatCommand(strcommand); //ProcessCommand(strcommand,0); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::AcceptStitchingImage() { mLog::Debug("Enter AcceptStitchingImage"); string strcommand = "USA"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); if (m_nImageCount == m_nCurrentImage) CompleteStitching(); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::RejectStitchingImage() { mLog::Debug("Enter RejectStitchingImage"); string strcommand = "USJ"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::CancelStitching() { mLog::Debug("Enter CancelStitching"); if (m_bStitchingInProgress) { string strcommand = "UCS"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::CompleteStitching() { mLog::Debug("Enter CompleteStitching"); if (m_bStitchingInProgress) { string strcommand = "USE"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::NewExtraView() { mLog::Debug("Enter NewExtraView"); string strcommand = "UEX"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::RepeatStitching() { mLog::Debug("Enter RepeatStitching"); if (m_bStitchingInProgress)//如果还没有取消或者结束拼接,则先取消拼接再重新开始 CancelStitching(); string strcommand = "USR"; FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 0); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetAutoPosiitonNo(int nPN) { mLog::Debug("Enter SetAutoPosiitonNo[{$}]", nPN); string strcommand = std::format("GPP{:03d}", nPN); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetExpEnable(bool nExpEnabled) { mLog::Debug("Enter SetExpEnable[{$}]", nExpEnabled); string strcommand = std::format("PRX{:d}", nExpEnabled); FormatCommand(strcommand); //add by wxx for DEL at 20231026:解决DEL拼接时系统不ready但机架一直使能 Delivermodule.ProcessCommand(strcommand,1); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetKV(int nKV) { mLog::Debug("Enter SetKV[{$}]", nKV); string strcommand = std::format("GKV{:03d}", nKV); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_nKV = nKV; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetMA(float fMA) { mLog::Debug("Enter SetMA[{$}]", fMA); int temp = fMA * 100; string strcommand = std::format("GMA{:06d}", temp); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_fMA = fMA; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetMS(float fMS) { mLog::Debug("Enter SetMS[{$}]", fMS); int temp = fMS * 10; string strcommand = std::format("GMS{:06d}", temp); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_fMS = fMS; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetMAS(float fMAS) { mLog::Debug("Enter SetMAS[{$}]", fMAS); int temp = fMAS * 100; string strcommand = std::format("GMX{:06d}", temp); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_fMAS = fMAS; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetWS(int nWS) { mLog::Debug("Enter SetWS[{$}]", nWS); if (nWS != m_MECHUnit.m_WS->Get()) { string strcommand = std::format("GWS{:01d}", nWS); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_nWS = nWS; //第一次会设置,第二次,就会跳过。除非发生了变化。 //此处有一个问题,因为ws 没有了返回值,我一旦设置,就认为成功。所以我把该值上传. 记不得当初是怎么跟他们协商的了。 } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetFO(int nFO) { mLog::Debug("Enter SetFO[{$}]", nFO); string strcommand = std::format("GFO{:01d}", nFO); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_nFO = nFO; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetTechMode(int nET) { mLog::Debug("Enter SetTechMode[{$}]", nET); if (nET < 0 || nET>2) { return RET_STATUS::RET_SUCCEED; } string strcommand = std::format("GET{:01d}", nET); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_nET = nET; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetAECField(int nAECFieldSel) { mLog::Debug("Enter SetAECField[{$}]", nAECFieldSel); string strcommand = std::format("GFI{:03d}", nAECFieldSel); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_nAECField = nAECFieldSel; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetDensity(float fAECDensity) { mLog::Debug("Enter SetDensity[{$}]", fAECDensity); if (fAECDensity != m_MECHUnit.m_AECDensity->Get()) { int temp = fAECDensity; int a, b; if (temp < 0) { a = 0; } else { a = 1; } b = abs(temp); string strcommand = std::format("GFN{:01d}{:01d}", a, b); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); //m_nAECDensity = temp; } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetCollimator(ECOM_COLLIMATOR_INFO& curCollimator) { float fWidth = curCollimator.fWidth; float fHeight = curCollimator.fHeight; mLog::Debug("SetCollimator:Width[{$}],Height[{$}]", fWidth, fHeight); string strcommand = std::format("GCL{:03d}{:03d}", (int)fHeight, (int)fWidth); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::OTCStitchDevice::SetFilter(int nFilter) { mLog::Debug("Enter SetFilter[{$}]", nFilter); string strcommand = std::format("GFL{:03d}", nFilter); FormatCommand(strcommand); Delivermodule.ProcessCommand(strcommand, 1); return RET_STATUS::RET_SUCCEED; } //----------------------------------------------------------------------------- // OTCStitchDriver //----------------------------------------------------------------------------- nsMech::OTCStitchDriver::OTCStitchDriver() { m_bDemoInitDataFlag = false; m_pDriGenDev = nullptr; m_pAttribute.reset(new ResDataObject()); m_pDescription.reset(new ResDataObject()); } nsMech::OTCStitchDriver::~OTCStitchDriver() { } auto nsMech::OTCStitchDriver::CreateDevice(int index) -> std::unique_ptr { mLog::Debug("Enter CreateDevice[{$}]", index); if (index == 0) { m_pDriGenDev = new OTCStitchDevice(EventCenter, m_SCF, m_ConfigFileName); auto dev = std::unique_ptr(new IODevice(m_pDriGenDev)); return dev; } unique_ptr dev; return dev; } void nsMech::OTCStitchDriver::FireNotify(int code, std::string key, std::string content) { mLog::Debug("Enter FireNotify"); EventCenter->OnNotify(code, key, content); } void nsMech::OTCStitchDriver::Prepare() { string strLogPath = GetProcessDirectory() + R"(\OEMDrivers\Mechanical\Conf\Log4CPP.Config.MECH.xml)"; //Log4CPP::ThreadContext::Map::Set("LogFileName", "Mech.OTCStitch"); Log4CPP::GlobalContext::Map::Set(ECOM::Utility::Hash("LogFileName"), "Mech.OTCStitch"); auto rc = Log4CPP::LogManager::LoadConfigFile(strLogPath.c_str()); mLog::gLogger = Log4CPP::LogManager::GetLogger("Mech.OTCStitch"); m_SCFDllName = GetConnectDLL(m_ConfigFileName); super::Prepare(); } bool nsMech::OTCStitchDriver::Connect() { mLog::Debug("Enter Connect"); ResDataObject Connection = GetConnectParam(m_ConfigFileName); mLog::Info("connections:{$} \n", Connection.encode()); auto erCode = m_SCF.Connect(Connection.encode(), &nsMech::OTCStitchDriver::callbackPackageProcess, SCF_PACKET_TRANSFER, 3000); if (erCode != SCF_ERR::SCF_SUCCEED) return erCode; auto rc = super::Connect(); if (!rc) return 0; return SCF_ERR::SCF_SUCCEED; } void nsMech::OTCStitchDriver::Disconnect() { mLog::Debug("Enter Disconnect"); super::Disconnect(); m_SCF.Disconnect(); } bool nsMech::OTCStitchDriver::isConnected() const { return super::isConnected(); } std::string nsMech::OTCStitchDriver::DriverProbe() { printf("line= %d,%s %s\n", __LINE__, __FUNCTION__, m_ConfigFileName.c_str()); ResDataObject r_config, HardwareInfo; if (r_config.loadFile(m_ConfigFileName.c_str())) { HardwareInfo.add("MajorID", r_config["CONFIGURATION"]["MajorID"]); HardwareInfo.add("MinorID", r_config["CONFIGURATION"]["MinorID"]); HardwareInfo.add("VendorID", r_config["CONFIGURATION"]["VendorID"]); HardwareInfo.add("ProductID", r_config["CONFIGURATION"]["ProductID"]); HardwareInfo.add("SerialID", r_config["CONFIGURATION"]["SerialID"]); } else { HardwareInfo.add("MajorID", "Machine"); HardwareInfo.add("MinorID", "Dr"); HardwareInfo.add("VendorID", "ECOM"); HardwareInfo.add("ProductID", "HF"); HardwareInfo.add("SerialID", "1234"); } string ret = HardwareInfo.encode(); printf("line= %d,%s %s\n", __LINE__, __FUNCTION__, m_ConfigFileName.c_str()); return ret; } bool nsMech::OTCStitchDriver::GetDeviceConfig(std::string& Cfg) { Cfg = m_DeviceConfigSend.encode(); printf("GetDeviceConfig over , %s", Cfg.c_str()); return true; } bool nsMech::OTCStitchDriver::SetDeviceConfig(std::string Cfg) { printf("\n--Func-- SetDeviceConfig %s\n", Cfg.c_str()); ResDataObject DeviceConfig; DeviceConfig.decode(Cfg.c_str()); ResDataObject DescriptionTempEx; DescriptionTempEx = DeviceConfig["DeviceConfig"]["Attribute"]; //mLog::Debug("Attribute:{$}", DescriptionTempEx.encode()); bool bSaveFile = false; //true:重新保存配置文件 string strAccess = ""; for (int i = 0; i < DescriptionTempEx.size(); i++) { string strKey = DescriptionTempEx.GetKey(i); ////mLog::Info("{$}", strKey.c_str()); printf("%s\n", strKey.c_str()); try { if (m_pAttribute->GetFirstOf(strKey.c_str()) >= 0) { strAccess = (string)(*m_pDescription)[strKey.c_str()]["Access"]; if ("RW" == strAccess) { //修改对应配置,在其他单元的配置项要同时调用其修改函数修改真实值 //1. 修改内存中的值,用于给上层发消息 (*m_pAttribute)[strKey.c_str()] = DescriptionTempEx[i]; //2. 拿到Innerkey int nConfigInfoCount = (int)m_Configurations["ConfigToolInfo"].GetKeyCount("AttributeInfo"); ////mLog::Info("nConfigInfoCount {$}", nConfigInfoCount); string strTemp = ""; //存储AttributeKey for (int nInfoIndex = 0; nInfoIndex < nConfigInfoCount; nInfoIndex++) { strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeKey"]; if (strTemp == strKey) { strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["InnerKey"]; break; } } //3. 修改配置文件中的值 if (SetDeviceConfigValue(m_Configurations, strTemp.c_str(), 1, DescriptionTempEx[i])) { //mLog::Debug("SetDeviceConfigValue over"); bSaveFile = true; } } else { ////mLog::Info("{$} is not a RW configuration item", strKey.c_str()); } } else { ////mLog::Info("without this attribute {$}", strKey.c_str()); } } catch (ResDataObjectExption& e) { printf("\nSetDriverConfig crashed: %s\n", e.what()); //mLog::Error("SetDriverConfig crashed: {$}", e.what()); return false; } } if (bSaveFile) { //3. 重新保存配置文件 SaveConfigFile(true); } return true; } bool nsMech::OTCStitchDriver::SaveConfigFile(bool bSendNotify) { m_ConfigAll["CONFIGURATION"] = m_Configurations; bool bRt = m_ConfigAll.SaveFile(m_ConfigFileName.c_str()); ////mLog::Info("SaveConfigFile over {$}", bRt); return true; } bool nsMech::OTCStitchDriver::GetDeviceConfigValue(ResDataObject config, const char* pInnerKey, int nPathID, string& strValue) { printf("line= %d,%s,pInnerKey=%s,nPathID=%d\n", __LINE__, __FUNCTION__, pInnerKey, nPathID); strValue = ""; string strTemp = pInnerKey; if (1 == nPathID) //从DriverConfig路径下每个DPC自己的配置文件读取 { int pos = 0; ResDataObject resTemp = config; while ((pos = strTemp.find_first_of(',')) != string::npos) { string Key = strTemp.substr(0, pos); string TempValue = resTemp[Key.c_str()].encode(); //printf("-TempValue=== %s\n", TempValue.c_str()); resTemp.clear(); resTemp.decode(TempValue.c_str()); strTemp = strTemp.substr(pos + 1, strTemp.length() - pos - 1); //printf("-************--%s\n", strTemp.c_str()); } if (strTemp != "") { strValue = (string)resTemp[strTemp.c_str()]; } else { strValue = (string)resTemp; } } //printf("------------%s\n", strValue.c_str()); return true; } bool nsMech::OTCStitchDriver::SetDeviceConfigValue(ResDataObject& config, const char* pInnerKey, int nPathID, const char* szValue) { string strTemp = pInnerKey; //mLog::Debug("Begin to change {$} item value to {$}", pInnerKey, szValue); printf("\n Begin to change {%s} item value to {%s}\n", pInnerKey, szValue); if (1 == nPathID) //从DriverConfig路径下每个DPC自己的配置文件读取 { try { int pos = 0; ResDataObject* resTemp = &config; while ((pos = strTemp.find_first_of(',')) != string::npos) { string Key = strTemp.substr(0, pos); resTemp = &(*resTemp)[Key.c_str()]; strTemp = strTemp.substr(pos + 1, strTemp.length() - pos - 1); } if (strTemp != "") { (*resTemp)[strTemp.c_str()] = szValue; } else { *resTemp = szValue; } } catch (ResDataObjectExption& e) { //mLog::Error("SetDriverConfigvalue crashed: {$}", e.what()); return false; } } return true; } std::string nsMech::OTCStitchDriver::GetResource() { ResDataObject r_config, temp; if (!temp.loadFile(m_ConfigFileName.c_str())) { return ""; } m_ConfigAll = temp; r_config = temp["CONFIGURATION"]; m_Configurations = r_config; ResDataObject DescriptionTemp; ResDataObject DescriptionSend; ResDataObject m_DescriptionSend; ResDataObject ListTemp; string strTemp = ""; //用于读取字符串配置信息 string strIndex = ""; //用于读取配置信息中的List项 int nTemp = -1; //用于读取整型配置信息 char sstream[10] = { 0 }; //用于转换值 string strValue = ""; //用于存储配置的值 string strType = ""; //用于存储配置的类型 int/float/string... try { //便利ConfigToolInfo 中 所有的AttributeInfo 属性段 int nConfigInfoCount = (int)m_Configurations["ConfigToolInfo"].GetKeyCount("AttributeInfo"); m_pAttribute->clear(); m_pDescription->clear(); for (int nInfoIndex = 0; nInfoIndex < nConfigInfoCount; nInfoIndex++) { DescriptionTemp.clear(); DescriptionSend.clear(); ListTemp.clear(); //AttributeType strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["Type"]; DescriptionTemp.add(ConfKey::DiosType, strTemp.c_str());//DiosGeneratorAttribute DescriptionSend.add(ConfKey::DiosType, strTemp.c_str());//DiosGeneratorAttribute strType = strTemp; //记录配置项的类型 //AttributeKey //1. 根据AttributeType,内部key和配置路径,拿到当前的真实值 strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["InnerKey"]; nTemp = (int)m_Configurations["ConfigToolInfo"][nInfoIndex]["PathID"]; GetDeviceConfigValue(r_config, strTemp.c_str(), nTemp, strValue); //得到strValue的值 //2. 赋值 strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeKey"]; if ("int" == strType) { (*m_pAttribute).add(strTemp.c_str(), atoi(strValue.c_str())); } else if ("float" == strType) { (*m_pAttribute).add(strTemp.c_str(), atoi(strValue.c_str())); } else //其它先按string类型处理 { (*m_pAttribute).add(strTemp.c_str(), strValue.c_str()); } //AttributeAccess strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["Access"]; DescriptionTemp.add(ConfKey::DiosAccess, strTemp.c_str()); DescriptionSend.add(ConfKey::DiosAccess, strTemp.c_str()); //AttributeRangeMin //strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["RangeMin"]; //if (strTemp != "") //不需要的配置项为空 //{ // DescriptionTemp.add(ConfKey::DiosRangeMin, strTemp.c_str()); //} ////AttributeRangeMax //strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["RangeMax"]; //if (strTemp != "") //不需要的配置项为空 //{ // DescriptionTemp.add(ConfKey::DiosRangeMax, strTemp.c_str()); //} //AttributeList nTemp = m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["ListNum"]; if (nTemp > 0) //ListNum不大于0时说明不需要list配置 { for (int nListIndex = 0; nListIndex < nTemp; nListIndex++) { strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["ListInfo"][nListIndex]; auto temKey = std::to_string(nListIndex); ListTemp.add(temKey.c_str(), strTemp.c_str()); } DescriptionTemp.add(ConfKey::DiosList, ListTemp); DescriptionSend.add(ConfKey::DiosList, ListTemp.encode()); } //AttributeRequired strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["Required"]; DescriptionTemp.add(ConfKey::DiosRequired, strTemp.c_str()); DescriptionSend.add(ConfKey::DiosRequired, strTemp.c_str()); //AttributeDefaultValue strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeDescripition"]["DefaultValue"]; if (strTemp != "") //不需要的配置项为空 { DescriptionTemp.add(ConfKey::DiosDefaultValue, strTemp.c_str()); DescriptionSend.add(ConfKey::DiosDefaultValue, strTemp.c_str()); } strTemp = (string)m_Configurations["ConfigToolInfo"][nInfoIndex]["AttributeKey"]; (*m_pDescription).add(strTemp.c_str(), DescriptionTemp); m_DescriptionSend.add(strTemp.c_str(), DescriptionSend.encode()); } } catch (ResDataObjectExption& e) { //mLog::Error("Get config error: {$}", e.what()); return ""; } ResDataObject resDeviceResource; resDeviceResource.add(ConfKey::DiosAttribute, (*m_pAttribute)); resDeviceResource.add(ConfKey::DiosDescription, (*m_pDescription)); ResDataObject DescriptionTempEx; DescriptionTempEx.add(ConfKey::DiosConfig, resDeviceResource); m_DeviceConfig.clear(); m_DeviceConfig = DescriptionTempEx; //mLog::Debug("local ************* get resource over {$}", DescriptionTempEx.encode()); printf("local ************* get resource over %s \n", DescriptionTempEx.encode()); resDeviceResource.clear(); resDeviceResource.add(ConfKey::DiosAttribute, (*m_pAttribute)); resDeviceResource.add(ConfKey::DiosDescription, m_DescriptionSend); DescriptionTempEx.clear(); DescriptionTempEx.add(ConfKey::DiosConfig, resDeviceResource); m_DeviceConfigSend.clear(); m_DeviceConfigSend = DescriptionTempEx; string res = m_DeviceConfigSend.encode(); //mLog::Debug("get resource over {$}", DescriptionTempEx.encode()); printf("************* get resource over %s \n", DescriptionTempEx.encode()); return res; } std::string nsMech::OTCStitchDriver::DeviceProbe() { ResDataObject r_config, HardwareInfo; if (r_config.loadFile(m_ConfigFileName.c_str())) { HardwareInfo.add("MajorID", r_config["CONFIGURATION"]["MajorID"]); HardwareInfo.add("MinorID", r_config["CONFIGURATION"]["MinorID"]); HardwareInfo.add("VendorID", r_config["CONFIGURATION"]["VendorID"]); HardwareInfo.add("ProductID", r_config["CONFIGURATION"]["ProductID"]); HardwareInfo.add("SerialID", r_config["CONFIGURATION"]["SerialID"]); } else { HardwareInfo.add("MajorID", "Machine"); HardwareInfo.add("MinorID", "Dr"); HardwareInfo.add("VendorID", "ECOM"); HardwareInfo.add("ProductID", "HF"); HardwareInfo.add("SerialID", "1234"); } string ret = HardwareInfo.encode(); return ret; } void nsMech::OTCStitchDriver::Dequeue(const char* Packet, DWORD Length) { DecodeFrame(Packet, Length); } PACKET_RET nsMech::OTCStitchDriver::callbackPackageProcess(const char* RecData, DWORD nLength, DWORD& PacketLength) { #if 0 if (nLength > 1) { mLog::Error("receive data_len[{$}]", nLength); for (int i = 0; i < nLength; i++) { if (i != nLength - 1) { mLog::Error("receive data[{$}][{$}]", i, RecData[i]); } else { mLog::Error("receive data[{$}][{$}]", i, RecData[i]); } } } #endif bool bHasHead = false; if (nLength < 1) { PacketLength = 0; //printf("nLength too small, nLength==%d \n", nLength); mLog::Error("nLength too small, nLength=={$}", nLength); return PACKET_USELESS; } else if (nLength > OTCStitch_Com_NormalLen) { PacketLength = nLength; //printf("nLength too big, nLength==%d \n", nLength); mLog::Error("nLength too big, nLength=={$}", nLength); return PACKET_USELESS; } for (DWORD i = 0; i < nLength; i++) { //寻找包头 if (RecData[i] == OTCStitch_STX && RecData[i] == OTCStitch_NAK) { if (i != 0) //包头之前的数据格式不对,全部扔掉 { PacketLength = i; char strtemp[OTCStitch_Com_NormalLen] = { 0 }; memcpy(strtemp, RecData, PacketLength); //printf("==IN unknown format data ==:[%s],UselessDataLength=%d,TotalLength=%d\n", strtemp, PacketLength, nLength); mLog::Error("\n==IN unknown format data ==:[{$}],UselessDataLength={$},TotalLength={$}", strtemp, PacketLength, nLength); return PACKET_USELESS; } else { bHasHead = true; } } //寻找包尾 if (RecData[i] == OTCStitch_ETX) { if (bHasHead) { if (i >= 4) //正常指令(不包含校验位) { if (i + 2 > nLength) { PacketLength = nLength; } else { PacketLength = i + 2; //+2 because ETX + Checksum } char strtemp[OTCStitch_Com_NormalLen] = { 0 }; memcpy(strtemp, RecData + 1, i - 1); //只有数据,+1 排除 STX ,-1 排除 ETX。 //printf("==IN==:[%s]\n", strtemp); //if (!((strtemp[0] == '9' && strtemp[1] == '9') || (strtemp[0] == '7' && strtemp[1] == '7'))) mLog::Info("==IN==:[{$}]", strtemp); return PACKET_ISPACKET; } else //空指令 { PacketLength = i + 1; char strtemp[OTCStitch_Com_NormalLen] = { 0 }; memcpy(strtemp, RecData, PacketLength); //空数据,格式正确但无有效命令。 //printf("==IN uselss data==:[%s]\n", strtemp); mLog::Error("==IN uselss data==:[{$}]", strtemp); return PACKET_USELESS; } } else //有包尾但无包头 { PacketLength = i + 1; char strtemp[OTCStitch_Com_NormalLen] = { 0 }; memcpy(strtemp, RecData, PacketLength); //printf("==IN no head data ==:[%s],NoHeadDataLength=%d,TotalLength=%d\n", strtemp, PacketLength, nLength); mLog::Error("==IN no head data ==:[{$}],NoHeadDataLength={$},TotalLength={$}", strtemp, PacketLength, nLength); return PACKET_USELESS; } } } if (bHasHead) { PacketLength = 0; } return PACKET_NOPACKET; } static nsMech::OTCStitchDriver gIODriver; extern "C" DIOS::Dev::IODriver * __cdecl GetIODriver() // 返回静态对象的引用, 调用者不能删除 ! { return &gIODriver; } extern "C" DIOS::Dev::IODriver * __cdecl CreateIODriver() // 返回新对象, 调用者必须自行删除此对象 ! { return new nsMech::OTCStitchDriver(); }