Remove all unnesessary classes and interfaces and complete job implementation

This commit is contained in:
luosheng
2023-03-29 12:25:14 +08:00
parent d2a8f1e22f
commit 7ba7904282
35 changed files with 170 additions and 471 deletions

View File

@@ -1,4 +1,5 @@
using System;
using ProtocolUnit = Modbus.Net.ProtocolUnit<byte[], byte[]>;
namespace Modbus.Net.Modbus.SelfDefinedSample
{

View File

@@ -49,48 +49,4 @@ namespace Modbus.Net.Modbus
}
}
/// <summary>
/// Modbus设备
/// </summary>
public class ModbusMachine : BaseMachine
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">设备的ID号</param>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="keepConnect">是否保持连接</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
/// <param name="endian">端格式</param>
public ModbusMachine(string id, ModbusType connectionType, string connectionString,
IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb)
: base(id, getAddresses, keepConnect, slaveAddress, masterAddress)
{
BaseUtility = new ModbusUtility(connectionType, connectionString, slaveAddress, masterAddress, endian);
AddressFormater = new AddressFormaterModbus();
AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100);
AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100);
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">设备的ID号</param>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
/// <param name="endian">端格式</param>
public ModbusMachine(string id, ModbusType connectionType, string connectionString,
IEnumerable<AddressUnit> getAddresses, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb)
: this(id, connectionType, connectionString, getAddresses, true, slaveAddress, masterAddress, endian)
{
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ProtocolUnit = Modbus.Net.ProtocolUnit<byte[], byte[]>;
namespace Modbus.Net.Modbus
{

View File

@@ -48,7 +48,7 @@ namespace Modbus.Net.Modbus
/// <summary>
/// Tcp协议字节伸缩
/// </summary>
public class ModbusTcpProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend
public class ModbusTcpProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
{
private static ushort _sendCount = 0;
private static readonly object _counterLock = new object();
@@ -93,7 +93,7 @@ namespace Modbus.Net.Modbus
/// <summary>
/// Rtu协议字节伸缩
/// </summary>
public class ModbusRtuProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend
public class ModbusRtuProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
{
/// <summary>
/// 协议扩展,协议内容发送前调用
@@ -128,7 +128,7 @@ namespace Modbus.Net.Modbus
/// <summary>
/// Ascii协议字节伸缩
/// </summary>
public class ModbusAsciiProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend
public class ModbusAsciiProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
{
/// <summary>
/// 协议扩展,协议内容发送前调用

View File

@@ -67,7 +67,7 @@ namespace Modbus.Net.Modbus
/// <summary>
/// Modbus基础Api入口
/// </summary>
public class ModbusUtility : BaseUtility, IUtilityMethodWriteSingleCoil
public class ModbusUtility : BaseUtility<byte[], byte[], ProtocolUnit<byte[], byte[]>, PipeUnit>, IUtilityMethodWriteSingleCoil
{
private static readonly ILogger<ModbusUtility> logger = LogProvider.CreateLogger<ModbusUtility>();

View File

@@ -26,7 +26,7 @@ namespace Modbus.Net.OPC
/// <summary>
/// Opc Da设备
/// </summary>
public abstract class OpcMachine : BaseMachine
public abstract class OpcMachine : BaseMachine<string, string>
{
/// <summary>
/// 构造函数
@@ -37,8 +37,8 @@ namespace Modbus.Net.OPC
protected OpcMachine(string id, IEnumerable<AddressUnit> getAddresses, bool keepConnect)
: base(id, getAddresses, keepConnect)
{
AddressCombiner = new AddressCombinerSingle();
AddressCombinerSet = new AddressCombinerSingle();
AddressCombiner = new AddressCombinerSingle<string>();
AddressCombinerSet = new AddressCombinerSingle<string>();
}
}
}

View File

@@ -50,51 +50,4 @@ namespace Modbus.Net.Siemens
{
}
}
/// <summary>
/// 西门子设备
/// </summary>
public class SiemensMachine : BaseMachine
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">设备id号</param>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="model">设备类型</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="keepConnect">是否保持连接</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
/// <param name="src">本机模块位0到7仅200使用其它型号不要填写</param>
/// <param name="dst">PLC模块位0到7仅200使用其它型号不要填写</param>
public SiemensMachine(string id, SiemensType connectionType, string connectionString, SiemensMachineModel model,
IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress, byte src = 1, byte dst = 0)
: base(id, getAddresses, keepConnect, slaveAddress, masterAddress)
{
BaseUtility = new SiemensUtility(connectionType, connectionString, model, slaveAddress, masterAddress, src, dst);
AddressFormater = new AddressFormaterSiemens();
AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100);
AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100);
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">设备id号</param>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="model">设备类型</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
/// <param name="src">本机模块位0到7仅200使用其它型号不要填写</param>
/// <param name="dst">PLC模块位0到7仅200使用其它型号不要填写</param>
public SiemensMachine(string id, SiemensType connectionType, string connectionString, SiemensMachineModel model,
IEnumerable<AddressUnit> getAddresses, byte slaveAddress, byte masterAddress, byte src = 1, byte dst = 0)
: this(id, connectionType, connectionString, model, getAddresses, true, slaveAddress, masterAddress, src, dst)
{
}
}
}

View File

@@ -62,7 +62,7 @@ namespace Modbus.Net.Siemens
/// <param name="unit">协议核心</param>
/// <param name="content">协议的参数</param>
/// <returns>设备返回的信息</returns>
private async Task<PipeUnit> ForceSendReceiveAsync(ProtocolUnit unit, IInputStruct content)
private async Task<PipeUnit> ForceSendReceiveAsync(ProtocolUnit<byte[], byte[]> unit, IInputStruct content)
{
return await base.SendReceiveAsync(unit, content);
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProtocolUnit = Modbus.Net.ProtocolUnit<byte[], byte[]>;
namespace Modbus.Net.Siemens
{

View File

@@ -5,7 +5,7 @@ namespace Modbus.Net.Siemens
/// <summary>
/// 西门子Tcp协议扩展
/// </summary>
public class SiemensTcpProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend
public class SiemensTcpProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
{
/// <summary>
/// 协议扩展,协议内容发送前调用
@@ -35,7 +35,7 @@ namespace Modbus.Net.Siemens
/// <summary>
/// 西门子Ppi协议扩展
/// </summary>
public class SiemensPpiProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend
public class SiemensPpiProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
{
/// <summary>
/// 协议扩展,协议内容发送前调用

View File

@@ -106,7 +106,7 @@ namespace Modbus.Net.Siemens
/// <param name="unit">协议的核心</param>
/// <param name="content">协议的参数</param>
/// <returns>返回的数据</returns>
public override PipeUnit SendReceive(ProtocolUnit unit, IInputStruct content)
public override PipeUnit SendReceive(ProtocolUnit<byte[], byte[]> unit, IInputStruct content)
{
return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content));
}
@@ -117,7 +117,7 @@ namespace Modbus.Net.Siemens
/// <param name="unit">发送的数据</param>
/// <param name="content">协议的参数</param>
/// <returns>返回的数据</returns>
public override async Task<PipeUnit> SendReceiveAsync(ProtocolUnit unit, IInputStruct content)
public override async Task<PipeUnit> SendReceiveAsync(ProtocolUnit<byte[], byte[]> unit, IInputStruct content)
{
if (ProtocolLinker != null && ProtocolLinker.IsConnected) return await base.SendReceiveAsync(unit, content);
if (_connectTryCount > 10) return null;
@@ -133,7 +133,7 @@ namespace Modbus.Net.Siemens
/// <param name="unit">发送的数据</param>
/// <param name="content">协议的参数</param>
/// <returns>返回的数据</returns>
private async Task<PipeUnit> ForceSendReceiveAsync(ProtocolUnit unit, IInputStruct content)
private async Task<PipeUnit> ForceSendReceiveAsync(ProtocolUnit<byte[], byte[]> unit, IInputStruct content)
{
return await base.SendReceiveAsync(unit, content);
}

View File

@@ -59,7 +59,7 @@ namespace Modbus.Net.Siemens
/// <summary>
/// 西门子通讯Api入口
/// </summary>
public class SiemensUtility : BaseUtility
public class SiemensUtility : BaseUtility<byte[], byte[], ProtocolUnit<byte[], byte[]>, PipeUnit>
{
private static readonly ILogger<SiemensUtility> logger = LogProvider.CreateLogger<SiemensUtility>();

View File

@@ -6,7 +6,7 @@ namespace Modbus.Net
/// 设备的抽象
/// </summary>
/// <typeparam name="TKey"></typeparam>
public interface IMachine<TKey> : IMachineProperty<TKey>, IMachineMethodData, IMachineReflectionCall where TKey : IEquatable<TKey>
public interface IMachine<TKey> : IMachineProperty<TKey>, IMachineMethodDatas, IMachineReflectionCall where TKey : IEquatable<TKey>
{
}
}

View File

@@ -13,19 +13,19 @@ namespace Modbus.Net
/// <summary>
/// Machine的数据读写接口
/// </summary>
public interface IMachineMethodData : IMachineMethod
public interface IMachineMethodDatas : IMachineMethod
{
/// <summary>
/// 读取数据
/// </summary>
/// <returns>从设备读取的数据</returns>
ReturnStruct<Dictionary<string, ReturnUnit>> GetDatas(MachineDataType getDataType);
ReturnStruct<Dictionary<string, ReturnUnit<double>>> GetDatas(MachineDataType getDataType);
/// <summary>
/// 读取数据
/// </summary>
/// <returns>从设备读取的数据</returns>
Task<ReturnStruct<Dictionary<string, ReturnUnit>>> GetDatasAsync(MachineDataType getDataType);
Task<ReturnStruct<Dictionary<string, ReturnUnit<double>>>> GetDatasAsync(MachineDataType getDataType);
/// <summary>
/// 写入数据

View File

@@ -56,12 +56,6 @@ namespace Modbus.Net
/// </summary>
/// <returns>是否断开成功</returns>
bool Disconnect();
/// <summary>
/// 获取设备的Id的字符串
/// </summary>
/// <returns></returns>
string GetMachineIdString();
}
/// <summary>

View File

@@ -1,12 +1,5 @@
namespace Modbus.Net
{
/// <summary>
/// 协议字节伸缩
/// </summary>
public interface IProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
{
}
/// <summary>
/// 协议字节伸缩
/// </summary>

View File

@@ -3,6 +3,7 @@ using Quartz.Impl;
using Quartz.Impl.Matchers;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
namespace Modbus.Net
@@ -10,14 +11,7 @@ namespace Modbus.Net
/// <summary>
/// 返回结果的定义类
/// </summary>
public class DataReturnDef : DataReturnDef<string>
{
}
/// <summary>
/// 返回结果的定义类
/// </summary>
public class DataReturnDef<TMachineKey> where TMachineKey : IEquatable<TMachineKey>
public class DataReturnDef<TMachineKey, TReturnUnit> where TMachineKey : IEquatable<TMachineKey> where TReturnUnit : struct
{
/// <summary>
/// 设备的Id
@@ -27,13 +21,13 @@ namespace Modbus.Net
/// <summary>
/// 返回的数据值
/// </summary>
public ReturnStruct<Dictionary<string, ReturnUnit>> ReturnValues { get; set; }
public ReturnStruct<Dictionary<string, ReturnUnit<TReturnUnit>>> ReturnValues { get; set; }
}
/// <summary>
/// 设备调度器创建类
/// </summary>
public sealed class MachineJobSchedulerCreator
public sealed class MachineJobSchedulerCreator<TMachineMethod, TMachineKey, TReturnUnit> where TMachineKey : IEquatable<TMachineKey> where TReturnUnit : struct where TMachineMethod : IMachineMethod
{
/// <summary>
/// 创建设备调度器
@@ -42,7 +36,7 @@ namespace Modbus.Net
/// <param name="count">重复次数负数为无限循环0为执行一次</param>
/// <param name="intervalSecond">间隔秒数</param>
/// <returns></returns>
public static async Task<MachineGetJobScheduler> CreateScheduler(string triggerKey, int count = 0, int intervalSecond = 1)
public static async Task<MachineGetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> CreateScheduler(string triggerKey, int count = 0, int intervalSecond = 1)
{
return await CreateScheduler(triggerKey, count, (double)intervalSecond);
}
@@ -54,12 +48,12 @@ namespace Modbus.Net
/// <param name="count">重复次数负数为无限循环0为执行一次</param>
/// <param name="intervalMilliSecond">间隔毫秒数</param>
/// <returns></returns>
public static async Task<MachineGetJobScheduler> CreateSchedulerMillisecond(string triggerKey, int count = 0, int intervalMilliSecond = 1000)
public static async Task<MachineGetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> CreateSchedulerMillisecond(string triggerKey, int count = 0, int intervalMilliSecond = 1000)
{
return await CreateScheduler(triggerKey, count, (double)intervalMilliSecond / 1000.0);
return await CreateScheduler(triggerKey, count, intervalMilliSecond / 1000.0);
}
private static async Task<MachineGetJobScheduler> CreateScheduler(string triggerKey, int count = 0, double interval = 1)
private static async Task<MachineGetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> CreateScheduler(string triggerKey, int count = 0, double interval = 1)
{
IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();
@@ -87,7 +81,7 @@ namespace Modbus.Net
var jobKeys = await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals("Modbus.Net.DataQuery.Group." + triggerKey));
await scheduler.DeleteJobs(jobKeys);
return new MachineGetJobScheduler(scheduler, trigger);
return new MachineGetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(scheduler, trigger);
}
/// <summary>
@@ -107,7 +101,7 @@ namespace Modbus.Net
/// <summary>
/// 获取数据任务
/// </summary>
public sealed class MachineGetJobScheduler
public sealed class MachineGetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit> where TMachineKey: IEquatable<TMachineKey> where TReturnUnit : struct where TMachineMethod : IMachineMethod
{
private IScheduler _scheduler;
@@ -147,18 +141,23 @@ namespace Modbus.Net
/// <param name="machineDataType">获取数据的方式</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public async Task<MachineQueryJobScheduler> From(string queryId, IMachineReflectionCall machine, MachineDataType machineDataType)
public async Task<MachineQueryJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> From(string queryId, IMachineReflectionCall machine, MachineDataType machineDataType)
{
JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name);
IJobDetail job = JobBuilder.Create<MachineGetDataJob>()
IJobDetail job = JobBuilder.Create<MachineGetDataJob<TReturnUnit>>()
.WithIdentity(jobKey)
.StoreDurably(true)
.Build();
string methodName = typeof(TMachineMethod).Name;
if (methodName.Substring(0,14) != "IMachineMethod")
{
throw new FormatException("IMachineMethod Name not match format exception");
}
job.JobDataMap.Put("DataType", machineDataType);
job.JobDataMap.Put("Machine", machine);
job.JobDataMap.Put("Function", "Datas");
job.JobDataMap.Put("Function", methodName.Remove(0,14));
if (_parentJobKey != null)
{
@@ -173,7 +172,7 @@ namespace Modbus.Net
await _scheduler.ScheduleJob(job, _trigger);
}
return new MachineQueryJobScheduler(_scheduler, _trigger, jobKey);
return new MachineQueryJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, jobKey);
}
/// <summary>
@@ -183,25 +182,12 @@ namespace Modbus.Net
/// <param name="values">要写入的数据模板</param>
/// <param name="machineDataType">获取数据的方式</param>
/// <returns></returns>
public Task<MachineQueryJobScheduler> Apply(string queryId, Dictionary<string, double> values, MachineDataType machineDataType)
{
return Apply<string>(queryId, values, machineDataType);
}
/// <summary>
/// 直接向任务队列中写一个数据模板
/// </summary>
/// <typeparam name="TMachineKey">设备的ID类型</typeparam>
/// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="values">要写入的数据模板</param>
/// <param name="machineDataType">获取数据的方式</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public async Task<MachineQueryJobScheduler> Apply<TMachineKey>(string queryId, Dictionary<string, double> values, MachineDataType machineDataType) where TMachineKey : IEquatable<TMachineKey>
public async Task<MachineQueryJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> Apply(string queryId, Dictionary<string, double> values, MachineDataType machineDataType)
{
JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name);
IJobDetail job = JobBuilder.Create<MachineQueryDataJob<TMachineKey>>()
IJobDetail job = JobBuilder.Create<MachineQueryDataJob<TMachineKey, TReturnUnit>>()
.WithIdentity(jobKey)
.StoreDurably(true)
.Build();
@@ -223,7 +209,7 @@ namespace Modbus.Net
await _scheduler.ScheduleJob(job, _trigger);
}
return new MachineQueryJobScheduler(_scheduler, _trigger, jobKey);
return new MachineQueryJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, jobKey);
}
/// <summary>
@@ -233,23 +219,10 @@ namespace Modbus.Net
/// <param name="values">要写入的数据模板</param>
/// <param name="machineDataType">获取数据的方式</param>
/// <returns></returns>
public Task<MachineSetJobScheduler> ApplyTo(string queryId, Dictionary<string, double> values, MachineDataType machineDataType)
{
return ApplyTo<string>(queryId, values, machineDataType);
}
/// <summary>
/// 直接向任务队列中写一个数据模板,并跳过处理数据流程
/// </summary>
/// <typeparam name="TMachineKey">设备的ID类型</typeparam>
/// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="values">要写入的数据模板</param>
/// <param name="machineDataType">获取数据的方式</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public async Task<MachineSetJobScheduler> ApplyTo<TMachineKey>(string queryId, Dictionary<string, double> values, MachineDataType machineDataType) where TMachineKey : IEquatable<TMachineKey>
public async Task<MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> ApplyTo(string queryId, Dictionary<string, double> values, MachineDataType machineDataType)
{
var applyJobScheduler = await Apply<TMachineKey>(queryId, values, machineDataType);
var applyJobScheduler = await Apply(queryId, values, machineDataType);
return await applyJobScheduler.Query();
}
}
@@ -257,7 +230,7 @@ namespace Modbus.Net
/// <summary>
/// 处理数据任务
/// </summary>
public sealed class MachineQueryJobScheduler
public sealed class MachineQueryJobScheduler<TMachineMethod, TMachineKey, TReturnUnit> where TMachineKey: IEquatable<TMachineKey> where TReturnUnit : struct where TMachineMethod : IMachineMethod
{
private IScheduler _scheduler;
@@ -284,26 +257,14 @@ namespace Modbus.Net
/// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="QueryDataFunc">处理数据的函数,输入返回读数据的定义和值,输出写数据字典</param>
/// <returns></returns>
public Task<MachineSetJobScheduler> Query(string queryId = null, Func<DataReturnDef, Dictionary<string, double>> QueryDataFunc = null)
{
return Query<string>(queryId, QueryDataFunc);
}
/// <summary>
/// 处理数据
/// </summary>
/// <typeparam name="TMachineKey">设备的ID类型</typeparam>
/// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="QueryDataFunc">处理数据的函数,输入返回读数据的定义和值,输出写数据字典</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public async Task<MachineSetJobScheduler> Query<TMachineKey>(string queryId = null, Func<DataReturnDef, Dictionary<string, double>> QueryDataFunc = null) where TMachineKey : IEquatable<TMachineKey>
public async Task<MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> Query(string queryId = null, Func<DataReturnDef<TMachineKey, TReturnUnit>, Dictionary<string, TReturnUnit>> QueryDataFunc = null)
{
if (queryId == null) return new MachineSetJobScheduler(_scheduler, _trigger, _parentJobKey);
if (queryId == null) return new MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, _parentJobKey);
JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name);
IJobDetail job = JobBuilder.Create<MachineQueryDataJob<TMachineKey>>()
IJobDetail job = JobBuilder.Create<MachineQueryDataJob<TMachineKey, TReturnUnit>>()
.WithIdentity(jobKey)
.StoreDurably(true)
.Build();
@@ -317,14 +278,14 @@ namespace Modbus.Net
await _scheduler.AddJob(job, true);
return new MachineSetJobScheduler(_scheduler, _trigger, jobKey);
return new MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, jobKey);
}
}
/// <summary>
/// 写入数据任务
/// </summary>
public sealed class MachineSetJobScheduler
public sealed class MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit> where TMachineKey: IEquatable<TMachineKey> where TReturnUnit : struct where TMachineMethod : IMachineMethod
{
private IScheduler _scheduler;
@@ -354,17 +315,22 @@ namespace Modbus.Net
/// <param name="machine">写入数据的设备实例</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public async Task<MachineDealJobScheduler> To(string queryId, IMachineReflectionCall machine)
public async Task<MachineDealJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> To(string queryId, IMachineReflectionCall machine)
{
JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name);
IJobDetail job = JobBuilder.Create<MachineSetDataJob>()
IJobDetail job = JobBuilder.Create<MachineSetDataJob<TReturnUnit>>()
.WithIdentity(jobKey)
.StoreDurably(true)
.Build();
.Build();
string methodName = typeof(TMachineMethod).Name;
if (methodName.Substring(0, 14) != "IMachineMethod")
{
throw new FormatException("IMachineMethod Name not match format exception");
}
job.JobDataMap.Put("Machine", machine);
job.JobDataMap.Put("Function", "Datas");
job.JobDataMap.Put("Function", methodName.Remove(0,14));
var listener = _scheduler.ListenerManager.GetJobListener("Modbus.Net.DataQuery.Chain." + _trigger.Key.Name) as JobChainingJobListenerWithDataMap;
if (listener == null) throw new NullReferenceException("Listener " + "Modbus.Net.DataQuery.Chain." + _trigger.Key.Name + " is null");
@@ -372,7 +338,7 @@ namespace Modbus.Net
await _scheduler.AddJob(job, true);
return new MachineDealJobScheduler(_scheduler, _trigger, jobKey);
return new MachineDealJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, jobKey);
}
/// <summary>
@@ -382,9 +348,9 @@ namespace Modbus.Net
/// <param name="machine">要获取数据的设备实例</param>
/// <param name="machineDataType">获取数据的方式</param>
/// <returns></returns>
public async Task<MachineQueryJobScheduler> From(string queryId, IMachineReflectionCall machine, MachineDataType machineDataType)
public async Task<MachineQueryJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> From(string queryId, IMachineReflectionCall machine, MachineDataType machineDataType)
{
return await new MachineGetJobScheduler(_scheduler, _trigger, _parentJobKey).From(queryId, machine, machineDataType);
return await new MachineGetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, _parentJobKey).From(queryId, machine, machineDataType);
}
/// <summary>
@@ -400,7 +366,7 @@ namespace Modbus.Net
/// <summary>
/// 处理写返回任务
/// </summary>
public sealed class MachineDealJobScheduler
public sealed class MachineDealJobScheduler<TMachineMethod, TMachineKey, TReturnUnit> where TMachineKey : IEquatable<TMachineKey> where TReturnUnit : struct where TMachineMethod : IMachineMethod
{
private IScheduler _scheduler;
@@ -423,7 +389,6 @@ namespace Modbus.Net
_parentJobKey = parentJobKey;
}
/// <summary>
/// 处理写返回
/// </summary>
@@ -432,22 +397,9 @@ namespace Modbus.Net
/// <param name="onFailure">失败回调方法参数为设备ID</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public async Task<MachineSetJobScheduler> Deal(string queryId = null, Func<string, Task> onSuccess = null, Func<string, int, string, Task> onFailure = null)
public async Task<MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>> Deal(string queryId = null, Func<string, Task> onSuccess = null, Func<string, int, string, Task> onFailure = null)
{
return await Deal<string>(queryId, onSuccess, onFailure);
}
/// <summary>
/// 处理写返回
/// </summary>
/// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="onSuccess">成功回调方法参数为设备ID</param>
/// <param name="onFailure">失败回调方法参数为设备ID</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public async Task<MachineSetJobScheduler> Deal<TMachineKey>(string queryId = null, Func<string, Task> onSuccess = null, Func<string, int, string, Task> onFailure = null) where TMachineKey : IEquatable<TMachineKey>
{
if (queryId == null) return new MachineSetJobScheduler(_scheduler, _trigger, _parentJobKey);
if (queryId == null) return new MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, _parentJobKey);
JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name);
IJobDetail job = JobBuilder.Create<MachineDealDataJob<TMachineKey>>()
@@ -464,14 +416,14 @@ namespace Modbus.Net
await _scheduler.AddJob(job, true);
return new MachineSetJobScheduler(_scheduler, _trigger, jobKey);
return new MachineSetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>(_scheduler, _trigger, jobKey);
}
}
/// <summary>
/// 获取数据任务
/// </summary>
public class MachineGetDataJob : IJob
public class MachineGetDataJob<TReturnUnit> : IJob where TReturnUnit : struct
{
/// <inheritdoc />
public async Task Execute(IJobExecutionContext context)
@@ -482,7 +434,7 @@ namespace Modbus.Net
context.JobDetail.JobDataMap.TryGetValue("Machine", out machine);
context.JobDetail.JobDataMap.TryGetValue("DataType", out machineDataType);
context.JobDetail.JobDataMap.TryGetValue("Function", out callFunction);
var values = await (machine as IMachineReflectionCall)!.InvokeGet<Dictionary<string, ReturnUnit>>((string)callFunction, new object[] { (MachineDataType)machineDataType });
var values = await (machine as IMachineReflectionCall)!.InvokeGet<Dictionary<string, ReturnUnit<TReturnUnit>>>((string)callFunction, new object[] { (MachineDataType)machineDataType });
context.JobDetail.JobDataMap.Put("Value", values);
await context.Scheduler.AddJob(context.JobDetail, true, false);
@@ -492,8 +444,7 @@ namespace Modbus.Net
/// <summary>
/// 处理数据任务
/// </summary>
/// <typeparam name="TMachineKey"></typeparam>
public class MachineQueryDataJob<TMachineKey> : IJob where TMachineKey : IEquatable<TMachineKey>
public class MachineQueryDataJob<TMachineKey, TReturnUnit> : IJob where TMachineKey : IEquatable<TMachineKey> where TReturnUnit : struct
{
/// <inheritdoc />
public async Task Execute(IJobExecutionContext context)
@@ -504,11 +455,11 @@ namespace Modbus.Net
context.JobDetail.JobDataMap.TryGetValue("Machine", out machine);
context.JobDetail.JobDataMap.TryGetValue("Value", out values);
context.JobDetail.JobDataMap.TryGetValue("QueryMethod", out QueryMethod);
Func<DataReturnDef, Dictionary<string, double>> QueryMethodDispatch = (Func<DataReturnDef, Dictionary<string, double>>)QueryMethod;
Func<DataReturnDef<TMachineKey, TReturnUnit>, Dictionary<string, TReturnUnit>> QueryMethodDispatch = (Func<DataReturnDef<TMachineKey, TReturnUnit>, Dictionary<string, TReturnUnit>>)QueryMethod;
if (QueryMethod != null && values != null)
{
context.JobDetail.JobDataMap.Put("SetValue", QueryMethodDispatch(new DataReturnDef() { MachineId = machine == null ? null : ((IMachineProperty<TMachineKey>)machine).GetMachineIdString(), ReturnValues = (ReturnStruct<Dictionary<string, ReturnUnit>>)values }));
context.JobDetail.JobDataMap.Put("SetValue", QueryMethodDispatch(new DataReturnDef<TMachineKey, TReturnUnit>() { MachineId = machine == null ? default : ((IMachineProperty<TMachineKey>)machine).Id, ReturnValues = (ReturnStruct<Dictionary<string, ReturnUnit<TReturnUnit>>>)values }));
await context.Scheduler.AddJob(context.JobDetail, true, false);
}
}
@@ -517,7 +468,7 @@ namespace Modbus.Net
/// <summary>
/// 写数据任务
/// </summary>
public class MachineSetDataJob : IJob
public class MachineSetDataJob<TReturnUnit> : IJob where TReturnUnit : struct
{
/// <inheritdoc />
public async Task Execute(IJobExecutionContext context)
@@ -533,7 +484,9 @@ namespace Modbus.Net
context.JobDetail.JobDataMap.TryGetValue("SetValue", out valuesSet);
context.JobDetail.JobDataMap.TryGetValue("Function", out callFunction);
if (valuesSet == null && values != null)
valuesSet = ((ReturnStruct<Dictionary<string, ReturnUnit>>)values).Datas.MapGetValuesToSetValues();
{
valuesSet = ((ReturnStruct<Dictionary<string, ReturnUnit<TReturnUnit>>>)values).Datas.MapGetValuesToSetValues();
}
if (valuesSet == null)
{
@@ -565,11 +518,11 @@ namespace Modbus.Net
ReturnStruct<bool> successValue = (ReturnStruct<bool>)success;
if (successValue.IsSuccess == true && onSuccess != null)
{
await ((Func<string, Task>)onSuccess)(((IMachineProperty<TMachineKey>)machine).GetMachineIdString());
await ((Func<TMachineKey, Task>)onSuccess)(((IMachineProperty<TMachineKey>)machine).Id);
}
if (successValue.IsSuccess == false && onFailure != null)
{
await ((Func<string, int, string, Task>)onFailure)(((IMachineProperty<TMachineKey>)machine).GetMachineIdString(), successValue.ErrorCode, successValue.ErrorMsg);
await ((Func<TMachineKey, int, string, Task>)onFailure)(((IMachineProperty<TMachineKey>)machine).Id, successValue.ErrorCode, successValue.ErrorMsg);
}
context.JobDetail.JobDataMap.Remove("Success");

View File

@@ -9,7 +9,7 @@ namespace Modbus.Net
/// <summary>
/// 多设备任务调度器
/// </summary>
public sealed class MultipleMachinesJobScheduler
public sealed class MultipleMachinesJobScheduler<TMachineMethod, TMachineKey, TReturnUnit> where TMachineKey: IEquatable<TMachineKey> where TReturnUnit : struct where TMachineMethod : IMachineMethod
{
private static int _machineCount = 0;
@@ -21,7 +21,7 @@ namespace Modbus.Net
/// <param name="count">重复次数负数为无限循环0为执行一次</param>
/// <param name="intervalSecond">间隔秒数</param>
/// <returns></returns>
public static ParallelLoopResult RunScheduler<TKey>(IEnumerable<IMachine<TKey>> machines, Func<IMachine<TKey>, MachineGetJobScheduler, Task> machineJobTemplate, int count = 0, int intervalSecond = 1) where TKey : IEquatable<TKey>
public static ParallelLoopResult RunScheduler(IEnumerable<IMachine<TMachineKey>> machines, Func<IMachine<TMachineKey>, MachineGetJobScheduler<TMachineMethod, TMachineKey, TReturnUnit>, Task> machineJobTemplate, int count = 0, int intervalSecond = 1)
{
_machineCount = machines.Count();
return Parallel.ForEach(machines, (machine, state, index) =>
@@ -29,25 +29,12 @@ namespace Modbus.Net
Task.Factory.StartNew(async () =>
{
Thread.Sleep((int)(intervalSecond * 1000.0 / _machineCount * index));
var getJobScheduler = await MachineJobSchedulerCreator.CreateScheduler("Trigger" + index, count, intervalSecond);
var getJobScheduler = await MachineJobSchedulerCreator<TMachineMethod, TMachineKey, TReturnUnit>.CreateScheduler("Trigger" + index, count, intervalSecond);
await machineJobTemplate(machine, getJobScheduler);
});
});
}
/// <summary>
/// 创建设备调度器
/// </summary>
/// <param name="machines">设备的集合</param>
/// <param name="machineJobTemplate">设备的运行模板</param>
/// <param name="count">重复次数负数为无限循环0为执行一次</param>
/// <param name="intervalSecond">间隔秒数</param>
/// <returns></returns>
public static ParallelLoopResult RunScheduler(IEnumerable<IMachine<string>> machines, Func<IMachine<string>, MachineGetJobScheduler, Task> machineJobTemplate, int count = 0, int intervalSecond = 1)
{
return RunScheduler<string>(machines, machineJobTemplate, count, intervalSecond);
}
/// <summary>
/// 取消任务
/// </summary>
@@ -56,7 +43,7 @@ namespace Modbus.Net
{
return Parallel.For(0, _machineCount, async index =>
{
await MachineJobSchedulerCreator.CancelJob("Trigger" + index);
await MachineJobSchedulerCreator<TMachineMethod, TMachineKey, TReturnUnit>.CancelJob("Trigger" + index);
});
}
}

View File

@@ -47,7 +47,7 @@ namespace Modbus.Net
var bytesExtend =
Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend"))
as
IProtocolLinkerBytesExtend;
IProtocolLinkerBytesExtend<byte[], byte[]>;
return bytesExtend?.BytesExtend(content);
}
@@ -62,7 +62,7 @@ namespace Modbus.Net
var bytesExtend =
Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend"))
as
IProtocolLinkerBytesExtend;
IProtocolLinkerBytesExtend<byte[], byte[]>;
return bytesExtend?.BytesDecact(content);
}

