DICOM cmove scu

21 篇文章 0 订阅

基于dcmtk cmove scu仅供参考

#ifndef DICOMCMOVESCU_H
#define DICOMCMOVESCU_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 CListCtrl;

struct tag_Movekey
{
	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 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;
	
	long dw;
	CListCtrl *listctr;
	//net
	std::string aet_;
	std::string ip_;
	int port_;
	std::string aeted_;
	bool secureConnection;
	unsigned short maxReceivePDULength;
	unsigned short acse_timeout;
	OFBool     mopt_abortAssociation;
	std::string    mopt_moveDestination;

	std::string sopClass;
	//回调指针
	tag_Movekey()
	{
		maxReceivePDULength=16383;
		secureConnection=false;
		acse_timeout=10;
	    mopt_abortAssociation = OFFalse;
		sopClass=UID_MOVEPatientRootQueryRetrieveInformationModel;
		//UID_MOVEStudyRootQueryRetrieveInformationModel
	}
};

class DicomCMoveScu
{
public:
	DicomCMoveScu();
	~DicomCMoveScu();

public:
	bool startMove();
	void move();
	OFCondition addPresentationContext(
		T_ASC_Parameters *params,
		const char *abstractSyntax,
		E_TransferSyntax preferredTransferSyntax);

	void SetParamter(tag_Movekey &movekey_);
private:
	T_ASC_Network *net_;
	tag_Movekey moveKey_;
	T_DIMSE_BlockingMode mopt_blockMode;
};
#endif


#include "winsock2.h"
#include "stdafx.h"
#include "DicomCMoveScu.h"

#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/ofstdinc.h"
#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/ofstd/ofconapp.h"
#include "dcmtk/dcmnet/dicom.h"
#include "dcmtk/dcmnet/dimse.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/dcmdata/dcdict.h"
#include "dcmtk/dcmdata/cmdlnarg.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcmetinf.h"
#include "dcmtk/dcmdata/dcuid.h"     
#include "dcmtk/dcmdata/dcdicent.h"
#include "dcmtk/dcmdata/dcostrmz.h" 
#include "../pacslog.h"

typedef struct {
	T_ASC_Association *assoc;
	T_ASC_PresentationContextID presId;
	long mopt_cancelAfterNResponses ;
	bool IsCancelNResponses;
	tag_Movekey *mokey;
} MyCallbackInfo;

static void
	moveCallback(void *callbackData, T_DIMSE_C_MoveRQ *request,
	int responseCount, T_DIMSE_C_MoveRSP *response)
{
	OFCondition cond = EC_Normal;
	MyCallbackInfo *myCallbackData;

	myCallbackData = OFstatic_cast(MyCallbackInfo*, callbackData);
	CString text;
	text.Format(_T("%d"),responseCount);
	myCallbackData->mokey->listctr->SetItemText(myCallbackData->mokey->dw-1,10,text);
	
	OFString temp_str;
	DICOM_INFO("Move Response " << responseCount << ":" << OFendl << DIMSE_dumpMessage(temp_str, *response, DIMSE_INCOMING));
	/* should we send a cancel back ?? */
	if (myCallbackData->IsCancelNResponses&&myCallbackData->mopt_cancelAfterNResponses == responseCount) {
		DICOM_INFO("Sending Cancel Request: MsgID " << request->MessageID
			<< ", PresID " << myCallbackData->presId);
		cond = DIMSE_sendCancelRequest(myCallbackData->assoc,
			myCallbackData->presId, request->MessageID);
		if (cond != EC_Normal) {
			DICOM_ERROR("Cancel Request Failed: " << DimseCondition::dump(temp_str, cond));
		}

	}
}


