Compare commits

..

805 Commits

Author SHA1 Message Date
Kimdiego2098
57dfc22ff7 更新版本号 2023-12-08 10:20:54 +08:00
Kimdiego2098
adc489b6ed 回退sqlsugar版本 2023-12-07 15:12:47 +08:00
Kimdiego2098
0623684315 nuget安装sqlite8.0.0 2023-12-07 14:34:14 +08:00
Kimdiego2098
68afccd859 修复OPC节点空间浏览窗口退出时报错的问题 2023-12-07 14:21:24 +08:00
Kimdiego2098
99eef8fb28 更新依赖包 2023-12-06 19:14:42 +08:00
Kimdiego2098
47e7685d39 串口代码整理 2023-12-06 18:54:33 +08:00
Kimdiego2098
b6ea596ade 整理代码 2023-12-06 18:35:52 +08:00
Kimdiego2098
44d60b469b 同步ts 2023-12-06 15:48:55 +08:00
Kimdiego2098
51087408df 同步ts 2023-12-06 15:16:54 +08:00
Kimdiego2098
96226d9e6e 同步ts 2023-12-06 14:56:12 +08:00
Kimdiego2098
28f0f62424 同步ts 2023-12-06 11:35:57 +08:00
Kimdiego2098
2e772a8cd4 同步touchsocket 2023-12-06 09:16:00 +08:00
Kimdiego2098
3fd192f0cf 变量表达式编辑 改为 多行文本框 2023-12-06 07:42:07 +08:00
Kimdiego2098
d16ae81961 更新demo;更新kafka 生成事件; 2023-12-04 20:28:36 +08:00
Kimdiego2098
211a8e093e 更新版本号 2023-12-01 21:23:51 +08:00
Kimdiego2098
84010a51d6 更改方法参数原;现由,分割 2023-12-01 21:22:27 +08:00
Kimdiego2098
e9700ea19b 更新依赖包 2023-12-01 19:55:17 +08:00
Kimdiego2098
e81ec68072 添加解决方案项 2023-11-30 17:44:26 +08:00
Kimdiego2098
6096e97708 modbusDtu更名 2023-11-30 10:47:37 +08:00
Kimdiego2098
6f302b66b4 添加ModbusRtu格式的DTU驱动 2023-11-30 10:16:26 +08:00
Kimdiego2098
b6e41890f7 同步TouchSocket 2023-11-30 10:16:20 +08:00
Kimdiego2098
be5332a048 添加离线后恢复间隔时间选项,添加重试次数选项 2023-11-29 20:47:23 +08:00
Kimdiego2098
4d72aeb0cd 修复种子数据带转义字符串时错误解析的问题 2023-11-29 19:04:56 +08:00
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
1820 changed files with 32346 additions and 40274 deletions

2
.gitignore vendored
View File

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

View File

@@ -1,103 +0,0 @@
[*.cs]
# CA1848: 使用 LoggerMessage 委托
dotnet_diagnostic.CA1848.severity = none
# CA2254: 模板应为静态表达式
dotnet_diagnostic.CA2254.severity = suggestion
[*.cs]
#### 命名样式 ####
# 命名规则
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# 符号规范
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# 命名样式
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
[*.vb]
#### 命名样式 ####
# 命名规则
dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion
dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface
dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
# 符号规范
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
dotnet_naming_symbols.类型.required_modifiers =
dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method
dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
dotnet_naming_symbols.非字段成员.required_modifiers =
# 命名样式
dotnet_naming_style.以_i_开始.required_prefix = I
dotnet_naming_style.以_i_开始.required_suffix =
dotnet_naming_style.以_i_开始.word_separator =
dotnet_naming_style.以_i_开始.capitalization = pascal_case
dotnet_naming_style.帕斯卡拼写法.required_prefix =
dotnet_naming_style.帕斯卡拼写法.required_suffix =
dotnet_naming_style.帕斯卡拼写法.word_separator =
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
dotnet_naming_style.帕斯卡拼写法.required_prefix =
dotnet_naming_style.帕斯卡拼写法.required_suffix =
dotnet_naming_style.帕斯卡拼写法.word_separator =
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case

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.20</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,152 +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 >
<!--<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" />
<PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="*" />
<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCDA" Version="*" />
<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCUA" Version="*" />
<PackageReference Include="ThingsGateway.Foundation.Adapter.Siemens" Version="*" />-->
<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" />
</ItemGroup>
<ItemGroup >
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</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.20</Version>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0;</TargetFrameworks>
<Version>4.0.0.9</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,417 +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)
{
ModbusServer01ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
ModbusServer02ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
ModbusServer03ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
ModbusServer04ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
}
}

View File

@@ -1,437 +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)
{
ModbusServer01ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
ModbusServer02ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
ModbusServer03ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
ModbusServer04ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
}
}

View File