View File

@@ -4,13 +4,6 @@ using System.Linq;
namespace Modbus.Net
{
/// <summary>
/// 地址组合器,组合后的每一组地址将只需一次向设备进行通讯
/// </summary>
public abstract class AddressCombiner : AddressCombiner<string>
{
}
/// <summary>
/// 地址组合器,组合后的每一组地址将只需一次向设备进行通讯
/// </summary>
@@ -24,22 +17,6 @@ namespace Modbus.Net
public abstract IEnumerable<CommunicationUnit<TKey>> Combine(IEnumerable<AddressUnit<TKey>> addresses);
}
/// <summary>
/// 连续的地址将组合成一组,向设备进行通讯
/// </summary>
public class AddressCombinerContinus : AddressCombinerContinus<string>
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="addressTranslator">地址转换器</param>
/// <param name="maxLength">单个发送协议允许的数据最长长度(字节)</param>
public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength)
: base(addressTranslator, maxLength)
{
}
}
/// <summary>
/// 连续的地址将组合成一组,向设备进行通讯
/// </summary>
@@ -226,13 +203,6 @@ namespace Modbus.Net
}
}
/// <summary>
/// 单个地址变为一组,每一个地址都进行一次查询
/// </summary>
public class AddressCombinerSingle : AddressCombinerSingle<string>
{
}
/// <summary>
/// 单个地址变为一组,每一个地址都进行一次查询
/// </summary>
@@ -269,23 +239,6 @@ namespace Modbus.Net
public int GapNumber { get; set; }
}
/// <summary>
/// 可以调过多少数量的地址,把两个地址段变为一组通讯
/// </summary>
public class AddressCombinerNumericJump : AddressCombinerNumericJump<string>
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="jumpByteCount">需要跳过的字节个数</param>
/// <param name="maxLength">单个协议允许的数据最长长度(字节)</param>
/// <param name="addressTranslator">地址转换器</param>
public AddressCombinerNumericJump(int jumpByteCount, int maxLength, AddressTranslator addressTranslator)
: base(jumpByteCount, maxLength, addressTranslator)
{
}
}
/// <summary>
/// 可以调过多少数量的地址,把两个地址段变为一组通讯
/// </summary>
@@ -382,23 +335,6 @@ namespace Modbus.Net
}
}
/// <summary>
/// 可以调过多少百分比的地址,把两个地址段变为一个
/// </summary>
public class AddressCombinerPercentageJump : AddressCombinerPercentageJump<string>
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="percentage">允许跳过的字节数除以待组合的地址的字节数的百分比</param>
/// <param name="maxLength">单个协议允许的数据最大长度</param>
/// <param name="addressTranslator">地址转换器</param>
public AddressCombinerPercentageJump(double percentage, int maxLength, AddressTranslator addressTranslator)
: base(percentage, maxLength, addressTranslator)
{
}
}
/// <summary>
/// 可以调过多少百分比的地址,把两个地址段变为一个
/// </summary>

