signal r for omni

This commit is contained in:
Stoyan Zlatev
2023-11-16 17:42:59 +01:00
parent a733da3c78
commit fa886a745f
26 changed files with 772 additions and 191 deletions
+67
View File
@@ -183,6 +183,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniPlus", "OmniPlus\OmniPl
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniPlus.UI", "OmniPlus.UI\OmniPlus.UI.csproj", "{6518211A-E83F-4171-97C4-A61FCF66D6E0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignalRClient", "SignalRClient\SignalRClient.csproj", "{5C16DAC4-71E5-49B4-A087-36C704AADCF1}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Utils\DateTimeServerShared\DateTimeServerShared.projitems*{4806d89a-fbfb-41bc-aaa7-2242444bf55a}*SharedItemsImports = 4
@@ -4249,6 +4251,70 @@ Global
{6518211A-E83F-4171-97C4-A61FCF66D6E0}.XP32bit|x64.Build.0 = Release|Any CPU
{6518211A-E83F-4171-97C4-A61FCF66D6E0}.XP32bit|x86.ActiveCfg = Release|Any CPU
{6518211A-E83F-4171-97C4-A61FCF66D6E0}.XP32bit|x86.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|Any CPU.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|Any CPU.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|Mixed Platforms.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|x64.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|x64.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|x86.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.COM|x86.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|x64.ActiveCfg = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|x64.Build.0 = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|x86.ActiveCfg = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Debug|x86.Build.0 = Debug|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|Any CPU.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|x64.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|x64.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|x86.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.PerformTest|x86.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|Any CPU.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|x64.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|x64.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|x86.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.Release|x86.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|x64.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|x64.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|x86.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.ReleaseTest|x86.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|Any CPU.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|x64.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|x64.Build.0 = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|x86.ActiveCfg = Release|Any CPU
{5C16DAC4-71E5-49B4-A087-36C704AADCF1}.XP32bit|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -4331,6 +4397,7 @@ Global
{F14940F8-3C86-4BB7-A915-B021E4B3052D} = {B4F8545B-F379-42A5-BDE9-763FD7B79598}
{F8D84B9A-0FCF-4083-B067-8C39B7314152} = {68323534-4337-4E3A-89BC-11D8BB55343A}
{6518211A-E83F-4171-97C4-A61FCF66D6E0} = {68323534-4337-4E3A-89BC-11D8BB55343A}
{5C16DAC4-71E5-49B4-A087-36C704AADCF1} = {68323534-4337-4E3A-89BC-11D8BB55343A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4BCB7B69-696C-436A-86F7-C91EA5588164}
+9 -1
View File
@@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
-92
View File
@@ -1,92 +0,0 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace COMVisibleEvents
{
[ComVisible(true)]
[Guid("8403C952-E751-4DE1-BD91-F35DEE19206E")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IEvents
{
[DispId(1)]
void OnDownloadCompleted();
[DispId(2)]
void OnDownloadFailed(string message);
}
[ComVisible(true)]
[Guid("2BF7DA6B-DDB3-42A5-BD65-92EE93ABB473")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IDemoEvents
{
[DispId(1)]
Task DownloadFileAsync(string address, string filename);
}
[ComVisible(true)]
[Guid("56C41646-10CB-4188-979D-23F70E0FFDF5")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IEvents))]
[ProgId("COMVisibleEvents.DemoEvents")]
public class DemoEvents : IDemoEvents
{
public delegate void OnDownloadCompletedDelegate();
public delegate void OnDownloadFailedDelegate(string message);
public event OnDownloadCompletedDelegate OnDownloadCompleted;
public event OnDownloadFailedDelegate OnDownloadFailed;
private string FileNamePath(string filename)
=> Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename);
public async Task DownloadFileAsync(string address, string filename)
{
try
{
using (var webClient = new WebClient())
{
await webClient
.DownloadFileTaskAsync(new Uri(address), FileNamePath(filename))
.ContinueWith(t =>
{
if (t.Status == TaskStatus.Faulted)
{
var failed = OnDownloadFailed;
failed?.Invoke(GetExceptions(t));
}
else
{
var completed = OnDownloadCompleted;
completed?.Invoke();
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
#region Local
string GetExceptions(Task task)
{
var innerExceptions = task.Exception?.Flatten().InnerExceptions;
if (innerExceptions == null)
return string.Empty;
var builder = new StringBuilder();
foreach (var e in innerExceptions)
builder.AppendLine(e.Message);
return builder.ToString();
}
#endregion Local
}
}
}
+6 -1
View File
@@ -46,7 +46,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Class1.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@@ -63,5 +62,11 @@
<Content Include="temperature_calibrations_26_10_2023\193400261_messurements.txt" />
<Content Include="temperature_calibrations_26_10_2023\temp.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SignalRClient\SignalRClient.csproj">
<Project>{5C16DAC4-71E5-49B4-A087-36C704AADCF1}</Project>
<Name>SignalRClient</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+13 -81
View File
@@ -1,97 +1,29 @@
using OmniPipes;
using SignalRClient;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CommonConsole
{
public class Program
{
private static OmniPipe server;
private static OmniPipe client;
static double value = 0.1;
static ExchangeHub exchangeI;
public static void Main()
{
// StartAsServer();
StartAsClient();
exchangeI = new ExchangeHub();
exchangeI.ExchangeQ += q => Console.WriteLine(q);
exchangeI.Connect("http://localhost:52822/");
//Task.Factory.StartNew(() =>
//{
// while (true)
// {
// server.SendMessage(2, 0.59);
// Thread.Sleep(3000);
// }
//});
Console.ReadKey();
Task.Factory.StartNew(() =>
Console.WriteLine($"{nameof(ExchangeHub)} - connected: {exchangeI.Connected}");
while (Console.ReadKey().Key == ConsoleKey.Enter)
{
while (true)
{
client.SendMessage(1, 0.95);
value += 0.1D;
exchangeI.SendExchangeQ(value);
}
Thread.Sleep(3000);
}
});
}
private static void StartAsClient()
{
client = new OmniPipe();
client.Connected += () =>
{
Console.WriteLine("Client connected");
};
client.Disconnected += () =>
{
Console.WriteLine("Client disconnected");
};
client.DoubleExchange += (x, v) =>
{
Console.WriteLine($"Received: (x:{x}, v:{v:0.0000})");
};
client.Exception += msg =>
{
Console.WriteLine(msg);
};
client.ConnectAsClient();
}
private static void StartAsServer()
{
server = new OmniPipe();
server.Connected += () =>
{
Console.WriteLine("Client connected");
};
server.Disconnected += () =>
{
Console.WriteLine("Client disconnected");
};
server.DoubleExchange += (x, v) =>
{
Console.WriteLine($"Received: (x:{x}, v:{v:0.0000})");
};
server.Exception += msg =>
{
Console.WriteLine(msg);
};
server.ConnectAsServer();
exchangeI.Dispose();
}
}
}
+20 -4
View File
@@ -1,7 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="COMS" value="COM4, COM, COM, COM, COM, COM, COM, COM"/>
<add key="OMNIDB" value="Server=SLASQL01.emea.sensus.net; Database=AuftragKopie; User ID=sa; Password=sqlserver;"/>
<add key="COMS" value="COM4, COM, COM, COM, COM, COM, COM, COM" />
<add key="OMNIDB" value="Server=SLASQL01.emea.sensus.net; Database=AuftragKopie; User ID=sa; Password=sqlserver;" />
<add key="SIGNALR" value="http://localhost:52822/" />
</appSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.29.0" newVersion="2.2.29.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+2 -1
View File
@@ -15,7 +15,8 @@ namespace OmniPlus.UI
this.InitializeComponent();
var omniDatabase = ConfigurationManager.AppSettings.Get("OMNIDB");
this.connectionsPool = new OmniPlusConnectionsPool(omniDatabase);
var signalRURL = ConfigurationManager.AppSettings.Get("SIGNALR");
this.connectionsPool = new OmniPlusConnectionsPool(omniDatabase, signalRURL);
this.HandleCreated += this.OmniPlusUI_HandleCreated;
this.HandleDestroyed += this.OmniPlusUI_HandleDestroyed;
+4
View File
@@ -100,9 +100,13 @@
<Compile Include="Options\OmniControlOptions.cs" />
<Compile Include="Options\SerialPortOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SignalRConnection.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="OmniPlusDatabase.sql" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+7 -2
View File
@@ -18,6 +18,7 @@ namespace OmniPlus
private readonly ConcurrentDictionary<int, OmniPlusConnection> connections;
private readonly ConcurrentDictionary<int, OmniPlusMeter> meters;
private readonly SignalRConnection signalRConnection;
private readonly OmniPlusDatabase database;
private readonly OmniPlusType omniType;
@@ -25,10 +26,11 @@ namespace OmniPlus
private string variant;
private BackgroundWorker background;
public OmniPlusConnectionsPool(string dbConnectionString)
public OmniPlusConnectionsPool(string dbConnectionString, string signalRURL)
{
this.connections = new ConcurrentDictionary<int, OmniPlusConnection>();
this.meters = new ConcurrentDictionary<int, OmniPlusMeter>();
this.signalRConnection = new SignalRConnection(signalRURL);
this.database = new OmniPlusDatabase(dbConnectionString);
this.omniType = new OmniPlusType();
@@ -67,6 +69,8 @@ namespace OmniPlus
public void InitializeInspection(params string[] portNames)
{
this.signalRConnection.Connect();
OmniPlusConnection connection;
OmniPlusMeter meter;
int position = 1;
@@ -126,7 +130,8 @@ namespace OmniPlus
foreach (var point in this.omniType.TestPoints)
{
// TODO: this.SetM3(point.VolumeM3H);
// TODO: 600 = 10min * 60sec - change for production.
this.signalRConnection.SetQAndWaitUntilReached(point.VolumeM3H, 600);
tasks = new Task[connectionsCount];
+39
View File
@@ -0,0 +1,39 @@
namespace OmniPlus
{
using SignalRClient;
using System.Threading;
public class SignalRConnection
{
private readonly ExchangeHub exchangeHub;
private readonly string url;
public SignalRConnection(string url)
{
this.url = url;
this.exchangeHub = new ExchangeHub();
}
internal void Connect()
=> this.exchangeHub.Connect(this.url);
public bool SetQAndWaitUntilReached(double value, int seconds)
{
var reached = false;
void WaitUntilReached(double _) => reached = true;
this.exchangeHub.ExchangeQ += WaitUntilReached;
this.exchangeHub.SetQ(value);
while (!reached && seconds >= 0)
{
Thread.Sleep(1000);
seconds--;
}
return reached;
}
}
}
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.29.0" newVersion="2.2.29.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+37
View File
@@ -0,0 +1,37 @@
using System;
using System.Runtime.InteropServices;
namespace SignalRClient.Contracts
{
public interface IExchangeHub : IDisposable
{
void SetQ(double value);
}
[Guid("4F018C57-9E7B-4391-8837-BCA6373E0AFE")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IExchangeClient
{
[DispId(1)]
bool Connected { get; }
[DispId(2)]
bool Connect(string url);
[DispId(3)]
void Dispose();
[DispId(4)]
void SetQ(double value);
}
[Guid("D140D0EA-220E-478E-91B6-5FE8D45B52D0")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IExchangeEvents
{
[DispId(1)]
void ExchangeQ(double value);
}
public delegate void DoubleEventHandler(double value);
}
+129
View File
@@ -0,0 +1,129 @@
using SignalRClient.Contracts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.AspNet.SignalR.Client;
namespace SignalRClient
{
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IExchangeEvents))]
[Guid("3FBA514A-326B-4F34-BFF4-425AF4115B43")]
[ProgId("SignalR.ExchangeHub")]
public class ExchangeHub : IExchangeClient, IExchangeHub
{
public const string HUB_DIR = "SignalRClient";
public const string HUB_NAME = "ExchangeHub";
public event DoubleEventHandler ExchangeQ;
private readonly ICollection<IDisposable> disposables;
private HubConnection connection;
private IHubProxy proxy;
public ExchangeHub()
{
Directory.CreateDirectory(HUB_DIR);
this.disposables = new List<IDisposable>();
}
public bool Connected { get; private set; }
public bool Connect(string url)
{
this.connection = new HubConnection(url);
this.connection.Closed += this.Connection_Closed;
this.connection.ConnectionSlow += Connection_ConnectionSlow;
this.connection.Error += this.Connection_Error;
this.connection.Received += this.Connection_Received;
this.connection.Reconnected += this.Connection_Reconnected;
this.connection.Reconnecting += this.Connection_Reconnecting;
this.connection.StateChanged += this.Connection_StateChanged;
this.proxy = this.connection.CreateHubProxy(HUB_NAME);
var setQ = this.proxy.On<double>(nameof(this.SetQ), x => this.ExchangeQ?.Invoke(x));
this.disposables.Add(setQ);
this.connection
.Start()
.Wait();
return this.connection.State == ConnectionState.Connected;
}
public void Dispose()
{
foreach (var disposable in this.disposables)
{
disposable?.Dispose();
}
this.connection.Stop();
}
// TODO:
public void SetQ(double value)
=> this.proxy
.Invoke(nameof(this.SetQ), new object[] { value })
.Wait();
private void Connection_Closed()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection closed!");
}
private void Connection_ConnectionSlow()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection is about to timeout!");
}
private void Connection_Error(Exception e)
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine(e.ToString());
}
private void Connection_Received(string data)
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine(data);
}
private void Connection_Reconnected()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection reconnected!");
}
private void Connection_Reconnecting()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection reconnecting!");
}
private void Connection_StateChanged(StateChange state)
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine($"{state.OldState} -> {state.NewState}");
}
private void FileAppendLine(string text)
=> File.AppendAllText($"{HUB_DIR}\\{DateTime.Now:yyyy_MM_dd}.txt", $"[{DateTime.Now:HH:mm:ss}] {text}{Environment.NewLine}");
}
}
+35
View File
@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SignalR")]
[assembly: AssemblyDescription("Exposes SignalR hubs implemented by LaaProductionWeb")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Sensus Laatzen")]
[assembly: AssemblyProduct("SignalR")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a841f176-bb9c-4b1b-b0c0-5dad7b5de34c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+67
View File
@@ -0,0 +1,67 @@
<?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>{A841F176-BB9C-4B1B-B0C0-5DAD7B5DE34C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SignalR</RootNamespace>
<AssemblyName>SignalR</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNet.SignalR.Client, Version=2.4.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.SignalR.Client.2.4.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Contracts\IExchangeHub.cs" />
<Compile Include="ExchangeHub.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy $(TargetFileName) C:\Temp
copy Newtonsoft.Json.dll C:\Temp
copy Microsoft.AspNet.SignalR.Client.dll C:\Temp
</PostBuildEvent>
</PropertyGroup>
</Project>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.SignalR.Client" version="2.4.3" targetFramework="net40" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net40" />
</packages>
@@ -0,0 +1,38 @@
using System;
using System.Runtime.InteropServices;
namespace SignalRClient.Contracts
{
public interface IExchangeHub : IDisposable
{
void SendExchangeQ(double value);
void SendExchangeV(double value);
}
[Guid("4F018C57-9E7B-4391-8837-BCA6373E0AFE")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IExchangeClient : IExchangeHub
{
bool Connected { get; }
bool Connect(string url);
new void Dispose();
new void SendExchangeQ(double value);
new void SendExchangeV(double value);
}
[Guid("D140D0EA-220E-478E-91B6-5FE8D45B52D0")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IExchangeEvents
{
void ExchangeQ(double value);
void ExchangeV(double value);
}
public delegate void DoubleEventHandler(double value);
}
+131
View File
@@ -0,0 +1,131 @@
using SignalRClient.Contracts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.AspNet.SignalR.Client;
namespace SignalRClient
{
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IExchangeEvents))]
[Guid("3FBA514A-326B-4F34-BFF4-425AF4115B43")]
[ProgId("SignalRClient.ExchangeHub")]
public class ExchangeHub : IExchangeClient
{
public const string HUB_DIR = ".\\SignalRClient";
public const string HUB_NAME = nameof(IExchangeHub);
public event DoubleEventHandler ExchangeQ;
public event DoubleEventHandler ExchangeV;
private readonly ICollection<IDisposable> disposables;
private HubConnection connection;
private IHubProxy proxy;
public ExchangeHub()
{
Directory.CreateDirectory(HUB_DIR);
this.disposables = new List<IDisposable>();
}
public bool Connected { get; private set; }
public bool Connect(string url)
{
this.connection = new HubConnection(url);
this.connection.Closed += this.Connection_Closed;
this.connection.ConnectionSlow += Connection_ConnectionSlow;
this.connection.Error += this.Connection_Error;
this.connection.Received += this.Connection_Received;
this.connection.Reconnected += this.Connection_Reconnected;
this.connection.Reconnecting += this.Connection_Reconnecting;
this.connection.StateChanged += this.Connection_StateChanged;
this.proxy = this.connection.CreateHubProxy(HUB_NAME);
var disposableQ = this.proxy.On<double>(nameof(this.SendExchangeQ), x => this.ExchangeQ?.Invoke(x));
var disposableV = this.proxy.On<double>(nameof(this.SendExchangeV), x => this.ExchangeV?.Invoke(x));
this.disposables.Add(disposableQ);
this.disposables.Add(disposableV);
this.connection
.Start()
.Wait();
return this.connection.State == ConnectionState.Connected;
}
public void Dispose()
{
foreach (var disposable in this.disposables)
{
disposable?.Dispose();
}
this.connection.Stop();
}
public void SendExchangeQ(double value)
=> this.proxy.Invoke(nameof(this.SendExchangeQ), new object[] { value });
public void SendExchangeV(Double value)
=> this.proxy.Invoke(nameof(this.SendExchangeV), new object[] { value });
private void Connection_Closed()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection closed!");
}
private void Connection_ConnectionSlow()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection is about to timeout!");
}
private void Connection_Error(Exception e)
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine(e.ToString());
}
private void Connection_Received(string data)
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine(data);
}
private void Connection_Reconnected()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection reconnected!");
}
private void Connection_Reconnecting()
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine("HubConnection reconnecting!");
}
private void Connection_StateChanged(StateChange state)
{
this.Connected = this.connection.State == ConnectionState.Connected;
this.FileAppendLine($"{state.OldState} -> {state.NewState}");
}
private void FileAppendLine(string text)
=> File.AppendAllText($"{HUB_DIR}\\{DateTime.Now:yyyy_MM_dd}.txt", $"[{DateTime.Now:HH:mm:ss}] {text}{Environment.NewLine}");
}
}
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SignalRClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SignalRClient")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("5c16dac4-71e5-49b4-a087-36c704aadcf1")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+62
View File
@@ -0,0 +1,62 @@
<?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>{5C16DAC4-71E5-49B4-A087-36C704AADCF1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SignalRClient</RootNamespace>
<AssemblyName>SignalRClient</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNet.SignalR.Client, Version=2.4.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.SignalR.Client.2.4.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Contracts\IExchangeHub.cs" />
<Compile Include="ExchangeHub.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy $(TargetFileName) C:\Temp
copy Newtonsoft.Json.dll C:\Temp
copy Microsoft.AspNet.SignalR.Client.dll C:\Temp</PostBuildEvent>
</PropertyGroup>
</Project>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.SignalR.Client" version="2.4.3" targetFramework="net40" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net40" />
</packages>