/// Responds to a cstore request, which kicks off a StreamToRules task public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request) { var taskID = _taskManager.NewTaskID(); var taskInfo = $"task: {taskID} messageID: {request.MessageID} connection: {((DICOMConnection)(base.UserState)).name}"; try { var fromConnection = _connectionFinder.GetDicomConnectionToLocalAETitle(_profileStorage.Current, Association.CalledAE); if (fromConnection == null) { //We have an inbound Association.CalledAE that we aren't configured for logger.Log(LogLevel.Warning, $"{taskInfo} There is no connection defined where the LocalAETitle matches the Association.CalledAE: {Association.CalledAE}"); return(new DicomCStoreResponse(request, DicomStatus.ProcessingFailure)); } logger.Log(LogLevel.Information, $"{taskInfo} CStoreRequest from {fromConnection.name}"); var conn = ((DICOMConnection)(base.UserState)); // var dir = profile.tempPath + Path.DirectorySeparatorChar + ((DICOMConnection)(base.UserState)).name + Path.DirectorySeparatorChar + "toRules"; // Directory.CreateDirectory(dir); // var filename = dir + Path.DirectorySeparatorChar + System.Guid.NewGuid(); // LifeImageLite.Logger.logger.Log(TraceEventType.Verbose, $"{taskInfo} Moving from {request.File.File.Name} to {filename}"); // request.File.File.Move(dstFileName: filename); RoutedItem routedItem = new RoutedItem( fromConnection: fromConnection.name, sourceFileName: request.File.File.Name, taskID: taskID) { type = RoutedItem.Type.DICOM }; request.Dataset.TryGetValue <string>(DicomTag.PatientID, 0, out routedItem.PatientID); request.Dataset.TryGetValue <string>(DicomTag.AccessionNumber, 0, out routedItem.AccessionNumber); request.Dataset.TryGetValue <string>(DicomTag.StudyInstanceUID, 0, out routedItem.Study); request.Dataset.TryGetValue <string>(DicomTag.StudyID, 0, out routedItem.StudyID); foreach (var item in request.Command) { logger.Log(LogLevel.Debug, $"Command tag: {item.Tag} value: {item.ValueRepresentation}"); } routedItem.id = $"PID:{routedItem.PatientID}, AN:{routedItem.AccessionNumber}"; // , UID:{routedItem.Study}"; //profile.rules.SendToRules(routedItem).Wait(); routedItem.priority = _util.GetPriority((ushort)request.Priority); _routedItemManager.Init(routedItem); _routedItemManager.Enqueue(conn, conn.toRules, nameof(conn.toRules), copy: true); DicomStatus status = DicomStatus.Success; DicomCStoreResponse response = new DicomCStoreResponse(request, status) { //Dataset = request.Dataset }; response.Command.AddOrUpdate(DicomTag.AffectedSOPInstanceUID, request.Dataset.GetValue <string>(DicomTag.SOPInstanceUID, 0)); response.Command.AddOrUpdate(DicomTag.AffectedSOPClassUID, request.Dataset.GetValue <string>(DicomTag.SOPClassUID, 0)); return(response); } catch (Exception e) { logger.Log(LogLevel.Critical, $"{taskInfo} {e.Message} {e.StackTrace}"); if (e.InnerException != null) { logger.Log(LogLevel.Critical, $"Inner Exception: {e.InnerException}"); } request.Dataset.AddOrUpdate(DicomTag.AffectedSOPInstanceUID, request.Dataset.GetValue <string>(DicomTag.SOPInstanceUID, 0)); return(new DicomCStoreResponse(request, new DicomStatus(DicomStatus.ProcessingFailure, $"CStore Response Exception: {e.Message} {e.StackTrace}"))); //out of resources not much flexibility here } finally { } }
public void CFind(RoutedItem routedItem, DICOMConnection Connection, int taskID) { var taskInfo = $"task: {taskID} connection: {Connection.name}"; var stopWatch = new Stopwatch(); stopWatch.Start(); try { LiCloudRequest cFindParams = LiCloudRequest.FromJson(routedItem.request, _logger); foreach (var tag in cFindParams.searchTags) { _logger.Log(LogLevel.Debug, $"{taskInfo} id: {routedItem.id} tag: {tag.Key} {tag.Value}"); } DicomCFindRequest cFind = null; string cfindlevel = ""; cFindParams.searchTags.TryGetValue("0008,0052", out cfindlevel); switch (cfindlevel) { case "SERIES": cFind = new DicomCFindRequest(DicomQueryRetrieveLevel.Series); break; case "IMAGE": cFind = new DicomCFindRequest(DicomQueryRetrieveLevel.Image); break; case "PATIENT": cFind = new DicomCFindRequest(DicomQueryRetrieveLevel.Patient); break; case "WORKLIST": case "NA": cFind = new DicomCFindRequest(DicomQueryRetrieveLevel.NotApplicable); break; case "STUDY": default: cFind = new DicomCFindRequest(DicomQueryRetrieveLevel.Study); break; } _logger.Log(LogLevel.Information, $"{taskInfo} Request id: {routedItem.id} MessageID: {cFind.MessageID} attempt: {routedItem.attempts}"); //default return tags // Encoding encoding = DicomEncoding.GetEncoding(cFindCharacterSet); // if(cFindCharacterSet != null){ // cFind.Dataset.AddOrUpdate(DicomTag.SpecificCharacterSet, cFindCharacterSet); // } // cFind.Dataset.AddOrUpdate(DicomTag.PatientID, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.PatientName, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.PatientBirthDate, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.PatientSex, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.StudyDate, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.AccessionNumber, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.StudyID, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.ModalitiesInStudy, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.StudyInstanceUID, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.NumberOfStudyRelatedInstances, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.NumberOfSeriesRelatedInstances, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.StudyDescription, encoding, ""); // cFind.Dataset.AddOrUpdate(DicomTag.ModalitiesInStudy, encoding, ""); cFind.Dataset.AddOrUpdate(DicomTag.AccessionNumber, ""); cFind.Dataset.AddOrUpdate(DicomTag.NumberOfStudyRelatedInstances, ""); cFind.Dataset.AddOrUpdate(DicomTag.NumberOfSeriesRelatedInstances, ""); cFind.Dataset.AddOrUpdate(DicomTag.Modality, ""); cFind.Dataset.AddOrUpdate(DicomTag.ModalitiesInStudy, ""); cFind.Dataset.AddOrUpdate(DicomTag.PatientID, ""); cFind.Dataset.AddOrUpdate(DicomTag.PatientName, ""); cFind.Dataset.AddOrUpdate(DicomTag.PatientBirthDate, ""); cFind.Dataset.AddOrUpdate(DicomTag.PatientSex, ""); cFind.Dataset.AddOrUpdate(DicomTag.StudyDate, ""); cFind.Dataset.AddOrUpdate(DicomTag.StudyID, ""); cFind.Dataset.AddOrUpdate(DicomTag.StudyInstanceUID, ""); cFind.Dataset.AddOrUpdate(DicomTag.StudyDescription, ""); // add the search tags foreach (KeyValuePair <string, string> tag in cFindParams.searchTags) { try { // if(cFindCharacterSet != null){ // Encoding iso = DicomEncoding.GetEncoding(cFindCharacterSet); // Encoding utf8 = Encoding.UTF8; // byte[] utfBytes = utf8.GetBytes(tag.Value); // byte[] isoBytes = Encoding.Convert(utf8, iso, utfBytes); // string value = iso.GetString(isoBytes); // //cFind.Dataset.AddOrUpdate(DicomTag.Parse(tag.Key), value); // cFind.Dataset.AddOrUpdate(DicomTag.Parse(tag.Key), Encoding.ASCII, value); // } else { cFind.Dataset.AddOrUpdate(DicomTag.Parse(tag.Key), tag.Value); // } } catch (Exception e) { _logger.LogFullException(e, taskInfo); } } //connect the cFind to the RoutedItem that originated the request //the cache was already primed in GetRequests cFind.UserState = routedItem; routedItem.MessageId = cFind.MessageID; routedItem.fromConnection = Connection.name; routedItem.toConnections.Clear(); routedItem.status = RoutedItem.Status.PENDING; // var riToCache = (RoutedItem)routedItem.Clone(); // riToCache.Enqueue(this, toRules, nameof(toRules)); cFind.OnResponseReceived = (DicomCFindRequest request, DicomCFindResponse response) => { RoutedItem ri = (RoutedItem)request.UserState; _logger.Log(LogLevel.Information, $"{taskInfo} Response id: {ri.id} MessageID: {request.MessageID} status: {response.Status} elapsed: {stopWatch.Elapsed}"); //DICOMConnection dicomConn = LITE.profile.GetDicomConnectionToLocalAETitle(Connection.localAETitle); DICOMConnection dicomConn = _connectionFinder.GetDicomConnectionToLocalAETitle(_profileStorage.Current, Connection.localAETitle); Dictionary <string, string> returnTagData = new Dictionary <string, string> { { "StatusCode", response.Status.Code.ToString() }, { "StatusDescription", response.Status.Description }, { "StatusErrorComment", response.Status.ErrorComment }, { "StatusState", response.Status.State.ToString() } }; if (response.Completed != 0 || response.Remaining != 0) { returnTagData.Add("Completed", response.Completed.ToString()); returnTagData.Add("Remaining", response.Remaining.ToString()); } string key = "response"; Dictionary <string, Dictionary <string, string> > results = new Dictionary <string, Dictionary <string, string> >(); if (response.Dataset != null) { // Copy into a map, DicomDataset wont serialize foreach (var dicomItem in response.Dataset) { _logger.Log(LogLevel.Debug, $"{taskInfo} Response id: {ri.id} MessageID: {request.MessageID}, {dicomItem.Tag.ToString()} {response.Dataset.GetValueOrDefault<string>(dicomItem.Tag, 0, "")}"); if (dicomItem.Tag.ToString() == "(0008,0054)") //BOUR-940 mask AETitle with conn name { returnTagData.Add(dicomItem.Tag.ToString(), Connection.name); } else { returnTagData.Add(dicomItem.Tag.ToString(), response.Dataset.GetValueOrDefault <string>(dicomItem.Tag, 0, "")); } if (dicomItem.Tag == DicomTag.StudyInstanceUID) { key = response.Dataset.GetValueOrDefault <string>(dicomItem.Tag, 0, ""); } } results.Add(key, returnTagData); } if ((results.Count == 0 && ri.response.Count == 0) || (results.Count > 0)) { string jsonResults = JsonSerializer.Serialize(results); // set results in RoutedItem ri.response.Add(jsonResults); } switch (response.Status.ToString()) { case "Success": ri.status = RoutedItem.Status.COMPLETED; ri.resultsTime = DateTime.Now; _routedItemManager.Init(ri); _routedItemManager.Dequeue(Connection, Connection.toDicom, nameof(Connection.toDicom), error: false); //var toCache = (RoutedItem)ri.Clone(); var toCache = _routedItemManager.Clone(); toCache.fromConnection = Connection.name; toCache.toConnections.Clear(); //BOUR-863 the toConnections on the toCache object weren't being cleared before rules so it contained DICOMConnection which toCache.attempts = 0; toCache.lastAttempt = DateTime.MinValue; _routedItemManager.Init(toCache); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); break; case "Pending": break; default: _routedItemManager.Init(ri); _routedItemManager.Dequeue(Connection, Connection.toDicom, nameof(Connection.toDicom), error: true); break; } }; dicomClient.AddRequest(cFind); } catch (DicomDataException e) { _logger.Log(LogLevel.Warning, $"{taskInfo} query: {routedItem} {e.Message} {e.StackTrace} "); routedItem.status = RoutedItem.Status.FAILED; routedItem.resultsTime = DateTime.Now; Dictionary <string, string> returnTagData = new Dictionary <string, string> { { "StatusCode", "-1" }, { "StatusDescription", $"Error: {e.Message}" }, { "StatusErrorComment", $"Error: {e.StackTrace}" }, { "StatusState", "" } }; string key = "response"; Dictionary <string, Dictionary <string, string> > results = new Dictionary <string, Dictionary <string, string> > { { key, returnTagData } }; string jsonResults = JsonSerializer.Serialize(results); routedItem.response.Add(jsonResults); _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, Connection.toDicom, nameof(Connection.toDicom), true); routedItem.fromConnection = Connection.name; routedItem.toConnections.Clear(); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); } catch (Exception e) { _logger.LogFullException(e, taskInfo); Dictionary <string, string> returnTagData = new Dictionary <string, string> { { "StatusCode", "-1" }, { "StatusDescription", $"Error: {e.Message}" }, { "StatusErrorComment", $"Error: {e.StackTrace}" }, { "StatusState", "" } }; string key = "response"; Dictionary <string, Dictionary <string, string> > results = new Dictionary <string, Dictionary <string, string> > { { key, returnTagData } }; string jsonResults = JsonSerializer.Serialize(results); routedItem.response.Add(jsonResults); if (routedItem.attempts > Connection.maxAttempts) { routedItem.status = RoutedItem.Status.FAILED; routedItem.resultsTime = DateTime.Now; _logger.Log(LogLevel.Debug, $"{taskInfo} id: {routedItem.id} exceeded max attempts."); _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, Connection.toDicom, nameof(Connection.toDicom), true); } routedItem.fromConnection = Connection.name; routedItem.toConnections.Clear(); _routedItemManager.Init(routedItem); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); } }