Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
KerlyJiang1 committed Dec 7, 2019
2 parents e831177 + bd35f0a commit cbec36c
Show file tree
Hide file tree
Showing 10 changed files with 314 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,16 @@ public PlcClient(ILogger<PlcClient> logger, TcpClient client)
{
this.logger = logger;
this.client = client;
this.ConnectionClosed += async (_, __) =>
{
await this.StopAsync().ConfigureAwait(false);
};
}

public event EventHandler ConnectionClosed;

public EndPoint RemoteEndPoint => this.remoteEndPoint;

public Task StartAsync()
{
if (this.started)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ private async void BackgroundReceivingTaskEntryPoint()
{
this.logger.LogError(e, "Error when receiving data from {0}", this.remoteEndPoint);
this.client.Close();
this.ConnectionClosed?.Invoke(this, new EventArgs());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ private async void BackgroundSendingTaskEntryPoint()
{
this.logger.LogError(e, "Error when receiving data from {0}", this.client.Client.RemoteEndPoint);
this.client.Close();
this.ConnectionClosed?.Invoke(this, new EventArgs());
}
}

Expand Down
13 changes: 11 additions & 2 deletions OneDotNet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TcpServerLab", "codelab\Tcp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crc32C.NET", "third_party\CRC32C.NET\Crc32C.NET\Crc32C.NET.csproj", "{C07C6AF2-0254-44EE-ABCB-18F7917605C0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TplLab", "codelab\TplLab\TplLab.csproj", "{B098D0FE-5AB8-4545-8155-4053876F3C3A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TplLab", "codelab\TplLab\TplLab.csproj", "{B098D0FE-5AB8-4545-8155-4053876F3C3A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeothermalResearchInstitute.Plc", "GeothermalResearchInstitute\GeothermalResearchInstitute.PlcClient\GeothermalResearchInstitute.Plc.csproj", "{9CC5AFAE-5A31-4E97-B0CE-780532B5150E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeothermalResearchInstitute.Plc", "GeothermalResearchInstitute\GeothermalResearchInstitute.PlcClient\GeothermalResearchInstitute.Plc.csproj", "{9CC5AFAE-5A31-4E97-B0CE-780532B5150E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolLab", "codelab\ProtocolLab\ProtocolLab.csproj", "{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -286,6 +288,12 @@ Global
{9CC5AFAE-5A31-4E97-B0CE-780532B5150E}.DebugNonWindows|Any CPU.Build.0 = Debug|Any CPU
{9CC5AFAE-5A31-4E97-B0CE-780532B5150E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9CC5AFAE-5A31-4E97-B0CE-780532B5150E}.Release|Any CPU.Build.0 = Release|Any CPU
{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF}.DebugNonWindows|Any CPU.ActiveCfg = Debug|Any CPU
{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF}.DebugNonWindows|Any CPU.Build.0 = Debug|Any CPU
{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -324,6 +332,7 @@ Global
{C07C6AF2-0254-44EE-ABCB-18F7917605C0} = {E307CA64-13F5-446A-BCA5-C611A235A2E4}
{B098D0FE-5AB8-4545-8155-4053876F3C3A} = {9D7C39A1-EF36-4491-8CC0-2D45C3B51580}
{9CC5AFAE-5A31-4E97-B0CE-780532B5150E} = {BB7EFF62-B03A-4996-9798-17DB422DD96F}
{27B72F6F-1DC2-47FC-BA6D-B133BE75C3CF} = {9D7C39A1-EF36-4491-8CC0-2D45C3B51580}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E0F2E2F1-944D-46B4-BA89-EE1F0BBD57A1}
Expand Down
8 changes: 8 additions & 0 deletions codelab/ProtocolLab/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Application
x:Class="ProtocolLab.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProtocolLab"
Startup="Application_Startup">
<Application.Resources />
</Application>
19 changes: 19 additions & 0 deletions codelab/ProtocolLab/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// <copyright file="App.xaml.cs" company="Shuai Zhang">
// Copyright Shuai Zhang. All rights reserved.
// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
// </copyright>

using System.Windows;

namespace ProtocolLab
{
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
var mainWindow = new MainWindow();
this.MainWindow = mainWindow;
this.MainWindow.Show();
}
}
}
51 changes: 51 additions & 0 deletions codelab/ProtocolLab/MainWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<Window
x:Class="ProtocolLab.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ProtocolLab"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
Loaded="Window_Loaded"
Unloaded="Window_Unloaded"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<DockPanel>
<StackPanel
VerticalAlignment="Stretch"
DockPanel.Dock="Top"
Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="5" />
<Setter Property="Padding" Value="15,5" />
</Style>
</StackPanel.Resources>
<Button
Click="Connect_Click"
Content="发送 Connect 命令"
ToolTip="当 PLC 通过 TCP 连接到服务端时,服务端会立刻向 PLC 发送 Connect 命令" />
<Button
Click="GetMetric_Click"
Content="发送 GetMetric 命令"
ToolTip="服务端会定期向保持连接的 PLC 发送 GetMetric 命令收集数据" />
<Button
Click="UpdateSwitch_Click"
Content="发送 UpdateSwitch 命令"
ToolTip="按下任何开关时会发送 UpdateSwitch 命令,此处发送内容以开启热泵风扇为例" />
</StackPanel>
<FlowDocumentScrollViewer Margin="5">
<FlowDocument
x:Name="LogDocument"
FontFamily="Calibre, Microsoft YaHei UI"
FontSize="9pt" />
</FlowDocumentScrollViewer>
</DockPanel>
</Grid>
</Window>
184 changes: 184 additions & 0 deletions codelab/ProtocolLab/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// <copyright file="MainWindow.xaml.cs" company="Shuai Zhang">
// Copyright Shuai Zhang. All rights reserved.
// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
// </copyright>

using System;
using System.Globalization;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;
using GeothermalResearchInstitute.Plc;
using GeothermalResearchInstitute.v2;
using Google.Protobuf.WellKnownTypes;
using Microsoft.Extensions.Logging;
using PlcClientList = System.Collections.Generic.List<GeothermalResearchInstitute.Plc.PlcClient>;

namespace ProtocolLab
{
public partial class MainWindow : Window, IDisposable
{
private const int PORT = 8888;

private readonly object lockObject = new object();
private readonly PlcClientList clients = new PlcClientList();
private readonly ILoggerFactory loggerFactory = LoggerFactory.Create(b => { });
private bool disposedValue;
private TcpListener listener;
private CancellationTokenSource cancellationTokenSource;
private Task backgroundTask;

public MainWindow()
{
this.InitializeComponent();
}

private PlcClient FirstPlcClient
{
get
{
lock (this.lockObject)
{
return this.clients.First();
}
}
}

public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (this.disposedValue)
{
return;
}

if (disposing)
{
this.loggerFactory.Dispose();
this.cancellationTokenSource.Dispose();
this.backgroundTask.Dispose();

lock (this.lockObject)
{
foreach (PlcClient c in this.clients)
{
c.Dispose();
}

this.clients.Clear();
}
}

this.disposedValue = true;
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.listener = TcpListener.Create(PORT);
this.listener.Start(20);
this.LogMessage(string.Format(
CultureInfo.CurrentCulture,
"正在监听 {0} 端口,等待 PLC 连接,PLC 连接上来后会在这里收到通知。",
PORT));

this.cancellationTokenSource = new CancellationTokenSource();
this.backgroundTask = Task.Run(this.BackgroundTaskEntryPoint, this.cancellationTokenSource.Token);
}

private async void Window_Unloaded(object sender, RoutedEventArgs e)
{
this.listener.Stop();
this.cancellationTokenSource.Cancel();
await this.backgroundTask.ConfigureAwait(true);
}

private async void Connect_Click(object sender, RoutedEventArgs e)
{
PlcClient c = this.FirstPlcClient;

this.LogMessage("Sending ConnectRequest");
TestResponse response = await c.TestAsync(
new TestRequest
{
A = 42,
B = 3.1415926F,
C = "Hello World!",
D = Timestamp.FromDateTimeOffset(DateTimeOffset.Parse("2019-10-29T21:42:13.00000+8:00", CultureInfo.InvariantCulture)),
},
deadline: DateTime.Now.AddSeconds(30))
.ConfigureAwait(true);
this.LogMessage("Received ConnectResponse");
}

private void GetMetric_Click(object sender, RoutedEventArgs e)
{
this.LogMessage("GetMetric");
}

private void UpdateSwitch_Click(object sender, RoutedEventArgs e)
{
this.LogMessage("UpdateSwitch");
}

private async void BackgroundTaskEntryPoint()
{
while (!this.cancellationTokenSource.IsCancellationRequested)
{
TcpClient client = await this.listener.AcceptTcpClientAsync().ConfigureAwait(false);
var plcClient = new PlcClient(this.loggerFactory.CreateLogger<PlcClient>(), client);
await plcClient.StartAsync().ConfigureAwait(false);
plcClient.ConnectionClosed += (sender, _) =>
{
var c = (PlcClient)sender;
lock (this.lockObject)
{
this.clients.Remove(c);
}

this.Dispatcher.Invoke(() =>
{
this.LogMessage(string.Format(
CultureInfo.CurrentCulture,
"PLC {0} 已断开连接。",
c.RemoteEndPoint));
});
};

lock (this.lockObject)
{
this.clients.Add(plcClient);
}

this.Dispatcher.Invoke(() =>
{
this.LogMessage(string.Format(
CultureInfo.CurrentCulture,
"PLC {0} 已连接,点击按钮向 PLC 发送消息,鼠标悬停在按钮上有相关说明。",
client.Client.RemoteEndPoint));
});
}
}

private void LogMessage(string message)
{
if (this.LogDocument.Blocks.FirstBlock == null)
{
this.LogDocument.Blocks.Add(new Paragraph(new Run(message)));
}
else
{
this.LogDocument.Blocks.InsertBefore(
this.LogDocument.Blocks.FirstBlock,
new Paragraph(new Run(message)));
}
}
}
}
18 changes: 18 additions & 0 deletions codelab/ProtocolLab/ProtocolLab.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\GeothermalResearchInstitute\GeothermalResearchInstitute.PlcClient\GeothermalResearchInstitute.Plc.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit cbec36c

Please sign in to comment.