Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@
<Property Name="ParentElementType" Value="SqlTable" />
<Property Name="NewName" Value="Major" />
</Operation>
<Operation Name="Rename Refactor" Key="dc4c4056-eedd-4d59-a2ea-823122e33c1d" ChangeDateTime="11/24/2020 01:03:41">
<Property Name="ElementName" Value="[dbo].[CMoveIPTable].[port]" />
<Property Name="ElementType" Value="SqlSimpleColumn" />
<Property Name="ParentElementName" Value="[dbo].[CMoveIPTable]" />
<Property Name="ParentElementType" Value="SqlTable" />
<Property Name="NewName" Value="Port" />
</Operation>
</Operations>
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<Build Include="dbo\Tables\Study.sql" />
<Build Include="dbo\Tables\ObjectInstance.sql" />
<Build Include="dbo\Tables\DICOMcloudDbVersion.sql" />
<Build Include="dbo\Tables\CMoveIPTable.sql" />
</ItemGroup>
<ItemGroup>
<RefactorLog Include="DICOMcloud.SqlServerDatabase.refactorlog" />
Expand Down
8 changes: 8 additions & 0 deletions DICOMcloud.SqlServerDatabase/dbo/Tables/CMoveIPTable.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE [dbo].[CMoveIPTable]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an Application Entity descriptor table (although it doesn't list the supported Services).
It doesn't have to be specifically for C-MOVE

(
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[IP] NVARCHAR(50) NOT NULL,
[Port] INT NOT NULL,
[AEtitle] NVARCHAR(50) NOT NULL UNIQUE,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The limit on the size of an AE Title is 16 characters (VR of AE),
see https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html

PRIMARY KEY ([Id])
)
44 changes: 44 additions & 0 deletions DICOMcloud.Wado.PacsInterface/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<!--*********** DICOMcloud: The following formats are supported *********
Local Storage:
<add key="app:PacsStorageConnection" value="C:\DICOMcloud\Storage" />
<add key="app:PacsStorageConnection" value="|DataDirectory|\App_Data\Storage\ds" />

Azure Blob Storage:
<add key="app:PacsStorageConnection" value="UseDevelopmentStorage=true;" />
<add key="app:PacsStorageConnection" value="DefaultEndpointsProtocol=https;AccountName=myAccount;AccountKey=myKey;" />
*************************************************************************-->
<!--*********** DICOMcloud: update your databbase connection string*********
<add key="app:PacsDataArchieve" value="TODO: ENTER YOUR SQL DATABASE CONNECTION STRING" />
***********************************************************-->
<add key="app:PacsStorageConnection" value="|DataDirectory|\App_Data\Storage\ds" />
<add key="app:PacsDataArchieve" value="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\DB\DICOMcloud.mdf;Initial Catalog=DICOMcloud;Integrated Security=True" />
<add key="app:enableAnonymizer" value="true" />
<add key="app:anonymizerOptions" value="BasicProfile,RetainUIDs,RetainLongFullDates,RetainPatientChars" />
<add key="cors:enabled" value="true" />
<add key="cors:origins" value="*" />
<add key="cors:headers" value="*" />
<add key="cors:methods" value="*" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Azure.KeyVault.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
114 changes: 114 additions & 0 deletions DICOMcloud.Wado.PacsInterface/DICOMcloud.Wado.PacsInterface.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EABECB00-E418-49F7-8907-2290082AFBE0}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>DICOMcloud.Wado.PacsInterface</RootNamespace>
<AssemblyName>DICOMcloud.Wado.PacsInterface</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dicom.Core, Version=4.0.4.0, Culture=neutral, PublicKeyToken=3a13f649e28eb09a, processorArchitecture=MSIL">
<HintPath>..\packages\fo-dicom.Desktop.4.0.5\lib\net45\Dicom.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PacsService\PacsServer.cs" />
<Compile Include="PacsService\SCPReleated\SCP.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DICOMcloud.Azure\DICOMcloud.Azure.csproj">
<Project>{85c81265-ca86-4c3d-93b9-7ac54fcd20af}</Project>
<Name>DICOMcloud.Azure</Name>
</ProjectReference>
<ProjectReference Include="..\DICOMcloud.DataAccess.Database\DICOMcloud.DataAccess.Database.csproj">
<Project>{4dbfd788-2ce9-449e-885a-70e55d83b528}</Project>
<Name>DICOMcloud.DataAccess.Database</Name>
</ProjectReference>
<ProjectReference Include="..\DICOMcloud\DICOMcloud.csproj">
<Project>{c9278c3e-53cb-4cb3-adb6-fe64d2585e7a}</Project>
<Name>DICOMcloud</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\fo-dicom.Desktop.4.0.5\build\net45\fo-dicom.Desktop.targets" Condition="Exists('..\packages\fo-dicom.Desktop.4.0.5\build\net45\fo-dicom.Desktop.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\fo-dicom.Desktop.4.0.5\build\net45\fo-dicom.Desktop.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\fo-dicom.Desktop.4.0.5\build\net45\fo-dicom.Desktop.targets'))" />
</Target>
</Project>
90 changes: 90 additions & 0 deletions DICOMcloud.Wado.PacsInterface/PacsService/PacsServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using Dicom.Network;
using DICOMcloud.DataAccess;
using DICOMcloud.DataAccess.Database;
using DICOMcloud.DataAccess.Database.Schema;
using DICOMcloud.IO;
using DICOMcloud.Media;
using DICOMcloud.Pacs;
using DICOMcloud.Wado.PacsInterface.PacsService.SCPReleated;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DICOMcloud.Wado.PacsInterface.PacsService

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While a PACS is probably the most likely target, the protocol implemented here is the DIMSE services.
It's the original protocol, of which WADO is an alternative.
So this is a DIMSEInterface and is offering DIMSEServer (apparently ready to offer C-STORE, C-FIND, and C-MOVE).
The namespace is OK as is, but you've accomplished a lot more than "just" PACS interface. It can be used for other purposes (this was in response to an Issue/Request for a proxy... this addresses a good chunk of what would be needed for such a proxy).

