diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/FakePlc.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/FakePlc.cs
deleted file mode 100644
index 4e55877e..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/FakePlc.cs
+++ /dev/null
@@ -1,356 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Buffers.Binary;
-using System.IO;
-using System.Net;
-using System.Net.NetworkInformation;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using GeothermalResearchInstitute.PlcV2;
-using GeothermalResearchInstitute.v2;
-using Google.Protobuf;
-
-namespace GeothermalResearchInstitute.FakePlcV2
-{
- public class FakePlc : IDisposable
- {
- private TcpClient client;
- private CancellationTokenSource cancellationTokenSource;
- private Task backgroundTask;
- private bool disposedValue = false;
-
- public FakePlc(byte[] id)
- {
- this.Mac = new PhysicalAddress(id);
- }
-
- ~FakePlc()
- {
- this.Dispose(false);
- }
-
- public PhysicalAddress Mac { get; }
-
- public Metric Metric { get; } = new Metric
- {
- OutputWaterCelsiusDegree = 11F,
- InputWaterCelsiusDegree = 13F,
- HeaterOutputWaterCelsiusDegree = 17F,
- EnvironmentCelsiusDegree = 19F,
- OutputWaterPressureMeter = 23F,
- InputWaterPressureMeter = 29F,
- HeaterPowerKilowatt = 31F,
- WaterPumpFlowRateCubicMeterPerHour = 37F,
- };
-
- public Switch Switch { get; } = new Switch
- {
- DevicePowerOn = true,
- ExhausterPowerOn = true,
- HeaterAutoOn = true,
- HeaterPowerOn = true,
- HeaterFanOn = true,
- HeaterCompressorOn = true,
- HeaterFourWayReversingOn = true,
- };
-
- public WorkingMode WorkingMode { get; } = new WorkingMode
- {
- DeviceWorkingMode = DeviceWorkingMode.TemperatureDetermination,
- DeviceFlowRateControlMode = DeviceFlowRateControlMode.VariableFrequency,
- WaterPumpWorkingMode = WaterPumpWorkingMode.FixedFlowRate,
- };
-
- public RunningParameter RunningParameter { get; } = new RunningParameter
- {
- SummerHeaterCelsiusDegree = 11F,
- WinterHeaterCelsiusDegree = 13F,
- ColdPowerKilowatt = 17F,
- WarmPowerKilowatt = 19F,
- WaterPumpFlowRateCubicMeterPerHour = 23F,
- WaterPumpFrequencyHertz = 29F,
- };
-
- public Alarm Alarm { get; } = new Alarm
- {
- LowFlowRate = false,
- HighHeaterPressure = false,
- LowHeaterPressure = false,
- NoPower = false,
- HeaterOverloadedBroken = false,
- ElectricalHeaterBroken = false,
- };
-
- public void Dispose()
- {
- this.Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- public async Task StartAsync(IPAddress address, int port)
- {
- this.client = new TcpClient();
- await this.client.ConnectAsync(address, port).ConfigureAwait(false);
-
- this.cancellationTokenSource = new CancellationTokenSource();
- this.backgroundTask = Task.Factory.StartNew(
- this.BackgroundTaskEntryPoint,
- this.cancellationTokenSource.Token,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
- }
-
- public async Task StopAsync()
- {
- if (this.client == null)
- {
- return;
- }
-
- this.cancellationTokenSource.Cancel();
- await this.backgroundTask.ConfigureAwait(false);
- this.client.Close();
-
- this.backgroundTask.Dispose();
- this.backgroundTask = null;
- this.cancellationTokenSource.Dispose();
- this.cancellationTokenSource = null;
- this.client.Dispose();
- this.client = null;
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposedValue)
- {
- if (disposing)
- {
- if (this.backgroundTask != null)
- {
- this.StopAsync().GetAwaiter().GetResult();
- }
- }
-
- this.disposedValue = true;
- }
- }
-
- private void BackgroundTaskEntryPoint()
- {
- using var reader = new BinaryReader(this.client.GetStream(), Encoding.ASCII, true);
- while (!this.cancellationTokenSource.IsCancellationRequested)
- {
- byte[] header = reader.ReadBytes(20);
- ushort contentLength = BinaryPrimitives.ReadUInt16BigEndian(header.AsSpan(0x12, 2));
- byte[] content = contentLength == 0 ? Array.Empty() : reader.ReadBytes(contentLength);
-
- var messageType = (PlcMessageType)BinaryPrimitives.ReadUInt16BigEndian(header.AsSpan(0x06, 2));
- PlcFrame responseFrame;
- switch (messageType)
- {
- case PlcMessageType.ConnectRequest:
- responseFrame = PlcFrame.Create(
- PlcMessageType.ConnectResponse,
- ByteString.CopyFrom(this.Mac.GetAddressBytes()));
- break;
- case PlcMessageType.GetMetricRequest:
- responseFrame = this.CreateGetMetricResponse();
- break;
- case PlcMessageType.GetSwitchRequest:
- responseFrame = this.CreateGetSwitchResponseFrame();
- break;
- case PlcMessageType.UpdateSwitchRequest:
- this.UpdateSwitch(content);
- responseFrame = this.CreateGetSwitchResponseFrame();
- break;
- case PlcMessageType.GetWorkingModeRequest:
- responseFrame = this.CreateGetWorkingModeResponseFrame();
- break;
- case PlcMessageType.UpdateWorkingModeRequest:
- this.UpdateWorkingMode(content);
- responseFrame = this.CreateGetWorkingModeResponseFrame();
- break;
- case PlcMessageType.GetRunningParameterRequest:
- responseFrame = this.CreateGetRunningParameterResponseFrame();
- break;
- case PlcMessageType.UpdateRunningParameterRequest:
- this.UpdateRunningParameter(content);
- responseFrame = this.CreateGetRunningParameterResponseFrame();
- break;
- case PlcMessageType.GetAlarmRequest:
- responseFrame = this.CreateGetAlarmResponseFrame();
- break;
- default:
- responseFrame = null;
- break;
- }
-
- if (responseFrame == null)
- {
- continue;
- }
-
- responseFrame.FrameHeader.SequenceNumber =
- BinaryPrimitives.ReadUInt32BigEndian(header.AsSpan(0x08, 4));
- responseFrame.WriteTo(this.client.GetStream());
- }
- }
-
- private void UpdateSwitch(ReadOnlySpan content)
- {
- if ((content[0] & 0x10) != 0)
- {
- this.Switch.DevicePowerOn = (content[0] & 0x01) == 1;
- }
-
- if ((content[1] & 0x10) != 0)
- {
- this.Switch.ExhausterPowerOn = (content[1] & 0x01) == 1;
- }
-
- if ((content[2] & 0x10) != 0)
- {
- this.Switch.HeaterAutoOn = (content[2] & 0x01) == 1;
- }
-
- if ((content[3] & 0x10) != 0)
- {
- this.Switch.HeaterPowerOn = (content[3] & 0x01) == 1;
- }
-
- if ((content[4] & 0x10) != 0)
- {
- this.Switch.HeaterFanOn = (content[4] & 0x01) == 1;
- }
-
- if ((content[5] & 0x10) != 0)
- {
- this.Switch.HeaterCompressorOn = (content[5] & 0x01) == 1;
- }
-
- if ((content[6] & 0x10) != 0)
- {
- this.Switch.HeaterFourWayReversingOn = (content[6] & 0x01) == 1;
- }
- }
-
- private void UpdateWorkingMode(byte[] content)
- {
- if (content[0] != 0)
- {
- this.WorkingMode.DeviceWorkingMode = (DeviceWorkingMode)content[0];
- }
-
- if (content[1] != 0)
- {
- this.WorkingMode.DeviceFlowRateControlMode = (DeviceFlowRateControlMode)content[1];
- }
-
- if (content[2] != 0)
- {
- this.WorkingMode.WaterPumpWorkingMode = (WaterPumpWorkingMode)content[2];
- }
- }
-
- private void UpdateRunningParameter(byte[] content)
- {
- this.RunningParameter.SummerHeaterCelsiusDegree = BitConverter.ToSingle(content.AsSpan(0, 4));
- this.RunningParameter.WinterHeaterCelsiusDegree = BitConverter.ToSingle(content.AsSpan(4, 4));
- this.RunningParameter.ColdPowerKilowatt = BitConverter.ToSingle(content.AsSpan(8, 4));
- this.RunningParameter.WarmPowerKilowatt = BitConverter.ToSingle(content.AsSpan(12, 4));
- this.RunningParameter.WaterPumpFlowRateCubicMeterPerHour = BitConverter.ToSingle(content.AsSpan(16, 4));
- this.RunningParameter.WaterPumpFrequencyHertz = BitConverter.ToSingle(content.AsSpan(20, 4));
- }
-
- private PlcFrame CreateGetMetricResponse()
- {
- byte[] responseContent = new byte[0x20];
- using (var writer = new BinaryWriter(new MemoryStream(responseContent)))
- {
- writer.Write(this.Metric.OutputWaterCelsiusDegree);
- writer.Write(this.Metric.InputWaterCelsiusDegree);
- writer.Write(this.Metric.HeaterOutputWaterCelsiusDegree);
- writer.Write(this.Metric.EnvironmentCelsiusDegree);
- writer.Write(this.Metric.OutputWaterPressureMeter);
- writer.Write(this.Metric.InputWaterPressureMeter);
- writer.Write(this.Metric.HeaterPowerKilowatt);
- writer.Write(this.Metric.WaterPumpFlowRateCubicMeterPerHour);
- }
-
- return PlcFrame.Create(
- PlcMessageType.GetMetricResponse,
- ByteString.CopyFrom(responseContent));
- }
-
- private PlcFrame CreateGetSwitchResponseFrame()
- {
- byte[] responseContent = new byte[0x07];
- responseContent[0] = (byte)(this.Switch.DevicePowerOn ? 0x01 : 0x00);
- responseContent[1] = (byte)(this.Switch.ExhausterPowerOn ? 0x01 : 0x00);
- responseContent[2] = (byte)(this.Switch.HeaterAutoOn ? 0x01 : 0x00);
- responseContent[3] = (byte)(this.Switch.HeaterPowerOn ? 0x01 : 0x00);
- responseContent[4] = (byte)(this.Switch.HeaterFanOn ? 0x01 : 0x00);
- responseContent[5] = (byte)(this.Switch.HeaterCompressorOn ? 0x01 : 0x00);
- responseContent[6] = (byte)(this.Switch.HeaterFourWayReversingOn ? 0x01 : 0x00);
-
- return PlcFrame.Create(
- PlcMessageType.GetSwitchResponse,
- ByteString.CopyFrom(responseContent));
- }
-
- private PlcFrame CreateGetWorkingModeResponseFrame()
- {
- byte[] responseContent = new byte[0x03];
- responseContent[0] = (byte)this.WorkingMode.DeviceWorkingMode;
- responseContent[1] = (byte)this.WorkingMode.DeviceFlowRateControlMode;
- responseContent[2] = (byte)this.WorkingMode.WaterPumpWorkingMode;
-
- return PlcFrame.Create(
- PlcMessageType.GetWorkingModeResponse,
- ByteString.CopyFrom(responseContent));
- }
-
- private PlcFrame CreateGetRunningParameterResponseFrame()
- {
- byte[] responseContent = new byte[0x18];
- using (var writer = new BinaryWriter(new MemoryStream(responseContent)))
- {
- writer.Write(this.RunningParameter.SummerHeaterCelsiusDegree);
- writer.Write(this.RunningParameter.WinterHeaterCelsiusDegree);
- writer.Write(this.RunningParameter.ColdPowerKilowatt);
- writer.Write(this.RunningParameter.WarmPowerKilowatt);
- writer.Write(this.RunningParameter.WaterPumpFlowRateCubicMeterPerHour);
- writer.Write(this.RunningParameter.WaterPumpFrequencyHertz);
- }
-
- return PlcFrame.Create(
- PlcMessageType.GetRunningParameterResponse,
- ByteString.CopyFrom(responseContent));
- }
-
- private PlcFrame CreateGetAlarmResponseFrame()
- {
- byte[] responseContent = new byte[0x0A];
- responseContent[0] = (byte)(this.Alarm.LowFlowRate ? 0x01 : 0x00);
- responseContent[1] = (byte)(this.Alarm.HighHeaterPressure ? 0x01 : 0x00);
- responseContent[2] = (byte)(this.Alarm.LowHeaterPressure ? 0x01 : 0x00);
- responseContent[3] = (byte)(this.Alarm.NoPower ? 0x01 : 0x00);
- responseContent[4] = (byte)(this.Alarm.HeaterOverloadedBroken ? 0x01 : 0x00);
- responseContent[5] = (byte)(this.Alarm.ElectricalHeaterBroken ? 0x01 : 0x00);
- responseContent[6] = (byte)(this.Alarm.NoWater ? 0x01 : 0x00);
- responseContent[7] = (byte)(this.Alarm.HighVoltage ? 0x01 : 0x00);
- responseContent[8] = (byte)(this.Alarm.LowVoltage ? 0x01 : 0x00);
- responseContent[9] = (byte)(this.Alarm.EmergencyStopped ? 0x01 : 0x00);
-
- return PlcFrame.Create(
- PlcMessageType.GetAlarmResponse,
- ByteString.CopyFrom(responseContent));
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/GeothermalResearchInstitute.FakePlcV2.csproj b/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/GeothermalResearchInstitute.FakePlcV2.csproj
deleted file mode 100644
index d67eef1f..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/GeothermalResearchInstitute.FakePlcV2.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- Exe
- $(CurrentTargetFramework)
-
- win-x64
- true
- False
- False
- False
-
-
-
-
-
-
-
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/Program.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/Program.cs
deleted file mode 100644
index e614db6d..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/Program.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Net;
-using System.Net.NetworkInformation;
-using System.Threading.Tasks;
-
-namespace GeothermalResearchInstitute.FakePlcV2
-{
- internal class Program
- {
- internal static async Task Main()
- {
- using var plc = new FakePlc(PhysicalAddress.Parse("10BF4879B2A4").GetAddressBytes());
- await plc.StartAsync(IPAddress.Loopback, 8889).ConfigureAwait(false);
- Console.ReadKey();
- await plc.StopAsync().ConfigureAwait(false);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/packages.lock.json b/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/packages.lock.json
deleted file mode 100644
index 65cb1867..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.FakePlcV2/packages.lock.json
+++ /dev/null
@@ -1,195 +0,0 @@
-{
- "version": 2,
- "dependencies": {
- "net6.0": {
- "DotNet.ReproducibleBuilds": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "+H2t/t34h6mhEoUvHi8yGXyuZ2GjSovcGYehJrS2MDm2XgmPfZL2Sdxg+uL2lKgZ4M6tTwKHIlxOob2bgh0NRQ==",
- "dependencies": {
- "Microsoft.SourceLink.AzureRepos.Git": "1.1.1",
- "Microsoft.SourceLink.Bitbucket.Git": "1.1.1",
- "Microsoft.SourceLink.GitHub": "1.1.1",
- "Microsoft.SourceLink.GitLab": "1.1.1"
- }
- },
- "Microsoft.CodeAnalysis.BannedApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.3, )",
- "resolved": "3.3.3",
- "contentHash": "vvz3XCHVrd/Ks4xPoutLmL/T2+8JcOk/OMs3ngwQqnzokQCGEDsY+WjK/txCsDWU29sX3fGzH/FnYwNV93O1mA=="
- },
- "Microsoft.CodeAnalysis.NetAnalyzers": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "cjG06LMeOADNUeCUaklOfVgrnVkLy80H5PVll4QHDUXv+C+6G9rHczrNdWjfb3xKv3Ts9s4UsP6J2ZWe52Gz4Q=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies": {
- "type": "Direct",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
- "dependencies": {
- "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
- }
- },
- "Microsoft.SourceLink.GitHub": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Nerdbank.GitVersioning": {
- "type": "Direct",
- "requested": "[3.5.113, )",
- "resolved": "3.5.113",
- "contentHash": "4fBSMkqhi410qlkjPm+Mxfk8iO3C7dmgdVS7ljsfVO21WEzZCHP1VCOqB6rlOPfPidR/oxX+/Do/I7meCAz+Jg=="
- },
- "StyleCop.Analyzers": {
- "type": "Direct",
- "requested": "[1.2.0-beta.435, )",
- "resolved": "1.2.0-beta.435",
- "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
- "dependencies": {
- "StyleCop.Analyzers.Unstable": "1.2.0.435"
- }
- },
- "Grpc.Core.Api": {
- "type": "Transitive",
- "resolved": "2.46.3",
- "contentHash": "uy1oe5baVa4V+C8ZyMiA8xYdNIx5A3PiacQL0f1zWDjF2z64Cb1MMXXRTs3GX+jeKpoK/RtOZg8UnJSm2KC/pQ==",
- "dependencies": {
- "System.Memory": "4.5.3"
- }
- },
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies.net461": {
- "type": "Transitive",
- "resolved": "1.0.3",
- "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
- },
- "Microsoft.SourceLink.AzureRepos.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "qB5urvw9LO2bG3eVAkuL+2ughxz2rR7aYgm2iyrB8Rlk9cp2ndvGRCvehk3rNIhRuNtQaeKwctOl1KvWiklv5w==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Bitbucket.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "cDzxXwlyWpLWaH0em4Idj0H3AmVo3L/6xRXKssYemx+7W52iNskj/SQ4FOmfCb8YQt39otTDNMveCZzYtMoucQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg=="
- },
- "Microsoft.SourceLink.GitLab": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "tvsg47DDLqqedlPeYVE2lmiTpND8F0hkrealQ5hYltSmvruy/Gr5nHAKSsjyw5L3NeM/HLMI5ORv7on/M4qyZw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "StyleCop.Analyzers.Unstable": {
- "type": "Transitive",
- "resolved": "1.2.0.435",
- "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
- },
- "crc32c.net": {
- "type": "Project"
- },
- "geothermalresearchinstitute.grpc": {
- "type": "Project",
- "dependencies": {
- "Google.Protobuf": "[3.21.6, )",
- "Grpc": "[2.46.3, )"
- }
- },
- "geothermalresearchinstitute.plcv2": {
- "type": "Project",
- "dependencies": {
- "Crc32C.NET": "[1.0.0, )",
- "GeothermalResearchInstitute.Grpc": "[1.0.0, )",
- "Microsoft.Extensions.Logging.Abstractions": "[6.0.0, )",
- "System.Memory": "[4.5.5, )",
- "System.Threading.Tasks.Dataflow": "[6.0.0, )"
- }
- },
- "Google.Protobuf": {
- "type": "CentralTransitive",
- "requested": "[3.21.6, )",
- "resolved": "3.21.6",
- "contentHash": "HSYHFnfuTu/O4Ijy0mCW9zxLI8MJfCZJ10dk3JGPrkLaRR4LsiPKzZrrnapf2G0tP2yRMkHCl+2LKLTXqGBn2A=="
- },
- "Grpc": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "79TsAcLBVl5J7AmtnV+GmgkhWlpK3D9JYJDhYxZGO0DKukbyrRxxcbaFlRZ84WGwTAW8LezrInUYgfiJi3zGVg==",
- "dependencies": {
- "Grpc.Core": "2.46.3"
- }
- },
- "Grpc.Core": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "lu7KP7BVWdvFXWbn/IFYHBQCpMohJwbLM1aL+nu2C0pY2CdS0idaUNAJNC2nZ60fXfqoxnSiERrIU6rC474oTw==",
- "dependencies": {
- "Grpc.Core.Api": "2.46.3",
- "System.Memory": "4.5.3"
- }
- },
- "Microsoft.Extensions.Logging.Abstractions": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
- },
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.5.5, )",
- "resolved": "4.5.5",
- "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
- },
- "System.Threading.Tasks.Dataflow": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
- }
- },
- "net6.0/win-x64": {
- "Grpc.Core": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "lu7KP7BVWdvFXWbn/IFYHBQCpMohJwbLM1aL+nu2C0pY2CdS0idaUNAJNC2nZ60fXfqoxnSiERrIU6rC474oTw==",
- "dependencies": {
- "Grpc.Core.Api": "2.46.3",
- "System.Memory": "4.5.3"
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.Grpc/GeothermalResearchInstitute.Grpc.csproj b/GeothermalResearchInstitute/GeothermalResearchInstitute.Grpc/GeothermalResearchInstitute.Grpc.csproj
deleted file mode 100644
index 436acde9..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.Grpc/GeothermalResearchInstitute.Grpc.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- $(CurrentTargetFramework)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.Grpc/packages.lock.json b/GeothermalResearchInstitute/GeothermalResearchInstitute.Grpc/packages.lock.json
deleted file mode 100644
index f9021b20..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.Grpc/packages.lock.json
+++ /dev/null
@@ -1,157 +0,0 @@
-{
- "version": 2,
- "dependencies": {
- "net6.0": {
- "DotNet.ReproducibleBuilds": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "+H2t/t34h6mhEoUvHi8yGXyuZ2GjSovcGYehJrS2MDm2XgmPfZL2Sdxg+uL2lKgZ4M6tTwKHIlxOob2bgh0NRQ==",
- "dependencies": {
- "Microsoft.SourceLink.AzureRepos.Git": "1.1.1",
- "Microsoft.SourceLink.Bitbucket.Git": "1.1.1",
- "Microsoft.SourceLink.GitHub": "1.1.1",
- "Microsoft.SourceLink.GitLab": "1.1.1"
- }
- },
- "Google.Protobuf": {
- "type": "Direct",
- "requested": "[3.21.6, )",
- "resolved": "3.21.6",
- "contentHash": "HSYHFnfuTu/O4Ijy0mCW9zxLI8MJfCZJ10dk3JGPrkLaRR4LsiPKzZrrnapf2G0tP2yRMkHCl+2LKLTXqGBn2A=="
- },
- "Grpc": {
- "type": "Direct",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "79TsAcLBVl5J7AmtnV+GmgkhWlpK3D9JYJDhYxZGO0DKukbyrRxxcbaFlRZ84WGwTAW8LezrInUYgfiJi3zGVg==",
- "dependencies": {
- "Grpc.Core": "2.46.3"
- }
- },
- "Grpc.Tools": {
- "type": "Direct",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "giDUsniVGpakcqR9UjkzUEfOFQLffg96uV/hYhP6Iht4/ila5vSGRWYfeuN2yei933KRXTqjCW+8RvcMONRSHA=="
- },
- "Microsoft.CodeAnalysis.BannedApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.3, )",
- "resolved": "3.3.3",
- "contentHash": "vvz3XCHVrd/Ks4xPoutLmL/T2+8JcOk/OMs3ngwQqnzokQCGEDsY+WjK/txCsDWU29sX3fGzH/FnYwNV93O1mA=="
- },
- "Microsoft.CodeAnalysis.NetAnalyzers": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "cjG06LMeOADNUeCUaklOfVgrnVkLy80H5PVll4QHDUXv+C+6G9rHczrNdWjfb3xKv3Ts9s4UsP6J2ZWe52Gz4Q=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies": {
- "type": "Direct",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
- "dependencies": {
- "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
- }
- },
- "Microsoft.SourceLink.GitHub": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Nerdbank.GitVersioning": {
- "type": "Direct",
- "requested": "[3.5.113, )",
- "resolved": "3.5.113",
- "contentHash": "4fBSMkqhi410qlkjPm+Mxfk8iO3C7dmgdVS7ljsfVO21WEzZCHP1VCOqB6rlOPfPidR/oxX+/Do/I7meCAz+Jg=="
- },
- "StyleCop.Analyzers": {
- "type": "Direct",
- "requested": "[1.2.0-beta.435, )",
- "resolved": "1.2.0-beta.435",
- "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
- "dependencies": {
- "StyleCop.Analyzers.Unstable": "1.2.0.435"
- }
- },
- "Grpc.Core.Api": {
- "type": "Transitive",
- "resolved": "2.46.3",
- "contentHash": "uy1oe5baVa4V+C8ZyMiA8xYdNIx5A3PiacQL0f1zWDjF2z64Cb1MMXXRTs3GX+jeKpoK/RtOZg8UnJSm2KC/pQ==",
- "dependencies": {
- "System.Memory": "4.5.3"
- }
- },
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies.net461": {
- "type": "Transitive",
- "resolved": "1.0.3",
- "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
- },
- "Microsoft.SourceLink.AzureRepos.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "qB5urvw9LO2bG3eVAkuL+2ughxz2rR7aYgm2iyrB8Rlk9cp2ndvGRCvehk3rNIhRuNtQaeKwctOl1KvWiklv5w==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Bitbucket.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "cDzxXwlyWpLWaH0em4Idj0H3AmVo3L/6xRXKssYemx+7W52iNskj/SQ4FOmfCb8YQt39otTDNMveCZzYtMoucQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg=="
- },
- "Microsoft.SourceLink.GitLab": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "tvsg47DDLqqedlPeYVE2lmiTpND8F0hkrealQ5hYltSmvruy/Gr5nHAKSsjyw5L3NeM/HLMI5ORv7on/M4qyZw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "StyleCop.Analyzers.Unstable": {
- "type": "Transitive",
- "resolved": "1.2.0.435",
- "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
- },
- "Grpc.Core": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "lu7KP7BVWdvFXWbn/IFYHBQCpMohJwbLM1aL+nu2C0pY2CdS0idaUNAJNC2nZ60fXfqoxnSiERrIU6rC474oTw==",
- "dependencies": {
- "Grpc.Core.Api": "2.46.3",
- "System.Memory": "4.5.3"
- }
- },
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.5.5, )",
- "resolved": "4.5.5",
- "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
- }
- }
- }
-}
\ No newline at end of file
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/FrameHeader.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/FrameHeader.cs
deleted file mode 100644
index c49ad0fa..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/FrameHeader.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Buffers.Binary;
-using System.Text.Json;
-using System.Threading.Tasks;
-using Overby.Extensions.AsyncBinaryReaderWriter;
-
-namespace GeothermalResearchInstitute.Plc
-{
- internal class FrameHeader
- {
- public FrameHeader(
- byte version,
- byte type,
- byte sequenceNumber,
- uint streamId,
- ushort contentOffset,
- ushort contentLength,
- uint contentChecksum)
- {
- this.Version = version;
- this.Type = type;
- this.SequenceNumber = sequenceNumber;
- this.StreamId = streamId;
- this.ContentOffset = contentOffset;
- this.ContentLength = contentLength;
- this.ContentChecksum = contentChecksum;
- }
-
- public byte Version { get; }
-
- public byte Type { get; }
-
- public byte SequenceNumber { get; }
-
- public uint StreamId { get; }
-
- public ushort ContentOffset { get; }
-
- public ushort ContentLength { get; }
-
- public uint ContentChecksum { get; }
-
- public static FrameHeader Parse(ReadOnlySpan buffer)
- {
- return new FrameHeader(
- version: buffer[4],
- type: buffer[5],
- sequenceNumber: buffer[6],
- streamId: BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(8, 4)),
- contentOffset: BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(12, 2)),
- contentLength: BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(14, 2)),
- contentChecksum: BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(16, 4)));
- }
-
- public void WriteTo(Span buffer)
- {
- // Write magic signature.
- buffer[0] = (byte)'D';
- buffer[1] = (byte)'R';
- buffer[2] = (byte)'Y';
- buffer[3] = 0;
-
- // Write version, type, sequence number.
- buffer[4] = this.Version;
- buffer[5] = this.Type;
- buffer[6] = this.SequenceNumber;
- buffer[7] = 0;
-
- // Write stream id.
- BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(8, 4), this.StreamId);
-
- // Write content offset & size.
- BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(12, 2), this.ContentOffset);
- BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(14, 2), this.ContentLength);
-
- // Write content checksum.
- BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(16, 4), this.ContentChecksum);
- }
-
- public async Task WriteTo(AsyncBinaryWriter binaryWriter)
- {
- // Write magic signature.
- await binaryWriter.WriteAsync((byte)'D').ConfigureAwait(false);
- await binaryWriter.WriteAsync((byte)'R').ConfigureAwait(false);
- await binaryWriter.WriteAsync((byte)'Y').ConfigureAwait(false);
- await binaryWriter.WriteAsync((byte)0).ConfigureAwait(false);
-
- // Write version, type, sequence number.
- await binaryWriter.WriteAsync((byte)this.Version).ConfigureAwait(false);
- await binaryWriter.WriteAsync((byte)this.Type).ConfigureAwait(false);
- await binaryWriter.WriteAsync((byte)this.SequenceNumber).ConfigureAwait(false);
- await binaryWriter.WriteAsync((byte)0).ConfigureAwait(false);
-
- // Write stream id.
- await binaryWriter
- .WriteAsync(BinaryPrimitives.ReverseEndianness((uint)this.StreamId))
- .ConfigureAwait(false);
-
- // Write content offset & size.
- await binaryWriter
- .WriteAsync(BinaryPrimitives.ReverseEndianness((ushort)this.ContentOffset))
- .ConfigureAwait(false);
- await binaryWriter
- .WriteAsync(BinaryPrimitives.ReverseEndianness((ushort)this.ContentLength))
- .ConfigureAwait(false);
-
- // Write content checksum.
- await binaryWriter
- .WriteAsync(BinaryPrimitives.ReverseEndianness((uint)this.ContentChecksum))
- .ConfigureAwait(false);
- }
-
- public override string ToString()
- {
- return JsonSerializer.Serialize(this);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/GeothermalResearchInstitute.Plc.csproj b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/GeothermalResearchInstitute.Plc.csproj
deleted file mode 100644
index bf98a9d4..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/GeothermalResearchInstitute.Plc.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- $(CurrentTargetFramework)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/HexUtils.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/HexUtils.cs
deleted file mode 100644
index 861c09e5..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/HexUtils.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Text;
-
-namespace GeothermalResearchInstitute.Plc
-{
- internal class HexUtils
- {
- private readonly ReadOnlyMemory bytes;
- private readonly int bytesPerLine;
- private readonly bool showHeader;
- private readonly bool showOffset;
- private readonly bool showAscii;
-
- private readonly StringBuilder sb = new StringBuilder();
-
- private int index;
-
- private HexUtils(
- ReadOnlyMemory bytes,
- int bytesPerLine,
- bool showHeader,
- bool showOffset,
- bool showAscii)
- {
- this.bytes = bytes;
- this.bytesPerLine = bytesPerLine;
- this.showHeader = showHeader;
- this.showOffset = showOffset;
- this.showAscii = showAscii;
- }
-
- public static string Dump(
- ReadOnlyMemory bytes,
- int bytesPerLine = 16,
- bool showHeader = true,
- bool showOffset = true,
- bool showAscii = true)
- {
- return new HexUtils(bytes, bytesPerLine, showHeader, showOffset, showAscii).Dump();
- }
-
- private static string Translate(byte b)
- {
- return b < 32 ? "." : Encoding.ASCII.GetString(new[] { b });
- }
-
- private string Dump()
- {
- if (this.showHeader)
- {
- this.WriteHeader();
- }
-
- this.WriteBody();
- return this.sb.ToString();
- }
-
- private void WriteHeader()
- {
- if (this.showOffset)
- {
- this.sb.Append("Offset(h) ");
- }
-
- for (int i = 0; i < this.bytesPerLine; i++)
- {
- this.sb.Append($"{i & 0xFF:X2}");
- if (i + 1 < this.bytesPerLine)
- {
- this.sb.Append(' ');
- }
- }
-
- this.sb.AppendLine();
- }
-
- private void WriteBody()
- {
- while (this.index < this.bytes.Length)
- {
- if (this.index % this.bytesPerLine == 0)
- {
- if (this.index > 0)
- {
- if (this.showAscii)
- {
- this.WriteAscii();
- }
-
- this.sb.AppendLine();
- }
-
- if (this.showOffset)
- {
- this.WriteOffset();
- }
- }
-
- this.WriteByte();
- if (this.index % this.bytesPerLine != 0 && this.index < this.bytes.Length)
- {
- this.sb.Append(' ');
- }
- }
-
- if (this.showAscii)
- {
- this.WriteAscii();
- }
- }
-
- private void WriteOffset()
- {
- this.sb.Append($"{this.index:X8} ");
- }
-
- private void WriteByte()
- {
- this.sb.Append($"{this.bytes.Span[this.index]:X2}");
- this.index++;
- }
-
- private void WriteAscii()
- {
- int backtrack = ((this.index - 1) / this.bytesPerLine) * this.bytesPerLine;
- int length = this.index - backtrack;
-
- // This is to fill up last string of the dump if it's shorter than _bytesPerLine
- this.sb.Append(new string(' ', (this.bytesPerLine - length) * 3));
-
- this.sb.Append(" ");
- for (int i = 0; i < length; i++)
- {
- this.sb.Append(Translate(this.bytes.Span[backtrack + i]));
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClient.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClient.cs
deleted file mode 100644
index e8c4528f..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClient.cs
+++ /dev/null
@@ -1,224 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Sockets;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Threading.Tasks.Dataflow;
-using GeothermalResearchInstitute.v2;
-using Google.Protobuf;
-using Grpc.Core;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.Plc
-{
- public partial class PlcClient : IDisposable
- {
- private readonly ILogger logger;
- private readonly TcpClient client;
- private readonly ConcurrentDictionary receivingContexts =
- new ConcurrentDictionary();
-
- private volatile bool started = false;
- private volatile bool stopped = false;
- private ManualResetEvent stoppedEvent;
- private EndPoint remoteEndPoint;
- private BufferBlock requestQueue;
- private int counter;
- private Task backgroundSendingTask;
- private Task backgroundReceivingTask;
- private Task backgroundDeadlineCollectionTask;
-
- private bool disposedValue = false;
-
- public PlcClient(ILogger 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)
- {
- return Task.CompletedTask;
- }
-
- if (!this.client.Connected)
- {
- return Task.FromException(new InvalidOperationException("Client disconnected"));
- }
-
- this.remoteEndPoint = this.client.Client?.RemoteEndPoint;
- this.stoppedEvent = new ManualResetEvent(false);
- this.requestQueue = new BufferBlock(new DataflowBlockOptions
- {
- BoundedCapacity = 20,
- EnsureOrdered = false,
- TaskScheduler = TaskScheduler.Default,
- });
- this.counter = 0;
-
- this.backgroundSendingTask = Task.Factory.StartNew(
- this.BackgroundSendingTaskEntryPoint,
- Task.Factory.CancellationToken,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
- this.backgroundReceivingTask = Task.Factory.StartNew(
- this.BackgroundReceivingTaskEntryPoint,
- Task.Factory.CancellationToken,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
- this.backgroundDeadlineCollectionTask = Task.Factory.StartNew(
- this.BackgroundDeadlineCollectionTaskEntryPoint,
- Task.Factory.CancellationToken,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
-
- this.started = true;
- return Task.CompletedTask;
- }
-
- public async Task StopAsync()
- {
- if (this.started && !this.stopped)
- {
- this.stoppedEvent.Set();
- this.requestQueue.Complete();
-
- await this.backgroundSendingTask.ConfigureAwait(false);
- await this.backgroundReceivingTask.ConfigureAwait(false);
-
- this.stopped = true;
- }
- }
-
- public void Dispose()
- {
- this.Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (this.disposedValue)
- {
- return;
- }
-
- if (disposing)
- {
- if (this.started)
- {
- if (!this.stopped)
- {
- this.StopAsync().GetAwaiter().GetResult();
- }
-
- this.stoppedEvent.Dispose();
- this.backgroundSendingTask.Dispose();
- this.backgroundReceivingTask.Dispose();
- this.client.Dispose();
- }
- }
-
- this.disposedValue = true;
- }
-
- private async Task InvokeAsync(
- string path,
- TRequest request,
- MessageParser responseParser,
- DateTime? deadline = null,
- CancellationToken cancellationToken = default)
- where TRequest : IMessage
- where TResponse : IMessage
- {
- var promise = new TaskCompletionSource();
-
- await this.requestQueue
- .SendAsync(
- new RequestContext
- {
- Path = path,
- Message = request,
- Deadline = deadline,
- CancellationToken = cancellationToken,
- TaskCompletionSource = promise,
- },
- cancellationToken)
- .ConfigureAwait(false);
- return await promise.Task
- .ContinueWith(
- future =>
- {
- if (future.IsFaulted)
- {
- throw new RpcException(new Status(
- StatusCode.Internal, future.Exception.ToString()));
- }
-
- if (future.IsCanceled)
- {
- throw new RpcException(Status.DefaultCancelled);
- }
-
- UnifiedFrameContent frame = future.Result;
- if (frame.Header.Status == 0)
- {
- return responseParser.ParseFrom(frame.Payload);
- }
- else
- {
- throw new RpcException(new Status(
- (StatusCode)frame.Header.Status,
- frame.Header.StatusMessage));
- }
- },
- cancellationToken,
- TaskContinuationOptions.DenyChildAttach,
- TaskScheduler.Default)
- .ConfigureAwait(false);
- }
-
- private void BackgroundDeadlineCollectionTaskEntryPoint()
- {
- while (!this.stoppedEvent.WaitOne(100))
- {
- DateTime now = DateTime.Now;
- foreach (KeyValuePair p in this.receivingContexts)
- {
- if (p.Value.CancellationToken.IsCancellationRequested
- || now > p.Value.Deadline)
- {
- if (this.receivingContexts.TryRemove(p.Key, out var _))
- {
- p.Value.TaskCompletionSource.SetResult(new UnifiedFrameContent
- {
- Header = new Header
- {
- Status = (int)StatusCode.DeadlineExceeded,
- StatusMessage = "Didn't receive message before deadline",
- },
- });
- }
- }
- }
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientApi.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientApi.cs
deleted file mode 100644
index 69e96a26..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientApi.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using GeothermalResearchInstitute.v2;
-
-namespace GeothermalResearchInstitute.Plc
-{
- public partial class PlcClient
- {
- public Task TestAsync(
- TestRequest request,
- DateTime? deadline = null,
- CancellationToken cancellationToken = default)
- {
- return this.InvokeAsync(
- "/bjdire.v2.DeviceService/Test",
- request,
- TestResponse.Parser,
- deadline,
- cancellationToken);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientReceiving.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientReceiving.cs
deleted file mode 100644
index 4eae4fb6..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientReceiving.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.IO;
-using System.Text;
-using System.Threading.Tasks;
-using GeothermalResearchInstitute.v2;
-using Microsoft.Extensions.Logging;
-using Overby.Extensions.AsyncBinaryReaderWriter;
-
-namespace GeothermalResearchInstitute.Plc
-{
- public partial class PlcClient
- {
- private async void BackgroundReceivingTaskEntryPoint()
- {
- try
- {
- using var binaryReader = new AsyncBinaryReader(this.client.GetStream(), Encoding.ASCII, true);
-
- while (!this.stoppedEvent.WaitOne(1000))
- {
- await this.DrainReceivingContexts(binaryReader).ConfigureAwait(false);
- }
-
- await this.DrainReceivingContexts(binaryReader).ConfigureAwait(false);
- }
- catch (IOException e)
- {
- this.logger.LogError(e, "Error when receiving data from {0}", this.remoteEndPoint);
- this.client.Close();
- this.ConnectionClosed?.Invoke(this, new EventArgs());
- }
- }
-
- private async Task DrainReceivingContexts(AsyncBinaryReader binaryReader)
- {
- while (!(this.receivingContexts.IsEmpty && this.requestQueue.Count == 0))
- {
- byte[] frameHeaderBytes = await binaryReader.ReadBytesAsync(20).ConfigureAwait(false);
- if (frameHeaderBytes.Length < 20)
- {
- throw new IOException("Socket closed during reading.");
- }
-
- var frameHeader = FrameHeader.Parse(frameHeaderBytes);
- if (frameHeader.ContentOffset != 20)
- {
- this.logger.LogCritical(
- "Invalid frame header with unexpected content offset, expected=20 actual={0}",
- frameHeader.ContentOffset);
- throw new InvalidDataException("Invalid frame header");
- }
-
- if (frameHeader.Version != 1)
- {
- this.logger.LogWarning(
- "Invalid frame header with unexpected version {0}",
- frameHeader.Version);
- throw new InvalidDataException("Invalid frame header");
- }
-
- byte[] framePayloadBytes = await binaryReader
- .ReadBytesAsync(frameHeader.ContentLength)
- .ConfigureAwait(false);
- if (framePayloadBytes.Length < frameHeader.ContentLength)
- {
- throw new IOException("Socket closed during reading.");
- }
-
- if (this.logger.IsEnabled(LogLevel.Debug))
- {
- var buffer = new byte[frameHeaderBytes.Length + framePayloadBytes.Length];
- Buffer.BlockCopy(frameHeaderBytes, 0, buffer, 0, frameHeaderBytes.Length);
- Buffer.BlockCopy(framePayloadBytes, 0, buffer, frameHeaderBytes.Length, framePayloadBytes.Length);
-
- this.logger.LogDebug(
- "Received streamId={0}:" + Environment.NewLine + "{1}",
- frameHeader.StreamId,
- HexUtils.Dump(buffer.AsMemory()));
- }
-
- if (this.receivingContexts.TryRemove((int)frameHeader.StreamId, out RequestContext requestContext))
- {
- this.Process(requestContext, frameHeader, framePayloadBytes);
- }
- else
- {
- this.logger.LogWarning("Dropped a frame with unexpected streamId {0}", frameHeader.StreamId);
- }
- }
- }
-
- private void Process(RequestContext requestContext, FrameHeader frameHeader, byte[] framePayloadBytes)
- {
- if (frameHeader.Type != 2)
- {
- this.logger.LogWarning("Dropped a frame with unexpected type {0}", frameHeader.Type);
- requestContext.TaskCompletionSource.SetException(new InvalidDataException("Invalid data received"));
- return;
- }
-
- var expectedChecksum = Crc32C.Crc32CAlgorithm.Compute(framePayloadBytes);
- if (frameHeader.ContentChecksum != expectedChecksum)
- {
- this.logger.LogWarning(
- "Dropped a frame with unexpected checksum {0}(expected {1})",
- frameHeader.ContentChecksum,
- expectedChecksum);
- requestContext.TaskCompletionSource.SetException(new InvalidDataException("Invalid data received"));
- return;
- }
-
- // TODO(zhangshuai.ustc): check deadline.
- var unifiedFrameContent = UnifiedFrameContent.Parser.ParseFrom(framePayloadBytes);
- requestContext.TaskCompletionSource.SetResult(unifiedFrameContent);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientRequestContext.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientRequestContext.cs
deleted file mode 100644
index 9f2ba6e9..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientRequestContext.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using GeothermalResearchInstitute.v2;
-using Google.Protobuf;
-
-namespace GeothermalResearchInstitute.Plc
-{
- public partial class PlcClient
- {
- private class RequestContext
- {
- public string Path { get; set; }
-
- public IMessage Message { get; set; }
-
- public DateTime? Deadline { get; set; }
-
- public CancellationToken CancellationToken { get; set; }
-
- public TaskCompletionSource TaskCompletionSource { get; set; }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientSending.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientSending.cs
deleted file mode 100644
index 269cd95a..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/PlcClientSending.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.IO;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Threading.Tasks.Dataflow;
-using GeothermalResearchInstitute.v2;
-using Google.Protobuf;
-using Grpc.Core;
-using Microsoft.Extensions.Logging;
-using Overby.Extensions.AsyncBinaryReaderWriter;
-
-namespace GeothermalResearchInstitute.Plc
-{
- public partial class PlcClient
- {
- private static async Task WriteFrame(
- AsyncBinaryWriter writer,
- byte type,
- byte seqNum,
- int streamId,
- byte[] contents)
- {
- uint contentChecksum = 0;
-
- // TODO(zhangshuai.ustc): Support other platform
- if (Environment.OSVersion.Platform == PlatformID.Win32NT
- || Environment.OSVersion.Platform == PlatformID.Win32Windows)
- {
- contentChecksum = Crc32C.Crc32CAlgorithm.Compute(contents);
- }
-
- var frameHeader = new FrameHeader(
- version: 1,
- type: type,
- sequenceNumber: seqNum,
- streamId: (uint)streamId,
- contentOffset: 20,
- contentLength: (ushort)contents.Length,
- contentChecksum: contentChecksum);
- await frameHeader.WriteTo(writer).ConfigureAwait(false);
- await writer.WriteAsync(contents).ConfigureAwait(false);
- }
-
- private async void BackgroundSendingTaskEntryPoint()
- {
- try
- {
- using var binaryWriter = new AsyncBinaryWriter(this.client.GetStream(), Encoding.ASCII, true);
- while (await this.requestQueue
- .OutputAvailableAsync()
- .ConfigureAwait(false))
- {
- await this.DrainSendingRequestContexts(binaryWriter).ConfigureAwait(false);
- }
- }
- catch (IOException e)
- {
- this.logger.LogError(e, "Error when receiving data from {0}", this.client.Client.RemoteEndPoint);
- this.client.Close();
- this.ConnectionClosed?.Invoke(this, new EventArgs());
- }
- }
-
- private async Task DrainSendingRequestContexts(AsyncBinaryWriter binaryWriter)
- {
- while (this.requestQueue.TryReceive(out RequestContext requestContext))
- {
- if (requestContext.CancellationToken.IsCancellationRequested
- || DateTime.Now > requestContext.Deadline)
- {
- requestContext.TaskCompletionSource.SetResult(new UnifiedFrameContent
- {
- Header = new Header
- {
- Status = (int)StatusCode.DeadlineExceeded,
- StatusMessage = Status.DefaultCancelled.Detail,
- },
- });
- }
-
- var unifiedFrameContent = new UnifiedFrameContent()
- {
- Header = new Header()
- {
- Path = requestContext.Path,
- },
- Payload = requestContext.Message.ToByteString(),
- };
- int streamId = Interlocked.Increment(ref this.counter);
- await this.WriteUnifiedFrameContent(binaryWriter, streamId, unifiedFrameContent)
- .ConfigureAwait(false);
- if (!this.receivingContexts.TryAdd(streamId, requestContext))
- {
- throw new InvalidOperationException("Impossible");
- }
-
- this.logger.LogDebug("Request recorded as streamId={0}: {1}", streamId, requestContext.Message);
- }
- }
-
- private async Task WriteUnifiedFrameContent(
- AsyncBinaryWriter writer,
- int streamId,
- UnifiedFrameContent unifiedFrameContent)
- {
- if (this.logger.IsEnabled(LogLevel.Debug))
- {
- using var memoryStream = new MemoryStream();
- using var memoryWriter = new AsyncBinaryWriter(memoryStream, Encoding.ASCII, false);
-
- await WriteFrame(memoryWriter, 2, 0, streamId, unifiedFrameContent.ToByteArray())
- .ConfigureAwait(false);
- byte[] sendingBytes = memoryStream.ToArray();
-
- this.logger.LogDebug(
- "Sending to {0} with streamId={1}:" + Environment.NewLine + "{2}",
- unifiedFrameContent.Header.Path,
- streamId,
- HexUtils.Dump(new ReadOnlyMemory(sendingBytes)));
- await writer.WriteAsync(sendingBytes).ConfigureAwait(false);
- }
- else
- {
- await WriteFrame(writer, 2, 0, streamId, unifiedFrameContent.ToByteArray())
- .ConfigureAwait(false);
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/packages.lock.json b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/packages.lock.json
deleted file mode 100644
index aeedc35d..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcClient/packages.lock.json
+++ /dev/null
@@ -1,202 +0,0 @@
-{
- "version": 2,
- "dependencies": {
- "net6.0": {
- "DotNet.ReproducibleBuilds": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "+H2t/t34h6mhEoUvHi8yGXyuZ2GjSovcGYehJrS2MDm2XgmPfZL2Sdxg+uL2lKgZ4M6tTwKHIlxOob2bgh0NRQ==",
- "dependencies": {
- "Microsoft.SourceLink.AzureRepos.Git": "1.1.1",
- "Microsoft.SourceLink.Bitbucket.Git": "1.1.1",
- "Microsoft.SourceLink.GitHub": "1.1.1",
- "Microsoft.SourceLink.GitLab": "1.1.1"
- }
- },
- "Microsoft.CodeAnalysis.BannedApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.3, )",
- "resolved": "3.3.3",
- "contentHash": "vvz3XCHVrd/Ks4xPoutLmL/T2+8JcOk/OMs3ngwQqnzokQCGEDsY+WjK/txCsDWU29sX3fGzH/FnYwNV93O1mA=="
- },
- "Microsoft.CodeAnalysis.NetAnalyzers": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "cjG06LMeOADNUeCUaklOfVgrnVkLy80H5PVll4QHDUXv+C+6G9rHczrNdWjfb3xKv3Ts9s4UsP6J2ZWe52Gz4Q=="
- },
- "Microsoft.Extensions.Logging.Abstractions": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies": {
- "type": "Direct",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
- "dependencies": {
- "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
- }
- },
- "Microsoft.SourceLink.GitHub": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Nerdbank.GitVersioning": {
- "type": "Direct",
- "requested": "[3.5.113, )",
- "resolved": "3.5.113",
- "contentHash": "4fBSMkqhi410qlkjPm+Mxfk8iO3C7dmgdVS7ljsfVO21WEzZCHP1VCOqB6rlOPfPidR/oxX+/Do/I7meCAz+Jg=="
- },
- "Overby.Extensions.AsyncBinaryReaderWriter": {
- "type": "Direct",
- "requested": "[1.0.39, )",
- "resolved": "1.0.39",
- "contentHash": "/4AdpYC4rgMOfmNjvU4kdEEqiEd3DfVWDbbzTIf3LoAbZ6GE46mM5FvmvQR2kYuMvEfqZo1mp1Rl1SAmjgXfrQ=="
- },
- "StyleCop.Analyzers": {
- "type": "Direct",
- "requested": "[1.2.0-beta.435, )",
- "resolved": "1.2.0-beta.435",
- "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
- "dependencies": {
- "StyleCop.Analyzers.Unstable": "1.2.0.435"
- }
- },
- "System.Text.Json": {
- "type": "Direct",
- "requested": "[6.0.6, )",
- "resolved": "6.0.6",
- "contentHash": "GZ+62pLOr544jwSvyXv5ezSfzlFBTjLuPhgOS2dnKuknAA8dPNUGXLKTHf9XdsudU9JpbtweXnE4oEiKEB2T1Q==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0",
- "System.Text.Encodings.Web": "6.0.0"
- }
- },
- "System.Threading.Tasks.Dataflow": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
- },
- "Grpc.Core.Api": {
- "type": "Transitive",
- "resolved": "2.46.3",
- "contentHash": "uy1oe5baVa4V+C8ZyMiA8xYdNIx5A3PiacQL0f1zWDjF2z64Cb1MMXXRTs3GX+jeKpoK/RtOZg8UnJSm2KC/pQ==",
- "dependencies": {
- "System.Memory": "4.5.3"
- }
- },
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies.net461": {
- "type": "Transitive",
- "resolved": "1.0.3",
- "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
- },
- "Microsoft.SourceLink.AzureRepos.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "qB5urvw9LO2bG3eVAkuL+2ughxz2rR7aYgm2iyrB8Rlk9cp2ndvGRCvehk3rNIhRuNtQaeKwctOl1KvWiklv5w==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Bitbucket.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "cDzxXwlyWpLWaH0em4Idj0H3AmVo3L/6xRXKssYemx+7W52iNskj/SQ4FOmfCb8YQt39otTDNMveCZzYtMoucQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg=="
- },
- "Microsoft.SourceLink.GitLab": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "tvsg47DDLqqedlPeYVE2lmiTpND8F0hkrealQ5hYltSmvruy/Gr5nHAKSsjyw5L3NeM/HLMI5ORv7on/M4qyZw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "StyleCop.Analyzers.Unstable": {
- "type": "Transitive",
- "resolved": "1.2.0.435",
- "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
- },
- "System.Runtime.CompilerServices.Unsafe": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
- },
- "System.Text.Encodings.Web": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
- "crc32c.net": {
- "type": "Project"
- },
- "geothermalresearchinstitute.grpc": {
- "type": "Project",
- "dependencies": {
- "Google.Protobuf": "[3.21.6, )",
- "Grpc": "[2.46.3, )"
- }
- },
- "Google.Protobuf": {
- "type": "CentralTransitive",
- "requested": "[3.21.6, )",
- "resolved": "3.21.6",
- "contentHash": "HSYHFnfuTu/O4Ijy0mCW9zxLI8MJfCZJ10dk3JGPrkLaRR4LsiPKzZrrnapf2G0tP2yRMkHCl+2LKLTXqGBn2A=="
- },
- "Grpc": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "79TsAcLBVl5J7AmtnV+GmgkhWlpK3D9JYJDhYxZGO0DKukbyrRxxcbaFlRZ84WGwTAW8LezrInUYgfiJi3zGVg==",
- "dependencies": {
- "Grpc.Core": "2.46.3"
- }
- },
- "Grpc.Core": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "lu7KP7BVWdvFXWbn/IFYHBQCpMohJwbLM1aL+nu2C0pY2CdS0idaUNAJNC2nZ60fXfqoxnSiERrIU6rC474oTw==",
- "dependencies": {
- "Grpc.Core.Api": "2.46.3",
- "System.Memory": "4.5.3"
- }
- },
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.5.5, )",
- "resolved": "4.5.5",
- "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
- }
- }
- }
-}
\ No newline at end of file
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/GeothermalResearchInstitute.PlcV2.csproj b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/GeothermalResearchInstitute.PlcV2.csproj
deleted file mode 100644
index 5585b5a0..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/GeothermalResearchInstitute.PlcV2.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- $(CurrentTargetFramework)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/HexUtils.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/HexUtils.cs
deleted file mode 100644
index a95dc0dd..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/HexUtils.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Text;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- internal class HexUtils
- {
- private readonly ReadOnlyMemory bytes;
- private readonly int bytesPerLine;
- private readonly bool showHeader;
- private readonly bool showOffset;
- private readonly bool showAscii;
-
- private readonly StringBuilder sb = new StringBuilder();
-
- private int index;
-
- private HexUtils(
- ReadOnlyMemory bytes,
- int bytesPerLine,
- bool showHeader,
- bool showOffset,
- bool showAscii)
- {
- this.bytes = bytes;
- this.bytesPerLine = bytesPerLine;
- this.showHeader = showHeader;
- this.showOffset = showOffset;
- this.showAscii = showAscii;
- }
-
- public static string Dump(
- ReadOnlyMemory bytes,
- int bytesPerLine = 16,
- bool showHeader = true,
- bool showOffset = true,
- bool showAscii = true)
- {
- return new HexUtils(bytes, bytesPerLine, showHeader, showOffset, showAscii).Dump();
- }
-
- private static string Translate(byte b)
- {
- return b < 32 ? "." : Encoding.ASCII.GetString(new[] { b });
- }
-
- private string Dump()
- {
- if (this.showHeader)
- {
- this.WriteHeader();
- }
-
- this.WriteBody();
- return this.sb.ToString();
- }
-
- private void WriteHeader()
- {
- if (this.showOffset)
- {
- this.sb.Append("Offset(h) ");
- }
-
- for (int i = 0; i < this.bytesPerLine; i++)
- {
- this.sb.Append($"{i & 0xFF:X2}");
- if (i + 1 < this.bytesPerLine)
- {
- this.sb.Append(' ');
- }
- }
-
- this.sb.AppendLine();
- }
-
- private void WriteBody()
- {
- while (this.index < this.bytes.Length)
- {
- if (this.index % this.bytesPerLine == 0)
- {
- if (this.index > 0)
- {
- if (this.showAscii)
- {
- this.WriteAscii();
- }
-
- this.sb.AppendLine();
- }
-
- if (this.showOffset)
- {
- this.WriteOffset();
- }
- }
-
- this.WriteByte();
- if (this.index % this.bytesPerLine != 0 && this.index < this.bytes.Length)
- {
- this.sb.Append(' ');
- }
- }
-
- if (this.showAscii)
- {
- this.WriteAscii();
- }
- }
-
- private void WriteOffset()
- {
- this.sb.Append($"{this.index:X8} ");
- }
-
- private void WriteByte()
- {
- this.sb.Append($"{this.bytes.Span[this.index]:X2}");
- this.index++;
- }
-
- private void WriteAscii()
- {
- int backtrack = ((this.index - 1) / this.bytesPerLine) * this.bytesPerLine;
- int length = this.index - backtrack;
-
- // This is to fill up last string of the dump if it's shorter than _bytesPerLine
- this.sb.Append(new string(' ', (this.bytesPerLine - length) * 3));
-
- this.sb.Append(" ");
- for (int i = 0; i < length; i++)
- {
- this.sb.Append(Translate(this.bytes.Span[backtrack + i]));
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClient.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClient.cs
deleted file mode 100644
index 5feb17d2..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClient.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Net;
-using System.Net.Sockets;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Threading.Tasks.Dataflow;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public partial class PlcClient : IDisposable
- {
- private readonly ILogger logger;
-
- private readonly TcpClient tcpClient;
-
- private readonly BufferBlock requestContextSendingBufferBlock =
- new BufferBlock(new DataflowBlockOptions
- {
- BoundedCapacity = 100,
- EnsureOrdered = false,
- TaskScheduler = TaskScheduler.Default,
- });
-
- private readonly Task sendingBackgroundTask;
- private readonly Task receivingBackgroundTask;
- private readonly Task deadlineBackgroundTask;
- private readonly SemaphoreSlim mutex = new SemaphoreSlim(1);
- private readonly CancellationTokenSource closingCancellationTokenSource = new CancellationTokenSource();
-
- private readonly ConcurrentDictionary requestContextReceivingDictionary =
- new ConcurrentDictionary();
-
- private int sequenceNumberGenerator = 0;
- private bool disposedValue = false;
-
- public PlcClient(ILogger logger, TcpClient tcpClient)
- {
- this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
- this.tcpClient = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient));
- this.RemoteEndPoint = tcpClient.Client.RemoteEndPoint;
-
- this.sendingBackgroundTask = Task.Factory.StartNew(
- this.SendingBackgroundTaskEntryPoint,
- CancellationToken.None,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
- this.receivingBackgroundTask = Task.Factory.StartNew(
- this.ReceivingBackgroundTaskEntryPoint,
- CancellationToken.None,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
- this.deadlineBackgroundTask = Task.Factory.StartNew(
- this.DeadlineBackgroundTaskEntryPoint,
- CancellationToken.None,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
- }
-
- ~PlcClient()
- {
- this.Dispose(false);
- }
-
- public event EventHandler OnClosed;
-
- public event EventHandler OnDebugSending;
-
- public event EventHandler OnDebugReceiving;
-
- public EndPoint RemoteEndPoint { get; }
-
- public void Dispose()
- {
- this.Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- public async Task Close()
- {
- await this.mutex.WaitAsync().ConfigureAwait(false);
- try
- {
- if (!this.closingCancellationTokenSource.IsCancellationRequested)
- {
- this.closingCancellationTokenSource.Cancel();
- this.requestContextSendingBufferBlock.Complete();
-
- await this.sendingBackgroundTask.ConfigureAwait(false);
- await this.receivingBackgroundTask.ConfigureAwait(false);
- await this.deadlineBackgroundTask.ConfigureAwait(false);
-
- this.tcpClient.Close();
- this.OnClosed?.Invoke(this, EventArgs.Empty);
- }
- }
- finally
- {
- this.mutex.Release();
- }
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposedValue)
- {
- if (disposing)
- {
- this.Close().GetAwaiter().GetResult();
-
- this.sendingBackgroundTask.Dispose();
- this.receivingBackgroundTask.Dispose();
- this.deadlineBackgroundTask.Dispose();
-
- this.tcpClient.Dispose();
- this.closingCancellationTokenSource.Dispose();
- this.mutex.Dispose();
- }
-
- this.disposedValue = true;
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientApi.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientApi.cs
deleted file mode 100644
index b84ce081..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientApi.cs
+++ /dev/null
@@ -1,454 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Buffers.Binary;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Threading.Tasks.Dataflow;
-using GeothermalResearchInstitute.v2;
-using Google.Protobuf;
-using Google.Protobuf.WellKnownTypes;
-using Grpc.Core;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public partial class PlcClient
- {
- public async Task ConnectAsync(ConnectRequest request, DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.ConnectRequest, ByteString.Empty),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.ConnectResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- return new ConnectResponse
- {
- Id = response.FrameBody,
- };
- }
-
- public async Task GetMetricAsync(GetMetricRequest request, DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.GetMetricRequest, ByteString.Empty),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetMetricResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new Metric
- {
- CreateTime = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow),
- OutputWaterCelsiusDegree = reader.ReadSingle(),
- InputWaterCelsiusDegree = reader.ReadSingle(),
- HeaterOutputWaterCelsiusDegree = reader.ReadSingle(),
- EnvironmentCelsiusDegree = reader.ReadSingle(),
- OutputWaterPressureMeter = reader.ReadSingle(),
- InputWaterPressureMeter = reader.ReadSingle(),
- HeaterPowerKilowatt = reader.ReadSingle(),
- WaterPumpFlowRateCubicMeterPerHour = reader.ReadSingle(),
- };
- }
-
- public async Task GetSwitchAsync(GetSwitchRequest request, DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.GetSwitchRequest, ByteString.Empty),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetSwitchResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new Switch
- {
- DevicePowerOn = reader.ReadByte() != 0,
- ExhausterPowerOn = reader.ReadByte() != 0,
- HeaterAutoOn = reader.ReadByte() != 0,
- HeaterPowerOn = reader.ReadByte() != 0,
- HeaterFanOn = reader.ReadByte() != 0,
- HeaterCompressorOn = reader.ReadByte() != 0,
- HeaterFourWayReversingOn = reader.ReadByte() != 0,
- };
- }
-
- public async Task UpdateSwitchAsync(UpdateSwitchRequest request, DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- if (request.UpdateMask.Paths.Count != 1)
- {
- throw new ArgumentException("Update not exact 1 field", nameof(request));
- }
-
- byte[] bytes = new byte[0x07];
- switch (request.UpdateMask.Paths.Single())
- {
- case "device_power_on":
- bytes[0] = (byte)(0x10 | (request.Switch.DevicePowerOn ? 1 : 0));
- break;
- case "exhauster_power_on":
- bytes[1] = (byte)(0x10 | (request.Switch.ExhausterPowerOn ? 1 : 0));
- break;
- case "heater_auto_on":
- bytes[2] = (byte)(0x10 | (request.Switch.HeaterAutoOn ? 1 : 0));
- break;
- case "heater_power_on":
- bytes[3] = (byte)(0x10 | (request.Switch.HeaterPowerOn ? 1 : 0));
- break;
- case "heater_fan_on":
- bytes[4] = (byte)(0x10 | (request.Switch.HeaterFanOn ? 1 : 0));
- break;
- case "heater_compressor_on":
- bytes[5] = (byte)(0x10 | (request.Switch.HeaterCompressorOn ? 1 : 0));
- break;
- case "heater_four_way_reversing_on":
- bytes[6] = (byte)(0x10 | (request.Switch.HeaterFourWayReversingOn ? 1 : 0));
- break;
- default:
- throw new InvalidDataException("Unrecognized update mask " + request.UpdateMask.Paths.Single());
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.UpdateSwitchRequest, ByteString.CopyFrom(bytes)),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetSwitchResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new Switch
- {
- DevicePowerOn = reader.ReadByte() != 0,
- ExhausterPowerOn = reader.ReadByte() != 0,
- HeaterAutoOn = reader.ReadByte() != 0,
- HeaterPowerOn = reader.ReadByte() != 0,
- HeaterFanOn = reader.ReadByte() != 0,
- HeaterCompressorOn = reader.ReadByte() != 0,
- HeaterFourWayReversingOn = reader.ReadByte() != 0,
- };
- }
-
- public async Task GetWorkingModeAsync(GetWorkingModeRequest request, DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.GetWorkingModeRequest, ByteString.Empty),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetWorkingModeResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new WorkingMode
- {
- DeviceWorkingMode = (DeviceWorkingMode)reader.ReadByte(),
- DeviceFlowRateControlMode = (DeviceFlowRateControlMode)reader.ReadByte(),
- WaterPumpWorkingMode = (WaterPumpWorkingMode)reader.ReadByte(),
- };
- }
-
- public async Task UpdateWorkingModeAsync(UpdateWorkingModeRequest request, DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- byte[] bytes = new byte[0x03];
- foreach (string path in request.UpdateMask.Paths)
- {
- switch (path)
- {
- case "device_working_mode":
- bytes[0] = (byte)request.WorkingMode.DeviceWorkingMode;
- break;
- case "device_flow_rate_control_mode":
- bytes[1] = (byte)request.WorkingMode.DeviceFlowRateControlMode;
- break;
- case "water_pump_working_mode":
- bytes[2] = (byte)request.WorkingMode.WaterPumpWorkingMode;
- break;
- default:
- throw new InvalidDataException("Unrecognized update mask " + path);
- }
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.UpdateWorkingModeRequest, ByteString.CopyFrom(bytes)),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetWorkingModeResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new WorkingMode
- {
- DeviceWorkingMode = (DeviceWorkingMode)reader.ReadByte(),
- DeviceFlowRateControlMode = (DeviceFlowRateControlMode)reader.ReadByte(),
- WaterPumpWorkingMode = (WaterPumpWorkingMode)reader.ReadByte(),
- };
- }
-
- public async Task GetAlarmAsync(GetAlarmRequest request, DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.GetAlarmRequest, ByteString.Empty),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetAlarmResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new Alarm
- {
- CreateTime = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow),
- LowFlowRate = reader.ReadByte() != 0,
- HighHeaterPressure = reader.ReadByte() != 0,
- LowHeaterPressure = reader.ReadByte() != 0,
- NoPower = reader.ReadByte() != 0,
- HeaterOverloadedBroken = reader.ReadByte() != 0,
- ElectricalHeaterBroken = reader.ReadByte() != 0,
- NoWater = reader.ReadByte() == 0,
- HighVoltage = reader.ReadByte() == 0,
- LowVoltage = reader.ReadByte() == 0,
- EmergencyStopped = reader.ReadByte() == 0,
- };
- }
-
- public async Task GetRunningParameterAsync(
- GetRunningParameterRequest request,
- DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.GetRunningParameterRequest, ByteString.Empty),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetRunningParameterResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new RunningParameter
- {
- SummerHeaterCelsiusDegree = reader.ReadSingle(),
- WinterHeaterCelsiusDegree = reader.ReadSingle(),
- ColdPowerKilowatt = reader.ReadSingle(),
- WarmPowerKilowatt = reader.ReadSingle(),
- WaterPumpFlowRateCubicMeterPerHour = reader.ReadSingle(),
- WaterPumpFrequencyHertz = reader.ReadSingle(),
- };
- }
-
- public async Task UpdateRunningParameterAsync(
- UpdateRunningParameterRequest request,
- DateTime? deadline)
- {
- if (request is null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- if (request.UpdateMask == null)
- {
- request.UpdateMask = FieldMask.FromFieldNumbers(
- RunningParameter.Descriptor.Fields.InFieldNumberOrder().Select(f => f.FieldNumber));
- }
-
- byte[] bytes = new byte[0x18];
- for (int i = 0; i < 0x18; i++)
- {
- bytes[i] = 0xFF;
- }
-
- foreach (string path in request.UpdateMask.Paths)
- {
- switch (path)
- {
- case "summer_heater_celsius_degree":
- if (!TryWriteBytes(
- bytes.AsSpan(0, 4),
- request.RunningParameter.SummerHeaterCelsiusDegree))
- {
- throw new InvalidOperationException();
- }
-
- break;
- case "winter_heater_celsius_degree":
- if (!TryWriteBytes(
- bytes.AsSpan(4, 4),
- request.RunningParameter.WinterHeaterCelsiusDegree))
- {
- throw new InvalidOperationException();
- }
-
- break;
- case "cold_power_kilowatt":
- if (!TryWriteBytes(
- bytes.AsSpan(8, 4),
- request.RunningParameter.ColdPowerKilowatt))
- {
- throw new InvalidOperationException();
- }
-
- break;
- case "warm_power_kilowatt":
- if (!TryWriteBytes(
- bytes.AsSpan(12, 4),
- request.RunningParameter.WarmPowerKilowatt))
- {
- throw new InvalidOperationException();
- }
-
- break;
- case "water_pump_flow_rate_cubic_meter_per_hour":
- if (!TryWriteBytes(
- bytes.AsSpan(16, 4),
- request.RunningParameter.WaterPumpFlowRateCubicMeterPerHour))
- {
- throw new InvalidOperationException();
- }
-
- break;
- case "water_pump_frequency_hertz":
- if (!TryWriteBytes(
- bytes.AsSpan(20, 4),
- request.RunningParameter.WaterPumpFrequencyHertz))
- {
- throw new InvalidOperationException();
- }
-
- break;
- default:
- throw new InvalidDataException("Unrecognized update mask " + path);
- }
- }
-
- PlcFrame response = await this.InvokeAsync(
- PlcFrame.Create(PlcMessageType.UpdateRunningParameterRequest, ByteString.CopyFrom(bytes)),
- deadline)
- .ConfigureAwait(false);
- if (response.FrameHeader.MessageType != PlcMessageType.GetRunningParameterResponse)
- {
- throw new InvalidDataException(
- "Response message type mismatch: " + response.FrameHeader.MessageType);
- }
-
- using var reader = new BinaryReader(new MemoryStream(response.FrameBody.ToByteArray()));
- return new RunningParameter
- {
- SummerHeaterCelsiusDegree = reader.ReadSingle(),
- WinterHeaterCelsiusDegree = reader.ReadSingle(),
- ColdPowerKilowatt = reader.ReadSingle(),
- WarmPowerKilowatt = reader.ReadSingle(),
- WaterPumpFlowRateCubicMeterPerHour = reader.ReadSingle(),
- WaterPumpFrequencyHertz = reader.ReadSingle(),
- };
- }
-
- private static bool TryWriteBytes(Span destination, float value)
- {
-#if NET48
- if (destination.Length < sizeof(float))
- {
- return false;
- }
-
- byte[] bytes = BitConverter.GetBytes(value);
- destination[0] = bytes[0];
- destination[1] = bytes[1];
- destination[2] = bytes[2];
- destination[3] = bytes[3];
-
- return true;
-#else
- return BitConverter.TryWriteBytes(destination, value);
-#endif
- }
-
- private Task InvokeAsync(PlcFrame request, DateTime? deadline)
- {
- if (this.closingCancellationTokenSource.IsCancellationRequested)
- {
- return Task.FromException(new RpcException(Status.DefaultCancelled));
- }
-
- var promise = new TaskCompletionSource();
- bool accepted = this.requestContextSendingBufferBlock.Post(new PlcRequestContext
- {
- TaskCompletionSource = promise,
- RequestFrame = request,
- Deadline = deadline,
- });
-
- if (!accepted)
- {
- promise.SetException(new RpcException(Status.DefaultCancelled));
- }
-
- return promise.Task;
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientDeadline.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientDeadline.cs
deleted file mode 100644
index e828cfa9..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientDeadline.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using Grpc.Core;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public partial class PlcClient
- {
- private void DeadlineBackgroundTaskEntryPoint()
- {
- CancellationToken closingCancellationToken = this.closingCancellationTokenSource.Token;
- while (!closingCancellationToken.WaitHandle.WaitOne(300))
- {
- DateTime now = DateTime.UtcNow;
- foreach (KeyValuePair entry in this.requestContextReceivingDictionary)
- {
- if (entry.Value.Deadline < now)
- {
- if (this.requestContextReceivingDictionary.TryRemove(
- entry.Key,
- out PlcRequestContext requestContext))
- {
- this.logger.LogWarning(
- "Request {0} to {1} exceed deadline, deadline={2:u}, now1={3:u}, now2={4:u}",
- entry.Key,
- this.RemoteEndPoint,
- entry.Value.Deadline,
- now,
- DateTime.UtcNow);
- requestContext.TaskCompletionSource.TrySetException(new RpcException(new Status(
- StatusCode.DeadlineExceeded, string.Empty)));
- }
- }
- }
- }
-
- foreach (KeyValuePair entry in this.requestContextReceivingDictionary)
- {
- if (this.requestContextReceivingDictionary.TryRemove(entry.Key, out PlcRequestContext requestContext))
- {
- requestContext.TaskCompletionSource.TrySetException(new RpcException(Status.DefaultCancelled));
- }
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientReceiving.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientReceiving.cs
deleted file mode 100644
index 12aafd57..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientReceiving.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.IO;
-using System.Text;
-using System.Threading;
-using Google.Protobuf;
-using Grpc.Core;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public partial class PlcClient
- {
- private void ReceivingBackgroundTaskEntryPoint()
- {
- CancellationToken closingCancellationToken = this.closingCancellationTokenSource.Token;
- using var reader = new BinaryReader(this.tcpClient.GetStream(), Encoding.ASCII, true);
- try
- {
- while (!closingCancellationToken.IsCancellationRequested)
- {
- byte[] headerBytes = reader.ReadBytes(20);
- if (headerBytes.Length != 20)
- {
- throw new IOException("Failed to read frame header");
- }
-
- var header = PlcFrameHeader.Parse(headerBytes);
- if (header.ContentOffset != 20)
- {
- throw new InvalidDataException("Content offset is not 20");
- }
-
- byte[] bodyBytes = reader.ReadBytes(header.ContentLength);
- if (bodyBytes.Length != header.ContentLength)
- {
- throw new IOException("Failed to read frame body");
- }
-
- if (this.logger.IsEnabled(LogLevel.Debug))
- {
- byte[] buffer = new byte[headerBytes.Length + bodyBytes.Length];
- Buffer.BlockCopy(headerBytes, 0, buffer, 0, headerBytes.Length);
- Buffer.BlockCopy(bodyBytes, 0, buffer, headerBytes.Length, bodyBytes.Length);
-
- this.logger.LogDebug(
- "Received {0} from {1}{2}{3}",
- header.SequenceNumber,
- this.RemoteEndPoint,
- Environment.NewLine,
- HexUtils.Dump(buffer));
- this.OnDebugReceiving?.Invoke(this, buffer);
- }
-
- if (this.requestContextReceivingDictionary.TryRemove(
- (int)header.SequenceNumber,
- out PlcRequestContext requestContext))
- {
- if (header.Crc32cChecksum != 0
- && header.Crc32cChecksum != Crc32C.Crc32CAlgorithm.Compute(bodyBytes))
- {
- this.logger.LogWarning(
- "Received frame crc32c checksum mismatch from {0}",
- this.RemoteEndPoint);
- requestContext.TaskCompletionSource.TrySetException(new RpcException(
- new Status(StatusCode.Internal, "Data transfer error, checksum mismatch.")));
- }
- else
- {
- requestContext.TaskCompletionSource.TrySetResult(new PlcFrame
- {
- FrameHeader = header,
- FrameBody = ByteString.CopyFrom(bodyBytes),
- });
- }
- }
- else
- {
- this.logger.LogWarning("Received unknown sequence number from {0}", this.RemoteEndPoint);
- }
- }
- }
- catch (IOException e)
- {
- this.logger.LogError(e, "Failed to receiving from {0}", this.RemoteEndPoint);
- this.Close().ConfigureAwait(false).GetAwaiter().GetResult();
- }
- catch (InvalidDataException e)
- {
- this.logger.LogError(e, "Received invalid data from {0}", this.RemoteEndPoint);
- this.Close().ConfigureAwait(false).GetAwaiter().GetResult();
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientSending.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientSending.cs
deleted file mode 100644
index 14f844e5..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcClientSending.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks.Dataflow;
-using Grpc.Core;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public partial class PlcClient
- {
- private async void SendingBackgroundTaskEntryPoint()
- {
- try
- {
- while (await this.requestContextSendingBufferBlock
- .OutputAvailableAsync()
- .ConfigureAwait(false))
- {
- DateTime utcNow = DateTime.UtcNow;
- while (this.requestContextSendingBufferBlock.TryReceive(out PlcRequestContext requestContext))
- {
- this.ProcessRequest(utcNow, requestContext);
- }
- }
- }
- catch (IOException e)
- {
- this.logger.LogError(e, "Failed to send message to {0}", this.RemoteEndPoint);
- this.Close().ConfigureAwait(false).GetAwaiter().GetResult();
- }
- }
-
- private void ProcessRequest(DateTime utcNow, PlcRequestContext requestContext)
- {
- if (requestContext.Deadline?.ToUniversalTime() < utcNow)
- {
- this.logger.LogDebug(
- "Request deadline exceeded, deadline={0:u}, now1={1:u}, now2={2:u}",
- requestContext.Deadline,
- utcNow,
- DateTime.UtcNow);
- requestContext.TaskCompletionSource.SetException(new RpcException(
- new Status(StatusCode.DeadlineExceeded, string.Empty)));
- return;
- }
-
- int sequenceNumber = Interlocked.Increment(ref this.sequenceNumberGenerator);
- requestContext.RequestFrame.FrameHeader.SequenceNumber = (uint)sequenceNumber;
-
- if (!this.requestContextReceivingDictionary.TryAdd(sequenceNumber, requestContext))
- {
- throw new InvalidOperationException(); // Should not happen.
- }
-
- if (this.logger.IsEnabled(LogLevel.Debug))
- {
- using var stream = new MemoryStream();
- requestContext.RequestFrame.WriteTo(stream);
- this.logger.LogDebug(
- "Sending {0} to {1}{2}{3}",
- sequenceNumber,
- this.RemoteEndPoint,
- Environment.NewLine,
- HexUtils.Dump(stream.ToArray()));
- this.OnDebugSending?.Invoke(this, stream.ToArray());
-
- stream.Seek(0, SeekOrigin.Begin);
- stream.CopyTo(this.tcpClient.GetStream());
- }
- else
- {
- requestContext.RequestFrame.WriteTo(this.tcpClient.GetStream());
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcFrame.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcFrame.cs
deleted file mode 100644
index c3eb303f..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcFrame.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System.IO;
-using Google.Protobuf;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public class PlcFrame
- {
- public PlcFrameHeader FrameHeader { get; set; }
-
- public ByteString FrameBody { get; set; }
-
- public static PlcFrame Create(PlcMessageType messageType, ByteString messageBody)
- {
- if (messageBody is null)
- {
- throw new System.ArgumentNullException(nameof(messageBody));
- }
-
- return new PlcFrame
- {
- FrameHeader = new PlcFrameHeader
- {
- MessageType = messageType,
- },
- FrameBody = messageBody,
- };
- }
-
- public void WriteTo(Stream outputStream)
- {
- this.FrameHeader.Crc32cChecksum = this.FrameBody.IsEmpty
- ? 0
- : Crc32C.Crc32CAlgorithm.Compute(this.FrameBody.ToByteArray());
- this.FrameHeader.ContentOffset = 0x14;
- this.FrameHeader.ContentLength = (ushort)this.FrameBody.Length;
-
- this.FrameHeader.WriteTo(outputStream);
- this.FrameBody.WriteTo(outputStream);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcFrameHeader.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcFrameHeader.cs
deleted file mode 100644
index 28d20517..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcFrameHeader.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Buffers.Binary;
-using System.IO;
-using System.Text;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public class PlcFrameHeader
- {
- public PlcMessageType MessageType { get; set; }
-
- public uint SequenceNumber { get; set; }
-
- public uint Crc32cChecksum { get; set; }
-
- public ushort ContentOffset { get; set; }
-
- public ushort ContentLength { get; set; }
-
- public static PlcFrameHeader Parse(ReadOnlySpan bytes)
- {
- if (bytes.Length != 20)
- {
- throw new ArgumentException("Header must has 20 bytes", nameof(bytes));
- }
-
- byte version = bytes[0x04];
- if (version != 0x02)
- {
- throw new InvalidDataException("Header version must be 2, but " + version + " received.");
- }
-
- return new PlcFrameHeader
- {
- MessageType = (PlcMessageType)BinaryPrimitives.ReadUInt16BigEndian(bytes.Slice(0x06, 2)),
- SequenceNumber = BinaryPrimitives.ReadUInt32BigEndian(bytes.Slice(0x08, 4)),
- Crc32cChecksum = BinaryPrimitives.ReadUInt32BigEndian(bytes.Slice(0x0C, 4)),
- ContentOffset = BinaryPrimitives.ReadUInt16BigEndian(bytes.Slice(0x10, 2)),
- ContentLength = BinaryPrimitives.ReadUInt16BigEndian(bytes.Slice(0x12, 2)),
- };
- }
-
- public void WriteTo(Stream outputStream)
- {
- using var writer = new BinaryWriter(outputStream, Encoding.ASCII, true);
-
- writer.Write('D');
- writer.Write('R');
- writer.Write('Y');
- writer.Write((byte)0x00);
-
- writer.Write((byte)0x02);
- writer.Write((byte)0x00);
- writer.Write(BinaryPrimitives.ReverseEndianness((ushort)this.MessageType));
-
- writer.Write(BinaryPrimitives.ReverseEndianness(this.SequenceNumber));
-
- writer.Write(BinaryPrimitives.ReverseEndianness(this.Crc32cChecksum));
-
- writer.Write(BinaryPrimitives.ReverseEndianness(this.ContentOffset));
- writer.Write(BinaryPrimitives.ReverseEndianness(this.ContentLength));
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcMessageType.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcMessageType.cs
deleted file mode 100644
index 3a1a2f10..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcMessageType.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System.Diagnostics.CodeAnalysis;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- [SuppressMessage("Design", "CA1028:枚举存储应为 Int32", Justification = "业务需求")]
- public enum PlcMessageType : ushort
- {
- ConnectRequest = 0x0100,
- ConnectResponse = 0x0101,
- GetMetricRequest = 0x0200,
- GetMetricResponse = 0x0201,
- GetSwitchRequest = 0x0300,
- GetSwitchResponse = 0x0301,
- UpdateSwitchRequest = 0x0400,
- GetRunningParameterRequest = 0x0500,
- GetRunningParameterResponse = 0x0501,
- UpdateRunningParameterRequest = 0x0600,
- GetWorkingModeRequest = 0x0700,
- GetWorkingModeResponse = 0x0701,
- UpdateWorkingModeRequest = 0x0800,
- GetAlarmRequest = 0x0900,
- GetAlarmResponse = 0x0901,
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcRequestContext.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcRequestContext.cs
deleted file mode 100644
index cd8cd3a1..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcRequestContext.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Threading.Tasks;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public class PlcRequestContext
- {
- public TaskCompletionSource TaskCompletionSource { get; set; }
-
- public PlcFrame RequestFrame { get; set; }
-
- public DateTime? Deadline { get; set; }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcServer.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcServer.cs
deleted file mode 100644
index 733719b3..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/PlcServer.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Net;
-using System.Net.Sockets;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.PlcV2
-{
- public class PlcServer
- {
- private readonly ILoggerFactory loggerFactory;
- private readonly TcpListener tcpListener;
-
- public PlcServer(ILoggerFactory loggerFactory, IPAddress ipAddress, int port)
- {
- this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
- this.tcpListener = new TcpListener(ipAddress, port);
- }
-
- public EndPoint LocalEndPoint => this.tcpListener.LocalEndpoint;
-
- public void Start()
- {
- this.tcpListener.Start(20);
- }
-
- public void Stop()
- {
- this.tcpListener.Stop();
- }
-
- public async Task AcceptAsync()
- {
- TcpClient tcpClient = await this.tcpListener
- .AcceptTcpClientAsync()
- .ConfigureAwait(false);
- return new PlcClient(this.loggerFactory.CreateLogger(), tcpClient);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/packages.lock.json b/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/packages.lock.json
deleted file mode 100644
index a13e89c0..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.PlcV2/packages.lock.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "version": 2,
- "dependencies": {
- "net6.0": {
- "DotNet.ReproducibleBuilds": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "+H2t/t34h6mhEoUvHi8yGXyuZ2GjSovcGYehJrS2MDm2XgmPfZL2Sdxg+uL2lKgZ4M6tTwKHIlxOob2bgh0NRQ==",
- "dependencies": {
- "Microsoft.SourceLink.AzureRepos.Git": "1.1.1",
- "Microsoft.SourceLink.Bitbucket.Git": "1.1.1",
- "Microsoft.SourceLink.GitHub": "1.1.1",
- "Microsoft.SourceLink.GitLab": "1.1.1"
- }
- },
- "Microsoft.CodeAnalysis.BannedApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.3, )",
- "resolved": "3.3.3",
- "contentHash": "vvz3XCHVrd/Ks4xPoutLmL/T2+8JcOk/OMs3ngwQqnzokQCGEDsY+WjK/txCsDWU29sX3fGzH/FnYwNV93O1mA=="
- },
- "Microsoft.CodeAnalysis.NetAnalyzers": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "cjG06LMeOADNUeCUaklOfVgrnVkLy80H5PVll4QHDUXv+C+6G9rHczrNdWjfb3xKv3Ts9s4UsP6J2ZWe52Gz4Q=="
- },
- "Microsoft.Extensions.Logging.Abstractions": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies": {
- "type": "Direct",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
- "dependencies": {
- "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
- }
- },
- "Microsoft.SourceLink.GitHub": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Nerdbank.GitVersioning": {
- "type": "Direct",
- "requested": "[3.5.113, )",
- "resolved": "3.5.113",
- "contentHash": "4fBSMkqhi410qlkjPm+Mxfk8iO3C7dmgdVS7ljsfVO21WEzZCHP1VCOqB6rlOPfPidR/oxX+/Do/I7meCAz+Jg=="
- },
- "StyleCop.Analyzers": {
- "type": "Direct",
- "requested": "[1.2.0-beta.435, )",
- "resolved": "1.2.0-beta.435",
- "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
- "dependencies": {
- "StyleCop.Analyzers.Unstable": "1.2.0.435"
- }
- },
- "System.Memory": {
- "type": "Direct",
- "requested": "[4.5.5, )",
- "resolved": "4.5.5",
- "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
- },
- "System.Threading.Tasks.Dataflow": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
- },
- "Grpc.Core.Api": {
- "type": "Transitive",
- "resolved": "2.46.3",
- "contentHash": "uy1oe5baVa4V+C8ZyMiA8xYdNIx5A3PiacQL0f1zWDjF2z64Cb1MMXXRTs3GX+jeKpoK/RtOZg8UnJSm2KC/pQ==",
- "dependencies": {
- "System.Memory": "4.5.3"
- }
- },
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q=="
- },
- "Microsoft.NETFramework.ReferenceAssemblies.net461": {
- "type": "Transitive",
- "resolved": "1.0.3",
- "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
- },
- "Microsoft.SourceLink.AzureRepos.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "qB5urvw9LO2bG3eVAkuL+2ughxz2rR7aYgm2iyrB8Rlk9cp2ndvGRCvehk3rNIhRuNtQaeKwctOl1KvWiklv5w==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Bitbucket.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "cDzxXwlyWpLWaH0em4Idj0H3AmVo3L/6xRXKssYemx+7W52iNskj/SQ4FOmfCb8YQt39otTDNMveCZzYtMoucQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg=="
- },
- "Microsoft.SourceLink.GitLab": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "tvsg47DDLqqedlPeYVE2lmiTpND8F0hkrealQ5hYltSmvruy/Gr5nHAKSsjyw5L3NeM/HLMI5ORv7on/M4qyZw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "StyleCop.Analyzers.Unstable": {
- "type": "Transitive",
- "resolved": "1.2.0.435",
- "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
- },
- "crc32c.net": {
- "type": "Project"
- },
- "geothermalresearchinstitute.grpc": {
- "type": "Project",
- "dependencies": {
- "Google.Protobuf": "[3.21.6, )",
- "Grpc": "[2.46.3, )"
- }
- },
- "Google.Protobuf": {
- "type": "CentralTransitive",
- "requested": "[3.21.6, )",
- "resolved": "3.21.6",
- "contentHash": "HSYHFnfuTu/O4Ijy0mCW9zxLI8MJfCZJ10dk3JGPrkLaRR4LsiPKzZrrnapf2G0tP2yRMkHCl+2LKLTXqGBn2A=="
- },
- "Grpc": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "79TsAcLBVl5J7AmtnV+GmgkhWlpK3D9JYJDhYxZGO0DKukbyrRxxcbaFlRZ84WGwTAW8LezrInUYgfiJi3zGVg==",
- "dependencies": {
- "Grpc.Core": "2.46.3"
- }
- },
- "Grpc.Core": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "lu7KP7BVWdvFXWbn/IFYHBQCpMohJwbLM1aL+nu2C0pY2CdS0idaUNAJNC2nZ60fXfqoxnSiERrIU6rC474oTw==",
- "dependencies": {
- "Grpc.Core.Api": "2.46.3",
- "System.Memory": "4.5.3"
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/FakeDevicesHostedService.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/FakeDevicesHostedService.cs
deleted file mode 100644
index c056a8b2..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/FakeDevicesHostedService.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using GeothermalResearchInstitute.FakePlcV2;
-using GeothermalResearchInstitute.ServerConsole.Options;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Options;
-
-namespace GeothermalResearchInstitute.ServerConsole
-{
- [SuppressMessage("Microsoft.Performance", "CA1812", Justification = "Instantiated with reflection.")]
- internal class FakeDevicesHostedService : IHostedService, IDisposable
- {
- private readonly IOptions coreOptions;
- private readonly FakePlc[] fakePlcList;
- private bool disposedValue = false;
-
- public FakeDevicesHostedService(
- IOptions coreOptions,
- IOptions deviceOptions)
- {
- this.coreOptions = coreOptions;
- this.fakePlcList = deviceOptions.Value.Devices
- .Select(d => new FakePlc(d.ComputeIdBinary()))
- .Take(coreOptions.Value.MaxFakeDeviceNum)
- .ToArray();
- }
-
- public async Task StartAsync(CancellationToken cancellationToken)
- {
- int port = this.coreOptions.Value.TcpPort;
- foreach (FakePlc plc in this.fakePlcList)
- {
- await plc.StartAsync(IPAddress.Loopback, port).ConfigureAwait(false);
- }
- }
-
- public async Task StopAsync(CancellationToken cancellationToken)
- {
- foreach (FakePlc plc in this.fakePlcList)
- {
- await plc.StopAsync().ConfigureAwait(false);
- }
- }
-
- public void Dispose()
- {
- this.Dispose(true);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposedValue)
- {
- if (disposing)
- {
- foreach (FakePlc plc in this.fakePlcList)
- {
- plc.StopAsync().ConfigureAwait(false).GetAwaiter().GetResult();
- plc.Dispose();
- }
- }
-
- this.disposedValue = true;
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GeothermalResearchInstitute.ServerConsole.csproj b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GeothermalResearchInstitute.ServerConsole.csproj
deleted file mode 100644
index 9723a7ad..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GeothermalResearchInstitute.ServerConsole.csproj
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
-
-
- Exe
- $(CurrentTargetFramework)
-
- win-x64
- true
- False
- False
- False
-
- $(BaseArtifactsPath)\GeothermalResearchInstitute.ServerConsole
- $(DefaultArtifactsFileMatch) *.ini *.sqlite
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PreserveNewest
- true
-
-
- PreserveNewest
- true
-
-
-
-
-
-
-
-
-
- PreserveNewest
- true
-
-
- PreserveNewest
- true
-
-
-
-
-
-
- Always
- true
-
-
-
-
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GrpcHostedService.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GrpcHostedService.cs
deleted file mode 100644
index bdf6fc7c..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GrpcHostedService.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Grpc.Core;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.ServerConsole
-{
- public class GrpcHostedService : IHostedService
- {
- private readonly ILogger logger;
- private readonly Server server;
-
- public GrpcHostedService(ILogger logger, Server server)
- {
- this.logger = logger;
- this.server = server;
- }
-
- public Task StartAsync(CancellationToken cancellationToken)
- {
- if (cancellationToken.IsCancellationRequested)
- {
- return Task.FromCanceled(cancellationToken);
- }
-
- this.server.Start();
- if (this.logger.IsEnabled(LogLevel.Information))
- {
- this.logger.LogInformation(
- "gRPC services are listening on {0}",
- string.Join(",", this.server.Ports.Select(p => $"{p.Host}:{p.BoundPort}")));
- }
-
- return Task.CompletedTask;
- }
-
- public Task StopAsync(CancellationToken cancellationToken)
- {
- this.logger.LogInformation("Killing gRPC server...");
- return this.server.KillAsync();
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GrpcServices/DeviceServiceImpl.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GrpcServices/DeviceServiceImpl.cs
deleted file mode 100644
index 8c9b969b..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/GrpcServices/DeviceServiceImpl.cs
+++ /dev/null
@@ -1,562 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using GeothermalResearchInstitute.PlcV2;
-using GeothermalResearchInstitute.ServerConsole.Models;
-using GeothermalResearchInstitute.ServerConsole.Options;
-using GeothermalResearchInstitute.ServerConsole.Utils;
-using GeothermalResearchInstitute.v2;
-using Google.Protobuf;
-using Grpc.Core;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using GrpcAlarm = GeothermalResearchInstitute.v2.Alarm;
-using GrpcAlarmChange = GeothermalResearchInstitute.v2.AlarmChange;
-using GrpcMetric = GeothermalResearchInstitute.v2.Metric;
-using ModelAlarm = GeothermalResearchInstitute.ServerConsole.Models.Alarm;
-using ModelAlarmChange = GeothermalResearchInstitute.ServerConsole.Models.AlarmChange;
-using ModelMetric = GeothermalResearchInstitute.ServerConsole.Models.Metric;
-
-namespace GeothermalResearchInstitute.ServerConsole.GrpcServices
-{
- [System.Diagnostics.CodeAnalysis.SuppressMessage(
- "Design", "CA1062:验证公共方法的参数", Justification = "由Grpc框架保证.")]
- public class DeviceServiceImpl : DeviceService.DeviceServiceBase, IDisposable
- {
- private readonly ILogger logger;
- private readonly IServiceProvider serviceProvider;
- private readonly PlcManager plcManager;
- private readonly Timer askAlarmTimer;
- private readonly Timer askMetricTimer;
- private bool disposedValue = false;
-
- public DeviceServiceImpl(
- ILogger logger,
- IOptions tasksOptions,
- IServiceProvider serviceProvider,
- PlcManager plcManager)
- {
- this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
- this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
- this.plcManager = plcManager ?? throw new ArgumentNullException(nameof(plcManager));
- this.askAlarmTimer = new Timer(
- this.AskPersistDeviceAlarm,
- null,
- TimeSpan.FromMilliseconds(tasksOptions.Value.CollectAlarmIntervalMillis),
- TimeSpan.FromMilliseconds(tasksOptions.Value.CollectAlarmIntervalMillis));
- this.askMetricTimer = new Timer(
- this.AskPersistDeviceMetric,
- null,
- TimeSpan.FromMilliseconds(tasksOptions.Value.CollectMetricIntervalMillis),
- TimeSpan.FromMilliseconds(tasksOptions.Value.CollectMetricIntervalMillis));
-
- IOptionsSnapshot coreOptions =
- this.serviceProvider.GetRequiredService>();
- this.logger.LogInformation("CoreOptions: {0}", coreOptions.Value);
- this.logger.LogInformation("TasksOptions: {0}", tasksOptions.Value);
-
- if (this.logger.IsEnabled(LogLevel.Debug))
- {
- IOptionsSnapshot deviceOptions = this.serviceProvider.GetRequiredService>();
- foreach (DeviceOptionsEntry d in deviceOptions.Value.Devices)
- {
- this.logger.LogDebug(
- "{0}={1}",
- string.Join(string.Empty, d.ComputeIdBinary().Select(b => b.ToString("X2", CultureInfo.InvariantCulture))),
- d.Name);
- }
-
- IOptionsSnapshot authenticationOptions = this.serviceProvider.GetRequiredService>();
- foreach (Credential c in authenticationOptions.Value.Credentials)
- {
- this.logger.LogDebug(c.ToString());
- }
- }
- }
-
- ~DeviceServiceImpl()
- {
- this.Dispose(false);
- }
-
- public void Dispose()
- {
- this.Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- public override Task Authenticate(
- AuthenticateRequest request, ServerCallContext context)
- {
- IOptionsSnapshot authenticationOptions = this.serviceProvider.GetRequiredService>();
- Credential credential = authenticationOptions.Value.Credentials.SingleOrDefault(
- c => string.Equals(c.Username, request.Username, StringComparison.Ordinal) &&
- string.Equals(c.Password, request.Password, StringComparison.Ordinal));
- if (credential == null)
- {
- throw new RpcException(new Status(StatusCode.Unauthenticated, "Invalid username or password."));
- }
- else
- {
- return Task.FromResult(new AuthenticateResponse()
- {
- Nickname = credential.Nickname,
- Role = credential.Role,
- });
- }
- }
-
- public override Task Test(TestRequest request, ServerCallContext context)
- {
- throw new RpcException(new Status(StatusCode.Unimplemented, "Not supported."));
- }
-
- public override Task Connect(ConnectRequest request, ServerCallContext context)
- {
- throw new RpcException(new Status(StatusCode.Unimplemented, "Not supported."));
- }
-
- public override Task ListDevices(ListDevicesRequest request, ServerCallContext context)
- {
- IOptionsSnapshot deviceOptions =
- this.serviceProvider.GetRequiredService>();
-
- var response = new ListDevicesResponse();
- response.Devices.Add(
- from d in deviceOptions.Value.Devices
- let id = ByteString.CopyFrom(d.ComputeIdBinary())
- join e in this.plcManager.PlcDictionary.AsEnumerable()
- on id equals e.Key into g
- from e in g.DefaultIfEmpty()
- select new Device
- {
- Id = id,
- Name = d.Name,
- Ipv4Address = e.Value == null
- ? ByteString.Empty
- : ByteString.CopyFrom(((IPEndPoint)e.Value.RemoteEndPoint).Address.GetAddressBytes()),
- Status = e.Value == null
- ? DeviceStatus.Disconnected
- : DeviceStatus.Healthy,
- });
-
- return Task.FromResult(response);
- }
-
- public override Task GetMetric(GetMetricRequest request, ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.GetMetricAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task GetSwitch(GetSwitchRequest request, ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.GetSwitchAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task UpdateSwitch(UpdateSwitchRequest request, ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.UpdateSwitchAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task ListMetrics(ListMetricsRequest request, ServerCallContext context)
- {
- string id = BitConverter.ToString(request.DeviceId.ToByteArray());
-
- DateTimeOffset endDateTime;
- if (string.IsNullOrEmpty(request.PageToken))
- {
- endDateTime = request.EndTime?.ToDateTimeOffset() ?? DateTimeOffset.UtcNow;
- }
- else
- {
- endDateTime = DateTimeOffset.Parse(request.PageToken, CultureInfo.InvariantCulture);
- }
-
- endDateTime = endDateTime.ToUniversalTime();
- DateTimeOffset? startDateTime = request.StartTime?.ToDateTimeOffset().ToUniversalTime();
-
- var response = new ListMetricsResponse();
- using (BjdireContext db = this.serviceProvider.GetRequiredService())
- {
- var metrics = (from m in db.Metrics
- where m.DeviceId == id
- && (startDateTime == null || startDateTime <= m.Timestamp)
- && m.Timestamp <= endDateTime
- orderby m.Timestamp descending
- select m)
- .Take(request.PageSize)
- .ToList();
- response.Metrics.AddRange(metrics.Select(metric =>
- {
- var m = new GrpcMetric();
- m.AssignFrom(metric);
- return m;
- }));
-
- if (metrics.Count == request.PageSize && metrics.Last().Timestamp > startDateTime)
- {
- response.NextPageToken = metrics.Last().Timestamp
- .ToUniversalTime()
- .ToString(CultureInfo.InvariantCulture);
- }
- }
-
- return Task.FromResult(response);
- }
-
- public override Task GetWorkingMode(GetWorkingModeRequest request, ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.GetWorkingModeAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task UpdateWorkingMode(
- UpdateWorkingModeRequest request,
- ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.UpdateWorkingModeAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task GetRunningParameter(
- GetRunningParameterRequest request,
- ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.GetRunningParameterAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task UpdateRunningParameter(
- UpdateRunningParameterRequest request,
- ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.UpdateRunningParameterAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task GetAlarm(GetAlarmRequest request, ServerCallContext context)
- {
- return this.Invoke(
- (client, request, deadline) => client.GetAlarmAsync(request, deadline),
- request.DeviceId,
- request,
- context);
- }
-
- public override Task ListAlarmChanges(
- ListAlarmChangesRequest request,
- ServerCallContext context)
- {
- string id = BitConverter.ToString(request.DeviceId.ToByteArray());
-
- DateTimeOffset endDateTime;
- if (string.IsNullOrEmpty(request.PageToken))
- {
- endDateTime = request.EndTime?.ToDateTimeOffset() ?? DateTimeOffset.UtcNow;
- }
- else
- {
- endDateTime = DateTimeOffset.Parse(request.PageToken, CultureInfo.InvariantCulture);
- }
-
- endDateTime = endDateTime.ToUniversalTime();
- DateTimeOffset? startDateTime = request.StartTime?.ToDateTimeOffset().ToUniversalTime();
-
- var response = new ListAlarmChangesResponse();
- using (BjdireContext db = this.serviceProvider.GetRequiredService())
- {
- var alarmChanges = (from m in db.AlarmChanges
- where m.DeviceId == id
- && (startDateTime == null || startDateTime <= m.Timestamp)
- && m.Timestamp <= endDateTime
- orderby m.Timestamp descending
- select m)
- .Take(request.PageSize)
- .ToList();
- response.AlarmChanges.AddRange(alarmChanges.Select(alarmChange =>
- {
- var m = new GrpcAlarmChange();
- m.AssignFrom(alarmChange);
- return m;
- }));
-
- if (alarmChanges.Count == request.PageSize && alarmChanges.Last().Timestamp > startDateTime)
- {
- response.NextPageToken = alarmChanges.Last().Timestamp
- .ToUniversalTime()
- .ToString(CultureInfo.InvariantCulture);
- }
- }
-
- return Task.FromResult(response);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposedValue)
- {
- if (disposing)
- {
- this.askAlarmTimer.Dispose();
- this.askMetricTimer.Dispose();
- }
-
- this.disposedValue = true;
- }
- }
-
- private static IEnumerable ComputeAlarmChanges(
- string deviceId,
- ModelAlarm lastKnownAlarm,
- ModelAlarm currentAlarm)
- {
- if (lastKnownAlarm.LowFlowRate != currentAlarm.LowFlowRate)
- {
- yield return new ModelAlarmChange
- {
- DeviceId = deviceId,
- Timestamp = currentAlarm.Timestamp,
- Type = AlarmType.LowFlowRate,
- Direction = currentAlarm.LowFlowRate
- ? AlarmChangeDirection.Appearance
- : AlarmChangeDirection.Disappearance,
- };
- }
-
- if (lastKnownAlarm.HighHeaterPressure != currentAlarm.HighHeaterPressure)
- {
- yield return new ModelAlarmChange
- {
- DeviceId = deviceId,
- Timestamp = currentAlarm.Timestamp,
- Type = AlarmType.HighHeaterPressure,
- Direction = currentAlarm.HighHeaterPressure
- ? AlarmChangeDirection.Appearance
- : AlarmChangeDirection.Disappearance,
- };
- }
-
- if (lastKnownAlarm.LowHeaterPressure != currentAlarm.LowHeaterPressure)
- {
- yield return new ModelAlarmChange
- {
- DeviceId = deviceId,
- Timestamp = currentAlarm.Timestamp,
- Type = AlarmType.LowHeaterPressure,
- Direction = currentAlarm.LowHeaterPressure
- ? AlarmChangeDirection.Appearance
- : AlarmChangeDirection.Disappearance,
- };
- }
-
- if (lastKnownAlarm.NoPower != currentAlarm.NoPower)
- {
- yield return new ModelAlarmChange
- {
- DeviceId = deviceId,
- Timestamp = currentAlarm.Timestamp,
- Type = AlarmType.NoPower,
- Direction = currentAlarm.NoPower
- ? AlarmChangeDirection.Appearance
- : AlarmChangeDirection.Disappearance,
- };
- }
-
- if (lastKnownAlarm.HeaterOverloadedBroken != currentAlarm.HeaterOverloadedBroken)
- {
- yield return new ModelAlarmChange
- {
- DeviceId = deviceId,
- Timestamp = currentAlarm.Timestamp,
- Type = AlarmType.HeaterOverloadedBroken,
- Direction = currentAlarm.HeaterOverloadedBroken
- ? AlarmChangeDirection.Appearance
- : AlarmChangeDirection.Disappearance,
- };
- }
-
- if (lastKnownAlarm.ElectricalHeaterBroken != currentAlarm.ElectricalHeaterBroken)
- {
- yield return new ModelAlarmChange
- {
- DeviceId = deviceId,
- Timestamp = currentAlarm.Timestamp,
- Type = AlarmType.ElectricalHeaterBroken,
- Direction = currentAlarm.ElectricalHeaterBroken
- ? AlarmChangeDirection.Appearance
- : AlarmChangeDirection.Disappearance,
- };
- }
- }
-
- private Task Invoke(
- Func> stub,
- ByteString deviceId,
- TRequest request,
- ServerCallContext context)
- {
- if (deviceId.IsEmpty)
- {
- throw new RpcException(new Status(StatusCode.InvalidArgument, "Must specify device_id."));
- }
-
- if (this.plcManager.PlcDictionary.TryGetValue(deviceId, out PlcClient client))
- {
- return stub.Invoke(client, request, context.Deadline);
- }
- else
- {
- throw new RpcException(new Status(StatusCode.NotFound, "Device is currently offline."));
- }
- }
-
- private async void AskPersistDeviceAlarm(object state)
- {
- IOptionsSnapshot coreOptions =
- this.serviceProvider.GetRequiredService>();
- IOptionsSnapshot deviceOptions =
- this.serviceProvider.GetRequiredService>();
-
- using BjdireContext db = this.serviceProvider.GetRequiredService();
-
- foreach (DeviceOptionsEntry d in deviceOptions.Value.Devices)
- {
- try
- {
- byte[] id = d.ComputeIdBinary();
- string deviceId = BitConverter.ToString(id);
- if (this.plcManager.PlcDictionary.TryGetValue(ByteString.CopyFrom(id), out PlcClient client))
- {
- this.logger.LogInformation("Ask alarm for {0}({1})", d.Id, d.Name);
-
- GrpcAlarm alarm = await client
- .GetAlarmAsync(
- new GetAlarmRequest(),
- DateTime.UtcNow.AddMilliseconds(
- coreOptions.Value.DefaultReadTimeoutMillis))
- .ConfigureAwait(false);
-
- var m = new ModelAlarm
- {
- DeviceId = deviceId,
- };
- alarm.AssignTo(m);
-
- ModelAlarm lastKnownAlarmInfo = (
- from mm in db.Alarms
- where mm.DeviceId == deviceId
- orderby mm.Timestamp descending
- select mm)
- .FirstOrDefault();
-
- if (lastKnownAlarmInfo == null)
- {
- lastKnownAlarmInfo = new ModelAlarm();
- }
-
- db.AlarmChanges.AddRange(ComputeAlarmChanges(deviceId, lastKnownAlarmInfo, m));
-
- db.Alarms.Add(m);
- }
- else
- {
- this.logger.LogWarning(
- "Failed to ask alarm for {0}({1}), currently offline.",
- d.Id,
- d.Name);
- }
- }
- catch (RpcException e)
- {
- this.logger.LogWarning(e, "Failed to ask alarm for {0}({1})", d.Id, d.Name);
- }
- }
-
- db.SaveChanges();
- }
-
- private async void AskPersistDeviceMetric(object state)
- {
- IOptionsSnapshot coreOptions =
- this.serviceProvider.GetRequiredService>();
- IOptionsSnapshot deviceOptions =
- this.serviceProvider.GetRequiredService>();
-
- using BjdireContext db = this.serviceProvider.GetRequiredService();
-
- foreach (DeviceOptionsEntry d in deviceOptions.Value.Devices)
- {
- try
- {
- byte[] id = d.ComputeIdBinary();
- if (this.plcManager.PlcDictionary.TryGetValue(ByteString.CopyFrom(id), out PlcClient client))
- {
- this.logger.LogInformation("Ask metric for {0}({1})", d.Id, d.Name);
-
- GrpcMetric metric = await client
- .GetMetricAsync(
- new GetMetricRequest(),
- DateTime.UtcNow.AddMilliseconds(
- coreOptions.Value.DefaultReadTimeoutMillis))
- .ConfigureAwait(false);
-
- var m = new ModelMetric
- {
- DeviceId = BitConverter.ToString(id),
- };
- metric.AssignTo(m);
-
- db.Metrics.Add(m);
- }
- else
- {
- this.logger.LogWarning(
- "Failed to ask metric for {0}({1}), currently offline.",
- d.Id,
- d.Name);
- }
- }
- catch (RpcException e)
- {
- this.logger.LogWarning(e, "Failed to ask metric for {0}({1})", d.Id, d.Name);
- }
- }
-
- db.SaveChanges();
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191214052037_InitialCreate.Designer.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191214052037_InitialCreate.Designer.cs
deleted file mode 100644
index 744990ed..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191214052037_InitialCreate.Designer.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-using GeothermalResearchInstitute.ServerConsole.Models;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-namespace GeothermalResearchInstitute.ServerConsole.Migrations
-{
- [DbContext(typeof(BjdireContext))]
- [Migration("20191214052037_InitialCreate")]
- partial class InitialCreate
- {
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "3.1.0");
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.Alarm", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("ElectricalHeaterBroken")
- .HasColumnType("INTEGER");
-
- b.Property("HeaterOverloadedBroken")
- .HasColumnType("INTEGER");
-
- b.Property("HighHeaterPressure")
- .HasColumnType("INTEGER");
-
- b.Property("LowFlowRate")
- .HasColumnType("INTEGER");
-
- b.Property("LowHeaterPressure")
- .HasColumnType("INTEGER");
-
- b.Property("NoPower")
- .HasColumnType("INTEGER");
-
- b.HasKey("DeviceId", "Timestamp");
-
- b.ToTable("Alarms");
- });
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.AlarmChange", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("Type")
- .HasColumnType("INTEGER");
-
- b.Property("Direction")
- .HasColumnType("INTEGER");
-
- b.HasKey("DeviceId", "Timestamp", "Type");
-
- b.ToTable("AlarmChanges");
- });
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.Metric", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("EnvironmentCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("HeaterOutputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("HeaterPowerKilowatt")
- .HasColumnType("REAL");
-
- b.Property("InputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("InputWaterPressureMeter")
- .HasColumnType("REAL");
-
- b.Property("OutputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("OutputWaterPressureMeter")
- .HasColumnType("REAL");
-
- b.Property("WaterPumpFlowRateCubicMeterPerHour")
- .HasColumnType("REAL");
-
- b.HasKey("DeviceId", "Timestamp");
-
- b.ToTable("Metrics");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191214052037_InitialCreate.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191214052037_InitialCreate.cs
deleted file mode 100644
index f2f37c3d..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191214052037_InitialCreate.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace GeothermalResearchInstitute.ServerConsole.Migrations
-{
- public partial class InitialCreate : Migration
- {
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- if (migrationBuilder is null)
- {
- throw new System.ArgumentNullException(nameof(migrationBuilder));
- }
-
- migrationBuilder.CreateTable(
- name: "AlarmChanges",
- columns: table => new
- {
- DeviceId = table.Column(nullable: false),
- Timestamp = table.Column(nullable: false),
- Type = table.Column(nullable: false),
- Direction = table.Column(nullable: false),
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_AlarmChanges", x => new { x.DeviceId, x.Timestamp, x.Type });
- });
-
- migrationBuilder.CreateTable(
- name: "Alarms",
- columns: table => new
- {
- DeviceId = table.Column(nullable: false),
- Timestamp = table.Column(nullable: false),
- LowFlowRate = table.Column(nullable: false),
- HighHeaterPressure = table.Column(nullable: false),
- LowHeaterPressure = table.Column(nullable: false),
- NoPower = table.Column(nullable: false),
- HeaterOverloadedBroken = table.Column(nullable: false),
- ElectricalHeaterBroken = table.Column(nullable: false),
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Alarms", x => new { x.DeviceId, x.Timestamp });
- });
-
- migrationBuilder.CreateTable(
- name: "Metrics",
- columns: table => new
- {
- DeviceId = table.Column(nullable: false),
- Timestamp = table.Column(nullable: false),
- OutputWaterCelsiusDegree = table.Column(nullable: false),
- InputWaterCelsiusDegree = table.Column(nullable: false),
- HeaterOutputWaterCelsiusDegree = table.Column(nullable: false),
- EnvironmentCelsiusDegree = table.Column(nullable: false),
- OutputWaterPressureMeter = table.Column(nullable: false),
- InputWaterPressureMeter = table.Column(nullable: false),
- HeaterPowerKilowatt = table.Column(nullable: false),
- WaterPumpFlowRateCubicMeterPerHour = table.Column(nullable: false),
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Metrics", x => new { x.DeviceId, x.Timestamp });
- });
- }
-
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- if (migrationBuilder is null)
- {
- throw new System.ArgumentNullException(nameof(migrationBuilder));
- }
-
- migrationBuilder.DropTable(
- name: "AlarmChanges");
-
- migrationBuilder.DropTable(
- name: "Alarms");
-
- migrationBuilder.DropTable(
- name: "Metrics");
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191215142314_Add4MoreAlarmTypes.Designer.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191215142314_Add4MoreAlarmTypes.Designer.cs
deleted file mode 100644
index 323dbf66..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191215142314_Add4MoreAlarmTypes.Designer.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-//
-using GeothermalResearchInstitute.ServerConsole.Models;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-namespace GeothermalResearchInstitute.ServerConsole.Migrations
-{
- [DbContext(typeof(BjdireContext))]
- [Migration("20191215142314_Add4MoreAlarmTypes")]
- partial class Add4MoreAlarmTypes
- {
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "3.1.0");
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.Alarm", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("ElectricalHeaterBroken")
- .HasColumnType("INTEGER");
-
- b.Property("EmergencyStopped")
- .HasColumnType("INTEGER");
-
- b.Property("HeaterOverloadedBroken")
- .HasColumnType("INTEGER");
-
- b.Property("HighHeaterPressure")
- .HasColumnType("INTEGER");
-
- b.Property("HighVoltage")
- .HasColumnType("INTEGER");
-
- b.Property("LowFlowRate")
- .HasColumnType("INTEGER");
-
- b.Property("LowHeaterPressure")
- .HasColumnType("INTEGER");
-
- b.Property("LowVoltage")
- .HasColumnType("INTEGER");
-
- b.Property("NoPower")
- .HasColumnType("INTEGER");
-
- b.Property("NoWater")
- .HasColumnType("INTEGER");
-
- b.HasKey("DeviceId", "Timestamp");
-
- b.ToTable("Alarms");
- });
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.AlarmChange", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("Type")
- .HasColumnType("INTEGER");
-
- b.Property("Direction")
- .HasColumnType("INTEGER");
-
- b.HasKey("DeviceId", "Timestamp", "Type");
-
- b.ToTable("AlarmChanges");
- });
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.Metric", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("EnvironmentCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("HeaterOutputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("HeaterPowerKilowatt")
- .HasColumnType("REAL");
-
- b.Property("InputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("InputWaterPressureMeter")
- .HasColumnType("REAL");
-
- b.Property("OutputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("OutputWaterPressureMeter")
- .HasColumnType("REAL");
-
- b.Property("WaterPumpFlowRateCubicMeterPerHour")
- .HasColumnType("REAL");
-
- b.HasKey("DeviceId", "Timestamp");
-
- b.ToTable("Metrics");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191215142314_Add4MoreAlarmTypes.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191215142314_Add4MoreAlarmTypes.cs
deleted file mode 100644
index 232ba886..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/20191215142314_Add4MoreAlarmTypes.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace GeothermalResearchInstitute.ServerConsole.Migrations
-{
- public partial class Add4MoreAlarmTypes : Migration
- {
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- if (migrationBuilder is null)
- {
- throw new System.ArgumentNullException(nameof(migrationBuilder));
- }
-
- migrationBuilder.AddColumn(
- name: "EmergencyStopped",
- table: "Alarms",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "HighVoltage",
- table: "Alarms",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "LowVoltage",
- table: "Alarms",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "NoWater",
- table: "Alarms",
- nullable: false,
- defaultValue: false);
- }
-
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- if (migrationBuilder is null)
- {
- throw new System.ArgumentNullException(nameof(migrationBuilder));
- }
-
- migrationBuilder.DropColumn(
- name: "EmergencyStopped",
- table: "Alarms");
-
- migrationBuilder.DropColumn(
- name: "HighVoltage",
- table: "Alarms");
-
- migrationBuilder.DropColumn(
- name: "LowVoltage",
- table: "Alarms");
-
- migrationBuilder.DropColumn(
- name: "NoWater",
- table: "Alarms");
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/BjdireContextModelSnapshot.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/BjdireContextModelSnapshot.cs
deleted file mode 100644
index 8c146bbc..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Migrations/BjdireContextModelSnapshot.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-//
-using GeothermalResearchInstitute.ServerConsole.Models;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-namespace GeothermalResearchInstitute.ServerConsole.Migrations
-{
- [DbContext(typeof(BjdireContext))]
- partial class BjdireContextModelSnapshot : ModelSnapshot
- {
- protected override void BuildModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "3.1.0");
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.Alarm", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("ElectricalHeaterBroken")
- .HasColumnType("INTEGER");
-
- b.Property("EmergencyStopped")
- .HasColumnType("INTEGER");
-
- b.Property("HeaterOverloadedBroken")
- .HasColumnType("INTEGER");
-
- b.Property("HighHeaterPressure")
- .HasColumnType("INTEGER");
-
- b.Property("HighVoltage")
- .HasColumnType("INTEGER");
-
- b.Property("LowFlowRate")
- .HasColumnType("INTEGER");
-
- b.Property("LowHeaterPressure")
- .HasColumnType("INTEGER");
-
- b.Property("LowVoltage")
- .HasColumnType("INTEGER");
-
- b.Property("NoPower")
- .HasColumnType("INTEGER");
-
- b.Property("NoWater")
- .HasColumnType("INTEGER");
-
- b.HasKey("DeviceId", "Timestamp");
-
- b.ToTable("Alarms");
- });
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.AlarmChange", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("Type")
- .HasColumnType("INTEGER");
-
- b.Property("Direction")
- .HasColumnType("INTEGER");
-
- b.HasKey("DeviceId", "Timestamp", "Type");
-
- b.ToTable("AlarmChanges");
- });
-
- modelBuilder.Entity("GeothermalResearchInstitute.ServerConsole.Models.Metric", b =>
- {
- b.Property("DeviceId")
- .HasColumnType("TEXT");
-
- b.Property("Timestamp")
- .HasColumnType("INTEGER");
-
- b.Property("EnvironmentCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("HeaterOutputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("HeaterPowerKilowatt")
- .HasColumnType("REAL");
-
- b.Property("InputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("InputWaterPressureMeter")
- .HasColumnType("REAL");
-
- b.Property("OutputWaterCelsiusDegree")
- .HasColumnType("REAL");
-
- b.Property("OutputWaterPressureMeter")
- .HasColumnType("REAL");
-
- b.Property("WaterPumpFlowRateCubicMeterPerHour")
- .HasColumnType("REAL");
-
- b.HasKey("DeviceId", "Timestamp");
-
- b.ToTable("Metrics");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/Alarm.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/Alarm.cs
deleted file mode 100644
index 37effab9..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/Alarm.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-
-namespace GeothermalResearchInstitute.ServerConsole.Models
-{
- public class Alarm
- {
- public string DeviceId { get; set; }
-
- public DateTimeOffset Timestamp { get; set; }
-
- // 流量低
- public bool LowFlowRate { get; set; }
-
- // 热泵压力高
- public bool HighHeaterPressure { get; set; }
-
- // 热泵压力低
- public bool LowHeaterPressure { get; set; }
-
- // 电源断相或相序错
- public bool NoPower { get; set; }
-
- // 热泵过载故障(热继电器)
- public bool HeaterOverloadedBroken { get; set; }
-
- // 电加热器故障
- public bool ElectricalHeaterBroken { get; set; }
-
- // 系统缺水故障
- public bool NoWater { get; set; }
-
- // 电源电压过高
- public bool HighVoltage { get; set; }
-
- // 电源电压过低
- public bool LowVoltage { get; set; }
-
- // 急停开关被按下
- public bool EmergencyStopped { get; set; }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/AlarmChange.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/AlarmChange.cs
deleted file mode 100644
index 8a7c357b..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/AlarmChange.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using GeothermalResearchInstitute.v2;
-
-namespace GeothermalResearchInstitute.ServerConsole.Models
-{
- public class AlarmChange
- {
- public string DeviceId { get; set; }
-
- public DateTimeOffset Timestamp { get; set; }
-
- public AlarmType Type { get; set; }
-
- public AlarmChangeDirection Direction { get; set; }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/BjdireContext.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/BjdireContext.cs
deleted file mode 100644
index a0d713fe..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/BjdireContext.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using GeothermalResearchInstitute.v2;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-namespace GeothermalResearchInstitute.ServerConsole.Models
-{
- public class BjdireContext : DbContext
- {
- public BjdireContext(DbContextOptions options)
- : base(options)
- {
- }
-
- public DbSet Alarms { get; set; }
-
- public DbSet AlarmChanges { get; set; }
-
- public DbSet Metrics { get; set; }
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- if (modelBuilder is null)
- {
- throw new ArgumentNullException(nameof(modelBuilder));
- }
-
- modelBuilder.Entity()
- .HasKey(m => new { m.DeviceId, m.Timestamp });
- modelBuilder.Entity()
- .HasKey(m => new { m.DeviceId, m.Timestamp, m.Type });
- modelBuilder.Entity()
- .Property(m => m.Type)
- .HasConversion(new EnumToNumberConverter());
- modelBuilder.Entity()
- .Property(m => m.Direction)
- .HasConversion(new EnumToNumberConverter());
- modelBuilder.Entity()
- .HasKey(m => new { m.DeviceId, m.Timestamp });
-
- if (this.Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqlite")
- {
- // SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations
- // here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations
- // To work around this, when the SQLite database provider is used, all model properties of type DateTimeOffset
- // use the DateTimeOffsetToBinaryConverter
- // Based on: https://github.com/aspnet/EntityFrameworkCore/issues/10784#issuecomment-415769754
- // This only supports millisecond precision, but should be sufficient for most use cases.
- foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
- {
- IEnumerable properties = entityType.ClrType.GetProperties()
- .Where(p => p.PropertyType == typeof(DateTimeOffset));
- foreach (PropertyInfo property in properties)
- {
- modelBuilder
- .Entity(entityType.Name)
- .Property(property.Name)
- .HasConversion(new DateTimeOffsetToBinaryConverter());
- }
- }
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/BjdireContextFactory.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/BjdireContextFactory.cs
deleted file mode 100644
index 11c8a72e..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/BjdireContextFactory.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Design;
-
-namespace GeothermalResearchInstitute.ServerConsole.Models
-{
- public class BjdireContextFactory : IDesignTimeDbContextFactory
- {
- public BjdireContext CreateDbContext(string[] args)
- {
- var builder = new DbContextOptionsBuilder();
- Program.DbContextOptionsBuilderAction.Invoke(builder);
- return new BjdireContext(builder.Options);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/Metric.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/Metric.cs
deleted file mode 100644
index fe4d6fae..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Models/Metric.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-
-namespace GeothermalResearchInstitute.ServerConsole.Models
-{
- public class Metric
- {
- public string DeviceId { get; set; }
-
- public DateTimeOffset Timestamp { get; set; }
-
- // 出水温度
- public float OutputWaterCelsiusDegree { get; set; }
-
- // 回水温度
- public float InputWaterCelsiusDegree { get; set; }
-
- // 加热器出水温度
- public float HeaterOutputWaterCelsiusDegree { get; set; }
-
- // 环境温度
- public float EnvironmentCelsiusDegree { get; set; }
-
- // 出水压力
- public float OutputWaterPressureMeter { get; set; }
-
- // 回水压力
- public float InputWaterPressureMeter { get; set; }
-
- // 加热器加热功率
- public float HeaterPowerKilowatt { get; set; }
-
- // 流量
- public float WaterPumpFlowRateCubicMeterPerHour { get; set; }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/AuthenticationOptions.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/AuthenticationOptions.cs
deleted file mode 100644
index eb07b98f..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/AuthenticationOptions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System.Collections.Generic;
-
-namespace GeothermalResearchInstitute.ServerConsole.Options
-{
- public class AuthenticationOptions
- {
- [System.Diagnostics.CodeAnalysis.SuppressMessage(
- "Usage", "CA2227:集合属性应为只读", Justification = "Sets with reflection.")]
- public ICollection Credentials { get; set; }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/CoreOptions.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/CoreOptions.cs
deleted file mode 100644
index 93a65a29..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/CoreOptions.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System.Text.Json;
-
-namespace GeothermalResearchInstitute.ServerConsole.Options
-{
- public class CoreOptions
- {
- public int GrpcPort { get; set; }
-
- public int TcpPort { get; set; }
-
- public int DefaultReadTimeoutMillis { get; set; }
-
- public int MaxFakeDeviceNum { get; set; }
-
- public override string ToString()
- {
- return JsonSerializer.Serialize(this);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/Credential.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/Credential.cs
deleted file mode 100644
index dd14be0a..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/Credential.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using GeothermalResearchInstitute.v2;
-
-namespace GeothermalResearchInstitute.ServerConsole.Options
-{
- public class Credential
- {
- public string Nickname { get; set; }
-
- public string Username { get; set; }
-
- public string Password { get; set; }
-
- public UserRole Role { get; set; }
-
- public override string ToString()
- {
- return this.Nickname + "(" + this.Username + ":" + this.Role + ")";
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/DeviceOptions.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/DeviceOptions.cs
deleted file mode 100644
index ef61f971..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/DeviceOptions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System.Collections.Generic;
-
-namespace GeothermalResearchInstitute.ServerConsole.Options
-{
- public class DeviceOptions
- {
- [System.Diagnostics.CodeAnalysis.SuppressMessage(
- "Usage", "CA2227:集合属性应为只读", Justification = "Sets with reflection.")]
- public ICollection Devices { get; set; }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/DeviceOptionsEntry.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/DeviceOptionsEntry.cs
deleted file mode 100644
index 5b7f6842..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/DeviceOptionsEntry.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Net.NetworkInformation;
-
-namespace GeothermalResearchInstitute.ServerConsole.Options
-{
- public class DeviceOptionsEntry
- {
- public string Id { get; set; }
-
- public string Name { get; set; }
-
- public byte[] ComputeIdBinary()
- {
- return PhysicalAddress
- .Parse(this.Id
-#if NET48
- .Replace(":", null)
- .Replace("-", null))
-#else
- .Replace(":", null, StringComparison.Ordinal)
- .Replace("-", null, StringComparison.Ordinal))
-#endif
- .GetAddressBytes();
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/TasksOptions.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/TasksOptions.cs
deleted file mode 100644
index 5d80bdea..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Options/TasksOptions.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System.Text.Json;
-
-namespace GeothermalResearchInstitute.ServerConsole.Options
-{
- public class TasksOptions
- {
- public int CollectAlarmIntervalMillis { get; set; }
-
- public int CollectMetricIntervalMillis { get; set; }
-
- public override string ToString()
- {
- return JsonSerializer.Serialize(this);
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/PlcHostedService.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/PlcHostedService.cs
deleted file mode 100644
index b7053dec..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/PlcHostedService.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Hosting;
-
-namespace GeothermalResearchInstitute.ServerConsole
-{
- public class PlcHostedService : IHostedService
- {
- private readonly PlcManager plcManager;
-
- public PlcHostedService(PlcManager plcManager)
- {
- this.plcManager = plcManager ?? throw new ArgumentNullException(nameof(plcManager));
- }
-
- public Task StartAsync(CancellationToken cancellationToken)
- {
- return this.plcManager.StartAsync(cancellationToken);
- }
-
- public Task StopAsync(CancellationToken cancellationToken)
- {
- return this.plcManager.StopAsync();
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/PlcManager.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/PlcManager.cs
deleted file mode 100644
index 5a4df582..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/PlcManager.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Diagnostics.CodeAnalysis;
-using System.Net.Sockets;
-using System.Threading;
-using System.Threading.Tasks;
-using GeothermalResearchInstitute.PlcV2;
-using GeothermalResearchInstitute.v2;
-using Google.Protobuf;
-using Grpc.Core;
-using Microsoft.Extensions.Logging;
-
-namespace GeothermalResearchInstitute.ServerConsole
-{
- [SuppressMessage(
- "Design",
- "CA1001:具有可释放字段的类型应该是可释放的",
- Justification = "Disposed in StopAsync, ensured by framework.")]
- public class PlcManager
- {
- private readonly ILogger logger;
- private readonly PlcServer plcServer;
- private CancellationTokenSource cancellationTokenSource;
- private Task backgroundTask;
-
- public PlcManager(ILogger logger, PlcServer plcServer)
- {
- this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
- this.plcServer = plcServer ?? throw new ArgumentNullException(nameof(plcServer));
- }
-
- public ConcurrentDictionary PlcDictionary { get; } =
- new ConcurrentDictionary();
-
- public Task StartAsync(CancellationToken cancellationToken)
- {
- if (cancellationToken.IsCancellationRequested)
- {
- return Task.FromCanceled(cancellationToken);
- }
-
- this.plcServer.Start();
- this.logger.LogInformation("PLC server is listening on {0}", this.plcServer.LocalEndPoint);
-
- this.PlcDictionary.Clear();
- this.cancellationTokenSource = new CancellationTokenSource();
- this.backgroundTask = Task.Factory.StartNew(
- this.BackgroundTaskEntryPoint,
- this.cancellationTokenSource.Token,
- TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
- TaskScheduler.Default);
-
- return Task.CompletedTask;
- }
-
- public async Task StopAsync()
- {
- this.cancellationTokenSource.Cancel();
- await this.backgroundTask.ConfigureAwait(false);
-
- foreach (ByteString id in this.PlcDictionary.Keys)
- {
- if (this.PlcDictionary.TryRemove(id, out PlcClient client))
- {
- await client.Close().ConfigureAwait(false);
- client.Dispose();
- }
- }
-
- this.plcServer.Stop();
-
- this.cancellationTokenSource.Dispose();
- this.cancellationTokenSource = null;
- this.backgroundTask.Dispose();
- this.backgroundTask = null;
- }
-
- private async void BackgroundTaskEntryPoint()
- {
- while (!this.cancellationTokenSource.IsCancellationRequested)
- {
- PlcClient client = null;
- try
- {
- client = await this.plcServer.AcceptAsync().ConfigureAwait(false);
- this.logger.LogInformation("TCP connection established from {0}", client.RemoteEndPoint);
- }
- catch (SocketException e)
- {
- this.logger.LogError(e, "Failed to TCP accept PLC.");
- continue;
- }
- catch (ObjectDisposedException)
- {
- // Ignore it.
- break;
- }
-
- ConnectResponse response;
- try
- {
- response = await client
- .ConnectAsync(new ConnectRequest(), DateTime.UtcNow.AddSeconds(10))
- .ConfigureAwait(false);
- this.logger.LogInformation(
- "ConnectResponse received from newly PLC {0}: {1}",
- client.RemoteEndPoint,
- response);
- }
- catch (RpcException e)
- {
- this.logger.LogWarning(
- e,
- "Failed to send ConnectRequest to newly PLC {0}, hang up.",
- client.RemoteEndPoint);
- await client.Close().ConfigureAwait(false);
- client.Dispose();
- continue;
- }
-
- client.OnClosed += (sender, args) =>
- {
- this.logger.LogInformation(
- "Client(MAC={0}, EndPoint={1}) disconnected.",
- BitConverter.ToString(response.Id.ToByteArray()),
- client.RemoteEndPoint);
- this.PlcDictionary.TryRemove(response.Id, out PlcClient _);
- };
-
- if (this.PlcDictionary.TryAdd(response.Id, client))
- {
- this.logger.LogInformation(
- "Client(MAC={0}, EndPoint={1}) connected.",
- BitConverter.ToString(response.Id.ToByteArray()),
- client.RemoteEndPoint);
- }
- else
- {
- this.logger.LogWarning(
- "Failed to add the client(MAC={0}, EndPoint={1}) into dictionary.",
- BitConverter.ToString(response.Id.ToByteArray()),
- client.RemoteEndPoint);
- await client.Close().ConfigureAwait(false);
- client.Dispose();
- }
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Program.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Program.cs
deleted file mode 100644
index 36b36739..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Program.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Net;
-using GeothermalResearchInstitute.PlcV2;
-using GeothermalResearchInstitute.ServerConsole.GrpcServices;
-using GeothermalResearchInstitute.ServerConsole.Models;
-using GeothermalResearchInstitute.ServerConsole.Options;
-using GeothermalResearchInstitute.v2;
-using Grpc.Core;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Serilog;
-
-namespace GeothermalResearchInstitute.ServerConsole
-{
- internal class Program
- {
- internal static readonly Action DbContextOptionsBuilderAction =
- builder => builder.UseSqlite("Data Source=bjdire.sqlite;");
-
- private static void Main(string[] args)
- {
- IHost host = new HostBuilder()
- .ConfigureHostConfiguration(builder => builder
- .SetBasePath(Environment.CurrentDirectory)
- .AddIniFile("appsettings.ini", optional: false, reloadOnChange: true)
- .AddCommandLine(args))
- .ConfigureAppConfiguration((context, builder) =>
- {
- IHostEnvironment env = context.HostingEnvironment;
- builder
- .SetBasePath(Environment.CurrentDirectory)
- .AddIniFile("appsettings.ini", optional: false, reloadOnChange: true)
- .AddIniFile($"appsettings.{env.EnvironmentName}.ini", optional: false, reloadOnChange: true)
- .AddCommandLine(args);
- })
- .ConfigureLogging((context, builder) =>
- {
- IHostEnvironment env = context.HostingEnvironment;
- if (env.IsDevelopment() || env.IsStaging())
- {
- builder.AddDebug();
- }
-
- Log.Logger = new LoggerConfiguration()
- .ReadFrom.Configuration(context.Configuration)
- .CreateLogger();
- builder.AddSerilog(dispose: true);
-
- builder.AddConfiguration(context.Configuration.GetSection("Logging"));
- })
- .ConfigureServices((context, builder) =>
- {
- IHostEnvironment env = context.HostingEnvironment;
- IConfiguration config = context.Configuration;
-
- // Configuration options.
- builder.Configure(config);
- builder.Configure(config.GetSection("core"));
- builder.Configure(config);
- builder.Configure(config.GetSection("tasks"));
-
- // Database.
- if (env.IsDevelopment())
- {
- // TODO(zhangshuai.ustc): Add fake data.
- builder.AddDbContext(
- options => options.UseInMemoryDatabase("bjdire"),
- ServiceLifetime.Transient,
- ServiceLifetime.Transient);
- }
- else
- {
- builder.AddDbContext(
- DbContextOptionsBuilderAction,
- ServiceLifetime.Transient,
- ServiceLifetime.Transient);
- }
-
- // PLC server.
- builder.AddSingleton(provider => new PlcServer(
- provider.GetRequiredService(),
- IPAddress.Any,
- provider.GetRequiredService>().Value.TcpPort));
- builder.AddSingleton();
-
- // gRPC services.
- builder.AddSingleton(serviceProvider =>
- {
- return new HCOONa.MicrosoftExtensions.Logging.GrpcAdapater.GrpcLogger(
- serviceProvider.GetRequiredService(),
- serviceProvider.GetRequiredService>());
- });
- builder.AddSingleton();
- builder.AddSingleton(serviceProvider =>
- {
- GrpcEnvironment.SetLogger(serviceProvider.GetRequiredService());
- return new Server
- {
- Services =
- {
- DeviceService.BindService(serviceProvider.GetRequiredService()),
- },
- Ports =
- {
- new ServerPort(
- "0.0.0.0",
- serviceProvider.GetRequiredService>().Value.GrpcPort,
- ServerCredentials.Insecure),
- },
- };
- });
-
- builder.AddHostedService();
- builder.AddHostedService();
-
-#if DEBUG
- if (env.IsDevelopment())
- {
- builder.AddHostedService();
- }
-#endif
- })
- .UseConsoleLifetime()
- .Build();
-
- ILogger programLogger = host.Services.GetRequiredService>();
- AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
- {
- programLogger.LogCritical("Global unhandled exception occurred!", (Exception)e.ExceptionObject);
- };
-
- using (host)
- {
- host.Run();
- }
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Properties/launchSettings.json b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Properties/launchSettings.json
deleted file mode 100644
index a1a400f7..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Properties/launchSettings.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "profiles": {
- "GeothermalResearchInstitute.ServerConsole": {
- "commandName": "Project",
- "commandLineArgs": "--Environment=Development"
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Utils/ConvertUtils.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Utils/ConvertUtils.cs
deleted file mode 100644
index ed73dc53..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/Utils/ConvertUtils.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using Google.Protobuf.WellKnownTypes;
-using GrpcAlarm = GeothermalResearchInstitute.v2.Alarm;
-using GrpcAlarmChange = GeothermalResearchInstitute.v2.AlarmChange;
-using GrpcMetric = GeothermalResearchInstitute.v2.Metric;
-using ModelAlarm = GeothermalResearchInstitute.ServerConsole.Models.Alarm;
-using ModelAlarmChange = GeothermalResearchInstitute.ServerConsole.Models.AlarmChange;
-using ModelMetric = GeothermalResearchInstitute.ServerConsole.Models.Metric;
-
-namespace GeothermalResearchInstitute.ServerConsole.Utils
-{
- internal static class ConvertUtils
- {
- public static GrpcAlarm AssignFrom(this GrpcAlarm gAlarm, ModelAlarm alarm)
- {
- gAlarm.CreateTime = Timestamp.FromDateTimeOffset(alarm.Timestamp);
- gAlarm.LowFlowRate = alarm.LowFlowRate;
- gAlarm.HighHeaterPressure = alarm.HighHeaterPressure;
- gAlarm.LowHeaterPressure = alarm.LowHeaterPressure;
- gAlarm.NoPower = alarm.NoPower;
- gAlarm.HeaterOverloadedBroken = alarm.HeaterOverloadedBroken;
- gAlarm.ElectricalHeaterBroken = alarm.ElectricalHeaterBroken;
- return gAlarm;
- }
-
- public static GrpcAlarm AssignTo(this GrpcAlarm gAlarm, ModelAlarm alarm)
- {
- alarm.Timestamp = gAlarm.CreateTime.ToDateTimeOffset();
- alarm.LowFlowRate = gAlarm.LowFlowRate;
- alarm.HighHeaterPressure = gAlarm.HighHeaterPressure;
- alarm.LowHeaterPressure = gAlarm.LowHeaterPressure;
- alarm.NoPower = gAlarm.NoPower;
- alarm.HeaterOverloadedBroken = gAlarm.HeaterOverloadedBroken;
- alarm.ElectricalHeaterBroken = gAlarm.ElectricalHeaterBroken;
- return gAlarm;
- }
-
- public static GrpcAlarmChange AssignFrom(this GrpcAlarmChange gAlarmChange, ModelAlarmChange alarmChange)
- {
- gAlarmChange.CreateTime = Timestamp.FromDateTimeOffset(alarmChange.Timestamp);
- gAlarmChange.AlarmType = alarmChange.Type;
- gAlarmChange.AlarmChangeDirection = alarmChange.Direction;
- return gAlarmChange;
- }
-
- public static GrpcMetric AssignFrom(this GrpcMetric gMetric, ModelMetric metric)
- {
- gMetric.CreateTime = Timestamp.FromDateTimeOffset(metric.Timestamp);
- gMetric.OutputWaterCelsiusDegree = metric.OutputWaterCelsiusDegree;
- gMetric.InputWaterCelsiusDegree = metric.InputWaterCelsiusDegree;
- gMetric.HeaterOutputWaterCelsiusDegree = metric.HeaterOutputWaterCelsiusDegree;
- gMetric.EnvironmentCelsiusDegree = metric.EnvironmentCelsiusDegree;
- gMetric.OutputWaterPressureMeter = metric.OutputWaterPressureMeter;
- gMetric.InputWaterPressureMeter = metric.InputWaterPressureMeter;
- gMetric.HeaterPowerKilowatt = metric.HeaterPowerKilowatt;
- gMetric.WaterPumpFlowRateCubicMeterPerHour = metric.WaterPumpFlowRateCubicMeterPerHour;
- return gMetric;
- }
-
- public static GrpcMetric AssignTo(this GrpcMetric gMetric, ModelMetric metric)
- {
- metric.Timestamp = gMetric.CreateTime.ToDateTimeOffset();
- metric.OutputWaterCelsiusDegree = gMetric.OutputWaterCelsiusDegree;
- metric.InputWaterCelsiusDegree = gMetric.InputWaterCelsiusDegree;
- metric.HeaterOutputWaterCelsiusDegree = gMetric.HeaterOutputWaterCelsiusDegree;
- metric.EnvironmentCelsiusDegree = gMetric.EnvironmentCelsiusDegree;
- metric.OutputWaterPressureMeter = gMetric.OutputWaterPressureMeter;
- metric.InputWaterPressureMeter = gMetric.InputWaterPressureMeter;
- metric.HeaterPowerKilowatt = gMetric.HeaterPowerKilowatt;
- metric.WaterPumpFlowRateCubicMeterPerHour = gMetric.WaterPumpFlowRateCubicMeterPerHour;
- return gMetric;
- }
- }
-}
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Development.ini b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Development.ini
deleted file mode 100644
index e5c40612..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Development.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-[core]
-MaxFakeDeviceNum = 1
-
-[tasks]
-; 5 seconds
-CollectMetricIntervalMillis = 5000
-
-[credentials]
-0:nickname = 开发用户0
-0:username = user
-0:password = user
-0:role = User
-1:nickname = 开发管理员1
-1:username = admin
-1:password = admin
-1:role = Administrator
-
-[devices]
-0:id = 10:BF:48:79:B2:A4
-0:name = 开发设备0
-1:id = BC:96:80:E6:70:16
-1:name = 开发设备1
-
-[Logging:LogLevel]
-Default = Debug
-
-[Serilog]
-MinimumLevel:Default = Debug
-WriteTo:Async:Args:configure:0:Args:rollOnFileSizeLimit = false
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Production.ini b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Production.ini
deleted file mode 100644
index c0985c2f..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Production.ini
+++ /dev/null
@@ -1,25 +0,0 @@
-[core]
-
-[credentials]
-; 增减用户无需重启服务
-; 用户昵称,将在上位机界面显示
-0:nickname = 刘冰
-; 用户名
-0:username = liubing
-; 密码
-0:password = liubing123
-; 身份,管理员(Administrator),用户(User)
-0:role = Administrator
-
-[devices]
-; 增减设备无需重启服务
-; 设备 MAC 地址
-0:id = 10:BF:48:79:B2:A4
-; 设备名称,将在上位机界面显示
-0:name = 开发设备0
-
-[Logging:LogLevel]
-Default = Information
-
-[Serilog]
-MinimumLevel:Default = Information
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Staging.ini b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Staging.ini
deleted file mode 100644
index c737aa5f..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.Staging.ini
+++ /dev/null
@@ -1,28 +0,0 @@
-[core]
-MaxFakeDeviceNum = 1
-
-[tasks]
-; 5 seconds
-CollectMetricIntervalMillis = 5000
-
-[credentials]
-0:nickname = 开发用户0
-0:username = user
-0:password = user
-0:role = User
-1:nickname = 开发管理员1
-1:username = admin
-1:password = admin
-1:role = Administrator
-
-[devices]
-0:id = 10:BF:48:79:B2:A4
-0:name = 开发设备0
-1:id = BC:96:80:E6:70:16
-1:name = 开发设备1
-
-[Logging:LogLevel]
-Default = Debug
-
-[Serilog]
-MinimumLevel:Default = Debug
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.ini b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.ini
deleted file mode 100644
index c4461d86..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/appsettings.ini
+++ /dev/null
@@ -1,34 +0,0 @@
-[core]
-GrpcPort = 8888
-TcpPort = 8889
-
-; 5 seconds
-DefaultReadTimeoutMillis = 5000
-
-[tasks]
-; 1 minute
-CollectAlarmIntervalMillis = 60000
-
-; 10 minutes
-CollectMetricIntervalMillis = 600000
-
-[credentials]
-
-[devices]
-
-[Serilog]
-Using:0 = Serilog.Sinks.Console
-MinimumLevel:Default = Debug
-MinimumLevel:Override:Microsoft.EntityFrameworkCore = Information
-MinimumLevel:Override:Microsoft.EntityFrameworkCore.Infrastructure = Warning
-WriteTo:0:Name = Console
-WriteTo:0:Args:outputTemplate = {Timestamp:yyyy-MM-ddTHH:mm:ss.fffzzz} {ThreadId} {Level} {SourceContext} {Message:l}{NewLine}{Exception}
-Enrich:0 = FromLogContext
-Enrich:1 = WithThreadId
-WriteTo:Async:Name = Async
-WriteTo:Async:Args:configure:0:Name = File
-WriteTo:Async:Args:configure:0:Args:path = log.txt
-WriteTo:Async:Args:configure:0:Args:outputTemplate = {Timestamp:yyyy-MM-ddTHH:mm:ss.fffzzz} {ThreadId} {Level} {SourceContext} {Message:l}{NewLine}{Exception}
-WriteTo:Async:Args:configure:0:Args:rollOnFileSizeLimit = true
-WriteTo:Async:Args:configure:0:Args:fileSizeLimitBytes = 104857600
-WriteTo:Async:Args:configure:0:Args:retainedFileCountLimit = 5
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/bjdire.sqlite b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/bjdire.sqlite
deleted file mode 100644
index e234fbb2..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/bjdire.sqlite
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:dca11ebff6fa896f7ab5cd900ce2bbcd6d4599435e2d5800f19266bd75d3191f
-size 36864
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/packages.lock.json b/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/packages.lock.json
deleted file mode 100644
index 346de03c..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.ServerConsole/packages.lock.json
+++ /dev/null
@@ -1,771 +0,0 @@
-{
- "version": 2,
- "dependencies": {
- "net6.0": {
- "DotNet.ReproducibleBuilds": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "+H2t/t34h6mhEoUvHi8yGXyuZ2GjSovcGYehJrS2MDm2XgmPfZL2Sdxg+uL2lKgZ4M6tTwKHIlxOob2bgh0NRQ==",
- "dependencies": {
- "Microsoft.SourceLink.AzureRepos.Git": "1.1.1",
- "Microsoft.SourceLink.Bitbucket.Git": "1.1.1",
- "Microsoft.SourceLink.GitHub": "1.1.1",
- "Microsoft.SourceLink.GitLab": "1.1.1"
- }
- },
- "Microsoft.CodeAnalysis.BannedApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.3, )",
- "resolved": "3.3.3",
- "contentHash": "vvz3XCHVrd/Ks4xPoutLmL/T2+8JcOk/OMs3ngwQqnzokQCGEDsY+WjK/txCsDWU29sX3fGzH/FnYwNV93O1mA=="
- },
- "Microsoft.CodeAnalysis.NetAnalyzers": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "cjG06LMeOADNUeCUaklOfVgrnVkLy80H5PVll4QHDUXv+C+6G9rHczrNdWjfb3xKv3Ts9s4UsP6J2ZWe52Gz4Q=="
- },
- "Microsoft.EntityFrameworkCore.Design": {
- "type": "Direct",
- "requested": "[6.0.9, )",
- "resolved": "6.0.9",
- "contentHash": "F+1dYjaxMG181+seb2xK4uLU1UoTR0UZRcfYzSQFfVFwAyWtCp3uooNorWYE3BnJAHNEVJgsGmlfYAEGsrewqg==",
- "dependencies": {
- "Humanizer.Core": "2.8.26",
- "Microsoft.EntityFrameworkCore.Relational": "6.0.9"
- }
- },
- "Microsoft.EntityFrameworkCore.InMemory": {
- "type": "Direct",
- "requested": "[6.0.9, )",
- "resolved": "6.0.9",
- "contentHash": "uQWxbNXOSvvQWgcDRTIfP6xC6NvyH/B8TlhCumzrPOy681LOS9RAoMPTlClboE3NyK5ptfzZhkO2vRTki0lFFw==",
- "dependencies": {
- "Microsoft.EntityFrameworkCore": "6.0.9"
- }
- },
- "Microsoft.EntityFrameworkCore.Sqlite": {
- "type": "Direct",
- "requested": "[6.0.9, )",
- "resolved": "6.0.9",
- "contentHash": "kaAUWwv967c1pZUD1xQ4+XYGaRfIxqaRjVE8sv8ZSG+FXdqz7wYT9GB/1Sv2j0hgqknOpTrUu4x5O6RVyhPjEA==",
- "dependencies": {
- "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.9",
- "SQLitePCLRaw.bundle_e_sqlite3": "2.0.6"
- }
- },
- "Microsoft.Extensions.Configuration.CommandLine": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "3nL1qCkZ1Oxx14ZTzgo4MmlO7tso7F+TtMZAY2jUAtTLyAcDp+EDjk3RqafoKiNaePyPvvlleEcBxh3b2Hzl1g==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "6.0.0",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration.Ini": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "4p1kPxibT+RNlj91k9SfvtNIUALqru9xmh+XT7Pfw80WAufCmgj3F81hpXZ4YOcFFphBSw1a+n8NZQooWxCHWQ==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "6.0.0",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0"
- }
- },
- "Microsoft.Extensions.DependencyInjection": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
- "dependencies": {
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
- "Microsoft.Extensions.Hosting": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "M8VzD0ni5VarIRT8njnwK4K2WSAo0kZH4Zc3mKcSGkP4CjDZ91T9ZEFmmwhmo4z7x8AFq+tW0WFi9wX+K2cxkQ==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "6.0.0",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.Configuration.Binder": "6.0.0",
- "Microsoft.Extensions.Configuration.CommandLine": "6.0.0",
- "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.0",
- "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0",
- "Microsoft.Extensions.Configuration.Json": "6.0.0",
- "Microsoft.Extensions.Configuration.UserSecrets": "6.0.0",
- "Microsoft.Extensions.DependencyInjection": "6.0.0",
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Physical": "6.0.0",
- "Microsoft.Extensions.Hosting.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging.Configuration": "6.0.0",
- "Microsoft.Extensions.Logging.Console": "6.0.0",
- "Microsoft.Extensions.Logging.Debug": "6.0.0",
- "Microsoft.Extensions.Logging.EventLog": "6.0.0",
- "Microsoft.Extensions.Logging.EventSource": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0"
- }
- },
- "Microsoft.Extensions.Logging": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
- "dependencies": {
- "Microsoft.Extensions.DependencyInjection": "6.0.0",
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0",
- "System.Diagnostics.DiagnosticSource": "6.0.0"
- }
- },
- "Microsoft.Extensions.Logging.Configuration": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "ZDskjagmBAbv+K8rYW9VhjPplhbOE63xUD0DiuydZJwt15dRyoqicYklLd86zzeintUc7AptDkHn+YhhYkYo8A==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "6.0.0",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.Configuration.Binder": "6.0.0",
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0",
- "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0"
- }
- },
- "Microsoft.Extensions.Logging.Debug": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "M9g/JixseSZATJE9tcMn9uzoD4+DbSglivFqVx8YkRJ7VVPmnvCEbOZ0AAaxsL1EKyI4cz07DXOOJExxNsUOHw==",
- "dependencies": {
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0"
- }
- },
- "Microsoft.Extensions.Options.ConfigurationExtensions": {
- "type": "Direct",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "bXWINbTn0vC0FYc9GaQTISbxhQLAMrvtbuvD9N6JelEaIS/Pr62wUCinrq5bf1WRBGczt1v4wDhxFtVFNcMdUQ==",
- "dependencies": {
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.Configuration.Binder": "6.0.0",
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0",
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.NETFramework.ReferenceAssemblies": {
- "type": "Direct",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
- "dependencies": {
- "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
- }
- },
- "Microsoft.SourceLink.GitHub": {
- "type": "Direct",
- "requested": "[1.1.1, )",
- "resolved": "1.1.1",
- "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Nerdbank.GitVersioning": {
- "type": "Direct",
- "requested": "[3.5.113, )",
- "resolved": "3.5.113",
- "contentHash": "4fBSMkqhi410qlkjPm+Mxfk8iO3C7dmgdVS7ljsfVO21WEzZCHP1VCOqB6rlOPfPidR/oxX+/Do/I7meCAz+Jg=="
- },
- "Serilog": {
- "type": "Direct",
- "requested": "[2.12.0, )",
- "resolved": "2.12.0",
- "contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg=="
- },
- "Serilog.Enrichers.Thread": {
- "type": "Direct",
- "requested": "[3.1.0, )",
- "resolved": "3.1.0",
- "contentHash": "85lWsGRJpRxvKT6j/H67no55SUBsBIvp556TKuBTGhjtoPeq+L7j/sDWbgAtvT0p7u7/phJyX6j35PQ4Vtqw0g==",
- "dependencies": {
- "Serilog": "2.3.0"
- }
- },
- "Serilog.Extensions.Logging": {
- "type": "Direct",
- "requested": "[3.1.0, )",
- "resolved": "3.1.0",
- "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==",
- "dependencies": {
- "Microsoft.Extensions.Logging": "2.0.0",
- "Serilog": "2.9.0"
- }
- },
- "Serilog.Settings.Configuration": {
- "type": "Direct",
- "requested": "[3.4.0, )",
- "resolved": "3.4.0",
- "contentHash": "ULloXSiapTb3zOWodC0G4WRDQzA5RjMEfZNZzOZpH8kC3t/lrISLblklIpKC44CX0sMDF40MnJwTIQ3pFQFs4g==",
- "dependencies": {
- "Microsoft.Extensions.Configuration.Binder": "2.0.0",
- "Microsoft.Extensions.DependencyModel": "3.0.0",
- "Serilog": "2.10.0"
- }
- },
- "Serilog.Sinks.Async": {
- "type": "Direct",
- "requested": "[1.5.0, )",
- "resolved": "1.5.0",
- "contentHash": "csHYIqAwI4Gy9oAhXYRwxGrQEAtBg3Ep7WaCzsnA1cZuBZjVAU0n7hWaJhItjO7hbLHh/9gRVxALCUB4Dv+gZw==",
- "dependencies": {
- "Serilog": "2.9.0"
- }
- },
- "Serilog.Sinks.Console": {
- "type": "Direct",
- "requested": "[4.1.0, )",
- "resolved": "4.1.0",
- "contentHash": "K6N5q+5fetjnJPvCmkWOpJ/V8IEIoMIB1s86OzBrbxwTyHxdx3pmz4H+8+O/Dc/ftUX12DM1aynx/dDowkwzqg==",
- "dependencies": {
- "Serilog": "2.10.0"
- }
- },
- "Serilog.Sinks.File": {
- "type": "Direct",
- "requested": "[5.0.0, )",
- "resolved": "5.0.0",
- "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
- "dependencies": {
- "Serilog": "2.10.0"
- }
- },
- "StyleCop.Analyzers": {
- "type": "Direct",
- "requested": "[1.2.0-beta.435, )",
- "resolved": "1.2.0-beta.435",
- "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
- "dependencies": {
- "StyleCop.Analyzers.Unstable": "1.2.0.435"
- }
- },
- "Grpc.Core.Api": {
- "type": "Transitive",
- "resolved": "2.46.3",
- "contentHash": "uy1oe5baVa4V+C8ZyMiA8xYdNIx5A3PiacQL0f1zWDjF2z64Cb1MMXXRTs3GX+jeKpoK/RtOZg8UnJSm2KC/pQ==",
- "dependencies": {
- "System.Memory": "4.5.3"
- }
- },
- "Humanizer.Core": {
- "type": "Transitive",
- "resolved": "2.8.26",
- "contentHash": "OiKusGL20vby4uDEswj2IgkdchC1yQ6rwbIkZDVBPIR6al2b7n3pC91elBul9q33KaBgRKhbZH3+2Ur4fnWx2A=="
- },
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q=="
- },
- "Microsoft.Data.Sqlite.Core": {
- "type": "Transitive",
- "resolved": "6.0.9",
- "contentHash": "vH2Mul/lTqCYIaLDl1ICvv8LrDl1870s7erbRjyWdMNWIzL05I+k6osKifzQpqFNkhAApjU3GgEYHuw1XZBoxA==",
- "dependencies": {
- "SQLitePCLRaw.core": "2.0.6"
- }
- },
- "Microsoft.EntityFrameworkCore": {
- "type": "Transitive",
- "resolved": "6.0.9",
- "contentHash": "3QxYF6TR14O3cSZitdzM10Smsw+hweLXyB45PN4ZVjrX4GqzUoGZ0ZC06r0ST7O7SgYxNjxw34ay5XXbBTX86A==",
- "dependencies": {
- "Microsoft.EntityFrameworkCore.Abstractions": "6.0.9",
- "Microsoft.EntityFrameworkCore.Analyzers": "6.0.9",
- "Microsoft.Extensions.Caching.Memory": "6.0.1",
- "Microsoft.Extensions.DependencyInjection": "6.0.0",
- "Microsoft.Extensions.Logging": "6.0.0",
- "System.Collections.Immutable": "6.0.0",
- "System.Diagnostics.DiagnosticSource": "6.0.0"
- }
- },
- "Microsoft.EntityFrameworkCore.Abstractions": {
- "type": "Transitive",
- "resolved": "6.0.9",
- "contentHash": "XglcSAr6EtjqJpI0DjMMDWkq3l5zG45hRHgrodZFMxNxE7KettJ+X8Em39Aaa0XQwH2P+NHVyK+xhtPX8ogdEA=="
- },
- "Microsoft.EntityFrameworkCore.Analyzers": {
- "type": "Transitive",
- "resolved": "6.0.9",
- "contentHash": "rNIx4fr7KWH4ypghhI+78PhCUYBHdjVbQ3yKvj/KmUIe4d9pysHXT3lF9TuReVdMDsn5mEx+3Yez8s80J4/JLA=="
- },
- "Microsoft.EntityFrameworkCore.Relational": {
- "type": "Transitive",
- "resolved": "6.0.9",
- "contentHash": "LAZHEvlgSg6OUzLUH3BoVneYrQj7cQqwwFnzSfwVGNjQvj5RRh7Vz0eSXLKfQD4xv5QuSm3l+MzFMZC1NBPQHw==",
- "dependencies": {
- "Microsoft.EntityFrameworkCore": "6.0.9",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0"
- }
- },
- "Microsoft.EntityFrameworkCore.Sqlite.Core": {
- "type": "Transitive",
- "resolved": "6.0.9",
- "contentHash": "yo2m2Tvi0f8SQPBaFTmmO2P+sLNl5Zz23JsV7J85N4AFXyDMvCiS0eza/90HgJ/RgrGssEIC2jvaABRreRKl/g==",
- "dependencies": {
- "Microsoft.Data.Sqlite.Core": "6.0.9",
- "Microsoft.EntityFrameworkCore.Relational": "6.0.9",
- "Microsoft.Extensions.DependencyModel": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==",
- "dependencies": {
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration.Abstractions": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==",
- "dependencies": {
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration.FileExtensions": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "6.0.0",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Physical": "6.0.0",
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration.Json": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "6.0.0",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0",
- "System.Text.Json": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration.UserSecrets": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "lB0Hb2V4+RUHy+LjEcqEr4EcV4RWc9EnjAV2GdtWQEdljQX+R4hGREftI7sInU9okP93pDrJiaj6QUJ6ZsslOA==",
- "dependencies": {
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.Configuration.Json": "6.0.0",
- "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Physical": "6.0.0"
- }
- },
- "Microsoft.Extensions.DependencyInjection.Abstractions": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
- },
- "Microsoft.Extensions.DependencyModel": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==",
- "dependencies": {
- "System.Buffers": "4.5.1",
- "System.Memory": "4.5.4",
- "System.Runtime.CompilerServices.Unsafe": "6.0.0",
- "System.Text.Encodings.Web": "6.0.0",
- "System.Text.Json": "6.0.0"
- }
- },
- "Microsoft.Extensions.FileProviders.Physical": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==",
- "dependencies": {
- "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0",
- "Microsoft.Extensions.FileSystemGlobbing": "6.0.0",
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.Extensions.FileSystemGlobbing": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw=="
- },
- "Microsoft.Extensions.Hosting.Abstractions": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==",
- "dependencies": {
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0"
- }
- },
- "Microsoft.Extensions.Logging.EventLog": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "rlo0RxlMd0WtLG3CHI0qOTp6fFn7MvQjlrCjucA31RqmiMFCZkF8CHNbe8O7tbBIyyoLGWB1he9CbaA5iyHthg==",
- "dependencies": {
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0",
- "System.Diagnostics.EventLog": "6.0.0"
- }
- },
- "Microsoft.Extensions.Logging.EventSource": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "BeDyyqt7nkm/nr+Gdk+L8n1tUT/u33VkbXAOesgYSNsxDM9hJ1NOBGoZfj9rCbeD2+9myElI6JOVVFmnzgeWQA==",
- "dependencies": {
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0",
- "Microsoft.Extensions.Primitives": "6.0.0",
- "System.Runtime.CompilerServices.Unsafe": "6.0.0",
- "System.Text.Json": "6.0.0"
- }
- },
- "Microsoft.Extensions.Primitives": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
- "Microsoft.NETFramework.ReferenceAssemblies.net461": {
- "type": "Transitive",
- "resolved": "1.0.3",
- "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
- },
- "Microsoft.SourceLink.AzureRepos.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "qB5urvw9LO2bG3eVAkuL+2ughxz2rR7aYgm2iyrB8Rlk9cp2ndvGRCvehk3rNIhRuNtQaeKwctOl1KvWiklv5w==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Bitbucket.Git": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "cDzxXwlyWpLWaH0em4Idj0H3AmVo3L/6xRXKssYemx+7W52iNskj/SQ4FOmfCb8YQt39otTDNMveCZzYtMoucQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg=="
- },
- "Microsoft.SourceLink.GitLab": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "tvsg47DDLqqedlPeYVE2lmiTpND8F0hkrealQ5hYltSmvruy/Gr5nHAKSsjyw5L3NeM/HLMI5ORv7on/M4qyZw==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "1.1.1",
- "Microsoft.SourceLink.Common": "1.1.1"
- }
- },
- "SQLitePCLRaw.bundle_e_sqlite3": {
- "type": "Transitive",
- "resolved": "2.0.6",
- "contentHash": "zssYqiaucyGArZfg74rJuzK0ewgZiidsRVrZTmP7JLNvK806gXg6PGA46XzoJGpNPPA5uRcumwvVp6YTYxtQ5w==",
- "dependencies": {
- "SQLitePCLRaw.core": "2.0.6",
- "SQLitePCLRaw.lib.e_sqlite3": "2.0.6",
- "SQLitePCLRaw.provider.e_sqlite3": "2.0.6"
- }
- },
- "SQLitePCLRaw.core": {
- "type": "Transitive",
- "resolved": "2.0.6",
- "contentHash": "Vh8n0dTvwXkCGur2WqQTITvk4BUO8i8h9ucSx3wwuaej3s2S6ZC0R7vqCTf9TfS/I4QkXO6g3W2YQIRFkOcijA==",
- "dependencies": {
- "System.Memory": "4.5.3"
- }
- },
- "SQLitePCLRaw.lib.e_sqlite3": {
- "type": "Transitive",
- "resolved": "2.0.6",
- "contentHash": "xlstskMKalKQl0H2uLNe0viBM6fvAGLWqKZUQ3twX5y1tSOZKe0+EbXopQKYdbjJytNGI6y5WSKjpI+kVr2Ckg=="
- },
- "SQLitePCLRaw.provider.e_sqlite3": {
- "type": "Transitive",
- "resolved": "2.0.6",
- "contentHash": "peXLJbhU+0clVBIPirihM1NoTBqw8ouBpcUsVMlcZ4k6fcL2hwgkctVB2Nt5VsbnOJcPspQL5xQK7QvLpxkMgg==",
- "dependencies": {
- "SQLitePCLRaw.core": "2.0.6"
- }
- },
- "StyleCop.Analyzers.Unstable": {
- "type": "Transitive",
- "resolved": "1.2.0.435",
- "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
- },
- "System.Buffers": {
- "type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
- },
- "System.Diagnostics.DiagnosticSource": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
- "System.Diagnostics.EventLog": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw=="
- },
- "System.Runtime.CompilerServices.Unsafe": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
- },
- "System.Text.Encodings.Web": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
- "crc32c.net": {
- "type": "Project"
- },
- "geothermalresearchinstitute.fakeplcv2": {
- "type": "Project",
- "dependencies": {
- "GeothermalResearchInstitute.PlcV2": "[1.0.0, )"
- }
- },
- "geothermalresearchinstitute.grpc": {
- "type": "Project",
- "dependencies": {
- "Google.Protobuf": "[3.21.6, )",
- "Grpc": "[2.46.3, )"
- }
- },
- "geothermalresearchinstitute.plcv2": {
- "type": "Project",
- "dependencies": {
- "Crc32C.NET": "[1.0.0, )",
- "GeothermalResearchInstitute.Grpc": "[1.0.0, )",
- "Microsoft.Extensions.Logging.Abstractions": "[6.0.0, )",
- "System.Memory": "[4.5.5, )",
- "System.Threading.Tasks.Dataflow": "[6.0.0, )"
- }
- },
- "hcoona.microsoftextensions.logging.grpcadapter": {
- "type": "Project",
- "dependencies": {
- "Grpc.Core": "[2.46.3, )",
- "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )"
- }
- },
- "Google.Protobuf": {
- "type": "CentralTransitive",
- "requested": "[3.21.6, )",
- "resolved": "3.21.6",
- "contentHash": "HSYHFnfuTu/O4Ijy0mCW9zxLI8MJfCZJ10dk3JGPrkLaRR4LsiPKzZrrnapf2G0tP2yRMkHCl+2LKLTXqGBn2A=="
- },
- "Grpc": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "79TsAcLBVl5J7AmtnV+GmgkhWlpK3D9JYJDhYxZGO0DKukbyrRxxcbaFlRZ84WGwTAW8LezrInUYgfiJi3zGVg==",
- "dependencies": {
- "Grpc.Core": "2.46.3"
- }
- },
- "Grpc.Core": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "lu7KP7BVWdvFXWbn/IFYHBQCpMohJwbLM1aL+nu2C0pY2CdS0idaUNAJNC2nZ60fXfqoxnSiERrIU6rC474oTw==",
- "dependencies": {
- "Grpc.Core.Api": "2.46.3",
- "System.Memory": "4.5.3"
- }
- },
- "Microsoft.Extensions.Caching.Abstractions": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==",
- "dependencies": {
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.Extensions.Caching.Memory": {
- "type": "CentralTransitive",
- "requested": "[6.0.1, )",
- "resolved": "6.0.1",
- "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==",
- "dependencies": {
- "Microsoft.Extensions.Caching.Abstractions": "6.0.0",
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0",
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration.Binder": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "b3ErKzND8LIC7o08QAVlKfaEIYEvLJbtmVbFZVBRXeu9YkKfSSzLZfR1SUfQPBIy9mKLhEtJgGYImkcMNaKE0A==",
- "dependencies": {
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0"
- }
- },
- "Microsoft.Extensions.Configuration.EnvironmentVariables": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "DjYkzqvhiHCq38LW71PcIxXk6nhtV6VySP9yDcSO0goPl7YCU1VG1f2Wbgy58lkA10pWkjHCblZPUyboCB93ZA==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "6.0.0",
- "Microsoft.Extensions.Configuration.Abstractions": "6.0.0"
- }
- },
- "Microsoft.Extensions.FileProviders.Abstractions": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==",
- "dependencies": {
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "Microsoft.Extensions.Logging.Abstractions": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
- },
- "Microsoft.Extensions.Logging.Console": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "gsqKzOEdsvq28QiXFxagmn1oRB9GeI5GgYCkoybZtQA0IUb7QPwf1WmN3AwJeNIsadTvIFQCiVK0OVIgKfOBGg==",
- "dependencies": {
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging": "6.0.0",
- "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
- "Microsoft.Extensions.Logging.Configuration": "6.0.0",
- "Microsoft.Extensions.Options": "6.0.0",
- "System.Text.Json": "6.0.0"
- }
- },
- "Microsoft.Extensions.Options": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
- "dependencies": {
- "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
- "Microsoft.Extensions.Primitives": "6.0.0"
- }
- },
- "System.Collections.Immutable": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.5.5, )",
- "resolved": "4.5.5",
- "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
- },
- "System.Text.Json": {
- "type": "CentralTransitive",
- "requested": "[6.0.6, )",
- "resolved": "6.0.6",
- "contentHash": "GZ+62pLOr544jwSvyXv5ezSfzlFBTjLuPhgOS2dnKuknAA8dPNUGXLKTHf9XdsudU9JpbtweXnE4oEiKEB2T1Q==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0",
- "System.Text.Encodings.Web": "6.0.0"
- }
- },
- "System.Threading.Tasks.Dataflow": {
- "type": "CentralTransitive",
- "requested": "[6.0.0, )",
- "resolved": "6.0.0",
- "contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
- }
- },
- "net6.0/win-x64": {
- "SQLitePCLRaw.lib.e_sqlite3": {
- "type": "Transitive",
- "resolved": "2.0.6",
- "contentHash": "xlstskMKalKQl0H2uLNe0viBM6fvAGLWqKZUQ3twX5y1tSOZKe0+EbXopQKYdbjJytNGI6y5WSKjpI+kVr2Ckg=="
- },
- "System.Diagnostics.EventLog": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw=="
- },
- "System.Text.Encodings.Web": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
- "dependencies": {
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
- "Grpc.Core": {
- "type": "CentralTransitive",
- "requested": "[2.46.3, )",
- "resolved": "2.46.3",
- "contentHash": "lu7KP7BVWdvFXWbn/IFYHBQCpMohJwbLM1aL+nu2C0pY2CdS0idaUNAJNC2nZ60fXfqoxnSiERrIU6rC474oTw==",
- "dependencies": {
- "Grpc.Core.Api": "2.46.3",
- "System.Memory": "4.5.3"
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.Wpf/App.xaml b/GeothermalResearchInstitute/GeothermalResearchInstitute.Wpf/App.xaml
deleted file mode 100644
index a4b93dfb..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.Wpf/App.xaml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/GeothermalResearchInstitute/GeothermalResearchInstitute.Wpf/App.xaml.cs b/GeothermalResearchInstitute/GeothermalResearchInstitute.Wpf/App.xaml.cs
deleted file mode 100644
index 3412bcda..00000000
--- a/GeothermalResearchInstitute/GeothermalResearchInstitute.Wpf/App.xaml.cs
+++ /dev/null
@@ -1,172 +0,0 @@
-//
-// Copyright Shuai Zhang. All rights reserved.
-// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Threading.Tasks;
-using System.Windows;
-using GeothermalResearchInstitute.v2;
-using GeothermalResearchInstitute.Wpf.Modules;
-using GeothermalResearchInstitute.Wpf.Options;
-using GeothermalResearchInstitute.Wpf.ViewModels;
-using GeothermalResearchInstitute.Wpf.Views;
-using Grpc.Core;
-using HCOONa.MicrosoftExtensions.Logging.GrpcAdapater;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Prism.Ioc;
-using Prism.Modularity;
-using Prism.Unity;
-using Prism.Unity.Ioc;
-using Serilog;
-using Unity;
-using Unity.Microsoft.DependencyInjection;
-
-namespace GeothermalResearchInstitute.Wpf
-{
- public partial class App : PrismApplication
- {
- private IUnityContainer UnityContainer { get; set; }
-
- private IHost Host { get; set; }
-
- protected override void OnStartup(StartupEventArgs e)
- {
- this.SetupExceptionHandling();
-
- this.UnityContainer = new UnityContainer();
-
- this.Host = new HostBuilder()
- .UseServiceProviderFactory(new ServiceProviderFactory(this.UnityContainer))
- .ConfigureHostConfiguration(builder => builder
- .SetBasePath(Environment.CurrentDirectory)
- .AddIniFile("appsettings.ini", optional: false, reloadOnChange: true)
- .AddCommandLine(e.Args))
- .ConfigureAppConfiguration((context, builder) =>
- {
- IHostEnvironment env = context.HostingEnvironment;
- builder
- .SetBasePath(Environment.CurrentDirectory)
- .AddIniFile("appsettings.ini", optional: false, reloadOnChange: true)
- .AddIniFile($"appsettings.{env.EnvironmentName}.ini", optional: false, reloadOnChange: true)
- .AddCommandLine(e.Args);
- })
- .ConfigureLogging((context, builder) =>
- {
- IHostEnvironment env = context.HostingEnvironment;
- if (env.IsDevelopment() || env.IsStaging())
- {
- builder.AddDebug();
- }
-
- Log.Logger = new LoggerConfiguration()
- .ReadFrom.Configuration(context.Configuration)
- .CreateLogger();
- builder.AddSerilog(dispose: true);
-
- builder.AddConfiguration(context.Configuration.GetSection("Logging"));
- })
- .ConfigureServices((context, builder) =>
- {
- IHostEnvironment env = context.HostingEnvironment;
- IConfiguration config = context.Configuration;
-
- builder.Configure(config.GetSection("core"));
-
- builder.AddSingleton(serviceProvider =>
- {
- return new GrpcLogger(
- serviceProvider.GetRequiredService(),
- serviceProvider.GetRequiredService>());
- });
-
- if (env.IsDevelopment())
- {
-#if DEBUG
- builder.AddSingleton<
- DeviceService.DeviceServiceClient,
- FakeClients.FakeDeviceServiceClient>();
-#endif
- }
- else
- {
- builder.AddSingleton(provider =>
- {
- IOptions coreOptions =
- provider.GetRequiredService>();
- return new Channel(
- coreOptions.Value.ServerGrpcAddress,
- coreOptions.Value.ServerGrpcPort,
- ChannelCredentials.Insecure);
- });
- builder.AddSingleton(provider =>
- new DeviceService.DeviceServiceClient(provider.GetRequiredService()));
- }
- })
- .Build();
-
- base.OnStartup(e);
- }
-
- protected override Window CreateShell()
- {
- return this.Container.Resolve();
- }
-
- protected override IContainerExtension CreateContainerExtension()
- {
- return new UnityContainerExtension(this.Host.Services.GetRequiredService());
- }
-
- protected override void RegisterTypes(IContainerRegistry containerRegistry)
- {
- containerRegistry.RegisterInstance(new ViewModelContext
- {
- Principal = null,
- UserBarVisibility = Visibility.Visible,
- BannerVisibility = Visibility.Collapsed,
- NavigateBackTarget = null,
- });
- }
-
- protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
- {
- base.ConfigureModuleCatalog(moduleCatalog);
- moduleCatalog
- .AddModule()
- .AddModule()
- .AddModule()
- .AddModule()
- .AddModule()
- .AddModule