Compare commits

..

14 Commits

Author SHA1 Message Date
Kimdiego2098
7ff777d178 更新版本 2024-02-25 14:48:23 +08:00
Kimdiego2098
861621189a 底层变量特性实体支持数组 2024-02-25 14:39:08 +08:00
Diego2098
dcc00e08fd 整理代码 2024-02-24 23:32:51 +08:00
Diego2098
a1b8a47d4b 更新示例 2024-02-24 22:43:49 +08:00
Diego2098
1fd6b5e239 更改动态变量类缓存 2024-02-24 21:45:59 +08:00
Diego2098
f91e45bf44 整理代码 2024-02-24 18:42:45 +08:00
Kimdiego2098
0675a45592 更新版本 2024-02-24 18:23:41 +08:00
Kimdiego2098
0c7c6ae451 s7协议首次CR请求时,判断方式错误 2024-02-24 18:23:10 +08:00
Diego2098
cf089e8c4c 更新版本 2024-02-24 17:19:09 +08:00
Diego2098
90928ac679 更新版本 2024-02-24 17:14:57 +08:00
Diego2098
3bbcf71784 整理代码 2024-02-24 17:12:23 +08:00
Diego2098
222734775d 整理代码 2024-02-24 16:32:47 +08:00
Diego2098
f23ee7a6e0 整理代码 2024-02-24 16:08:37 +08:00
Diego2098
5b075aa6d5 更新底层变量类,添加源代码生成方法 2024-02-24 14:39:53 +08:00
54 changed files with 1334 additions and 303 deletions

View File

@@ -6,7 +6,7 @@
<LangVersion>11.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>5.0.1.0</Version>
<Version>5.0.1.10</Version>
<Authors>Diego</Authors>
<Company>Diego</Company>
<Product>Diego</Product>

View File

@@ -14,7 +14,11 @@
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<OutputPath></OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugSymbols>True</DebugSymbols>
<DebugType>Embedded</DebugType>
<EmbedAllSources>True</EmbedAllSources>
</PropertyGroup>
<ItemGroup>
<None Include="$(SolutionDir)Foundation.props" Pack="true" PackagePath="\" />
</ItemGroup>

View File

@@ -11,7 +11,7 @@
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="SqlSugarCore.Dm" Version="1.3.0" />
<PackageReference Include="SqlSugarCore.Kdbndp" Version="7.4.0" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.142" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.143" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
<PackageReference Include="System.Text.Json" Version="8.0.2" />

View File

@@ -23,6 +23,7 @@ using NewLife;
using System.Reflection;
using ThingsGateway.Core.Extension;
using ThingsGateway.Core.Extension.Json;
namespace ThingsGateway.Components;
@@ -520,7 +521,7 @@ public partial class AppDataTable<TItem, SearchItem, AddItem, EditItem> : IAppDa
{
value = dt2.ToDefaultDateTimeFormat(AppService.TimezoneOffset);
}
keyValuePairs.Add(item, value?.ToString());
keyValuePairs.Add(item, value?.ToJsonString(true));
}
}
DetailModelPairs = keyValuePairs;

View File

@@ -13,41 +13,18 @@ using ThingsGateway.Foundation;
namespace ThingsGateway.Demo;
/// <inheritdoc/>
public class VariableDemo : IVariable
public class VariableDemo : VariableClass
{
/// <inheritdoc/>
public int? IntervalTime { get; set; }
/// <inheritdoc/>
public string? RegisterAddress { get; set; }
/// <inheritdoc/>
public int Index { get; set; }
/// <inheritdoc/>
public IThingsGatewayBitConverter ThingsGatewayBitConverter { get; set; }
/// <inheritdoc/>
public DataTypeEnum DataType { get; set; }
/// <inheritdoc/>
public object? Value { get; set; }
public override object? Value => _value;
private object _value;
public bool IsOnline { get; set; }
public string? LastErrorMessage => VariableSource?.LastErrorMessage;
public IVariableSource VariableSource { get; set; }
public OperResult SetValue(object value, DateTime dateTime = default, bool isOnline = false)
public override OperResult SetValue(object value, DateTime dateTime = default, bool isOnline = false)
{
Value = value ?? "null";
_value = value ?? "null";
IsOnline = isOnline;
return new();
}
public Task<OperResult> SetValueToDeviceAsync(string value, string? executive = null, CancellationToken cancellationToken = default)
{
return Task.FromResult(new OperResult());
}
}

View File

@@ -13,28 +13,6 @@ using ThingsGateway.Foundation;
namespace ThingsGateway.Demo;
/// <inheritdoc/>
public class VariableSourceDemo : IVariableSourceT<IVariable>
public class VariableSourceDemo : VariableSourceClass
{
/// <inheritdoc/>
public TimeTick IntervalTimeTick { get; set; }
/// <inheritdoc/>
public string RegisterAddress { get; set; }
/// <inheritdoc/>
public int Length { get; set; }
/// <inheritdoc/>
public string? LastErrorMessage { get; set; }
/// <inheritdoc/>
public ICollection<IVariable> VariableRunTimes { get; set; } = new List<IVariable>();
public TimeTick TimeTick { get; set; }
public void AddVariable(IVariable variable)
{
variable.VariableSource = this;
VariableRunTimes.Add(variable);
}
}

View File

@@ -12,7 +12,6 @@ using BlazorComponent;
using Microsoft.AspNetCore.Components;
using ThingsGateway.Components;
using ThingsGateway.Foundation;
using TouchSocket.Core;
@@ -25,7 +24,7 @@ public partial class AdapterDebugPage : AdapterDebugBase
/// <summary>
/// VariableRunTimes
/// </summary>
public List<IVariable> VariableRunTimes;
public List<VariableDemo> VariableRunTimes;
/// <summary>
/// MaxPack

View File

