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
101 changes: 51 additions & 50 deletions ApplicationServer/AppServerPipe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

namespace WorkflowServer
{
/// <summary>
/// Class is used to communicate and run processing workflows on data received from the client.
/// </summary>
internal class AppServerPipe
{
public event EventHandler<EventArgs> PipeConnected;
Expand All @@ -23,8 +26,6 @@ internal class AppServerPipe
private ProcessMs2ScansDelegate? Ms2Delegate { get; set; }
// static class with processing workflows?
public AppServerPipe(NamedPipeServerStream pipeServer,
StreamWriter sw,
StreamReader sr,
int ms1ScanQueueThreshold,
int ms2ScanQueueThreshold,
ProcessMs1ScansDelegate ms1Delegate = null,
Expand All @@ -39,83 +40,55 @@ public AppServerPipe(NamedPipeServerStream pipeServer,
Ms2Delegate = ms2Delegate;
}

/// <summary>
/// Begins the server connection; starts the async buffer reader; connects event handler methods to events.
/// </summary>
public void StartServer()
{
PipeConnected += (obj, sender) =>
{
Console.WriteLine("Pipe client connected. Sent from event.");
};
// delegate for processing needs to be used as a function.
ProcessMs1ScansDelegate ms1Del = (o, scans) =>
{
// select highest m/z from the scans and send a singlescandataobject back to client
List<double> mzPrecursors = new();
foreach (var sc in scans.ListSsdo)
{
double max = sc.YArray.Max();
int posX = Array.IndexOf(sc.YArray, max);
mzPrecursors.Add(sc.XArray[posX]);
}

foreach (var mz in mzPrecursors)
{
SingleScanDataObject ssdoTemp = new()
{
ScanOrder = 2,
ScanNumber = 10,
PrecursorScanNumber = 3,
MzPrecursor = 15,
XArray = new double[] { 0, 0 },
YArray = new double[] { 0, 0 }
};
string temp = JsonConvert.SerializeObject(ssdoTemp);
byte[] buffer = Encoding.UTF8.GetBytes(temp);
byte[] length = BitConverter.GetBytes(buffer.Length);
byte[] finalBuffer = length.Concat(buffer).ToArray();
PipeServer.Write(finalBuffer, 0, finalBuffer.Length);
PipeServer.WaitForPipeDrain();
}

};


PipeDataReceived += HandleDataReceived;
Ms1ScanQueueThresholdReached += ms1Del.Invoke;
Ms1ScanQueueThresholdReached += Ms1Delegate.Invoke;
Ms2ScanQueueThresholdReached += Ms2Delegate.Invoke;
Ms1ProcessingCompleted += (object? obj, ProcessingCompletedEventArgs sender) =>
{


Console.WriteLine("Ms1 Processing Completed");
};
Ms2ProcessingCompleted += (object? obj, ProcessingCompletedEventArgs sender) =>
{
byte[] buffer = Encoding.UTF8.GetBytes("15");
var taskResult = new ValueTask();
taskResult = PipeServer.WriteAsync(buffer);
buffer = null;

Console.WriteLine("Ms2 Processing Completed.");
};

var connectionResult = PipeServer.BeginWaitForConnection(Connected, null);
// wait for the connection to occur before proceeding.
connectionResult.AsyncWaitHandle.WaitOne();
connectionResult.AsyncWaitHandle.Close();
var serializer = new JsonSerializer();
StartReaderAsync();
while (PipeServer.IsConnected)
{

}
}
/// <summary>
/// Used to determine which queue scan that was received from server should go into.
/// </summary>
/// <param name="obj"></param>
/// <param name="eventArgs"></param>
/// <exception cref="ArgumentException"></exception>
private void HandleDataReceived(object? obj, PipeEventArgs eventArgs)
{
// convert pipeeventargs to single scan data object
SingleScanDataObject ssdo = eventArgs.ToSingleScanDataObject();
if (ssdo == null) throw new ArgumentException("single scan data object is null");

// TODO: refactor and make handling more robust downstream.
if (ssdo.ScanOrder == 1)
{
ScanQueueMS1.Enqueue(ssdo);
if (ScanQueueMS1.Count == Ms1ScanQueueThreshold)
{
// method raises event
OnMs1QueueThresholdReached(ScanQueueMS1);
}
}
Expand All @@ -124,32 +97,51 @@ private void HandleDataReceived(object? obj, PipeEventArgs eventArgs)
ScanQueueMS2.Enqueue(ssdo);
if (ScanQueueMS2.Count == Ms2ScanQueueThreshold)
{
// method raises handler
OnMs2QueueThresholdReached(ScanQueueMS2);
}
}
} // TODO: Handle scan order > 2.
Console.WriteLine("\n");
}
/// <summary>
/// Triggers event that begins processing of Ms1 queue.
/// </summary>
/// <param name="queue"></param>
private void OnMs1QueueThresholdReached(Queue<SingleScanDataObject> queue)
{
Ms1ScanQueueThresholdReached?.Invoke(this,
new ScanQueueThresholdReachedEventArgs(queue.DequeueChunk(Ms1ScanQueueThreshold)));
}
/// <summary>
/// Triggers event that begins processing of Ms2 queue.
/// </summary>
/// <param name="queue"></param>
private void OnMs2QueueThresholdReached(Queue<SingleScanDataObject> queue)
{
Ms2ScanQueueThresholdReached?.Invoke(this,
new ScanQueueThresholdReachedEventArgs(queue.DequeueChunk(Ms2ScanQueueThreshold)));
}
/// <summary>
/// Callback method used to wait for client pipe connection.
/// </summary>
/// <param name="ar"></param>
private void Connected(IAsyncResult ar)
{
OnConnection();
PipeServer.EndWaitForConnection(ar);
}

private void OnConnection()
{
PipeConnected?.Invoke(this, EventArgs.Empty);
}

/// <summary>
/// Begins asynchronous buffer reading. Converts the first four bytes into the integer size of the object contained in the rest of the buffer.
/// Then creates the buffer of that size and reads the data into the buffer.
///
/// DO NOT MODIFY OR THINK ABOUT
/// MODIFYING THIS METHOD UNLESS YOU 100% KNOW WHAT IT DOES AND WHAT YOU ARE CHANGING.
/// </summary>
/// <param name="packetReceived">The Action delegate determines what is done with the byte buffer that is received.</param>
private void StartByteReaderAsync(Action<byte[]> packetReceived)
{
byte[] byteDataLength = new byte[sizeof(int)];
Expand All @@ -169,11 +161,20 @@ private void StartByteReaderAsync(Action<byte[]> packetReceived)
});
});
}