@@ -1,4 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
</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,159 +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>
/// TCP读写设备
/// </summary>
public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
{
/// <summary>
/// <inheritdoc cref="ReadWriteDevicesSerialSessionBase"/>
/// </summary>
/// <param name="serialSession"></param>
public ReadWriteDevicesSerialSessionBase(SerialSession serialSession)
{
SerialSession = serialSession;
WaitingClientEx = SerialSession.CreateWaitingClient(new() { ThrowBreakException = true });
SerialSession.Received -= Received;
SerialSession.Connecting -= Connecting;
SerialSession.Connected -= Connected;
SerialSession.Disconnecting -= Disconnecting;
SerialSession.Disconnected -= Disconnected;
SerialSession.Connecting += Connecting;
SerialSession.Connected += Connected;
SerialSession.Disconnecting += Disconnecting;
SerialSession.Disconnected += Disconnected;
SerialSession.Received += Received;
Logger = SerialSession.Logger;
}
/// <summary>
/// 接收解析
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual Task Received(SerialSession client, ReceivedDataEventArgs e)
{
return EasyTask.CompletedTask;
}
/// <summary>
/// 串口管理对象
/// </summary>
public SerialSession SerialSession { get; }
/// <summary>
/// WaitingClientEx
/// </summary>
public virtual IWaitingClient<SerialSession> WaitingClientEx { get; }
/// <inheritdoc/>
public override void Connect(CancellationToken cancellationToken)
{
SerialSession.Connect();
}
/// <inheritdoc/>
public override Task ConnectAsync(CancellationToken cancellationToken)
{
return SerialSession.ConnectAsync();
}
/// <inheritdoc/>
public override void Disconnect()
{
if (CascadeDisposal)
SerialSession.Close();
}
/// <inheritdoc/>
public override void Dispose()
{
Disconnect();
SerialSession.Received -= Received;
SerialSession.Connecting -= Connecting;
SerialSession.Connected -= Connected;
SerialSession.Disconnecting -= Disconnecting;
SerialSession.Disconnected -= Disconnected;
if (CascadeDisposal)
SerialSession.SafeDispose();
}
/// <inheritdoc/>
public OperResult<byte[]> SendThenResponse(byte[] data, WaitingOptions waitingOptions = null, CancellationToken cancellationToken = default)
{
try
{
waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
ResponsedData result = SerialSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data);
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public async Task<OperResult<byte[]>> SendThenResponseAsync(byte[] data, WaitingOptions waitingOptions = null, CancellationToken cancellationToken = default)
{
try
{
waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
ResponsedData result = await SerialSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data);
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <inheritdoc/>
public override string ToString()
{
return SerialSession.SerialProperty.ToString();
}
/// <summary>
/// Connected
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual Task Connected(ISerialSession client, ConnectedEventArgs e)
{
Logger?.Debug(client.SerialProperty.ToString() + "连接成功");
SetDataAdapter();
return EasyTask.CompletedTask;
}
private Task Connecting(ISerialSession client, SerialConnectingEventArgs e)
{
Logger?.Debug(client.SerialProperty.ToString() + "正在连接");
return EasyTask.CompletedTask;
}
private Task Disconnected(ISerialSessionBase client, DisconnectEventArgs e)
{
Logger?.Debug(client.SerialProperty.ToString() + "断开连接-" + e.Message);
return EasyTask.CompletedTask;
}
private Task Disconnecting(ISerialSessionBase client, DisconnectEventArgs e)
{
Logger?.Debug(client.SerialProperty.ToString() + "正在主动断开连接-" + e.Message);
return EasyTask.CompletedTask;
}
}

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,498 +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 System.Data;
using System.Reflection;
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// IContainerExtensions
/// </summary>
public static class ContainerExtension
{
#region RegisterSingleton
/// <summary>
/// 注册单例
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTo"></typeparam>
/// <param name="container"></param>
/// <param name="instance"></param>
/// <returns></returns>
public static IContainer RegisterSingleton<TFrom, TTo>(this IContainer container, TTo instance)
where TFrom : class
where TTo : class, TFrom
{
RegisterSingleton(container, typeof(TFrom), instance);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="instance"></param>
/// <returns></returns>
public static IContainer RegisterSingleton(this IContainer container, object instance)
{
if (instance is null)
{
throw new ArgumentNullException(nameof(instance));
}
RegisterSingleton(container, instance.GetType(), instance);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static IContainer RegisterSingleton(this IContainer container, Type fromType)
{
if (fromType is null)
{
throw new ArgumentNullException(nameof(fromType));
}
RegisterSingleton(container, fromType, fromType);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTo"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <param name="instance"></param>
/// <returns></returns>
public static IContainer RegisterSingleton<TFrom, TTo>(this IContainer container, string key, TTo instance)
where TFrom : class
where TTo : class, TFrom
{
RegisterSingleton(container, typeof(TFrom), instance, key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="instance"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton(this IContainer container, Type fromType, object instance, string key = "")
{
container.Register(new DependencyDescriptor(fromType, instance), key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <param name="container"></param>
/// <param name="instance"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton<TFrom>(this IContainer container, object instance, string key = "")
{
container.Register(new DependencyDescriptor(typeof(TFrom), instance), key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="instance"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton(this IContainer container, object instance, string key = "")
{
container.Register(new DependencyDescriptor(instance.GetType(), instance), key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton<TFrom>(this IContainer container, string key = "")
{
container.Register(new DependencyDescriptor(typeof(TFrom), typeof(TFrom), Lifetime.Singleton), key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="toType"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton(this IContainer container, Type fromType, Type toType, string key = "")
{
container.Register(new DependencyDescriptor(fromType, toType, Lifetime.Singleton), key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="func"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton<TFrom>(this IContainer container, Func<IContainer, object> func, string key = "")
{
container.Register(new DependencyDescriptor(typeof(TFrom), Lifetime.Singleton)
{
ImplementationFactory = func
}, key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="func"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton(this IContainer container, Type fromType, Func<IContainer, object> func, string key = "")
{
container.Register(new DependencyDescriptor(fromType, Lifetime.Singleton)
{
ImplementationFactory = func
}, key);
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTO"></typeparam>
/// <param name="container"></param>
/// <returns></returns>
public static IContainer RegisterSingleton<TFrom, TTO>(this IContainer container)
where TFrom : class
where TTO : class, TFrom
{
RegisterSingleton(container, typeof(TFrom), typeof(TTO));
return container;
}
/// <summary>
/// 注册单例
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTO"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterSingleton<TFrom, TTO>(this IContainer container, string key)
where TFrom : class
where TTO : class, TFrom
{
RegisterSingleton(container, typeof(TFrom), typeof(TTO), key);
return container;
}
#endregion RegisterSingleton
#region Transient
/// <summary>
/// 注册临时映射
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTO"></typeparam>
/// <param name="container"></param>
/// <returns></returns>
public static IContainer RegisterTransient<TFrom, TTO>(this IContainer container)
where TFrom : class
where TTO : class, TFrom
{
RegisterTransient(container, typeof(TFrom), typeof(TTO));
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterTransient<TFrom>(this IContainer container, string key = "")
where TFrom : class
{
RegisterTransient(container, typeof(TFrom), typeof(TFrom), key);
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTO"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterTransient<TFrom, TTO>(this IContainer container, string key = "")
where TFrom : class
where TTO : class, TFrom
{
RegisterTransient(container, typeof(TFrom), typeof(TTO), key);
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterTransient(this IContainer container, Type fromType, string key = "")
{
RegisterTransient(container, fromType, fromType, key);
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="toType"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterTransient(this IContainer container, Type fromType, Type toType, string key = "")
{
container.Register(new DependencyDescriptor(fromType, toType, Lifetime.Transient), key);
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
/// <param name="container"></param>
/// <param name="func"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterTransient<TFrom>(this IContainer container, Func<IContainer, object> func, string key = "")
{
container.Register(new DependencyDescriptor(typeof(TFrom), Lifetime.Transient)
{
ImplementationFactory = func
}, key);
return container;
}
/// <summary>
/// 注册临时映射
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="func"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer RegisterTransient(this IContainer container, Type fromType, Func<IContainer, object> func, string key = "")
{
container.Register(new DependencyDescriptor(fromType, Lifetime.Transient)
{
ImplementationFactory = func
}, key);
return container;
}
#endregion Transient
#region Unregister
/// <summary>
/// 移除注册信息
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer Unregister(this IContainer container, Type fromType, string key = "")
{
container.Unregister(new DependencyDescriptor(fromType), key);
return container;
}
/// <summary>
/// 移除注册信息
/// </summary>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static IContainer Unregister<TFrom>(this IContainer container, string key = "")
{
container.Unregister(new DependencyDescriptor(typeof(TFrom)), key);
return container;
}
#endregion Unregister
#region Resolve
/// <summary>
/// 创建类型对应的实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T Resolve<T>(this IContainer container, string key = "")
{
return (T)container.Resolve(typeof(T), key);
}
/// <summary>
/// 创建<see cref="Lifetime.Transient"/>生命的未注册的根类型实例。一般适用于:目标类型没有注册,但是其成员类型已经注册的情况。
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static object ResolveWithoutRoot(this IContainer container, Type fromType)
{
object[] ops = null;
var ctor = fromType.GetConstructors().FirstOrDefault(x => x.IsDefined(typeof(DependencyInjectAttribute), true));
if (ctor is null)
{
//如果没有被特性标记,那就取构造函数参数最多的作为注入目标
if (fromType.GetConstructors().Length == 0)
{
throw new Exception($"没有找到类型{fromType.FullName}的公共构造函数。");
}
ctor = fromType.GetConstructors().OrderByDescending(x => x.GetParameters().Length).First();
}
DependencyTypeAttribute dependencyTypeAttribute = null;
if (fromType.IsDefined(typeof(DependencyTypeAttribute), true))
{
dependencyTypeAttribute = fromType.GetCustomAttribute<DependencyTypeAttribute>();
}
var parameters = ctor.GetParameters();
var ps = new object[parameters.Length];
if (dependencyTypeAttribute == null || dependencyTypeAttribute.Type.HasFlag(DependencyType.Constructor))
{
for (var i = 0; i < parameters.Length; i++)
{
if (ops != null && ops.Length - 1 >= i)
{
ps[i] = ops[i];
}
else
{
if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
{
ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default;
}
else
{
if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
{
var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
var type = attribute.Type ?? parameters[i].ParameterType;
ps[i] = container.Resolve(type, attribute.Key);
}
else
{
ps[i] = container.Resolve(parameters[i].ParameterType, null);
}
}
}
}
}
if (ps == null || ps.Length == 0)
{
return Activator.CreateInstance(fromType);
}
return Activator.CreateInstance(fromType, ps);
}
/// <summary>
/// 创建<see cref="Lifetime.Transient"/>生命的未注册的根类型实例。一般适用于:目标类型没有注册,但是其成员类型已经注册的情况。
/// </summary>
/// <param name="container"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static T ResolveWithoutRoot<T>(this IContainer container)
{
return (T)ResolveWithoutRoot(container, typeof(T));
}
/// <summary>
/// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。
/// </summary>
/// <param name="container"></param>
/// <param name="fromType"></param>
/// <param name="key"></param>
/// <returns></returns>
public static object TryResolve(this IContainer container, Type fromType, string key = "")
{
if (container.IsRegistered(fromType))
{
return container.Resolve(fromType, key);
}
return default;
}
/// <summary>
/// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T TryResolve<T>(this IContainer container, string key = "")
{
return (T)TryResolve(container, typeof(T), key);
}
#endregion Resolve
}
}

View File

@@ -1,114 +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;
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 手动IOC容器
/// </summary>
public abstract class ManualContainer : IContainer
{
private readonly ConcurrentDictionary<string, object> m_singletonInstances = new ConcurrentDictionary<string, object>();
IEnumerator<DependencyDescriptor> IEnumerable<DependencyDescriptor>.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
/// <summary>
/// 判断指定的类型是否已在容器中注册。
/// <para>
/// 在本容器中,一般均会返回<see langword="true"/>。
/// </para>
/// </summary>
/// <param name="fromType"></param>
/// <param name="key"></param>
/// <returns></returns>
public virtual bool IsRegistered(Type fromType, string key = "")
{
return true;
}
/// <summary>
/// 注册描述符。
/// <para>
/// 一般情况下,本容器只会处理单例实例模式。
/// </para>
/// </summary>
/// <param name="descriptor"></param>
/// <param name="key"></param>
public virtual void Register(DependencyDescriptor descriptor, string key = "")
{
if (descriptor.Lifetime == Lifetime.Singleton)
{
if (descriptor.ToInstance != null)
{
this.m_singletonInstances.AddOrUpdate($"{descriptor.FromType.FullName}{key}", descriptor.ToInstance, (k, v) => descriptor.ToInstance);
}
}
}
/// <inheritdoc/>
/// <exception cref="Exception"></exception>
public object Resolve(Type fromType, string key = "")
{
if (fromType.FullName == "ThingsGateway.Foundation.Core.IContainer")
{
return this;
}
if (this.TryResolve(fromType, out var instance, key))
{
return instance;
}
throw new Exception($"没有解决容器所需类型:{fromType.FullName}");
}
/// <summary>
/// 默认不实现该功能
/// </summary>
/// <param name="descriptor"></param>
/// <param name="key"></param>
/// <exception cref="NotImplementedException"></exception>
public virtual void Unregister(DependencyDescriptor descriptor, string key = "")
{
throw new NotImplementedException();
}
/// <summary>
/// 尝试解决Ioc容器所需类型。
/// <para>
/// 本方法仅实现了在单例实例注册下的获取。
/// </para>
/// </summary>
/// <param name="fromType"></param>
/// <param name="instance"></param>
/// <param name="key"></param>
/// <returns></returns>
protected virtual bool TryResolve(Type fromType, out object instance, string key = "")
{
if (key.IsNullOrEmpty())
{
return this.m_singletonInstances.TryGetValue(fromType.FullName, out instance);
}
return this.m_singletonInstances.TryGetValue($"{fromType.FullName}{key}", out instance);
}
}
}

View File

@@ -1,66 +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;
using System.Linq.Expressions;
namespace ThingsGateway.Foundation.Core
{
#if NET6_0_OR_GREATER
/// <summary>
/// 实例生成
/// </summary>
public static class InstanceCreater
{
/// <summary>
/// 根据对象类型创建对象实例
/// </summary>
/// <param name="key">对象类型</param>
/// <returns></returns>
public static object Create(Type key)
{
return Activator.CreateInstance(key);
}
}
#else
/// <summary>
/// 实例生成
/// </summary>
public static class InstanceCreater
{
private static readonly Hashtable m_paramCache = Hashtable.Synchronized(new Hashtable());//缓存
/// <summary>
/// 根据对象类型创建对象实例
/// </summary>
/// <param name="key">对象类型</param>
/// <returns></returns>
public static object Create(Type key)
{
var value = (Func<object>)m_paramCache[key];
if (value == null)
{
value = CreateInstanceByType(key);
m_paramCache[key] = value;
}
return value();
}
private static Func<object> CreateInstanceByType(Type type)
{
return Expression.Lambda<Func<object>>(Expression.New(type), null).Compile();
}
}
#endif
}

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,42 +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>
/// DmtpRouteServiceExtension
/// </summary>
public static class DmtpRouteServiceExtension
{
/// <summary>
/// 添加Dmtp路由服务。
/// </summary>
/// <param name="container"></param>
public static void AddDmtpRouteService(this IContainer container)
{
container.RegisterSingleton<IDmtpRouteService, DmtpRouteService>();
}
/// <summary>
/// 添加基于设定委托的Dmtp路由服务。
/// </summary>
/// <param name="container"></param>
/// <param name="func"></param>
public static void AddDmtpRouteService(this IContainer container, Func<string, IDmtpActor> func)
{
container.RegisterSingleton<IDmtpRouteService>(new DmtpRouteService()
{
FindDmtpActor = func
});
}
}
}

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,148 +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
#if !NET45
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThingsGateway.Foundation.Core;
using ThingsGateway.Foundation.Sockets;
using HttpClient = System.Net.Http.HttpClient;
using HttpMethod = System.Net.Http.HttpMethod;
namespace ThingsGateway.Foundation.Http
{
/// <summary>
/// 这是基于<see cref="System.Net.Http.HttpClient"/>的通讯模型。
/// </summary>
public class HttpClientSlim : DisposableObject
{
private readonly System.Net.Http.HttpClient m_httpClient;
/// <summary>
/// 这是基于<see cref="System.Net.Http.HttpClient"/>的通讯模型。
/// </summary>
/// <param name="httpClient"></param>
public HttpClientSlim(System.Net.Http.HttpClient httpClient = default)
{
httpClient ??= new System.Net.Http.HttpClient();
this.m_httpClient = httpClient;
}
/// <summary>
/// 配置
/// </summary>
public TouchSocketConfig Config { get; private set; }
/// <summary>
/// Ioc容器
/// </summary>
public IContainer Container { get; private set; }
/// <summary>
/// 插件管理器
/// </summary>
public IPluginsManager PluginsManager { get; private set; }
/// <summary>
/// 日志记录器
/// </summary>
public ILog Logger { get; private set; }
/// <summary>
/// 通讯客户端
/// </summary>
public System.Net.Http.HttpClient HttpClient => this.m_httpClient;
/// <summary>
/// 加载配置
/// </summary>
/// <param name="config"></param>
protected virtual void LoadConfig(TouchSocketConfig config)
{
this.m_httpClient.BaseAddress ??= config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty);
this.Logger ??= this.Container.Resolve<ILog>();
}
/// <summary>
/// 配置
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public HttpClientSlim Setup(TouchSocketConfig config)
{
if (config == null)
{
throw new ArgumentNullException(nameof(config));
}
this.ThrowIfDisposed();
this.BuildConfig(config);
this.PluginsManager.Raise(nameof(ILoadingConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config));
this.LoadConfig(this.Config);
this.PluginsManager.Raise(nameof(ILoadedConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
return this;
}
private void BuildConfig(TouchSocketConfig config)
{
this.Config = config;
if (!(config.GetValue(TouchSocketCoreConfigExtension.ContainerProperty) is IContainer container))
{
container = new Container();
}
if (!container.IsRegistered(typeof(ILog)))
{
container.RegisterSingleton<ILog, LoggerGroup>();
}
if (!(config.GetValue(TouchSocketCoreConfigExtension.PluginsManagerProperty) is IPluginsManager pluginsManager))
{
pluginsManager = new PluginsManager(container);
}
if (container.IsRegistered(typeof(IPluginsManager)))
{
pluginsManager = container.Resolve<IPluginsManager>();
}
else
{
container.RegisterSingleton<IPluginsManager>(pluginsManager);
}
if (config.GetValue(TouchSocketCoreConfigExtension.ConfigureContainerProperty) is Action<IContainer> actionContainer)
{
actionContainer.Invoke(container);
}
if (config.GetValue(TouchSocketCoreConfigExtension.ConfigurePluginsProperty) is Action<IPluginsManager> actionPluginsManager)
{
pluginsManager.Enable = true;
actionPluginsManager.Invoke(pluginsManager);
}
this.Container = container;
this.PluginsManager = pluginsManager;
}
}
}
#endif

View File

@@ -1,60 +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>
/// RpcServerFactory
/// </summary>
public class RpcServerFactory : IRpcServerFactory
{
private readonly IContainer m_container;
private readonly ILog m_logger;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="container"></param>
/// <param name="logger"></param>
public RpcServerFactory(IContainer container, ILog logger)
{
this.m_container = container;
this.m_logger = logger;
}
IRpcServer IRpcServerFactory.Create(ICallContext callContext, object[] ps)
{
try
{
return (IRpcServer)this.m_container.Resolve(callContext.MethodInstance.ServerFromType);
}
catch (System.Exception ex)
{
this.m_logger.Exception(ex);
throw;
}
}
}
}

View File

@@ -1,536 +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 System.Collections;
using System.Collections.Concurrent;
using System.Reflection;
namespace ThingsGateway.Foundation.Rpc
{
/// <summary>
/// Rpc仓库
/// </summary>
public class RpcStore : DisposableObject, IEnumerable<IRpcParser>
{
private readonly ConcurrentList<IRpcParser> m_parsers = new ConcurrentList<IRpcParser>();
private readonly ConcurrentDictionary<Type, List<MethodInstance>> m_serverTypes = new ConcurrentDictionary<Type, List<MethodInstance>>();
/// <summary>
/// 实例化一个Rpc仓库。
/// <para>需要指定<see cref="IContainer"/>容器。一般和对应的服务器、客户端共用一个容器比较好。</para>
/// </summary>
public RpcStore(IContainer container)
{
this.Container = container ?? throw new ArgumentNullException(nameof(container));
if (!container.IsRegistered(typeof(IRpcServerFactory)))
{
this.Container.RegisterSingleton<IRpcServerFactory, RpcServerFactory>();
}
}
/// <summary>
/// 内置IOC容器
/// </summary>
public IContainer Container { get; private set; }
/// <summary>
/// 服务类型
/// </summary>
public Type[] ServerTypes => this.m_serverTypes.Keys.ToArray();
/// <summary>
/// 执行Rpc
/// </summary>
/// <param name="rpcServer"></param>
/// <param name="ps"></param>
/// <param name="callContext"></param>
/// <returns></returns>
public static InvokeResult Execute(IRpcServer rpcServer, object[] ps, ICallContext callContext)
{
var invokeResult = new InvokeResult();
try
{
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = callContext.MethodInstance.Filters[i].ExecutingAsync(callContext, ps, invokeResult)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
}
if (invokeResult.Status != InvokeStatus.Ready)
{
return invokeResult;
}
//调用
switch (callContext.MethodInstance.TaskType)
{
case TaskReturnType.Task:
{
callContext.MethodInstance.InvokeAsync(rpcServer, ps)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
break;
case TaskReturnType.TaskObject:
{
invokeResult.Result = callContext.MethodInstance.InvokeObjectAsync(rpcServer, ps)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
break;
default:
case TaskReturnType.None:
{
if (callContext.MethodInstance.HasReturn)
{
invokeResult.Result = callContext.MethodInstance.Invoke(rpcServer, ps);
}
else
{
callContext.MethodInstance.Invoke(rpcServer, ps);
}
}
break;
}
invokeResult.Status = InvokeStatus.Success;
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = callContext.MethodInstance.Filters[i].ExecutedAsync(callContext, ps, invokeResult)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
}
}
catch (TargetInvocationException ex)
{
invokeResult.Status = InvokeStatus.InvocationException;
invokeResult.Message = ex.InnerException != null ? $"函数内部发生异常,信息:{ex.InnerException.Message}" : "函数内部发生异常,信息:未知";
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = callContext.MethodInstance.Filters[i].ExecutExceptionAsync(callContext, ps, invokeResult, ex)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
}
}
catch (Exception ex)
{
invokeResult.Status = InvokeStatus.Exception;
invokeResult.Message = ex.Message;
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = callContext.MethodInstance.Filters[i].ExecutExceptionAsync(callContext, ps, invokeResult, ex).ConfigureAwait(false).GetAwaiter().GetResult();
}
}
}
return invokeResult;
}
/// <summary>
/// 异步执行Rpc
/// </summary>
/// <param name="rpcServer"></param>
/// <param name="ps"></param>
/// <param name="callContext"></param>
/// <returns></returns>
public static async Task<InvokeResult> ExecuteAsync(IRpcServer rpcServer, object[] ps, ICallContext callContext)
{
var invokeResult = new InvokeResult();
try
{
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = await callContext.MethodInstance.Filters[i].ExecutingAsync(callContext, ps, invokeResult);
}
}
if (invokeResult.Status != InvokeStatus.Ready)
{
return invokeResult;
}
//调用
switch (callContext.MethodInstance.TaskType)
{
case TaskReturnType.Task:
{
await (Task)callContext.MethodInstance.Invoke(rpcServer, ps);
}
break;
case TaskReturnType.TaskObject:
{
invokeResult.Result = await callContext.MethodInstance.InvokeObjectAsync(rpcServer, ps);
}
break;
default:
case TaskReturnType.None:
{
if (callContext.MethodInstance.HasReturn)
{
invokeResult.Result = callContext.MethodInstance.Invoke(rpcServer, ps);
}
else
{
callContext.MethodInstance.Invoke(rpcServer, ps);
}
}
break;
}
invokeResult.Status = InvokeStatus.Success;
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = await callContext.MethodInstance.Filters[i].ExecutedAsync(callContext, ps, invokeResult);
}
}
}
catch (TargetInvocationException ex)
{
invokeResult.Status = InvokeStatus.InvocationException;
invokeResult.Message = ex.InnerException != null ? $"函数内部发生异常,信息:{ex.InnerException.Message}" : "函数内部发生异常,信息:未知";
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = await callContext.MethodInstance.Filters[i].ExecutExceptionAsync(callContext, ps, invokeResult, ex);
}
}
}
catch (Exception ex)
{
invokeResult.Status = InvokeStatus.Exception;
invokeResult.Message = ex.Message;
if (callContext.MethodInstance.Filters != null)
{
for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
{
invokeResult = await callContext.MethodInstance.Filters[i].ExecutExceptionAsync(callContext, ps, invokeResult, ex);
}
}
}
return invokeResult;
}
/// <summary>
/// 添加Rpc解析器
/// </summary>
/// <param name="parser">解析器实例</param>
/// <param name="applyServer">是否应用已注册服务</param>
public void AddRpcParser(IRpcParser parser, bool applyServer = true)
{
this.ThrowIfDisposed();
this.m_parsers.Add(parser);
//parser.SetRpcStore(this);
if (applyServer)
{
foreach (var item in this.m_serverTypes)
{
parser.OnRegisterServer(item.Value.ToArray());
}
}
}
/// <summary>
/// 获取所有已注册的函数。
/// </summary>
public MethodInstance[] GetAllMethods()
{
var methods = new List<MethodInstance>();
foreach (var item in this.m_serverTypes.Values)
{
methods.AddRange(item);
}
return methods.ToArray();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.m_parsers.GetEnumerator();
}
/// <summary>
/// 返回枚举对象
/// </summary>
/// <returns></returns>
IEnumerator<IRpcParser> IEnumerable<IRpcParser>.GetEnumerator()
{
return this.m_parsers.GetEnumerator();
}
/// <summary>
/// 本地获取代理
/// </summary>
/// <param name="namespace"></param>
/// <param name="attrbuteTypes"></param>
/// <returns></returns>
public string GetProxyCodes(string @namespace, params Type[] attrbuteTypes)
{
var cellCodes = this.GetProxyInfo(attrbuteTypes);
return CodeGenerator.ConvertToCode(@namespace, cellCodes);
}
/// <summary>
/// 获取生成的代理
/// </summary>
/// <typeparam name="TAttribute"></typeparam>
/// <param name="namespace"></param>
/// <returns></returns>
public string GetProxyCodes<TAttribute>(string @namespace) where TAttribute : RpcAttribute
{
var cellCodes = this.GetProxyInfo(new Type[] { typeof(TAttribute) });
return CodeGenerator.ConvertToCode(@namespace, cellCodes);
}
/// <summary>
/// 从本地获取代理
/// </summary>
/// <param name="attrbuteType"></param>
/// <returns></returns>
public ServerCellCode[] GetProxyInfo(Type[] attrbuteType)
{
if (this.DisposedValue)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
var codes = new List<ServerCellCode>();
foreach (var attrbute in attrbuteType)
{
foreach (var item in this.m_serverTypes.Keys)
{
var serverCellCode = CodeGenerator.Generator(item, attrbute);
codes.Add(serverCellCode);
}
}
return codes.ToArray();
}
/// <summary>
/// 获取服务类型对应的服务方法。
/// </summary>
/// <param name="serverType"></param>
/// <returns></returns>
public MethodInstance[] GetServerMethodInstances(Type serverType)
{
return this.m_serverTypes[serverType].ToArray();
}
/// <summary>
/// 移除Rpc解析器
/// </summary>
/// <param name="parser"></param>
/// <returns></returns>
public bool RemoveRpcParser(IRpcParser parser)
{
return this.m_parsers.Remove(parser);
}
/// <summary>
/// 移除注册服务
/// </summary>
/// <param name="provider"></param>
/// <returns></returns>
public int UnregisterServer(IRpcServer provider)
{
return this.UnregisterServer(provider.GetType());
}
/// <summary>
/// 移除注册服务
/// </summary>
/// <param name="providerType"></param>
/// <returns></returns>
public int UnregisterServer(Type providerType)
{
this.ThrowIfDisposed();
if (!typeof(IRpcServer).IsAssignableFrom(providerType))
{
throw new RpcException("类型不相符");
}
if (this.RemoveServer(providerType, out var instances))
{
foreach (var parser in this)
{
parser.OnUnregisterServer(instances);
}
return instances.Length;
}
return 0;
}
/// <summary>
/// 移除注册服务
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public int UnregisterServer<T>() where T : IRpcServer
{
return this.UnregisterServer(typeof(T));
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (!this.DisposedValue)
{
foreach (var item in this)
{
item.SafeDispose();
}
}
base.Dispose(disposing);
}
private bool RemoveServer(Type type, out MethodInstance[] methodInstances)
{
foreach (var newType in this.m_serverTypes.Keys)
{
if (newType.FullName == type.FullName)
{
this.m_serverTypes.TryRemove(newType, out var list);
methodInstances = list.ToArray();
return true;
}
}
methodInstances = null;
return false;
}
#region
/// <summary>
/// 注册为单例服务
/// </summary>
/// <param name="serverFromType"></param>
/// <param name="rpcServer"></param>
/// <returns></returns>
public void RegisterServer(Type serverFromType, IRpcServer rpcServer)
{
if (!typeof(IRpcServer).IsAssignableFrom(serverFromType))
{
throw new RpcException($"注册类型必须与{nameof(IRpcServer)}有继承关系");
}
if (!serverFromType.IsAssignableFrom(rpcServer.GetType()))
{
throw new RpcException("实例类型必须与注册类型有继承关系。");
}
foreach (var item in this.m_serverTypes.Keys)
{
if (item.FullName == serverFromType.FullName)
{
return;
}
}
var methodInstances = CodeGenerator.GetMethodInstances(serverFromType, rpcServer.GetType());
foreach (var item in methodInstances)
{
item.ServerFactory = this.Container.Resolve<IRpcServerFactory>() ?? throw new ArgumentNullException($"{nameof(IRpcServerFactory)}");
}
this.m_serverTypes.TryAdd(serverFromType, new List<MethodInstance>(methodInstances));
this.Container.RegisterSingleton(serverFromType, rpcServer);
foreach (var parser in this)
{
parser.OnRegisterServer(methodInstances);
}
}
/// <summary>
/// 注册服务
/// </summary>
/// <param name="serverFromType"></param>
/// <param name="serverToType"></param>
/// <returns></returns>
public void RegisterServer(Type serverFromType, Type serverToType)
{
if (!typeof(IRpcServer).IsAssignableFrom(serverFromType))
{
throw new RpcException($"注册类型必须与{nameof(IRpcServer)}有继承关系");
}
if (!serverFromType.IsAssignableFrom(serverToType))
{
throw new RpcException("实例类型必须与注册类型有继承关系。");
}
foreach (var item in this.m_serverTypes.Keys)
{
if (item.FullName == serverFromType.FullName)
{
return;
}
}
if (typeof(ITransientRpcServer).IsAssignableFrom(serverFromType))
{
this.Container.RegisterTransient(serverFromType, serverToType);
}
else
{
this.Container.RegisterSingleton(serverFromType, serverToType);
}
var methodInstances = CodeGenerator.GetMethodInstances(serverFromType, serverToType);
foreach (var item in methodInstances)
{
item.ServerFactory = this.Container.Resolve<IRpcServerFactory>() ?? throw new ArgumentNullException($"{nameof(IRpcServerFactory)}");
}
this.m_serverTypes.TryAdd(serverFromType, new List<MethodInstance>(methodInstances));
foreach (var parser in this)
{
parser.OnRegisterServer(methodInstances);
}
}
#endregion
}
}

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,48 +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.Rpc
{
/// <summary>
/// 全局Rpc仓库配置插件。
/// </summary>
public class GlobalRpcStorePlugin : PluginBase
{
private readonly RpcStore m_rpcStore;
/// <summary>
/// 全局Rpc仓库配置插件。
/// </summary>
/// <param name="container"></param>
public GlobalRpcStorePlugin(IContainer container)
{
if (container.IsRegistered(typeof(RpcStore)))
{
this.m_rpcStore = container.Resolve<RpcStore>();
}
else
{
this.m_rpcStore = new RpcStore(container);
container.RegisterSingleton<RpcStore>(this.m_rpcStore);
}
}
/// <summary>
/// 全局配置Rpc服务
/// </summary>
/// <param name="action"></param>
public void ConfigureRpcStore(Action<RpcStore> action)
{
action?.Invoke(this.m_rpcStore);
}
}
}

View File

@@ -1,48 +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.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
/// <summary>
/// Connecting
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate Task SerialConnectingEventHandler<TClient>(TClient client, SerialConnectingEventArgs e);
/// <summary>
/// 客户端连接事件。
/// </summary>
public class SerialConnectingEventArgs : MsgPermitEventArgs
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="serialPort"></param>
public SerialConnectingEventArgs(SerialPort serialPort)
{
this.SerialPort = serialPort;
this.IsPermitOperation = true;
}
/// <summary>
/// 客户端Id。该Id的赋值仅在服务器适用。
/// </summary>
public string Id { get; set; }
/// <summary>
/// 新初始化的通信器
/// </summary>
public SerialPort SerialPort { get; private set; }
}

View File

@@ -1,38 +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 static class SerialConfigExtension
{
/// <summary>
/// 串口属性
/// </summary>
public static readonly DependencyProperty<SerialProperty> SerialProperty =
DependencyProperty<SerialProperty>.Register("SerialProperty", new());
/// <summary>
/// 设置串口
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static TouchSocketConfig SetSerialProperty(this TouchSocketConfig config, SerialProperty value)
{
config.SetValue(SerialProperty, value);
return config;
}
}

View File

@@ -1,58 +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.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
/// <summary>
/// SocketExtension
/// </summary>
public static class SerialPortExtensions
{
/// <summary>
/// 会使用同步锁,保证所有数据上缓存区。
/// </summary>
/// <param name="serialPort"></param>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
public static void AbsoluteSend(this SerialPort serialPort, byte[] buffer, int offset, int length)
{
lock (serialPort)
{
serialPort.Write(buffer, offset, length);
}
}
/// <summary>
/// 尝试关闭<see cref="SerialPort"/>。不会抛出异常。
/// </summary>
/// <param name="serialPort"></param>
public static void TryClose(this SerialPort serialPort)
{
lock (serialPort)
{
try
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
}
catch
{
}
}
}
}

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>
/// <inheritdoc cref="ISerialSessionBase"/>
/// </summary>
public interface ISerialSession : ISerialSessionBase, IClientSender, IPluginObject
{
/// <summary>
/// 成功打开串口
/// </summary>
ConnectedEventHandler<ISerialSession> Connected { get; set; }
/// <summary>
/// 准备连接串口的时候
/// </summary>
SerialConnectingEventHandler<ISerialSession> Connecting { get; set; }
/// <summary>
/// 连接串口
/// </summary>
/// <exception cref="Exception"></exception>
ISerialSession Connect();
/// <summary>
/// 配置服务器
/// </summary>
/// <param name="config"></param>
/// <exception cref="Exception"></exception>
ISerialSession Setup(TouchSocketConfig config);
}

View File

@@ -1,76 +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.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
/// <summary>
/// 串口连接接口。
/// </summary>
public interface ISerialSessionBase : IClient, ISender, IDefaultSender, IPluginObject, IRequsetInfoSender
{
/// <summary>
/// 是否允许自由调用<see cref="SetDataHandlingAdapter"/>进行赋值。
/// </summary>
bool CanSetDataHandlingAdapter { get; }
/// <summary>
/// 客户端配置
/// </summary>
TouchSocketConfig Config { get; }
/// <summary>
/// 数据处理适配器
/// </summary>
SingleStreamDataHandlingAdapter DataHandlingAdapter { get; }
/// <summary>
/// 断开连接
/// </summary>
DisconnectEventHandler<ISerialSessionBase> Disconnected { get; set; }
/// <summary>
/// 即将断开连接(仅主动断开时有效)。
/// <para>
/// </para>
/// </summary>
DisconnectEventHandler<ISerialSessionBase> Disconnecting { get; set; }
/// <summary>
/// 主通信器
/// </summary>
SerialPort MainSerialPort { get; }
/// <summary>
/// 判断是否在线
/// </summary>
bool Online { get; }
/// <summary>
/// 串口描述
/// </summary>
SerialProperty SerialProperty { get; }
/// <summary>
/// 关闭客户端。
/// </summary>
/// <param name="msg"></param>
/// <exception cref="Exception"></exception>
void Close(string msg = TouchSocketCoreUtility.Empty);
/// <summary>
/// 设置数据处理适配器
/// </summary>
/// <param name="adapter"></param>
void SetDataHandlingAdapter(SingleStreamDataHandlingAdapter adapter);
}

View File

@@ -1,380 +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 System.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
internal sealed class InternalSerialCore : SerialCore
{
}
/// <summary>
/// Serial核心
/// </summary>
public class SerialCore : IDisposable, ISender
{
/// <summary>
/// 最小缓存尺寸
/// </summary>
public int MinBufferSize { get; set; } = 1024 * 10;
/// <summary>
/// 最大缓存尺寸
/// </summary>
public int MaxBufferSize { get; set; } = 1024 * 1024 * 10;
#region
/// <summary>
/// 同步根
/// </summary>
public readonly object SyncRoot = new object();
private long m_bufferRate;
private SpinLock m_lock;
private bool m_online => m_serialPort?.IsOpen == true;
private int m_receiveBufferSize = 1024 * 10;
private ValueCounter m_receiveCounter;
private int m_sendBufferSize = 1024 * 10;
private ValueCounter m_sendCounter;
private readonly EasyLock m_semaphore = new EasyLock();
private SerialPort m_serialPort;
#endregion
/// <summary>
/// Tcp核心
/// </summary>
public SerialCore()
{
this.m_lock = new SpinLock(Debugger.IsAttached);
this.m_receiveCounter = new ValueCounter
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnReceivePeriod
};
this.m_sendCounter = new ValueCounter
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnSendPeriod
};
}
/// <summary>
/// 析构函数
/// </summary>
~SerialCore()
{
this.SafeDispose();
}
/// <inheritdoc/>
public bool CanSend => this.m_online;
/// <summary>
/// 当中断Tcp的时候。当为<see langword="true"/>时,意味着是调用<see cref="Close(string)"/>。当为<see langword="false"/>时,则是其他中断。
/// </summary>
public Action<SerialCore, bool, string> OnBreakOut { get; set; }
/// <summary>
/// 当发生异常的时候
/// </summary>
public Action<SerialCore, Exception> OnException { get; set; }
/// <summary>
/// 在线状态
/// </summary>
public bool Online { get => this.m_online; }
/// <summary>
/// UserToken
/// </summary>
public ByteBlock UserToken { get; set; }
/// <summary>
/// 当收到数据的时候
/// </summary>
public Action<SerialCore, ByteBlock> OnReceived { get; set; }
/// <summary>
/// 接收缓存池,运行时的值会根据流速自动调整
/// </summary>
public int ReceiveBufferSize
{
get => this.m_receiveBufferSize;
}
/// <summary>
/// 接收计数器
/// </summary>
public ValueCounter ReceiveCounter { get => this.m_receiveCounter; }
/// <summary>
/// 发送缓存池,运行时的值会根据流速自动调整
/// </summary>
public int SendBufferSize
{
get => this.m_sendBufferSize;
}
/// <summary>
/// 发送计数器
/// </summary>
public ValueCounter SendCounter { get => this.m_sendCounter; }
/// <summary>
/// SerialPort
/// </summary>
public SerialPort MainSerialPort { get => this.m_serialPort; }
/// <summary>
/// 开始以Iocp方式接收
/// </summary>
public virtual void BeginIocpReceive()
{
var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize);
this.UserToken = byteBlock;
byteBlock.SetLength(0);
if (this.m_serialPort.BytesToRead > 0)
{
this.m_bufferRate += 2;
this.ProcessReceived();
}
m_serialPort.DataReceived += MainSerialPort_DataReceived;
}
private void MainSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
this.m_bufferRate = 1;
this.ProcessReceived();
}
catch (Exception ex)
{
this.PrivateBreakOut(false, ex.ToString());
}
}
/// <summary>
/// 请求关闭
/// </summary>
/// <param name="msg"></param>
public virtual void Close(string msg)
{
this.PrivateBreakOut(true, msg);
}
/// <summary>
/// 释放对象
/// </summary>
public void Dispose()
{
GC.SuppressFinalize(this);
UserToken.SafeDispose();
}
/// <summary>
/// 重置环境,并设置新的<see cref="m_serialPort"/>。
/// </summary>
/// <param name="socket"></param>
public virtual void Reset(SerialPort socket)
{
if (socket is null)
{
throw new ArgumentNullException(nameof(socket));
}
if (!socket.IsOpen)
{
throw new Exception("新的SerialPort必须在连接状态。");
}
this.Reset();
this.m_serialPort = socket;
}
/// <summary>
/// 重置环境。
/// </summary>
public virtual void Reset()
{
this.m_receiveCounter.Reset();
this.m_sendCounter.Reset();
this.m_serialPort = null;
this.OnReceived = null;
this.OnBreakOut = null;
this.UserToken = null;
this.m_bufferRate = 1;
this.m_lock = new SpinLock();
this.m_receiveBufferSize = this.MinBufferSize;
this.m_sendBufferSize = this.MinBufferSize;
}
/// <summary>
/// 发送数据。
/// <para>
/// 内部会根据是否启用Ssl进行直接发送还是Ssl发送。
/// </para>
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
public virtual void Send(byte[] buffer, int offset, int length)
{
var lockTaken = false;
try
{
this.m_lock.Enter(ref lockTaken);
this.m_serialPort.Write(buffer, offset, length);
}
finally
{
if (lockTaken) this.m_lock.Exit(false);
}
this.m_sendCounter.Increment(length);
}
/// <summary>
/// 异步发送数据。
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public virtual async Task SendAsync(byte[] buffer, int offset, int length)
{
try
{
await this.m_semaphore.WaitAsync();
this.m_serialPort.Write(buffer, offset, length);
}
finally
{
this.m_semaphore.Release();
}
this.m_sendCounter.Increment(length);
}
/// <summary>
/// 当中断Tcp时。
/// </summary>
/// <param name="manual">当为<see langword="true"/>时,意味着是调用<see cref="Close(string)"/>。当为<see langword="false"/>时,则是其他中断。</param>
/// <param name="msg"></param>
protected virtual void BreakOut(bool manual, string msg)
{
this.OnBreakOut?.Invoke(this, manual, msg);
}
/// <summary>
/// 当发生异常的时候
/// </summary>
/// <param name="ex"></param>
protected virtual void Exception(Exception ex)
{
this.OnException?.Invoke(this, ex);
}
/// <summary>
/// 当收到数据的时候
/// </summary>
/// <param name="byteBlock"></param>
protected virtual void Received(ByteBlock byteBlock)
{
this.OnReceived?.Invoke(this, byteBlock);
}
private void HandleBuffer(ByteBlock byteBlock)
{
try
{
this.m_receiveCounter.Increment(byteBlock.Length);
this.Received(byteBlock);
}
catch (Exception ex)
{
this.Exception(ex);
}
finally
{
byteBlock.Dispose();
}
}
private void OnReceivePeriod(long value)
{
this.m_receiveBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize);
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.ReadBufferSize = this.m_receiveBufferSize;
}
}
private void OnSendPeriod(long value)
{
this.m_sendBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize);
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.WriteBufferSize = this.m_sendBufferSize;
}
}
private void PrivateBreakOut(bool manual, string msg)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
this.BreakOut(manual, msg);
}
}
}
private void ProcessReceived()
{
if (!this.m_online)
{
UserToken?.SafeDispose();
return;
}
if (m_serialPort.BytesToRead > 0)
{
var byteBlock = UserToken;
byte[] buffer = BytePool.Default.Rent(m_serialPort.BytesToRead);
int num = m_serialPort.Read(buffer, 0, m_serialPort.BytesToRead);
byteBlock.Write(buffer, 0, num);
byteBlock.SetLength(num);
this.HandleBuffer(byteBlock);
try
{
var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, this.MaxBufferSize));
newByteBlock.SetLength(0);
UserToken = newByteBlock;
if (m_serialPort.BytesToRead > 0)
{
this.m_bufferRate += 2;
this.ProcessReceived();
}
}
catch (Exception ex)
{
this.PrivateBreakOut(false, ex.ToString());
}
}
}
}

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
using System.ComponentModel;
using System.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
/// <summary>
/// 串口属性
/// </summary>
public class SerialProperty
{
/// <summary>
/// COM
/// </summary>
[Description("COM口")]
public string PortName { get; set; } = "COM1";
/// <summary>
/// 波特率
/// </summary>
[Description("波特率")]
public int BaudRate { get; set; } = 9600;
/// <summary>
/// 数据位
/// </summary>
[Description("数据位")]
public int DataBits { get; set; } = 8;
/// <summary>
/// 校验位
/// </summary>
[Description("校验位")]
public Parity Parity { get; set; } = Parity.None;
/// <summary>
/// 停止位
/// </summary>
[Description("停止位")]
public StopBits StopBits { get; set; } = StopBits.One;
/// <inheritdoc/>
public override string ToString()
{
return $"{PortName}[{BaudRate},{DataBits},{StopBits},{Parity}]";
}
}