@@ -13,12 +13,8 @@ namespace ThingsGateway.Gateway.Application;
/// <summary>
/// 连读报文信息
/// </summary>
public class VariableSourceRead : IVariableSourceT<IVariable>
public class VariableSourceRead : IVariableSource
{
public VariableSourceRead()
{
}
/// <summary>
/// 读取地址,传入时需要去除额外信息
/// </summary>
@@ -27,7 +23,9 @@ public class VariableSourceRead : IVariableSourceT<IVariable>
/// <summary>
/// 需分配的变量列表
/// </summary>
public ICollection<IVariable> VariableRunTimes { get; private set; } = new List<IVariable>();
public IEnumerable<IVariable> VariableRunTimes => _variableRunTimes;
private List<IVariable> _variableRunTimes = new List<IVariable>();
/// <summary>
/// 间隔时间实现
@@ -37,7 +35,7 @@ public class VariableSourceRead : IVariableSourceT<IVariable>
public void AddVariable(IVariable variable)
{
variable.VariableSource = this;
VariableRunTimes.Add(variable);
_variableRunTimes.Add(variable);
}
/// <summary>

View File

@@ -5,6 +5,7 @@
@using Microsoft.AspNetCore.Authorization;
@using Microsoft.Extensions.DependencyInjection
@using System.Collections.Concurrent
@using Newtonsoft.Json.Linq
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Admin.Blazor
@using ThingsGateway.Core.Extension
@@ -76,6 +77,21 @@
<ItemColTemplate>
@switch (context.Header.Value)
{
case nameof(context.Item.Value):
case nameof(context.Item.RawValue):
case nameof(context.Item.LastSetValue):
@if (context.Header.CellClass?.Contains("text-truncate") == true)
{
<span title=@JToken.FromObject( context.Value)>
@JToken.FromObject(context.Value)
</span>
}
else
{
@context.Value
}
break;
case nameof(context.Item.IsOnline):
<EnableChip Value="context.Item.IsOnline" DisabledLabel=@AppService.I18n.T("离线") EnabledLabel=@AppService.I18n.T("在线")>
</EnableChip>
@@ -103,6 +119,7 @@
}
</ItemColTemplate>
</AppDataTable>

View File

@@ -108,6 +108,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OpcUa"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Dlt645", "plugin\ThingsGateway.Plugin.Dlt645\ThingsGateway.Plugin.Dlt645.csproj", "{96E46443-1F30-4CEB-BBD7-920DD59F1BB7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.SourceGenerator", "foundation\ThingsGateway.Foundation.SourceGenerator\src\ThingsGateway.Foundation.SourceGenerator.csproj", "{D87C13E8-F5E8-493B-9137-4B5B6FBC46D7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -266,6 +268,10 @@ Global
{96E46443-1F30-4CEB-BBD7-920DD59F1BB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96E46443-1F30-4CEB-BBD7-920DD59F1BB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96E46443-1F30-4CEB-BBD7-920DD59F1BB7}.Release|Any CPU.Build.0 = Release|Any CPU
{D87C13E8-F5E8-493B-9137-4B5B6FBC46D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D87C13E8-F5E8-493B-9137-4B5B6FBC46D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D87C13E8-F5E8-493B-9137-4B5B6FBC46D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D87C13E8-F5E8-493B-9137-4B5B6FBC46D7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -311,9 +317,10 @@ Global
{0D994CAE-42F3-4CDA-9132-94515D7EF40E} = {D43C0E54-5B4B-4F00-A782-CAB91782D284}
{6AB13A30-C2DD-479D-BBE3-7ACFC104A416} = {D43C0E54-5B4B-4F00-A782-CAB91782D284}
{96E46443-1F30-4CEB-BBD7-920DD59F1BB7} = {D43C0E54-5B4B-4F00-A782-CAB91782D284}
{D87C13E8-F5E8-493B-9137-4B5B6FBC46D7} = {267B2DEB-0207-4F52-94E4-A1FF6B19214D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {789BA852-9F20-4421-A555-E665A12587D1}
RESX_NeutralResourcesLanguage = zh-Hans
SolutionGuid = {789BA852-9F20-4421-A555-E665A12587D1}
EndGlobalSection
EndGlobal

View File

@@ -1,42 +0,0 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
using ThingsGateway.Foundation.Dlt645;
using TouchSocket.Core;
namespace ThingsGateway.Foundation
{
internal class Dlt645MasterTest
{
/// <summary>
/// 新建链路
/// </summary>
/// <returns></returns>
public IChannel GetChannel()
{
TouchSocketConfig touchSocketConfig = new TouchSocketConfig();
return touchSocketConfig.GetSerialPortWithOption(new("COM1")); //直接获取串口对象
//return touchSocketConfig.GetChannel(ChannelTypeEnum.SerialPortClient, null, null, new("COM1"));//通过链路枚举获取对象
}
/// <summary>
/// 新建协议对象
/// </summary>
/// <param name="channel"></param>
/// <returns></returns>
public IProtocol GetProtocol(IChannel channel)
{
var client = new Dlt645_2007Master(channel);
client.Station = "311111111114";//表号
return client;
}
}
}

View File

@@ -0,0 +1,79 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
using ThingsGateway.Foundation.Modbus;
using TouchSocket.Core;
namespace ThingsGateway.Foundation
{
internal class ModbusMasterTest
{
private static ModbusMaster GetMaster()
{
var clientConfig = new TouchSocketConfig();
clientConfig.ConfigureContainer(a => a.AddConsoleLogger());
//创建通道也可以通过TouchSocketConfig.GetChannel扩展获取
var clientChannel = clientConfig.GetTcpClientWithIPHost("tcp://127.0.0.1:502");
//var clientChannel = clientConfig.GetSerialPortWithOption("COM1");
//clientChannel.Logger.LogLevel = LogLevel.Trace;
ModbusMaster modbusMaster = new(clientChannel)
{
//modbus协议格式
ModbusType = Modbus.ModbusTypeEnum.ModbusRtu,
//ModbusType = Modbus.ModbusTypeEnum.ModbusTcp,
};
return modbusMaster;
}
public static void Test()
{
using ModbusMaster modbusMaster = GetMaster();
//构造实体类对象,传入协议对象与连读打包的最大数量
ModbusVariable modbusVariable = new(modbusMaster, 100);
Test(modbusVariable, new ushort[] { 1, 2 });
Console.WriteLine(modbusVariable.ToJsonString());
Console.ReadLine();
static void Test(ModbusVariable modbusVariable, object value)
{
//源生成WriteData1与WriteData2方法(Write{属性名称})
modbusVariable.WriteData3("123", default);
modbusVariable.WriteData2(1, default);
modbusVariable.WriteData1(value, default);
//执行连读
modbusVariable.MulRead();
Console.WriteLine(modbusVariable.ToJsonString());
//执行连读
modbusVariable.MulRead();
Console.WriteLine(modbusVariable.ToJsonString());
}
}
}
[GeneratorVariable]
public partial class ModbusVariable : VariableObject
{
[VariableRuntime(RegisterAddress = "400001;arraylen=2")]
public ushort[] Data1 { get; set; }
[VariableRuntime(RegisterAddress = "400051")]
public ushort Data2 { get; set; }
[VariableRuntime(RegisterAddress = "400061;len=10")]
public string Data3 { get; set; }
public ModbusVariable(IProtocol protocol, int maxPack) : base(protocol, maxPack)
{
}
}
}

View File

@@ -1,61 +0,0 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
using Newtonsoft.Json.Linq;
using ThingsGateway.Foundation.Modbus;
using TouchSocket.Core;
namespace ThingsGateway.Foundation
{
internal class ModbusMatserTest
{
public async Task Test()
{
var clientConfig = new TouchSocketConfig();
//创建通道也可以通过TouchSocketConfig.GetChannel扩展获取
var clientChannel = clientConfig.GetTcpClientWithIPHost("tcp://127.0.0.1:502");
//创建modbus客户端传入通道
using ModbusMaster modbusMaster = new(clientChannel)
{
//modbus协议格式
//ModbusType = Modbus.ModbusTypeEnum.ModbusRtu,
ModbusType = Modbus.ModbusTypeEnum.ModbusTcp,
};
//测试5千次
for (int i = 0; i < 5000; i++)
{
//读写对应数据类型
var result = await modbusMaster.ReadInt32Async("40001", 1);
if (!result.IsSuccess)
{
Console.WriteLine(result);
}
}
var wResult = await modbusMaster.WriteAsync("40001", 1);
//动态类型读写
var objResult = await modbusMaster.ReadAsync("40001", 1, DataTypeEnum.Int32);
var objWResult = await modbusMaster.WriteAsync("40001", JToken.FromObject(1), DataTypeEnum.Int32);
//地址说明
//单独设置解析顺序
var objABCDResult = await modbusMaster.ReadAsync("40001;dataformat=badc", 1, DataTypeEnum.Int32);
//单独设置站号
var objSResult = await modbusMaster.ReadAsync("40001;dataformat=badc;s=2", 1, DataTypeEnum.Int32);
//单独设置写入功能码
var objFWResult = await modbusMaster.ReadAsync("40001;s=2;w=16", 1, DataTypeEnum.Int16);
}
}
}

View File

@@ -8,21 +8,14 @@
// QQ群605534569
//------------------------------------------------------------------------------
using TouchSocket.Core;
namespace ThingsGateway.Foundation
{
internal class Program
{
private static async Task Main(string[] args)
private static void Main(string[] args)
{
Dlt645MasterTest dlt645MasterTest = new Dlt645MasterTest();
var channel = dlt645MasterTest.GetChannel();
var protocol = dlt645MasterTest.GetProtocol(channel);
var data = await protocol.ReadDoubleAsync("02010100"); //读取A相电压
Console.WriteLine(data.ToJsonString());
Console.ReadLine();
ModbusMasterTest.Test();
//S7MatserTest.Test();
}
}
}

View File

@@ -0,0 +1,89 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
using ThingsGateway.Foundation.SiemensS7;
using TouchSocket.Core;
namespace ThingsGateway.Foundation
{
internal class S7MatserTest
{
private static void Test(S7Variable s7Variable, ushort value)
{
s7Variable.WriteData1(value, default);
s7Variable.WriteData2(value, default);
//执行连读
s7Variable.MulRead();
Console.WriteLine(s7Variable.ToJsonString());
//源生成WriteData1与WriteData2方法(Write{属性名称})
var data1 = s7Variable.WriteData1(value + 10, default);
var data2 = s7Variable.WriteData2(value + 10, default);
//执行连读
s7Variable.MulRead();
Console.WriteLine(s7Variable.ToJsonString());
}
private static SiemensS7Master GetMaster()
{
var clientConfig = new TouchSocketConfig();
clientConfig.ConfigureContainer(a => a.AddConsoleLogger());
//创建通道也可以通过TouchSocketConfig.GetChannel扩展获取
var clientChannel = clientConfig.GetTcpClientWithIPHost("tcp://127.0.0.1:102");
//clientChannel.Logger.LogLevel = LogLevel.Trace;
SiemensS7Master siemensS7Master = new(clientChannel)
{
SiemensType = SiemensTypeEnum.S1500,
};
return siemensS7Master;
}
public static void Test()
{
using SiemensS7Master siemensS7Master = GetMaster();
//构造实体类对象,传入协议对象与连读打包的最大数量
S7Variable s7Variable = new(siemensS7Master, 100);
Test(s7Variable, 10);
Console.ReadLine();
static void Test(S7Variable s7Variable, ushort value)
{
s7Variable.WriteData1(value, default);
s7Variable.WriteData2(value, default);
//执行连读
s7Variable.MulRead();
Console.WriteLine(s7Variable.ToJsonString());
//源生成WriteData1与WriteData2方法(Write{属性名称})
var data1 = s7Variable.WriteData1(value + 10, default);
var data2 = s7Variable.WriteData2(value + 10, default);
//执行连读
s7Variable.MulRead();
Console.WriteLine(s7Variable.ToJsonString());
}
}
}
[GeneratorVariable]
public partial class S7Variable : VariableObject
{
[VariableRuntime(RegisterAddress = "M100")]
public ushort Data1 { get; set; }
[VariableRuntime(RegisterAddress = "M200")]
public ushort Data2 { get; set; }
public S7Variable(IProtocol protocol, int maxPack) : base(protocol, maxPack)
{
}
}
}

View File

@@ -5,11 +5,16 @@
<OutputPath>$(SolutionDir)bin\$(Configuration)\$(MSBuildProjectName)\</OutputPath>
<DocumentationFile></DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\ThingsGateway.Foundation.Dlt645\src\ThingsGateway.Foundation.Dlt645.csproj" />
<ProjectReference Include="..\..\ThingsGateway.Foundation.Modbus\src\ThingsGateway.Foundation.Modbus.csproj">
</ProjectReference>
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="5.0.1.9" />
<PackageReference Include="ThingsGateway.Foundation.Dlt645" Version="5.0.1.9" />
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="5.0.1.9" />
</ItemGroup>
<!--<ItemGroup>
<ProjectReference Include="..\..\ThingsGateway.Foundation.Dlt645\src\ThingsGateway.Foundation.Dlt645.csproj" />
<ProjectReference Include="..\..\ThingsGateway.Foundation.Modbus\src\ThingsGateway.Foundation.Modbus.csproj" />
<ProjectReference Include="..\..\ThingsGateway.Foundation.SiemensS7\src\ThingsGateway.Foundation.SiemensS7.csproj" />
<ProjectReference Include="..\..\ThingsGateway.Foundation.SourceGenerator\src\ThingsGateway.Foundation.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>-->
</Project>

View File

@@ -20,7 +20,7 @@ internal static class PackHelper
/// <param name="maxPack">最大打包长度</param>
/// <param name="defaultIntervalTime">默认间隔时间</param>
/// <returns></returns>
public static List<T> LoadSourceRead<T>(ProtocolBase device, List<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSourceT<IVariable>, new()
public static List<T> LoadSourceRead<T>(ProtocolBase device, List<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSource, new()
{
var byteConverter = device.ThingsGatewayBitConverter;
var result = new List<T>();

View File

@@ -7,8 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\foundation\ThingsGateway.Foundation\src\ThingsGateway.Foundation.csproj">
<Private>True</Private>
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -23,7 +23,7 @@ public class PackHelper
/// <param name="maxPack">最大打包长度</param>
/// <param name="defaultIntervalTime">默认间隔时间</param>
/// <returns></returns>
public static List<T> LoadSourceRead<T>(IProtocol device, List<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSourceT<IVariable>, new()
public static List<T> LoadSourceRead<T>(IProtocol device, List<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSource, new()
{
if (deviceVariables == null)
throw new ArgumentNullException(nameof(deviceVariables));
@@ -94,7 +94,7 @@ public class PackHelper
return deviceVariableSourceReads;
}
private static List<T> LoadSourceRead<T>(Dictionary<ModbusAddress, IVariable> addressList, int functionCode, int intervalTime, int maxPack) where T : IVariableSourceT<IVariable>, new()
private static List<T> LoadSourceRead<T>(Dictionary<ModbusAddress, IVariable> addressList, int functionCode, int intervalTime, int maxPack) where T : IVariableSource, new()
{
List<T> sourceReads = new();
//按地址和长度排序

View File

@@ -7,8 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\foundation\ThingsGateway.Foundation\src\ThingsGateway.Foundation.csproj">
<Private>True</Private>
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>

View File

@@ -5,5 +5,7 @@
<Description>工业设备通讯协议-OpcDa协议</Description>
<DocumentationFile></DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType></DebugType>
</PropertyGroup>
</Project>

View File

@@ -55,19 +55,14 @@ internal class SiemensS7DataHandleAdapter : ReadWriteDevicesSingleStreamDataHand
default:
//添加返回代码校验
if (response.Length == 22)
if (response[5] == 0xD0)//首次握手0XD0连接确认
{
if (response[21] != 0x00)
{
result = new($"PLC返回错误返回代码{response[21].ToString("X2")}") { Content = response, Content2 = FilterResult.Success };
}
else
{
result = new() { Content = response, Content2 = FilterResult.Success };
}
result = new() { Content = response, Content2 = FilterResult.Success };
}
else
{
//其余情况判断错误代码
if (response[17] + response[18] > 0)
{
result = new($"PLC返回错误错误类型{response[17].ToString("X2")}错误代码:{response[18].ToString("X2")}") { Content = response, Content2 = FilterResult.Success };
@@ -78,6 +73,7 @@ internal class SiemensS7DataHandleAdapter : ReadWriteDevicesSingleStreamDataHand
}
}
break;
}
}

View File

@@ -20,7 +20,7 @@ internal static class PackHelper
/// <param name="maxPack">最大打包长度</param>
/// <param name="defaultIntervalTime">默认间隔时间</param>
/// <returns></returns>
public static List<T> LoadSourceRead<T>(SiemensS7Master device, List<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSourceT<IVariable>, new()
public static List<T> LoadSourceRead<T>(SiemensS7Master device, List<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSource, new()
{
var byteConverter = device.ThingsGatewayBitConverter;
var result = new List<T>();
@@ -138,7 +138,7 @@ internal static class PackHelper
return result;
}
private static List<T> LoadSourceRead<T>(Dictionary<SiemensAddress, IVariable> addressList, int functionCode, int intervalTime, SiemensS7Master siemensS7Net) where T : IVariableSourceT<IVariable>, new()
private static List<T> LoadSourceRead<T>(Dictionary<SiemensAddress, IVariable> addressList, int functionCode, int intervalTime, SiemensS7Master siemensS7Net) where T : IVariableSource, new()
{
List<T> sourceReads = new();
//实际地址与长度排序

View File

@@ -30,10 +30,10 @@ internal partial class SiemensHelper
0x01, 0x0A, // PDU Max Length
0xC1, // Src TSAP Identifier
0x02, // Src TSAP Length (2 bytes)
0x01, 0x00, // Src TSAP (需重写)
0x01, 0x02, // Src TSAP (需重写)
0xC2, // Dst TSAP Identifier
0x02, // Dst TSAP Length (2 bytes)
0x01, 0x02 // Dst TSAP (需重写)
0x01, 0x00 // Dst TSAP (需重写)
};
// ISO连接请求报文(也包含ISO头和COTP头)

View File

@@ -7,8 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\foundation\ThingsGateway.Foundation\src\ThingsGateway.Foundation.csproj">
<Private>True</Private>
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,9 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------

View File

@@ -0,0 +1,118 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
#if !NET45_OR_GREATER
using Microsoft.CodeAnalysis;
namespace ThingsGateway.Foundation
{
internal static class Utils
{
public static bool IsInheritFrom(this ITypeSymbol typeSymbol, string baseType)
{
if (typeSymbol.ToDisplayString() == baseType)
{
return true;
}
if (typeSymbol.BaseType != null)
{
var b = IsInheritFrom(typeSymbol.BaseType, baseType);
if (b)
{
return true;
}
}
foreach (var item in typeSymbol.AllInterfaces)
{
var b = IsInheritFrom(item, baseType);
if (b)
{
return true;
}
}
return false;
}
public static string RenameCamelCase(this string str)
{
var firstChar = str[0];
if (firstChar == char.ToLowerInvariant(firstChar))
{
return str;
}
var name = str.ToCharArray();
name[0] = char.ToLowerInvariant(firstChar);
return new string(name);
}
public static bool HasAttribute(this ISymbol symbol, INamedTypeSymbol attribute)
{
foreach (var attr in symbol.GetAttributes())
{
var attrClass = attr.AttributeClass;
if (attrClass != null && attrClass.ToDisplayString() == attribute.ToDisplayString())
{
return true;
}
}
return false;
}
public static bool HasAttribute(this ISymbol symbol, string attribute, out AttributeData attributeData)
{
foreach (var attr in symbol.GetAttributes())
{
var attrClass = attr.AttributeClass;
if (attrClass != null && attrClass.ToDisplayString() == attribute)
{
attributeData = attr;
return true;
}
}
attributeData = default;
return false;
}
public static bool HasFlags(int value, int flag)
{
return (value & flag) == flag;
}
public static bool HasReturn(this IMethodSymbol method)
{
if (method.ReturnsVoid || method.ReturnType.ToDisplayString() == typeof(Task).FullName)
{
return false;
}
return true;
}
}
}
#endif

View File

@@ -0,0 +1,135 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
#if !NET45_OR_GREATER
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Reflection;
using System.Text;
namespace ThingsGateway.Foundation
{
internal sealed class VariableCodeBuilder
{
private readonly INamedTypeSymbol m_pluginClass;
public VariableCodeBuilder(INamedTypeSymbol pluginClass)
{
this.m_pluginClass = pluginClass;
}
public string Prefix { get; set; }
public IEnumerable<string> Usings
{
get
{
yield return "using System;";
yield return "using System.Diagnostics;";
yield return "using ThingsGateway.Foundation;";
yield return "using System.Threading.Tasks;";
}
}
public string GetFileName()
{
return this.m_pluginClass.ToDisplayString() + "Generator";
}
public bool TryToSourceText(out SourceText sourceText)
{
var code = this.ToString();
if (string.IsNullOrEmpty(code))
{
sourceText = null;
return false;
}
sourceText = SourceText.From(code, Encoding.UTF8);
return true;
}
public override string ToString()
{
var propertys = this.FindPropertys().ToList();
if (propertys.Count == 0)
{
return null;
}
var codeString = new StringBuilder();
codeString.AppendLine("/*");
codeString.AppendLine("此代码由Variable工具直接生成非必要请不要修改此处代码");
codeString.AppendLine("*/");
codeString.AppendLine("#pragma warning disable");
foreach (var item in this.Usings)
{
codeString.AppendLine(item);
}
codeString.AppendLine($"namespace {this.m_pluginClass.ContainingNamespace}");
codeString.AppendLine("{");
codeString.AppendLine($"[global::System.CodeDom.Compiler.GeneratedCode(\"ThingsGateway.Foundation\",\"{Assembly.GetExecutingAssembly().GetName().Version.ToString()}\")]");
codeString.AppendLine($"partial class {this.m_pluginClass.Name}");
codeString.AppendLine("{");
foreach (var item in propertys)
{
this.BuildMethod(codeString, item);
}
codeString.AppendLine("}");
codeString.AppendLine("}");
return codeString.ToString();
}
private void BuildMethod(StringBuilder stringBuilder, IPropertySymbol propertySymbol)
{
var attributeData = propertySymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass.ToDisplayString() == VariableSyntaxReceiver.VariableRuntimeAttributeTypeName);
stringBuilder.AppendLine();
stringBuilder.AppendLine($"public OperResult Write{propertySymbol.Name}(object value,CancellationToken cancellationToken=default)");
stringBuilder.AppendLine("{");
stringBuilder.AppendLine($"return WriteValue(\"{propertySymbol.Name}\",value,cancellationToken);");
stringBuilder.AppendLine("}");
stringBuilder.AppendLine();
stringBuilder.AppendLine();
stringBuilder.AppendLine($"public Task<OperResult> Write{propertySymbol.Name}Async(object value,CancellationToken cancellationToken=default)");
stringBuilder.AppendLine("{");
stringBuilder.AppendLine($"return WriteValueAsync(\"{propertySymbol.Name}\",value,cancellationToken);");
stringBuilder.AppendLine("}");
stringBuilder.AppendLine();
}
private IEnumerable<IPropertySymbol> FindPropertys()
{
return this.m_pluginClass
.GetMembers()
.OfType<IPropertySymbol>()
.Where(m =>
{
return m.GetAttributes().Any(a => a.AttributeClass.ToDisplayString() == VariableSyntaxReceiver.VariableRuntimeAttributeTypeName);
});
}
}
}
#endif

View File

@@ -0,0 +1,89 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
#if !NET45_OR_GREATER
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace ThingsGateway.Foundation
{
/// <summary>
/// 源生成
/// </summary>
[Generator]
public class VariableObjectSourceGenerator : ISourceGenerator
{
private string m_generatorVariableAttribute = @"
using System;
namespace ThingsGateway.Foundation
{
/// <summary>
/// 使用源生成变量写入方法的调用。
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
internal class GeneratorVariableAttribute:Attribute
{
}
}
";
/// <inheritdoc/>
public void Initialize(GeneratorInitializationContext context)
{
//Debugger.Launch();
context.RegisterForPostInitialization(a =>
{
a.AddSource(nameof(this.m_generatorVariableAttribute), this.m_generatorVariableAttribute);
});
context.RegisterForSyntaxNotifications(() => new VariableSyntaxReceiver());
}
/// <inheritdoc/>
public void Execute(GeneratorExecutionContext context)
{
var s = context.Compilation.GetMetadataReference(context.Compilation.Assembly);
if (context.SyntaxReceiver is VariableSyntaxReceiver receiver)
{
var builders = receiver
.GetVariableObjectTypes(context.Compilation)
.Select(i => new VariableCodeBuilder(i))
.Distinct();
foreach (var builder in builders)
{
if (builder.TryToSourceText(out var sourceText))
{
var tree = CSharpSyntaxTree.ParseText(sourceText);
var root = tree.GetRoot().NormalizeWhitespace();
var ret = root.ToFullString();
context.AddSource($"{builder.GetFileName()}.g.cs", ret);
}
}
}
}
}
}
#endif

View File

@@ -0,0 +1,117 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
#if !NET45_OR_GREATER
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ThingsGateway.Foundation
{
internal sealed class VariableSyntaxReceiver : ISyntaxReceiver
{
public const string GeneratorVariableAttributeTypeName = "ThingsGateway.Foundation.GeneratorVariableAttribute";
public const string VariableRuntimeAttributeTypeName = "ThingsGateway.Foundation.VariableRuntimeAttribute";
/// <summary>
/// 接口列表
/// </summary>
private readonly List<ClassDeclarationSyntax> m_classSyntaxList = new List<ClassDeclarationSyntax>();
/// <summary>
/// 访问语法树
/// </summary>
/// <param name="syntaxNode"></param>
void ISyntaxReceiver.OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if (syntaxNode is ClassDeclarationSyntax syntax)
{
this.m_classSyntaxList.Add(syntax);
}
}
public static INamedTypeSymbol GeneratorVariableAttributeAttribute { get; private set; }
/// <summary>
/// 获取所有插件符号
/// </summary>
/// <param name="compilation"></param>
/// <returns></returns>
public IEnumerable<INamedTypeSymbol> GetVariableObjectTypes(Compilation compilation)
{
GeneratorVariableAttributeAttribute = compilation.GetTypeByMetadataName(GeneratorVariableAttributeTypeName);
if (GeneratorVariableAttributeAttribute == null)
{
yield break;
}
foreach (var classSyntax in this.m_classSyntaxList)
{
var @class = compilation.GetSemanticModel(classSyntax.SyntaxTree).GetDeclaredSymbol(classSyntax);
if (@class != null && IsVariableObject(@class))
{
yield return @class;
}
}
}
/// <summary>
/// 是否为变量类
/// </summary>
/// <param name="class"></param>
/// <returns></returns>
public static bool IsVariableObject(INamedTypeSymbol @class)
{
if (GeneratorVariableAttributeAttribute is null)
{
return false;
}
if (@class.IsAbstract)
{
return false;
}
return @class.BaseType.ToDisplayString() == "ThingsGateway.Foundation.VariableObject";
}
/// <summary>
/// 返回是否声明指定的特性
/// </summary>
/// <param name="symbol"></param>
/// <param name="attribute"></param>
/// <returns></returns>
public static bool HasAttribute(ISymbol symbol, INamedTypeSymbol attribute)
{
foreach (var attr in symbol.GetAttributes())
{
var attrClass = attr.AttributeClass;
if (attrClass != null && attrClass.AllInterfaces.Contains(attribute))
{
return true;
}
}
return false;
}
}
}
#endif

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Foundation.props" />
<PropertyGroup>
<Description>工业设备通讯协议-源生成器</Description>
<TargetFrameworks>netstandard2.0;</TargetFrameworks>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<NoPackageAnalysis>true</NoPackageAnalysis>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType></DebugType>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,49 @@
param($installPath, $toolsPath, $package, $project)
$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers" ) * -Resolve
foreach($analyzersPath in $analyzersPaths)
{
# Install the language agnostic analyzers.
if (Test-Path $analyzersPath)
{
foreach ($analyzerFilePath in Get-ChildItem $analyzersPath -Filter *.dll)
{
if($project.Object.AnalyzerReferences)
{
$project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
}
}
}
}
# $project.Type gives the language name like (C# or VB.NET)
$languageFolder = ""
if($project.Type -eq "C#")
{
$languageFolder = "cs"
}
if($project.Type -eq "VB.NET")
{
$languageFolder = "vb"
}
if($languageFolder -eq "")
{
return
}
foreach($analyzersPath in $analyzersPaths)
{
# Install language specific analyzers.
$languageAnalyzersPath = join-path $analyzersPath $languageFolder
if (Test-Path $languageAnalyzersPath)
{
foreach ($analyzerFilePath in Get-ChildItem $languageAnalyzersPath -Filter *.dll)
{
if($project.Object.AnalyzerReferences)
{
$project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
}
}
}
}

View File

@@ -0,0 +1,56 @@
param($installPath, $toolsPath, $package, $project)
$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers" ) * -Resolve
foreach($analyzersPath in $analyzersPaths)
{
# Uninstall the language agnostic analyzers.
if (Test-Path $analyzersPath)
{
foreach ($analyzerFilePath in Get-ChildItem $analyzersPath -Filter *.dll)
{
if($project.Object.AnalyzerReferences)
{
$project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
}
}
}
}
# $project.Type gives the language name like (C# or VB.NET)
$languageFolder = ""
if($project.Type -eq "C#")
{
$languageFolder = "cs"
}
if($project.Type -eq "VB.NET")
{
$languageFolder = "vb"
}
if($languageFolder -eq "")
{
return
}
foreach($analyzersPath in $analyzersPaths)
{
# Uninstall language specific analyzers.
$languageAnalyzersPath = join-path $analyzersPath $languageFolder
if (Test-Path $languageAnalyzersPath)
{
foreach ($analyzerFilePath in Get-ChildItem $languageAnalyzersPath -Filter *.dll)
{
if($project.Object.AnalyzerReferences)
{
try
{
$project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
}
catch
{
}
}
}
}
}

View File

@@ -496,10 +496,7 @@ namespace ThingsGateway.Foundation
/// <exception cref="Exception"></exception>
public void Send(IRequestInfo requestInfo)
{
if (this.DisposedValue)
{
return;
}
this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());

View File

@@ -42,7 +42,7 @@ namespace ThingsGateway.Foundation
private DelaySender m_delaySender;
private volatile bool m_online;
private readonly EasyLock m_semaphoreForConnect = new();
private readonly TcpCore m_tcpCore = new TcpCore();
private readonly TcpCore m_tcpCore = new();
#endregion
@@ -215,6 +215,10 @@ namespace ThingsGateway.Foundation
/// <inheritdoc/>
public int Port { get; private set; }
/// <inheritdoc/>
[Obsolete("该配置已被弃用,正式版发布时会直接删除", true)]
public ReceiveType ReceiveType { get; private set; }
/// <inheritdoc/>
public bool UseSsl => this.GetTcpCore().UseSsl;
@@ -227,10 +231,6 @@ namespace ThingsGateway.Foundation
/// <inheritdoc/>
public bool IsClient => true;
/// <inheritdoc/>
[Obsolete("该配置已被弃用,正式版发布时会直接删除", true)]
public ReceiveType ReceiveType => default;
#endregion
#region
@@ -450,7 +450,7 @@ namespace ThingsGateway.Foundation
#endregion Connect
#region TgReceiver
#region Receiver
private TgReceiver m_receiver;
@@ -466,7 +466,7 @@ namespace ThingsGateway.Foundation
this.m_receiver = null;
}
#endregion TgReceiver
#endregion Receiver
/// <inheritdoc/>
public override string ToString()
@@ -532,7 +532,6 @@ namespace ThingsGateway.Foundation
/// 当收到适配器处理的数据时。
/// </summary>
/// <param name="e"></param>
/// <returns>如果返回<see langword="true"/>则表示数据已被处理,且不会再向下传递。</returns>
protected virtual Task ReceivedData(ReceivedDataEventArgs e)
{
return this.PluginManager.RaiseAsync(nameof(ITcpReceivedPlugin.OnTcpReceived), this, e);
@@ -651,10 +650,7 @@ namespace ThingsGateway.Foundation
/// <exception cref="Exception"></exception>
public void Send(IRequestInfo requestInfo)
{
if (this.DisposedValue)
{
return;
}
this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());

View File

@@ -69,7 +69,7 @@ namespace ThingsGateway.Foundation
/// <inheritdoc/>
protected override async Task OnConnected(ConnectedEventArgs e)
{
Logger?.Debug($"{ToString()} {FoundationConst.Connected}");
Logger?.Debug($"{ToString()} {FoundationConst.Connected}");
if (Started != null)
await Started.Invoke(this);
await base.OnConnected(e);
@@ -78,7 +78,7 @@ namespace ThingsGateway.Foundation
/// <inheritdoc/>
protected override async Task OnConnecting(SerialConnectingEventArgs e)
{
Logger?.Debug($"{ToString()} {FoundationConst.Connecting}{(e.Message.IsNullOrEmpty() ? string.Empty : $"-{e.Message}")}");
Logger?.Debug($"{ToString()} {FoundationConst.Connecting}{(e.Message.IsNullOrEmpty() ? string.Empty : $"-{e.Message}")}");
if (Starting != null)
await Starting.Invoke(this);
await base.OnConnecting(e);

View File

@@ -67,7 +67,7 @@ namespace ThingsGateway.Foundation
/// <inheritdoc/>
protected override async Task OnConnected(ConnectedEventArgs e)
{
Logger?.Debug($"{ToString()} {FoundationConst.Connected}");
Logger?.Debug($"{ToString()} {FoundationConst.Connected}");
if (Started != null)
await Started.Invoke(this);
await base.OnConnected(e);

View File

@@ -29,14 +29,14 @@ namespace ThingsGateway.Foundation
/// <inheritdoc/>
protected override Task OnConnected(TClient socketClient, ConnectedEventArgs e)
{
Logger?.Debug($"{socketClient.ToString()} {FoundationConst.Connected}");
Logger?.Debug($"{socketClient.ToString()} {FoundationConst.Connected}");
return base.OnConnected(socketClient, e);
}
/// <inheritdoc/>
protected override Task OnConnecting(TClient socketClient, ConnectingEventArgs e)
{
Logger?.Debug($"{socketClient.ToString()} {FoundationConst.Connecting}");
Logger?.Debug($"{socketClient.ToString()} {FoundationConst.Connecting}");
return base.OnConnecting(socketClient, e);
}

View File

@@ -409,14 +409,20 @@ namespace ThingsGateway.Foundation
#region Windows下UDP连接被重置错误10054
#if NET45_OR_GREATER
const int SIP_UDP_CONNRESET = -1744830452;
socket.IOControl(SIP_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null);
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
if (this.Config.GetValue(TouchSocketConfigExtension.UdpConnResetProperty))
{
const int SIP_UDP_CONNRESET = -1744830452;
socket.IOControl(SIP_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null);
}
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (this.Config.GetValue(TouchSocketConfigExtension.UdpConnResetProperty))
{
const int SIP_UDP_CONNRESET = -1744830452;
socket.IOControl(SIP_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null);
}
}
#endif
#endregion Windows下UDP连接被重置错误10054

View File

@@ -39,6 +39,30 @@ public static class DataTypeExtension
};
}
/// <summary>
/// 获取DataTypeEnum
/// </summary>
/// <param name="coreType"></param>
/// <returns></returns>
public static DataTypeEnum GetDataType(this TypeCode coreType)
{
return coreType switch
{
TypeCode.String => DataTypeEnum.String,
TypeCode.Boolean => DataTypeEnum.Boolean,
TypeCode.Byte => DataTypeEnum.Byte,
TypeCode.Int16 => DataTypeEnum.Int16,
TypeCode.UInt16 => DataTypeEnum.UInt16,
TypeCode.Int32 => DataTypeEnum.Int32,
TypeCode.UInt32 => DataTypeEnum.UInt32,
TypeCode.Int64 => DataTypeEnum.Int64,
TypeCode.UInt64 => DataTypeEnum.UInt64,
TypeCode.Single => DataTypeEnum.Single,
TypeCode.Double => DataTypeEnum.Double,
_ => DataTypeEnum.Object,
};
}
/// <summary>
/// 获取实际字节长度不能确定返回0bool返回1
/// </summary>

View File

@@ -108,7 +108,7 @@ public interface IProtocol : IDisposable
/// <summary>
/// 连读寄存器打包
/// </summary>
List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSourceT<IVariable>, new();
List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSource, new();
#endregion

View File

@@ -11,12 +11,18 @@
namespace ThingsGateway.Foundation;
/// <summary>
/// IVariableSource
/// 变量特性
/// </summary>
public interface IVariableSourceT<T> : IVariableSource where T : IVariable
[AttributeUsage(AttributeTargets.Property)]
public class VariableRuntimeAttribute : Attribute
{
/// <summary>
/// 已打包变量
/// 寄存器地址
/// </summary>
ICollection<T> VariableRunTimes { get; }
public string? RegisterAddress { get; set; }
/// <summary>
/// 数据类型默认不填时会使用属性的Type
/// </summary>
public DataTypeEnum DataType { get; set; }
}

View File

@@ -45,16 +45,6 @@ public interface IVariable
/// </summary>
IVariableSource VariableSource { get; set; }
/// <summary>
/// 是否在线
/// </summary>
bool IsOnline { get; }
/// <summary>
/// 离线原因
/// </summary>
string? LastErrorMessage { get; }
/// <summary>
/// 实时值
/// </summary>
@@ -68,13 +58,4 @@ public interface IVariable
/// <param name="isOnline">是否在线</param>
/// <returns></returns>
OperResult SetValue(object value, DateTime dateTime = default, bool isOnline = true);
/// <summary>
/// 写入值/方法到设备中
/// </summary>
/// <param name="value">写入值/方法参数</param>
/// <param name="executive">执行方</param>
/// <param name="cancellationToken">取消令箭</param>
/// <returns></returns>
Task<OperResult> SetValueToDeviceAsync(string value, string? executive = null, CancellationToken cancellationToken = default);
}

View File

@@ -21,7 +21,7 @@ namespace ThingsGateway.Foundation
string? LastErrorMessage { get; set; }
/// <summary>
/// 最后一次失败原因
/// 添加变量
/// </summary>
void AddVariable(IVariable variable);

View File

@@ -0,0 +1,67 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation;
/// <summary>
/// VariableClass
/// </summary>
public class VariableClass : IVariable
{
private object? _value;
/// <summary>
/// 数据类型
/// </summary>
public virtual DataTypeEnum DataType { get; set; }
/// <summary>
/// 偏移量注意如果是布尔类型Index应该为bit的偏移
/// </summary>
public virtual int Index { get; set; }
/// <summary>
/// 执行间隔
/// </summary>
public virtual int? IntervalTime { get; set; }
/// <summary>
/// 寄存器地址
/// </summary>
public virtual string? RegisterAddress { get; set; }
/// <summary>
/// 数据转换规则
/// </summary>
public virtual IThingsGatewayBitConverter ThingsGatewayBitConverter { get; set; }
/// <summary>
/// 实时值
/// </summary>
public virtual object? Value => _value;
/// <summary>
/// IVariableSource
/// </summary>
public IVariableSource VariableSource { get; set; }
/// <summary>
/// 赋值变量
/// </summary>
/// <param name="value">值</param>
/// <param name="dateTime">采集时间</param>
/// <param name="isOnline">是否在线</param>
/// <returns></returns>
public virtual OperResult SetValue(object value, DateTime dateTime = default, bool isOnline = true)
{
_value = value;
return new();
}
}

View File

@@ -0,0 +1,193 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
using Newtonsoft.Json.Linq;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation;
/// <summary>
/// VariableObject
/// </summary>
public abstract class VariableObject
{
private IProtocol protocol;
private int maxPack;
/// <summary>
/// VariableObject
/// </summary>
public VariableObject(IProtocol protocol, int maxPack)
{
this.protocol = protocol;
this.maxPack = maxPack;
}
private List<VariableSourceClass>? deviceVariableSourceReads;
/// <summary>
/// <see cref="VariableRuntimeAttribute"/>特性连读,反射赋值到继承类中的属性
/// </summary>
public async Task<OperResult> MulReadAsync(CancellationToken cancellationToken = default)
{
try
{
GetVariableSources();
//连读
foreach (var item in deviceVariableSourceReads)
{
var result = await protocol.ReadAsync(item.RegisterAddress, item.Length);
if (result.IsSuccess)
{
item.VariableRunTimes.PraseStructContent(protocol, result.Content, item, exWhenAny: true);
}
else
{
item.LastErrorMessage = result.ErrorMessage;
item.VariableRunTimes.ForEach(a => a.SetValue(null, isOnline: false));
return new(result);
}
}
//结果反射赋值
var dict1 = VariableObjectHelper.GetPairs(GetType());
foreach (var pair in dict1)
{
pair.Value.Property.SetValue(this, pair.Value.VariableClass.Value);
}
return new();
}
catch (Exception ex)
{
return new(ex);
}
}
private Dictionary<string, VariableRuntimeProperty>? dict;
private void GetVariableSources()
{
if (deviceVariableSourceReads == null)
{
dict = VariableObjectHelper.GetPairs(GetType());
List<VariableClass> variableClasss = new();
foreach (var pair in dict)
{
var dataType = pair.Value.Attribute.DataType == DataTypeEnum.Object ? Type.GetTypeCode(pair.Value.Property.PropertyType.IsArray ? pair.Value.Property.PropertyType.GetElementType() : pair.Value.Property.PropertyType).GetDataType() : pair.Value.Attribute.DataType;
VariableClass variableClass = new VariableClass()
{
DataType = dataType,
RegisterAddress = pair.Value.Attribute.RegisterAddress,
IntervalTime = 1000,
};
pair.Value.VariableClass = variableClass;
variableClasss.Add(variableClass);
}
deviceVariableSourceReads = protocol.LoadSourceRead<VariableSourceClass>(variableClasss, maxPack, 1000);
}
}
/// <summary>
/// <see cref="VariableRuntimeAttribute"/>特性连读,反射赋值到继承类中的属性
/// </summary>
public OperResult MulRead(CancellationToken cancellationToken = default)
{
try
{
GetVariableSources();
//连读
foreach (var item in deviceVariableSourceReads)
{
var result = protocol.Read(item.RegisterAddress, item.Length);
if (result.IsSuccess)
{
item.VariableRunTimes.PraseStructContent(protocol, result.Content, item, exWhenAny: true);
}
else
{
item.LastErrorMessage = result.ErrorMessage;
item.VariableRunTimes.ForEach(a => a.SetValue(null, isOnline: false));
return new(result);
}
}
//结果反射赋值
var dict1 = VariableObjectHelper.GetPairs(GetType());
foreach (var pair in dict1)
{
pair.Value.Property.SetValue(this, pair.Value.VariableClass.Value);
}
return new();
}
catch (Exception ex)
{
return new(ex);
}
}
/// <summary>
/// 写入值到设备中
/// </summary>
/// <param name="propertyName">属性名称,必须使用<see cref="VariableRuntimeAttribute"/>特性</param>
/// <param name="value">写入值</param>
/// <param name="cancellationToken">取消令箭</param>
public OperResult WriteValue(string propertyName, object value, CancellationToken cancellationToken = default)
{
try
{
GetVariableSources();
if (string.IsNullOrEmpty(propertyName))
{
return new($"propertyName不能为 null 或空。");
}
if (!dict.TryGetValue(propertyName, out var variableRuntimeProperty))
{
return new($"该属性未被识别,可能没有使用{typeof(VariableRuntimeAttribute)}特性标识");
}
var result = protocol.Write(variableRuntimeProperty.VariableClass.RegisterAddress, JToken.FromObject(value), variableRuntimeProperty.VariableClass.DataType, cancellationToken);
return result;
}
catch (Exception ex)
{
return new(ex);
}
}
/// <summary>
/// 写入值到设备中
/// </summary>
/// <param name="propertyName">属性名称,必须使用<see cref="VariableRuntimeAttribute"/>特性</param>
/// <param name="value">写入值</param>
/// <param name="cancellationToken">取消令箭</param>
public async Task<OperResult> WriteValueAsync(string propertyName, object value, CancellationToken cancellationToken = default)
{
try
{
GetVariableSources();
if (string.IsNullOrEmpty(propertyName))
{
return new($"propertyName不能为 null 或空。");
}
if (!dict.TryGetValue(propertyName, out var variableRuntimeProperty))
{
return new($"该属性未被识别,可能没有使用{typeof(VariableRuntimeAttribute)}特性标识");
}
var result = await protocol.WriteAsync(variableRuntimeProperty.VariableClass.RegisterAddress, JToken.FromObject(value), variableRuntimeProperty.VariableClass.DataType, cancellationToken);
return result;
}
catch (Exception ex)
{
return new(ex);
}
}
}

View File

@@ -0,0 +1,41 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
using System.Reflection;
using ThingsGateway.Foundation;
internal static class VariableObjectHelper
{
private static MemoryCache<Type, Dictionary<string, VariableRuntimeProperty>> variablePropertyDicts = new MemoryCache<Type, Dictionary<string, VariableRuntimeProperty>>();
public static Dictionary<string, VariableRuntimeProperty> GetPairs(Type type)
{
if (variablePropertyDicts.TryGetValue(type, out var value))
{
return value;
}
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var dictionary = new Dictionary<string, VariableRuntimeProperty>();
foreach (var propertyInfo in properties)
{
VariableRuntimeAttribute variableRuntimeAttribute = propertyInfo.GetCustomAttribute<VariableRuntimeAttribute>();
if (variableRuntimeAttribute == null)
{
continue;
}
dictionary.Add(propertyInfo.Name, new VariableRuntimeProperty(variableRuntimeAttribute, propertyInfo));
}
variablePropertyDicts.AddCache(type, dictionary, 60 * 60 * 1000);
return dictionary;
}
}

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
using System.Reflection;
namespace ThingsGateway.Foundation;
/// <summary>
/// VariableRuntimeProperty
/// </summary>
internal class VariableRuntimeProperty
{
public VariableRuntimeAttribute Attribute { get; }
public PropertyInfo Property { get; }
public VariableClass VariableClass { get; set; }
public VariableRuntimeProperty(VariableRuntimeAttribute attribute, PropertyInfo property)
{
Attribute = attribute;
Property = property;
}
}

View File

@@ -0,0 +1,44 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
{
/// <summary>
/// VariableSourceClass
/// </summary>
public class VariableSourceClass : IVariableSource
{
private List<IVariable> _variableRunTimes = new();
/// <inheritdoc/>
public string? LastErrorMessage { get; set; }
/// <inheritdoc/>
public int Length { get; set; }
/// <inheritdoc/>
public string RegisterAddress { get; set; }
/// <inheritdoc/>
public TimeTick TimeTick { get; set; }
/// <summary>
/// 已打包变量
/// </summary>
public IEnumerable<IVariable> VariableRunTimes => _variableRunTimes;
/// <inheritdoc/>
public virtual void AddVariable(IVariable variable)
{
variable.VariableSource = this;
_variableRunTimes.Add(variable);
}
}
}

View File

@@ -155,7 +155,7 @@ public abstract class ProtocolBase : DisposableObject, IProtocol
#region
/// <inheritdoc/>
public abstract List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSourceT<IVariable>, new();
public abstract List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSource, new();
/// <inheritdoc/>
public virtual string GetAddressDescription()
@@ -462,6 +462,12 @@ public abstract class ProtocolBase : DisposableObject, IProtocol
}
else
{
string address1 = address;
IThingsGatewayBitConverter transformParameter = ByteTransUtil.GetTransByAddress(ref address1, ThingsGatewayBitConverter);
if (transformParameter.ArrayLength > 1)
{
return new("需要写入数组");
}
return dataType switch
{
DataTypeEnum.String => await WriteAsync(address, value.ToObject<String>(), cancellationToken),
@@ -510,6 +516,12 @@ public abstract class ProtocolBase : DisposableObject, IProtocol
}
else
{
string address1 = address;
IThingsGatewayBitConverter transformParameter = ByteTransUtil.GetTransByAddress(ref address1, ThingsGatewayBitConverter);
if (transformParameter.ArrayLength > 1)
{
return new("需要写入数组");
}
return dataType switch
{
DataTypeEnum.String => Write(address, value.ToObject<String>(), cancellationToken),

View File

@@ -6,23 +6,26 @@
</PropertyGroup>
<ItemGroup>
<None Include="..\..\..\.editorconfig" Link=".editorconfig" />
<None Include="..\..\..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NewLife.Core" Version="10.7.2024.202" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="TouchSocket" Version="2.0.0-beta.275" />
<PackageReference Include="NewLife.Core" Version="10.7.2024.202" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="TouchSocket" Version="2.0.0-beta.277" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'!='net45'">
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'!='net6'">
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\ThingsGateway.Foundation.SourceGenerator\src\tools\*.ps1" PackagePath="tools" Pack="true" Visible="false" />
<None Include="..\..\ThingsGateway.Foundation.SourceGenerator\src\bin\$(Configuration)\netstandard2.0\ThingsGateway.Foundation.SourceGenerator.dll" PackagePath="analyzers\dotnet\cs" Pack="true" Visible="false" />
</ItemGroup>
</Project>

View File

@@ -36,77 +36,91 @@ public static class ByteTransExtension
switch (dataType)
{
case DataTypeEnum.String:
Set(organizedVariable, byteConverter.ToString(buffer, index, byteConverter.StringLength ?? 1));
if (byteConverter.ArrayLength > 1)
{
List<String> strings = new();
for (int i = 0; i < byteConverter.ArrayLength; i++)
{
var data = byteConverter.ToString(buffer, index + i * byteConverter.StringLength ?? 1, byteConverter.StringLength ?? 1);
strings.Add(data);
}
Set(organizedVariable, strings.ToArray());
}
else
{
Set(organizedVariable,
byteConverter.ToString(buffer, index, byteConverter.StringLength ?? 1));
}
break;
case DataTypeEnum.Boolean:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToBoolean(buffer, index, byteConverter.StringLength.Value, plc.BitReverse(organizedVariable.RegisterAddress)) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToBoolean(buffer, index, byteConverter.ArrayLength.Value, plc.BitReverse(organizedVariable.RegisterAddress)) :
byteConverter.ToBoolean(buffer, index, plc.BitReverse(organizedVariable.RegisterAddress))
);
break;
case DataTypeEnum.Byte:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToByte(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToByte(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToByte(buffer, index));
break;
case DataTypeEnum.Int16:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToInt16(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToInt16(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToInt16(buffer, index));
break;
case DataTypeEnum.UInt16:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToUInt16(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToUInt16(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToUInt16(buffer, index));
break;
case DataTypeEnum.Int32:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToInt32(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToInt32(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToInt32(buffer, index));
break;
case DataTypeEnum.UInt32:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToUInt32(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToUInt32(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToUInt32(buffer, index));
break;
case DataTypeEnum.Int64:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToInt64(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToInt64(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToInt64(buffer, index));
break;
case DataTypeEnum.UInt64:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToUInt64(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToUInt64(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToUInt64(buffer, index));
break;
case DataTypeEnum.Single:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToSingle(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToSingle(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToSingle(buffer, index));
break;
case DataTypeEnum.Double:
Set(organizedVariable,
byteConverter.StringLength > 1 ?
byteConverter.ToDouble(buffer, index, byteConverter.StringLength.Value) :
byteConverter.ArrayLength > 1 ?
byteConverter.ToDouble(buffer, index, byteConverter.ArrayLength.Value) :
byteConverter.ToDouble(buffer, index));
break;

View File

@@ -22,10 +22,6 @@ namespace ThingsGateway.Foundation;
/// </summary>
public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
{
private readonly EndianType endianType;
private DataFormatEnum? dataFormat;
/// <inheritdoc/>
#if NET6_0_OR_GREATER
@@ -61,7 +57,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
/// <param name="endianType"></param>
public ThingsGatewayBitConverter(EndianType endianType)
{
this.endianType = endianType;
this.EndianType = endianType;
}
/// <summary>
@@ -69,24 +65,14 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
/// </summary>
public ThingsGatewayBitConverter(EndianType endianType, DataFormatEnum dataFormat)
{
this.endianType = endianType; this.dataFormat = dataFormat;
this.EndianType = endianType; this.DataFormat = dataFormat;
}
/// <inheritdoc/>
public virtual DataFormatEnum? DataFormat
{
get
{
return dataFormat;
}
set
{
dataFormat = value;
}
}
public virtual DataFormatEnum? DataFormat { get; set; }
/// <inheritdoc/>
public virtual EndianType EndianType => endianType;
public virtual EndianType EndianType { get; init; }
/// <inheritdoc/>
public virtual bool IsStringReverseByteWord { get; set; }
@@ -298,7 +284,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
/// <inheritdoc/>
public virtual bool IsSameOfSet()
{
return !(BitConverter.IsLittleEndian ^ (endianType == EndianType.Little));
return !(BitConverter.IsLittleEndian ^ (EndianType == EndianType.Little));
}
/// <inheritdoc/>

BIN
src/nuget.exe Normal file

Binary file not shown.