{
public class PacsServer
{
private static IDicomServer _server;

public static string AETitle { get; private set; }

public static IObjectStoreService StorageService { get; private set; }

public static IObjectArchieveQueryService QueryService { get; private set; }

public static IObjectRetrieveService RetrieveService { get; private set; }

public static IDatabaseFactory DatabaseService { get; private set; }

public static void Start(int port, string aet)
{
AETitle = aet;
string storageConection = ConfigurationManager.AppSettings["app:PacsStorageConnection"];
if (storageConection.StartsWith("|datadirectory|", StringComparison.OrdinalIgnoreCase))
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var lastIndex = storageConection.IndexOf('|', 1);
var userPathPart = storageConection.Substring(lastIndex + 1);
storageConection = appDataPath + userPathPart;
}
IDicomMediaIdFactory mediaIdFactory = new DicomMediaIdFactory();
DbSchemaProvider schemaProvider = new StorageDbSchemaProvider();

DatabaseService = new SqlDatabaseFactory(ConfigurationManager.AppSettings["app:PacsDataArchieve"]);

IObjectArchieveDataAccess dataAccess =
new ObjectArchieveDataAccess(
schemaProvider,
new ObjectArchieveDataAdapter(
schemaProvider,
DatabaseService
)
);

IMediaStorageService storageService = new FileStorageService(storageConection);

IDicomMediaWriterFactory dicomMediaWriterFactory =
new DicomMediaWriterFactory(
storageService,
mediaIdFactory
);

StorageService = new ObjectStoreService(
new Pacs.Commands.DCloudCommandFactory(
storageService,
dataAccess,
dicomMediaWriterFactory,
mediaIdFactory
)
);

QueryService = new ObjectArchieveQueryService(dataAccess);

RetrieveService = new ObjectRetrieveService(
storageService,
dicomMediaWriterFactory,
mediaIdFactory
);

_server = DicomServer.Create<SCP>(port);
}

public static void Stop()
{
_server.Dispose();
}
}
}
Loading