View File

@@ -1,815 +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.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
/// <inheritdoc cref="SerialSessionBase"/>
public class SerialSession : SerialSessionBase
{
/// <summary>
/// 接收到数据
/// </summary>
public ReceivedEventHandler<SerialSession> Received { get; set; }
/// <inheritdoc/>
protected override async Task ReceivedData(ReceivedDataEventArgs e)
{
if (this.Received != null)
{
await this.Received.Invoke(this, e);
if (e.Handled)
{
return;
}
}
await base.ReceivedData(e);
}
}
/// <summary>
/// 串口管理
/// </summary>
public class SerialSessionBase : BaseSerial, ISerialSession
{
static readonly Protocol SerialPort = new("SerialSession");
/// <summary>
/// 构造函数
/// </summary>
public SerialSessionBase()
{
this.Protocol = SerialPort;
this.m_serialCore = new InternalSerialCore();
}
#region
private DelaySender m_delaySender;
private bool m_online => MainSerialPort?.IsOpen == true;
private readonly EasyLock m_semaphore = new();
private readonly InternalSerialCore m_serialCore;
#endregion
#region
/// <inheritdoc/>
public ConnectedEventHandler<ISerialSession> Connected { get; set; }
/// <inheritdoc/>
public SerialConnectingEventHandler<ISerialSession> Connecting { get; set; }
/// <inheritdoc/>
public DisconnectEventHandler<ISerialSessionBase> Disconnected { get; set; }
/// <inheritdoc/>
public DisconnectEventHandler<ISerialSessionBase> Disconnecting { get; set; }
private Task PrivateOnConnected(object o)
{
return this.OnConnected((ConnectedEventArgs)o);
}
/// <summary>
/// 已经建立连接
/// </summary>
/// <param name="e"></param>
protected virtual async Task OnConnected(ConnectedEventArgs e)
{
try
{
if (this.Connected != null)
{
await this.Connected.Invoke(this, e);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpConnectedPlugin.OnTcpConnected), this, e);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.Connected)}中发生错误。", ex);
}
}
private Task PrivateOnConnecting(SerialConnectingEventArgs e)
{
if (this.CanSetDataHandlingAdapter)
{
this.SetDataHandlingAdapter(this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty).Invoke());
}
return this.OnConnecting(e);
}
/// <summary>
/// 准备连接的时候,此时并未建立连接
/// </summary>
/// <param name="e"></param>
protected virtual async Task OnConnecting(SerialConnectingEventArgs e)
{
try
{
if (this.Connecting != null)
{
await this.Connecting.Invoke(this, e);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpConnectingPlugin.OnTcpConnecting), this, e);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.OnConnecting)}中发生错误。", ex);
}
}
private Task PrivateOnDisconnected(object obj)
{
this.m_receiver?.TryInputReceive(default, default);
return this.OnDisconnected((DisconnectEventArgs)obj);
}
/// <summary>
/// 断开连接。在客户端未设置连接状态时,不会触发
/// </summary>
/// <param name="e"></param>
protected virtual async Task OnDisconnected(DisconnectEventArgs e)
{
try
{
if (this.Disconnected != null)
{
await this.Disconnected.Invoke(this, e).ConfigureAwait(false);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpDisconnectedPlugin.OnTcpDisconnected), this, e).ConfigureAwait(false);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.Disconnected)}中发生错误。", ex);
}
}
private Task PrivateOnDisconnecting(object obj)
{
return this.OnDisconnecting((DisconnectEventArgs)obj);
}
/// <summary>
/// 即将断开连接(仅主动断开时有效)。
/// </summary>
/// <param name="e"></param>
protected virtual async Task OnDisconnecting(DisconnectEventArgs e)
{
try
{
if (this.Disconnecting != null)
{
await this.Disconnecting.Invoke(this, e).ConfigureAwait(false);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpDisconnectingPlugin.OnTcpDisconnecting), this, e).ConfigureAwait(false);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.Disconnecting)}中发生错误。", ex);
}
}
#endregion
#region
/// <inheritdoc/>
public DateTime LastReceivedTime => this.GetSerialCore().ReceiveCounter.LastIncrement;
/// <inheritdoc/>
public DateTime LastSendTime => this.GetSerialCore().SendCounter.LastIncrement;
/// <inheritdoc/>
public IContainer Container { get; private set; }
/// <inheritdoc/>
public virtual bool CanSetDataHandlingAdapter => true;
/// <inheritdoc/>
public TouchSocketConfig Config { get; private set; }
/// <inheritdoc/>
public SingleStreamDataHandlingAdapter DataHandlingAdapter { get; private set; }
/// <inheritdoc/>
public SerialProperty SerialProperty { get; private set; }
/// <inheritdoc/>
public SerialPort MainSerialPort { get; private set; }
/// <inheritdoc/>
public bool Online { get => this.m_online; }
/// <inheritdoc/>
public bool CanSend => this.m_online;
/// <inheritdoc/>
public IPluginsManager PluginsManager { get; private set; }
/// <inheritdoc/>
public Protocol Protocol { get; set; }
#endregion
#region
/// <inheritdoc/>
public virtual void Close(string msg = TouchSocketCoreUtility.Empty)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, msg));
this.MainSerialPort.TryClose();
this.BreakOut(default, true, msg);
}
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
this.BreakOut(default, true, $"{nameof(Dispose)}主动断开");
}
}
base.Dispose(disposing);
}
#endregion
#region Connect
/// <summary>
/// 打开串口
/// </summary>
protected void Open()
{
lock (this.SyncRoot)
{
if (this.m_online)
{
return;
}
if (this.DisposedValue)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (this.Config == null)
{
throw new ArgumentNullException(nameof(this.Config), "配置文件不能为空。");
}
var serialProperty = this.Config.GetValue(SerialConfigExtension.SerialProperty) ?? throw new ArgumentNullException("串口配置不能为空。");
this.MainSerialPort.SafeDispose();
var serialPort = CreateSerial(serialProperty);
this.PrivateOnConnecting(new(serialPort))
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
serialPort.Open();
this.SetSerialPort(serialPort);
this.BeginReceive();
Task.Factory.StartNew(this.PrivateOnConnected, new ConnectedEventArgs());
}
}
private void BeginReceive()
{
this.GetSerialCore().BeginIocpReceive();
}
/// <inheritdoc/>
public virtual ISerialSession Connect()
{
this.Open();
return this;
}
/// <inheritdoc/>
public Task<ISerialSession> ConnectAsync()
{
return Task.Run(() =>
{
return this.Connect();
});
}
#endregion Connect
#region Receiver
private Receiver m_receiver;
/// <inheritdoc/>
public IReceiver CreateReceiver()
{
return this.m_receiver ??= new Receiver(this);
}
/// <inheritdoc/>
public void ClearReceiver()
{
this.m_receiver = null;
}
#endregion
private void BreakOut(SerialCore core, bool manual, string msg)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
Task.Factory.StartNew(this.PrivateOnDisconnected, new DisconnectEventArgs(manual, msg));
}
}
}
private SerialCore GetSerialCore()
{
this.ThrowIfDisposed();
return this.m_serialCore ?? throw new ObjectDisposedException(this.GetType().Name);
}
/// <inheritdoc/>
public override int ReceiveBufferSize
{
get => this.GetSerialCore().ReceiveBufferSize;
}
/// <inheritdoc/>
public override int SendBufferSize
{
get => this.GetSerialCore().SendBufferSize;
}
/// <inheritdoc/>
public virtual void SetDataHandlingAdapter(SingleStreamDataHandlingAdapter adapter)
{
if (!this.CanSetDataHandlingAdapter)
{
throw new Exception($"不允许自由调用{nameof(SetDataHandlingAdapter)}进行赋值。");
}
this.SetAdapter(adapter);
}
/// <inheritdoc/>
public ISerialSession Setup(TouchSocketConfig config)
{
if (config == null)
{
throw new ArgumentNullException(nameof(config));
}
this.ThrowIfDisposed();
this.BuildConfig(config);
this.PluginsManager.Raise(nameof(ILoadingConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config));
this.LoadConfig(this.Config);
this.PluginsManager.Raise(nameof(ILoadedConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
return this;
}
private void BuildConfig(TouchSocketConfig config)
{
this.Config = config;
if (!(config.GetValue(TouchSocketCoreConfigExtension.ContainerProperty) is IContainer container))
{
container = new Container();
}
if (!container.IsRegistered(typeof(ILog)))
{
container.RegisterSingleton<ILog, LoggerGroup>();
}
if (!(config.GetValue(TouchSocketCoreConfigExtension.PluginsManagerProperty) is IPluginsManager pluginsManager))
{
pluginsManager = new PluginsManager(container);
}
if (container.IsRegistered(typeof(IPluginsManager)))
{
pluginsManager = container.Resolve<IPluginsManager>();
}
else
{
container.RegisterSingleton<IPluginsManager>(pluginsManager);
}
if (config.GetValue(TouchSocketCoreConfigExtension.ConfigureContainerProperty) is Action<IContainer> actionContainer)
{
actionContainer.Invoke(container);
}
if (config.GetValue(TouchSocketCoreConfigExtension.ConfigurePluginsProperty) is Action<IPluginsManager> actionPluginsManager)
{
pluginsManager.Enable = true;
actionPluginsManager.Invoke(pluginsManager);
}
this.Container = container;
this.PluginsManager = pluginsManager;
}
private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
if (this.m_receiver != null)
{
if (this.m_receiver.TryInputReceive(byteBlock, requestInfo))
{
return;
}
}
this.ReceivedData(new ReceivedDataEventArgs(byteBlock, requestInfo)).GetFalseAwaitResult();
}
/// <summary>
/// 当收到适配器处理的数据时。
/// </summary>
/// <param name="e"></param>
/// <returns>如果返回<see langword="true"/>则表示数据已被处理,且不会再向下传递。</returns>
protected virtual Task ReceivedData(ReceivedDataEventArgs e)
{
return this.PluginsManager.RaiseAsync(nameof(ITcpReceivedPlugin.OnTcpReceived), this, e);
}
/// <summary>
/// 当即将发送时,如果覆盖父类方法,则不会触发插件。
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
/// <returns>返回值表示是否允许发送</returns>
protected virtual async Task<bool> SendingData(byte[] buffer, int offset, int length)
{
if (this.PluginsManager.GetPluginCount(nameof(ITcpSendingPlugin.OnTcpSending)) > 0)
{
var args = new SendingEventArgs(buffer, offset, length);
await this.PluginsManager.RaiseAsync(nameof(ITcpSendingPlugin.OnTcpSending), this, args).ConfigureAwait(false);
return args.IsPermitOperation;
}
return true;
}
/// <summary>
/// 加载配置
/// </summary>
/// <param name="config"></param>
protected virtual void LoadConfig(TouchSocketConfig config)
{
this.SerialProperty = config.GetValue(SerialConfigExtension.SerialProperty);
this.Logger ??= this.Container.Resolve<ILog>();
}
/// <summary>
/// 设置适配器,该方法不会检验<see cref="CanSetDataHandlingAdapter"/>的值。
/// </summary>
/// <param name="adapter"></param>
protected void SetAdapter(SingleStreamDataHandlingAdapter adapter)
{
this.ThrowIfDisposed();
if (adapter is null)
{
throw new ArgumentNullException(nameof(adapter));
}
if (this.Config != null)
{
adapter.Config(this.Config);
}
adapter.Logger = this.Logger;
adapter.OnLoaded(this);
adapter.ReceivedCallBack = this.PrivateHandleReceivedData;
adapter.SendCallBack = this.DefaultSend;
adapter.SendAsyncCallBack = this.DefaultSendAsync;
this.DataHandlingAdapter = adapter;
}
private static SerialPort CreateSerial(SerialProperty serialProperty)
{
SerialPort serialPort = new(serialProperty.PortName, serialProperty.BaudRate, serialProperty.Parity, serialProperty.DataBits, serialProperty.StopBits)
{
DtrEnable = true,
RtsEnable = true
};
return serialPort;
}
#region
#region
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="requestInfo"></param>
/// <exception cref="NotConnectedException"></exception>
/// <exception cref="OverlengthException"></exception>
/// <exception cref="Exception"></exception>
public void Send(IRequestInfo requestInfo)
{
if (this.DisposedValue)
{
return;
}
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}
if (!this.DataHandlingAdapter.CanSendRequestInfo)
{
throw new NotSupportedException($"当前适配器不支持对象发送。");
}
this.DataHandlingAdapter.SendInput(requestInfo);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="buffer"><inheritdoc/></param>
/// <param name="offset"><inheritdoc/></param>
/// <param name="length"><inheritdoc/></param>
/// <exception cref="NotConnectedException"><inheritdoc/></exception>
/// <exception cref="OverlengthException"><inheritdoc/></exception>
/// <exception cref="Exception"><inheritdoc/></exception>
public virtual void Send(byte[] buffer, int offset, int length)
{
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}
this.DataHandlingAdapter.SendInput(buffer, offset, length);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="transferBytes"><inheritdoc/></param>
/// <exception cref="NotConnectedException"><inheritdoc/></exception>
/// <exception cref="OverlengthException"><inheritdoc/></exception>
/// <exception cref="Exception"><inheritdoc/></exception>
public virtual void Send(IList<ArraySegment<byte>> transferBytes)
{
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}
if (this.DataHandlingAdapter.CanSplicingSend)
{
this.DataHandlingAdapter.SendInput(transferBytes);
}
else
{
var length = 0;
foreach (var item in transferBytes)
{
length += item.Count;
}
using (var byteBlock = new ByteBlock(length))
{
foreach (var item in transferBytes)
{
byteBlock.Write(item.Array, item.Offset, item.Count);
}
this.DataHandlingAdapter.SendInput(byteBlock.Buffer, 0, byteBlock.Len);
}
}
}
#endregion
#region
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <exception cref="NotConnectedException"></exception>
/// <exception cref="OverlengthException"></exception>
/// <exception cref="Exception"></exception>
public virtual Task SendAsync(byte[] buffer, int offset, int length)
{
this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}
return this.DataHandlingAdapter.SendInputAsync(buffer, offset, length);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="requestInfo"></param>
/// <exception cref="NotConnectedException"></exception>
/// <exception cref="OverlengthException"></exception>
/// <exception cref="Exception"></exception>
public virtual Task SendAsync(IRequestInfo requestInfo)
{
this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}
if (!this.DataHandlingAdapter.CanSendRequestInfo)
{
throw new NotSupportedException($"当前适配器不支持对象发送。");
}
return this.DataHandlingAdapter.SendInputAsync(requestInfo);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="transferBytes"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public virtual Task SendAsync(IList<ArraySegment<byte>> transferBytes)
{
this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{
throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}
if (this.DataHandlingAdapter.CanSplicingSend)
{
return this.DataHandlingAdapter.SendInputAsync(transferBytes);
}
else
{
var length = 0;
foreach (var item in transferBytes)
{
length += item.Count;
}
using (var byteBlock = new ByteBlock(length))
{
foreach (var item in transferBytes)
{
byteBlock.Write(item.Array, item.Offset, item.Count);
}
return this.DataHandlingAdapter.SendInputAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
}
}
#endregion
/// <inheritdoc/>
public void DefaultSend(byte[] buffer, int offset, int length)
{
if (this.SendingData(buffer, offset, length).GetFalseAwaitResult())
{
this.GetSerialCore().Send(buffer, offset, length);
}
}
/// <inheritdoc/>
public async Task DefaultSendAsync(byte[] buffer, int offset, int length)
{
if (await this.SendingData(buffer, offset, length))
{
await this.GetSerialCore().SendAsync(buffer, offset, length);
}
}
#endregion
#region
private void SetSerialPort(SerialPort serialPort)
{
if (serialPort == null)
{
return;
}
this.MainSerialPort = serialPort;
this.SerialProperty ??= new();
this.SerialProperty.Parity = serialPort.Parity;
this.SerialProperty.PortName = serialPort.PortName;
this.SerialProperty.StopBits = serialPort.StopBits;
this.SerialProperty.DataBits = serialPort.DataBits;
this.SerialProperty.BaudRate = serialPort.BaudRate;
var delaySenderOption = this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty);
if (delaySenderOption != null)
{
this.m_delaySender = new DelaySender(delaySenderOption, this.MainSerialPort.AbsoluteSend);
}
this.m_serialCore.Reset(serialPort);
this.m_serialCore.OnReceived = this.HandleReceived;
this.m_serialCore.OnBreakOut = this.BreakOut;
if (this.Config.GetValue(TouchSocketConfigExtension.MinBufferSizeProperty) is int minValue)
{
this.m_serialCore.MinBufferSize = minValue;
}
if (this.Config.GetValue(TouchSocketConfigExtension.MaxBufferSizeProperty) is int maxValue)
{
this.m_serialCore.MaxBufferSize = maxValue;
}
}
private void HandleReceived(SerialCore core, ByteBlock byteBlock)
{
try
{
if (this.DisposedValue)
{
return;
}
if (this.ReceivingData(byteBlock).GetFalseAwaitResult())
{
return;
}
if (this.DataHandlingAdapter == null)
{
this.Logger.Error(this, TouchSocketResource.NullDataAdapter.GetDescription());
return;
}
this.DataHandlingAdapter.ReceivedInput(byteBlock);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, "在处理数据时发生错误", ex);
}
}
/// <summary>
/// 当收到原始数据
/// </summary>
/// <param name="byteBlock"></param>
/// <returns>如果返回<see langword="true"/>则表示数据已被处理,且不会再向下传递。</returns>
protected virtual Task<bool> ReceivingData(ByteBlock byteBlock)
{
if (this.PluginsManager.GetPluginCount(nameof(ITcpReceivingPlugin.OnTcpReceiving)) > 0)
{
return this.PluginsManager.RaiseAsync(nameof(ITcpReceivingPlugin.OnTcpReceiving), this, new ByteBlockEventArgs(byteBlock));
}
return Task.FromResult(false);
}
#endregion
}