/// <summary>
/// Starts the reader asynchronously and triggers the PipeDataReceived event when data is received from the pipe.
/// </summary>
public void StartReaderAsync()
{
StartByteReaderAsync((b) =>
PipeDataReceived?.Invoke(this, new PipeEventArgs(b)));
}

private void SendScanToClient(object obj, ProcessingCompletedEventArgs sender)
{
byte[] buffer = sender.Ssdo.CreateSerializedSingleScanDataObject();
PipeServer.WriteAsync(buffer, 0, buffer.Length);
PipeServer.WaitForPipeDrain();
}
}
}
35 changes: 33 additions & 2 deletions ApplicationServer/Program.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
using System.IO.Pipes;
using ClientServerCommunication;
using Data;
using ClientServerCommLibrary;
using InstrumentControl;
using Newtonsoft;
using Newtonsoft.Json;
using WorkflowServer;

namespace ApplicationServer
{
public class Program
{
public static void Main(string[] args)
{
NamedPipeServerStream pipe = new NamedPipeServerStream("test", PipeDirection.InOut,5,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

ProcessMs1ScansDelegate ms1Del = (obj, ev) =>
{
//Console.WriteLine(ev.ListSsdo.First().MaxX);
};
ProcessMs2ScansDelegate ms2Del = (obj, ev) =>
{
//Console.WriteLine(ev.ListSsdo.First().PrecursorScanNumber);
};
AppServerPipe appPipe = new(pipe, 1, 1, ms1Del, ms2Del);

bool connectedBool = false;
appPipe.PipeConnected += (obj, ev) =>
{
connectedBool = true;
};
appPipe.PipeDataReceived += (obj, ev) =>
{
var scan = ev.ToSingleScanDataObject();
Console.WriteLine(scan.MaxX);
};
appPipe.StartServer();
while (connectedBool)
{
//appPipe.PipeDataReceived += (obj, ev) =>
//{
// var scan = ev.ToSingleScanDataObject();
// Console.WriteLine(scan.MaxX.ToString());
//};
}
}
}
}
3 changes: 1 addition & 2 deletions ApplicationServer/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"profiles": {
"ApplicationServer": {
"commandName": "Project",
"commandLineArgs": "simple Server"
"commandName": "Project"
}
}
}
3 changes: 2 additions & 1 deletion ApplicationServer/ScanQueue/ScanQueue.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Data;
using ClientServerCommLibrary;


