dicom cfind scu

21 篇文章 0 订阅
//头文件
#ifndef DICOMCFINDSCU_H
#define DICOMCFINDSCU_H

#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/ofcond.h"    /* for class OFCondition */
#include "dcmtk/dcmdata/dcxfer.h"  /* for E_TransferSyntax */
#include "dcmtk/dcmnet/dimse.h"    /* for T_DIMSE_BlockingMode */

#include <string>


class DcmDataset;
class DcmTransportLayer;
class OFConsoleApplication;
struct T_ASC_Association;
struct T_ASC_Parameters;
struct T_DIMSE_C_FindRQ;
struct T_DIMSE_C_FindRSP;


class DicomCfindScuCallback
{
public:
	DicomCfindScuCallback();

	virtual ~DicomCfindScuCallback() {}
  virtual void callback(
        T_DIMSE_C_FindRQ *request,
        int responseCount,
        T_DIMSE_C_FindRSP *rsp,
        DcmDataset *responseIdentifiers) = 0;

  void setAssociation(T_ASC_Association *assoc);

  void setPresentationContextID(T_ASC_PresentationContextID presId);

protected: 

   T_ASC_Association *assoc_;

   T_ASC_PresentationContextID presId_;

private:

  DicomCfindScuCallback(const DicomCfindScuCallback& other);

  DicomCfindScuCallback& operator=(const DicomCfindScuCallback& other);
};
//默认回调
class DicomCfindScuDefaultCallback:
	public DicomCfindScuCallback
{
public:
	DicomCfindScuDefaultCallback(int cancelAfterNResponses);

  virtual void callback(
        T_DIMSE_C_FindRQ *request,
        int responseCount,
        T_DIMSE_C_FindRSP *rsp,
        DcmDataset *responseIdentifiers);
protected:
  int cancelAfterNResponses_;
};

struct tag_findkey
{
	std::string studydate;
	std::string studytime;
	std::string paitientId;
	std::string paitientname;
	std::string accessionNumber;
	std::string birthdate;
	std::string studyid;
	std::string studyInstanceUid;
	std::string studyDes;
	std::string refphName;
	std::string sericeNumber;
	std::string sericeUid;
	std::string instanceNumber;
	std::string instanceUid;
	std::string reqId;
	std::string ppsid;
	std::string studyinMod;
	std::string sericeMod;
	std::string ppsdate;
	std::string ppstime;
	std::string ql;
	//net
	std::string aet_;
	std::string ip_;
	int port_;
	std::string aeted_;
	bool secureConnection;
	unsigned short maxReceivePDULength;
	unsigned short acse_timeout;
	//回调指针
	DicomCfindScuCallback *ccallback;
	tag_findkey()
	{
		maxReceivePDULength=16383;
		secureConnection=false;
		acse_timeout=10;
	}
};


class DicomCfindScu
{
public:
	DicomCfindScu();
	~DicomCfindScu();
	OFCondition initializeNetwork(int acse_timeout);


	OFCondition setTransportLayer(DcmTransportLayer *tLayer);


	OFCondition dropNetwork();

	OFCondition addPresentationContext(
		T_ASC_Parameters *params,
		const char *abstractSyntax,
		E_TransferSyntax preferredTransferSyntax);
   bool find();
   bool cfind();
   void SetParamter(tag_findkey &findkey);
   void setFindType(int findtype_);
private:
   tag_findkey findkey_;
    T_ASC_Network *net_;
	int findtype;
};
#endif

//源文件

#include "winsock2.h"
#include "stdafx.h"
#include "DicomCfindScu.h"
#include "dcmtk/ofstd/ofstdinc.h"

#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdicent.h"
#include "dcmtk/dcmdata/dcdict.h"
#include "dcmtk/dcmdata/dcpath.h"
#include "dcmtk/ofstd/ofconapp.h"
#include "dcmtk/dcmdata/dcdeftag.h"

#include "../pacslog.h"

static void DicomCfindScuprogress(
	void *callbackData,
	T_DIMSE_C_FindRQ *request,
	int responseCount,
	T_DIMSE_C_FindRSP *rsp,
	DcmDataset *responseIdentifiers)
{
	DicomCfindScuCallback *callback = OFreinterpret_cast(DicomCfindScuCallback *, callbackData);
	if (callback) callback->callback(request, responseCount, rsp, responseIdentifiers);
}

DicomCfindScuCallback::DicomCfindScuCallback()
	: assoc_(NULL)
	, presId_(0)
{

}