View File

@@ -1,47 +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 abstract class BaseSocket : DependencyObject, ISocket
{
/// <summary>
/// 同步根。
/// </summary>
protected readonly object SyncRoot = new object();
/// <inheritdoc/>
public abstract int SendBufferSize { get; }
/// <inheritdoc/>
public abstract int ReceiveBufferSize { get; }
/// <inheritdoc/>
public ILog Logger { get; set; }
}
}

View File

@@ -1,69 +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>
/// Tcp客户端终端接口
/// </summary>
public interface ITcpClient : ITcpClientBase, IClientSender, IPluginObject
{
/// <summary>
/// 成功连接到服务器
/// </summary>
ConnectedEventHandler<ITcpClient> Connected { get; set; }
/// <summary>
/// 准备连接的时候
/// </summary>
ConnectingEventHandler<ITcpClient> Connecting { get; set; }
/// <summary>
/// 远程IPHost。
/// </summary>
IPHost RemoteIPHost { get; }
/// <summary>
/// 连接服务器
/// </summary>
/// <exception cref="TimeoutException"></exception>
/// <exception cref="Exception"></exception>
ITcpClient Connect(int timeout = 5000);
/// <summary>
/// 异步连接服务器
/// </summary>
/// <exception cref="TimeoutException"></exception>
/// <exception cref="Exception"></exception>
Task<ITcpClient> ConnectAsync(int timeout = 5000);
/// <summary>
/// 配置服务器
/// </summary>
/// <param name="config"></param>
/// <exception cref="Exception"></exception>
ITcpClient Setup(TouchSocketConfig config);
}
}