namespace ApplicationServer
{
Expand Down
2 changes: 1 addition & 1 deletion ApplicationServer/ScanQueue/ThresholdReachedEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Data;
using ClientServerCommLibrary;

namespace ApplicationServer
{
Expand Down
1 change: 1 addition & 0 deletions ApplicationServer/WorkflowServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
</ItemGroup>

<ItemGroup>
Expand Down
14 changes: 14 additions & 0 deletions Client/IScanTranslator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ClientServerCommLibrary;

namespace Client
{
public abstract class ScanTranslator
{
public abstract void Translate(SingleScanDataObject ssdo);
}
}
20 changes: 16 additions & 4 deletions Client/InstrumentClient.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\NUnit.3.13.3\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.13.3\build\NUnit.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand All @@ -12,6 +13,8 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
Expand Down Expand Up @@ -47,6 +50,9 @@
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=3.13.3.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.13.3\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Spectrum-1.0, Version=1.1.0.1, Culture=neutral, PublicKeyToken=c03bf447005257eb, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Thermo\Instruments\TNG\OrbitrapFusionLumos\3.3\System\Programs\Spectrum-1.0.dll</HintPath>
Expand All @@ -73,9 +79,13 @@
<Compile Include="Factories\ThermoTribridFactory.cs" />
<Compile Include="InstrumentClientPipe.cs" />
<Compile Include="InstrumentInterfaces\IInstrument.cs" />
<Compile Include="InstrumentInterfaces\Thermo\DataHandling\InstrumentSettingEnums.cs" />
<Compile Include="InstrumentInterfaces\Thermo\DataHandling\MsScanExtensions.cs" />
<Compile Include="InstrumentInterfaces\Thermo\DataHandling\ThermoTribridSsdoMapping.cs" />
<Compile Include="InstrumentInterfaces\Thermo\InterfaceImplementations\ThermoQE.cs" />
<Compile Include="InstrumentInterfaces\Thermo\InterfaceImplementations\ThermoTribrid.cs" />
<Compile Include="InstrumentInterfaces\Thermo\ThermoScanTranslator\ThermoTribridScanTranslator.cs" />
<Compile Include="IScanTranslator.cs" />
<Compile Include="MsScanReadyToSendEventArgs.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand All @@ -90,11 +100,13 @@
<Project>{0e9b5801-5167-44cc-90d3-c8caf1df8f6a}</Project>
<Name>ClientServerCommLibrary</Name>
</ProjectReference>
<ProjectReference Include="..\Data\Data.csproj">
<Project>{6b34249b-a513-4a4a-9ed5-cb633bcab646}</Project>
<Name>Data</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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\NUnit.3.13.3\build\NUnit.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit.3.13.3\build\NUnit.props'))" />
</Target>
</Project>
Loading