Add receiver (not complete)
This commit is contained in:
@@ -135,15 +135,15 @@ namespace MachineJob.Service
|
||||
|
||||
return values.MapGetValuesToSetValues();
|
||||
}
|
||||
else if(dataReturnDef.ReturnValues.IsSuccess == null)
|
||||
else if (dataReturnDef.ReturnValues.IsSuccess == null)
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
Dictionary<string, double> ans = new Dictionary<string, double>();
|
||||
|
||||
for (int i = 0; i< 10; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
ans["Test" + (i+1)] = r.Next(65536) - 32768;
|
||||
ans["Test" + (i + 1)] = r.Next(65536) - 32768;
|
||||
}
|
||||
|
||||
return ans;
|
||||
@@ -153,7 +153,7 @@ namespace MachineJob.Service
|
||||
_logger.LogError(dataReturnDef.MachineId + " Return Error.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Samples/ModbusTcpToRtu/ConsoleLogProvider.cs
Normal file
36
Samples/ModbusTcpToRtu/ConsoleLogProvider.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Quartz.Logging;
|
||||
|
||||
namespace ModbusTcpToRtu
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Samples/ModbusTcpToRtu/ModbusTcpToRtu.csproj
Normal file
23
Samples/ModbusTcpToRtu/ModbusTcpToRtu.csproj
Normal file
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>dotnet-ModbusTcpToRtu-b7b7d9ed-80ce-4790-86de-5c3cf21e0a2e</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
||||
<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\Modbus.Net.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
38
Samples/ModbusTcpToRtu/Program.cs
Normal file
38
Samples/ModbusTcpToRtu/Program.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using ModbusTcpToRtu;
|
||||
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();
|
||||
|
||||
163
Samples/ModbusTcpToRtu/Worker.cs
Normal file
163
Samples/ModbusTcpToRtu/Worker.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using Modbus.Net;
|
||||
using Modbus.Net.Modbus;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Impl.Matchers;
|
||||
using BaseUtility = Modbus.Net.BaseUtility<byte[], byte[], Modbus.Net.ProtocolUnit<byte[], byte[]>, Modbus.Net.PipeUnit>;
|
||||
using MultipleMachinesJobScheduler = Modbus.Net.MultipleMachinesJobScheduler<Modbus.Net.IMachineMethodDatas, string, double>;
|
||||
|
||||
namespace ModbusTcpToRtu
|
||||
{
|
||||
public class Worker : BackgroundService
|
||||
{
|
||||
private readonly ILogger<Worker> _logger;
|
||||
|
||||
private BaseUtility readUtility;
|
||||
|
||||
private BaseUtility writeUtility;
|
||||
|
||||
public Worker(ILogger<Worker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
var triggerKey = "Modbus.Net.Job.Utility.SchedulerTrigger";
|
||||
var jobKey = "Modbus.Net.Job.Utility.JobKey";
|
||||
|
||||
var intervalMilliSecond = int.Parse(ConfigurationReader.GetValue("Utility", "interval")) * 1000;
|
||||
var count = int.Parse(ConfigurationReader.GetValue("Utility", "count"));
|
||||
|
||||
var readWriteGroup = ConfigurationReader.GetContent<List<ReadWriteGroup>>("Utility", "readwrite");
|
||||
|
||||
var readType = Enum.Parse<ModbusType>(ConfigurationReader.GetValue("Utility:read", "type"));
|
||||
var readAddress = ConfigurationReader.GetValue("Utility:read", "address");
|
||||
var readSlaveAddress = byte.Parse(ConfigurationReader.GetValue("Utility:read", "slaveAddress"));
|
||||
var readMasterAddress = byte.Parse(ConfigurationReader.GetValue("Utility:read", "masterAddress"));
|
||||
var writeType = Enum.Parse<ModbusType>(ConfigurationReader.GetValue("Utility:write", "type"));
|
||||
var writeAddress = ConfigurationReader.GetValue("Utility:write", "address");
|
||||
var writeSlaveAddress = byte.Parse(ConfigurationReader.GetValue("Utility:write", "slaveAddress"));
|
||||
var writeMasterAddress = byte.Parse(ConfigurationReader.GetValue("Utility:write", "masterAddress"));
|
||||
|
||||
readUtility = new ModbusUtility(readType, readAddress, readSlaveAddress, readMasterAddress, Endian.BigEndianLsb);
|
||||
writeUtility = new ModbusUtility(writeType, writeAddress, writeSlaveAddress, writeMasterAddress, Endian.BigEndianLsb);
|
||||
|
||||
IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();
|
||||
|
||||
await scheduler.Start();
|
||||
|
||||
ITrigger trigger;
|
||||
if (intervalMilliSecond <= 0)
|
||||
{
|
||||
trigger = TriggerBuilder.Create()
|
||||
.WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey)
|
||||
.StartNow()
|
||||
.Build();
|
||||
}
|
||||
else if (count >= 0)
|
||||
trigger = TriggerBuilder.Create()
|
||||
.WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey)
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromMilliseconds(intervalMilliSecond)).WithRepeatCount(count))
|
||||
.Build();
|
||||
else
|
||||
trigger = TriggerBuilder.Create()
|
||||
.WithIdentity(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey)
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(b => b.WithInterval(TimeSpan.FromMilliseconds(intervalMilliSecond)).RepeatForever())
|
||||
.Build();
|
||||
|
||||
IJobListener listener;
|
||||
if (intervalMilliSecond <= 0)
|
||||
{
|
||||
listener = new JobChainingJobLIstenerWithDataMapRepeated("Modbus.Net.DataQuery.Chain." + triggerKey, new string[2] { "Value", "SetValue" }, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
listener = new JobChainingJobListenerWithDataMap("Modbus.Net.DataQuery.Chain." + triggerKey, new string[2] { "Value", "SetValue" });
|
||||
}
|
||||
scheduler.ListenerManager.AddJobListener(listener, GroupMatcher<JobKey>.GroupEquals("Modbus.Net.DataQuery.Group." + triggerKey));
|
||||
|
||||
if (await scheduler.GetTrigger(new TriggerKey(triggerKey)) != null)
|
||||
{
|
||||
await scheduler.UnscheduleJob(new TriggerKey(triggerKey, "Modbus.Net.DataQuery.Group." + triggerKey));
|
||||
}
|
||||
var jobKeys = await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals("Modbus.Net.DataQuery.Group." + triggerKey));
|
||||
await scheduler.DeleteJobs(jobKeys);
|
||||
|
||||
var job = JobBuilder.Create<UtilityPassDataJob>()
|
||||
.WithIdentity(jobKey)
|
||||
.StoreDurably(true)
|
||||
.Build();
|
||||
|
||||
job.JobDataMap.Put("UtilityRead", readUtility);
|
||||
job.JobDataMap.Put("UtilityReadWriteGroup", readWriteGroup);
|
||||
job.JobDataMap.Put("UtilityWrite", writeUtility);
|
||||
|
||||
await scheduler.ScheduleJob(job, trigger);
|
||||
|
||||
}
|
||||
|
||||
public override Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.Run(() => MultipleMachinesJobScheduler.CancelJob());
|
||||
}
|
||||
}
|
||||
|
||||
public class UtilityPassDataJob : IJob
|
||||
{
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
object utilityReadObject;
|
||||
object utilityWriteObject;
|
||||
object utilityReadWriteGroupObject;
|
||||
|
||||
context.JobDetail.JobDataMap.TryGetValue("UtilityRead", out utilityReadObject);
|
||||
context.JobDetail.JobDataMap.TryGetValue("UtilityWrite", out utilityWriteObject);
|
||||
context.JobDetail.JobDataMap.TryGetValue("UtilityReadWriteGroup", out utilityReadWriteGroupObject);
|
||||
|
||||
var readUtility = (BaseUtility)utilityReadObject;
|
||||
var writeUtility = (BaseUtility)utilityWriteObject;
|
||||
var utilityReadWriteGroup = (List<ReadWriteGroup>)utilityReadWriteGroupObject;
|
||||
|
||||
if (readUtility.IsConnected != true)
|
||||
await readUtility.ConnectAsync();
|
||||
if (writeUtility.IsConnected != true)
|
||||
await writeUtility.ConnectAsync();
|
||||
foreach (var rwGroup in utilityReadWriteGroup)
|
||||
{
|
||||
var datas = await readUtility.GetDatasAsync(rwGroup.ReadStart / 10000 + "X " + rwGroup.ReadStart % 10000, rwGroup.ReadCount * 2);
|
||||
if (datas.IsSuccess == true)
|
||||
{
|
||||
var ans = await writeUtility.SetDatasAsync(rwGroup.WriteStart / 10000 + "X " + rwGroup.WriteStart % 10000, ByteArrayToObjectArray(datas.Datas));
|
||||
if (ans.Datas)
|
||||
{
|
||||
Console.WriteLine("success");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static object[] ByteArrayToObjectArray(byte[] arrBytes)
|
||||
{
|
||||
List<object> objArray = new List<object>();
|
||||
foreach (byte b in arrBytes)
|
||||
{
|
||||
objArray.Add(b);
|
||||
}
|
||||
return objArray.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public class ReadWriteGroup
|
||||
{
|
||||
public int ReadStart { get; set; }
|
||||
public int ReadCount { get; set; }
|
||||
public int WriteStart { get; set; }
|
||||
}
|
||||
}
|
||||
8
Samples/ModbusTcpToRtu/appsettings.Development.json
Normal file
8
Samples/ModbusTcpToRtu/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Samples/ModbusTcpToRtu/appsettings.default.json
Normal file
53
Samples/ModbusTcpToRtu/appsettings.default.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
55
Samples/ModbusTcpToRtu/appsettings.json
Normal file
55
Samples/ModbusTcpToRtu/appsettings.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"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": {
|
||||
"Utility": {
|
||||
"interval": 10, //间隔时常(秒)
|
||||
"count": -1, //不要动
|
||||
"readwrite": [
|
||||
{
|
||||
"readStart": 40001, //读取开始地址
|
||||
"readCount": 16, //读取字的个数
|
||||
"writeStart": 40001 //写入开始地址
|
||||
}, //可以写多个
|
||||
{
|
||||
"readStart": 40016, //读取开始地址
|
||||
"readCount": 16, //读取字的个数
|
||||
"writeStart": 40016 //写入开始地址
|
||||
} //可以写多个
|
||||
],
|
||||
"read": {
|
||||
"type": "Tcp",
|
||||
"address": "127.0.0.1:502", //读取的设备地址
|
||||
"slaveAddress": 2, //从站地址
|
||||
"masterAddress": 1 //主站地址
|
||||
},
|
||||
"write": {
|
||||
"type": "Rtu",
|
||||
"address": "COM2", //写入的设备地址
|
||||
"slaveAddress": 3, //从站地址
|
||||
"masterAddress": 1 //主站地址
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Samples/SampleModbusRtuServer/ConsoleLogProvider.cs
Normal file
36
Samples/SampleModbusRtuServer/ConsoleLogProvider.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Samples/SampleModbusRtuServer/DatabaseWrite.cs
Normal file
34
Samples/SampleModbusRtuServer/DatabaseWrite.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
39
Samples/SampleModbusRtuServer/Program.cs
Normal file
39
Samples/SampleModbusRtuServer/Program.cs
Normal 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();
|
||||
|
||||
59
Samples/SampleModbusRtuServer/SampleModbusRtuServer.csproj
Normal file
59
Samples/SampleModbusRtuServer/SampleModbusRtuServer.csproj
Normal 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>
|
||||
85
Samples/SampleModbusRtuServer/Worker.cs
Normal file
85
Samples/SampleModbusRtuServer/Worker.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Samples/SampleModbusRtuServer/appsettings.Development.json
Normal file
21
Samples/SampleModbusRtuServer/appsettings.Development.json
Normal 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"
|
||||
}
|
||||
}
|
||||
21
Samples/SampleModbusRtuServer/appsettings.Production.json
Normal file
21
Samples/SampleModbusRtuServer/appsettings.Production.json
Normal 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"
|
||||
}
|
||||
}
|
||||
53
Samples/SampleModbusRtuServer/appsettings.default.json
Normal file
53
Samples/SampleModbusRtuServer/appsettings.default.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
249
Samples/SampleModbusRtuServer/appsettings.json
Normal file
249
Samples/SampleModbusRtuServer/appsettings.json
Normal 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user