View File

@@ -1,29 +0,0 @@
<Project>
<PropertyGroup>
<Version>3.0.0.20</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,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,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);
}
}
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);
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
}
}
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);
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
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);
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);
}
}
}

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);
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);
}
}
}

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);
}
}
}
}
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);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
}
}
}
}
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);
}
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
}
}
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);
}
}
}
}
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);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
}
}
}
}
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);
}
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
}
}
/// <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);
}
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}"));
}
}
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}"));
}
}
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}"));
}
}
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}"));
}
}
}

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,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,59 +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.Logging;
namespace ThingsGateway.Plugin.OPCUA;
public partial class OPCUAServer
{
private class OPCUALogger : ILogger
{
private ILog _log;
public OPCUALogger(ILog log)
{
_log = log;
}
/// <summary>
/// Set the log level
/// </summary>
public Microsoft.Extensions.Logging.LogLevel LogLevel { get; set; } = Microsoft.Extensions.Logging.LogLevel.Trace;
/// <inheritdoc/>
public IDisposable BeginScope<TState>(TState state) => default;
/// <inheritdoc/>
public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) => logLevel >= LogLevel;
/// <inheritdoc/>
public void Log<TState>(
Microsoft.Extensions.Logging.LogLevel logLevel,
EventId eventId,
TState state,
Exception exception,
Func<TState, Exception, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
else
{
var message = formatter(state, exception);
_log.Log((Foundation.Core.LogLevel)(byte)logLevel, state, message, exception);
if (logLevel > Microsoft.Extensions.Logging.LogLevel.Information)
{
}
}
}
}
}

