Compare commits

..

18 Commits

Author SHA1 Message Date
Kimdiego2098
95d723c578 2.0.9.3 2023-08-22 11:31:36 +08:00
Kimdiego2098
2fcd853e86 去除mqtt throw an _MqttConnectingFailedException_.报错信息 2023-08-22 11:26:22 +08:00
Kimdiego2098
07eef7c812 更新批量写入方法,注意rpc入口参数变化,mqtt等RPC接口参数变化 2023-08-22 11:23:03 +08:00
Kimdiego2098
b01e0757fa 修正部分代码格式 2023-08-21 19:59:07 +08:00
Kimdiego2098
32844a20c6 2.0.9.2 2023-08-19 12:08:49 +08:00
Kimdiego2098
5b6532c601 xml 2023-08-19 11:06:05 +08:00
Kimdiego2098
2c5b4b4027 修复TcpClient重复释放导致锁异常 2023-08-19 11:05:29 +08:00
Kimdiego2098
72d7ecf195 mas1.0.2默认中文 2023-08-18 18:36:30 +08:00
Kimdiego2098
2cfa6b4306 更新masa1.0.2 2023-08-18 13:59:17 +08:00
Kimdiego2098
6f6ffde0ab 2.0.9.1 2023-08-18 13:33:45 +08:00
Kimdiego2098
1694739a16 修改锁为EasyLock 2023-08-18 12:07:01 +08:00
Kimdiego2098
95d1e8bfca 代码文件编码统一utf-8 2023-08-18 09:57:03 +08:00
Kimdiego2098
60dec08e3c 更换DEMO Include为PackageReference 2023-08-17 15:30:35 +08:00
Kimdiego2098
a99d71be93 底层驱动添加netstandard输出 2023-08-17 15:24:07 +08:00
Kimdiego2098
f1331b6a0c 2.0.8 2023-08-17 10:58:48 +08:00
Kimdiego2098
10d66b642b 调整readme,方便copy账密 2023-08-17 10:28:47 +08:00
Kimdiego2098
cd2310e4a8 优化变量地址输入分割方法;s7读写字符串添加默认编码 2023-08-17 09:50:10 +08:00
Kimdiego2098
1b399cf6b0 优化s7读写字符串,更改特殊方法为读写共用 2023-08-16 17:20:20 +08:00
89 changed files with 1295 additions and 956 deletions

View File

