同步框架代码

master
smartwyy 6 months ago
parent eb04b0b759
commit 5c245778ea

@ -1,9 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net6.0;net6.0-windows</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DocumentationFile>bin\Debug\Common.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\Common.xml</DocumentationFile>
</PropertyGroup>
</Project>

@ -1,16 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<TargetFrameworks>net6.0;net6.0-windows</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DocumentationFile>bin\Debug\Entity.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\Entity.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.3.4" />
<PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.1.9" />

@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<TargetFrameworks>net6.0;net6.0-windows</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

@ -224,12 +224,12 @@ public static class BitUtls
{
if (length < 17)
{
int d = Byte2Int16(bytes, startBit, length);
int d = Byte2UInt16(bytes, startBit, length);
return (float)(d * factor);
}
else
{
var d = Byte2Int32(bytes, startBit, length);
var d = Byte2UInt32(bytes, startBit, length);
return (float)(d * factor);
}
}

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<ImportGroup Condition=" '$(TargetFramework)' == 'net6.0' AND '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)system.text.json\7.0.0\buildTransitive\net6.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\7.0.0\buildTransitive\net6.0\System.Text.Json.targets')" />
</ImportGroup>
<ImportGroup Condition=" '$(TargetFramework)' == 'net6.0-windows' AND '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)system.text.json\7.0.0\buildTransitive\net6.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\7.0.0\buildTransitive\net6.0\System.Text.Json.targets')" />
</ImportGroup>
</Project>

@ -0,0 +1,83 @@
using System.Collections.Concurrent;
namespace HybirdFrameworkDriver.Common;
public class MsgCache<T, TReq, TResp>
{
private readonly ConcurrentDictionary<string, MsgPair<TReq, TResp>> _dictionary = new();
private static readonly string MsgKey = "msg_";
public void Add(string key, dynamic value)
{
_dictionary[key] = value;
}
public bool TryGet(string key, out MsgPair<TReq, TResp>? value)
{
return _dictionary.TryGetValue(key, out value);
}
public void Remove(string key)
{
_dictionary.Remove(key, out var value);
}
public void AddByMsgId(int key, MsgPair<TReq, TResp> value)
{
_dictionary[MsgKey + key] = value;
}
public bool TryGetMsgId(int key, out MsgPair<TReq, TResp>? value)
{
return _dictionary.TryGetValue(MsgKey + key, out value);
}
public void RemoveMsgId(int key)
{
_dictionary.Remove(MsgKey + key, out var value);
}
}
public class MsgPair<TReq, TResp>
{
private readonly ManualResetEvent _lock = new(false);
private TReq? _req;
public TReq? Req
{
get => _req;
set
{
_req = value;
ClearResp();
}
}
private TResp? _resp;
public void ClearResp()
{
_resp = default;
}
public void SetResp(TResp? resp)
{
_resp = resp;
_lock.Set();
_lock.Reset();
}
public TResp? GetResp(TimeSpan? timeSpan = default)
{
if (timeSpan != null)
{
_lock.WaitOne(timeSpan.Value);
}
else
{
_lock.WaitOne();
}
return _resp;
}
}

@ -1,15 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net6.0;net6.0-windows</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DocumentationFile>bin\Debug\HybirdFrameworkDriver.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\HybirdFrameworkDriver.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autofac" Version="7.0.1"/>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0"/>

