Add receiver (not complete)

This commit is contained in:
parallelbgls
2023-10-12 15:16:48 +08:00
parent 511434d18a
commit d23b942464
41 changed files with 1592 additions and 42 deletions

View File

@@ -0,0 +1,36 @@
using Quartz.Logging;
namespace SampleModbusRtuServer
{
// simple log provider to get something to the console
public class ConsoleLogProvider : ILogProvider
{
private readonly IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production"}.json", true)
.Build();
public Logger GetLogger(string name)
{
return (level, func, exception, parameters) =>
{
if (level >= configuration.GetSection("Quartz").GetValue<Quartz.Logging.LogLevel>("LogLevel") && func != null)
{
Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
}
return true;
};
}
public IDisposable OpenNestedContext(string message)
{
throw new NotImplementedException();
}
public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,34 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MachineJob
{
public class DatabaseWriteContext : DbContext
{
private static readonly IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.default.json", optional: false, reloadOnChange: true)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true, reloadOnChange: true)
.Build();
private static readonly string connectionString = configuration.GetConnectionString("DatabaseWriteConnectionString")!;
public DbSet<DatabaseWriteEntity>? DatabaseWrites { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
}
[Table(name: "databasewrites")]
public partial class DatabaseWriteEntity
{
[Key]
public int Id { get; set; }
public DateTime UpdateTime { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
using SampleModbusRtuServer;
using SampleModbusRtuServer.Service;
using Serilog;
IHost host = Host.CreateDefaultBuilder(args).UseWindowsService()
.ConfigureAppConfiguration((hostingContext, config) =>
{
var configuration = config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production"}.json", true)
.AddEnvironmentVariables()
.Build();
Directory.SetCurrentDirectory(hostingContext.HostingEnvironment.ContentRootPath);
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("Log\\log..txt", Serilog.Events.LogEventLevel.Error, shared: true, rollingInterval: RollingInterval.Day)
.CreateLogger();
var loggerFactory = new LoggerFactory().AddSerilog(Log.Logger);
Quartz.Logging.LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
Modbus.Net.LogProvider.SetLogProvider(loggerFactory);
}
)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(Log.Logger, true));
})
.Build();
await host.RunAsync();

View File

@@ -0,0 +1,59 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-SampleModbusRtuServer-b9a42287-9797-4b7f-81e6-0796c51ff8e0</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<_ContentIncludedByDefault Remove="appsettings.default.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net.Modbus\Modbus.Net.Modbus.csproj" />
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net.OPC\Modbus.Net.Opc.csproj" />
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net.Siemens\Modbus.Net.Siemens.csproj" />
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net\Modbus.Net.csproj" />
<ProjectReference Include="..\MachineJob.CodeGenerator\MachineJob.CodeGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.default.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.Production.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,85 @@
using Modbus.Net.Modbus;
using MultipleMachinesJobScheduler = Modbus.Net.MultipleMachinesJobScheduler<Modbus.Net.IMachineMethodDatas, string, double>;
namespace SampleModbusRtuServer.Service
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private byte[] threex = new byte[19998];
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
ModbusRtuProtocolReceiver receiver = new ModbusRtuProtocolReceiver("COM2", 1);
receiver.DataProcess = receiveContent =>
{
byte[] returnBytes = null;
var readContent = new byte[receiveContent.Count * 2];
var values = receiveContent.WriteContent;
if (values != null)
{
try
{
/*using (var context = new DatabaseWriteContext())
{
context.DatabaseWrites?.Add(new DatabaseWriteEntity
{
Value1 = values["Test1"].DeviceValue,
Value2 = values["Test2"].DeviceValue,
Value3 = values["Test3"].DeviceValue,
Value4 = values["Test4"].DeviceValue,
Value5 = values["Test5"].DeviceValue,
Value6 = values["Test6"].DeviceValue,
Value7 = values["Test7"].DeviceValue,
Value8 = values["Test8"].DeviceValue,
Value9 = values["Test9"].DeviceValue,
Value10 = values["Test10"].DeviceValue,
UpdateTime = DateTime.Now,
});
context.SaveChanges();
}*/
switch (receiveContent.FunctionCode)
{
case (byte)ModbusProtocolFunctionCode.WriteMultiRegister:
{
Array.Copy(receiveContent.WriteContent, 0, threex, receiveContent.StartAddress * 2, receiveContent.Count);
returnBytes = new WriteDataModbusProtocol().Format(receiveContent.SlaveAddress, receiveContent.FunctionCode, receiveContent.StartAddress, receiveContent.Count);
break;
}
}
}
catch
{
//ignore
}
}
else
{
switch (receiveContent.FunctionCode)
{
case (byte)ModbusProtocolFunctionCode.ReadHoldRegister:
{
Array.Copy(threex, receiveContent.StartAddress, readContent, 0, readContent.Length);
returnBytes = new ReadDataModbusProtocol().Format(receiveContent.SlaveAddress, receiveContent.FunctionCode, (byte)receiveContent.Count, readContent);
break;
}
}
}
if (returnBytes != null) return returnBytes;
else return null;
};
await receiver.ConnectAsync();
}
public override Task StopAsync(CancellationToken cancellationToken)
{
return Task.Run(() => MultipleMachinesJobScheduler.CancelJob());
}
}
}