void DicomCfindScuCallback::setAssociation(T_ASC_Association *assoc)
{
	assoc_ = assoc;
}

void DicomCfindScuCallback::setPresentationContextID(T_ASC_PresentationContextID presId)
{
	presId_ = presId;
}

DicomCfindScuDefaultCallback::DicomCfindScuDefaultCallback(int cancelAfterNResponses)
	:DicomCfindScuCallback(),
	cancelAfterNResponses_(cancelAfterNResponses)
{

}
void DicomCfindScuDefaultCallback::callback(
	T_DIMSE_C_FindRQ *request,
	int responseCount,
	T_DIMSE_C_FindRSP *rsp,
	DcmDataset *responseIdentifiers)
{

	OFString temp_str;
	DCMNET_INFO("Received Find Response " << responseCount);
	DCMNET_DEBUG(DIMSE_dumpMessage(temp_str, *rsp, DIMSE_INCOMING));
	DCMNET_DEBUG("Response Identifiers:" << OFendl << DcmObject::PrintHelper(*responseIdentifiers));


	if (cancelAfterNResponses_ == responseCount)
	{
		DCMNET_INFO("Sending Cancel Request (MsgID " << request->MessageID
			<< ", PresID " << OFstatic_cast(unsigned int, presId_) << ")");
		OFCondition cond = DIMSE_sendCancelRequest(assoc_, presId_, request->MessageID);
		if (cond.bad())
		{
			OFString temp_str;
			DCMNET_ERROR("Cancel Request Failed: " << DimseCondition::dump(temp_str, cond));
		}
	}
}

//=====================================================
DicomCfindScu::DicomCfindScu()
	:net_(0)
	,findtype(0)
{

}
DicomCfindScu::~DicomCfindScu()
{
	 dropNetwork();
	 delete findkey_.ccallback;
}
OFCondition DicomCfindScu::initializeNetwork(int acse_timeout)
{
	 return ASC_initializeNetwork(NET_REQUESTOR, 0, acse_timeout, &net_);
}


OFCondition DicomCfindScu::setTransportLayer(DcmTransportLayer *tLayer)
{
	return ASC_setTransportLayer(net_, tLayer, 0);
}


OFCondition DicomCfindScu::dropNetwork()
{
	if (net_) return ASC_dropNetwork(&net_); else return EC_Normal;
}