View File

@@ -1,58 +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 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 />
<MCheckbox Class="ma-1" Label=@node.DescriptionWithOutSugar(a=>a.LoadType) Dense HideDetails="@("auto")" @bind-Value=@node.LoadType />
<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,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 Furion;
using Mapster;
using Microsoft.Extensions.Hosting;
using SqlSugar;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using ThingsGateway.Foundation.Extension;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.QuestDB;
public class QuestDB : UpLoadBase
{
private readonly ConcurrentQueue<QuestDBHistoryValue> DeviceVariableRunTimes = new();
private readonly QuestDBProperty driverPropertys = new();
private readonly QuestDBVariableProperty variablePropertys = new();
private TypeAdapterConfig _config;
private GlobalDeviceData _globalDeviceData;
private List<DeviceVariableRunTime> _uploadVariables = new();
private TimerTick exTimerTick;
public QuestDB()
{
_config = new TypeAdapterConfig();
_config.ForType<DeviceVariableRunTime, HistoryValue>()
.Map(dest => dest.Value, (src) => ValueReturn(src))
.Map(dest => dest.CollectTime, (src) => src.CollectTime.ToUniversalTime())//注意sqlsugar插入时无时区直接utc时间
.Map(dest => dest.CreateTime, (src) => DateTime.UtcNow);//注意sqlsugar插入时无时区直接utc时间
}
private static object ValueReturn(DeviceVariableRunTime src)
{
if (src.Value?.ToString()?.IsBoolValue() == true)
{
if (src.Value.ToBoolean())
{
return 1;
}
else
{
return 0;
}
}
else
{
return src.Value;
}
}
public override Type DriverDebugUIType => null;
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
public override List<DeviceVariableRunTime> UploadVariables => _uploadVariables;
public override VariablePropertyBase VariablePropertys => variablePropertys;
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
SqlSugarClient db = GetHisDbAsync();
db.DbMaintenance.CreateDatabase();
db.CodeFirst.InitTables(typeof(QuestDBHistoryValue));
await Task.CompletedTask;
}
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var db = GetHisDbAsync();
{
if (!driverPropertys.IsInterval)
{
try
{
////变化推送
var varList = DeviceVariableRunTimes.ToListWithDequeue();
if (varList?.Count != 0)
{
await InserableAsync(db, varList, cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
else
{
if (exTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.ToList().Adapt<List<QuestDBHistoryValue>>(_config);
if (varList?.Count != 0)
{
await InserableAsync(db, varList, cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
}
public override bool IsConnected() => _uploadVariables?.Count > 0;
protected override void Dispose(bool disposing)
{
try
{
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
_uploadVariables = null;
}
catch (Exception ex)
{
LogMessage?.LogError(ex);
}
base.Dispose(disposing);
}
protected override void Init(UploadDeviceRunTime device)
{
_globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).ToBoolean())
.ToList();
_uploadVariables = tags;
if (!driverPropertys.IsInterval)
{
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
}
if (_uploadVariables.Count == 0)
{
LogMessage.LogWarning("插件变量数量为0");
}
if (driverPropertys.IntervalTime < 1)
driverPropertys.IntervalTime = 10;
exTimerTick = new(driverPropertys.IntervalTime * 1000);
}
/// <summary>
/// Aop设置
/// </summary>
/// <param name="db"></param>
private static void AopSetting(SqlSugarClient db)
{
var config = db.CurrentConnectionConfig;
// 设置超时时间
db.Ado.CommandTimeOut = 30;
// 打印SQL语句
db.Aop.OnLogExecuting = (sql, pars) =>
{
//如果不是开发环境就打印sql
if (App.HostEnvironment.IsDevelopment())
{
if (sql.StartsWith("SELECT"))
{
Console.ForegroundColor = ConsoleColor.Green;
}
if (sql.StartsWith("UPDATE"))
{
Console.ForegroundColor = ConsoleColor.Yellow;
}
if (sql.StartsWith("INSERT"))
{
Console.ForegroundColor = ConsoleColor.Blue;
}
if (sql.StartsWith("DELETE"))
{
Console.ForegroundColor = ConsoleColor.Red;
}
WriteSqlLog(UtilMethods.GetSqlString(config.DbType, sql, pars));
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine();
}
};
//异常
db.Aop.OnError = (ex) =>
{
//如果不是开发环境就打印日志
if (App.WebHostEnvironment.IsDevelopment())
{
if (ex.Parametres == null) return;
Console.ForegroundColor = ConsoleColor.Red;
var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
WriteSqlLogError(UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
Console.ForegroundColor = ConsoleColor.White;
}
};
}
private static void WriteSqlLog(string msg)
{
Console.WriteLine("【Sql执行时间】" + DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat());
Console.WriteLine("【Sql语句】" + msg + Environment.NewLine);
}
private static void WriteSqlLogError(string msg)
{
Console.WriteLine("【Sql执行错误时间】" + DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat());
Console.WriteLine("【Sql语句】" + msg + Environment.NewLine);
}
/// <summary>
/// 获取数据库链接
/// </summary>
/// <returns></returns>
private SqlSugarClient GetHisDbAsync()
{
var configureExternalServices = new ConfigureExternalServices
{
EntityService = (type, column) => // 修改列可空-1、带?问号 2、String类型若没有Required
{
if ((type.PropertyType.IsGenericType && type.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
|| (type.PropertyType == typeof(string) && type.GetCustomAttribute<RequiredAttribute>() == null))
column.IsNullable = true;
},
};
var sqlSugarClient = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = driverPropertys.ConnectStr,//连接字符串
DbType = DbType.QuestDB,//数据库类型
IsAutoCloseConnection = true, //不设成true要手动close
ConfigureExternalServices = configureExternalServices,
}
);
AopSetting(sqlSugarClient);//aop配置
return sqlSugarClient;
}
private async Task InserableAsync(SqlSugarClient db, List<QuestDBHistoryValue> dbInserts, CancellationToken cancellationToken)
{
try
{
var result = await db.Insertable(dbInserts).ExecuteCommandAsync(cancellationToken);
if (result > 0)
LogMessage.Trace(FoundationConst.LogMessageHeader + dbInserts.ToJsonString());
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData();
foreach (var item in cacheData)
{
try
{
var data = item.CacheStr.FromJsonString<List<QuestDBHistoryValue>>();
var cacheresult = await db.Insertable(data).ExecuteCommandAsync(cancellationToken);
if (cacheresult > 0)
{
await CacheDb.DeleteCacheData(item.Id);
LogMessage.Trace(FoundationConst.LogMessageHeader + $"主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex);
}
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex);
await CacheDb.AddCacheData("", dbInserts.ToJsonString(), driverPropertys.CacheMaxCount);
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (!driverPropertys.IsInterval)
DeviceVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<QuestDBHistoryValue>(_config));
}
}

View File

@@ -1,31 +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.QuestDB;
public class QuestDBProperty : UpDriverPropertyBase
{
[DeviceProperty("链接字符串", "")] public string ConnectStr { get; set; } = "host=localhost;port=8812;username=admin;password=quest;database=qdb;ServerCompatibilityMode=NoTypeLoading;";
[DeviceProperty("是否间隔插入", "False时将每次变化写入")] public bool IsInterval { get; set; } = true;
[DeviceProperty("间隔时间", "秒,实时表时代表更新间隔,历史表时代表插入间隔")] public int IntervalTime { get; set; } = 10;
[DeviceProperty("缓存最大条数", "默认2千条")] public int CacheMaxCount { get; set; } = 2000;
/// <summary>
/// 线程循环间隔
/// </summary>
[DeviceProperty("线程循环间隔", "最小10ms")]
public int CycleInterval { get; set; } = 1000;
}

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);
}
}
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);
}
}
}
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);
}
}
}
}
}
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);
}
}
}
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);
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
}
}
}
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);
}
}
}
}
}
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);
}
}
}
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);
}
}
}
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
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);
await CacheDb.AddCacheData(queueName, data, driverPropertys.CacheMaxCount);
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<VariableData>());
}
}