View File

@@ -0,0 +1,21 @@
{
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Debug",
"Microsoft.Hosting.Lifetime": "Debug"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft": "Debug",
"Microsoft.Hosting.Lifetime": "Debug"
}
},
"Quartz": {
"LogLevel": "Debug"
}
}

View File

@@ -0,0 +1,21 @@
{
"Serilog": {
"MinimumLevel": {
"Default": "Error",
"Override": {
"Microsoft": "Error",
"Microsoft.Hosting.Lifetime": "Error"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Error",
"Microsoft.Hosting.Lifetime": "Error"
}
},
"Quartz": {
"LogLevel": "Error"
}
}

View File

@@ -0,0 +1,53 @@
{
"Modbus.Net": {
"TCP": {
"ConnectionTimeout": "5000",
"FetchSleepTime": "100",
"FullDuplex": "True",
"Modbus": {
"ModbusPort": "502",
"IP": "192.168.1.1"
},
"Siemens": {
"SiemensPort": "102",
"IP": "192.168.1.1"
}
},
"UDP": {
"ConnectionTimeout": "5000",
"FetchSleepTime": "100",
"FullDuplex": "True",
"Modbus": {
"ModbusPort": "502",
"IP": "192.168.1.1"
}
},
"COM": {
"FetchSleepTime": "100",
"ConnectionTimeout": "5000",
"BaudRate": "BaudRate9600",
"Parity": "None",
"StopBits": "One",
"DataBits": "Eight",
"Handshake": "None",
"FullDuplex": "False",
"Modbus": {
"COM": "COM1"
},
"Siemens": {
"COM": "COM2",
"Parity": "Even"
}
},
"OpcDa": {
"Host": "opcda://localhost/test"
},
"OpcUa": {
"Host": "opc.tcp://localhost/test"
},
"Controller": {
"WaitingListCount": "100",
"NoResponse": false
}
}
}

View File

@@ -0,0 +1,249 @@
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"Quartz": {
"LogLevel": "Info"
},
"ConnectionStrings": {
"DatabaseWriteConnectionString": "Server=127.0.0.1; User ID=root; Password=123456; Database=modbusnettest;"
},
"Modbus.Net": {
"Machine": [
{
"a:id": "ModbusMachine1",
"b:protocol": "Modbus",
"c:type": "Tcp",
"d:connectionString": "127.0.0.1",
"e:addressMap": "AddressMapModbus",
"f:keepConnect": true,
"g:slaveAddress": 1,
"h:masterAddress": 2,
"i:endian": "BigEndianLsb"
},
{
"a:id": "SiemensMachine1",
"b:protocol": "Siemens",
"c:type": "Tcp",
"d:connectionString": "127.0.0.1",
"e:model": "S7_1200",
"f:addressMap": "AddressMapSiemens",
"g:keepConnect": true,
"h:slaveAddress": 1,
"i:masterAddress": 2,
"j:src": 1,
"k:dst": 0
},
{
"a:id": "ModbusMachine2",
"b:protocol": "Modbus",
"c:type": "Rtu",
"d:connectionString": "COM1",
"e:addressMap": "AddressMapModbus",
"f:keepConnect": true,
"g:slaveAddress": 1,
"h:masterAddress": 2,
"i:endian": "BigEndianLsb"
},
{
"a:id": "SiemensMachine2",
"b:protocol": "Siemens",
"c:type": "Ppi",
"d:connectionString": "COM2",
"e:model": "S7_200",
"f:addressMap": "AddressMapSiemens",
"g:keepConnect": true,
"h:slaveAddress": 2,
"i:masterAddress": 0,
"j:src": 1,
"k:dst": 0
},
{
"a:id": "OpcMachine1",
"b:protocol": "Opc",
"c:type": "Da",
"d:connectionString": "opcda://localhost/Matrikon.OPC.Simulation.1",
"e:addressMap": "AddressMapOpc",
"f:tagSpliter": "."
}
],
"addressMap": {
"AddressMapModbus": [
{
"Area": "4X",
"Address": 1,
"DataType": "Int16",
"Id": "1",
"Name": "Test1"
},
{
"Area": "4X",
"Address": 2,
"DataType": "Int16",
"Id": "2",
"Name": "Test2"
},
{
"Area": "4X",
"Address": 3,
"DataType": "Int16",
"Id": "3",
"Name": "Test3"
},
{
"Area": "4X",
"Address": 4,
"DataType": "Int16",
"Id": "4",
"Name": "Test4"
},
{
"Area": "4X",
"Address": 5,
"DataType": "Int16",
"Id": "5",
"Name": "Test5"
},
{
"Area": "4X",
"Address": 6,
"DataType": "Int16",
"Id": "6",
"Name": "Test6"
},
{
"Area": "4X",
"Address": 7,
"DataType": "Int16",
"Id": "7",
"Name": "Test7"
},
{
"Area": "4X",
"Address": 8,
"DataType": "Int16",
"Id": "8",
"Name": "Test8"
},
{
"Area": "4X",
"Address": 9,
"DataType": "Int16",
"Id": "9",
"Name": "Test9"
},
{
"Area": "4X",
"Address": 10,
"DataType": "Int16",
"Id": "10",
"Name": "Test10"
}
],
"AddressMapSiemens": [
{
"Area": "DB1",
"Address": 0,
"DataType": "Int16",
"Id": "1",
"Name": "Test1"
},
{
"Area": "DB1",
"Address": 2,
"DataType": "Int16",
"Id": "2",
"Name": "Test2"
},
{
"Area": "DB1",
"Address": 4,
"DataType": "Int16",
"Id": "3",
"Name": "Test3"
},
{
"Area": "DB1",
"Address": 6,
"DataType": "Int16",
"Id": "4",
"Name": "Test4"
},
{
"Area": "DB1",
"Address": 8,
"DataType": "Int16",
"Id": "5",
"Name": "Test5"
},
{
"Area": "DB1",
"Address": 10,
"DataType": "Int16",
"Id": "6",
"Name": "Test6"
},
{
"Area": "DB1",
"Address": 12,
"DataType": "Int16",
"Id": "7",
"Name": "Test7"
},
{
"Area": "DB1",
"Address": 14,
"DataType": "Int16",
"Id": "8",
"Name": "Test8"
},
{
"Area": "DB1",
"Address": 16,
"DataType": "Int16",
"Id": "9",
"Name": "Test9"
},
{
"Area": "DB1",
"Address": 18,
"DataType": "Int16",
"Id": "10",
"Name": "Test10"
}
],
"AddressMapOpc": [
{
"Area": "Random",
"Address": "Real4",
"DataType": "Single",
"Id": "1",
"Name": "Test1",
"DecimalPos": 2
},
{
"Area": "Random",
"Address": "Real8",
"DataType": "Double",
"Id": "2",
"Name": "Test2",
"DecimalPos": 4
}
]
}
}
}