@@ -22,7 +22,9 @@
[ThingsGateway演示地址](http://120.24.62.140:5000/) [ThingsGateway演示地址](http://120.24.62.140:5000/)
账户 : **superAdmin** 密码 : **111111** 账户 : **superAdmin**
密码 : **111111**
## 赞助 ## 赞助

View File

@@ -1,7 +1,7 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Version>2.0.7.0</Version> <Version>2.0.9.3</Version>
<Authors>Diego</Authors> <Authors>Diego</Authors>
<Product>ThingsGateway</Product> <Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright> <Copyright>© 2023-present Diego</Copyright>

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -20,19 +20,19 @@ namespace ThingsGateway.Admin.Blazor.Core;
public partial class AppBarItems public partial class AppBarItems
{ {
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 链接
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_COPYRIGHT_URL { get; set; } public string CONFIG_COPYRIGHT_URL { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>Ȩ /// 版权
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_COPYRIGHT { get; set; } public string CONFIG_COPYRIGHT { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 标题
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_TITLE { get; set; } public string CONFIG_TITLE { get; set; }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Components;
namespace ThingsGateway.Admin.Blazor.Core; namespace ThingsGateway.Admin.Blazor.Core;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><><CDA3> <20>ı<EFBFBD><C4B1><EFBFBD>ʾ /// 启用/停用 文本提示
/// </summary> /// </summary>
public partial class EnableChip public partial class EnableChip
{ {
@@ -46,5 +46,5 @@ public partial class EnableChip
private string TextColor => Value ? "green" : "error"; private string TextColor => Value ? "green" : "error";
private string Color => Value ? "green-lighten" : "warning-lighten"; private string Color => Value ? "green-lighten" : "warning-lighten";
private string Label => Value ? EnabledLabel ?? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : DisabledLabel ?? "ͣ<EFBFBD><EFBFBD>"; private string Label => Value ? EnabledLabel ?? "启用" : DisabledLabel ?? "停用";
} }

View File

@@ -1,18 +1,18 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
namespace ThingsGateway.Admin.Blazor.Core; namespace ThingsGateway.Admin.Blazor.Core;
/// <summary> /// <summary>
/// <EFBFBD>ղ<EFBFBD>/<2F><><EFBFBD>ݷ<EFBFBD>ʽ /// 收藏/快捷方式
/// </summary> /// </summary>
public partial class Favorite public partial class Favorite
{ {

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -22,17 +22,17 @@ public partial class Foter
{ {
private string Version = ""; private string Version = "";
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 链接
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_COPYRIGHT_URL { get; set; } public string CONFIG_COPYRIGHT_URL { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>Ȩ /// 版权
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_COPYRIGHT { get; set; } public string CONFIG_COPYRIGHT { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 标题
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_TITLE { get; set; } public string CONFIG_TITLE { get; set; }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -20,23 +20,23 @@ namespace ThingsGateway.Admin.Blazor.Core;
public partial class Logo public partial class Logo
{ {
/// <summary> /// <summary>
/// Logo<EFBFBD>߶<EFBFBD> /// Logo高度
/// </summary> /// </summary>
[Parameter] [Parameter]
public int HeightInt { get; set; } public int HeightInt { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 链接
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_COPYRIGHT_URL { get; set; } public string CONFIG_COPYRIGHT_URL { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>Ȩ /// 版权
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_COPYRIGHT { get; set; } public string CONFIG_COPYRIGHT { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 标题
/// </summary> /// </summary>
[Parameter] [Parameter]
public string CONFIG_TITLE { get; set; } public string CONFIG_TITLE { get; set; }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -34,7 +34,7 @@ public partial class PageTabs
return op; return op;
} }
/// <summary> /// <summary>
/// Tabsʵ<EFBFBD><EFBFBD> /// Tabs实例
/// </summary> /// </summary>
public PPageTabs PPageTabs { get; private set; } public PPageTabs PPageTabs { get; private set; }
@@ -46,7 +46,7 @@ public partial class PageTabs
[Parameter] [Parameter]
public IEnumerable<string> SelfPatterns { get; set; } public IEnumerable<string> SelfPatterns { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 子组件
/// </summary> /// </summary>
[Parameter] [Parameter]
public RenderFragment ChildContent { get; set; } public RenderFragment ChildContent { get; set; }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -49,11 +49,11 @@ public partial class UserMenu
var ret = str?.ToJsonWithT<UnifyResult<string>>(); var ret = str?.ToJsonWithT<UnifyResult<string>>();
if (ret?.Code != 200) if (ret?.Code != 200)
{ {
await PopupService.EnqueueSnackbarAsync("ע<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>", AlertTypes.Error); await PopupService.EnqueueSnackbarAsync("注销失败", AlertTypes.Error);
} }
else else
{ {
await PopupService.EnqueueSnackbarAsync("ע<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("注销成功", AlertTypes.Success);
await Task.Delay(500); await Task.Delay(500);
NavigationManager.NavigateTo(NavigationManager.Uri); NavigationManager.NavigateTo(NavigationManager.Uri);
} }

View File

@@ -0,0 +1,68 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion.DependencyInjection;
namespace BlazorComponent.I18n;
/// <summary>
/// CookieStorage
/// </summary>
public class CookieStorage : IScoped
{
private readonly IJSRuntime _jsRuntime;
/// <summary>
/// CookieStorage
/// </summary>
/// <param name="jsRuntime"></param>
public CookieStorage(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
/// <summary>
/// GetCookieAsync
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<string> GetCookieAsync(string key)
{
return await _jsRuntime.InvokeAsync<string>(JsInteropConstants.GetCookie, key);
}
/// <summary>
/// GetCookie
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string GetCookie(string key)
{
if (_jsRuntime is IJSInProcessRuntime jsInProcess)
{
return jsInProcess.Invoke<string>(JsInteropConstants.GetCookie, key);
}
return null;
}
/// <summary>
/// SetItemAsync
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
public async void SetItemAsync<T>(string key, T value)
{
try
{
await _jsRuntime.InvokeVoidAsync(JsInteropConstants.SetCookie, key, value?.ToString());
}
catch
{
}
}
}

View File

@@ -10,6 +10,8 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using BlazorComponent;
using Furion; using Furion;
using Masa.Blazor; using Masa.Blazor;
@@ -61,6 +63,8 @@ public class Startup : AppStartup
}); });
options.Locale = new Locale("zh-CN", "en-US");
}); });
services.AddScoped<InitTimezone>(); services.AddScoped<InitTimezone>();

View File

@@ -14,7 +14,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Masa.Blazor" Version="1.0.1" /> <PackageReference Include="Masa.Blazor" Version="1.0.2" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.10" />
</ItemGroup> </ItemGroup>

View File

@@ -857,5 +857,38 @@
设置深浅主题统一由这个方法为入口 设置深浅主题统一由这个方法为入口
</summary> </summary>
</member> </member>
<member name="T:BlazorComponent.I18n.CookieStorage">
<summary>
CookieStorage
</summary>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.#ctor(Microsoft.JSInterop.IJSRuntime)">
<summary>
CookieStorage
</summary>
<param name="jsRuntime"></param>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.GetCookieAsync(System.String)">
<summary>
GetCookieAsync
</summary>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.GetCookie(System.String)">
<summary>
GetCookie
</summary>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.SetItemAsync``1(System.String,``0)">
<summary>
SetItemAsync
</summary>
<typeparam name="T"></typeparam>
<param name="key"></param>
<param name="value"></param>
</member>
</members> </members>
</doc> </doc>

View File

@@ -153,7 +153,7 @@ public class UserResoures : IDisposable
{ {
if (MasaBlazor.Theme.Dark != isDark || isDark == null) if (MasaBlazor.Theme.Dark != isDark || isDark == null)
MasaBlazor.ToggleTheme(); MasaBlazor.ToggleTheme();
_cookieStorage?.SetItemAsync(BlazorResourceConst.ThemeCookieKey, isDark.ToJsonString()); _cookieStorage?.SetItemAsync(BlazorResourceConst.ThemeCookieKey, MasaBlazor.Theme.Dark.ToJsonString());
} }
private void InitCookie(IRequestCookieCollection cookies) private void InitCookie(IRequestCookieCollection cookies)

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -18,7 +18,7 @@ using ThingsGateway.Admin.Core;
namespace ThingsGateway.Admin.Blazor; namespace ThingsGateway.Admin.Blazor;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ҳ /// 首页
/// </summary> /// </summary>
public partial class Index public partial class Index
{ {

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -18,7 +18,7 @@ using ThingsGateway.Admin.Core;
namespace ThingsGateway.Admin.Blazor; namespace ThingsGateway.Admin.Blazor;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 个人设置
/// </summary> /// </summary>
public partial class UserCenter public partial class UserCenter
{ {
@@ -50,25 +50,25 @@ public partial class UserCenter
{ {
await UserCenterService.UpdateUserDefaultRazorAsync(UserManager.UserId, DefaultMenuId); await UserCenterService.UpdateUserDefaultRazorAsync(UserManager.UserId, DefaultMenuId);
await MainLayout.StateHasChangedAsync(); await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
async Task OnShortcutSaveAsync() async Task OnShortcutSaveAsync()
{ {
await UserCenterService.UpdateWorkbenchAsync(_menusChoice); await UserCenterService.UpdateWorkbenchAsync(_menusChoice);
await MainLayout.StateHasChangedAsync(); await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
async Task OnUpdatePasswordInfoAsync(FormContext context) async Task OnUpdatePasswordInfoAsync(FormContext context)
{ {
var success = context.Validate(); var success = context.Validate();
if (success) if (success)
{ {
//<EFBFBD><EFBFBD>֤<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD> //验证成功,操作业务
_passwordInfoInput.Id = UserResoures.CurrentUser.Id; _passwordInfoInput.Id = UserResoures.CurrentUser.Id;
await UserCenterService.EditPasswordAsync(_passwordInfoInput); await UserCenterService.EditPasswordAsync(_passwordInfoInput);
await MainLayout.StateHasChangedAsync(); await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>¼", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功,将重新登录", AlertTypes.Success);
await Task.Delay(2000); await Task.Delay(2000);
NavigationManager.NavigateTo(NavigationManager.Uri); NavigationManager.NavigateTo(NavigationManager.Uri);
} }
@@ -78,6 +78,6 @@ public partial class UserCenter
{ {
await UserCenterService.UpdateUserInfoAsync(_updateInfoInput); await UserCenterService.UpdateUserInfoAsync(_updateInfoInput);
await MainLayout.StateHasChangedAsync(); await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
} }

View File

@@ -12,7 +12,7 @@
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.8.8.40" /> <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.8.8.40" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.8.8.40" /> <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.8.8.40" />
<PackageReference Include="Furion.Pure" Version="4.8.8.40" /> <PackageReference Include="Furion.Pure" Version="4.8.8.40" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.96" /> <PackageReference Include="SqlSugarCore" Version="5.1.4.99" />
<PackageReference Include="UAParser" Version="3.1.47" /> <PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" /> <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
<PackageReference Include="MiniExcel" Version="1.31.2" /> <PackageReference Include="MiniExcel" Version="1.31.2" />

View File

@@ -89,13 +89,8 @@ public class RpcControler : IDynamicApiController
[Description("写入变量")] [Description("写入变量")]
public async Task<Dictionary<string, OperResult>> WriteDeviceMethods(Dictionary<string, string> objs) public async Task<Dictionary<string, OperResult>> WriteDeviceMethods(Dictionary<string, string> objs)
{ {
Dictionary<string, OperResult> operResultDict = new(); var result = await RpcCore.InvokeDeviceMethodAsync($"WebApi-{UserManager.UserAccount}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", objs);
foreach (KeyValuePair<string, string> obj in objs) return result;
{
var result = await RpcCore.InvokeDeviceMethodAsync($"WebApi-{UserManager.UserAccount}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", obj);
operResultDict.Add(obj.Key, result);
}
return operResultDict;
} }
} }

View File

@@ -36,6 +36,10 @@ public abstract class CollectBase : DriverBase
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public abstract bool IsSupportRequest { get; } public abstract bool IsSupportRequest { get; }
/// <summary>
/// 一般底层驱动也有可能为null
/// </summary>
protected abstract IReadWriteDevice PLC { get; }
/// <summary> /// <summary>
/// 数据转换器 /// 数据转换器
@@ -177,10 +181,22 @@ public abstract class CollectBase : DriverBase
} }
/// <summary> /// <summary>
/// 写入变量值 /// 批量写入变量值,需返回变量名称/结果
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public abstract Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token); public virtual async Task<Dictionary<string, OperResult>> WriteValuesAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
{
if (PLC == null)
throw new("未初始化成功");
Dictionary<string, OperResult> operResults = new();
foreach (var writeInfo in writeInfoLists)
{
var result = await PLC.WriteAsync(writeInfo.Key.VariableAddress, writeInfo.Key.DataType, writeInfo.Value.ToString(), token);
await Task.Delay(10, token); //防止密集写入
operResults.Add(writeInfo.Key.Name, result);
}
return operResults;
}
/// <summary> /// <summary>
/// 初始化 /// 初始化

View File

@@ -48,92 +48,172 @@ public class RpcSingletonService : ISingleton
/// 反向RPC入口方法 /// 反向RPC入口方法
/// </summary> /// </summary>
/// <param name="sourceDes">触发该方法的源说明</param> /// <param name="sourceDes">触发该方法的源说明</param>
/// <param name="item">指定键为变量名称,值为附带方法参数或写入值</param> /// <param name="items">指定键为变量名称,值为附带方法参数或写入值</param>
/// <param name="isBlazor">如果是true不检查<see cref="MemoryVariable.RpcWriteEnable"/>字段</param> /// <param name="isBlazor">如果是true不检查<see cref="MemoryVariable.RpcWriteEnable"/>字段</param>
/// <param name="token"><see cref="CancellationToken"/> 取消源</param> /// <param name="token"><see cref="CancellationToken"/> 取消源</param>
/// <returns></returns> /// <returns></returns>
public async Task<OperResult> InvokeDeviceMethodAsync(string sourceDes, KeyValuePair<string, string> item, bool isBlazor = false, CancellationToken token = default) public async Task<Dictionary<string, OperResult>> InvokeDeviceMethodAsync(string sourceDes, Dictionary<string, string> items, bool isBlazor = false, CancellationToken token = default)
{ {
//避免并发过高这里延时10ms Dictionary<CollectDeviceCore, Dictionary<DeviceVariableRunTime, JToken>> WriteVariables = new();
await Task.Delay(10, token); Dictionary<CollectDeviceCore, Dictionary<DeviceVariableRunTime, string>> WriteMethods = new();
OperResult data = new(); Dictionary<string, OperResult> results = new();
var tag = _globalDeviceData.AllVariables.FirstOrDefault(it => it.Name == item.Key); foreach (var item in items)
if (tag == null) return new OperResult("不存在变量:" + item.Key);
if (tag.ProtectTypeEnum == ProtectTypeEnum.ReadOnly) return new OperResult("只读变量");
if (!tag.RpcWriteEnable && !isBlazor) return new OperResult("不允许远程写入");
if (tag.IsMemoryVariable == true)
{ {
return tag.SetValue(item.Value);
}
var dev = _collectDeviceHostService.CollectDeviceCores.FirstOrDefault(it => it.Device.Id == tag.DeviceId);
if (dev == null) return new OperResult("系统错误,不存在对应采集设备,请稍候重试");
if (dev.Device.DeviceStatus == DeviceStatusEnum.OffLine) return new OperResult("设备已离线");
if (dev.Device.DeviceStatus == DeviceStatusEnum.Pause) return new OperResult("设备已暂停");
if (string.IsNullOrEmpty(tag.OtherMethod))
{
//写入变量
JToken tagValue;
try
{
tagValue = JToken.Parse(item.Value);
}
catch (Exception)
{
tagValue = JToken.Parse("\"" + item.Value + "\"");
}
data = await dev.InVokeWriteAsync(tag, tagValue, token); OperResult data = new();
_logQueues.Enqueue( var tag = _globalDeviceData.AllVariables.FirstOrDefault(it => it.Name == item.Key);
new RpcLog() if (tag == null)
results.Add(item.Key, new("不存在变量:" + item.Key));
if (tag.ProtectTypeEnum == ProtectTypeEnum.ReadOnly)
results.Add(item.Key, new("只读变量:" + item.Key));
if (!tag.RpcWriteEnable && !isBlazor)
results.Add(item.Key, new("不允许远程写入:" + item.Key));
if (tag.IsMemoryVariable == true)
{
results.Add(item.Key, tag.SetValue(item.Value));
}
var dev = _collectDeviceHostService.CollectDeviceCores.FirstOrDefault(it => it.Device.Id == tag.DeviceId);
if (dev == null)
results.Add(item.Key, new OperResult("系统错误,不存在对应采集设备,请稍候重试"));
if (dev.Device.DeviceStatus == DeviceStatusEnum.OffLine)
results.Add(item.Key, new OperResult("设备已离线"));
if (dev.Device.DeviceStatus == DeviceStatusEnum.Pause)
results.Add(item.Key, new OperResult("设备已暂停"));
if (!results.ContainsKey(item.Key))
{
if (string.IsNullOrEmpty(tag.OtherMethod))
{ {
LogTime = SysDateTimeExtensions.CurrentDateTime, //写入变量
OperateMessage = data.Exception, JToken tagValue;
IsSuccess = data.IsSuccess, try
OperateMethod = WriteVariable, {
OperateObject = tag.Name, tagValue = JToken.Parse(item.Value);
OperateSource = sourceDes, }
ParamJson = item.Value, catch (Exception)
ResultJson = data.Message {
tagValue = JToken.Parse("\"" + item.Value + "\"");
}
if (WriteVariables.ContainsKey(dev))
{
WriteVariables[dev].Add(tag, tagValue);
}
else
{
WriteVariables.Add(dev, new());
WriteVariables[dev].Add(tag, tagValue);
}
}
else
{
if (WriteMethods.ContainsKey(dev))
{
WriteMethods[dev].Add(tag, item.Value);
}
else
{
WriteVariables.Add(dev, new());
WriteVariables[dev].Add(tag, item.Value);
}
} }
);
if (!data.IsSuccess)
{
_logger.LogWarning($"写入变量[{tag.Name}]失败:{data.Message}");
} }
} }
else
foreach (var item in WriteVariables)
{ {
//执行变量附带的方法
var method = dev.DeviceVariableMethodSources.FirstOrDefault(it => it.DeviceVariable == tag);
try try
{ {
data = await dev.InvokeMethodAsync(method, false, item.Value, token); var result = await item.Key.InVokeWriteAsync(item.Value, token);
foreach (var resultItem in result)
{
string operObj;
string parJson;
if (resultItem.Key.IsNullOrEmpty())
{
operObj = items.Select(x => x.Key).ToJsonString();
parJson = items.Select(x => x.Value).ToJsonString();
}
else
{
operObj = resultItem.Key;
parJson = items[resultItem.Key];
}
_logQueues.Enqueue(
new RpcLog()
{
LogTime = SysDateTimeExtensions.CurrentDateTime,
OperateMessage = resultItem.Value.Exception,
IsSuccess = resultItem.Value.IsSuccess,
OperateMethod = WriteVariable,
OperateObject = operObj,
OperateSource = sourceDes,
ParamJson = parJson,
ResultJson = resultItem.Value.Message
}
);
if (!resultItem.Value.IsSuccess)
{
_logger.LogWarning($"写入变量[{resultItem.Key}]失败:{resultItem.Value.Message}");
}
}
results.AddRange(result);
} }
catch (Exception ex) catch (Exception ex)
{ {
data = new OperResult<string>(ex); _logger.LogWarning($"写入变量异常:{ex.Message + Environment.NewLine + ex.StackTrace}");
}
_logQueues.Enqueue(
new RpcLog()
{
LogTime = SysDateTimeExtensions.CurrentDateTime,
OperateMessage = data.Exception,
IsSuccess = data.IsSuccess,
OperateMethod = tag.OtherMethod,
OperateObject = tag.Name,
OperateSource = sourceDes,
ParamJson = item.Value?.ToString(),
ResultJson = data.Message
}
);
if (!data.IsSuccess)
{
_logger.LogWarning($"执行变量[{tag.Name}]方法[{tag.OtherMethod}]失败:{data.Message}");
} }
} }
return data; foreach (var item in WriteMethods)
{
foreach (var writeMethod in item.Value)
{
//执行变量附带的方法
var method = item.Key.DeviceVariableMethodSources.FirstOrDefault(it => it.DeviceVariable == writeMethod.Key);
OperResult<string> result;
try
{
result = await item.Key.InvokeMethodAsync(method, false, writeMethod.Value, token);
results.Add(writeMethod.Key.Name, result);
}
catch (Exception ex)
{
result = new OperResult<string>(ex);
results.Add(writeMethod.Key.Name, result);
}
_logQueues.Enqueue(
new RpcLog()
{
LogTime = SysDateTimeExtensions.CurrentDateTime,
OperateMessage = result.Exception,
IsSuccess = result.IsSuccess,
OperateMethod = writeMethod.Key.OtherMethod,
OperateObject = writeMethod.Key.Name,
OperateSource = sourceDes,
ParamJson = writeMethod.Value?.ToString(),
ResultJson = result.Message
} }
);
if (!result.IsSuccess)
{
_logger.LogWarning($"执行变量[{writeMethod.Key.Name}]方法[{writeMethod.Key.OtherMethod}]失败:{result.Message}");
}
}
}
return results;
}
private async Task RpcLogInsertAsync() private async Task RpcLogInsertAsync()
{ {

View File

@@ -1855,6 +1855,11 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="P:ThingsGateway.Application.CollectBase.PLC">
<summary>
一般底层驱动也有可能为null
</summary>
</member>
<member name="P:ThingsGateway.Application.CollectBase.ThingsGatewayBitConverter"> <member name="P:ThingsGateway.Application.CollectBase.ThingsGatewayBitConverter">
<summary> <summary>
数据转换器 数据转换器
@@ -1906,9 +1911,9 @@
采集驱动读取 采集驱动读取
</summary> </summary>
</member> </member>
<member name="M:ThingsGateway.Application.CollectBase.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.Application.CollectBase.WriteValuesAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
<summary> <summary>
写入变量值 批量写入变量值,需返回变量名称/结果
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
@@ -2242,12 +2247,12 @@
<member name="M:ThingsGateway.Application.RpcSingletonService.#ctor(Microsoft.Extensions.Logging.ILogger{ThingsGateway.Application.RpcSingletonService})"> <member name="M:ThingsGateway.Application.RpcSingletonService.#ctor(Microsoft.Extensions.Logging.ILogger{ThingsGateway.Application.RpcSingletonService})">
<inheritdoc cref="T:ThingsGateway.Application.RpcSingletonService"/> <inheritdoc cref="T:ThingsGateway.Application.RpcSingletonService"/>
</member> </member>
<member name="M:ThingsGateway.Application.RpcSingletonService.InvokeDeviceMethodAsync(System.String,System.Collections.Generic.KeyValuePair{System.String,System.String},System.Boolean,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.Application.RpcSingletonService.InvokeDeviceMethodAsync(System.String,System.Collections.Generic.Dictionary{System.String,System.String},System.Boolean,System.Threading.CancellationToken)">
<summary> <summary>
反向RPC入口方法 反向RPC入口方法
</summary> </summary>
<param name="sourceDes">触发该方法的源说明</param> <param name="sourceDes">触发该方法的源说明</param>
<param name="item">指定键为变量名称,值为附带方法参数或写入值</param> <param name="items">指定键为变量名称,值为附带方法参数或写入值</param>
<param name="isBlazor">如果是true不检查<see cref="P:ThingsGateway.Application.MemoryVariable.RpcWriteEnable"/>字段</param> <param name="isBlazor">如果是true不检查<see cref="P:ThingsGateway.Application.MemoryVariable.RpcWriteEnable"/>字段</param>
<param name="token"><see cref="T:System.Threading.CancellationToken"/> 取消源</param> <param name="token"><see cref="T:System.Threading.CancellationToken"/> 取消源</param>
<returns></returns> <returns></returns>
@@ -3505,7 +3510,7 @@
执行特殊方法 执行特殊方法
</summary> </summary>
</member> </member>
<member name="M:ThingsGateway.Application.CollectDeviceCore.InVokeWriteAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.Application.CollectDeviceCore.InVokeWriteAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
<summary> <summary>
执行变量写入 执行变量写入
</summary> </summary>

View File

@@ -330,11 +330,6 @@ public class CollectDeviceCore
return ThreadRunReturn.Continue; return ThreadRunReturn.Continue;
} }
if (DeviceVariableSourceReads.Count == 0 && Device.DeviceVariableRunTimes.Where(a => string.IsNullOrEmpty(a.OtherMethod)).Any())
{
//无采集变量
return ThreadRunReturn.Continue;
}
if (token.IsCancellationRequested) if (token.IsCancellationRequested)
return ThreadRunReturn.Break; return ThreadRunReturn.Break;
@@ -534,7 +529,7 @@ public class CollectDeviceCore
if (!string.IsNullOrEmpty(methodResult.MethodStr)) if (!string.IsNullOrEmpty(methodResult.MethodStr))
{ {
string[] strs = methodResult.MethodStr?.Trim()?.Split(';'); string[] strs = methodResult.MethodStr?.Trim()?.TrimEnd(';').Split(';');
try try
{ {
int index = 0; int index = 0;
@@ -546,6 +541,8 @@ public class CollectDeviceCore
} }
else else
{ {
if (strs.Length <= index)
continue;
//得到对于的方法参数值 //得到对于的方法参数值
methodResult.MethodObj[i] = methodResult.Converter.ConvertFrom(strs[index], ps[i].ParameterType); methodResult.MethodObj[i] = methodResult.Converter.ConvertFrom(strs[index], ps[i].ParameterType);
index++; index++;
@@ -601,8 +598,8 @@ public class CollectDeviceCore
if (!string.IsNullOrEmpty(deviceVariableMethodSource.MethodStr) || !string.IsNullOrEmpty(value)) if (!string.IsNullOrEmpty(deviceVariableMethodSource.MethodStr) || !string.IsNullOrEmpty(value))
{ {
string[] strs1 = deviceVariableMethodSource.MethodStr?.Trim()?.Split(';'); string[] strs1 = deviceVariableMethodSource.MethodStr?.Trim()?.TrimEnd(';').Split(';');
string[] strs2 = value?.Trim()?.Split(';'); string[] strs2 = value?.Trim()?.TrimEnd(';').Split(';');
//通过分号分割,并且合并参数 //通过分号分割,并且合并参数
var strs = strs1?.SpliceArray(strs2); var strs = strs1?.SpliceArray(strs2);
int index = 0; int index = 0;
@@ -668,18 +665,25 @@ public class CollectDeviceCore
if (method.HasReturn && result != null && result.IsSuccess) if (method.HasReturn && result != null && result.IsSuccess)
{ {
var content = deviceVariableMethodSource.Converter.ConvertTo(result.Content?.ToString()?.Replace($"\0", "")); var content = deviceVariableMethodSource.Converter.ConvertTo(result.Content?.ToString()?.Replace($"\0", ""));
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(content); if (isRead)
if (!operResult.IsSuccess)
{ {
_logger?.LogWarning(operResult.Message, ToString()); var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(content);
if (!operResult.IsSuccess)
{
_logger?.LogWarning(operResult.Message, ToString());
}
} }
} }
else else
{ {
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(null); if (isRead)
if (!operResult.IsSuccess)
{ {
_logger?.LogWarning(operResult.Message, ToString()); var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(null);
if (!operResult.IsSuccess)
{
_logger?.LogWarning(operResult.Message, ToString());
}
} }
} }
return result; return result;
@@ -708,46 +712,46 @@ public class CollectDeviceCore
/// 执行变量写入 /// 执行变量写入
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal async Task<OperResult> InVokeWriteAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token) internal async Task<Dictionary<string, OperResult>> InVokeWriteAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
{ {
try try
{ {
await easyLock.WaitAsync(); await easyLock.WaitAsync();
if (IsShareChannel) _driver.InitDataAdapter(); if (IsShareChannel) _driver.InitDataAdapter();
Dictionary<string, OperResult> results = new();
foreach (var deviceVariable in writeInfoLists.Keys)
{
if (!string.IsNullOrEmpty(deviceVariable.WriteExpressions))
{
var jToken = writeInfoLists[deviceVariable];
object rawdata;
if (jToken is JValue jValue)
{
rawdata = jValue.Value;
}
else
{
rawdata = jToken.ToString();
}
object data;
try
{
data = deviceVariable.WriteExpressions.GetExpressionsResult(rawdata);
writeInfoLists[deviceVariable] = JToken.FromObject(data);
}
catch (Exception ex)
{
results.Add(deviceVariable.Name, new OperResult(deviceVariable.Name + " 转换写入表达式失败:" + ex.Message));
}
}
if (!string.IsNullOrEmpty(deviceVariable.WriteExpressions))
{
var jToken = value;
object rawdata;
if (jToken is JValue jValue)
{
rawdata = jValue.Value;
}
else
{
rawdata = jToken.ToString();
}
object data;
try
{
data = deviceVariable.WriteExpressions.GetExpressionsResult(rawdata);
var result = await _driver.WriteValueAsync(deviceVariable, JToken.FromObject(data), token);
return result;
}
catch (Exception ex)
{
return new OperResult(deviceVariable.Name + " 转换写入表达式失败:" + ex.Message);
}
} }
else var result = await _driver.WriteValuesAsync(writeInfoLists.
{ Where(a => !results.Any(b => b.Key == a.Key.Name)).
var result = await _driver.WriteValueAsync(deviceVariable, value, token); ToDictionary(item => item.Key, item => item.Value),
return result; token);
}
} return result;
catch (Exception ex)
{
return (new OperResult(ex));
} }
finally finally
{ {
@@ -755,6 +759,8 @@ public class CollectDeviceCore
} }
} }
/// <summary> /// <summary>
/// 执行轮询特殊方法,并设置变量值 /// 执行轮询特殊方法,并设置变量值
/// </summary> /// </summary>

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -21,7 +21,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor; namespace ThingsGateway.Blazor;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>excel /// 导入excel
/// </summary> /// </summary>
public partial class ImportExcel public partial class ImportExcel
{ {
@@ -33,21 +33,21 @@ public partial class ImportExcel
bool isSaveImport; bool isSaveImport;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 导入
/// </summary> /// </summary>
[Parameter] [Parameter]
public Func<Dictionary<string, ImportPreviewOutputBase>, Task> Import { get; set; } public Func<Dictionary<string, ImportPreviewOutputBase>, Task> Import { get; set; }
/// <summary> /// <summary>
/// <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ʾ /// 是否显示
/// </summary> /// </summary>
public bool IsShowImport { get; set; } public bool IsShowImport { get; set; }
/// <summary> /// <summary>
/// Ԥ<EFBFBD><EFBFBD> /// 预览
/// </summary> /// </summary>
[Parameter] [Parameter]
public Func<IBrowserFile, Task<Dictionary<string, ImportPreviewOutputBase>>> Preview { get; set; } public Func<IBrowserFile, Task<Dictionary<string, ImportPreviewOutputBase>>> Preview { get; set; }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 当前步数
/// </summary> /// </summary>
public int Step { get; set; } public int Step { get; set; }
@@ -75,7 +75,7 @@ public partial class ImportExcel
StateHasChanged(); StateHasChanged();
await Import.Invoke(ImportPreviews); await Import.Invoke(ImportPreviews);
_importFile = null; _importFile = null;
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
finally finally
{ {

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -54,7 +54,7 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
/// </summary> /// </summary>
public UdpSessionPage UdpSessionPage; public UdpSessionPage UdpSessionPage;
/// <summary> /// <summary>
/// ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>1-TCPCLIENT<EFBFBD><EFBFBD>2-<2D><><EFBFBD>ڣ<EFBFBD>3-UDP<EFBFBD><EFBFBD>4-TCPServer /// 选择,1-TCPCLIENT2-串口,3-UDP4-TCPServer
/// </summary> /// </summary>
[Parameter] [Parameter]
public ChannelEnum Channel { get; set; } public ChannelEnum Channel { get; set; }
@@ -65,12 +65,12 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
public override ThingsGateway.Foundation.IReadWriteDevice Plc { get; set; } public override ThingsGateway.Foundation.IReadWriteDevice Plc { get; set; }
/// <summary> /// <summary>
/// ģ<EFBFBD><EFBFBD> /// 模板
/// </summary> /// </summary>
[Parameter] [Parameter]
public RenderFragment ChildContent { get; set; } public RenderFragment ChildContent { get; set; }
/// <summary> /// <summary>
/// <EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD> /// 自定义模板
/// </summary> /// </summary>
[Parameter] [Parameter]
public RenderFragment OtherContent { get; set; } public RenderFragment OtherContent { get; set; }
@@ -100,7 +100,7 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
TcpServerPage.LogAction = LogOut; TcpServerPage.LogAction = LogOut;
if (UdpSessionPage != null) if (UdpSessionPage != null)
UdpSessionPage.LogAction = LogOut; UdpSessionPage.LogAction = LogOut;
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
StateHasChanged(); StateHasChanged();
} }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -20,7 +20,7 @@ namespace ThingsGateway.Blazor;
public partial class SerialClientPage public partial class SerialClientPage
{ {
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 日志输出
/// </summary> /// </summary>
public Action<LogLevel, object, string, Exception> LogAction; public Action<LogLevel, object, string, Exception> LogAction;
@@ -36,7 +36,7 @@ public partial class SerialClientPage
SerialClient.SafeDispose(); SerialClient.SafeDispose();
} }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 获取对象
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public SerialClient GetSerialClient() public SerialClient GetSerialClient()
@@ -47,7 +47,7 @@ public partial class SerialClientPage
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace }); LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage)); config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetSerialProperty(serialProperty); config.SetSerialProperty(serialProperty);
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
SerialClient.Setup(config); SerialClient.Setup(config);
return SerialClient; return SerialClient;
} }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -23,7 +23,7 @@ namespace ThingsGateway.Blazor;
public partial class TcpClientPage public partial class TcpClientPage
{ {
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 日志输出
/// </summary> /// </summary>
public Action<LogLevel, object, string, Exception> LogAction; public Action<LogLevel, object, string, Exception> LogAction;
@@ -33,7 +33,7 @@ public partial class TcpClientPage
/// </summary> /// </summary>
private string IP = "127.0.0.1"; private string IP = "127.0.0.1";
/// <summary> /// <summary>
/// <EFBFBD>˿<EFBFBD> /// 端口
/// </summary> /// </summary>
[Parameter] [Parameter]
public int Port { get; set; } = 502; public int Port { get; set; } = 502;
@@ -73,7 +73,7 @@ public partial class TcpClientPage
} }
} }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 获取对象
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public TcpClientEx GetTcpClient() public TcpClientEx GetTcpClient()
@@ -83,7 +83,7 @@ public partial class TcpClientPage
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace }); LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage)); config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(IP + ":" + Port)).SetBufferLength(300); config.SetRemoteIPHost(new IPHost(IP + ":" + Port)).SetBufferLength(300);
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
TcpClientEx.Setup(config); TcpClientEx.Setup(config);
return TcpClientEx; return TcpClientEx;
} }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -19,7 +19,7 @@ namespace ThingsGateway.Blazor;
public partial class TcpServerPage public partial class TcpServerPage
{ {
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 日志输出
/// </summary> /// </summary>
public Action<LogLevel, object, string, Exception> LogAction; public Action<LogLevel, object, string, Exception> LogAction;
@@ -62,7 +62,7 @@ public partial class TcpServerPage
} }
} }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 获取对象
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public TcpService GetTcpServer() public TcpService GetTcpServer()
@@ -73,7 +73,7 @@ public partial class TcpServerPage
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage)); config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) }); config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) });
config.SetBufferLength(300); config.SetBufferLength(300);
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
TcpServer.Setup(config); TcpServer.Setup(config);
return TcpServer; return TcpServer;
} }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -19,7 +19,7 @@ namespace ThingsGateway.Blazor;
public partial class UdpSessionPage : IDisposable public partial class UdpSessionPage : IDisposable
{ {
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 日志输出
/// </summary> /// </summary>
public Action<LogLevel, object, string, Exception> LogAction; public Action<LogLevel, object, string, Exception> LogAction;
@@ -62,7 +62,7 @@ public partial class UdpSessionPage : IDisposable
} }
} }
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 获取对象
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public UdpSession GetUdpSession() public UdpSession GetUdpSession()
@@ -73,7 +73,7 @@ public partial class UdpSessionPage : IDisposable
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage)); config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300); config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300);
config.SetBindIPHost(new IPHost(0)); config.SetBindIPHost(new IPHost(0));
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
UdpSession.Setup(config); UdpSession.Setup(config);
return UdpSession; return UdpSession;
} }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -32,7 +32,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor; namespace ThingsGateway.Blazor;
/// <summary> /// <summary>
/// <EFBFBD>豸״̬ҳ<EFBFBD><EFBFBD> /// 设备状态页面
/// </summary> /// </summary>
public partial class DeviceStatusPage : IDisposable public partial class DeviceStatusPage : IDisposable
{ {
@@ -110,7 +110,7 @@ public partial class DeviceStatusPage : IDisposable
{ {
try try
{ {
var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?"); var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
if (confirm) if (confirm)
{ {
isAllRestart = true; isAllRestart = true;
@@ -142,8 +142,8 @@ public partial class DeviceStatusPage : IDisposable
} }
async Task ConfigAsync(long devId, bool? isStart) async Task ConfigAsync(long devId, bool? isStart)
{ {
var str = isStart == true ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>ͣ"; var str = isStart == true ? "启动" : "暂停";
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"ȷ<EFBFBD><EFBFBD>{str}?"); var confirm = await PopupService.OpenConfirmDialogAsync(str, $"确定{str}?");
if (confirm) if (confirm)
{ {
CollectDeviceHostService.ConfigDeviceThread(devId, isStart == true); CollectDeviceHostService.ConfigDeviceThread(devId, isStart == true);
@@ -167,19 +167,19 @@ public partial class DeviceStatusPage : IDisposable
memoryStream.Seek(0, SeekOrigin.Begin); memoryStream.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: memoryStream); using var streamRef = new DotNetStreamReference(stream: memoryStream);
Helper ??= await JS.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js"); Helper ??= await JS.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js");
await Helper.InvokeVoidAsync("downloadFileFromStream", $"<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.txt", streamRef); await Helper.InvokeVoidAsync("downloadFileFromStream", $"报文导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.txt", streamRef);
} }
finally finally
{ {
isDownExport = false; isDownExport = false;
} }
} }
//ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //去除单个采集重启
//async Task RestartAsync(long devId) //async Task RestartAsync(long devId)
//{ //{
// try // try
// { // {
// var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?"); // var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
// if (confirm) // if (confirm)
// { // {
// isRestart = true; // isRestart = true;
@@ -231,8 +231,8 @@ public partial class DeviceStatusPage : IDisposable
async Task UpConfigAsync(long devId, bool? isStart) async Task UpConfigAsync(long devId, bool? isStart)
{ {
var str = isStart == true ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>ͣ"; var str = isStart == true ? "启动" : "暂停";
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"ȷ<EFBFBD><EFBFBD>{str}?"); var confirm = await PopupService.OpenConfirmDialogAsync(str, $"确定{str}?");
if (confirm) if (confirm)
{ {
UploadDeviceHostService.ConfigDeviceThread(devId, isStart == true); UploadDeviceHostService.ConfigDeviceThread(devId, isStart == true);
@@ -253,7 +253,7 @@ public partial class DeviceStatusPage : IDisposable
{ {
try try
{ {
var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?"); var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
if (confirm) if (confirm)
{ {
isRestart = true; isRestart = true;

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -28,7 +28,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor; namespace ThingsGateway.Blazor;
/// <summary> /// <summary>
/// ʵʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ /// 实时数据页
/// </summary> /// </summary>
public partial class DeviceVariableRunTimePage public partial class DeviceVariableRunTimePage
{ {
@@ -37,13 +37,13 @@ public partial class DeviceVariableRunTimePage
List<DeviceTree> _deviceGroups = new(); List<DeviceTree> _deviceGroups = new();
string _searchName; string _searchName;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 设备名称
/// </summary> /// </summary>
[Parameter] [Parameter]
[SupplyParameterFromQuery] [SupplyParameterFromQuery]
public string DeviceName { get; set; } public string DeviceName { get; set; }
/// <summary> /// <summary>
/// <EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 上传设备名称
/// </summary> /// </summary>
[Parameter] [Parameter]
[SupplyParameterFromQuery] [SupplyParameterFromQuery]
@@ -149,15 +149,23 @@ public partial class DeviceVariableRunTimePage
private EventCallback<string> WriteValueAsync; private EventCallback<string> WriteValueAsync;
private async Task OnWriteValueAsync(DeviceVariableRunTime tag, string value) private async Task OnWriteValueAsync(DeviceVariableRunTime tag, string value)
{ {
var data = await RpcCore?.InvokeDeviceMethodAsync($"BLAZOR-{UserResoures.CurrentUser.Account}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", new KeyValuePair<string, string>(tag.Name, value), true); var data = await RpcCore?.InvokeDeviceMethodAsync($"BLAZOR-{UserResoures.CurrentUser.Account}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}",
if (!data.IsSuccess)
new Dictionary<string, string>()
{
{ tag.Name, value}
}
, true);
if (data.Count > 0 && !data.FirstOrDefault().Value.IsSuccess)
{ {
throw new(data.Message); throw new(data.FirstOrDefault().Value.Message);
} }
} }
private async Task WriteAsync(DeviceVariableRunTime collectVariableRunTime) private async Task WriteAsync(DeviceVariableRunTime collectVariableRunTime)
{ {
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD> // 将异步方法添加到事件回调上
WriteValueAsync = EventCallback.Factory.Create<string>(this, value => OnWriteValueAsync(collectVariableRunTime, value)); WriteValueAsync = EventCallback.Factory.Create<string>(this, value => OnWriteValueAsync(collectVariableRunTime, value));
await PopupService.OpenAsync(typeof(WriteValue), new Dictionary<string, object>() await PopupService.OpenAsync(typeof(WriteValue), new Dictionary<string, object>()
{ {

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -19,7 +19,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor; namespace ThingsGateway.Blazor;
/// <summary> /// <summary>
/// Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣҳ<EFBFBD><EFBFBD> /// 硬件信息页面
/// </summary> /// </summary>
public partial class HardwareInfoPage public partial class HardwareInfoPage
{ {

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -25,7 +25,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor; namespace ThingsGateway.Blazor;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ʷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD> /// 历史报警页面
/// </summary> /// </summary>
public partial class HistoryAlarmPage public partial class HistoryAlarmPage
{ {
@@ -75,7 +75,7 @@ public partial class HistoryAlarmPage
} }
catch (Exception ex) catch (Exception ex)
{ {
await InvokeAsync(async () => await PopupService.EnqueueSnackbarAsync("<EFBFBD><EFBFBD>ѯʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD>" + ex.Message, AlertTypes.Warning)); await InvokeAsync(async () => await PopupService.EnqueueSnackbarAsync("查询失败,请检查网络连接:" + ex.Message, AlertTypes.Warning));
return new() return new()
{ {
Current = 1, Current = 1,

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -23,7 +23,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor; namespace ThingsGateway.Blazor;
/// <summary> /// <summary>
/// ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD> /// 时序库页面
/// </summary> /// </summary>
public partial class HistoryValuePage public partial class HistoryValuePage
{ {
@@ -74,7 +74,7 @@ public partial class HistoryValuePage
} }
catch (Exception ex) catch (Exception ex)
{ {
await InvokeAsync(async () => await PopupService.EnqueueSnackbarAsync("<EFBFBD><EFBFBD>ѯʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD>" + ex.Message, AlertTypes.Warning)); await InvokeAsync(async () => await PopupService.EnqueueSnackbarAsync("查询失败,请检查网络连接:" + ex.Message, AlertTypes.Warning));
return new() return new()
{ {
Current = 1, Current = 1,

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -22,7 +22,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor; namespace ThingsGateway.Blazor;
/// <summary> /// <summary>
/// ʵʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 实时报警
/// </summary> /// </summary>
public partial class RealAlarmPage public partial class RealAlarmPage
{ {

View File

@@ -15,7 +15,7 @@ namespace ThingsGateway.Foundation;
/// <summary> /// <summary>
/// 自增 /// 自增
/// </summary> /// </summary>
public sealed class EasyIncrementCount : DisposableObject public sealed class EasyIncrementCount : IDisposable
{ {
private long current = 0; private long current = 0;
private readonly EasyLock easyLock; private readonly EasyLock easyLock;
@@ -30,6 +30,11 @@ public sealed class EasyIncrementCount : DisposableObject
IncreaseTick = tick; IncreaseTick = tick;
easyLock = new EasyLock(); easyLock = new EasyLock();
} }
/// <inheritdoc cref="EasyIncrementCount"/>
~EasyIncrementCount()
{
easyLock.SafeDispose();
}
/// <summary> /// <summary>
/// Tick /// Tick
@@ -117,10 +122,10 @@ public sealed class EasyIncrementCount : DisposableObject
} }
easyLock.Release(); easyLock.Release();
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) public void Dispose()
{ {
easyLock.SafeDispose(); easyLock.SafeDispose();
base.Dispose(disposing);
} }
} }

View File

@@ -15,11 +15,15 @@ namespace ThingsGateway.Foundation;
/// <summary> /// <summary>
/// EasyLock使用轻量级SemaphoreSlim锁只允许一个并发量并记录并发信息 /// EasyLock使用轻量级SemaphoreSlim锁只允许一个并发量并记录并发信息
/// </summary> /// </summary>
public sealed class EasyLock : DisposableObject public sealed class EasyLock : IDisposable
{ {
private static long lockWaitCount; private static long lockWaitCount;
private readonly Lazy<SemaphoreSlim> m_waiterLock = new(() => new SemaphoreSlim(1)); private readonly Lazy<SemaphoreSlim> m_waiterLock = new(() => new SemaphoreSlim(1));
/// <inheritdoc/>
~EasyLock()
{
m_waiterLock.Value.SafeDispose();
}
/// <summary> /// <summary>
/// 当前正在等待的数量 /// 当前正在等待的数量
/// </summary> /// </summary>
@@ -28,6 +32,13 @@ public sealed class EasyLock : DisposableObject
/// 当前锁是否在等待当中 /// 当前锁是否在等待当中
/// </summary> /// </summary>
public bool IsWaitting => m_waiterLock.Value.CurrentCount == 0; public bool IsWaitting => m_waiterLock.Value.CurrentCount == 0;
/// <inheritdoc/>
public void Dispose()
{
m_waiterLock.Value.SafeDispose();
}
/// <summary> /// <summary>
/// 离开锁 /// 离开锁
/// </summary> /// </summary>
@@ -73,10 +84,5 @@ public sealed class EasyLock : DisposableObject
await m_waiterLock.Value.WaitAsync(timeSpan, token); await m_waiterLock.Value.WaitAsync(timeSpan, token);
Interlocked.Decrement(ref lockWaitCount); Interlocked.Decrement(ref lockWaitCount);
} }
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
m_waiterLock.Value.SafeDispose();
base.Dispose(disposing);
}
} }

View File

@@ -325,26 +325,30 @@ public class TcpClientBaseEx : BaseSocket, ITcpClient
/// <param name="disposing"></param> /// <param name="disposing"></param>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
try if (!DisposedValue)
{ {
privateEasyLock.Wait(); try
if (this.m_online)
{ {
this.m_online = false;
this.MainSocket.TryClose();
this.PrivateOnDisconnecting(new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
this.MainSocket.SafeDispose(); privateEasyLock.Wait();
this.m_delaySender.SafeDispose(); if (this.m_online)
this.m_workStream.SafeDispose(); {
this.DataHandlingAdapter.SafeDispose(); this.m_online = false;
this.PluginsManager.SafeDispose(); this.MainSocket.TryClose();
this.PrivateOnDisconnected(new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开")); this.PrivateOnDisconnecting(new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
this.MainSocket.SafeDispose();
this.m_delaySender.SafeDispose();
this.m_workStream.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
this.PluginsManager.SafeDispose();
this.PrivateOnDisconnected(new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
}
}
finally
{
privateEasyLock.Release();
} }
}
finally
{
privateEasyLock.Release();
} }
privateEasyLock.SafeDispose(); privateEasyLock.SafeDispose();

View File

@@ -19,7 +19,7 @@ namespace ThingsGateway.Foundation;
internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClient> where TClient : IClient, IDefaultSender, ISender internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClient> where TClient : IClient, IDefaultSender, ISender
{ {
private readonly Func<ResponsedData, bool> m_func; private readonly Func<ResponsedData, bool> m_func;
private readonly SemaphoreSlim m_lock = new(1); private readonly EasyLock easyLock = new();
private readonly WaitData<ResponsedData> m_waitData = new WaitData<ResponsedData>(); private readonly WaitData<ResponsedData> m_waitData = new WaitData<ResponsedData>();
private readonly WaitDataAsync<ResponsedData> m_waitDataAsync = new WaitDataAsync<ResponsedData>(); private readonly WaitDataAsync<ResponsedData> m_waitDataAsync = new WaitDataAsync<ResponsedData>();
@@ -55,6 +55,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
this.Client = default; this.Client = default;
this.m_waitData.SafeDispose(); this.m_waitData.SafeDispose();
this.m_waitDataAsync.SafeDispose(); this.m_waitDataAsync.SafeDispose();
this.easyLock.SafeDispose();
base.Dispose(disposing); base.Dispose(disposing);
} }
@@ -121,7 +122,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
{ {
try try
{ {
m_lock.Wait(); easyLock.Wait();
this.m_breaked = false; this.m_breaked = false;
this.Reset(); this.Reset();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient) if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
@@ -184,7 +185,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
} }
finally finally
{ {
m_lock.Release(); easyLock.Release();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient) if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
{ {
tcpClient.Disconnected -= this.OnDisconnected; tcpClient.Disconnected -= this.OnDisconnected;
@@ -224,7 +225,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
{ {
try try
{ {
await m_lock.WaitAsync(); await easyLock.WaitAsync();
this.m_breaked = false; this.m_breaked = false;
this.Reset(); this.Reset();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient) if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
@@ -287,7 +288,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
} }
finally finally
{ {
m_lock.Release(); easyLock.Release();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient) if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
{ {
tcpClient.Disconnected -= this.OnDisconnected; tcpClient.Disconnected -= this.OnDisconnected;

View File

@@ -46,19 +46,6 @@ public static class StringExtensions
} }
/// <summary>
/// 将16进制的字符转换为int32。
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
public static int ByHexStringToInt32(this string hexString)
{
if (string.IsNullOrEmpty(hexString))
{
return default;
}
return int.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
}
/// <summary> /// <summary>
/// <inheritdoc cref="Path.Combine(string[])"/> /// <inheritdoc cref="Path.Combine(string[])"/>
/// 并把\\转为/ /// 并把\\转为/

View File

@@ -13,7 +13,6 @@
using System.IO.Ports; using System.IO.Ports;
using TouchSocket.Resources; using TouchSocket.Resources;
using TouchSocket.Sockets;
namespace ThingsGateway.Foundation.Serial; namespace ThingsGateway.Foundation.Serial;

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments> <OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression> <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
@@ -13,7 +13,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="TouchSocket" Version="2.0.0-beta.135" /> <PackageReference Include="TouchSocket" Version="2.0.0-beta.138" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'!='net45'"> <ItemGroup Condition="'$(TargetFramework)'!='net45'">
<PackageReference Include="System.IO.Ports" Version="7.0.0" /> <PackageReference Include="System.IO.Ports" Version="7.0.0" />

View File

@@ -588,6 +588,9 @@
<member name="M:ThingsGateway.Foundation.EasyIncrementCount.#ctor(System.Int64,System.Int64,System.Int32)"> <member name="M:ThingsGateway.Foundation.EasyIncrementCount.#ctor(System.Int64,System.Int64,System.Int32)">
<inheritdoc cref="T:ThingsGateway.Foundation.EasyIncrementCount"/> <inheritdoc cref="T:ThingsGateway.Foundation.EasyIncrementCount"/>
</member> </member>
<member name="M:ThingsGateway.Foundation.EasyIncrementCount.Finalize">
<inheritdoc cref="T:ThingsGateway.Foundation.EasyIncrementCount"/>
</member>
<member name="P:ThingsGateway.Foundation.EasyIncrementCount.IncreaseTick"> <member name="P:ThingsGateway.Foundation.EasyIncrementCount.IncreaseTick">
<summary> <summary>
Tick Tick
@@ -623,7 +626,7 @@
重置当前序号的初始值 重置当前序号的初始值
</summary> </summary>
</member> </member>
<member name="M:ThingsGateway.Foundation.EasyIncrementCount.Dispose(System.Boolean)"> <member name="M:ThingsGateway.Foundation.EasyIncrementCount.Dispose">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="T:ThingsGateway.Foundation.EasyLock"> <member name="T:ThingsGateway.Foundation.EasyLock">
@@ -631,6 +634,9 @@
EasyLock使用轻量级SemaphoreSlim锁只允许一个并发量并记录并发信息 EasyLock使用轻量级SemaphoreSlim锁只允许一个并发量并记录并发信息
</summary> </summary>
</member> </member>
<member name="M:ThingsGateway.Foundation.EasyLock.Finalize">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.EasyLock.LockWaitCount"> <member name="P:ThingsGateway.Foundation.EasyLock.LockWaitCount">
<summary> <summary>
当前正在等待的数量 当前正在等待的数量
@@ -641,6 +647,9 @@
当前锁是否在等待当中 当前锁是否在等待当中
</summary> </summary>
</member> </member>
<member name="M:ThingsGateway.Foundation.EasyLock.Dispose">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.EasyLock.Release"> <member name="M:ThingsGateway.Foundation.EasyLock.Release">
<summary> <summary>
离开锁 离开锁
@@ -666,9 +675,6 @@
进入锁 进入锁
</summary> </summary>
</member> </member>
<member name="M:ThingsGateway.Foundation.EasyLock.Dispose(System.Boolean)">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.TcpClientEx"> <member name="T:ThingsGateway.Foundation.TcpClientEx">
<summary> <summary>
简单TCP客户端 简单TCP客户端
@@ -1283,13 +1289,6 @@
<param name="value"></param> <param name="value"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:ThingsGateway.Foundation.Extension.String.StringExtensions.ByHexStringToInt32(System.String)">
<summary>
将16进制的字符转换为int32。
</summary>
<param name="hexString"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Extension.String.StringExtensions.CombinePathOS(System.String,System.String[])"> <member name="M:ThingsGateway.Foundation.Extension.String.StringExtensions.CombinePathOS(System.String,System.String[])">
<summary> <summary>
<inheritdoc cref="M:System.IO.Path.Combine(System.String[])"/> <inheritdoc cref="M:System.IO.Path.Combine(System.String[])"/>

View File

@@ -31,11 +31,11 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
private DataFormat dataFormat; private DataFormat dataFormat;
/// <inheritdoc/> /// <inheritdoc/>
[JsonIgnore] [JsonIgnore]
public Encoding Encoding { get; set; } = Encoding.UTF8; public virtual Encoding Encoding { get; set; } = Encoding.UTF8;
/// <inheritdoc/> /// <inheritdoc/>
public BcdFormat? BcdFormat { get; set; } public virtual BcdFormat? BcdFormat { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public int StringLength { get; set; } public virtual int StringLength { get; set; }
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
@@ -55,7 +55,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public DataFormat DataFormat public virtual DataFormat DataFormat
{ {
get get
{ {
@@ -69,9 +69,9 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
/// <inheritdoc/> /// <inheritdoc/>
public EndianType EndianType => endianType; public virtual EndianType EndianType => endianType;
/// <inheritdoc/> /// <inheritdoc/>
public bool IsStringReverseByteWord { get; set; } public virtual bool IsStringReverseByteWord { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public virtual IThingsGatewayBitConverter CreateByDateFormat(DataFormat dataFormat) public virtual IThingsGatewayBitConverter CreateByDateFormat(DataFormat dataFormat)
@@ -86,7 +86,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return byteConverter; return byteConverter;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(bool value) public virtual byte[] GetBytes(bool value)
{ {
return GetBytes(new bool[1] return GetBytes(new bool[1]
{ {
@@ -95,13 +95,13 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(bool[] values) public virtual byte[] GetBytes(bool[] values)
{ {
return values?.BoolArrayToByte(); return values?.BoolArrayToByte();
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(short value) public virtual byte[] GetBytes(short value)
{ {
byte[] bytes = BitConverter.GetBytes(value); byte[] bytes = BitConverter.GetBytes(value);
if (!IsSameOfSet()) if (!IsSameOfSet())
@@ -111,7 +111,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return bytes; return bytes;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(short[] value) public virtual byte[] GetBytes(short[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -123,7 +123,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(ushort value) public virtual byte[] GetBytes(ushort value)
{ {
byte[] bytes = BitConverter.GetBytes(value); byte[] bytes = BitConverter.GetBytes(value);
if (!IsSameOfSet()) if (!IsSameOfSet())
@@ -133,7 +133,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return bytes; return bytes;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(ushort[] value) public virtual byte[] GetBytes(ushort[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -144,12 +144,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(int value) public virtual byte[] GetBytes(int value)
{ {
return ByteTransDataFormat4(BitConverter.GetBytes(value)); return ByteTransDataFormat4(BitConverter.GetBytes(value));
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(int[] value) public virtual byte[] GetBytes(int[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -160,12 +160,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(uint value) public virtual byte[] GetBytes(uint value)
{ {
return ByteTransDataFormat4(BitConverter.GetBytes(value)); return ByteTransDataFormat4(BitConverter.GetBytes(value));
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(uint[] value) public virtual byte[] GetBytes(uint[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -176,12 +176,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(long value) public virtual byte[] GetBytes(long value)
{ {
return ByteTransDataFormat8(BitConverter.GetBytes(value)); return ByteTransDataFormat8(BitConverter.GetBytes(value));
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(long[] value) public virtual byte[] GetBytes(long[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -192,12 +192,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(ulong value) public virtual byte[] GetBytes(ulong value)
{ {
return ByteTransDataFormat8(BitConverter.GetBytes(value)); return ByteTransDataFormat8(BitConverter.GetBytes(value));
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(ulong[] value) public virtual byte[] GetBytes(ulong[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -208,12 +208,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(float value) public virtual byte[] GetBytes(float value)
{ {
return ByteTransDataFormat4(BitConverter.GetBytes(value)); return ByteTransDataFormat4(BitConverter.GetBytes(value));
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(float[] value) public virtual byte[] GetBytes(float[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -224,12 +224,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(double value) public virtual byte[] GetBytes(double value)
{ {
return ByteTransDataFormat8(BitConverter.GetBytes(value)); return ByteTransDataFormat8(BitConverter.GetBytes(value));
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(double[] value) public virtual byte[] GetBytes(double[] value)
{ {
byte[] numArray = new byte[value.Length * 2]; byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index) for (int index = 0; index < value.Length; ++index)
@@ -240,7 +240,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] GetBytes(string value) public virtual byte[] GetBytes(string value)
{ {
if (value == null) if (value == null)
{ {
@@ -280,7 +280,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
/// <inheritdoc/> /// <inheritdoc/>
public bool IsSameOfSet() public virtual bool IsSameOfSet()
{ {
return !(BitConverter.IsLittleEndian ^ (endianType == EndianType.Little)); return !(BitConverter.IsLittleEndian ^ (endianType == EndianType.Little));
} }
@@ -288,7 +288,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
/// <inheritdoc/> /// <inheritdoc/>
public bool ToBoolean(byte[] buffer, int offset) public virtual bool ToBoolean(byte[] buffer, int offset)
{ {
byte[] bytes = new byte[buffer.Length]; byte[] bytes = new byte[buffer.Length];
Array.Copy(buffer, 0, bytes, 0, buffer.Length); Array.Copy(buffer, 0, bytes, 0, buffer.Length);
@@ -296,7 +296,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte ToByte(byte[] buffer, int offset) public virtual byte ToByte(byte[] buffer, int offset)
{ {
byte[] bytes = new byte[1]; byte[] bytes = new byte[1];
Array.Copy(buffer, offset, bytes, 0, bytes.Length); Array.Copy(buffer, offset, bytes, 0, bytes.Length);
@@ -304,7 +304,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public byte[] ToByte(byte[] buffer, int offset, int length) public virtual byte[] ToByte(byte[] buffer, int offset, int length)
{ {
byte[] bytes = new byte[length]; byte[] bytes = new byte[length];
Array.Copy(buffer, offset, bytes, 0, bytes.Length); Array.Copy(buffer, offset, bytes, 0, bytes.Length);
@@ -317,7 +317,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
/// <param name="buffer"></param> /// <param name="buffer"></param>
/// <param name="offset"></param> /// <param name="offset"></param>
/// <returns></returns> /// <returns></returns>
public double ToDouble(byte[] buffer, int offset) public virtual double ToDouble(byte[] buffer, int offset)
{ {
byte[] bytes = ByteTransDataFormat8(buffer, offset); byte[] bytes = ByteTransDataFormat8(buffer, offset);
@@ -325,7 +325,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public short ToInt16(byte[] buffer, int offset) public virtual short ToInt16(byte[] buffer, int offset)
{ {
byte[] bytes = new byte[2]; byte[] bytes = new byte[2];
Array.Copy(buffer, offset, bytes, 0, bytes.Length); Array.Copy(buffer, offset, bytes, 0, bytes.Length);
@@ -337,7 +337,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public int ToInt32(byte[] buffer, int offset) public virtual int ToInt32(byte[] buffer, int offset)
{ {
byte[] bytes = ByteTransDataFormat4(buffer, offset); byte[] bytes = ByteTransDataFormat4(buffer, offset);
@@ -345,14 +345,14 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public long ToInt64(byte[] buffer, int offset) public virtual long ToInt64(byte[] buffer, int offset)
{ {
byte[] bytes = ByteTransDataFormat8(buffer, offset); byte[] bytes = ByteTransDataFormat8(buffer, offset);
return BitConverter.ToInt64(bytes, 0); return BitConverter.ToInt64(bytes, 0);
} }
/// <inheritdoc/> /// <inheritdoc/>
public float ToSingle(byte[] buffer, int offset) public virtual float ToSingle(byte[] buffer, int offset)
{ {
byte[] bytes = ByteTransDataFormat4(buffer, offset); byte[] bytes = ByteTransDataFormat4(buffer, offset);
@@ -360,13 +360,13 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public string ToString(byte[] buffer) public virtual string ToString(byte[] buffer)
{ {
return ToString(buffer, 0, buffer.Length); return ToString(buffer, 0, buffer.Length);
} }
/// <inheritdoc/> /// <inheritdoc/>
public string ToString(byte[] buffer, int offset, int length) public virtual string ToString(byte[] buffer, int offset, int length)
{ {
byte[] numArray = buffer.SelectMiddle(offset, length); byte[] numArray = buffer.SelectMiddle(offset, length);
if (BcdFormat != null) if (BcdFormat != null)
@@ -385,7 +385,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public ushort ToUInt16(byte[] buffer, int offset) public virtual ushort ToUInt16(byte[] buffer, int offset)
{ {
byte[] bytes = new byte[2]; byte[] bytes = new byte[2];
Array.Copy(buffer, offset, bytes, 0, 2); Array.Copy(buffer, offset, bytes, 0, 2);
@@ -397,7 +397,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public uint ToUInt32(byte[] buffer, int offset) public virtual uint ToUInt32(byte[] buffer, int offset)
{ {
byte[] bytes = ByteTransDataFormat4(buffer, offset); byte[] bytes = ByteTransDataFormat4(buffer, offset);
@@ -405,7 +405,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public ulong ToUInt64(byte[] buffer, int offset) public virtual ulong ToUInt64(byte[] buffer, int offset)
{ {
byte[] bytes = ByteTransDataFormat8(buffer, offset); byte[] bytes = ByteTransDataFormat8(buffer, offset);
return BitConverter.ToUInt64(bytes, 0); return BitConverter.ToUInt64(bytes, 0);
@@ -508,7 +508,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public bool[] ToBoolean(byte[] buffer, int offset, int len) public virtual bool[] ToBoolean(byte[] buffer, int offset, int len)
{ {
bool[] flagArray = new bool[len]; bool[] flagArray = new bool[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -519,7 +519,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public double[] ToDouble(byte[] buffer, int offset, int len) public virtual double[] ToDouble(byte[] buffer, int offset, int len)
{ {
double[] numArray = new double[len]; double[] numArray = new double[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -530,7 +530,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public short[] ToInt16(byte[] buffer, int offset, int len) public virtual short[] ToInt16(byte[] buffer, int offset, int len)
{ {
short[] numArray = new short[len]; short[] numArray = new short[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -541,7 +541,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public int[] ToInt32(byte[] buffer, int offset, int len) public virtual int[] ToInt32(byte[] buffer, int offset, int len)
{ {
int[] numArray = new int[len]; int[] numArray = new int[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -552,7 +552,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public long[] ToInt64(byte[] buffer, int offset, int len) public virtual long[] ToInt64(byte[] buffer, int offset, int len)
{ {
long[] numArray = new long[len]; long[] numArray = new long[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -562,7 +562,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
return numArray; return numArray;
} }
/// <inheritdoc/> /// <inheritdoc/>
public float[] ToSingle(byte[] buffer, int offset, int len) public virtual float[] ToSingle(byte[] buffer, int offset, int len)
{ {
float[] numArray = new float[len]; float[] numArray = new float[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -573,7 +573,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public ushort[] ToUInt16(byte[] buffer, int offset, int len) public virtual ushort[] ToUInt16(byte[] buffer, int offset, int len)
{ {
ushort[] numArray = new ushort[len]; ushort[] numArray = new ushort[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -584,7 +584,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public uint[] ToUInt32(byte[] buffer, int offset, int len) public virtual uint[] ToUInt32(byte[] buffer, int offset, int len)
{ {
uint[] numArray = new uint[len]; uint[] numArray = new uint[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)
@@ -595,7 +595,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
} }
/// <inheritdoc/> /// <inheritdoc/>
public ulong[] ToUInt64(byte[] buffer, int offset, int len) public virtual ulong[] ToUInt64(byte[] buffer, int offset, int len)
{ {
ulong[] numArray = new ulong[len]; ulong[] numArray = new ulong[len];
for (int index = 0; index < len; ++index) for (int index = 0; index < len; ++index)

View File

@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Foundataion\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj" /> <PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="2.0.9" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -12,7 +12,7 @@ namespace ModbusDemo
{ {
static async Task Main(string[] args) static async Task Main(string[] args)
{ {
//await ModbusClientAsync(); await ModbusClientAsync();
await ModbusServerAsync(); await ModbusServerAsync();

View File

@@ -8,7 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Foundataion\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj" /> <PackageReference Include="ThingsGateway.Foundation.Adapter.OPCUA" Version="2.0.9" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,7 +1,7 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Version>2.0.7.0</Version> <Version>2.0.9.3</Version>
<Authors>Diego</Authors> <Authors>Diego</Authors>
<Product>ThingsGateway</Product> <Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright> <Copyright>© 2023-present Diego</Copyright>

View File

@@ -60,45 +60,94 @@ public class ModbusAddress : DeviceAddressBase
/// <inheritdoc/> /// <inheritdoc/>
public override void Parse(string address, int length) public override void Parse(string address, int length)
{ {
Length = length; var result = ParseFrom(address, length);
if (address.IndexOf(';') < 0) if (result.IsSuccess)
{ {
Address(address); Length = result.Content.Length;
AddressStart = result.Content.AddressStart;
ReadFunction = result.Content.ReadFunction;
if (result.Content.Station > 0)
Station = result.Content.Station;
WriteFunction = result.Content.WriteFunction;
} }
else }
/// <summary>
/// 解析地址
/// </summary>
/// <param name="address"></param>
/// <param name="length"></param>
/// <returns></returns>
public static OperResult<ModbusAddress> ParseFrom(string address, int length)
{
try
{ {
string[] strArray = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); ModbusAddress modbusAddress = new()
for (int index = 0; index < strArray.Length; ++index)
{ {
if (strArray[index].ToUpper().StartsWith("S=")) Length = length
};
if (address.IndexOf(';') < 0)
{
Address(address);
}
else
{
string[] strArray = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
for (int index = 0; index < strArray.Length; ++index)
{ {
if (Convert.ToInt16(strArray[index].Substring(2)) > 0) if (strArray[index].ToUpper().StartsWith("S="))
Station = byte.Parse(strArray[index].Substring(2)); {
} if (Convert.ToInt16(strArray[index].Substring(2)) > 0)
else if (strArray[index].ToUpper().StartsWith("W=")) modbusAddress.Station = byte.Parse(strArray[index].Substring(2));
{ }
if (Convert.ToInt16(strArray[index].Substring(2)) > 0) else if (strArray[index].ToUpper().StartsWith("W="))
this.WriteFunction = byte.Parse(strArray[index].Substring(2)); {
} if (Convert.ToInt16(strArray[index].Substring(2)) > 0)
else if (!strArray[index].Contains("=")) modbusAddress.WriteFunction = byte.Parse(strArray[index].Substring(2));
{ }
Address(strArray[index]); else if (!strArray[index].Contains("="))
{
Address(strArray[index]);
}
} }
} }
}
void Address(string address) return OperResult.CreateSuccessResult(modbusAddress);
void Address(string address)
{
var readF = ushort.Parse(address.Substring(0, 1));
if (readF > 4)
throw new("功能码错误");
switch (readF)
{
case 0:
modbusAddress.ReadFunction = 1;
break;
case 1:
modbusAddress.ReadFunction = 2;
break;
case 3:
modbusAddress.ReadFunction = 4;
break;
case 4:
modbusAddress.ReadFunction = 3;
break;
}
modbusAddress.AddressStart = int.Parse(address.Substring(1)) - 1;
}
}
catch (Exception ex)
{ {
var readF = ushort.Parse(address.Substring(0, 1)); return new OperResult<ModbusAddress>(ex);
if (readF > 4)
throw new("功能码错误");
GetFunction(readF);
AddressStart = int.Parse(address.Substring(1)) - 1;
} }
} }
/// <inheritdoc/> /// <inheritdoc/>
public override string ToString() public override string ToString()
{ {
@@ -115,24 +164,6 @@ public class ModbusAddress : DeviceAddressBase
return stringGeter.ToString(); return stringGeter.ToString();
} }
private void GetFunction(ushort readF)
{
switch (readF)
{
case 0:
ReadFunction = 1;
break;
case 1:
ReadFunction = 2;
break;
case 3:
ReadFunction = 4;
break;
case 4:
ReadFunction = 3;
break;
}
}
private string GetFunctionString(int readF) private string GetFunctionString(int readF)
{ {
return readF switch return readF switch

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<!--<GenerateDocumentationFile>True</GenerateDocumentationFile>--> <!--<GenerateDocumentationFile>True</GenerateDocumentationFile>-->
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>

View File

@@ -38,6 +38,14 @@
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.Parse(System.String,System.Int32)"> <member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.Parse(System.String,System.Int32)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ParseFrom(System.String,System.Int32)">
<summary>
解析地址
</summary>
<param name="address"></param>
<param name="length"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ToString"> <member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ToString">
<inheritdoc/> <inheritdoc/>
</member> </member>

View File

@@ -301,50 +301,94 @@ public class OPCDAClient : DisposableObject
return OPCNode?.ToString(); return OPCNode?.ToString();
} }
/// <summary> /// <summary>
/// 写入值 /// 批量写入值
/// </summary> /// </summary>
/// <param name="valueName">写入</param>
/// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public OperResult WriteItem(string valueName, JToken value) public Dictionary<string, OperResult> WriteItem(Dictionary<string, JToken> writeInfos)
{ {
Dictionary<string, OperResult> results = new();
if (PrivateConnect()) if (PrivateConnect())
{ {
try try
{ {
var group = Groups.FirstOrDefault(it => it.OpcItems.Any(a => a.ItemID == valueName)); var valueGroup = writeInfos.GroupBy(itemId =>
if (group == null) {
return new OperResult("不存在该变量" + valueName); var group = Groups.FirstOrDefault(it => it.OpcItems.Any(a => a.ItemID == itemId.Key));
var item = group.OpcItems.Where(it => it.ItemID == valueName).FirstOrDefault(); return group;
int[] serverHandle = new int[1] { item.ServerHandle }; }).ToList();
int[] PErrors = new int[1];
var jtoken = value;
var rank = jtoken.CalculateActualValueRank();
object rawWriteValue;
switch (rank) foreach (var item1 in valueGroup)
{ {
case -1: if (item1.Key == null)
rawWriteValue = ((JValue)jtoken).Value; {
break; foreach (var item2 in item1)
default: {
var jarray = ((JArray)jtoken); results.Add(item2.Key, new OperResult("不存在该变量" + item2.Key));
rawWriteValue = jarray.Select(j => (object)j).ToArray(); }
break; }
else
{
List<int> ServerHandles = new();
List<object> Values = new();
foreach (var item2 in item1)
{
var opcItem = item1.Key.OpcItems.Where(it => it.ItemID == item2.Key).FirstOrDefault();
ServerHandles.Add(opcItem.ServerHandle);
var jtoken = item2.Value;
var rank = jtoken.CalculateActualValueRank();
object rawWriteValue;
switch (rank)
{
case -1:
rawWriteValue = ((JValue)jtoken).Value;
break;
default:
var jarray = ((JArray)jtoken);
rawWriteValue = jarray.Select(j => (object)j).ToArray();
break;
}
Values.Add(rawWriteValue);
}
var result = item1.Key.Write(Values.ToArray(), ServerHandles.ToArray(), out var PErrors);
var data = item1.ToList();
for (int i = 0; i < data.Count; i++)
{
results.Add(data[i].Key, PErrors[i] == 0 ? OperResult.CreateSuccessResult() : new OperResult("错误代码:" + PErrors[i]));
}
}
} }
object[] Value = new object[1] { rawWriteValue }; return results;
var result = group.Write(Value, serverHandle, out PErrors);
return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
return new OperResult(ex.Message); var keys = writeInfos.Keys.ToList();
foreach (var item in keys)
{
results.AddOrUpdate(item, new(ex));
}
return results;
} }
} }
return new OperResult(); else
{
var keys = writeInfos.Keys.ToList();
foreach (var item in keys)
{
results.AddOrUpdate(item, new("未初始化连接"));
}
return results;
}
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<!--<GenerateDocumentationFile>True</GenerateDocumentationFile>--> <!--<GenerateDocumentationFile>True</GenerateDocumentationFile>-->
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>

View File

@@ -520,12 +520,10 @@
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString"> <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.String,Newtonsoft.Json.Linq.JToken)"> <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken})">
<summary> <summary>
写入值 批量写入值
</summary> </summary>
<param name="valueName">写入</param>
<param name="value"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)"> <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)">

View File

@@ -521,29 +521,33 @@ public class OPCUAClient : DisposableObject
/// <summary> /// <summary>
/// 异步写opc标签 /// 异步写opc标签
/// </summary> /// </summary>
public async Task<OperResult> WriteNodeAsync(string tag, JToken value, CancellationToken token = default) public async Task<Dictionary<string, OperResult>> WriteNodeAsync(Dictionary<string, JToken> writeInfoLists, CancellationToken token = default)
{ {
Dictionary<string, OperResult> results = new();
try try
{ {
WriteValue valueToWrite = new() WriteValueCollection valuesToWrite = new();
foreach (var item in writeInfoLists)
{ {
NodeId = new NodeId(tag), WriteValue valueToWrite = new()
AttributeId = Attributes.Value, {
}; NodeId = new NodeId(item.Key),
var variableNode = (VariableNode)ReadNode(tag.ToString(), false); AttributeId = Attributes.Value,
await typeSystem.LoadType(variableNode.DataType, true, true); };
var dataValue = JsonUtils.Decode( var variableNode = (VariableNode)ReadNode(item.Key, false);
m_session.MessageContext, await typeSystem.LoadType(variableNode.DataType, true, true);
variableNode.DataType, var dataValue = JsonUtils.Decode(
TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), m_session.MessageContext,
value.CalculateActualValueRank(), variableNode.DataType,
value TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable),
); item.Value.CalculateActualValueRank(),
valueToWrite.Value = dataValue; item.Value
WriteValueCollection valuesToWrite = new() );
{ valueToWrite.Value = dataValue;
valueToWrite
}; valuesToWrite.Add(valueToWrite);
}
var result = await m_session.WriteAsync( var result = await m_session.WriteAsync(
requestHeader: null, requestHeader: null,
@@ -551,15 +555,29 @@ public class OPCUAClient : DisposableObject
ClientBase.ValidateResponse(result.Results, valuesToWrite); ClientBase.ValidateResponse(result.Results, valuesToWrite);
ClientBase.ValidateDiagnosticInfos(result.DiagnosticInfos, valuesToWrite); ClientBase.ValidateDiagnosticInfos(result.DiagnosticInfos, valuesToWrite);
if (!StatusCode.IsGood(result.Results[0]))
var keys = writeInfoLists.Keys.ToList();
for (int i = 0; i < keys.Count; i++)
{ {
return new OperResult(result.Results[0].ToString()); if (!StatusCode.IsGood(result.Results[i]))
results.Add(keys[i], new(result.Results[i].ToString()));
else
{
results.Add(keys[i], OperResult.CreateSuccessResult());
}
} }
return OperResult.CreateSuccessResult();
return results;
} }
catch (Exception ex) catch (Exception ex)
{ {
return new OperResult(ex); var keys = writeInfoLists.Keys.ToList();
foreach (var item in keys)
{
results.Add(item, new(ex));
}
return results;
} }
} }

View File

@@ -375,7 +375,7 @@
从服务器读取值 从服务器读取值
</summary> </summary>
</member> </member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.String,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
<summary> <summary>
异步写opc标签 异步写opc标签
</summary> </summary>

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<!--<GenerateDocumentationFile>True</GenerateDocumentationFile>--> <!--<GenerateDocumentationFile>True</GenerateDocumentationFile>-->
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using Newtonsoft.Json.Linq;
using ThingsGateway.Application; using ThingsGateway.Application;
using ThingsGateway.Foundation; using ThingsGateway.Foundation;
using ThingsGateway.Foundation.Serial; using ThingsGateway.Foundation.Serial;
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
public class ModbusRtu : CollectBase public class ModbusRtu : CollectBase
{ {
private readonly ModbusRtuProperty driverPropertys = new(); private readonly ModbusRtuProperty driverPropertys = new();
/// <inheritdoc/>
protected override IReadWriteDevice PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu _plc; private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu _plc;
/// <inheritdoc/> /// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusRtuDebugDriverPage); public override Type DriverDebugUIType => typeof(ModbusRtuDebugDriverPage);
@@ -74,12 +74,6 @@ public class ModbusRtu : CollectBase
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack); return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
} }
/// <inheritdoc/>
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
{
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null) protected override void Init(CollectDeviceRunTime device, object client = null)
{ {

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using Newtonsoft.Json.Linq;
using ThingsGateway.Application; using ThingsGateway.Application;
using ThingsGateway.Foundation; using ThingsGateway.Foundation;
@@ -22,6 +20,8 @@ public class ModbusRtuOverTcp : CollectBase
{ {
private readonly ModbusRtuOverTcpProperty driverPropertys = new(); private readonly ModbusRtuOverTcpProperty driverPropertys = new();
/// <inheritdoc/>
protected override IReadWriteDevice PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp _plc; private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp _plc;
/// <inheritdoc/> /// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusRtuOverTcpDebugDriverPage); public override Type DriverDebugUIType => typeof(ModbusRtuOverTcpDebugDriverPage);
@@ -61,11 +61,7 @@ public class ModbusRtuOverTcp : CollectBase
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack); return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
} }
/// <inheritdoc/>
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
{
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using Newtonsoft.Json.Linq;
using ThingsGateway.Application; using ThingsGateway.Application;
using ThingsGateway.Foundation; using ThingsGateway.Foundation;
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
public class ModbusRtuOverUdp : CollectBase public class ModbusRtuOverUdp : CollectBase
{ {
private readonly ModbusRtuOverUdpProperty driverPropertys = new(); private readonly ModbusRtuOverUdpProperty driverPropertys = new();
/// <inheritdoc/>
protected override IReadWriteDevice PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp _plc; private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp _plc;
/// <inheritdoc/> /// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusRtuOverUdpDebugDriverPage); public override Type DriverDebugUIType => typeof(ModbusRtuOverUdpDebugDriverPage);
@@ -65,11 +65,7 @@ public class ModbusRtuOverUdp : CollectBase
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack); return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
} }
/// <inheritdoc/>
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
{
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -201,16 +201,25 @@ public class ModbusServer : UpLoadBase
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result)) if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
{ {
var resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{CurDevice.Name}-{client.IP + ":" + client.Port}", var resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{CurDevice.Name}-{client.IP + ":" + client.Port}",
new(tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, result.GetSystemType(), bytes).ToString())); new Dictionary<string, string>
{
{tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, result.GetSystemType(), bytes).ToString()},
}
);
var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult(); var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult();
return result1; return result1.FirstOrDefault().Value;
} }
else else
{ {
var resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{CurDevice.Name}-{client.IP + ":" + client.Port}", var resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusServer)}-{CurDevice.Name}-{client.IP + ":" + client.Port}",
new(tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, tag.Value.DataType, bytes).ToString())); new Dictionary<string, string>
{
{tag.Value.Name, thingsGatewayBitConverter.GetDynamicDataFormBytes(addressStr ?? string.Empty, result.GetSystemType(), bytes).ToString()},
}
);
var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult(); var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult();
return result1; return result1.FirstOrDefault().Value;
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using Newtonsoft.Json.Linq;
using ThingsGateway.Application; using ThingsGateway.Application;
using ThingsGateway.Foundation; using ThingsGateway.Foundation;
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
/// </summary> /// </summary>
public class ModbusTcp : CollectBase public class ModbusTcp : CollectBase
{ {
/// <inheritdoc/>
protected override IReadWriteDevice PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp _plc; private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp _plc;
private readonly ModbusTcpProperty driverPropertys = new(); private readonly ModbusTcpProperty driverPropertys = new();
@@ -67,11 +67,7 @@ public class ModbusTcp : CollectBase
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack); return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
} }
/// <inheritdoc/>
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
{
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using Newtonsoft.Json.Linq;
using ThingsGateway.Application; using ThingsGateway.Application;
using ThingsGateway.Foundation; using ThingsGateway.Foundation;
@@ -21,6 +19,8 @@ namespace ThingsGateway.Modbus;
/// <inheritdoc/> /// <inheritdoc/>
public class ModbusUdp : CollectBase public class ModbusUdp : CollectBase
{ {
/// <inheritdoc/>
protected override IReadWriteDevice PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp _plc; private ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp _plc;
private readonly ModbusUdpProperty driverPropertys = new(); private readonly ModbusUdpProperty driverPropertys = new();
@@ -66,11 +66,7 @@ public class ModbusUdp : CollectBase
return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack); return deviceVariables.LoadSourceRead(_plc, driverPropertys.MaxPack);
} }
/// <inheritdoc/>
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
{
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -7,6 +7,9 @@
<member name="T:ThingsGateway.Modbus.ModbusRtuOverTcp"> <member name="T:ThingsGateway.Modbus.ModbusRtuOverTcp">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:ThingsGateway.Modbus.ModbusRtuOverTcp.PLC">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Modbus.ModbusRtuOverTcp.DriverDebugUIType"> <member name="P:ThingsGateway.Modbus.ModbusRtuOverTcp.DriverDebugUIType">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -34,9 +37,6 @@
<member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})"> <member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.Dispose(System.Boolean)"> <member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.Dispose(System.Boolean)">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -116,6 +116,9 @@
<inheritdoc/> <inheritdoc/>
</summary> </summary>
</member> </member>
<member name="P:ThingsGateway.Modbus.ModbusRtuOverUdp.PLC">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Modbus.ModbusRtuOverUdp.DriverDebugUIType"> <member name="P:ThingsGateway.Modbus.ModbusRtuOverUdp.DriverDebugUIType">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -143,9 +146,6 @@
<member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})"> <member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.Dispose(System.Boolean)"> <member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.Dispose(System.Boolean)">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -168,6 +168,9 @@
<member name="T:ThingsGateway.Modbus.ModbusRtu"> <member name="T:ThingsGateway.Modbus.ModbusRtu">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:ThingsGateway.Modbus.ModbusRtu.PLC">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Modbus.ModbusRtu.DriverDebugUIType"> <member name="P:ThingsGateway.Modbus.ModbusRtu.DriverDebugUIType">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -200,9 +203,6 @@
<member name="M:ThingsGateway.Modbus.ModbusRtu.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})"> <member name="M:ThingsGateway.Modbus.ModbusRtu.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Modbus.ModbusRtu.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Modbus.ModbusRtu.Init(ThingsGateway.Application.CollectDeviceRunTime,System.Object)"> <member name="M:ThingsGateway.Modbus.ModbusRtu.Init(ThingsGateway.Application.CollectDeviceRunTime,System.Object)">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -400,6 +400,9 @@
<inheritdoc/> <inheritdoc/>
</summary> </summary>
</member> </member>
<member name="P:ThingsGateway.Modbus.ModbusTcp.PLC">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Modbus.ModbusTcp.DriverDebugUIType"> <member name="P:ThingsGateway.Modbus.ModbusTcp.DriverDebugUIType">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -427,9 +430,6 @@
<member name="M:ThingsGateway.Modbus.ModbusTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})"> <member name="M:ThingsGateway.Modbus.ModbusTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Modbus.ModbusTcp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Modbus.ModbusTcp.Dispose(System.Boolean)"> <member name="M:ThingsGateway.Modbus.ModbusTcp.Dispose(System.Boolean)">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -507,6 +507,9 @@
<member name="T:ThingsGateway.Modbus.ModbusUdp"> <member name="T:ThingsGateway.Modbus.ModbusUdp">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:ThingsGateway.Modbus.ModbusUdp.PLC">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Modbus.ModbusUdp.DriverDebugUIType"> <member name="P:ThingsGateway.Modbus.ModbusUdp.DriverDebugUIType">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -534,9 +537,6 @@
<member name="M:ThingsGateway.Modbus.ModbusUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})"> <member name="M:ThingsGateway.Modbus.ModbusUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Modbus.ModbusUdp.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Modbus.ModbusUdp.Dispose(System.Boolean)"> <member name="M:ThingsGateway.Modbus.ModbusUdp.Dispose(System.Boolean)">
<inheritdoc/> <inheritdoc/>
</member> </member>

View File

@@ -340,9 +340,7 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
&& driverPropertys.DeviceRpcEnable; && driverPropertys.DeviceRpcEnable;
if (rpcEnable == true) if (rpcEnable == true)
{ {
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + rpcrequestid, item);
results.Add(item.Key, result);
} }
else else
@@ -356,6 +354,12 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
results.Add(item.Key, new("不存在该变量")); results.Add(item.Key, new("不存在该变量"));
} }
} }
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + rpcrequestid, nameValue
.Where(a => !results.Any(b => b.Key == a.Key))
.ToDictionary(a => a.Key, a => a.Value));
results.AddRange(result);
rpcResponse = new() rpcResponse = new()
{ {
DeviceId = rpcdevicename, DeviceId = rpcdevicename,

View File

@@ -317,6 +317,7 @@ public class MqttClient : UpLoadBase
.WithTcpServer(driverPropertys.IP, driverPropertys.Port)//服务器 .WithTcpServer(driverPropertys.IP, driverPropertys.Port)//服务器
.WithCleanSession(true) .WithCleanSession(true)
.WithKeepAlivePeriod(TimeSpan.FromSeconds(120.0)) .WithKeepAlivePeriod(TimeSpan.FromSeconds(120.0))
.WithoutThrowOnNonSuccessfulConnectResponse()
.Build(); .Build();
_mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder() _mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter( .WithTopicFilter(
@@ -405,40 +406,48 @@ public class MqttClient : UpLoadBase
return; return;
if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic) if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
return; return;
var rpcData = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>(); var rpcDatas = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
if (rpcData == null) if (rpcDatas == null)
return; return;
MqttRpcResult mqttRpcResult = new(); MqttRpcResult mqttRpcResult = new() { RpcId = rpcDatas.RpcId, Success = true };
try try
{ {
var nv = rpcData.Adapt<KeyValuePair<string, string>>(); foreach (var rpcData in rpcDatas.WriteInfos)
var tag = _uploadVariables.FirstOrDefault(a => a.Name == nv.Key);
if (tag != null)
{ {
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
if (rpcEnable == true) var tag = _uploadVariables.FirstOrDefault(a => a.Name == rpcData.Key);
if (tag != null)
{ {
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + arg.ClientId, nv); var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
if (rpcEnable == true)
mqttRpcResult = new() { Message = result.Message, RpcId = rpcData.RpcId, Success = result.IsSuccess }; {
}
else
{
mqttRpcResult.Success = false;
mqttRpcResult.Message.Add(rpcData.Key, new("权限不足,变量不支持写入"));
}
} }
else else
{ {
mqttRpcResult = new() { Message = "权限不足,变量不支持写入", RpcId = rpcData.RpcId, Success = false }; mqttRpcResult.Success = false;
mqttRpcResult.Message.Add(rpcData.Key, new("不存在该变量"));
} }
}
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + arg.ClientId,
rpcDatas.WriteInfos.Where(
a => !mqttRpcResult.Message.Any(b => b.Key == a.Key)).ToDictionary(a => a.Key, a => a.Value));
mqttRpcResult.Message.AddRange(result);
mqttRpcResult.Success = !mqttRpcResult.Message.Any(a => !a.Value.IsSuccess);
}
else
{
mqttRpcResult = new() { Message = "不存在该变量", RpcId = rpcData.RpcId, Success = false };
}
} }
catch (Exception ex) catch (Exception ex)
{ {
LogMessage?.LogWarning(ex, ToString()); LogMessage?.LogWarning(ex, ToString());
mqttRpcResult = new() { Message = "Failed", RpcId = rpcData.RpcId, Success = false };
} }
try try
{ {

View File

@@ -10,6 +10,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using System.Collections.Generic;
using ThingsGateway.Foundation;
namespace ThingsGateway.Mqtt; namespace ThingsGateway.Mqtt;
/// <summary> /// <summary>
@@ -22,13 +26,9 @@ public class MqttRpcNameVaueWithId
/// </summary> /// </summary>
public string RpcId { get; set; } public string RpcId { get; set; }
/// <summary> /// <summary>
/// 通常是变量名称 /// "WriteInfos":{"test":"1"}
/// </summary> /// </summary>
public string Key { get; set; } public Dictionary<string, string> WriteInfos { get; set; } = new();
/// <summary>
/// 值
/// </summary>
public string Value { get; set; }
} }
/// <summary> /// <summary>
/// MqttRpc输出 /// MqttRpc输出
@@ -42,7 +42,7 @@ public class MqttRpcResult
/// <summary> /// <summary>
/// 消息 /// 消息
/// </summary> /// </summary>
public string Message { get; set; } public Dictionary<string, OperResult> Message { get; set; } = new();
/// <summary> /// <summary>
/// 是否成功 /// 是否成功
/// </summary> /// </summary>

View File

@@ -260,41 +260,46 @@ public class MqttServer : UpLoadBase
return; return;
if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic) if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
return; return;
var rpcData = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>(); var rpcDatas = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
if (rpcData == null) if (rpcDatas == null)
return; return;
MqttRpcResult mqttRpcResult = new(); MqttRpcResult mqttRpcResult = new() { RpcId = rpcDatas.RpcId, Success = true };
try try
{ {
var nv = rpcData.Adapt<KeyValuePair<string, string>>(); foreach (var rpcData in rpcDatas.WriteInfos)
var tag = _uploadVariables.FirstOrDefault(a => a.Name == nv.Key);
if (tag != null)
{ {
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
if (rpcEnable == true) var tag = _uploadVariables.FirstOrDefault(a => a.Name == rpcData.Key);
if (tag != null)
{ {
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + IdWithName[arg.ClientId], nv); var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
if (rpcEnable == true)
mqttRpcResult = new() { Message = result.Message, RpcId = rpcData.RpcId, Success = result.IsSuccess }; {
}
else
{
mqttRpcResult.Success = false;
mqttRpcResult.Message.Add(rpcData.Key, new("权限不足,变量不支持写入"));
}
} }
else else
{ {
mqttRpcResult = new() { Message = "权限不足,变量不支持写入", RpcId = rpcData.RpcId, Success = false }; mqttRpcResult.Success = false;
mqttRpcResult.Message.Add(rpcData.Key, new("不存在该变量"));
} }
}
} var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + arg.ClientId,
else rpcDatas.WriteInfos.Where(
{ a => !mqttRpcResult.Message.Any(b => b.Key == a.Key)).ToDictionary(a => a.Key, a => a.Value));
mqttRpcResult = new() { Message = "不存在该变量", RpcId = rpcData.RpcId, Success = false };
} mqttRpcResult.Message.AddRange(result);
mqttRpcResult.Success = !mqttRpcResult.Message.Any(a => !a.Value.IsSuccess);
} }
catch (Exception ex) catch (Exception ex)
{ {
LogMessage?.LogWarning(ex, ToString()); LogMessage?.LogWarning(ex, ToString());
mqttRpcResult = new() { Message = "Failed", RpcId = rpcData.RpcId, Success = false };
} }
try try
{ {
@@ -302,7 +307,7 @@ public class MqttServer : UpLoadBase
.WithTopic($"{driverPropertys.RpcSubTopic}") .WithTopic($"{driverPropertys.RpcSubTopic}")
.WithPayload(mqttRpcResult.ToJson()).Build(); .WithPayload(mqttRpcResult.ToJson()).Build();
await _mqttServer.InjectApplicationMessage( await _mqttServer.InjectApplicationMessage(
new InjectedMqttApplicationMessage(variableMessage)); new InjectedMqttApplicationMessage(variableMessage));
} }
catch catch
{ {

View File

@@ -294,14 +294,9 @@
标识 标识
</summary> </summary>
</member> </member>
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.Key"> <member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.WriteInfos">
<summary> <summary>
通常是变量名称 "WriteInfos":{"test":"1"}
</summary>
</member>
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.Value">
<summary>
</summary> </summary>
</member> </member>
<member name="T:ThingsGateway.Mqtt.MqttRpcResult"> <member name="T:ThingsGateway.Mqtt.MqttRpcResult">

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -25,7 +25,7 @@ using Yitter.IdGenerator;
namespace ThingsGateway.OPCDA; namespace ThingsGateway.OPCDA;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 导入变量
/// </summary> /// </summary>
public partial class ImportVariable public partial class ImportVariable
{ {
@@ -38,7 +38,7 @@ public partial class ImportVariable
private bool overlay = true; private bool overlay = true;
/// <summary> /// <summary>
/// opc<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// opc对象
/// </summary> /// </summary>
[Parameter] [Parameter]
public ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient PLC { get; set; } public ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient PLC { get; set; }
@@ -62,7 +62,7 @@ public partial class ImportVariable
private List<BrowseElement> Selected { get; set; } = new(); private List<BrowseElement> Selected { get; set; } = new();
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD> /// 获取设备与变量列表
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public (CollectDevice, List<DeviceVariable>) GetImportVariableList() public (CollectDevice, List<DeviceVariable>) GetImportVariableList()
@@ -145,7 +145,7 @@ public partial class ImportVariable
{ {
new() new()
{ {
Name = "δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", Name = "未完成连接",
Tag = new(), Tag = new(),
Nodes = null Nodes = null
} }

View File

@@ -35,7 +35,7 @@ public class OPCDAClient : CollectBase
{ {
internal CollectDeviceRunTime Device; internal CollectDeviceRunTime Device;
internal ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient PLC = null; internal ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient _plc = null;
private readonly OPCDAClientProperty driverPropertys = new(); private readonly OPCDAClientProperty driverPropertys = new();
private ConcurrentList<DeviceVariableRunTime> _deviceVariables = new(); private ConcurrentList<DeviceVariableRunTime> _deviceVariables = new();
@@ -50,17 +50,20 @@ public class OPCDAClient : CollectBase
/// <inheritdoc/> /// <inheritdoc/>
public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little); public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little);
/// <inheritdoc/>
protected override IReadWriteDevice PLC => null;
/// <inheritdoc/> /// <inheritdoc/>
public override Task AfterStopAsync() public override Task AfterStopAsync()
{ {
PLC?.Disconnect(); _plc?.Disconnect();
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken token) public override async Task BeforStartAsync(CancellationToken token)
{ {
PLC.Connect(); _plc.Connect();
await Task.CompletedTask; await Task.CompletedTask;
} }
@@ -69,14 +72,14 @@ public class OPCDAClient : CollectBase
{ {
} }
/// <inheritdoc/> /// <inheritdoc/>
public override bool IsConnected() => PLC?.IsConnected == true; public override bool IsConnected() => _plc?.IsConnected == true;
/// <inheritdoc/> /// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables) public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{ {
_deviceVariables = new(deviceVariables); _deviceVariables = new(deviceVariables);
if (deviceVariables.Count > 0) if (deviceVariables.Count > 0)
{ {
var result = PLC.AddItemsWithSave(deviceVariables.Select(a => a.VariableAddress).ToList()); var result = _plc.AddItemsWithSave(deviceVariables.Select(a => a.VariableAddress).ToList());
var sourVars = result?.Select( var sourVars = result?.Select(
it => it =>
{ {
@@ -98,26 +101,31 @@ public class OPCDAClient : CollectBase
public override async Task<OperResult<byte[]>> ReadSourceAsync(DeviceVariableSourceRead deviceVariableSourceRead, CancellationToken token) public override async Task<OperResult<byte[]>> ReadSourceAsync(DeviceVariableSourceRead deviceVariableSourceRead, CancellationToken token)
{ {
await Task.CompletedTask; await Task.CompletedTask;
var result = PLC.ReadItemsWithGroup(deviceVariableSourceRead.Address); var result = _plc.ReadItemsWithGroup(deviceVariableSourceRead.Address);
return result.Copy<byte[]>(); return result.Copy<byte[]>();
} }
/// <inheritdoc/> /// <inheritdoc/>
public override Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token) public override Task<Dictionary<string, OperResult>> WriteValuesAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
{ {
var result = PLC.WriteItem(deviceVariable.VariableAddress, value); var result = _plc.WriteItem(writeInfoLists.ToDictionary(a => a.Key.VariableAddress, a => a.Value));
return Task.FromResult(result); return Task.FromResult(result.ToDictionary(a =>
{
return writeInfoLists.Keys.FirstOrDefault(b => b.VariableAddress == a.Key).Name;
}, a => a.Value));
} }
/// <inheritdoc/> /// <inheritdoc/>
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
if (PLC != null) if (_plc != null)
PLC.DataChangedHandler -= DataChangedHandler; _plc.DataChangedHandler -= DataChangedHandler;
PLC?.Disconnect(); _plc?.Disconnect();
PLC?.SafeDispose(); _plc?.SafeDispose();
PLC = null; _plc = null;
base.Dispose(disposing); base.Dispose(disposing);
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -134,12 +142,12 @@ public class OPCDAClient : CollectBase
ActiveSubscribe = driverPropertys.ActiveSubscribe, ActiveSubscribe = driverPropertys.ActiveSubscribe,
CheckRate = driverPropertys.CheckRate CheckRate = driverPropertys.CheckRate
}; };
if (PLC == null) if (_plc == null)
{ {
PLC = new(LogMessage); _plc = new(LogMessage);
PLC.DataChangedHandler += DataChangedHandler; _plc.DataChangedHandler += DataChangedHandler;
} }
PLC.Init(opcNode); _plc.Init(opcNode);
} }
/// <inheritdoc/> /// <inheritdoc/>

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Components;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using ThingsGateway.Admin.Blazor.Core; using ThingsGateway.Admin.Blazor.Core;
@@ -32,7 +33,7 @@ using Yitter.IdGenerator;
namespace ThingsGateway.OPCDA; namespace ThingsGateway.OPCDA;
/// <summary> /// <summary>
/// OPCDA<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD> /// OPCDA调试页面
/// </summary> /// </summary>
public partial class OPCDAClientDebugDriverPage : IDisposable public partial class OPCDAClientDebugDriverPage : IDisposable
{ {
@@ -64,7 +65,7 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
{ {
opcDAClientPage.LogAction = defalutDebugDriverPage.LogOut; opcDAClientPage.LogAction = defalutDebugDriverPage.LogOut;
opcDAClientPage.ValueAction = ValueOut; opcDAClientPage.ValueAction = ValueOut;
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
_plc = opcDAClientPage.OPC; _plc = opcDAClientPage.OPC;
StateHasChanged(); StateHasChanged();
} }
@@ -92,12 +93,12 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
{ {
if (data?.Item2?.Count == 0) if (data?.Item2?.Count == 0)
{ {
await PopupService.EnqueueSnackbarAsync("<EFBFBD>޿<EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>", AlertTypes.Warning); await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
return; return;
} }
await defalutDebugDriverPage.DownDeviceExportAsync(data?.Item1); await defalutDebugDriverPage.DownDeviceExportAsync(data?.Item1);
await defalutDebugDriverPage.DownDeviceVariableExportAsync(data?.Item2, data?.Item1.Name); await defalutDebugDriverPage.DownDeviceVariableExportAsync(data?.Item2, data?.Item1.Name);
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
} }
private async Task DeviceImport() private async Task DeviceImport()
@@ -107,12 +108,12 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
{ {
if (data?.Item2?.Count == 0) if (data?.Item2?.Count == 0)
{ {
await PopupService.EnqueueSnackbarAsync("<EFBFBD>޿<EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>", AlertTypes.Warning); await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
return; return;
} }
await defalutDebugDriverPage.DeviceImportAsync(data?.Item1); await defalutDebugDriverPage.DeviceImportAsync(data?.Item1);
await defalutDebugDriverPage.DeviceVariableImportAsync(data?.Item2); await defalutDebugDriverPage.DeviceVariableImportAsync(data?.Item2);
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
} }
@@ -147,19 +148,24 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
{ {
try try
{ {
var data = _plc.WriteItem(defalutDebugDriverPage.Address, defalutDebugDriverPage.WriteValue); var data = _plc.WriteItem(
if (data.IsSuccess) new()
{
{defalutDebugDriverPage.Address, defalutDebugDriverPage.WriteValue }
}
);
if (data.Values.FirstOrDefault().IsSuccess)
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - д<EFBFBD><EFBFBD>" + data.Message)); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - 写入" + data.Values.FirstOrDefault().Message));
} }
else else
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message)); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Values.FirstOrDefault().Message));
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "д<EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD>" + ex.Message)); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "写入失败:" + ex.Message));
} }
return Task.CompletedTask; return Task.CompletedTask;

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -25,7 +25,7 @@ namespace ThingsGateway.OPCDA;
public partial class OPCDAClientPage public partial class OPCDAClientPage
{ {
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 日志输出
/// </summary> /// </summary>
public Action<LogLevel, object, string, Exception> LogAction; public Action<LogLevel, object, string, Exception> LogAction;
@@ -35,7 +35,7 @@ public partial class OPCDAClientPage
public ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient OPC; public ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient OPC;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 日志输出
/// </summary> /// </summary>
public Action<List<ItemReadResult>> ValueAction; public Action<List<ItemReadResult>> ValueAction;
@@ -85,7 +85,7 @@ public partial class OPCDAClientPage
} }
private ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient GetOPCClient() private ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient GetOPCClient()
{ {
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
OPC.Init(node); OPC.Init(node);
return OPC; return OPC;
} }

View File

@@ -40,6 +40,9 @@
<member name="P:ThingsGateway.OPCDA.OPCDAClient.ThingsGatewayBitConverter"> <member name="P:ThingsGateway.OPCDA.OPCDAClient.ThingsGatewayBitConverter">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:ThingsGateway.OPCDA.OPCDAClient.PLC">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.OPCDA.OPCDAClient.AfterStopAsync"> <member name="M:ThingsGateway.OPCDA.OPCDAClient.AfterStopAsync">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -58,7 +61,7 @@
<member name="M:ThingsGateway.OPCDA.OPCDAClient.ReadSourceAsync(ThingsGateway.Application.DeviceVariableSourceRead,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.OPCDA.OPCDAClient.ReadSourceAsync(ThingsGateway.Application.DeviceVariableSourceRead,System.Threading.CancellationToken)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.OPCDA.OPCDAClient.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.OPCDA.OPCDAClient.WriteValuesAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.OPCDA.OPCDAClient.Dispose(System.Boolean)"> <member name="M:ThingsGateway.OPCDA.OPCDAClient.Dispose(System.Boolean)">

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -29,7 +29,7 @@ using Yitter.IdGenerator;
namespace ThingsGateway.OPCUA; namespace ThingsGateway.OPCUA;
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 导入变量
/// </summary> /// </summary>
public partial class ImportVariable public partial class ImportVariable
{ {
@@ -41,7 +41,7 @@ public partial class ImportVariable
private bool overlay = true; private bool overlay = true;
/// <summary> /// <summary>
/// opc<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// opc对象
/// </summary> /// </summary>
[Parameter] [Parameter]
public ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient PLC { get; set; } public ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient PLC { get; set; }
@@ -67,7 +67,7 @@ public partial class ImportVariable
private List<ReferenceDescription> Selected { get; set; } = new(); private List<ReferenceDescription> Selected { get; set; } = new();
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD> /// 获取设备与变量列表
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public async Task<(CollectDevice, List<DeviceVariable>)> GetImportVariableListAsync() public async Task<(CollectDevice, List<DeviceVariable>)> GetImportVariableListAsync()
@@ -202,7 +202,7 @@ public partial class ImportVariable
{ {
if (!PLC.Connected) if (!PLC.Connected)
{ {
return new() { new() { Name = "δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", Tag = new(), Nodes = null } }; return new() { new() { Name = "未完成连接", Tag = new(), Nodes = null } };
} }
List<OPCUATagModel> nodes = new() List<OPCUATagModel> nodes = new()
{ {

View File

@@ -36,7 +36,13 @@ namespace ThingsGateway.OPCUA;
/// </summary> /// </summary>
public class OPCUAClient : CollectBase public class OPCUAClient : CollectBase
{ {
internal Foundation.Adapter.OPCUA.OPCUAClient _plc = null;
internal CollectDeviceRunTime Device;
readonly PeriodicTimer _periodicTimer = new(TimeSpan.FromSeconds(60)); readonly PeriodicTimer _periodicTimer = new(TimeSpan.FromSeconds(60));
private readonly OPCUAClientProperty driverPropertys = new();
private List<DeviceVariableRunTime> _deviceVariables = new();
/// <summary> /// <summary>
/// OPCUA客户端 /// OPCUA客户端
/// </summary> /// </summary>
@@ -45,33 +51,6 @@ public class OPCUAClient : CollectBase
_ = RunTimerAsync(); _ = RunTimerAsync();
} }
private async Task RunTimerAsync()
{
while (await _periodicTimer.WaitForNextTickAsync())
{
if (PLC != null && PLC.Session == null)
{
try
{
await PLC.ConnectAsync();
}
catch (Exception ex)
{
LogMessage.Exception(ex);
}
}
}
}
internal CollectDeviceRunTime Device;
internal Foundation.Adapter.OPCUA.OPCUAClient PLC = null;
private List<DeviceVariableRunTime> _deviceVariables = new();
private readonly OPCUAClientProperty driverPropertys = new();
/// <inheritdoc/> /// <inheritdoc/>
public override Type DriverDebugUIType => typeof(OPCUAClientDebugDriverPage); public override Type DriverDebugUIType => typeof(OPCUAClientDebugDriverPage);
@@ -83,18 +62,23 @@ public class OPCUAClient : CollectBase
/// <inheritdoc/> /// <inheritdoc/>
public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little); public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little);
/// <inheritdoc/>
protected override IReadWriteDevice PLC => null;
/// <inheritdoc/> /// <inheritdoc/>
public override Task AfterStopAsync() public override Task AfterStopAsync()
{ {
PLC?.Disconnect(); _plc?.Disconnect();
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken token) public override async Task BeforStartAsync(CancellationToken token)
{ {
await PLC?.ConnectAsync(); await _plc?.ConnectAsync();
} }
/// <inheritdoc/> /// <inheritdoc/>
public override void InitDataAdapter() public override void InitDataAdapter()
{ {
@@ -104,14 +88,14 @@ public class OPCUAClient : CollectBase
public override bool IsConnected() public override bool IsConnected()
{ {
return PLC.Connected; return _plc.Connected;
} }
/// <inheritdoc/> /// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables) public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{ {
_deviceVariables = deviceVariables; _deviceVariables = deviceVariables;
PLC.Variables.AddRange(deviceVariables.Select(a => a.VariableAddress).ToList()); _plc.Variables.AddRange(deviceVariables.Select(a => a.VariableAddress).ToList());
var dataLists = deviceVariables.ChunkTrivialBetter(driverPropertys.GroupSize); var dataLists = deviceVariables.ChunkTrivialBetter(driverPropertys.GroupSize);
var dataResult = new List<DeviceVariableSourceRead>(); var dataResult = new List<DeviceVariableSourceRead>();
foreach (var variable in dataLists) foreach (var variable in dataLists)
@@ -131,7 +115,7 @@ public class OPCUAClient : CollectBase
/// <inheritdoc/> /// <inheritdoc/>
public override async Task<OperResult<byte[]>> ReadSourceAsync(DeviceVariableSourceRead deviceVariableSourceRead, CancellationToken token) public override async Task<OperResult<byte[]>> ReadSourceAsync(DeviceVariableSourceRead deviceVariableSourceRead, CancellationToken token)
{ {
var result = await PLC.ReadJTokenValueAsync(deviceVariableSourceRead.DeviceVariables.Select(a => a.VariableAddress).ToArray(), token); var result = await _plc.ReadJTokenValueAsync(deviceVariableSourceRead.DeviceVariables.Select(a => a.VariableAddress).ToArray(), token);
foreach (var data in result) foreach (var data in result)
{ {
if (!token.IsCancellationRequested) if (!token.IsCancellationRequested)
@@ -184,26 +168,33 @@ public class OPCUAClient : CollectBase
} }
} }
/// <inheritdoc/> /// <inheritdoc/>
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token) public override async Task<Dictionary<string, OperResult>> WriteValuesAsync(Dictionary<DeviceVariableRunTime, JToken> writeInfoLists, CancellationToken token)
{ {
var result = await PLC.WriteNodeAsync(deviceVariable.VariableAddress, value, token); var result = await _plc.WriteNodeAsync(writeInfoLists.ToDictionary(a => a.Key.VariableAddress, a => a.Value), token);
return result; return result.ToDictionary(a =>
{
return writeInfoLists.Keys.FirstOrDefault(b => b.VariableAddress == a.Key)?.Name;
}
, a => a.Value);
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
_periodicTimer?.Dispose(); _periodicTimer?.Dispose();
if (PLC != null) if (_plc != null)
{ {
PLC.DataChangedHandler -= DataChangedHandler; _plc.DataChangedHandler -= DataChangedHandler;
PLC.Disconnect(); _plc.Disconnect();
PLC.SafeDispose(); _plc.SafeDispose();
PLC = null; _plc = null;
} }
base.Dispose(disposing); base.Dispose(disposing);
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null) protected override void Init(CollectDeviceRunTime device, object client = null)
{ {
@@ -220,13 +211,13 @@ public class OPCUAClient : CollectBase
UserName = driverPropertys.UserName, UserName = driverPropertys.UserName,
Password = driverPropertys.Password Password = driverPropertys.Password
}; };
if (PLC == null) if (_plc == null)
{ {
PLC = new(LogMessage); _plc = new(LogMessage);
PLC.DataChangedHandler += DataChangedHandler; _plc.DataChangedHandler += DataChangedHandler;
} }
PLC.OPCNode = opcNode; _plc.OPCNode = opcNode;
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -252,7 +243,7 @@ public class OPCUAClient : CollectBase
return; return;
} }
//尝试固定点位的数据类型 //尝试固定点位的数据类型
var type = TypeInfo.GetSystemType(TypeInfo.GetBuiltInType(data.variableNode.DataType, PLC.Session.SystemContext.TypeTable), data.variableNode.ValueRank); var type = TypeInfo.GetSystemType(TypeInfo.GetBuiltInType(data.variableNode.DataType, _plc.Session.SystemContext.TypeTable), data.variableNode.ValueRank);
var itemReads = _deviceVariables.Where(it => it.VariableAddress == data.variableNode.NodeId).ToList(); var itemReads = _deviceVariables.Where(it => it.VariableAddress == data.variableNode.NodeId).ToList();
@@ -296,4 +287,23 @@ public class OPCUAClient : CollectBase
LogMessage?.LogWarning(ex, ToString()); LogMessage?.LogWarning(ex, ToString());
} }
} }
private async Task RunTimerAsync()
{
while (await _periodicTimer.WaitForNextTickAsync())
{
if (_plc != null && _plc.Session == null)
{
try
{
await _plc.ConnectAsync();
}
catch (Exception ex)
{
LogMessage.Exception(ex);
}
}
}
}
} }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -21,6 +21,7 @@ using Newtonsoft.Json.Linq;
using Opc.Ua; using Opc.Ua;
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using ThingsGateway.Admin.Blazor.Core; using ThingsGateway.Admin.Blazor.Core;
@@ -33,7 +34,7 @@ using Yitter.IdGenerator;
namespace ThingsGateway.OPCUA; namespace ThingsGateway.OPCUA;
/// <summary> /// <summary>
/// OPCUA<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD> /// OPCUA调试页面
/// </summary> /// </summary>
public partial class OPCUAClientDebugDriverPage public partial class OPCUAClientDebugDriverPage
{ {
@@ -69,7 +70,7 @@ public partial class OPCUAClientDebugDriverPage
if (firstRender) if (firstRender)
{ {
opcUAClientPage.LogAction = defalutDebugDriverPage.LogOut; opcUAClientPage.LogAction = defalutDebugDriverPage.LogOut;
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //载入配置
_plc = opcUAClientPage.OPC; _plc = opcUAClientPage.OPC;
_plc.DataChangedHandler += Plc_DataChangedHandler; _plc.DataChangedHandler += Plc_DataChangedHandler;
StateHasChanged(); StateHasChanged();
@@ -83,7 +84,7 @@ public partial class OPCUAClientDebugDriverPage
await _plc.AddSubscriptionAsync(YitIdHelper.NextId().ToString(), new[] { defalutDebugDriverPage.Address }); await _plc.AddSubscriptionAsync(YitIdHelper.NextId().ToString(), new[] { defalutDebugDriverPage.Address });
else else
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "未连接"));
} }
} }
private async Task DownDeviceExport() private async Task DownDeviceExport()
@@ -91,12 +92,12 @@ public partial class OPCUAClientDebugDriverPage
var data = await ImportVariable?.GetImportVariableListAsync(); var data = await ImportVariable?.GetImportVariableListAsync();
if (data.Item2?.Count == 0) if (data.Item2?.Count == 0)
{ {
await PopupService.EnqueueSnackbarAsync("<EFBFBD>޿<EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>", AlertTypes.Warning); await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
return; return;
} }
await defalutDebugDriverPage.DownDeviceExportAsync(data.Item1); await defalutDebugDriverPage.DownDeviceExportAsync(data.Item1);
await defalutDebugDriverPage.DownDeviceVariableExportAsync(data.Item2, data.Item1.Name); await defalutDebugDriverPage.DownDeviceVariableExportAsync(data.Item2, data.Item1.Name);
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
private async Task DeviceImport() private async Task DeviceImport()
@@ -104,12 +105,12 @@ public partial class OPCUAClientDebugDriverPage
var data = await ImportVariable?.GetImportVariableListAsync(); var data = await ImportVariable?.GetImportVariableListAsync();
if (data.Item2?.Count == 0) if (data.Item2?.Count == 0)
{ {
await PopupService.EnqueueSnackbarAsync("<EFBFBD>޿<EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>", AlertTypes.Warning); await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
return; return;
} }
await defalutDebugDriverPage.DeviceImportAsync(data.Item1); await defalutDebugDriverPage.DeviceImportAsync(data.Item1);
await defalutDebugDriverPage.DeviceVariableImportAsync(data.Item2); await defalutDebugDriverPage.DeviceVariableImportAsync(data.Item2);
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success); await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
} }
private void Plc_DataChangedHandler((VariableNode variableNode, DataValue dataValue, Newtonsoft.Json.Linq.JToken jToken) item) private void Plc_DataChangedHandler((VariableNode variableNode, DataValue dataValue, Newtonsoft.Json.Linq.JToken jToken) item)
@@ -138,7 +139,7 @@ public partial class OPCUAClientDebugDriverPage
} }
else else
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "未连接"));
} }
} }
private void Remove() private void Remove()
@@ -147,7 +148,7 @@ public partial class OPCUAClientDebugDriverPage
_plc.RemoveSubscription(""); _plc.RemoveSubscription("");
else else
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "未连接"));
} }
} }
@@ -157,24 +158,29 @@ public partial class OPCUAClientDebugDriverPage
{ {
if (_plc.Connected) if (_plc.Connected)
{ {
var data = await _plc.WriteNodeAsync(defalutDebugDriverPage.Address, JToken.Parse(defalutDebugDriverPage.WriteValue)); var data = await _plc.WriteNodeAsync(
if (data.IsSuccess) new()
{
{ defalutDebugDriverPage.Address, JToken.Parse(defalutDebugDriverPage.WriteValue)}
}
);
if (data.Values.FirstOrDefault().IsSuccess)
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - д<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>")); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - 写入成功"));
} }
else else
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - д<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD> " + data.Message)); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - 写入失败 " + data.Values.FirstOrDefault().Message));
} }
} }
else else
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "未连接"));
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - " + "д<EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD>" + ex.Message)); defalutDebugDriverPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + " - " + "写入失败:" + ex.Message));
} }
} }
} }

View File

@@ -1,12 +1,12 @@
#region copyright #region copyright
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 此代码版权(除特别声明外的代码)归作者本人Diego所有
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> // 源代码使用协议遵循本仓库的开源协议及附加协议
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569 // QQ群:605534569
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
@@ -25,7 +25,7 @@ namespace ThingsGateway.OPCUA;
public partial class OPCUAClientPage public partial class OPCUAClientPage
{ {
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> /// 日志输出
/// </summary> /// </summary>
public Action<LogLevel, object, string, Exception> LogAction; public Action<LogLevel, object, string, Exception> LogAction;
/// <summary> /// <summary>

View File

@@ -490,16 +490,22 @@ src.IsOnline ? StatusCodes.Good : StatusCodes.Bad);
//仅当指定了值时才将值写入 //仅当指定了值时才将值写入
if (variable.Value != null) if (variable.Value != null)
{ {
var nv = new KeyValuePair<string, string>(variable.SymbolicName, value?.ToString());
var result = _rpcCore.InvokeDeviceMethodAsync("OPCUASERVER-" + context1?.OperationContext?.Session?.Identity?.DisplayName, nv).ConfigureAwait(true).GetAwaiter().GetResult(); var result = _rpcCore.InvokeDeviceMethodAsync("OPCUASERVER-" + context1?.OperationContext?.Session?.Identity?.DisplayName,
if (result.IsSuccess) new()
{
{ variable.SymbolicName, value?.ToString() }
}
).ConfigureAwait(true).GetAwaiter().GetResult();
if (result.Values.FirstOrDefault().IsSuccess)
{ {
return StatusCodes.Good; return StatusCodes.Good;
} }
else else
{ {
return new(StatusCodes.BadWaitingForResponse, result.Message); return new(StatusCodes.BadWaitingForResponse, result.Values.FirstOrDefault().Message);
} }
} }
} }

View File

@@ -50,6 +50,9 @@
<member name="P:ThingsGateway.OPCUA.OPCUAClient.ThingsGatewayBitConverter"> <member name="P:ThingsGateway.OPCUA.OPCUAClient.ThingsGatewayBitConverter">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:ThingsGateway.OPCUA.OPCUAClient.PLC">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.OPCUA.OPCUAClient.AfterStopAsync"> <member name="M:ThingsGateway.OPCUA.OPCUAClient.AfterStopAsync">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -68,7 +71,7 @@
<member name="M:ThingsGateway.OPCUA.OPCUAClient.ReadSourceAsync(ThingsGateway.Application.DeviceVariableSourceRead,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.OPCUA.OPCUAClient.ReadSourceAsync(ThingsGateway.Application.DeviceVariableSourceRead,System.Threading.CancellationToken)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.OPCUA.OPCUAClient.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.OPCUA.OPCUAClient.WriteValuesAsync(System.Collections.Generic.Dictionary{ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.OPCUA.OPCUAClient.Dispose(System.Boolean)"> <member name="M:ThingsGateway.OPCUA.OPCUAClient.Dispose(System.Boolean)">

View File

@@ -56,11 +56,13 @@ public class RabbitMQClientProperty : UpDriverPropertyBase
/// </summary> /// </summary>
[DeviceProperty("虚拟Host", "")] [DeviceProperty("虚拟Host", "")]
public string VirtualHost { get; set; } = ConnectionFactory.DefaultVHost; public string VirtualHost { get; set; } = ConnectionFactory.DefaultVHost;
/// <summary>
/// RoutingKey ///// <summary>
/// </summary> ///// RoutingKey
[DeviceProperty("路由名称", "")] ///// </summary>
public string RoutingKey { get; set; } = "TG"; //[DeviceProperty("路由名称", "")]
//public string RoutingKey { get; set; } = "TG";
/// <summary> /// <summary>
/// 交换机名称 /// 交换机名称
/// </summary> /// </summary>

View File

@@ -85,11 +85,6 @@
VirtualHost VirtualHost
</summary> </summary>
</member> </member>
<member name="P:ThingsGateway.RabbitMQ.RabbitMQClientProperty.RoutingKey">
<summary>
RoutingKey
</summary>
</member>
<member name="P:ThingsGateway.RabbitMQ.RabbitMQClientProperty.ExchangeName"> <member name="P:ThingsGateway.RabbitMQ.RabbitMQClientProperty.ExchangeName">
<summary> <summary>
交换机名称 交换机名称

View File

@@ -53,18 +53,19 @@ namespace ThingsGateway.Siemens
} }
else if (it.DataTypeEnum.GetSystemType() == typeof(string)) else if (it.DataTypeEnum.GetSystemType() == typeof(string))
{ {
lastLen = it.ThingsGatewayBitConverter.StringLength;
if (siemensS7Net.CurrentPlc == SiemensEnum.S200Smart) if (siemensS7Net.CurrentPlc == SiemensEnum.S200Smart)
{ {
//字符串在S200Smart中第一个字节不属于实际内容 //字符串在S200Smart中第一个字节不属于实际内容
it.Index += 1; it.Index += 1;
it.ThingsGatewayBitConverter.StringLength -= 1; //it.ThingsGatewayBitConverter.StringLength -= 1;
lastLen = it.ThingsGatewayBitConverter.StringLength + 1;
} }
else else
{ {
//字符串在S7中前两个字节不属于实际内容 //字符串在S7中前两个字节不属于实际内容
it.Index += 2; it.Index += 2;
it.ThingsGatewayBitConverter.StringLength -= 2; //it.ThingsGatewayBitConverter.StringLength -= 2;
lastLen = it.ThingsGatewayBitConverter.StringLength + 2;
} }
} }
else if (it.DataTypeEnum.GetSystemType() == typeof(object)) else if (it.DataTypeEnum.GetSystemType() == typeof(object))

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
using Newtonsoft.Json.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -19,6 +17,7 @@ using System.Threading.Tasks;
using ThingsGateway.Application; using ThingsGateway.Application;
using ThingsGateway.Foundation; using ThingsGateway.Foundation;
using ThingsGateway.Foundation.Extension;
namespace ThingsGateway.Siemens; namespace ThingsGateway.Siemens;
/// <summary> /// <summary>
@@ -30,6 +29,8 @@ public abstract class Siemens : CollectBase
/// PLC /// PLC
/// </summary> /// </summary>
protected SiemensS7PLC _plc; protected SiemensS7PLC _plc;
/// <inheritdoc/>
protected override IReadWriteDevice PLC => _plc;
/// <summary> /// <summary>
/// SiemensProperty /// SiemensProperty
/// </summary> /// </summary>
@@ -79,59 +80,51 @@ public abstract class Siemens : CollectBase
/// <see cref="SiemensS7PLC.ReadDateAsync(string,CancellationToken)"/> /// <see cref="SiemensS7PLC.ReadDateAsync(string,CancellationToken)"/>
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[DeviceMethod("ReadDate", "")] [DeviceMethod("ReadWriteDateAsync", "")]
public Task<OperResult<System.DateTime>> ReadDateAsync(string address, CancellationToken token) public async Task<OperResult<System.DateTime>> ReadWriteDateAsync(string address, System.DateTime? value = null, CancellationToken token = default)
{ {
return _plc?.ReadDateAsync(address, token); if (value == null)
return await _plc?.ReadDateAsync(address, token);
else
return (await _plc?.WriteDateAsync(address, value.Value, token)).Copy<System.DateTime>();
} }
/// <summary> /// <summary>
/// <see cref="SiemensS7PLC.ReadDateTimeAsync(string,CancellationToken)"/> /// <see cref="SiemensS7PLC.ReadDateTimeAsync(string,CancellationToken)"/>
/// </summary> /// </summary>
/// <param name="address"></param> /// <param name="address"></param>
/// <param name="value"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
[DeviceMethod("ReadDateTime", "")] [DeviceMethod("ReadWriteDateTimeAsync", "")]
public Task<OperResult<System.DateTime>> ReadDateTimeAsync(string address, CancellationToken token) public async Task<OperResult<System.DateTime>> ReadWriteDateTimeAsync(string address, System.DateTime? value = null, CancellationToken token = default)
{ {
return _plc?.ReadDateTimeAsync(address, token); if (value == null)
return await _plc?.ReadDateTimeAsync(address, token);
else
return (await _plc?.WriteDateTimeAsync(address, value.Value, token)).Copy<System.DateTime>();
} }
/// <summary> /// <summary>
/// <see cref="SiemensS7PLC.ReadStringAsync(string,Encoding,CancellationToken)"/> /// <see cref="SiemensS7PLC.ReadStringAsync(string,Encoding,CancellationToken)"/>
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[DeviceMethod("ReadString", "")] [DeviceMethod("ReadWriteStringAsync", "")]
public Task<OperResult<string>> ReadStringAsync(string address, Encoding encoding, CancellationToken token) public async Task<OperResult<string>> ReadWriteStringAsync(string address, Encoding encoding, string value = null, CancellationToken token = default)
{ {
return _plc?.ReadStringAsync(address, encoding, token); encoding ??= Encoding.UTF8;
if (value == null)
return await _plc?.ReadStringAsync(address, encoding, token);
else
return (await _plc?.WriteAsync(address, value, token)).Copy<string>();
} }
/// <summary>
/// <see cref="SiemensS7PLC.WriteDateAsync(string,System.DateTime,CancellationToken)"/>
/// </summary>
/// <returns></returns>
[DeviceMethod("WriteDate", "")]
public Task<OperResult> WriteDateAsync(string address, System.DateTime dateTime, CancellationToken token)
{
return _plc?.WriteDateAsync(address, dateTime, token);
}
/// <summary>
/// <see cref="SiemensS7PLC.WriteDateTimeAsync(string,System.DateTime,CancellationToken)"/>
/// </summary>
/// <returns></returns>
[DeviceMethod("WriteDateTime", "")]
public Task<OperResult> WriteDateTimeAsync(string address, System.DateTime dateTime, CancellationToken token)
{
return _plc?.WriteDateTimeAsync(address, dateTime, token);
}
/// <inheritdoc/>
public override async Task<OperResult> WriteValueAsync(DeviceVariableRunTime deviceVariable, JToken value, CancellationToken token)
{
return await _plc.WriteAsync(deviceVariable.VariableAddress, deviceVariable.DataType, value.ToString(), token);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -88,6 +88,9 @@
PLC PLC
</summary> </summary>
</member> </member>
<member name="P:ThingsGateway.Siemens.Siemens.PLC">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Siemens.Siemens.driverPropertys"> <member name="F:ThingsGateway.Siemens.Siemens.driverPropertys">
<summary> <summary>
SiemensProperty SiemensProperty
@@ -117,41 +120,27 @@
<member name="M:ThingsGateway.Siemens.Siemens.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})"> <member name="M:ThingsGateway.Siemens.Siemens.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:ThingsGateway.Siemens.Siemens.ReadDateAsync(System.String,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.Siemens.Siemens.ReadWriteDateAsync(System.String,System.Nullable{System.DateTime},System.Threading.CancellationToken)">
<summary> <summary>
<see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateAsync(System.String,System.Threading.CancellationToken)"/> <see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateAsync(System.String,System.Threading.CancellationToken)"/>
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:ThingsGateway.Siemens.Siemens.ReadDateTimeAsync(System.String,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.Siemens.Siemens.ReadWriteDateTimeAsync(System.String,System.Nullable{System.DateTime},System.Threading.CancellationToken)">
<summary> <summary>
<see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateTimeAsync(System.String,System.Threading.CancellationToken)"/> <see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateTimeAsync(System.String,System.Threading.CancellationToken)"/>
</summary> </summary>
<param name="address"></param> <param name="address"></param>
<param name="value"></param>
<param name="token"></param> <param name="token"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:ThingsGateway.Siemens.Siemens.ReadStringAsync(System.String,System.Text.Encoding,System.Threading.CancellationToken)"> <member name="M:ThingsGateway.Siemens.Siemens.ReadWriteStringAsync(System.String,System.Text.Encoding,System.String,System.Threading.CancellationToken)">
<summary> <summary>
<see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadStringAsync(System.String,System.Text.Encoding,System.Threading.CancellationToken)"/> <see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadStringAsync(System.String,System.Text.Encoding,System.Threading.CancellationToken)"/>
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:ThingsGateway.Siemens.Siemens.WriteDateAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
<summary>
<see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateAsync(System.String,System.DateTime,System.Threading.CancellationToken)"/>
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Siemens.Siemens.WriteDateTimeAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
<summary>
<see cref="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateTimeAsync(System.String,System.DateTime,System.Threading.CancellationToken)"/>
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Siemens.Siemens.WriteValueAsync(ThingsGateway.Application.DeviceVariableRunTime,Newtonsoft.Json.Linq.JToken,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Siemens.Siemens.Dispose(System.Boolean)"> <member name="M:ThingsGateway.Siemens.Siemens.Dispose(System.Boolean)">
<inheritdoc/> <inheritdoc/>
</member> </member>

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 77 KiB