@ -12,7 +12,7 @@ public class ModbusTcpMaster
private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusTcpMaster));
private ModbusTcpNet ModbusTcpNet;
private ModbusTcpNet? ModbusTcpNet;
public string Ip { get; set; } = "127.0.0.1";
@ -23,6 +23,11 @@ public class ModbusTcpMaster
public int Duration { get; set; } = 1000;
public bool Connected { get; set; }
/// <summary>
/// 自动重连开关
/// </summary>
public bool AutoReConnect { get; set; }
public string connectId { get; set; }
public MyReadAction? ReadAction { get; set; }
@ -36,8 +41,8 @@ public class ModbusTcpMaster
public bool Connect()
{
Thread.Sleep(Duration);
GetLog().Info($"begin to connect {Ip}:{Port}");
try
{
if (ModbusTcpNet == null)
@ -55,12 +60,20 @@ public class ModbusTcpMaster
else
{
GetLog().Info($"connect {Ip}:{Port} failed {result.Message}");
if (AutoReConnect)
{
return Connect();
}
}
}
}
catch (Exception e)
{
GetLog().Error($"connect {Ip}:{Port} exception {e.Message}");
if (AutoReConnect)
{
return Connect();
}
}
return Connected;
@ -112,7 +125,7 @@ public class ModbusTcpMaster
return null;
}
public byte[]? BatchRead(int registerNo, int length)
public byte[]? BatchReadHolderRegister(int registerNo, int length)
{
OperateResult<byte[]> result = ModbusTcpNet.Read("x=3;" + registerNo, (ushort)length);
if (result.IsSuccess) return result.Content;
@ -120,6 +133,58 @@ public class ModbusTcpMaster
return null;
}
public byte[]? BatchReadInputRegister(int registerNo, int length)
{
OperateResult<byte[]> result = ModbusTcpNet.Read("x=4;" + registerNo, (ushort)length);
if (result.IsSuccess) return result.Content;
return null;
}
/// <summary>
/// 读取线圈,需要指定起始地址,如果富文本地址不指定,默认使用的功能码是 0x01<br />
/// To read the coil, you need to specify the start address. If the rich text address is not specified, the default function code is 0x01.
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <returns>带有成功标志的bool对象</returns>
public OperateResult<bool> ReadCoil(string address) => ModbusTcpNet.ReadBool(address);
/// <summary>
/// 批量的读取线圈,需要指定起始地址,读取长度,如果富文本地址不指定,默认使用的功能码是 0x01<br />
/// For batch reading coils, you need to specify the start address and read length. If the rich text address is not specified, the default function code is 0x01.
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <param name="length">读取长度</param>
/// <returns>带有成功标志的bool数组对象</returns>
public OperateResult<bool[]> ReadCoil(string address, ushort length)
{
return ModbusTcpNet.ReadBool(address, length);
}
/// <summary>
/// 读取输入线圈,需要指定起始地址,如果富文本地址不指定,默认使用的功能码是 0x02<br />
/// To read the input coil, you need to specify the start address. If the rich text address is not specified, the default function code is 0x02.
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <returns>带有成功标志的bool对象</returns>
public OperateResult<bool> ReadDiscrete(string address)
{
return ModbusTcpNet.ReadDiscrete(address);
}
/// <summary>
/// 批量的读取输入点,需要指定起始地址,读取长度,如果富文本地址不指定,默认使用的功能码是 0x02<br />
/// To read input points in batches, you need to specify the start address and read length. If the rich text address is not specified, the default function code is 0x02
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <param name="length">读取长度</param>
/// <returns>带有成功标志的bool数组对象</returns>
public OperateResult<bool[]> ReadDiscrete(string address, ushort length)
{
return ModbusTcpNet.ReadDiscrete(address, length);
}
public bool WriteValue<T>(ModbusProperty<T> property)
{
var value = property.Value;

@ -30,6 +30,6 @@ public class ModbusSession
public byte[]? Read(int registerNo, int length)
{
return ModbusTcpMaster.BatchRead(registerNo, length);
return ModbusTcpMaster.BatchReadHolderRegister(registerNo, length);
}
}

@ -2,6 +2,7 @@
using Autofac;
using Autofac.Core;
using DotNetty.Codecs;
using DotNetty.Common.Internal.Logging;
using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
@ -10,6 +11,8 @@ using DotNetty.Transport.Channels.Sockets;
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Autofac.Attribute;
using log4net;
using Microsoft.Extensions.Logging;
using LogLevel = DotNetty.Handlers.Logging.LogLevel;
namespace HybirdFrameworkDriver.TcpServer;
@ -28,8 +31,14 @@ public class TcpServer<TH, TD, TE> : IDisposable where TH : IChannelHandler
private int _port = 9000;
public LogLevel? LogLevel { get; set; }
public TcpServer()
{
if (LogLevel != null)
{
InternalLoggerFactory.DefaultFactory.AddProvider(new Log4NetProvider());
}
bossGroup = new MultithreadEventLoopGroup();
workerGroup = new MultithreadEventLoopGroup();
bootstrap = new ServerBootstrap();
@ -42,7 +51,10 @@ public class TcpServer<TH, TD, TE> : IDisposable where TH : IChannelHandler
{
var serverListenerHandler = new ServerListenerHandler<TH, TD, TE>();
var pipeline = channel.Pipeline;
pipeline.AddLast(new LoggingHandler(""));
if (LogLevel != null)
{
pipeline.AddLast(new LoggingHandler(LogLevel.Value));
}
pipeline.AddLast(serverListenerHandler);
pipeline.AddLast(new IdleStateHandler(0, 0, 180)); //检测空闲连接
//业务handler 这里是实际处理业务的Handler

@ -1,15 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net6.0;net6.0-windows</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DocumentationFile>bin\Debug\Repository.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\Repository.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SqlSugar.IOC" Version="2.0.0"/>
<PackageReference Include="SqlSugarCore" Version="5.1.4.115"/>

@ -1,15 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net6.0;net6.0-windows</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DocumentationFile>bin\Debug\Service.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\Service.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetty.Buffers" Version="0.7.5" />
<PackageReference Include="DotNetty.Codecs" Version="0.7.5" />

Loading…
Cancel
Save