diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs
index e704324..bc01a23 100644
--- a/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs
+++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -27,7 +26,7 @@ namespace Modbus.Net.HJ212
else
{
ProtocolLinker = new HJ212ProtocolLinker(ip, int.Parse(ConfigurationReader.GetValueDirect("TCP:" + ip, "HJ212Port") ?? ConfigurationReader.GetValueDirect("TCP:Modbus", "HJ212Port") ?? "443"));
- }
+ }
}
///
diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs
index c006b2a..26a09c0 100644
--- a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs
+++ b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs
@@ -25,7 +25,7 @@ namespace Modbus.Net.HJ212
Array.Copy(lengthCalc, 0, newFormat, 0, 6);
//Modbus/Rtu协议扩张,增加CRC校验
var crc = new byte[2];
- Crc16.GetInstance().GetCRC(content, ref crc);
+ Crc16.GetInstance().GetCRC(content, ref crc);
string crcString = BitConverter.ToString(crc).Replace("-", string.Empty);
crcString = "&&" + crcString;
var crcCalc = Encoding.ASCII.GetBytes(crcString);
diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs
index f8334e6..3b7f7cc 100644
--- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs
+++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs
@@ -169,4 +169,9 @@ namespace Modbus.Net.Modbus
return newContent.ToArray();
}
}
+
+ public class ModbusRtuProtocolReceiverBytesExtend : ModbusRtuProtocolLinkerBytesExtend
+ {
+
+ }
}
\ No newline at end of file
diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolReceiver.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolReceiver.cs
new file mode 100644
index 0000000..40ae8d8
--- /dev/null
+++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolReceiver.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Modbus.Net.Modbus
+{
+ public class ModbusRtuProtocolReceiver : ProtocolReceiver
+ {
+ public ModbusRtuProtocolReceiver(string com, int slaveAddress)
+ : base(com, slaveAddress)
+ {
+
+ }
+
+ protected override Func DataExplain
+ {
+ get
+ {
+ return receiveBytes =>
+ {
+ var writeContent = receiveBytes.Length > 6 ? new byte[receiveBytes.Length - 7] : null;
+ if (receiveBytes.Length > 6) Array.Copy(receiveBytes, 7, writeContent, 0, receiveBytes.Length - 7);
+ return new ReceiveDataDef()
+ {
+ SlaveAddress = receiveBytes[0],
+ FunctionCode = receiveBytes[1],
+ StartAddress = (ushort)(receiveBytes[2] * 256 + receiveBytes[3]),
+ Count = (ushort)(receiveBytes[4] * 256 + receiveBytes[5]),
+ WriteByteCount = (byte)(receiveBytes.Length > 6 ? receiveBytes[6] : 0),
+ WriteContent = writeContent
+ };
+ };
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs
index b7293ce..d13f8b3 100644
--- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs
+++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs
@@ -292,12 +292,13 @@ namespace Modbus.Net.Modbus
var outputStruct = await
Wrapper.SendReceiveAsync(Wrapper[typeof(WriteDataModbusProtocol)],
inputStruct);
+ var ans = outputStruct?.WriteCount * 2 == BigEndianLsbValueHelper.Instance.ObjectArrayToByteArray(setContents).Length;
return new ReturnStruct()
{
- Datas = outputStruct?.WriteCount == setContents.Length,
- IsSuccess = outputStruct?.WriteCount == setContents.Length,
- ErrorCode = outputStruct?.WriteCount == setContents.Length ? 0 : -2,
- ErrorMsg = outputStruct?.WriteCount == setContents.Length ? "" : "Data length mismatch"
+ Datas = ans,
+ IsSuccess = ans,
+ ErrorCode = ans ? 0 : -2,
+ ErrorMsg = ans ? "" : "Data length mismatch"
};
}
catch (ModbusProtocolErrorException e)
diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtilityServer.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtilityServer.cs
new file mode 100644
index 0000000..5c4c258
--- /dev/null
+++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtilityServer.cs
@@ -0,0 +1,7 @@
+namespace Modbus.Net.Modbus
+{
+ public class ModbusUtilityServer
+ {
+
+ }
+}
diff --git a/Modbus.Net/Modbus.Net.sln b/Modbus.Net/Modbus.Net.sln
index 5b176af..f3312da 100644
--- a/Modbus.Net/Modbus.Net.sln
+++ b/Modbus.Net/Modbus.Net.sln
@@ -49,7 +49,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.HJ212", "Modbus.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.CodeGenerator", "Modbus.Net.CodeGenerator\Modbus.Net.CodeGenerator.csproj", "{D3210531-BA79-49B2-9F99-09FD0E1627B6}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MachineJob.CodeGenerator", "..\Samples\MachineJob.CodeGenerator\MachineJob.CodeGenerator.csproj", "{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MachineJob.CodeGenerator", "..\Samples\MachineJob.CodeGenerator\MachineJob.CodeGenerator.csproj", "{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ModbusTcpToRtu", "..\Samples\ModbusTcpToRtu\ModbusTcpToRtu.csproj", "{9CA7E35C-B5BC-4743-8732-1D8912AA12D8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleModbusRtuServer", "..\Samples\SampleModbusRtuServer\SampleModbusRtuServer.csproj", "{CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -211,6 +215,22 @@ Global
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|Any CPU.Build.0 = Release|Any CPU
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|x64.ActiveCfg = Release|Any CPU
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|x64.Build.0 = Release|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Debug|x64.Build.0 = Debug|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Release|x64.ActiveCfg = Release|Any CPU
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8}.Release|x64.Build.0 = Release|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Debug|x64.Build.0 = Debug|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Release|x64.ActiveCfg = Release|Any CPU
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -222,6 +242,8 @@ Global
{AA3A42D2-0502-41D3-929A-BAB729DF07D6} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
{414956B8-DBD4-414C-ABD3-565580739646} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
{7337BC9A-ED07-463D-8FCD-A82896CEC6BE} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
+ {9CA7E35C-B5BC-4743-8732-1D8912AA12D8} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
+ {CB85D4B3-EEA2-431F-A47F-1DE7FB0A4802} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF00D64E-3C70-474A-8A81-E9E48017C4B5}
diff --git a/Modbus.Net/Modbus.Net/Configuration/ConfigurationReader.cs b/Modbus.Net/Modbus.Net/Configuration/ConfigurationReader.cs
index 6829f81..fd670a4 100644
--- a/Modbus.Net/Modbus.Net/Configuration/ConfigurationReader.cs
+++ b/Modbus.Net/Modbus.Net/Configuration/ConfigurationReader.cs
@@ -41,6 +41,20 @@ namespace Modbus.Net
return ans;
}
+ public static ContentType? GetContent(string path, string key) where ContentType : class
+ {
+ var root = configuration.GetSection("Modbus.Net");
+ var firstColon = path.IndexOf(":");
+ while (firstColon != -1)
+ {
+ root = root?.GetSection(path.Substring(0, firstColon));
+ path = path.Substring(firstColon + 1);
+ firstColon = path.IndexOf(":");
+ }
+ root = root?.GetSection(path);
+ return root?.GetSection(key).Get();
+ }
+
///
/// 根据路径,直接查找路径上是否有该元素
///
diff --git a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs
index 5f83e7a..3936851 100644
--- a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs
+++ b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
+using System;
using System.Threading.Tasks;
namespace Modbus.Net
@@ -14,18 +15,10 @@ namespace Modbus.Net
///
public abstract class BaseConnector : IConnectorWithController where TParamIn : class
{
- ///
- /// 数据返回代理参数
- ///
- ///
- ///
- ///
- public delegate MessageReturnCallbackArgs MessageReturnDelegate(object sender, MessageReturnArgs args);
-
///
/// 数据返回代理
///
- public event MessageReturnDelegate MessageReturn;
+ public Func, MessageReturnCallbackArgs> MessageReturn { get; set; }
///
public void AddController(IController controller)
@@ -76,7 +69,7 @@ namespace Modbus.Net
///
protected TParamIn InvokeReturnMessage(TParamOut receiveMessage)
{
- return MessageReturn?.Invoke(this, new MessageReturnArgs { ReturnMessage = receiveMessage })?.SendMessage;
+ return MessageReturn?.Invoke(new MessageReturnArgs { ReturnMessage = receiveMessage })?.SendMessage;
}
}
}
\ No newline at end of file
diff --git a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs
index 5a149f7..1ed5696 100644
--- a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs
+++ b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs
@@ -278,7 +278,7 @@ namespace Modbus.Net
}
// Release unmanaged resources
Controller?.SendStop();
- ReceiveMsgThreadStop();
+ ReceiveMsgThreadStop();
Linkers?.Remove((_slave, _com));
logger.LogInformation("Com connector {ConnectionToken} Removed", _com);
if (Linkers?.Count(p => p.Item2 == _com) == 0)
@@ -288,12 +288,12 @@ namespace Modbus.Net
SerialPort?.Close();
}
SerialPort?.Dispose();
- logger.LogInformation("Com interface {Com} Disposed", _com);
+ logger.LogInformation("Com interface {Com} Disposed", _com);
if (Connectors.ContainsKey(_com))
{
Connectors[_com] = null;
Connectors.Remove(_com);
- }
+ }
}
}
@@ -500,7 +500,7 @@ namespace Modbus.Net
if (_receiveThread == null)
{
_receiveThreadCancel = new CancellationTokenSource();
- _receiveThread = Task.Run(async ()=>await ReceiveMessage(_receiveThreadCancel.Token), _receiveThreadCancel.Token);
+ _receiveThread = Task.Run(async () => await ReceiveMessage(_receiveThreadCancel.Token), _receiveThreadCancel.Token);
try
{
await _receiveThread;
diff --git a/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs b/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs
index 5447680..9eea657 100644
--- a/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs
+++ b/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs
@@ -32,18 +32,10 @@ namespace Modbus.Net
///
public abstract class EventHandlerConnector : ChannelHandlerAdapter, IConnectorWithController where TParamIn : class
{
- ///
- /// 数据返回代理参数
- ///
- ///
- ///
- ///
- public delegate MessageReturnCallbackArgs MessageReturnDelegate(object sender, MessageReturnArgs args);
-
///
/// 数据返回代理
///
- public event MessageReturnDelegate MessageReturn;
+ public Func, MessageReturnCallbackArgs> MessageReturn { get; set; }
///
public void AddController(IController controller)
@@ -84,7 +76,7 @@ namespace Modbus.Net
///
protected TParamIn InvokeReturnMessage(TParamOut receiveMessage)
{
- return MessageReturn?.Invoke(this, new MessageReturnArgs { ReturnMessage = receiveMessage })?.SendMessage;
+ return MessageReturn?.Invoke(new MessageReturnArgs { ReturnMessage = receiveMessage })?.SendMessage;
}
}
}
\ No newline at end of file
diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs
index bf784f6..a96a3de 100644
--- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs
+++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs
@@ -1,4 +1,3 @@
-using Quartz.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -106,8 +105,8 @@ namespace Modbus.Net
finally
{
_sendingThreadCancel.Dispose();
- _sendingThreadCancel = null;
- }
+ _sendingThreadCancel = null;
+ }
}
}
diff --git a/Modbus.Net/Modbus.Net/Controller/NoResponseController.cs b/Modbus.Net/Modbus.Net/Controller/NoResponseController.cs
index 5b686ef..ef90627 100644
--- a/Modbus.Net/Modbus.Net/Controller/NoResponseController.cs
+++ b/Modbus.Net/Modbus.Net/Controller/NoResponseController.cs
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
-using Quartz.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs b/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs
index d9942bf..79428f6 100644
--- a/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs
+++ b/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs
@@ -36,5 +36,34 @@ namespace Modbus.Net
}
throw new NotImplementedException(controllerName + " not found exception");
}
+
+ ///
+ /// 添加一个Controller
+ ///
+ /// ProtocolLinker实例
+ /// 参数
+ /// Connector实例
+ /// 如果没有发现控制器,报错
+ public static void AddController(this IProtocolReceiver protocolReceiver, object[] constructorParams, IConnector connector)
+ {
+ IController controller = null;
+ var assemblies = AssemblyHelper.GetAllLibraryAssemblies();
+ string controllerName = protocolReceiver.GetType().Name.Substring(0, protocolReceiver.GetType().Name.Length - 16) + "ResponseController";
+ foreach (var assembly in assemblies)
+ {
+ var controllerType = assembly.GetType(assembly.GetName().Name + "." + controllerName);
+ if (controllerType != null)
+ {
+ controller = assembly.CreateInstance(controllerType.FullName, true, BindingFlags.Default, null, constructorParams, null, null) as IController;
+ break;
+ }
+ }
+ if (controller != null)
+ {
+ ((IConnectorWithController)connector).AddController(controller);
+ return;
+ }
+ throw new NotImplementedException(controllerName + " not found exception");
+ }
}
}
diff --git a/Modbus.Net/Modbus.Net/Interface/IConnector.cs b/Modbus.Net/Modbus.Net/Interface/IConnector.cs
index d570a3a..48cf3dc 100644
--- a/Modbus.Net/Modbus.Net/Interface/IConnector.cs
+++ b/Modbus.Net/Modbus.Net/Interface/IConnector.cs
@@ -1,3 +1,4 @@
+using System;
using System.Threading.Tasks;
namespace Modbus.Net
@@ -5,8 +6,13 @@ namespace Modbus.Net
///
/// Эӽӿ
///
- public interface IConnector
+ public interface IConnector
{
+ ///
+ /// ݷش
+ ///
+ Func, MessageReturnCallbackArgs> MessageReturn { get; set; }
+
///
/// ʶConnectorӹؼ
///
diff --git a/Modbus.Net/Modbus.Net/Interface/IConnectorWithController.cs b/Modbus.Net/Modbus.Net/Interface/IConnectorWithController.cs
index 4fab028..2575da5 100644
--- a/Modbus.Net/Modbus.Net/Interface/IConnectorWithController.cs
+++ b/Modbus.Net/Modbus.Net/Interface/IConnectorWithController.cs
@@ -3,7 +3,7 @@
///
/// 基础的协议连接接口
///
- public interface IConnectorWithController : IConnector
+ public interface IConnectorWithController : IConnector
{
///
/// 增加传输控制器
diff --git a/Modbus.Net/Modbus.Net/Interface/IMachineServerMethod.cs b/Modbus.Net/Modbus.Net/Interface/IMachineServerMethod.cs
new file mode 100644
index 0000000..db400a6
--- /dev/null
+++ b/Modbus.Net/Modbus.Net/Interface/IMachineServerMethod.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Modbus.Net.Interface
+{
+ ///
+ /// Machine的数据读写接口
+ ///
+ public interface IMachineServerMethodDatas : IMachineMethod
+ {
+ ///
+ /// 从站发送事件
+ ///
+ event EventHandler ServerMessageEvent;
+
+ ///
+ /// 读取数据
+ ///
+ /// 从设备读取的数据
+ Task>>> ServerReadDatasAsync(MachineDataType getDataType);
+
+ ///
+ /// 写入数据
+ ///
+ /// 写入类型
+ /// 需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述
+ /// 是否写入成功
+ Task> ServerUploadDatasAsync(MachineDataType setDataType, Dictionary values);
+ }
+}
diff --git a/Modbus.Net/Modbus.Net/Interface/IProtocolReceiver.cs b/Modbus.Net/Modbus.Net/Interface/IProtocolReceiver.cs
new file mode 100644
index 0000000..9c00d97
--- /dev/null
+++ b/Modbus.Net/Modbus.Net/Interface/IProtocolReceiver.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Modbus.Net
+{
+ ///
+ /// 协议接收器接口
+ ///
+ /// 从Receiver传出的数据类型
+ /// 向Receiver传入的数据类型
+ public interface IProtocolReceiver
+ {
+ ///
+ /// 转发事件
+ ///
+ Func DispatchEvent { get; }
+
+ ///
+ /// 通讯字符串
+ ///
+ string ConnectionToken { get; }
+
+ ///
+ /// 设备是否连接
+ ///
+ bool IsConnected { get; }
+
+ ///
+ /// 连接设备
+ ///
+ /// 设备是否连接成功
+ Task ConnectAsync();
+
+ ///
+ /// 断开设备
+ ///
+ /// 设备是否断开成功
+ bool Disconnect();
+
+ ///
+ /// 接收并发送数据
+ ///
+ /// 接收协议的内容
+ /// 发送协议的内容
+ TParamIn ReceiveSend(TParamOut content);
+
+ ///
+ /// 接收并发送数据,不进行协议扩展和收缩,用于特殊协议
+ ///
+ /// 发送协议的内容
+ /// 接收协议的内容
+ TParamIn ReceiveSendWithoutExtAndDec(TParamOut content);
+
+ ///
+ /// 检查接收的数据是否正确
+ ///
+ /// 接收协议的内容
+ /// 协议是否是正确的
+ bool? CheckRight(TParamOut content);
+ }
+}
\ No newline at end of file
diff --git a/Modbus.Net/Modbus.Net/Interface/IUtilityServer.cs b/Modbus.Net/Modbus.Net/Interface/IUtilityServer.cs
new file mode 100644
index 0000000..5b48f40
--- /dev/null
+++ b/Modbus.Net/Modbus.Net/Interface/IUtilityServer.cs
@@ -0,0 +1,9 @@
+namespace Modbus.Net
+{
+ ///
+ /// Api入口的抽象
+ ///
+ public interface IUtilityServer : IUtilityProperty, IUtilityServerMethodDatas
+ {
+ }
+}
\ No newline at end of file
diff --git a/Modbus.Net/Modbus.Net/Interface/IUtilityServerMethod.cs b/Modbus.Net/Modbus.Net/Interface/IUtilityServerMethod.cs
new file mode 100644
index 0000000..0befef8
--- /dev/null
+++ b/Modbus.Net/Modbus.Net/Interface/IUtilityServerMethod.cs
@@ -0,0 +1,33 @@
+using System.Threading.Tasks;
+
+namespace Modbus.Net
+{
+ ///
+ /// Utility方法读写接口
+ ///
+ public interface IUtilityServerMethod
+ {
+ }
+
+ ///
+ /// Utility的数据读写接口
+ ///
+ public interface IUtilityServerMethodDatas : IUtilityServerMethod
+ {
+ ///
+ /// 获取数据
+ ///
+ /// 开始地址
+ /// 获取字节数个数
+ /// 接收到的byte数据
+ Task> GetServerDatasAsync(string startAddress, int getByteCount);
+
+ ///
+ /// 设置数据
+ ///
+ /// 开始地址
+ /// 设置数据
+ /// 是否设置成功
+ Task> SetServerDatasAsync(string startAddress, object[] setContents);
+ }
+}
diff --git a/Modbus.Net/Modbus.Net/Linker/ProtocolReceiver.cs b/Modbus.Net/Modbus.Net/Linker/ProtocolReceiver.cs
new file mode 100644
index 0000000..009aa0f
--- /dev/null
+++ b/Modbus.Net/Modbus.Net/Linker/ProtocolReceiver.cs
@@ -0,0 +1,216 @@
+using System;
+using System.IO.Ports;
+using System.Reflection;
+using System.Threading.Tasks;
+
+namespace Modbus.Net
+{
+ ///
+ /// 基本的协议连接器
+ ///
+ public abstract class ProtocolReceiver : ProtocolReceiver
+ {
+ protected ProtocolReceiver(string com, int slaveAddress, BaudRate? baudRate = null, Parity? parity = null, StopBits? stopBits = null, DataBits? dataBits = null, Handshake? handshake = null,
+ int? connectionTimeout = null, bool? isFullDuplex = null)
+ {
+ baudRate = Enum.Parse(baudRate != null ? baudRate.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "BaudRate"));
+ parity = Enum.Parse(parity != null ? parity.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "Parity"));
+ stopBits = Enum.Parse(stopBits != null ? stopBits.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "StopBits"));
+ dataBits = Enum.Parse(dataBits != null ? dataBits.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "DataBits"));
+ handshake = Enum.Parse(handshake != null ? handshake.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "Handshake"));
+ connectionTimeout = int.Parse(connectionTimeout != null ? connectionTimeout.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "ConnectionTimeout"));
+ isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "FullDuplex"));
+ BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate.Value, parity.Value, stopBits.Value, dataBits.Value, handshake.Value, connectionTimeout.Value, isFullDuplex.Value);
+ var noResponse = bool.Parse(ConfigurationReader.GetValue("COM:" + com, "NoResponse") ?? ConfigurationReader.GetValue("Controller", "NoResponse"));
+ if (noResponse)
+ {
+ ((IConnectorWithController)BaseConnector).AddController(new NoResponseController(int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime"))));
+ }
+ else
+ {
+ this.AddController(new object[2] { com, slaveAddress }, BaseConnector);
+ }
+ BaseConnector.MessageReturn = receiveMessage => new MessageReturnCallbackArgs() { SendMessage = ReceiveSend(receiveMessage.ReturnMessage) };
+ }
+
+ ///
+ /// 发送并接收数据
+ ///
+ /// 发送协议的内容
+ /// 接收协议的内容
+ public override byte[] ReceiveSend(byte[] content)
+ {
+ var checkRight = CheckRight(content);
+ if (checkRight == true)
+ {
+ var decBytes = BytesDecact(content);
+ var explainContent = DataExplain(decBytes);
+ var returnBytes = DataProcess(explainContent);
+ var extBytes = BytesExtend(returnBytes);
+ return extBytes;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// 协议内容扩展,发送时根据需要扩展
+ ///
+ /// 扩展前的基本协议内容
+ /// 扩展后的协议内容
+ public virtual byte[] BytesExtend(byte[] content)
+ {
+ //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
+ var bytesExtend =
+ Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend"))
+ as
+ IProtocolLinkerBytesExtend;
+ return bytesExtend?.BytesExtend(content);
+ }
+
+ ///
+ /// 协议内容缩减,接收时根据需要缩减
+ ///
+ /// 缩减前的完整协议内容
+ /// 缩减后的协议内容
+ public virtual byte[] BytesDecact(byte[] content)
+ {
+ //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
+ var bytesExtend =
+ Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend"))
+ as
+ IProtocolLinkerBytesExtend;
+ return bytesExtend?.BytesDecact(content);
+ }
+
+ ///
+ /// 检查接收的数据是否正确
+ ///
+ /// 接收协议的内容
+ /// 协议是否是正确的
+ public override bool? CheckRight(byte[] content)
+ {
+ if (content == null)
+ {
+ Disconnect();
+ return false;
+ }
+ if (content.Length == 0) return null;
+ return true;
+ }
+
+ protected abstract Func DataExplain { get; }
+
+ public Func DataProcess { get; set; } = null;
+ }
+
+ public abstract class ProtocolReceiver : IProtocolReceiver
+ where TParamIn : class
+ {
+ ///
+ /// 传输连接器
+ ///
+ protected IConnector BaseConnector;
+
+ ///
+ /// 连接设备
+ ///
+ /// 设备是否连接成功
+ public async Task ConnectAsync()
+ {
+ return await BaseConnector.ConnectAsync();
+ }
+
+ ///
+ /// 断开设备
+ ///
+ /// 设备是否断开成功
+ public bool Disconnect()
+ {
+ return BaseConnector.Disconnect();
+ }
+
+ ///
+ /// 通讯字符串
+ ///
+ public string ConnectionToken => BaseConnector.ConnectionToken;
+
+ ///
+ /// 设备是否连接
+ ///
+ public bool IsConnected => BaseConnector != null && BaseConnector.IsConnected;
+
+ public virtual Func DispatchEvent
+ {
+ get
+ {
+ return receiveContent => ReceiveSend(receiveContent);
+ }
+ }
+
+ ///
+ /// 发送并接收数据
+ ///
+ /// 发送协议的内容
+ /// 接收协议的内容
+ public virtual TParamIn ReceiveSend(TParamOut content)
+ {
+ return ReceiveSendWithoutExtAndDec(content);
+ }
+
+ ///
+ /// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议
+ ///
+ /// 发送协议的内容
+ /// 接收协议的内容
+ public virtual TParamIn ReceiveSendWithoutExtAndDec(TParamOut content)
+ {
+ var checkRight = CheckRight(content);
+ if (checkRight == true)
+ {
+ if (DispatchEvent != null)
+ {
+ var returnContent = DispatchEvent(content);
+ return returnContent;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// 检查接收的数据是否正确
+ ///
+ /// 接收协议的内容
+ /// 协议是否是正确的
+ public virtual bool? CheckRight(TParamOut content)
+ {
+ if (content != null) return true;
+ Disconnect();
+ return false;
+ }
+ }
+
+ public class ReceiveDataDef
+ {
+ public byte SlaveAddress { get; set; }
+
+ public byte FunctionCode { get; set; }
+
+ public ushort StartAddress { get; set; }
+
+ public ushort Count { get; set; }
+
+ public byte WriteByteCount { get; set; }
+
+ public byte[] WriteContent { get; set; }
+ }
+}
diff --git a/Modbus.Net/Modbus.Net/Machine/BaseServer.cs b/Modbus.Net/Modbus.Net/Machine/BaseServer.cs
new file mode 100644
index 0000000..f4f04a2
--- /dev/null
+++ b/Modbus.Net/Modbus.Net/Machine/BaseServer.cs
@@ -0,0 +1,6 @@
+namespace Modbus.Net.Machine
+{
+ public class BaseServer
+ {
+ }
+}
diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj
index 0be88e2..6e1eca0 100644
--- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj
+++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj
@@ -39,6 +39,7 @@
+
diff --git a/Modbus.Net/Modbus.Net/Utility/BaseUtilityServer.cs b/Modbus.Net/Modbus.Net/Utility/BaseUtilityServer.cs
new file mode 100644
index 0000000..396dc41
--- /dev/null
+++ b/Modbus.Net/Modbus.Net/Utility/BaseUtilityServer.cs
@@ -0,0 +1,120 @@
+using Microsoft.Extensions.Logging;
+using System.Threading.Tasks;
+
+namespace Modbus.Net
+{
+ ///
+ /// 基础Api入口
+ ///
+ public abstract class BaseUtilityServer : IUtilityServer
+ where TProtocolUnit : class, IProtocolFormatting where TParamOut : class
+ where TPipeUnit : PipeUnit, TProtocolUnit>
+ {
+ private static readonly ILogger> logger = LogProvider.CreateLogger>();
+
+ ///
+ /// 协议收发主体
+ ///
+ protected IProtocol Wrapper;
+
+ ///
+ /// 构造器
+ ///
+ protected BaseUtilityServer(byte slaveAddress, byte masterAddress)
+ {
+ SlaveAddress = slaveAddress;
+ MasterAddress = masterAddress;
+ AddressTranslator = new AddressTranslatorBase();
+ }
+
+ ///
+ /// 连接字符串
+ ///
+ protected string ConnectionString { get; set; }
+
+ ///
+ /// 从站号
+ ///
+ public byte SlaveAddress { get; set; }
+
+ ///
+ /// 主站号
+ ///
+ public byte MasterAddress { get; set; }
+
+ ///
+ /// 获取数据
+ ///
+ /// 开始地址
+ /// 获取字节数个数
+ /// 接收到的byte数据
+ public abstract Task> GetServerDatasAsync(string startAddress, int getByteCount);
+
+ ///
+ /// 设置数据
+ ///
+ /// 开始地址
+ /// 设置数据
+ /// 是否设置成功
+ public abstract Task> SetServerDatasAsync(string startAddress, object[] setContents);
+
+ ///
+ /// 协议是否遵循小端格式
+ ///
+ public abstract Endian Endian { get; }
+
+ ///
+ /// 设备是否已经连接
+ ///
+ public bool IsConnected => Wrapper?.ProtocolLinker != null && Wrapper.ProtocolLinker.IsConnected;
+
+ ///
+ /// 标识设备的连接关键字
+ ///
+ public string ConnectionToken
+ => Wrapper?.ProtocolLinker == null ? ConnectionString : Wrapper.ProtocolLinker.ConnectionToken;
+
+ ///
+ /// 地址翻译器
+ ///
+ public AddressTranslator AddressTranslator { get; set; }
+
+ ///
+ /// 连接设备
+ ///
+ /// 设备是否连接成功
+ public async Task ConnectAsync()
+ {
+ return await Wrapper.ConnectAsync();
+ }
+
+ ///
+ /// 断开设备
+ ///
+ /// 设备是否断开成功
+ public bool Disconnect()
+ {
+ return Wrapper.Disconnect();
+ }
+
+ ///
+ /// 返回Utility的方法集合
+ ///
+ /// Utility方法集合类型
+ /// Utility方法集合
+ public TUtilityMethod GetUtilityMethods() where TUtilityMethod : class, IUtilityMethod
+ {
+ if (this is TUtilityMethod)
+ {
+ return this as TUtilityMethod;
+ }
+ return null;
+ }
+
+ ///
+ /// 设置连接类型
+ ///
+ /// 连接类型
+ public abstract void SetConnectionType(int connectionType);
+ }
+}
\ No newline at end of file
diff --git a/Samples/MachineJob/Worker.cs b/Samples/MachineJob/Worker.cs
index 3eca9c2..1b6cb03 100644
--- a/Samples/MachineJob/Worker.cs
+++ b/Samples/MachineJob/Worker.cs
@@ -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 ans = new Dictionary();
- 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;
}
-
+
}
}
}
\ No newline at end of file
diff --git a/Samples/ModbusTcpToRtu/ConsoleLogProvider.cs b/Samples/ModbusTcpToRtu/ConsoleLogProvider.cs
new file mode 100644
index 0000000..f2507e0
--- /dev/null
+++ b/Samples/ModbusTcpToRtu/ConsoleLogProvider.cs
@@ -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("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();
+ }
+ }
+}
diff --git a/Samples/ModbusTcpToRtu/ModbusTcpToRtu.csproj b/Samples/ModbusTcpToRtu/ModbusTcpToRtu.csproj
new file mode 100644
index 0000000..573e877
--- /dev/null
+++ b/Samples/ModbusTcpToRtu/ModbusTcpToRtu.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net6.0
+ enable
+ enable
+ dotnet-ModbusTcpToRtu-b7b7d9ed-80ce-4790-86de-5c3cf21e0a2e
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/ModbusTcpToRtu/Program.cs b/Samples/ModbusTcpToRtu/Program.cs
new file mode 100644
index 0000000..9861b2a
--- /dev/null
+++ b/Samples/ModbusTcpToRtu/Program.cs
@@ -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();
+
+ services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(Log.Logger, true));
+ })
+ .Build();
+
+await host.RunAsync();
+
diff --git a/Samples/ModbusTcpToRtu/Worker.cs b/Samples/ModbusTcpToRtu/Worker.cs
new file mode 100644
index 0000000..29895a6
--- /dev/null
+++ b/Samples/ModbusTcpToRtu/Worker.cs
@@ -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, Modbus.Net.PipeUnit>;
+using MultipleMachinesJobScheduler = Modbus.Net.MultipleMachinesJobScheduler;
+
+namespace ModbusTcpToRtu
+{
+ public class Worker : BackgroundService
+ {
+ private readonly ILogger _logger;
+
+ private BaseUtility readUtility;
+
+ private BaseUtility writeUtility;
+
+ public Worker(ILogger 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>("Utility", "readwrite");
+
+ var readType = Enum.Parse(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(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.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.GroupEquals("Modbus.Net.DataQuery.Group." + triggerKey));
+ await scheduler.DeleteJobs(jobKeys);
+
+ var job = JobBuilder.Create()
+ .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)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