View File

@@ -32,45 +32,6 @@ namespace Modbus.Net
Id
}
/// <summary>
/// 设备
/// </summary>
public abstract class BaseMachine : BaseMachine<string, string>
{
/// <summary>
/// 构造器
/// </summary>
/// <param name="id">设备的ID号</param>
/// <param name="getAddresses">需要与设备通讯的地址</param>
protected BaseMachine(string id, IEnumerable<AddressUnit> getAddresses) : base(id, getAddresses)
{
}
/// <summary>
/// 构造器
/// </summary>
/// <param name="id">设备的ID号</param>
/// <param name="getAddresses">需要与设备通讯的地址</param>
/// <param name="keepConnect">是否保持连接</param>
protected BaseMachine(string id, IEnumerable<AddressUnit> getAddresses, bool keepConnect)
: base(id, getAddresses, keepConnect)
{
}
/// <summary>
/// 构造器
/// </summary>
/// <param name="id">设备的ID号</param>
/// <param name="getAddresses">需要与设备通讯的地址</param>
/// <param name="keepConnect">是否保持连接</param>
/// <param name="slaveAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
protected BaseMachine(string id, IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress,
byte masterAddress) : base(id, getAddresses, keepConnect, slaveAddress, masterAddress)
{
}
}
/// <summary>
/// 设备
/// </summary>
@@ -193,7 +154,7 @@ namespace Modbus.Net
/// 读取数据
/// </summary>
/// <returns>从设备读取的数据</returns>
public ReturnStruct<Dictionary<string, ReturnUnit>> GetDatas(MachineDataType getDataType)
public ReturnStruct<Dictionary<string, ReturnUnit<double>>> GetDatas(MachineDataType getDataType)
{
return AsyncHelper.RunSync(() => GetDatasAsync(getDataType));
}
@@ -203,17 +164,17 @@ namespace Modbus.Net
/// 读取数据
/// </summary>
/// <returns>从设备读取的数据</returns>
public async Task<ReturnStruct<Dictionary<string, ReturnUnit>>> GetDatasAsync(MachineDataType getDataType)
public async Task<ReturnStruct<Dictionary<string, ReturnUnit<double>>>> GetDatasAsync(MachineDataType getDataType)
{
try
{
var ans = new Dictionary<string, ReturnUnit>();
var ans = new Dictionary<string, ReturnUnit<double>>();
//检测并连接设备
if (!BaseUtility.IsConnected)
await BaseUtility.ConnectAsync();
//如果无法连接,终止
if (!BaseUtility.IsConnected) return
new ReturnStruct<Dictionary<string, ReturnUnit>>()
new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
{
Datas = null,
IsSuccess = false,
@@ -238,7 +199,7 @@ namespace Modbus.Net
//如果没有数据,终止
if (datas.IsSuccess == false || datas.Datas == null)
{
return new ReturnStruct<Dictionary<string, ReturnUnit>>()
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
{
Datas = null,
IsSuccess = false,
@@ -252,7 +213,7 @@ namespace Modbus.Net
BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName]))
{
return new ReturnStruct<Dictionary<string, ReturnUnit>>()
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
{
Datas = null,
IsSuccess = false,
@@ -310,14 +271,14 @@ namespace Modbus.Net
{
//如果没有数据返回空
if (datas.Datas.Length == 0)
ans.Add(key, new ReturnUnit
ans.Add(key, new ReturnUnit<double>
{
DeviceValue = null,
AddressUnit = address.MapAddressUnitTUnitKeyToAddressUnit(),
});
else
ans.Add(key,
new ReturnUnit
new ReturnUnit<double>
{
DeviceValue =
Convert.ToDouble(
@@ -334,7 +295,7 @@ namespace Modbus.Net
if (ErrorCount >= _maxErrorCount)
Disconnect();
return new ReturnStruct<Dictionary<string, ReturnUnit>>()
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
{
Datas = null,
IsSuccess = false,
@@ -350,7 +311,7 @@ namespace Modbus.Net
//返回数据
if (ans.All(p => p.Value.DeviceValue == null)) ans = null;
ErrorCount = 0;
return new ReturnStruct<Dictionary<string, ReturnUnit>>
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>
{
Datas = ans,
IsSuccess = true,
@@ -365,7 +326,7 @@ namespace Modbus.Net
if (ErrorCount >= _maxErrorCount)
Disconnect();
return new ReturnStruct<Dictionary<string, ReturnUnit>>()
return new ReturnStruct<Dictionary<string, ReturnUnit<double>>>()
{
Datas = null,
IsSuccess = false,
@@ -676,17 +637,17 @@ namespace Modbus.Net
}
/// <inheritdoc />
public async Task<ReturnStruct<T>> InvokeGet<T>(string functionName, object[] parameters)
public Task<ReturnStruct<T>> InvokeGet<T>(string functionName, object[] parameters)
{
var machineMethodType = GetType();
var machineMethod = this as IMachineMethod;
var machineSetMethod = machineMethodType.GetMethod("Get" + functionName + "Async");
var ans = machineSetMethod.Invoke(machineMethod, parameters);
return await (Task<ReturnStruct<T>>)ans;
return (Task<ReturnStruct<T>>)ans;
}
/// <inheritdoc />
public async Task<ReturnStruct<bool>> InvokeSet<T>(string functionName, object[] parameters, T datas)
public Task<ReturnStruct<bool>> InvokeSet<T>(string functionName, object[] parameters, T datas)
{
var machineMethodType = GetType();
var machineMethod = this as IMachineMethod;
@@ -695,7 +656,7 @@ namespace Modbus.Net
Array.Copy(parameters, allParams, parameters.Length);
allParams[parameters.Length] = datas;
var ans = machineSetMethod.Invoke(machineMethod, allParams);
return await (Task<ReturnStruct<bool>>)ans;
return (Task<ReturnStruct<bool>>)ans;
}
/// <summary>
@@ -716,15 +677,6 @@ namespace Modbus.Net
return BaseUtility.Disconnect();
}
/// <summary>
/// 获取设备的Id字符串格式
/// </summary>
/// <returns></returns>
public string GetMachineIdString()
{
return Id.ToString();
}
/// <summary>
/// 通过Id获取数据字段定义
/// </summary>
@@ -758,13 +710,6 @@ namespace Modbus.Net
}
}
/// <summary>
/// 通讯单元
/// </summary>
public class CommunicationUnit : CommunicationUnit<string>
{
}
/// <summary>
/// 通讯单元
/// </summary>
@@ -811,12 +756,12 @@ namespace Modbus.Net
/// <summary>
/// 返回的数据单元
/// </summary>
public class ReturnUnit
public class ReturnUnit<TReturn> where TReturn : struct
{
/// <summary>
/// 返回的数据
/// </summary>
public double? DeviceValue { get; set; }
public TReturn? DeviceValue { get; set; }
/// <summary>
/// 数据定义
@@ -906,34 +851,4 @@ namespace Modbus.Net
return Area.ToUpper() == other.Area.ToUpper() && Address == other.Address || Id.Equals(other.Id);
}
}
/// <summary>
/// AddressUnit扩展
/// </summary>
public static class AddressUnitExtend
{
/// <summary>
/// 映射泛型AddressUnit到字符串型AddressUnit
/// </summary>
/// <param name="addressUnit"></param>
/// <returns></returns>
public static AddressUnit MapAddressUnitTUnitKeyToAddressUnit<TUnitKey>(this AddressUnit<TUnitKey> addressUnit) where TUnitKey : IEquatable<TUnitKey>
{
return new AddressUnit()
{
Id = addressUnit.ToString(),
Area = addressUnit.Area,
Address = addressUnit.Address,
SubAddress = addressUnit.SubAddress,
DataType = addressUnit.DataType,
Zoom = addressUnit.Zoom,
DecimalPos = addressUnit.DecimalPos,
CommunicationTag = addressUnit.CommunicationTag,
Name = addressUnit.Name,
Unit = addressUnit.Unit,
CanWrite = addressUnit.CanWrite,
UnitExtend = addressUnit.UnitExtend
};
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Modbus.Net
@@ -14,13 +15,43 @@ namespace Modbus.Net
/// </summary>
/// <param name="getValues">获取的数据</param>
/// <returns>应该写入的数据</returns>
public static Dictionary<string, double> MapGetValuesToSetValues(this Dictionary<string, ReturnUnit> getValues)
public static Dictionary<string, TSend> MapGetValuesToSetValues<TSend>(this Dictionary<string, ReturnUnit<TSend>> getValues) where TSend : struct
{
if (getValues == null) return null;
return (from getValue in getValues
where getValue.Value.DeviceValue != null
select new KeyValuePair<string, double>(getValue.Key, getValue.Value.DeviceValue.Value)).ToDictionary(
select new KeyValuePair<string, TSend>(getValue.Key, getValue.Value.DeviceValue.Value)).ToDictionary(
p => p.Key, p => p.Value);
}
}
/// <summary>
/// AddressUnit扩展
/// </summary>
public static class AddressUnitExtend
{
/// <summary>
/// 映射泛型AddressUnit到字符串型AddressUnit
/// </summary>
/// <param name="addressUnit"></param>
/// <returns></returns>
public static AddressUnit MapAddressUnitTUnitKeyToAddressUnit<TUnitKey>(this AddressUnit<TUnitKey> addressUnit) where TUnitKey : IEquatable<TUnitKey>
{
return new AddressUnit()
{
Id = addressUnit.ToString(),
Area = addressUnit.Area,
Address = addressUnit.Address,
SubAddress = addressUnit.SubAddress,
DataType = addressUnit.DataType,
Zoom = addressUnit.Zoom,
DecimalPos = addressUnit.DecimalPos,
CommunicationTag = addressUnit.CommunicationTag,
Name = addressUnit.Name,
Unit = addressUnit.Unit,
CanWrite = addressUnit.CanWrite,
UnitExtend = addressUnit.UnitExtend
};
}
}
}

View File

@@ -8,7 +8,7 @@ namespace Modbus.Net
/// <summary>
/// 基本协议
/// </summary>
public abstract class BaseProtocol : BaseProtocol<byte[], byte[], ProtocolUnit, PipeUnit>
public abstract class BaseProtocol : BaseProtocol<byte[], byte[], ProtocolUnit<byte[], byte[]>, PipeUnit>
{
/// <summary>
/// 构造器
@@ -42,7 +42,7 @@ namespace Modbus.Net
/// <param name="content">输入信息的结构化描述</param>
/// <returns>输出信息的结构化描述</returns>
public override async Task<PipeUnit>
SendReceiveAsync(ProtocolUnit unit, IInputStruct content)
SendReceiveAsync(ProtocolUnit<byte[], byte[]> unit, IInputStruct content)
{
if (content != null)
{

View File

@@ -8,7 +8,7 @@ namespace Modbus.Net
/// <summary>
/// 管道单元
/// </summary>
public class PipeUnit : PipeUnit<byte[], byte[], IProtocolLinker<byte[], byte[]>, ProtocolUnit>
public class PipeUnit : PipeUnit<byte[], byte[], IProtocolLinker<byte[], byte[]>, ProtocolUnit<byte[], byte[]>>
{
/// <summary>
/// 构造函数
@@ -26,7 +26,7 @@ namespace Modbus.Net
/// <param name="protocolUnit">协议单元</param>
/// <param name="parameters">传递给输入结构的参数</param>
/// <param name="success">上次的管道是否成功执行</param>
protected PipeUnit(IProtocolLinker<byte[], byte[]> protocolLinker, ProtocolUnit protocolUnit, byte[] parameters,
protected PipeUnit(IProtocolLinker<byte[], byte[]> protocolLinker, ProtocolUnit<byte[], byte[]> protocolUnit, byte[] parameters,
bool success) : base(protocolLinker, protocolUnit, parameters, success)
{
}
@@ -44,7 +44,7 @@ namespace Modbus.Net
var content = inputStructCreator.Invoke(ReturnParams);
if (ProtocolLinker != null)
return new PipeUnit(ProtocolLinker, null,
await ProtocolLinker.SendReceiveAsync(ProtocolUnit.TranslateContent(endian, content)),
await ProtocolLinker.SendReceiveAsync(ProtocolUnit<byte[], byte[]>.TranslateContent(endian, content)),
true);
}
return new PipeUnit(ProtocolLinker, null, ReturnParams, false);
@@ -57,7 +57,7 @@ namespace Modbus.Net
/// <param name="inputStructCreator">构造输入结构的函数</param>
/// <returns>发送完成之后新的管道实例</returns>
public new async Task<PipeUnit> SendReceiveAsync(
ProtocolUnit unit,
ProtocolUnit<byte[], byte[]> unit,
Func<byte[], IInputStruct> inputStructCreator)
{
var receiveContent = await SendReceiveAsyncParamOut(unit, inputStructCreator);

View File

@@ -2,13 +2,6 @@
namespace Modbus.Net
{
/// <summary>
/// 协议单元
/// </summary>
public abstract class ProtocolUnit : ProtocolUnit<byte[], byte[]>
{
}
/// <summary>
/// 协议单元
/// </summary>

View File

@@ -27,19 +27,6 @@ public enum Endian
namespace Modbus.Net
{
/// <summary>
/// 基础Api入口
/// </summary>
public abstract class BaseUtility : BaseUtility<byte[], byte[], ProtocolUnit, PipeUnit>
{
/// <summary>
/// 构造器
/// </summary>
protected BaseUtility(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
{
}
}
/// <summary>
/// 基础Api入口
/// </summary>

View File

@@ -11,8 +11,4 @@
<ProjectReference Include="..\..\Modbus.Net\Modbus.Net\Modbus.Net.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Scripts\" />
</ItemGroup>
</Project>

View File

@@ -3,6 +3,8 @@ using Microsoft.AspNetCore.Mvc;
using Modbus.Net;
using Modbus.Net.Modbus;
using System.Diagnostics;
using MachineJobSchedulerCreator = Modbus.Net.MachineJobSchedulerCreator<Modbus.Net.IMachineMethodDatas, string, double>;
using ModbusMachine = Modbus.Net.Modbus.ModbusMachine<string, string>;
namespace AnyType.Controllers
{

View File

@@ -16,7 +16,7 @@ namespace CrossLamp.Controllers
_logger = logger;
}
private static BaseUtility? _utility = null;
private static IUtility? _utility = null;
public ActionResult Index()
{

View File

@@ -15,8 +15,8 @@ namespace TripleAdd.Controllers
_logger = logger;
}
private static BaseUtility? utility;
private static BaseMachine? machine;
private static IUtility? utility;
private static IMachine<string>? machine;
public ActionResult Index()
{
@@ -54,15 +54,15 @@ namespace TripleAdd.Controllers
{
if (machine == null)
{
machine = new ModbusMachine("1", ModbusType.Tcp, "192.168.0.161", new List<AddressUnit>()
machine = new ModbusMachine<string, string>("1", ModbusType.Tcp, "192.168.0.161", new List<AddressUnit>()
{
new AddressUnit() {Id = "1", Area = "4X", Address = 1, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
new AddressUnit() {Id = "2", Area = "4X", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
new AddressUnit() {Id = "3", Area = "4X", Address = 3, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
new AddressUnit() {Id = "4", Area = "4X", Address = 4, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
}, 2, 0);
machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator, 100000);
machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator, 100000);
machine.AddressCombiner = new AddressCombinerContinus<string>(machine.AddressTranslator, 100000);
machine.AddressCombinerSet = new AddressCombinerContinus<string>(machine.AddressTranslator, 100000);
}
var resultFormat = (await machine.GetDatasAsync(MachineDataType.CommunicationTag)).Datas.MapGetValuesToSetValues();
return SetValue(new ushort[4] { (ushort)resultFormat["Add1"], (ushort)resultFormat["Add2"], (ushort)resultFormat["Add3"], (ushort)resultFormat["Ans"] });

View File

@@ -6,16 +6,16 @@ namespace Modbus.Net.Tests
[TestClass]
public class EndianTest
{
private BaseMachine? _modbusTcpMachine;
private BaseMachine<string, string>? _modbusTcpMachine;
private BaseMachine? _modbusTcpMachine2;
private BaseMachine<string, string>? _modbusTcpMachine2;
[TestInitialize]
public void Init()
{
_modbusTcpMachine = new ModbusMachine("1", ModbusType.Tcp, "127.0.0.1", null, true, 1, 0);
_modbusTcpMachine = new ModbusMachine<string, string>("1", ModbusType.Tcp, "127.0.0.1", null, true, 1, 0);
_modbusTcpMachine2 = new ModbusMachine("2", ModbusType.Tcp, "127.0.0.1", null, true, 1, 0, Endian.LittleEndianLsb);
_modbusTcpMachine2 = new ModbusMachine<string, string>("2", ModbusType.Tcp, "127.0.0.1", null, true, 1, 0, Endian.LittleEndianLsb);
}
[TestMethod]

View File

@@ -44,7 +44,7 @@ namespace Modbus.Net.Tests
DataType = typeof(bool)
}
}, true, 2, 0);
var success = await baseMachine.GetMachineMethods<IMachineMethodData>().SetDatasAsync(
var success = await baseMachine.GetMachineMethods<IMachineMethodDatas>().SetDatasAsync(
MachineDataType.Address,
new Dictionary<string, double>
{
@@ -53,9 +53,9 @@ namespace Modbus.Net.Tests
}
});
Assert.AreEqual(success, true);
var datas = await baseMachine.GetMachineMethods<IMachineMethodData>().GetDatasAsync(MachineDataType.Address);
var datas = await baseMachine.GetMachineMethods<IMachineMethodDatas>().GetDatasAsync(MachineDataType.Address);
Assert.AreEqual(datas.Datas["0X 1.0"].DeviceValue, 1);
success = await baseMachine.GetMachineMethods<IMachineMethodData>().SetDatasAsync(
success = await baseMachine.GetMachineMethods<IMachineMethodDatas>().SetDatasAsync(
MachineDataType.Address,
new Dictionary<string, double>
{

View File

@@ -6,15 +6,15 @@ namespace Modbus.Net.Tests
[TestClass]
public class ModbusMultiStationTest
{
private BaseMachine? _modbusRtuMachine1;
private BaseMachine<string, string>? _modbusRtuMachine1;
private BaseMachine? _modbusRtuMachine2;
private BaseMachine<string, string>? _modbusRtuMachine2;
[TestInitialize]
public void Init()
{
_modbusRtuMachine1 = new ModbusMachine("1", ModbusType.Rtu, "COM1", null, true, 1, 0);
_modbusRtuMachine2 = new ModbusMachine("2", ModbusType.Rtu, "COM1", null, true, 2, 0);
_modbusRtuMachine1 = new ModbusMachine<string, string>("1", ModbusType.Rtu, "COM1", null, true, 1, 0);
_modbusRtuMachine2 = new ModbusMachine<string, string>("2", ModbusType.Rtu, "COM1", null, true, 2, 0);
}
[TestMethod]

View File

@@ -6,20 +6,20 @@ namespace Modbus.Net.Tests
[TestClass]
public class ModbusTest
{
private BaseMachine? _modbusTcpMachine;
private BaseMachine<string, string>? _modbusTcpMachine;
private BaseMachine? _modbusRtuMachine;
private BaseMachine<string, string>? _modbusRtuMachine;
private BaseMachine? _modbusAsciiMachine;
private BaseMachine<string, string>? _modbusAsciiMachine;
[TestInitialize]
public void Init()
{
_modbusTcpMachine = new ModbusMachine("1", ModbusType.Tcp, "192.168.3.10", null, true, 2, 0);
_modbusTcpMachine = new ModbusMachine<string, string>("1", ModbusType.Tcp, "192.168.3.10", null, true, 2, 0);
_modbusRtuMachine = new ModbusMachine("2", ModbusType.Rtu, "COM5", null, true, 2, 0);
_modbusRtuMachine = new ModbusMachine<string, string>("2", ModbusType.Rtu, "COM5", null, true, 2, 0);
_modbusAsciiMachine = new ModbusMachine("3", ModbusType.Ascii, "COM5", null, true, 2, 0);
_modbusAsciiMachine = new ModbusMachine<string, string>("3", ModbusType.Ascii, "COM5", null, true, 2, 0);
}
[TestMethod]

View File

@@ -6,12 +6,12 @@ namespace Modbus.Net.Tests
[TestClass]
public class SiemensTest
{
private BaseMachine? _siemensTcpMachine;
private BaseMachine<string, string>? _siemensTcpMachine;
[TestInitialize]
public void Init()
{
_siemensTcpMachine = new SiemensMachine("1", SiemensType.Tcp, "192.168.3.10", SiemensMachineModel.S7_1200, null, true, 2, 0);
_siemensTcpMachine = new SiemensMachine<string, string>("1", SiemensType.Tcp, "192.168.3.10", SiemensMachineModel.S7_1200, null, true, 2, 0);
}
[TestMethod]