comparison OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp @ 5853:4d932683049d get-scu tip

very first implementation of C-Get SCU
author Alain Mazy <am@orthanc.team>
date Tue, 29 Oct 2024 17:25:49 +0100
parents a8e9113dc8f1
children
comparison
equal deleted inserted replaced
5839:7aef730c0859 5853:4d932683049d
34 #include "../OrthancConfiguration.h" 34 #include "../OrthancConfiguration.h"
35 #include "../QueryRetrieveHandler.h" 35 #include "../QueryRetrieveHandler.h"
36 #include "../ServerContext.h" 36 #include "../ServerContext.h"
37 #include "../ServerJobs/DicomModalityStoreJob.h" 37 #include "../ServerJobs/DicomModalityStoreJob.h"
38 #include "../ServerJobs/DicomMoveScuJob.h" 38 #include "../ServerJobs/DicomMoveScuJob.h"
39 #include "../ServerJobs/DicomGetScuJob.h"
39 #include "../ServerJobs/OrthancPeerStoreJob.h" 40 #include "../ServerJobs/OrthancPeerStoreJob.h"
40 #include "../ServerToolbox.h" 41 #include "../ServerToolbox.h"
41 #include "../StorageCommitmentReports.h" 42 #include "../StorageCommitmentReports.h"
42 43
43 44
1620 OrthancRestApi::GetApi(call).SubmitCommandsJob 1621 OrthancRestApi::GetApi(call).SubmitCommandsJob
1621 (call, job.release(), true /* synchronous by default */, request); 1622 (call, job.release(), true /* synchronous by default */, request);
1622 return; 1623 return;
1623 } 1624 }
1624 1625
1626
1627 /***************************************************************************
1628 * DICOM C-Get SCU
1629 ***************************************************************************/
1630
1631 static void DicomGet(RestApiPostCall& call)
1632 {
1633 if (call.IsDocumentation())
1634 {
1635 OrthancRestApi::DocumentSubmitCommandsJob(call);
1636 call.GetDocumentation()
1637 .SetTag("Networking")
1638 .SetSummary("Trigger C-GET SCU")
1639 .SetDescription("Start a C-GET SCU command as a job, in order to retrieve DICOM resources "
1640 "from a remote DICOM modality whose identifier is provided in the URL: ")
1641 // "https://orthanc.uclouvain.be/book/users/rest.html#performing-c-move")
1642 .SetRequestField(KEY_QUERY, RestApiCallDocumentation::Type_JsonObject,
1643 "A query object identifying all the DICOM resources to be retrieved", true)
1644 .SetRequestField(KEY_LOCAL_AET, RestApiCallDocumentation::Type_String,
1645 "Local AET that is used for this commands, defaults to `DicomAet` configuration option. "
1646 "Ignored if `DicomModalities` already sets `LocalAet` for this modality.", false)
1647 .SetRequestField(KEY_TIMEOUT, RestApiCallDocumentation::Type_Number,
1648 "Timeout for the C-GET command, in seconds", false)
1649 .SetUriArgument("id", "Identifier of the modality of interest");
1650 return;
1651 }
1652
1653 ServerContext& context = OrthancRestApi::GetContext(call);
1654
1655 Json::Value request;
1656
1657 if (!call.ParseJsonRequest(request) ||
1658 request.type() != Json::objectValue ||
1659 !request.isMember(KEY_QUERY) ||
1660 request[KEY_QUERY].type() != Json::objectValue)
1661 {
1662 throw OrthancException(ErrorCode_BadFileFormat, "Must provide a JSON body containing fields " +
1663 std::string(KEY_QUERY));
1664 }
1665
1666 std::string localAet = Toolbox::GetJsonStringField // TODO-GET: keep this ?
1667 (request, KEY_LOCAL_AET, context.GetDefaultLocalApplicationEntityTitle());
1668
1669 const RemoteModalityParameters source =
1670 MyGetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
1671
1672 std::unique_ptr<DicomGetScuJob> job(new DicomGetScuJob(context));
1673
1674 job->SetQueryFormat(DicomToJsonFormat_Short); // TODO-GET: keep this ?
1675 job->SetLocalAet(localAet);
1676 job->SetRemoteModality(source);
1677
1678 // TODO-GET: asynchronous
1679 // TODO-GET: permissive
1680
1681
1682 if (request[KEY_QUERY].isMember("PatientID")) // TODO-GET: handle get of multiple resources + series + instances
1683 {
1684 job->AddResourceToRetrieve(ResourceType_Patient, request[KEY_QUERY]["PatientID"].asString());
1685 }
1686 else if (request[KEY_QUERY].isMember("StudyInstanceUID")) // TODO-GET: handle get of multiple resources + series + instances
1687 {
1688 job->AddResourceToRetrieve(ResourceType_Study, request[KEY_QUERY]["StudyInstanceUID"].asString());
1689 }
1690
1691 if (request.isMember(KEY_TIMEOUT))
1692 {
1693 job->SetTimeout(SerializationToolbox::ReadUnsignedInteger(request, KEY_TIMEOUT));
1694 }
1695
1696 OrthancRestApi::GetApi(call).SubmitCommandsJob
1697 (call, job.release(), true /* synchronous by default */, request);
1698 return;
1699 }
1625 1700
1626 1701
1627 /*************************************************************************** 1702 /***************************************************************************
1628 * Orthanc Peers => Store client 1703 * Orthanc Peers => Store client
1629 ***************************************************************************/ 1704 ***************************************************************************/
2542 Register("/modalities/{id}/find-instance", DicomFindInstance); 2617 Register("/modalities/{id}/find-instance", DicomFindInstance);
2543 Register("/modalities/{id}/find", DicomFind); 2618 Register("/modalities/{id}/find", DicomFind);
2544 Register("/modalities/{id}/store", DicomStore); 2619 Register("/modalities/{id}/store", DicomStore);
2545 Register("/modalities/{id}/store-straight", DicomStoreStraight); // New in 1.6.1 2620 Register("/modalities/{id}/store-straight", DicomStoreStraight); // New in 1.6.1
2546 Register("/modalities/{id}/move", DicomMove); 2621 Register("/modalities/{id}/move", DicomMove);
2622 Register("/modalities/{id}/get", DicomGet);
2547 Register("/modalities/{id}/configuration", GetModalityConfiguration); // New in 1.8.1 2623 Register("/modalities/{id}/configuration", GetModalityConfiguration); // New in 1.8.1
2548 2624
2549 // For Query/Retrieve 2625 // For Query/Retrieve
2550 Register("/modalities/{id}/query", DicomQuery); 2626 Register("/modalities/{id}/query", DicomQuery);
2551 Register("/queries", ListQueries); 2627 Register("/queries", ListQueries);