View File

@@ -1,334 +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.Hosting;
using SqlSugar;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.String;
using Yitter.IdGenerator;
namespace ThingsGateway.Plugin.SQLDB;
public class SQLDB : UpLoadBase
{
private readonly ConcurrentQueue<SQLHistoryValue> DeviceVariableRunTimes = new();
private readonly SQLDBProperty driverPropertys = new();
private readonly SQLDBVariableProperty variablePropertys = new();
private TypeAdapterConfig _config;
private GlobalDeviceData _globalDeviceData;
private List<DeviceVariableRunTime> _uploadVariables = new();
private TimerTick exTimerTick;
private TimerTick exRealTimerTick;
public SQLDB()
{
_config = new TypeAdapterConfig();
_config.ForType<DeviceVariableRunTime, SQLHistoryValue>()
.Map(dest => dest.Id, (src) => YitIdHelper.NextId())
.Map(dest => dest.CreateTime, (src) => DateTime.Now);
}
public override Type DriverDebugUIType => null;
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
public override List<DeviceVariableRunTime> UploadVariables => _uploadVariables;
public override VariablePropertyBase VariablePropertys => variablePropertys;
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
var db = GetHisDbAsync();
db.CodeFirst.InitTables(typeof(SQLHistoryValue));
db.MappingTables.Add("SQLRealValue", driverPropertys.ReadDBTableName); // typeof(类).Name 可以拿到类名
db.CodeFirst.InitTables(typeof(SQLRealValue)); //生成的表名是 newTableName
await Task.CompletedTask;
}
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var db = GetHisDbAsync();
if (driverPropertys.IsReadDB)
{
if (exRealTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.ToList().Adapt<List<SQLRealValue>>();
if (varList?.Count != 0)
{
//var result = await db.Storageable(varList).As(driverPropertys.ReadDBTableName).ExecuteCommandAsync(cancellationToken);
await db.Fastest<SQLRealValue>().AS(driverPropertys.ReadDBTableName).PageSize(100000).BulkUpdateAsync(varList);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
else
{
if (!driverPropertys.IsInterval)
{
try
{
////变化推送
var varList = DeviceVariableRunTimes.ToListWithDequeue();
if (varList?.Count != 0)
{
await InserableAsync(db, varList, cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
else
{
if (exTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.ToList().Adapt<List<SQLHistoryValue>>(_config);
if (varList?.Count != 0)
{
await InserableAsync(db, varList, cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
}
/// <summary>
/// 获取数据库链接
/// </summary>
/// <returns></returns>
public SqlSugarClient GetHisDbAsync()
{
var configureExternalServices = new ConfigureExternalServices
{
EntityService = (type, column) => // 修改列可空-1、带?问号 2、String类型若没有Required
{
if ((type.PropertyType.IsGenericType && type.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
|| (type.PropertyType == typeof(string) && type.GetCustomAttribute<RequiredAttribute>() == null))
column.IsNullable = true;
},
};
var sqlSugarClient = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = driverPropertys.ConnectStr,//连接字符串
DbType = driverPropertys.DbType,//数据库类型
IsAutoCloseConnection = true, //不设成true要手动close
ConfigureExternalServices = configureExternalServices,
}
);
AopSetting(sqlSugarClient);//aop配置
return sqlSugarClient;
}
public override bool IsConnected() => _uploadVariables?.Count > 0;
protected override void Dispose(bool disposing)
{
try
{
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
_uploadVariables = null;
}
catch (Exception ex)
{
LogMessage?.LogError(ex);
}
base.Dispose(disposing);
}
protected override void Init(UploadDeviceRunTime device)
{
_globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).ToBoolean())
.ToList();
_uploadVariables = tags;
if (!driverPropertys.IsReadDB)
if (!driverPropertys.IsInterval)
{
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
}
if (_uploadVariables.Count == 0)
{
LogMessage.LogWarning("插件变量数量为0");
}
if (driverPropertys.IntervalTime < 1)
driverPropertys.IntervalTime = 10;
exTimerTick = new(driverPropertys.IntervalTime * 1000);
exRealTimerTick = new(driverPropertys.IntervalTime * 1000);
}
/// <summary>
/// Aop设置
/// </summary>
/// <param name="db"></param>
private static void AopSetting(SqlSugarClient db)
{
var config = db.CurrentConnectionConfig;
// 设置超时时间
db.Ado.CommandTimeOut = 30;
// 打印SQL语句
db.Aop.OnLogExecuting = (sql, pars) =>
{
//如果不是开发环境就打印sql
if (App.HostEnvironment.IsDevelopment())
{
if (sql.StartsWith("SELECT"))
{
Console.ForegroundColor = ConsoleColor.Green;
}
if (sql.StartsWith("UPDATE"))
{
Console.ForegroundColor = ConsoleColor.Yellow;
}
if (sql.StartsWith("INSERT"))
{
Console.ForegroundColor = ConsoleColor.Blue;
}
if (sql.StartsWith("DELETE"))
{
Console.ForegroundColor = ConsoleColor.Red;
}
WriteSqlLog(UtilMethods.GetSqlString(config.DbType, sql, pars));
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine();
}
};
//异常
db.Aop.OnError = (ex) =>
{
//如果不是开发环境就打印日志
if (App.WebHostEnvironment.IsDevelopment())
{
if (ex.Parametres == null) return;
Console.ForegroundColor = ConsoleColor.Red;
var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
WriteSqlLogError(UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
Console.ForegroundColor = ConsoleColor.White;
}
};
}
private static void WriteSqlLog(string msg)
{
Console.WriteLine("【Sql执行时间】" + DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat());
Console.WriteLine("【Sql语句】" + msg + Environment.NewLine);
}
private static void WriteSqlLogError(string msg)
{
Console.WriteLine("【Sql执行错误时间】" + DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat());
Console.WriteLine("【Sql语句】" + msg + Environment.NewLine);
}
private async Task InserableAsync(SqlSugarClient db, List<SQLHistoryValue> dbInserts, CancellationToken cancellationToken)
{
try
{
var result = await db.Insertable(dbInserts).SplitTable().ExecuteCommandAsync();
if (result > 0)
LogMessage.Trace(FoundationConst.LogMessageHeader + dbInserts.ToJsonString());
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData();
foreach (var item in cacheData)
{
try
{
var data = item.CacheStr.FromJsonString<List<SQLHistoryValue>>();
var cacheresult = await db.Insertable(data).SplitTable().ExecuteCommandAsync();
if (cacheresult > 0)
{
await CacheDb.DeleteCacheData(item.Id);
LogMessage.Trace(FoundationConst.LogMessageHeader + $"主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex);
}
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex);
await CacheDb.AddCacheData("", dbInserts.ToJsonString(), driverPropertys.CacheMaxCount);
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (!driverPropertys.IsReadDB)
if (!driverPropertys.IsInterval)
DeviceVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<SQLHistoryValue>(_config));
}
}

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,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,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_400DebugPage
{
/// <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.S400);
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,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

@@ -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 Furion;
using Mapster;
using Microsoft.Extensions.Hosting;
using SqlSugar;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using ThingsGateway.Foundation.Extension;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.SQLDB;
public class TDengineDB : UpLoadBase
{
private readonly ConcurrentQueue<TDHistoryValue> DeviceVariableRunTimes = new();
private readonly TDengineDBProperty driverPropertys = new();
private readonly TDengineDBVariableProperty variablePropertys = new();
private GlobalDeviceData _globalDeviceData;
private TypeAdapterConfig _config;
private List<DeviceVariableRunTime> _uploadVariables = new();
private TimerTick exTimerTick;
public TDengineDB()
{
_config = new TypeAdapterConfig();
_config.ForType<DeviceVariableRunTime, HistoryValue>()
.Map(dest => dest.Value, (src) => ValueReturn(src));
}
private static object ValueReturn(DeviceVariableRunTime src)
{
if (src.Value?.ToString()?.IsBoolValue() == true)
{
if (src.Value.ToBoolean())
{
return 1;
}
else
{
return 0;
}
}
else
{
return src.Value;
}
}
public override Type DriverDebugUIType => null;
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
public override List<DeviceVariableRunTime> UploadVariables => _uploadVariables;
public override VariablePropertyBase VariablePropertys => variablePropertys;
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
SqlSugarClient db = GetHisDbAsync();
db.DbMaintenance.CreateDatabase();
db.CodeFirst.InitTables(typeof(TDHistoryValue));
await Task.CompletedTask;
}
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var db = GetHisDbAsync();
{
if (!driverPropertys.IsInterval)
{
try
{
////变化推送
var varList = DeviceVariableRunTimes.ToListWithDequeue();
if (varList?.Count != 0)
{
await InserableAsync(db, varList, cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
else
{
if (exTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.ToList().Adapt<List<TDHistoryValue>>(_config);
if (varList?.Count != 0)
{
await InserableAsync(db, varList, cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex);
}
}
}
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
}
public override bool IsConnected() => _uploadVariables?.Count > 0;
protected override void Dispose(bool disposing)
{
try
{
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
_uploadVariables = null;
}
catch (Exception ex)
{
LogMessage?.LogError(ex);
}
base.Dispose(disposing);
}
protected override void Init(UploadDeviceRunTime device)
{
_globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).ToBoolean())
.ToList();
_uploadVariables = tags;
if (!driverPropertys.IsInterval)
{
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
}
if (_uploadVariables.Count == 0)
{
LogMessage.LogWarning("插件变量数量为0");
}
if (driverPropertys.IntervalTime < 1)
driverPropertys.IntervalTime = 10;
exTimerTick = new(driverPropertys.IntervalTime * 1000);
}
/// <summary>
/// Aop设置
/// </summary>
/// <param name="db"></param>
private static void AopSetting(SqlSugarClient db)
{
var config = db.CurrentConnectionConfig;
// 设置超时时间
db.Ado.CommandTimeOut = 30;
// 打印SQL语句
db.Aop.OnLogExecuting = (sql, pars) =>
{
//如果不是开发环境就打印sql
if (App.HostEnvironment.IsDevelopment())
{
if (sql.StartsWith("SELECT"))
{
Console.ForegroundColor = ConsoleColor.Green;
}
if (sql.StartsWith("UPDATE"))
{
Console.ForegroundColor = ConsoleColor.Yellow;
}
if (sql.StartsWith("INSERT"))
{
Console.ForegroundColor = ConsoleColor.Blue;
}
if (sql.StartsWith("DELETE"))
{
Console.ForegroundColor = ConsoleColor.Red;
}
WriteSqlLog(UtilMethods.GetSqlString(config.DbType, sql, pars));
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine();
}
};
//异常
db.Aop.OnError = (ex) =>
{
//如果不是开发环境就打印日志
if (App.WebHostEnvironment.IsDevelopment())
{
if (ex.Parametres == null) return;
Console.ForegroundColor = ConsoleColor.Red;
var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
WriteSqlLogError(UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
Console.ForegroundColor = ConsoleColor.White;
}
};
}
private static void WriteSqlLog(string msg)
{
Console.WriteLine("【Sql执行时间】" + DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat());
Console.WriteLine("【Sql语句】" + msg + Environment.NewLine);
}
private static void WriteSqlLogError(string msg)
{
Console.WriteLine("【Sql执行错误时间】" + DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat());
Console.WriteLine("【Sql语句】" + msg + Environment.NewLine);
}
/// <summary>
/// 获取数据库链接
/// </summary>
/// <returns></returns>
private SqlSugarClient GetHisDbAsync()
{
var configureExternalServices = new ConfigureExternalServices
{
EntityService = (type, column) => // 修改列可空-1、带?问号 2、String类型若没有Required
{
if ((type.PropertyType.IsGenericType && type.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
|| (type.PropertyType == typeof(string) && type.GetCustomAttribute<RequiredAttribute>() == null))
column.IsNullable = true;
},
};
var sqlSugarClient = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = driverPropertys.ConnectStr,//连接字符串
DbType = DbType.TDengine,//数据库类型
IsAutoCloseConnection = true, //不设成true要手动close
ConfigureExternalServices = configureExternalServices,
}
);
AopSetting(sqlSugarClient);//aop配置
return sqlSugarClient;
}
private async Task InserableAsync(SqlSugarClient db, List<TDHistoryValue> dbInserts, CancellationToken cancellationToken)
{
try
{
var result = await db.Insertable(dbInserts).ExecuteCommandAsync(cancellationToken);
if (result > 0)
LogMessage.Trace(FoundationConst.LogMessageHeader + dbInserts.ToJsonString());
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData();
foreach (var item in cacheData)
{
try
{
var data = item.CacheStr.FromJsonString<List<TDHistoryValue>>();
var cacheresult = await db.Insertable(data).ExecuteCommandAsync(cancellationToken);
if (cacheresult > 0)
{
await CacheDb.DeleteCacheData(item.Id);
LogMessage.Trace(FoundationConst.LogMessageHeader + $"主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex);
}
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex);
await CacheDb.AddCacheData("", dbInserts.ToJsonString(), driverPropertys.CacheMaxCount);
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (!driverPropertys.IsInterval)
DeviceVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<TDHistoryValue>(_config));
}
}

View File

@@ -1,32 +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.SQLDB;
public class TDengineDBProperty : UpDriverPropertyBase
{
[DeviceProperty("链接字符串", "")] public string ConnectStr { get; set; } = "Host=localhost;Port=6030;Username=root;Password=taosdata;Database=test";
[DeviceProperty("是否间隔插入", "False时将每次变化写入")] public bool IsInterval { get; set; } = true;
[DeviceProperty("间隔时间", "秒,实时表时代表更新间隔,历史表时代表插入间隔")] public int IntervalTime { get; set; } = 10;
[DeviceProperty("缓存最大条数", "默认2千条")] public int CacheMaxCount { get; set; } = 2000;
/// <summary>
/// 线程循环间隔
/// </summary>
[DeviceProperty("线程循环间隔", "最小10ms")]
public int CycleInterval { get; set; } = 1000;
}

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,108 @@ 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
Directory.Build.props = Directory.Build.props
..\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("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.ApiController", "Web\ThingsGateway.Gateway.ApiController\ThingsGateway.Gateway.ApiController.csproj", "{5D7BE567-2345-46C8-9F54-DDC1DA96D198}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OPCUA", "plugin\ThingsGateway.Plugin.OPCUA\ThingsGateway.Plugin.OPCUA.csproj", "{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}"
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}") = "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}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.SQLDB", "Plugin\ThingsGateway.Plugin.SQLDB\ThingsGateway.Plugin.SQLDB.csproj", "{7EBD5500-0DA0-415A-831D-5DC350917501}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.QuestDB", "Plugin\ThingsGateway.Plugin.QuestDB\ThingsGateway.Plugin.QuestDB.csproj", "{A99787D7-A93B-4357-A8B5-B5F1FD2930AB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.TDengineDB", "Plugin\ThingsGateway.Plugin.TDengineDB\ThingsGateway.Plugin.TDengineDB.csproj", "{2C827B2C-75DF-413B-9AB2-2D1B438AC082}"
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,114 +136,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
{7EBD5500-0DA0-415A-831D-5DC350917501}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EBD5500-0DA0-415A-831D-5DC350917501}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EBD5500-0DA0-415A-831D-5DC350917501}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EBD5500-0DA0-415A-831D-5DC350917501}.Release|Any CPU.Build.0 = Release|Any CPU
{A99787D7-A93B-4357-A8B5-B5F1FD2930AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A99787D7-A93B-4357-A8B5-B5F1FD2930AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A99787D7-A93B-4357-A8B5-B5F1FD2930AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A99787D7-A93B-4357-A8B5-B5F1FD2930AB}.Release|Any CPU.Build.0 = Release|Any CPU
{2C827B2C-75DF-413B-9AB2-2D1B438AC082}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C827B2C-75DF-413B-9AB2-2D1B438AC082}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C827B2C-75DF-413B-9AB2-2D1B438AC082}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C827B2C-75DF-413B-9AB2-2D1B438AC082}.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
@@ -254,33 +255,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} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{616CA361-B667-42C8-B4DC-097C7CD39830} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{16C62A28-BACE-4391-91F8-C2D78D063A1E} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{8FA03089-322F-44CB-8E4B-F2637388E944} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{14FF7150-6DB7-455B-AD00-6AB4DE37855B} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{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} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{5D7BE567-2345-46C8-9F54-DDC1DA96D198} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{5CF1B3EC-84E2-484A-8DFC-2ECD2EE18E2F} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{CD0F211A-F65B-4026-9750-68AC3C70D012} = {9EB46BB6-D4EA-4B06-95EE-6C971E653030}
{5CD79F91-7182-4A9D-9BEF-4DF410C782D2} = {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}
{7EBD5500-0DA0-415A-831D-5DC350917501} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{A99787D7-A93B-4357-A8B5-B5F1FD2930AB} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{2C827B2C-75DF-413B-9AB2-2D1B438AC082} = {CC8D0880-B73E-4DFC-9052-86504728708E}
{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.20</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-"
}
}
}

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