mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-28 06:07:10 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98f3f2d519 | ||
|
|
b76b4e8d68 | ||
|
|
07285a7c61 | ||
|
|
03c0dfef37 | ||
|
|
6ef6929c35 | ||
|
|
e3c0c173f0 | ||
|
|
7d64e058d4 | ||
|
|
e97ee9b64b | ||
|
|
6a03e39eeb |
@@ -26,6 +26,7 @@ namespace ThingsGateway.Admin.Application;
|
||||
[Route("openapi/auth")]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
[LoggingMonitor]
|
||||
[ApiController]
|
||||
public class OpenApiController : ControllerBase
|
||||
{
|
||||
private readonly IAuthService _authService;
|
||||
|
||||
@@ -15,16 +15,13 @@ namespace ThingsGateway.Admin.Application;
|
||||
|
||||
[Route("api/[controller]/[action]")]
|
||||
[AllowAnonymous]
|
||||
[ApiController]
|
||||
public class TestController : ControllerBase
|
||||
{
|
||||
[HttpPost]
|
||||
public Task Test(string data)
|
||||
[HttpGet]
|
||||
public void Test()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
{
|
||||
"ThingsGateway.Admin.Application.BaseDataEntity": {
|
||||
"CreateOrgId": "CreateOrgId"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.BaseEntity": {
|
||||
"SortCode": "SortCode",
|
||||
"CreateTime": "CreateTime",
|
||||
"CreateUser": "CreateUser",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"UpdateUser": "UpdateUser"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.BlazorAuthenticationHandler": {
|
||||
"UserExpire": "User expired, please login again"
|
||||
},
|
||||
@@ -24,9 +35,6 @@
|
||||
"LatestLoginTime": "LatestLoginTime",
|
||||
"LatestLoginDevice": "LatestLoginDevice",
|
||||
"LatestLoginAddress": "LatestLoginAddress",
|
||||
"SortCode": "SortCode",
|
||||
"CreateTime": "CreateTime",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"OrgNames": "OrgNames",
|
||||
"PositionName": "PositionName",
|
||||
"OrgId": "Org",
|
||||
@@ -60,9 +68,6 @@
|
||||
"Name": "Name",
|
||||
"Name.Required": "{0} is required",
|
||||
"Category": "Category",
|
||||
"SortCode": "Sort",
|
||||
"CreateTime": "CreateTime",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"OrgId": "Org",
|
||||
"Global": "Global",
|
||||
"Status": "Status",
|
||||
@@ -105,9 +110,6 @@
|
||||
"Category": "Category",
|
||||
"Target": "Target",
|
||||
"NavLinkMatch": "NavLinkMatch",
|
||||
"SortCode": "Sort",
|
||||
"CreateTime": "CreateTime",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"ParentId": "Parent",
|
||||
"ResourceDup": "Duplicate name {0} exists",
|
||||
"ResourceParentChoiceSelf": "Parent cannot choose itself",
|
||||
@@ -134,9 +136,6 @@
|
||||
"Status": "Status",
|
||||
"OrgId": "Organization",
|
||||
"Remark": "Remarks",
|
||||
"SortCode": "SortCode",
|
||||
"CreateTime": "CreateTime",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"Dup": "Duplicate position exists with Category {0} and Name {1}",
|
||||
"CodeDup": "Duplicate code {0} exists",
|
||||
"NameDup": "Duplicate name {0} exists",
|
||||
@@ -159,9 +158,6 @@
|
||||
"Names": "Names",
|
||||
"Remark": "Remarks",
|
||||
"DirectorId": "Director",
|
||||
"SortCode": "SortCode",
|
||||
"CreateTime": "CreateTime",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"Dup": "Duplicate organization exists with Category {0} and Name {1}",
|
||||
"CodeDup": "Duplicate code {0} exists",
|
||||
"NameDup": "Duplicate name {0} exists",
|
||||
@@ -358,9 +354,6 @@
|
||||
"Name": "Name",
|
||||
"Code": "Code",
|
||||
"Remark": "Remark",
|
||||
"SortCode": "Sort",
|
||||
"CreateTime": "CreateTime",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"DemoCanotUpdateWebsitePolicy": "DEMO environment does not allow modifying website settings",
|
||||
"DictDup": "Duplicate configuration exists, category {0}, name {1}"
|
||||
},
|
||||
|
||||
@@ -1,469 +1,462 @@
|
||||
{
|
||||
"ThingsGateway.Admin.Application.BaseDataEntity": {
|
||||
"CreateOrgId": "创建机构Id"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.BaseEntity": {
|
||||
"SortCode": "排序",
|
||||
"CreateTime": "创建时间",
|
||||
"CreateUser": "创建人",
|
||||
"UpdateTime": "更新时间",
|
||||
"UpdateUser": "更新人"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.BlazorAuthenticationHandler": {
|
||||
"UserExpire": "用户登录已过期,请重新登录"
|
||||
},
|
||||
"UserExpire": "用户登录已过期,请重新登录"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.SysUser": {
|
||||
"Disable": "禁用",
|
||||
"Enable": "启用",
|
||||
"GrantRole": "分配角色",
|
||||
"ExitVerificat": "您已被强制下线",
|
||||
"PasswordEdited": "密码被修改,已退出登录",
|
||||
"Avatar": "头像",
|
||||
"Account": "账号",
|
||||
"Account.Required": " {0} 是必填项",
|
||||
"Password": "密码",
|
||||
"Status": "状态",
|
||||
"Phone": "手机",
|
||||
"Email": "邮箱",
|
||||
"LastLoginIp": "上次登录ip",
|
||||
"LastLoginDevice": "上次登录设备",
|
||||
"LastLoginTime": "上次登录时间",
|
||||
"LastLoginAddress": "上次登录地点",
|
||||
"LatestLoginIp": "最新登录ip",
|
||||
"LatestLoginTime": "最新登录时间",
|
||||
"LatestLoginDevice": "最新登录设备",
|
||||
"LatestLoginAddress": "最新登录地点",
|
||||
"SortCode": "排序",
|
||||
"CreateTime": "创建时间",
|
||||
"UpdateTime": "更新时间",
|
||||
"OrgNames": "机构名称",
|
||||
"PositionName": "职位名称",
|
||||
"OrgId": "机构",
|
||||
"PositionId": "职位",
|
||||
"DirectorId": "主管",
|
||||
"CheckSelf": "禁止 {0} 自己",
|
||||
"CanotDeleteAdminUser": "不可删除系统内置超管用户",
|
||||
"CanotEditAdminUser": "不可编辑超管用户",
|
||||
"CanotGrantAdmin": "不能分配超管角色",
|
||||
"EmailDup": "存在重复的邮箱 {0}",
|
||||
"AccountDup": "存在重复的账号 {0}",
|
||||
"CanotDeleteSelf": "不可删除自己",
|
||||
"EmailError": "邮箱 {0} 格式错误",
|
||||
"PhoneError": "手机号码 {0} 格式错误",
|
||||
"NoOrg": "组织机构不存在",
|
||||
"DirectorSelf": "不能设置自己为主管",
|
||||
"ThingsGateway.Admin.Application.SysUser": {
|
||||
"Disable": "禁用",
|
||||
"Enable": "启用",
|
||||
"GrantRole": "分配角色",
|
||||
"ExitVerificat": "您已被强制下线",
|
||||
"PasswordEdited": "密码被修改,已退出登录",
|
||||
"Avatar": "头像",
|
||||
"Account": "账号",
|
||||
"Account.Required": " {0} 是必填项",
|
||||
"Password": "密码",
|
||||
"Status": "状态",
|
||||
"Phone": "手机",
|
||||
"Email": "邮箱",
|
||||
"LastLoginIp": "上次登录ip",
|
||||
"LastLoginDevice": "上次登录设备",
|
||||
"LastLoginTime": "上次登录时间",
|
||||
"LastLoginAddress": "上次登录地点",
|
||||
"LatestLoginIp": "最新登录ip",
|
||||
"LatestLoginTime": "最新登录时间",
|
||||
"LatestLoginDevice": "最新登录设备",
|
||||
"LatestLoginAddress": "最新登录地点",
|
||||
"OrgNames": "机构名称",
|
||||
"PositionName": "职位名称",
|
||||
"OrgId": "机构",
|
||||
"PositionId": "职位",
|
||||
"DirectorId": "主管",
|
||||
"CheckSelf": "禁止 {0} 自己",
|
||||
"CanotDeleteAdminUser": "不可删除系统内置超管用户",
|
||||
"CanotEditAdminUser": "不可编辑超管用户",
|
||||
"CanotGrantAdmin": "不能分配超管角色",
|
||||
"EmailDup": "存在重复的邮箱 {0}",
|
||||
"AccountDup": "存在重复的账号 {0}",
|
||||
"CanotDeleteSelf": "不可删除自己",
|
||||
"EmailError": "邮箱 {0} 格式错误",
|
||||
"PhoneError": "手机号码 {0} 格式错误",
|
||||
"NoOrg": "组织机构不存在",
|
||||
"DirectorSelf": "不能设置自己为主管",
|
||||
|
||||
|
||||
"DemoCanotUpdatePassword": "DEMO环境不允许修改密码",
|
||||
"OldPasswordError": "原密码错误",
|
||||
"ConfirmPasswordDiff": "两次输入的密码不一致",
|
||||
"PasswordLengthLess": "密码长度不能小于 {0} ",
|
||||
"PasswordMustNum ": "密码必须包含数字",
|
||||
"PasswordMustLow": "密码必须包含小写字母",
|
||||
"PasswordMustUpp": "密码必须包含大写字母",
|
||||
"PasswordMustSpecial": "密码必须包含特殊字符"
|
||||
},
|
||||
"DemoCanotUpdatePassword": "DEMO环境不允许修改密码",
|
||||
"OldPasswordError": "原密码错误",
|
||||
"ConfirmPasswordDiff": "两次输入的密码不一致",
|
||||
"PasswordLengthLess": "密码长度不能小于 {0} ",
|
||||
"PasswordMustNum ": "密码必须包含数字",
|
||||
"PasswordMustLow": "密码必须包含小写字母",
|
||||
"PasswordMustUpp": "密码必须包含大写字母",
|
||||
"PasswordMustSpecial": "密码必须包含特殊字符"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.SysRole": {
|
||||
"Code": "编码",
|
||||
"Name": "名称",
|
||||
"Name.Required": " {0} 是必填项",
|
||||
"Category": "分类",
|
||||
"SortCode": "排序",
|
||||
"Global": "全局",
|
||||
"Status": "状态",
|
||||
"OrgId": "机构",
|
||||
"CreateTime": "创建时间",
|
||||
"UpdateTime": "更新时间",
|
||||
"ThingsGateway.Admin.Application.SysRole": {
|
||||
"Code": "编码",
|
||||
"Name": "名称",
|
||||
"Name.Required": " {0} 是必填项",
|
||||
"Category": "分类",
|
||||
"Global": "全局",
|
||||
"Status": "状态",
|
||||
"OrgId": "机构",
|
||||
|
||||
"CanotDeleteAdmin": "不可删除系统内置超管角色",
|
||||
"CanotEditAdmin": "不可编辑超管角色",
|
||||
"CanotGrantAdmin": "不能分配超管角色",
|
||||
"CanotDeleteAdmin": "不可删除系统内置超管角色",
|
||||
"CanotEditAdmin": "不可编辑超管角色",
|
||||
"CanotGrantAdmin": "不能分配超管角色",
|
||||
|
||||
"NameDup": "存在重复的角色名称 {0}",
|
||||
"OrgNotNull": "机构不能为空",
|
||||
"SameOrgNameDup": "存在重复的角色名称 {0}",
|
||||
"CannotRoleScopeAll": "机构角色不能选择全局数据范围",
|
||||
"CodeDup": "存在重复的编码 {0}"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.RoleCategoryEnum": {
|
||||
"Global": "全局",
|
||||
"Org": "机构"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.DataScopeEnum": {
|
||||
"SCOPE_SELF": "仅自己",
|
||||
"SCOPE_ALL": "全部",
|
||||
"SCOPE_ORG": "仅所属组织",
|
||||
"SCOPE_ORG_CHILD": "所属组织及以下",
|
||||
"SCOPE_ORG_DEFINE": "自定义"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.DefaultDataScope": {
|
||||
"ScopeCategory": "数据范围",
|
||||
"ScopeDefineOrgIdList": "自定义列表"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.SysResource": {
|
||||
"Title": "标题",
|
||||
"Module": "模块",
|
||||
"Title.Required": "{0} 是必填项",
|
||||
"Href.Required": "{0} 是必填项",
|
||||
"Icon": "图标",
|
||||
"Href": "路径",
|
||||
"Code": "编码",
|
||||
"Category": "分类",
|
||||
"Target": "跳转类型",
|
||||
"NavLinkMatch": "匹配类型",
|
||||
"SortCode": "排序",
|
||||
"ParentId": "上级菜单",
|
||||
"CreateTime": "创建时间",
|
||||
"UpdateTime": "更新时间",
|
||||
"ResourceDup": "存在重复的名称 {0}",
|
||||
"ResourceParentChoiceSelf": "父级不能选择自己",
|
||||
"ResourceParentNull": "父级不存在 {0}",
|
||||
"NotFoundResource": "系统异常,没找到该菜单",
|
||||
"ModuleIdDiff": "模块与上级菜单不一致",
|
||||
"CanotDeleteSystemResource": "不可删除系统资源 {0}",
|
||||
"ResourceMenuHrefNotNull": "菜单的路径不能为空"
|
||||
},
|
||||
"NameDup": "存在重复的角色名称 {0}",
|
||||
"OrgNotNull": "机构不能为空",
|
||||
"SameOrgNameDup": "存在重复的角色名称 {0}",
|
||||
"CannotRoleScopeAll": "机构角色不能选择全局数据范围",
|
||||
"CodeDup": "存在重复的编码 {0}"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.RoleCategoryEnum": {
|
||||
"Global": "全局",
|
||||
"Org": "机构"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.DataScopeEnum": {
|
||||
"SCOPE_SELF": "仅自己",
|
||||
"SCOPE_ALL": "全部",
|
||||
"SCOPE_ORG": "仅所属组织",
|
||||
"SCOPE_ORG_CHILD": "所属组织及以下",
|
||||
"SCOPE_ORG_DEFINE": "自定义"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.DefaultDataScope": {
|
||||
"ScopeCategory": "数据范围",
|
||||
"ScopeDefineOrgIdList": "自定义列表"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.SysResource": {
|
||||
"Title": "标题",
|
||||
"Module": "模块",
|
||||
"Title.Required": "{0} 是必填项",
|
||||
"Href.Required": "{0} 是必填项",
|
||||
"Icon": "图标",
|
||||
"Href": "路径",
|
||||
"Code": "编码",
|
||||
"Category": "分类",
|
||||
"Target": "跳转类型",
|
||||
"NavLinkMatch": "匹配类型",
|
||||
"ParentId": "上级菜单",
|
||||
"ResourceDup": "存在重复的名称 {0}",
|
||||
"ResourceParentChoiceSelf": "父级不能选择自己",
|
||||
"ResourceParentNull": "父级不存在 {0}",
|
||||
"NotFoundResource": "系统异常,没找到该菜单",
|
||||
"ModuleIdDiff": "模块与上级菜单不一致",
|
||||
"CanotDeleteSystemResource": "不可删除系统资源 {0}",
|
||||
"ResourceMenuHrefNotNull": "菜单的路径不能为空"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.SysOrgCopyInput": {
|
||||
"TargetId": "目标机构",
|
||||
"ContainsChild": "包含下级",
|
||||
"ContainsPosition": "包含职位"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.SysPosition": {
|
||||
"Category.Required": "{0} 是必填项",
|
||||
"Name.Required": "{0} 是必填项",
|
||||
"Code.Required": "{0} 是必填项",
|
||||
"OrgId.MinValue": "{0} 是必填项",
|
||||
"Category": "分类",
|
||||
"Name": "名称",
|
||||
"Code": "代码",
|
||||
"Status": "状态",
|
||||
"OrgId": "机构",
|
||||
"Remark": "备注",
|
||||
"SortCode": "排序",
|
||||
"CreateTime": "创建时间",
|
||||
"UpdateTime": "更新时间",
|
||||
"Dup": "存在重复的岗位 分类 {0} 名称 {1}",
|
||||
"CodeDup": "存在重复的编码 {0}",
|
||||
"NameDup": "存在重复的名称 {0}",
|
||||
"CanotContainsSelf": "不可包含自己",
|
||||
"TargetNameDup": "目标节点存在重复的名称 {0}",
|
||||
"ParentChoiceSelf": "父级不能选择自己",
|
||||
"ParentNull": "父级不存在 {0}",
|
||||
"DeleteUserFirst": "请先删除职位下的用户"
|
||||
"ThingsGateway.Admin.Application.SysOrgCopyInput": {
|
||||
"TargetId": "目标机构",
|
||||
"ContainsChild": "包含下级",
|
||||
"ContainsPosition": "包含职位"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.SysPosition": {
|
||||
"Category.Required": "{0} 是必填项",
|
||||
"Name.Required": "{0} 是必填项",
|
||||
"Code.Required": "{0} 是必填项",
|
||||
"OrgId.MinValue": "{0} 是必填项",
|
||||
"Category": "分类",
|
||||
"Name": "名称",
|
||||
"Code": "代码",
|
||||
"Status": "状态",
|
||||
"OrgId": "机构",
|
||||
"Remark": "备注",
|
||||
"Dup": "存在重复的岗位 分类 {0} 名称 {1}",
|
||||
"CodeDup": "存在重复的编码 {0}",
|
||||
"NameDup": "存在重复的名称 {0}",
|
||||
"CanotContainsSelf": "不可包含自己",
|
||||
"TargetNameDup": "目标节点存在重复的名称 {0}",
|
||||
"ParentChoiceSelf": "父级不能选择自己",
|
||||
"ParentNull": "父级不存在 {0}",
|
||||
"DeleteUserFirst": "请先删除职位下的用户"
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.SysOrg": {
|
||||
"Category.Required": "{0} 是必填项",
|
||||
"Name.Required": "{0} 是必填项",
|
||||
"Code.Required": "{0} 是必填项",
|
||||
"Category": "分类",
|
||||
"Name": "名称",
|
||||
"Code": "代码",
|
||||
"Status": "状态",
|
||||
"ParentId": "上级机构",
|
||||
"Names": "机构全称",
|
||||
"Remark": "备注",
|
||||
"DirectorId": "主管",
|
||||
"SortCode": "排序",
|
||||
"CreateTime": "创建时间",
|
||||
"UpdateTime": "更新时间",
|
||||
"Dup": "存在重复的机构 分类 {0} 名称 {1}",
|
||||
"CodeDup": "存在重复的编码 {0}",
|
||||
"NameDup": "存在重复的名称 {0}",
|
||||
"CanotContainsSelf": "不可包含自己",
|
||||
"TargetNameDup": "目标节点存在重复的名称 {0}",
|
||||
"ParentChoiceSelf": "父级不能选择自己",
|
||||
"ParentNull": "父级不存在 {0}",
|
||||
"DeleteUserFirst": "请先删除机构下的用户",
|
||||
"DeleteRoleFirst": "请先删除机构下的角色",
|
||||
"DeletePositionFirst": "请先删除机构下的职位",
|
||||
"RootOrg": "无法创建顶层机构"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.OrgEnum": {
|
||||
"COMPANY": "公司",
|
||||
"DEPT": "部门"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.PositionCategoryEnum": {
|
||||
"HIGH": "高层",
|
||||
"MIDDLE": "中层",
|
||||
"LOW": "低层"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.SysOrg": {
|
||||
"Category.Required": "{0} 是必填项",
|
||||
"Name.Required": "{0} 是必填项",
|
||||
"Code.Required": "{0} 是必填项",
|
||||
"Category": "分类",
|
||||
"Name": "名称",
|
||||
"Code": "代码",
|
||||
"Status": "状态",
|
||||
"ParentId": "上级机构",
|
||||
"Names": "机构全称",
|
||||
"Remark": "备注",
|
||||
"DirectorId": "主管",
|
||||
"Dup": "存在重复的机构 分类 {0} 名称 {1}",
|
||||
"CodeDup": "存在重复的编码 {0}",
|
||||
"NameDup": "存在重复的名称 {0}",
|
||||
"CanotContainsSelf": "不可包含自己",
|
||||
"TargetNameDup": "目标节点存在重复的名称 {0}",
|
||||
"ParentChoiceSelf": "父级不能选择自己",
|
||||
"ParentNull": "父级不存在 {0}",
|
||||
"DeleteUserFirst": "请先删除机构下的用户",
|
||||
"DeleteRoleFirst": "请先删除机构下的角色",
|
||||
"DeletePositionFirst": "请先删除机构下的职位",
|
||||
"RootOrg": "无法创建顶层机构"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.OrgEnum": {
|
||||
"COMPANY": "公司",
|
||||
"DEPT": "部门"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.PositionCategoryEnum": {
|
||||
"HIGH": "高层",
|
||||
"MIDDLE": "中层",
|
||||
"LOW": "低层"
|
||||
},
|
||||
|
||||
//controller
|
||||
"ThingsGateway.Admin.Application.AuthController": {
|
||||
//auth
|
||||
"AuthController": "登录API",
|
||||
"LoginAsync": "登录",
|
||||
"LogoutAsync": "注销"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.TestController": {
|
||||
//auth
|
||||
"TestController": "测试API",
|
||||
"Test": "测试"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.OpenApiAuthController": {
|
||||
//auth
|
||||
"OpenApiAuthController": "登录API",
|
||||
"LoginAsync": "登录",
|
||||
"LogoutAsync": "注销"
|
||||
},
|
||||
//controller
|
||||
"ThingsGateway.Admin.Application.AuthController": {
|
||||
//auth
|
||||
"AuthController": "登录API",
|
||||
"LoginAsync": "登录",
|
||||
"LogoutAsync": "注销"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.TestController": {
|
||||
//auth
|
||||
"TestController": "测试API",
|
||||
"Test": "测试"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.OpenApiAuthController": {
|
||||
//auth
|
||||
"OpenApiAuthController": "登录API",
|
||||
"LoginAsync": "登录",
|
||||
"LogoutAsync": "注销"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
"ThingsGateway.Admin.Application.FileService": {
|
||||
"FileNullError": "文件不能为空",
|
||||
"FileLengthError": "文件大小不允许超过 {0} M",
|
||||
"FileTypeError": "不支持 {0} 格式"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.FileService": {
|
||||
"FileNullError": "文件不能为空",
|
||||
"FileLengthError": "文件大小不允许超过 {0} M",
|
||||
"FileTypeError": "不支持 {0} 格式"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.UnifyResultProvider": {
|
||||
"TokenOver": "登录已过期,请重新登录",
|
||||
"NoPermission": "禁止访问,没有权限"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.UnifyResultProvider": {
|
||||
"TokenOver": "登录已过期,请重新登录",
|
||||
"NoPermission": "禁止访问,没有权限"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.AuthService": {
|
||||
"TenantNull": "租户不存在",
|
||||
"OrgDisable": "所属公司/部门已停用,请联系管理员",
|
||||
"SingleLoginWarn": "您的账号已在别处登录",
|
||||
"UserNull": "用户 {0} 不存在",
|
||||
"PasswordError": "密码错误次数过多,请 {0} 分钟后再试",
|
||||
"AuthErrorMax": "账号密码错误,超过 {0} 次后将锁定 {1} 分钟,错误次数 {2} ",
|
||||
"UserDisable": "账号 {0} 已停用",
|
||||
"MustDesc": "密码需要DESC加密后传入",
|
||||
"UserNoModule": "该账号未分配模块,请联系管理员"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.AuthService": {
|
||||
"TenantNull": "租户不存在",
|
||||
"OrgDisable": "所属公司/部门已停用,请联系管理员",
|
||||
"SingleLoginWarn": "您的账号已在别处登录",
|
||||
"UserNull": "用户 {0} 不存在",
|
||||
"PasswordError": "密码错误次数过多,请 {0} 分钟后再试",
|
||||
"AuthErrorMax": "账号密码错误,超过 {0} 次后将锁定 {1} 分钟,错误次数 {2} ",
|
||||
"UserDisable": "账号 {0} 已停用",
|
||||
"MustDesc": "密码需要DESC加密后传入",
|
||||
"UserNoModule": "该账号未分配模块,请联系管理员"
|
||||
},
|
||||
|
||||
|
||||
"ThingsGateway.Admin.Application.HardwareInfo": {
|
||||
"Environment": "主机环境",
|
||||
"FrameworkDescription": "NET框架",
|
||||
"OsArchitecture": "系统架构",
|
||||
"UUID": "唯一编码",
|
||||
"UpdateTime": "更新时间"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.HistoryHardwareInfo": {
|
||||
"DriveUsage": "磁盘使用率",
|
||||
"MemoryUsage": "内存",
|
||||
"CpuUsage": "CPU使用率",
|
||||
"Temperature": "温度",
|
||||
"Battery": "电池"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.HardwareInfo": {
|
||||
"Environment": "主机环境",
|
||||
"FrameworkDescription": "NET框架",
|
||||
"OsArchitecture": "系统架构",
|
||||
"UUID": "唯一编码",
|
||||
"UpdateTime": "更新时间"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.HistoryHardwareInfo": {
|
||||
"DriveUsage": "磁盘使用率",
|
||||
"MemoryUsage": "内存",
|
||||
"CpuUsage": "CPU使用率",
|
||||
"Temperature": "温度",
|
||||
"Battery": "电池"
|
||||
},
|
||||
|
||||
//oper
|
||||
"ThingsGateway.Admin.Application.OperDescAttribute": {
|
||||
//dict
|
||||
"SaveDict": "修改字典",
|
||||
"DeleteDict": "删除字典",
|
||||
"EditLoginPolicy": "修改登录策略",
|
||||
"EditPasswordPolicy": "修改密码策略",
|
||||
"EditPagePolicy": "修改页面策略",
|
||||
"EditWebsitePolicy": "修改网站设置",
|
||||
//operlog
|
||||
"DeleteOperLog": "删除操作日志",
|
||||
"ExportOperLog": "导出操作日志",
|
||||
//oper
|
||||
"ThingsGateway.Admin.Application.OperDescAttribute": {
|
||||
//dict
|
||||
"SaveDict": "修改字典",
|
||||
"DeleteDict": "删除字典",
|
||||
"EditLoginPolicy": "修改登录策略",
|
||||
"EditPasswordPolicy": "修改密码策略",
|
||||
"EditPagePolicy": "修改页面策略",
|
||||
"EditWebsitePolicy": "修改网站设置",
|
||||
//operlog
|
||||
"DeleteOperLog": "删除操作日志",
|
||||
"ExportOperLog": "导出操作日志",
|
||||
|
||||
//resource
|
||||
"SaveResource": "修改资源",
|
||||
"DeleteResource": "删除资源",
|
||||
//resource
|
||||
"SaveResource": "修改资源",
|
||||
"DeleteResource": "删除资源",
|
||||
|
||||
//role
|
||||
"SaveRole": "修改角色",
|
||||
"DeleteRole": "删除角色",
|
||||
"RoleGrantResource": "角色授权资源",
|
||||
"RoleGrantUser": "角色授权用户",
|
||||
"RoleGrantApiPermission": "角色授权OpenApi",
|
||||
"GrantApi": "API",
|
||||
"GrantUser": "用户",
|
||||
"GrantRole": "角色",
|
||||
"GrantResource": "资源",
|
||||
//user
|
||||
"SaveUser": "修改用户",
|
||||
"DeleteuSER": "删除用户",
|
||||
"ResetPassword": "重置密码",
|
||||
"UserGrantRole": "用户授权角色",
|
||||
"UserGrantResource": "用户授权资源",
|
||||
"UserGrantApiPermission": "用户授权OpenApi",
|
||||
//role
|
||||
"SaveRole": "修改角色",
|
||||
"DeleteRole": "删除角色",
|
||||
"RoleGrantResource": "角色授权资源",
|
||||
"RoleGrantUser": "角色授权用户",
|
||||
"RoleGrantApiPermission": "角色授权OpenApi",
|
||||
"GrantApi": "API",
|
||||
"GrantUser": "用户",
|
||||
"GrantRole": "角色",
|
||||
"GrantResource": "资源",
|
||||
//user
|
||||
"SaveUser": "修改用户",
|
||||
"DeleteuSER": "删除用户",
|
||||
"ResetPassword": "重置密码",
|
||||
"UserGrantRole": "用户授权角色",
|
||||
"UserGrantResource": "用户授权资源",
|
||||
"UserGrantApiPermission": "用户授权OpenApi",
|
||||
|
||||
//usercenter
|
||||
"UpdateUserInfo": "更新个人信息",
|
||||
"WorkbenchInfo": "更新个人工作台",
|
||||
"UpdatePassword": "更新个人密码",
|
||||
//usercenter
|
||||
"UpdateUserInfo": "更新个人信息",
|
||||
"WorkbenchInfo": "更新个人工作台",
|
||||
"UpdatePassword": "更新个人密码",
|
||||
|
||||
//session
|
||||
"ExitVerificat": "强退令牌",
|
||||
"ExitSession": "强退会话",
|
||||
//session
|
||||
"ExitVerificat": "强退令牌",
|
||||
"ExitSession": "强退会话",
|
||||
|
||||
|
||||
"CopyOrg": "复制机构",
|
||||
"DeleteOrg": "删除机构",
|
||||
"SaveOrg": "保存机构",
|
||||
"CopyOrg": "复制机构",
|
||||
"DeleteOrg": "删除机构",
|
||||
"SaveOrg": "保存机构",
|
||||
|
||||
"DeletePosition": "删除岗位",
|
||||
"SavePosition": "保存岗位",
|
||||
"DeletePosition": "删除岗位",
|
||||
"SavePosition": "保存岗位",
|
||||
|
||||
"NoPermission": "无权限操作",
|
||||
"NoPermission": "无权限操作",
|
||||
|
||||
"CopyResource": "复制资源",
|
||||
"ChangeParentResource": "更改父节点"
|
||||
},
|
||||
"CopyResource": "复制资源",
|
||||
"ChangeParentResource": "更改父节点"
|
||||
},
|
||||
|
||||
//service
|
||||
//service
|
||||
|
||||
"ThingsGateway.Admin.Application.HardwareJob": {
|
||||
"GetHardwareInfoFail": "获取硬件信息出错"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.HardwareJob": {
|
||||
"GetHardwareInfoFail": "获取硬件信息出错"
|
||||
},
|
||||
|
||||
//dto
|
||||
"ThingsGateway.Admin.Application.UserSelectorOutput": {
|
||||
"Account": "账号",
|
||||
"OrgId": "机构"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.ResourceTableSearchModel": {
|
||||
"Module": "模块",
|
||||
"Href": "路径",
|
||||
"Title": "标题"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.WorkbenchInfo": {
|
||||
"Razor": "主页",
|
||||
"Shortcuts": "快捷方式"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.UpdatePasswordInput": {
|
||||
"Password": "密码",
|
||||
"NewPassword": "新密码",
|
||||
"ConfirmPassword": "确认密码",
|
||||
"Password.Required": " {0} 是必填项",
|
||||
"NewPassword.Required": " {0} 是必填项",
|
||||
"ConfirmPassword.Required": " {0} 是必填项"
|
||||
},
|
||||
//dto
|
||||
"ThingsGateway.Admin.Application.UserSelectorOutput": {
|
||||
"Account": "账号",
|
||||
"OrgId": "机构"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.ResourceTableSearchModel": {
|
||||
"Module": "模块",
|
||||
"Href": "路径",
|
||||
"Title": "标题"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.WorkbenchInfo": {
|
||||
"Razor": "主页",
|
||||
"Shortcuts": "快捷方式"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.UpdatePasswordInput": {
|
||||
"Password": "密码",
|
||||
"NewPassword": "新密码",
|
||||
"ConfirmPassword": "确认密码",
|
||||
"Password.Required": " {0} 是必填项",
|
||||
"NewPassword.Required": " {0} 是必填项",
|
||||
"ConfirmPassword.Required": " {0} 是必填项"
|
||||
},
|
||||
|
||||
|
||||
"ThingsGateway.Admin.Application.VerificatInfo": {
|
||||
"Expire": "过期时间(分)",
|
||||
"Online": "在线状态",
|
||||
"VerificatTimeout": "超时时间",
|
||||
"Device": "登录设备",
|
||||
"LoginIp": "登录IP",
|
||||
"LoginTime": "登录时间"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.VerificatInfo": {
|
||||
"Expire": "过期时间(分)",
|
||||
"Online": "在线状态",
|
||||
"VerificatTimeout": "超时时间",
|
||||
"Device": "登录设备",
|
||||
"LoginIp": "登录IP",
|
||||
"LoginTime": "登录时间"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.SessionOutput": {
|
||||
"Account": "账号",
|
||||
"Online": "在线状态",
|
||||
"LatestLoginIp": "最新登录ip",
|
||||
"LatestLoginTime": "最新登录时间",
|
||||
"VerificatCount": "令牌数量"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.SessionOutput": {
|
||||
"Account": "账号",
|
||||
"Online": "在线状态",
|
||||
"LatestLoginIp": "最新登录ip",
|
||||
"LatestLoginTime": "最新登录时间",
|
||||
"VerificatCount": "令牌数量"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.SysDict": {
|
||||
"Category.Required": "{0} 是必填项",
|
||||
"Name.Required": "{0} 是必填项",
|
||||
"Code.Required": "{0} 是必填项",
|
||||
"Category": "分类",
|
||||
"Name": "名称",
|
||||
"Code": "代码",
|
||||
"Remark": "备注",
|
||||
"SortCode": "排序",
|
||||
"CreateTime": "创建时间",
|
||||
"UpdateTime": "更新时间",
|
||||
"DictDup": "存在重复的配置 分类 {0} 名称 {1}",
|
||||
"DemoCanotUpdateWebsitePolicy": "DEMO环境不允许修改网站设置"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.SysDict": {
|
||||
"Category.Required": "{0} 是必填项",
|
||||
"Name.Required": "{0} 是必填项",
|
||||
"Code.Required": "{0} 是必填项",
|
||||
"Category": "分类",
|
||||
"Name": "名称",
|
||||
"Code": "代码",
|
||||
"Remark": "备注",
|
||||
"DictDup": "存在重复的配置 分类 {0} 名称 {1}",
|
||||
"DemoCanotUpdateWebsitePolicy": "DEMO环境不允许修改网站设置"
|
||||
},
|
||||
|
||||
|
||||
"ThingsGateway.Admin.Application.SysOperateLog": {
|
||||
"ClassName": "类名",
|
||||
"ExeMessage": "具体消息",
|
||||
"MethodName": "方法名称",
|
||||
"ParamJson": "请求参数",
|
||||
"ReqMethod": "请求方式",
|
||||
"ReqUrl": "请求地址",
|
||||
"ResultJson": "返回结果",
|
||||
"Category": "日志分类",
|
||||
"ExeStatus": "执行状态",
|
||||
"Name": "日志名称",
|
||||
"OpAccount": "账号",
|
||||
"OpBrowser": "浏览器",
|
||||
"OpIp": "ip",
|
||||
"OpOs": "系统",
|
||||
"OpTime": "操作时间",
|
||||
"VerificatId": "验证Id"
|
||||
"ThingsGateway.Admin.Application.SysOperateLog": {
|
||||
"ClassName": "类名",
|
||||
"ExeMessage": "具体消息",
|
||||
"MethodName": "方法名称",
|
||||
"ParamJson": "请求参数",
|
||||
"ReqMethod": "请求方式",
|
||||
"ReqUrl": "请求地址",
|
||||
"ResultJson": "返回结果",
|
||||
"Category": "日志分类",
|
||||
"ExeStatus": "执行状态",
|
||||
"Name": "日志名称",
|
||||
"OpAccount": "账号",
|
||||
"OpBrowser": "浏览器",
|
||||
"OpIp": "ip",
|
||||
"OpOs": "系统",
|
||||
"OpTime": "操作时间",
|
||||
"VerificatId": "验证Id"
|
||||
|
||||
},
|
||||
"ThingsGateway.Admin.Application.OperateLogPageInput": {
|
||||
"SearchDate": "时间范围",
|
||||
"Account": "操作账号",
|
||||
"Category": "分类"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.LoginInput": {
|
||||
"Account": "登录账号",
|
||||
"Password": "登录密码",
|
||||
"Account.Required": "{0} 是必填项",
|
||||
"Password.Required": "{0} 是必填项"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.LogoutInput": {
|
||||
"VerificatId.Required": "{0} 是必填项"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.AppConfig": {
|
||||
"LoginPolicy": "登录策略",
|
||||
"PasswordPolicy": "密码策略",
|
||||
"PagePolicy": "页面设置",
|
||||
"WebsitePolicy": "网站设置"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.LoginPolicy": {
|
||||
"SingleOpen": "单用户登录开关",
|
||||
"ErrorLockTime": "登录错误锁定时长(分)",
|
||||
"ErrorResetTime": "登录错误次数过期时长(分)",
|
||||
"ErrorCount": "登录错误次数锁定阈值",
|
||||
"VerificatExpireTime": "登录过期时间(分)",
|
||||
"ErrorLockTime.MinValue": " {0} 值太小",
|
||||
"ErrorResetTime.MinValue": " {0} 值太小",
|
||||
"ErrorCount.MinValue": " {0} 值太小",
|
||||
"VerificatExpireTime.MinValue": " {0} 值太小"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.PagePolicy": {
|
||||
"Shortcuts": "默认快捷方式",
|
||||
"Razor": "默认主页"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.PasswordPolicy": {
|
||||
"DefaultPassword": "默认用户密码",
|
||||
"DefaultPassword.Required": " {0} 是必填项",
|
||||
"PasswordMinLen": "密码最小长度",
|
||||
"PasswordMinLen.MinValue": " {0} 值太小",
|
||||
"PasswordContainNum": "包含数字",
|
||||
"PasswordContainLower": "包含小写字母",
|
||||
"PasswordContainUpper": "包含大写字母",
|
||||
"PasswordContainChar": "包含特殊字符"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.WebsitePolicy": {
|
||||
"WebStatus": "是否开放",
|
||||
"CloseTip": "关闭提示",
|
||||
"CloseTip.Required": " {0} 是必填项"
|
||||
},
|
||||
},
|
||||
"ThingsGateway.Admin.Application.OperateLogPageInput": {
|
||||
"SearchDate": "时间范围",
|
||||
"Account": "操作账号",
|
||||
"Category": "分类"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.LoginInput": {
|
||||
"Account": "登录账号",
|
||||
"Password": "登录密码",
|
||||
"Account.Required": "{0} 是必填项",
|
||||
"Password.Required": "{0} 是必填项"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.LogoutInput": {
|
||||
"VerificatId.Required": "{0} 是必填项"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.AppConfig": {
|
||||
"LoginPolicy": "登录策略",
|
||||
"PasswordPolicy": "密码策略",
|
||||
"PagePolicy": "页面设置",
|
||||
"WebsitePolicy": "网站设置"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.LoginPolicy": {
|
||||
"SingleOpen": "单用户登录开关",
|
||||
"ErrorLockTime": "登录错误锁定时长(分)",
|
||||
"ErrorResetTime": "登录错误次数过期时长(分)",
|
||||
"ErrorCount": "登录错误次数锁定阈值",
|
||||
"VerificatExpireTime": "登录过期时间(分)",
|
||||
"ErrorLockTime.MinValue": " {0} 值太小",
|
||||
"ErrorResetTime.MinValue": " {0} 值太小",
|
||||
"ErrorCount.MinValue": " {0} 值太小",
|
||||
"VerificatExpireTime.MinValue": " {0} 值太小"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.PagePolicy": {
|
||||
"Shortcuts": "默认快捷方式",
|
||||
"Razor": "默认主页"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.PasswordPolicy": {
|
||||
"DefaultPassword": "默认用户密码",
|
||||
"DefaultPassword.Required": " {0} 是必填项",
|
||||
"PasswordMinLen": "密码最小长度",
|
||||
"PasswordMinLen.MinValue": " {0} 值太小",
|
||||
"PasswordContainNum": "包含数字",
|
||||
"PasswordContainLower": "包含小写字母",
|
||||
"PasswordContainUpper": "包含大写字母",
|
||||
"PasswordContainChar": "包含特殊字符"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.WebsitePolicy": {
|
||||
"WebStatus": "是否开放",
|
||||
"CloseTip": "关闭提示",
|
||||
"CloseTip.Required": " {0} 是必填项"
|
||||
},
|
||||
|
||||
|
||||
|
||||
//enum
|
||||
"ThingsGateway.Admin.Application.ResourceCategoryEnum": {
|
||||
"Module": "模块",
|
||||
"Menu": "菜单",
|
||||
"Button": "按钮"
|
||||
},
|
||||
//enum
|
||||
"ThingsGateway.Admin.Application.ResourceCategoryEnum": {
|
||||
"Module": "模块",
|
||||
"Menu": "菜单",
|
||||
"Button": "按钮"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.TargetEnum": {
|
||||
"_self": "本窗口",
|
||||
"_blank": "新窗口",
|
||||
"_parent": "父级窗口",
|
||||
"_top": "顶级窗口"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.DictTypeEnum": {
|
||||
"System": "系统配置",
|
||||
"Define": "业务配置"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.TargetEnum": {
|
||||
"_self": "本窗口",
|
||||
"_blank": "新窗口",
|
||||
"_parent": "父级窗口",
|
||||
"_top": "顶级窗口"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.DictTypeEnum": {
|
||||
"System": "系统配置",
|
||||
"Define": "业务配置"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.LogCateGoryEnum": {
|
||||
"Login": "登录",
|
||||
"Logout": "注销",
|
||||
"Operate": "操作",
|
||||
"Exception": "异常"
|
||||
},
|
||||
"ThingsGateway.Admin.Application.LogCateGoryEnum": {
|
||||
"Login": "登录",
|
||||
"Logout": "注销",
|
||||
"Operate": "操作",
|
||||
"Exception": "异常"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Application.LogEnum": {
|
||||
"SUCCESS": "成功",
|
||||
"FAIL": "失败"
|
||||
}
|
||||
"ThingsGateway.Admin.Application.LogEnum": {
|
||||
"SUCCESS": "成功",
|
||||
"FAIL": "失败"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,26 +22,19 @@ using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
using ThingsGateway.Extension;
|
||||
using ThingsGateway.SpecificationDocument;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
|
||||
internal sealed class ApiPermissionService : IApiPermissionService
|
||||
{
|
||||
private readonly IApiDescriptionGroupCollectionProvider _apiDescriptionGroupCollectionProvider;
|
||||
private readonly SwaggerGeneratorOptions _generatorOptions;
|
||||
|
||||
public ApiPermissionService(
|
||||
IOptions<SwaggerGeneratorOptions> generatorOptions,
|
||||
IApiDescriptionGroupCollectionProvider apiDescriptionGroupCollectionProvider)
|
||||
{
|
||||
_generatorOptions = generatorOptions.Value;
|
||||
_apiDescriptionGroupCollectionProvider = apiDescriptionGroupCollectionProvider;
|
||||
}
|
||||
private IEnumerable<string> GetDocumentNames()
|
||||
{
|
||||
return _generatorOptions.SwaggerDocs.Keys;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<OpenApiPermissionTreeSelector> ApiPermissionTreeSelector()
|
||||
@@ -53,37 +46,37 @@ internal sealed class ApiPermissionService : IApiPermissionService
|
||||
permissions = new();
|
||||
|
||||
Dictionary<string, OpenApiPermissionTreeSelector> groupOpenApis = new();
|
||||
foreach (var item in GetDocumentNames())
|
||||
{
|
||||
OpenApiPermissionTreeSelector openApiPermissionTreeSelector = new() { ApiName = item ?? "Default" };
|
||||
groupOpenApis.TryAdd(openApiPermissionTreeSelector.ApiName, openApiPermissionTreeSelector);
|
||||
}
|
||||
|
||||
var apiDescriptions = _apiDescriptionGroupCollectionProvider.ApiDescriptionGroups.Items;
|
||||
|
||||
foreach (var item1 in apiDescriptions)
|
||||
{
|
||||
foreach (var item in item1.Items)
|
||||
{
|
||||
if (item.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
|
||||
{
|
||||
OpenApiPermissionTreeSelector openApiPermissionTreeSelector = new() { ApiName = controllerActionDescriptor.ControllerName ?? "Default" };
|
||||
groupOpenApis.TryAdd(openApiPermissionTreeSelector.ApiName, openApiPermissionTreeSelector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取所有需要数据权限的控制器
|
||||
var controllerTypes =
|
||||
App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(RolePermissionAttribute), false));
|
||||
|
||||
foreach (var groupOpenApi in groupOpenApis)
|
||||
//foreach (var groupOpenApi in groupOpenApis)
|
||||
{
|
||||
|
||||
foreach (var apiDescriptionGroup in apiDescriptions)
|
||||
{
|
||||
|
||||
|
||||
var routes = apiDescriptionGroup.Items.Where(api => api.ActionDescriptor is ControllerActionDescriptor);
|
||||
|
||||
OpenApiPermissionTreeSelector openApiPermissionTreeSelector = groupOpenApi.Value;
|
||||
|
||||
Dictionary<string, OpenApiPermissionTreeSelector> openApiPermissionTreeSelectorDict = new();
|
||||
|
||||
foreach (var route in routes)
|
||||
{
|
||||
if (!SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(groupOpenApi.Key, route))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var actionDesc = (ControllerActionDescriptor)route.ActionDescriptor;
|
||||
if (!actionDesc.ControllerTypeInfo.CustomAttributes.Any(a => a.AttributeType == typeof(RolePermissionAttribute)))
|
||||
continue;
|
||||
@@ -116,10 +109,8 @@ internal sealed class ApiPermissionService : IApiPermissionService
|
||||
}
|
||||
|
||||
|
||||
openApiPermissionTreeSelector.Children.AddRange(openApiPermissionTreeSelectorDict.Values);
|
||||
|
||||
if (openApiPermissionTreeSelector.Children.Any(a => a.Children.Count > 0))
|
||||
permissions.Add(openApiPermissionTreeSelector);
|
||||
if (openApiPermissionTreeSelectorDict.Values.Any(a => a.Children.Count > 0))
|
||||
permissions.AddRange(openApiPermissionTreeSelectorDict.Values);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -96,9 +96,9 @@ public class AuthService : IAuthService
|
||||
/// </summary>
|
||||
public async Task LoginOutAsync()
|
||||
{
|
||||
if (UserManager.UserId == 0)
|
||||
if (UserManager.VerificatId == 0)
|
||||
return;
|
||||
var verificatId = UserManager.UserId;
|
||||
var verificatId = UserManager.VerificatId;
|
||||
//获取用户信息
|
||||
var userinfo = await _sysUserService.GetUserByAccountAsync(UserManager.UserAccount, UserManager.TenantId).ConfigureAwait(false);
|
||||
if (userinfo != null)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.4" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.0" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.191" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.193" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
|
||||
@@ -30,9 +30,9 @@
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.4" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="9.0.4" />
|
||||
<PackageReference Include="System.Threading.RateLimiting" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="9.0.5" />
|
||||
<PackageReference Include="System.Threading.RateLimiting" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Remove="SeedData\Admin\*.json" />
|
||||
|
||||
@@ -41,7 +41,7 @@ public partial class SessionPage
|
||||
{
|
||||
var op = new DialogOption()
|
||||
{
|
||||
IsScrolling = false,
|
||||
IsScrolling = true,
|
||||
Title = Localizer[nameof(VerificatInfo)],
|
||||
ShowMaximizeButton = true,
|
||||
Class = "dialog-table",
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net8.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.16" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net9.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
|
||||
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
@@ -18,6 +21,7 @@ using Microsoft.Extensions.Options;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Unicode;
|
||||
@@ -291,6 +295,21 @@ public class Startup : AppStartup
|
||||
services.AddAuthorizationCore();
|
||||
services.AddScoped<IAuthorizationHandler, BlazorServerAuthenticationHandler>();
|
||||
services.AddScoped<AuthenticationStateProvider, BlazorServerAuthenticationStateProvider>();
|
||||
|
||||
#if NET9_0_OR_GREATER
|
||||
var certificate = X509CertificateLoader.LoadPkcs12FromFile("ThingsGateway.pfx", "ThingsGateway", X509KeyStorageFlags.EphemeralKeySet);
|
||||
#else
|
||||
var certificate = new X509Certificate2("ThingsGateway.pfx", "ThingsGateway", X509KeyStorageFlags.EphemeralKeySet);
|
||||
#endif
|
||||
services.AddDataProtection()
|
||||
.PersistKeysToFileSystem(new DirectoryInfo("../keys"))
|
||||
.ProtectKeysWithCertificate(certificate)
|
||||
.UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
|
||||
{
|
||||
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
|
||||
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
<!--安装服务守护-->
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
@@ -54,8 +54,8 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -72,6 +72,9 @@
|
||||
<None Update="pm2-linux.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="ThingsGateway.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="thingsgateway.service">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
BIN
src/Admin/ThingsGateway.AdminServer/ThingsGateway.pfx
Normal file
BIN
src/Admin/ThingsGateway.AdminServer/ThingsGateway.pfx
Normal file
Binary file not shown.
@@ -43,18 +43,18 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.16" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.16" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="8.0.2" />
|
||||
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="8.0.1" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="9.0.4" />
|
||||
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="9.0.4" />
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="9.0.5" />
|
||||
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="9.0.5" />
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.5" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="8.0.16" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="9.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.0.2" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.6.0" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.6.2-beta05" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<PluginVersion>10.5.13</PluginVersion>
|
||||
<ProPluginVersion>10.5.13</ProPluginVersion>
|
||||
<PluginVersion>10.5.19</PluginVersion>
|
||||
<ProPluginVersion>10.5.19</ProPluginVersion>
|
||||
<AuthenticationVersion>2.1.7</AuthenticationVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ public class Startup : AppStartup
|
||||
{
|
||||
public void Configure(IServiceCollection services)
|
||||
{
|
||||
Foundation.LocalizerUtil.SetLocalizerFactory((a) => App.CreateLocalizerByType(a));
|
||||
services.AddScoped<IPlatformService, PlatformService>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
|
||||
set
|
||||
{
|
||||
_heartbeat = value;
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(value));
|
||||
if (!_heartbeat.IsNullOrEmpty())
|
||||
{
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
private string _heartbeat;
|
||||
@@ -59,6 +62,8 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
|
||||
return;//此处可判断,如果为服务器,则不用使用心跳。
|
||||
}
|
||||
|
||||
HeartbeatTime = Math.Max(HeartbeatTime, 1000);
|
||||
|
||||
if (DtuId.IsNullOrWhiteSpace()) return;
|
||||
|
||||
if (client is ITcpClient tcpClient)
|
||||
|
||||
@@ -70,7 +70,7 @@ public static class PluginUtil
|
||||
{
|
||||
action += a =>
|
||||
{
|
||||
a.UseCheckClear()
|
||||
a.UseTcpSessionCheckClear()
|
||||
.SetCheckClearType(CheckClearType.All)
|
||||
.SetTick(TimeSpan.FromMilliseconds(channelOptions.CheckClearTime))
|
||||
.SetOnClose(async (c, t) =>
|
||||
|
||||
@@ -114,13 +114,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
|
||||
this.SafeDispose();
|
||||
}
|
||||
|
||||
#region 属性
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual int SendDelayTime { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual int Timeout { get; set; } = 3000;
|
||||
#region
|
||||
|
||||
private ILog? _deviceLogger;
|
||||
|
||||
@@ -143,6 +137,18 @@ public abstract class DeviceBase : DisposableObject, IDevice
|
||||
public bool OnLine => Channel.Online;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 属性
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual int SendDelayTime { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual int Timeout { get; set; } = 3000;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="IThingsGatewayBitConverter.IsStringReverseByteWord"/>
|
||||
/// </summary>
|
||||
@@ -562,9 +568,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
|
||||
finally
|
||||
{
|
||||
waitLock.Release();
|
||||
if (waitData.WaitResult != null)
|
||||
waitData.WaitResult.Sign = sign;
|
||||
clientChannel.WaitHandlePool.Destroy(waitData);
|
||||
clientChannel.WaitHandlePool.Destroy(sign);
|
||||
Channel.ChannelReceivedWaitDict.TryRemove(sign, out _);
|
||||
}
|
||||
}
|
||||
@@ -962,7 +966,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
|
||||
if (tcpServiceChannel.TryGetClient($"ID={dtu.DtuId}", out var client))
|
||||
{
|
||||
client.WaitHandlePool?.SafeDispose();
|
||||
client.Close();
|
||||
_ = client.CloseAsync();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -150,6 +150,13 @@ public static class LoggerExtensions
|
||||
logger.Log(TouchSocket.Core.LogLevel.Info, null, msg, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出提示日志
|
||||
/// </summary>
|
||||
public static void LogDebug(this ILog logger, string msg)
|
||||
{
|
||||
logger.Log(TouchSocket.Core.LogLevel.Debug, null, msg, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// 输出Trace日志
|
||||
/// </summary>
|
||||
|
||||
@@ -83,9 +83,20 @@
|
||||
"ThingsGateway.Foundation.ConverterConfig": {
|
||||
"DataFormat": "DataFormat",
|
||||
"Encoding": "Encoding",
|
||||
"EncodingName": "字符串编码",
|
||||
"EncodingName": "EncodingName",
|
||||
"VariableStringLength": "VariableStringLength",
|
||||
"Stringlength": "Stringlength",
|
||||
"BcdFormat": "BcdFormat格式"
|
||||
"BcdFormat": "BcdFormat"
|
||||
},
|
||||
|
||||
"ThingsGateway.Foundation.DeviceBase": {
|
||||
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"DataFormat": "DataFormat",
|
||||
"Timeout": "Timeout",
|
||||
"IsStringReverseByteWord": "IsStringReverseByteWord"
|
||||
},
|
||||
"ThingsGateway.Foundation.DtuServiceDeviceBase": {
|
||||
"DtuId": "DtuId(UTF8)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,18 @@
|
||||
"VariableStringLength": "变长字符串",
|
||||
"Stringlength": "字符串长度",
|
||||
"BcdFormat": "BCD格式"
|
||||
},
|
||||
|
||||
"ThingsGateway.Foundation.DeviceBase": {
|
||||
|
||||
"SendDelayTime": "发送延时",
|
||||
"DataFormat": "解析规则",
|
||||
"Timeout": "读写超时",
|
||||
"IsStringReverseByteWord": "字符串反转"
|
||||
},
|
||||
"ThingsGateway.Foundation.DtuServiceDeviceBase": {
|
||||
"DtuId": "Dtu注册包(UTF8)"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.4" />
|
||||
<PackageReference Include="TouchSocket" Version="3.1.1" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.5" />
|
||||
<PackageReference Include="TouchSocket" Version="3.1.2" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.16" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Version="8.0.16" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Version="9.0.5" />
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -40,9 +40,7 @@ public class AsyncReadWriteLock
|
||||
|
||||
private void ReleaseWriter()
|
||||
{
|
||||
Interlocked.Decrement(ref _writerCount);
|
||||
|
||||
if (Interlocked.Read(ref _writerCount) == 0)
|
||||
if (Interlocked.Decrement(ref _writerCount) == 0)
|
||||
{
|
||||
var resetEvent = _readerLock;
|
||||
_readerLock = new(false);
|
||||
|
||||
@@ -125,7 +125,9 @@ internal sealed class InternalTableColumn(string fieldName, Type fieldType, stri
|
||||
/// </summary>
|
||||
public string? RequiredErrorMessage { get; set; }
|
||||
|
||||
|
||||
public bool IsFixedSearchWhenSelect { get; set; } = true;
|
||||
|
||||
public int Cols { get; set; }
|
||||
|
||||
public bool? IgnoreWhenExport { get; set; }
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace ThingsGateway.Gateway.Application;
|
||||
[Route("openApi/control")]
|
||||
[RolePermission]
|
||||
[LoggingMonitor]
|
||||
[ApiController]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class ControlController : ControllerBase
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace ThingsGateway.Gateway.Application;
|
||||
[ApiDescriptionSettings("ThingsGateway.OpenApi", Order = 200)]
|
||||
[DisplayName("数据状态")]
|
||||
[Route("openApi/runtimeInfo")]
|
||||
[ApiController]
|
||||
[RolePermission]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class RuntimeInfoController : ControllerBase
|
||||
|
||||
@@ -35,6 +35,7 @@ public abstract class BusinessBaseWithCacheAlarmModel<VarModel, DevModel, AlarmM
|
||||
{
|
||||
try
|
||||
{
|
||||
LogMessage?.LogInformation($"Add {typeof(DevModel).Name} data to file cache, count {data.Count}");
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.Id = CommonUtils.GetSingleId();
|
||||
@@ -100,6 +101,7 @@ public abstract class BusinessBaseWithCacheAlarmModel<VarModel, DevModel, AlarmM
|
||||
{
|
||||
if (_memoryAlarmModelQueue.Count > _businessPropertyWithCache.QueueMaxCount)
|
||||
{
|
||||
LogMessage?.LogWarning($"{typeof(AlarmModel).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase [QueueMaxCount] or Enable cache");
|
||||
_memoryAlarmModelQueue.Clear();
|
||||
_memoryAlarmModelQueue.Enqueue(data);
|
||||
return;
|
||||
|
||||
@@ -36,6 +36,7 @@ public abstract class BusinessBaseWithCacheDeviceModel<VarModel, DevModel> : Bus
|
||||
|
||||
try
|
||||
{
|
||||
LogMessage?.LogInformation($"Add {typeof(DevModel).Name} data to file cache, count {data.Count}");
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.Id = CommonUtils.GetSingleId();
|
||||
@@ -101,6 +102,7 @@ public abstract class BusinessBaseWithCacheDeviceModel<VarModel, DevModel> : Bus
|
||||
{
|
||||
if (_memoryDevModelQueue.Count > _businessPropertyWithCache.QueueMaxCount)
|
||||
{
|
||||
LogMessage?.LogWarning($"{typeof(DevModel).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase [QueueMaxCount] or Enable cache");
|
||||
_memoryDevModelQueue.Clear();
|
||||
_memoryDevModelQueue.Enqueue(data);
|
||||
return;
|
||||
|
||||
@@ -39,6 +39,7 @@ public abstract class BusinessBaseWithCacheVariableModel<VarModel> : BusinessBas
|
||||
{
|
||||
try
|
||||
{
|
||||
LogMessage?.LogInformation($"Add {typeof(VarModel).Name} data to file cache, count {data.Count}");
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.Id = CommonUtils.GetSingleId();
|
||||
@@ -147,6 +148,7 @@ public abstract class BusinessBaseWithCacheVariableModel<VarModel> : BusinessBas
|
||||
{
|
||||
if (_memoryVarModelQueue.Count > _businessPropertyWithCache.QueueMaxCount)
|
||||
{
|
||||
LogMessage?.LogWarning($"{typeof(VarModel).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase [QueueMaxCount] or Enable cache");
|
||||
_memoryVarModelQueue.Clear();
|
||||
_memoryVarModelQueue.Enqueue(data);
|
||||
return;
|
||||
|
||||
@@ -38,4 +38,11 @@ public class BusinessPropertyWithCache : BusinessPropertyBase
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual int QueueMaxCount { get; set; } = 100000;
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public virtual bool OnlineFilter { get; set; } = false;
|
||||
|
||||
[DynamicProperty]
|
||||
public bool GroupUpdate { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -162,6 +162,8 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
{
|
||||
if (_exTTimerTick.IsTickHappen())
|
||||
{
|
||||
if (LogMessage.LogLevel <= LogLevel.Debug)
|
||||
LogMessage?.LogDebug($"Interval {typeof(VarModel).Name} data, count {IdVariableRuntimes.Count}");
|
||||
// 间隔推送全部变量
|
||||
var variableRuntimes = IdVariableRuntimes.Select(a => a.Value);
|
||||
VariableTimeInterval(variableRuntimes, variableRuntimes.Adapt<List<VariableBasicData>>());
|
||||
@@ -177,6 +179,8 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
{
|
||||
if (CollectDevices != null)
|
||||
{
|
||||
if (LogMessage.LogLevel <= LogLevel.Debug)
|
||||
LogMessage?.LogDebug($"Interval {typeof(DevModel).Name} data, count {CollectDevices.Count}");
|
||||
|
||||
// 间隔推送全部设备
|
||||
foreach (var deviceRuntime in CollectDevices.Select(a => a.Value))
|
||||
|
||||
@@ -152,6 +152,8 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
{
|
||||
if (_exTTimerTick.IsTickHappen())
|
||||
{
|
||||
if (LogMessage.LogLevel <= LogLevel.Debug)
|
||||
LogMessage?.LogDebug($"Interval {typeof(VarModel).Name} data, count {IdVariableRuntimes.Count}");
|
||||
// 上传所有变量信息
|
||||
var variableRuntimes = IdVariableRuntimes.Select(a => a.Value);
|
||||
VariableTimeInterval(variableRuntimes, variableRuntimes.Adapt<List<VariableBasicData>>());
|
||||
@@ -168,6 +170,8 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
{
|
||||
if (CollectDevices != null)
|
||||
{
|
||||
if (LogMessage.LogLevel <= LogLevel.Debug)
|
||||
LogMessage?.LogDebug($"Interval {typeof(DevModel).Name} data, count {CollectDevices.Count}");
|
||||
// 上传所有设备信息
|
||||
foreach (var deviceRuntime in CollectDevices.Select(a => a.Value))
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
List<string> strings = new List<string>();
|
||||
|
||||
// 使用正则表达式查找输入字符串中的所有匹配项
|
||||
Regex regex = new Regex(@"\$\{(.+?)\}");
|
||||
Regex regex = TopicRegex();
|
||||
MatchCollection matches = regex.Matches(input);
|
||||
|
||||
// 遍历匹配结果,将匹配到的字符串添加到列表中
|
||||
@@ -89,10 +89,12 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
// 上传内容
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
|
||||
// 如果是报警列表,则将整个分组转换为 JSON 字符串
|
||||
string json = group.Select(a => a).ToList().ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
var gList = group.Select(a => a).ToList();
|
||||
string json = gList.ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -101,7 +103,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,15 +113,16 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
string json = data.Select(a => a).ToList().ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json));
|
||||
var gList = data.Select(a => a).ToList();
|
||||
string json = gList.ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json));
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,9 +159,10 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
// 如果是设备列表,则将整个分组转换为 JSON 字符串
|
||||
string json = group.Select(a => a).ToList().ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
var gList = group.Select(a => a).ToList();
|
||||
string json = gList.ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -167,7 +171,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,15 +182,16 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
string json = data.Select(a => a).ToList().ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json));
|
||||
var gList = data.Select(a => a).ToList();
|
||||
string json = gList.ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json));
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,9 +226,10 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
// 如果是变量列表,则将整个分组转换为 JSON 字符串
|
||||
string json = group.Select(a => a).ToList().ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
var gList = group.Select(a => a).ToList();
|
||||
string json = gList.ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -232,7 +238,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,15 +249,16 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
string json = data.Select(a => a).ToList().ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
var gList = data.Select(a => a).ToList();
|
||||
string json = gList.ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -294,10 +301,11 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
// 上传内容
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
|
||||
// 如果是变量列表,则将整个分组转换为 JSON 字符串
|
||||
string json = group.Select(a => a).GroupBy(a => a.DeviceName, b => b).ToDictionary(a => a.Key, b => b.ToList()).ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, group.Count()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -306,7 +314,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicJsonList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,14 +326,14 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
string json = data.Select(a => a).GroupBy(a => a.DeviceName, b => b).ToDictionary(a => a.Key, b => b.ToList()).ToJsonNetString(_businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, data.Count()));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
string json = JsonExtensions.ToJsonNetString(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -369,7 +377,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
protected List<TopicArray> GetAlarmTopicArrays(IEnumerable<AlarmModel> item)
|
||||
{
|
||||
IEnumerable<dynamic>? data = Application.DynamicModelExtension.GetDynamicModel<AlarmModel>(item, _businessPropertyWithCacheIntervalScript.BigTextScriptAlarmModel);
|
||||
List<TopicArray> topicJsonList = new List<TopicArray>();
|
||||
List<TopicArray> topicArrayList = new List<TopicArray>();
|
||||
var topics = Match(_businessPropertyWithCacheIntervalScript.AlarmTopic);
|
||||
if (topics.Count > 0)
|
||||
{
|
||||
@@ -392,9 +400,10 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
// 上传内容
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
var json = Serialize(group.Select(a => a).ToList().ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
var gList = group.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -403,7 +412,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
var json = Serialize(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,26 +422,27 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
var json = Serialize(data.Select(a => a).ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json));
|
||||
var gList = data.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
var json = Serialize(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json));
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return topicJsonList;
|
||||
return topicArrayList;
|
||||
}
|
||||
|
||||
protected List<TopicArray> GetDeviceTopicArray(IEnumerable<DevModel> item)
|
||||
{
|
||||
IEnumerable<dynamic>? data = Application.DynamicModelExtension.GetDynamicModel<DevModel>(item, _businessPropertyWithCacheIntervalScript.BigTextScriptDeviceModel);
|
||||
List<TopicArray> topicJsonList = new List<TopicArray>();
|
||||
List<TopicArray> topicArrayList = new List<TopicArray>();
|
||||
var topics = Match(_businessPropertyWithCacheIntervalScript.DeviceTopic);
|
||||
if (topics.Count > 0)
|
||||
{
|
||||
@@ -457,9 +467,10 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
// 如果是设备列表,则将整个分组转换为 JSON 字符串
|
||||
var json = Serialize(group.Select(a => a).ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
var gList = group.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -468,7 +479,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
var json = Serialize(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,25 +490,26 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
var json = Serialize(data.Select(a => a).ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json));
|
||||
var gList = data.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
var json = Serialize(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json));
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return topicJsonList;
|
||||
return topicArrayList;
|
||||
}
|
||||
|
||||
protected List<TopicArray> GetVariableTopicArray(IEnumerable<VarModel> item)
|
||||
{
|
||||
IEnumerable<dynamic>? data = Application.DynamicModelExtension.GetDynamicModel<VarModel>(item, _businessPropertyWithCacheIntervalScript.BigTextScriptVariableModel);
|
||||
List<TopicArray> topicJsonList = new List<TopicArray>();
|
||||
List<TopicArray> topicArrayList = new List<TopicArray>();
|
||||
var topics = Match(_businessPropertyWithCacheIntervalScript.VariableTopic);
|
||||
if (topics.Count > 0)
|
||||
{
|
||||
@@ -522,9 +534,10 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
// 如果是变量列表,则将整个分组转换为 JSON 字符串
|
||||
var json = Serialize(group.Select(a => a).ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
var gList = group.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -533,7 +546,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
var json = Serialize(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,19 +557,20 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
var json = Serialize(data.Select(a => a).ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
var gList = data.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
var json = Serialize(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return topicJsonList;
|
||||
return topicArrayList;
|
||||
}
|
||||
|
||||
protected List<TopicArray> GetVariableBasicDataTopicArray(IEnumerable<VariableBasicData> item)
|
||||
@@ -571,7 +585,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
data = item;
|
||||
}
|
||||
|
||||
List<TopicArray> topicJsonList = new List<TopicArray>();
|
||||
List<TopicArray> topicArrayList = new List<TopicArray>();
|
||||
var topics = Match(_businessPropertyWithCacheIntervalScript.VariableTopic);
|
||||
if (topics.Count > 0)
|
||||
{
|
||||
@@ -596,9 +610,10 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
// 如果是变量列表,则将整个分组转换为 JSON 字符串
|
||||
var json = Serialize(group.Select(a => a).ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
var gList = group.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -607,7 +622,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
var json = Serialize(gro, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
topicArrayList.Add(new(topic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -618,25 +633,40 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
var json = Serialize(data.Select(a => a).ToList(), _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
var gList = data.Select(a => a).ToList();
|
||||
var json = Serialize(gList, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, gList.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
var json = Serialize(group, _businessPropertyWithCacheIntervalScript.JsonFormattingIndented);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
topicArrayList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return topicJsonList;
|
||||
return topicArrayList;
|
||||
}
|
||||
|
||||
|
||||
protected string GetString(string topic, byte[] json, int count)
|
||||
protected string GetDetailLogString(TopicArray topicArray, int queueCount)
|
||||
{
|
||||
return $"Topic:{topic}{Environment.NewLine}PayLoad:{Encoding.UTF8.GetString(json)} {Environment.NewLine} VarModelQueue:{count}";
|
||||
if (queueCount > 0)
|
||||
return $"Up Topic:{topicArray.Topic}{Environment.NewLine}PayLoad:{Encoding.UTF8.GetString(topicArray.Json)} {Environment.NewLine} VarModelQueue:{queueCount}";
|
||||
else
|
||||
return $"Up Topic:{topicArray.Topic}{Environment.NewLine}PayLoad:{Encoding.UTF8.GetString(topicArray.Json)}";
|
||||
}
|
||||
|
||||
protected string GetCountLogString(TopicArray topicArray, int queueCount)
|
||||
{
|
||||
if (queueCount > 0)
|
||||
return $"Up Topic:{topicArray.Topic}{Environment.NewLine}Count:{topicArray.Count} {Environment.NewLine} VarModelQueue:{queueCount}";
|
||||
else
|
||||
return $"Up Topic:{topicArray.Topic}{Environment.NewLine}Count:{topicArray.Count}";
|
||||
|
||||
}
|
||||
[GeneratedRegex(@"\$\{(.+?)\}")]
|
||||
private static partial Regex TopicRegex();
|
||||
#endregion 封装方法
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ using TouchSocket.Core;
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
/// <summary>
|
||||
/// 抽象类 <see cref="BusinessBaseWithCacheIntervalVariableModel{T}"/>,表示具有缓存间隔功能的业务基类,其中 T 代表变量模型。
|
||||
/// 抽象类 <see cref="BusinessBaseWithCacheIntervalVariableModel{VarModel}"/>,表示具有缓存间隔功能的业务基类,其中 T 代表变量模型。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">变量模型类型</typeparam>
|
||||
public abstract class BusinessBaseWithCacheIntervalVariableModel<T> : BusinessBaseWithCacheVariableModel<T>
|
||||
/// <typeparam name="VarModel">变量模型类型</typeparam>
|
||||
public abstract class BusinessBaseWithCacheIntervalVariableModel<VarModel> : BusinessBaseWithCacheVariableModel<VarModel>
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于定时触发的时间间隔。
|
||||
@@ -110,6 +110,8 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<T> : BusinessBa
|
||||
{
|
||||
if (_exTTimerTick.IsTickHappen())
|
||||
{
|
||||
if (LogMessage.LogLevel <= LogLevel.Debug)
|
||||
LogMessage?.LogDebug($"Interval {typeof(VarModel).Name} data, count {IdVariableRuntimes.Count}");
|
||||
//间隔推送全部变量
|
||||
var variableRuntimes = IdVariableRuntimes.Select(a => a.Value);
|
||||
VariableTimeInterval(variableRuntimes, variableRuntimes.Adapt<List<VariableBasicData>>());
|
||||
|
||||
@@ -17,6 +17,11 @@ namespace ThingsGateway.Gateway.Application;
|
||||
/// </summary>
|
||||
public class BusinessPropertyWithCacheIntervalScript : BusinessPropertyWithCacheInterval
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否显示详细日志
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public bool DetailLog { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 缩进格式化
|
||||
|
||||
@@ -12,11 +12,12 @@ namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
public struct TopicArray
|
||||
{
|
||||
public TopicArray(string topic, byte[] json)
|
||||
public TopicArray(string topic, byte[] json, int count)
|
||||
{
|
||||
Topic = topic; Json = json;
|
||||
Topic = topic; Json = json; Count = count;
|
||||
}
|
||||
|
||||
public int Count { get; set; } = 1;
|
||||
public byte[] Json { get; set; }
|
||||
public string Topic { get; set; }
|
||||
|
||||
|
||||
@@ -12,10 +12,11 @@ namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
public struct TopicJson
|
||||
{
|
||||
public TopicJson(string topic, string json)
|
||||
public TopicJson(string topic, string json, int count)
|
||||
{
|
||||
Topic = topic; Json = json;
|
||||
Topic = topic; Json = json; Count = count;
|
||||
}
|
||||
public int Count { get; set; } = 1;
|
||||
|
||||
public string Json { get; set; }
|
||||
public string Topic { get; set; }
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://thingsgateway.cn/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
/// <summary>
|
||||
/// 插件配置项
|
||||
/// <br></br>
|
||||
/// 使用<see cref="DynamicPropertyAttribute"/> 标识所需的配置属性
|
||||
/// </summary>
|
||||
public abstract class CollectFoundationPackPropertyBase : CollectFoundationPropertyBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大打包长度
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public ushort MaxPack { get; set; } = 100;
|
||||
|
||||
|
||||
}
|
||||
public abstract class CollectFoundationPropertyBase : CollectPropertyRetryBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 读写超时时间
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual ushort Timeout { get; set; } = 3000;
|
||||
|
||||
/// <summary>
|
||||
/// 帧前时间ms
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual int SendDelayTime { get; set; } = 0;
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public bool IsStringReverseByteWord { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认解析顺序
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual DataFormatEnum DataFormat { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件配置项
|
||||
/// <br></br>
|
||||
/// 使用<see cref="DynamicPropertyAttribute"/> 标识所需的配置属性
|
||||
/// </summary>
|
||||
public abstract class CollectFoundationDtuPropertyBase : CollectFoundationPropertyBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 默认DtuId
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public string? DtuId { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件配置项
|
||||
/// <br></br>
|
||||
/// 使用<see cref="DynamicPropertyAttribute"/> 标识所需的配置属性
|
||||
/// </summary>
|
||||
public abstract class CollectFoundationDtuPackPropertyBase : CollectFoundationPackPropertyBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 默认DtuId
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public string? DtuId { get; set; }
|
||||
|
||||
|
||||
}
|
||||
@@ -25,12 +25,30 @@ public abstract class CollectPropertyBase : DriverPropertyBase
|
||||
/// <summary>
|
||||
/// 离线后恢复运行的间隔时间
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual int ReIntervalTime { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 失败重试次数,默认3
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual int RetryCount { get; set; } = 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件配置项
|
||||
/// <br></br>
|
||||
/// 使用<see cref="DynamicPropertyAttribute"/> 标识所需的配置属性
|
||||
/// </summary>
|
||||
public abstract class CollectPropertyRetryBase : CollectPropertyBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 离线后恢复运行的间隔时间
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public override int ReIntervalTime { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 失败重试次数,默认3
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public override int RetryCount { get; set; } = 3;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace ThingsGateway.Gateway.Application;
|
||||
[SugarTable("variable", TableDescription = "设备变量表")]
|
||||
[Tenant(SqlSugarConst.DB_Custom)]
|
||||
[SugarIndex("index_device", nameof(Variable.DeviceId), OrderByType.Asc)]
|
||||
[SugarIndex("unique_variable_name", nameof(Variable.Name), OrderByType.Asc, nameof(Variable.DeviceId), OrderByType.Asc, true)]
|
||||
[SugarIndex("unique_deviceid_variable_name", nameof(Variable.Name), OrderByType.Asc, nameof(Variable.DeviceId), OrderByType.Asc, true)]
|
||||
public class Variable : BaseDataEntity, IValidatableObject
|
||||
{
|
||||
|
||||
|
||||
@@ -1,8 +1,76 @@
|
||||
{
|
||||
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPackPropertyBase": {
|
||||
"DtuId": "DtuId(UTF8)"
|
||||
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPropertyBase": {
|
||||
"DtuId": "DtuId(UTF8)"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationPackPropertyBase": {
|
||||
|
||||
"MaxPack": "MaxPack"
|
||||
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationPropertyBase": {
|
||||
"DataFormat": "DataFormat",
|
||||
"IsStringReverseByteWord": "IsStringReverseByteWord",
|
||||
"Timeout": "Timeout",
|
||||
"SendDelayTime": "SendDelayTime"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectPropertyRetryBase": {
|
||||
"ReIntervalTime": "ReIntervalTime",
|
||||
"RetryCount": "RetryCount"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectPropertyBase": {
|
||||
"ReIntervalTime": "ReIntervalTime",
|
||||
"RetryCount": "RetryCount",
|
||||
"ConcurrentCount": "ConcurrentCount"
|
||||
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.BusinessPropertyWithCacheIntervalScript": {
|
||||
|
||||
"DetailLog": "DetailLog",
|
||||
"JsonFormattingIndented": "JsonFormattingIndented",
|
||||
|
||||
"BigTextScriptDeviceModel": "BigTextScriptDeviceModel",
|
||||
"BigTextScriptVariableModel": "BigTextScriptVariableModel",
|
||||
"BigTextScriptAlarmModel": "BigTextScriptAlarmModel",
|
||||
|
||||
"IsDeviceList": "IsDeviceList",
|
||||
"IsVariableList": "IsVariableList",
|
||||
"IsAlarmList": "IsAlarmList",
|
||||
|
||||
"DeviceTopic": "DeviceTopic",
|
||||
"VariableTopic": "VariableTopic",
|
||||
"AlarmTopic": "AlarmTopic"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.BusinessPropertyWithCacheInterval": {
|
||||
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.BusinessPropertyWithCache": {
|
||||
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
|
||||
"GroupUpdate": "GroupUpdate",
|
||||
"OnlineFilter": "OnlineFilter"
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.BusinessUpdateEnum": {
|
||||
"Change": "Change",
|
||||
"Interval": "Interval",
|
||||
"IntervalOrChange": "IntervalOrChange"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.ControlController": {
|
||||
@@ -30,55 +98,17 @@
|
||||
"ActiveTime": "ActiveTime",
|
||||
"DeviceVariableCount": "DeviceVariableCount",
|
||||
"LastErrorMessage": "LastErrorMessage",
|
||||
|
||||
"Name": "Name",
|
||||
"DeviceStatus": "DeviceStatus",
|
||||
"RedundantType": "RedundantType",
|
||||
"PluginName": "PluginName",
|
||||
"Name.Required": " {0} cannot be empty",
|
||||
"Description": "Description",
|
||||
"ChannelId": "Channel",
|
||||
"ChannelName": "ChannelName",
|
||||
"IntervalTime": "IntervalTime",
|
||||
"IntervalTime.MinValue": " {0} value is too small",
|
||||
|
||||
"PluginName": "PluginName",
|
||||
"PluginName.Required": "{0} cannot be empty",
|
||||
|
||||
"LogEnable": "LogEnable",
|
||||
"LogLevel": "LogLevel",
|
||||
"RedundantSwitchType": "RedundantSwitchType",
|
||||
"RedundantScanIntervalTime": "RedundantScanIntervalTime",
|
||||
"RedundantScript": "RedundantScript",
|
||||
|
||||
"Enable": "Enable",
|
||||
|
||||
"RedundantEnable": "RedundantEnable",
|
||||
"RedundantDeviceId": "RedundantDevice",
|
||||
|
||||
"Remark1": "Remark1",
|
||||
"Remark2": "Remark2",
|
||||
"Remark3": "Remark3",
|
||||
"Remark4": "Remark4",
|
||||
"Remark5": "Remark5",
|
||||
|
||||
|
||||
"RedundantDeviceNotNull": "When enabling redundancy, you must select a redundant device",
|
||||
"SaveDevice": "Add/Modify Device",
|
||||
"CopyDevice": "Copy Device",
|
||||
"DeleteDevice": "Delete Device",
|
||||
"ClearDevice": "Clear Device",
|
||||
"ExportDevice": "Export Device",
|
||||
"ImportDevice": "Import Device",
|
||||
"ImportNullError": "Unable to recognize",
|
||||
"RedundantDeviceError": "Redundant device error",
|
||||
"ChannelError": "Channel error",
|
||||
"NotNull": "{0} does not exist",
|
||||
"DeviceNotNull": "Device name does not exist",
|
||||
"NameDump": "Duplicate device name {0}",
|
||||
"PluginName.Required": "{0} cannot be empty"
|
||||
|
||||
|
||||
|
||||
"DeviceStatus": "DeviceStatus",
|
||||
|
||||
"PluginNotNull": "Plugin name does not exist"
|
||||
|
||||
},
|
||||
|
||||
@@ -94,60 +124,11 @@
|
||||
"Value": "Value",
|
||||
"AlarmEnable": "AlarmEnable",
|
||||
|
||||
"Name": "Name",
|
||||
"Description": "Description",
|
||||
"Group": "Group",
|
||||
"CollectGroup": "CollectGroup",
|
||||
"DeviceId": "CollectionDevice",
|
||||
"DeviceId.MinValue": "{0} cannot be empty",
|
||||
"DeviceId.Required": "{0} cannot be empty",
|
||||
"IntervalTime": "IntervalTime",
|
||||
"IntervalTime.MinValue": "{0} value is too small",
|
||||
"Enable": "Enable",
|
||||
"ProtectType": "ProtectType",
|
||||
"DataType": "DataType",
|
||||
"ReadExpressions": "ReadExpressions",
|
||||
"WriteExpressions": "WriteExpressions",
|
||||
"RpcWriteEnable": "RpcWriteEnable",
|
||||
"SaveValue": "SaveValue",
|
||||
"DynamicVariable": "DynamicVariable",
|
||||
"ArrayLength": "ArrayLength",
|
||||
|
||||
"AlarmDelay": "AlarmDelay",
|
||||
"BoolOpenAlarmEnable": "BoolOpenAlarmEnable",
|
||||
"BoolOpenRestrainExpressions": "BoolOpenRestrainExpressions",
|
||||
"BoolOpenAlarmText": "BoolOpenAlarmText",
|
||||
"BoolCloseAlarmEnable": "BoolCloseAlarmEnable",
|
||||
"BoolCloseRestrainExpressions": "BoolCloseRestrainExpressions",
|
||||
"BoolCloseAlarmText": "BoolCloseAlarmText",
|
||||
"HAlarmEnable": "HAlarmEnable",
|
||||
"HRestrainExpressions": "HRestrainExpressions",
|
||||
"HAlarmText": "HAlarmText",
|
||||
"HAlarmCode": "HAlarmCode",
|
||||
"HHAlarmEnable": "HHAlarmEnable",
|
||||
"HHRestrainExpressions": "HHRestrainExpressions",
|
||||
"HHAlarmText": "HHAlarmText",
|
||||
"HHAlarmCode": "HHAlarmCode",
|
||||
"LAlarmEnable": "LAlarmEnable",
|
||||
"LRestrainExpressions": "LRestrainExpressions",
|
||||
"LAlarmText": "LAlarmText",
|
||||
"LAlarmCode": "LAlarmCode",
|
||||
"LLAlarmEnable": "LLAlarmEnable",
|
||||
"LLRestrainExpressions": "LLRestrainExpressions",
|
||||
"LLAlarmText": "LLAlarmText",
|
||||
"LLAlarmCode": "LLAlarmCode",
|
||||
"CustomAlarmEnable": "CustomAlarmEnable",
|
||||
"CustomRestrainExpressions": "CustomRestrainExpressions",
|
||||
"CustomAlarmText": "CustomAlarmText",
|
||||
"CustomAlarmCode": "CustomAlarmCode",
|
||||
"Unit": "Unit",
|
||||
"RegisterAddress": "RegisterAddress",
|
||||
"OtherMethod": "OtherMethod",
|
||||
"Remark1": "Remark1",
|
||||
"Remark2": "Remark2",
|
||||
"Remark3": "Remark3",
|
||||
"Remark4": "Remark4",
|
||||
"Remark5": "Remark5",
|
||||
"AlarmCode": "AlarmCode",
|
||||
"RecoveryCode": "RecoveryCode",
|
||||
"AlarmLimit": "AlarmLimit",
|
||||
@@ -171,10 +152,7 @@
|
||||
"Name": "Name",
|
||||
"Description": "Description",
|
||||
"DeviceId": "CollectionDevice",
|
||||
"DeviceId.MinValue": "{0} cannot be empty",
|
||||
"DeviceId.Required": "{0} cannot be empty",
|
||||
"IntervalTime": "IntervalTime",
|
||||
"IntervalTime.MinValue": "{0} value is too small",
|
||||
"Enable": "Enable",
|
||||
"ProtectType": "ProtectType",
|
||||
"DataType": "DataType",
|
||||
@@ -349,51 +327,21 @@
|
||||
"NameDump": "Duplicate device name {0}"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.ChannelRuntime": {
|
||||
"Name": "Name",
|
||||
"Name.Required": "{0} cannot be empty",
|
||||
"ChannelType": "ChannelType",
|
||||
"PluginName": "PluginName",
|
||||
"PluginName.Required": "{0} cannot be empty",
|
||||
"LogLevel": "LogLevel",
|
||||
|
||||
"Enable": "Enable",
|
||||
"LogEnable": "LogEnable",
|
||||
"RemoteUrl": "RemoteUrl",
|
||||
"BindUrl": "BindUrl",
|
||||
"PortName": "PortName",
|
||||
"BaudRate": "BaudRate",
|
||||
"DataBits": "DataBits",
|
||||
"Parity": "Parity",
|
||||
"StopBits": "StopBits",
|
||||
"DtrEnable": "DtrEnable",
|
||||
"RtsEnable": "RtsEnable",
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"MaxConcurrentCount": "MaxConcurrentCount",
|
||||
"PluginType": "PluginType",
|
||||
"DeviceRuntimeCount": "DeviceRuntimeCount",
|
||||
"MaxConcurrentCount": "MaxConcurrentCount"
|
||||
|
||||
|
||||
"MaxClientCount": "MaxClientCount",
|
||||
"CheckClearTime": "CheckClearTime",
|
||||
"Heartbeat": "Heartbeat",
|
||||
"HeartbeatTime": "HeartbeatTime",
|
||||
"DtuId": "DtuId",
|
||||
"DtuSeviceType": "DtuSeviceType",
|
||||
|
||||
"SaveChannel": "Add/Modify Channel",
|
||||
"CopyChannel": "Copy Channel",
|
||||
"DeleteChannel": "Delete Channel",
|
||||
"ClearChannel": "Clear Channel",
|
||||
"ExportChannel": "Export Channel",
|
||||
"ImportChannel": "Import Channel",
|
||||
"ImportNullError": "Unable to recognize",
|
||||
"NotOther": "Not supporting other channel types",
|
||||
"Connect": "Connect",
|
||||
"Confim": "Confim",
|
||||
"Disconnect": "Disconnect",
|
||||
"Channel": "Channel",
|
||||
"NameDump": "Duplicate channel name {0}"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.Channel": {
|
||||
"SortCode": "SortCode",
|
||||
"CreateTime": "CreateTime",
|
||||
"CreateUser": "CreateUser",
|
||||
"UpdateTime": "UpdateTime",
|
||||
"UpdateUser": "UpdateUser",
|
||||
|
||||
"Name": "Name",
|
||||
"Name.Required": "{0} cannot be empty",
|
||||
"ChannelType": "ChannelType",
|
||||
|
||||
@@ -1,4 +1,70 @@
|
||||
{
|
||||
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPackPropertyBase": {
|
||||
"DtuId": "Dtu注册包(UTF8)"
|
||||
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPropertyBase": {
|
||||
"DtuId": "Dtu注册包(UTF8)"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationPackPropertyBase": {
|
||||
|
||||
"MaxPack": "最大打包长度"
|
||||
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationPropertyBase": {
|
||||
"DataFormat": "解析规则",
|
||||
"IsStringReverseByteWord": "字符串反转",
|
||||
"Timeout": "读写超时时间",
|
||||
"SendDelayTime": "发送延时"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectPropertyRetryBase": {
|
||||
"ReIntervalTime": "离线恢复时间",
|
||||
"RetryCount": "失败重试次数"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectPropertyBase": {
|
||||
"ReIntervalTime": "离线恢复时间",
|
||||
"RetryCount": "失败重试次数",
|
||||
"ConcurrentCount": "最大并发数量"
|
||||
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.BusinessPropertyWithCacheIntervalScript": {
|
||||
|
||||
"DetailLog": "详细日志",
|
||||
"JsonFormattingIndented": "Json缩进格式化",
|
||||
|
||||
"BigTextScriptDeviceModel": "设备上传脚本",
|
||||
"BigTextScriptVariableModel": "变量上传脚本",
|
||||
"BigTextScriptAlarmModel": "报警上传脚本",
|
||||
|
||||
"IsDeviceList": "设备状态列表上传",
|
||||
"IsVariableList": "变量列表上传",
|
||||
"IsAlarmList": "报警列表上传",
|
||||
|
||||
"DeviceTopic": "设备主题",
|
||||
"VariableTopic": "变量主题",
|
||||
"AlarmTopic": "报警主题"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.BusinessPropertyWithCacheInterval": {
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.BusinessPropertyWithCache": {
|
||||
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存",
|
||||
|
||||
"GroupUpdate": "分组上传",
|
||||
"OnlineFilter": "过滤离线变量"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.BusinessUpdateEnum": {
|
||||
"Change": "变化",
|
||||
"Interval": "定时",
|
||||
@@ -29,50 +95,16 @@
|
||||
"ActiveTime": "活跃时间",
|
||||
"DeviceVariableCount": "变量数量",
|
||||
"LastErrorMessage": "离线原因",
|
||||
|
||||
"Name": "名称",
|
||||
"DeviceStatus": "设备状态",
|
||||
"RedundantType": "冗余状态",
|
||||
"PluginName": "插件名称",
|
||||
"Name.Required": " {0} 不可为空",
|
||||
"Description": "描述",
|
||||
"ChannelId": "通道",
|
||||
"ChannelName": "通道",
|
||||
"ChannelId.MinValue": " {0} 不可为空",
|
||||
"ChannelId.Required": " {0} 不可为空",
|
||||
"IntervalTime": "默认执行间隔",
|
||||
"IntervalTime.MinValue": " {0} 值太小",
|
||||
"PluginName": "插件名称",
|
||||
"PluginName.Required": "{0} 插件名称不可为空",
|
||||
"PluginName.Required": "{0} 插件名称不可为空"
|
||||
|
||||
"Enable": "设备使能",
|
||||
"LogEnable": "启用调试日志",
|
||||
"LogLevel": "日志等级",
|
||||
"RedundantEnable": "启用冗余",
|
||||
"RedundantDeviceId": "冗余设备",
|
||||
"RedundantSwitchType": "冗余操作模式",
|
||||
"RedundantScanIntervalTime": "冗余检测时间",
|
||||
"RedundantScript": "冗余检测脚本",
|
||||
"Remark1": "备用1",
|
||||
"Remark2": "备用2",
|
||||
"Remark3": "备用3",
|
||||
"Remark4": "备用4",
|
||||
"Remark5": "备用5",
|
||||
|
||||
"RedundantDeviceNotNull": "启用冗余时,必须选择备用设备",
|
||||
|
||||
"SaveDevice": "添加/修改设备",
|
||||
"CopyDevice": "复制设备",
|
||||
"DeleteDevice": "删除设备",
|
||||
"ClearDevice": "清空设备",
|
||||
"ExportDevice": "导出设备",
|
||||
"ImportDevice": "导入设备",
|
||||
|
||||
"DeviceStatus": "设备状态",
|
||||
|
||||
"ImportNullError": "无法识别",
|
||||
"RedundantDeviceError": "冗余设备错误",
|
||||
"ChannelError": "通道错误",
|
||||
"NotNull": " {0} 不存在",
|
||||
"DeviceNotNull": "设备名称不存在",
|
||||
"PluginNotNull": "插件不存在"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.VariableRuntime": {
|
||||
"ChangeTime": "变化时间",
|
||||
@@ -85,72 +117,14 @@
|
||||
"Value": "实时值",
|
||||
"RuntimeType": "动态类型",
|
||||
"AlarmEnable": "报警使能",
|
||||
|
||||
"Name": "名称",
|
||||
"SortCode": "排序",
|
||||
"Name.Required": " {0} 不可为空",
|
||||
"Description": "描述",
|
||||
"Group": "业务组",
|
||||
"CollectGroup": "采集组",
|
||||
"DeviceId": "采集设备",
|
||||
"DeviceId.MinValue": " {0} 不可为空",
|
||||
"DeviceId.Required": " {0} 不可为空",
|
||||
"IntervalTime": "执行间隔",
|
||||
"IntervalTime.MinValue": " {0} 值太小",
|
||||
|
||||
"ArrayLength": "数组长度",
|
||||
"Enable": "变量使能",
|
||||
"ProtectType": "读写权限",
|
||||
"DataType": "数据类型",
|
||||
"ReadExpressions": "读取表达式",
|
||||
"WriteExpressions": "写入表达式",
|
||||
"RpcWriteEnable": "远程写入",
|
||||
"SaveValue": "保存初始值",
|
||||
"DynamicVariable": "动态变量",
|
||||
|
||||
"AlarmDelay": "报警延时",
|
||||
"BoolOpenAlarmEnable": "布尔开报警使能",
|
||||
"BoolOpenRestrainExpressions": "布尔开报警约束",
|
||||
"BoolOpenAlarmText": "布尔开报警文本",
|
||||
|
||||
"BoolCloseAlarmEnable": "布尔关报警使能",
|
||||
"BoolCloseRestrainExpressions": "布尔关报警约束",
|
||||
"BoolCloseAlarmText": "布尔关报警文本",
|
||||
|
||||
"HAlarmEnable": "高报使能",
|
||||
"HRestrainExpressions": "高报约束",
|
||||
"HAlarmText": "高报文本",
|
||||
"HAlarmCode": "高限值",
|
||||
|
||||
"HHAlarmEnable": "高高报使能",
|
||||
"HHRestrainExpressions": "高高报约束",
|
||||
"HHAlarmText": "高高报文本",
|
||||
"HHAlarmCode": "高高限值",
|
||||
|
||||
"LAlarmEnable": "低报使能",
|
||||
"LRestrainExpressions": "低报约束",
|
||||
"LAlarmText": "低报文本",
|
||||
"LAlarmCode": "低限值",
|
||||
|
||||
"LLAlarmEnable": "低低报使能",
|
||||
"LLRestrainExpressions": "低低报约束",
|
||||
"LLAlarmText": "低低报文本",
|
||||
"LLAlarmCode": "低低限值",
|
||||
|
||||
"CustomAlarmEnable": "自定义报警使能",
|
||||
"CustomRestrainExpressions": "自定义报警约束",
|
||||
"CustomAlarmText": "自定义报警文本",
|
||||
"CustomAlarmCode": "自定义报警限值",
|
||||
|
||||
"Unit": "单位",
|
||||
"RegisterAddress": "变量地址",
|
||||
"OtherMethod": "特殊方法",
|
||||
|
||||
"Remark1": "备用1",
|
||||
"Remark2": "备用2",
|
||||
"Remark3": "备用3",
|
||||
"Remark4": "备用4",
|
||||
"Remark5": "备用5",
|
||||
|
||||
"AlarmCode": "报警值",
|
||||
"RecoveryCode": "恢复值",
|
||||
"AlarmLimit": "报警限值",
|
||||
@@ -172,13 +146,9 @@
|
||||
"AlarmEnable": "报警使能",
|
||||
|
||||
"Name": "名称",
|
||||
"Name.Required": " {0} 不可为空",
|
||||
"Description": "描述",
|
||||
"DeviceId": "采集设备",
|
||||
"DeviceId.MinValue": " {0} 不可为空",
|
||||
"DeviceId.Required": " {0} 不可为空",
|
||||
"IntervalTime": "执行间隔",
|
||||
"IntervalTime.MinValue": " {0} 值太小",
|
||||
|
||||
"ArrayLength": "数组长度",
|
||||
"Enable": "变量使能",
|
||||
@@ -370,58 +340,20 @@
|
||||
"NameDump": "设备名称 {0} 重复"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.ChannelRuntime": {
|
||||
"Name": "名称",
|
||||
"Name.Required": " {0} 不可为空",
|
||||
"ChannelType": "通道类型",
|
||||
"Enable": "启用",
|
||||
"LogEnable": "启用调试日志",
|
||||
"LogLevel": "日志等级",
|
||||
"PluginName": "插件名称",
|
||||
"PluginName.Required": "{0} 插件名称不可为空",
|
||||
|
||||
"RemoteUrl": "远程url",
|
||||
"BindUrl": "本地url",
|
||||
|
||||
"PortName": "COM口",
|
||||
"BaudRate": "波特率",
|
||||
"DataBits": "数据位",
|
||||
"Parity": "校验位",
|
||||
"StopBits": "停止位",
|
||||
"DtrEnable": "Dtr",
|
||||
"RtsEnable": "Rts",
|
||||
"CacheTimeout": "接收缓存超时",
|
||||
"ConnectTimeout": "连接超时",
|
||||
"MaxConcurrentCount": "最大并发数",
|
||||
|
||||
|
||||
"MaxClientCount": "最大连接数",
|
||||
"CheckClearTime": "客户端连接滑动过期时间",
|
||||
"Heartbeat": "心跳内容(utf8)",
|
||||
"HeartbeatTime": "心跳间隔",
|
||||
"DtuId": "Dtu终端注册包(utf-8)",
|
||||
"DtuSeviceType": "DTU服务类型",
|
||||
|
||||
|
||||
"SaveChannel": "添加/修改通道",
|
||||
"CopyChannel": "复制通道",
|
||||
"DeleteChannel": "删除通道",
|
||||
"ClearChannel": "清空通道",
|
||||
"ExportChannel": "导出通道",
|
||||
"ImportChannel": "导入通道",
|
||||
|
||||
"ImportNullError": "无法识别",
|
||||
|
||||
"NotOther": "不支持其他通道类型",
|
||||
"Connect": "连接",
|
||||
"Confim": "创建",
|
||||
"Disconnect": "断开",
|
||||
"Channel": "通道",
|
||||
"NameDump": "通道名称 {0} 重复",
|
||||
|
||||
"DeviceRuntimeCounts": "设备数量"
|
||||
"PluginType": "插件类型",
|
||||
"MaxConcurrentCount": "最大并发数量",
|
||||
"DeviceRuntimeCount": "设备数量"
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.Channel": {
|
||||
"SortCode": "排序",
|
||||
"CreateTime": "创建时间",
|
||||
"CreateUser": "创建人",
|
||||
"UpdateTime": "更新时间",
|
||||
"UpdateUser": "更新人",
|
||||
|
||||
"Name": "名称",
|
||||
"Name.Required": " {0} 不可为空",
|
||||
"ChannelType": "通道类型",
|
||||
|
||||
@@ -103,7 +103,7 @@ public class ChannelRuntime : Channel, IChannelOptions, IDisposable
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public int? DeviceRuntimeCounts => DeviceRuntimes?.Count;
|
||||
public int? DeviceRuntimeCount => DeviceRuntimes?.Count;
|
||||
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
|
||||
@@ -14,6 +14,8 @@ using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using SqlSugar;
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
@@ -28,7 +30,7 @@ public class Startup : AppStartup
|
||||
services.AddConfigurableOptions<RpcLogOptions>();
|
||||
|
||||
//底层多语言配置
|
||||
//Foundation.LocalizerUtil.SetLocalizerFactory((a) => App.CreateLocalizerByType(a));
|
||||
Foundation.LocalizerUtil.SetLocalizerFactory((a) => App.CreateLocalizerByType(a));
|
||||
|
||||
TypeAdapterConfig.GlobalSettings.Scan(App.Assemblies.ToArray());
|
||||
// 配置默认全局映射(支持覆盖)
|
||||
@@ -93,12 +95,11 @@ public class Startup : AppStartup
|
||||
using var db = DbContext.GetDB<Variable>();
|
||||
if (db.DbMaintenance.IsAnyIndex("unique_variable_name"))
|
||||
{
|
||||
var tables = db.DbMaintenance.DropIndex("unique_variable_name");
|
||||
DropIndex(db, "unique_variable_name", "variable");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
|
||||
var fullName = Assembly.GetExecutingAssembly().FullName;//获取程序集全名
|
||||
CodeFirstUtils.CodeFirst(fullName!);//CodeFirst
|
||||
|
||||
@@ -136,4 +137,34 @@ public class Startup : AppStartup
|
||||
serviceProvider.GetService<ILoggerFactory>().CreateLogger(nameof(ThingsGateway)).LogInformation("ThingsGateway is stopping...");
|
||||
});
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除指定表上的索引(自动根据数据库类型生成正确的 DROP INDEX SQL)
|
||||
/// </summary>
|
||||
/// <param name="db">数据库连接</param>
|
||||
/// <param name="indexName">索引名</param>
|
||||
/// <param name="tableName">表名(部分数据库需要)</param>
|
||||
private static void DropIndex(SqlSugarClient db, string indexName, string tableName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(indexName))
|
||||
throw new ArgumentNullException(nameof(indexName));
|
||||
|
||||
string dropIndexSql;
|
||||
|
||||
switch (db.CurrentConnectionConfig.DbType)
|
||||
{
|
||||
case SqlSugar.DbType.MySql:
|
||||
case SqlSugar.DbType.SqlServer:
|
||||
dropIndexSql = $"DROP INDEX {indexName} ON {tableName};";
|
||||
break;
|
||||
|
||||
default:
|
||||
dropIndexSql = $"DROP INDEX {indexName};";
|
||||
break;
|
||||
}
|
||||
db.Ado.ExecuteCommand(dropIndexSql);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.0" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.1" />
|
||||
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.1" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.2" />
|
||||
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.2" />
|
||||
<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
</EditorItem>
|
||||
|
||||
|
||||
<EditorItem Field=@context.DeviceRuntimeCounts FieldExpression=@(()=> context.DeviceRuntimeCounts ) />
|
||||
<EditorItem Field=@context.DeviceRuntimeCount FieldExpression=@(()=> context.DeviceRuntimeCount ) />
|
||||
|
||||
</FieldItems>
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ThingsGateway.Gateway.Application;
|
||||
using ThingsGateway.NewLife.Json.Extension;
|
||||
|
||||
|
||||
@@ -19,11 +19,12 @@ namespace ThingsGateway.Management;
|
||||
[Route("openApi/autoUpdate")]
|
||||
[RolePermission]
|
||||
[LoggingMonitor]
|
||||
[ApiController]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class AutoUpdateControler : ControllerBase
|
||||
public class AutoUpdateController : ControllerBase
|
||||
{
|
||||
private IUpdateZipFileHostedService _updateZipFileService;
|
||||
public AutoUpdateControler(IUpdateZipFileHostedService updateZipFileService)
|
||||
public AutoUpdateController(IUpdateZipFileHostedService updateZipFileService)
|
||||
{
|
||||
_updateZipFileService = updateZipFileService;
|
||||
}
|
||||
@@ -14,8 +14,8 @@
|
||||
"Password": "Password"
|
||||
},
|
||||
|
||||
"ThingsGateway.Management.AutoUpdateControler": {
|
||||
"AutoUpdateControler": "AutoUpdate",
|
||||
"ThingsGateway.Management.AutoUpdateController": {
|
||||
"AutoUpdateController": "AutoUpdate",
|
||||
"Update": "Update"
|
||||
},
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
"Unregister": "取消注册",
|
||||
"Password": "注册码"
|
||||
},
|
||||
"ThingsGateway.Management.AutoUpdateControler": {
|
||||
"AutoUpdateControler": "程序更新",
|
||||
"ThingsGateway.Management.AutoUpdateController": {
|
||||
"AutoUpdateController": "程序更新",
|
||||
"Update": "更新"
|
||||
},
|
||||
"ThingsGateway.Upgrade.UpdateZipFile": {
|
||||
|
||||
@@ -55,7 +55,7 @@ internal sealed class RedundancyHostedService : BackgroundService, IRedundancyHo
|
||||
public string LogPath { get; }
|
||||
private TcpDmtpClient TcpDmtpClient;
|
||||
private TcpDmtpService TcpDmtpService;
|
||||
private TcpDmtpClient GetTcpDmtpClient(RedundancyOptions redundancy)
|
||||
private async Task<TcpDmtpClient> GetTcpDmtpClient(RedundancyOptions redundancy)
|
||||
{
|
||||
_log = new LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Trace };
|
||||
_log?.AddLogger(new EasyLogger(Log_Out) { LogLevel = TouchSocket.Core.LogLevel.Trace });
|
||||
@@ -81,11 +81,11 @@ internal sealed class RedundancyHostedService : BackgroundService, IRedundancyHo
|
||||
.SetMaxFailCount(redundancy.MaxErrorCount);
|
||||
});
|
||||
|
||||
tcpDmtpClient.Setup(config);
|
||||
await tcpDmtpClient.SetupAsync(config).ConfigureAwait(false);
|
||||
return tcpDmtpClient;
|
||||
}
|
||||
|
||||
private TcpDmtpService GetTcpDmtpService(RedundancyOptions redundancy)
|
||||
private async Task<TcpDmtpService> GetTcpDmtpService(RedundancyOptions redundancy)
|
||||
{
|
||||
_log = new LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Trace };
|
||||
_log?.AddLogger(new EasyLogger(Log_Out) { LogLevel = TouchSocket.Core.LogLevel.Trace });
|
||||
@@ -111,7 +111,7 @@ internal sealed class RedundancyHostedService : BackgroundService, IRedundancyHo
|
||||
.SetMaxFailCount(redundancy.MaxErrorCount);
|
||||
});
|
||||
|
||||
tcpDmtpService.Setup(config);
|
||||
await tcpDmtpService.SetupAsync(config).ConfigureAwait(false);
|
||||
return tcpDmtpService;
|
||||
}
|
||||
|
||||
@@ -325,13 +325,13 @@ internal sealed class RedundancyHostedService : BackgroundService, IRedundancyHo
|
||||
{
|
||||
if (RedundancyOptions.IsMaster)
|
||||
{
|
||||
TcpDmtpService = GetTcpDmtpService(RedundancyOptions);
|
||||
TcpDmtpService = await GetTcpDmtpService(RedundancyOptions).ConfigureAwait(false);
|
||||
await TcpDmtpService.StartAsync().ConfigureAwait(false);//启动
|
||||
await ActiveAsync().ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
TcpDmtpClient = GetTcpDmtpClient(RedundancyOptions);
|
||||
TcpDmtpClient = await GetTcpDmtpClient(RedundancyOptions).ConfigureAwait(false);
|
||||
await StandbyAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,8 @@
|
||||
"FEHead": "FEHead",
|
||||
"OperCode": "OperCode",
|
||||
"Password": "Password",
|
||||
"Station": "Station",
|
||||
"DtuId": "DtuId",
|
||||
"CheckClearTime": "CheckClearTime",
|
||||
"Heartbeat": "Heartbeat",
|
||||
"Station": "Station"
|
||||
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"DataFormat": "DataFormat",
|
||||
"Timeout": "Timeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"IsStringReverseByteWord": "IsStringReverseByteWord"
|
||||
},
|
||||
|
||||
"ThingsGateway.Foundation.Dlt645.DltResource": {
|
||||
|
||||
@@ -3,18 +3,8 @@
|
||||
"FEHead": "前导符报文头",
|
||||
"OperCode": "操作员代码",
|
||||
"Password": "写入密码",
|
||||
"Station": "通讯地址",
|
||||
"DtuId": "Dtu注册包(UTF8)",
|
||||
"CheckClearTime": "连接滑动过期时间",
|
||||
"Heartbeat": "心跳检测(UTF8)",
|
||||
"HeartbeatTime": "心跳间隔时间",
|
||||
"Station": "通讯地址"
|
||||
|
||||
"CacheTimeout": "组包缓存时间",
|
||||
"SendDelayTime": "发送延时",
|
||||
"DataFormat": "解析规则",
|
||||
"Timeout": "读写超时",
|
||||
"ConnectTimeout": "连接超时",
|
||||
"IsStringReverseByteWord": "字符串反转"
|
||||
},
|
||||
|
||||
"ThingsGateway.Foundation.Dlt645.DltResource": {
|
||||
@@ -41,7 +31,6 @@
|
||||
"StationString": "特指站号",
|
||||
"Data": "起始地址",
|
||||
"Reverse": "字节反转"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,36 +10,14 @@
|
||||
|
||||
"ThingsGateway.Foundation.Modbus.ModbusMaster": {
|
||||
"ModbusType": "ModbusType",
|
||||
"Station": "Station",
|
||||
"DtuId": "DtuId",
|
||||
"CheckClearTime": "CheckClearTime",
|
||||
"Heartbeat": "Heartbeat",
|
||||
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"DataFormat": "DataFormat",
|
||||
"Timeout": "Timeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"IsStringReverseByteWord": "IsStringReverseByteWord"
|
||||
"Station": "Station"
|
||||
},
|
||||
"ThingsGateway.Foundation.Modbus.ModbusSlave": {
|
||||
"ModbusType": "ModbusType",
|
||||
"Station": "Station",
|
||||
"CheckClearTime": "CheckClearTime",
|
||||
"MulStation": "MulStation",
|
||||
"IsWriteMemory": "IsWriteMemory",
|
||||
"MaxClientCount": "MaxClientCount",
|
||||
|
||||
"DtuId": "DtuId",
|
||||
"HeartbeatTime": "HeartbeatTime",
|
||||
"Heartbeat": "Heartbeat",
|
||||
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"DataFormat": "DataFormat",
|
||||
"Timeout": "Timeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"IsStringReverseByteWord": "IsStringReverseByteWord"
|
||||
"IsWriteMemory": "IsWriteMemory"
|
||||
},
|
||||
|
||||
"ThingsGateway.Foundation.Modbus.ModbusResource": {
|
||||
|
||||
@@ -11,37 +11,16 @@
|
||||
|
||||
"ThingsGateway.Foundation.Modbus.ModbusMaster": {
|
||||
"ModbusType": "Modbus类型",
|
||||
"Station": "站号",
|
||||
"DtuId": "Dtu注册包(UTF8)",
|
||||
"CheckClearTime": "连接滑动过期时间",
|
||||
"Heartbeat": "心跳检测(UTF8)",
|
||||
"HeartbeatTime": "心跳间隔时间",
|
||||
|
||||
"CacheTimeout": "组包缓存时间",
|
||||
"SendDelayTime": "发送延时",
|
||||
"DataFormat": "解析规则",
|
||||
"Timeout": "读写超时",
|
||||
"ConnectTimeout": "连接超时",
|
||||
"IsStringReverseByteWord": "字符串反转"
|
||||
"Station": "站号"
|
||||
|
||||
},
|
||||
"ThingsGateway.Foundation.Modbus.ModbusSlave": {
|
||||
"ModbusType": "Modbus类型",
|
||||
"Station": "默认站号",
|
||||
"CheckClearTime": "连接滑动过期时间",
|
||||
"MulStation": "多站点",
|
||||
"IsWriteMemory": "立即写入内存",
|
||||
"MaxClientCount": "最大连接数量",
|
||||
"IsWriteMemory": "立即写入内存"
|
||||
|
||||
"DtuId": "Dtu注册包(UTF8)",
|
||||
"Heartbeat": "心跳检测(UTF8)",
|
||||
"HeartbeatTime": "心跳间隔时间",
|
||||
|
||||
"CacheTimeout": "组包缓存时间",
|
||||
"SendDelayTime": "发送延时",
|
||||
"DataFormat": "解析规则",
|
||||
"Timeout": "读写超时",
|
||||
"ConnectTimeout": "连接超时",
|
||||
"IsStringReverseByteWord": "字符串反转"
|
||||
},
|
||||
"ThingsGateway.Foundation.Modbus.ModbusResource": {
|
||||
"AddressDes": "线圈寄存器使用从 00001 开始的地址编号。\n离散输入寄存器使用从 10001 开始的地址编号。\n输入寄存器使用从 30001 开始的地址编号。\n保持寄存器使用从 40001 开始的地址编号。\n举例:40001=>保持寄存器第一个寄存器\n额外格式\n设备站号 ,比如40001;s=2; ,代表设备地址为2的保持寄存器第一个寄存器\n写入功能码 ,比如40001;w=16; ,代表保持寄存器第一个寄存器,写入值时采用0x10功能码\nDTU模式(只在TCPService中起作用) ,比如40001;id=T123T; ,代表保持寄存器第一个寄存器,DTU注册包为T123T(UTF-8字符串)",
|
||||
|
||||
@@ -10,14 +10,7 @@
|
||||
"SiemensS7Type": "SiemensS7Type",
|
||||
"LocalTSAP": "LocalTSAP",
|
||||
"Rack": "Rack",
|
||||
"Slot": "Slot",
|
||||
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"DataFormat": "DataFormat",
|
||||
"Timeout": "Timeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"IsStringReverseByteWord": "IsStringReverseByteWord"
|
||||
"Slot": "Slot"
|
||||
},
|
||||
|
||||
"ThingsGateway.Foundation.SiemensS7.SiemensS7Resource": {
|
||||
|
||||
@@ -10,14 +10,8 @@
|
||||
"SiemensS7Type": "S7类型",
|
||||
"LocalTSAP": "本地TSAP",
|
||||
"Rack": "机架号",
|
||||
"Slot": "槽号",
|
||||
"Slot": "槽号"
|
||||
|
||||
"CacheTimeout": "组包缓存时间",
|
||||
"SendDelayTime": "发送延时",
|
||||
"DataFormat": "解析规则",
|
||||
"Timeout": "读写超时",
|
||||
"ConnectTimeout": "连接超时",
|
||||
"IsStringReverseByteWord": "字符串反转"
|
||||
},
|
||||
|
||||
"ThingsGateway.Foundation.SiemensS7.SiemensS7Resource": {
|
||||
|
||||
@@ -398,7 +398,7 @@ public partial class SiemensS7Master : DeviceBase
|
||||
|
||||
try
|
||||
{
|
||||
var result2 = await GetResponsedDataAsync(new S7Send(ISO_CR), channel, Timeout).ConfigureAwait(false);
|
||||
var result2 = await SendThenReturnMessageBaseAsync(new S7Send(ISO_CR), channel).ConfigureAwait(false);
|
||||
if (!result2.IsSuccess)
|
||||
{
|
||||
Logger?.LogWarning(SiemensS7Resource.Localizer["HandshakeError1", channel.ToString(), result2]);
|
||||
@@ -415,7 +415,7 @@ public partial class SiemensS7Master : DeviceBase
|
||||
}
|
||||
try
|
||||
{
|
||||
var result2 = await GetResponsedDataAsync(new S7Send(S7_PN), channel, Timeout).ConfigureAwait(false);
|
||||
var result2 = await SendThenReturnMessageBaseAsync(new S7Send(S7_PN), channel).ConfigureAwait(false);
|
||||
if (!result2.IsSuccess)
|
||||
{
|
||||
Logger?.LogWarning(SiemensS7Resource.Localizer["HandshakeError2", channel.ToString(), result2]);
|
||||
|
||||
@@ -38,6 +38,4 @@ public class RealDBProducerProperty : BusinessPropertyWithCacheInterval
|
||||
public string? BigTextScriptHistoryTable { get; set; }
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public bool GroupUpdate { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -3,16 +3,9 @@
|
||||
"BigTextConnectStr": "ConnectString",
|
||||
"TableName": "TableName",
|
||||
"BigTextScriptHistoryTable": "DynamicScriptHistoryTable",
|
||||
"RealTableBusinessInterval": "RealTableBusinessInterval",
|
||||
"RealTableBusinessInterval": "RealTableBusinessInterval"
|
||||
|
||||
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
"GroupUpdate": "GroupUpdate"
|
||||
},
|
||||
"ThingsGateway.Plugin.QuestDB.QuestDBHistoryValue": {
|
||||
"Id": "Id",
|
||||
@@ -35,16 +28,8 @@
|
||||
"BigTextScriptHistoryTable": "DynamicScriptHistoryTable",
|
||||
"BigTextScriptRealTable": "DynamicScriptRealTable",
|
||||
"RealTableBusinessInterval": "RealTableBusinessInterval",
|
||||
"SqlDBSplitType": "SplitType",
|
||||
"SqlDBSplitType": "SplitType"
|
||||
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
"GroupUpdate": "GroupUpdate"
|
||||
},
|
||||
"ThingsGateway.Plugin.SqlDB.SQLHistoryValue": {
|
||||
"Id": "Id",
|
||||
@@ -81,15 +66,7 @@
|
||||
"ThingsGateway.Plugin.SqlHistoryAlarm.SQLHistoryAlarmProperty": {
|
||||
"DbType": "DbType",
|
||||
"BigTextConnectStr": "ConnectString",
|
||||
"TableName": "TableName",
|
||||
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable"
|
||||
"TableName": "TableName"
|
||||
},
|
||||
|
||||
"ThingsGateway.Plugin.SqlHistoryAlarm.HistoryAlarm": {
|
||||
|
||||
@@ -3,16 +3,8 @@
|
||||
"BigTextConnectStr": "连接字符串",
|
||||
"TableName": "表名称",
|
||||
"BigTextScriptHistoryTable": "历史表动态脚本",
|
||||
"RealTableBusinessInterval": "实时表定时上传间隔",
|
||||
"RealTableBusinessInterval": "实时表定时上传间隔"
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存",
|
||||
"GroupUpdate": "分组上传"
|
||||
},
|
||||
"ThingsGateway.Plugin.QuestDB.QuestDBHistoryValue": {
|
||||
"Id": "变量Id",
|
||||
@@ -35,15 +27,8 @@
|
||||
"BigTextScriptHistoryTable": "历史表动态脚本",
|
||||
"BigTextScriptRealTable": "实时表动态脚本",
|
||||
"RealTableBusinessInterval": "实时表定时上传间隔",
|
||||
"SqlDBSplitType": "分表模式",
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存",
|
||||
"GroupUpdate": "分组上传"
|
||||
"SqlDBSplitType": "分表模式"
|
||||
|
||||
},
|
||||
"ThingsGateway.Plugin.SqlDB.SQLHistoryValue": {
|
||||
"Id": "变量Id",
|
||||
@@ -80,15 +65,8 @@
|
||||
"ThingsGateway.Plugin.SqlHistoryAlarm.SQLHistoryAlarmProperty": {
|
||||
"DbType": "数据库类型",
|
||||
"BigTextConnectStr": "链接字符串",
|
||||
"TableName": "表名称",
|
||||
"TableName": "表名称"
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存"
|
||||
},
|
||||
"ThingsGateway.Plugin.SqlHistoryAlarm.HistoryAlarm": {
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ using Mapster;
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
using ThingsGateway.Extension.Generic;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.Plugin.DB;
|
||||
|
||||
@@ -87,7 +88,7 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
|
||||
}
|
||||
private async ValueTask<OperResult> UpdateVarModel(IEnumerable<QuestDBHistoryValue> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await InserableAsync(item.ToList(), cancellationToken).ConfigureAwait(false);
|
||||
var result = await InserableAsync(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true).ToList(), cancellationToken).ConfigureAwait(false);
|
||||
if (success != result.IsSuccess)
|
||||
{
|
||||
if (!result.IsSuccess)
|
||||
|
||||
@@ -78,7 +78,4 @@ public class SqlDBProducerProperty : BusinessPropertyWithCacheInterval
|
||||
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
|
||||
public string? BigTextScriptHistoryTable { get; set; }
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public bool GroupUpdate { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Mapster;
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
using ThingsGateway.Extension.Generic;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.NewLife;
|
||||
using ThingsGateway.Plugin.DB;
|
||||
@@ -94,7 +95,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
|
||||
|
||||
private async ValueTask<OperResult> UpdateVarModel(IEnumerable<SQLHistoryValue> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await InserableAsync(item.ToList(), cancellationToken).ConfigureAwait(false);
|
||||
var result = await InserableAsync(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true).ToList(), cancellationToken).ConfigureAwait(false);
|
||||
if (success != result.IsSuccess)
|
||||
{
|
||||
if (!result.IsSuccess)
|
||||
|
||||
@@ -33,4 +33,5 @@ public class SqlHistoryAlarmProperty : BusinessPropertyWithCache
|
||||
[Required]
|
||||
public string TableName { get; set; } = "historyAlarm";
|
||||
|
||||
public override bool OnlineFilter { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using SqlSugar.TDengine;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Extension.Generic;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.Plugin.DB;
|
||||
|
||||
@@ -90,7 +91,7 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
|
||||
}
|
||||
private async ValueTask<OperResult> UpdateVarModel(IEnumerable<TDengineDBHistoryValue> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await InserableAsync(item.ToList(), cancellationToken).ConfigureAwait(false);
|
||||
var result = await InserableAsync(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true).ToList(), cancellationToken).ConfigureAwait(false);
|
||||
if (success != result.IsSuccess)
|
||||
{
|
||||
if (!result.IsSuccess)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.11" GeneratePathProperty="true">
|
||||
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.31" GeneratePathProperty="true">
|
||||
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ public class Dlt645_2007Master : CollectFoundationBase
|
||||
|
||||
ArgumentNullException.ThrowIfNull(channel);
|
||||
//载入配置
|
||||
_plc.DataFormat = _driverPropertys.DataFormat;
|
||||
_plc.DtuId = _driverPropertys.DtuId;
|
||||
_plc.SendDelayTime = _driverPropertys.SendDelayTime;
|
||||
_plc.Timeout = _driverPropertys.Timeout;
|
||||
|
||||
@@ -15,38 +15,14 @@ namespace ThingsGateway.Plugin.Dlt645;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class Dlt645_2007MasterProperty : CollectPropertyBase
|
||||
public class Dlt645_2007MasterProperty : CollectFoundationDtuPropertyBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 读写超时时间
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public ushort Timeout { get; set; } = 3000;
|
||||
|
||||
/// <summary>
|
||||
/// 帧前时间ms
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public int SendDelayTime { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 默认解析顺序
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public DataFormatEnum DataFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认地址
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public string Station { get; set; } = "111111111111";
|
||||
|
||||
/// <summary>
|
||||
/// 默认DtuId
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public string? DtuId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
|
||||
@@ -3,20 +3,6 @@
|
||||
"FEHead": "FEHead",
|
||||
"OperCode": "OperCode",
|
||||
"Password": "Password",
|
||||
"Station": "DefaultStation",
|
||||
"DtuId": "DefaultDtuId",
|
||||
|
||||
"Heartbeat": "Heartbeat",
|
||||
"DataFormat": "DataFormat",
|
||||
"IsStringReverseByteWord": "StringReverseByteWord",
|
||||
"CheckClearTime": "CheckClearTime",
|
||||
"Timeout": "Timeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"MaxPack": "MaxPack",
|
||||
"ReIntervalTime": "ReIntervalTime",
|
||||
"RetryCount": "RetryCount",
|
||||
"ConcurrentCount": "ConcurrentCount"
|
||||
"Station": "DefaultStation"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,21 +3,9 @@
|
||||
"FEHead": "前导符报文头",
|
||||
"OperCode": "操作员代码",
|
||||
"Password": "写入密码",
|
||||
"Station": "通讯地址",
|
||||
"DtuId": "Dtu注册包(UTF8)",
|
||||
"HeartbeatTime": "心跳间隔时间",
|
||||
"Station": "通讯地址"
|
||||
|
||||
|
||||
|
||||
"Heartbeat": "心跳验证(UTF8)",
|
||||
"DataFormat": "解析规则",
|
||||
"IsStringReverseByteWord": "字符串反转",
|
||||
"CheckClearTime": "客户端连接滑动过期时间",
|
||||
"Timeout": "读写超时时间",
|
||||
"ConnectTimeout": "连接超时时间",
|
||||
"SendDelayTime": "发送延时",
|
||||
"CacheTimeout": "组包缓存过期时间",
|
||||
"MaxPack": "最大打包长度",
|
||||
"ReIntervalTime": "离线恢复时间",
|
||||
"RetryCount": "失败重试次数",
|
||||
"ConcurrentCount": "最大并发数量"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,25 +2,11 @@
|
||||
"ThingsGateway.Plugin.Webhook.WebhookVariableProperty": {
|
||||
},
|
||||
"ThingsGateway.Plugin.Webhook.WebhookProperty": {
|
||||
"DetailLog": "DetailLog",
|
||||
"JsonFormattingIndented": "JsonFormattingIndented",
|
||||
"BigTextScriptDeviceModel": "BigTextScriptDeviceModel",
|
||||
"BigTextScriptVariableModel": "BigTextScriptVariableModel",
|
||||
"BigTextScriptAlarmModel": "BigTextScriptAlarmModel",
|
||||
"IsDeviceList": "IsDeviceList",
|
||||
"IsVariableList": "IsVariableList",
|
||||
"IsAlarmList": "IsAlarmList",
|
||||
|
||||
"DeviceTopic": "DeviceCallbackUrl",
|
||||
"VariableTopic": "VariableCallbackUrl",
|
||||
"AlarmTopic": "AlarmCallbackUrl",
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
"GroupUpdate": "GroupUpdate"
|
||||
"AlarmTopic": "AlarmCallbackUrl"
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,26 +4,9 @@
|
||||
|
||||
"ThingsGateway.Plugin.Webhook.WebhookProperty": {
|
||||
|
||||
"DetailLog": "详细日志",
|
||||
|
||||
"JsonFormattingIndented": "Json缩进格式化",
|
||||
"BigTextScriptDeviceModel": "设备上传脚本",
|
||||
"BigTextScriptVariableModel": "变量上传脚本",
|
||||
"BigTextScriptAlarmModel": "报警上传脚本",
|
||||
"IsDeviceList": "设备状态列表上传",
|
||||
"IsVariableList": "变量列表上传",
|
||||
"IsAlarmList": "报警列表上传",
|
||||
"DeviceTopic": "设备回调Url",
|
||||
"VariableTopic": "变量回调Url",
|
||||
"AlarmTopic": "报警回调Url",
|
||||
"AlarmTopic": "报警回调Url"
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存",
|
||||
"GroupUpdate": "分组上传"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,10 @@ using BootstrapBlazor.Components;
|
||||
|
||||
using Mapster;
|
||||
|
||||
using ThingsGateway.Extension.Generic;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.NewLife.Extension;
|
||||
|
||||
using TouchSocket.Core;
|
||||
|
||||
namespace ThingsGateway.Plugin.Webhook;
|
||||
|
||||
@@ -133,18 +135,18 @@ public partial class Webhook : BusinessBaseWithCacheIntervalScript<VariableBasic
|
||||
|
||||
private readonly HttpClient client = new HttpClient();
|
||||
|
||||
private async Task<OperResult> WebhookUpAsync(string topic, byte[] payLoad, int count, CancellationToken cancellationToken)
|
||||
private async Task<OperResult> WebhookUpAsync(TopicArray topicArray, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
// 设置请求内容
|
||||
//var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
using var content = new ByteArrayContent(payLoad);
|
||||
using var content = new ByteArrayContent(topicArray.Json);
|
||||
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
|
||||
|
||||
try
|
||||
{
|
||||
// 发送POST请求
|
||||
HttpResponseMessage response = await client.PostAsync(topic, content, cancellationToken).ConfigureAwait(false);
|
||||
HttpResponseMessage response = await client.PostAsync(topicArray.Topic, content, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// 检查响应状态
|
||||
if (response.IsSuccessStatusCode)
|
||||
@@ -152,12 +154,14 @@ public partial class Webhook : BusinessBaseWithCacheIntervalScript<VariableBasic
|
||||
if (_driverPropertys.DetailLog)
|
||||
{
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Trace)
|
||||
LogMessage.LogTrace(GetString(topic, payLoad, _memoryVarModelQueue.Count));
|
||||
LogMessage.LogTrace(GetDetailLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
else if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage.LogTrace($"Topic:{topic}{Environment.NewLine}Count:{count} {Environment.NewLine} VarModelQueue:{_memoryVarModelQueue.Count}");
|
||||
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
return new();
|
||||
}
|
||||
@@ -175,11 +179,11 @@ public partial class Webhook : BusinessBaseWithCacheIntervalScript<VariableBasic
|
||||
|
||||
#region private
|
||||
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicJsonList, int count, CancellationToken cancellationToken)
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicArrayList, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var topicJson in topicJsonList)
|
||||
foreach (var topicArray in topicArrayList)
|
||||
{
|
||||
var result = await WebhookUpAsync(topicJson.Topic, topicJson.Json, count, cancellationToken).ConfigureAwait(false);
|
||||
var result = await WebhookUpAsync(topicArray, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return result;
|
||||
@@ -203,21 +207,21 @@ public partial class Webhook : BusinessBaseWithCacheIntervalScript<VariableBasic
|
||||
|
||||
private ValueTask<OperResult> UpdateAlarmModel(IEnumerable<AlarmVariable> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetAlarmTopicArrays(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetAlarmTopicArrays(item);
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
private ValueTask<OperResult> UpdateDevModel(IEnumerable<DeviceBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var topicJsonList = GetDeviceTopicArray(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetDeviceTopicArray(item);
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
private ValueTask<OperResult> UpdateVarModel(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetVariableBasicDataTopicArray(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetVariableBasicDataTopicArray(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true));
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,13 +15,5 @@ namespace ThingsGateway.Plugin.Webhook;
|
||||
/// </summary>
|
||||
public class WebhookProperty : BusinessPropertyWithCacheIntervalScript
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否显示详细日志
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public bool DetailLog { get; set; } = true;
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public bool GroupUpdate { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Confluent.Kafka;
|
||||
|
||||
using Mapster;
|
||||
|
||||
using ThingsGateway.Extension.Generic;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
@@ -127,11 +128,11 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
|
||||
|
||||
#region private
|
||||
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicJsonList, int count, CancellationToken cancellationToken)
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicArrayList, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var topicJson in topicJsonList)
|
||||
foreach (var topicArray in topicArrayList)
|
||||
{
|
||||
var result = await KafKaUpAsync(topicJson.Topic, topicJson.Json, count, cancellationToken).ConfigureAwait(false);
|
||||
var result = await KafKaUpAsync(topicArray, cancellationToken).ConfigureAwait(false);
|
||||
if (success != result.IsSuccess)
|
||||
{
|
||||
if (!result.IsSuccess)
|
||||
@@ -150,20 +151,20 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
|
||||
|
||||
private async ValueTask<OperResult> UpdateAlarmModel(IEnumerable<AlarmVariable> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetAlarmTopicArrays(item);
|
||||
return await Update(topicJsonList, item.Count(), cancellationToken).ConfigureAwait(false);
|
||||
var topicArrayList = GetAlarmTopicArrays(item);
|
||||
return await Update(topicArrayList, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async ValueTask<OperResult> UpdateDevModel(IEnumerable<DeviceBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetDeviceTopicArray(item);
|
||||
return await Update(topicJsonList, item.Count(), cancellationToken).ConfigureAwait(false);
|
||||
var topicArrayList = GetDeviceTopicArray(item);
|
||||
return await Update(topicArrayList, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async ValueTask<OperResult> UpdateVarModel(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetVariableBasicDataTopicArray(item);
|
||||
return await Update(topicJsonList, item.Count(), cancellationToken).ConfigureAwait(false);
|
||||
var topicArrayList = GetVariableBasicDataTopicArray(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true));
|
||||
return await Update(topicArrayList, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion private
|
||||
@@ -203,13 +204,13 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
|
||||
/// <summary>
|
||||
/// kafka上传,返回上传结果
|
||||
/// </summary>
|
||||
public async ValueTask<OperResult> KafKaUpAsync(string topic, byte[] payLoad, int count, CancellationToken cancellationToken)
|
||||
public async ValueTask<OperResult> KafKaUpAsync(TopicArray topicArray, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
using CancellationTokenSource cancellationTokenSource = new(_driverPropertys.Timeout);
|
||||
using CancellationTokenSource stoppingToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, cancellationToken);
|
||||
var result = await _producer.ProduceAsync(topic, new Message<Null, byte[]> { Value = payLoad }, stoppingToken.Token).ConfigureAwait(false);
|
||||
var result = await _producer.ProduceAsync(topicArray.Topic, new Message<Null, byte[]> { Value = topicArray.Json }, stoppingToken.Token).ConfigureAwait(false);
|
||||
if (result.Status != PersistenceStatus.Persisted)
|
||||
{
|
||||
return new OperResult("Upload fail");
|
||||
@@ -219,12 +220,14 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
|
||||
if (_driverPropertys.DetailLog)
|
||||
{
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Trace)
|
||||
LogMessage.LogTrace(GetString(topic, payLoad, _memoryVarModelQueue.Count));
|
||||
LogMessage.LogTrace(GetDetailLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
else if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage.LogTrace($"Topic:{topic}{Environment.NewLine}Count:{count} {Environment.NewLine} VarModelQueue:{_memoryVarModelQueue.Count}");
|
||||
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
return OperResult.Success;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,6 @@ public class KafkaProducerProperty : BusinessPropertyWithCacheIntervalScript
|
||||
[DynamicProperty]
|
||||
public string BootStrapServers { get; set; } = "127.0.0.1:9092";
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示详细日志
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public bool DetailLog { get; set; } = true;
|
||||
/// <summary>
|
||||
/// 发布超时时间
|
||||
/// </summary>
|
||||
@@ -52,8 +47,4 @@ public class KafkaProducerProperty : BusinessPropertyWithCacheIntervalScript
|
||||
[DynamicProperty]
|
||||
public SaslMechanism SaslMechanism { get; set; } = SaslMechanism.Plain;
|
||||
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public bool GroupUpdate { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -1,30 +1,12 @@
|
||||
{
|
||||
"ThingsGateway.Plugin.Kafka.KafkaProducerProperty": {
|
||||
"BootStrapServers": "BootStrapServers",
|
||||
"DetailLog": "DetailLog",
|
||||
"Timeout": "Timeout",
|
||||
"SaslUsername": "SaslUsername",
|
||||
"SaslPassword": "SaslPassword",
|
||||
"SecurityProtocol": "SecurityProtocol",
|
||||
"SaslMechanism": "SaslMechanism",
|
||||
"SaslMechanism": "SaslMechanism"
|
||||
|
||||
"JsonFormattingIndented": "JsonFormattingIndented",
|
||||
"BigTextScriptDeviceModel": "BigTextScriptDeviceModel",
|
||||
"BigTextScriptVariableModel": "BigTextScriptVariableModel",
|
||||
"BigTextScriptAlarmModel": "BigTextScriptAlarmModel",
|
||||
"IsDeviceList": "IsDeviceList",
|
||||
"IsVariableList": "IsVariableList",
|
||||
"IsAlarmList": "IsAlarmList",
|
||||
"DeviceTopic": "DeviceTopic",
|
||||
"VariableTopic": "VariableTopic",
|
||||
"AlarmTopic": "AlarmTopic",
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
"GroupUpdate": "GroupUpdate"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,12 @@
|
||||
{
|
||||
"ThingsGateway.Plugin.Kafka.KafkaProducerProperty": {
|
||||
"BootStrapServers": "服务地址",
|
||||
"DetailLog": "详细日志",
|
||||
"Timeout": "发布超时时间",
|
||||
"SaslUsername": "用户名",
|
||||
"SaslPassword": "密码",
|
||||
"SecurityProtocol": "SecurityProtocol",
|
||||
"SaslMechanism": "SaslMechanism",
|
||||
"SaslMechanism": "SaslMechanism"
|
||||
|
||||
"JsonFormattingIndented": "Json缩进格式化",
|
||||
"BigTextScriptDeviceModel": "设备上传脚本",
|
||||
"BigTextScriptVariableModel": "变量上传脚本",
|
||||
"BigTextScriptAlarmModel": "报警上传脚本",
|
||||
|
||||
"IsDeviceList": "设备状态列表上传",
|
||||
"IsVariableList": "变量列表上传",
|
||||
"IsAlarmList": "报警列表上传",
|
||||
"DeviceTopic": "设备主题",
|
||||
"VariableTopic": "变量主题",
|
||||
"AlarmTopic": "报警主题",
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存",
|
||||
"GroupUpdate": "分组上传"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
{
|
||||
"ThingsGateway.Plugin.Modbus.ModbusMasterProperty": {
|
||||
"ModbusType": "ProtocolType",
|
||||
"Heartbeat": "Heartbeat",
|
||||
"Station": "DefaultStation",
|
||||
"DtuId": "DefaultDtuId",
|
||||
"DataFormat": "DataFormat",
|
||||
"IsStringReverseByteWord": "StringReverseByteWord",
|
||||
"CheckClearTime": "CheckClearTime",
|
||||
"Timeout": "Timeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"MaxPack": "MaxPack",
|
||||
"ReIntervalTime": "ReIntervalTime",
|
||||
"RetryCount": "RetryCount",
|
||||
"MaxConcurrentCount": "MaxConcurrentCount"
|
||||
"Station": "DefaultStation"
|
||||
|
||||
},
|
||||
"ThingsGateway.Plugin.Modbus.ModbusSlave": {
|
||||
"CanStartService": "Unable to Start Service",
|
||||
@@ -26,24 +14,11 @@
|
||||
"Station": "DefaultStation",
|
||||
"DataFormat": "DataFormat",
|
||||
"IsStringReverseByteWord": "IsStringReverseByteWord",
|
||||
"CheckClearTime": "CheckClearTime",
|
||||
"DeviceRpcEnable": "DeviceRpcEnable",
|
||||
"IsWriteMemory": "IsWriteMemory",
|
||||
"MulStation": "MultipleStations",
|
||||
"MaxClientCount": "MaxClientCount",
|
||||
"MulStation": "MultipleStations"
|
||||
|
||||
"DtuId": "DtuId",
|
||||
"HeartbeatTime": "HeartbeatTime",
|
||||
"Heartbeat": "Heartbeat",
|
||||
|
||||
"Timeout": "Timeout",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"SendDelayTime": "SendDelayTime",
|
||||
"CacheTimeout": "CacheTimeout",
|
||||
"MaxPack": "MaxPack",
|
||||
"ReIntervalTime": "ReIntervalTime",
|
||||
"RetryCount": "RetryCount",
|
||||
"MaxConcurrentCount": "MaxConcurrentCount"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Plugin.Modbus.ModbusSlaveVariableProperty": {
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
{
|
||||
"ThingsGateway.Plugin.Modbus.ModbusMasterProperty": {
|
||||
"ModbusType": "协议类型",
|
||||
"Heartbeat": "心跳检测(UTF8)",
|
||||
"Station": "默认站号",
|
||||
"DtuId": "Dtu注册包(UTF8)",
|
||||
"DataFormat": "解析规则",
|
||||
"IsStringReverseByteWord": "字符串反转",
|
||||
"CheckClearTime": "客户端连接滑动过期时间",
|
||||
"Timeout": "读写超时时间",
|
||||
"ConnectTimeout": "连接超时时间",
|
||||
"SendDelayTime": "发送延时",
|
||||
"CacheTimeout": "组包缓存过期时间",
|
||||
"MaxPack": "最大打包长度",
|
||||
"ReIntervalTime": "离线恢复时间",
|
||||
"RetryCount": "失败重试次数",
|
||||
"MaxConcurrentCount": "最大并发数量"
|
||||
"Station": "默认站号"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Plugin.Modbus.ModbusSlave": {
|
||||
@@ -27,24 +15,10 @@
|
||||
"Station": "默认站号",
|
||||
"DataFormat": "解析规则",
|
||||
"IsStringReverseByteWord": "字符串反转",
|
||||
"CheckClearTime": "客户端连接滑动过期时间",
|
||||
"DeviceRpcEnable": "允许写入",
|
||||
"IsWriteMemory": "立即写入内存",
|
||||
"MulStation": "多站点",
|
||||
"MaxClientCount": "最大连接数",
|
||||
"MulStation": "多站点"
|
||||
|
||||
"DtuId": "Dtu注册包(UTF8)",
|
||||
"HeartbeatTime": "心跳间隔时间",
|
||||
"Heartbeat": "心跳检测(UTF8)",
|
||||
|
||||
"Timeout": "读写超时时间",
|
||||
"ConnectTimeout": "连接超时时间",
|
||||
"SendDelayTime": "发送延时",
|
||||
"CacheTimeout": "组包缓存过期时间",
|
||||
"MaxPack": "最大打包长度",
|
||||
"ReIntervalTime": "离线恢复时间",
|
||||
"RetryCount": "失败重试次数",
|
||||
"MaxConcurrentCount": "最大并发数量"
|
||||
},
|
||||
|
||||
"ThingsGateway.Plugin.Modbus.ModbusSlaveVariableProperty": {
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace ThingsGateway.Plugin.Modbus;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusMasterProperty : CollectPropertyBase
|
||||
public class ModbusMasterProperty : CollectFoundationDtuPackPropertyBase
|
||||
{
|
||||
[DynamicProperty]
|
||||
public ModbusTypeEnum ModbusType { get; set; }
|
||||
@@ -28,38 +28,5 @@ public class ModbusMasterProperty : CollectPropertyBase
|
||||
[DynamicProperty]
|
||||
public byte Station { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 默认DtuId
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public string? DtuId { get; set; } = "DtuId";
|
||||
|
||||
/// <summary>
|
||||
/// 默认解析顺序
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public DataFormatEnum DataFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 读写超时时间
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public ushort Timeout { get; set; } = 3000;
|
||||
|
||||
/// <summary>
|
||||
/// 发送延时ms
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public int SendDelayTime { get; set; } = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 最大打包长度
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public ushort MaxPack { get; set; } = 100;
|
||||
|
||||
[DynamicProperty]
|
||||
public bool IsStringReverseByteWord { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ public class ModbusSlaveProperty : BusinessPropertyBase
|
||||
[DynamicProperty]
|
||||
public bool IsStringReverseByteWord { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 多站点
|
||||
/// </summary>
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
{
|
||||
"ThingsGateway.Plugin.Mqtt.MqttClientVariableProperty": {
|
||||
"VariableRpcEnable": "VariableRpcEnable",
|
||||
"Group": "Group"
|
||||
"VariableRpcEnable": "VariableRpcEnable"
|
||||
},
|
||||
"ThingsGateway.Plugin.Mqtt.MqttClientProperty": {
|
||||
"IP": "IP",
|
||||
"Port": "Port",
|
||||
"MqttQualityOfServiceLevel": "QoS",
|
||||
"MqttProtocolVersion": "MqttProtocolVersion",
|
||||
"DetailLog": "DetailLog",
|
||||
"TLS": "TLS",
|
||||
"CAFile_BrowserFile": "CAFile",
|
||||
"ClientCertificateFile_BrowserFile": "ClientCertificateFile",
|
||||
@@ -21,54 +20,20 @@
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"DeviceRpcEnable": "DeviceRpcEnable",
|
||||
"RpcWriteTopic": "RpcWriteTopic",
|
||||
"RpcQuestTopic": "RpcQuestTopic",
|
||||
"JsonFormattingIndented": "JsonFormattingIndented",
|
||||
"BigTextScriptDeviceModel": "BigTextScriptDeviceModel",
|
||||
"BigTextScriptVariableModel": "BigTextScriptVariableModel",
|
||||
"BigTextScriptAlarmModel": "BigTextScriptAlarmModel",
|
||||
"IsDeviceList": "IsDeviceList",
|
||||
"IsVariableList": "IsVariableList",
|
||||
"IsAlarmList": "IsAlarmList",
|
||||
"DeviceTopic": "DeviceTopic",
|
||||
"VariableTopic": "VariableTopic",
|
||||
"AlarmTopic": "AlarmTopic",
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
"GroupUpdate": "GroupUpdate"
|
||||
"RpcQuestTopic": "RpcQuestTopic"
|
||||
|
||||
|
||||
},
|
||||
"ThingsGateway.Plugin.Mqtt.MqttServerProperty": {
|
||||
"IP": "IP",
|
||||
"Port": "Port",
|
||||
"DetailLog": "DetailLog",
|
||||
"MqttQualityOfServiceLevel": "QoS",
|
||||
"WebSocketPort": "WebSocketPort",
|
||||
"StartWithId": "StartWithId",
|
||||
"AnonymousEnable": "AnonymousEnable",
|
||||
"DeviceRpcEnable": "DeviceRpcEnable",
|
||||
"RpcWriteTopic": "RpcWriteTopic",
|
||||
"JsonFormattingIndented": "JsonFormattingIndented",
|
||||
"BigTextScriptDeviceModel": "BigTextScriptDeviceModel",
|
||||
"BigTextScriptVariableModel": "BigTextScriptVariableModel",
|
||||
"BigTextScriptAlarmModel": "BigTextScriptAlarmModel",
|
||||
"IsDeviceList": "IsDeviceList",
|
||||
"IsVariableList": "IsVariableList",
|
||||
"IsAlarmList": "IsAlarmList",
|
||||
"DeviceTopic": "DeviceTopic",
|
||||
"VariableTopic": "VariableTopic",
|
||||
"AlarmTopic": "AlarmTopic",
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
"GroupUpdate": "GroupUpdate"
|
||||
"RpcWriteTopic": "RpcWriteTopic"
|
||||
|
||||
},
|
||||
|
||||
"ThingsGateway.Plugin.Mqtt.MqttCollectProperty": {
|
||||
@@ -85,27 +50,8 @@
|
||||
"UserName": "UserName",
|
||||
"Password": "Password",
|
||||
"ConnectId": "ConnectId",
|
||||
"ConnectTimeout": "ConnectTimeout",
|
||||
"DeviceRpcEnable": "DeviceRpcEnable",
|
||||
"RpcWriteTopic": "RpcWriteTopic",
|
||||
"RpcQuestTopic": "RpcQuestTopic",
|
||||
"JsonFormattingIndented": "JsonFormattingIndented",
|
||||
"BigTextScriptDeviceModel": "BigTextScriptDeviceModel",
|
||||
"BigTextScriptVariableModel": "BigTextScriptVariableModel",
|
||||
"BigTextScriptAlarmModel": "BigTextScriptAlarmModel",
|
||||
"IsDeviceList": "IsDeviceList",
|
||||
"IsVariableList": "IsVariableList",
|
||||
"IsAlarmList": "IsAlarmList",
|
||||
"DeviceTopic": "DeviceTopic",
|
||||
"VariableTopic": "VariableTopic",
|
||||
"AlarmTopic": "AlarmTopic",
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable"
|
||||
"ConnectTimeout": "ConnectTimeout"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
{
|
||||
"ThingsGateway.Plugin.Mqtt.MqttClientVariableProperty": {
|
||||
"VariableRpcEnable": "启用RPC",
|
||||
"Group": "分组名称"
|
||||
"VariableRpcEnable": "启用RPC"
|
||||
},
|
||||
|
||||
"ThingsGateway.Plugin.Mqtt.MqttClientProperty": {
|
||||
"IP": "IP",
|
||||
"Port": "端口",
|
||||
"DetailLog": "详细日志",
|
||||
"MqttQualityOfServiceLevel": "QoS",
|
||||
"MqttProtocolVersion": "协议版本",
|
||||
"TLS": "TLS",
|
||||
"CAFile_BrowserFile": "CA文件",
|
||||
"ClientCertificateFile_BrowserFile": "客户端证书",
|
||||
"ClientKeyFile_BrowserFile": "客户端key文件",
|
||||
|
||||
|
||||
"IsWebSocket": "Websocket",
|
||||
"WebSocketUrl": "WebSocketUrl",
|
||||
"UserName": "用户名",
|
||||
@@ -23,58 +21,20 @@
|
||||
"ConnectTimeout": "连接超时时间",
|
||||
"DeviceRpcEnable": "允许Rpc写入",
|
||||
"RpcWriteTopic": "Rpc写入主题",
|
||||
"RpcQuestTopic": "Rpc请求数据主题",
|
||||
"RpcQuestTopic": "Rpc请求数据主题"
|
||||
|
||||
"JsonFormattingIndented": "Json缩进格式化",
|
||||
"BigTextScriptDeviceModel": "设备上传脚本",
|
||||
"BigTextScriptVariableModel": "变量上传脚本",
|
||||
"BigTextScriptAlarmModel": "报警上传脚本",
|
||||
"IsDeviceList": "设备状态列表上传",
|
||||
"IsVariableList": "变量列表上传",
|
||||
"IsAlarmList": "报警列表上传",
|
||||
"DeviceTopic": "设备主题",
|
||||
"VariableTopic": "变量主题",
|
||||
"AlarmTopic": "报警主题",
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存",
|
||||
"GroupUpdate": "分组上传"
|
||||
},
|
||||
"ThingsGateway.Plugin.Mqtt.MqttServerProperty": {
|
||||
"IP": "IP",
|
||||
"Port": "端口",
|
||||
"DetailLog": "详细日志",
|
||||
"MqttQualityOfServiceLevel": "QoS",
|
||||
"WebSocketPort": "Websocket端口",
|
||||
"StartWithId": "允许连接的ID前缀",
|
||||
|
||||
"AnonymousEnable": "允许匿名登录",
|
||||
"DeviceRpcEnable": "允许Rpc写入",
|
||||
"RpcWriteTopic": "Rpc写入主题",
|
||||
"RpcWriteTopic": "Rpc写入主题"
|
||||
|
||||
"JsonFormattingIndented": "Json缩进格式化",
|
||||
"BigTextScriptDeviceModel": "设备上传脚本",
|
||||
"BigTextScriptVariableModel": "变量上传脚本",
|
||||
"BigTextScriptAlarmModel": "报警上传脚本",
|
||||
"IsDeviceList": "设备状态列表上传",
|
||||
"IsVariableList": "变量列表上传",
|
||||
"IsAlarmList": "报警列表上传",
|
||||
"DeviceTopic": "设备主题",
|
||||
"VariableTopic": "变量主题",
|
||||
"AlarmTopic": "报警主题",
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存",
|
||||
"GroupUpdate": "分组上传"
|
||||
},
|
||||
|
||||
"ThingsGateway.Plugin.Mqtt.MqttCollectProperty": {
|
||||
@@ -91,29 +51,10 @@
|
||||
"UserName": "用户名",
|
||||
"Password": "密码",
|
||||
"ConnectId": "连接ID",
|
||||
"ConnectTimeout": "连接超时时间",
|
||||
"DeviceRpcEnable": "允许Rpc写入",
|
||||
"RpcWriteTopic": "Rpc写入主题",
|
||||
"RpcQuestTopic": "Rpc请求数据主题",
|
||||
"ConnectTimeout": "连接超时时间"
|
||||
|
||||
|
||||
"JsonFormattingIndented": "Json缩进格式化",
|
||||
"BigTextScriptDeviceModel": "设备上传脚本",
|
||||
"BigTextScriptVariableModel": "变量上传脚本",
|
||||
"BigTextScriptAlarmModel": "报警上传脚本",
|
||||
"IsDeviceList": "设备状态列表上传",
|
||||
"IsVariableList": "变量列表上传",
|
||||
"IsAlarmList": "报警列表上传",
|
||||
"DeviceTopic": "设备主题",
|
||||
"VariableTopic": "变量主题",
|
||||
"AlarmTopic": "报警主题",
|
||||
|
||||
"BusinessUpdateEnum": "上传模式",
|
||||
"BusinessInterval": "定时上传间隔",
|
||||
"IsAllVariable": "选择全部变量",
|
||||
"QueueMaxCount": "内存队列最大数量",
|
||||
"CacheFileMaxLength": "缓存文件最大长度(mb)",
|
||||
"SplitSize": "上传每页条数",
|
||||
"CacheEnable": "启用缓存"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ using Newtonsoft.Json.Linq;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Extension.Generic;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
using ThingsGateway.NewLife;
|
||||
@@ -69,13 +70,13 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
{
|
||||
device = deviceData.Name,
|
||||
};
|
||||
var topicJson = new TopicArray()
|
||||
var topicArray = new TopicArray()
|
||||
{
|
||||
Topic = "v1/gateway/connect",
|
||||
Json = Serialize(json, _driverPropertys.JsonFormattingIndented)
|
||||
};
|
||||
|
||||
topicJsonTBList.Add(topicJson);
|
||||
topicJsonTBList.Add(topicArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -83,17 +84,17 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
{
|
||||
device = deviceData.Name,
|
||||
};
|
||||
var topicJson = new TopicArray()
|
||||
var topicArray = new TopicArray()
|
||||
{
|
||||
Topic = "v1/gateway/disconnect",
|
||||
Json = Serialize(json, _driverPropertys.JsonFormattingIndented)
|
||||
};
|
||||
|
||||
topicJsonTBList.Add(topicJson);
|
||||
topicJsonTBList.Add(topicArray);
|
||||
}
|
||||
|
||||
}
|
||||
var result = await Update(topicJsonTBList, 1, default).ConfigureAwait(false);
|
||||
var result = await Update(topicJsonTBList, default).ConfigureAwait(false);
|
||||
if (success != result.IsSuccess)
|
||||
{
|
||||
if (!result.IsSuccess)
|
||||
@@ -206,11 +207,11 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
|
||||
#region private
|
||||
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicJsonList, int count, CancellationToken cancellationToken)
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicArrayList, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var topicJson in topicJsonList)
|
||||
foreach (TopicArray topicArray in topicArrayList)
|
||||
{
|
||||
var result = await MqttUpAsync(topicJson.Topic, topicJson.Json, count, cancellationToken).ConfigureAwait(false);
|
||||
var result = await MqttUpAsync(topicArray, cancellationToken).ConfigureAwait(false);
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return result;
|
||||
if (success != result.IsSuccess)
|
||||
@@ -231,21 +232,21 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
|
||||
private ValueTask<OperResult> UpdateAlarmModel(IEnumerable<AlarmVariable> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetAlarmTopicArrays(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetAlarmTopicArrays(item);
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
private ValueTask<OperResult> UpdateDevModel(IEnumerable<DeviceBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var topicJsonList = GetDeviceTopicArray(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetDeviceTopicArray(item);
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
private ValueTask<OperResult> UpdateVarModel(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetVariableBasicDataTopicArray(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetVariableBasicDataTopicArray(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true));
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
#endregion private
|
||||
@@ -463,7 +464,7 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
/// <summary>
|
||||
/// 上传mqtt,返回上传结果
|
||||
/// </summary>
|
||||
public async ValueTask<OperResult> MqttUpAsync(string topic, byte[] payLoad, int count, CancellationToken cancellationToken = default)
|
||||
public async ValueTask<OperResult> MqttUpAsync(TopicArray topicArray, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -471,20 +472,22 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
if (isConnect.IsSuccess)
|
||||
{
|
||||
var variableMessage = new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topic).WithRetainFlag(true)
|
||||
.WithPayload(payLoad).Build();
|
||||
.WithTopic(topicArray.Topic).WithQualityOfServiceLevel(_driverPropertys.MqttQualityOfServiceLevel)
|
||||
.WithPayload(topicArray.Json).Build();
|
||||
var result = await _mqttClient.PublishAsync(variableMessage, cancellationToken).ConfigureAwait(false);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
if (_driverPropertys.DetailLog)
|
||||
{
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Trace)
|
||||
LogMessage.LogTrace(GetString(topic, payLoad, _memoryVarModelQueue.Count));
|
||||
LogMessage.LogTrace(GetDetailLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
else if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage.LogTrace($"Topic:{topic}{Environment.NewLine}Count:{count} {Environment.NewLine} VarModelQueue:{_memoryVarModelQueue.Count}");
|
||||
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
return OperResult.Success;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using BootstrapBlazor.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace ThingsGateway.Plugin.Mqtt;
|
||||
|
||||
@@ -33,6 +34,11 @@ public class MqttClientProperty : BusinessPropertyWithCacheIntervalScript
|
||||
[DynamicProperty]
|
||||
public int Port { get; set; } = 1883;
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public MqttQualityOfServiceLevel MqttQualityOfServiceLevel { get; set; } = MqttQualityOfServiceLevel.AtMostOnce;
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public MqttProtocolVersion MqttProtocolVersion { get; set; } = MqttProtocolVersion.V311;
|
||||
|
||||
@@ -60,12 +66,6 @@ public class MqttClientProperty : BusinessPropertyWithCacheIntervalScript
|
||||
[FileValidation(Extensions = [".txt", ".pem"], FileSize = 1024 * 1024)]
|
||||
internal IBrowserFile ClientKeyFile_BrowserFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示详细日志
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public bool DetailLog { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否websocket连接
|
||||
/// </summary>
|
||||
@@ -120,8 +120,4 @@ public class MqttClientProperty : BusinessPropertyWithCacheIntervalScript
|
||||
[DynamicProperty(Remark = "这个主题接收到任何数据都会把全部的信息发送到变量/设备/报警主题中")]
|
||||
public string RpcQuestTopic { get; set; }
|
||||
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public bool GroupUpdate { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ using Newtonsoft.Json.Linq;
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.Extension.Generic;
|
||||
using ThingsGateway.Foundation;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
using ThingsGateway.NewLife.Extension;
|
||||
@@ -141,11 +142,11 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
}
|
||||
#region private
|
||||
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicJsonList, int count, CancellationToken cancellationToken)
|
||||
private async ValueTask<OperResult> Update(List<TopicArray> topicArrayList, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var topicJson in topicJsonList)
|
||||
foreach (var topicArray in topicArrayList)
|
||||
{
|
||||
var result = await MqttUpAsync(topicJson.Topic, topicJson.Json, count, cancellationToken).ConfigureAwait(false);
|
||||
var result = await MqttUpAsync(topicArray, cancellationToken).ConfigureAwait(false);
|
||||
if (success != result.IsSuccess)
|
||||
{
|
||||
if (!result.IsSuccess)
|
||||
@@ -164,21 +165,21 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
|
||||
private ValueTask<OperResult> UpdateAlarmModel(IEnumerable<AlarmVariable> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetAlarmTopicArrays(item);
|
||||
var topicArrayList = GetAlarmTopicArrays(item);
|
||||
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
private ValueTask<OperResult> UpdateDevModel(IEnumerable<DeviceBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetDeviceTopicArray(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetDeviceTopicArray(item);
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
private ValueTask<OperResult> UpdateVarModel(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
|
||||
{
|
||||
var topicJsonList = GetVariableBasicDataTopicArray(item);
|
||||
return Update(topicJsonList, item.Count(), cancellationToken);
|
||||
var topicArrayList = GetVariableBasicDataTopicArray(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true));
|
||||
return Update(topicArrayList, cancellationToken);
|
||||
}
|
||||
|
||||
#endregion private
|
||||
@@ -261,12 +262,12 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
{
|
||||
foreach (var item in varData)
|
||||
{
|
||||
var topicJsonList = GetVariableBasicData(item);
|
||||
foreach (var topicJson in topicJsonList)
|
||||
var topicArrayList = GetVariableBasicDataTopicArray(item);
|
||||
foreach (var topicArray in topicArrayList)
|
||||
{
|
||||
Messages.Add(new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topicJson.Topic)
|
||||
.WithPayload(topicJson.Json).Build());
|
||||
.WithTopic(topicArray.Topic)
|
||||
.WithPayload(topicArray.Json).Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,12 +277,12 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
{
|
||||
foreach (var item in devData)
|
||||
{
|
||||
var topicJsonList = GetDeviceData(item);
|
||||
foreach (var topicJson in topicJsonList)
|
||||
var topicArrayList = GetDeviceTopicArray(item);
|
||||
foreach (var topicArray in topicArrayList)
|
||||
{
|
||||
Messages.Add(new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topicJson.Topic)
|
||||
.WithPayload(topicJson.Json).Build());
|
||||
.WithTopic(topicArray.Topic)
|
||||
.WithPayload(topicArray.Json).Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,12 +291,12 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
{
|
||||
foreach (var item in alramData)
|
||||
{
|
||||
var topicJsonList = GetAlarms(item);
|
||||
foreach (var topicJson in topicJsonList)
|
||||
var topicArrayList = GetAlarmTopicArrays(item);
|
||||
foreach (var topicArray in topicArrayList)
|
||||
{
|
||||
Messages.Add(new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topicJson.Topic)
|
||||
.WithPayload(topicJson.Json).Build());
|
||||
.WithTopic(topicArray.Topic)
|
||||
.WithPayload(topicArray.Json).Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,25 +395,27 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
|
||||
/// <summary>
|
||||
/// 上传mqtt,返回上传结果
|
||||
/// </summary>
|
||||
public async ValueTask<OperResult> MqttUpAsync(string topic, byte[] payLoad, int count, CancellationToken cancellationToken = default)
|
||||
public async ValueTask<OperResult> MqttUpAsync(TopicArray topicArray, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topic)
|
||||
.WithPayload(payLoad).Build();
|
||||
.WithTopic(topicArray.Topic).WithQualityOfServiceLevel(_driverPropertys.MqttQualityOfServiceLevel)
|
||||
.WithPayload(topicArray.Json).Build();
|
||||
await _mqttServer.InjectApplicationMessage(
|
||||
new InjectedMqttApplicationMessage(message), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (_driverPropertys.DetailLog)
|
||||
{
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Trace)
|
||||
LogMessage.LogTrace(GetString(topic, payLoad, _memoryVarModelQueue.Count));
|
||||
LogMessage.LogTrace(GetDetailLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
else if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage.LogTrace($"Topic:{topic}{Environment.NewLine}Count:{count} {Environment.NewLine} VarModelQueue:{_memoryVarModelQueue.Count}");
|
||||
|
||||
if (LogMessage.LogLevel <= TouchSocket.Core.LogLevel.Debug)
|
||||
LogMessage.LogDebug(GetCountLogString(topicArray, _memoryVarModelQueue.Count));
|
||||
}
|
||||
return OperResult.Success;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace ThingsGateway.Plugin.Mqtt;
|
||||
|
||||
/// <summary>
|
||||
@@ -27,11 +29,8 @@ public class MqttServerProperty : BusinessPropertyWithCacheIntervalScript
|
||||
[DynamicProperty]
|
||||
public int Port { get; set; } = 1883;
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示详细日志
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public bool DetailLog { get; set; } = true;
|
||||
public MqttQualityOfServiceLevel MqttQualityOfServiceLevel { get; set; } = MqttQualityOfServiceLevel.AtMostOnce;
|
||||
|
||||
/// <summary>
|
||||
/// WebSocket端口
|
||||
@@ -66,6 +65,4 @@ public class MqttServerProperty : BusinessPropertyWithCacheIntervalScript
|
||||
|
||||
|
||||
|
||||
[DynamicProperty]
|
||||
public bool GroupUpdate { get; set; } = false;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
"OpcIP": "OpcIP",
|
||||
"OpcName": "OpcName",
|
||||
"UpdateRate": "UpdateRate",
|
||||
"SourceTimestampEnable": "SourceTimestampEnable",
|
||||
"ReIntervalTime": "ReIntervalTime",
|
||||
"RetryCount": "RetryCount"
|
||||
"SourceTimestampEnable": "SourceTimestampEnable"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
"OpcIP": "OpcIP",
|
||||
"OpcName": "OpcName",
|
||||
"UpdateRate": "订阅推送间隔",
|
||||
"SourceTimestampEnable": "服务端时间戳",
|
||||
"ReIntervalTime": "离线恢复时间",
|
||||
"RetryCount": "失败重试次数"
|
||||
"SourceTimestampEnable": "服务端时间戳"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ThingsGateway.Plugin.OpcDa;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class OpcDaMasterProperty : CollectPropertyBase
|
||||
public class OpcDaMasterProperty : CollectPropertyRetryBase
|
||||
{
|
||||
/// <summary>
|
||||
/// OpcIP
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
"LoadType": "LoadType",
|
||||
"AutoAcceptUntrustedCertificates": "AutoAcceptUntrustedCertificates",
|
||||
"ExportC": "ExportCertificate",
|
||||
"SourceTimestampEnable": "SourceTimestampEnable",
|
||||
"ReIntervalTime": "ReIntervalTime",
|
||||
"RetryCount": "RetryCount"
|
||||
"SourceTimestampEnable": "SourceTimestampEnable"
|
||||
},
|
||||
"ThingsGateway.Plugin.OpcUa.OpcUaServerProperty": {
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
"LoadType": "加载服务端数据类型",
|
||||
"AutoAcceptUntrustedCertificates": "自动接受不受信任的证书",
|
||||
"SourceTimestampEnable": "服务端时间戳",
|
||||
"ExportC": "导出证书",
|
||||
"ReIntervalTime": "离线恢复时间",
|
||||
"RetryCount": "失败重试次数"
|
||||
"ExportC": "导出证书"
|
||||
},
|
||||
"ThingsGateway.Plugin.OpcUa.OpcUaServerProperty": {
|
||||
"IsAllVariable": "选择全部变量",
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ThingsGateway.Plugin.OpcUa;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class OpcUaMasterProperty : CollectPropertyBase
|
||||
public class OpcUaMasterProperty : CollectPropertyRetryBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 连接Url
|
||||
|
||||
@@ -202,6 +202,7 @@ public partial class OpcUaServer : BusinessBase
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (success)
|
||||
|
||||
@@ -4,28 +4,10 @@
|
||||
"Port": "Port",
|
||||
"UserName": "UserName",
|
||||
"Password": "Password",
|
||||
"DetailLog": "DetailLog",
|
||||
"IsQueueDeclare": "IsQueueDeclare",
|
||||
"VirtualHost": "VirtualHost",
|
||||
"ExchangeName": "ExchangeName",
|
||||
"ExchangeName": "ExchangeName"
|
||||
|
||||
"JsonFormattingIndented": "JsonFormattingIndented",
|
||||
"BigTextScriptDeviceModel": "BigTextScriptDeviceModel",
|
||||
"BigTextScriptVariableModel": "BigTextScriptVariableModel",
|
||||
"BigTextScriptAlarmModel": "BigTextScriptAlarmModel",
|
||||
"IsDeviceList": "IsDeviceList",
|
||||
"IsVariableList": "IsVariableList",
|
||||
"IsAlarmList": "IsAlarmList",
|
||||
"DeviceTopic": "DeviceTopic",
|
||||
"VariableTopic": "VariableTopic",
|
||||
"AlarmTopic": "AlarmTopic",
|
||||
"BusinessUpdateEnum": "BusinessUpdateEnum",
|
||||
"BusinessInterval": "BusinessInterval",
|
||||
"IsAllVariable": "IsAllVariable",
|
||||
"QueueMaxCount": "QueueMaxCount",
|
||||
"CacheFileMaxLength": "CacheFileMaxLength(mb)",
|
||||
"SplitSize": "SplitSize",
|
||||
"CacheEnable": "CacheEnable",
|
||||
"GroupUpdate": "GroupUpdate"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user