DicomCMoveScu::DicomCMoveScu()
	:net_(0),
	mopt_blockMode(DIMSE_BLOCKING)
{

}
DicomCMoveScu::~DicomCMoveScu()
{

}
void DicomCMoveScu::SetParamter(tag_Movekey &movekey)
{
	moveKey_=movekey;
}
OFCondition DicomCMoveScu::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 DicomCMoveScu::startMove()
{
	OFString temp_str;
	T_ASC_Parameters *params = NULL;
	const char *opt_peer=moveKey_.ip_.c_str();
	OFCmdUnsignedInt opt_port =moveKey_.port_;
	DIC_NODENAME localHost;
	DIC_NODENAME peerHost;
	T_ASC_Association *assoc = NULL;
	const char *opt_peerTitle =moveKey_.aeted_.c_str();
	const char *opt_ourTitle =moveKey_.aet_.c_str();

	if (!dcmDataDict.isDictionaryLoaded())
	{
		DICOM_INFO("no data dictionary loaded, check environment variable: "
			<< DCM_DICT_ENVIRONMENT_VARIABLE);
	}
	//1 初始化网络
	OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, moveKey_.acse_timeout, &net_);
	if (cond.bad())
	{
		DICOM_FATAL("cannot create network: " << DimseCondition::dump(temp_str, cond));
		return false;
	}
	//2 创建参数
	cond = ASC_createAssociationParameters(¶ms, moveKey_.acse_timeout);
	if (cond.bad()) {
		DICOM_FATAL(DimseCondition::dump(temp_str, cond));
		return false;
	}
	//设置ae
	ASC_setAPTitles(params, opt_ourTitle, opt_peerTitle, NULL);
	gethostname(localHost, sizeof(localHost) - 1);
	sprintf(peerHost, "%s:%d", opt_peer, OFstatic_cast(int, opt_port));
	//设置演示地址
	ASC_setPresentationAddresses(params, localHost, peerHost);
	//添加演示上下文
	cond = addPresentationContext(params, moveKey_.sopClass.c_str(),
		EXS_LittleEndianExplicit);

	if (cond.bad()) {
		DICOM_FATAL(DimseCondition::dump(temp_str, cond));
		return false;
	}
	DICOM_DEBUG("Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ));
    DICOM_INFO("请求关联");
	cond = ASC_requestAssociation(net_, params, &assoc);
	if (cond.bad()) {
		if (cond == DUL_ASSOCIATIONREJECTED) {
			T_ASC_RejectParameters rej;

			ASC_getRejectParameters(params, &rej);
			DICOM_FATAL("Association Rejected:");
			DICOM_FATAL(ASC_printRejectParameters(temp_str, &rej));
			return false;
		} else {
			DICOM_FATAL("Association Request Failed:");
			DICOM_FATAL( DimseCondition::dump(temp_str, cond));
			return false;
		}
	}

	DICOM_DEBUG("Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_AC));

	if (ASC_countAcceptedPresentationContexts(params) == 0) {
		DICOM_FATAL("No Acceptable Presentation Contexts");
		return false;
	}
	DICOM_INFO("Association Accepted (Max Send PDV: " << assoc->sendPDVLength << ")");

	cond = EC_Normal;

	T_ASC_PresentationContextID presId;
	T_DIMSE_C_MoveRQ    req;
	T_DIMSE_C_MoveRSP   rsp;
	DIC_US              msgId = assoc->nextMsgID++;
	DcmDataset          *rspIds = NULL;
	const char          *sopClass;
	DcmDataset          *statusDetail = NULL;
	 MyCallbackInfo      callbackData;
	
	presId = ASC_findAcceptedPresentationContextID(assoc, moveKey_.sopClass.c_str());
	if (presId == 0) return false;

	DICOM_INFO("Sending Move Request: MsgID " << msgId);
	
	callbackData.assoc = assoc;
	callbackData.presId = presId;
	callbackData.IsCancelNResponses=false;
	callbackData.mokey=&moveKey_;

	req.MessageID = msgId;
	strcpy(req.AffectedSOPClassUID, moveKey_.sopClass.c_str());
	req.Priority = DIMSE_PRIORITY_MEDIUM;
	req.DataSetType = DIMSE_DATASET_PRESENT;
	if (moveKey_.mopt_moveDestination.empty()) {
		ASC_getAPTitles(assoc->params, req.MoveDestination,
			NULL, NULL);
	} else {
		strcpy(req.MoveDestination, moveKey_.mopt_moveDestination.c_str());
	}
	DcmDataset dest;
	dest.putAndInsertString(DCM_QueryRetrieveLevel,moveKey_.ql.c_str());
	dest.putAndInsertString(DCM_StudyInstanceUID,moveKey_.studyInstanceUid.c_str());

	DICOM_INFO("移动条件:" << OFendl << DcmObject::PrintHelper(dest));

	cond = DIMSE_moveUser(assoc, presId, &req, &dest,
		moveCallback, &callbackData, mopt_blockMode, moveKey_.acse_timeout, net_, 0,
		NULL, &rsp, &statusDetail, &rspIds, OFTrue);

	if (cond==EC_Normal) {
		OFString temp_str;
		DICOM_INFO(DIMSE_dumpMessage(temp_str, rsp, DIMSE_INCOMING));
		if (rspIds != NULL) {
			DICOM_INFO("Response Identifiers:" << OFendl << DcmObject::PrintHelper(*rspIds));
		}
	} else {
		OFString temp_str;
		DICOM_ERROR("Move Request Failed: " << DimseCondition::dump(temp_str, cond));
	}
	if (statusDetail != NULL) {
		DICOM_WARN("Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail));
		delete statusDetail;
	}

	if (rspIds != NULL) delete rspIds;


	if (cond == EC_Normal)
	{
		if (moveKey_.mopt_abortAssociation) {
			DICOM_INFO("Aborting Association");
			cond = ASC_abortAssociation(assoc);
			if (cond.bad()) {
				DICOM_FATAL("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
				return false;
			}
		} else {

			DICOM_INFO("Releasing Association");
			cond = ASC_releaseAssociation(assoc);
			if (cond.bad())
			{
				DICOM_FATAL("Association Release Failed:");
				DICOM_FATAL( 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_FATAL("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
			return false;
		}
	}
	else if (cond == DUL_PEERABORTEDASSOCIATION)
	{
		DICOM_INFO("Peer Aborted Association");
	}
	else
	{
		DICOM_ERROR( "Move SCU Failed: " << DimseCondition::dump(temp_str, cond));
		DICOM_INFO("Aborting Association");
		cond = ASC_abortAssociation(assoc);
		if (cond.bad()) {
			DICOM_FATAL("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
			return false;
		}
	}

	cond = ASC_destroyAssociation(&assoc);
	if (cond.bad()) {
		DICOM_FATAL(DimseCondition::dump(temp_str, cond));
		return false;
	}
	cond = ASC_dropNetwork(&net_);
	if (cond.bad()) {
		DICOM_FATAL(DimseCondition::dump(temp_str, cond));
		return false;
	}
	return false;
}
void DicomCMoveScu::move()
{
	startMove();
	delete this;
}

DICOM协议交流群:107534874

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值