Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
95d723c578 | ||
![]() |
2fcd853e86 | ||
![]() |
07eef7c812 | ||
![]() |
b01e0757fa | ||
![]() |
32844a20c6 | ||
![]() |
5b6532c601 | ||
![]() |
2c5b4b4027 | ||
![]() |
72d7ecf195 | ||
![]() |
2cfa6b4306 | ||
![]() |
6f6ffde0ab | ||
![]() |
1694739a16 | ||
![]() |
95d1e8bfca | ||
![]() |
60dec08e3c | ||
![]() |
a99d71be93 | ||
![]() |
f1331b6a0c | ||
![]() |
10d66b642b | ||
![]() |
cd2310e4a8 | ||
![]() |
1b399cf6b0 | ||
![]() |
877445bc0a | ||
![]() |
9a5b345bde | ||
![]() |
fc9e8ea7b3 | ||
![]() |
32be6fcfc1 | ||
![]() |
49847236c2 | ||
![]() |
d8424443e6 | ||
![]() |
f3b571ec3f | ||
![]() |
99318bb5d7 | ||
![]() |
1aa154c9aa | ||
![]() |
c65d8a445b | ||
![]() |
80f4f85570 | ||
![]() |
5beee43a6b |
@@ -22,7 +22,9 @@
|
||||
|
||||
[ThingsGateway演示地址](http://120.24.62.140:5000/)
|
||||
|
||||
账户 : **superAdmin** 密码 : **111111**
|
||||
账户 : **superAdmin**
|
||||
|
||||
密码 : **111111**
|
||||
|
||||
## 赞助
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<Version>2.0.6.0</Version>
|
||||
<Version>2.0.9.3</Version>
|
||||
<Authors>Diego</Authors>
|
||||
<Product>ThingsGateway</Product>
|
||||
<Copyright>© 2023-present Diego</Copyright>
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -20,19 +20,19 @@ namespace ThingsGateway.Admin.Blazor.Core;
|
||||
public partial class AppBarItems
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 链接
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_COPYRIGHT_URL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>Ȩ
|
||||
/// 版权
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_COPYRIGHT { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_TITLE { get; set; }
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace ThingsGateway.Admin.Blazor.Core;
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>/ͣ<><CDA3> <20>ı<EFBFBD><C4B1><EFBFBD>ʾ
|
||||
/// 启用/停用 文本提示
|
||||
/// </summary>
|
||||
public partial class EnableChip
|
||||
{
|
||||
@@ -46,5 +46,5 @@ public partial class EnableChip
|
||||
|
||||
private string TextColor => Value ? "green" : "error";
|
||||
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 ?? "停用";
|
||||
}
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Admin.Blazor.Core;
|
||||
/// <summary>
|
||||
/// <EFBFBD>ղ<EFBFBD>/<2F><><EFBFBD>ݷ<EFBFBD>ʽ
|
||||
/// 收藏/快捷方式
|
||||
/// </summary>
|
||||
public partial class Favorite
|
||||
{
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -22,17 +22,17 @@ public partial class Foter
|
||||
{
|
||||
private string Version = "";
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 链接
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_COPYRIGHT_URL { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>Ȩ
|
||||
/// 版权
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_COPYRIGHT { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_TITLE { get; set; }
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -20,23 +20,23 @@ namespace ThingsGateway.Admin.Blazor.Core;
|
||||
public partial class Logo
|
||||
{
|
||||
/// <summary>
|
||||
/// Logo<EFBFBD>߶<EFBFBD>
|
||||
/// Logo高度
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int HeightInt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 链接
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_COPYRIGHT_URL { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>Ȩ
|
||||
/// 版权
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_COPYRIGHT { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CONFIG_TITLE { get; set; }
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -34,7 +34,7 @@ public partial class PageTabs
|
||||
return op;
|
||||
}
|
||||
/// <summary>
|
||||
/// Tabsʵ<EFBFBD><EFBFBD>
|
||||
/// Tabs实例
|
||||
/// </summary>
|
||||
public PPageTabs PPageTabs { get; private set; }
|
||||
|
||||
@@ -46,7 +46,7 @@ public partial class PageTabs
|
||||
[Parameter]
|
||||
public IEnumerable<string> SelfPatterns { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 子组件
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -49,11 +49,11 @@ public partial class UserMenu
|
||||
var ret = str?.ToJsonWithT<UnifyResult<string>>();
|
||||
if (ret?.Code != 200)
|
||||
{
|
||||
await PopupService.EnqueueSnackbarAsync("ע<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>", AlertTypes.Error);
|
||||
await PopupService.EnqueueSnackbarAsync("注销失败", AlertTypes.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
await PopupService.EnqueueSnackbarAsync("ע<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
|
||||
await PopupService.EnqueueSnackbarAsync("注销成功", AlertTypes.Success);
|
||||
await Task.Delay(500);
|
||||
NavigationManager.NavigateTo(NavigationManager.Uri);
|
||||
}
|
||||
|
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,6 +10,8 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using BlazorComponent;
|
||||
|
||||
using Furion;
|
||||
|
||||
using Masa.Blazor;
|
||||
@@ -61,6 +63,8 @@ public class Startup : AppStartup
|
||||
|
||||
|
||||
});
|
||||
options.Locale = new Locale("zh-CN", "en-US");
|
||||
|
||||
});
|
||||
|
||||
services.AddScoped<InitTimezone>();
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
<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" />
|
||||
|
||||
</ItemGroup>
|
||||
|
@@ -857,5 +857,38 @@
|
||||
设置深浅主题统一由这个方法为入口
|
||||
</summary>
|
||||
</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>
|
||||
</doc>
|
||||
|
@@ -153,7 +153,7 @@ public class UserResoures : IDisposable
|
||||
{
|
||||
if (MasaBlazor.Theme.Dark != isDark || isDark == null)
|
||||
MasaBlazor.ToggleTheme();
|
||||
_cookieStorage?.SetItemAsync(BlazorResourceConst.ThemeCookieKey, isDark.ToJsonString());
|
||||
_cookieStorage?.SetItemAsync(BlazorResourceConst.ThemeCookieKey, MasaBlazor.Theme.Dark.ToJsonString());
|
||||
}
|
||||
|
||||
private void InitCookie(IRequestCookieCollection cookies)
|
||||
|
@@ -48,8 +48,7 @@
|
||||
var controllerTypes = App.EffectiveTypes.
|
||||
Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
|
||||
&& u.IsDefined(typeof(Microsoft.AspNetCore.Components.RouteAttribute), false))
|
||||
.Where(it => it.Assembly != typeof(BlazorApp).Assembly)
|
||||
;
|
||||
.Where(it => it.Assembly != typeof(BlazorApp).Assembly);
|
||||
var assemblys = controllerTypes?.Select(it => it.Assembly)?.Distinct();
|
||||
return assemblys;
|
||||
}
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -18,7 +18,7 @@ using ThingsGateway.Admin.Core;
|
||||
|
||||
namespace ThingsGateway.Admin.Blazor;
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ҳ
|
||||
/// 首页
|
||||
/// </summary>
|
||||
public partial class Index
|
||||
{
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -18,7 +18,7 @@ using ThingsGateway.Admin.Core;
|
||||
|
||||
namespace ThingsGateway.Admin.Blazor;
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 个人设置
|
||||
/// </summary>
|
||||
public partial class UserCenter
|
||||
{
|
||||
@@ -50,25 +50,25 @@ public partial class UserCenter
|
||||
{
|
||||
await UserCenterService.UpdateUserDefaultRazorAsync(UserManager.UserId, DefaultMenuId);
|
||||
await MainLayout.StateHasChangedAsync();
|
||||
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
|
||||
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
|
||||
}
|
||||
|
||||
async Task OnShortcutSaveAsync()
|
||||
{
|
||||
await UserCenterService.UpdateWorkbenchAsync(_menusChoice);
|
||||
await MainLayout.StateHasChangedAsync();
|
||||
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
|
||||
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
|
||||
}
|
||||
async Task OnUpdatePasswordInfoAsync(FormContext context)
|
||||
{
|
||||
var success = context.Validate();
|
||||
if (success)
|
||||
{
|
||||
//<EFBFBD><EFBFBD>֤<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>
|
||||
//验证成功,操作业务
|
||||
_passwordInfoInput.Id = UserResoures.CurrentUser.Id;
|
||||
await UserCenterService.EditPasswordAsync(_passwordInfoInput);
|
||||
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);
|
||||
NavigationManager.NavigateTo(NavigationManager.Uri);
|
||||
}
|
||||
@@ -78,6 +78,6 @@ public partial class UserCenter
|
||||
{
|
||||
await UserCenterService.UpdateUserInfoAsync(_updateInfoInput);
|
||||
await MainLayout.StateHasChangedAsync();
|
||||
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
|
||||
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
|
||||
}
|
||||
}
|
@@ -12,7 +12,7 @@
|
||||
<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.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="Yitter.IdGenerator" Version="1.0.14" />
|
||||
<PackageReference Include="MiniExcel" Version="1.31.2" />
|
||||
|
@@ -89,13 +89,8 @@ public class RpcControler : IDynamicApiController
|
||||
[Description("写入变量")]
|
||||
public async Task<Dictionary<string, OperResult>> WriteDeviceMethods(Dictionary<string, string> objs)
|
||||
{
|
||||
Dictionary<string, OperResult> operResultDict = new();
|
||||
foreach (KeyValuePair<string, string> obj in objs)
|
||||
{
|
||||
var result = await RpcCore.InvokeDeviceMethodAsync($"WebApi-{UserManager.UserAccount}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", obj);
|
||||
operResultDict.Add(obj.Key, result);
|
||||
}
|
||||
return operResultDict;
|
||||
var result = await RpcCore.InvokeDeviceMethodAsync($"WebApi-{UserManager.UserAccount}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", objs);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -36,6 +36,10 @@ public abstract class CollectBase : DriverBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract bool IsSupportRequest { get; }
|
||||
/// <summary>
|
||||
/// 一般底层驱动,也有可能为null
|
||||
/// </summary>
|
||||
protected abstract IReadWriteDevice PLC { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据转换器
|
||||
@@ -177,10 +181,22 @@ public abstract class CollectBase : DriverBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入变量值
|
||||
/// 批量写入变量值,需返回变量名称/结果
|
||||
/// </summary>
|
||||
/// <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>
|
||||
/// 初始化
|
||||
|
@@ -48,92 +48,172 @@ public class RpcSingletonService : ISingleton
|
||||
/// 反向RPC入口方法
|
||||
/// </summary>
|
||||
/// <param name="sourceDes">触发该方法的源说明</param>
|
||||
/// <param name="item">指定键为变量名称,值为附带方法参数或写入值</param>
|
||||
/// <param name="items">指定键为变量名称,值为附带方法参数或写入值</param>
|
||||
/// <param name="isBlazor">如果是true,不检查<see cref="MemoryVariable.RpcWriteEnable"/>字段</param>
|
||||
/// <param name="token"><see cref="CancellationToken"/> 取消源</param>
|
||||
/// <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
|
||||
await Task.Delay(10, token);
|
||||
OperResult data = new();
|
||||
var tag = _globalDeviceData.AllVariables.FirstOrDefault(it => it.Name == item.Key);
|
||||
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)
|
||||
Dictionary<CollectDeviceCore, Dictionary<DeviceVariableRunTime, JToken>> WriteVariables = new();
|
||||
Dictionary<CollectDeviceCore, Dictionary<DeviceVariableRunTime, string>> WriteMethods = new();
|
||||
Dictionary<string, OperResult> results = new();
|
||||
foreach (var item in items)
|
||||
{
|
||||
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);
|
||||
_logQueues.Enqueue(
|
||||
new RpcLog()
|
||||
OperResult data = new();
|
||||
var tag = _globalDeviceData.AllVariables.FirstOrDefault(it => it.Name == item.Key);
|
||||
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,
|
||||
IsSuccess = data.IsSuccess,
|
||||
OperateMethod = WriteVariable,
|
||||
OperateObject = tag.Name,
|
||||
OperateSource = sourceDes,
|
||||
ParamJson = item.Value,
|
||||
ResultJson = data.Message
|
||||
//写入变量
|
||||
JToken tagValue;
|
||||
try
|
||||
{
|
||||
tagValue = JToken.Parse(item.Value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
data = new OperResult<string>(ex);
|
||||
}
|
||||
_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}");
|
||||
_logger.LogWarning($"写入变量异常:{ex.Message + Environment.NewLine + ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
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()
|
||||
{
|
||||
|
@@ -55,7 +55,7 @@ public interface IVariableService : ITransient
|
||||
/// <summary>
|
||||
/// 导出
|
||||
/// </summary>
|
||||
Task<MemoryStream> ExportFileAsync(List<DeviceVariable> collectDeviceVariables = null);
|
||||
Task<MemoryStream> ExportFileAsync(List<DeviceVariable> collectDeviceVariables = null, string deviceName = null);
|
||||
/// <summary>
|
||||
/// 导出
|
||||
/// </summary>
|
||||
|
@@ -318,7 +318,7 @@ public class VariableService : DbRepository<DeviceVariable>, IVariableService
|
||||
|
||||
/// <inheritdoc/>
|
||||
[OperDesc("导出采集变量表", IsRecordPar = false)]
|
||||
public async Task<MemoryStream> ExportFileAsync(List<DeviceVariable> deviceVariables = null)
|
||||
public async Task<MemoryStream> ExportFileAsync(List<DeviceVariable> deviceVariables = null, string deviceName = null)
|
||||
{
|
||||
deviceVariables ??= await GetListAsync(a => !a.IsMemoryVariable);
|
||||
|
||||
@@ -343,7 +343,8 @@ public class VariableService : DbRepository<DeviceVariable>, IVariableService
|
||||
);
|
||||
Dictionary<string, object> variableExport = new();
|
||||
//变量实体没有包含设备名称,手动插入
|
||||
variableExport.Add(ExportHelpers.DeviceName, collectDeviceDicts[devData.DeviceId].Name);
|
||||
var devName = collectDeviceDicts.GetValueOrDefault(devData.DeviceId)?.Name ?? deviceName;
|
||||
variableExport.Add(ExportHelpers.DeviceName, devName);
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
|
@@ -1855,6 +1855,11 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Application.CollectBase.PLC">
|
||||
<summary>
|
||||
一般底层驱动,也有可能为null
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Application.CollectBase.ThingsGatewayBitConverter">
|
||||
<summary>
|
||||
数据转换器
|
||||
@@ -1906,9 +1911,9 @@
|
||||
采集驱动读取
|
||||
</summary>
|
||||
</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>
|
||||
<returns></returns>
|
||||
</member>
|
||||
@@ -2242,12 +2247,12 @@
|
||||
<member name="M:ThingsGateway.Application.RpcSingletonService.#ctor(Microsoft.Extensions.Logging.ILogger{ThingsGateway.Application.RpcSingletonService})">
|
||||
<inheritdoc cref="T:ThingsGateway.Application.RpcSingletonService"/>
|
||||
</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>
|
||||
反向RPC入口方法
|
||||
</summary>
|
||||
<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="token"><see cref="T:System.Threading.CancellationToken"/> 取消源</param>
|
||||
<returns></returns>
|
||||
@@ -3175,7 +3180,7 @@
|
||||
编辑变量
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.IVariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable})">
|
||||
<member name="M:ThingsGateway.Application.IVariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable},System.String)">
|
||||
<summary>
|
||||
导出
|
||||
</summary>
|
||||
@@ -3270,7 +3275,7 @@
|
||||
<member name="M:ThingsGateway.Application.VariableService.MemoryVariableExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.MemoryVariable})">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.VariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable})">
|
||||
<member name="M:ThingsGateway.Application.VariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable},System.String)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.VariableService.MemoryVariablePreviewAsync(Microsoft.AspNetCore.Components.Forms.IBrowserFile)">
|
||||
@@ -3505,7 +3510,7 @@
|
||||
执行特殊方法
|
||||
</summary>
|
||||
</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>
|
||||
|
@@ -536,6 +536,7 @@ public class AlarmWorker : BackgroundService
|
||||
HisAlarmTask = await Task.Factory.StartNew(async () =>
|
||||
{
|
||||
_logger?.LogInformation($"历史报警线程开始");
|
||||
await Task.Yield();//返回线程控制,不再阻塞
|
||||
try
|
||||
{
|
||||
await Task.Delay(500, stoppingToken.Token);
|
||||
@@ -561,8 +562,14 @@ public class AlarmWorker : BackgroundService
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (stoppingToken.Token.IsCancellationRequested)
|
||||
{
|
||||
IsExited = true;
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
_logger.LogWarning("连接历史报警表失败,尝试初始化表");
|
||||
sqlSugarClient.CodeFirst.InitTables(typeof(HistoryAlarm));
|
||||
isSuccess = true;
|
||||
StatuString = OperResult.CreateSuccessResult();
|
||||
|
@@ -269,6 +269,7 @@ public class CollectDeviceCore
|
||||
{
|
||||
isInitSuccess = false;
|
||||
GlobalDeviceData.CollectDevices.RemoveWhere(it => it.Id == Device.Id);
|
||||
easyLock.SafeDispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,11 +330,6 @@ public class CollectDeviceCore
|
||||
return ThreadRunReturn.Continue;
|
||||
}
|
||||
|
||||
if (DeviceVariableSourceReads.Count == 0 && Device.DeviceVariableRunTimes.Where(a => string.IsNullOrEmpty(a.OtherMethod)).Any())
|
||||
{
|
||||
//无采集变量
|
||||
return ThreadRunReturn.Continue;
|
||||
}
|
||||
if (token.IsCancellationRequested)
|
||||
return ThreadRunReturn.Break;
|
||||
|
||||
@@ -533,7 +529,7 @@ public class CollectDeviceCore
|
||||
|
||||
if (!string.IsNullOrEmpty(methodResult.MethodStr))
|
||||
{
|
||||
string[] strs = methodResult.MethodStr?.Trim()?.Split(';');
|
||||
string[] strs = methodResult.MethodStr?.Trim()?.TrimEnd(';').Split(';');
|
||||
try
|
||||
{
|
||||
int index = 0;
|
||||
@@ -545,6 +541,8 @@ public class CollectDeviceCore
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strs.Length <= index)
|
||||
continue;
|
||||
//得到对于的方法参数值
|
||||
methodResult.MethodObj[i] = methodResult.Converter.ConvertFrom(strs[index], ps[i].ParameterType);
|
||||
index++;
|
||||
@@ -600,8 +598,8 @@ public class CollectDeviceCore
|
||||
|
||||
if (!string.IsNullOrEmpty(deviceVariableMethodSource.MethodStr) || !string.IsNullOrEmpty(value))
|
||||
{
|
||||
string[] strs1 = deviceVariableMethodSource.MethodStr?.Trim()?.Split(';');
|
||||
string[] strs2 = value?.Trim()?.Split(';');
|
||||
string[] strs1 = deviceVariableMethodSource.MethodStr?.Trim()?.TrimEnd(';').Split(';');
|
||||
string[] strs2 = value?.Trim()?.TrimEnd(';').Split(';');
|
||||
//通过分号分割,并且合并参数
|
||||
var strs = strs1?.SpliceArray(strs2);
|
||||
int index = 0;
|
||||
@@ -667,18 +665,25 @@ public class CollectDeviceCore
|
||||
if (method.HasReturn && result != null && result.IsSuccess)
|
||||
{
|
||||
var content = deviceVariableMethodSource.Converter.ConvertTo(result.Content?.ToString()?.Replace($"\0", ""));
|
||||
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(content);
|
||||
if (!operResult.IsSuccess)
|
||||
if (isRead)
|
||||
{
|
||||
_logger?.LogWarning(operResult.Message, ToString());
|
||||
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(content);
|
||||
if (!operResult.IsSuccess)
|
||||
{
|
||||
_logger?.LogWarning(operResult.Message, ToString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(null);
|
||||
if (!operResult.IsSuccess)
|
||||
if (isRead)
|
||||
{
|
||||
_logger?.LogWarning(operResult.Message, ToString());
|
||||
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(null);
|
||||
if (!operResult.IsSuccess)
|
||||
{
|
||||
_logger?.LogWarning(operResult.Message, ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -707,46 +712,46 @@ public class CollectDeviceCore
|
||||
/// 执行变量写入
|
||||
/// </summary>
|
||||
/// <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
|
||||
{
|
||||
await easyLock.WaitAsync();
|
||||
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.WriteValueAsync(deviceVariable, value, token);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (new OperResult(ex));
|
||||
var result = await _driver.WriteValuesAsync(writeInfoLists.
|
||||
Where(a => !results.Any(b => b.Key == a.Key.Name)).
|
||||
ToDictionary(item => item.Key, item => item.Value),
|
||||
token);
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -754,6 +759,8 @@ public class CollectDeviceCore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 执行轮询特殊方法,并设置变量值
|
||||
/// </summary>
|
||||
|
@@ -62,6 +62,7 @@ public class CollectDeviceThread : IAsyncDisposable
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await StopThreadAsync();
|
||||
easyLock.SafeDispose();
|
||||
CollectDeviceCores.Clear();
|
||||
}
|
||||
|
||||
|
@@ -167,7 +167,7 @@ public class HistoryValueWorker : BackgroundService
|
||||
HistoryValueTask = await Task.Factory.StartNew(async () =>
|
||||
{
|
||||
_logger?.LogInformation($"历史数据线程开始");
|
||||
IsExited = false;
|
||||
await Task.Yield();//返回线程控制,不再阻塞
|
||||
try
|
||||
{
|
||||
var result = await GetHisDbAsync();
|
||||
@@ -191,8 +191,14 @@ public class HistoryValueWorker : BackgroundService
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (stoppingToken.Token.IsCancellationRequested)
|
||||
{
|
||||
IsExited = true;
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
_logger.LogWarning("连接历史数据表失败,尝试初始化表");
|
||||
sqlSugarClient.CodeFirst.InitTables(typeof(HistoryValue));
|
||||
LastIsSuccess = true;
|
||||
StatuString = OperResult.CreateSuccessResult();
|
||||
@@ -204,6 +210,7 @@ public class HistoryValueWorker : BackgroundService
|
||||
_logger.LogWarning(ex, "连接历史数据库失败");
|
||||
}
|
||||
}
|
||||
IsExited = false;
|
||||
|
||||
while (!stoppingToken.Token.IsCancellationRequested)
|
||||
{
|
||||
@@ -299,7 +306,6 @@ public class HistoryValueWorker : BackgroundService
|
||||
LastIsSuccess = false;
|
||||
}
|
||||
}
|
||||
IsExited = true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -317,9 +323,11 @@ public class HistoryValueWorker : BackgroundService
|
||||
IsExited = true;
|
||||
_logger?.LogError(ex, $"历史数据循环异常");
|
||||
}
|
||||
IsExited = true;
|
||||
}
|
||||
, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重启
|
||||
/// </summary>
|
||||
|
@@ -225,7 +225,13 @@ public class UploadDeviceCore
|
||||
{
|
||||
_logger?.LogError(ex, $"{Device.Name} 释放失败");
|
||||
}
|
||||
isInitSuccess = false;
|
||||
finally
|
||||
{
|
||||
isInitSuccess = false;
|
||||
easyLock.SafeDispose();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -51,6 +51,7 @@ public class UploadDeviceThread : IAsyncDisposable
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await StopThreadAsync();
|
||||
easyLock.SafeDispose();
|
||||
UploadDeviceCores.Clear();
|
||||
}
|
||||
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -21,7 +21,7 @@ using ThingsGateway.Application;
|
||||
|
||||
namespace ThingsGateway.Blazor;
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>excel
|
||||
/// 导入excel
|
||||
/// </summary>
|
||||
public partial class ImportExcel
|
||||
{
|
||||
@@ -33,21 +33,21 @@ public partial class ImportExcel
|
||||
|
||||
bool isSaveImport;
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 导入
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<Dictionary<string, ImportPreviewOutputBase>, Task> Import { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ʾ
|
||||
/// 是否显示
|
||||
/// </summary>
|
||||
public bool IsShowImport { get; set; }
|
||||
/// <summary>
|
||||
/// Ԥ<EFBFBD><EFBFBD>
|
||||
/// 预览
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<IBrowserFile, Task<Dictionary<string, ImportPreviewOutputBase>>> Preview { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 当前步数
|
||||
/// </summary>
|
||||
public int Step { get; set; }
|
||||
|
||||
@@ -75,7 +75,7 @@ public partial class ImportExcel
|
||||
StateHasChanged();
|
||||
await Import.Invoke(ImportPreviews);
|
||||
_importFile = null;
|
||||
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
|
||||
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -54,7 +54,7 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
|
||||
/// </summary>
|
||||
public UdpSessionPage UdpSessionPage;
|
||||
/// <summary>
|
||||
/// ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>1-TCPCLIENT<EFBFBD><EFBFBD>2-<2D><><EFBFBD>ڣ<EFBFBD>3-UDP<EFBFBD><EFBFBD>4-TCPServer
|
||||
/// 选择,1-TCPCLIENT,2-串口,3-UDP,4-TCPServer
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public ChannelEnum Channel { get; set; }
|
||||
@@ -65,12 +65,12 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
|
||||
public override ThingsGateway.Foundation.IReadWriteDevice Plc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ģ<EFBFBD><EFBFBD>
|
||||
/// 模板
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>
|
||||
/// 自定义模板
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment OtherContent { get; set; }
|
||||
@@ -100,7 +100,7 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
|
||||
TcpServerPage.LogAction = LogOut;
|
||||
if (UdpSessionPage != null)
|
||||
UdpSessionPage.LogAction = LogOut;
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//载入配置
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
@@ -127,7 +127,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
/// 导入设备
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task DownDeviceExportAsync(CollectDevice data)
|
||||
public async Task DeviceImportAsync(CollectDevice data)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -145,7 +145,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
/// 导入变量
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task DownDeviceExportAsync(List<DeviceVariable> data)
|
||||
public async Task DeviceVariableImportAsync(List<DeviceVariable> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -159,6 +159,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 导出
|
||||
/// </summary>
|
||||
@@ -187,6 +188,51 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出到excel
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task DownDeviceExportAsync(CollectDevice data)
|
||||
{
|
||||
try
|
||||
{
|
||||
isDownExport = true;
|
||||
StateHasChanged();
|
||||
using var memoryStream = await CollectDeviceService.ExportFileAsync(new List<CollectDevice>() { data });
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
using var streamRef = new DotNetStreamReference(stream: memoryStream);
|
||||
_helper ??= await JS.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js");
|
||||
await _helper.InvokeVoidAsync("downloadFileFromStream", $"设备导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出到excel
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task DownDeviceVariableExportAsync(List<DeviceVariable> data, string devName)
|
||||
{
|
||||
try
|
||||
{
|
||||
isDownExport = true;
|
||||
StateHasChanged();
|
||||
using var memoryStream = await VariableService.ExportFileAsync(data, devName);
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
using var streamRef = new DotNetStreamReference(stream: memoryStream);
|
||||
_helper ??= await JS.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js");
|
||||
await _helper.InvokeVoidAsync("downloadFileFromStream", $"变量导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void LogOut(TouchSocket.Core.LogLevel logLevel, object source, string message, Exception exception)
|
||||
{
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ThingsGateway.Blazor;
|
||||
public partial class SerialClientPage
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
@@ -36,7 +36,7 @@ public partial class SerialClientPage
|
||||
SerialClient.SafeDispose();
|
||||
}
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SerialClient GetSerialClient()
|
||||
@@ -47,7 +47,7 @@ public partial class SerialClientPage
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetSerialProperty(serialProperty);
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//载入配置
|
||||
SerialClient.Setup(config);
|
||||
return SerialClient;
|
||||
}
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ThingsGateway.Blazor;
|
||||
public partial class TcpClientPage
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
@@ -33,7 +33,7 @@ public partial class TcpClientPage
|
||||
/// </summary>
|
||||
private string IP = "127.0.0.1";
|
||||
/// <summary>
|
||||
/// <EFBFBD>˿<EFBFBD>
|
||||
/// 端口
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int Port { get; set; } = 502;
|
||||
@@ -73,7 +73,7 @@ public partial class TcpClientPage
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TcpClientEx GetTcpClient()
|
||||
@@ -83,7 +83,7 @@ public partial class TcpClientPage
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetRemoteIPHost(new IPHost(IP + ":" + Port)).SetBufferLength(300);
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//载入配置
|
||||
TcpClientEx.Setup(config);
|
||||
return TcpClientEx;
|
||||
}
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ThingsGateway.Blazor;
|
||||
public partial class TcpServerPage
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
@@ -62,7 +62,7 @@ public partial class TcpServerPage
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TcpService GetTcpServer()
|
||||
@@ -73,7 +73,7 @@ public partial class TcpServerPage
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) });
|
||||
config.SetBufferLength(300);
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//载入配置
|
||||
TcpServer.Setup(config);
|
||||
return TcpServer;
|
||||
}
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ThingsGateway.Blazor;
|
||||
public partial class UdpSessionPage : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
@@ -62,7 +62,7 @@ public partial class UdpSessionPage : IDisposable
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public UdpSession GetUdpSession()
|
||||
@@ -73,7 +73,7 @@ public partial class UdpSessionPage : IDisposable
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300);
|
||||
config.SetBindIPHost(new IPHost(0));
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//载入配置
|
||||
UdpSession.Setup(config);
|
||||
return UdpSession;
|
||||
}
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -32,7 +32,7 @@ using ThingsGateway.Application;
|
||||
namespace ThingsGateway.Blazor;
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD>豸״̬ҳ<EFBFBD><EFBFBD>
|
||||
/// 设备状态页面
|
||||
/// </summary>
|
||||
public partial class DeviceStatusPage : IDisposable
|
||||
{
|
||||
@@ -110,7 +110,7 @@ public partial class DeviceStatusPage : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
|
||||
if (confirm)
|
||||
{
|
||||
isAllRestart = true;
|
||||
@@ -142,8 +142,8 @@ public partial class DeviceStatusPage : IDisposable
|
||||
}
|
||||
async Task ConfigAsync(long devId, bool? isStart)
|
||||
{
|
||||
var str = isStart == true ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>ͣ";
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"ȷ<EFBFBD><EFBFBD>{str}?");
|
||||
var str = isStart == true ? "启动" : "暂停";
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"确定{str}?");
|
||||
if (confirm)
|
||||
{
|
||||
CollectDeviceHostService.ConfigDeviceThread(devId, isStart == true);
|
||||
@@ -167,19 +167,19 @@ public partial class DeviceStatusPage : IDisposable
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
using var streamRef = new DotNetStreamReference(stream: memoryStream);
|
||||
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
|
||||
{
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
//ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//去除单个采集重启
|
||||
//async Task RestartAsync(long devId)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
|
||||
// var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
|
||||
// if (confirm)
|
||||
// {
|
||||
// isRestart = true;
|
||||
@@ -231,8 +231,8 @@ public partial class DeviceStatusPage : IDisposable
|
||||
|
||||
async Task UpConfigAsync(long devId, bool? isStart)
|
||||
{
|
||||
var str = isStart == true ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>ͣ";
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"ȷ<EFBFBD><EFBFBD>{str}?");
|
||||
var str = isStart == true ? "启动" : "暂停";
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"确定{str}?");
|
||||
if (confirm)
|
||||
{
|
||||
UploadDeviceHostService.ConfigDeviceThread(devId, isStart == true);
|
||||
@@ -253,7 +253,7 @@ public partial class DeviceStatusPage : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
|
||||
var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
|
||||
if (confirm)
|
||||
{
|
||||
isRestart = true;
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -28,7 +28,7 @@ using ThingsGateway.Application;
|
||||
|
||||
namespace ThingsGateway.Blazor;
|
||||
/// <summary>
|
||||
/// ʵʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ
|
||||
/// 实时数据页
|
||||
/// </summary>
|
||||
public partial class DeviceVariableRunTimePage
|
||||
{
|
||||
@@ -37,13 +37,13 @@ public partial class DeviceVariableRunTimePage
|
||||
List<DeviceTree> _deviceGroups = new();
|
||||
string _searchName;
|
||||
/// <summary>
|
||||
/// <EFBFBD>豸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[SupplyParameterFromQuery]
|
||||
public string DeviceName { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD>ϴ<EFBFBD><EFBFBD>豸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 上传设备名称
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[SupplyParameterFromQuery]
|
||||
@@ -149,15 +149,23 @@ public partial class DeviceVariableRunTimePage
|
||||
private EventCallback<string> WriteValueAsync;
|
||||
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);
|
||||
if (!data.IsSuccess)
|
||||
var data = await RpcCore?.InvokeDeviceMethodAsync($"BLAZOR-{UserResoures.CurrentUser.Account}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}",
|
||||
|
||||
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)
|
||||
{
|
||||
// <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));
|
||||
await PopupService.OpenAsync(typeof(WriteValue), new Dictionary<string, object>()
|
||||
{
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -19,7 +19,7 @@ using ThingsGateway.Application;
|
||||
namespace ThingsGateway.Blazor;
|
||||
|
||||
/// <summary>
|
||||
/// Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣҳ<EFBFBD><EFBFBD>
|
||||
/// 硬件信息页面
|
||||
/// </summary>
|
||||
public partial class HardwareInfoPage
|
||||
{
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -25,7 +25,7 @@ using ThingsGateway.Application;
|
||||
namespace ThingsGateway.Blazor;
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ʷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
|
||||
/// 历史报警页面
|
||||
/// </summary>
|
||||
public partial class HistoryAlarmPage
|
||||
{
|
||||
@@ -75,7 +75,7 @@ public partial class HistoryAlarmPage
|
||||
}
|
||||
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()
|
||||
{
|
||||
Current = 1,
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -23,7 +23,7 @@ using ThingsGateway.Application;
|
||||
|
||||
namespace ThingsGateway.Blazor;
|
||||
/// <summary>
|
||||
/// ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
|
||||
/// 时序库页面
|
||||
/// </summary>
|
||||
public partial class HistoryValuePage
|
||||
{
|
||||
@@ -74,7 +74,7 @@ public partial class HistoryValuePage
|
||||
}
|
||||
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()
|
||||
{
|
||||
Current = 1,
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -22,7 +22,7 @@ using ThingsGateway.Application;
|
||||
|
||||
namespace ThingsGateway.Blazor;
|
||||
/// <summary>
|
||||
/// ʵʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 实时报警
|
||||
/// </summary>
|
||||
public partial class RealAlarmPage
|
||||
{
|
||||
|
@@ -428,13 +428,13 @@
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.WriteAsync">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DownDeviceExportAsync(ThingsGateway.Application.CollectDevice)">
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DeviceImportAsync(ThingsGateway.Application.CollectDevice)">
|
||||
<summary>
|
||||
导入设备
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DownDeviceExportAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable})">
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DeviceVariableImportAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable})">
|
||||
<summary>
|
||||
导入变量
|
||||
</summary>
|
||||
@@ -447,6 +447,18 @@
|
||||
<param name="values"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DownDeviceExportAsync(ThingsGateway.Application.CollectDevice)">
|
||||
<summary>
|
||||
导出到excel
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DownDeviceVariableExportAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable},System.String)">
|
||||
<summary>
|
||||
导出到excel
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Application.DriverDebugUIBase.LogOut(TouchSocket.Core.LogLevel,System.Object,System.String,System.Exception)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
|
@@ -15,7 +15,7 @@ namespace ThingsGateway.Foundation;
|
||||
/// <summary>
|
||||
/// 自增
|
||||
/// </summary>
|
||||
public sealed class EasyIncrementCount : DisposableObject
|
||||
public sealed class EasyIncrementCount : IDisposable
|
||||
{
|
||||
private long current = 0;
|
||||
private readonly EasyLock easyLock;
|
||||
@@ -30,6 +30,11 @@ public sealed class EasyIncrementCount : DisposableObject
|
||||
IncreaseTick = tick;
|
||||
easyLock = new EasyLock();
|
||||
}
|
||||
/// <inheritdoc cref="EasyIncrementCount"/>
|
||||
~EasyIncrementCount()
|
||||
{
|
||||
easyLock.SafeDispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tick
|
||||
@@ -117,10 +122,10 @@ public sealed class EasyIncrementCount : DisposableObject
|
||||
}
|
||||
easyLock.Release();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
public void Dispose()
|
||||
{
|
||||
easyLock.SafeDispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
@@ -15,11 +15,15 @@ namespace ThingsGateway.Foundation;
|
||||
/// <summary>
|
||||
/// EasyLock,使用轻量级SemaphoreSlim锁,只允许一个并发量,并记录并发信息
|
||||
/// </summary>
|
||||
public sealed class EasyLock : DisposableObject
|
||||
public sealed class EasyLock : IDisposable
|
||||
{
|
||||
private static long lockWaitCount;
|
||||
private readonly Lazy<SemaphoreSlim> m_waiterLock = new(() => new SemaphoreSlim(1));
|
||||
|
||||
/// <inheritdoc/>
|
||||
~EasyLock()
|
||||
{
|
||||
m_waiterLock.Value.SafeDispose();
|
||||
}
|
||||
/// <summary>
|
||||
/// 当前正在等待的数量
|
||||
/// </summary>
|
||||
@@ -28,6 +32,13 @@ public sealed class EasyLock : DisposableObject
|
||||
/// 当前锁是否在等待当中
|
||||
/// </summary>
|
||||
public bool IsWaitting => m_waiterLock.Value.CurrentCount == 0;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
m_waiterLock.Value.SafeDispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开锁
|
||||
/// </summary>
|
||||
@@ -73,10 +84,5 @@ public sealed class EasyLock : DisposableObject
|
||||
await m_waiterLock.Value.WaitAsync(timeSpan, token);
|
||||
Interlocked.Decrement(ref lockWaitCount);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
m_waiterLock.Value.SafeDispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
}
|
@@ -29,7 +29,6 @@ using System.Runtime.InteropServices;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
using TouchSocket.Resources;
|
||||
using TouchSocket.Sockets;
|
||||
|
||||
namespace ThingsGateway.Foundation;
|
||||
|
||||
@@ -326,27 +325,33 @@ public class TcpClientBaseEx : BaseSocket, ITcpClient
|
||||
/// <param name="disposing"></param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
if (!DisposedValue)
|
||||
{
|
||||
privateEasyLock.Wait();
|
||||
if (this.m_online)
|
||||
try
|
||||
{
|
||||
this.m_online = false;
|
||||
this.MainSocket.TryClose();
|
||||
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)}主动断开"));
|
||||
privateEasyLock.Wait();
|
||||
if (this.m_online)
|
||||
{
|
||||
this.m_online = false;
|
||||
this.MainSocket.TryClose();
|
||||
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();
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ namespace ThingsGateway.Foundation;
|
||||
internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClient> where TClient : IClient, IDefaultSender, ISender
|
||||
{
|
||||
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 WaitDataAsync<ResponsedData> m_waitDataAsync = new WaitDataAsync<ResponsedData>();
|
||||
|
||||
@@ -55,6 +55,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
|
||||
this.Client = default;
|
||||
this.m_waitData.SafeDispose();
|
||||
this.m_waitDataAsync.SafeDispose();
|
||||
this.easyLock.SafeDispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -121,7 +122,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
|
||||
{
|
||||
try
|
||||
{
|
||||
m_lock.Wait();
|
||||
easyLock.Wait();
|
||||
this.m_breaked = false;
|
||||
this.Reset();
|
||||
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
|
||||
@@ -184,7 +185,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_lock.Release();
|
||||
easyLock.Release();
|
||||
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
|
||||
{
|
||||
tcpClient.Disconnected -= this.OnDisconnected;
|
||||
@@ -224,7 +225,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
|
||||
{
|
||||
try
|
||||
{
|
||||
await m_lock.WaitAsync();
|
||||
await easyLock.WaitAsync();
|
||||
this.m_breaked = false;
|
||||
this.Reset();
|
||||
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
|
||||
@@ -287,7 +288,7 @@ internal class WaitingClientEx<TClient> : DisposableObject, IWaitingClient<TClie
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_lock.Release();
|
||||
easyLock.Release();
|
||||
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
|
||||
{
|
||||
tcpClient.Disconnected -= this.OnDisconnected;
|
||||
|
@@ -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>
|
||||
/// <inheritdoc cref="Path.Combine(string[])"/>
|
||||
/// 并把\\转为/
|
||||
|
@@ -15,6 +15,17 @@ namespace ThingsGateway.Foundation.Extension;
|
||||
/// <inheritdoc/>
|
||||
public static class OperResultExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 复制信息,包含第一个泛型类
|
||||
/// </summary>
|
||||
public static OperResult<T1> Copy<T1, T2>(this OperResult<T1, T2> result)
|
||||
{
|
||||
OperResult<T1> result1 = new(result.ResultCode, result.Message)
|
||||
{
|
||||
Content = result.Content1
|
||||
};
|
||||
return result1;
|
||||
}
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
|
@@ -13,7 +13,6 @@
|
||||
using System.IO.Ports;
|
||||
|
||||
using TouchSocket.Resources;
|
||||
using TouchSocket.Sockets;
|
||||
|
||||
namespace ThingsGateway.Foundation.Serial;
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks>
|
||||
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<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 Condition="'$(TargetFramework)'!='net45'">
|
||||
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
|
||||
|
@@ -588,6 +588,9 @@
|
||||
<member name="M:ThingsGateway.Foundation.EasyIncrementCount.#ctor(System.Int64,System.Int64,System.Int32)">
|
||||
<inheritdoc cref="T:ThingsGateway.Foundation.EasyIncrementCount"/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.EasyIncrementCount.Finalize">
|
||||
<inheritdoc cref="T:ThingsGateway.Foundation.EasyIncrementCount"/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.EasyIncrementCount.IncreaseTick">
|
||||
<summary>
|
||||
Tick
|
||||
@@ -623,7 +626,7 @@
|
||||
重置当前序号的初始值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.EasyIncrementCount.Dispose(System.Boolean)">
|
||||
<member name="M:ThingsGateway.Foundation.EasyIncrementCount.Dispose">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.EasyLock">
|
||||
@@ -631,6 +634,9 @@
|
||||
EasyLock,使用轻量级SemaphoreSlim锁,只允许一个并发量,并记录并发信息
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.EasyLock.Finalize">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.EasyLock.LockWaitCount">
|
||||
<summary>
|
||||
当前正在等待的数量
|
||||
@@ -641,6 +647,9 @@
|
||||
当前锁是否在等待当中
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.EasyLock.Dispose">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.EasyLock.Release">
|
||||
<summary>
|
||||
离开锁
|
||||
@@ -666,9 +675,6 @@
|
||||
进入锁
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.EasyLock.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.TcpClientEx">
|
||||
<summary>
|
||||
简单TCP客户端
|
||||
@@ -1283,13 +1289,6 @@
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</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[])">
|
||||
<summary>
|
||||
<inheritdoc cref="M:System.IO.Path.Combine(System.String[])"/>
|
||||
@@ -1313,6 +1312,11 @@
|
||||
<member name="T:ThingsGateway.Foundation.Extension.OperResultExtensions">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Extension.OperResultExtensions.Copy``2(ThingsGateway.Foundation.OperResult{``0,``1})">
|
||||
<summary>
|
||||
复制信息,包含第一个泛型类
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Extension.OperResultExtensions.Copy``1(ThingsGateway.Foundation.OperResult)">
|
||||
<summary>
|
||||
复制信息,不包含泛型类
|
||||
|
@@ -31,11 +31,11 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
private DataFormat dataFormat;
|
||||
/// <inheritdoc/>
|
||||
[JsonIgnore]
|
||||
public Encoding Encoding { get; set; } = Encoding.UTF8;
|
||||
public virtual Encoding Encoding { get; set; } = Encoding.UTF8;
|
||||
/// <inheritdoc/>
|
||||
public BcdFormat? BcdFormat { get; set; }
|
||||
public virtual BcdFormat? BcdFormat { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public int StringLength { get; set; }
|
||||
public virtual int StringLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
@@ -55,7 +55,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DataFormat DataFormat
|
||||
public virtual DataFormat DataFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -69,9 +69,9 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public EndianType EndianType => endianType;
|
||||
public virtual EndianType EndianType => endianType;
|
||||
/// <inheritdoc/>
|
||||
public bool IsStringReverseByteWord { get; set; }
|
||||
public virtual bool IsStringReverseByteWord { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual IThingsGatewayBitConverter CreateByDateFormat(DataFormat dataFormat)
|
||||
@@ -86,7 +86,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return byteConverter;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(bool value)
|
||||
public virtual byte[] GetBytes(bool value)
|
||||
{
|
||||
return GetBytes(new bool[1]
|
||||
{
|
||||
@@ -95,13 +95,13 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(bool[] values)
|
||||
public virtual byte[] GetBytes(bool[] values)
|
||||
{
|
||||
return values?.BoolArrayToByte();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(short value)
|
||||
public virtual byte[] GetBytes(short value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
@@ -111,7 +111,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return bytes;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(short[] value)
|
||||
public virtual byte[] GetBytes(short[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -123,7 +123,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(ushort value)
|
||||
public virtual byte[] GetBytes(ushort value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
@@ -133,7 +133,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return bytes;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(ushort[] value)
|
||||
public virtual byte[] GetBytes(ushort[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -144,12 +144,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(int value)
|
||||
public virtual byte[] GetBytes(int value)
|
||||
{
|
||||
return ByteTransDataFormat4(BitConverter.GetBytes(value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(int[] value)
|
||||
public virtual byte[] GetBytes(int[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -160,12 +160,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(uint value)
|
||||
public virtual byte[] GetBytes(uint value)
|
||||
{
|
||||
return ByteTransDataFormat4(BitConverter.GetBytes(value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(uint[] value)
|
||||
public virtual byte[] GetBytes(uint[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -176,12 +176,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(long value)
|
||||
public virtual byte[] GetBytes(long value)
|
||||
{
|
||||
return ByteTransDataFormat8(BitConverter.GetBytes(value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(long[] value)
|
||||
public virtual byte[] GetBytes(long[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -192,12 +192,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(ulong value)
|
||||
public virtual byte[] GetBytes(ulong value)
|
||||
{
|
||||
return ByteTransDataFormat8(BitConverter.GetBytes(value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(ulong[] value)
|
||||
public virtual byte[] GetBytes(ulong[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -208,12 +208,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(float value)
|
||||
public virtual byte[] GetBytes(float value)
|
||||
{
|
||||
return ByteTransDataFormat4(BitConverter.GetBytes(value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(float[] value)
|
||||
public virtual byte[] GetBytes(float[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -224,12 +224,12 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(double value)
|
||||
public virtual byte[] GetBytes(double value)
|
||||
{
|
||||
return ByteTransDataFormat8(BitConverter.GetBytes(value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(double[] value)
|
||||
public virtual byte[] GetBytes(double[] value)
|
||||
{
|
||||
byte[] numArray = new byte[value.Length * 2];
|
||||
for (int index = 0; index < value.Length; ++index)
|
||||
@@ -240,7 +240,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public byte[] GetBytes(string value)
|
||||
public virtual byte[] GetBytes(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
@@ -280,7 +280,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsSameOfSet()
|
||||
public virtual bool IsSameOfSet()
|
||||
{
|
||||
return !(BitConverter.IsLittleEndian ^ (endianType == EndianType.Little));
|
||||
}
|
||||
@@ -288,7 +288,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ToBoolean(byte[] buffer, int offset)
|
||||
public virtual bool ToBoolean(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[buffer.Length];
|
||||
Array.Copy(buffer, 0, bytes, 0, buffer.Length);
|
||||
@@ -296,7 +296,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public byte ToByte(byte[] buffer, int offset)
|
||||
public virtual byte ToByte(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[1];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
@@ -304,7 +304,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
@@ -317,7 +317,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public double ToDouble(byte[] buffer, int offset)
|
||||
public virtual double ToDouble(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ByteTransDataFormat8(buffer, offset);
|
||||
|
||||
@@ -325,7 +325,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public short ToInt16(byte[] buffer, int offset)
|
||||
public virtual short ToInt16(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[2];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
@@ -337,7 +337,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int ToInt32(byte[] buffer, int offset)
|
||||
public virtual int ToInt32(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ByteTransDataFormat4(buffer, offset);
|
||||
|
||||
@@ -345,14 +345,14 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public long ToInt64(byte[] buffer, int offset)
|
||||
public virtual long ToInt64(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ByteTransDataFormat8(buffer, offset);
|
||||
return BitConverter.ToInt64(bytes, 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public float ToSingle(byte[] buffer, int offset)
|
||||
public virtual float ToSingle(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ByteTransDataFormat4(buffer, offset);
|
||||
|
||||
@@ -360,13 +360,13 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string ToString(byte[] buffer)
|
||||
public virtual string ToString(byte[] buffer)
|
||||
{
|
||||
return ToString(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
/// <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);
|
||||
if (BcdFormat != null)
|
||||
@@ -385,7 +385,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ushort ToUInt16(byte[] buffer, int offset)
|
||||
public virtual ushort ToUInt16(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[2];
|
||||
Array.Copy(buffer, offset, bytes, 0, 2);
|
||||
@@ -397,7 +397,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public uint ToUInt32(byte[] buffer, int offset)
|
||||
public virtual uint ToUInt32(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ByteTransDataFormat4(buffer, offset);
|
||||
|
||||
@@ -405,7 +405,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ulong ToUInt64(byte[] buffer, int offset)
|
||||
public virtual ulong ToUInt64(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = ByteTransDataFormat8(buffer, offset);
|
||||
return BitConverter.ToUInt64(bytes, 0);
|
||||
@@ -508,7 +508,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -519,7 +519,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -530,7 +530,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -541,7 +541,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -552,7 +552,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -562,7 +562,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
return numArray;
|
||||
}
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -573,7 +573,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -584,7 +584,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
@@ -595,7 +595,7 @@ public class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
|
||||
/// <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];
|
||||
for (int index = 0; index < len; ++index)
|
||||
|
@@ -1,14 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Foundataion\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="2.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -12,7 +12,7 @@ namespace ModbusDemo
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
//await ModbusClientAsync();
|
||||
await ModbusClientAsync();
|
||||
|
||||
await ModbusServerAsync();
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Foundataion\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCUA" Version="2.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<Version>2.0.6.0</Version>
|
||||
<Version>2.0.9.3</Version>
|
||||
<Authors>Diego</Authors>
|
||||
<Product>ThingsGateway</Product>
|
||||
<Copyright>© 2023-present Diego</Copyright>
|
||||
|
@@ -60,45 +60,94 @@ public class ModbusAddress : DeviceAddressBase
|
||||
/// <inheritdoc/>
|
||||
public override void Parse(string address, int length)
|
||||
{
|
||||
Length = length;
|
||||
if (address.IndexOf(';') < 0)
|
||||
var result = ParseFrom(address, length);
|
||||
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);
|
||||
for (int index = 0; index < strArray.Length; ++index)
|
||||
ModbusAddress modbusAddress = new()
|
||||
{
|
||||
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)
|
||||
Station = byte.Parse(strArray[index].Substring(2));
|
||||
}
|
||||
else if (strArray[index].ToUpper().StartsWith("W="))
|
||||
{
|
||||
if (Convert.ToInt16(strArray[index].Substring(2)) > 0)
|
||||
this.WriteFunction = byte.Parse(strArray[index].Substring(2));
|
||||
}
|
||||
else if (!strArray[index].Contains("="))
|
||||
{
|
||||
Address(strArray[index]);
|
||||
if (strArray[index].ToUpper().StartsWith("S="))
|
||||
{
|
||||
if (Convert.ToInt16(strArray[index].Substring(2)) > 0)
|
||||
modbusAddress.Station = byte.Parse(strArray[index].Substring(2));
|
||||
}
|
||||
else if (strArray[index].ToUpper().StartsWith("W="))
|
||||
{
|
||||
if (Convert.ToInt16(strArray[index].Substring(2)) > 0)
|
||||
modbusAddress.WriteFunction = byte.Parse(strArray[index].Substring(2));
|
||||
}
|
||||
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));
|
||||
if (readF > 4)
|
||||
throw new("功能码错误");
|
||||
GetFunction(readF);
|
||||
AddressStart = int.Parse(address.Substring(1)) - 1;
|
||||
return new OperResult<ModbusAddress>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
@@ -115,24 +164,6 @@ public class ModbusAddress : DeviceAddressBase
|
||||
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)
|
||||
{
|
||||
return readF switch
|
||||
|
@@ -16,290 +16,294 @@ using ThingsGateway.Foundation.Extension.Bool;
|
||||
using ThingsGateway.Foundation.Extension.Byte;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
internal class ModbusHelper
|
||||
{
|
||||
internal class ModbusHelper
|
||||
/// <summary>
|
||||
/// 添加Crc16
|
||||
/// </summary>
|
||||
internal static byte[] AddCrc(byte[] command)
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加Crc16
|
||||
/// </summary>
|
||||
internal static byte[] AddCrc(byte[] command)
|
||||
{
|
||||
return EasyCRC16.CRC16(command);
|
||||
}
|
||||
return EasyCRC16.CRC16(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加ModbusTcp报文头
|
||||
/// </summary>
|
||||
internal static byte[] AddModbusTcpHead(byte[] modbus, ushort id)
|
||||
{
|
||||
byte[] tcp = new byte[modbus.Length + 6];
|
||||
tcp[0] = BitConverter.GetBytes(id)[1];
|
||||
tcp[1] = BitConverter.GetBytes(id)[0];
|
||||
tcp[4] = BitConverter.GetBytes(modbus.Length)[1];
|
||||
tcp[5] = BitConverter.GetBytes(modbus.Length)[0];
|
||||
modbus.CopyTo(tcp, 6);
|
||||
return tcp;
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加ModbusTcp报文头
|
||||
/// </summary>
|
||||
internal static byte[] AddModbusTcpHead(byte[] modbus, ushort id)
|
||||
{
|
||||
byte[] tcp = new byte[modbus.Length + 6];
|
||||
tcp[0] = BitConverter.GetBytes(id)[1];
|
||||
tcp[1] = BitConverter.GetBytes(id)[0];
|
||||
tcp[4] = BitConverter.GetBytes(modbus.Length)[1];
|
||||
tcp[5] = BitConverter.GetBytes(modbus.Length)[0];
|
||||
modbus.CopyTo(tcp, 6);
|
||||
return tcp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// modbus地址格式说明
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string GetAddressDescription()
|
||||
/// <summary>
|
||||
/// modbus地址格式说明
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string GetAddressDescription()
|
||||
{
|
||||
StringBuilder stringBuilder = new();
|
||||
stringBuilder.AppendLine("Modbus寄存器");
|
||||
stringBuilder.AppendLine("线圈寄存器使用从 00001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("离散输入寄存器使用从 10001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("输入寄存器使用从 30001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("保持寄存器使用从 40001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("举例:");
|
||||
stringBuilder.AppendLine("40001=>保持寄存器第一个寄存器");
|
||||
stringBuilder.AppendLine("额外格式:");
|
||||
stringBuilder.AppendLine("设备站号 ,比如40001;s=2; ,代表设备地址为2的保持寄存器第一个寄存器");
|
||||
stringBuilder.AppendLine("写入功能码 ,比如40001;w=16; ,代表保持寄存器第一个寄存器,写入值时采用0x10功能码,而不是默认的0x06功能码");
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// 通过错误码来获取到对应的文本消息
|
||||
/// </summary>
|
||||
internal static string GetDescriptionByErrorCode(byte code)
|
||||
{
|
||||
return code switch
|
||||
{
|
||||
StringBuilder stringBuilder = new();
|
||||
stringBuilder.AppendLine("Modbus寄存器");
|
||||
stringBuilder.AppendLine("线圈寄存器使用从 00001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("离散输入寄存器使用从 10001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("输入寄存器使用从 30001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("保持寄存器使用从 40001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("举例:");
|
||||
stringBuilder.AppendLine("40001=>保持寄存器第一个寄存器");
|
||||
stringBuilder.AppendLine("额外格式:");
|
||||
stringBuilder.AppendLine("设备站号 ,比如40001;s=2; ,代表设备地址为2的保持寄存器第一个寄存器");
|
||||
stringBuilder.AppendLine("写入功能码 ,比如40001;w=16; ,代表保持寄存器第一个寄存器,写入值时采用0x10功能码,而不是默认的0x06功能码");
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// 通过错误码来获取到对应的文本消息
|
||||
/// </summary>
|
||||
internal static string GetDescriptionByErrorCode(byte code)
|
||||
{
|
||||
return code switch
|
||||
{
|
||||
1 => "不支持的功能码",
|
||||
2 => "读取寄存器越界",
|
||||
3 => "读取长度超限",
|
||||
4 => "读写异常",
|
||||
_ => "未知错误",
|
||||
};
|
||||
}
|
||||
1 => "不支持的功能码",
|
||||
2 => "读取寄存器越界",
|
||||
3 => "读取长度超限",
|
||||
4 => "读写异常",
|
||||
_ => "未知错误",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取modbus数据区内容,返回数据需去除Crc和报文头,例如:01 03 02 00 01,发送数据需报文头
|
||||
/// </summary>
|
||||
/// <param name="send">发送数据</param>
|
||||
/// <param name="response">返回数据</param>
|
||||
/// <returns></returns>
|
||||
internal static OperResult<byte[]> GetModbusData(byte[] send, byte[] response)
|
||||
/// <summary>
|
||||
/// 获取modbus数据区内容,返回数据需去除Crc和报文头,例如:01 03 02 00 01,发送数据需报文头
|
||||
/// </summary>
|
||||
/// <param name="send">发送数据</param>
|
||||
/// <param name="response">返回数据</param>
|
||||
/// <returns></returns>
|
||||
internal static OperResult<byte[], FilterResult> GetModbusData(byte[] send, byte[] response)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (response[1] >= 0x80)//错误码
|
||||
return new OperResult<byte[]>(GetDescriptionByErrorCode(response[2]));
|
||||
if (send.Length == 0)
|
||||
{
|
||||
var result = OperResult.CreateSuccessResult(GenericExtensions.ArrayRemoveBegin(response, 3));
|
||||
result.Message = "接收数据正确,但主机并没有主动请求数据";
|
||||
result.ResultCode = ResultCode.Canceled;
|
||||
return result;
|
||||
}
|
||||
if (send[0] != response[0])
|
||||
return new OperResult<byte[]>(string.Format("站号不一致", send[0], response[0]));
|
||||
if (send[1] != response[1])
|
||||
return new OperResult<byte[]>(response) { Message = "功能码不一致" };
|
||||
if (response.Length > 3)
|
||||
return OperResult.CreateSuccessResult(GenericExtensions.ArrayRemoveBegin(response, 3));
|
||||
else
|
||||
return new OperResult<byte[]>(response) { Message = "数据长度为0" };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 去除Crc,返回modbus数据区
|
||||
/// </summary>
|
||||
/// <param name="send"></param>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="crcCheck"></param>
|
||||
/// <returns></returns>
|
||||
internal static OperResult<byte[]> GetModbusRtuData(byte[] send, byte[] response, bool crcCheck = true)
|
||||
{
|
||||
if (response.Length < 5)
|
||||
return new OperResult<byte[]>("数据长度不足" + response.ToHexString());
|
||||
if (crcCheck && !EasyCRC16.CheckCRC16(response))
|
||||
return new OperResult<byte[]>("Crc校验失败" + DataTransUtil.ByteToHexString(response, ' '));
|
||||
return GetModbusData(send, response.RemoveLast(2));
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取读取报文
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetReadModbusCommand(string address, int length, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
return GetReadModbusCommand(mAddress, length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取写入布尔量报文,根据地址识别功能码
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteBoolModbusCommand(string address, bool[] values, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
//功能码或实际长度
|
||||
if (values?.Length > 1 || mAddress.WriteFunction == 15)
|
||||
return GetWriteBoolModbusCommand(mAddress, values, values.Length);
|
||||
else
|
||||
return GetWriteBoolModbusCommand(address, values[0], station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
if (response.Length < 3)
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
/// <summary>
|
||||
/// 获取写入字报文,根据地址识别功能码
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteModbusCommand(string address, byte[] value, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
//功能码或实际长度
|
||||
if (value?.Length > 2 || mAddress.WriteFunction == 16)
|
||||
return GetWriteModbusCommand(mAddress, value);
|
||||
else
|
||||
return GetWriteOneModbusCommand(mAddress, value);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
if (response[1] >= 0x80)//错误码
|
||||
return new OperResult<byte[], FilterResult>(GetDescriptionByErrorCode(response[2])) { Content2 = FilterResult.Success };
|
||||
if ((response.Length < response[2] + 3))
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
|
||||
if (send.Length == 0)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
var result = OperResult.CreateSuccessResult(GenericExtensions.ArrayRemoveBegin(response, 3), FilterResult.Success);
|
||||
result.Message = "接收数据正确,但主机并没有主动请求数据";
|
||||
return result;
|
||||
}
|
||||
if (send[0] != response[0])
|
||||
return new OperResult<byte[], FilterResult>(string.Format("站号不一致", send[0], response[0])) { Content2 = FilterResult.Success };
|
||||
if (send[1] != response[1])
|
||||
return new OperResult<byte[], FilterResult>() { Message = "功能码不一致", Content2 = FilterResult.Success };
|
||||
return OperResult.CreateSuccessResult(GenericExtensions.ArrayRemoveBegin(response, 3), FilterResult.Success);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取读取报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetReadModbusCommand(ModbusAddress mAddress, int length)
|
||||
catch (Exception ex)
|
||||
{
|
||||
byte[] array = new byte[6]
|
||||
{
|
||||
(byte) mAddress.Station,
|
||||
(byte) mAddress.ReadFunction,
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[1],
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[0],
|
||||
BitConverter.GetBytes(length)[1],
|
||||
BitConverter.GetBytes(length)[0]
|
||||
};
|
||||
|
||||
return OperResult.CreateSuccessResult(array);
|
||||
return new OperResult<byte[], FilterResult>(ex.Message) { Content2 = FilterResult.Success };
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 去除Crc,返回modbus数据区
|
||||
/// </summary>
|
||||
/// <param name="send"></param>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="crcCheck"></param>
|
||||
/// <returns></returns>
|
||||
internal static OperResult<byte[], FilterResult> GetModbusRtuData(byte[] send, byte[] response, bool crcCheck = true)
|
||||
{
|
||||
if (response.Length < 3)
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
/// <summary>
|
||||
/// 获取05写入布尔量报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteBoolModbusCommand(string address, bool value, byte station)
|
||||
if (crcCheck && !EasyCRC16.CheckCRC16(response))
|
||||
return new OperResult<byte[], FilterResult>("Crc校验失败" + DataTransUtil.ByteToHexString(response, ' ')) { Content2 = FilterResult.Success };
|
||||
return GetModbusData(send, response.RemoveLast(2));
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取读取报文
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetReadModbusCommand(string address, int length, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (address.IndexOf('.') <= 0)
|
||||
{
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
return GetWriteBoolModbusCommand(mAddress, value);
|
||||
}
|
||||
return new("不支持写入字寄存器的某一位");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
return GetReadModbusCommand(mAddress, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取05写入布尔量报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteBoolModbusCommand(ModbusAddress mAddress, bool value)
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取写入布尔量报文,根据地址识别功能码
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteBoolModbusCommand(string address, bool[] values, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
//功能码或实际长度
|
||||
if (values?.Length > 1 || mAddress.WriteFunction == 15)
|
||||
return GetWriteBoolModbusCommand(mAddress, values, values.Length);
|
||||
else
|
||||
return GetWriteBoolModbusCommand(address, values[0], station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取写入字报文,根据地址识别功能码
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteModbusCommand(string address, byte[] value, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
//功能码或实际长度
|
||||
if (value?.Length > 2 || mAddress.WriteFunction == 16)
|
||||
return GetWriteModbusCommand(mAddress, value);
|
||||
else
|
||||
return GetWriteOneModbusCommand(mAddress, value);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取读取报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetReadModbusCommand(ModbusAddress mAddress, int length)
|
||||
{
|
||||
byte[] array = new byte[6]
|
||||
{
|
||||
byte[] array = new byte[6]
|
||||
{
|
||||
(byte) mAddress.Station,
|
||||
(byte)5,
|
||||
(byte) mAddress.ReadFunction,
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[1],
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[0],
|
||||
0,
|
||||
0
|
||||
};
|
||||
if (value)
|
||||
{
|
||||
array[4] = 0xFF;
|
||||
array[5] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[4] = 0;
|
||||
array[5] = 0;
|
||||
}
|
||||
return OperResult.CreateSuccessResult(array);
|
||||
}
|
||||
BitConverter.GetBytes(length)[1],
|
||||
BitConverter.GetBytes(length)[0]
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 获取15写入布尔量报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteBoolModbusCommand(ModbusAddress mAddress, bool[] values, int length)
|
||||
return OperResult.CreateSuccessResult(array);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取05写入布尔量报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteBoolModbusCommand(string address, bool value, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
if (address.IndexOf('.') <= 0)
|
||||
{
|
||||
byte[] numArray1 = values.BoolArrayToByte();
|
||||
byte[] numArray2 = new byte[7 + numArray1.Length];
|
||||
numArray2[0] = (byte)mAddress.Station;
|
||||
numArray2[1] = (byte)15;
|
||||
numArray2[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray2[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
numArray2[4] = (byte)(length / 256);
|
||||
numArray2[5] = (byte)(length % 256);
|
||||
numArray2[6] = (byte)numArray1.Length;
|
||||
numArray1.CopyTo(numArray2, 7);
|
||||
return OperResult.CreateSuccessResult(numArray2);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
ModbusAddress mAddress = new(address, station);
|
||||
return GetWriteBoolModbusCommand(mAddress, value);
|
||||
}
|
||||
return new("不支持写入字寄存器的某一位");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取16写入字报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteModbusCommand(ModbusAddress mAddress, byte[] values)
|
||||
catch (Exception ex)
|
||||
{
|
||||
byte[] numArray = new byte[7 + values.Length];
|
||||
numArray[0] = (byte)mAddress.Station;
|
||||
numArray[1] = (byte)16;
|
||||
numArray[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
numArray[4] = (byte)(values.Length / 2 / 256);
|
||||
numArray[5] = (byte)(values.Length / 2 % 256);
|
||||
numArray[6] = (byte)values.Length;
|
||||
values.CopyTo(numArray, 7);
|
||||
return OperResult.CreateSuccessResult(numArray);
|
||||
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取6写入字报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteOneModbusCommand(ModbusAddress mAddress, byte[] values)
|
||||
/// <summary>
|
||||
/// 获取05写入布尔量报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteBoolModbusCommand(ModbusAddress mAddress, bool value)
|
||||
{
|
||||
byte[] array = new byte[6]
|
||||
{
|
||||
byte[] numArray = new byte[4 + values.Length];
|
||||
numArray[0] = (byte)mAddress.Station;
|
||||
numArray[1] = (byte)6;
|
||||
numArray[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
values.CopyTo(numArray, 4);
|
||||
return OperResult.CreateSuccessResult(numArray);
|
||||
(byte) mAddress.Station,
|
||||
(byte)5,
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[1],
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[0],
|
||||
0,
|
||||
0
|
||||
};
|
||||
if (value)
|
||||
{
|
||||
array[4] = 0xFF;
|
||||
array[5] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[4] = 0;
|
||||
array[5] = 0;
|
||||
}
|
||||
return OperResult.CreateSuccessResult(array);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取15写入布尔量报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteBoolModbusCommand(ModbusAddress mAddress, bool[] values, int length)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] numArray1 = values.BoolArrayToByte();
|
||||
byte[] numArray2 = new byte[7 + numArray1.Length];
|
||||
numArray2[0] = (byte)mAddress.Station;
|
||||
numArray2[1] = (byte)15;
|
||||
numArray2[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray2[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
numArray2[4] = (byte)(length / 256);
|
||||
numArray2[5] = (byte)(length % 256);
|
||||
numArray2[6] = (byte)numArray1.Length;
|
||||
numArray1.CopyTo(numArray2, 7);
|
||||
return OperResult.CreateSuccessResult(numArray2);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取16写入字报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteModbusCommand(ModbusAddress mAddress, byte[] values)
|
||||
{
|
||||
byte[] numArray = new byte[7 + values.Length];
|
||||
numArray[0] = (byte)mAddress.Station;
|
||||
numArray[1] = (byte)16;
|
||||
numArray[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
numArray[4] = (byte)(values.Length / 2 / 256);
|
||||
numArray[5] = (byte)(values.Length / 2 % 256);
|
||||
numArray[6] = (byte)values.Length;
|
||||
values.CopyTo(numArray, 7);
|
||||
return OperResult.CreateSuccessResult(numArray);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取6写入字报文
|
||||
/// </summary>
|
||||
private static OperResult<byte[]> GetWriteOneModbusCommand(ModbusAddress mAddress, byte[] values)
|
||||
{
|
||||
byte[] numArray = new byte[4 + values.Length];
|
||||
numArray[0] = (byte)mAddress.Station;
|
||||
numArray[1] = (byte)6;
|
||||
numArray[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
values.CopyTo(numArray, 4);
|
||||
return OperResult.CreateSuccessResult(numArray);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -48,47 +48,14 @@ public class ModbusRtuDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<M
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Success;
|
||||
request.Content = result.Content1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (response.Length <= 1)
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
//如果长度不足,返回缓存
|
||||
return FilterResult.Cache;
|
||||
}
|
||||
if (!(response[1] <= 0x10))
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
//功能码不对,返回放弃
|
||||
return FilterResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((response.Length > response[2] + 4))
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
//如果长度已经超了,说明这段报文已经不能继续解析了,直接返回放弃
|
||||
return FilterResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
//否则返回缓存
|
||||
return FilterResult.Cache;
|
||||
}
|
||||
}
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
}
|
||||
return result.Content2;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -10,6 +10,8 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Extension;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
@@ -38,6 +40,7 @@ public class ModbusRtuOverUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAd
|
||||
protected override OperResult<byte[]> UnpackResponse(
|
||||
byte[] send, byte[] response)
|
||||
{
|
||||
return ModbusHelper.GetModbusRtuData(send, response, Crc16CheckEnable);
|
||||
var result = ModbusHelper.GetModbusRtuData(send, response, Crc16CheckEnable);
|
||||
return result.Copy();
|
||||
}
|
||||
}
|
||||
|
@@ -10,13 +10,12 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Extension;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// ModbusTcpDataHandleAdapter
|
||||
/// </summary>
|
||||
public class ModbusTcpDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusTcpMessage>
|
||||
{
|
||||
@@ -58,48 +57,14 @@ public class ModbusTcpDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<M
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Success;
|
||||
request.Content = result.Content1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//如果返回错误,具体分析
|
||||
var op = result.Copy<byte[], FilterResult>();
|
||||
if (response.Length == 9)
|
||||
{
|
||||
if (response[7] >= 0x80)//错误码
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
}
|
||||
if (response.Length < 10)
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Cache;
|
||||
//如果长度不足,返回缓存
|
||||
}
|
||||
if ((response.Length > response[8] + 9))
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Success;
|
||||
//如果长度已经超了,说明这段报文已经不能继续解析了,直接返回放弃
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Cache;
|
||||
//否则返回缓存
|
||||
}
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
}
|
||||
return result.Content2;
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Extension;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
@@ -50,6 +51,7 @@ public class ModbusUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter<M
|
||||
/// <inheritdoc/>
|
||||
protected override OperResult<byte[]> UnpackResponse(byte[] send, byte[] response)
|
||||
{
|
||||
return ModbusHelper.GetModbusData(send.RemoveBegin(6), response.RemoveBegin(6));
|
||||
var result = ModbusHelper.GetModbusData(send.RemoveBegin(6), response.RemoveBegin(6));
|
||||
return result.Copy();
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<GenerateDocumentationFile>True</GenerateDocumentationFile>-->
|
||||
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks>
|
||||
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
|
@@ -38,6 +38,14 @@
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.Parse(System.String,System.Int32)">
|
||||
<inheritdoc/>
|
||||
</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">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -458,7 +466,7 @@
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
ModbusTcpDataHandleAdapter
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.IsCheckMessageId">
|
||||
|
@@ -301,54 +301,99 @@ public class OPCDAClient : DisposableObject
|
||||
return OPCNode?.ToString();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写入值
|
||||
/// 批量写入值
|
||||
/// </summary>
|
||||
/// <param name="valueName">写入</param>
|
||||
/// <param name="value"></param>
|
||||
/// <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())
|
||||
{
|
||||
try
|
||||
{
|
||||
var group = Groups.FirstOrDefault(it => it.OpcItems.Any(a => a.ItemID == valueName));
|
||||
if (group == null)
|
||||
return new OperResult("不存在该变量" + valueName);
|
||||
var item = group.OpcItems.Where(it => it.ItemID == valueName).FirstOrDefault();
|
||||
int[] serverHandle = new int[1] { item.ServerHandle };
|
||||
int[] PErrors = new int[1];
|
||||
var jtoken = value;
|
||||
var rank = jtoken.CalculateActualValueRank();
|
||||
object rawWriteValue;
|
||||
switch (rank)
|
||||
var valueGroup = writeInfos.GroupBy(itemId =>
|
||||
{
|
||||
var group = Groups.FirstOrDefault(it => it.OpcItems.Any(a => a.ItemID == itemId.Key));
|
||||
return group;
|
||||
}).ToList();
|
||||
|
||||
|
||||
|
||||
|
||||
foreach (var item1 in valueGroup)
|
||||
{
|
||||
case -1:
|
||||
rawWriteValue = ((JValue)jtoken).Value;
|
||||
break;
|
||||
default:
|
||||
var jarray = ((JArray)jtoken);
|
||||
rawWriteValue = jarray.Select(j => (object)j).ToArray();
|
||||
break;
|
||||
if (item1.Key == null)
|
||||
{
|
||||
foreach (var item2 in item1)
|
||||
{
|
||||
results.Add(item2.Key, new OperResult("不存在该变量" + item2.Key));
|
||||
}
|
||||
}
|
||||
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 };
|
||||
var result = group.Write(Value, serverHandle, out PErrors);
|
||||
return result;
|
||||
return results;
|
||||
}
|
||||
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/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
PrivateDisconnect();
|
||||
checkLock.SafeDispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<GenerateDocumentationFile>True</GenerateDocumentationFile>-->
|
||||
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks>
|
||||
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
|
@@ -520,12 +520,10 @@
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString">
|
||||
<inheritdoc/>
|
||||
</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>
|
||||
<param name="valueName">写入</param>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)">
|
||||
|
@@ -109,7 +109,6 @@ public static class JsonUtils
|
||||
{
|
||||
if (ValueRank == ValueRanks.Scalar)
|
||||
{
|
||||
Type type = TypeInfo.GetSystemType(builtInType, ValueRank);
|
||||
switch (builtInType)
|
||||
{
|
||||
case BuiltInType.Null: { var variant = decoder.ReadVariant(fieldName); return variant.Value; }
|
||||
@@ -124,7 +123,7 @@ public static class JsonUtils
|
||||
case BuiltInType.UInt64: { return decoder.ReadUInt64(fieldName); }
|
||||
case BuiltInType.Float: { return decoder.ReadFloat(fieldName); }
|
||||
case BuiltInType.Double: { return decoder.ReadDouble(fieldName); }
|
||||
case BuiltInType.String: { return decoder.ReadString(fieldName); }
|
||||
case BuiltInType.String: { return decoder.ReadField(fieldName, out var token) ? token?.ToString() : null; }
|
||||
case BuiltInType.DateTime: { return decoder.ReadDateTime(fieldName); }
|
||||
case BuiltInType.Guid: { return decoder.ReadGuid(fieldName); }
|
||||
case BuiltInType.ByteString: { return decoder.ReadByteString(fieldName); }
|
||||
@@ -138,7 +137,8 @@ public static class JsonUtils
|
||||
case BuiltInType.DataValue: { return decoder.ReadDataValue(fieldName); }
|
||||
case BuiltInType.Enumeration:
|
||||
{
|
||||
return type.IsEnum ? decoder.ReadEnumerated(fieldName, type) : (object)decoder.ReadInt32(fieldName);
|
||||
Type type = TypeInfo.GetSystemType(builtInType, ValueRank);
|
||||
return type.IsEnum ? decoder.ReadEnumerated(fieldName, type) : decoder.ReadInt32(fieldName);
|
||||
}
|
||||
case BuiltInType.DiagnosticInfo: { return decoder.ReadDiagnosticInfo(fieldName); }
|
||||
case BuiltInType.Variant: { return decoder.ReadVariant(fieldName); }
|
||||
@@ -300,7 +300,7 @@ public static class JsonUtils
|
||||
case BuiltInType.DataValue: { encoder.WriteDataValue(fieldName, (DataValue)value); return; }
|
||||
case BuiltInType.Enumeration:
|
||||
{
|
||||
if (value.GetType().IsEnum)
|
||||
if (value?.GetType().IsEnum == true)
|
||||
{
|
||||
encoder.WriteEnumerated(fieldName, (Enum)value);
|
||||
}
|
||||
|
@@ -230,7 +230,7 @@ public class OPCUAClient : DisposableObject
|
||||
StartNodeId = variableNode.NodeId,
|
||||
AttributeId = Attributes.Value,
|
||||
DisplayName = items[i],
|
||||
Filter = new DataChangeFilter() { DeadbandValue = OPCNode.DeadBand, DeadbandType = (int)DeadbandType.Absolute, Trigger = DataChangeTrigger.StatusValue },
|
||||
Filter = OPCNode.DeadBand == 0 ? null : new DataChangeFilter() { DeadbandValue = OPCNode.DeadBand, DeadbandType = (int)DeadbandType.Absolute, Trigger = DataChangeTrigger.StatusValue },
|
||||
SamplingInterval = OPCNode?.UpdateRate ?? 1000,
|
||||
};
|
||||
await typeSystem.LoadType(variableNode.DataType, true, true);
|
||||
@@ -249,7 +249,7 @@ public class OPCUAClient : DisposableObject
|
||||
m_subscription.Create();
|
||||
foreach (var item in m_subscription.MonitoredItems.Where(a => a.Status.Error != null && StatusCode.IsBad(a.Status.Error.StatusCode)))
|
||||
{
|
||||
item.Filter = new DataChangeFilter() { DeadbandValue = OPCNode.DeadBand, DeadbandType = (int)DeadbandType.None, Trigger = DataChangeTrigger.StatusValue };
|
||||
item.Filter = OPCNode.DeadBand == 0 ? null : new DataChangeFilter() { DeadbandValue = OPCNode.DeadBand, DeadbandType = (int)DeadbandType.None, Trigger = DataChangeTrigger.StatusValue };
|
||||
}
|
||||
m_subscription.ApplyChanges();
|
||||
|
||||
@@ -320,12 +320,21 @@ public class OPCUAClient : DisposableObject
|
||||
VariableNode variableNode = (VariableNode)ReadNode(monitoreditem.StartNodeId.ToString(), false);
|
||||
foreach (var value in monitoreditem.DequeueValues())
|
||||
{
|
||||
var data = JsonUtils.Encode(m_session.MessageContext, TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), value.Value);
|
||||
if (data == null && value.Value != null)
|
||||
if (value.Value != null)
|
||||
{
|
||||
Log.Warning($"{monitoreditem.StartNodeId}转换出错,原始值String为{value.Value}");
|
||||
var data = JsonUtils.Encode(m_session.MessageContext, TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), value.Value);
|
||||
if (data == null && value.Value != null)
|
||||
{
|
||||
Log.Warning($"{monitoreditem.StartNodeId}转换出错,原始值String为{value.Value}");
|
||||
}
|
||||
DataChangedHandler?.Invoke((variableNode, value, data));
|
||||
}
|
||||
DataChangedHandler?.Invoke((variableNode, value, data));
|
||||
else
|
||||
{
|
||||
var data = JValue.CreateNull();
|
||||
DataChangedHandler?.Invoke((variableNode, value, data));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -512,29 +521,33 @@ public class OPCUAClient : DisposableObject
|
||||
/// <summary>
|
||||
/// 异步写opc标签
|
||||
/// </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
|
||||
{
|
||||
WriteValue valueToWrite = new()
|
||||
WriteValueCollection valuesToWrite = new();
|
||||
foreach (var item in writeInfoLists)
|
||||
{
|
||||
NodeId = new NodeId(tag),
|
||||
AttributeId = Attributes.Value,
|
||||
};
|
||||
var variableNode = (VariableNode)ReadNode(tag.ToString(), false);
|
||||
await typeSystem.LoadType(variableNode.DataType, true, true);
|
||||
var dataValue = JsonUtils.Decode(
|
||||
m_session.MessageContext,
|
||||
variableNode.DataType,
|
||||
TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable),
|
||||
value.CalculateActualValueRank(),
|
||||
value
|
||||
);
|
||||
valueToWrite.Value = dataValue;
|
||||
WriteValueCollection valuesToWrite = new()
|
||||
{
|
||||
valueToWrite
|
||||
};
|
||||
WriteValue valueToWrite = new()
|
||||
{
|
||||
NodeId = new NodeId(item.Key),
|
||||
AttributeId = Attributes.Value,
|
||||
};
|
||||
var variableNode = (VariableNode)ReadNode(item.Key, false);
|
||||
await typeSystem.LoadType(variableNode.DataType, true, true);
|
||||
var dataValue = JsonUtils.Decode(
|
||||
m_session.MessageContext,
|
||||
variableNode.DataType,
|
||||
TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable),
|
||||
item.Value.CalculateActualValueRank(),
|
||||
item.Value
|
||||
);
|
||||
valueToWrite.Value = dataValue;
|
||||
|
||||
valuesToWrite.Add(valueToWrite);
|
||||
}
|
||||
|
||||
|
||||
var result = await m_session.WriteAsync(
|
||||
requestHeader: null,
|
||||
@@ -542,15 +555,29 @@ public class OPCUAClient : DisposableObject
|
||||
|
||||
ClientBase.ValidateResponse(result.Results, 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)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
var keys = writeInfoLists.Keys.ToList();
|
||||
foreach (var item in keys)
|
||||
{
|
||||
results.Add(item, new(ex));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -855,6 +882,7 @@ public class OPCUAClient : DisposableObject
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
Disconnect();
|
||||
checkLock.SafeDispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
|
@@ -375,7 +375,7 @@
|
||||
从服务器读取值
|
||||
</summary>
|
||||
</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>
|
||||
异步写opc标签
|
||||
</summary>
|
||||
|
@@ -124,7 +124,7 @@ internal partial class SiemensHelper
|
||||
}
|
||||
|
||||
byte err = content[21];
|
||||
if (err == byte.MaxValue)
|
||||
if (err != byte.MaxValue)
|
||||
{
|
||||
return new OperResult<byte[]>((int)content[21] + GetCpuError(content[21]));
|
||||
}
|
||||
@@ -301,7 +301,7 @@ internal partial class SiemensHelper
|
||||
{
|
||||
return new OperResult<string>("在PLC中不是字符串类型");
|
||||
}
|
||||
var result2 = await plc.ReadAsync(address, 2 + result1.Content[1]);
|
||||
var result2 = await plc.ReadAsync(address, 2 + result1.Content[1], token);
|
||||
if (!result2.IsSuccess)
|
||||
{
|
||||
return result2.Copy<string>();
|
||||
|
@@ -54,32 +54,9 @@ public class SiemensS7PLCDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapte
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
//如果返回错误,具体分析
|
||||
if (response.Length < 21)
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
//如果长度不足,返回缓存
|
||||
return FilterResult.Cache;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
//如果长度已经超了,说明这段报文已经不能继续解析了,直接返回放弃
|
||||
return FilterResult.Success;
|
||||
}
|
||||
}
|
||||
request.ResultCode = result.ResultCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<GenerateDocumentationFile>True</GenerateDocumentationFile>-->
|
||||
<TargetFrameworks>net45;net6.0;net7.0</TargetFrameworks>
|
||||
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
|
@@ -32,7 +32,7 @@ internal static class ModbusHelper
|
||||
|
||||
IThingsGatewayBitConverter transformParameter = ByteTransformUtil.GetTransByAddress(ref address, byteConverter);
|
||||
item.ThingsGatewayBitConverter = transformParameter;
|
||||
//item.VariableAddress = address;
|
||||
item.VariableAddress = address;
|
||||
item.Index = device.GetBitOffset(item.VariableAddress);
|
||||
}
|
||||
|
||||
|
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.Foundation.Serial;
|
||||
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
|
||||
public class ModbusRtu : CollectBase
|
||||
{
|
||||
private readonly ModbusRtuProperty driverPropertys = new();
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu _plc;
|
||||
/// <inheritdoc/>
|
||||
public override Type DriverDebugUIType => typeof(ModbusRtuDebugDriverPage);
|
||||
@@ -74,12 +74,6 @@ public class ModbusRtu : CollectBase
|
||||
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/>
|
||||
protected override void Init(CollectDeviceRunTime device, object client = null)
|
||||
{
|
||||
|
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -22,6 +20,8 @@ public class ModbusRtuOverTcp : CollectBase
|
||||
{
|
||||
|
||||
private readonly ModbusRtuOverTcpProperty driverPropertys = new();
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp _plc;
|
||||
/// <inheritdoc/>
|
||||
public override Type DriverDebugUIType => typeof(ModbusRtuOverTcpDebugDriverPage);
|
||||
@@ -61,11 +61,7 @@ public class ModbusRtuOverTcp : CollectBase
|
||||
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/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
|
||||
public class ModbusRtuOverUdp : CollectBase
|
||||
{
|
||||
private readonly ModbusRtuOverUdpProperty driverPropertys = new();
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp _plc;
|
||||
/// <inheritdoc/>
|
||||
public override Type DriverDebugUIType => typeof(ModbusRtuOverUdpDebugDriverPage);
|
||||
@@ -65,11 +65,7 @@ public class ModbusRtuOverUdp : CollectBase
|
||||
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/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
@@ -201,16 +201,25 @@ public class ModbusServer : UpLoadBase
|
||||
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
|
||||
{
|
||||
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();
|
||||
return result1;
|
||||
return result1.FirstOrDefault().Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
return result1;
|
||||
return result1.FirstOrDefault().Value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -22,6 +20,8 @@ namespace ThingsGateway.Modbus;
|
||||
/// </summary>
|
||||
public class ModbusTcp : CollectBase
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp _plc;
|
||||
|
||||
private readonly ModbusTcpProperty driverPropertys = new();
|
||||
@@ -67,11 +67,7 @@ public class ModbusTcp : CollectBase
|
||||
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/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
@@ -10,8 +10,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using ThingsGateway.Application;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
@@ -21,6 +19,8 @@ namespace ThingsGateway.Modbus;
|
||||
/// <inheritdoc/>
|
||||
public class ModbusUdp : CollectBase
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => _plc;
|
||||
private ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp _plc;
|
||||
|
||||
private readonly ModbusUdpProperty driverPropertys = new();
|
||||
@@ -66,11 +66,7 @@ public class ModbusUdp : CollectBase
|
||||
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/>
|
||||
protected override void Dispose(bool disposing)
|
||||
|
@@ -7,6 +7,9 @@
|
||||
<member name="T:ThingsGateway.Modbus.ModbusRtuOverTcp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverTcp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverTcp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -34,9 +37,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</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)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -116,6 +116,9 @@
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverUdp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtuOverUdp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -143,9 +146,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtuOverUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</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)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -168,6 +168,9 @@
|
||||
<member name="T:ThingsGateway.Modbus.ModbusRtu">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtu.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusRtu.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -200,9 +203,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusRtu.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</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)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -400,6 +400,9 @@
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusTcp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusTcp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -427,9 +430,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusTcp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</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)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -507,6 +507,9 @@
|
||||
<member name="T:ThingsGateway.Modbus.ModbusUdp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusUdp.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Modbus.ModbusUdp.DriverDebugUIType">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -534,9 +537,6 @@
|
||||
<member name="M:ThingsGateway.Modbus.ModbusUdp.LoadSourceRead(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariableRunTime})">
|
||||
<inheritdoc/>
|
||||
</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)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
|
@@ -49,7 +49,7 @@ public class IotSharpClient : UpLoadBase
|
||||
private const string WriteMethod = "WRITE";
|
||||
|
||||
private readonly IotSharpClientProperty driverPropertys = new();
|
||||
private readonly EasyLock lockobj = new();
|
||||
private readonly EasyLock easyLock = new();
|
||||
private readonly IotSharpClientVariableProperty variablePropertys = new();
|
||||
private ConcurrentQueue<DeviceData> _collectDeviceRunTimes = new();
|
||||
private ConcurrentQueue<VariableData> _collectVariableRunTimes = new();
|
||||
@@ -204,6 +204,7 @@ public class IotSharpClient : UpLoadBase
|
||||
{
|
||||
try
|
||||
{
|
||||
easyLock.SafeDispose();
|
||||
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
|
||||
|
||||
_globalDeviceData?.CollectDevices?.ForEach(a =>
|
||||
@@ -339,9 +340,7 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
|
||||
&& driverPropertys.DeviceRpcEnable;
|
||||
if (rpcEnable == true)
|
||||
{
|
||||
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + rpcrequestid, item);
|
||||
|
||||
results.Add(item.Key, result);
|
||||
|
||||
}
|
||||
else
|
||||
@@ -355,6 +354,12 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
|
||||
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()
|
||||
{
|
||||
DeviceId = rpcdevicename,
|
||||
@@ -472,7 +477,7 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
|
||||
return OperResult.CreateSuccessResult();
|
||||
try
|
||||
{
|
||||
await lockobj.WaitAsync();
|
||||
await easyLock.WaitAsync();
|
||||
if (_mqttClient?.IsConnected == true)
|
||||
return OperResult.CreateSuccessResult();
|
||||
using var timeoutToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(driverPropertys.ConnectTimeOut));
|
||||
@@ -497,7 +502,7 @@ GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
|
||||
}
|
||||
finally
|
||||
{
|
||||
lockobj.Release();
|
||||
easyLock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -43,7 +43,7 @@ namespace ThingsGateway.Mqtt;
|
||||
public class MqttClient : UpLoadBase
|
||||
{
|
||||
private readonly MqttClientProperty driverPropertys = new();
|
||||
private readonly EasyLock lockobj = new();
|
||||
private readonly EasyLock easyLock = new();
|
||||
private readonly MqttClientVariableProperty variablePropertys = new();
|
||||
private List<CollectDeviceRunTime> _collectDevice;
|
||||
private ConcurrentQueue<DeviceData> _collectDeviceRunTimes = new();
|
||||
@@ -285,6 +285,7 @@ public class MqttClient : UpLoadBase
|
||||
{
|
||||
try
|
||||
{
|
||||
easyLock.SafeDispose();
|
||||
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
|
||||
|
||||
_globalDeviceData?.CollectDevices?.ForEach(a =>
|
||||
@@ -311,11 +312,12 @@ public class MqttClient : UpLoadBase
|
||||
{
|
||||
var mqttFactory = new MqttFactory(new PrivateLogger(LogMessage));
|
||||
_mqttClientOptions = mqttFactory.CreateClientOptionsBuilder()
|
||||
.WithClientId(driverPropertys.ConnectId)
|
||||
.WithClientId(driverPropertys.ConnectId)
|
||||
.WithCredentials(driverPropertys.UserName, driverPropertys.Password)//账密
|
||||
.WithTcpServer(driverPropertys.IP, driverPropertys.Port)//服务器
|
||||
.WithCleanSession(true)
|
||||
.WithKeepAlivePeriod(TimeSpan.FromSeconds(120.0))
|
||||
.WithoutThrowOnNonSuccessfulConnectResponse()
|
||||
.Build();
|
||||
_mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
|
||||
.WithTopicFilter(
|
||||
@@ -404,40 +406,48 @@ public class MqttClient : UpLoadBase
|
||||
return;
|
||||
if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
|
||||
return;
|
||||
var rpcData = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcData == null)
|
||||
var rpcDatas = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcDatas == null)
|
||||
return;
|
||||
|
||||
MqttRpcResult mqttRpcResult = new();
|
||||
MqttRpcResult mqttRpcResult = new() { RpcId = rpcDatas.RpcId, Success = true };
|
||||
try
|
||||
{
|
||||
var nv = rpcData.Adapt<KeyValuePair<string, string>>();
|
||||
var tag = _uploadVariables.FirstOrDefault(a => a.Name == nv.Key);
|
||||
if (tag != null)
|
||||
foreach (var rpcData in rpcDatas.WriteInfos)
|
||||
{
|
||||
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);
|
||||
|
||||
mqttRpcResult = new() { Message = result.Message, RpcId = rpcData.RpcId, Success = result.IsSuccess };
|
||||
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
|
||||
if (rpcEnable == true)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult.Success = false;
|
||||
mqttRpcResult.Message.Add(rpcData.Key, new("权限不足,变量不支持写入"));
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
LogMessage?.LogWarning(ex, ToString());
|
||||
mqttRpcResult = new() { Message = "Failed", RpcId = rpcData.RpcId, Success = false };
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -520,7 +530,7 @@ public class MqttClient : UpLoadBase
|
||||
return OperResult.CreateSuccessResult();
|
||||
try
|
||||
{
|
||||
await lockobj.WaitAsync();
|
||||
await easyLock.WaitAsync();
|
||||
if (_mqttClient?.IsConnected == true)
|
||||
return OperResult.CreateSuccessResult();
|
||||
using var timeoutToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(driverPropertys.ConnectTimeOut));
|
||||
@@ -548,7 +558,7 @@ public class MqttClient : UpLoadBase
|
||||
}
|
||||
finally
|
||||
{
|
||||
lockobj.Release();
|
||||
easyLock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,10 @@
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
namespace ThingsGateway.Mqtt;
|
||||
|
||||
/// <summary>
|
||||
@@ -22,13 +26,9 @@ public class MqttRpcNameVaueWithId
|
||||
/// </summary>
|
||||
public string RpcId { get; set; }
|
||||
/// <summary>
|
||||
/// 通常是变量名称
|
||||
/// "WriteInfos":{"test":"1"}
|
||||
/// </summary>
|
||||
public string Key { get; set; }
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
public Dictionary<string, string> WriteInfos { get; set; } = new();
|
||||
}
|
||||
/// <summary>
|
||||
/// MqttRpc输出
|
||||
@@ -42,7 +42,7 @@ public class MqttRpcResult
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
public Dictionary<string, OperResult> Message { get; set; } = new();
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
|
@@ -260,41 +260,46 @@ public class MqttServer : UpLoadBase
|
||||
return;
|
||||
if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
|
||||
return;
|
||||
var rpcData = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcData == null)
|
||||
var rpcDatas = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment).FromJson<MqttRpcNameVaueWithId>();
|
||||
if (rpcDatas == null)
|
||||
return;
|
||||
MqttRpcResult mqttRpcResult = new();
|
||||
MqttRpcResult mqttRpcResult = new() { RpcId = rpcDatas.RpcId, Success = true };
|
||||
try
|
||||
{
|
||||
var nv = rpcData.Adapt<KeyValuePair<string, string>>();
|
||||
var tag = _uploadVariables.FirstOrDefault(a => a.Name == nv.Key);
|
||||
if (tag != null)
|
||||
foreach (var rpcData in rpcDatas.WriteInfos)
|
||||
{
|
||||
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);
|
||||
|
||||
mqttRpcResult = new() { Message = result.Message, RpcId = rpcData.RpcId, Success = result.IsSuccess };
|
||||
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
|
||||
if (rpcEnable == true)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult.Success = false;
|
||||
mqttRpcResult.Message.Add(rpcData.Key, new("权限不足,变量不支持写入"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult = new() { Message = "权限不足,变量不支持写入", RpcId = rpcData.RpcId, Success = false };
|
||||
mqttRpcResult.Success = false;
|
||||
mqttRpcResult.Message.Add(rpcData.Key, new("不存在该变量"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttRpcResult = new() { Message = "不存在该变量", RpcId = rpcData.RpcId, Success = false };
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage?.LogWarning(ex, ToString());
|
||||
mqttRpcResult = new() { Message = "Failed", RpcId = rpcData.RpcId, Success = false };
|
||||
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -302,7 +307,7 @@ public class MqttServer : UpLoadBase
|
||||
.WithTopic($"{driverPropertys.RpcSubTopic}")
|
||||
.WithPayload(mqttRpcResult.ToJson()).Build();
|
||||
await _mqttServer.InjectApplicationMessage(
|
||||
new InjectedMqttApplicationMessage(variableMessage));
|
||||
new InjectedMqttApplicationMessage(variableMessage));
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@@ -294,14 +294,9 @@
|
||||
标识
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.Key">
|
||||
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.WriteInfos">
|
||||
<summary>
|
||||
通常是变量名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Mqtt.MqttRpcNameVaueWithId.Value">
|
||||
<summary>
|
||||
值
|
||||
"WriteInfos":{"test":"1"}
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Mqtt.MqttRpcResult">
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -25,7 +25,7 @@ using Yitter.IdGenerator;
|
||||
|
||||
namespace ThingsGateway.OPCDA;
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 导入变量
|
||||
/// </summary>
|
||||
public partial class ImportVariable
|
||||
{
|
||||
@@ -38,7 +38,7 @@ public partial class ImportVariable
|
||||
private bool overlay = true;
|
||||
|
||||
/// <summary>
|
||||
/// opc<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// opc对象
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient PLC { get; set; }
|
||||
@@ -62,7 +62,7 @@ public partial class ImportVariable
|
||||
private List<BrowseElement> Selected { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ȡ<EFBFBD>豸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
|
||||
/// 获取设备与变量列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (CollectDevice, List<DeviceVariable>) GetImportVariableList()
|
||||
@@ -145,7 +145,7 @@ public partial class ImportVariable
|
||||
{
|
||||
new()
|
||||
{
|
||||
Name = "δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||||
Name = "未完成连接",
|
||||
Tag = new(),
|
||||
Nodes = null
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ public class OPCDAClient : CollectBase
|
||||
{
|
||||
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 ConcurrentList<DeviceVariableRunTime> _deviceVariables = new();
|
||||
@@ -50,17 +50,20 @@ public class OPCDAClient : CollectBase
|
||||
/// <inheritdoc/>
|
||||
public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little);
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task AfterStopAsync()
|
||||
{
|
||||
PLC?.Disconnect();
|
||||
_plc?.Disconnect();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task BeforStartAsync(CancellationToken token)
|
||||
{
|
||||
PLC.Connect();
|
||||
_plc.Connect();
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -69,14 +72,14 @@ public class OPCDAClient : CollectBase
|
||||
{
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override bool IsConnected() => PLC?.IsConnected == true;
|
||||
public override bool IsConnected() => _plc?.IsConnected == true;
|
||||
/// <inheritdoc/>
|
||||
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
|
||||
{
|
||||
_deviceVariables = new(deviceVariables);
|
||||
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(
|
||||
it =>
|
||||
{
|
||||
@@ -98,26 +101,31 @@ public class OPCDAClient : CollectBase
|
||||
public override async Task<OperResult<byte[]>> ReadSourceAsync(DeviceVariableSourceRead deviceVariableSourceRead, CancellationToken token)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
var result = PLC.ReadItemsWithGroup(deviceVariableSourceRead.Address);
|
||||
var result = _plc.ReadItemsWithGroup(deviceVariableSourceRead.Address);
|
||||
return result.Copy<byte[]>();
|
||||
}
|
||||
|
||||
|
||||
/// <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);
|
||||
return Task.FromResult(result);
|
||||
var result = _plc.WriteItem(writeInfoLists.ToDictionary(a => a.Key.VariableAddress, a => a.Value));
|
||||
return Task.FromResult(result.ToDictionary(a =>
|
||||
{
|
||||
return writeInfoLists.Keys.FirstOrDefault(b => b.VariableAddress == a.Key).Name;
|
||||
}, a => a.Value));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (PLC != null)
|
||||
PLC.DataChangedHandler -= DataChangedHandler;
|
||||
PLC?.Disconnect();
|
||||
PLC?.SafeDispose();
|
||||
PLC = null;
|
||||
if (_plc != null)
|
||||
_plc.DataChangedHandler -= DataChangedHandler;
|
||||
_plc?.Disconnect();
|
||||
_plc?.SafeDispose();
|
||||
_plc = null;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
@@ -134,12 +142,12 @@ public class OPCDAClient : CollectBase
|
||||
ActiveSubscribe = driverPropertys.ActiveSubscribe,
|
||||
CheckRate = driverPropertys.CheckRate
|
||||
};
|
||||
if (PLC == null)
|
||||
if (_plc == null)
|
||||
{
|
||||
PLC = new(LogMessage);
|
||||
PLC.DataChangedHandler += DataChangedHandler;
|
||||
_plc = new(LogMessage);
|
||||
_plc.DataChangedHandler += DataChangedHandler;
|
||||
}
|
||||
PLC.Init(opcNode);
|
||||
_plc.Init(opcNode);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@@ -60,6 +60,25 @@
|
||||
<PModal @bind-Value="IsShowImportVariableList" OnCancel="() => IsShowImportVariableList = false"
|
||||
Title=导入OPC变量 Height=@("700") Persistent
|
||||
MaxWidth="1500" OnSave="DownDeviceExport">
|
||||
<SaveContent Context="save">
|
||||
<MMenu OffsetY Context="menu">
|
||||
<ActivatorContent>
|
||||
<MButton @attributes="@menu.Attrs" Color="primary"
|
||||
Class="my-1 mx-2 ">
|
||||
导出
|
||||
<AppChevronDown></AppChevronDown>
|
||||
</MButton>
|
||||
</ActivatorContent>
|
||||
<ChildContent>
|
||||
<MList>
|
||||
<MListItem OnClick="()=>DownDeviceExport()" Disabled="save.Loading" Loading="save.Loading">导出到excel</MListItem>
|
||||
<MListItem OnClick="()=>DeviceImport()" Disabled="save.Loading" Loading="save.Loading">导入到系统</MListItem>
|
||||
</MList>
|
||||
|
||||
</ChildContent>
|
||||
</MMenu>
|
||||
|
||||
</SaveContent>
|
||||
<ChildContent>
|
||||
@if (IsShowImportVariableList)
|
||||
{
|
||||
@@ -67,11 +86,5 @@
|
||||
}
|
||||
</ChildContent>
|
||||
|
||||
|
||||
<SaveContent Context="save">
|
||||
<MButton Text Color="primary" OnClick="save.Click" Disabled="defalutDebugDriverPage.isDownExport" Loading="defalutDebugDriverPage.isDownExport">
|
||||
<MLabel>导入</MLabel>
|
||||
</MButton>
|
||||
</SaveContent>
|
||||
</PModal>
|
||||
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Components;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ThingsGateway.Admin.Blazor.Core;
|
||||
@@ -32,7 +33,7 @@ using Yitter.IdGenerator;
|
||||
namespace ThingsGateway.OPCDA;
|
||||
|
||||
/// <summary>
|
||||
/// OPCDA<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
|
||||
/// OPCDA调试页面
|
||||
/// </summary>
|
||||
public partial class OPCDAClientDebugDriverPage : IDisposable
|
||||
{
|
||||
@@ -64,7 +65,7 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
|
||||
{
|
||||
opcDAClientPage.LogAction = defalutDebugDriverPage.LogOut;
|
||||
opcDAClientPage.ValueAction = ValueOut;
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//载入配置
|
||||
_plc = opcDAClientPage.OPC;
|
||||
StateHasChanged();
|
||||
}
|
||||
@@ -92,12 +93,27 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
|
||||
{
|
||||
if (data?.Item2?.Count == 0)
|
||||
{
|
||||
await PopupService.EnqueueSnackbarAsync("<EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>", AlertTypes.Warning);
|
||||
await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
|
||||
return;
|
||||
}
|
||||
await defalutDebugDriverPage.DownDeviceExportAsync(data?.Item1);
|
||||
await defalutDebugDriverPage.DownDeviceExportAsync(data?.Item2);
|
||||
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
|
||||
await defalutDebugDriverPage.DownDeviceVariableExportAsync(data?.Item2, data?.Item1.Name);
|
||||
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
|
||||
}
|
||||
}
|
||||
private async Task DeviceImport()
|
||||
{
|
||||
var data = ImportVariable?.GetImportVariableList();
|
||||
if (data != null)
|
||||
{
|
||||
if (data?.Item2?.Count == 0)
|
||||
{
|
||||
await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
|
||||
return;
|
||||
}
|
||||
await defalutDebugDriverPage.DeviceImportAsync(data?.Item1);
|
||||
await defalutDebugDriverPage.DeviceVariableImportAsync(data?.Item2);
|
||||
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,19 +148,24 @@ public partial class OPCDAClientDebugDriverPage : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = _plc.WriteItem(defalutDebugDriverPage.Address, defalutDebugDriverPage.WriteValue);
|
||||
if (data.IsSuccess)
|
||||
var data = _plc.WriteItem(
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ThingsGateway.OPCDA;
|
||||
public partial class OPCDAClientPage
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
@@ -35,7 +35,7 @@ public partial class OPCDAClientPage
|
||||
public ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient OPC;
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<List<ItemReadResult>> ValueAction;
|
||||
|
||||
@@ -85,7 +85,7 @@ public partial class OPCDAClientPage
|
||||
}
|
||||
private ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient GetOPCClient()
|
||||
{
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//载入配置
|
||||
OPC.Init(node);
|
||||
return OPC;
|
||||
}
|
||||
|
@@ -40,6 +40,9 @@
|
||||
<member name="P:ThingsGateway.OPCDA.OPCDAClient.ThingsGatewayBitConverter">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.OPCDA.OPCDAClient.PLC">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.AfterStopAsync">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
@@ -58,7 +61,7 @@
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.ReadSourceAsync(ThingsGateway.Application.DeviceVariableSourceRead,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</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/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.OPCDA.OPCDAClient.Dispose(System.Boolean)">
|
||||
|
@@ -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>
|
||||
// Դ<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
|
||||
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<EFBFBD><EFBFBD>605534569
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
@@ -29,7 +29,7 @@ using Yitter.IdGenerator;
|
||||
namespace ThingsGateway.OPCUA;
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 导入变量
|
||||
/// </summary>
|
||||
public partial class ImportVariable
|
||||
{
|
||||
@@ -41,7 +41,7 @@ public partial class ImportVariable
|
||||
|
||||
private bool overlay = true;
|
||||
/// <summary>
|
||||
/// opc<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// opc对象
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient PLC { get; set; }
|
||||
@@ -67,7 +67,7 @@ public partial class ImportVariable
|
||||
|
||||
private List<ReferenceDescription> Selected { get; set; } = new();
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>ȡ<EFBFBD>豸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
|
||||
/// 获取设备与变量列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<(CollectDevice, List<DeviceVariable>)> GetImportVariableListAsync()
|
||||
@@ -202,7 +202,7 @@ public partial class ImportVariable
|
||||
{
|
||||
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()
|
||||
{
|
||||
|
@@ -36,7 +36,13 @@ namespace ThingsGateway.OPCUA;
|
||||
/// </summary>
|
||||
public class OPCUAClient : CollectBase
|
||||
{
|
||||
internal Foundation.Adapter.OPCUA.OPCUAClient _plc = null;
|
||||
internal CollectDeviceRunTime Device;
|
||||
readonly PeriodicTimer _periodicTimer = new(TimeSpan.FromSeconds(60));
|
||||
private readonly OPCUAClientProperty driverPropertys = new();
|
||||
|
||||
private List<DeviceVariableRunTime> _deviceVariables = new();
|
||||
|
||||
/// <summary>
|
||||
/// OPCUA客户端
|
||||
/// </summary>
|
||||
@@ -45,33 +51,6 @@ public class OPCUAClient : CollectBase
|
||||
_ = 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/>
|
||||
public override Type DriverDebugUIType => typeof(OPCUAClientDebugDriverPage);
|
||||
|
||||
@@ -83,18 +62,23 @@ public class OPCUAClient : CollectBase
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ThingsGatewayBitConverter ThingsGatewayBitConverter { get; } = new(EndianType.Little);
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override IReadWriteDevice PLC => null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task AfterStopAsync()
|
||||
{
|
||||
PLC?.Disconnect();
|
||||
_plc?.Disconnect();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task BeforStartAsync(CancellationToken token)
|
||||
{
|
||||
await PLC?.ConnectAsync();
|
||||
await _plc?.ConnectAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void InitDataAdapter()
|
||||
{
|
||||
@@ -104,14 +88,14 @@ public class OPCUAClient : CollectBase
|
||||
public override bool IsConnected()
|
||||
{
|
||||
|
||||
return PLC.Connected;
|
||||
return _plc.Connected;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> 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 dataResult = new List<DeviceVariableSourceRead>();
|
||||
foreach (var variable in dataLists)
|
||||
@@ -131,7 +115,7 @@ public class OPCUAClient : CollectBase
|
||||
/// <inheritdoc/>
|
||||
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)
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
@@ -184,26 +168,33 @@ public class OPCUAClient : CollectBase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <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);
|
||||
return result;
|
||||
var result = await _plc.WriteNodeAsync(writeInfoLists.ToDictionary(a => a.Key.VariableAddress, a => a.Value), token);
|
||||
return result.ToDictionary(a =>
|
||||
{
|
||||
return writeInfoLists.Keys.FirstOrDefault(b => b.VariableAddress == a.Key)?.Name;
|
||||
}
|
||||
, a => a.Value);
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_periodicTimer?.Dispose();
|
||||
if (PLC != null)
|
||||
if (_plc != null)
|
||||
{
|
||||
PLC.DataChangedHandler -= DataChangedHandler;
|
||||
PLC.Disconnect();
|
||||
PLC.SafeDispose();
|
||||
PLC = null;
|
||||
_plc.DataChangedHandler -= DataChangedHandler;
|
||||
_plc.Disconnect();
|
||||
_plc.SafeDispose();
|
||||
_plc = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Init(CollectDeviceRunTime device, object client = null)
|
||||
{
|
||||
@@ -220,13 +211,13 @@ public class OPCUAClient : CollectBase
|
||||
UserName = driverPropertys.UserName,
|
||||
Password = driverPropertys.Password
|
||||
};
|
||||
if (PLC == null)
|
||||
if (_plc == null)
|
||||
{
|
||||
PLC = new(LogMessage);
|
||||
PLC.DataChangedHandler += DataChangedHandler;
|
||||
_plc = new(LogMessage);
|
||||
_plc.DataChangedHandler += DataChangedHandler;
|
||||
}
|
||||
|
||||
PLC.OPCNode = opcNode;
|
||||
_plc.OPCNode = opcNode;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -252,7 +243,7 @@ public class OPCUAClient : CollectBase
|
||||
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();
|
||||
|
||||
@@ -296,4 +287,23 @@ public class OPCUAClient : CollectBase
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user