OFCondition DicomCfindScu::addPresentationContext(
	T_ASC_Parameters *params,
	const char *abstractSyntax,
	E_TransferSyntax preferredTransferSyntax)
{

	const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL };
	int numTransferSyntaxes = 0;

	switch (preferredTransferSyntax) {
	case EXS_LittleEndianImplicit:
		transferSyntaxes[0]  = UID_LittleEndianImplicitTransferSyntax;
		numTransferSyntaxes = 1;
		break;
	case EXS_LittleEndianExplicit:
		transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
		transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
		transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
		numTransferSyntaxes = 3;
		break;
	case EXS_BigEndianExplicit:
		transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax;
		transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax;
		transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
		numTransferSyntaxes = 3;
		break;
	default:

		if (gLocalByteOrder == EBO_LittleEndian)  /* defined in dcxfer.h */
		{
			transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
			transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
		} else {
			transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax;
			transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax;
		}
		transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
		numTransferSyntaxes = 3;
		break;
	}

	return ASC_addPresentationContext(
		params, 1, abstractSyntax,
		transferSyntaxes, numTransferSyntaxes);
}
bool DicomCfindScu::cfind()
{
	T_ASC_Association *assoc = NULL;
	T_ASC_Parameters *params = NULL;
	DIC_NODENAME localHost;
	DIC_NODENAME peerHost;
	OFString temp_str;
	OFCondition cond=EC_Normal;
	const char *abstractSyntax=UID_FINDPatientRootQueryRetrieveInformationModel;
	OFBool abortAssociation=OFTrue;
	//==============================
	T_ASC_PresentationContextID presId;
	T_DIMSE_C_FindRQ req;
	T_DIMSE_C_FindRSP rsp;
	int repeatCount=1;
	T_DIMSE_BlockingMode  opt_blockMode = DIMSE_BLOCKING;

#ifdef HAVE_WINSOCK_H
	WSAData winSockData;
	/* we need at least version 1.1 */
	WORD winSockVersionNeeded = MAKEWORD( 1, 1 );
	WSAStartup(winSockVersionNeeded, &winSockData);
#endif
	//1 初始化网络
	cond=initializeNetwork(findkey_.acse_timeout);
	 if (cond.bad()) {
		 DICOM_ERROR(DimseCondition::dump(temp_str, cond));
		 return false;
	 }
	 //2 创建关联参数
	cond=ASC_createAssociationParameters(¶ms,findkey_.maxReceivePDULength);
	if (cond.bad()){
		DICOM_ERROR(DimseCondition::dump(temp_str, cond));
		return false;
	}

	//3 设置aet
	ASC_setAPTitles(params, findkey_.aet_.c_str(), findkey_.aeted_.c_str(), NULL);

	//4 设置安全存
	cond = ASC_setTransportLayerType(params, findkey_.secureConnection);
	if (cond.bad()) return false;

	//5 添加演示地址
	gethostname(localHost, sizeof(localHost) - 1);
	sprintf(peerHost, "%s:%d", findkey_.ip_.c_str(), findkey_.port_);
	ASC_setPresentationAddresses(params, localHost, peerHost);

	//6 添加演示上下文
	cond = addPresentationContext(params, abstractSyntax,EXS_LittleEndianExplicit);
	if (cond.bad()) return false;
	DICOM_INFO("Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ));
	DCMNET_INFO("Requesting Association");
	
	// 7请求关联
	cond = ASC_requestAssociation(net_, params, &assoc);

	if (cond.bad()) {
		if (cond == DUL_ASSOCIATIONREJECTED) {
			T_ASC_RejectParameters rej;
			ASC_getRejectParameters(params, &rej);

			DICOM_ERROR("Association Rejected:" << OFendl << ASC_printRejectParameters(temp_str, &rej));
			return false;
		} else {
			DICOM_ERROR("Association Request Failed: " << DimseCondition::dump(temp_str, cond));
			return false;
		}
	}
	DICOM_INFO("Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_AC));
    

	//8关联上下文数量
	if (ASC_countAcceptedPresentationContexts(params) == 0) {
		DICOM_ERROR("No Acceptable Presentation Contexts");
		return false;
	}

	//9查找
	presId = ASC_findAcceptedPresentationContextID(assoc, abstractSyntax);
	if (presId == 0) {
		DICOM_ERROR("No presentation context");
		return false;
	}
	/* prepare C-FIND-RQ message */
	bzero(OFreinterpret_cast(char*, &req), sizeof(req));
	strcpy(req.AffectedSOPClassUID, abstractSyntax);
	req.DataSetType = DIMSE_DATASET_PRESENT;
	req.Priority = DIMSE_PRIORITY_LOW;

	/* prepare the callback data */
	findkey_.ccallback->setAssociation(assoc);
	findkey_.ccallback->setPresentationContextID(presId);
	int n = repeatCount;
	cond=EC_Normal;
	DcmDataset dset;
	if (findtype==0){
		dset.putAndInsertString(DCM_PatientID,findkey_.paitientId.c_str());
		dset.putAndInsertString(DCM_PatientName,findkey_.paitientname.c_str());
		dset.putAndInsertString(DCM_PatientBirthDate,findkey_.birthdate.c_str());
		dset.putAndInsertString(DCM_StudyDate,findkey_.studydate.c_str());
		dset.putAndInsertString(DCM_StudyTime,findkey_.studytime.c_str());
		dset.putAndInsertString(DCM_AccessionNumber,findkey_.accessionNumber.c_str());
		dset.putAndInsertString(DCM_StudyID,findkey_.studyid.c_str());
		dset.putAndInsertString(DCM_StudyInstanceUID,findkey_.studyInstanceUid.c_str());
		dset.putAndInsertString(DCM_StudyDescription,findkey_.studyDes.c_str());
		dset.insertEmptyElement(DCM_ModalitiesInStudy);
		dset.putAndInsertString(DCM_ReferringPhysicianName,findkey_.paitientId.c_str());
		dset.putAndInsertString(DCM_NumberOfStudyRelatedInstances,"");
		dset.putAndInsertString(DCM_SeriesNumber,findkey_.sericeNumber.c_str());
		dset.putAndInsertString(DCM_SeriesInstanceUID,findkey_.sericeUid.c_str());
		dset.putAndInsertString(DCM_InstanceNumber,findkey_.instanceNumber.c_str());
		dset.putAndInsertString(DCM_SOPInstanceUID,findkey_.instanceUid.c_str());
		dset.putAndInsertString(DCM_RequestedProcedureID,findkey_.reqId.c_str());
		dset.putAndInsertString(DCM_ScheduledProcedureStepID ,findkey_.reqId.c_str());
		dset.putAndInsertString(DCM_RequestedProcedureID,findkey_.ppsid.c_str());
		dset.putAndInsertString(DCM_ModalitiesInStudy,findkey_.studyinMod.c_str());
		dset.putAndInsertString(DCM_Modality,findkey_.sericeMod.c_str());
		dset.putAndInsertString(DCM_PerformedProcedureStepStartDate,findkey_.ppsdate.c_str());
		dset.putAndInsertString(DCM_PerformedProcedureStepStartTime,findkey_.ppstime.c_str());
		dset.putAndInsertString(DCM_QueryRetrieveLevel,findkey_.ql.c_str());
	}
	else if (findtype==1){
		dset.putAndInsertString(DCM_StudyInstanceUID,findkey_.studyInstanceUid.c_str());
		dset.putAndInsertString(DCM_QueryRetrieveLevel,findkey_.ql.c_str());
		dset.insertEmptyElement(DCM_Modality);
		dset.insertEmptyElement(DCM_SeriesNumber);
		dset.insertEmptyElement(DCM_SeriesDescription);
		dset.insertEmptyElement(DCM_SeriesInstanceUID);
		dset.insertEmptyElement(DCM_NumberOfSeriesRelatedInstances);
	}
	//DICOM_INFO("查找条件:" << OFendl << DcmObject::PrintHelper(dset));
	while (cond.good() && n--)
	{
		DcmDataset *statusDetail = NULL;
		req.MessageID = assoc->nextMsgID++;
		if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
		{
			DICOM_INFO("Sending Find Request");
			DICOM_DEBUG(DIMSE_dumpMessage(temp_str, req, DIMSE_OUTGOING, NULL, presId));
		} else {
			DICOM_INFO("Sending Find Request (MsgID " << req.MessageID << ")");
		}
		DICOM_INFO("Request Identifiers:" << OFendl << DcmObject::PrintHelper(dset));
		
		/* finally conduct transmission of data */
		cond = DIMSE_findUser(assoc, presId, &req, &dset,
			DicomCfindScuprogress, findkey_.ccallback, opt_blockMode, findkey_.acse_timeout,
			&rsp, &statusDetail);

		if (statusDetail != NULL) {
			DICOM_DEBUG("Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail));
			delete statusDetail;
		}
	}
	//10释放关联
	if (cond == EC_Normal)
	{
		if (abortAssociation) {
			DICOM_INFO("Aborting Association");
			cond = ASC_abortAssociation(assoc);
			if (cond.bad()) {
				DICOM_ERROR("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
				return false;
			}
		} else {
			/* release association */
			DICOM_INFO("Releasing Association");
			cond = ASC_releaseAssociation(assoc);
			if (cond.bad())
			{
				DCMNET_ERROR("Association Release Failed: " << DimseCondition::dump(temp_str, cond));
				return false;
			}
		}
	}
	else if (cond == DUL_PEERREQUESTEDRELEASE)
	{
		DICOM_ERROR("Protocol Error: Peer requested release (Aborting)");
		DICOM_INFO("Aborting Association");
		cond = ASC_abortAssociation(assoc);
		if (cond.bad()) {
			DICOM_ERROR("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
			return false;
		}
	}
	else if (cond == DUL_PEERABORTEDASSOCIATION)
	{
		DICOM_INFO("Peer Aborted Association");
	}
	else
	{
		DICOM_ERROR("Find SCU Failed: " << DimseCondition::dump(temp_str, cond));
		DICOM_INFO("Aborting Association");
		cond = ASC_abortAssociation(assoc);
		if (cond.bad()) {
			DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
			return false;
		}
	}
	//11 删除关联
	cond = ASC_destroyAssociation(&assoc);
	if (cond.bad())
		DICOM_ERROR(DimseCondition::dump(temp_str, cond));
	//12 删除网络
	dropNetwork();

	return true;
}
void DicomCfindScu::SetParamter(tag_findkey &findkey)
{
	findkey_=findkey;
}
bool DicomCfindScu::find()
{
	bool isok=false;
	isok=cfind();
	delete this;
	return isok;
}
 void DicomCfindScu::setFindType(int findtype_)
 {
	 findtype=findtype_;
 }

//dicom协议交流群:107534874

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值