#include "stdafx.h" #include #include "Helper.JSON.hpp" #include "DIOS.Dev.Mech.HanQing3D.hpp" 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 HanQing3D_TIMEOUTVALUE 100 #define HanQing3D_LoopDefHBTime 500 static const int msTimeOut_Lock = 200; //通讯接口锁定时间 #define HanQing3D_Com_NormalLen 128 #define HanQing3D_STX 0x02 #define HanQing3D_ETX 0x03 #define HanQing3D_SynClientName "HanQing_Syn" #define HanQing3D_SynHandSwitch1 "I0" #define HanQing3D_SynHandSwitch2 "I1" /* *串口/以太网通信帧格式: 解释: = 1 ASCII 0x02 帧头 = 2 ASCII 字符表示的命令ID = 命令参数 = 1 ASCII 0x03 帧尾 串口通信设置: . 19200 波特率 . No Parity . 8 Data Bits . 0 Stop Bit . 无握手过程 */ Log4CPP::Logger* mLog::gLogger = nullptr; //指令操作关联结构 nsMech::tFrameMapItem::tFrameMapItem() { m_fFun = NULL; } nsMech::tFrameMapItem::tFrameMapItem(cbFun f) { m_fFun = f; } nsMech::tFrameMapItem& nsMech::tFrameMapItem::operator =(const tFrameMapItem& value) { m_fFun = value.m_fFun; return *this; } //响应操作对照表 static std::map arFrame; //查找响应操作对照表执行对应操作 static char CMDHeader[HanQing3D_Com_NormalLen] = { 0 }; static bool DecodeFrame(const char* strFrame, int length) { memset(CMDHeader,0, HanQing3D_Com_NormalLen-1); strncpy_s(CMDHeader, strFrame+1, 3); auto found = arFrame.find(CMDHeader);//此处pr用来在arFrame中找到对于的包头 if (found == arFrame.end()) { return false; } //found->second.tChangeWaitState(0, data); int cmdHead = found->first.length(); memcpy(CMDHeader, strFrame + cmdHead+1, length - cmdHead-2); found->second.m_fFun(CMDHeader, length - cmdHead);//第二个参数 不重要 return true; } void DataSpliToNumbers(const char* name, vector& arry) { string strtemp = name; string strName = strtemp; std::size_t oldPos = 0; std::size_t findPos = strtemp.find(","); while (findPos != string::npos) { strName = strtemp.substr(oldPos, findPos - oldPos); arry.push_back(atoi(strName.c_str())); if (findPos != strtemp.length()) { oldPos = findPos + 1; findPos = strtemp.find(",", oldPos); if (findPos == string::npos) { strName = strtemp.substr(oldPos, strtemp.length() - oldPos); break; } } else { break; } } strName.erase(strName.length()-1); arry.push_back(atoi(strName.c_str())); } //----------------------------------------------------------------------------- // HanQing3DDevice //----------------------------------------------------------------------------- nsSerialGPM::CDeliverModule nsMech::HanQing3DDevice::m_tDelivermodule; int nsMech::HanQing3DDevice::m_iLoopTime = HanQing3D_LoopDefHBTime; nsMech::HanQing3DDevice::HanQing3DDevice(std::shared_ptr center, nsSCF::SCF SCF, string configfile /*= ""*/):super(center, SCF) { assert(EventCenter); string version; if (GetVersion(version, hMyModule)) mLog::Debug("\n===============log begin : version:{$} ===================\n", version.c_str()); else mLog::Debug("\n===============log begin : version:0.0.0.0 ===================\n"); ResDataObject Conftemp; if (!configfile.empty()) { Conftemp.loadFile(configfile.c_str()); m_MechConfig = Conftemp["CONFIGURATION"]; TransJsonText(m_MechConfig); } //Mechanical m_MECHUnit.m_MechState.reset(new MechStateMould(AttrKey::MACHINE_STATUS_STANDBY, AttrKey::MACHINE_STATUS_SHUTDOWN, AttrKey::MACHINE_STATUS_SERVICE, 1)); m_MECHUnit.m_TID.reset(new TIDMould(3.5, 0, 10000, 1)); m_MECHUnit.m_SID.reset(new SIDMould(123.5, 0, 10000, 1)); if (m_MechConfig.GetKeyCount("MechanicalAngle") > 0) { if (m_MechConfig["MechanicalAngle"].GetKeyCount("min") > 0) m_nMinAngle = m_MechConfig["MechanicalAngle"]["min"]; if (m_MechConfig["MechanicalAngle"].GetKeyCount("max") > 0) m_nMaxAngle = m_MechConfig["MechanicalAngle"]["max"]; mLog::Debug("config:MechanicalAngle[min:{$},max:{$}]", m_nMinAngle, m_nMaxAngle); } m_MECHUnit.m_TubeAngle.reset(new TubeAngleMould(90, m_nMinAngle, m_nMaxAngle, 1)); if (m_MechConfig.GetKeyCount("MechanicalHeight") > 0) { if (m_MechConfig["MechanicalHeight"].GetKeyCount("min") > 0) m_nMinHeight = m_MechConfig["MechanicalHeight"]["min"]; if (m_MechConfig["MechanicalHeight"].GetKeyCount("max") > 0) m_nMaxHeight = m_MechConfig["MechanicalHeight"]["max"]; mLog::Debug("config:MechanicalHeight[min:{$},max:{$}]", m_nMinHeight, m_nMaxHeight); } m_MECHUnit.m_TubeHeight.reset(new TubeHeightMould(150, m_nMinHeight, m_nMaxHeight, 1)); m_MECHUnit.m_PostionNumber.reset(new POSITIONNUMBERMould(0, 0, 1000, 1)); //TOMO m_MECHUnit.m_Tomo_Type.reset(new TOMOTypeMould(31, 0, 100, 1)); m_MECHUnit.m_Tomo_ScanDirection.reset(new TOMOScanDirectionMould(AttrKey::TOMODIR_NULL, AttrKey::TOMODIR_NULL, AttrKey::Grid_MAX, 1)); m_MECHUnit.m_Tomo_FrameCount.reset(new TOMOFrameCountMould(30, 0, 100, 1)); m_MECHUnit.m_Tomo_FrameRate.reset(new TOMOFrameRateMould(4, 0, 60, 1)); m_MECHUnit.m_Tomo_ScanAngle.reset(new TOMOScanAngleMould(15, -180, 180, 1)); m_MECHUnit.m_Tomo_ScanImageNumber.reset(new TOMOScanImageNumberMould(29, 0, 100, 1)); //拼接 m_MECHUnit.m_StitchingState.reset(new StitchingStateMould(AttrKey::STITCHSTATE_ERR, AttrKey::STITCHSTATE_ERR, AttrKey::STITCHSTATE_MAX, 1)); 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_StitchPID.reset(new StitchPIDMould(0, 0, 1000, 1)); m_MECHUnit.m_StitchDirection.reset(new StitchDirectionMould(AttrKey::STITCHDIR_NULL, AttrKey::STITCHDIR_NULL, AttrKey::STITCHDIR_MAX, 1)); m_MECHUnit.m_StitchType.reset(new StitchTypeMould(AttrKey::STITCHTYPE_NULL, AttrKey::STITCHTYPE_NULL, AttrKey::STITCHTYPE_MAX, 1)); m_MECHUnit.m_StitchStepLength.reset(new StitchStepLengthMould(0, 0, 1000, 1)); m_MECHUnit.m_FPDPosition.reset(new FPDPositionMould(0, 0, 100, 1)); m_MECHUnit.m_TotalImageCount.reset(new TotalImageCountMould(0, 0, 100, 1)); m_MECHUnit.m_CurrentImageNumber.reset(new CurrentImageNumberMould(0, 0, 100, 1)); //上报错误消息 m_MSGUnit.reset(new nsDetail::MSGUnit(center, MechUnitType)); //串口数据处理类初始化 m_tDelivermodule.InitSendModle(this ,&ProcessClientData, WriteLog); m_nCMDType_WaitTime = m_tDelivermodule.SetPriority(true, false, false, true, 100); m_nCMDType_HB = m_tDelivermodule.SetPriority(false, true, false, true, 100); m_nCMDType_WaitACK = m_tDelivermodule.SetPriority(true, false, 3, false, 0, true, 1000); mLog::Debug("m_nCMDType_WaitTime[{$}]m_nCMDType_HB[{$}] m_nCMDType_WaitACK[{$}]", m_nCMDType_WaitTime, m_nCMDType_HB, m_nCMDType_WaitACK); //配置响应操作对照表 OnCallBack(); //将机架可以对外提供的指令注册集进行补充 Register(); m_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hMoveBeginEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_pHardwareStatusThread = NULL; //启动硬件状态轮询进程 StartHardwareStatusThread(); //设置初始参数 RefreshData(); } nsMech::HanQing3DDevice::~HanQing3DDevice() { #if Dios_V3 if (m_pSynClient) { if (!m_pSynClient->IsClosed()) { m_pSynClient->Close(); } delete m_pSynClient; m_pSynClient = NULL; } #endif ResetEvent(m_hMoveBeginEvent); SetEvent(m_hExitEvent); Sleep(m_iLoopTime); m_tDelivermodule.EixtSendModle(); mLog::Debug("\n===============log end ===================\n"); } std::string HanQing3DDevice::GetGUID() const { mLog::Debug("\n===============GetGUID : {$} ===================\n", StitchMechUnitType); return StitchMechUnitType; } RET_STATUS nsMech::HanQing3DDevice::RefreshData() { #if Dios_V3 m_pSynClient = new LogicClient(HanQing3D_SynClientName, "NSQ", "", false); if (m_pSynClient->Open("diosChannel", ALL_ACCESS)) { mLog::Debug("Dios_V3 Create {$} Client success", HanQing3D_SynClientName); } else { mLog::Debug("Dios_V3 Create {$} Client failed", HanQing3D_SynClientName); } #endif if (m_MechConfig.GetKeyCount(AttrKey::TID) > 0) { float tempValue = (float)m_MechConfig[AttrKey::TID]; m_MECHUnit.m_TID->Update(tempValue); } GetAllAxisPosition(); return RET_STATUS::RET_SUCCEED; } void nsMech::HanQing3DDevice::Register() { auto Disp = &Dispatch; superMech::RegisterExamInfo(Disp); superMech::RegisterNormalControl(Disp); superMech::RegisterTOMOControl(Disp); superMech::RegisterStitchingControl(Disp); Disp->Get.Push(m_MSGUnit->GetKey().c_str(), [this](std::string& out) { out = m_MSGUnit->JSGet(); return RET_STATUS::RET_SUCCEED; }); Disp->Get.Push("StitchPlanMinAngle", [this](std::string& out) { out = to_string(m_nMinAngle); return RET_STATUS::RET_SUCCEED; }); Disp->Get.Push("StitchPlanMaxAngle", [this](std::string& out) { out = to_string(m_nMaxAngle); return RET_STATUS::RET_SUCCEED; }); Disp->Get.Push("StitchPlanMinHeight", [this](std::string& out) { out = to_string(m_nMinHeight); return RET_STATUS::RET_SUCCEED; }); Disp->Get.Push("StitchPlanMaxHeight", [this](std::string& out) { out = to_string(m_nMaxHeight); return RET_STATUS::RET_SUCCEED; }); auto fun_SendStitchState = [this](auto in, auto& out) { FireNotify(AttrKey::STITCHINGSTATE, m_MECHUnit.m_StitchingState->Get()); return RET_STATUS::RET_SUCCEED; }; Disp->Action.Push("SendStitchState", fun_SendStitchState); //3D特有 auto fun_StopAllAxis = [this](auto in, auto& out) { return StopAllAxis(); }; Disp->Action.Push("StopAllAxis", fun_StopAllAxis); auto fun_MoveToRelativeDistance = [this](auto in, auto& out) { int value[2]{0}; ResDataObject json; json.decode(in.c_str()); //mLog::Debug("MoveToRelativeDistance:[{$}]",json.encode()); int paramCount = json.GetKeyCount("P0"); for (int i = 0; i < paramCount; i++) { value[i] = json[i]; } return MoveToRelativeDistance(value[0], value[1]); }; Disp->Action.Push("MoveToRelativeDistance", fun_MoveToRelativeDistance); auto fun_MoveToPositionNumber = [this](auto in, auto& out) { int value[2]{ 0 }; ResDataObject json; json.decode(in.c_str()); int paramCount = json.GetKeyCount("P0"); for (int i = 0; i < paramCount; i++) { value[i] = json[i]; } return MoveToPositionNumber(value[0], value[1]); }; Disp->Action.Push("MoveToPositionNumber", fun_MoveToPositionNumber); auto fun_GetAllAxisPosition = [this](auto in, auto& out) { return GetAllAxisPosition(); }; Disp->Action.Push("GetAllAxisPosition", fun_GetAllAxisPosition); auto fun_SetPositionNumber = [this](auto in, auto& out) { int value[5]{ 0 }; ResDataObject json; json.decode(in.c_str()); int paramCount = json.GetKeyCount("P0"); for (int i = 0; i < paramCount; i++) { value[i] = json[i]; } return SetAxisPositionNumber(value[0], value[1], value[2], value[3], value[4]); }; Disp->Action.Push("SetAxisPosition", fun_SetPositionNumber); } void nsMech::HanQing3DDevice::FireNotify(std::string key, std::string content) { EventCenter->OnNotify(1, key, content); } void nsMech::HanQing3DDevice::FireNotify(std::string key, const int content) { std::string str = std::format("{:d}", content); EventCenter->OnNotify(1, key, str); } void nsMech::HanQing3DDevice::FireNotify(std::string key, const float content) { std::string str = std::format("{:f}", content); EventCenter->OnNotify(1, key, str); } void nsMech::HanQing3DDevice::FireErrorMessage(const bool Act, const int Code, const char* ResInfo) { string ErrorCode("Mech_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); if(Code == 0) m_MSGUnit->DelErrorMessage("0", level, ResInfo); else m_MSGUnit->DelErrorMessage(ErrorCode.c_str(), level, ResInfo); } } void nsMech::HanQing3DDevice::FireWarnMessage(const bool Act, const int Code, const char* ResInfo) { string ErrorCode("Mech_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); } } RET_STATUS nsMech::HanQing3DDevice::HWSend(const char* strCommand, int lengh, bool reSend, int nTimeOut) { if (!m_SCF) return RET_STATUS::RET_FAILED; char strSendCommand[HanQing3D_Com_NormalLen] = { 0 }; int copyCode = memcpy_s(strSendCommand + 1, HanQing3D_Com_NormalLen - 3, strCommand, lengh); if (copyCode) { mLog::Error("copy cmd[{$}][{$}] error[{$}]", strCommand, lengh, copyCode); return RET_STATUS::RET_FAILED; } strSendCommand[0] = HanQing3D_STX; strSendCommand[lengh + 1] = HanQing3D_ETX; if (strncmp(strCommand, "FFF", 3) != 0) { if (reSend) { mLog::Debug("==OUT==: [{$}] wait for ACK \n", strSendCommand); //find_item->second.tChangeWaitState(1, strCommand, lengh); } else { mLog::Debug("==OUT==: [{$}] \n", strSendCommand); } } int retLength; m_SCF.Lock(msTimeOut_Lock) .SendPacket(strSendCommand, lengh+2, nTimeOut, retLength); //Sleep(nTimeOut); return RET_STATUS::RET_SUCCEED; } void HanQing3DDevice::OnCallBack() { mLog::Debug("Enter OnCallBack"); auto HWNotProcess = [](const char* value, int length) -> void { mLog::Warn(" This commands didn't need to process!"); }; auto HWAPS = [this](const char* value, int length) -> void { //assert(value && length >= 3); int data = atoi(value + 2); mLog::Debug("begin tomo[{$}]", data); if (data == 1) { FireNotify(AttrKey::TomoTID, m_MECHUnit.m_TID->Get());//3.5 FireNotify(AttrKey::TomoSID, m_MECHUnit.m_SID->Get());//123.5 FireNotify(AttrKey::TomoScanDirection, m_MECHUnit.m_Tomo_ScanDirection->Get());//m_nDirection FireNotify(AttrKey::TomoScanAngle, m_MECHUnit.m_Tomo_ScanAngle->Get());//15 FireNotify(AttrKey::TomoScanImageNumber, m_MECHUnit.m_Tomo_FrameCount->Get() - 1); } else if (data == 2) { m_mTomoResult.clear(); m_MECHUnit.m_Tomo_ScanImageNumber->Update(0); } else if (data == 0) { FireNotify(AttrKey::TomoScanImageNumber, m_MECHUnit.m_Tomo_ScanImageNumber->Get()); } }; auto HWAPE = [this](const char* value, int length) -> void { //assert(value && length >= 3); mLog::Debug("end tomo"); FireNotify(AttrKey::TomoScanImageNumber, m_MECHUnit.m_Tomo_ScanImageNumber->Get()); }; auto HWSPA = [this](const char* value, int length) -> void { //assert(value && length >= 3); vector data; DataSpliToNumbers(value+2, data); mLog::Debug("mechine position[{$}]", value + 2); FireNotify(AttrKey::TUBEHEIGHT, data[2]); FireNotify(AttrKey::TUBEANGLE, data[3]); for (int i = 0; i < AxisCount; i++) { MechStatus[i].SetPosition(data[i]); FireNotify("Pos" + MechStatus[i].GetName(), data[i]); } }; auto HWERR = [this](const char* value, int length) -> void { //assert(value && length >= 3); int data = atoi(value + 2); mLog::Debug("Mech get error[{$}]", data); if (data > 0) { FireErrorMessage(true, data, "get Mech error"); } else { FireErrorMessage(false, data, "del Mech error"); } }; auto HWSTA = [this](const char* value, int length) -> void { //assert(value && length >= 3); vector data; DataSpliToNumbers(value + 2, data); mLog::Debug("mechine status[{$}]", value + 2); int moveCount = 0; for (int i = 0; i < AxisCount; i++) { MechStatus[i].SetState(data[i]); if (MechStatus[i].GetState() == Axis::AXIS_MOVE) { moveCount++; } FireNotify("Status"+ MechStatus[i].GetName(), data[i]); } if (moveCount == 0) { ResetEvent(m_hMoveBeginEvent); } else { SetEvent(m_hMoveBeginEvent); } }; auto HWHAD = [this](const char* value, int length) -> void { //assert(value && length >= 3); int data = atoi(value + 2); HAND_SWITCH emHS = HAND_MAX; switch (data) { case 0: { emHS = HAND_OFF; SetFunToOtherUnit(HanQing3D_SynHandSwitch2, 0); SetFunToOtherUnit(HanQing3D_SynHandSwitch1, 0); }break; case 10: { emHS = HAND_DWON1; SetFunToOtherUnit(HanQing3D_SynHandSwitch1, 1); }break; case 11: { emHS = HAND_DWON2; SetFunToOtherUnit(HanQing3D_SynHandSwitch2,1); }break; } }; auto HWINE = [this](const char* value, int length) -> void { //assert(value && length >= 3); vector data; DataSpliToNumbers(value + 2, data); char index[3]{ 0 }; strncpy(index, value, 2); int countNum = atoi(index); if (countNum >= 2) { mLog::Debug("tomo Exp info[{$}:{$},{$}]", countNum, data[0], data[1]); m_MECHUnit.m_Tomo_ScanImageNumber->Update(countNum - 1); m_mTomoResult[countNum - 1] = tTomoResult(data[0] / 1000.0 - 90, data[1] / 100.0); } }; auto HWUSC = [this](const char* value, int length) -> void { //assert(value && length >= 3); int data = atoi(value); if (m_MECHUnit.m_CurrentImageNumber->Update(data)) { mLog::Debug("stitching current image[{$}:{$}]", m_MECHUnit.m_CurrentImageNumber->Get(), m_MECHUnit.m_TotalImageCount->Get()); FireNotify(AttrKey::CURRENTIMAGENUMBER, data); } if (m_MECHUnit.m_CurrentImageNumber->Get() >= m_MECHUnit.m_TotalImageCount->Get()) { EndStitching(); } }; auto HWUSN = [this](const char* value, int length) -> void { //assert(value && length >= 3); int data = atoi(value); if (m_MECHUnit.m_TotalImageCount->Update(data)) { mLog::Debug("stitching current image[{$}:{$}]", m_MECHUnit.m_CurrentImageNumber->Get(), m_MECHUnit.m_TotalImageCount->Get()); FireNotify(AttrKey::CURRENTIMAGENUMBER, m_MECHUnit.m_CurrentImageNumber->Get()); FireNotify(AttrKey::TOTALIMAGECOUNT, data); } }; auto HWUST = [this](const char* value, int length) -> void { //assert(value && length >= 3); int data = atoi(value); if (m_MECHUnit.m_StitchingState->Update(data)) { int status = -1; switch (data) { case 8: //拼接错误 { status = AttrKey::STITCHSTATE_ERR; mLog::Error("get error"); FireErrorMessage(true, 100, "get Mech error"); }break; case 6: //拼接初始化,此时设置拼接相应参数 { status = AttrKey::STITCHSTATE_INIT; m_MECHUnit.m_strInfo = "Stitch Init"; }break; case 7: //拼接就绪,参数设置成功 { status = AttrKey::STITCHSTATE_STANDBY; m_MECHUnit.m_strInfo = "Stitch Standby, Need Moving to the initial position"; }break; case 1: //拼接开始 { status = AttrKey::STITCHSTATE_START; m_MECHUnit.m_strInfo = "Stitch Start"; }break; case 2: //拼接机架需要向指定位置运动 { status = AttrKey::STITCHSTATE_NEED_MOVE; m_MECHUnit.m_strInfo = "Stitch Need Move"; }break; case 3: //拼接机架正在运动 { status = AttrKey::STITCHSTATE_MOVING; m_MECHUnit.m_strInfo = "Stitch Moving"; }break; case 9: //拼接机架到达初始位置 { status = AttrKey::STITCHSTATE_REACH_INIT; m_MECHUnit.m_strInfo = "Stitch Reach to the initial position"; }break; case 4: //拼接机架到达下一个位置 { status = AttrKey::STITCHSTATE_REACH_NEXT; m_MECHUnit.m_strInfo = "Stitch Reach to the next position"; }break; case 11: //拼接机架到达额外位置 { status = AttrKey::STITCHSTATE_REACH_EXTRA; m_MECHUnit.m_strInfo = "Stitch Reach to the Extra position"; }break; case 5: //拼接完成 { status = AttrKey::STITCHSTATE_END; m_MECHUnit.m_strInfo = "Stitch Finish"; }break; default: break; } if (m_MECHUnit.m_StitchingState->Update(status)) { FireNotify(AttrKey::STITCHINGSTATE, status); } mLog::Debug("stitching:[{$}]", m_MECHUnit.m_strInfo.c_str()); FireNotify(AttrKey::UNITINFO, m_MECHUnit.m_strInfo); if (data == 4 || data == 11) { m_MECHUnit.m_strInfo = "Stitch Ready"; if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_READY)) { Sleep(2000); FireNotify(AttrKey::STITCHINGSTATE, AttrKey::STITCHSTATE_READY); } mLog::Debug("stitching:[{$}]", m_MECHUnit.m_strInfo.c_str()); FireNotify(AttrKey::UNITINFO, m_MECHUnit.m_strInfo); } } }; // 有部分前缀是包含关系, 长的包含短的, 因此长的在前面, 短的在后面 // Device 是个短寿命对象, 而 arFrame 是静态变量 !!! // 因此, 在添加到 arFrame 之前, 务必先清零 !!! arFrame.clear(); arFrame["APS"] = tFrameMapItem(HWAPS); arFrame["APE"] = tFrameMapItem(HWAPE); arFrame["SPA"] = tFrameMapItem(HWSPA); arFrame["ERR"] = tFrameMapItem(HWERR); arFrame["STA"] = tFrameMapItem(HWSTA); arFrame["HAD"] = tFrameMapItem(HWHAD); arFrame["INE"] = tFrameMapItem(HWINE); arFrame["USC"] = tFrameMapItem(HWUSC); arFrame["USN"] = tFrameMapItem(HWUSN); arFrame["UST"] = tFrameMapItem(HWUST); arFrame["FFF"] = tFrameMapItem(HWNotProcess);//命令格式:校验和错误 } //串口数据处理类对外接口 void __stdcall nsMech::HanQing3DDevice::ProcessClientData(const char* pData, unsigned long nDataLength, void* lparam) { HanQing3DDevice* pCurMech = (HanQing3DDevice*)lparam; pCurMech->HWSend(pData, nDataLength); } void __stdcall nsMech::HanQing3DDevice::WriteLog(const char* pData, nsSerialGPM::LOG_V2_LEVEL level) { switch (level) { case nsSerialGPM::LOG_V2_FATAL: case nsSerialGPM::LOG_V2_ERROR: mLog::Error(pData); break; case nsSerialGPM::LOG_V2_WARNING: mLog::Warn(pData); break; case nsSerialGPM::LOG_V2_DEBUG: mLog::Debug(pData); break; case nsSerialGPM::LOG_V2_INFO: mLog::Debug(pData); break; default: break; } } RET_STATUS nsMech::HanQing3DDevice::HWSendWaittimeCMD(char* strCommand, int lengh, int headLengh) { return m_tDelivermodule.ProcessCommand(strCommand, lengh, m_nCMDType_WaitTime, headLengh); } RET_STATUS nsMech::HanQing3DDevice::HWSendHBCMD(char* strCommand, int lengh, int headLengh) { return m_tDelivermodule.ProcessCommand(strCommand, lengh, m_nCMDType_HB, headLengh); } RET_STATUS nsMech::HanQing3DDevice::HWSendWaitACKCMD(char* strCommand, int lengh, int headLengh) { return m_tDelivermodule.ProcessCommand(strCommand, lengh, m_nCMDType_WaitACK, headLengh); } bool nsMech::HanQing3DDevice::StartHardwareStatusThread() { mLog::Debug("Enter Start HardwareStatus Thread "); if (m_pHardwareStatusThread == NULL) { DWORD m_HardwareStatusID; m_pHardwareStatusThread = CreateThread(0, 0, HardwareStatusThread, this, 0, &m_HardwareStatusID); if (m_pHardwareStatusThread == NULL) { mLog::Error("Start HardwareStatus Thread Failed"); return false; } } return true; } DWORD nsMech::HanQing3DDevice::HardwareStatusThread(LPVOID pParam) { HanQing3DDevice* pCurMech = (HanQing3DDevice*)pParam; if (pCurMech == NULL) { return false; } mLog::Debug("HardwareStatusThread start"); if ((int)pCurMech->m_MechConfig["loopTime"] >= 0) { pCurMech->m_iLoopTime = (int)pCurMech->m_MechConfig["loopTime"]; } mLog::Debug("loopTime = {$}", pCurMech->m_iLoopTime); HANDLE hEventArray[2]; hEventArray[0] = pCurMech->m_hExitEvent; hEventArray[1] = pCurMech->m_hMoveBeginEvent; while (pCurMech->m_iLoopTime) { DWORD dwResult = WaitForMultipleObjects(2, hEventArray, FALSE, INFINITE); switch (dwResult) { case WAIT_OBJECT_0: { mLog::Debug("get exit event, HardwareStatusThread stop"); return true; }break; case WAIT_OBJECT_0 + 1: { Sleep(pCurMech->m_iLoopTime); mLog::Debug("loop get pos"); pCurMech->GetAllAxisPosition(); }break; } } mLog::Debug("HardwareStatusThread stop"); return true; } //检查信息接口 RET_STATUS nsMech::HanQing3DDevice::SetStudyInfo(ResDataObject& pParam) { auto& P0 = pParam[0]; SetPatientInfo(P0); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetViewInfo(ResDataObject& pParam) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetPatientInfo(ResDataObject& pParam) { ECOM_PATIENT Info; Info.strPatientName = (string)pParam["PatientName"]; Info.strSex = (string)pParam["Sex"]; Info.strAge = (string)pParam["Age"]; Info.strPatientID = (string)pParam["PatientID"]; Info.strPatientSize = (string)pParam["PatientSize"]; Info.strStudyDescription = (string)pParam["StudyDescription"]; Info.strAccessionNumber = (string)pParam["AccessionNumber"]; mLog::Debug("Enter SetPatientInfo:[Name:{$}],[Sex:{$}],[Age:{$}],[ID:{$}],[Size:{$}],[Description:{$}],[AccessionNumber:{$}]", Info.strPatientName.c_str(), Info.strSex.c_str(), Info.strAge.c_str(), Info.strPatientID.c_str(), Info.strPatientSize.c_str(), Info.strStudyDescription.c_str(), Info.strAccessionNumber.c_str()); return RET_STATUS::RET_SUCCEED; } //基本 RET_STATUS nsMech::HanQing3DDevice::Reset() { mLog::Debug("Enter Reset"); FireErrorMessage(false, 0, "clear all Mech error"); mLog::Debug("End Reset"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetTechParamsInfo(ResDataObject& pParam) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetPositionNumber(int pn) { mLog::Debug("Enter SetPositionNumber:[{$}]", pn); m_MECHUnit.m_PostionNumber->Update(pn); char temp[50] = { 0 }; sprintf_s(temp, "PSN99%05d", pn); return HWSendWaittimeCMD(temp, strlen(temp)); FireNotify(AttrKey::POSITIONNUMBER, m_MECHUnit.m_PostionNumber->Get()); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetSID(float value) { mLog::Debug("Enter SetSID:[{$}]", value); m_MECHUnit.m_SID->Update(value); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetSOD(float value) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::MoveToHome(string& value) { int PosNum = atoi(value.c_str()); mLog::Debug("Enter MoveToHome:[{$}]", PosNum); if (PosNum > 0 && PosNum < 100) { char temp[50] = { 0 }; sprintf_s(temp, "HOM99%02d", PosNum); return HWSendWaittimeCMD(temp, strlen(temp)); } return RET_STATUS::RET_FAILED; } RET_STATUS nsMech::HanQing3DDevice::MoveMech(string& value) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::StopMech(string& value) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetGrid(AttrKey::MECH_GRIDSTATE GridState) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetAutoTracking(int nAutoTracking) { mLog::Debug("Enter MoveToHome:[{$}]", nAutoTracking); char temp[50] = { 0 }; sprintf_s(temp, "USI"); return HWSendWaittimeCMD(temp, strlen(temp)); } //Tomo RET_STATUS nsMech::HanQing3DDevice::SetTomoEnable(bool enable) { if (m_MECHUnit.m_MechState->Update(AttrKey::MACHINE_STATUS_3DDR)) FireNotify(AttrKey::MACHSTATE, m_MECHUnit.m_MechState->Get()); mLog::Debug("Enter SetTomoEnable:[{$}]", enable); if (enable >= 0 && enable <= 1) { char temp[50] = { 0 }; sprintf_s(temp, "APR99%02d", enable); return HWSendWaittimeCMD(temp, strlen(temp)); } return RET_STATUS::RET_FAILED; } RET_STATUS nsMech::HanQing3DDevice::SetTomoExpMode(string& value) { mLog::Debug("Enter SetTomoExpMode:[{$}]", value.c_str()); char temp[50] = { 0 }; if (value == "Single") { sprintf_s(temp, "APM9920,00,00,00"); return HWSendWaittimeCMD(temp, strlen(temp)); } else if(value == "TOMO") { mLog::Debug("Enter SetTomoExpMode:[{$},{$},{$},{$}]", m_MECHUnit.m_Tomo_Type->Get(), m_MECHUnit.m_Tomo_ScanAngle->Get(), m_MECHUnit.m_Tomo_FrameCount->Get(), m_MECHUnit.m_Tomo_FrameRate->Get()); sprintf_s(temp, "APM99%02d,%02d,%02d,%02d", m_MECHUnit.m_Tomo_Type->Get(), m_MECHUnit.m_Tomo_ScanAngle->Get(), m_MECHUnit.m_Tomo_FrameCount->Get(), m_MECHUnit.m_Tomo_FrameRate->Get()); return HWSendWaittimeCMD(temp, strlen(temp)); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetTomoTechnical(string& value) { ResDataObject json; json.decode(value.c_str()); mLog::Debug("Enter SetTomoTechnical:[{$}]", json.encode()); string strValue = (string)json[AttrKey::TomoViewId]; if (strValue == "2D") { m_MECHUnit.m_Tomo_Type->Update(20); } else if (strValue == "3D") { m_MECHUnit.m_Tomo_Type->Update(31); } m_MECHUnit.m_Tomo_ScanAngle->Update(atoi(((string)json[AttrKey::TomoRotateAngle]).c_str())); m_MECHUnit.m_Tomo_FrameCount->Update(atoi(((string)json[AttrKey::TomoFrameCount]).c_str())); m_MECHUnit.m_Tomo_FrameRate->Update(atoi(((string)json[AttrKey::TomoFrameRate]).c_str())); m_MECHUnit.m_SID->Update(atoi(((string)json[AttrKey::SID]).c_str())); char temp[50] = { 0 }; sprintf_s(temp, "APM99%02d,%02d,%02d,%02d", m_MECHUnit.m_Tomo_Type->Get(), m_MECHUnit.m_Tomo_ScanAngle->Get(), m_MECHUnit.m_Tomo_FrameCount->Get(), m_MECHUnit.m_Tomo_FrameRate->Get()); return HWSendWaittimeCMD(temp, strlen(temp)); } RET_STATUS nsMech::HanQing3DDevice::GetTomoResults(std::string& result) { if (m_MECHUnit.m_MechState->Update(AttrKey::MACHINE_STATUS_STANDBY)) FireNotify(AttrKey::MACHSTATE, m_MECHUnit.m_MechState->Get()); mLog::Debug("Enter GetTomoResults"); ResDataObject json; ResDataObject jsonAngle; ResDataObject jsonHeight; if (m_mTomoResult.empty()) { mLog::Debug("use test TomoResults Data"); float dataAngle[15] = { -7.2 ,-6.1 ,-5.0 ,-4.5 ,-3.4 ,-2.3 ,-1.3 ,0 ,1.3 ,2.4 ,3.5 ,4.5 ,5.1 ,6.1 ,7.2 }; float dataHeight[15] = { 315,290,264,252,226,201,176,150,112,1087,162,1036,1024,998,973 }; for (int i = 0; i < 15; i++) { jsonAngle.add(to_string(i).c_str(), dataAngle[i]); jsonHeight.add(to_string(i).c_str(), dataHeight[i]); } json.add("P0", jsonAngle); json.add("P1", jsonHeight); FireNotify(AttrKey::TomoScanImageNumber, 15); } else { for (auto& item : m_mTomoResult) { jsonAngle.add(to_string(item.first).c_str(), item.second.nAngle); jsonHeight.add(to_string(item.first).c_str(), item.second.nHeight); } json.add("P0", jsonAngle); json.add("P1", jsonHeight); FireNotify(AttrKey::TomoScanImageNumber, m_MECHUnit.m_Tomo_ScanImageNumber->Get()); } mLog::Debug("TomoResults:[{$}]", json.encode()); result = json.encode(); return RET_STATUS::RET_SUCCEED; } bool nsMech::HanQing3DDevice::SetFunToOtherUnit(const char* Signal, int SWstatus) { bool res{ false }; #if Dios_V3 if (m_pSynClient != NULL) { if (!m_pSynClient->IsClosed()) { ResDataObject Request, Response; Request.add("P0", Signal); Request.add("P0", SWstatus); m_pSynClient->Action("SimulateHandSwitchSignal", Request, Response, 4993, "DIOS/DEVICE/SyncBox"); mLog::Debug("SimulateHandSwitchSignal[{$}:{$}] to SYN", Signal, SWstatus); res = true; } else { mLog::Debug("{$} Client is Close", HanQing3D_SynClientName); } } else { mLog::Debug("{$} Client is NULL", HanQing3D_SynClientName); } #endif return res; } //拼接相应接口 RET_STATUS nsMech::HanQing3DDevice::BeginStitching() { if (m_MECHUnit.m_MechState->Update(AttrKey::MACHINE_STATUS_STITCH)) FireNotify(AttrKey::MACHSTATE, m_MECHUnit.m_MechState->Get()); mLog::Debug("Enter BeginStitching"); char temp[50] = { 0 }; sprintf_s(temp, "USS"); HWSendWaittimeCMD(temp, strlen(temp)); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::InitStitching() { mLog::Debug("Enter InitStitching"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::EndStitching() { if (m_MECHUnit.m_MechState->Update(AttrKey::MACHINE_STATUS_STANDBY)) FireNotify(AttrKey::MACHSTATE, m_MECHUnit.m_MechState->Get()); mLog::Debug("Enter EndStitching"); char temp[50] = { 0 }; sprintf_s(temp, "USE"); return HWSendWaittimeCMD(temp, strlen(temp)); } RET_STATUS nsMech::HanQing3DDevice::SetupStitching(string& value) { EndStitching(); Sleep(500); ResDataObject json,P0; json.decode(value.c_str()); if (json.GetKeyCount("P0") > 0) { P0 = json[0]; } else P0 = json; int nInitHeight = atoi(((string)P0[AttrKey::STITCHHEIGHT]).c_str()); int nTargetLength = atoi(((string)P0[AttrKey::STITCHLENGTH]).c_str()); int nOverlap = atoi(((string)P0[AttrKey::STITCHOVERLAP]).c_str()); int nSID = atoi(((string)P0[AttrKey::STITCHSID]).c_str()); int nTID = atoi(((string)P0[AttrKey::STITCHTID]).c_str()); int nPID = atoi(((string)P0[AttrKey::STITCHPID]).c_str()); int nDirection = atoi(((string)P0[AttrKey::STITCHDIRECTION]).c_str()); int nStitchType = atoi(((string)P0[AttrKey::STITCHTYPE]).c_str()); mLog::Debug("Enter SetupStitching:[InitHeight:{$},TotalLength:{$},Overlap:{$},SID:{$},TID:{$},PID:{$},Direction:{$},StitchType:{$}]", nInitHeight, nTargetLength, nOverlap, nSID, nTID, nPID, nDirection, nStitchType); m_MECHUnit.m_TID->Update(nPID); m_MECHUnit.m_SID->Update(nSID); m_MECHUnit.m_StitchHeight->Update(nInitHeight); m_MECHUnit.m_StitchOverLap->Update(nOverlap); m_MECHUnit.m_StitchDirection->Update(nDirection); m_MECHUnit.m_StitchType->Update(nStitchType); m_MECHUnit.m_CurrentImageNumber->Update(0); //总长度校验 int maxLength = m_MECHUnit.m_TubeHeight->GetLimitMax() - m_MECHUnit.m_TubeHeight->GetLimitMin(); if (nTargetLength > (maxLength - 5)) { mLog::Warn("StitchingLengh[{$}] too big [height min:{$},height max:{$}],need change to[{$}]", nTargetLength, m_MECHUnit.m_TubeHeight->GetLimitMax(), m_MECHUnit.m_TubeHeight->GetLimitMin(), maxLength - 5); nTargetLength = maxLength - 5; } m_MECHUnit.m_StitchLength->Update(nTargetLength); //总张数计算 int totalImage = std::ceil(((float)nTargetLength - (float)nOverlap) / ((float)m_nFPDLengh - (float)nOverlap)); { m_MECHUnit.m_TotalImageCount->Update(totalImage); FireNotify(AttrKey::TOTALIMAGECOUNT, totalImage); }//计算步长 float tempStepLength = (float)nTargetLength / (float)totalImage; m_MECHUnit.m_StitchStepLength->Update(tempStepLength); mLog::Debug("compute TransStitching [total ImageCount:{$},StepLength:{$}]", totalImage, tempStepLength); char temp[50] = { 0 }; sprintf_s(temp, "USP%02d,%02d,%01d,%02d,%03d", totalImage, nDirection, nStitchType, nOverlap, nInitHeight); HWSendWaittimeCMD(temp, strlen(temp)); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::AcceptStitchingImage() { mLog::Debug("Enter AcceptStitchingImage"); char temp[50] = { 0 }; sprintf_s(temp, "USA"); HWSendWaittimeCMD(temp, strlen(temp)); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_Accept_Image)) { FireNotify(AttrKey::STITCHINGSTATE, AttrKey::STITCHSTATE_Accept_Image); m_MECHUnit.m_strInfo = "Stitch Accept Current image"; mLog::Debug("stitching:[{$}]", m_MECHUnit.m_strInfo.c_str()); FireNotify(AttrKey::UNITINFO, m_MECHUnit.m_strInfo); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::RejectStitchingImage() { mLog::Debug("Enter RejectStitchingImage"); char temp[50] = { 0 }; sprintf_s(temp, "USJ"); return HWSendWaittimeCMD(temp, strlen(temp)); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_Reject_Image)) { FireNotify(AttrKey::STITCHINGSTATE, AttrKey::STITCHSTATE_Reject_Image); m_MECHUnit.m_strInfo = "Stitch Reject Current Image"; mLog::Debug("stitching:[{$}]", m_MECHUnit.m_strInfo.c_str()); FireNotify(AttrKey::UNITINFO, m_MECHUnit.m_strInfo); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::CancelStitching() { if (m_MECHUnit.m_MechState->Update(AttrKey::MACHINE_STATUS_STANDBY)) FireNotify(AttrKey::MACHSTATE, m_MECHUnit.m_MechState->Get()); mLog::Debug("Enter CancelStitching"); char temp[50] = { 0 }; sprintf_s(temp, "UCS"); HWSendWaittimeCMD(temp, strlen(temp)); if (m_MECHUnit.m_StitchingState->Update(AttrKey::STITCHSTATE_CANCEL)) { FireNotify(AttrKey::STITCHINGSTATE, AttrKey::STITCHSTATE_CANCEL); m_MECHUnit.m_strInfo = "Stitch Cancel"; mLog::Debug("stitching:[{$}]", m_MECHUnit.m_strInfo.c_str()); FireNotify(AttrKey::UNITINFO, m_MECHUnit.m_strInfo); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::CompleteStitching() { if (m_MECHUnit.m_MechState->Update(AttrKey::MACHINE_STATUS_STANDBY)) FireNotify(AttrKey::MACHSTATE, m_MECHUnit.m_MechState->Get()); mLog::Debug("Enter CompleteStitching"); char temp[50] = { 0 }; sprintf_s(temp, "USE"); return HWSendWaittimeCMD(temp, strlen(temp)); } RET_STATUS nsMech::HanQing3DDevice::NewExtraView() { mLog::Debug("Enter NewExtraView"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::RepeatStitching() { mLog::Debug("Enter RepeatStitching"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetAutoPosiitonNo(int nPN) { mLog::Debug("Enter SetAutoPosiitonNo:[{$}]", nPN); return RET_STATUS::RET_SUCCEED; } //牛头 RET_STATUS nsMech::HanQing3DDevice::SetExpEnable(bool nExpEnabled) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetWS(int nWS) { mLog::Debug("Enter SetWS:[{$}]", nWS); if (m_nWS == nWS)return RET_STATUS::RET_SUCCEED; m_nWS = nWS; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetKV(int nKV) { mLog::Debug("Enter SetKV:[{$}]", nKV); if (m_nKV == nKV)return RET_STATUS::RET_SUCCEED; m_nKV = nKV; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetMA(float fMA) { mLog::Debug("Enter SetMA:[{$}]", fMA); if (m_fMA == fMA)return RET_STATUS::RET_SUCCEED; m_fMA = fMA; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetMS(float fMS) { mLog::Debug("Enter SetMS:[{$}]", fMS); if (m_fMS == fMS)return RET_STATUS::RET_SUCCEED; m_fMS = fMS; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetMAS(float fMAS) { mLog::Debug("Enter SetMAS:[{$}]", fMAS); if (m_fMAS == fMAS)return RET_STATUS::RET_SUCCEED; m_fMAS = fMAS; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetFO(int nFO) { mLog::Debug("Enter SetFO:[{$}]", nFO); if (m_nFocus == nFO)return RET_STATUS::RET_SUCCEED; m_nFocus = nFO; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetTechMode(int nET) { mLog::Debug("Enter SetTechMode:[{$}]", nET); if (m_nET == nET)return RET_STATUS::RET_SUCCEED; m_nET = nET; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetAECField(int nAECFieldSel) { mLog::Debug("Enter SetAECField:[{$}]", nAECFieldSel); if (m_nAECField == nAECFieldSel)return RET_STATUS::RET_SUCCEED; m_nAECField = nAECFieldSel; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetDensity(float nAECDensity) { mLog::Debug("Enter SetDensity:[{$}]", nAECDensity); if (m_nAECDensity == nAECDensity)return RET_STATUS::RET_SUCCEED; m_nAECDensity = nAECDensity; return RET_STATUS::RET_SUCCEED; } RET_STATUS nsMech::HanQing3DDevice::SetBodySize(string strSize) { mLog::Debug("Enter SetBodySize:[{$}]", strSize.c_str()); char temp[50] = { 0 }; int nPS = 2; if (strSize == "Small") { nPS = 1; } else if (strSize == "Middle") { nPS = 2; } else if (strSize == "Large") { nPS = 3; } else if (strSize == "Child") { nPS = 4; } if (m_nBodySize == nPS)return RET_STATUS::RET_SUCCEED; m_nBodySize = nPS; return RET_STATUS::RET_SUCCEED; } //悬吊特有 RET_STATUS nsMech::HanQing3DDevice::StopAllAxis() { mLog::Debug("Enter StopAllAxis"); ResetEvent(m_hMoveBeginEvent); char temp[50] = { 0 }; sprintf_s(temp, "STP99"); return HWSendWaittimeCMD(temp, strlen(temp)); } RET_STATUS nsMech::HanQing3DDevice::MoveToRelativeDistance(int axisNum, int distance) { mLog::Debug("Enter MoveToHome:[{$},{$}]", axisNum, distance); if (axisNum > 0 && axisNum < 100) { char temp[50] = { 0 }; sprintf_s(temp, "MOV%02d%+07d", axisNum, distance); return HWSendWaittimeCMD(temp, strlen(temp)); } return RET_STATUS::RET_FAILED; } RET_STATUS nsMech::HanQing3DDevice::MoveToPositionNumber(int axisNum, int PosNum) { mLog::Debug("Enter MoveToPositionNomber:[{$},{$}]", axisNum, PosNum); if (axisNum > 0 && axisNum < 100) { char temp[50] = { 0 }; sprintf_s(temp, "MVT%02d%+07d", axisNum, PosNum); return HWSendWaittimeCMD(temp, strlen(temp)); } return RET_STATUS::RET_FAILED; } RET_STATUS nsMech::HanQing3DDevice::GetAllAxisPosition() { mLog::Debug("Enter GetAllAxisPosition"); char temp[50] = { 0 }; sprintf_s(temp, "POS99"); return HWSendWaittimeCMD(temp, strlen(temp)); } RET_STATUS nsMech::HanQing3DDevice::SetAxisPositionNumber(int axisNum, int xPos, int yPos, int zPos, int rPos) { mLog::Debug("Enter SetPositionNomber:[{$},{$},{$},{$},{$}]", axisNum, xPos, yPos, zPos, rPos); if (axisNum > 0 && axisNum < 100) { char temp[50] = { 0 }; sprintf_s(temp, "HMX%02d%+07d,%+07d,%+07d,%+07d", axisNum, xPos, yPos, zPos, rPos); return HWSendWaittimeCMD(temp, strlen(temp)); } return RET_STATUS::RET_FAILED; } //----------------------------------------------------------------------------- // HanQing3DDriver //----------------------------------------------------------------------------- nsMech::HanQing3DDriver::HanQing3DDriver() { m_pDriGenDev = nullptr; m_pAttribute.reset(new ResDataObject()); m_pDescription.reset(new ResDataObject()); } nsMech::HanQing3DDriver::~HanQing3DDriver() { } auto nsMech::HanQing3DDriver::CreateDevice(int index) -> std::unique_ptr { mLog::Debug("Enter CreateDevice[{$}]", index); ////mLog::Info("Enter CreateDevice, index={$}", index); if (index == 0) { m_pDriGenDev = new HanQing3DDevice(EventCenter, m_SCF, m_ConfigFileName); auto dev = std::unique_ptr(new IODevice(m_pDriGenDev)); return dev; } //mLog::Error("unknown index"); unique_ptr dev; return dev; } void nsMech::HanQing3DDriver::FireNotify(int code, std::string key, std::string content) { mLog::Debug("Enter FireNotify"); EventCenter->OnNotify(code, key, content); } void nsMech::HanQing3DDriver::Prepare() { string strLogPath = GetProcessDirectory() + R"(\OEMDrivers\Mechanical\Conf\Log4CPP.Config.MECH.xml)"; //Log4CPP::ThreadContext::Map::Set("LogFileName", "Mech.HanQing3D"); Log4CPP::GlobalContext::Map::Set(ECOM::Utility::Hash("LogFileName"), "Mech.HanQing3D"); auto rc = Log4CPP::LogManager::LoadConfigFile(strLogPath.c_str()); mLog::gLogger = Log4CPP::LogManager::GetLogger("Mech.HanQing3D"); m_SCFDllName = GetConnectDLL(m_ConfigFileName); super::Prepare(); } bool nsMech::HanQing3DDriver::Connect() { mLog::Debug("Enter Connect"); ResDataObject Connection = GetConnectParam(m_ConfigFileName); mLog::Info("connections:{$} \n", Connection.encode()); auto erCode = m_SCF.Connect(Connection.encode(), &nsMech::HanQing3DDriver::callbackPackageProcess, SCF_PACKET_TRANSFER, 3000); if (erCode != SCF_ERR::SCF_SUCCEED) return false; //return erCode; auto rc = super::Connect(); if (!rc) return false; //return 0; return true; //return SCF_ERR::SCF_SUCCEED; } void nsMech::HanQing3DDriver::Disconnect() { mLog::Debug("Enter Disconnect"); super::Disconnect(); m_SCF.Disconnect(); } bool nsMech::HanQing3DDriver::isConnected() const { return super::isConnected(); } std::string nsMech::HanQing3DDriver::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::HanQing3DDriver::GetDeviceConfig(std::string& Cfg) { Cfg = m_DeviceConfigSend.encode(); printf("GetDeviceConfig over , %s", Cfg.c_str()); return true; } bool nsMech::HanQing3DDriver::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::HanQing3DDriver::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::HanQing3DDriver::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::HanQing3DDriver::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::HanQing3DDriver::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::HanQing3DDriver::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::HanQing3DDriver::Dequeue(const char* Packet, DWORD Length) { DecodeFrame(Packet, Length); } static char strRcvTemp[HanQing3D_Com_NormalLen] = { 0 }; PACKET_RET nsMech::HanQing3DDriver::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; mLog::Error("nLength too small, nLength=={$}", nLength); return PACKET_USELESS; } else if (nLength > HanQing3D_Com_NormalLen-1) { PacketLength = nLength; mLog::Error("nLength too big, nLength=={$}", nLength); return PACKET_USELESS; } memset(strRcvTemp, 0, HanQing3D_Com_NormalLen); for (DWORD i = 0; i < nLength; i++) { //寻找包头 if (RecData[i] == HanQing3D_STX) { if (i != 0) //包头之前的数据格式不对,全部扔掉 { PacketLength = i; memcpy_s(strRcvTemp, HanQing3D_Com_NormalLen - 1, RecData, PacketLength); mLog::Error("==IN unknown format data ==:[{$}],UselessDataLength={$},TotalLength={$}", strRcvTemp, PacketLength, nLength); return PACKET_USELESS; } else { bHasHead = true; } } //寻找包尾 if (RecData[i] == HanQing3D_ETX) { PacketLength = i + 1; //because ETX if (bHasHead) { if (i >= 6) //正常指令:STX(1BYTE) + CMDid(3BYTE) + [AxisNumber(2BYTE)] { memcpy_s(strRcvTemp, HanQing3D_Com_NormalLen - 1, RecData + 1, i - 1); //起始位置:+1 排除STX,长度:-1 排除ETX if (strncmp(strRcvTemp,"FFF",3) != 0) mLog::Info("==IN==:[{$}]", strRcvTemp); HanQing3DDevice::m_tDelivermodule.CheckReceive(strRcvTemp, 3); return PACKET_ISPACKET; } else //空指令 { memcpy_s(strRcvTemp, HanQing3D_Com_NormalLen - 1, RecData, PacketLength); //空数据,格式正确但无有效命令 mLog::Error("==IN uselss data==:[{$}]", strRcvTemp); return PACKET_USELESS; } } else //有包尾但无包头 { memcpy_s(strRcvTemp, HanQing3D_Com_NormalLen - 1, RecData, PacketLength); mLog::Error("==IN no head data ==:[{$}],NoHeadDataLength={$},TotalLength={$}", strRcvTemp, PacketLength, nLength); return PACKET_USELESS; } } } if (bHasHead) { PacketLength = 0; } return PACKET_NOPACKET; } //模块对外接口 static nsMech::HanQing3DDriver gIODriver; extern "C" DIOS::Dev::IODriver * __cdecl GetIODriver() // 返回静态对象的引用, 调用者不能删除 ! { return &gIODriver; } extern "C" DIOS::Dev::IODriver * __cdecl CreateIODriver() // 返回新对象, 调用者必须自行删除此对象 ! { return new nsMech::HanQing3DDriver(); }