Compare commits

..

782 Commits

Author SHA1 Message Date
Kimdiego2098
c7c3c35100 补充git漏掉的props文件 2023-11-29 13:37:52 +08:00
Kimdiego2098
2f0df3c552 修复aop拦截不生效的问题,更新版本号,整理props文件 2023-11-29 12:43:05 +08:00
Kimdiego2098
e6effcd921 更新依赖包 2023-11-28 22:06:43 +08:00
Kimdiego2098
cd462b9523 修正导出设备表的sheet名称 2023-11-28 09:30:47 +08:00
Kimdiego2098
7e2e17d38b 整理部分底层代码 2023-11-27 16:17:12 +08:00
Kimdiego2098
665d616a06 整理部分项目项 2023-11-27 11:11:15 +08:00
Kimdiego2098
ced90f5bb9 更新版本号 2023-11-24 14:48:53 +08:00
Kimdiego2098
ca0ddb6cb4 10功能码写入时 修改需判断的crc长度 2023-11-24 14:48:28 +08:00
Kimdiego2098
3d733813e1 修复 modbusTcpDtu 初始化 空指针错误 2023-11-24 09:44:47 +08:00
Kimdiego2098
45ddc0b154 OPCUA插件afterStop方法重写时需执行父类方法 2023-11-23 20:51:08 +08:00
Kimdiego2098
87294497f3 调整网关状态页面 2023-11-23 20:49:35 +08:00
Kimdiego2098
5f45f9c0d0 修改内存缓存mapster选项 2023-11-23 15:22:39 +08:00
Kimdiego2098
7f78c06793 添加kafka的SecurityProtocol与SaslMechanism参数说明 2023-11-22 21:29:08 +08:00
Kimdiego2098
8ea5b7eebc 修复上个提交导致的excel导入产生空指针错误 2023-11-22 20:52:58 +08:00
Kimdiego2098
e49cd511af excel导入导出设备表时,去除多余的字段 2023-11-22 16:09:41 +08:00
Kimdiego2098
15c88646df socktClient重载toString 2023-11-22 15:28:04 +08:00
Kimdiego2098
f47919543d 更新版本号 2023-11-22 14:06:52 +08:00
Kimdiego2098
a95291d9cd 代码文件编码更改 2023-11-22 14:02:41 +08:00
Kimdiego2098
033deb3d29 修复变量上传属性在编辑页面不显示的问题 2023-11-22 13:35:44 +08:00
Kimdiego2098
923994c1f4 修复变量上传属性在编辑页面不显示的问题 2023-11-22 13:30:42 +08:00
Kimdiego2098
3d45b839b4 去除不存在的菜单 2023-11-21 18:19:14 +08:00
Kimdiego2098
55d1efa212 调整循环延时时间限值 2023-11-21 16:27:11 +08:00
Kimdiego2098
21d794a0e5 调试mqtt依赖 2023-11-21 15:07:07 +08:00
Kimdiego2098
614022a78c 去除上传间隔1s限制 2023-11-21 11:46:33 +08:00
Kimdiego2098
c00688e23a 整理代码 2023-11-21 11:41:44 +08:00
Kimdiego2098
5c69917d19 更新依赖 2023-11-21 08:44:47 +08:00
Kimdiego2098
6a5eb75b6c 更新版本号 2023-11-20 23:05:12 +08:00
Kimdiego2098
727c55eaa2 去除treeview 2023-11-20 23:04:54 +08:00
Kimdiego2098
9b03173ec5 去除treeview显示 2023-11-20 22:53:34 +08:00
Kimdiego2098
ab95855d6d 更新版本号 2023-11-20 22:47:18 +08:00
Kimdiego2098
bb84594c6b mqttserver/client插件支持websocket通道,直接对接前端 2023-11-20 22:42:08 +08:00
Kimdiego2098
97392c76b1 mqttserver/client插件支持websocket通道,直接对接前端 2023-11-20 22:33:26 +08:00
Kimdiego2098
53aec2b306 modbusTcpServer最大连接数设为3w 2023-11-20 19:46:07 +08:00
Kimdiego2098
a0a381dc63 更新依赖 2023-11-20 17:35:42 +08:00
Kimdiego2098
4fa95edeec 添加admin-解决方案 2023-11-20 15:38:33 +08:00
Kimdiego2098
b944f1d70e 修复设备curd服务aop失效的问题 2023-11-19 23:30:11 +08:00
Kimdiego2098
0f1a5d0085 更新版本号 2023-11-19 22:32:53 +08:00
Kimdiego2098
e7e10222e7 modbus server 添加是否立即写入内存的选项 2023-11-19 22:32:13 +08:00
Kimdiego2098
87c4fda588 默认开启多标签 2023-11-19 22:31:47 +08:00
Kimdiego2098
0ff820de6f 添加历史报警插件 2023-11-19 22:19:05 +08:00
Kimdiego2098
0dcf55e6d9 修复4.0代码 s7协议未设置适配器导致初始化/读写失败的问题 2023-11-19 21:49:32 +08:00
Kimdiego2098
a69842c910 增加上传插件 缓存基类 2023-11-19 15:20:01 +08:00
Kimdiego2098
318f635e4d 获取插件继承属性时,去除不重写特性的属性 2023-11-19 14:15:58 +08:00
Kimdiego2098
abf0d72316 整理文件 2023-11-18 23:04:51 +08:00
Kimdiego2098
5cd89c8844 整理文件 2023-11-18 23:04:25 +08:00
Kimdiego2098
501c1af38c 整理文件 2023-11-18 23:03:24 +08:00
Kimdiego2098
8526e130d9 整理文件 2023-11-18 23:03:02 +08:00
Kimdiego2098
76fd08eade 整理文件 2023-11-18 23:02:28 +08:00
Kimdiego2098
bfe48ae9d2 整理文件 2023-11-18 23:01:56 +08:00
Kimdiego2098
8547cdba7c 去除不必要的文件 2023-11-18 22:52:26 +08:00
Kimdiego2098
00d0cd631d 去除不必要的文件 2023-11-18 22:50:03 +08:00
Kimdiego2098
04460d13cd 迁移4.0 2023-11-18 22:45:24 +08:00
Kimdiego2098
a17a15e5d7 迁移4.0 2023-11-18 22:43:36 +08:00
Kimdiego2098
bfe2465658 添加停止线程等待时间 2023-11-16 22:32:22 +08:00
Kimdiego2098
4568987785 s7握手失败后,手动关闭连接 2023-11-11 10:26:05 +08:00
Kimdiego2098
c0e5a1419d fix:修复线程阻塞检测触发重启时,后台变量列表不再刷新的问题! 2023-11-10 09:00:50 +08:00
Kimdiego2098
23ac7ab748 历史数据上传成功后,才上传缓存数据 2023-11-09 18:55:56 +08:00
Kimdiego2098
5622dc74a8 update 2023-11-08 16:19:46 +08:00
Kimdiego2098
528986f4f0 发布3.0.1版本 2023-11-03 11:32:13 +08:00
Kimdiego2098
e6b8ff3f91 update touchsocket 2023-11-03 11:27:12 +08:00
Kimdiego2098
3fc3c5296f update touchsocket 2023-11-03 11:19:26 +08:00
Kimdiego2098
f4f2a14a31 不存在插件时,报错内容优化 2023-11-01 14:51:08 +08:00
Kimdiego2098
fa3f464cb6 update webapiClient 2023-11-01 14:21:53 +08:00
Kimdiego2098
bed20538ae 调整Timeout属性为int数据类型 2023-10-31 23:49:46 +08:00
Kimdiego2098
3da461c6e6 更新发布版3.0.0.28 2023-10-31 17:47:07 +08:00
Kimdiego2098
9c73e8452a 更新OPCUAClient,订阅模式适配 分组 2023-10-31 10:55:50 +08:00
Kimdiego2098
750dab69d3 update 2023-10-31 00:24:00 +08:00
Kimdiego2098
702d0da47c tcpservice停止时执行shutdown方法,修复demo发布不显示页面的问题 2023-10-30 21:31:30 +08:00
Kimdiego2098
3a955b1e53 添加部分Pro内容 2023-10-29 19:39:38 +08:00
Kimdiego2098
d408bd93e8 添加部分Pro内容 2023-10-29 19:34:17 +08:00
Kimdiego2098
63fd9eb1de 更新文档 2023-10-28 22:06:58 +08:00
Kimdiego2098
4718ab6ddf 发布3.0.0.27版本;
优化设备线程启停逻辑
添加winform(blazor) demo
部分页面显示内容优化
2023-10-28 22:03:52 +08:00
Kimdiego2098
affd4b3a26 发布3.0.0.27版本;
优化设备线程启停逻辑
添加winform(blazor) demo
部分页面显示内容优化
2023-10-28 22:00:35 +08:00
Kimdiego2098
6a660dbcda 优化设备线程启停逻辑 2023-10-28 21:58:09 +08:00
Kimdiego2098
5ff3af8b48 添加部分Pro内容 2023-10-28 21:21:03 +08:00
Kimdiego2098
9d49070f93 添加winform(blazor) demo 2023-10-28 15:20:12 +08:00
Kimdiego2098
5b3994a1dd 调整pro类库 2023-10-28 10:54:26 +08:00
Diego2098
bb1e62c580 设备状态页面显示优化 2023-10-27 20:19:26 +08:00
Diego2098
29cc776908 状态显示:已退出自动更新 2023-10-27 20:18:57 +08:00
Kimdiego2098
d2ef60b2ec 报文显示限长500 2023-10-27 14:53:19 +08:00
Kimdiego2098
41ea496d41 tcpserver 报文输出 添加 ip端口 提示 2023-10-27 14:41:35 +08:00
Kimdiego2098
c69bb38929 update the tcpserver class and add log output for start and stop 2023-10-27 14:24:26 +08:00
Kimdiego2098
23b3f8494e 优化线程上下文转换 2023-10-26 19:16:24 +08:00
Kimdiego2098
0ff94eec1b 添加ConfigureAwait 2023-10-26 18:06:33 +08:00
Kimdiego2098
f67a638565 优化设备导出逻辑 2023-10-26 15:15:43 +08:00
Kimdiego2098
778cf71c61 优化设备导出逻辑 2023-10-26 15:10:26 +08:00
Kimdiego2098
e2da083b48 3.0.0.25 2023-10-26 13:21:40 +08:00
Kimdiego2098
dcc48c0d4b Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-10-26 13:20:54 +08:00
Kimdiego2098
2446b4a591 3.0.0.25 2023-10-26 13:20:31 +08:00
Kimdiego2098
a973d633c8 update 2023-10-26 13:19:18 +08:00
Kimdiego2098
c3b11e6e0f s7添加错误返回码提示,组包处理 2023-10-26 13:05:06 +08:00
Kimdiego2098
44bec2d99e 增加硬件信息 相关json配置 2023-10-26 10:54:48 +08:00
Kimdiego2098
0d59d0a3f6 更新nuget依赖 2023-10-26 09:37:01 +08:00
Kimdiego2098
ddc8372b09 硬件信息页面添加刷新条件 2023-10-26 09:20:25 +08:00
Kimdiego2098
ea7325f4e0 更新文档 2023-10-25 00:53:27 +08:00
Kimdiego2098
6048f95415 update touchsocket 2023-10-25 00:53:17 +08:00
Kimdiego2098
5682705b8d <Version>3.0.0.24</Version> 2023-10-24 23:48:20 +08:00
Kimdiego2098
6c3b82607d 更改S7协议 设备属性,注意删除了DstTSAP,改为较直观的 机架号/槽位号 2023-10-24 23:47:35 +08:00
Kimdiego2098
486c9f4ebf 添加属性识别 16进制写入 2023-10-24 23:46:50 +08:00
Kimdiego2098
7c8adebf2d 添加nuget依赖包 2023-10-24 20:50:39 +08:00
Kimdiego2098
ce98bb0dc1 更新nuget包 2023-10-24 00:37:46 +08:00
Kimdiego2098
60b49a4296 调整解决方案文件夹 2023-10-24 00:13:03 +08:00
Kimdiego2098
5d0a2ffae0 暂时屏蔽mqttserver 遗留消息错误 2023-10-23 20:51:11 +08:00
Kimdiego2098
bbcf7c722a 调整编码 2023-10-23 20:47:00 +08:00
Kimdiego2098
66574eec6d 调整mqttlog 2023-10-23 20:46:17 +08:00
Kimdiego2098
305df3a42c 调整mqttlog 2023-10-23 20:43:58 +08:00
Kimdiego2098
323c6f4270 添加部分兼容方法 2023-10-22 02:42:16 +08:00
Kimdiego2098
c056b2b14c 添加部分兼容方法 2023-10-22 02:26:18 +08:00
Kimdiego2098
02ebb07fd8 update touchsocket 2023-10-22 02:26:04 +08:00
Kimdiego2098
59db0890c3 调整代码格式 2023-10-21 19:15:26 +08:00
Kimdiego2098
3ea0d9ed3a update touchsocket 2023-10-21 19:08:21 +08:00
Kimdiego2098
0371d11dd5 调整代码格式 2023-10-21 19:03:15 +08:00
Kimdiego2098
12f1ebaee9 调整代码格式 2023-10-21 19:02:58 +08:00
Kimdiego2098
5202cc22d1 3.0.0.23 2023-10-20 21:38:22 +08:00
Kimdiego2098
07a34bdcbf 优化SQLDB实时表模式,插入/更新 2023-10-20 21:38:07 +08:00
Kimdiego2098
27806da4be sqlsugar提示默认中文 2023-10-20 21:37:42 +08:00
Kimdiego2098
a15dd1a3ce update touchsocket 2023-10-20 21:03:29 +08:00
Kimdiego2098
6cc7451c7c 优化 ModbusServer 内存占用 2023-10-20 01:53:48 +08:00
Kimdiego2098
652aeee782 3.0.0.21 2023-10-20 01:19:18 +08:00
Kimdiego2098
8e1e887b8f 优化OPCUAServer,取消注册,提供多url写入 2023-10-20 01:19:05 +08:00
Kimdiego2098
6601a2de64 更新赞助名单 2023-10-19 21:15:35 +08:00
Kimdiego2098
75a42ffc32 更新文档 2023-10-19 20:36:28 +08:00
Kimdiego2098
8a80a52f5f 更新版本:3.0.0.20 2023-10-19 20:27:31 +08:00
Kimdiego2098
b373a434ba 优化modbusServer内存管理 2023-10-19 20:24:39 +08:00
Kimdiego2098
cd78fdafe6 update touchsocket 2023-10-19 20:23:43 +08:00
Kimdiego2098
7a1b4c6db7 update toucksocket 2023-10-18 21:51:49 +08:00
Kimdiego2098
f2c7664033 更新文档 2023-10-18 20:42:10 +08:00
Kimdiego2098
12b295f067 发布驱动包 2023-10-18 18:04:37 +08:00
Diego2098
3ee46da40f !12 【轻量级 PR】:修正心跳事件中的参数
Merge pull request !12 from youthalan/N/A
2023-10-18 06:59:17 +00:00
youthalan
beadaa7212 修正心跳事件中的参数
Signed-off-by: youthalan <youthalan@126.com>
2023-10-18 06:58:03 +00:00
Kimdiego2098
16ef09426f 更新版本号 2023-10-18 13:13:03 +08:00
Kimdiego2098
b8c1f1f5a9 初始化 采集/上传线程时 直接返回线程控制 2023-10-18 13:11:59 +08:00
Kimdiego2098
e027b5cbd6 更新OPCUAClient类库 2023-10-18 13:09:25 +08:00
Kimdiego2098
bf1bd73ad1 更新OPCUAClient类库 2023-10-18 12:45:26 +08:00
Kimdiego2098
86fc95119a 更新OPCUAClient类库 2023-10-18 12:44:58 +08:00
Kimdiego2098
b3a76ea17b 更新版本号与nuget发布 2023-10-18 12:39:42 +08:00
Kimdiego2098
bababd9d53 更新OPCUAClient类库 2023-10-18 12:38:20 +08:00
Diego2098
8cd5180531 !11 补充OPCClient类库事件的缺失文件
Merge pull request !11 from youthalan/N/A
2023-10-18 04:34:34 +00:00
youthalan
f1ccbade8c 补充OPCClient类库事件的缺失文件
Signed-off-by: youthalan <youthalan@126.com>
2023-10-18 04:32:39 +00:00
Diego2098
a66f4b0417 !10 添加连接或断开事件
Merge pull request !10 from youthalan/N/A
2023-10-18 04:20:22 +00:00
youthalan
ff495b2261 修改OPCUAClient类添加连接或断开事件,修改注入时不需要带参数
Signed-off-by: youthalan <youthalan@126.com>
2023-10-18 03:48:05 +00:00
Kimdiego2098
90e5824212 update 3.0.0.16 2023-10-18 00:38:36 +08:00
Kimdiego2098
3d64021062 opcuaClient浏览空间 添加是否显示子变量的选项 2023-10-18 00:36:44 +08:00
Kimdiego2098
fb8ed7428d 更改日志输出内容 2023-10-18 00:15:07 +08:00
Kimdiego2098
bdc273c10a update 3.0.0.15 2023-10-18 00:07:24 +08:00
Kimdiego2098
2d96cffdc7 增加不支持单文件发布的说明 2023-10-17 23:47:24 +08:00
Kimdiego2098
4356fccbcd update tdengineDB plugin 2023-10-17 23:43:48 +08:00
Kimdiego2098
a169fd4ce7 update touchsocket 2023-10-17 23:12:19 +08:00
Kimdiego2098
dcd418139e TD时序库插件,创建时间更改为主键 2023-10-17 23:08:09 +08:00
Kimdiego2098
0cac2062d3 update touchsocket 2023-10-17 23:06:21 +08:00
Kimdiego2098
854c5d4ade 更新nuget包 2023-10-17 21:00:50 +08:00
Kimdiego2098
0f96c6ec84 update SQLDB 2023-10-16 20:50:10 +08:00
Kimdiego2098
b219bd66c1 update touchsocket and other 2023-10-16 20:36:51 +08:00
Kimdiego2098
cb52f2c0b3 3.0.0.13 2023-10-16 17:44:09 +08:00
Kimdiego2098
d3273e03ef 增加关系库存储插件; 2023-10-16 17:40:17 +08:00
Kimdiego2098
afbfd963f3 增加时序库存储插件; 2023-10-16 17:40:13 +08:00
Kimdiego2098
2cd101c5f3 更新pro用户列表 2023-10-16 17:39:14 +08:00
Kimdiego2098
b10bc24dee 3.0.0.12 2023-10-16 08:47:39 +08:00
Kimdiego2098
51a23df861 opcuaclient添加是否加载服务端数据类型的选项 2023-10-16 08:46:46 +08:00
Kimdiego2098
03a0a9dad9 fix:tcpservice dispose err 2023-10-16 08:46:32 +08:00
Diego2098
362c0affbe !9 增加可选择安全订阅
Merge pull request !9 from youthalan/N/A
2023-10-16 00:33:19 +00:00
youthalan
d5b523479f 增加可选择安全订阅,以加快订阅速度
Signed-off-by: youthalan <youthalan@126.com>
2023-10-16 00:26:59 +00:00
Kimdiego2098
7719b8f6d7 更新3.0.0.11 2023-10-15 20:26:18 +08:00
Diego2098
3656c0d524 读取数据类型方法改为批量 2023-10-15 20:21:23 +08:00
Kimdiego2098
8b9e0dd6ea 同步Pro版本 2023-10-13 20:14:35 +08:00
Kimdiego2098
b3921b1037 update touchsocket 2023-10-13 19:16:12 +08:00
Kimdiego2098
d7d96e5dbf update nuget 2023-10-13 16:14:42 +08:00
Kimdiego2098
3934395b7b update 3.0.0.7 2023-10-13 11:54:27 +08:00
Kimdiego2098
04fbe9a529 添加三菱mc 3e帧二进制通讯协议文档 2023-10-13 11:51:51 +08:00
Kimdiego2098
badd6dd9a2 update demo 2023-10-12 18:52:44 +08:00
Kimdiego2098
059082456d 参数名称修改 2023-10-12 14:57:58 +08:00
Kimdiego2098
405b68e22f fix:mqtt保留消息未更新/更新错误 2023-10-12 14:57:36 +08:00
Kimdiego2098
c90bf6692c 3.0.0.6 2023-10-11 16:35:10 +08:00
Kimdiego2098
b5ea5d0cc5 update nuget 2023-10-11 16:28:18 +08:00
Kimdiego2098
243617a1e1 调整代码执行顺序 2023-10-11 16:19:34 +08:00
Kimdiego2098
9e703edd59 update ManageGateway 2023-10-11 10:59:33 +08:00
Kimdiego2098
d6c2cf2810 update ManageGateway 2023-10-11 10:41:09 +08:00
Kimdiego2098
ae7811acfa update 3.0.0.5 2023-10-10 21:09:34 +08:00
Kimdiego2098
e55731c099 fix:modbusRtu写入返回报文缓存逻辑修复 2023-10-10 21:08:42 +08:00
Kimdiego2098
9df5c74da4 update touchsocket 2023-10-10 20:03:40 +08:00
Kimdiego2098
8b75f9f785 update touchsocket 2023-10-10 20:02:15 +08:00
Kimdiego2098
bf12428cf4 fix:signalR razor dispose接口 2023-10-09 18:11:23 +08:00
Kimdiego2098
b551df978b update uaparser 2023-10-09 10:56:22 +08:00
Kimdiego2098
c91d85d2f0 添加MqttRpcDemo 2023-10-07 12:04:17 +08:00
Kimdiego2098
965237fa1f 添加清理日志任务配置参数 2023-10-06 18:28:06 +08:00
Kimdiego2098
24cd9afc06 update 3.0.0.2 2023-10-05 15:32:50 +08:00
Diego2098
602fdefebd update Directory.Build.props 2023-10-05 15:21:51 +08:00
Kimdiego2098
7e7818aa17 修复重启共享通道中的单个设备时,导致通道内其他设备变量异常 2023-10-05 00:34:12 +08:00
Kimdiego2098
27a6023a6a update opcuaclient 2023-10-04 17:12:47 +08:00
Kimdiego2098
3861879900 update opcuaclient 2023-10-04 16:59:15 +08:00
Kimdiego2098
807eeb8351 update nuget 2023-10-04 02:04:09 +08:00
Kimdiego2098
045fa53d58 update 3.0.0.1 2023-10-04 01:42:27 +08:00
Kimdiego2098
69d405ece7 实时报警列表线程同步 2023-10-04 01:27:03 +08:00
Kimdiego2098
d3dc4d0c5b modbusRtu 适配器 过滤干扰头部数据 2023-10-04 01:26:44 +08:00
Kimdiego2098
7beba1188e 更新种子数据 2023-10-04 01:24:34 +08:00
Kimdiego2098
9779ebe12c update windowsService bat 2023-10-03 19:11:42 +08:00
Kimdiego2098
f72cfaa093 update demo 2023-10-03 18:54:01 +08:00
Kimdiego2098
cf8ccafb4a rpc调用提示优化 2023-10-03 18:20:39 +08:00
Kimdiego2098
7fe281b0b8 fix:rpc 特殊方法分类错误 2023-10-03 17:05:49 +08:00
Kimdiego2098
5f70e9574f update demo 2023-10-02 22:37:50 +08:00
Kimdiego2098
4be51923ba update driverDebugPage 2023-10-02 18:34:55 +08:00
Kimdiego2098
a72c78f4a4 update opcuaClient 2023-10-02 18:30:58 +08:00
Diego2098
b4d32a6de1 add s7 wstring addressSign 2023-10-01 16:54:42 +08:00
Diego2098
8a6b2d5daa add s7 wstring addressSign 2023-10-01 16:49:07 +08:00
Diego2098
bebadeef14 更新demo 2023-10-01 13:33:25 +08:00
Kimdiego2098
3551be67f0 update demo csproj 2023-10-01 00:33:33 +08:00
Kimdiego2098
1103950b25 add EncodingMapper 2023-10-01 00:25:04 +08:00
Kimdiego2098
9d06e01cec 更新文档 2023-09-30 23:28:50 +08:00
Kimdiego2098
24be946b7e 默认不启用远程更新 2023-09-30 23:23:44 +08:00
Kimdiego2098
f56d2fc60f 更新readme 2023-09-30 23:09:48 +08:00
Kimdiego2098
9f8356f409 同步3.0.0版本代码 2023-09-30 23:05:53 +08:00
Kimdiego2098
8e6345d938 更新文档 2023-09-26 20:03:58 +08:00
Kimdiego2098
0eac78bd1c 2.1.0.15 2023-09-20 11:50:06 +08:00
Kimdiego2098
21db2502d0 2.1.0.15 2023-09-20 11:47:10 +08:00
Kimdiego2098
38c3492123 添加kafka/mq/iotsharp的间隔上传 2023-09-20 11:46:17 +08:00
Diego2098
6376bff476 fix:上传设备选择驱动时没有正确刷新 2023-09-18 00:10:02 +08:00
Kimdiego2098
38495a3ebc 2.1.0.14 2023-09-15 14:02:15 +08:00
Kimdiego2098
cf00897be2 ExpressionEvaluator改为多实例 2023-09-15 14:01:54 +08:00
Kimdiego2098
da640f24ec 2.1.0.13 2023-09-15 13:23:59 +08:00
Kimdiego2098
ed6a777c42 add dispose() 2023-09-15 13:23:39 +08:00
Kimdiego2098
81af4485d3 2.1.0.12 2023-09-15 13:20:29 +08:00
Kimdiego2098
94d8f0237d 更新多个依赖包版本 2023-09-15 13:19:04 +08:00
Kimdiego2098
c5e579dd38 修复因重复注册cancellationToken.Register导致的内存暴涨! 2023-09-15 13:17:36 +08:00
Kimdiego2098
7865e76ee2 CancellationToken代替CancellationTokenSource传入 2023-09-15 13:16:56 +08:00
Kimdiego2098
4d37212cc0 2.1.0.11 2023-09-11 09:35:24 +08:00
Kimdiego2098
9ca43f0bb4 feat:ManageGatewayWorker part 2023-09-11 09:31:26 +08:00
Kimdiego2098
fe8d262175 feat:ManageGatewayWorker part 2023-09-11 09:09:48 +08:00
Kimdiego2098
493d6e7165 feat:ManageGatewayWorker part 2023-09-11 09:09:03 +08:00
Kimdiego2098
17b630bcd8 TGAPPInfp更名APPInfo 2023-09-11 08:57:13 +08:00
Kimdiego2098
018c5ad3b4 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-09-11 08:54:01 +08:00
Kimdiego2098
a14b4da977 feat:ManageGatewayWorker part 2023-09-11 08:53:52 +08:00
Diego2098
01b4597cc7 !7 修复无法修改变量值问题
Merge pull request !7 from 如阳如木/master
2023-09-07 10:14:45 +00:00
如阳如木
0b083ccc1c 删除&& LastSetValue?.ToString() != data?.ToString()
Signed-off-by: 如阳如木 <970143933@qq.com>
2023-09-07 08:42:49 +00:00
Kimdiego2098
ca22cb0eae ManageGatewayConfig.json 2023-09-06 17:29:58 +08:00
Kimdiego2098
bcbb8e5f8c fix:_mqttServer null error 2023-09-06 17:27:36 +08:00
Kimdiego2098
bea286cdd4 2.1.0.10 2023-09-06 17:16:28 +08:00
Kimdiego2098
892d2ee8d2 从数据库取原属性 2023-09-06 17:14:24 +08:00
Kimdiego2098
7440608c14 更改变量 最近一次值 为 上次值 2023-09-06 16:44:58 +08:00
Kimdiego2098
6246f0295b 更改 变量最近一次值 为 上次值 2023-09-06 16:44:42 +08:00
Kimdiego2098
53c39d9b43 2.1.0.9 2023-09-06 16:30:50 +08:00
Kimdiego2098
9a50b60031 fix:串口断连/拔出/断电等情况,重新连接 2023-09-06 16:29:48 +08:00
Kimdiego2098
fd74527320 feat:ManageGatewayWorker part 2023-09-06 16:15:38 +08:00
Kimdiego2098
f91fb522ac feat:ManageGatewayWorker part 2023-09-06 16:10:29 +08:00
Kimdiego2098
7019c02b18 feat:ManageGatewayWorker part 2023-09-05 23:59:18 +08:00
Kimdiego2098
94f8422b9b feat:ManageGatewayWorker part 2023-09-05 23:37:02 +08:00
Kimdiego2098
b25c01567a feat:ManageGatewayWorker part 2023-09-05 23:33:02 +08:00
Kimdiego2098
b9329885de 2.1.0.8 2023-09-05 09:19:58 +08:00
Kimdiego2098
ac88c4cff9 fix:PeriodicTimer dispose 2023-09-05 09:17:26 +08:00
Kimdiego2098
9674f2d238 2.1.0.7 2023-09-05 09:06:39 +08:00
Kimdiego2098
38c9ecb6f1 fix:error!the stream dispose 2023-09-05 09:04:34 +08:00
Kimdiego2098
be9e9cdd5a Revert "fix:error!the stearm dispose"
This reverts commit a6d99fe227.
2023-09-05 09:03:49 +08:00
Kimdiego2098
afdaf07446 feat:mqttBroker part 2023-09-05 08:58:49 +08:00
Kimdiego2098
5caaf10225 fix:error!the stearm dispose 2023-09-05 08:57:42 +08:00
Diego2098
daffc3a776 feat:mqttBroker part 2023-09-04 22:34:31 +08:00
Diego2098
34c9748ce5 fix:uploadDeivce复制多个,ID重复问题 2023-09-04 22:11:50 +08:00
Diego2098
f17acbf4d1 刷新后选择行清空 2023-09-04 22:09:26 +08:00
Diego2098
229f56ce2f fix:采集设备线程初始化时更新活跃时间 2023-09-04 20:13:49 +08:00
Diego2098
0847bedc51 fix:特殊情况下无法获取程序集文件修改日期,所以去除 页脚-编译时间显示 2023-09-04 19:49:17 +08:00
Kimdiego2098
9e4546c305 fix:sqlsugar json支持类型改为bigstring 2023-09-04 17:09:38 +08:00
Kimdiego2098
97b01bf26a 更新文档 2023-09-04 15:03:03 +08:00
Kimdiego2098
e7011628d0 恢复Sqlite默认数据库 2023-09-02 19:17:32 +08:00
Kimdiego2098
044ffdecbd fix: page取消注入瞬时服务,改为App.GetService 2023-09-02 19:13:57 +08:00
Kimdiego2098
1a06a3543b feat:mqttBroker part 2023-09-02 13:55:21 +08:00
Kimdiego2098
5fedc0bf1e 更新文档 2023-08-31 09:17:59 +08:00
Kimdiego2098
7a881f867e 更新 变量管理-上传设备筛选功能 2023-08-31 08:58:30 +08:00
Kimdiego2098
dfe73a6cfb 2.1.0.6 2023-08-30 17:19:18 +08:00
Kimdiego2098
45d0fb27ad add windows service create/delete bat 2023-08-30 17:18:35 +08:00
Kimdiego2098
31890af61d update statusPage; 2023-08-30 14:12:50 +08:00
Kimdiego2098
a54b3ecc15 默认检测重连频率为10分钟 2023-08-29 17:56:59 +08:00
Kimdiego2098
c37cd1bd51 2.1.0.5 2023-08-29 17:44:28 +08:00
Kimdiego2098
0e3ee89cbf 添加报文日志入库选项 2023-08-29 17:42:56 +08:00
Kimdiego2098
a049176c14 添加 页脚 编译时间显示 2023-08-29 17:01:46 +08:00
Kimdiego2098
5ef2b0089e 调整导入excel错误提示 2023-08-29 16:45:54 +08:00
Kimdiego2098
1cc4899593 update opcdaclient null error 2023-08-29 15:24:29 +08:00
Kimdiego2098
26d1390be9 update GetBoolValue 2023-08-29 12:40:21 +08:00
Kimdiego2098
dc65584fb3 调整种子文件,增加Pro版本种子文件录入 2023-08-29 09:42:54 +08:00
Kimdiego2098
b3d5a708d5 更新2.1.0.4 2023-08-28 19:31:00 +08:00
Kimdiego2098
904a5d296b 修复串口基类 缓存包 失效错误;完善modbusrtu长度校验 2023-08-28 19:25:22 +08:00
Kimdiego2098
cc82e6a47a 更新touchsocket版本,更新2.1.0.3 2023-08-28 18:12:18 +08:00
Kimdiego2098
a9d02ec854 修复浏览大量节点空间时,BrowseNext方法参数releaseContinuationPoints改为false 2023-08-28 17:44:02 +08:00
Kimdiego2098
6b5a2d3767 修复调试界面-opcuaclient浏览节点展开逻辑错误 2023-08-28 10:51:35 +08:00
Kimdiego2098
10d9060b94 更新小版本2.1.0.2 2023-08-27 17:17:37 +08:00
Kimdiego2098
8441839c01 更新dlt645地址说明 2023-08-27 17:16:59 +08:00
Kimdiego2098
b669f5838f 添加日志查询 时间区间条件 2023-08-27 16:58:45 +08:00
Kimdiego2098
1a942f9ce1 2.1.0.1 2023-08-27 16:31:03 +08:00
Kimdiego2098
ae840758f7 dlt645添加数据标识校验 2023-08-27 16:30:32 +08:00
Kimdiego2098
082c08e5f9 更新dlt645,添加地址/控制码的校验规则 2023-08-27 16:15:51 +08:00
Kimdiego2098
74a43557ab 更新touchsocket 2023-08-27 15:59:57 +08:00
Kimdiego2098
184271789d 更新 Opc.Ua Version="1.4.372.56" 2023-08-27 14:33:24 +08:00
Kimdiego2098
fa61b0cad8 opcda/ua浏览地址空间 初始只加载首层节点 2023-08-27 14:14:47 +08:00
Kimdiego2098
7b197a90d1 opcuaclient浏览地址空间 初始只加载首层节点 2023-08-27 13:06:03 +08:00
Diego2098
62384af2f6 update MqttNetLogger 2023-08-26 21:38:14 +08:00
Diego2098
b466202a1a update MqttNetLogger 2023-08-26 20:40:23 +08:00
Diego2098
7ab38c18d8 添加在线/离线方法参数 2023-08-26 17:18:47 +08:00
Diego2098
39841ee43e 更新opcuaclient 2023-08-26 15:38:22 +08:00
Diego2098
e419800d98 更新opcuaclient,添加checkDomain属性,去除多余代码,更新SelectEndpoint方法 2023-08-26 15:33:03 +08:00
Kimdiego2098
63c99ab69a 更新文档 2023-08-25 19:49:02 +08:00
Kimdiego2098
e2a8fd2279 更新版本2.1.0 2023-08-25 19:45:28 +08:00
Kimdiego2098
bbde520471 更新解决方案 2023-08-25 19:38:47 +08:00
Kimdiego2098
45fb12f98e 更新DLT645文档 2023-08-25 19:33:33 +08:00
Kimdiego2098
4be3dcce50 添加DLT645_2007协议插件 2023-08-25 19:33:08 +08:00
Kimdiego2098
d12a41c769 调整Test位置 2023-08-25 19:32:27 +08:00
Kimdiego2098
ed9a58c9ed 调整非主从协议的状态判断策略;OPCUA去除主动连接 2023-08-25 17:23:00 +08:00
Kimdiego2098
4389cea5a1 crc校验优化 2023-08-22 17:01:10 +08:00
Kimdiego2098
d24854920b OPCUAClient添加是否使用SourceTime的选项 2023-08-22 16:15:34 +08:00
Kimdiego2098
9902443bee 更新文档 2023-08-22 12:21:45 +08:00
Kimdiego2098
8040b2ef16 2.0.9.3 2023-08-22 11:31:36 +08:00
Kimdiego2098
4533680b10 去除mqtt throw an _MqttConnectingFailedException_.报错信息 2023-08-22 11:26:22 +08:00
Kimdiego2098
3b28175135 更新批量写入方法,注意rpc入口参数变化,mqtt等RPC接口参数变化 2023-08-22 11:23:03 +08:00
Kimdiego2098
8e22812265 修正部分代码格式 2023-08-21 19:59:07 +08:00
Kimdiego2098
409bc91b9e 2.0.9.2 2023-08-19 12:08:49 +08:00
Kimdiego2098
61fe543a2a xml 2023-08-19 11:06:05 +08:00
Kimdiego2098
8a949a7e64 修复TcpClient重复释放导致锁异常 2023-08-19 11:05:29 +08:00
Kimdiego2098
b0dc9fb97a mas1.0.2默认中文 2023-08-18 18:36:30 +08:00
Kimdiego2098
83114d1002 更新masa1.0.2 2023-08-18 13:59:17 +08:00
Kimdiego2098
94a25a903f 2.0.9.1 2023-08-18 13:33:45 +08:00
Kimdiego2098
4f402f9e55 修改锁为EasyLock 2023-08-18 12:07:01 +08:00
Kimdiego2098
27bb2e3dcc 代码文件编码统一utf-8 2023-08-18 09:57:03 +08:00
Kimdiego2098
66cc52f6ec 更换DEMO Include为PackageReference 2023-08-17 15:30:35 +08:00
Kimdiego2098
ed1367b116 底层驱动添加netstandard输出 2023-08-17 15:24:07 +08:00
Kimdiego2098
5c055352e4 2.0.8 2023-08-17 10:58:48 +08:00
Kimdiego2098
8dcff5ada1 调整readme,方便copy账密 2023-08-17 10:28:47 +08:00
Kimdiego2098
4b8b23d7d5 优化变量地址输入分割方法;s7读写字符串添加默认编码 2023-08-17 09:50:10 +08:00
Kimdiego2098
e576f6aed3 优化s7读写字符串,更改特殊方法为读写共用 2023-08-16 17:20:20 +08:00
Kimdiego2098
97ab04da91 修复写入返回结果时的解析,0XFF为成功 2023-08-16 15:56:25 +08:00
Kimdiego2098
c6361bb36e 修复s7字符串打包读取 2023-08-16 15:47:37 +08:00
Kimdiego2098
b0b3dc225d 修复s7字符串读取 2023-08-16 15:35:15 +08:00
Kimdiego2098
9cbaba192a 主动释放锁 2023-08-16 14:56:47 +08:00
Kimdiego2098
f511598e13 OPCUA死区不再固定传入 2023-08-16 14:21:19 +08:00
Kimdiego2098
5ffff3b7aa fix: 优化JsonUtils中的获取type语句顺序 2023-08-16 08:59:18 +08:00
Kimdiego2098
24c4fa1c4f OPC系列增加导出excel/导入系统双选项 2023-08-15 17:38:40 +08:00
Kimdiego2098
7f312c1273 OPCUA采集设备写入字符串,不再需要传入双引号 2023-08-15 14:15:39 +08:00
Kimdiego2098
ef5c226c81 历史数据/报警 线程初始化时不再阻塞 2023-08-15 12:12:00 +08:00
Kimdiego2098
3f029cf799 更改ItemGroup Condition条件 2023-08-14 17:36:59 +08:00
Kimdiego2098
5bf64a8bec 传播token;
更新admin解决方案
2023-08-14 16:43:30 +08:00
Kimdiego2098
89f9c537f8 优化适配器解析代码 2023-08-14 14:21:00 +08:00
Kimdiego2098
e8d7f57818 2.0.6 2023-08-13 16:57:12 +08:00
Kimdiego2098
9b42fa78e7 OPCUACClient订阅初始化添加trycatch 2023-08-13 16:29:59 +08:00
Kimdiego2098
96d98e8f39 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-08-13 15:53:33 +08:00
Kimdiego2098
1f3a281e78 更新opcuaclient,初始读取server类型改为动态读取 2023-08-13 15:50:47 +08:00
Diego2098
dab4b66ee0 更新nuget包 2023-08-12 12:09:50 +08:00
Kimdiego2098
64dd192ddb 修复批量令牌强退失效 2023-08-11 15:15:50 +08:00
Kimdiego2098
b0a5c383d0 中间变量导入时添加标识 2023-08-11 14:15:22 +08:00
Kimdiego2098
4836cc99eb 2.0.5 2023-08-10 18:23:40 +08:00
Kimdiego2098
ba33873354 去除不需要的模板 2023-08-10 16:28:52 +08:00
Kimdiego2098
12c838cab0 修改详情模板 2023-08-10 11:23:18 +08:00
Kimdiego2098
a83a1c83a7 添加自定义详情模板 2023-08-10 10:35:19 +08:00
Kimdiego2098
2234f47170 底层修改:如果连接端口断开,停止等待返回 2023-08-10 10:35:01 +08:00
Kimdiego2098
4bae1b17fc 上传DTO添加 单位 参数 2023-08-10 09:09:09 +08:00
Kimdiego2098
6a7a0e0fa6 调整调试页面 2023-08-09 23:45:53 +08:00
Kimdiego2098
bff987c55f 添加单文件发布配置 2023-08-09 15:12:55 +08:00
Kimdiego2098
e467006913 去除页面多余引号 2023-08-09 13:45:27 +08:00
Kimdiego2098
1d646d4a6d 更新2.0.4 2023-08-09 13:00:10 +08:00
Kimdiego2098
70bd4936a1 更新opcua写入 2023-08-09 12:43:05 +08:00
Kimdiego2098
5ae7add6d2 更新opcua调试页面 2023-08-09 12:01:23 +08:00
Kimdiego2098
02b206ce7c 更新opcua 2023-08-09 11:47:04 +08:00
Kimdiego2098
2ea626a567 修复中间变量导入错误 2023-08-09 09:00:49 +08:00
Kimdiego2098
653909ec11 修正错误注释 2023-08-08 18:09:23 +08:00
Kimdiego2098
1d7c148eaf opcua添加初始化连接错误重试 2023-08-08 18:04:24 +08:00
Kimdiego2098
94a7e130ca 更新readme 2023-08-08 16:14:06 +08:00
Kimdiego2098
609abacdf0 优化大量设备线程重启的耗时 2023-08-08 14:02:00 +08:00
Kimdiego2098
033ff2e49a 2.0.3 2023-08-08 12:59:14 +08:00
Kimdiego2098
00a9bf0641 底层部分方法更改 2023-08-08 12:31:42 +08:00
Kimdiego2098
100f322456 报警/历史值查询时区转换 2023-08-08 09:05:15 +08:00
Kimdiego2098
2251e08d30 时间最小最大值时不再转换时区 2023-08-08 08:39:20 +08:00
Kimdiego2098
14e9beef53 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-08-08 08:28:37 +08:00
Kimdiego2098
c7cce23d54 默认不启用单用户登录 2023-08-08 08:28:27 +08:00
Diego2098
7becf32352 更新文档 2023-08-07 22:31:51 +08:00
Diego2098
741eda9f4e 去除DateTimeOffset类型 2023-08-07 22:30:38 +08:00
Kimdiego2098
473f51481c 更新文档 2023-08-07 17:38:53 +08:00
Kimdiego2098
684f9bd11b 更新readme 2023-08-07 17:34:32 +08:00
Kimdiego2098
b4b7f0c360 更新文件 2023-08-07 17:24:28 +08:00
Kimdiego2098
cf42d02628 更新文件 2023-08-07 17:16:53 +08:00
Kimdiego2098
cc9a9eab7b 更新文件 2023-08-07 16:56:45 +08:00
Kimdiego2098
784d6abc9b 更新文件 2023-08-07 16:33:36 +08:00
Kimdiego2098
0eafc07184 更新文件 2023-08-07 16:30:23 +08:00
Kimdiego2098
7e9499bd2e 更新文件 2023-08-07 15:46:30 +08:00
Kimdiego2098
d01a52aa95 更新文件 2023-08-07 15:36:49 +08:00
Kimdiego2098
6bcd492980 去除多余解决方案配置 2023-08-07 15:31:22 +08:00
Kimdiego2098
96b15da04b 添加发布脚本 2023-08-07 15:23:53 +08:00
Kimdiego2098
e0f1801693 更新readme 2023-08-07 15:18:42 +08:00
Kimdiego2098
d195ad85c5 更新readme 2023-08-07 15:13:21 +08:00
Kimdiego2098
773f7b6c1b 更新文档 2023-08-07 15:10:42 +08:00
Kimdiego2098
40f29fe399 2.0.0 2023-08-07 15:09:53 +08:00
Kimdiego2098
b19eb117c1 调试更新Blazor代码时不再跳转登录界面 2023-07-25 22:00:27 +08:00
Kimdiego2098
f930ba5eff 取消不必要的错误日志 2023-07-25 20:50:33 +08:00
Kimdiego2098
fbbda6c230 变量值更新错误提示; 2023-07-25 20:48:17 +08:00
Kimdiego2098
47db4968e5 优化大批量excel变量表导入效率 2023-07-25 18:26:48 +08:00
Kimdiego2098
1aff2e518c 删除不必要延时 2023-07-25 16:52:56 +08:00
Kimdiego2098
24134ca49e 发布1.7.6 2023-07-25 14:22:11 +08:00
Kimdiego2098
aadbe05a5e 优化导入excel效率 2023-07-25 14:21:17 +08:00
Kimdiego2098
18eddf4700 添加上传插件获取采集设备属性值的快捷方法 2023-07-23 13:44:37 +08:00
Kimdiego2098
0869ba7e70 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-07-23 09:59:11 +08:00
Kimdiego2098
cba5db1c53 线程完成时不再需要全局数据移除,有可能会导致偶发全局数据丢失 2023-07-23 09:58:43 +08:00
Kimdiego2098
0aa5430e23 线程完成时不要需要全局数据移除,有可能会导致偶发全局数据丢失 2023-07-23 09:57:03 +08:00
Kimdiego2098
88a91828cb 更新icon包版本 2023-07-23 00:03:46 +08:00
Kimdiego2098
27af89f5fe 更新icon包版本 2023-07-22 23:59:03 +08:00
Kimdiego2098
6f6d483bfe 修改插件日志为自定义日志 2023-07-22 23:34:09 +08:00
Kimdiego2098
915072c191 更新文档 2023-07-22 20:48:29 +08:00
Kimdiego2098
76077b92ae 发布1.7.4 2023-07-22 20:47:26 +08:00
Kimdiego2098
f0d1a527a5 修正错误名称 2023-07-22 20:32:34 +08:00
Kimdiego2098
fdb2a96d1c 添加上传插件最后错误原因 2023-07-22 20:10:45 +08:00
Kimdiego2098
849e3ac187 修复上传设备暂停按钮失效 2023-07-22 19:56:56 +08:00
Kimdiego2098
5c4cf21c59 OPCUAServer 数组维度不再写any;rpc写入添加延时 2023-07-22 17:02:44 +08:00
Kimdiego2098
40ee3e5d9b 更改假死检测间隔5分钟 2023-07-22 11:05:56 +08:00
Kimdiego2098
77a7cc034e 添加OPCUAServer线程间隔配置项,优化最后一次错误提示 2023-07-22 11:03:56 +08:00
Kimdiego2098
82b7881765 支持OPCUAServer数组类型,添加缓存文件存在判断 2023-07-21 21:28:39 +08:00
Kimdiego2098
3515775267 去除OPCUA写入数组维度校验 2023-07-20 17:37:49 +08:00
Kimdiego2098
10e12aa1c1 更新文档 2023-07-20 12:48:13 +08:00
Kimdiego2098
7fb4e62aa3 kafka尝试自动加载c库 2023-07-20 12:40:59 +08:00
Kimdiego2098
2605eaa614 修复中间变量Rpc写入 2023-07-20 10:55:37 +08:00
Kimdiego2098
8e97b4820d ModbusServer添加自定义循环间隔,修复中间变量写入 2023-07-20 10:55:17 +08:00
Kimdiego2098
89af4cdb68 更新文档 2023-07-19 18:02:31 +08:00
Kimdiego2098
6099c1a25a 更新文档 2023-07-19 15:43:28 +08:00
Kimdiego2098
fd23758aea 更改左侧菜单为手风琴效果 2023-07-19 15:00:40 +08:00
Kimdiego2098
8ad0b89db1 更新文档 2023-07-19 14:34:27 +08:00
Kimdiego2098
e7dffa3ff4 修改OPCUAClient心跳频率默认3s 2023-07-18 14:49:27 +08:00
Kimdiego2098
2772b5d2e2 更改OPCUAClient心跳频率为30000 2023-07-18 14:15:02 +08:00
Kimdiego2098
df6d9b5f70 更新1.7.3版本 2023-07-18 12:16:33 +08:00
Kimdiego2098
c9622d6d57 更新masa 稳定版以及其他包 2023-07-18 12:11:37 +08:00
Kimdiego2098
1f0b7c3c7e 修复添加订阅时,值死区过滤逻辑 2023-07-18 11:13:21 +08:00
Kimdiego2098
c12245037e 修复异步锁上下文切换导致OPCUA 心跳事件出错 2023-07-18 09:58:01 +08:00
Kimdiego2098
fe6d2a50a5 修复OPCUAClient调试界面重复输出订阅值 2023-07-18 08:51:27 +08:00
Kimdiego2098
7be84950f8 修改OPCUAClient的心跳频率配置项 2023-07-18 08:48:18 +08:00
Kimdiego2098
ba212da222 添加重启锁 2023-07-17 21:40:47 +08:00
2248356998 qq.com
122b833256 Merge branch 'master' of https://gitee.com/diego2098/thingsgateway-docs 2023-07-17 20:59:53 +08:00
2248356998 qq.com
7c73479041 更新opcua心跳状态日志 2023-07-17 20:59:32 +08:00
Diego2098
151f2e99ae 更新文档 2023-07-16 20:46:16 +08:00
Diego2098
da367e813f 更新授权名单 2023-07-16 20:31:56 +08:00
2248356998 qq.com
9143dfe336 更新文档 2023-07-16 18:27:22 +08:00
2248356998 qq.com
29914d6a72 更新文档 2023-07-16 18:12:55 +08:00
2248356998 qq.com
0dbef72a97 更新文档 2023-07-16 18:07:31 +08:00
2248356998 qq.com
3bb118bfe1 更新文档 2023-07-16 17:49:33 +08:00
2248356998 qq.com
85ce3be077 更新文档 2023-07-16 17:48:22 +08:00
2248356998 qq.com
064c2bf0a8 更新文档 2023-07-16 17:41:52 +08:00
2248356998 qq.com
c96d06ccc5 更新文档 2023-07-16 17:35:04 +08:00
2248356998 qq.com
a658dbb753 更新文档地址 2023-07-16 17:32:49 +08:00
2248356998 qq.com
bf5d5b629e 迁移文档 2023-07-16 17:28:26 +08:00
2248356998 qq.com
241d576519 冗余设备删除后会导致后台出错 2023-07-16 11:36:45 +08:00
2248356998 qq.com
7807e9bdd0 更新readme 2023-07-16 10:28:43 +08:00
2248356998 qq.com
fcbf15fed6 删除无用属性 2023-07-16 09:40:00 +08:00
2248356998 qq.com
cd90a11209 修复1.7.0版本修改导致的mqttrpc映射错误 2023-07-15 22:56:28 +08:00
2248356998 qq.com
ff65707ea2 增加 上传插件的列表分割大小,因为某些情况下传输字节太大会导致失败 2023-07-15 22:42:34 +08:00
2248356998 qq.com
b16026070c 导入提示的当前行显示未初始 2023-07-15 22:35:12 +08:00
2248356998 qq.com
1b5fbf86d8 格式化整理 2023-07-15 22:32:54 +08:00
2248356998 qq.com
5eb1be8101 插件报文截取前200字符,防止页面渲染过多 2023-07-15 20:04:14 +08:00
2248356998 qq.com
6a863cd26a kafka插件增加超时选项 2023-07-15 17:27:35 +08:00
2248356998 qq.com
87ebb7b6c7 历史服务修复变量在线状态显示错误 2023-07-15 15:46:39 +08:00
2248356998 qq.com
1233a74307 发布1.7.2版本 2023-07-15 11:10:29 +08:00
2248356998 qq.com
221890acfb 优化OPCUA错误提示 2023-07-14 17:33:11 +08:00
2248356998 qq.com
687c7e766e OPCUA在取消订阅时应该走读取方法 2023-07-14 17:22:19 +08:00
2248356998 qq.com
ba22c407d3 优化导入excel提示 2023-07-14 16:23:42 +08:00
2248356998 qq.com
a8b9ed56b5 优化导入excel提示 2023-07-14 16:23:35 +08:00
2248356998 qq.com
3004869e19 kafka 插件释放时取消事件注册 2023-07-14 14:35:40 +08:00
2248356998 qq.com
1145853fe1 更改属性说明 2023-07-14 12:23:46 +08:00
2248356998 qq.com
f1617a25b1 添加kafka插件null传播 2023-07-14 10:41:04 +08:00
2248356998 qq.com
932be558d9 opcda JValue转object 2023-07-14 10:14:05 +08:00
2248356998 qq.com
ee3a37d3b9 opcua读取值JValue转为object 2023-07-14 10:04:05 +08:00
2248356998 qq.com
5ac412a582 RabbitMQ,IotSharp添加离线缓存 2023-07-13 19:54:12 +08:00
2248356998 qq.com
1625290bc3 Variable Value数据类型改为object 2023-07-13 18:18:53 +08:00
2248356998 qq.com
1ec169ad49 中间变量页种子ID重复 2023-07-13 17:47:22 +08:00
2248356998 qq.com
53be552e44 复制设备没有及时刷新缓存 2023-07-13 17:38:45 +08:00
2248356998 qq.com
d3a75d46b9 发布1.7.1 2023-07-13 11:19:17 +08:00
2248356998 qq.com
256512c961 代码格式化 2023-07-13 11:18:36 +08:00
2248356998 qq.com
5c12ac5bcc OPCDA增加数组支持,增加写入动态类型支持 2023-07-13 11:16:31 +08:00
2248356998 qq.com
02a2bcb113 优化OPCUA数组类型转换 2023-07-13 09:02:36 +08:00
2248356998 qq.com
1f0a01c725 修复blazor界面null错误 2023-07-12 22:12:11 +08:00
2248356998 qq.com
6ea164ede1 更新ReadMe 2023-07-12 21:33:05 +08:00
2248356998 qq.com
65bae85ecc 删除重复文件 2023-07-12 21:30:41 +08:00
2248356998 qq.com
2fd7dcf4d0 更新nuget包 2023-07-12 21:21:50 +08:00
2248356998 qq.com
aa3bbbe038 V1.7.0发布
1、增加采集通道冗余
2、优化多个界面
3、导出导入功能优化
4、增加中间变量
5、OPCUAClient支持动态类型
6、离线缓存多处覆盖,包含上传插件/历史报警/时序库
7、增加通用调试界面,增加s7调试
8、其他优化
2023-07-12 21:16:38 +08:00
2248356998 qq.com
6cb09a6f95 修复AppDataTable清空MForm模型导致筛选列清空的问题 2023-07-10 13:18:14 +08:00
2248356998 qq.com
45868f05d3 修复写入s7协议 bit值 偏移错误(以byte数据块为准) 2023-07-08 17:01:44 +08:00
2248356998 qq.com
aac7401e20 修复读取s7协议 bit值 偏移错误(以byte数据块为准) 2023-07-08 11:44:57 +08:00
2248356998 qq.com
c2fc290edd 默认添加kafka插件 种子数据 2023-07-07 17:13:00 +08:00
2248356998 qq.com
330357fc36 修复布尔量解析时反转字节导致结果值不符的错误 2023-07-06 14:05:09 +08:00
2248356998 qq.com
f4a3d6a64e null传播 2023-07-03 14:13:00 +08:00
2248356998 qq.com
2e0963ec81 添加x86架构 2023-07-03 10:48:52 +08:00
2248356998 qq.com
897cb6e62a 补充插件实例内容 2023-07-02 19:50:09 +08:00
2248356998 qq.com
80868bd48e blazor组件初始化并行执行,导致sugar单例DB出现线程偶发错误,暂增加copyNew()解决 2023-06-29 16:42:19 +08:00
2248356998 qq.com
b3df78c56f blazor组件初始化并行执行,导致sugar单例DB出现线程偶发错误,暂增加copyNew()解决 2023-06-29 16:36:03 +08:00
2248356998 qq.com
783a4259e3 sqlsugar偶发线程故障,添加copyNew方法 2023-06-28 18:54:45 +08:00
2248356998 qq.com
fcf19b8dc8 登录跳转uri优化 2023-06-28 15:47:35 +08:00
2248356998 qq.com
1f9f89817d 更新开源说明 2023-06-28 10:48:33 +08:00
2248356998 qq.com
7b94da7d85 update openapiUser datatableUI 2023-06-26 19:51:02 +08:00
2248356998 qq.com
164406f6c2 css脚本结果不采用 System.Text.Json.JsonSerializer 2023-06-26 19:44:17 +08:00
2248356998 qq.com
90ef2adc6b OPCUAClient修复当变量为string类型时的数值过滤失败导致添加订阅失效 2023-06-26 19:43:00 +08:00
2248356998 qq.com
d65f10f88b 停用采集设备时,变量获取运行态出错 2023-06-26 16:43:48 +08:00
2248356998 qq.com
dca0ece9e0 登录后跳转原url 2023-06-26 14:46:24 +08:00
2248356998 qq.com
baabc155c8 cookie授权验证失败时返回登录界面 2023-06-26 14:36:41 +08:00
Diego2098
7eb94412d6 更新nuget类库 2023-06-25 18:59:09 +08:00
2248356998 qq.com
0fc8b24f85 添加报警事件None枚举 2023-06-20 13:10:58 +08:00
2248356998 qq.com
88f6ef5b96 修复cpu核心等于1时报错,修正登录错误提示 2023-06-20 09:09:08 +08:00
Diego2098
7442483419 修复modbusServer 初始化错误 2023-06-17 18:14:13 +08:00
2248356998 qq.com
9c61933c04 sugar添加取消令箭 2023-06-15 17:38:36 +08:00
2248356998 qq.com
2b36a99720 增加变量运行态 CollectVariableRuntime 所在设备属性 2023-06-15 16:50:08 +08:00
2248356998 qq.com
c2cfc42ba4 parallel.foreach无序体验不好,退回为foreach 2023-06-14 11:04:09 +08:00
2248356998 qq.com
4f32704e08 update 1.6.1 version 2023-06-13 22:39:47 +08:00
2248356998 qq.com
fccf43685f update nuget package 2023-06-13 22:39:25 +08:00
2248356998 qq.com
39135d81ad update driver messagesui 2023-06-13 22:26:19 +08:00
2248356998 qq.com
ff4b10681e 并行关闭线程 2023-06-12 14:41:08 +08:00
2248356998 qq.com
10b7908fc2 添加mqtt/kafka上传内容显示 2023-06-12 14:40:53 +08:00
2248356998 qq.com
31790da8c6 优化大量变量excel上传的验证过程 2023-06-12 11:35:27 +08:00
2248356998 qq.com
4621201c47 更新文档站点地址 2023-06-11 18:37:50 +08:00
2248356998 qq.com
692ac31dbf 删除docs 2023-06-11 18:22:15 +08:00
2248356998 qq.com
ed1d163d55 更新1.6.0版本 2023-06-11 17:58:57 +08:00
2248356998 qq.com
e931c9040c 缓存最大默认2000 2023-06-11 17:56:34 +08:00
2248356998 qq.com
f23cb48ea4 添加离线缓存大小限制配置 2023-06-11 17:55:03 +08:00
2248356998 qq.com
c3b2b6b07b 上传插件线程等待时间改为10ms 2023-06-11 17:47:16 +08:00
2248356998 qq.com
f89bf590ba 导入变量优化 2023-06-11 17:46:23 +08:00
2248356998 qq.com
fea17dc00b 添加mqttClient离线缓存 2023-06-11 17:45:46 +08:00
2248356998 qq.com
dbb1069920 添加kafka离线缓存 2023-06-11 17:45:27 +08:00
Diego2098
afc4ccfaa9 !6 部分配置会导致SqlServer自动建库失败
Merge pull request !6 from samisgod/master
2023-06-10 06:55:34 +00:00
samisgod
38d55a1c07 fix db init for SqlServer 2023-06-10 14:51:29 +08:00
2248356998 qq.com
5fca29f103 增加pwa 2023-06-09 17:53:41 +08:00
2248356998 qq.com
78f34b2ca4 修复停用验证码时登录失败显示null报错 2023-06-09 17:09:17 +08:00
2248356998 qq.com
8e8028e809 统一文件编码 2023-06-09 15:04:54 +08:00
2248356998 qq.com
8dc70687f8 update solution folder 2023-06-09 14:30:53 +08:00
2248356998 qq.com
fa22f9ee64 upload deviceStatusPage 2023-06-09 10:32:11 +08:00
2248356998 qq.com
b33c0d3f81 update deviceStatusPage 2023-06-09 09:49:03 +08:00
2248356998 qq.com
339009add4 remove dotNET China declaration 2023-06-09 09:10:30 +08:00
2248356998 qq.com
798c823c4b add dotNET China declaration 2023-06-09 09:02:17 +08:00
Diego2098
14ad86f2a3 重启线程时增加运行状态界面空传播防止报错 2023-06-08 21:35:07 +08:00
2248356998 qq.com
a3a714dc17 add upload plugin code description 2023-06-08 17:47:53 +08:00
2248356998 qq.com
e8d8b0d41d 迁移导入变量功能到驱动调试内 2023-06-08 15:11:58 +08:00
2248356998 qq.com
17daad8f89 plugin unload test,but failed 2023-06-08 10:52:39 +08:00
2248356998 qq.com
e178263b3b 更改默认api文档为Knife4j 2023-06-07 20:34:31 +08:00
2248356998 qq.com
4febbc261e 缓存键增加Type-TypeHandle句柄 2023-06-07 18:42:58 +08:00
2248356998 qq.com
ef3a6942fd 修改OPCUA证书路径,增加默认接收不收信任证书与其选项;
OPCDA整理;
2023-06-07 18:03:57 +08:00
2248356998 qq.com
f8ac2be62b 重启线程WebApi修改 2023-06-07 11:32:18 +08:00
2248356998 qq.com
25447c34e5 添加注释提示 2023-06-07 11:28:11 +08:00
2248356998 qq.com
37cdf8fd48 GC策略更改,大量变量实例手动清空以快速内存释放 2023-06-07 11:19:24 +08:00
2248356998 qq.com
ac8e7dc959 上传1.5.1 2023-06-06 19:37:04 +08:00
2248356998 qq.com
8293382840 Merge branch 'master' of https://gitee.com/diego2098/ThingsGateway 2023-06-05 08:33:50 +08:00
Diego2098
d85a3e7743 S7-TCP连接修复死锁 2023-06-02 22:20:21 +08:00
2248356998 qq.com
f3f5ffb5c8 增加KINGVIEW 配置 2023-05-29 01:32:37 +08:00
2248356998 qq.com
99e6702c62 超管用户名称不可更改 2023-05-26 00:14:05 +08:00
2248356998 qq.com
e143c25078 初步添加OPCUAClient调试界面;更新依赖 2023-05-25 23:41:11 +08:00
2248356998 qq.com
3fb67972be OPCUA安全策略添加全部选项 2023-05-25 00:59:21 +08:00
2248356998 qq.com
61c04d4e09 OPCUA安全策略添加全部选项 2023-05-25 00:58:47 +08:00
2248356998 qq.com
b22f728958 添加OPCDAClient调试页面 2023-05-25 00:11:00 +08:00
2248356998 qq.com
112be7e383 修改程序根目录为文件所在目录 2023-05-24 14:37:45 +08:00
2248356998 qq.com
6a7f83fed5 默认添加服务守护支持 2023-05-24 14:32:21 +08:00
2248356998 qq.com
4b9698a735 ModbusServer添加自定义数据类型;修复发布时静态文件路径错误 2023-05-24 12:31:20 +08:00
2248356998 qq.com
ec3d203a6d Add copyright notices 2023-05-23 23:54:28 +08:00
2248356998 qq.com
e77b8f5475 update TGTcpClient 2023-05-23 22:42:48 +08:00
2248356998 qq.com
da8bbd321f 添加Modbus系列插件调试页面;添加Modbus组包解析缓存超时时间; 2023-05-23 20:50:44 +08:00
2248356998 qq.com
98fd011def update HardwareInfoService 2023-05-23 12:04:04 +08:00
2248356998 qq.com
9dccbc5316 nuget更新 2023-05-23 11:59:28 +08:00
2248356998 qq.com
03fa26daf9 硬件界面添加限值防报错 2023-05-23 11:46:19 +08:00
2248356998 qq.com
fbc41e3895 初步添加插件驱动调试页面 2023-05-22 18:50:30 +08:00
2248356998 qq.com
f1a6d0c02c 初步添加插件驱动调试页面 2023-05-22 18:41:09 +08:00
2248356998 qq.com
67f6bb7155 Razor文件格式化清理 2023-05-22 18:40:50 +08:00
2248356998 qq.com
86282f596c 删除调试代码... 2023-05-22 17:09:21 +08:00
2248356998 qq.com
e0f24c795c 更改变量读取间隔限制最低为10ms 2023-05-22 15:17:22 +08:00
2248356998 qq.com
7d44ed860c 明确System.Management版本 2023-05-22 14:51:02 +08:00
2248356998 qq.com
091094a24c 硬件信息获取添加异常拦截 2023-05-22 14:33:30 +08:00
2248356998 qq.com
ba18ee518c update adapter 2023-05-22 12:42:31 +08:00
2248356998 qq.com
513a031691 代码清理 2023-05-21 22:39:33 +08:00
2248356998 qq.com
cc79de1106 优化opcua质量戳提示;添加数据转换基础方法;TCP等待返回时默认断开连接立即返回 2023-05-21 10:51:56 +08:00
2248356998 qq.com
bd90e8efb2 modbus 组包优化 2023-05-20 21:41:16 +08:00
2248356998 qq.com
4bd88ff11d 类型更换 2023-05-20 17:13:14 +08:00
2248356998 qq.com
d27ee61292 可指定OPCUA节点数据类型 2023-05-20 15:40:17 +08:00
2248356998 qq.com
0c20b3345f 更新文档 2023-05-20 13:52:23 +08:00
2248356998 qq.com
0f3c8c7193 添加自定义OPCUAServer数据类型 2023-05-20 12:34:06 +08:00
2248356998 qq.com
16761ec605 导入规则优化,主动抛出名称重复错误 2023-05-19 22:55:53 +08:00
2248356998 qq.com
1069440cda 更改插件时开启刷新设备属性 2023-05-19 22:26:37 +08:00
2248356998 qq.com
60f5702f17 判断OPCUAServer状态时增加tryCatch 2023-05-19 21:27:20 +08:00
2248356998 qq.com
ee70133e47 判断OPCUAServer状态时增加tryCatch 2023-05-19 21:24:56 +08:00
2248356998 qq.com
06a9fdeb2e 优化tcp拆包组包 2023-05-19 20:28:51 +08:00
2248356998 qq.com
f14bd62004 快捷方式null错误 2023-05-19 16:33:57 +08:00
2248356998 qq.com
67cbaf22b7 更新依赖包 2023-05-19 16:23:21 +08:00
2248356998 qq.com
60b166dba2 UDP通讯优化 2023-05-19 16:21:42 +08:00
2248356998 qq.com
66e1647ede 添加链路锁 2023-05-19 14:27:47 +08:00
2248356998 qq.com
a1a35c00a5 分包数量显示错误 2023-05-19 10:13:48 +08:00
2248356998 qq.com
b02e3361c4 Modbus读写锁更新 2023-05-19 10:05:54 +08:00
2248356998 qq.com
2b9ceaa25a Modbus读写锁更新 2023-05-19 09:53:56 +08:00
2248356998 qq.com
109b5a9755 删除sqlsugar旧版本代码,会导致sqlite不兼容 2023-05-19 09:15:32 +08:00
2248356998 qq.com
cc4df86c10 适配mysql;修复写入表达式转换;优化web页面写入体验 2023-05-18 23:38:40 +08:00
2248356998 qq.com
e93532c395 数据库初始化修复 2023-05-18 22:24:27 +08:00
2248356998 qq.com
6ff688326a 数据库连接自动释放 2023-05-18 21:06:06 +08:00
2248356998 qq.com
eda5d2872f 编辑页面添加 变量 允许远程写入选项 2023-05-18 21:03:44 +08:00
2248356998 qq.com
dc88394f5f 修复枚举类型在mysql中类型出错的问题 2023-05-18 20:58:14 +08:00
Diego2098
ec85c9a2c6 修改文件大小限制 2023-05-17 22:29:59 +08:00
Diego2098
1341638556 更新设备读写锁 2023-05-17 22:05:31 +08:00
2248356998 qq.com
4875dfee11 touchSocket修复UDP在windows下重置连接的问题;更新nuget 2023-05-17 16:54:33 +08:00
2248356998 qq.com
d834ba8bd4 代码格式清理 2023-05-17 16:49:25 +08:00
2248356998 qq.com
6191067771 修复CancellationTokenSource未释放导致Linux下偶发内存问题 2023-05-17 16:44:52 +08:00
2248356998 qq.com
6c3a571163 OPCUAServer节点数据类型增加在读取表达式转换后的判断 2023-05-16 09:05:58 +08:00
Diego2098
5efb07e10e ModbusClient添加帧前时间 2023-05-15 22:45:55 +08:00
2248356998 qq.com
b25ec18ce6 修复using作用域导致获取的服务可能被释放的问题 2023-05-15 19:21:35 +08:00
2248356998 qq.com
f3cd281241 nuget更新 2023-05-15 18:55:27 +08:00
2248356998 qq.com
58b93cbf4c mqttClient同步间隔上传的实体类 2023-05-12 18:22:06 +08:00
2248356998 qq.com
57fc0349ff update mqttClient 2023-05-12 16:40:55 +08:00
2248356998 qq.com
d0a2cea772 MqttClient增加间隔上传选项;更改线程循环间隔说明定义 2023-05-12 16:31:57 +08:00
Diego2098
58d5801fb5 update readme 2023-05-10 21:18:43 +08:00
Diego2098
e5f2e59798 增加api控制采集启停等方法 2023-05-10 21:17:34 +08:00
Diego2098
1166921057 提交kafka插件 2023-05-10 21:17:09 +08:00
2248356998 qq.com
aeb49576f2 update readme 2023-05-10 17:49:52 +08:00
2248356998 qq.com
7ef1fecef8 共享链路写入变量修复;Nuget更新 2023-05-10 16:33:59 +08:00
2248356998 qq.com
fd630373b5 更新文档 2023-05-09 17:51:55 +08:00
2248356998 qq.com
d365d8f170 更新文档 2023-05-09 17:47:22 +08:00
2248356998 qq.com
dfa5e1172f OPCUAClient/Server 修改证书有效期为100年 2023-05-09 14:37:18 +08:00
2248356998 qq.com
daf195898a 添加控制台logo 2023-05-08 18:10:07 +08:00
2248356998 qq.com
c61c0a39cf Code Cleanup 2023-05-08 18:03:32 +08:00
2248356998 qq.com
6137e6baa5 add GetSciptValue 2023-05-08 17:45:13 +08:00
2248356998 qq.com
fd16fd9ffe modbus rtu 粘包优化 2023-05-08 15:59:35 +08:00
2248356998 qq.com
2b8bd5f2cc modbus rtu报文粘包优化;共享链路切换延时;上传插件添加报文界面 2023-05-08 15:57:33 +08:00
2248356998 qq.com
d312c2e9e7 plc read with CancellationToken 2023-05-08 13:33:01 +08:00
2248356998 qq.com
578b0d2268 粘包优化 2023-05-08 10:55:16 +08:00
2248356998 qq.com
ffb41b0109 Rpc条件bug修复 2023-05-07 18:06:27 +08:00
2248356998 qq.com
c63fb5d796 OPCUAServer修复匿名登录 2023-05-07 18:06:09 +08:00
2248356998 qq.com
8caee732e8 更新文档 2023-05-07 16:56:41 +08:00
2248356998 qq.com
df5381adce 属性顺序调整 2023-05-05 09:46:11 +08:00
2248356998 qq.com
f34836b7fa 更新文档 2023-05-04 22:58:36 +08:00
2248356998 qq.com
44b459883a update CollectDeviceThread 2023-05-04 10:58:45 +08:00
2248356998 qq.com
14a8592ae3 更新文档 2023-05-02 22:11:55 +08:00
2248356998 qq.com
787d0dce4a 更新1.5.0 2023-05-02 22:06:09 +08:00
2248356998 qq.com
8be05ff93d 1、共享链路支持;
2、设备报文查看;
3、采集线程重构;
2023-05-02 21:58:11 +08:00
2248356998 qq.com
3014af565c mqtt重连锁优化 2023-04-27 11:19:32 +08:00
2248356998 qq.com
315252bdc4 添加常用转换 2023-04-24 17:54:00 +08:00
2248356998 qq.com
c36c3b4607 masa更新 2023-04-24 11:16:28 +08:00
2248356998 qq.com
7d5e939bab 更新包 2023-04-24 09:26:47 +08:00
Diego2098
f75c9d1eed 报警后台服务去除多余接口
Signed-off-by: Diego2098 <2248356998@qq.com>
2023-04-19 00:48:13 +00:00
2248356998 qq.com
38cb9855ea 添加docker文件 2023-04-17 17:39:12 +08:00
2248356998 qq.com
ed8b56d624 单文件发布 2023-04-17 15:13:40 +08:00
2248356998 qq.com
bca48b13ae update SqlSugarConfig 2023-04-17 11:58:41 +08:00
2248356998 qq.com
29426edb05 删除其他信息 2023-04-17 11:05:38 +08:00
2248356998 qq.com
33a2dc687f 验证码更新修复 2023-04-17 09:05:44 +08:00
2248356998 qq.com
e2398a21b2 1、字段null约束修改
2、ModbusServer绑定端口优化
2023-04-16 15:02:09 +08:00
2248356998 qq.com
f19530276e 更新readme 2023-04-16 13:34:29 +08:00
2248356998 qq.com
2b9b92a78c 更新1.4.0
注意Excel导入已不适用以前版本
1、去除动态更新插件
2、改用MiniExcel,支持动态导入,excel配置更简单
3、优化多处界面与后台逻辑,部分方法规范更名
4、修复外网地址获取错误等
2023-04-15 20:48:56 +08:00
2248356998 qq.com
99c55dac10 修复报警文本逻辑 2023-04-11 13:40:13 +08:00
2248356998 qq.com
25667e46f9 1,修复控制台报错(echarts.js问题,已删除)2,多处Dispose修正 2023-04-07 08:48:34 +08:00
2248356998 qq.com
2f4e8f2399 过滤 2023-04-06 14:46:24 +08:00
2248356998 qq.com
9169183769 历史数据库选择为sqlite时查询转换日期错误 2023-04-05 18:04:33 +08:00
2248356998 qq.com
c420f50831 启用开发环境web详细日志,调整App.Razor位置,添加网页ico 2023-04-05 17:14:26 +08:00
2248356998 qq.com
c6c9279ef4 update console/file datetime format 2023-04-05 15:49:00 +08:00
2248356998 qq.com
c125e2991d 更新readme 2023-04-04 18:41:56 +08:00
2248356998 qq.com
5348b19d6a 😀版本1.3.1 2023-04-04 17:55:52 +08:00
2248356998 qq.com
afd426daac 网关软件时间统一UTC 2023-04-04 17:55:15 +08:00
2248356998 qq.com
202c511cfa update iotSharpClient 2023-04-04 11:07:05 +08:00
2248356998 qq.com
651eb295a4 😀 更新1.3.0 2023-04-04 10:15:34 +08:00
2248356998 qq.com
d798aaed33 update iotSharpClient 2023-04-04 09:25:16 +08:00
2248356998 qq.com
63ef347cc9 update iotSharpClient 2023-04-04 09:23:22 +08:00
2248356998 qq.com
3139b2d5a0 IosSharpClient Rpc优化 2023-04-04 09:22:22 +08:00
2248356998 qq.com
2c80bbb244 IotSharp Rpc方法完善 2023-04-04 09:19:48 +08:00
2248356998 qq.com
af06755ada 添加写入多个变量的api方法 2023-04-04 09:18:58 +08:00
2248356998 qq.com
97d6dbaa6c update IotSharpClient 2023-04-03 20:16:38 +08:00
2248356998 qq.com
74cf82a1c7 更新种子 2023-04-03 19:34:12 +08:00
2248356998 qq.com
74634889ab 添加IotSharp插件 2023-04-03 19:30:52 +08:00
2248356998 qq.com
dbe30fcd77 分页显示令牌 2023-04-03 15:29:35 +08:00
2248356998 qq.com
24a7f3a320 后台启动时Furion RootServices NULL值 2023-04-03 15:19:59 +08:00
2248356998 qq.com
d3650f1145 修复不存在采集设备时,初始化报警/历史服务bug 2023-04-03 14:12:56 +08:00
2248356998 qq.com
4801db9050 弹窗消息在SignalR订阅方法中需InvokeAsync 2023-04-03 13:35:14 +08:00
2248356998 qq.com
6445281658 修复规范化结果包装2次导致登录返回结果不正确的问题 2023-04-03 12:45:19 +08:00
2248356998 qq.com
87719f5938 更新演示地址 2023-04-03 10:47:49 +08:00
2248356998 qq.com
5ba1ec433b readme 2023-04-02 18:12:18 +08:00
2248356998 qq.com
7c5b382458 readme 2023-04-02 18:08:56 +08:00
2248356998 qq.com
8960426128 更新readme 2023-04-02 18:05:54 +08:00
2248356998 qq.com
e1d47d5a92 更新readme 2023-04-02 18:05:28 +08:00
2248356998 qq.com
9407c272aa 更新包 2023-04-02 17:10:32 +08:00
2248356998 qq.com
bccbd7b400 添加注释 2023-04-02 16:59:46 +08:00
2248356998 qq.com
a24dc010ec 调整依赖,添加关系图 2023-04-01 17:28:35 +08:00
2248356998 qq.com
c5e5d50fb8 调整依赖,更新版本1.2.1 2023-04-01 15:45:02 +08:00
2248356998 qq.com
be1c520320 整理 2023-04-01 13:57:57 +08:00
2248356998 qq.com
3d18d0f893 😀 OPCUAServer支持历史查询数据 2023-03-31 18:32:55 +08:00
2248356998 qq.com
c3351a38a6 添加ThingsGateway.Foundation注释 2023-03-31 16:25:33 +08:00
2248356998 qq.com
0b86340a8d 硬件信息获取添加延时 2023-03-30 20:51:08 +08:00
2248356998 qq.com
829371b032 脚本显示优化 2023-03-30 19:51:38 +08:00
2248356998 qq.com
b342207bc7 更新文档 2023-03-30 19:39:35 +08:00
2248356998 qq.com
58f4fdced3 mqtt/mq上传 添加上传实体自定义脚本 2023-03-30 19:07:18 +08:00
2248356998 qq.com
253844cbcf 表达式整理 2023-03-30 16:23:03 +08:00
2248356998 qq.com
e2e2b9ffb4 更新版本 2023-03-30 14:12:39 +08:00
2248356998 qq.com
2568042f5f 更新文档 2023-03-30 14:11:16 +08:00
2248356998 qq.com
722edf4b9a readme 2023-03-30 14:06:03 +08:00
2248356998 qq.com
e406d364e4 更新readme,nuget 2023-03-30 14:05:00 +08:00
2248356998 qq.com
31c37f41b2 删除多余代码 2023-03-30 13:53:57 +08:00
2248356998 qq.com
6cd879bbc5 opcua 写入添加用户名日志 2023-03-30 13:32:32 +08:00
2248356998 qq.com
b7974050fe 去除ua数据类型验证 2023-03-30 13:20:26 +08:00
2248356998 qq.com
e9c9d0816e 更新readme 2023-03-30 13:13:44 +08:00
2248356998 qq.com
a437692e1a 类命名错误更改 2023-03-30 13:11:46 +08:00
2248356998 qq.com
2a14d2f3c8 发布文件添加 2023-03-30 13:11:43 +08:00
2248356998 qq.com
559e2d1889 添加OPCUAServer插件,修复个别bug 2023-03-30 13:10:31 +08:00
Diego2098
a1aa919f80 1、OPCUAClient修复客户端证书未自动生成
2、修复异步方法错误使用
2023-03-30 00:15:13 +08:00
2248356998 qq.com
cbccb27a5a 添加部分代码注释 2023-03-29 16:22:01 +08:00
2248356998 qq.com
bbad36d576 驱动支持主机名称 2023-03-29 11:07:21 +08:00
2248356998 qq.com
df6c9d55b5 修复初始化失败导致的一系列问题 2023-03-29 10:53:42 +08:00
2248356998 qq.com
36a1d9c364 上传插件间隔时间修正 2023-03-28 16:40:00 +08:00
2248356998 qq.com
1f3681d5ac 历史变量enable失效 2023-03-28 16:38:29 +08:00
2248356998 qq.com
0159f8e53f 历史报表时间格式改为yyyy-MM-dd HH:mm:ss ffffff 2023-03-28 16:31:53 +08:00
2248356998 qq.com
0432be64fc 采集设备状态判断错误 2023-03-28 16:21:30 +08:00
2248356998 qq.com
481e062961 采集设备状态判断错误 2023-03-28 15:55:01 +08:00
2248356998 qq.com
72b8abdeb6 修复历史保存值 频繁时出现值相同的问题 2023-03-28 15:14:30 +08:00
2248356998 qq.com
7ec3ee41d1 opc 活动时间修正 2023-03-28 14:15:14 +08:00
2248356998 qq.com
b765fa4769 添加写入采集时间的接口,而不是固定DateTime.Now 2023-03-28 14:03:11 +08:00
2248356998 qq.com
06685b162e 更新tcpclient 2023-03-28 13:52:33 +08:00
2248356998 qq.com
7bcad7c424 修复linux 分隔符错误问题 2023-03-28 11:48:16 +08:00
2248356998 qq.com
6e054b3cc6 更改插件文件不存在时的日志信息 2023-03-28 10:21:39 +08:00
2248356998 qq.com
e643f6b0f8 更改项目引用结构 2023-03-28 10:21:23 +08:00
2248356998 qq.com
e44c0f85c2 swagger文档 2023-03-27 19:01:04 +08:00
Iot边缘设备
ea66e968eb !5 添加部署文档
* 添加部署文档
2023-03-27 10:22:30 +00:00
2248356998 qq.com
f7e73d804e 属性/字段缓存获取只包含public 2023-03-27 14:49:09 +08:00
2248356998 qq.com
2ff4df56a1 更新masa-1.0.0-preview.10 2023-03-27 14:27:15 +08:00
2248356998 qq.com
346c45fe0c 优化变量上传属性页 2023-03-27 12:00:10 +08:00
2248356998 qq.com
f98b42a36e 采集设备活动时间应正常刷新 2023-03-27 10:51:54 +08:00
2248356998 qq.com
f77a0a266c 添加设备复制功能 2023-03-27 10:42:02 +08:00
2248356998 qq.com
0be672788f update code collation 2023-03-27 08:49:10 +08:00
2248356998 qq.com
e2e3d11d42 update code collation 2023-03-26 19:48:08 +08:00
2248356998 qq.com
bb127bb567 更新nuget包 2023-03-26 18:52:16 +08:00
2248356998 qq.com
8eb4f89db8 发行1.10版本 2023-03-26 18:10:12 +08:00
2248356998 qq.com
4a87ea3e70 实时数据界面优化 2023-03-26 17:39:05 +08:00
2248356998 qq.com
61115fce99 1、采用异步AutoResetEvent,修复多个设备下采集太慢的问题
2、弃用IntelligentConcurrentQueue(touchsocket集成类)
2023-03-26 17:32:29 +08:00
2248356998 qq.com
4f31120394 1、优化设备状态页,减少signalr刷新所需包大小
2、日志前置等级添加
2023-03-24 18:32:10 +08:00
2248356998 qq.com
b085cd65ce 修复导出表格时,null值报错 2023-03-23 22:09:53 +08:00
2248356998 qq.com
f76ec0721a 导入错误时,忽略大于10行的错误信息显示 2023-03-23 20:01:19 +08:00
2248356998 qq.com
ef3944fbbf 更新readme 2023-03-22 15:29:35 +08:00
2248356998 qq.com
b158fbc0d8 优化log等级、json配置注解 2023-03-22 15:26:42 +08:00
2248356998 qq.com
68f2d66e97 OPCUA写入测试 2023-03-22 14:06:32 +08:00
2248356998 qq.com
0cdd1735bd 设备运行状态页面改为扩展 2023-03-22 13:46:23 +08:00
2248356998 qq.com
70f5ead20b 更新文档 2023-03-22 10:44:44 +08:00
Diego2098
574e5616f8 rbmq插件优化 2023-03-21 23:38:00 +08:00
Diego2098
94fa810590 分包失败提示 2023-03-21 23:28:30 +08:00
Diego2098
37f69da701 设备组列宽调整,补充上传设备组 2023-03-21 23:10:59 +08:00
Diego2098
f2f8448ade 1、更新DataTypeEnum
2、OPCUA写入时需实际数据类型
2023-03-21 22:47:10 +08:00
Diego2098
b357d3fff2 更新Tests 2023-03-21 22:46:12 +08:00
2248356998 qq.com
b417194905 表格无数据时,修改默认宽度 2023-03-21 18:17:18 +08:00
2248356998 qq.com
d8741da20a S7nuget版本 2023-03-21 15:44:50 +08:00
2248356998 qq.com
c469be9a62 masa nuget版本更改 2023-03-21 14:31:36 +08:00
2248356998 qq.com
ff4eb339ef GC策略修改 2023-03-21 14:07:17 +08:00
2248356998 qq.com
78489383c0 更新文档 2023-03-21 14:03:49 +08:00
2248356998 qq.com
f67c1b415f 更新文档 2023-03-21 13:56:14 +08:00
2248356998 qq.com
570c16d921 修改s7属性注释 2023-03-21 13:51:05 +08:00
2248356998 qq.com
c8bc60568a 更新readme 2023-03-21 13:49:10 +08:00
2248356998 qq.com
73de3ba856 更新S7协议插件 2023-03-21 13:45:58 +08:00
2248356998 qq.com
6a69be8537 修改S7特殊方法 2023-03-21 13:41:32 +08:00
2248356998 qq.com
3ee381d505 修改s7 2023-03-21 13:38:43 +08:00
2248356998 qq.com
7ce744e2e4 添加西门子S7协议插件 2023-03-21 13:37:17 +08:00
2248356998 qq.com
b81d21c991 版本恢复 2023-03-21 11:45:18 +08:00
2248356998 qq.com
e9fe0992c6 更新nuget,暂缓链路复用功能 2023-03-20 13:34:59 +08:00
2248356998 qq.com
d5ef9018fa 默认不开启转储 2023-03-20 09:22:11 +08:00
2248356998 qq.com
c2737a7c51 更新opcda文档 2023-03-19 23:18:24 +08:00
2248356998 qq.com
4b6d8733c6 格式清理 2023-03-19 23:12:58 +08:00
2248356998 qq.com
f22a3e0955 修复null值报错 2023-03-19 23:02:08 +08:00
2248356998 qq.com
4b8144a2f7 添加设备组,变量按设备组别搜索 2023-03-19 22:56:02 +08:00
2248356998 qq.com
abac52e23c 更新readme,opcda核心库提示 2023-03-19 20:40:54 +08:00
2248356998 qq.com
9aa089313e 尝试修复中文在mac上乱码 2023-03-19 17:29:01 +08:00
2248356998 qq.com
b18f2c481a 修正中文在mac上乱码 2023-03-19 16:45:14 +08:00
2248356998 qq.com
ec83b9f77b 删除未知文件 2023-03-19 16:35:24 +08:00
2248356998 qq.com
fad5495e02 Merge branch 'master' of https://gitee.com/diego2098/ThingsGateway 2023-03-19 16:34:26 +08:00
2248356998 qq.com
70dec1171e 添加设备组功能 2023-03-19 16:34:15 +08:00
士心
0673a6fce3 !4 修复MacOS环境下,数据库报错的问题
* 修复macos环境下,数据库报错
2023-03-19 08:28:54 +00:00
2248356998 qq.com
8f525b1407 准备更新设备组/变量组功能 2023-03-19 11:49:06 +08:00
2248356998 qq.com
e83a991a4b 更新ReadMe 2023-03-18 17:56:18 +08:00
2248356998 qq.com
c000432a52 1、最后校验失败时应该提示日志
2、暂停时设备状态修正
2023-03-18 17:49:08 +08:00
2248356998 qq.com
c06d2d6927 更新文档 2023-03-18 16:47:29 +08:00
2248356998 qq.com
aa29653a8f ByteBlock实际长度 2023-03-18 16:45:39 +08:00
2248356998 qq.com
3f7e4ad486 修正串口描述类ToString 2023-03-18 16:32:15 +08:00
2248356998 qq.com
0eab546b2f 更新文档 2023-03-18 16:23:23 +08:00
2248356998 qq.com
8830d216d1 更新nuget 2023-03-18 16:16:27 +08:00
2248356998 qq.com
9fa1e3d449 更新readme 2023-03-18 16:15:14 +08:00
2248356998 qq.com
fe5dce7159 添加ModbusRtu种子数据 2023-03-18 16:14:37 +08:00
2248356998 qq.com
952fa31548 添加ModbusRtu插件 2023-03-18 16:14:25 +08:00
2248356998 qq.com
cc058ccc61 添加串口基础类 2023-03-18 16:14:08 +08:00
2248356998 qq.com
bc26ed9701 更新文档 2023-03-17 18:19:14 +08:00
2248356998 qq.com
26135fc1a0 更新文档 2023-03-17 17:52:04 +08:00
2248356998 qq.com
0bd14672ff 种子数据更改 2023-03-17 17:51:58 +08:00
2248356998 qq.com
7c7150cde8 采集检测间隔修改 2023-03-17 17:40:34 +08:00
2248356998 qq.com
b08282b0c1 上传插件添加循环间隔属性 2023-03-17 17:30:06 +08:00
2248356998 qq.com
3bf6e1befc 添加rbmq插件种子数据 2023-03-17 16:30:02 +08:00
2248356998 qq.com
52692371ac rbmq插件文件夹更名 2023-03-17 16:16:23 +08:00
2248356998 qq.com
159ac1d8bb 优化内存queue,修复mqtt插件可能超出字节限制的情况 2023-03-17 16:04:24 +08:00
2248356998 qq.com
7f1ffdbc79 添加rbmq插件 2023-03-17 16:03:44 +08:00
2248356998 qq.com
5fe64931dc 设备禁用时,变量绑定的设备对应选项会显示禁用(灰色) 2023-03-17 11:29:14 +08:00
2248356998 qq.com
ee67855b48 更新readme 2023-03-16 17:33:25 +08:00
2248356998 qq.com
594a97f43f 选择插件时自动更新属性 2023-03-16 17:33:17 +08:00
2248356998 qq.com
7fb435a8b4 更新赞助名单 2023-03-16 11:35:58 +08:00
2248356998 qq.com
01e74d6116 限流服务默认不开启 2023-03-16 09:47:20 +08:00
2248356998 qq.com
b321d75b39 增加简易定时看板 2023-03-15 16:01:54 +08:00
2248356998 qq.com
1e47a45723 更新历史配置说明 2023-03-15 09:11:33 +08:00
Diego2098
88c609e5ef !3 update handbook/docs/05、网关配置/5.5、其他配置.mdx.
Merge pull request !3 from zhubanghao/N/A
2023-03-14 13:39:16 +00:00
zhubanghao
775d1a424e update handbook/docs/05、网关配置/5.5、其他配置.mdx.
Signed-off-by: zhubanghao <58813184@qq.com>
2023-03-14 13:05:33 +00:00
1785 changed files with 28982 additions and 36059 deletions

2
.gitignore vendored
View File

@@ -363,4 +363,6 @@ MigrationBackup/
FodyWeavers.xsd
/framework/*pro*
/framework/*Pro*

View File

@@ -1,7 +0,0 @@
[*.cs]
# CA1848: 使用 LoggerMessage 委托
dotnet_diagnostic.CA1848.severity = none
# CA2254: 模板应为静态表达式
dotnet_diagnostic.CA2254.severity = suggestion

View File

@@ -1,63 +0,0 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

364
framework/.gitignore vendored
View File

@@ -1,364 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@@ -1,15 +0,0 @@
<Project>
<PropertyGroup>
<Version>3.0.0.8</Version>
<LangVersion>latest</LangVersion>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Authors>Diego</Authors>
<Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright>
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
</PropertyGroup>
</Project>

View File

@@ -1,148 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'">
<DefineConstants>Pro</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'">
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor.cs" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor.cs" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor" />
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Melsec\ThingsGateway.Foundation.Adapter.Melsec.csproj" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor.cs" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor.cs" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor" />
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.AllenBradleyCip\ThingsGateway.Foundation.Adapter.AllenBradleyCip.csproj" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsTcpDebugPage.razor.cs" Link="Pages\OmronFins\OmronFinsTcpDebugPage.razor.cs" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsUdpDebugPage.razor.cs" Link="Pages\OmronFins\OmronFinsUdpDebugPage.razor.cs" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsTcpDebugPage.razor" Link="Pages\OmronFins\OmronFinsTcpDebugPage.razor" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsUdpDebugPage.razor" Link="Pages\OmronFins\OmronFinsUdpDebugPage.razor" />
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Omron\ThingsGateway.Foundation.Adapter.Omron.csproj" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Secs\Page\SecsHsmsTcpDebugPage.razor.cs" Link="Pages\Secs\SecsHsmsTcpDebugPage.razor.cs" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Secs\Page\SecsHsmsTcpDebugPage.razor" Link="Pages\Secs\SecsHsmsTcpDebugPage.razor" />
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Secs\ThingsGateway.Foundation.Adapter.Secs.csproj" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.TS550\Page\TS550DebugPage.razor.cs" Link="Pages\TS550\TS550DebugPage.razor.cs" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.TS550\Page\TS550DebugPage.razor" Link="Pages\TS550\TS550DebugPage.razor" />
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.TS550\ThingsGateway.Foundation.Adapter.TS550.csproj" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialDebugPage.razor.cs" Link="Pages\Vigor\VigorSerialDebugPage.razor.cs" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialOverTcpDebugPage.razor.cs" Link="Pages\Vigor\VigorSerialOverTcpDebugPage.razor.cs" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialDebugPage.razor" Link="Pages\Vigor\VigorSerialDebugPage.razor" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialOverTcpDebugPage.razor" Link="Pages\Vigor\VigorSerialOverTcpDebugPage.razor" />
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Vigor\ThingsGateway.Foundation.Adapter.Vigor.csproj" />
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialDebugPage.razor.cs" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialDebugPage.razor.cs" />
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialOverTcpDebugPage.razor.cs" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialOverTcpDebugPage.razor.cs" />
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialDebugPage.razor" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialDebugPage.razor" />
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialOverTcpDebugPage.razor" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialOverTcpDebugPage.razor" />
<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.HZW_QTJC_01\ThingsGateway.Foundation.Adapter.HZW_QTJC_01.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007DebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\MqttRpcNameVaueWithId.cs" Link="Pages\Mqtt\MqttRpcNameVaueWithId.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor.cs" Link="Pages\Mqtt\MqttClientDebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor.cs" Link="Pages\Mqtt\MqttClientPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\PrivateLogger.cs" Link="Pages\Mqtt\PrivateLogger.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClient.cs" Link="Pages\Mqtt\MqttRpcClient.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClientExtensions.cs" Link="Pages\Mqtt\MqttRpcClientExtensions.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcTopicPair.cs" Link="Pages\Mqtt\MqttRpcTopicPair.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor" Link="Pages\DLT645\DLT645_2007DebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor" Link="Pages\Modbus\ModbusRtuDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverTcpDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuOverTcpDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverTcpDebugPage.razor" Link="Pages\Modbus\ModbusRtuOverTcpDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverUdpDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuOverUdpDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverUdpDebugPage.razor" Link="Pages\Modbus\ModbusRtuOverUdpDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusSerialServerDebugPage.razor.cs" Link="Pages\Modbus\ModbusSerialServerDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusSerialServerDebugPage.razor" Link="Pages\Modbus\ModbusSerialServerDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDebugPage.razor.cs" Link="Pages\Modbus\ModbusTcpDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDebugPage.razor" Link="Pages\Modbus\ModbusTcpDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDtuDebugPage.razor.cs" Link="Pages\Modbus\ModbusTcpDtuDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDtuDebugPage.razor" Link="Pages\Modbus\ModbusTcpDtuDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpServerDebugPage.razor.cs" Link="Pages\Modbus\ModbusTcpServerDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpServerDebugPage.razor" Link="Pages\Modbus\ModbusTcpServerDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusUdpDebugPage.razor.cs" Link="Pages\Modbus\ModbusUdpDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusUdpDebugPage.razor" Link="Pages\Modbus\ModbusUdpDebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientDebugPage.razor.cs" Link="Pages\OPCDA\OPCDAClientDebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientPage.razor.cs" Link="Pages\OPCDA\OPCDAClientPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAImportVariable.razor.cs" Link="Pages\OPCDA\OPCDAImportVariable.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientDebugPage.razor" Link="Pages\OPCDA\OPCDAClientDebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientPage.razor" Link="Pages\OPCDA\OPCDAClientPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAImportVariable.razor" Link="Pages\OPCDA\OPCDAImportVariable.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientDebugPage.razor" Link="Pages\OPCUA\OPCUAClientDebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientPage.razor" Link="Pages\OPCUA\OPCUAClientPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAImportVariable.razor" Link="Pages\OPCUA\OPCUAImportVariable.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientDebugPage.razor.cs" Link="Pages\OPCUA\OPCUAClientDebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientPage.razor.cs" Link="Pages\OPCUA\OPCUAClientPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAImportVariable.razor.cs" Link="Pages\OPCUA\OPCUAImportVariable.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1200DebugPage.razor" Link="Pages\Siemens\S7_1200DebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1500DebugPage.razor" Link="Pages\Siemens\S7_1500DebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200DebugPage.razor" Link="Pages\Siemens\S7_200DebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200SMARTDebugPage.razor" Link="Pages\Siemens\S7_200SMARTDebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_300DebugPage.razor" Link="Pages\Siemens\S7_300DebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_400DebugPage.razor" Link="Pages\Siemens\S7_400DebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1200DebugPage.razor.cs" Link="Pages\Siemens\S7_1200DebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1500DebugPage.razor.cs" Link="Pages\Siemens\S7_1500DebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200DebugPage.razor.cs" Link="Pages\Siemens\S7_200DebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200SMARTDebugPage.razor.cs" Link="Pages\Siemens\S7_200SMARTDebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_300DebugPage.razor.cs" Link="Pages\Siemens\S7_300DebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_400DebugPage.razor.cs" Link="Pages\Siemens\S7_400DebugPage.razor.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj" />
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj" />
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj" />
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj" />
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj" />
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Pages\Mqtt\" />
</ItemGroup>
<ItemGroup>
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor" Link="Pages\Mqtt\MqttClientDebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor" Link="Pages\Mqtt\MqttClientPage.razor" />
<PackageReference Include="MQTTnet" Version="4.3.1.873" />
</ItemGroup>
</Project>

View File

@@ -1,9 +1,10 @@
<Project>
<PropertyGroup>
<Version>3.0.0.8</Version>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0;</TargetFrameworks>
<Version>4.0.0.6</Version>
<LangVersion>latest</LangVersion>
<Authors>Diego</Authors>
<Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright>
@@ -11,7 +12,7 @@
<SignAssembly>True</SignAssembly>
<DelaySign>False</DelaySign>
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
</PropertyGroup>

View File

@@ -1,480 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.DLT645;
/// <summary>
/// DLT645_2007
/// </summary>
public class DLT645_2007 : ReadWriteDevicesSerialSessionBase
{
/// <summary>
/// DLT645_2007
/// </summary>
/// <param name="serialSession"></param>
public DLT645_2007(SerialSession serialSession) : base(serialSession)
{
ThingsGatewayBitConverter = new DLT645_2007BitConverter(EndianType.Big);
RegisterByteLength = 2;
}
/// <summary>
/// 增加FE FE FE FE的报文头部
/// </summary>
[Description("前导符报文头")]
public bool EnableFEHead { get; set; }
/// <summary>
/// 写入需操作员代码
/// </summary>
[Description("操作员代码")]
public string OperCode { get; set; }
/// <summary>
/// 写入密码
/// </summary>
[Description("写入密码")]
public string Password { get; set; }
/// <summary>
/// 通讯地址BCD码一般应该是12个字符
/// </summary>
[Description("通讯地址")]
public string Station { get; set; }
/// <inheritdoc/>
public override string GetAddressDescription()
{
var str = """
-----------------------------------------
02010100 A相电压
02020100 A相电流
02030000
00000000 ()
00010000 ()
""";
return base.GetAddressDescription() + Environment.NewLine + str;
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
try
{
Connect(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
if (commandResult.IsSuccess)
{
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override void SetDataAdapter(object socketClient = null)
{
var dataHandleAdapter = new DLT645_2007DataHandleAdapter
{
EnableFEHead = EnableFEHead
};
SerialSession.SetDataHandlingAdapter(dataHandleAdapter);
}
/// <inheritdoc/>
public override OperResult Write(string address, string value, CancellationToken cancellationToken = default)
{
try
{
Connect(cancellationToken);
Password ??= string.Empty;
OperCode ??= string.Empty;
if (Password.Length < 8)
Password = Password.PadLeft(8, '0');
if (OperCode.Length < 8)
OperCode = OperCode.PadLeft(8, '0');
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
if (commandResult.IsSuccess)
{
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override async Task<OperResult> WriteAsync(string address, string value, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
Password ??= string.Empty;
OperCode ??= string.Empty;
if (Password.Length < 8)
Password = Password.PadLeft(8, '0');
if (OperCode.Length < 8)
OperCode = OperCode.PadLeft(8, '0');
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, uint value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, double value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, float value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, long value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, ulong value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, ushort value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, short value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, int value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
#region
/// <summary>
/// 广播校时
/// </summary>
/// <param name="dateTime"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public OperResult BroadcastTime(DateTime dateTime, CancellationToken cancellationToken = default)
{
try
{
Connect(cancellationToken);
string str = $"{dateTime.Second:D2}{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}{dateTime.Year % 100:D2}";
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.BroadcastTime, str.ByHexStringToBytes().ToArray(), "999999999999".ByHexStringToBytes());
if (commandResult.IsSuccess)
{
SerialSession.Send(commandResult.Content);
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 冻结
/// </summary>
/// <param name="dateTime"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> FreezeAsync(DateTime dateTime, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
string str = $"{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}";
if (Station.IsNullOrEmpty()) Station = string.Empty;
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.Freeze, str.ByHexStringToBytes().ToArray(), Station.ByHexStringToBytes().Reverse().ToArray());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 读取通信地址
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult<string>> ReadDeviceStationAsync(CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.ReadStation, null, "AAAAAAAAAAAA".ByHexStringToBytes());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
var buffer = result1.Content.SelectMiddle(0, 6).BytesAdd(-0x33);
return OperResult.CreateSuccessResult(buffer.Reverse().ToArray().ToHexString());
}
else
{
return new OperResult<string>(result1);
}
}
else
{
return new OperResult<string>(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 修改波特率
/// </summary>
/// <param name="baudRate"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> WriteBaudRateAsync(int baudRate, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
byte baudRateByte;
switch (baudRate)
{
case 600: baudRateByte = 0x02; break;
case 1200: baudRateByte = 0x04; break;
case 2400: baudRateByte = 0x08; break;
case 4800: baudRateByte = 0x10; break;
case 9600: baudRateByte = 0x20; break;
case 19200: baudRateByte = 0x40; break;
default: return new OperResult<string>($"不支持此波特率:{baudRate}");
}
if (Station.IsNullOrEmpty()) Station = string.Empty;
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteBaudRate, new byte[] { baudRateByte }, Station.ByHexStringToBytes().Reverse().ToArray());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 更新通信地址
/// </summary>
/// <param name="station"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> WriteDeviceStationAsync(string station, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteStation, station.ByHexStringToBytes().Reverse().ToArray(), "AAAAAAAAAAAA".ByHexStringToBytes());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 修改密码
/// </summary>
/// <param name="level"></param>
/// <param name="oldPassword"></param>
/// <param name="newPassword"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> WritePasswordAsync(byte level, string oldPassword, string newPassword, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
if (Station.IsNullOrEmpty()) Station = string.Empty;
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
string str = $"04000C{(level + 1):D2}";
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WritePassword,
str.ByHexStringToBytes().Reverse().ToArray()
.SpliceArray(oldPassword.ByHexStringToBytes().Reverse().ToArray())
.SpliceArray(newPassword.ByHexStringToBytes().Reverse().ToArray())
, Station.ByHexStringToBytes().Reverse().ToArray());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
#endregion
}

View File

@@ -1,480 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.DLT645;
/// <summary>
/// DLT645_2007
/// </summary>
public class DLT645_2007OverTcp : ReadWriteDevicesTcpClientBase
{
/// <summary>
/// DLT645_2007
/// </summary>
/// <param name="tcpClient"></param>
public DLT645_2007OverTcp(TcpClient tcpClient) : base(tcpClient)
{
ThingsGatewayBitConverter = new DLT645_2007BitConverter(EndianType.Big);
RegisterByteLength = 2;
}
/// <summary>
/// 增加FE FE FE FE的报文头部
/// </summary>
[Description("前导符报文头")]
public bool EnableFEHead { get; set; }
/// <summary>
/// 写入需操作员代码
/// </summary>
[Description("操作员代码")]
public string OperCode { get; set; }
/// <summary>
/// 写入密码
/// </summary>
[Description("写入密码")]
public string Password { get; set; }
/// <summary>
/// 通讯地址BCD码一般应该是12个字符
/// </summary>
[Description("通讯地址")]
public string Station { get; set; }
/// <inheritdoc/>
public override string GetAddressDescription()
{
var str = """
-----------------------------------------
02010100 A相电压
02020100 A相电流
02030000
00000000 ()
00010000 ()
""";
return base.GetAddressDescription() + Environment.NewLine + str;
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
try
{
Connect(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
if (commandResult.IsSuccess)
{
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override void SetDataAdapter(object socketClient = null)
{
var dataHandleAdapter = new DLT645_2007DataHandleAdapter
{
EnableFEHead = EnableFEHead
};
TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
}
/// <inheritdoc/>
public override OperResult Write(string address, string value, CancellationToken cancellationToken = default)
{
try
{
Connect(cancellationToken);
Password ??= string.Empty;
OperCode ??= string.Empty;
if (Password.Length < 8)
Password = Password.PadLeft(8, '0');
if (OperCode.Length < 8)
OperCode = OperCode.PadLeft(8, '0');
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
if (commandResult.IsSuccess)
{
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override async Task<OperResult> WriteAsync(string address, string value, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
Password ??= string.Empty;
OperCode ??= string.Empty;
if (Password.Length < 8)
Password = Password.PadLeft(8, '0');
if (OperCode.Length < 8)
OperCode = OperCode.PadLeft(8, '0');
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, uint value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, double value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, float value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, long value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, ulong value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, ushort value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, short value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, int value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
#region
/// <summary>
/// 广播校时
/// </summary>
/// <param name="dateTime"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public OperResult BroadcastTime(DateTime dateTime, CancellationToken cancellationToken = default)
{
try
{
Connect(cancellationToken);
string str = $"{dateTime.Second:D2}{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}{dateTime.Year % 100:D2}";
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.BroadcastTime, str.ByHexStringToBytes().Reverse().ToArray(), "999999999999".ByHexStringToBytes());
if (commandResult.IsSuccess)
{
TcpClient.Send(commandResult.Content);
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 冻结
/// </summary>
/// <param name="dateTime"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> FreezeAsync(DateTime dateTime, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
string str = $"{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}";
if (Station.IsNullOrEmpty()) Station = string.Empty;
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.Freeze, str.ByHexStringToBytes().Reverse().ToArray(), Station.ByHexStringToBytes().Reverse().ToArray());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 读取通信地址
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult<string>> ReadDeviceStationAsync(CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.ReadStation, null, "AAAAAAAAAAAA".ByHexStringToBytes());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
var buffer = result1.Content.SelectMiddle(0, 6).BytesAdd(-0x33);
return OperResult.CreateSuccessResult(buffer.Reverse().ToArray().ToHexString());
}
else
{
return new OperResult<string>(result1);
}
}
else
{
return new OperResult<string>(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 修改波特率
/// </summary>
/// <param name="baudRate"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> WriteBaudRateAsync(int baudRate, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
byte baudRateByte;
switch (baudRate)
{
case 600: baudRateByte = 0x02; break;
case 1200: baudRateByte = 0x04; break;
case 2400: baudRateByte = 0x08; break;
case 4800: baudRateByte = 0x10; break;
case 9600: baudRateByte = 0x20; break;
case 19200: baudRateByte = 0x40; break;
default: return new OperResult<string>($"不支持此波特率:{baudRate}");
}
if (Station.IsNullOrEmpty()) Station = string.Empty;
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteBaudRate, new byte[] { baudRateByte }, Station.ByHexStringToBytes().Reverse().ToArray());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 更新通信地址
/// </summary>
/// <param name="station"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> WriteDeviceStationAsync(string station, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteStation, station.ByHexStringToBytes().Reverse().ToArray(), "AAAAAAAAAAAA".ByHexStringToBytes());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
/// <summary>
/// 修改密码
/// </summary>
/// <param name="level"></param>
/// <param name="oldPassword"></param>
/// <param name="newPassword"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OperResult> WritePasswordAsync(byte level, string oldPassword, string newPassword, CancellationToken cancellationToken = default)
{
try
{
await ConnectAsync(cancellationToken);
if (Station.IsNullOrEmpty()) Station = string.Empty;
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
string str = $"04000C{level:D2}";
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WritePassword,
str.ByHexStringToBytes().Reverse().ToArray()
.SpliceArray(oldPassword.ByHexStringToBytes().Reverse().ToArray())
.SpliceArray(newPassword.ByHexStringToBytes().Reverse().ToArray())
, Station.ByHexStringToBytes().Reverse().ToArray());
if (commandResult.IsSuccess)
{
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
var result1 = ((MessageBase)result.RequestInfo);
if (result1.IsSuccess)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result1);
}
}
else
{
return new OperResult(commandResult);
}
}
catch (Exception ex)
{
return new OperResult<string>(ex);
}
}
#endregion
}

View File

@@ -1,421 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections.Concurrent;
using ThingsGateway.Foundation.Extension.Bool;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
{
/// <summary>
/// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
/// </summary>
public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, Task<OperResult>> WriteData;
/// <summary>
/// 继电器
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer01ByteBlocks = new();
/// <summary>
/// 开关输入
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer02ByteBlocks = new();
/// <summary>
/// 输入寄存器
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer03ByteBlocks = new();
/// <summary>
/// 保持寄存器
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer04ByteBlocks = new();
/// <inheritdoc/>
public ModbusSerialServer(SerialSession serialSession) : base(serialSession)
{
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
RegisterByteLength = 2;
}
/// <summary>
/// 多站点
/// </summary>
public bool MulStation { get; set; }
/// <summary>
/// 默认站点
/// </summary>
public byte Station { get; set; } = 1;
/// <inheritdoc/>
public override void Dispose()
{
foreach (var item in ModbusServer01ByteBlocks)
{
item.Value.SafeDispose();
}
foreach (var item in ModbusServer02ByteBlocks)
{
item.Value.SafeDispose();
}
foreach (var item in ModbusServer03ByteBlocks)
{
item.Value.SafeDispose();
}
foreach (var item in ModbusServer04ByteBlocks)
{
item.Value.SafeDispose();
}
ModbusServer01ByteBlocks.Clear();
ModbusServer02ByteBlocks.Clear();
ModbusServer03ByteBlocks.Clear();
ModbusServer04ByteBlocks.Clear();
base.Dispose();
}
/// <inheritdoc/>
public override string GetAddressDescription()
{
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
ModbusAddress mAddress;
try
{
mAddress = ModbusAddress.ParseFrom(address, Station);
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
if (MulStation)
{
Init(mAddress);
}
else
{
if (Station != mAddress.Station)
{
return new OperResult<byte[]>("地址错误");
}
Init(mAddress);
}
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
switch (mAddress.ReadFunction)
{
case 1:
byte[] bytes0 = new byte[len];
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
ModbusServer01ByteBlock.Read(bytes0);
return OperResult.CreateSuccessResult(bytes0);
case 2:
byte[] bytes1 = new byte[len];
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
ModbusServer02ByteBlock.Read(bytes1);
return OperResult.CreateSuccessResult(bytes1);
case 3:
byte[] bytes3 = new byte[len];
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer03ByteBlock.Read(bytes3);
return OperResult.CreateSuccessResult(bytes3);
case 4:
byte[] bytes4 = new byte[len];
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer04ByteBlock.Read(bytes4);
return OperResult.CreateSuccessResult(bytes4);
}
return new OperResult<byte[]>("功能码错误");
}
/// <inheritdoc/>
public override Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
{
return Task.FromResult(Read(address, length));
}
/// <inheritdoc/>
public override void SetDataAdapter(object socketClient)
{
ModbusSerialServerDataHandleAdapter dataHandleAdapter = new();
dataHandleAdapter.CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout);
SerialSession.SetDataHandlingAdapter(dataHandleAdapter);
}
/// <inheritdoc/>
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
{
ModbusAddress mAddress;
try
{
mAddress = ModbusAddress.ParseFrom(address, Station);
}
catch (Exception ex)
{
return new OperResult(ex);
}
if (MulStation)
{
Init(mAddress);
}
else
{
if (Station != mAddress.Station)
{
return new OperResult("地址错误");
}
Init(mAddress);
}
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
switch (mAddress.ReadFunction)
{
case 3:
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer03ByteBlock.Write(value);
return OperResult.CreateSuccessResult();
case 4:
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer04ByteBlock.Write(value);
return OperResult.CreateSuccessResult();
}
return new OperResult("功能码错误");
}
/// <inheritdoc/>
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
{
ModbusAddress mAddress;
try
{
mAddress = ModbusAddress.ParseFrom(address, Station);
}
catch (Exception ex)
{
return (new OperResult(ex));
}
if (MulStation)
{
Init(mAddress);
}
else
{
if (Station != mAddress.Station)
{
return (new OperResult("地址错误"));
}
Init(mAddress);
}
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
switch (mAddress.ReadFunction)
{
case 1:
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
return (OperResult.CreateSuccessResult());
case 2:
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
return (OperResult.CreateSuccessResult());
}
return new OperResult("功能码错误");
}
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
{
return Task.FromResult(Write(address, value));
}
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
{
return Task.FromResult(Write(address, value));
}
/// <inheritdoc/>
protected override async Task Received(SerialSession client, ReceivedDataEventArgs e)
{
try
{
var requestInfo = e.RequestInfo;
//接收外部报文
if (requestInfo is ModbusSerialServerMessage modbusServerMessage)
{
if (modbusServerMessage.CurModbusAddress == null)
{
return;//无法解析直接返回
}
if (!modbusServerMessage.IsSuccess)
{
return;//无法解析直接返回
}
if (modbusServerMessage.CurModbusAddress.WriteFunction == 0)//读取
{
var data = Read(modbusServerMessage.CurModbusAddress.ToString(), modbusServerMessage.Length);
if (data.IsSuccess)
{
var coreData = data.Content;
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
{
coreData = data.Content.Select(m => m > 0).ToArray().BoolArrayToByte().SelectMiddle(0, (int)Math.Ceiling(modbusServerMessage.Length / 8.0));
}
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 2).SpliceArray(new byte[] { (byte)coreData.Length }, coreData);
SerialSession.Send(sendData);
}
else
{
WriteError(SerialSession, modbusServerMessage);//返回错误码
}
}
else//写入
{
var coreData = modbusServerMessage.Content;
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
{
//写入继电器
if (WriteData != null)
{
// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess)
{
WriteSuccess03(SerialSession, modbusServerMessage);
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
else
{
//写入内存区
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess)
{
WriteSuccess03(SerialSession, modbusServerMessage);
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
}
else
{
//写入寄存器
if (WriteData != null)
{
if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(SerialSession, modbusServerMessage);
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
else
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(SerialSession, modbusServerMessage);
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
}
}
}
}
catch (Exception ex)
{
Logger.LogError(ex, ToString());
}
//返回错误码
static void WriteError(SerialSession SerialSession, ModbusSerialServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 2)
.SpliceArray(new byte[] { (byte)1 });//01 lllegal function
sendData[1] = (byte)(sendData[1] + 128);
SerialSession.Send(sendData);
}
}
private static void WriteSuccess03(SerialSession SerialSession, ModbusSerialServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 6);
SerialSession.Send(sendData);
}
private void Init(ModbusAddress mAddress)
{
if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
}
}

View File

@@ -1,441 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections.Concurrent;
using System.ComponentModel;
using ThingsGateway.Foundation.Extension.Bool;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
{
/// <summary>
/// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
/// </summary>
public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, Task<OperResult>> WriteData;
/// <summary>
/// 继电器
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer01ByteBlocks = new();
/// <summary>
/// 开关输入
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer02ByteBlocks = new();
/// <summary>
/// 输入寄存器
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer03ByteBlocks = new();
/// <summary>
/// 保持寄存器
/// </summary>
private ConcurrentDictionary<byte, ByteBlock> ModbusServer04ByteBlocks = new();
/// <inheritdoc/>
public ModbusTcpServer(TcpService tcpService) : base(tcpService)
{
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
RegisterByteLength = 2;
}
/// <summary>
/// 多站点
/// </summary>
[Description("多站点")]
public bool MulStation { get; set; }
/// <summary>
/// 默认站点
/// </summary>
[Description("默认站点")]
public byte Station { get; set; } = 1;
/// <inheritdoc/>
public override void Dispose()
{
foreach (var item in ModbusServer01ByteBlocks)
{
item.Value.SafeDispose();
}
foreach (var item in ModbusServer02ByteBlocks)
{
item.Value.SafeDispose();
}
foreach (var item in ModbusServer03ByteBlocks)
{
item.Value.SafeDispose();
}
foreach (var item in ModbusServer04ByteBlocks)
{
item.Value.SafeDispose();
}
ModbusServer01ByteBlocks.Clear();
ModbusServer02ByteBlocks.Clear();
ModbusServer03ByteBlocks.Clear();
ModbusServer04ByteBlocks.Clear();
base.Dispose();
}
/// <inheritdoc/>
public override string GetAddressDescription()
{
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
ModbusAddress mAddress;
try
{
mAddress = ModbusAddress.ParseFrom(address, Station);
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
if (MulStation)
{
Init(mAddress);
}
else
{
if (Station != mAddress.Station)
{
return new OperResult<byte[]>("地址错误");
}
Init(mAddress);
}
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
switch (mAddress.ReadFunction)
{
case 1:
byte[] bytes0 = new byte[len];
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
ModbusServer01ByteBlock.Read(bytes0);
return OperResult.CreateSuccessResult(bytes0);
case 2:
byte[] bytes1 = new byte[len];
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
ModbusServer02ByteBlock.Read(bytes1);
return OperResult.CreateSuccessResult(bytes1);
case 3:
byte[] bytes3 = new byte[len];
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer03ByteBlock.Read(bytes3);
return OperResult.CreateSuccessResult(bytes3);
case 4:
byte[] bytes4 = new byte[len];
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer04ByteBlock.Read(bytes4);
return OperResult.CreateSuccessResult(bytes4);
}
return new OperResult<byte[]>("功能码错误");
}
/// <inheritdoc/>
public override Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
{
return Task.FromResult(Read(address, length));
}
/// <inheritdoc/>
public override void SetDataAdapter(object socketClient)
{
if (socketClient is SocketClient client)
{
ModbusTcpServerDataHandleAdapter dataHandleAdapter = new();
dataHandleAdapter.CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout);
client.SetDataHandlingAdapter(dataHandleAdapter);
}
else
{
foreach (var item in TcpService.GetClients())
{
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
{
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
};
item.SetDataHandlingAdapter(dataHandleAdapter);
}
}
}
/// <inheritdoc/>
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
{
ModbusAddress mAddress;
try
{
mAddress = ModbusAddress.ParseFrom(address, Station);
}
catch (Exception ex)
{
return new OperResult(ex);
}
if (MulStation)
{
Init(mAddress);
}
else
{
if (Station != mAddress.Station)
{
return new OperResult("地址错误");
}
Init(mAddress);
}
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
switch (mAddress.ReadFunction)
{
case 3:
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer03ByteBlock.Write(value);
return OperResult.CreateSuccessResult();
case 4:
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
ModbusServer04ByteBlock.Write(value);
return OperResult.CreateSuccessResult();
}
return new OperResult("功能码错误");
}
/// <inheritdoc/>
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
{
ModbusAddress mAddress;
try
{
mAddress = ModbusAddress.ParseFrom(address, Station);
}
catch (Exception ex)
{
return (new OperResult(ex));
}
if (MulStation)
{
Init(mAddress);
}
else
{
if (Station != mAddress.Station)
{
return (new OperResult("地址错误"));
}
Init(mAddress);
}
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
switch (mAddress.ReadFunction)
{
case 1:
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
return (OperResult.CreateSuccessResult());
case 2:
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
return (OperResult.CreateSuccessResult());
}
return new OperResult("功能码错误");
}
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
{
return Task.FromResult(Write(address, value));
}
/// <inheritdoc/>
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
{
return Task.FromResult(Write(address, value));
}
/// <inheritdoc/>
protected override async Task Received(SocketClient client, ReceivedDataEventArgs e)
{
try
{
var requestInfo = e.RequestInfo;
//接收外部报文
if (requestInfo is ModbusTcpServerMessage modbusServerMessage)
{
if (modbusServerMessage.CurModbusAddress == null)
{
return;//无法解析直接返回
}
if (!modbusServerMessage.IsSuccess)
{
return;//无法解析直接返回
}
if (modbusServerMessage.CurModbusAddress.WriteFunction == 0)//读取
{
var data = Read(modbusServerMessage.CurModbusAddress.ToString(), modbusServerMessage.Length);
if (data.IsSuccess)
{
var coreData = data.Content;
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
{
coreData = data.Content.Select(m => m > 0).ToArray().BoolArrayToByte().SelectMiddle(0, (int)Math.Ceiling(modbusServerMessage.Length / 8.0));
}
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 8).SpliceArray(new byte[] { (byte)coreData.Length }, coreData);
sendData[5] = (byte)(sendData.Length - 6);
client.Send(sendData);
}
else
{
WriteError(client, modbusServerMessage);//返回错误码
}
}
else//写入
{
var coreData = modbusServerMessage.Content;
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
{
//写入继电器
if (WriteData != null)
{
// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess)
{
WriteSuccess03(client, modbusServerMessage);
}
else
{
WriteError(client, modbusServerMessage);
}
}
else
{
WriteError(client, modbusServerMessage);
}
}
else
{
//写入内存区
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess)
{
WriteSuccess03(client, modbusServerMessage);
}
else
{
WriteError(client, modbusServerMessage);
}
}
}
else
{
//写入寄存器
if (WriteData != null)
{
if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(client, modbusServerMessage);
}
else
{
WriteError(client, modbusServerMessage);
}
}
else
{
WriteError(client, modbusServerMessage);
}
}
else
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(client, modbusServerMessage);
}
else
{
WriteError(client, modbusServerMessage);
}
}
}
}
}
}
catch (Exception ex)
{
Logger.LogError(ex, ToString());
}
//返回错误码
static void WriteError(SocketClient client, ModbusTcpServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 8)
.SpliceArray(new byte[] { (byte)1 });//01 lllegal function
sendData[5] = (byte)(sendData.Length - 6);
sendData[7] = (byte)(sendData[7] + 128);
client.Send(sendData);
}
}
private static void WriteSuccess03(SocketClient client, ModbusTcpServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 12);
sendData[5] = (byte)(sendData.Length - 6);
client.Send(sendData);
}
private void Init(ModbusAddress mAddress)
{
if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
}
}

View File

@@ -1,8 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
</PropertyGroup>
</Project>

View File

@@ -1,129 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Siemens;
public partial class SiemensS7PLC : ReadWriteDevicesTcpClientBase
{
private static OperResult<byte[]> GetWriteBitCommand(string address, bool data)
{
try
{
var result = SiemensAddress.ParseFrom(address);
return SiemensHelper.GetWriteBitCommand(result, data);
}
catch (Exception ex)
{
return new(ex);
}
}
private OperResult<List<byte[]>> GetReadByteCommand(string address, int length)
{
try
{
var from = SiemensAddress.ParseFrom(address, length);
ushort num1 = 0;
var listBytes = new List<byte[]>();
while (num1 < length)
{
//pdu长度重复生成报文直至全部生成
ushort num2 = (ushort)Math.Min(length - num1, pdu_length);
from.Length = num2;
var result = GetReadByteCommand(new SiemensAddress[1] { from });
if (!result.IsSuccess) return new(result);
listBytes.AddRange(result.Content);
num1 += num2;
if (from.DataCode == (byte)S7WordLength.Timer || from.DataCode == (byte)S7WordLength.Counter)
{
from.Address += num2 / 2;
}
else
{
from.Address += num2 * 8;
}
}
return OperResult.CreateSuccessResult(listBytes);
}
catch (Exception ex)
{
return new OperResult<List<byte[]>>(ex);
}
}
private OperResult<List<byte[]>> GetReadByteCommand(SiemensAddress[] siemensAddress)
{
if (siemensAddress.Length <= 19)
{
return ByteTransformUtil.GetResultFromBytes(SiemensHelper.GetReadCommand(siemensAddress), m => new List<byte[]>() { m });
}
List<byte[]> byteList = new();
List<SiemensAddress[]> s7AddressDataArrayList = siemensAddress.ArraySplitByLength(19);
for (int index = 0; index < s7AddressDataArrayList.Count; ++index)
{
var result = GetReadByteCommand(s7AddressDataArrayList[index]);
if (!result.IsSuccess)
{
return result;
}
byteList.AddRange(result.Content);
}
return OperResult.CreateSuccessResult(byteList);
}
private OperResult<List<byte[]>> GetWriteByteCommand(string address, byte[] value)
{
try
{
var s_Address = SiemensAddress.ParseFrom(address);
return GetWriteByteCommand(s_Address, value);
}
catch (Exception ex)
{
return new(ex);
}
}
/// <summary>
/// DefalutConverter
/// </summary>
public static ThingsGatewayBitConverter DefalutConverter = new(BitConverter.IsLittleEndian ? EndianType.Little : EndianType.Big);
private OperResult<List<byte[]>> GetWriteByteCommand(SiemensAddress address, byte[] value)
{
int length1 = value.Length;
ushort index = 0;
List<byte[]> bytes = new();
while (index < length1)
{
//pdu长度重复生成报文直至全部生成
ushort length2 = (ushort)Math.Min(length1 - index, pdu_length);
byte[] data = DefalutConverter.ToByte(value, index, length2);
OperResult<byte[]> result1 = SiemensHelper.GetWriteByteCommand(address, data);
if (!result1.IsSuccess)
{
return new(result1);
}
bytes.Add(result1.Content);
index += length2;
address.Address += length2 * 8;
}
return OperResult.CreateSuccessResult(bytes);
}
}

View File

@@ -1,121 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 读写扩展方法
/// </summary>
public static class ReadWriteDevicesExtensions
{
/// <summary>
/// 在返回的字节数组中解析每个变量的值
/// 根据每个变量的<see cref="IDeviceVariableRunTime.Index"/>
/// 不支持变长字符串类型变量一定不能存在于变量List中
/// </summary>
/// <param name="values">设备变量List</param>
/// <param name="plc">设备</param>
/// <param name="buffer">返回的字节数组</param>
/// <param name="startIndex">开始序号</param>
public static void PraseStructContent<T>(this IList<T> values, IReadWrite plc, byte[] buffer, int startIndex = 0) where T : IDeviceVariableRunTime
{
foreach (IDeviceVariableRunTime organizedVariable in values)
{
var deviceValue = organizedVariable;
IThingsGatewayBitConverter byteConverter = deviceValue.ThingsGatewayBitConverter;
var dataType = organizedVariable.DataTypeEnum;
int index = organizedVariable.Index;
switch (dataType)
{
case DataTypeEnum.String:
Set(organizedVariable, byteConverter.ToString(buffer, index + startIndex, byteConverter.Length ?? 1));
break;
case DataTypeEnum.Boolean:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToBoolean(buffer, index + (startIndex * 8), byteConverter.Length.Value, plc.IsBitReverse(organizedVariable.VariableAddress)) :
byteConverter.ToBoolean(buffer, index + (startIndex * 8), plc.IsBitReverse(organizedVariable.VariableAddress))
);
break;
case DataTypeEnum.Byte:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToByte(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToByte(buffer, index + startIndex));
break;
case DataTypeEnum.Int16:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToInt16(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToInt16(buffer, index + startIndex));
break;
case DataTypeEnum.UInt16:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToUInt16(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToUInt16(buffer, index + startIndex));
break;
case DataTypeEnum.Int32:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToInt32(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToInt32(buffer, index + startIndex));
break;
case DataTypeEnum.UInt32:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToUInt32(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToUInt32(buffer, index + startIndex));
break;
case DataTypeEnum.Int64:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToInt64(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToInt64(buffer, index + startIndex));
break;
case DataTypeEnum.UInt64:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToUInt64(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToUInt64(buffer, index + startIndex));
break;
case DataTypeEnum.Single:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToSingle(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToSingle(buffer, index + startIndex));
break;
case DataTypeEnum.Double:
Set(organizedVariable,
byteConverter.Length > 1 ?
byteConverter.ToDouble(buffer, index + (startIndex), byteConverter.Length.Value) :
byteConverter.ToDouble(buffer, index + startIndex));
break;
default:
break;
}
}
static void Set(IDeviceVariableRunTime organizedVariable, object num)
{
var operResult = organizedVariable.SetValue(num); ;
if (!operResult.IsSuccess)
{
throw new Exception(operResult.Message);
}
}
}
}

View File

@@ -1,118 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Extension;
/// <summary>
/// 对象拓展类
/// </summary>
public static class ObjectExtensions
{
/// <summary>
/// 转换布尔值
/// </summary>
/// <returns></returns>
public static bool ToBoolean(this object value, bool defaultValue = false) => value?.ToString().ToUpper() switch
{
"0" or "FALSE" => false,
"1" or "TRUE" => true,
_ => defaultValue,
};
/// <summary>
/// ToLong
/// </summary>
/// <returns></returns>
public static long ToLong(this object value, long defaultValue = 0)
{
if (value == null || value.ToString().IsNullOrEmpty())
{
return defaultValue;
}
else
{
if (value is bool boolValue)
{
return boolValue ? 1 : 0;
}
return Int64.TryParse(value.ToString(), out var n) ? n : defaultValue;
}
}
/// <summary>
/// ToInt
/// </summary>
/// <returns></returns>
public static int ToInt(this object value, int defaultValue = 0)
{
if (value == null || value.ToString().IsNullOrEmpty())
{
return defaultValue;
}
else
{
if (value is bool boolValue)
{
return boolValue ? 1 : 0;
}
return int.TryParse(value.ToString(), out int n) ? n : defaultValue;
}
}
/// <summary>
/// ToDecimal
/// </summary>
/// <returns></returns>
public static decimal ToDecimal(this object value, int defaultValue = 0)
{
if (value is Double d)
{
return Double.IsNaN(d) ? defaultValue : (Decimal)d;
}
var str = value?.ToString();
if (str.IsNullOrEmpty())
{
return defaultValue;
}
else
{
if (value is bool boolValue)
{
return boolValue ? 1 : 0;
}
return Decimal.TryParse(str, out var n) ? n : defaultValue;
}
}
/// <summary>
/// ToDecimal
/// </summary>
/// <returns></returns>
public static double ToDouble(this object value, double defaultValue = 0)
{
if (value is Double d)
{
return Double.IsNaN(d) ? defaultValue : (Double)d;
}
var str = value?.ToString();
if (str.IsNullOrEmpty())
{
return (double)defaultValue;
}
else
{
if (value is bool boolValue)
{
return boolValue ? 1 : 0;
}
return (double)(double.TryParse(str, out var n) ? n : defaultValue);
}
}
}

View File

@@ -1,120 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// DateHandleAdapterExtension
/// </summary>
public static class DataHandlingAdapterExtension
{
#region SingleStreamDataHandlingAdapter
/// <summary>
/// 将<see cref="TouchSocketConfig"/>中的配置,装载在<see cref="SingleStreamDataHandlingAdapter"/>上。
/// </summary>
/// <param name="adapter"></param>
/// <param name="config"></param>
public static void Config(this SingleStreamDataHandlingAdapter adapter, TouchSocketConfig config)
{
if (config.GetValue(DataHandlingAdapterExtension.MaxPackageSizeProperty) is int v1)
{
adapter.MaxPackageSize = v1;
}
if (config.GetValue(DataHandlingAdapterExtension.CacheTimeoutProperty) != TimeSpan.Zero)
{
adapter.CacheTimeout = config.GetValue(DataHandlingAdapterExtension.CacheTimeoutProperty);
}
if (config.GetValue(DataHandlingAdapterExtension.CacheTimeoutEnableProperty) is bool v2)
{
adapter.CacheTimeoutEnable = v2;
}
if (config.GetValue(DataHandlingAdapterExtension.UpdateCacheTimeWhenRevProperty) is bool v3)
{
adapter.UpdateCacheTimeWhenRev = v3;
}
}
#endregion
#region
/// <summary>
/// 适配器数据包缓存启用。默认为缺省null如果有正常值会在设置适配器时直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/>
/// </summary>
public static readonly DependencyProperty<bool?> CacheTimeoutEnableProperty = DependencyProperty<bool?>.Register("CacheTimeoutEnable", null);
/// <summary>
/// 适配器数据包缓存时长。默认为缺省(<see cref="TimeSpan.Zero"/>)。当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/>
/// </summary>
public static readonly DependencyProperty<TimeSpan> CacheTimeoutProperty = DependencyProperty<TimeSpan>.Register("CacheTimeout", TimeSpan.Zero);
/// <summary>
/// 适配器数据包最大值。默认缺省null当该值有效时会在设置适配器时直接作用于<see cref="DataHandlingAdapter.MaxPackageSize"/>
/// </summary>
public static readonly DependencyProperty<int?> MaxPackageSizeProperty = DependencyProperty<int?>.Register("MaxPackageSize", null);
/// <summary>
/// 适配器数据包缓存策略。默认缺省null当该值有效时会在设置适配器时直接作用于<see cref="SingleStreamDataHandlingAdapter.UpdateCacheTimeWhenRev"/>
/// </summary>
public static readonly DependencyProperty<bool?> UpdateCacheTimeWhenRevProperty = DependencyProperty<bool?>.Register("UpdateCacheTimeWhenRev", null);
/// <summary>
/// 适配器数据包缓存时长。默认为缺省(<see cref="TimeSpan.Zero"/>)。当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/>
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static TouchSocketConfig SetCacheTimeout(this TouchSocketConfig config, TimeSpan value)
{
config.SetValue(CacheTimeoutProperty, value);
return config;
}
/// <summary>
/// 适配器数据包缓存启用。默认为缺省null如果有正常值会在设置适配器时直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeoutEnable"/>
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static TouchSocketConfig SetCacheTimeoutEnable(this TouchSocketConfig config, bool value)
{
config.SetValue(CacheTimeoutEnableProperty, value);
return config;
}
/// <summary>
/// 适配器数据包最大值。默认缺省null当该值有效时会在设置适配器时直接作用于<see cref="DataHandlingAdapter.MaxPackageSize"/>
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static TouchSocketConfig SetMaxPackageSize(this TouchSocketConfig config, int value)
{
config.SetValue(MaxPackageSizeProperty, value);
return config;
}
/// <summary>
/// 适配器数据包缓存策略。默认缺省null当该值有效时会在设置适配器时直接作用于<see cref="SingleStreamDataHandlingAdapter.UpdateCacheTimeWhenRev"/>
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static TouchSocketConfig SetUpdateCacheTimeWhenRev(this TouchSocketConfig config, bool value)
{
config.SetValue(UpdateCacheTimeWhenRevProperty, value);
return config;
}
#endregion
}
}

View File

@@ -1,98 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Dmtp
{
/// <summary>
/// TcpDmtpAdapter
/// </summary>
public class TcpDmtpAdapter : CustomFixedHeaderByteBlockDataHandlingAdapter<DmtpMessage>
{
private SpinLock m_locker = new SpinLock();
/// <inheritdoc/>
public override bool CanSendRequestInfo => true;
/// <inheritdoc/>
public override bool CanSplicingSend => false;
/// <inheritdoc/>
public override int HeaderLength => 6;
/// <inheritdoc/>
protected override DmtpMessage GetInstance()
{
return new DmtpMessage();
}
/// <inheritdoc/>
protected override void OnReceivedSuccess(DmtpMessage request)
{
request.SafeDispose();
}
/// <inheritdoc/>
protected override void PreviewSend(IRequestInfo requestInfo)
{
if (!(requestInfo is DmtpMessage message))
{
throw new Exception($"无法将{nameof(requestInfo)}转换为{nameof(DmtpMessage)}");
}
if (message.BodyByteBlock != null && message.BodyByteBlock.Length > this.MaxPackageSize)
{
throw new Exception("发送的BodyLength={requestInfo.BodyLength},大于设定的MaxPackageSize={this.MaxPackageSize}");
}
using (var byteBlock = new ByteBlock(message.GetLength()))
{
message.Build(byteBlock);
this.GoSend(byteBlock.Buffer, 0, byteBlock.Len);
}
}
/// <inheritdoc/>
protected override void PreviewSend(IList<ArraySegment<byte>> transferBytes)
{
if (transferBytes.Count == 0)
{
return;
}
var length = 0;
foreach (var item in transferBytes)
{
length += item.Count;
}
if (length > this.MaxPackageSize)
{
throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送");
}
var lockTaken = false;
try
{
this.m_locker.Enter(ref lockTaken);
foreach (var item in transferBytes)
{
this.GoSend(item.Array, item.Offset, item.Count);
}
}
finally
{
if (lockTaken)
{
this.m_locker.Exit(false);
}
}
}
}
}

View File

@@ -1,243 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using ThingsGateway.Foundation.Resources;
namespace ThingsGateway.Foundation.Http
{
/// <summary>
/// Http客户端
/// </summary>
public class HttpClient : HttpClientBase
{
}
/// <summary>
/// Http客户端基类
/// </summary>
public class HttpClientBase : TcpClientBase, IHttpClient
{
private readonly object m_requestLocker = new object();
private readonly WaitData<HttpResponse> m_waitData;
private bool m_getContent;
/// <summary>
/// 构造函数
/// </summary>
public HttpClientBase()
{
this.m_waitData = new WaitData<HttpResponse>();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="timeout"></param>
/// <returns></returns>
public override ITcpClient Connect(int timeout = 5000)
{
if (this.Config.GetValue(HttpConfigExtensions.HttpProxyProperty) is HttpProxy httpProxy)
{
var proxyHost = httpProxy.Host;
var credential = httpProxy.Credential;
var remoteHost = this.Config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty);
try
{
this.Config.SetRemoteIPHost(proxyHost);
base.Connect(timeout);
var request = new HttpRequest();
request.InitHeaders()
.SetHost(remoteHost.Host)
.SetUrl(remoteHost.Host, true)
.AsMethod("CONNECT");
var response = this.Request(request, timeout: timeout);
if (response.IsProxyAuthenticationRequired)
{
if (credential is null)
{
throw new Exception("未指定代理的凭据。");
}
var authHeader = response.Headers.Get(HttpHeaders.ProxyAuthenticate);
if (authHeader.IsNullOrEmpty())
{
throw new Exception("未指定代理身份验证质询。");
}
var ares = new AuthenticationChallenge(authHeader, credential);
request.Headers.Add(HttpHeaders.ProxyAuthorization, ares.ToString());
if (!response.KeepAlive)
{
base.Close("代理要求关闭连接,随后重写连接。");
base.Connect(timeout);
}
response = this.Request(request, timeout: timeout);
}
if (response.StatusCode != 200)
{
throw new Exception(response.StatusMessage);
}
}
finally
{
this.Config.SetRemoteIPHost(remoteHost);
}
}
else
{
base.Connect(timeout);
}
return this;
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="request"><inheritdoc/></param>
/// <param name="onlyRequest"><inheritdoc/></param>
/// <param name="timeout"><inheritdoc/></param>
/// <param name="token"><inheritdoc/></param>
/// <returns></returns>
public HttpResponse Request(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default)
{
lock (this.m_requestLocker)
{
this.m_getContent = false;
using (var byteBlock = new ByteBlock())
{
request.Build(byteBlock);
this.m_waitData.Reset();
this.m_waitData.SetCancellationToken(token);
this.DefaultSend(byteBlock);
if (onlyRequest)
{
return default;
}
switch (this.m_waitData.Wait(timeout))
{
case WaitDataStatus.SetRunning:
return this.m_waitData.WaitResult;
case WaitDataStatus.Overtime:
throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription());
case WaitDataStatus.Canceled:
return default;
case WaitDataStatus.Default:
case WaitDataStatus.Disposed:
default:
throw new Exception(TouchSocketHttpResource.UnknownError.GetDescription());
}
}
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="request"></param>
/// <param name="onlyRequest"></param>
/// <param name="timeout"></param>
/// <param name="token"></param>
/// <returns></returns>
public HttpResponse RequestContent(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default)
{
lock (this.m_requestLocker)
{
this.m_getContent = true;
using (var byteBlock = new ByteBlock())
{
request.Build(byteBlock);
this.m_waitData.Reset();
this.m_waitData.SetCancellationToken(token);
this.DefaultSend(byteBlock);
if (onlyRequest)
{
return default;
}
switch (this.m_waitData.Wait(timeout))
{
case WaitDataStatus.SetRunning:
return this.m_waitData.WaitResult;
case WaitDataStatus.Overtime:
throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription());
case WaitDataStatus.Canceled:
return default;
case WaitDataStatus.Default:
case WaitDataStatus.Disposed:
default:
throw new Exception(TouchSocketHttpResource.UnknownError.GetDescription());
}
}
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
this.m_waitData?.Dispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override Task ReceivedData(ReceivedDataEventArgs e)
{
if (e.RequestInfo is HttpResponse response)
{
if (this.m_getContent)
{
response.TryGetContent(out _);
}
this.m_waitData.Set(response);
}
return base.ReceivedData(e);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="e"></param>
protected override async Task OnConnecting(ConnectingEventArgs e)
{
this.Protocol = Protocol.Http;
this.SetDataHandlingAdapter(new HttpClientDataHandlingAdapter());
await base.OnConnecting(e);
}
}
}

View File

@@ -1,93 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation.Rpc
{
/// <summary>
/// Rpc异常
/// </summary>
[Serializable]
public class RpcException : Exception
{
/// <summary>
///构造函数
/// </summary>
public RpcException() : base() { }
/// <summary>
///构造函数
/// </summary>
/// <param name="message"></param>
public RpcException(string message) : base(message) { }
/// <summary>
///构造函数
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
public RpcException(string message, System.Exception inner) : base(message, inner) { }
/// <summary>
///构造函数
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
protected RpcException(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
/// <summary>
/// Rpc调用异常
/// </summary>
[Serializable]
public class RpcInvokeException : Exception
{
/// <summary>
///构造函数
/// </summary>
public RpcInvokeException() : base() { }
/// <summary>
///构造函数
/// </summary>
/// <param name="message"></param>
public RpcInvokeException(string message) : base(message) { }
/// <summary>
///构造函数
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
public RpcInvokeException(string message, System.Exception inner) : base(message, inner) { }
/// <summary>
///构造函数
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
protected RpcInvokeException(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}

View File

@@ -1,43 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Serial;
/// <summary>
/// 通讯基类
/// </summary>
public abstract class BaseSerial : DependencyObject, ISerial
{
/// <summary>
/// 同步根。
/// </summary>
protected readonly object SyncRoot = new object();
private int m_receiveBufferSize = 1024 * 10;
private int m_sendBufferSize = 1024 * 10;
/// <inheritdoc/>
public virtual int SendBufferSize
{
get => this.m_sendBufferSize;
set => this.m_sendBufferSize = value < 1024 ? 1024 : value;
}
/// <inheritdoc/>
public virtual int ReceiveBufferSize
{
get => this.m_receiveBufferSize;
set => this.m_receiveBufferSize = value < 1024 ? 1024 : value;
}
/// <inheritdoc/>
public ILog Logger { get; set; }
}

View File

@@ -1,109 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation.Sockets
{
/// <summary>
/// 发送等待接口
/// </summary>
public interface IWaitSender : ISenderBase
{
/// <summary>
/// 发送字节流
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
byte[] SendThenReturn(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 发送字节流
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
byte[] SendThenReturn(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 发送流中的有效数据
/// </summary>
/// <param name="byteBlock">数据块载体</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
byte[] SendThenReturn(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 异步发送
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
Task<byte[]> SendThenReturnAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 异步发送
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
Task<byte[]> SendThenReturnAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 异步发送
/// </summary>
/// <param name="byteBlock">数据块载体</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
Task<byte[]> SendThenReturnAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
}
}

View File

@@ -1,119 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation.Sockets
{
/// <summary>
/// 等待型客户端。
/// </summary>
public interface IWaitingClient<TClient> : IWaitSender, IDisposable where TClient : IClient, ISender
{
/// <summary>
/// 等待设置。
/// </summary>
public WaitingOptions WaitingOptions { get; }
/// <summary>
/// 客户端终端
/// </summary>
TClient Client { get; }
/// <summary>
/// 发送字节流
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
ResponsedData SendThenResponse(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 发送字节流
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
ResponsedData SendThenResponse(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 发送流中的有效数据
/// </summary>
/// <param name="byteBlock">数据块载体</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
ResponsedData SendThenResponse(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 异步发送
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 异步发送
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
/// <summary>
/// 异步发送
/// </summary>
/// <param name="byteBlock">数据块载体</param>
/// <param name="timeout">超时时间</param>
/// <param name="cancellationToken">取消令箭</param>
/// <exception cref="NotConnectedException">客户端没有连接</exception>
/// <exception cref="OverlengthException">发送数据超长</exception>
/// <exception cref="Exception">其他异常</exception>
/// <returns>返回的数据</returns>
Task<ResponsedData> SendThenResponseAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default);
}
}

View File

@@ -1,29 +0,0 @@
<Project>
<PropertyGroup>
<Version>3.0.0.8</Version>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Authors>Diego</Authors>
<Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright>
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
<SignAssembly>True</SignAssembly>
<DelaySign>False</DelaySign>
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
</PropertyGroup>
<!--<PropertyGroup>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>-->
<ItemGroup>
<ProjectReference Include="..\..\Web\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj">
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -1,111 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.DLT645;
/// <inheritdoc/>
public class DLT645_2007 : CollectBase
{
private readonly DLT645_2007Property driverPropertys = new();
private ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007 _plc;
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(DLT645_2007DebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <summary>
/// <inheritdoc/>
/// </summary>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc?.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
await _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.SerialSession?.CanSend == true;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, 0);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
_plc?.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetSerialProperty(new()
{
PortName = driverPropertys.PortName,
BaudRate = driverPropertys.BaudRate,
DataBits = driverPropertys.DataBits,
Parity = driverPropertys.Parity,
StopBits = driverPropertys.StopBits,
})
;
client = new SerialSession();
((SerialSession)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((SerialSession)client)
{
FrameTime = driverPropertys.FrameTime,
CacheTimeout = driverPropertys.CacheTimeout,
DataFormat = driverPropertys.DataFormat,
EnableFEHead = driverPropertys.EnableFEHead,
OperCode = driverPropertys.OperCode,
Password = driverPropertys.Password,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,103 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.DLT645;
/// <inheritdoc/>
public class DLT645_2007OverTcp : CollectBase
{
private readonly DLT645_2007OverTcpProperty driverPropertys = new();
private ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp _plc;
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(DLT645_2007OverTcpDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc?.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
await _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.TcpClient?.CanSend == true;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, 0);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client)
{
FrameTime = driverPropertys.FrameTime,
CacheTimeout = driverPropertys.CacheTimeout,
DataFormat = driverPropertys.DataFormat,
EnableFEHead = driverPropertys.EnableFEHead,
OperCode = driverPropertys.OperCode,
Password = driverPropertys.Password,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,23 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
global using System.Collections.Generic;
global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.Demo;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;
global using ThingsGateway.Gateway.Application;
global using ThingsGateway.Gateway.Core;

View File

@@ -1,413 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Confluent.Kafka;
using Mapster;
namespace ThingsGateway.Plugin.Kafka;
using Furion;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.Generic;
using ThingsGateway.Foundation.Extension.String;
/// <summary>
/// Kafka消息生产
/// </summary>
public class KafkaProducer : UpLoadBase
{
private readonly ConcurrentQueue<DeviceData> _collectDeviceRunTimes = new();
private readonly ConcurrentQueue<VariableData> _collectVariableRunTimes = new();
private readonly KafkaProducerProperty driverPropertys = new();
private readonly KafkaProducerVariableProperty variablePropertys = new();
private GlobalDeviceData _globalDeviceData;
private List<DeviceVariableRunTime> _uploadVariables = new();
private bool isSuccess = true;
private IProducer<Null, string> producer;
private ProducerBuilder<Null, string> producerBuilder;
private ProducerConfig producerconfig;
/// <inheritdoc/>
public override Type DriverDebugUIType => null;
/// <inheritdoc/>
public override DriverPropertyBase DriverPropertys => driverPropertys;
private TimerTick exVariableTimerTick;
private TimerTick exDeviceTimerTick;
/// <inheritdoc/>
public override List<DeviceVariableRunTime> UploadVariables => _uploadVariables;
/// <inheritdoc/>
public override VariablePropertyBase VariablePropertys => variablePropertys;
/// <inheritdoc/>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task BeforStartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var varList = _collectVariableRunTimes.ToListWithDequeue();
if (varList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = varList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in varData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await KafKaUp(driverPropertys.VariableTopic, item.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
else
{
if (exVariableTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.Adapt<List<VariableData>>();
if (varList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = varList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in varData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await KafKaUp(driverPropertys.VariableTopic, item.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var devList = _collectDeviceRunTimes.ToListWithDequeue();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await KafKaUp(driverPropertys.DeviceTopic, item.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
else
{
if (exDeviceTimerTick.IsTickHappen())
{
var devList = _collectDevice.Adapt<List<DeviceData>>();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await KafKaUp(driverPropertys.DeviceTopic, item.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override bool IsConnected() => isSuccess;
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_collectDevice.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ForEach(a =>
{
a.DeviceStatusChange -= DeviceStatusChange;
});
_uploadVariables?.ForEach(a =>
{
a.VariableValueChange -= VariableValueChange;
});
producer?.Dispose();
_uploadVariables = null;
_collectDeviceRunTimes.Clear();
_collectVariableRunTimes.Clear();
base.Dispose(disposing);
}
private List<CollectDeviceRunTime> _collectDevice;
/// <summary>
/// 初始化
/// </summary>
/// <param name="device"></param>
protected override void Init(UploadDeviceRunTime device)
{
#region Kafka
//1、生产者配置
producerconfig = new ProducerConfig
{
BootstrapServers = driverPropertys.BootStrapServers,
ClientId = driverPropertys.ClientId,
};
//2、创建生产者
producerBuilder = new ProducerBuilder<Null, string>(producerconfig);
//3、错误日志监视
producerBuilder.SetErrorHandler((p, msg) =>
{
isSuccess = false;
LogMessage?.LogWarning(msg.Reason);
});
//kafka
try
{
producer = producerBuilder.Build();
}
catch (DllNotFoundException)
{
if (!Library.IsLoaded)
{
string fileEx = ".dll";
string osStr = "win-";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
osStr = "win-";
fileEx = ".dll";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
osStr = "linux-";
fileEx = ".so";
}
else
{
osStr = "osx-";
fileEx = ".dylib";
}
osStr += RuntimeInformation.ProcessArchitecture.ToString().ToLower();
var pathToLibrd = System.IO.Path.Combine(AppContext.BaseDirectory, "Plugins", "ThingsGateway.Plugin.Kafka", "runtimes", osStr, "native", $"librdkafka{fileEx}");
Library.Load(pathToLibrd);
}
producer = producerBuilder.Build();
}
#endregion
_globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).GetBoolValue()).ToList();
_uploadVariables = tags;
_collectDevice = _globalDeviceData.CollectDevices.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ToList();
_collectDevice.ForEach(a =>
{
a.DeviceStatusChange += DeviceStatusChange;
});
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
if (driverPropertys.UploadInterval <= 1000) driverPropertys.UploadInterval = 1000;
exVariableTimerTick = new(driverPropertys.UploadInterval);
exDeviceTimerTick = new(driverPropertys.UploadInterval);
}
private void DeviceStatusChange(CollectDeviceRunTime collectDeviceRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectDeviceRunTimes.Enqueue(collectDeviceRunTime.Adapt<DeviceData>());
}
private async Task KafKaUp(string topic, string payLoad, CancellationToken cancellationToken)
{
try
{
using CancellationTokenSource cancellationTokenSource = new();
using CancellationTokenSource stoppingToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, cancellationToken);
Task<DeliveryResult<Null, string>> resultTask = producer.ProduceAsync(topic, new Message<Null, string> { Value = payLoad }, stoppingToken.Token);
var timeOutResult = await Task.WhenAny(resultTask, Task.Delay(driverPropertys.TimeOut, stoppingToken.Token));
if (timeOutResult == resultTask)
{
var result = (timeOutResult as Task<DeliveryResult<Null, string>>).Result;
if (result.Status != PersistenceStatus.Persisted)
{
isSuccess = false;
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
else
{
isSuccess = true;
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData();
foreach (var item in cacheData)
{
var cacheResult = await producer.ProduceAsync(item.Topic, new Message<Null, string> { Value = item.CacheStr }, stoppingToken.Token);
if (cacheResult.Status == PersistenceStatus.Persisted)
{
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
await CacheDb.DeleteCacheData(item.Id);
}
}
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{topic}{Environment.NewLine}负载:{payLoad}");
}
}
else
{
isSuccess = false;
stoppingToken.Cancel();
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<VariableData>());
}
}

View File

@@ -1,108 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Modbus;
/// <inheritdoc/>
public class ModbusRtu : CollectBase
{
private readonly ModbusRtuProperty driverPropertys = new();
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu _plc;
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusRtuDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <summary>
/// <inheritdoc/>
/// </summary>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc?.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
await _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
_plc?.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.SerialSession?.CanSend == true;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, driverPropertys.MaxPack);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetSerialProperty(new()
{
PortName = driverPropertys.PortName,
BaudRate = driverPropertys.BaudRate,
DataBits = driverPropertys.DataBits,
Parity = driverPropertys.Parity,
StopBits = driverPropertys.StopBits,
})
;
client = new SerialSession();
((SerialSession)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((SerialSession)client)
{
Crc16CheckEnable = driverPropertys.Crc16CheckEnable,
FrameTime = driverPropertys.FrameTime,
CacheTimeout = driverPropertys.CacheTimeout,
DataFormat = driverPropertys.DataFormat,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,98 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Modbus;
/// <inheritdoc/>
public class ModbusRtuOverTcp : CollectBase
{
private readonly ModbusRtuOverTcpProperty driverPropertys = new();
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp _plc;
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusRtuOverTcpDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc?.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
await _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.TcpClient?.CanSend == true;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, driverPropertys.MaxPack);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
_plc?.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client)
{
Crc16CheckEnable = driverPropertys.Crc16CheckEnable,
FrameTime = driverPropertys.FrameTime,
CacheTimeout = driverPropertys.CacheTimeout,
DataFormat = driverPropertys.DataFormat,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,102 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusRtuOverUdp : CollectBase
{
private readonly ModbusRtuOverUdpProperty driverPropertys = new();
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp _plc;
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusRtuOverUdpDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task BeforStartAsync(CancellationToken cancellationToken)
{
return _plc.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.UdpSession?.CanSend == true;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, driverPropertys.MaxPack);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
_plc?.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
.SetBindIPHost(new IPHost(0))
;
client = new UdpSession();
((UdpSession)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((UdpSession)client)
{
Crc16CheckEnable = driverPropertys.Crc16CheckEnable,
FrameTime = driverPropertys.FrameTime,
DataFormat = driverPropertys.DataFormat,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,241 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion;
using Microsoft.Extensions.Logging;
using SqlSugar;
using System.Collections.Concurrent;
using ThingsGateway.Foundation.Adapter.Modbus;
using ThingsGateway.Foundation.Extension;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusSerialServer : UpLoadBase
{
private readonly ModbusSerialServerProperty driverPropertys = new();
private readonly ModbusSerialServerVariableProperty variablePropertys = new();
private Dictionary<ModbusAddress, DeviceVariableRunTime> _ModbusTags;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusSerialServer _plc;
private ConcurrentQueue<(string, DeviceVariableRunTime)> Values = new();
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusSerialServerDebugPage);
/// <inheritdoc/>
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override List<DeviceVariableRunTime> UploadVariables => _ModbusTags?.Values.ToList();
/// <inheritdoc/>
public override VariablePropertyBase VariablePropertys => variablePropertys;
RpcSingletonService RpcCore { get; set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task BeforStartAsync(CancellationToken cancellationToken)
{
return _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var list = Values.ToListWithDequeue();
foreach (var item in list)
{
if (cancellationToken.IsCancellationRequested)
break;
var type = GetPropertyValue(item.Item2, nameof(ModbusSerialServerVariableProperty.ModbusType));
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, result, cancellationToken);
}
else
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, item.Item2.DataTypeEnum, cancellationToken);
}
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.SerialSession?.CanSend == true;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_ModbusTags?.Values?.ToList()?.ForEach(a => a.VariableValueChange -= VariableValueChange);
if (_plc != null)
_plc.WriteData -= WriteData;
_plc?.Disconnect();
_plc?.SafeDispose();
_ModbusTags?.Clear();
_ModbusTags = null;
Values?.Clear();
Values = null;
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(UploadDeviceRunTime device)
{
var service = new SerialSession();
FoundataionConfig.SetSerialProperty(new()
{
PortName = driverPropertys.PortName,
BaudRate = driverPropertys.BaudRate,
DataBits = driverPropertys.DataBits,
Parity = driverPropertys.Parity,
StopBits = driverPropertys.StopBits,
})
;
service = new SerialSession();
((SerialSession)service).Setup(FoundataionConfig);
//载入配置
_plc = new(service)
{
DataFormat = driverPropertys.DataFormat,
Station = driverPropertys.Station,
CacheTimeout = driverPropertys.CacheTimeout,
MulStation = driverPropertys.MulStation
};
var _globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => !string.IsNullOrEmpty(GetPropertyValue(b, nameof(variablePropertys.ServiceAddress))))
.ToList();
tags.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
VariableValueChange(a);
});
_plc.WriteData += WriteData;
try
{
_ModbusTags = tags.ToDictionary(a =>
{
ModbusAddress address = ModbusAddress.ParseFrom(
GetPropertyValue(a, nameof(variablePropertys.ServiceAddress))
, driverPropertys.Station);
return address;
});
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
tags.ForEach(a =>
{
a.VariableValueChange -= VariableValueChange;
});
_plc.WriteData -= WriteData;
}
RpcCore = App.GetService<RpcSingletonService>();
}
/// <inheritdoc/>
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
var address = GetPropertyValue(collectVariableRunTime, nameof(variablePropertys.ServiceAddress));
if (address != null && collectVariableRunTime.Value != null)
{
Values?.Enqueue((address, collectVariableRunTime));
}
}
/// <summary>
/// RPC写入
/// </summary>
/// <param name="address"></param>
/// <param name="bytes"></param>
/// <param name="thingsGatewayBitConverter"></param>
/// <param name="client"></param>
/// <returns></returns>
private async Task<OperResult> WriteData(ModbusAddress address, byte[] bytes, IThingsGatewayBitConverter thingsGatewayBitConverter, SerialSession client)
{
try
{
var tag = _ModbusTags.FirstOrDefault(a => a.Key?.AddressStart == address.AddressStart && a.Key?.Station == address.Station && a.Key?.ReadFunction == address.ReadFunction);
if (tag.Value == null) return OperResult.CreateSuccessResult();
var enable =
GetPropertyValue(tag.Value, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
&& driverPropertys.DeviceRpcEnable;
if (!enable) return new OperResult("不允许写入");
var type = GetPropertyValue(tag.Value, nameof(ModbusSerialServerVariableProperty.ModbusType));
var addressStr = GetPropertyValue(tag.Value, nameof(ModbusSerialServerVariableProperty.ServiceAddress));
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
{
var result1 = await RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusSerialServer)}-{CurrentDevice.Name}",
new Dictionary<string, string>
{
{
tag.Value.Name,
thingsGatewayBitConverter.GetDataFormBytes(addressStr , bytes,result).ToString()
},
}
);
return result1.FirstOrDefault().Value;
}
else
{
var result1 = await RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusSerialServer)}-{CurrentDevice.Name}",
new Dictionary<string, string>
{
{
tag.Value.Name,
thingsGatewayBitConverter.GetDataFormBytes(addressStr , bytes,result).ToString()
},
}
);
return result1.FirstOrDefault().Value;
}
}
catch (Exception ex)
{
return new OperResult(ex.Message);
}
}
}

View File

@@ -1,102 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusTcp : CollectBase
{
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp _plc;
private readonly ModbusTcpProperty driverPropertys = new();
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusTcpDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc?.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
await _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.TcpClient?.CanSend == true;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, driverPropertys.MaxPack);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
_plc?.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client)
{
DataFormat = driverPropertys.DataFormat,
FrameTime = driverPropertys.FrameTime,
CacheTimeout = driverPropertys.CacheTimeout,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut,
IsCheckMessageId = driverPropertys.MessageIdCheckEnable
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,105 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusTcpDtu : CollectBase
{
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDtu _plc;
private readonly ModbusTcpProperty driverPropertys = new();
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusTcpDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc?.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
await _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.TcpService?.ServerState == ServerState.Running;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, driverPropertys.MaxPack);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
_plc?.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
IPHost iPHost = new(driverPropertys.Port);
if (!string.IsNullOrEmpty(driverPropertys.IP))
{
iPHost = new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}");
}
FoundataionConfig.SetListenIPHosts(new IPHost[] { iPHost });
client = new TcpService();
((TcpService)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpService)client)
{
DataFormat = driverPropertys.DataFormat,
FrameTime = driverPropertys.FrameTime,
CacheTimeout = driverPropertys.CacheTimeout,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut,
IsCheckMessageId = driverPropertys.MessageIdCheckEnable
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,237 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion;
using Microsoft.Extensions.Logging;
using SqlSugar;
using System.Collections.Concurrent;
using ThingsGateway.Foundation.Adapter.Modbus;
using ThingsGateway.Foundation.Extension;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusTcpServer : UpLoadBase
{
private readonly ModbusTcpServerProperty driverPropertys = new();
private readonly ModbusTcpServerVariableProperty variablePropertys = new();
private Dictionary<ModbusAddress, DeviceVariableRunTime> _ModbusTags;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpServer _plc;
private ConcurrentQueue<(string, DeviceVariableRunTime)> Values = new();
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusTcpServerDebugPage);
/// <inheritdoc/>
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override List<DeviceVariableRunTime> UploadVariables => _ModbusTags?.Values.ToList();
/// <inheritdoc/>
public override VariablePropertyBase VariablePropertys => variablePropertys;
RpcSingletonService RpcCore { get; set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task BeforStartAsync(CancellationToken cancellationToken)
{
return _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var list = Values.ToListWithDequeue();
foreach (var item in list)
{
if (cancellationToken.IsCancellationRequested)
break;
var type = GetPropertyValue(item.Item2, nameof(ModbusTcpServerVariableProperty.ModbusType));
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, result, cancellationToken);
}
else
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, item.Item2.DataTypeEnum, cancellationToken);
}
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.TcpService?.ServerState == ServerState.Running;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_ModbusTags?.Values?.ToList()?.ForEach(a => a.VariableValueChange -= VariableValueChange);
if (_plc != null)
_plc.WriteData -= WriteData;
_plc?.Disconnect();
_plc?.SafeDispose();
_ModbusTags?.Clear();
_ModbusTags = null;
Values?.Clear();
Values = null;
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(UploadDeviceRunTime device)
{
IPHost iPHost = new(driverPropertys.Port);
if (!string.IsNullOrEmpty(driverPropertys.IP))
{
iPHost = new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}");
}
FoundataionConfig.SetListenIPHosts(new IPHost[] { iPHost });
var service = new TcpService();
service.Setup(FoundataionConfig);
//载入配置
_plc = new(service)
{
DataFormat = driverPropertys.DataFormat,
Station = driverPropertys.Station,
CacheTimeout = driverPropertys.CacheTimeout,
MulStation = driverPropertys.MulStation
};
var _globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => !string.IsNullOrEmpty(GetPropertyValue(b, nameof(variablePropertys.ServiceAddress))))
.ToList();
tags.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
VariableValueChange(a);
});
_plc.WriteData += WriteData;
try
{
_ModbusTags = tags.ToDictionary(a =>
{
ModbusAddress address = ModbusAddress.ParseFrom(
GetPropertyValue(a, nameof(variablePropertys.ServiceAddress))
, driverPropertys.Station);
return address;
});
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
tags.ForEach(a =>
{
a.VariableValueChange -= VariableValueChange;
});
_plc.WriteData -= WriteData;
}
RpcCore = App.GetService<RpcSingletonService>();
}
/// <inheritdoc/>
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
var address = GetPropertyValue(collectVariableRunTime, nameof(variablePropertys.ServiceAddress));
if (address != null && collectVariableRunTime.Value != null)
{
Values?.Enqueue((address, collectVariableRunTime));
}
}
/// <summary>
/// RPC写入
/// </summary>
/// <param name="address"></param>
/// <param name="bytes"></param>
/// <param name="thingsGatewayBitConverter"></param>
/// <param name="client"></param>
/// <returns></returns>
private async Task<OperResult> WriteData(ModbusAddress address, byte[] bytes, IThingsGatewayBitConverter thingsGatewayBitConverter, SocketClient client)
{
try
{
var tag = _ModbusTags.FirstOrDefault(a => a.Key?.AddressStart == address.AddressStart && a.Key?.Station == address.Station && a.Key?.ReadFunction == address.ReadFunction);
if (tag.Value == null) return OperResult.CreateSuccessResult();
var enable =
GetPropertyValue(tag.Value, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
&& driverPropertys.DeviceRpcEnable;
if (!enable) return new OperResult("不允许写入");
var type = GetPropertyValue(tag.Value, nameof(ModbusTcpServerVariableProperty.ModbusType));
var addressStr = GetPropertyValue(tag.Value, nameof(ModbusTcpServerVariableProperty.ServiceAddress));
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
{
var result1 = await RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusTcpServer)}-{CurrentDevice.Name}-{client.IP + ":" + client.Port}",
new Dictionary<string, string>
{
{
tag.Value.Name,
thingsGatewayBitConverter.GetDataFormBytes(addressStr , bytes,result).ToString()
},
}
);
return result1.FirstOrDefault().Value;
}
else
{
var result1 = await RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusTcpServer)}-{CurrentDevice.Name}-{client.IP + ":" + client.Port}",
new Dictionary<string, string>
{
{
tag.Value.Name,
thingsGatewayBitConverter.GetDataFormBytes(addressStr , bytes,result).ToString()
},
}
);
return result1.FirstOrDefault().Value;
}
}
catch (Exception ex)
{
return new OperResult(ex.Message);
}
}
}

View File

@@ -1,101 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Modbus;
/// <inheritdoc/>
public class ModbusUdp : CollectBase
{
private readonly ModbusUdpProperty driverPropertys = new();
private ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp _plc;
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusUdpDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override bool IsSupportRequest => true;
/// <inheritdoc/>
public override IThingsGatewayBitConverter ThingsGatewayBitConverter { get => _plc?.ThingsGatewayBitConverter; }
/// <inheritdoc/>
protected override IReadWrite PLC => _plc;
/// <inheritdoc/>
public override Task AfterStopAsync()
{
_plc.Disconnect();
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task BeforStartAsync(CancellationToken cancellationToken)
{
return _plc.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override void InitDataAdapter()
{
_plc.SetDataAdapter();
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.UdpSession?.CanSend == true;
}
/// <inheritdoc/>
public override List<DeviceVariableSourceRead> LoadSourceRead(List<DeviceVariableRunTime> deviceVariables)
{
return _plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(deviceVariables, driverPropertys.MaxPack);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_plc?.Disconnect();
_plc?.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
.SetBindIPHost(new IPHost(0))
;
client = new UdpSession();
((UdpSession)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((UdpSession)client)
{
DataFormat = driverPropertys.DataFormat,
FrameTime = driverPropertys.FrameTime,
Station = driverPropertys.Station,
TimeOut = driverPropertys.TimeOut,
IsCheckMessageId = driverPropertys.MessageIdCheckEnable
};
}
/// <inheritdoc/>
protected override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken)
{
return await _plc.ReadAsync(address, length, cancellationToken);
}
}

View File

@@ -1,59 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/ModbusRtu"
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor;
@namespace ThingsGateway.Foundation.Demo
<SerialSessionPage @ref=SerialSessionPage></SerialSessionPage>
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">驱动配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
@if (_plc != null)
{
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.FrameTime)) Dense HideDetails="@("auto")" @bind-Value=@_plc.FrameTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.CacheTimeout)) Dense HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Station)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Station></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.TimeOut)) Dense HideDetails="@("auto")" @bind-Value=@_plc.TimeOut></MTextField>
<MSelect Class="ma-1" Outlined Style="max-width:200px" @bind-Value="_plc.DataFormat" Label="@(_plc.DescriptionWithOutSugar(x => x.DataFormat))"
Items=@(typeof(DataFormat).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataFormat)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
<MCheckbox Class="ma-1" Style="max-width:200px" Label=@(_plc.DescriptionWithOutSugar(x => x.Crc16CheckEnable)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Crc16CheckEnable></MCheckbox>
}
</MRow>
</MCard>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections">
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,40 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command=" set dir=&quot;$(SolutionDir)Web\ThingsGateway.Web.Entry\bin\$(Configuration)\$(TargetFramework)\Plugins\$(AssemblyName)&quot;&#xD;&#xA; if not exist %25dir%25 md %25dir%25 &#xD;&#xA;copy &quot;$(TargetDir)*Modbus*.dll&quot; %25dir%25&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" />
</Target>
<ItemGroup>
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIBase.cs" Link="DebugPage\DriverDebugUIBase.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor.cs" Link="DebugPage\DriverDebugUIPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor.cs" Link="DebugPage\SerialSessionPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor.cs" Link="DebugPage\TcpClientPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor.cs" Link="DebugPage\TcpServerPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor.cs" Link="DebugPage\UdpSessionPage.razor.cs" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor" Link="DebugPage\DriverDebugUIPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor" Link="DebugPage\SerialSessionPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor" Link="DebugPage\TcpClientPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor" Link="DebugPage\TcpServerPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor" Link="DebugPage\UdpSessionPage.razor" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj" />
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj">
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -1,601 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion;
using IoTSharp.Data;
using Mapster;
using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Client;
using System.Collections.Concurrent;
using ThingsGateway.Admin.Core;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.Generic;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.Mqtt;
/// <summary>
/// 参考IotSharpClient.SDK.MQTT
/// </summary>
public class IotSharpClient : UpLoadBase
{
/// <summary>
/// rpcmethodname存疑定为自定义方法在ThingsGateway上写入变量的方法固定为"Write"
/// </summary>
private const string WriteMethod = "WRITE";
private readonly IotSharpClientProperty driverPropertys = new();
private readonly EasyLock easyLock = new();
private readonly IotSharpClientVariableProperty variablePropertys = new();
private ConcurrentQueue<DeviceData> _collectDeviceRunTimes = new();
private ConcurrentQueue<VariableData> _collectVariableRunTimes = new();
private GlobalDeviceData _globalDeviceData;
private IMqttClient _mqttClient;
private MqttClientOptions _mqttClientOptions;
private MqttClientSubscribeOptions _mqttSubscribeOptions;
private RpcSingletonService _rpcCore;
private List<DeviceVariableRunTime> _uploadVariables = new();
private CollectDeviceWorker collectDeviceHostService;
/// <inheritdoc/>
public override Type DriverDebugUIType => null;
private TimerTick exVariableTimerTick;
private TimerTick exDeviceTimerTick;
/// <inheritdoc/>
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override List<DeviceVariableRunTime> UploadVariables => _uploadVariables;
/// <inheritdoc/>
public override VariablePropertyBase VariablePropertys => variablePropertys;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
if (_mqttClient != null)
{
var result = await TryMqttClientAsync(cancellationToken);
if (!result.IsSuccess)
{
LogMessage?.LogWarning($"{ToString()}-连接MqttServer失败{result.Message}");
}
}
}
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var varList = _collectVariableRunTimes.ToListWithDequeue();
if (varList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = varList.GroupBy(a => a.DeviceName).ToList();
foreach (var item in varData)
{
try
{
Dictionary<string, object> nameValueDict = new();
foreach (var pair in item)
{
//只用最新的变量值
nameValueDict.AddOrUpdate(pair.Name, pair.Value);
}
if (!cancellationToken.IsCancellationRequested)
{
await MqttUp($"devices/{item.Key}/telemetry", nameValueDict.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
else
{
if (exVariableTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.Adapt<List<VariableData>>();
if (varList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = varList.GroupBy(a => a.DeviceName).ToList();
foreach (var item in varData)
{
try
{
Dictionary<string, object> nameValueDict = new();
foreach (var pair in item)
{
//只用最新的变量值
nameValueDict.AddOrUpdate(pair.Name, pair.Value);
}
if (!cancellationToken.IsCancellationRequested)
{
await MqttUp($"devices/{item.Key}/telemetry", nameValueDict.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var devList = _collectDeviceRunTimes.ToListWithDequeue();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
else
{
if (exDeviceTimerTick.IsTickHappen())
{
var devList = _collectDevice.Adapt<List<DeviceData>>();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <inheritdoc/>
public override bool IsConnected() => _mqttClient?.IsConnected == true;
/// <inheritdoc/>
public override string ToString()
{
return $" {nameof(IotSharpClient)}-IP:{driverPropertys.IP}-Port:{driverPropertys.Port}-Accesstoken:{driverPropertys.Accesstoken}";
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
try
{
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
_collectDevice?.ForEach(a =>
{
a.DeviceStatusChange -= DeviceStatusChange;
});
_mqttClient?.SafeDispose();
_mqttClient = null;
_uploadVariables = null;
_collectDeviceRunTimes.Clear();
_collectVariableRunTimes.Clear();
_collectDeviceRunTimes = null;
_collectVariableRunTimes = null;
}
catch (Exception ex)
{
LogMessage?.LogError(ex, ToString());
}
}
private List<CollectDeviceRunTime> _collectDevice;
/// <inheritdoc/>
protected override void Init(UploadDeviceRunTime device)
{
var mqttFactory = new MqttFactory(new PrivateLogger(LogMessage));
_mqttClientOptions = mqttFactory.CreateClientOptionsBuilder()
.WithClientId(Guid.NewGuid().ToString())
.WithCredentials(driverPropertys.Accesstoken)//账密
.WithTcpServer(driverPropertys.IP, driverPropertys.Port)//服务器
.WithCleanSession(true)
.WithKeepAlivePeriod(TimeSpan.FromSeconds(120.0))
.Build();
_mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic($"devices/+/rpc/request/+/+");//RPC控制请求需要订阅
})
.Build();
_mqttClient = mqttFactory.CreateMqttClient();
_mqttClient.ConnectedAsync += MqttClient_ConnectedAsync;
_mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
_globalDeviceData = App.GetService<GlobalDeviceData>();
_rpcCore = App.GetService<RpcSingletonService>();
collectDeviceHostService = BackgroundServiceUtil.GetBackgroundService<CollectDeviceWorker>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).GetBoolValue())
.ToList();
_uploadVariables = tags;
_collectDevice = _globalDeviceData.CollectDevices.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ToList();
_collectDevice?.ForEach(a =>
{
a.DeviceStatusChange += DeviceStatusChange;
});
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
if (driverPropertys.UploadInterval <= 1000) driverPropertys.UploadInterval = 1000;
exVariableTimerTick = new(driverPropertys.UploadInterval);
exDeviceTimerTick = new(driverPropertys.UploadInterval);
}
private void DeviceStatusChange(CollectDeviceRunTime collectDeviceRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectDeviceRunTimes.Enqueue(collectDeviceRunTime.Adapt<DeviceData>());
}
private async Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs e)
{
if (e.ApplicationMessage.Topic.StartsWith($"devices/") && e.ApplicationMessage.Topic.Contains("/rpc/request/"))
{
var tps = e.ApplicationMessage.Topic.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var rpcmethodname = tps[4];
var rpcdevicename = tps[1];
var rpcrequestid = tps[5];
if (!string.IsNullOrEmpty(rpcmethodname) && !string.IsNullOrEmpty(rpcdevicename) && !string.IsNullOrEmpty(rpcrequestid))
{
var rpcResponse = new RpcResponse()
{
DeviceId = rpcdevicename,
ResponseId = rpcrequestid,
Method = rpcmethodname,
Success = false,
Data = "参数为空"
};
await SendResponseAsync(rpcResponse);
return;
}
if (!driverPropertys.DeviceRpcEnable)
{
var rpcResponse = new RpcResponse()
{
DeviceId = rpcdevicename,
ResponseId = rpcrequestid,
Method = rpcmethodname,
Success = false,
Data = "不允许写入"
};
await SendResponseAsync(rpcResponse);
return;
}
//rpcmethodname定为自定义方法在ThingsGateway上写入变量的方法固定为"Write"
if (rpcmethodname.ToUpper() != WriteMethod)
{
var rpcResponse = new RpcResponse()
{
DeviceId = rpcdevicename,
ResponseId = rpcrequestid,
Method = rpcmethodname,
Success = false,
Data = "不支持的方法"
};
await SendResponseAsync(rpcResponse);
return;
}
else
{
RpcResponse rpcResponse = new();
var nameValue = e.ApplicationMessage.ConvertPayloadToString().FromJsonString<List<KeyValuePair<string, string>>>();
Dictionary<string, OperResult> results = new();
if (nameValue?.Count > 0)
{
foreach (var item in nameValue)
{
var tag = _uploadVariables.FirstOrDefault(a => a.Name == item.Key);
if (tag != null)
{
var rpcEnable =
GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean()
&& driverPropertys.DeviceRpcEnable;
if (rpcEnable == true)
{
}
else
{
results.Add(item.Key, new OperResult("权限不足,变量不支持写入"));
}
}
else
{
results.Add(item.Key, new OperResult("不存在该变量"));
}
}
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + rpcrequestid, nameValue
.Where(a => !results.Any(b => b.Key == a.Key))
.ToDictionary(a => a.Key, a => a.Value));
results.AddRange(result);
rpcResponse = new()
{
DeviceId = rpcdevicename,
ResponseId = rpcrequestid,
Method = rpcmethodname,
Success = !results.Any(a => !a.Value.IsSuccess),
Data = results.ToJsonString()
};
}
else
{
rpcResponse = new()
{
DeviceId = rpcdevicename,
ResponseId = rpcrequestid,
Method = rpcmethodname,
Success = false,
Data = "消息体参数无法解析"
};
}
await SendResponseAsync(rpcResponse);
}
}
async Task SendResponseAsync(RpcResponse rpcResponse)
{
try
{
var topic = $"devices/{rpcResponse.DeviceId}/rpc/response/{rpcResponse.Method}/{rpcResponse.ResponseId}";
var variableMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{topic}")
.WithPayload(rpcResponse.ToJsonString()).Build();
var isConnect = await TryMqttClientAsync(CancellationToken.None);
if (isConnect.IsSuccess)
await _mqttClient.PublishAsync(variableMessage);
}
catch
{
}
}
}
private async Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
{
var subResult = await _mqttClient.SubscribeAsync(_mqttSubscribeOptions);
if (subResult.Items.Any(a => a.ResultCode > (MqttClientSubscribeResultCode)10))
{
LogMessage?.LogWarning(subResult.Items
.Where(a => a.ResultCode > (MqttClientSubscribeResultCode)10)
.Select(a => a.ToString()).ToJsonString());
}
}
/// <summary>
/// 上传mqtt内容并进行离线缓存
/// </summary>
/// <param name="topic"></param>
/// <param name="payLoad"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task MqttUp(string topic, string payLoad, CancellationToken cancellationToken)
{
var variableMessage = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payLoad).Build();
var isConnect = await TryMqttClientAsync(cancellationToken);
if (isConnect.IsSuccess)
{
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData();
foreach (var item in cacheData)
{
var cacheMessage = new MqttApplicationMessageBuilder()
.WithTopic(item.Topic)
.WithPayload(item.CacheStr).Build();
var cacheResult = await _mqttClient.PublishAsync(cacheMessage, cancellationToken);
if (cacheResult.IsSuccess)
{
await CacheDb.DeleteCacheData(item.Id);
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
}
}
var result = await _mqttClient.PublishAsync(variableMessage, cancellationToken);
if (!result.IsSuccess)
{
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
else
{
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{topic}{Environment.NewLine}负载:{payLoad}");
}
}
else
{
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
}
private async Task<OperResult> TryMqttClientAsync(CancellationToken cancellationToken)
{
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
return await Cilent();
async Task<OperResult> Cilent()
{
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
try
{
await easyLock.WaitAsync();
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
using var timeoutToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(driverPropertys.ConnectTimeOut));
using CancellationTokenSource StoppingToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token);
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
if (_mqttClient == null)
return new OperResult("未初始化");
var result = await _mqttClient?.ConnectAsync(_mqttClientOptions, StoppingToken.Token);
if (result.ResultCode == MqttClientConnectResultCode.Success)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result.ReasonString);
}
}
catch (Exception ex)
{
return new OperResult(ex);
}
finally
{
easyLock.Release();
}
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<VariableData>());
}
}

View File

@@ -1,569 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion;
using Mapster;
using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Client;
using System.Collections.Concurrent;
using System.Text;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.Generic;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.Mqtt;
/// <summary>
/// MqttClient
/// </summary>
public class MqttClient : UpLoadBase
{
private readonly MqttClientProperty driverPropertys = new();
private readonly EasyLock easyLock = new();
private readonly MqttClientVariableProperty variablePropertys = new();
private List<CollectDeviceRunTime> _collectDevice;
private ConcurrentQueue<DeviceData> _collectDeviceRunTimes = new();
private ConcurrentQueue<VariableData> _collectVariableRunTimes = new();
private GlobalDeviceData _globalDeviceData;
private IMqttClient _mqttClient;
private MqttClientOptions _mqttClientOptions;
private MqttClientSubscribeOptions _mqttSubscribeOptions;
private RpcSingletonService _rpcCore;
private List<DeviceVariableRunTime> _uploadVariables = new();
private CollectDeviceWorker collectDeviceHostService;
private TimerTick exDeviceTimerTick;
private TimerTick exVariableTimerTick;
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(MqttClientDebugPage);
/// <inheritdoc/>
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override List<DeviceVariableRunTime> UploadVariables => _uploadVariables;
/// <inheritdoc/>
public override VariablePropertyBase VariablePropertys => variablePropertys;
/// <inheritdoc/>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
if (_mqttClient != null)
{
var result = await TryMqttClientAsync(cancellationToken);
if (!result.IsSuccess)
{
LogMessage?.LogWarning($"{ToString()}-连接MqttServer失败{result.Message}");
}
}
}
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var varList = _collectVariableRunTimes.ToListWithDequeue();
if (varList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = varList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in varData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await MqttUp($"{driverPropertys.VariableTopic}", item.GetSciptListValue(driverPropertys.BigTextScriptVariableModel), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
else
{
if (exVariableTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.Adapt<List<VariableData>>();
if (varList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = varList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in varData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await MqttUp($"{driverPropertys.VariableTopic}", item.GetSciptListValue(driverPropertys.BigTextScriptVariableModel), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var devList = _collectDeviceRunTimes.ToListWithDequeue();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await MqttUp($"{driverPropertys.DeviceTopic}", item.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
else
{
if (exDeviceTimerTick.IsTickHappen())
{
var devList = _collectDevice.Adapt<List<DeviceData>>();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await MqttUp($"{driverPropertys.DeviceTopic}", item.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override bool IsConnected() => _mqttClient?.IsConnected == true;
/// <inheritdoc/>
public override string ToString()
{
return $" {nameof(MqttClient)} IP:{driverPropertys.IP} Port:{driverPropertys.Port}";
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
try
{
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
_globalDeviceData?.CollectDevices?.ForEach(a =>
{
a.DeviceStatusChange -= DeviceStatusChange;
});
_mqttClient?.SafeDispose();
_mqttClient = null;
_uploadVariables = null;
_collectDeviceRunTimes.Clear();
_collectVariableRunTimes.Clear();
_collectDeviceRunTimes = null;
_collectVariableRunTimes = null;
base.Dispose(disposing);
}
catch (Exception ex)
{
LogMessage?.LogError(ex, ToString());
}
}
/// <inheritdoc/>
protected override void Init(UploadDeviceRunTime device)
{
var mqttFactory = new MqttFactory(new PrivateLogger(LogMessage));
_mqttClientOptions = mqttFactory.CreateClientOptionsBuilder()
.WithClientId(driverPropertys.ConnectId)
.WithCredentials(driverPropertys.UserName, driverPropertys.Password)//账密
.WithTcpServer(driverPropertys.IP, driverPropertys.Port)//服务器
.WithCleanSession(true)
.WithKeepAlivePeriod(TimeSpan.FromSeconds(120.0))
.WithoutThrowOnNonSuccessfulConnectResponse()
.Build();
_mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic(driverPropertys.RpcWriteTopic);
})
.WithTopicFilter(
f =>
{
f.WithTopic(driverPropertys.QuestRpcTopic);
})
.Build();
_mqttClient = mqttFactory.CreateMqttClient();
_mqttClient.ConnectedAsync += MqttClient_ConnectedAsync;
_mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
_globalDeviceData = App.GetService<GlobalDeviceData>();
_rpcCore = App.GetService<RpcSingletonService>();
collectDeviceHostService = BackgroundServiceUtil.GetBackgroundService<CollectDeviceWorker>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).GetBoolValue())
.ToList();
_uploadVariables = tags;
_collectDevice = _globalDeviceData.CollectDevices.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ToList();
if (!driverPropertys.IsInterval)
{
_collectDevice.ForEach(a =>
{
a.DeviceStatusChange += DeviceStatusChange;
});
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
}
if (driverPropertys.UploadInterval <= 1000) driverPropertys.UploadInterval = 1000;
exVariableTimerTick = new(driverPropertys.UploadInterval);
exDeviceTimerTick = new(driverPropertys.UploadInterval);
}
private async Task AllPublishAsync(CancellationToken cancellationToken)
{
//保留消息
//分解List避免超出mqtt字节大小限制
var varData = _globalDeviceData.AllVariables.Adapt<List<VariableData>>().ChunkTrivialBetter(driverPropertys.SplitSize);
var devData = _globalDeviceData.CollectDevices.Adapt<List<DeviceData>>().ChunkTrivialBetter(driverPropertys.SplitSize);
var isConnect = await TryMqttClientAsync(cancellationToken);
foreach (var item in devData)
{
var devMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.DeviceTopic}")
.WithPayload(item.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel)).Build();
if (isConnect.IsSuccess)
await _mqttClient.PublishAsync(devMessage, cancellationToken);
}
foreach (var item in varData)
{
var varMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.VariableTopic}")
.WithPayload(item.GetSciptListValue(driverPropertys.BigTextScriptVariableModel)).Build();
if (isConnect.IsSuccess)
await _mqttClient.PublishAsync(varMessage, cancellationToken);
}
}
private void DeviceStatusChange(CollectDeviceRunTime collectDeviceRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectDeviceRunTimes.Enqueue(collectDeviceRunTime.Adapt<DeviceData>());
}
private async Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs args)
{
if (args.ApplicationMessage.Topic == driverPropertys.QuestRpcTopic && args.ApplicationMessage.PayloadSegment.Count > 0)
{
await AllPublishAsync(CancellationToken.None);
return;
}
if (!driverPropertys.DeviceRpcEnable || string.IsNullOrEmpty(args.ClientId))
return;
if (args.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
return;
var rpcDatas = Encoding.UTF8.GetString(args.ApplicationMessage.PayloadSegment).FromJsonString<MqttRpcNameVaueWithId>();
if (rpcDatas == null)
return;
MqttRpcResult mqttRpcResult = new() { RpcId = rpcDatas.RpcId, Success = true };
try
{
foreach (var rpcData in rpcDatas.WriteInfos)
{
var tag = _uploadVariables.FirstOrDefault(a => a.Name == rpcData.Key);
if (tag != null)
{
var rpcEnable = GetPropertyValue(tag, nameof(variablePropertys.VariableRpcEnable)).ToBoolean();
if (rpcEnable == true)
{
}
else
{
mqttRpcResult.Success = false;
mqttRpcResult.Message.Add(rpcData.Key, new("权限不足,变量不支持写入"));
}
}
else
{
mqttRpcResult.Success = false;
mqttRpcResult.Message.Add(rpcData.Key, new("不存在该变量"));
}
}
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + args.ClientId,
rpcDatas.WriteInfos.Where(
a => !mqttRpcResult.Message.Any(b => b.Key == a.Key)).ToDictionary(a => a.Key, a => a.Value));
mqttRpcResult.Message.AddRange(result);
mqttRpcResult.Success = !mqttRpcResult.Message.Any(a => !a.Value.IsSuccess);
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
var variableMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.RpcSubTopic}")
.WithPayload(mqttRpcResult.ToJsonString()).Build();
var isConnect = await TryMqttClientAsync(CancellationToken.None);
if (isConnect.IsSuccess)
await _mqttClient.PublishAsync(variableMessage);
}
catch
{
}
}
private async Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
{
var subResult = await _mqttClient.SubscribeAsync(_mqttSubscribeOptions);
if (subResult.Items.Any(a => a.ResultCode > (MqttClientSubscribeResultCode)10))
{
LogMessage?.Warning($"订阅失败-{subResult.Items
.Where(a => a.ResultCode > (MqttClientSubscribeResultCode)10)
.Select(a =>
new
{
Topic = a.TopicFilter.Topic,
ResultCode = a.ResultCode.ToString()
}
)
.ToJsonString()}");
}
}
/// <summary>
/// 上传mqtt内容并进行离线缓存
/// </summary>
/// <param name="topic"></param>
/// <param name="payLoad"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task MqttUp(string topic, string payLoad, CancellationToken cancellationToken)
{
var variableMessage = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payLoad).Build();
var isConnect = await TryMqttClientAsync(cancellationToken);
if (isConnect.IsSuccess)
{
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData();
foreach (var item in cacheData)
{
var cacheMessage = new MqttApplicationMessageBuilder()
.WithTopic(item.Topic)
.WithPayload(item.CacheStr).Build();
var cacheResult = await _mqttClient.PublishAsync(cacheMessage, cancellationToken);
if (cacheResult.IsSuccess)
{
await CacheDb.DeleteCacheData(item.Id);
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
}
}
var result = await _mqttClient.PublishAsync(variableMessage, cancellationToken);
if (!result.IsSuccess)
{
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
else
{
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{topic}{Environment.NewLine}负载:{payLoad}");
}
}
else
{
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
}
private async Task<OperResult> TryMqttClientAsync(CancellationToken cancellationToken)
{
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
return await Cilent();
async Task<OperResult> Cilent()
{
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
try
{
await easyLock.WaitAsync();
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
using var timeoutToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(driverPropertys.ConnectTimeOut));
using CancellationTokenSource StoppingToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token);
if (_mqttClient?.IsConnected == true)
return OperResult.CreateSuccessResult();
if (_mqttClient == null)
{
return new OperResult("未初始化");
}
var result = await _mqttClient?.ConnectAsync(_mqttClientOptions, StoppingToken.Token);
if (result.ResultCode == MqttClientConnectResultCode.Success)
{
return OperResult.CreateSuccessResult();
}
else
{
return new OperResult(result.ReasonString);
}
}
catch (Exception ex)
{
return new OperResult(ex);
}
finally
{
easyLock.Release();
}
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<VariableData>());
}
}

View File

@@ -1,85 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/MqttClient"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Masa.Blazor.Presets;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension;
@using Masa.Blazor
<MqttClientPage @ref=mqttClientPage></MqttClientPage>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections" ShowDefaultOtherContent=false>
<ReadWriteContent>
<div class="my-1 py-1">
<MTextarea Class="mx-1 my-1" Label="订阅主题" Dense Outlined HideDetails="@("auto")" @bind-Value=@driverDebugUIPage.Address />
<MButton Class="mx-1 my-1" Color="primary" OnClick="SubscribeAsync">
添加
</MButton>
<MButton Class="mx-1 my-1" Color="primary" OnClick="UnsubscribeAsync">
移除
</MButton>
<MTextarea Class="mx-1 my-1" Label="发布主题" Dense Outlined HideDetails="@("auto")" @bind-Value=@PublishTopic />
<MTextarea Class="mx-1 my-1" Label="发布内容" Dense Outlined HideDetails="@("auto")" @bind-Value=@PublishValue />
<MButton Class="mx-1 my-1" Color="primary" OnClick="PublishAsync">
发布
</MButton>
<MSubheader Class="mt-4 font-weight-black"> Rpc </MSubheader>
<MTextarea Class="mx-1 mt-3 my-1" Label="Rpc主题" Dense Outlined HideDetails="@("auto")" @bind-Value=@MqttRpcTopicPair.RequestTopic />
<MTextarea Class="mx-1 mt-3 my-1" Label="Rpc返回主题" Dense Outlined HideDetails="@("auto")" @bind-Value=@MqttRpcTopicPair.ResponseTopic />
<MTextarea Class="mx-1 mt-3 my-1" Label="Rpc内容" Dense Outlined HideDetails="@("auto")" @bind-Value=@driverDebugUIPage.WriteValue />
<MButton Class="mx-1 my-1" Color="primary" OnClick="RpcExecuteAsync">
执行
</MButton>
</div>
<MCol Class="my-1 py-1">
<MRow NoGutters>
</MRow>
</MCol>
</ReadWriteContent>
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,152 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Masa.Blazor;
using Microsoft.AspNetCore.Components;
using MQTTnet;
using MQTTnet.Extensions.Rpc;
using System.Collections.Generic;
using System.Text;
using ThingsGateway.Plugin.Mqtt;
namespace ThingsGateway.Foundation.Demo;
/// <summary>
/// MqttClientDebugPage
/// </summary>
public partial class MqttClientDebugPage : IDisposable
{
private DriverDebugUIPage driverDebugUIPage;
private MqttClientPage mqttClientPage;
[Inject]
IPopupService PopupService { get; set; }
/// <inheritdoc/>
public void Dispose()
{
mqttClientPage.SafeDispose();
}
/// <inheritdoc/>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
if (mqttClientPage != null)
{
mqttClientPage.LogAction = driverDebugUIPage.LogOut;
}
//初始化
driverDebugUIPage.Address = "ThingsGateway/Variable";
driverDebugUIPage.WriteValue = new MqttRpcNameVaueWithId()
{
RpcId = Guid.NewGuid().ToString(),
WriteInfos = new Dictionary<string, string>()
{
{ "tag1", "123" }
}
}.ToJsonString();
;
mqttClientPage.IP = "127.0.0.1";
mqttClientPage.Port = 1883;
mqttClientPage.UserName = "admin";
mqttClientPage.Password = "111111";
mqttClientPage.StateHasChangedAsync();
//载入配置
StateHasChanged();
driverDebugUIPage.Sections.Clear();
}
base.OnAfterRender(firstRender);
}
private async Task SubscribeAsync()
{
try
{
var mqttSubscribeOptions = mqttClientPage.MqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic(driverDebugUIPage.Address);
})
.Build();
await mqttClientPage.MqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + $"订阅{driverDebugUIPage.Address}成功"));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
private async Task UnsubscribeAsync()
{
try
{
var mqttSubscribeOptions = mqttClientPage.MqttFactory.CreateUnsubscribeOptionsBuilder()
.WithTopicFilter(driverDebugUIPage.Address)
.Build();
await mqttClientPage.MqttClient.UnsubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + $"取消订阅{driverDebugUIPage.Address}成功"));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
string PublishTopic;
string PublishValue;
private async Task PublishAsync()
{
try
{
var devMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{PublishTopic}")
.WithPayload(PublishValue).Build();
await mqttClientPage.MqttClient.PublishAsync(devMessage, CancellationToken.None);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + $"发布{PublishTopic}成功"));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
MqttRpcTopicPair MqttRpcTopicPair = new() { RequestTopic = "ThingsGateway/RpcWrite", ResponseTopic = "ThingsGateway/RpcSub" };
private async Task RpcExecuteAsync()
{
try
{
using MqttRpcClient mqttRpcClient = new(mqttClientPage.MqttClient);
var data = await mqttRpcClient.ExecuteAsync(MqttRpcTopicPair, driverDebugUIPage.WriteValue, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce, TimeSpan.FromSeconds(10));
var str = Encoding.UTF8.GetString(data);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + str));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
}

View File

@@ -1,119 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using MQTTnet;
using MQTTnet.Client;
using System.Text;
using ThingsGateway.Plugin.Mqtt;
namespace ThingsGateway.Foundation.Demo;
/// <summary>
/// MqttClientPage
/// </summary>
public partial class MqttClientPage
{
/// <summary>
/// 日志输出
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
/// <summary>
/// OPC
/// </summary>
public IMqttClient MqttClient;
public MqttClientOptions MqttClientOptions;
public MqttFactory MqttFactory;
public string ConnectId;
public string IP;
public string Password;
public int Port;
public string UserName;
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
{
MqttClient.SafeDispose();
}
/// <inheritdoc/>
protected override void OnInitialized()
{
MqttFactory = new MqttFactory(new PrivateLogger(new EasyLogger(LogAction) { LogLevel = LogLevel.Trace }));
MqttClient = MqttFactory.CreateMqttClient();
MqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
base.OnInitialized();
}
private async Task Connect()
{
try
{
await MqttClient.DisconnectAsync();
await GetMqttClient();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private async Task DisConnect()
{
try
{
await MqttClient.DisconnectAsync();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private async Task<IMqttClient> GetMqttClient()
{
//载入配置
MqttClientOptions = MqttFactory.CreateClientOptionsBuilder()
.WithClientId(ConnectId)
.WithCredentials(UserName, Password)//账密
.WithTcpServer(IP, Port)//服务器
.WithCleanSession(true)
.WithKeepAlivePeriod(TimeSpan.FromSeconds(120.0))
.WithoutThrowOnNonSuccessfulConnectResponse()
.Build();
await MqttClient.ConnectAsync(MqttClientOptions);
return MqttClient;
}
private void LogOut(byte logLevel, object source, string message, Exception exception) => LogAction?.Invoke((LogLevel)logLevel, source, message, exception);
private Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs args)
{
LogAction?.Invoke(LogLevel.Info, this, $"[{args.ApplicationMessage.Topic}]{Encoding.UTF8.GetString(args.ApplicationMessage.PayloadSegment)}", null);
return Task.CompletedTask;
}
public Task StateHasChangedAsync()
{
return InvokeAsync(StateHasChanged);
}
}

View File

@@ -1,49 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using MQTTnet.Diagnostics;
namespace ThingsGateway.Plugin.Mqtt
{
internal class PrivateLogger : IMqttNetLogger
{
readonly ILog LogMessage;
public PrivateLogger(ILog logger)
{
LogMessage = logger;
}
public bool IsEnabled => true;
public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception)
{
switch (logLevel)
{
case MqttNetLogLevel.Verbose:
LogMessage?.Log(LogLevel.Trace, source, message != null ? (parameters != null ? message != null ? (parameters != null ? string.Format(message, parameters) : message) : string.Empty : message) : string.Empty, exception);
break;
case MqttNetLogLevel.Info:
LogMessage?.Log(LogLevel.Info, source, message != null ? (parameters != null ? string.Format(message, parameters) : message) : string.Empty, exception);
break;
case MqttNetLogLevel.Warning:
LogMessage?.Log(LogLevel.Warning, source, message != null ? (parameters != null ? string.Format(message, parameters) : message) : string.Empty, exception);
break;
case MqttNetLogLevel.Error:
LogMessage?.Log(LogLevel.Warning, source, message != null ? (parameters != null ? string.Format(message, parameters) : message) : string.Empty, exception);
break;
}
}
}
}

View File

@@ -1,34 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>Ϊȫ<CEAA>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EBA3A9><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><DFB1><EFBFBD>Diego<67><6F><EFBFBD><EFBFBD>
// Դ<><D4B4><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Э<EFBFBD><D0AD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD>ֿ<EFBFBD><D6BF>Ŀ<EFBFBD>ԴЭ<D4B4><EFBFBD><E9BCB0><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>
// GiteeԴ<65><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<62><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<><CAB9><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<51><C8BA>605534569
//------------------------------------------------------------------------------
#endregion
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using MQTTnet.Protocol;
using System.Text;
namespace MQTTnet.Extensions.Rpc
{
public static class MqttRpcClientExtensions
{
public static Task<byte[]> ExecuteAsync(this MqttRpcClient client, MqttRpcTopicPair mqttRpcTopicPair, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, TimeSpan timeout)
{
if (client == null) throw new ArgumentNullException(nameof(client));
var buffer = Encoding.UTF8.GetBytes(payload ?? string.Empty);
return client.ExecuteAsync(mqttRpcTopicPair, buffer, qualityOfServiceLevel, timeout);
}
}
}

View File

@@ -1,25 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>Ϊȫ<CEAA>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EBA3A9><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><DFB1><EFBFBD>Diego<67><6F><EFBFBD><EFBFBD>
// Դ<><D4B4><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Э<EFBFBD><D0AD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD>ֿ<EFBFBD><D6BF>Ŀ<EFBFBD>ԴЭ<D4B4><EFBFBD><E9BCB0><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>
// GiteeԴ<65><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<62><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<><CAB9><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<51><C8BA>605534569
//------------------------------------------------------------------------------
#endregion
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace MQTTnet.Extensions.Rpc
{
public sealed class MqttRpcTopicPair
{
public string RequestTopic { get; set; }
public string ResponseTopic { get; set; }
}
}

View File

@@ -1,37 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command=" set dir=&quot;$(SolutionDir)Web\ThingsGateway.Web.Entry\bin\$(Configuration)\$(TargetFramework)\Plugins\$(AssemblyName)&quot;&#xD;&#xA; if not exist %25dir%25 md %25dir%25 &#xD;&#xA;copy &quot;$(TargetDir)*Mqtt*.dll&quot; %25dir%25&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" />
</Target>
<ItemGroup>
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj">
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIBase.cs" Link="DebugPage\DriverDebugUIBase.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor.cs" Link="DebugPage\DriverDebugUIPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor.cs" Link="DebugPage\SerialSessionPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor.cs" Link="DebugPage\TcpClientPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor.cs" Link="DebugPage\TcpServerPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor.cs" Link="DebugPage\UdpSessionPage.razor.cs" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor" Link="DebugPage\DriverDebugUIPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor" Link="DebugPage\SerialSessionPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor" Link="DebugPage\TcpClientPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor" Link="DebugPage\TcpServerPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor" Link="DebugPage\UdpSessionPage.razor" />
</ItemGroup>
</Project>

View File

@@ -1,46 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using System.IO.Ports;
@using System.Collections.Concurrent;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Adapter.OPCDA;
@using Masa.Blazor
@implements IDisposable
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">设备配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.GroupSize) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.GroupSize />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.UpdateRate) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.UpdateRate />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.DeadBand) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.DeadBand />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.CheckRate) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.CheckRate />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.OPCIP) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.OPCIP />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.OPCName) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.OPCName />
<MCheckbox Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.ActiveSubscribe) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.ActiveSubscribe />
<MButton Class="ma-1" OnClick=@Connect Color="primary">
连接
</MButton>
<MButton Class="ma-1" OnClick=@DisConnect Color="red">
断开
</MButton>
</MRow>
</MCard>

View File

@@ -1,43 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<DefineConstants>Plugin</DefineConstants>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command=" set dir=&quot;$(SolutionDir)Web\ThingsGateway.Web.Entry\bin\$(Configuration)\$(TargetFramework)\Plugins\$(AssemblyName)&quot;&#xD;&#xA; if not exist %25dir%25 md %25dir%25 &#xD;&#xA;copy &quot;$(TargetDir)*OPCDA*.dll&quot; %25dir%25&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" />
</Target>
<ItemGroup>
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIBase.cs" Link="DebugPage\DriverDebugUIBase.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor.cs" Link="DebugPage\DriverDebugUIPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor.cs" Link="DebugPage\SerialSessionPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor.cs" Link="DebugPage\TcpClientPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor.cs" Link="DebugPage\TcpServerPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor.cs" Link="DebugPage\UdpSessionPage.razor.cs" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor" Link="DebugPage\DriverDebugUIPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor" Link="DebugPage\SerialSessionPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor" Link="DebugPage\TcpClientPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor" Link="DebugPage\TcpServerPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor" Link="DebugPage\UdpSessionPage.razor" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj" />
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj">
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -1,57 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using System.IO.Ports;
@using System.Collections.Concurrent;
@using Opc.Ua.Client;
@using Opc.Ua;
@using System.Linq;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Adapter.OPCUA;
@using Masa.Blazor
@implements IDisposable
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">设备配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.GroupSize) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.GroupSize />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.UpdateRate) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.UpdateRate />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.DeadBand) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.DeadBand />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.KeepAliveInterval) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.KeepAliveInterval />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.OPCUrl) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.OPCUrl />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.UserName) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.UserName />
<MTextField Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.Password) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.Password />
<MCheckbox Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.ActiveSubscribe) Dense Outlined HideDetails="@("auto")" @bind-Value=@node.ActiveSubscribe />
<MCheckbox Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.IsUseSecurity) Dense HideDetails="@("auto")" @bind-Value=@node.IsUseSecurity />
<MCheckbox Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.CheckDomain) Dense HideDetails="@("auto")" @bind-Value=@node.CheckDomain />
<MButton Class="ma-1" OnClick=@ConnectAsync Color="primary">
连接
</MButton>
<MButton Class="ma-1" OnClick=@DisConnect Color="red">
断开
</MButton>
</MRow>
</MCard>

View File

@@ -1,43 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<DefineConstants>Plugin</DefineConstants>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command=" set dir=&quot;$(SolutionDir)Web\ThingsGateway.Web.Entry\bin\$(Configuration)\$(TargetFramework)\Plugins\$(AssemblyName)&quot;&#xD;&#xA; if not exist %25dir%25 md %25dir%25 &#xD;&#xA;copy &quot;$(TargetDir)*OPCUA*.dll&quot; %25dir%25&#xD;&#xA;copy &quot;$(TargetDir)*OPC.UA*.dll&quot; %25dir%25&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" />
</Target>
<ItemGroup>
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIBase.cs" Link="DebugPage\DriverDebugUIBase.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor.cs" Link="DebugPage\DriverDebugUIPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor.cs" Link="DebugPage\SerialSessionPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor.cs" Link="DebugPage\TcpClientPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor.cs" Link="DebugPage\TcpServerPage.razor.cs" />
<Compile Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor.cs" Link="DebugPage\UdpSessionPage.razor.cs" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\DriverDebugUIPage.razor" Link="DebugPage\DriverDebugUIPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\SerialSessionPage.razor" Link="DebugPage\SerialSessionPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpClientPage.razor" Link="DebugPage\TcpClientPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\TcpServerPage.razor" Link="DebugPage\TcpServerPage.razor" />
<Content Include="..\..\Demo\ThingsGateway.Foundation.Demo.Rcl\Components\DebugPage\UdpSessionPage.razor" Link="DebugPage\UdpSessionPage.razor" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Server" Version="1.4.372.56" />
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj" />
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj">
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
</Project>

View File

@@ -1,35 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorComponent
@using Masa.Blazor
@using Masa.Blazor.Presets
@using System.Net.Http.Json
@using System.IO;
@using System.Text.Json;
@using System.Reflection;
@using ThingsGateway.Components;
@using ThingsGateway.Admin.Core;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension.String;
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Core;
@using ThingsGateway.Gateway.Application;
@using ThingsGateway.Gateway.Core;

View File

@@ -1,495 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion;
using Mapster;
using Microsoft.Extensions.Logging;
using RabbitMQ.Client;
using System.Collections.Concurrent;
using System.Text;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.Generic;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.RabbitMQ;
/// <summary>
/// RabbitMQ
/// </summary>
public class RabbitMQClient : UpLoadBase
{
private readonly RabbitMQClientProperty driverPropertys = new();
private readonly RabbitMQClientVariableProperty variablePropertys = new();
private ConcurrentQueue<DeviceData> _collectDeviceRunTimes = new();
private ConcurrentQueue<VariableData> _collectVariableRunTimes = new();
private IConnection _connection;
private ConnectionFactory _connectionFactory;
private GlobalDeviceData _globalDeviceData;
private IModel _model;
private RpcSingletonService _rpcCore;
private List<DeviceVariableRunTime> _uploadVariables = new();
/// <inheritdoc/>
public override Type DriverDebugUIType => null;
/// <inheritdoc/>
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override List<DeviceVariableRunTime> UploadVariables => _uploadVariables;
/// <inheritdoc/>
public override VariablePropertyBase VariablePropertys => variablePropertys;
/// <inheritdoc/>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task BeforStartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private TimerTick exDeviceTimerTick;
private TimerTick exVariableTimerTick;
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
try
{
if (_model == null)
{
try
{
// 创建连接
_connection ??= _connectionFactory.CreateConnection();
// 创建通道
_model ??= _connection.CreateModel();
// 声明路由队列
if (driverPropertys.IsQueueDeclare)
{
_model?.QueueDeclare(driverPropertys.VariableQueueName, true, false, false);
_model?.QueueDeclare(driverPropertys.DeviceQueueName, true, false, false);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
if (!driverPropertys.IsInterval)
{
////变化推送
var varList = _collectVariableRunTimes.ToListWithDequeue();
if (varList?.Count != 0)
{
if (driverPropertys.IsList)
{
var listChunk = varList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var variables in listChunk)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
var data = variables.GetSciptListValue(driverPropertys.BigTextScriptVariableModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.VariableQueueName, data, properties);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
else
{
foreach (var variable in varList)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
var data = variable.GetSciptListValue(driverPropertys.BigTextScriptVariableModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.VariableQueueName, data, properties);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
}
else
{
if (exVariableTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.Adapt<List<VariableData>>();
if (varList?.Count != 0)
{
if (driverPropertys.IsList)
{
var listChunk = varList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var variables in listChunk)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
var data = variables.GetSciptListValue(driverPropertys.BigTextScriptVariableModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.VariableQueueName, data, properties);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
else
{
foreach (var variable in varList)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
var data = variable.GetSciptListValue(driverPropertys.BigTextScriptVariableModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.VariableQueueName, data, properties);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var devList = _collectDeviceRunTimes.ToListWithDequeue();
if (devList?.Count != 0)
{
if (driverPropertys.IsList)
{
var listChunk = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var devices in listChunk)
{
try
{
var data = devices.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.DeviceQueueName, data, properties);
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
else
{
foreach (var devices in devList)
{
try
{
var data = devices.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.DeviceQueueName, data, properties);
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
}
else
{
if (exDeviceTimerTick.IsTickHappen())
{
var devList = _collectDevice.Adapt<List<DeviceData>>();
if (devList?.Count != 0)
{
if (driverPropertys.IsList)
{
var listChunk = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var devices in listChunk)
{
try
{
var data = devices.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.DeviceQueueName, data, properties);
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
else
{
foreach (var devices in devList)
{
try
{
var data = devices.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel);
// 设置消息持久化
IBasicProperties properties = _model?.CreateBasicProperties();
await Publish(driverPropertys.DeviceQueueName, data, properties);
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <inheritdoc/>
public override bool IsConnected() => _connection?.IsOpen == true;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $" {nameof(RabbitMQClient)} IP:{driverPropertys.IP} Port:{driverPropertys.Port}";
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_globalDeviceData?.AllVariables.ForEach(a => a.VariableValueChange -= VariableValueChange);
_collectDevice?.ForEach(a =>
{
a.DeviceStatusChange -= DeviceStatusChange;
});
_model?.SafeDispose();
_connection?.SafeDispose();
_uploadVariables = null;
_collectDeviceRunTimes.Clear();
_collectVariableRunTimes.Clear();
_collectDeviceRunTimes = null;
_collectVariableRunTimes = null;
}
private List<CollectDeviceRunTime> _collectDevice;
/// <inheritdoc/>
protected override void Init(UploadDeviceRunTime device)
{
_connectionFactory = new ConnectionFactory
{
HostName = driverPropertys.IP,
Port = driverPropertys.Port,
UserName = driverPropertys.UserName,
Password = driverPropertys.Password,
VirtualHost = driverPropertys.VirtualHost,
};
_globalDeviceData = App.GetService<GlobalDeviceData>();
_rpcCore = App.GetService<RpcSingletonService>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => b.VariablePropertys[device.Id].Any(c =>
{
if (c.PropertyName == nameof(variablePropertys.Enable))
{
return c.Value?.GetBoolValue() == true;
}
else
return false;
}))
.ToList();
_uploadVariables = tags;
_collectDevice = _globalDeviceData.CollectDevices.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ToList();
_collectDevice.ForEach(a =>
{
a.DeviceStatusChange += DeviceStatusChange;
DeviceStatusChange(a);
});
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
VariableValueChange(a);
});
if (driverPropertys.UploadInterval <= 1000) driverPropertys.UploadInterval = 1000;
exVariableTimerTick = new(driverPropertys.UploadInterval);
exDeviceTimerTick = new(driverPropertys.UploadInterval);
}
private void DeviceStatusChange(CollectDeviceRunTime collectDeviceRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectDeviceRunTimes.Enqueue(collectDeviceRunTime.Adapt<DeviceData>());
}
private async Task Publish(string queueName, string data, IBasicProperties properties)
{
try
{
if (properties != null)
properties.Persistent = true;
if (_model != null)
_model.BasicPublish(driverPropertys.ExchangeName, queueName, properties, Encoding.UTF8.GetBytes(data));
else
{
await CacheDb.AddCacheData(queueName, data, driverPropertys.CacheMaxCount);
return;
}
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData(10);
foreach (var item in cacheData)
{
try
{
_model?.BasicPublish(driverPropertys.ExchangeName, item.Topic, properties, Encoding.UTF8.GetBytes(item.CacheStr));
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
await CacheDb.DeleteCacheData(item.Id);
}
catch
{
}
}
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{queueName}{Environment.NewLine}负载:{data}");
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
await CacheDb.AddCacheData(queueName, data, driverPropertys.CacheMaxCount);
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<VariableData>());
}
}

View File

@@ -1,68 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/S7_1200"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension;
@using ThingsGateway.Foundation.Serial;
@using Masa.Blazor
<TcpClientPage @ref=TcpClientPage></TcpClientPage>
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">驱动配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
@if (_plc != null)
{
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.FrameTime)) Dense HideDetails="@("auto")" @bind-Value=@_plc.FrameTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.CacheTimeout)) Dense HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.TimeOut)) Dense HideDetails="@("auto")" @bind-Value=@_plc.TimeOut></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Slot)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Slot></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Rack)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Rack></MTextField>
<MSelect Class="ma-1" Outlined Style="max-width:200px" @bind-Value="_plc.DataFormat" Label="@(_plc.DescriptionWithOutSugar(x => x.DataFormat))"
Items=@(typeof(DataFormat).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataFormat)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
}
</MRow>
</MCard>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections">
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,91 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Adapter.Siemens;
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class S7_1200DebugPage
{
/// <summary>
/// SerialSessionPage
/// </summary>
private TcpClientPage TcpClientPage;
private DriverDebugUIPage driverDebugUIPage;
private ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC _plc;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_sections.Add((
"""
private static async Task ModbusClientAsync()
{
//链路基础配置项
var config = new TouchSocketConfig();
config
.SetRemoteIPHost(new IPHost("127.0.0.1:502"))//TCP/UDP链路才需要
var tcpClient1 = new TcpClient();//链路对象
tcpClient1.Setup(config);
//创建协议对象,构造函数需要传入对应链路对象
SiemensS7PLC plc = new(tcpClient1,SiemensEnum.S1500)
{
//协议配置
DataFormat = DataFormat.ABCD,
FrameTime = 0,
CacheTimeout = 1000,
ConnectTimeOut = 3000,
Station = 1,
TimeOut = 3000,
IsCheckMessageId = true
};
#region
var bytesResult = await plc.ReadAsync("400001", 20);
var int32sResult = await plc.ReadInt32Async("400001", 20);
#endregion
}
""", "csharp"));
if (TcpClientPage != null)
TcpClientPage.LogAction = driverDebugUIPage.LogOut;
_plc = new ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC(TcpClientPage.GetTcpClient(), SiemensEnum.S1200);
driverDebugUIPage.Plc = _plc;
//初始化
driverDebugUIPage.Address = "M100";
int index = 0;
driverDebugUIPage.DeviceVariableRunTimes.ForEach(a => a.VariableAddress = "M" + (100 + index++));
TcpClientPage.Port = 102;
TcpClientPage.StateHasChangedAsync();
//载入配置
StateHasChanged();
}
base.OnAfterRender(firstRender);
}
}

View File

@@ -1,68 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/S7_1500"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension;
@using ThingsGateway.Foundation.Serial;
@using Masa.Blazor
<TcpClientPage @ref=TcpClientPage></TcpClientPage>
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">驱动配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
@if (_plc != null)
{
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.FrameTime)) Dense HideDetails="@("auto")" @bind-Value=@_plc.FrameTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.CacheTimeout)) Dense HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.TimeOut)) Dense HideDetails="@("auto")" @bind-Value=@_plc.TimeOut></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Slot)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Slot></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Rack)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Rack></MTextField>
<MSelect Class="ma-1" Outlined Style="max-width:200px" @bind-Value="_plc.DataFormat" Label="@(_plc.DescriptionWithOutSugar(x => x.DataFormat))"
Items=@(typeof(DataFormat).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataFormat)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
}
</MRow>
</MCard>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections">
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,92 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Adapter.Siemens;
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class S7_1500DebugPage
{
/// <summary>
/// SerialSessionPage
/// </summary>
private TcpClientPage TcpClientPage;
private DriverDebugUIPage driverDebugUIPage;
private ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC _plc;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_sections.Add((
"""
private static async Task ModbusClientAsync()
{
//链路基础配置项
var config = new TouchSocketConfig();
config
.SetRemoteIPHost(new IPHost("127.0.0.1:502"))//TCP/UDP链路才需要
var tcpClient1 = new TcpClient();//链路对象
tcpClient1.Setup(config);
//创建协议对象,构造函数需要传入对应链路对象
SiemensS7PLC plc = new(tcpClient1,SiemensEnum.S1500)
{
//协议配置
DataFormat = DataFormat.ABCD,
FrameTime = 0,
CacheTimeout = 1000,
ConnectTimeOut = 3000,
Station = 1,
TimeOut = 3000,
IsCheckMessageId = true
};
#region
var bytesResult = await plc.ReadAsync("400001", 20);
var int32sResult = await plc.ReadInt32Async("400001", 20);
#endregion
}
""", "csharp"));
if (TcpClientPage != null)
TcpClientPage.LogAction = driverDebugUIPage.LogOut;
_plc = new ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC(TcpClientPage.GetTcpClient(), SiemensEnum.S1500);
driverDebugUIPage.Plc = _plc;
//初始化
driverDebugUIPage.Address = "M100";
int index = 0;
driverDebugUIPage.DeviceVariableRunTimes.ForEach(a => a.VariableAddress = "M" + (100 + index++));
TcpClientPage.Port = 102;
TcpClientPage.StateHasChangedAsync();
//载入配置
StateHasChanged();
}
base.OnAfterRender(firstRender);
}
}

View File

@@ -1,68 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/S7_200"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension;
@using ThingsGateway.Foundation.Serial;
@using Masa.Blazor
<TcpClientPage @ref=TcpClientPage></TcpClientPage>
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">驱动配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
@if (_plc != null)
{
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.FrameTime)) Dense HideDetails="@("auto")" @bind-Value=@_plc.FrameTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.CacheTimeout)) Dense HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.TimeOut)) Dense HideDetails="@("auto")" @bind-Value=@_plc.TimeOut></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Slot)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Slot></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Rack)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Rack></MTextField>
<MSelect Class="ma-1" Outlined Style="max-width:200px" @bind-Value="_plc.DataFormat" Label="@(_plc.DescriptionWithOutSugar(x => x.DataFormat))"
Items=@(typeof(DataFormat).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataFormat)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
}
</MRow>
</MCard>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections">
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,92 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Adapter.Siemens;
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class S7_200DebugPage
{
/// <summary>
/// SerialSessionPage
/// </summary>
private TcpClientPage TcpClientPage;
private DriverDebugUIPage driverDebugUIPage;
private ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC _plc;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_sections.Add((
"""
private static async Task ModbusClientAsync()
{
//链路基础配置项
var config = new TouchSocketConfig();
config
.SetRemoteIPHost(new IPHost("127.0.0.1:502"))//TCP/UDP链路才需要
var tcpClient1 = new TcpClient();//链路对象
tcpClient1.Setup(config);
//创建协议对象,构造函数需要传入对应链路对象
SiemensS7PLC plc = new(tcpClient1,SiemensEnum.S1500)
{
//协议配置
DataFormat = DataFormat.ABCD,
FrameTime = 0,
CacheTimeout = 1000,
ConnectTimeOut = 3000,
Station = 1,
TimeOut = 3000,
IsCheckMessageId = true
};
#region
var bytesResult = await plc.ReadAsync("400001", 20);
var int32sResult = await plc.ReadInt32Async("400001", 20);
#endregion
}
""", "csharp"));
if (TcpClientPage != null)
TcpClientPage.LogAction = driverDebugUIPage.LogOut;
_plc = new ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC(TcpClientPage.GetTcpClient(), SiemensEnum.S200);
driverDebugUIPage.Plc = _plc;
//初始化
driverDebugUIPage.Address = "M100";
int index = 0;
driverDebugUIPage.DeviceVariableRunTimes.ForEach(a => a.VariableAddress = "M" + (100 + index++));
TcpClientPage.Port = 102;
TcpClientPage.StateHasChangedAsync();
//载入配置
StateHasChanged();
}
base.OnAfterRender(firstRender);
}
}

View File

@@ -1,68 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/S7_200SMART"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension;
@using ThingsGateway.Foundation.Serial;
@using Masa.Blazor
<TcpClientPage @ref=TcpClientPage></TcpClientPage>
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">驱动配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
@if (_plc != null)
{
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.FrameTime)) Dense HideDetails="@("auto")" @bind-Value=@_plc.FrameTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.CacheTimeout)) Dense HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.TimeOut)) Dense HideDetails="@("auto")" @bind-Value=@_plc.TimeOut></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Slot)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Slot></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Rack)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Rack></MTextField>
<MSelect Class="ma-1" Outlined Style="max-width:200px" @bind-Value="_plc.DataFormat" Label="@(_plc.DescriptionWithOutSugar(x => x.DataFormat))"
Items=@(typeof(DataFormat).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataFormat)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
}
</MRow>
</MCard>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections">
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,92 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Adapter.Siemens;
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class S7_200SMARTDebugPage
{
/// <summary>
/// SerialSessionPage
/// </summary>
private TcpClientPage TcpClientPage;
private DriverDebugUIPage driverDebugUIPage;
private ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC _plc;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_sections.Add((
"""
private static async Task ModbusClientAsync()
{
//链路基础配置项
var config = new TouchSocketConfig();
config
.SetRemoteIPHost(new IPHost("127.0.0.1:502"))//TCP/UDP链路才需要
var tcpClient1 = new TcpClient();//链路对象
tcpClient1.Setup(config);
//创建协议对象,构造函数需要传入对应链路对象
SiemensS7PLC plc = new(tcpClient1,SiemensEnum.S1500)
{
//协议配置
DataFormat = DataFormat.ABCD,
FrameTime = 0,
CacheTimeout = 1000,
ConnectTimeOut = 3000,
Station = 1,
TimeOut = 3000,
IsCheckMessageId = true
};
#region
var bytesResult = await plc.ReadAsync("400001", 20);
var int32sResult = await plc.ReadInt32Async("400001", 20);
#endregion
}
""", "csharp"));
if (TcpClientPage != null)
TcpClientPage.LogAction = driverDebugUIPage.LogOut;
_plc = new ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC(TcpClientPage.GetTcpClient(), SiemensEnum.S200Smart);
driverDebugUIPage.Plc = _plc;
//初始化
driverDebugUIPage.Address = "M100";
int index = 0;
driverDebugUIPage.DeviceVariableRunTimes.ForEach(a => a.VariableAddress = "M" + (100 + index++));
TcpClientPage.Port = 102;
TcpClientPage.StateHasChangedAsync();
//载入配置
StateHasChanged();
}
base.OnAfterRender(firstRender);
}
}

View File

@@ -1,68 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/S7_300"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension;
@using ThingsGateway.Foundation.Serial;
@using Masa.Blazor
<TcpClientPage @ref=TcpClientPage></TcpClientPage>
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">驱动配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
@if (_plc != null)
{
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.FrameTime)) Dense HideDetails="@("auto")" @bind-Value=@_plc.FrameTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.CacheTimeout)) Dense HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.TimeOut)) Dense HideDetails="@("auto")" @bind-Value=@_plc.TimeOut></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Slot)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Slot></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Rack)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Rack></MTextField>
<MSelect Class="ma-1" Outlined Style="max-width:200px" @bind-Value="_plc.DataFormat" Label="@(_plc.DescriptionWithOutSugar(x => x.DataFormat))"
Items=@(typeof(DataFormat).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataFormat)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
}
</MRow>
</MCard>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections">
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,92 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Adapter.Siemens;
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class S7_300DebugPage
{
/// <summary>
/// SerialSessionPage
/// </summary>
private TcpClientPage TcpClientPage;
private DriverDebugUIPage driverDebugUIPage;
private ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC _plc;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_sections.Add((
"""
private static async Task ModbusClientAsync()
{
//链路基础配置项
var config = new TouchSocketConfig();
config
.SetRemoteIPHost(new IPHost("127.0.0.1:502"))//TCP/UDP链路才需要
var tcpClient1 = new TcpClient();//链路对象
tcpClient1.Setup(config);
//创建协议对象,构造函数需要传入对应链路对象
SiemensS7PLC plc = new(tcpClient1,SiemensEnum.S1500)
{
//协议配置
DataFormat = DataFormat.ABCD,
FrameTime = 0,
CacheTimeout = 1000,
ConnectTimeOut = 3000,
Station = 1,
TimeOut = 3000,
IsCheckMessageId = true
};
#region
var bytesResult = await plc.ReadAsync("400001", 20);
var int32sResult = await plc.ReadInt32Async("400001", 20);
#endregion
}
""", "csharp"));
if (TcpClientPage != null)
TcpClientPage.LogAction = driverDebugUIPage.LogOut;
_plc = new ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC(TcpClientPage.GetTcpClient(), SiemensEnum.S300);
driverDebugUIPage.Plc = _plc;
//初始化
driverDebugUIPage.Address = "M100";
int index = 0;
driverDebugUIPage.DeviceVariableRunTimes.ForEach(a => a.VariableAddress = "M" + (100 + index++));
TcpClientPage.Port = 102;
TcpClientPage.StateHasChangedAsync();
//载入配置
StateHasChanged();
}
base.OnAfterRender(firstRender);
}
}

View File

@@ -1,68 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/S7_400"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension;
@using ThingsGateway.Foundation.Serial;
@using Masa.Blazor
<TcpClientPage @ref=TcpClientPage></TcpClientPage>
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">驱动配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
@if (_plc != null)
{
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.FrameTime)) Dense HideDetails="@("auto")" @bind-Value=@_plc.FrameTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.CacheTimeout)) Dense HideDetails="@("auto")" @bind-Value=@_plc.CacheTimeout></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.TimeOut)) Dense HideDetails="@("auto")" @bind-Value=@_plc.TimeOut></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Slot)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Slot></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(_plc.DescriptionWithOutSugar(x => x.Rack)) Dense HideDetails="@("auto")" @bind-Value=@_plc.Rack></MTextField>
<MSelect Class="ma-1" Outlined Style="max-width:200px" @bind-Value="_plc.DataFormat" Label="@(_plc.DescriptionWithOutSugar(x => x.DataFormat))"
Items=@(typeof(DataFormat).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataFormat)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
}
</MRow>
</MCard>
<DriverDebugUIPage @ref=driverDebugUIPage Sections="_sections">
</DriverDebugUIPage>
@code {
private readonly List<(string Code, string Language)> _sections = new();
}

View File

@@ -1,54 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Siemens
{
/// <inheritdoc/>
public class S7_1200 : Siemens
{
/// <summary>
/// <inheritdoc/>
/// </summary>
public override Type DriverDebugUIType => typeof(S7_1200DebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client, SiemensEnum.S1200)
{
DataFormat = driverPropertys.DataFormat,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
TimeOut = driverPropertys.TimeOut
};
if (driverPropertys.LocalTSAP != 0)
{
_plc.LocalTSAP = driverPropertys.LocalTSAP;
}
if (driverPropertys.DestTSAP != 0)
{
_plc.DestTSAP = driverPropertys.DestTSAP;
}
}
}
}

View File

@@ -1,53 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Siemens
{
/// <inheritdoc/>
public class S7_1500 : Siemens
{
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(S7_1500DebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client, SiemensEnum.S1500)
{
DataFormat = driverPropertys.DataFormat,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
TimeOut = driverPropertys.TimeOut
};
if (driverPropertys.LocalTSAP != 0)
{
_plc.LocalTSAP = driverPropertys.LocalTSAP;
}
if (driverPropertys.DestTSAP != 0)
{
_plc.DestTSAP = driverPropertys.DestTSAP;
}
}
}
}

View File

@@ -1,53 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Siemens
{
/// <inheritdoc/>
public class S7_200 : Siemens
{
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(S7_200DebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client, SiemensEnum.S200)
{
DataFormat = driverPropertys.DataFormat,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
TimeOut = driverPropertys.TimeOut
};
if (driverPropertys.LocalTSAP != 0)
{
_plc.LocalTSAP = driverPropertys.LocalTSAP;
}
if (driverPropertys.DestTSAP != 0)
{
_plc.DestTSAP = driverPropertys.DestTSAP;
}
}
}
}

View File

@@ -1,52 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Siemens
{
/// <inheritdoc/>
public class S7_200SMART : Siemens
{
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(S7_200SMARTDebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client, SiemensEnum.S200Smart)
{
DataFormat = driverPropertys.DataFormat,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
TimeOut = driverPropertys.TimeOut
};
if (driverPropertys.LocalTSAP != 0)
{
_plc.LocalTSAP = driverPropertys.LocalTSAP;
}
if (driverPropertys.DestTSAP != 0)
{
_plc.DestTSAP = driverPropertys.DestTSAP;
}
}
}
}

View File

@@ -1,53 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Siemens
{
/// <inheritdoc/>
public class S7_300 : Siemens
{
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(S7_300DebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client, SiemensEnum.S300)
{
DataFormat = driverPropertys.DataFormat,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
TimeOut = driverPropertys.TimeOut
};
if (driverPropertys.LocalTSAP != 0)
{
_plc.LocalTSAP = driverPropertys.LocalTSAP;
}
if (driverPropertys.DestTSAP != 0)
{
_plc.DestTSAP = driverPropertys.DestTSAP;
}
}
}
}

View File

@@ -1,53 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Plugin.Siemens
{
/// <inheritdoc/>
public class S7_400 : Siemens
{
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(S7_400DebugPage);
/// <inheritdoc/>
public override CollectDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
protected override void Init(CollectDeviceRunTime device, object client = null)
{
if (client == null)
{
FoundataionConfig.SetRemoteIPHost(new IPHost($"{driverPropertys.IP}:{driverPropertys.Port}"))
;
client = new TcpClient();
((TcpClient)client).Setup(FoundataionConfig);
}
//载入配置
_plc = new((TcpClient)client, SiemensEnum.S400)
{
DataFormat = driverPropertys.DataFormat,
ConnectTimeOut = driverPropertys.ConnectTimeOut,
TimeOut = driverPropertys.TimeOut
};
if (driverPropertys.LocalTSAP != 0)
{
_plc.LocalTSAP = driverPropertys.LocalTSAP;
}
if (driverPropertys.DestTSAP != 0)
{
_plc.DestTSAP = driverPropertys.DestTSAP;
}
}
}
}

View File

@@ -1,35 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorComponent
@using Masa.Blazor
@using Masa.Blazor.Presets
@using System.Net.Http.Json
@using System.IO;
@using System.Text.Json;
@using System.Reflection;
@using ThingsGateway.Components;
@using ThingsGateway.Admin.Core;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Foundation.Extension.String;
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Core;
@using ThingsGateway.Gateway.Application;
@using ThingsGateway.Gateway.Core;

View File

@@ -3,48 +3,40 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33927.249
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj", "{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{9EB46BB6-D4EA-4B06-95EE-6C971E653030}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{4E66C22C-0636-4949-BF6A-9E3BBE1550BA}"
ProjectSection(SolutionItems) = preProject
Web\Directory.Build.props = Web\Directory.Build.props
admin\Directory.Build.props = admin\Directory.Build.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "script", "script", "{4A64518E-C072-4607-BBF7-7D392CEC9D58}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "admin\ThingsGateway.Components\ThingsGateway.Components.csproj", "{0A891D8E-23B3-46AD-8D30-565EE5004F93}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "admin\ThingsGateway.Core\ThingsGateway.Core.csproj", "{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Core", "admin\ThingsGateway.Admin.Core\ThingsGateway.Admin.Core.csproj", "{5DA3D2BD-6768-4479-B52F-49E022EFF310}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Blazor", "admin\ThingsGateway.Admin.Blazor\ThingsGateway.Admin.Blazor.csproj", "{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Application", "admin\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{D6685A42-2712-417A-92C5-5EFF90B9FA94}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.ApiController", "admin\ThingsGateway.Admin.ApiController\ThingsGateway.Admin.ApiController.csproj", "{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}"
ProjectSection(SolutionItems) = preProject
web\Directory.Build.props = web\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Core", "web\ThingsGateway.Web.Core\ThingsGateway.Web.Core.csproj", "{D37EC028-EA46-4510-8261-6E780A906314}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Entry", "web\ThingsGateway.Web.Entry\ThingsGateway.Web.Entry.csproj", "{C5F662EB-991F-438D-BF61-EF87E7371C04}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{97B23D8B-C6C0-4746-A21F-C7B49354B284}"
ProjectSection(SolutionItems) = preProject
..\.gitignore = ..\.gitignore
..\README.md = ..\README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "Web\ThingsGateway.Components\ThingsGateway.Components.csproj", "{799C49A4-8E23-475A-A82D-080854718BEE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj", "{6961511A-8787-42AF-827D-B630B2AF4791}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Core", "Web\ThingsGateway.Admin.Core\ThingsGateway.Admin.Core.csproj", "{616CA361-B667-42C8-B4DC-097C7CD39830}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Application", "Web\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{16C62A28-BACE-4391-91F8-C2D78D063A1E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.ApiController", "Web\ThingsGateway.Admin.ApiController\ThingsGateway.Admin.ApiController.csproj", "{8FA03089-322F-44CB-8E4B-F2637388E944}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Blazor", "Web\ThingsGateway.Admin.Blazor\ThingsGateway.Admin.Blazor.csproj", "{14FF7150-6DB7-455B-AD00-6AB4DE37855B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Entry", "Web\ThingsGateway.Web.Entry\ThingsGateway.Web.Entry.csproj", "{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Core", "Web\ThingsGateway.Web.Core\ThingsGateway.Web.Core.csproj", "{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "Web\ThingsGateway.Core\ThingsGateway.Core.csproj", "{51313113-7BB8-494E-9C24-6787BECE39BB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Admin", "Admin", "{79E7042F-F9E3-4D87-BFA9-4B7DD9736735}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E8D2CBBA-9BCC-44E0-B192-BA0214010203}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Foundation", "Foundation", "{B6288ADE-A570-4962-8907-991B0FF2D89C}"
ProjectSection(SolutionItems) = preProject
Foundation\Directory.Build.props = Foundation\Directory.Build.props
EndProjectSection
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "foundation", "foundation", "{268A1A81-2685-47E1-9986-5934A58A31A4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -52,58 +44,56 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Release|Any CPU.Build.0 = Release|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Release|Any CPU.Build.0 = Release|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Debug|Any CPU.Build.0 = Debug|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Release|Any CPU.ActiveCfg = Release|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Release|Any CPU.Build.0 = Release|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Release|Any CPU.Build.0 = Release|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Release|Any CPU.Build.0 = Release|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Release|Any CPU.Build.0 = Release|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Release|Any CPU.Build.0 = Release|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Release|Any CPU.Build.0 = Release|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Release|Any CPU.Build.0 = Release|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.Build.0 = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.Build.0 = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.Build.0 = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.Build.0 = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.Build.0 = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.Build.0 = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.Build.0 = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.Build.0 = Release|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891} = {B6288ADE-A570-4962-8907-991B0FF2D89C}
{799C49A4-8E23-475A-A82D-080854718BEE} = {BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15}
{616CA361-B667-42C8-B4DC-097C7CD39830} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{16C62A28-BACE-4391-91F8-C2D78D063A1E} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{8FA03089-322F-44CB-8E4B-F2637388E944} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{14FF7150-6DB7-455B-AD00-6AB4DE37855B} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{51313113-7BB8-494E-9C24-6787BECE39BB} = {BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15}
{79E7042F-F9E3-4D87-BFA9-4B7DD9736735} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{0A891D8E-23B3-46AD-8D30-565EE5004F93} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{5DA3D2BD-6768-4479-B52F-49E022EFF310} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{D6685A42-2712-417A-92C5-5EFF90B9FA94} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{D37EC028-EA46-4510-8261-6E780A906314} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{C5F662EB-991F-438D-BF61-EF87E7371C04} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{6961511A-8787-42AF-827D-B630B2AF4791} = {268A1A81-2685-47E1-9986-5934A58A31A4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C49B2D3E-6818-4E28-91B7-6E4E7E264BBB}

View File

@@ -1,49 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33927.249
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj", "{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "Web\ThingsGateway.Components\ThingsGateway.Components.csproj", "{799C49A4-8E23-475A-A82D-080854718BEE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "Web\ThingsGateway.Core\ThingsGateway.Core.csproj", "{51313113-7BB8-494E-9C24-6787BECE39BB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.UpgradeManger", "UpgradeManger\ThingsGateway.UpgradeManger\ThingsGateway.UpgradeManger.csproj", "{84362F1D-E788-4646-B555-5A3629B55EFC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Upgrade", "UpgradeManger\ThingsGateway.Upgrade\ThingsGateway.Upgrade.csproj", "{681F774F-7B0B-450A-917C-1385E1847CA6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Release|Any CPU.Build.0 = Release|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Release|Any CPU.Build.0 = Release|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Release|Any CPU.Build.0 = Release|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Release|Any CPU.Build.0 = Release|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C49B2D3E-6818-4E28-91B7-6E4E7E264BBB}
EndGlobalSection
EndGlobal

View File

@@ -3,107 +3,107 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33927.249
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj", "{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "foundation\ThingsGateway.foundation\ThingsGateway.Foundation.csproj", "{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Foundation", "Foundation", "{0874CBC5-C583-4FAD-BA93-94571D446898}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "foundation", "foundation", "{0874CBC5-C583-4FAD-BA93-94571D446898}"
ProjectSection(SolutionItems) = preProject
Foundation\Directory.Build.props = Foundation\Directory.Build.props
foundation\Directory.Build.props = foundation\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.DLT645", "Foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj", "{92963877-0185-45A5-A0EB-CEC0D55FF9B0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.DLT645", "foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj", "{92963877-0185-45A5-A0EB-CEC0D55FF9B0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.Modbus", "Foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj", "{24510CCE-0B60-4A03-9719-CF367C3528E9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.Modbus", "foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj", "{24510CCE-0B60-4A03-9719-CF367C3528E9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.OPCDA", "Foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj", "{566783A4-222B-46F5-AA12-0753997B3254}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.OPCDA", "foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj", "{566783A4-222B-46F5-AA12-0753997B3254}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.OPCUA", "Foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj", "{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.OPCUA", "foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj", "{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.Siemens", "Foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj", "{9695B353-D773-40DD-B65E-7B10EB0C16EC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.Siemens", "foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj", "{9695B353-D773-40DD-B65E-7B10EB0C16EC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Demo", "Demo", "{95008B83-0324-4A7C-80DE-2BBDDD1A9099}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "demo", "demo", "{358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}"
ProjectSection(SolutionItems) = preProject
Demo\Directory.Build.props = Demo\Directory.Build.props
demo\Directory.Build.props = demo\Directory.Build.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{9EB46BB6-D4EA-4B06-95EE-6C971E653030}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Photino", "demo\ThingsGateway.Foundation.Demo.Photino\ThingsGateway.Foundation.Demo.Photino.csproj", "{2192217C-CF77-422E-9E63-DF4003ABF01A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Rcl", "demo\ThingsGateway.Foundation.Demo.Rcl\ThingsGateway.Foundation.Demo.Rcl.csproj", "{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Winform", "demo\ThingsGateway.Foundation.Demo.Winform\ThingsGateway.Foundation.Demo.Winform.csproj", "{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gateway", "gateway", "{DFB97103-FC3A-4DC3-A327-DA8C65BDA607}"
ProjectSection(SolutionItems) = preProject
Web\Directory.Build.props = Web\Directory.Build.props
gateway\Directory.Build.props = gateway\Directory.Build.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "script", "script", "{4A64518E-C072-4607-BBF7-7D392CEC9D58}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{4E66C22C-0636-4949-BF6A-9E3BBE1550BA}"
ProjectSection(SolutionItems) = preProject
admin\Directory.Build.props = admin\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "admin\ThingsGateway.Components\ThingsGateway.Components.csproj", "{0A891D8E-23B3-46AD-8D30-565EE5004F93}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "admin\ThingsGateway.Core\ThingsGateway.Core.csproj", "{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Core", "admin\ThingsGateway.Admin.Core\ThingsGateway.Admin.Core.csproj", "{5DA3D2BD-6768-4479-B52F-49E022EFF310}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Blazor", "admin\ThingsGateway.Admin.Blazor\ThingsGateway.Admin.Blazor.csproj", "{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Application", "admin\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{D6685A42-2712-417A-92C5-5EFF90B9FA94}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.ApiController", "admin\ThingsGateway.Admin.ApiController\ThingsGateway.Admin.ApiController.csproj", "{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Core", "gateway\ThingsGateway.Gateway.Core\ThingsGateway.Gateway.Core.csproj", "{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Blazor", "gateway\ThingsGateway.Gateway.Blazor\ThingsGateway.Gateway.Blazor.csproj", "{69EA3D89-CB40-425A-8D70-5E4A33337BE5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Application", "gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj", "{90AB5C24-1AA3-4F58-9987-B307B92B5193}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.ApiController", "gateway\ThingsGateway.Gateway.ApiController\ThingsGateway.Gateway.ApiController.csproj", "{4C7A5A90-8292-413B-8848-419D9DCDE66F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}"
ProjectSection(SolutionItems) = preProject
web\Directory.Build.props = web\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Core", "web\ThingsGateway.Web.Core\ThingsGateway.Web.Core.csproj", "{D37EC028-EA46-4510-8261-6E780A906314}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Entry", "web\ThingsGateway.Web.Entry\ThingsGateway.Web.Entry.csproj", "{C5F662EB-991F-438D-BF61-EF87E7371C04}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugin", "plugin", "{E65490B8-D2E2-4693-B39C-15703B1EBFBB}"
ProjectSection(SolutionItems) = preProject
plugin\Directory.Build.props = plugin\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Modbus", "plugin\ThingsGateway.Plugin.Modbus\ThingsGateway.Plugin.Modbus.csproj", "{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Mqtt", "plugin\ThingsGateway.Plugin.Mqtt\ThingsGateway.Plugin.Mqtt.csproj", "{53C870AE-0249-4485-AE63-F8A16EA4BCB4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{97B23D8B-C6C0-4746-A21F-C7B49354B284}"
ProjectSection(SolutionItems) = preProject
..\.gitignore = ..\.gitignore
..\README.md = ..\README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "Web\ThingsGateway.Components\ThingsGateway.Components.csproj", "{799C49A4-8E23-475A-A82D-080854718BEE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Kafka", "plugin\ThingsGateway.Plugin.Kafka\ThingsGateway.Plugin.Kafka.csproj", "{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Core", "Web\ThingsGateway.Admin.Core\ThingsGateway.Admin.Core.csproj", "{616CA361-B667-42C8-B4DC-097C7CD39830}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.SQLDB", "plugin\ThingsGateway.Plugin.SQLDB\ThingsGateway.Plugin.SQLDB.csproj", "{C102AB3A-377E-4753-AFA7-C13250D7DF00}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Application", "Web\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{16C62A28-BACE-4391-91F8-C2D78D063A1E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.QuestDB", "plugin\ThingsGateway.Plugin.QuestDB\ThingsGateway.Plugin.QuestDB.csproj", "{0DE1D254-0BD2-4D98-B939-5440BE5EB552}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.ApiController", "Web\ThingsGateway.Admin.ApiController\ThingsGateway.Admin.ApiController.csproj", "{8FA03089-322F-44CB-8E4B-F2637388E944}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.TDengineDB", "plugin\ThingsGateway.Plugin.TDengineDB\ThingsGateway.Plugin.TDengineDB.csproj", "{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Blazor", "Web\ThingsGateway.Admin.Blazor\ThingsGateway.Admin.Blazor.csproj", "{14FF7150-6DB7-455B-AD00-6AB4DE37855B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.RabbitMQ", "plugin\ThingsGateway.Plugin.RabbitMQ\ThingsGateway.Plugin.RabbitMQ.csproj", "{A8E68E17-4EBF-4E4C-8272-B489329A68BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Entry", "Web\ThingsGateway.Web.Entry\ThingsGateway.Web.Entry.csproj", "{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Siemens", "plugin\ThingsGateway.Plugin.Siemens\ThingsGateway.Plugin.Siemens.csproj", "{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Core", "Web\ThingsGateway.Web.Core\ThingsGateway.Web.Core.csproj", "{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.DLT645", "plugin\ThingsGateway.Plugin.DLT645\ThingsGateway.Plugin.DLT645.csproj", "{AC4295F2-AB2F-4137-99EF-80FA5C83896B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "Web\ThingsGateway.Core\ThingsGateway.Core.csproj", "{51313113-7BB8-494E-9C24-6787BECE39BB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OPCDA", "plugin\ThingsGateway.Plugin.OPCDA\ThingsGateway.Plugin.OPCDA.csproj", "{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Admin", "Admin", "{79E7042F-F9E3-4D87-BFA9-4B7DD9736735}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OPCUA", "plugin\ThingsGateway.Plugin.OPCUA\ThingsGateway.Plugin.OPCUA.csproj", "{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gateway", "Gateway", "{000C3C62-345E-451C-8CEE-6F2C6A087116}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.ApiController", "Web\ThingsGateway.Gateway.ApiController\ThingsGateway.Gateway.ApiController.csproj", "{5D7BE567-2345-46C8-9F54-DDC1DA96D198}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Application", "Web\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj", "{5CF1B3EC-84E2-484A-8DFC-2ECD2EE18E2F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Blazor", "Web\ThingsGateway.Gateway.Blazor\ThingsGateway.Gateway.Blazor.csproj", "{CD0F211A-F65B-4026-9750-68AC3C70D012}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Core", "Web\ThingsGateway.Gateway.Core\ThingsGateway.Gateway.Core.csproj", "{5CD79F91-7182-4A9D-9BEF-4DF410C782D2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugin", "Plugin", "{CC8D0880-B73E-4DFC-9052-86504728708E}"
ProjectSection(SolutionItems) = preProject
Plugin\Directory.Build.props = Plugin\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Modbus", "Plugin\ThingsGateway.Plugin.Modbus\ThingsGateway.Plugin.Modbus.csproj", "{2057E5BE-FACA-4D44-A2BA-E1F864A8DAFF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.DLT645", "Plugin\ThingsGateway.Plugin.DLT645\ThingsGateway.Plugin.DLT645.csproj", "{A723D4D7-B796-4D97-BA68-95E5696C9559}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Kafka", "Plugin\ThingsGateway.Plugin.Kafka\ThingsGateway.Plugin.Kafka.csproj", "{D9944D52-81B4-4DBC-8C3B-2A334CCBD4F6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Mqtt", "Plugin\ThingsGateway.Plugin.Mqtt\ThingsGateway.Plugin.Mqtt.csproj", "{C5C89B2F-D9C9-4A67-A9BE-4E5F0B42162F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OPCDA", "Plugin\ThingsGateway.Plugin.OPCDA\ThingsGateway.Plugin.OPCDA.csproj", "{7562C85D-267D-4718-8857-422B625C5BD0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OPCUA", "Plugin\ThingsGateway.Plugin.OPCUA\ThingsGateway.Plugin.OPCUA.csproj", "{A0E1EAC7-10DD-4520-973F-CC385BBFBD84}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.RabbitMQ", "Plugin\ThingsGateway.Plugin.RabbitMQ\ThingsGateway.Plugin.RabbitMQ.csproj", "{503529C4-842A-47F0-928B-C8DC5B0A367D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Siemens", "Plugin\ThingsGateway.Plugin.Siemens\ThingsGateway.Plugin.Siemens.csproj", "{8A9F6586-3320-4F03-B3DA-09BF39AA90A0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E8D2CBBA-9BCC-44E0-B192-BA0214010203}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpgradeManger", "UpgradeManger", "{237C7BC5-7B07-40B5-AF42-CE2F8E0893C3}"
ProjectSection(SolutionItems) = preProject
UpgradeManger\Directory.Build.props = UpgradeManger\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.UpgradeManger", "UpgradeManger\ThingsGateway.UpgradeManger\ThingsGateway.UpgradeManger.csproj", "{84362F1D-E788-4646-B555-5A3629B55EFC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Upgrade", "UpgradeManger\ThingsGateway.Upgrade\ThingsGateway.Upgrade.csproj", "{681F774F-7B0B-450A-917C-1385E1847CA6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Rcl", "Demo\ThingsGateway.Foundation.Demo.Rcl\ThingsGateway.Foundation.Demo.Rcl.csproj", "{637A662B-7B70-4CE8-8F5F-0A095B9D77EC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Photino", "Demo\ThingsGateway.Foundation.Demo.Photino\ThingsGateway.Foundation.Demo.Photino.csproj", "{C5519C51-0A0C-4317-A43D-FFBB6B344ACB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.SQLHisAlarm", "plugin\ThingsGateway.Plugin.SQLHisAlarm\ThingsGateway.Plugin.SQLHisAlarm.csproj", "{0947E6C0-6371-4483-B0ED-191FB5073151}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -135,102 +135,114 @@ Global
{9695B353-D773-40DD-B65E-7B10EB0C16EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9695B353-D773-40DD-B65E-7B10EB0C16EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9695B353-D773-40DD-B65E-7B10EB0C16EC}.Release|Any CPU.Build.0 = Release|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{799C49A4-8E23-475A-A82D-080854718BEE}.Release|Any CPU.Build.0 = Release|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Debug|Any CPU.Build.0 = Debug|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Release|Any CPU.ActiveCfg = Release|Any CPU
{616CA361-B667-42C8-B4DC-097C7CD39830}.Release|Any CPU.Build.0 = Release|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16C62A28-BACE-4391-91F8-C2D78D063A1E}.Release|Any CPU.Build.0 = Release|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FA03089-322F-44CB-8E4B-F2637388E944}.Release|Any CPU.Build.0 = Release|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14FF7150-6DB7-455B-AD00-6AB4DE37855B}.Release|Any CPU.Build.0 = Release|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1}.Release|Any CPU.Build.0 = Release|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC}.Release|Any CPU.Build.0 = Release|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51313113-7BB8-494E-9C24-6787BECE39BB}.Release|Any CPU.Build.0 = Release|Any CPU
{5D7BE567-2345-46C8-9F54-DDC1DA96D198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D7BE567-2345-46C8-9F54-DDC1DA96D198}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D7BE567-2345-46C8-9F54-DDC1DA96D198}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D7BE567-2345-46C8-9F54-DDC1DA96D198}.Release|Any CPU.Build.0 = Release|Any CPU
{5CF1B3EC-84E2-484A-8DFC-2ECD2EE18E2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CF1B3EC-84E2-484A-8DFC-2ECD2EE18E2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CF1B3EC-84E2-484A-8DFC-2ECD2EE18E2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CF1B3EC-84E2-484A-8DFC-2ECD2EE18E2F}.Release|Any CPU.Build.0 = Release|Any CPU
{CD0F211A-F65B-4026-9750-68AC3C70D012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD0F211A-F65B-4026-9750-68AC3C70D012}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD0F211A-F65B-4026-9750-68AC3C70D012}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD0F211A-F65B-4026-9750-68AC3C70D012}.Release|Any CPU.Build.0 = Release|Any CPU
{5CD79F91-7182-4A9D-9BEF-4DF410C782D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CD79F91-7182-4A9D-9BEF-4DF410C782D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CD79F91-7182-4A9D-9BEF-4DF410C782D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CD79F91-7182-4A9D-9BEF-4DF410C782D2}.Release|Any CPU.Build.0 = Release|Any CPU
{2057E5BE-FACA-4D44-A2BA-E1F864A8DAFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2057E5BE-FACA-4D44-A2BA-E1F864A8DAFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2057E5BE-FACA-4D44-A2BA-E1F864A8DAFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2057E5BE-FACA-4D44-A2BA-E1F864A8DAFF}.Release|Any CPU.Build.0 = Release|Any CPU
{A723D4D7-B796-4D97-BA68-95E5696C9559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A723D4D7-B796-4D97-BA68-95E5696C9559}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A723D4D7-B796-4D97-BA68-95E5696C9559}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A723D4D7-B796-4D97-BA68-95E5696C9559}.Release|Any CPU.Build.0 = Release|Any CPU
{D9944D52-81B4-4DBC-8C3B-2A334CCBD4F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9944D52-81B4-4DBC-8C3B-2A334CCBD4F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9944D52-81B4-4DBC-8C3B-2A334CCBD4F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9944D52-81B4-4DBC-8C3B-2A334CCBD4F6}.Release|Any CPU.Build.0 = Release|Any CPU
{C5C89B2F-D9C9-4A67-A9BE-4E5F0B42162F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5C89B2F-D9C9-4A67-A9BE-4E5F0B42162F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5C89B2F-D9C9-4A67-A9BE-4E5F0B42162F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5C89B2F-D9C9-4A67-A9BE-4E5F0B42162F}.Release|Any CPU.Build.0 = Release|Any CPU
{7562C85D-267D-4718-8857-422B625C5BD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7562C85D-267D-4718-8857-422B625C5BD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7562C85D-267D-4718-8857-422B625C5BD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7562C85D-267D-4718-8857-422B625C5BD0}.Release|Any CPU.Build.0 = Release|Any CPU
{A0E1EAC7-10DD-4520-973F-CC385BBFBD84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0E1EAC7-10DD-4520-973F-CC385BBFBD84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0E1EAC7-10DD-4520-973F-CC385BBFBD84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0E1EAC7-10DD-4520-973F-CC385BBFBD84}.Release|Any CPU.Build.0 = Release|Any CPU
{503529C4-842A-47F0-928B-C8DC5B0A367D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{503529C4-842A-47F0-928B-C8DC5B0A367D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{503529C4-842A-47F0-928B-C8DC5B0A367D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{503529C4-842A-47F0-928B-C8DC5B0A367D}.Release|Any CPU.Build.0 = Release|Any CPU
{8A9F6586-3320-4F03-B3DA-09BF39AA90A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A9F6586-3320-4F03-B3DA-09BF39AA90A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A9F6586-3320-4F03-B3DA-09BF39AA90A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A9F6586-3320-4F03-B3DA-09BF39AA90A0}.Release|Any CPU.Build.0 = Release|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84362F1D-E788-4646-B555-5A3629B55EFC}.Release|Any CPU.Build.0 = Release|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{681F774F-7B0B-450A-917C-1385E1847CA6}.Release|Any CPU.Build.0 = Release|Any CPU
{637A662B-7B70-4CE8-8F5F-0A095B9D77EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{637A662B-7B70-4CE8-8F5F-0A095B9D77EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{637A662B-7B70-4CE8-8F5F-0A095B9D77EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{637A662B-7B70-4CE8-8F5F-0A095B9D77EC}.Release|Any CPU.Build.0 = Release|Any CPU
{C5519C51-0A0C-4317-A43D-FFBB6B344ACB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5519C51-0A0C-4317-A43D-FFBB6B344ACB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5519C51-0A0C-4317-A43D-FFBB6B344ACB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5519C51-0A0C-4317-A43D-FFBB6B344ACB}.Release|Any CPU.Build.0 = Release|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Release|Any CPU.Build.0 = Release|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Release|Any CPU.Build.0 = Release|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Release|Any CPU.Build.0 = Release|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.Build.0 = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.Build.0 = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.Build.0 = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.Build.0 = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.Build.0 = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.Build.0 = Release|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Release|Any CPU.Build.0 = Release|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Release|Any CPU.Build.0 = Release|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Release|Any CPU.Build.0 = Release|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Release|Any CPU.Build.0 = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.Build.0 = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.Build.0 = Release|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Release|Any CPU.Build.0 = Release|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Release|Any CPU.Build.0 = Release|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Release|Any CPU.Build.0 = Release|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Release|Any CPU.Build.0 = Release|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Release|Any CPU.Build.0 = Release|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Release|Any CPU.Build.0 = Release|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Release|Any CPU.Build.0 = Release|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Release|Any CPU.Build.0 = Release|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Release|Any CPU.Build.0 = Release|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Release|Any CPU.Build.0 = Release|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Release|Any CPU.Build.0 = Release|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -242,33 +254,33 @@ Global
{566783A4-222B-46F5-AA12-0753997B3254} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{9695B353-D773-40DD-B65E-7B10EB0C16EC} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{799C49A4-8E23-475A-A82D-080854718BEE} = {BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15}
{616CA361-B667-42C8-B4DC-097C7CD39830} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{16C62A28-BACE-4391-91F8-C2D78D063A1E} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{8FA03089-322F-44CB-8E4B-F2637388E944} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{14FF7150-6DB7-455B-AD00-6AB4DE37855B} = {79E7042F-F9E3-4D87-BFA9-4B7DD9736735}
{2861AA39-AAAE-47ED-9ACC-4C165DDF3EF1} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{9FF2A8A6-48D0-4D8A-9EAD-1905174291CC} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{51313113-7BB8-494E-9C24-6787BECE39BB} = {BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15}
{79E7042F-F9E3-4D87-BFA9-4B7DD9736735} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{000C3C62-345E-451C-8CEE-6F2C6A087116} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{5D7BE567-2345-46C8-9F54-DDC1DA96D198} = {000C3C62-345E-451C-8CEE-6F2C6A087116}
{5CF1B3EC-84E2-484A-8DFC-2ECD2EE18E2F} = {000C3C62-345E-451C-8CEE-6F2C6A087116}
{CD0F211A-F65B-4026-9750-68AC3C70D012} = {000C3C62-345E-451C-8CEE-6F2C6A087116}
{5CD79F91-7182-4A9D-9BEF-4DF410C782D2} = {000C3C62-345E-451C-8CEE-6F2C6A087116}
{BB9C2A85-7A8A-4CF9-BF44-34DE9848EC15} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{2057E5BE-FACA-4D44-A2BA-E1F864A8DAFF} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{A723D4D7-B796-4D97-BA68-95E5696C9559} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{D9944D52-81B4-4DBC-8C3B-2A334CCBD4F6} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{C5C89B2F-D9C9-4A67-A9BE-4E5F0B42162F} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{7562C85D-267D-4718-8857-422B625C5BD0} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{A0E1EAC7-10DD-4520-973F-CC385BBFBD84} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{503529C4-842A-47F0-928B-C8DC5B0A367D} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{8A9F6586-3320-4F03-B3DA-09BF39AA90A0} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{84362F1D-E788-4646-B555-5A3629B55EFC} = {237C7BC5-7B07-40B5-AF42-CE2F8E0893C3}
{681F774F-7B0B-450A-917C-1385E1847CA6} = {237C7BC5-7B07-40B5-AF42-CE2F8E0893C3}
{637A662B-7B70-4CE8-8F5F-0A095B9D77EC} = {95008B83-0324-4A7C-80DE-2BBDDD1A9099}
{C5519C51-0A0C-4317-A43D-FFBB6B344ACB} = {95008B83-0324-4A7C-80DE-2BBDDD1A9099}
{2192217C-CF77-422E-9E63-DF4003ABF01A} = {358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB} = {358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325} = {358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}
{0A891D8E-23B3-46AD-8D30-565EE5004F93} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{5DA3D2BD-6768-4479-B52F-49E022EFF310} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{D6685A42-2712-417A-92C5-5EFF90B9FA94} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{69EA3D89-CB40-425A-8D70-5E4A33337BE5} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{90AB5C24-1AA3-4F58-9987-B307B92B5193} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{4C7A5A90-8292-413B-8848-419D9DCDE66F} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{D37EC028-EA46-4510-8261-6E780A906314} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{C5F662EB-991F-438D-BF61-EF87E7371C04} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{53C870AE-0249-4485-AE63-F8A16EA4BCB4} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{C102AB3A-377E-4753-AFA7-C13250D7DF00} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{0DE1D254-0BD2-4D98-B939-5440BE5EB552} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{A8E68E17-4EBF-4E4C-8272-B489329A68BF} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{AC4295F2-AB2F-4137-99EF-80FA5C83896B} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{0947E6C0-6371-4483-B0ED-191FB5073151} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C49B2D3E-6818-4E28-91B7-6E4E7E264BBB}

View File

@@ -1,17 +0,0 @@
<Project>
<PropertyGroup>
<Version>3.0.0.8</Version>
<LangVersion>latest</LangVersion>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Authors>Diego</Authors>
<Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright>
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
<SignAssembly>True</SignAssembly>
<DelaySign>False</DelaySign>
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
</Project>

View File

@@ -1,270 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Diagnostics;
using ThingsGateway.Foundation.Core;
namespace ThingsGateway.Upgrade
{
/// <summary>
/// StartCommand.txt 中配置启动主程序的指令,比如
/// 如果是直接启动ThingsGateway.Web.Entry.exe
/// 如果是WindowsServiceNet Start ThingsGateway
/// 如果是其他部署(linuxpm2等等),填写对应的启动命令
/// </summary>
internal class Program
{
static void Main(string[] args)
{
//Thread.Sleep(15000);
Thread.Sleep(5000);
var path = args[0];
if (Directory.Exists(path))
{
var data = DirectoryUtility.GetDirectories(path);
if (data.Length == 0)
{
ConsleError($"目录{path}下不存在文件");
}
else
{
var oldFolder = $"{AppContext.BaseDirectory}FileTemp/ThingsGatewayOld/{DateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}";
try
{
//复制原文件,错误时可恢复
ConsleInfo($"正在备份原文件");
CopyDirectory(AppContext.BaseDirectory, oldFolder, new[] { "logs", "FileTemp" }, new[] { "ThingsGateway.Upgrade" });
ConsleInfo($"备份原文件成功");
//停止主程序进程
string filePath = $"{AppContext.BaseDirectory}ThingsGateway.Web.Entry";
// 查找正在运行的进程
var process = Process.GetProcesses().Where(p =>
{
try
{
if (p.ProcessName == "ThingsGateway.Web.Entry")
{
return (Path.GetDirectoryName(p.MainModule.FileName) + Path.DirectorySeparatorChar).Equals(AppContext.BaseDirectory, StringComparison.OrdinalIgnoreCase);
//return true;
}
return false;
}
catch (Exception)
{
return false; // 进程访问被拒绝或没有主模块
}
})?.FirstOrDefault();
if (process != null)
{
var exit = process.WaitForExit(300000);
if (!exit)
{
ConsleError("无法终止主程序,更新过程停止");
Recovery(oldFolder);
Directory.Delete(oldFolder, true);
Directory.Delete(path, true);
return;
}
}
//程序已退出
//复制文件到主程序文件夹
ConsleInfo($"正在复制文件到主程序文件夹");
CopyDirectory(path, AppContext.BaseDirectory, new[] { "logs", "FileTemp" }, new[] { "ThingsGateway.Upgrade" });
ConsleInfo($"复制文件到主程序文件夹成功");
//尝试启动
var dataString = FileUtil.ReadFile($"{AppContext.BaseDirectory}StartCommand.txt");//读取文件
var startCommand = dataString;
StartCommand(startCommand);
Thread.Sleep(5000);
// 查找正在运行的进程
var process1 = Process.GetProcesses().Where(p =>
{
try
{
if (p.ProcessName == "ThingsGateway.Web.Entry")
{
return (Path.GetDirectoryName(p.MainModule.FileName) + Path.DirectorySeparatorChar).Equals(AppContext.BaseDirectory, StringComparison.OrdinalIgnoreCase);
//return true;
}
return false;
}
catch (Exception)
{
return false; // 进程访问被拒绝或没有主模块
}
})?.FirstOrDefault();
if (process1 != null)
{
//代表启动正常
ConsleInfo("更新成功");
Directory.Delete(oldFolder, true);
Directory.Delete(path, true);
return;
}
else
{
//恢复原文件
Recovery(oldFolder);
Directory.Delete(oldFolder, true);
Directory.Delete(path, true);
}
}
catch (Exception ex)
{
ConsleError(ex.ToString());
//恢复原文件
Recovery(oldFolder);
Directory.Delete(oldFolder, true);
Directory.Delete(path, true);
}
}
}
else
{
ConsleError($"不存在目录{path}");
//尝试启动
var dataString1 = FileUtil.ReadFile($"{AppContext.BaseDirectory}StartCommand.txt");//读取文件
var startCommand1 = dataString1;
StartCommand(startCommand1);
}
Thread.Sleep(10000);
Console.ReadLine();
}
private static void Recovery(string oldFolder)
{
ConsleInfo("更新失败,恢复原文件");
CopyDirectory(oldFolder, AppContext.BaseDirectory, new[] { "logs", "FileTemp" }, new[] { "ThingsGateway.Upgrade" });
//尝试启动
var dataString1 = FileUtil.ReadFile($"{AppContext.BaseDirectory}StartCommand.txt");//读取文件
var startCommand1 = dataString1;
StartCommand(startCommand1);
}
/// <summary>
/// 复制文件夹及文件
/// </summary>
/// <param name="sourceFolder">原文件路径</param>
/// <param name="destFolder">目标文件路径</param>
/// <param name="ignoreFolder">忽略文件夹</param>
/// <param name="ignoreFiles">忽略文件</param>
/// <returns></returns>
public static void CopyDirectory(string sourceFolder, string destFolder, string[] ignoreFolder, string[] ignoreFiles)
{
//如果目标路径不存在,则创建目标路径
if (!Directory.Exists(destFolder))
{
Directory.CreateDirectory(destFolder);
}
//得到原文件根目录下的所有文件
var files = Directory.GetFiles(sourceFolder);
foreach (var file in files)
{
if (ignoreFiles.Contains(Path.GetFileNameWithoutExtension(file)))
{ continue; }
var name = Path.GetFileName(file);
var dest = Path.Combine(destFolder, name);
File.Copy(file, dest, true);//复制文件
}
//得到原文件根目录下的所有文件夹
var folders = Directory.GetDirectories(sourceFolder);
foreach (var folder in folders)
{
if (ignoreFolder.Contains(Path.GetFileName(folder)))
{ continue; }
var name = Path.GetFileName(folder);
var dest = Path.Combine(destFolder, name);
CopyDirectory(folder, dest, ignoreFolder, ignoreFiles);//构建目标路径,递归复制文件
}
}
public static void ConsleInfo(string str)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(str);
}
public static void ConsleError(string str)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(str);
}
public static void StartCommand(string command)
{
// 创建进程对象
Process process = new Process();
// 设置进程启动信息
process.StartInfo.FileName = GetCommandInterpreter(); // 获取当前平台的命令解释器
process.StartInfo.Arguments = GetCommandArguments(command); // 获取命令行参数
process.StartInfo.UseShellExecute = true;
process.StartInfo.WorkingDirectory = AppContext.BaseDirectory;
// 启动进程
process.Start();
}
// 获取当前平台的命令解释器
static string GetCommandInterpreter()
{
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
{
return "cmd.exe";
}
else if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux))
{
return "/bin/bash";
}
else if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX))
{
return "/bin/bash";
}
throw new PlatformNotSupportedException("该平台不支持执行命令行。");
}
// 获取命令行参数
static string GetCommandArguments(string command)
{
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
{
return $"/c {command}";
}
else // Linux 或 macOS
{
return $"-c \"{command}\"";
}
}
}
}

View File

@@ -1,8 +0,0 @@
{
"profiles": {
"ThingsGateway.Upgrade": {
"commandName": "Project",
"commandLineArgs": "E:\\Tg\\ThingsGateway\\ThingsGateway-DEV\\framework\\Web\\ThingsGateway.Web.Entry\\bin\\Debug\\net6.0\\FileTemp\\tcp---127.0.0.1-7400-"
}
}
}

View File

@@ -1 +0,0 @@
Net Start ThingsGateway

View File

@@ -1,32 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command=" set dir=&quot;$(SolutionDir)Web\ThingsGateway.Web.Entry\bin\$(Configuration)\$(TargetFramework)\&quot;&#xD;&#xA; if not exist %25dir%25 md %25dir%25 &#xD;&#xA;copy &quot;$(TargetDir)*&quot; %25dir%25&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" />
</Target>
<ItemGroup>
<None Remove="StartCommand.txt" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Foundation\ThingsGateway.Foundation\Foundation\Utils\FileUtil.cs" Link="FileUtil.cs" />
<Compile Include="..\..\Foundation\ThingsGateway.Foundation\TouchSocket\Core\Extensions\DateTimeExtensions.cs" Link="DateTimeExtensions.cs" />
<Compile Include="..\..\Foundation\ThingsGateway.Foundation\TouchSocket\Core\IO\DirectoryUtility.cs" Link="DirectoryUtility.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="StartCommand.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -1,26 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@namespace ThingsGateway.UpgradeManger
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

View File

@@ -1,23 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Components;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.Rpc;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -1,11 +0,0 @@
[
{
"Href": "/index",
"Title": "首页"
},
{
"Title": "更新管理",
"Href": "/UpgradeManger"
}
]

View File

@@ -1,36 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/"
@layout BaseLayout
@inject NavigationManager NavigationManager
@namespace ThingsGateway.UpgradeManger
@using Microsoft.AspNetCore.Authorization;
@code {
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
/// <returns></returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
NavigationManager.NavigateTo("index");
}
await base.OnAfterRenderAsync(firstRender);
}
}

View File

@@ -1,57 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/index"
<div class="ml-2">
<div class="my-6 ">
<MLabel Class="text-h3" Color="primary">ThingsGateway</MLabel>
</div>
<div>
<strong class="text--lighten-1 text-h5 my-1">文档</strong>
</div>
<div class="my-2 ml-4">
<PCopyableText>
https://diego2098.gitee.io/thingsgateway-docs/
</PCopyableText>
</div>
<div>
<strong class="text--lighten-1 text-h5 my-1">协议</strong>
</div>
<div class="my-2 ml-4">
<PCopyableText Text="https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE.zh">
Apache-2.0开源协议
</PCopyableText>
</div>
<div>
<strong class="text--lighten-1 text-h5 my-1">赞助</strong>
</div>
<div class="my-2 ml-4">
<PCopyableText Text="https://diego2098.gitee.io/thingsgateway-docs/docs/donate">
ThingsGateway赞助途径
</PCopyableText>
</div>
<div>
<strong class="text--lighten-1 text-h5 my-1">社区</strong>
</div>
<div class="my-2 ml-4">
<PCopyableText Text="605534569">
QQ群605534569
</PCopyableText>
</div>
</div>

View File

@@ -1,262 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/UpgradeManger"
@namespace ThingsGateway.UpgradeManger
@using System.Linq.Expressions;
@using BlazorComponent;
@using Mapster;
@using Masa.Blazor.Presets;
@using System.IO;
@using Masa.Blazor;
@using Microsoft.AspNetCore.Authorization;
@inherits BaseComponentBase
@inject NavigationManager NavigationManager
@layout MainLayout
<MRow NoGutters>
<MCol Md=@(IsShowTreeView?2:0)>
<MSheet Show=IsShowTreeView Style=@($"height: calc(100vh - {BlazorResourceConst.DefaultHeight}px);border-radius:0px;")>
<MCardTitle Class="text-body-2">
当前已连接的客户端
</MCardTitle>
<MVirtualScroll Context="item" Class="my-2" Height=@($"calc(100vh - {BlazorResourceConst.DefaultHeight+100}px)") OverscanCount=2 ItemSize="60" Items="TcpDmtpSocketClients">
<ItemContent>
<MListItem OnClick=@(()=>ChoiceTcpDmtpSocketClient(item))>
<MListItemContent>
<MListItemTitle>
<div class="mt-1 d-flex align-center justify-space-between" title=@($"{item.GetIPPort()} - {item.Id}")>
<span>@($"{item.GetIPPort()} - {item.Id}")</span>
</div>
</MListItemTitle>
</MListItemContent>
</MListItem>
<MDivider></MDivider>
</ItemContent>
</MVirtualScroll>
</MSheet>
</MCol>
<MCol Md=@(IsShowTreeView?10:12)>
<MButton Class="mx-1" OnClick=@(() =>
{
IsShowTreeView=!IsShowTreeView;
}
) Color="primary" Icon>
<MIcon>mdi-menu</MIcon>
</MButton>
<MSheet Rounded="false" Class="pa-2" Style="width:100%">
<MRow Class="my-1" Justify="JustifyTypes.Start" Align="AlignTypes.Start" NoGutters>
<MCol Md="5">
@if (TcpDmtpSocketClient != null && GatewayInfo != null)
{
<MSheet Class="ml-4">
<MDescriptions Title="当前选择的网关" Bordered="true">
<ActionsContent>
<MButton Class="text-capitalize mr-1" Color="primary" OnClick="()=>ChoiceTcpDmtpSocketClient(TcpDmtpSocketClient)">
刷新
</MButton>
</ActionsContent>
<ChildContent>
<MDescriptionsItem Label=连接信息 Span=3>@($"{TcpDmtpSocketClient.GetIPPort()} - {TcpDmtpSocketClient.Id}")</MDescriptionsItem>
<MDescriptionsItem Label=连接状态 Span=3 Class=@(!TcpDmtpSocketClient.CanSend?"red--text":"green--text")>@TcpDmtpSocketClient.CanSend</MDescriptionsItem>
<MDescriptionsItem Label=更新时间 Span=3>@GatewayInfo.UpdateTime</MDescriptionsItem>
<MDescriptionsItem Label=软件版本 Span=3>@GatewayInfo.Version</MDescriptionsItem>
<MDescriptionsItem Label=采集设备数量 Span=3>@GatewayInfo.CollectDeviceCount</MDescriptionsItem>
<MDescriptionsItem Label=上传设备数量 Span=3>@GatewayInfo.UploadDeviceCount</MDescriptionsItem>
<MDescriptionsItem Label=变量数量 Span=3>@GatewayInfo.VariableCount</MDescriptionsItem>
</ChildContent>
</MDescriptions>
</MSheet>
<MTabs @bind-Value="tab" Class="ma-2">
<MTab Value=1> 配置更新 </MTab>
<MTab Value=2> 软件更新 </MTab>
</MTabs>
<MTabsItems Value="tab">
<MTabItem Value="1">
@if (tab == 1)
{
<MContainer>
<MRow Dense>
<MCol Cols="12" Md="12">
<div class="m-descriptions-header__title my-2">
导出配置信息
</div>
</MCol>
<MCol Cols="12" Md="12">
<MButton Color="primary" Loading=isUploadLoading Disabled=disabled Class="ma-2" OnClick=@(()=>ExcelUpload())>
导出网关配置信息
</MButton>
</MCol>
<MCol Cols="12" Md="12">
<MButton Color="primary" Loading=isUploadLoading Disabled=disabled Class="ma-2" OnClick=@(()=>DBUpload())>
导出网关配置数据库(SQLITE)
</MButton>
</MCol>
</MRow>
<MDivider></MDivider>
<MRow Dense>
<MCol Cols="12" Md="12">
<div class="m-descriptions-header__title my-2">
更新网关配置信息
</div>
</MCol>
<MCol Cols="12" Md="12">
<MFileInput Label="采集设备Excel" HideDetails=@("true") @bind-Value="_importCollectDevicesFile" Style="width:90%;" ShowSize></MFileInput>
</MCol>
<MCol Cols="12" Md="12">
<MSwitch Label=删除后更新 HideDetails=@("true") @bind-Value=@IsCollectDevicesFullUp />
</MCol>
<MCol Cols="12" Md="12">
<MFileInput Label="上传设备Excel" HideDetails=@("true") @bind-Value="_importUploadDevicesFile" Style="width:90%;" ShowSize></MFileInput>
</MCol>
<MCol Cols="12" Md="12">
<MSwitch Label=删除后更新 HideDetails=@("true") @bind-Value=@IsUploadDevicesFullUp />
</MCol>
<MCol Cols="12" Md="12">
<MFileInput Label="采集变量Excel" HideDetails=@("true") @bind-Value="_importDeviceVariablesFile" Style="width:90%;" ShowSize></MFileInput>
</MCol>
<MCol Cols="12" Md="12">
<MSwitch Label=删除后更新 HideDetails=@("true") @bind-Value=@IsDeviceVariablesFullUp />
</MCol>
<MCol Cols="12" Md="12">
<MFileInput Label="内存变量Excel" HideDetails=@("true") @bind-Value="_importMemoryVariablesFile" Style="width:90%;" ShowSize></MFileInput>
</MCol>
<MCol Cols="12" Md="12">
<MSwitch Label=删除后更新 HideDetails=@("true") @bind-Value=@IsMemoryVariablesFullUp />
</MCol>
<MCol Cols="12" Md="12">
<MButton Loading=isUploadLoading Disabled=disabled Class="ma-2" Color="primary"
OnClick=@(()=>ExcelDown())>
推送Excel文件
</MButton>
</MCol>
</MRow>
<MDivider></MDivider>
<MRow Dense>
<MCol Cols="12" Md="12">
<div class="m-descriptions-header__title my-2">
重启
</div>
</MCol>
<MCol Cols="12" Md="12">
<MButton Color="primary" Loading=isUploadLoading Disabled=disabled Class="ma-2" OnClick=@(()=>DBRestart())>
重启网关运行态
</MButton>
</MCol>
<MCol Cols="12" Md="12">
</MCol>
</MRow>
</MContainer>
}
</MTabItem>
<MTabItem Value="2">
@if (tab == 2)
{
<MCol Cols="12" Md="12">
<MButton Loading=isUploadLoading Disabled=disabled Class="ma-2" Color="primary"
OnClick=@(()=>FileDown())>
推送文件
</MButton>
</MCol>
<MCol Cols="12" Md="12">
<MButton Loading=isUploadLoading Disabled=disabled Class="ma-2" Color="primary"
OnClick=@(()=>FileRestart())>
重启更新
</MButton>
</MCol>
}
</MTabItem>
</MTabsItems>
}
</MCol>
<MCol Md="7">
<MCard Style="overflow-y:auto;width:100%" Elevation="0" Flat Class="ml-4">
<ConsoleTxt Messages="UpgradeManger.Messages" Height=600></ConsoleTxt>
</MCard>
</MCol>
</MRow>
</MSheet>
</MCol>
</MRow>
@code {
StringNumber tab;
bool IsShowTreeView = true;
}

View File

@@ -1,325 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using BlazorComponent;
using Masa.Blazor;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.JSInterop;
using ThingsGateway.Core;
using ThingsGateway.Foundation.Dmtp;
using ThingsGateway.Foundation.Dmtp.Rpc;
namespace ThingsGateway.UpgradeManger;
/// <summary>
/// UpgradeManger
/// </summary>
public partial class UpgradeMangerPage
{
readonly PeriodicTimer _periodicTimer = new(TimeSpan.FromSeconds(5));
IBrowserFile _importCollectDevicesFile;
IBrowserFile _importDeviceVariablesFile;
IBrowserFile _importMemoryVariablesFile;
IBrowserFile _importUploadDevicesFile;
private bool IsCollectDevicesFullUp;
private bool IsDeviceVariablesFullUp;
private bool IsMemoryVariablesFullUp;
private bool isUploadLoading;
private bool IsUploadDevicesFullUp;
private IJSObjectReference JSObjectReference;
[Inject]
IJSRuntime JSRuntime { get; set; }
List<TcpDmtpSocketClient> TcpDmtpSocketClients { get; set; }
[Inject]
UpgradeManger UpgradeManger { get; set; }
/// <inheritdoc/>
public override void Dispose()
{
_periodicTimer?.Dispose();
base.Dispose();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
protected override void OnInitialized()
{
_ = RunTimerAsync();
base.OnInitialized();
}
bool disabled => TcpDmtpSocketClient?.CanSend != true;
GatewayInfo GatewayInfo;
TcpDmtpSocketClient TcpDmtpSocketClient;
GatewayExcel GatewayExcel;
async Task ExcelUpload()
{
try
{
isUploadLoading = true;
GatewayExcel = await TcpDmtpSocketClient.GetDmtpRpcActor().InvokeTAsync<GatewayExcel>("GetGatewayExcelAsync", InvokeOption.WaitInvoke);
if (GatewayExcel.CollectDevice?.Length > 0)
{
try
{
GatewayExcel.CollectDevice.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: GatewayExcel.CollectDevice);
JSObjectReference ??= await JSRuntime.LoadModuleAsync("js/downloadFileFromStream");
await JSObjectReference.InvokeVoidAsync("downloadFileFromStream", $"{TcpDmtpSocketClient.GetIPPort()}采集设备表导出{DateTimeExtensions.CurrentDateTime.ToString("yyyy-MM-dd HH-mm-ss-fff zz")}.xlsx", streamRef);
}
catch (Exception ex)
{
UpgradeManger.LogMessage.LogWarning(ex, "采集设备表导出失败");
}
}
if (GatewayExcel.UploadDevice?.Length > 0)
{
try
{
GatewayExcel.UploadDevice.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: GatewayExcel.UploadDevice);
JSObjectReference ??= await JSRuntime.LoadModuleAsync("js/downloadFileFromStream");
await JSObjectReference.InvokeVoidAsync("downloadFileFromStream", $"{TcpDmtpSocketClient.GetIPPort()}上传设备表导出{DateTimeExtensions.CurrentDateTime.ToString("yyyy-MM-dd HH-mm-ss-fff zz")}.xlsx", streamRef);
}
catch (Exception ex)
{
UpgradeManger.LogMessage.LogWarning(ex, "上传设备表导出失败");
}
}
if (GatewayExcel.MemoryVariable?.Length > 0)
{
try
{
GatewayExcel.MemoryVariable.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: GatewayExcel.MemoryVariable);
JSObjectReference ??= await JSRuntime.LoadModuleAsync("js/downloadFileFromStream");
await JSObjectReference.InvokeVoidAsync("downloadFileFromStream", $"{TcpDmtpSocketClient.GetIPPort()}内存变量表导出{DateTimeExtensions.CurrentDateTime.ToString("yyyy-MM-dd HH-mm-ss-fff zz")}.xlsx", streamRef);
}
catch (Exception ex)
{
UpgradeManger.LogMessage.LogWarning(ex, "内存变量表导出失败");
}
}
if (GatewayExcel.DeviceVariable?.Length > 0)
{
try
{
GatewayExcel.DeviceVariable.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: GatewayExcel.DeviceVariable);
JSObjectReference ??= await JSRuntime.LoadModuleAsync("js/downloadFileFromStream");
await JSObjectReference.InvokeVoidAsync("downloadFileFromStream", $"{TcpDmtpSocketClient.GetIPPort()}采集变量表导出{DateTimeExtensions.CurrentDateTime.ToString("yyyy-MM-dd HH-mm-ss-fff zz")}.xlsx", streamRef);
}
catch (Exception ex)
{
UpgradeManger.LogMessage.LogWarning(ex, "采集变量表导出失败");
}
}
await PopupService.EnqueueSnackbarAsync("上传成功", AlertTypes.Success);
}
finally { isUploadLoading = false; }
}
async Task DBUpload()
{
try
{
isUploadLoading = true;
await UpgradeManger.DBUpload(TcpDmtpSocketClient);
}
finally { isUploadLoading = false; }
}
/// <summary>
/// 下发子网关配置
/// </summary>
/// <returns></returns>
private async Task ExcelDown()
{
try
{
isUploadLoading = true;
GatewayExcel gatewayExcel = new();
if (_importCollectDevicesFile != null)
{
using var fs1 = new MemoryStream();
using var stream1 = _importCollectDevicesFile.OpenReadStream(512000000);
await stream1.CopyToAsync(fs1);
fs1.Seek(0, SeekOrigin.Begin);
gatewayExcel.CollectDevice = fs1;
}
if (_importUploadDevicesFile != null)
{
using var fs2 = new MemoryStream();
using var stream2 = _importUploadDevicesFile.OpenReadStream(512000000);
await stream2.CopyToAsync(fs2);
fs2.Seek(0, SeekOrigin.Begin);
gatewayExcel.UploadDevice = fs2;
}
if (_importDeviceVariablesFile != null)
{
using var fs3 = new MemoryStream();
using var stream3 = _importDeviceVariablesFile.OpenReadStream(512000000);
await stream3.CopyToAsync(fs3);
fs3.Seek(0, SeekOrigin.Begin);
gatewayExcel.DeviceVariable = fs3;
}
if (_importMemoryVariablesFile != null)
{
using var fs4 = new MemoryStream();
using var stream4 = _importMemoryVariablesFile.OpenReadStream(512000000);
await stream4.CopyToAsync(fs4);
fs4.Seek(0, SeekOrigin.Begin);
gatewayExcel.MemoryVariable = fs4;
}
var result = await TcpDmtpSocketClient.GetDmtpRpcActor().InvokeTAsync<OperResult>("SetGatewayExcelAsync", new InvokeOption(30000), gatewayExcel);
if (result.IsSuccess)
{
await PopupService.EnqueueSnackbarAsync("更新成功", AlertTypes.Success);
}
else
{
await PopupService.EnqueueSnackbarAsync(result.Message, AlertTypes.Error);
}
}
catch (Exception ex)
{
await PopupService.EnqueueSnackbarAsync(ex.Message, AlertTypes.Error);
}
finally
{
isUploadLoading = false;
}
}
private async Task FileDown()
{
try
{
isUploadLoading = true;
var data = Program.app.MainWindow.ShowOpenFolder("选择更新文件夹", AppContext.BaseDirectory);
if (data.Length > 0)
{
await Task.Run(async () =>
{
await UpgradeManger.FileDown(TcpDmtpSocketClient, data.FirstOrDefault());
}
);
await PopupService.EnqueueSnackbarAsync("推送成功", AlertTypes.Success);
}
}
finally { isUploadLoading = false; }
}
private async Task FileRestart()
{
try
{
isUploadLoading = true;
var confirm = await PopupService.ConfirmAsync("重启", "网关重启会暂时断开连接会在约1分钟后重新连接 ?", AlertTypes.Warning);
if (confirm)
{
await TcpDmtpSocketClient.GetDmtpRpcActor().InvokeTAsync<OperResult>("FileRestart", InvokeOption.WaitSend);
}
}
finally
{
isUploadLoading = false;
}
}
/// <summary>
/// DBRestart
/// </summary>
/// <returns></returns>
private async Task DBRestart()
{
try
{
isUploadLoading = true;
await TcpDmtpSocketClient.GetDmtpRpcActor().InvokeTAsync<OperResult>("DBRestartAsync", new InvokeOption(30000));
await PopupService.EnqueueSnackbarAsync("重启成功", AlertTypes.Success);
}
finally
{
isUploadLoading = false;
}
}
async Task ChoiceTcpDmtpSocketClient(TcpDmtpSocketClient item)
{
TcpDmtpSocketClient = item;
GatewayInfo = await item.GetDmtpRpcActor().InvokeTAsync<GatewayInfo>("GetGatewayInfo", InvokeOption.WaitInvoke);
}
private async Task RefreshAsync()
{
await Task.CompletedTask;
TcpDmtpSocketClients = UpgradeManger.TcpDmtpService.GetClients().ToList();
}
private async Task RunTimerAsync()
{
await RefreshAsync();
while (await _periodicTimer.WaitForNextTickAsync())
{
try
{
await RefreshAsync();
await InvokeAsync(StateHasChanged);
}
catch
{
}
}
}
}

View File

@@ -1,49 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Microsoft.Extensions.DependencyInjection;
using Photino.Blazor;
namespace ThingsGateway.UpgradeManger;
internal class Program
{
internal static PhotinoBlazorApp app;
[STAThread]
private static void Main(string[] args)
{
System.IO.Directory.SetCurrentDirectory(AppContext.BaseDirectory);
var appBuilder = PhotinoBlazorAppBuilder.CreateDefault(args);
appBuilder.RootComponents.Add<App>("#app");
appBuilder.Services.ThingsGatewayComponentsConfigureServices();
appBuilder.Services.AddSingleton<UpgradeManger>();
app = appBuilder.Build();
app.MainWindow.SetTitle("ThingsGateway.UpgradeManger");
app.MainWindow.SetIconFile("wwwroot/favicon.ico");
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
};
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
var upgradeManger = app.Services.GetService<UpgradeManger>();
_ = upgradeManger.ExecuteAsync(cancellationTokenSource.Token);
app.Run();
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
Thread.Sleep(2000);
}
}

View File

@@ -1,42 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@namespace ThingsGateway.UpgradeManger
@inherits LayoutComponentBase
<CascadingValue Value="IsMobile" Name="IsMobile">
<MApp>
<MErrorHandler>
@Body
</MErrorHandler>
</MApp>
</CascadingValue>
@code {
public bool IsMobile { get; set; }
[Inject]
public MasaBlazor MasaBlazor { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
MasaBlazor.BreakpointChanged += BreakpointOnOnUpdate;
}
private void BreakpointOnOnUpdate(object sender, BreakpointChangedEventArgs e)
{
IsMobile = MasaBlazor.Breakpoint.Mobile;
if (e.MobileChanged)
{
StateHasChanged();
}
}
}

View File

@@ -1,91 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@namespace ThingsGateway.UpgradeManger
@using System.Text;
@inherits LayoutComponentBase
@layout BaseLayout
<PPageTabsProvider>
<CascadingValue Value="@this" IsFixed>
<CascadingValue Value="@Changed" Name="Changed">
<MNavigationDrawer Color="barcolor" @bind-Value="_drawerOpen" App Width="200">
<Logo CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_TITLE=@CONFIG_TITLE HeightInt=@(IsMobile?BlazorResourceConst.AppBarHeight:BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight) />
<AppList ClassString="overflow-y-auto" Routable
StyleString=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight}px);")
Items="Navs" />
</MNavigationDrawer>
<MAppBar Color="barcolor" Style=@($"{(!(IsMobile||_drawerOpen!=true)? "left:200px;":"")}") Elevation="1" App Flat ClippedRight Dense ElevateOnScroll
MaxHeight="@(BlazorResourceConst.AppBarHeight)" Height="@(BlazorResourceConst.AppBarHeight)">
<MButton Class="mr-0" Icon Small=IsMobile OnClick=@(() => _drawerOpen = !_drawerOpen)>
<MIcon>mdi-menu</MIcon>
</MButton>
</MAppBar>
<MMain Style=@($"{(!(IsMobile||_drawerOpen!=true)? "padding-left:200px;":"")}")>
<div class="full-width">
<PageTabs @ref="_pageTabs" PageTabItems="pageTabItems" />
</div>
<MDivider Center></MDivider>
<MCard Flat Class="overflow-y-auto overflow-x-hidden ma-auto pa-0 rounded-0" Style=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight+BlazorResourceConst.FooterHeight}px);")>
<PPageContainer PageTabs="@_pageTabs?.PPageTabs">
@Body
</PPageContainer>
</MCard>
<MSheet Class="d-flex justify-center align-center rounded-0" Style=@($"height: {BlazorResourceConst.FooterHeight}px;")>
<Foter CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_COPYRIGHT_URL=@CONFIG_COPYRIGHT_URL CONFIG_TITLE=@CONFIG_TITLE></Foter>
</MSheet>
</MMain>
</CascadingValue>
</CascadingValue>
</PPageTabsProvider>
@code {
bool Changed { get; set; }
private bool? _drawerOpen = true;
private PageTabs _pageTabs;
/// <summary>
/// IsMobile
/// </summary>
[CascadingParameter(Name = "IsMobile")]
public bool IsMobile { get; set; }
}
@code {
private string CONFIG_COPYRIGHT = "Diego";
private string CONFIG_COPYRIGHT_URL = "https://gitee.com/diego2098/ThingsGateway";
private string CONFIG_TITLE = "ThingsGateway";
}
@code {
private List<NavItem> Navs { get; set; } = new();
private List<PageTabItem> pageTabItems { get; set; } = new();
protected override void OnInitialized()
{
var dataString =FileUtil. ReadFile($"{AppContext.BaseDirectory}Navs.json");//读取文件
Navs=dataString.FromJsonString<List<NavItem>>();
pageTabItems = Navs.PasePageTabItem();
base.OnInitialized();
}
}

View File

@@ -1,35 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<ApplicationIcon>wwwroot\favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Photino.Blazor" Version="2.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Update="Navs.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="UpgradeMangerConfig.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -1,266 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Diagnostics;
using ThingsGateway.Core;
using ThingsGateway.Foundation.Dmtp;
using ThingsGateway.Foundation.Dmtp.FileTransfer;
using ThingsGateway.Foundation.Dmtp.Rpc;
namespace ThingsGateway.UpgradeManger;
/// <summary>
/// UpgradeManger
/// </summary>
public partial class UpgradeManger
{
/// <summary>
/// UpgradeMangerConfig
/// </summary>
public UpgradeMangerConfig Config;
/// <summary>
/// Messages
/// </summary>
public ConcurrentLinkedList<(Microsoft.Extensions.Logging.LogLevel level, string message)> Messages = new();
/// <summary>
/// TcpDmtpService
/// </summary>
public TcpDmtpService TcpDmtpService;
/// <summary>
/// LogMessage
/// </summary>
public LoggerGroup LogMessage;
/// <inheritdoc/>
public async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
var dataString = FileUtil.ReadFile($"{AppContext.BaseDirectory}UpgradeMangerConfig.json");//读取文件
Config = dataString.FromJsonString<UpgradeMangerConfig>();
}
catch (Exception ex)
{
LogMessage.LogError(ex, "程序初始化配置失败");
}
TcpDmtpService = CreateTcpDmtpService(Config);
while (!stoppingToken.IsCancellationRequested)
{
try
{
TcpDmtpService.Start();
await Task.Delay(10000, stoppingToken);
}
catch (TaskCanceledException)
{
}
catch (ObjectDisposedException)
{
}
catch (Exception ex)
{
LogMessage.LogError(ex, ToString());
}
}
TcpDmtpService.Dispose();
}
private TcpDmtpService CreateTcpDmtpService(UpgradeMangerConfig autoUpdateConfig)
{
var config = new TouchSocketConfig()
.SetListenIPHosts(autoUpdateConfig.UpdateServerUri)
.SetVerifyToken(autoUpdateConfig.VerifyToken)
.ConfigureContainer(a =>
{
a.AddLogger(LogMessage);
a.AddDmtpRouteService();//添加路由策略
})
.ConfigurePlugins(a =>
{
a.UseDmtpFileTransfer();//必须添加文件传输插件
a.UseDmtpHeartbeat()//使用Dmtp心跳
.SetTick(TimeSpan.FromSeconds(3))
.SetMaxFailCount(3);
a.UseDmtpRpc();
});
TcpDmtpService service = new TcpDmtpService();
service.Connecting = (client, e) =>
{
service.Logger.Info($"{client.GetIPPort()}Connecting");
return EasyTask.CompletedTask;
};//有客户端正在连接
service.Connected = (client, e) => { service.Logger.Info($"{client.GetIPPort()}Connected"); return EasyTask.CompletedTask; };//有客户端连接
service.Disconnected = (client, e) => { service.Logger.Info($"{client.GetIPPort()}Disconnected"); return EasyTask.CompletedTask; };//有客户端断开连接
service.Setup(config);
return service;
}
/// <summary>
/// 底层日志输出
/// </summary>
private void LogOut(ThingsGateway.Foundation.Core.LogLevel logLevel, object source, string message, Exception exception)
{
Messages.Add(((Microsoft.Extensions.Logging.LogLevel)logLevel,
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat()} - {message} {exception}"));
if (Messages.Count > 2500)
{
Messages.Clear();
}
}
/// <summary>
/// DBUpload
/// </summary>
/// <param name="tcpDmtpSocketClient"></param>
/// <returns></returns>
public async Task DBUpload(TcpDmtpSocketClient tcpDmtpSocketClient)
{
var folderPath = $"{AppContext.BaseDirectory}ThingsGatewayDB/";
// 检查文件夹是否存在
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
var metadata = new Metadata();//传递到客户端的元数据
metadata.Add(FilePluginUtil.DmtpType, DmtpTypeEnum.GatewayDB.ToString());
var fileOperator = new FileOperator//实例化本次传输的控制器,用于获取传输进度、速度、状态等。
{
SavePath = $"{folderPath}/{tcpDmtpSocketClient.IP}-{tcpDmtpSocketClient.Port}ThingsGateway.db",//服务器本地保存路径
ResourcePath = string.Empty,//请求客户端文件的资源路径
Metadata = metadata,//传递到客户端的元数据
Timeout = TimeSpan.FromSeconds(60),//传输超时时长
TryCount = 10,//当遇到失败时,尝试次数
FileSectionSize = 1024 * 512//分包大小,当网络较差时,应该适当减小该值
};
//此处的作用相当于Timer定时每秒输出当前的传输进度和速度。
var loopAction = LoopAction.CreateLoopAction(-1, 1000, (loop) =>
{
if (fileOperator.Result.ResultCode != ResultCode.Default)
{
loop.Dispose();
}
LogMessage.Info($"进度:{fileOperator.Progress},速度:{fileOperator.Speed() / 1024}kb/s");
});
//此方法会阻塞直到传输结束也可以使用PullFileAsync
var result = await tcpDmtpSocketClient.GetDmtpFileTransferActor().PullFileAsync(fileOperator);
loopAction.Run();
LogMessage.Info($" {result.ResultCode},具体消息:{result.Message}");
if (result.ResultCode != ResultCode.Success)
throw new Exception(result.Message);
OpenFile(folderPath);
}
/// <summary>
/// DBUpload
/// </summary>
/// <returns></returns>
public async Task FileDown(TcpDmtpSocketClient tcpDmtpSocketClient, string folderPath)
{
string[] files = Directory.GetFiles(folderPath, "", SearchOption.AllDirectories);
await files.ParallelForEachAsync(async (file, cancellationToken) =>
{
try
{
if (!Path.GetRelativePath(folderPath, file).Contains("FileTemp"))
{
var metadata = new Metadata();//传递到客户端的元数据
metadata.Add(FilePluginUtil.DmtpType, DmtpTypeEnum.File.ToString());
metadata.Add(FilePluginUtil.FileName, Path.GetRelativePath(folderPath, file));
var fileOperator = new FileOperator//实例化本次传输的控制器,用于获取传输进度、速度、状态等。
{
SavePath = string.Empty,//客户端本地保存路径
ResourcePath = file,//服务器文件的资源路径
Metadata = metadata,//传递到客户端的元数据
Timeout = TimeSpan.FromSeconds(60),//传输超时时长
TryCount = 10,//当遇到失败时,尝试次数
FileSectionSize = 1024 * 512//分包大小,当网络较差时,应该适当减小该值
};
//此处的作用相当于Timer定时每秒输出当前的传输进度和速度。
var loopAction = LoopAction.CreateLoopAction(-1, 1000, (loop) =>
{
if (fileOperator.Result.ResultCode != ResultCode.Default)
{
loop.Dispose();
}
LogMessage.Info($"进度:{fileOperator.Progress},速度:{fileOperator.Speed() / 1024}kb/s");
});
//此方法会阻塞直到传输结束也可以使用PullFileAsync
var result = await tcpDmtpSocketClient.GetDmtpFileTransferActor().PushFileAsync(fileOperator);
loopAction.Run();
LogMessage.Info($" {result.ResultCode},具体消息:{result.Message}");
if (result.ResultCode != ResultCode.Success)
throw new Exception(result.Message);
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex, "传输出错");
}
}, 10);
}
/// <summary>
/// 打开指定目录下的文件
/// </summary>
private static void OpenFile(string folderPath)
{
Process process = new Process();
if (OperatingSystem.IsWindows())
{
process.StartInfo.FileName = "explorer.exe";
process.StartInfo.Arguments = folderPath.Replace("/", "\\");
}
else if (OperatingSystem.IsMacOS())
{
process.StartInfo.FileName = "open";
process.StartInfo.Arguments = folderPath;
}
else if (OperatingSystem.IsLinux())
{
process.StartInfo.FileName = "xdg-open";
process.StartInfo.Arguments = folderPath;
}
else
{
throw new NotSupportedException("不支持的操作系统");
}
process.Start();
}
}

View File

@@ -1,4 +0,0 @@
{
"UpdateServerUri": "127.0.0.1:7400", //管理服务IP
"VerifyToken": "ThingsGateway" //验证Token
}

View File

@@ -1,104 +0,0 @@
{
"RECORDS": [
{
"Id": "22222222222222",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_SWAGGER_NAME",
"ConfigValue": "admin",
"Remark": "swagger账号",
"SortCode": "1",
"IsDelete": "false"
},
{
"Id": "22222222222223",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_SWAGGER_PASSWORD",
"ConfigValue": "123456",
"Remark": "swagger密码",
"SortCode": "2",
"IsDelete": "false"
},
{
"Id": "22222222222224",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_SWAGGERLOGIN_OPEN",
"ConfigValue": "false",
"Remark": "swagger开启登录",
"SortCode": "3",
"IsDelete": "false"
},
{
"Id": "22222222222226",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_TITLE",
"ConfigValue": "ThingsGateway",
"Remark": "标题",
"SortCode": "5",
"IsDelete": "false"
},
{
"Id": "22222222222228",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_COPYRIGHT",
"ConfigValue": "ThingsGateway ©2023 Diego",
"Remark": "系统版权",
"SortCode": "6",
"IsDelete": "false"
},
{
"Id": "22222222222229",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_COPYRIGHT_URL",
"ConfigValue": "https://gitee.com/diego2098/ThingsGateway",
"Remark": "系统版权链接地址",
"SortCode": "7",
"IsDelete": "false"
},
{
"Id": "22222222222231",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_PASSWORD",
"ConfigValue": "111111",
"Remark": "默认用户密码",
"SortCode": "8",
"IsDelete": "false"
},
{
"Id": "22222222222227",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_VERIFICAT_EXPIRES",
"ConfigValue": "14400",
"Remark": "Verificat过期时间(分)",
"SortCode": "9",
"IsDelete": "false"
},
{
"Id": "22222222222232",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_SINGLE_OPEN",
"ConfigValue": "false",
"Remark": "单用户登录开关",
"SortCode": "10",
"IsDelete": "false"
},
{
"Id": "22222222222230",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_CAPTCHA_OPEN",
"ConfigValue": "true",
"Remark": "登录验证码开关",
"SortCode": "11",
"IsDelete": "false"
},
{
"Id": "22222222222225",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_REMARK",
"ConfigValue": "边缘采集网关",
"Remark": "说明",
"SortCode": "12",
"IsDelete": "false"
}
]
}

View File

@@ -1,16 +0,0 @@
{
"RECORDS": [
{
"Id": "212725263001001",
"Code": "superAdmin",
"Name": "超级管理员",
"SortCode": "1"
},
{
"Id": "212725263001002",
"Code": "admin",
"Name": "业务管理员",
"SortCode": "2"
}
]
}

View File

@@ -1,34 +0,0 @@
{
"RECORDS": [
{
"Id": "212725263002001",
"Account": "superAdmin",
"LastLoginDevice": "PC",
"LastLoginIp": "0.0.0.1",
"LastLoginTime": "2023-03-03 21:18:43.7092169",
"LatestLoginDevice": "PC",
"LatestLoginIp": "0.0.0.1",
"LatestLoginTime": "2023-03-03 21:19:16.1043309",
"Password": "7DA385A25A98388E",
"SortCode": "1",
"UserEnable": "true",
"IsDelete": "false",
"UpdateTime": "2023-03-03 21:19:16.1202211"
},
{
"Id": "201725263002001",
"Account": "admin",
"LastLoginDevice": "PC",
"LastLoginIp": "0.0.0.1",
"LastLoginTime": "2023-03-03 18:20:49.1875384",
"LatestLoginDevice": "PC",
"LatestLoginIp": "0.0.0.1",
"LatestLoginTime": "2023-03-03 18:23:08.6424099",
"Password": "7DA385A25A98388E",
"SortCode": "2",
"UserEnable": "true",
"IsDelete": "false",
"UpdateTime": "2023-03-03 18:23:08.6727296"
}
]
}

View File

@@ -1,204 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/admin/role"
@using System.Linq.Expressions;
@using BlazorComponent;
@using Masa.Blazor.Presets;
@using Microsoft.AspNetCore.Authorization;
@using ThingsGateway.Admin.Application;
@namespace ThingsGateway.Admin.Blazor
@attribute [Authorize]
@inject UserResoures UserResoures
@inherits BaseComponentBase
@layout MainLayout
<AppDataTable @ref="_datatable" TItem="SysRole" SearchItem="RolePageInput" AddItem="RoleAddInput" EditItem="RoleEditInput" DescFunc=@(memberInfo=>memberInfo.GetCustomAttribute<SqlSugar.SugarColumn>(true)?.ColumnDescription)
SearchModel="@search" IsShowSearchKey
QueryCallAsync="QueryCallAsync" AddCallAsync="AddCallAsync"
EditCallAsync="EditCallAsync" DeleteCallAsync="DeleteCallAsync"
IsShowQueryButton
IsShowAddButton=@UserResoures.IsHasButtonWithRole("sysroleadd")
IsShowDeleteButton=@UserResoures.IsHasButtonWithRole("sysroledelete")
IsShowEditButton=@UserResoures.IsHasButtonWithRole("sysroleedit")>
<AddTemplate>
@GetRenderFragment(context)
</AddTemplate>
<EditTemplate>
@GetRenderFragment(context)
</EditTemplate>
<ItemColOperTemplate>
<MList Dense>
@if (@UserResoures.IsHasButtonWithRole("sysroleperresuorce"))
{
<MListItem OnClick="async()=>
{
ChoiceRoleId=context.Item.Id;
await ResuorceInitAsync();
IsShowResuorces=true;
}">
<MListItemTitle Class="ml-2">资源权限</MListItemTitle>
</MListItem>
}
@if (@UserResoures.IsHasButtonWithRole("sysroleperuser"))
{
<MListItem OnClick="async()=>
{
ChoiceRoleId=context.Item.Id;
await UserInitAsync();
IsShowUsers=true;
}">
<MListItemTitle Class="ml-2">授权用户</MListItemTitle>
</MListItem>
}
</MList>
</ItemColOperTemplate>
</AppDataTable>
<PDrawer @bind-Value="IsShowResuorces" OnCancel="() => IsShowResuorces = false"
Title=资源授权
Width=@(IsMobile?"100%":"600")
MaxWidth="600" OnSave="OnRoleHasResuorcesSaveAsync">
@if (IsShowResuorces)
{
<MSheet Outlined Class="ma-0 pa-2">
<MRow Align="AlignTypes.Center">
<MCol> <MLabel Class="ml-4 font-weight-black">菜单</MLabel> </MCol>
<MDivider Vertical />
<MCol> <MLabel Class="ml-4 font-weight-black">按钮</MLabel> </MCol>
</MRow>
</MSheet>
@foreach (var menu in ResTreeSelectors)
{
<MSheet Outlined Class="ma-0 pa-4">
<MRow Align="AlignTypes.Center">
<MCol>
<MListItem IsActive=@(RoleHasResuorces.Any(it=>it.MenuId==menu.Id))>
<ItemContent>
<MListItemContent>
<MListItemTitle>@menu.Title</MListItemTitle>
</MListItemContent>
<MListItemAction>
<MCheckbox TValue=bool Value="@context.Active" ValueChanged=@(enable=>
{
if(!enable)
RoleHasResuorces.RemoveWhere(it=>it.MenuId==menu.Id);
else if(!RoleHasResuorces.Any(it=>it.MenuId==menu.Id))
RoleHasResuorces.Add(new() {MenuId=menu.Id});
}
)></MCheckbox>
</MListItemAction>
</ItemContent>
</MListItem>
</MCol>
<MDivider Vertical />
<MCol>
@GetButtonCore(menu)
</MCol>
</MRow>
</MSheet>
}
}
</PDrawer>
<PDrawer @bind-Value="IsShowUsers" OnCancel="() => IsShowUsers = false"
Title=授权用户
Width=@(IsMobile?"100%":"500")
MaxWidth="500" OnSave="OnUsersSaveAsync">
<MCard Flat Class="ma-0 pa-4">
<MCardTitle Class="py-2">
<MTextField Dense Style="max-width:200px;" HideDetails=@("auto") Class="my-1 mx-2 ml-6" @bind-Value="SearchKey"
Outlined Label=@typeof(SysUser).GetDescription(nameof(SysUser.Account)) />
</MCardTitle>
<MTreeview Class="my-1" Dense OpenAll TItem="UserSelectorOutput" TKey="UserSelectorOutput" Selectable @bind-Value="UsersChoice"
Items="AllUsers" ItemText="r=>r.Account" ItemChildren="r=>null"
ItemKey=@(r=>r)>
<LabelContent>
<span title=@context.Item.Account>
@context.Item.Account
</span>
</LabelContent>
</MTreeview>
</MCard>
</PDrawer>
@code {
RenderFragment GetButtonCore(RoleGrantResourceMenu menu)
{
RenderFragment ViewSubMenu = null;
foreach (var button in menu.Button ?? new())
{
ViewSubMenu +=
@<MListItem Class="ml-6" IsActive=@(RoleHasResuorces.FirstOrDefault(it=>it.MenuId==menu.Id)?.ButtonInfo?.Contains(button.Id)==true)>
<ItemContent>
<MListItemContent>
<MListItemTitle>@button.Title</MListItemTitle>
</MListItemContent>
<MListItemAction>
<MCheckbox TValue=bool Value="@context.Active" ValueChanged=@(a=>
{
if(!a)
{
RoleHasResuorces.FirstOrDefault(it=>it.MenuId==menu.Id)?.ButtonInfo?.RemoveWhere(it=>it==button.Id);
}
else
{
if( !(RoleHasResuorces.FirstOrDefault(it=>it.MenuId==menu.Id)?.ButtonInfo?.Any(it=>it==button.Id)==true))
{
if(!RoleHasResuorces.Any(it=>it.MenuId==menu.Id))
{
RoleHasResuorces.Add(new() {MenuId=menu.Id});
}
RoleHasResuorces.FirstOrDefault(it=>it.MenuId==menu.Id).ButtonInfo.Add(button.Id);
}
}
})></MCheckbox>
</MListItemAction>
</ItemContent>
</MListItem>
;
}
return ViewSubMenu;
}
RenderFragment GetRenderFragment(RoleAddInput context)
{
RenderFragment renderFragment =
@<div>
<MSubheader Class="mt-4 font-weight-black"> @(context.Description(x => x.Name)) </MSubheader>
<MTextField Dense Outlined HideDetails="@("auto")" @bind-Value=@context.Name />
<MSubheader Class="mt-4 mb-5 font-weight-black">@(context.Description(x => x.SortCode)) </MSubheader>
<MSlider @bind-Value=@context.SortCode Class="mb-5" TValue=int ThumbLabel="@("always")" Dense />
</div>
;
return renderFragment;
}
}

View File

@@ -1,112 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Masa.Blazor;
using Masa.Blazor.Presets;
using SqlSugar;
namespace ThingsGateway.Admin.Blazor;
/// <summary>
/// 角色页面
/// </summary>
public partial class Role
{
private readonly RolePageInput search = new();
private IAppDataTable _datatable;
private List<UserSelectorOutput> AllUsers;
long ChoiceRoleId;
bool IsShowResuorces;
bool IsShowUsers;
List<RoleGrantResourceMenu> ResTreeSelectors = new();
List<RelationRoleResuorce> RoleHasResuorces = new();
private List<UserSelectorOutput> UsersChoice;
[CascadingParameter]
MainLayout MainLayout { get; set; }
private string SearchKey { get; set; }
private Task AddCallAsync(RoleAddInput input)
{
return App.GetService<RoleService>().AddAsync(input);
}
private async Task DeleteCallAsync(IEnumerable<SysRole> sysRoles)
{
await App.GetService<RoleService>().DeleteAsync(sysRoles.Select(a => a.Id).ToArray());
await MainLayout.StateHasChangedAsync();
}
private async Task EditCallAsync(RoleEditInput input)
{
await App.GetService<RoleService>().EditAsync(input);
await MainLayout.StateHasChangedAsync();
}
private async Task OnRoleHasResuorcesSaveAsync(ModalActionEventArgs args)
{
try
{
GrantResourceInput userGrantRoleInput = new();
var data = new List<SysResource>();
userGrantRoleInput.Id = ChoiceRoleId;
userGrantRoleInput.GrantInfoList = RoleHasResuorces;
await App.GetService<RoleService>().GrantResourceAsync(userGrantRoleInput);
IsShowResuorces = false;
}
catch (Exception ex)
{
args.Cancel();
await PopupService.EnqueueSnackbarAsync(ex, false);
}
await MainLayout.StateHasChangedAsync();
}
private async Task OnUsersSaveAsync(ModalActionEventArgs args)
{
try
{
GrantUserInput userGrantRoleInput = new();
userGrantRoleInput.Id = ChoiceRoleId;
userGrantRoleInput.GrantInfoList = UsersChoice.Select(it => it.Id).ToList();
await App.GetService<RoleService>().GrantUserAsync(userGrantRoleInput);
IsShowUsers = false;
}
catch (Exception ex)
{
args.Cancel();
await PopupService.EnqueueSnackbarAsync(ex, false);
}
await MainLayout.StateHasChangedAsync();
}
private Task<ISqlSugarPagedList<SysRole>> QueryCallAsync(RolePageInput input)
{
return App.GetService<RoleService>().PageAsync(input);
}
private async Task ResuorceInitAsync()
{
ResTreeSelectors = (await App.GetService<ResourceService>().GetRoleGrantResourceMenusAsync());
RoleHasResuorces = (await App.GetService<RoleService>().OwnResourceAsync(ChoiceRoleId))?.GrantInfoList;
}
private async Task<List<UserSelectorOutput>> UserInitAsync()
{
AllUsers = await App.GetService<SysUserService>().UserSelectorAsync(SearchKey);
var data = await App.GetService<RoleService>().OwnUserAsync(ChoiceRoleId);
UsersChoice = AllUsers.Where(a => data.Contains(a.Id)).ToList();
return AllUsers;
}
}

View File

@@ -1,100 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Masa.Blazor;
using Masa.Blazor.Presets;
namespace ThingsGateway.Admin.Blazor;
/// <summary>
/// 用户界面
/// </summary>
public partial class User
{
private readonly UserPageInput search = new();
private IAppDataTable _datatable;
private List<SysRole> AllRoles;
long ChoiceUserId;
bool IsShowRoles;
List<SysRole> RolesChoice = new();
string SearchName;
[CascadingParameter]
MainLayout MainLayout { get; set; }
private Task AddCallAsync(UserAddInput input)
{
return App.GetService<SysUserService>().AddAsync(input);
}
private async Task DeleteCallAsync(IEnumerable<SysUser> users)
{
await App.GetService<SysUserService>().DeleteAsync(users.Select(a => a.Id).ToArray());
await MainLayout.StateHasChangedAsync();
}
private async Task EditCallAsync(UserEditInput users)
{
await App.GetService<SysUserService>().EditAsync(users);
await MainLayout.StateHasChangedAsync();
}
private async Task OnRolesSaveAsync(ModalActionEventArgs args)
{
try
{
UserGrantRoleInput userGrantRoleInput = new();
userGrantRoleInput.Id = ChoiceUserId;
userGrantRoleInput.RoleIdList = RolesChoice.Select(it => it.Id).ToList();
await App.GetService<SysUserService>().GrantRoleAsync(userGrantRoleInput);
IsShowRoles = false;
}
catch (Exception ex)
{
args.Cancel();
await PopupService.EnqueueSnackbarAsync(ex, false);
}
await MainLayout.StateHasChangedAsync();
}
private Task<ISqlSugarPagedList<SysUser>> QueryCallAsync(UserPageInput input)
{
return App.GetService<SysUserService>().PageAsync(input);
}
private async Task ResetPasswordAsync(SysUser sysUser)
{
await App.GetService<SysUserService>().ResetPasswordAsync(sysUser.Id);
await PopupService.EnqueueSnackbarAsync(new("成功", AlertTypes.Success));
await MainLayout.StateHasChangedAsync();
}
private async Task RoleInitAsync()
{
AllRoles = await App.GetService<RoleService>().RoleSelectorAsync();
var data = await App.GetService<RoleService>().GetRoleIdListByUserIdAsync(ChoiceUserId);
RolesChoice = AllRoles.Where(a => data.Contains(a.Id)).ToList();
}
private async Task UserStatusChangeAsync(SysUser context, bool enable)
{
try
{
if (enable)
await App.GetService<SysUserService>().EnableUserAsync(context.Id);
else
await App.GetService<SysUserService>().DisableUserAsync(context.Id);
}
finally
{
await _datatable?.QueryClickAsync();
await MainLayout.StateHasChangedAsync();
}
}
}

View File

@@ -1,213 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/login"
@layout BaseLayout
@inherits BaseComponentBase
@namespace ThingsGateway.Admin.Blazor
@using BlazorComponent;
@using Furion.DataEncryption;
@using Masa.Blazor.Presets;
@using ThingsGateway.Admin.Application;
<Ajax></Ajax>
@if (IsMobile)
{
<MCard @onkeydown=Enter Height=@("100%")>
@GetLoginCore()
</MCard>
}
else
{
<MRow NoGutters Style="height:100%">
<MCol Md=7 Sm=12>
<MSheet Elevation=1 Style="width:100%; height:100%;" Class="d-flex align-start flex-column mb-6">
<div class="d-flex align-center ml-12 mt-12">
<MAvatar Size="40" Color="teal">
<span class="white--text text-h6">@CONFIG_TITLE?.GetNameLen2()</span>
</MAvatar>
<h1>@CONFIG_TITLE</h1>
</div>
<div class="d-flex align-center ml-12 mt-12 mb-auto">
<h3>@CONFIG_REMARK</h3>
</div>
<div class="d-flex align-center pa-2" style="width:100%;height:100%;">
<MImage Src=@(BlazorResourceConst.ResourceUrl+"images/login-left.svg")></MImage>
</div>
</MSheet>
</MCol>
<MCol Md=5 Sm=12 Align="AlignTypes.Center">
<MRow Md=6 Sm=12 Justify="JustifyTypes.Center" Align="AlignTypes.Center">
<MCard Class="px-16 py-12" @onkeydown=Enter>
@GetLoginCore()
</MCard>
</MRow>
</MCol>
</MRow>
}
@code {
RenderFragment GetLoginCore()
{
RenderFragment ViewSubMenu =
@<div class="mt-2 px-2 py-1 mx-auto text-center my-auto">
<MAvatar Size=80>
<MImage Src=@UserLogoUrl>
</MImage>
</MAvatar>
<h5 class="mt-2 mb-12">@Welcome 👋</h5>
<MTextField TValue="string"
Label=账号
Outlined
HideDetails="@("auto")"
@bind-Value=@loginModel.Account>
</MTextField>
<MTextField TValue="string"
Class="mt-5"
Label="密码"
Type="@(_showPassword ? "text" : "password")"
AppendIcon="@(_showPassword ? "mdi-eye" : "mdi-eye-off")"
OnAppendClick="()=>_showPassword = !_showPassword"
Outlined
HideDetails="@("auto")"
@bind-Value=@Password>
</MTextField>
@if (_showCaptcha)
{
<PImageCaptcha @ref=captcha @bind-Value="CaptchaValue"
TextFieldClass="mt-5 mx-auto"
Label=验证码 Outlined Dense
OnRefresh="RefreshCode"
ErrorMessage=验证码错误>
</PImageCaptcha>
}
<MButton Class="mt-8 rounded-4" OnClick=LoginAsync Height=45 Width=@("100%") Color="primary">登录</MButton>
</div>
;
return ViewSubMenu;
}
}
@code {
private string CaptchaValue;
bool _showPassword;
bool _showCaptcha;
private readonly LoginInput loginModel = new();
[Inject]
AjaxService AjaxService { get; set; }
string UserLogoUrl { get; set; } = BlazorResourceConst.ResourceUrl + "images/defaultUser.svg";
string Welcome { get; set; }
private ValidCodeOutput CaptchaInfo { get; set; }
private string Password { get; set; }
private string CONFIG_REMARK { get; set; }
private string CONFIG_TITLE { get; set; }
private async Task Enter(KeyboardEventArgs e)
{
if (e.Code == "Enter" || e.Code == "NumpadEnter")
{
await LoginAsync();
}
}
private PImageCaptcha captcha;
private async Task LoginAsync()
{
loginModel.ValidCodeReqNo = CaptchaInfo.ValidCodeReqNo;
loginModel.ValidCode = CaptchaValue;
loginModel.Password = DESCEncryption.Encrypt(Password, DESCKeyConst.DESCKey);
if (IsMobile)
{
loginModel.Device = AuthDeviceTypeEnum.APP;
}
else
{
loginModel.Device = AuthDeviceTypeEnum.PC;
}
var ajaxOption = new AjaxOption { Url = "/auth/b/login", Data = loginModel, };
var str = await AjaxService.GetMessageAsync(ajaxOption);
if (str != null)
{
var ret = str.FromJsonString<UnifyResult<LoginOutput>>();
if (ret.Code != 200)
{
if (captcha != null)
{
await captcha.RefreshCode();
}
await PopupService.EnqueueSnackbarAsync(new("登录错误" + ": " + ret.Msg.ToString(), AlertTypes.Error));
}
else
{
await PopupService.EnqueueSnackbarAsync(new("登录成功", AlertTypes.Success));
await Task.Delay(500);
var userId = await App.GetService<SysUserService>().GetIdByAccountAsync(loginModel.Account);
var data = await App.GetService<UserCenterService>().GetLoginDefaultRazorAsync(userId);
var sameLevelMenus = await App.GetService<ResourceService>().GetaMenuAndSpaListAsync();
if (NavigationManager.ToAbsoluteUri(NavigationManager.Uri).AbsolutePath == "/Login" || NavigationManager.ToAbsoluteUri(NavigationManager.Uri).AbsolutePath == "/")
await AjaxService.GotoAsync(sameLevelMenus.FirstOrDefault(a => a.Id == data)?.Component ?? "index");
else
await AjaxService.GotoAsync(NavigationManager.Uri);
}
}
else
{
if (captcha != null)
{
await captcha.RefreshCode();
}
await PopupService.EnqueueSnackbarAsync(new("登录错误", AlertTypes.Error));
}
}
[Inject]
private NavigationManager NavigationManager { get; set; }
/// <inheritdoc/>
protected override async Task OnParametersSetAsync()
{
#if DEBUG
loginModel.Account = "superAdmin";
Password = "111111";
#endif
GetCaptchaInfo();
CONFIG_TITLE = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_TITLE))?.ConfigValue;
CONFIG_REMARK = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_REMARK))?.ConfigValue;
_showCaptcha = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_CAPTCHA_OPEN))?.ConfigValue?.ToBoolean() == true;
Welcome = "欢迎使用" + CONFIG_TITLE + "!";
await base.OnParametersSetAsync();
}
private void GetCaptchaInfo()
{
CaptchaInfo = App.GetService<AuthService>().GetCaptchaInfo();
}
private Task<string> RefreshCode()
{
CaptchaInfo = App.GetService<AuthService>().GetCaptchaInfo();
return Task.FromResult(CaptchaInfo.CodeValue);
}
}

View File

@@ -1,123 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@namespace ThingsGateway.Admin.Blazor
@using Masa.Blazor.Presets
@using ThingsGateway.Admin.Application;
@inherits LayoutComponentBase
@layout BaseLayout
@if (UserManager.UserId > 0)
{
<SysSignalR></SysSignalR>
}
<PPageTabsProvider>
<CascadingValue Value="@this" IsFixed>
<CascadingValue Value="@Changed" Name="Changed">
<MNavigationDrawer Color="barcolor" @bind-Value="_drawerOpen" App Width="200">
@if (IsMobile)
{
<MSystemBar Color="barcolor" Height="@(BlazorResourceConst.PageTabsHeight)">
<MButton Icon OnClick=@(()=> _drawerOpen = !_drawerOpen)>
<MIcon>
mdi-close-thick
</MIcon>
</MButton>
<MSpacer />
<AppbarButtons />
</MSystemBar>
}
<Logo CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_TITLE=@CONFIG_TITLE HeightInt=@(IsMobile?BlazorResourceConst.AppBarHeight:BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight) />
<AppList ClassString="overflow-y-auto" Routable
StyleString=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight}px);")
Items="Navs" />
</MNavigationDrawer>
<MAppBar Color="barcolor" Style=@($"{(!(IsMobile||_drawerOpen!=true)? "left:200px;":"")}") Elevation="1" App Flat ClippedRight Dense ElevateOnScroll
MaxHeight="@(BlazorResourceConst.AppBarHeight)" Height="@(BlazorResourceConst.AppBarHeight)">
<MButton Class="mr-0" Icon Small=IsMobile OnClick=@(() => _drawerOpen = !_drawerOpen)>
<MIcon>mdi-menu</MIcon>
</MButton>
<AppBarItems BreadcrumbSysResources="BreadcrumbSysResources" SearchSysResources="SearchSysResources" CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_COPYRIGHT_URL=@CONFIG_COPYRIGHT_URL CONFIG_TITLE=@CONFIG_TITLE>
</AppBarItems>
</MAppBar>
<MMain Style=@($"{(!(IsMobile||_drawerOpen!=true)? "padding-left:200px;":"")}")>
<div class="full-width">
<PageTabs @ref="_pageTabs" PageTabItems="PageTabItems" />
</div>
<MDivider Center></MDivider>
<MCard Flat Class="overflow-y-auto overflow-x-hidden ma-auto pa-0 rounded-0" Style=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight+BlazorResourceConst.FooterHeight}px);")>
<PPageContainer PageTabs="@_pageTabs?.PPageTabs">
@Body
</PPageContainer>
</MCard>
<MSheet Class="d-flex justify-center align-center rounded-0" Style=@($"height: {BlazorResourceConst.FooterHeight}px; ")>
<Foter CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_COPYRIGHT_URL=@CONFIG_COPYRIGHT_URL CONFIG_TITLE=@CONFIG_TITLE></Foter>
</MSheet>
</MMain>
</CascadingValue>
</CascadingValue>
</PPageTabsProvider>
@code {
private bool? _drawerOpen = true;
private PageTabs _pageTabs;
private List<SysResource> BreadcrumbSysResources = new();
private string CONFIG_COPYRIGHT = "";
private string CONFIG_COPYRIGHT_URL = "";
private string CONFIG_TITLE = "";
private List<SysResource> SearchSysResources = new();
/// <summary>
/// IsMobile
/// </summary>
[CascadingParameter(Name = "IsMobile")]
public bool IsMobile { get; set; }
bool Changed { get; set; }
private List<NavItem> Navs { get; set; } = new();
private List<PageTabItem> PageTabItems { get; set; } = new();
[Inject]
private UserResoures UserResoures { get; set; }
/// <summary>
/// 页面刷新
/// </summary>
/// <returns></returns>
public async Task StateHasChangedAsync()
{
CONFIG_COPYRIGHT = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_COPYRIGHT)).ConfigValue;
CONFIG_TITLE = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_TITLE)).ConfigValue;
CONFIG_COPYRIGHT_URL = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_COPYRIGHT_URL)).ConfigValue;
await UserResoures.InitUserAsync();
await UserResoures.InitMenuAsync();
Navs = UserResoures.Menus.ParseNavItem();
PageTabItems = UserResoures.PageTabItems;
SearchSysResources = UserResoures.SameLevelMenus;
BreadcrumbSysResources = UserResoures.AllSameLevelMenuSpas;
Changed = !Changed;
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
protected override async Task OnInitializedAsync()
{
await StateHasChangedAsync();
await base.OnInitializedAsync();
}
}

View File

@@ -1,92 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion.DependencyInjection;
using SqlSugar;
using System.Collections;
using System.Data;
using System.Reflection;
namespace ThingsGateway.Admin.Core;
/// <summary>
/// 对象拓展
/// </summary>
[SuppressSniffer]
public static class ListExtensions
{
/// <summary>
/// SqlSugar是否忽略字段
/// </summary>
/// <param name="pi"></param>
/// <returns></returns>
private static bool IsIgnoreColumn(PropertyInfo pi)
{
return pi.GetCustomAttribute<SugarColumn>(false).IsIgnore == true;
}
/// <summary>
/// SqlSugar是否Json字段
/// </summary>
/// <param name="pi"></param>
/// <returns></returns>
private static bool IsJsonColumn(PropertyInfo pi)
{
return pi.GetCustomAttribute<SugarColumn>(false).IsJson == true;
}
/// <summary>
/// List转DataTable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static DataTable ToDataTable<T>(this List<T> list)
{
DataTable result = new();
if (list.Count > 0)
{
var propertys = list[0].GetType().GetPropertiesWithCache();
foreach (PropertyInfo pi in propertys)
{
Type colType = pi.PropertyType;
if (colType.IsGenericType && colType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
colType = colType.GetGenericArguments().First();
}
if (IsIgnoreColumn(pi))
continue;
if (IsJsonColumn(pi))//如果是json特性就是sting类型
colType = typeof(string);
if (colType.IsEnum)//如果是Enum需要转string才会保存Enum字符串
colType = typeof(string);
result.Columns.Add(pi.Name, colType);
}
for (int i = 0; i < list.Count; i++)
{
ArrayList tempList = new();
foreach (PropertyInfo pi in propertys)
{
if (IsIgnoreColumn(pi))
continue;
object obj = pi.GetValue(list[i], null);
if (IsJsonColumn(pi))//如果是json特性就是转化为json格式
obj = obj?.ToJsonString();//如果json字符串是空就传null
tempList.Add(obj);
}
object[] array = tempList.ToArray();
result.LoadDataRow(array, true);
}
}
return result;
}
}

Some files were not shown because too many files have changed in this diff Show More