Compare commits

...

175 Commits

Author SHA1 Message Date
Kimdiego2098
a64ab7df4e 更新版本号 2023-11-24 14:48:53 +08:00
Kimdiego2098
82cd64cb50 10功能码写入时 修改需判断的crc长度 2023-11-24 14:48:28 +08:00
Kimdiego2098
065bfb8694 修复 modbusTcpDtu 初始化 空指针错误 2023-11-24 09:44:47 +08:00
Kimdiego2098
6db335cf87 OPCUA插件afterStop方法重写时需执行父类方法 2023-11-23 20:51:08 +08:00
Kimdiego2098
155f4670e9 调整网关状态页面 2023-11-23 20:49:35 +08:00
Kimdiego2098
50522b571a 修改内存缓存mapster选项 2023-11-23 15:22:39 +08:00
Kimdiego2098
8e138863ce 添加kafka的SecurityProtocol与SaslMechanism参数说明 2023-11-22 21:29:08 +08:00
Kimdiego2098
7d8dfe628d 修复上个提交导致的excel导入产生空指针错误 2023-11-22 20:52:58 +08:00
Kimdiego2098
8baed5b306 excel导入导出设备表时,去除多余的字段 2023-11-22 16:09:41 +08:00
Kimdiego2098
41a5ffd214 socktClient重载toString 2023-11-22 15:28:04 +08:00
Kimdiego2098
c6aec3a1af 更新版本号 2023-11-22 14:06:52 +08:00
Kimdiego2098
22e30f7a62 代码文件编码更改 2023-11-22 14:02:41 +08:00
Kimdiego2098
57711b8ab5 修复变量上传属性在编辑页面不显示的问题 2023-11-22 13:35:44 +08:00
Kimdiego2098
90ff1259ea 修复变量上传属性在编辑页面不显示的问题 2023-11-22 13:30:42 +08:00
Kimdiego2098
d88fc5ccd7 去除不存在的菜单 2023-11-21 18:19:14 +08:00
Kimdiego2098
5aaca2aa9c 调整循环延时时间限值 2023-11-21 16:27:11 +08:00
Kimdiego2098
8b9ca56e17 调试mqtt依赖 2023-11-21 15:07:07 +08:00
Kimdiego2098
e4f3772e6d 去除上传间隔1s限制 2023-11-21 11:46:33 +08:00
Kimdiego2098
d58ec81d20 整理代码 2023-11-21 11:41:44 +08:00
Kimdiego2098
415aae44b6 更新依赖 2023-11-21 08:44:47 +08:00
Kimdiego2098
a533286658 更新版本号 2023-11-20 23:05:12 +08:00
Kimdiego2098
e59f91cd82 去除treeview 2023-11-20 23:04:54 +08:00
Kimdiego2098
5f8b85d8a4 去除treeview显示 2023-11-20 22:53:34 +08:00
Kimdiego2098
47c7b88436 更新版本号 2023-11-20 22:47:18 +08:00
Kimdiego2098
90006782f2 mqttserver/client插件支持websocket通道,直接对接前端 2023-11-20 22:42:08 +08:00
Kimdiego2098
c3d49cbe70 mqttserver/client插件支持websocket通道,直接对接前端 2023-11-20 22:33:26 +08:00
Kimdiego2098
112323a360 modbusTcpServer最大连接数设为3w 2023-11-20 19:46:07 +08:00
Kimdiego2098
9d08c90fda 更新依赖 2023-11-20 17:35:42 +08:00
Kimdiego2098
602d24deec 添加admin-解决方案 2023-11-20 15:38:33 +08:00
Kimdiego2098
a2b9f66785 修复设备curd服务aop失效的问题 2023-11-19 23:30:11 +08:00
Kimdiego2098
7cbf289b50 更新版本号 2023-11-19 22:32:53 +08:00
Kimdiego2098
4097da79a5 modbus server 添加是否立即写入内存的选项 2023-11-19 22:32:13 +08:00
Kimdiego2098
91b7ae554f 默认开启多标签 2023-11-19 22:31:47 +08:00
Kimdiego2098
3121aa2542 添加历史报警插件 2023-11-19 22:19:05 +08:00
Kimdiego2098
4bf895e6e1 修复4.0代码 s7协议未设置适配器导致初始化/读写失败的问题 2023-11-19 21:49:32 +08:00
Kimdiego2098
0c5489e920 增加上传插件 缓存基类 2023-11-19 15:20:01 +08:00
Kimdiego2098
d63c3aaa80 获取插件继承属性时,去除不重写特性的属性 2023-11-19 14:15:58 +08:00
Kimdiego2098
4f188ea6cc 整理文件 2023-11-18 23:04:51 +08:00
Kimdiego2098
acb17018ae 整理文件 2023-11-18 23:04:25 +08:00
Kimdiego2098
2affe2988d 整理文件 2023-11-18 23:03:24 +08:00
Kimdiego2098
4174dd2206 整理文件 2023-11-18 23:03:02 +08:00
Kimdiego2098
e1c492f238 整理文件 2023-11-18 23:02:28 +08:00
Kimdiego2098
fb08e34fa3 整理文件 2023-11-18 23:01:56 +08:00
Kimdiego2098
a1793a0afe 去除不必要的文件 2023-11-18 22:52:26 +08:00
Kimdiego2098
4da9763b49 去除不必要的文件 2023-11-18 22:50:03 +08:00
Kimdiego2098
81e0918bd0 迁移4.0 2023-11-18 22:45:24 +08:00
Kimdiego2098
c1e064f06d 迁移4.0 2023-11-18 22:43:36 +08:00
Kimdiego2098
1c52be8b47 添加停止线程等待时间 2023-11-16 22:32:22 +08:00
Kimdiego2098
bcd82055ca s7握手失败后,手动关闭连接 2023-11-11 10:26:05 +08:00
Kimdiego2098
c47d95d170 fix:修复线程阻塞检测触发重启时,后台变量列表不再刷新的问题! 2023-11-10 09:00:50 +08:00
Kimdiego2098
3e62f1ad51 历史数据上传成功后,才上传缓存数据 2023-11-09 18:55:56 +08:00
Kimdiego2098
8dcae973ef update 2023-11-08 16:19:46 +08:00
Kimdiego2098
4cf35f7294 发布3.0.1版本 2023-11-03 11:32:13 +08:00
Kimdiego2098
94c77d151b update touchsocket 2023-11-03 11:27:12 +08:00
Kimdiego2098
7f600e2b4b update touchsocket 2023-11-03 11:19:26 +08:00
Kimdiego2098
c809d0ba87 不存在插件时,报错内容优化 2023-11-01 14:51:08 +08:00
Kimdiego2098
50f038ec89 update webapiClient 2023-11-01 14:21:53 +08:00
Kimdiego2098
9199a255a2 调整Timeout属性为int数据类型 2023-10-31 23:49:46 +08:00
Kimdiego2098
d324537b47 更新发布版3.0.0.28 2023-10-31 17:47:07 +08:00
Kimdiego2098
d0c05685f7 更新OPCUAClient,订阅模式适配 分组 2023-10-31 10:55:50 +08:00
Kimdiego2098
1063c930b5 update 2023-10-31 00:24:00 +08:00
Kimdiego2098
79cbd44366 tcpservice停止时执行shutdown方法,修复demo发布不显示页面的问题 2023-10-30 21:31:30 +08:00
Kimdiego2098
7fdac1c5cb 添加部分Pro内容 2023-10-29 19:39:38 +08:00
Kimdiego2098
0c0cf72ebb 添加部分Pro内容 2023-10-29 19:34:17 +08:00
Kimdiego2098
8e2fe175ed 更新文档 2023-10-28 22:06:58 +08:00
Kimdiego2098
d1cff037c9 发布3.0.0.27版本;
优化设备线程启停逻辑
添加winform(blazor) demo
部分页面显示内容优化
2023-10-28 22:03:52 +08:00
Kimdiego2098
fc88a2fafa 发布3.0.0.27版本;
优化设备线程启停逻辑
添加winform(blazor) demo
部分页面显示内容优化
2023-10-28 22:00:35 +08:00
Kimdiego2098
45fcceb056 优化设备线程启停逻辑 2023-10-28 21:58:09 +08:00
Kimdiego2098
7043477038 添加部分Pro内容 2023-10-28 21:21:03 +08:00
Kimdiego2098
7dd685cf54 添加winform(blazor) demo 2023-10-28 15:20:12 +08:00
Kimdiego2098
5f5e4969c0 调整pro类库 2023-10-28 10:54:26 +08:00
Diego2098
8a53fd19e9 设备状态页面显示优化 2023-10-27 20:19:26 +08:00
Diego2098
baf4714c36 状态显示:已退出自动更新 2023-10-27 20:18:57 +08:00
Kimdiego2098
7ba9ac7a5b 报文显示限长500 2023-10-27 14:53:19 +08:00
Kimdiego2098
85b8f26e8e tcpserver 报文输出 添加 ip端口 提示 2023-10-27 14:41:35 +08:00
Kimdiego2098
594a0f1410 update the tcpserver class and add log output for start and stop 2023-10-27 14:24:26 +08:00
Kimdiego2098
d317d757d7 优化线程上下文转换 2023-10-26 19:16:24 +08:00
Kimdiego2098
fdf0ba6318 添加ConfigureAwait 2023-10-26 18:06:33 +08:00
Kimdiego2098
15bf7de5fa 优化设备导出逻辑 2023-10-26 15:15:43 +08:00
Kimdiego2098
d3402b058e 优化设备导出逻辑 2023-10-26 15:10:26 +08:00
Kimdiego2098
e7dfdd4031 3.0.0.25 2023-10-26 13:21:40 +08:00
Kimdiego2098
b2dd7b6364 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-10-26 13:20:54 +08:00
Kimdiego2098
9bd6d9abbf 3.0.0.25 2023-10-26 13:20:31 +08:00
Kimdiego2098
cd14428fea update 2023-10-26 13:19:18 +08:00
Kimdiego2098
19d9f03c2b s7添加错误返回码提示,组包处理 2023-10-26 13:05:06 +08:00
Kimdiego2098
0d57e72bbf 增加硬件信息 相关json配置 2023-10-26 10:54:48 +08:00
Kimdiego2098
329516a61b 更新nuget依赖 2023-10-26 09:37:01 +08:00
Kimdiego2098
d566869589 硬件信息页面添加刷新条件 2023-10-26 09:20:25 +08:00
Kimdiego2098
9cb8d8e6c7 更新文档 2023-10-25 00:53:27 +08:00
Kimdiego2098
9de3c57e5d update touchsocket 2023-10-25 00:53:17 +08:00
Kimdiego2098
f32ff92b0b <Version>3.0.0.24</Version> 2023-10-24 23:48:20 +08:00
Kimdiego2098
88d71e271e 更改S7协议 设备属性,注意删除了DstTSAP,改为较直观的 机架号/槽位号 2023-10-24 23:47:35 +08:00
Kimdiego2098
fd9c14612a 添加属性识别 16进制写入 2023-10-24 23:46:50 +08:00
Kimdiego2098
e26e5a160f 添加nuget依赖包 2023-10-24 20:50:39 +08:00
Kimdiego2098
b836bfed22 更新nuget包 2023-10-24 00:37:46 +08:00
Kimdiego2098
a4b598c6d0 调整解决方案文件夹 2023-10-24 00:13:03 +08:00
Kimdiego2098
c9ab755839 暂时屏蔽mqttserver 遗留消息错误 2023-10-23 20:51:11 +08:00
Kimdiego2098
9920edba53 调整编码 2023-10-23 20:47:00 +08:00
Kimdiego2098
12bd7280d1 调整mqttlog 2023-10-23 20:46:17 +08:00
Kimdiego2098
d30ea7f63b 调整mqttlog 2023-10-23 20:43:58 +08:00
Kimdiego2098
ebd3390db6 添加部分兼容方法 2023-10-22 02:42:16 +08:00
Kimdiego2098
9a374a9ebc 添加部分兼容方法 2023-10-22 02:26:18 +08:00
Kimdiego2098
b1bc22cb08 update touchsocket 2023-10-22 02:26:04 +08:00
Kimdiego2098
4930d53890 调整代码格式 2023-10-21 19:15:26 +08:00
Kimdiego2098
c31327b5bc update touchsocket 2023-10-21 19:08:21 +08:00
Kimdiego2098
3f2aa1f1e1 调整代码格式 2023-10-21 19:03:15 +08:00
Kimdiego2098
6e78c00a96 调整代码格式 2023-10-21 19:02:58 +08:00
Kimdiego2098
c27dde085e 3.0.0.23 2023-10-20 21:38:22 +08:00
Kimdiego2098
d26cc308c0 优化SQLDB实时表模式,插入/更新 2023-10-20 21:38:07 +08:00
Kimdiego2098
fb1efdf290 sqlsugar提示默认中文 2023-10-20 21:37:42 +08:00
Kimdiego2098
3c99f2a472 update touchsocket 2023-10-20 21:03:29 +08:00
Kimdiego2098
affe9a44e0 优化 ModbusServer 内存占用 2023-10-20 01:53:48 +08:00
Kimdiego2098
43730fa519 3.0.0.21 2023-10-20 01:19:18 +08:00
Kimdiego2098
d39aa22b09 优化OPCUAServer,取消注册,提供多url写入 2023-10-20 01:19:05 +08:00
Kimdiego2098
e232a6b6ea 更新赞助名单 2023-10-19 21:15:35 +08:00
Kimdiego2098
71ebb36fe9 更新文档 2023-10-19 20:36:28 +08:00
Kimdiego2098
78a0b86327 更新版本:3.0.0.20 2023-10-19 20:27:31 +08:00
Kimdiego2098
2636c16a97 优化modbusServer内存管理 2023-10-19 20:24:39 +08:00
Kimdiego2098
fd77c0242d update touchsocket 2023-10-19 20:23:43 +08:00
Kimdiego2098
e74819a900 update toucksocket 2023-10-18 21:51:49 +08:00
Kimdiego2098
9b7f696c9b 更新文档 2023-10-18 20:42:10 +08:00
Kimdiego2098
0230d614e7 发布驱动包 2023-10-18 18:04:37 +08:00
Diego2098
252d99ad78 !12 【轻量级 PR】:修正心跳事件中的参数
Merge pull request !12 from youthalan/N/A
2023-10-18 06:59:17 +00:00
youthalan
1ffc200350 修正心跳事件中的参数
Signed-off-by: youthalan <youthalan@126.com>
2023-10-18 06:58:03 +00:00
Kimdiego2098
807d89b2b2 更新版本号 2023-10-18 13:13:03 +08:00
Kimdiego2098
4013afa1f1 初始化 采集/上传线程时 直接返回线程控制 2023-10-18 13:11:59 +08:00
Kimdiego2098
a580927ceb 更新OPCUAClient类库 2023-10-18 13:09:25 +08:00
Kimdiego2098
bf2cf52034 更新OPCUAClient类库 2023-10-18 12:45:26 +08:00
Kimdiego2098
81bb8b7c31 更新OPCUAClient类库 2023-10-18 12:44:58 +08:00
Kimdiego2098
a825007fb5 更新版本号与nuget发布 2023-10-18 12:39:42 +08:00
Kimdiego2098
988124d96a 更新OPCUAClient类库 2023-10-18 12:38:20 +08:00
Diego2098
f0de815296 !11 补充OPCClient类库事件的缺失文件
Merge pull request !11 from youthalan/N/A
2023-10-18 04:34:34 +00:00
youthalan
0e2d58c887 补充OPCClient类库事件的缺失文件
Signed-off-by: youthalan <youthalan@126.com>
2023-10-18 04:32:39 +00:00
Diego2098
b155382626 !10 添加连接或断开事件
Merge pull request !10 from youthalan/N/A
2023-10-18 04:20:22 +00:00
youthalan
f362d740af 修改OPCUAClient类添加连接或断开事件,修改注入时不需要带参数
Signed-off-by: youthalan <youthalan@126.com>
2023-10-18 03:48:05 +00:00
Kimdiego2098
4a85e31a4f update 3.0.0.16 2023-10-18 00:38:36 +08:00
Kimdiego2098
302c270ad5 opcuaClient浏览空间 添加是否显示子变量的选项 2023-10-18 00:36:44 +08:00
Kimdiego2098
3c1517d0f3 更改日志输出内容 2023-10-18 00:15:07 +08:00
Kimdiego2098
f9fb222044 update 3.0.0.15 2023-10-18 00:07:24 +08:00
Kimdiego2098
e8edc02ba3 增加不支持单文件发布的说明 2023-10-17 23:47:24 +08:00
Kimdiego2098
95a44e3053 update tdengineDB plugin 2023-10-17 23:43:48 +08:00
Kimdiego2098
74a9fe9a87 update touchsocket 2023-10-17 23:12:19 +08:00
Kimdiego2098
4d03f9ea1a TD时序库插件,创建时间更改为主键 2023-10-17 23:08:09 +08:00
Kimdiego2098
67c96ca991 update touchsocket 2023-10-17 23:06:21 +08:00
Kimdiego2098
88fb793c68 更新nuget包 2023-10-17 21:00:50 +08:00
Kimdiego2098
d6d02d8cc5 update SQLDB 2023-10-16 20:50:10 +08:00
Kimdiego2098
c5a3f8e2e3 update touchsocket and other 2023-10-16 20:36:51 +08:00
Kimdiego2098
27e8653a1a 3.0.0.13 2023-10-16 17:44:09 +08:00
Kimdiego2098
863beda82c 增加关系库存储插件; 2023-10-16 17:40:17 +08:00
Kimdiego2098
bac84c3ecd 增加时序库存储插件; 2023-10-16 17:40:13 +08:00
Kimdiego2098
2fca2ad9f8 更新pro用户列表 2023-10-16 17:39:14 +08:00
Kimdiego2098
dd75286fe0 3.0.0.12 2023-10-16 08:47:39 +08:00
Kimdiego2098
7f91792cf1 opcuaclient添加是否加载服务端数据类型的选项 2023-10-16 08:46:46 +08:00
Kimdiego2098
0e0ccad311 fix:tcpservice dispose err 2023-10-16 08:46:32 +08:00
Diego2098
0691f72e67 !9 增加可选择安全订阅
Merge pull request !9 from youthalan/N/A
2023-10-16 00:33:19 +00:00
youthalan
7e38a51720 增加可选择安全订阅,以加快订阅速度
Signed-off-by: youthalan <youthalan@126.com>
2023-10-16 00:26:59 +00:00
Kimdiego2098
34ca8243a3 更新3.0.0.11 2023-10-15 20:26:18 +08:00
Diego2098
112fea7632 读取数据类型方法改为批量 2023-10-15 20:21:23 +08:00
Kimdiego2098
378763e4ee 同步Pro版本 2023-10-13 20:14:35 +08:00
Kimdiego2098
517bd0394d update touchsocket 2023-10-13 19:16:12 +08:00
Kimdiego2098
70adb97fb5 update nuget 2023-10-13 16:14:42 +08:00
Kimdiego2098
623d44cabe update 3.0.0.7 2023-10-13 11:54:27 +08:00
Kimdiego2098
0d479ca00b 添加三菱mc 3e帧二进制通讯协议文档 2023-10-13 11:51:51 +08:00
Kimdiego2098
8bc49ef437 update demo 2023-10-12 18:52:44 +08:00
Kimdiego2098
f83fcec786 参数名称修改 2023-10-12 14:57:58 +08:00
Kimdiego2098
93690ce40d fix:mqtt保留消息未更新/更新错误 2023-10-12 14:57:36 +08:00
Kimdiego2098
f82c5f2f27 3.0.0.6 2023-10-11 16:35:10 +08:00
Kimdiego2098
a83c1c3899 update nuget 2023-10-11 16:28:18 +08:00
Kimdiego2098
91d6aed109 调整代码执行顺序 2023-10-11 16:19:34 +08:00
Kimdiego2098
db8f8fe51d update ManageGateway 2023-10-11 10:59:33 +08:00
Kimdiego2098
4596004b17 update ManageGateway 2023-10-11 10:41:09 +08:00
Kimdiego2098
d5540906cb update 3.0.0.5 2023-10-10 21:09:34 +08:00
Kimdiego2098
90796a979d fix:modbusRtu写入返回报文缓存逻辑修复 2023-10-10 21:08:42 +08:00
Kimdiego2098
2190a87772 update touchsocket 2023-10-10 20:03:40 +08:00
Kimdiego2098
c5953b83f8 update touchsocket 2023-10-10 20:02:15 +08:00
1807 changed files with 50379 additions and 42707 deletions

2
.gitignore vendored
View File

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

View File

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

View File

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

364
framework/.gitignore vendored
View File

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

View File

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

View File

@@ -1,481 +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.Generic;
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,481 +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.Generic;
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,442 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.DLT645</name>
</assembly>
<members>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DataInfo">
<summary>
解析参数
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.ByteLength">
<summary>
解析长度
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.Digtal">
<summary>
小数位
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.IsSigned">
<summary>
有符号解析
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDataInfos(System.Byte[])">
<summary>
获取返回的解析信息
</summary>
<param name="buffer"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDLT645_2007Command(System.String,System.Int32,System.Byte,System.String,System.Byte[],System.String[])">
<summary>
获取DLT645报文
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.#ctor(ThingsGateway.Foundation.Serial.SerialSession)">
<summary>
DLT645_2007
</summary>
<param name="serialSession"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.EnableFEHead">
<summary>
增加FE FE FE FE的报文头部
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.OperCode">
<summary>
写入需操作员代码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Password">
<summary>
写入密码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Station">
<summary>
通讯地址BCD码一般应该是12个字符
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.GetAddressDescription">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.SetDataAdapter">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
<summary>
广播校时
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
<summary>
冻结
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadDeviceStationAsync(System.Threading.CancellationToken)">
<summary>
读取通信地址
</summary>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
<summary>
修改波特率
</summary>
<param name="baudRate"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
<summary>
更新通信地址
</summary>
<param name="station"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
<summary>
修改密码
</summary>
<param name="level"></param>
<param name="oldPassword"></param>
<param name="newPassword"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.ControlCode">
<summary>
控制码
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Read">
<summary>
读数据
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadSub">
<summary>
读后续数据
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadStation">
<summary>
读站号
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Write">
<summary>
写数据
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteStation">
<summary>
写站号
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.BroadcastTime">
<summary>
广播校时
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Freeze">
<summary>
冻结
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteBaudRate">
<summary>
更新波特率
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WritePassword">
<summary>
更新密码
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address">
<summary>
DLT645_2007Address
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.UInt16)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.Byte[])">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.DataId">
<summary>
数据标识
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Reverse">
<summary>
反转解析
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Station">
<summary>
站号信息
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Parse(System.String,System.Int32)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ParseFrom(System.String,System.Int32)">
<summary>
解析地址
</summary>
<param name="address"></param>
<param name="length"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ToString">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.#ctor(ThingsGateway.Foundation.EndianType)">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToDouble(System.Byte[],System.Int32)">
<summary>
DLT645协议转换double
</summary>
<param name="buffer">带数据项标识</param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[],System.Int32,System.Int32)">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter">
<summary>
DLT645_2007DataHandleAdapter
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.EnableFEHead">
<summary>
增加FE FE FE FE的报文头部
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.PackCommand(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.GetInstance">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message,System.Byte[],System.Byte[],System.Byte[])">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.#ctor(ThingsGateway.Foundation.TcpClient)">
<summary>
DLT645_2007
</summary>
<param name="tcpClient"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.EnableFEHead">
<summary>
增加FE FE FE FE的报文头部
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.OperCode">
<summary>
写入需操作员代码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Password">
<summary>
写入密码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Station">
<summary>
通讯地址BCD码一般应该是12个字符
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.GetAddressDescription">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.SetDataAdapter">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
<summary>
广播校时
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
<summary>
冻结
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadDeviceStationAsync(System.Threading.CancellationToken)">
<summary>
读取通信地址
</summary>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
<summary>
修改波特率
</summary>
<param name="baudRate"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
<summary>
更新通信地址
</summary>
<param name="station"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
<summary>
修改密码
</summary>
<param name="level"></param>
<param name="oldPassword"></param>
<param name="newPassword"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.HeadBytesLength">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.CheckHeadBytes(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.SendBytesThen">
<inheritdoc/>
</member>
</members>
</doc>

View File

@@ -1,421 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections.Concurrent;
using System.Collections.Generic;
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, 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 void Received(ByteBlock byteBlock, IRequestInfo requestInfo)
{
try
{
//接收外部报文
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 ((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 ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(SerialSession, modbusServerMessage);
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
else
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(SerialSession, modbusServerMessage);
}
else
{
WriteError(SerialSession, modbusServerMessage);
}
}
}
}
}
}
catch (Exception ex)
{
Logger.LogError(ex, ToString());
}
//返回错误码
static void WriteError(SerialSession SerialSession, ModbusSerialServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 2)
.SpliceArray(new byte[] { (byte)1 });//01 lllegal function
sendData[1] = (byte)(sendData[1] + 128);
SerialSession.Send(sendData);
}
}
private static void WriteSuccess03(SerialSession SerialSession, ModbusSerialServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 6);
SerialSession.Send(sendData);
}
private void Init(ModbusAddress mAddress)
{
if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
}
}

View File

@@ -1,441 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections.Concurrent;
using System.Collections.Generic;
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, 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 void Received(SocketClient client, IRequestInfo requestInfo)
{
try
{
//接收外部报文
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 ((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 ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(client, modbusServerMessage);
}
else
{
WriteError(client, modbusServerMessage);
}
}
else
{
WriteError(client, modbusServerMessage);
}
}
else
{
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess)
{
WriteSuccess03(client, modbusServerMessage);
}
else
{
WriteError(client, modbusServerMessage);
}
}
}
}
}
}
catch (Exception ex)
{
Logger.LogError(ex, ToString());
}
//返回错误码
static void WriteError(SocketClient client, ModbusTcpServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 8)
.SpliceArray(new byte[] { (byte)1 });//01 lllegal function
sendData[5] = (byte)(sendData.Length - 6);
sendData[7] = (byte)(sendData[7] + 128);
client.Send(sendData);
}
}
private static void WriteSuccess03(SocketClient client, ModbusTcpServerMessage modbusServerMessage)
{
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 12);
sendData[5] = (byte)(sendData.Length - 6);
client.Send(sendData);
}
private void Init(ModbusAddress mAddress)
{
if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
}
}

View File

@@ -1,3 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
</Project>

View File

@@ -1,579 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.OPCDA</name>
</assembly>
<members>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
<summary>
移除符合条件的元素
</summary>
<typeparam name="T"></typeparam>
<param name="this"></param>
<param name="where"></param>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_SYSTEM_DEFAULT">
<summary>
The WIN32 system default locale.
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_USER_DEFAULT">
<summary>
The WIN32 user default locale.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.CreateInstance(System.Guid,System.String)">
<summary>
创建一个COM服务器的实例。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.GetSystemMessage(System.Int32)">
<summary>
指定错误消息文本检索系统。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.InitializeSecurity">
<summary>
初始化COM安全。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID)">
<summary>
从枚举器读取guid。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID)">
<summary>
从枚举器读取guid。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.RealseComServer(System.Object)">
<summary>
释放 COM 对象
</summary>
<param name="m_server"></param>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.Convert.FILETIME_BaseTime">
<summary>
windows的filetime是从1601-1-1 00:00:00开始的datetime是从1-1-1 00:00:00开始的
datetime和filetime的滴答单位都是100ns100纳秒千万分之一秒所以转换时只需要考虑开始时间即可
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnDataChangedHandler">
<summary>
值变化
</summary>
<param name="opcItems"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnReadCompletedHandler">
<summary>
读取
</summary>
<param name="opcItems"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnWriteCompletedHandler">
<summary>
写入
</summary>
<param name="opcItems"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult">
<summary>
返回结果
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Name">
<summary>
ID
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Quality">
<summary>
Quality
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.TimeStamp">
<summary>
TimeStamp
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Value">
<summary>
Value
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.InitIoInterfaces(System.Object)">
<summary>
建立连接
</summary>
<param name="handle"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.ReadAsync">
<summary>
组读取
</summary>
<exception cref="T:System.Runtime.InteropServices.ExternalException"></exception>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem">
<summary>
OpcItem
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.#ctor(System.String)">
<summary>
OpcItem
</summary>
<param name="itemId"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.AccessPath">
<summary>
AccessPath
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Blob">
<summary>
Blob
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.BlobSize">
<summary>
BlobSize
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ClientHandle">
<summary>
ClientHandle
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.IsActive">
<summary>
active(1) or not(0)
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ItemID">
<summary>
数据项在opc server的完全名称
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Quality">
<summary>
Quality
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.RunTimeDataType">
<summary>
RunTimeDataType
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ServerHandle">
<summary>
ServerHandle
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.TimeStamp">
<summary>
TimeStamp
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Value">
<summary>
Value
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.AddGroup(System.String,System.Boolean,System.Int32,System.Single)">
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.Browse(System.String)">
<summary>
获取节点
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.GetServerStatus">
<summary>
服务器状态
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus">
<summary>
ServerStatus
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.CurrentTime">
<summary>
CurrentTime
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.LastUpdateTime">
<summary>
LastUpdateTime
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.ServerState">
<summary>
ServerState
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.StartTime">
<summary>
StartTime
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.VendorInfo">
<summary>
VendorInfo
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.Version">
<summary>
Version
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery">
<summary>
OpcDiscovery
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery.GetOpcServer(System.String,System.String)">
<summary>
GetOpcServer
</summary>
<param name="serverName"></param>
<param name="host"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPoint">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPointContainer">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnectionPoints">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnections">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumString">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumUnknown">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCCommon">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCShutdown">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CONNECTDATA">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEDIRECTION">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEFILTER">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSETYPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCDATASOURCE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCENUMSCOPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCEUTYPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCNAMESPACETYPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer10">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer20">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer30">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_XMLDAServer10">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumOPCItemAttributes">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO3">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowse">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowseServerAddressSpace">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCDataCallback">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemDeadbandMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemIO">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemProperties">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemSamplingMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCPublicGroupStateMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServer">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerPublicGroups">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEELEMENT">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADER">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADERWRITE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMATTRIBUTES">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMDEF">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER1">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADERWRITE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTIES">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTY">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMRESULT">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMSTATE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMVQT">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATUS">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Constants">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Qualities">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Properties">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.DataChangedEventHandler">
<summary>
订阅变化项
</summary>
<param name="values"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient">
<summary>
OPCDAClient
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ItemDicts">
<summary>
当前保存的需订阅列表
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.#ctor(ThingsGateway.Foundation.ILog)">
<summary>
<inheritdoc/>
</summary>
<param name="logger"></param>
</member>
<member name="E:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.DataChangedHandler">
<summary>
数据变化事件
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.IsConnected">
<summary>
是否连接成功
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.OPCNode">
<summary>
当前配置
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItems(System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.List{ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem}})">
<summary>
添加节点,需要在连接成功后执行
</summary>
<param name="items">组名称/变量节点,注意每次添加的组名称不能相同</param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItemsWithSave(System.Collections.Generic.List{System.String})">
<summary>
设置节点并保存,每次重连会自动添加节点
</summary>
<param name="items"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Connect">
<summary>
连接服务器
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Disconnect">
<summary>
断开连接
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetBrowseElements(System.String)">
<summary>
浏览节点
</summary>
<param name="itemId"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetServerStatus">
<summary>
获取服务状态
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Init(ThingsGateway.Foundation.Adapter.OPCDA.OPCNode)">
<summary>
初始化设置
</summary>
<param name="node"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ReadItemsWithGroup(System.String)">
<summary>
按OPC组读取组内变量结果会在订阅事件中返回
</summary>
<param name="groupName">组名称值为null时读取全部组</param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.RemoveItems(System.Collections.Generic.List{System.String})">
<summary>
移除节点
</summary>
<param name="items"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken})">
<summary>
批量写入值
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode">
<summary>
OPCDA连接配置项
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ActiveSubscribe">
<summary>
是否订阅
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.CheckRate">
<summary>
内部检测重连间隔/min
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.DeadBand">
<summary>
死区
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.GroupSize">
<summary>
分组大小
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCIP">
<summary>
OPCIP
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCName">
<summary>
OPCNAME
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.UpdateRate">
<summary>
订阅间隔
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ToString">
<summary>
<inheritdoc/>
</summary>
<returns></returns>
</member>
</members>
</doc>

View File

@@ -1,468 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.OPCUA</name>
</assembly>
<members>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
<summary>
移除符合条件的元素
</summary>
<typeparam name="T"></typeparam>
<param name="this"></param>
<param name="where"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.SelectAsync``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.Threading.Tasks.Task{``1}})">
<summary>
异步Select
</summary>
<typeparam name="T"></typeparam>
<typeparam name="TResult"></typeparam>
<param name="source"></param>
<param name="selector"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils">
<summary>
辅助类
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.Browse(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean)">
<summary>
Browses the address space and returns the references found.
</summary>
<param name="session">The session.</param>
<param name="nodesToBrowse">The set of browse operations to perform.</param>
<param name="throwOnError">if set to <c>true</c> a exception will be thrown on an error.</param>
<returns>
The references found. Null if an error occurred.
</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.PrepareBrowseNext(Opc.Ua.BrowseResultCollection)">
<summary>
Create the continuation point collection from the browse result
collection for the BrowseNext service.
</summary>
<param name="browseResultCollection">The browse result collection to use.</param>
<returns>The collection of continuation points for the BrowseNext service.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean,System.Threading.CancellationToken)">
<summary>
浏览地址空间
</summary>
<param name="session"></param>
<param name="nodesToBrowse"></param>
<param name="throwOnError"></param>
<param name="cancellationToken"></param>
<returns></returns>
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescription,System.Boolean,System.Threading.CancellationToken)">
<summary>
浏览地址空间
</summary>
<param name="session"></param>
<param name="nodeToBrowse"></param>
<param name="throwOnError"></param>
<param name="cancellationToken"></param>
<returns></returns>
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseSuperTypesAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,System.Boolean)">
<summary>
浏览地址空间并返回指定类型的所有节点
</summary>
<param name="session"></param>
<param name="typeId"></param>
<param name="throwOnError"></param>
<returns></returns>
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForInstanceAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
<summary>
Collects the fields for the instance.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForType(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
<summary>
Collects the fields for the type.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ConstructEventAsync(Opc.Ua.Client.ISession,Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList,System.Collections.Generic.Dictionary{Opc.Ua.NodeId,System.Type},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.NodeId})">
<summary>
Constructs an event object from a notification.
</summary>
<param name="session">The session.</param>
<param name="monitoredItem">The monitored item that produced the notification.</param>
<param name="notification">The notification.</param>
<param name="knownEventTypes">The known event types.</param>
<param name="eventTypeMappings">Mapping between event types and known event types.</param>
<returns>
The event object. Null if the notification is not a valid event type.
</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.DiscoverServers(Opc.Ua.ApplicationConfiguration)">
<summary>
Discovers the servers on the local machine.
</summary>
<param name="configuration">The configuration.</param>
<returns>A list of server urls.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.FindEventType(Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList)">
<summary>
Finds the type of the event for the notification.
</summary>
<param name="monitoredItem">The monitored item.</param>
<param name="notification">The notification.</param>
<returns>The NodeId of the EventType.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAttributeDisplayText(Opc.Ua.Client.ISession,System.UInt32,Opc.Ua.Variant)">
<summary>
指定的属性的显示文本。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.SelectEndpoint(System.String,System.Boolean)">
<summary>
Finds the endpoint that best matches the current settings.
</summary>
<param name="discoveryUrl">The discovery URL.</param>
<param name="useSecurity">if set to <c>true</c> select an endpoint that uses security.</param>
<returns>The best available endpoint.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.TranslateBrowsePaths(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.NamespaceTable,System.Threading.CancellationToken,System.String[])">
<summary>
返回一组相对路径的节点id
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection})">
<summary>
Collects the fields for the instance node.
</summary>
<param name="session">The session.</param>
<param name="nodeId">The node id.</param>
<param name="parentPath">The parent path.</param>
<param name="fields">The event fields.</param>
<param name="fieldNodeIds">The node id for the declaration of the field.</param>
<param name="foundNodes">The table of found nodes.</param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ContainsPath(Opc.Ua.SimpleAttributeOperandCollection,Opc.Ua.QualifiedNameCollection)">
<summary>
判断指定的select子句包含的浏览路径。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAccessLevelDisplayText(System.Byte)">
<summary>
访问级别属性的显示文本。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetEventNotifierDisplayText(System.Byte)">
<summary>
事件通知属性的显示文本
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils">
<summary>
扩展方法
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Decode(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
<summary>
解析获取DataValue
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecoderObject(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
<summary>
解析获取object
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecodeRawData(Opc.Ua.JsonDecoder,Opc.Ua.BuiltInType,System.Int32,System.String)">
<summary>
DecodeRawData
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Encode(Opc.Ua.IServiceMessageContext,Opc.Ua.BuiltInType,System.Object)">
<summary>
OPCUAValue解析为Jtoken
</summary>
<param name="Context"></param>
<param name="type"></param>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CreateEncoder(Opc.Ua.IServiceMessageContext,System.IO.Stream,System.Boolean,System.Boolean,System.Boolean,System.Boolean)">
<summary>
CreateEncoder
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CalculateActualValueRank(Newtonsoft.Json.Linq.JToken)">
<summary>
维度
</summary>
<param name="jToken"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode">
<summary>
OPCUAClient配置项
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.OPCUrl">
<summary>
OPCUrl
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UserName">
<summary>
登录账号
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.Password">
<summary>
登录密码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.CheckDomain">
<summary>
检查域
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UpdateRate">
<summary>
更新间隔
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ActiveSubscribe">
<summary>
是否订阅
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.GroupSize">
<summary>
分组大小
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.DeadBand">
<summary>
死区
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.KeepAliveInterval">
<summary>
KeepAliveInterval/ms
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.IsUseSecurity">
<summary>
安全策略
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ToString">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.DataChangedEventHandler">
<summary>
订阅委托
</summary>
<param name="value"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient">
<summary>
OPCUAClient
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCNode">
<summary>
当前配置
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ProductUri">
<summary>
ProductUri
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Variables">
<summary>
当前保存的变量名称列表
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient._variableDicts">
<summary>
当前的变量名称/OPC变量节点
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.dic_subscriptions">
<summary>
当前的订阅组,组名称/组
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReConnectHandler">
<summary>
SessionReconnectHandler
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.#ctor(ThingsGateway.Foundation.ILog)">
<summary>
默认的构造函数实例化一个新的OPC UA类
</summary>
</member>
<member name="E:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.DataChangedHandler">
<summary>
订阅
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AppConfig">
<summary>
配置信息
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Connected">
<summary>
连接状态
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCUAName">
<summary>
OPCUAClient
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Session">
<summary>
当前活动会话。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AddSubscriptionAsync(System.String,System.String[])">
<summary>
新增订阅需要指定订阅组名称订阅的tag名数组
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveAllSubscription">
<summary>
移除所有的订阅消息
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveSubscription(System.String)">
<summary>
移除订阅消息
</summary>
<param name="subscriptionName">组名称</param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.BrowseNodeReferenceAsync(System.String)">
<summary>
浏览一个节点的引用
</summary>
<param name="tag">节点值</param>
<returns>引用节点描述</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.CallMethodByNodeId(System.String,System.String,System.Object[])">
<summary>
调用服务器的方法
</summary>
<param name="tagParent">方法的父节点tag</param>
<param name="tag">方法的节点tag</param>
<param name="args">传递的参数</param>
<returns>输出的结果值</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadHistoryRawDataValues(System.String,System.DateTime,System.DateTime,System.UInt32,System.Boolean,System.Threading.CancellationToken)">
<summary>
读取历史数据
</summary>
<param name="tag">节点的索引</param>
<param name="start">开始时间</param>
<param name="end">结束时间</param>
<param name="count">读取的个数</param>
<param name="containBound">是否包含边界</param>
<param name="cancellationToken">cancellationToken</param>
<returns>读取的数据列表</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync">
<summary>
连接到服务器
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Disconnect">
<summary>
断开连接。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync(System.String)">
<summary>
Creates a new session.
</summary>
<returns>The new session object.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(System.String[],System.Threading.CancellationToken)">
<summary>
从服务器读取值
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
<summary>
异步写opc标签
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(Opc.Ua.NodeId[],System.Threading.CancellationToken)">
<summary>
从服务器读取值
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNodeAsync(System.String,System.Boolean,System.Threading.CancellationToken)">
<summary>
从服务器或缓存读取节点
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
<summary>
读取一个节点的所有属性
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.Collections.Generic.List{System.String},System.Threading.CancellationToken)">
<summary>
读取节点的所有属性
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributes(System.String)">
<summary>
读取一个节点的所有属性
</summary>
<param name="tag">节点信息</param>
<returns>节点的特性值</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Dispose(System.Boolean)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Server_ReconnectComplete(System.Object,System.EventArgs)">
<summary>
连接处理器连接事件处理完成。
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute">
<summary>
读取属性过程中用于描述的
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Name">
<summary>
属性的名称
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.StatusCode">
<summary>
操作结果状态描述
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Type">
<summary>
属性的类型描述
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Value">
<summary>
属性的值,如果读取错误,返回文本描述
</summary>
</member>
</members>
</doc>

View File

@@ -1,131 +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.Generic;
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,336 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.Siemens</name>
</assembly>
<members>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.S7Area">
<summary>
区域
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.PE">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.PA">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.MK">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.DB">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.CT">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.TM">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.AI">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.AQ">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress">
<summary>
西门子PLC地址数据信息
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.BitCode">
<summary>
bit位偏移
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.DataCode">
<summary>
数据块代码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.DbBlock">
<summary>
DB块数据信息
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.GetAddressStart(System.String,System.Boolean)">
<summary>
获取起始地址
</summary>
<param name="address"></param>
<param name="isCounterOrTimer"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.GetBitCode(System.String)">
<summary>
获取bit
</summary>
<param name="address"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ParseFrom(System.String)">
<summary>
解析地址
</summary>
<param name="address"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ParseFrom(System.String,System.Int32)">
<summary>
解析地址
</summary>
<param name="address"></param>
<param name="length"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.Parse(System.String,System.Int32)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ToString">
<inheritdoc />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.DateTime">
<summary>
https://github.com/S7NetPlus/s7netplus/blob/develop/S7.Net/Types/DateTime.cs
Contains the methods to convert between <see cref="T:System.DateTime"/> and S7 representation of datetime values.
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.DateTime.SpecMaximumDateTime">
<summary>
The maximum <see cref="T:System.DateTime"/> value supported by the specification.
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.DateTime.SpecMinimumDateTime">
<summary>
The minimum <see cref="T:System.DateTime"/> value supported by the specification.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.FromByteArray(System.Byte[])">
<summary>
Parses a <see cref="T:System.DateTime"/> value from bytes.
</summary>
<param name="bytes">Input bytes read from PLC.</param>
<returns>A <see cref="T:System.DateTime"/> object representing the value read from PLC.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when the length of
<paramref name="bytes"/> is not 8 or any value in <paramref name="bytes"/>
is outside the valid range of values.</exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToArray(System.Byte[])">
<summary>
Parses an array of <see cref="T:System.DateTime"/> values from bytes.
</summary>
<param name="bytes">Input bytes read from PLC.</param>
<returns>An array of <see cref="T:System.DateTime"/> objects representing the values read from PLC.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when the length of
<paramref name="bytes"/> is not a multiple of 8 or any value in
<paramref name="bytes"/> is outside the valid range of values.</exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToByteArray(System.DateTime)">
<summary>
Converts a <see cref="T:System.DateTime"/> value to a byte array.
</summary>
<param name="dateTime">The DateTime value to convert.</param>
<returns>A byte array containing the S7 date time representation of <paramref name="dateTime"/>.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when the value of
<paramref name="dateTime"/> is before <see cref="P:SpecMinimumDateTime"/>
or after <see cref="P:SpecMaximumDateTime"/>.</exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToByteArray(System.DateTime[])">
<summary>
Converts an array of <see cref="T:System.DateTime"/> values to a byte array.
</summary>
<param name="dateTimes">The DateTime values to convert.</param>
<returns>A byte array containing the S7 date time representations of <paramref name="dateTimes"/>.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when any value of
<paramref name="dateTimes"/> is before <see cref="P:SpecMinimumDateTime"/>
or after <see cref="P:SpecMaximumDateTime"/>.</exception>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensHelper.S7_MULRW_HEADER">
<summary>
S7连读写请求头(包含ISO头和COTP头)
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Bit">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Byte">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Char">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Word">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Int">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.DWord">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.DInt">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Real">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Counter">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Timer">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage.HeadBytesLength">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage.CheckHeadBytes(System.Byte[])">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S200">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S200Smart">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S300">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S400">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S1200">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S1500">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC">
<summary>
相关命令含义源自网络资料/Shrap7/s7netplus
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.#ctor(ThingsGateway.Foundation.TcpClient,ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum)">
<summary>
传入PLC类型程序内会改变相应PLC类型的S7协议LocalTSAP RemoteTSAP等
</summary>
<param name="tcpClient"></param>
<param name="siemensPLCEnum"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.CurrentPlc">
<summary>
当前PLC类型
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.GetAddressDescription">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.GetBitOffset(System.String)">
<summary>
<inheritdoc/>
</summary>
<param name="address"></param>
<returns></returns>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.DestTSAP">
<summary>
远程TSAP需重新连接
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.LocalTSAP">
<summary>
本地TSAP需重新连接
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.PDULength">
<summary>
PDULength
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.Rack">
<summary>
机架号,需重新连接
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.Slot">
<summary>
槽号,需重新连接
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateAsync(System.String,System.Threading.CancellationToken)">
<summary>
读取日期
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateTimeAsync(System.String,System.Threading.CancellationToken)">
<summary>
读取时间
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadStringAsync(System.String,System.Text.Encoding,System.Threading.CancellationToken)">
<summary>
读取变长字符串
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.SetDataAdapter">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
<summary>
写入日期
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateTimeAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
<summary>
写入时间
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter">
<summary>
SiemensS7PLCDataHandleAdapter
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.PackCommand(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.GetInstance">
<summary>
<inheritdoc/>
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage,System.Byte[],System.Byte[],System.Byte[])">
<inheritdoc/>
</member>
</members>
</doc>

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;
/// <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,127 +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;
namespace ThingsGateway.Foundation;
/// <summary>
/// 服务设备
/// </summary>
public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase
{
/// <inheritdoc cref="ReadWriteDevicesTcpServerBase"/>
public ReadWriteDevicesTcpServerBase(TcpService tcpService)
{
TcpService = tcpService;
TcpService.Connecting += Connecting;
TcpService.Connected += Connected;
TcpService.Received += Received;
TcpService.Disconnecting += Disconnecting;
TcpService.Disconnected += Disconnected;
Logger = TcpService.Logger;
}
/// <summary>
/// 连接超时时间
/// </summary>
[Description("连接超时时间")]
public ushort ConnectTimeOut { get; set; } = 3000;
/// <summary>
/// 服务管理对象
/// </summary>
public TcpService TcpService { get; }
/// <inheritdoc/>
public override void Connect(CancellationToken cancellationToken)
{
TcpService.Start();
}
/// <inheritdoc/>
public override Task ConnectAsync(CancellationToken cancellationToken)
{
return Task.Run(() => TcpService.Start());
}
/// <inheritdoc/>
public override void Disconnect()
{
if (CascadeDisposal)
TcpService.Stop();
}
/// <inheritdoc/>
public override void Dispose()
{
TcpService.Connecting -= Connecting;
TcpService.Connected -= Connected;
TcpService.Disconnecting -= Disconnecting;
TcpService.Disconnected -= Disconnected;
Disconnect();
if (CascadeDisposal)
TcpService.SafeDispose();
}
/// <inheritdoc/>
public override string ToString()
{
return TcpService.ServerName;
}
/// <summary>
/// 接收解析
/// </summary>
protected virtual void Received(SocketClient client, IRequestInfo requestInfo)
{
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
protected virtual void Connected(SocketClient client, ConnectedEventArgs e)
{
Logger?.Debug(client.IP + ":" + client.Port + "连接成功");
}
/// <inheritdoc/>
protected virtual void Connecting(SocketClient client, ConnectingEventArgs e)
{
Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
SetDataAdapter(client);
}
/// <inheritdoc/>
protected virtual void Disconnected(ITcpClientBase client, DisconnectEventArgs e)
{
Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message);
}
/// <inheritdoc/>
protected virtual void Disconnecting(ITcpClientBase client, DisconnectEventArgs e)
{
Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message);
}
private void Received(SocketClient client, ByteBlock byteBlock, IRequestInfo requestInfo)
{
try
{
Received(client, requestInfo);
}
catch (Exception ex)
{
Logger.Exception(this, ex);
}
}
}

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,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net45'">
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" PrivateAssets="All" />
<PackageReference Include="System.Reflection.Emit.ILGeneration" Version="4.7.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'!='net45'">
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,275 +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
{
/// <summary>
/// 消息通知类。内部全为弱引用。
/// </summary>
public class AppMessenger
{
private static AppMessenger m_instance;
private readonly ReaderWriterLockSlim m_lockSlim = new ReaderWriterLockSlim();
private readonly Dictionary<string, List<MessageInstance>> m_tokenAndInstance = new Dictionary<string, List<MessageInstance>>();
/// <summary>
/// 默认单例实例
/// </summary>
public static AppMessenger Default
{
get
{
if (m_instance != null)
{
return m_instance;
}
lock (typeof(AppMessenger))
{
if (m_instance != null)
{
return m_instance;
}
m_instance = new AppMessenger();
return m_instance;
}
}
}
/// <summary>
/// 允许多广播注册
/// </summary>
public bool AllowMultiple { get; set; }
/// <summary>
/// 添加
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="messageInstance"></param>
/// <exception cref="MessageRegisteredException"></exception>
public void Add(string cancellationToken, MessageInstance messageInstance)
{
using (var writeLock = new WriteLock(this.m_lockSlim))
{
if (this.m_tokenAndInstance.ContainsKey(cancellationToken))
{
if (!this.AllowMultiple)
{
throw new MessageRegisteredException(TouchSocketCoreResource.TokenExisted.GetDescription(cancellationToken));
}
this.m_tokenAndInstance[cancellationToken].Add(messageInstance);
}
else
{
this.m_tokenAndInstance.Add(cancellationToken, new List<MessageInstance>()
{
messageInstance
});
}
}
}
/// <summary>
/// 判断能否触发该消息,意味着该消息是否已经注册。
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public bool CanSendMessage(string cancellationToken)
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
return this.m_tokenAndInstance.ContainsKey(cancellationToken);
}
}
/// <summary>
/// 清除所有消息
/// </summary>
public void Clear()
{
using (var writeLock = new WriteLock(this.m_lockSlim))
{
this.m_tokenAndInstance.Clear();
}
}
/// <summary>
/// 获取所有消息
/// </summary>
/// <returns></returns>
public string[] GetAllMessage()
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
return this.m_tokenAndInstance.Keys.ToArray();
}
}
/// <summary>
/// 移除
/// </summary>
/// <param name="cancellationToken"></param>
public void Remove(string cancellationToken)
{
using (var writeLock = new WriteLock(this.m_lockSlim))
{
this.m_tokenAndInstance.Remove(cancellationToken);
}
}
/// <summary>
/// 按对象移除
/// </summary>
/// <param name="messageObject"></param>
public void Remove(IMessageObject messageObject)
{
using (var writeLock = new WriteLock(this.m_lockSlim))
{
var key = new List<string>();
foreach (var item in this.m_tokenAndInstance.Keys)
{
foreach (var item2 in this.m_tokenAndInstance[item].ToArray())
{
if (messageObject == item2.MessageObject)
{
this.m_tokenAndInstance[item].Remove(item2);
if (this.m_tokenAndInstance[item].Count == 0)
{
key.Add(item);
}
}
}
}
foreach (var item in key)
{
this.m_tokenAndInstance.Remove(item);
}
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="parameters"></param>
/// <exception cref="MessageNotFoundException"></exception>
public Task SendAsync(string cancellationToken, params object[] parameters)
{
return Task.Run(() =>
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
if (this.m_tokenAndInstance.TryGetValue(cancellationToken, out var list))
{
var clear = new List<MessageInstance>();
foreach (var item in list)
{
if (!item.Info.IsStatic && !item.WeakReference.TryGetTarget(out _))
{
clear.Add(item);
continue;
}
try
{
item.Invoke(item.MessageObject, parameters);
}
catch
{
}
}
foreach (var item in clear)
{
list.Remove(item);
}
}
else
{
throw new MessageNotFoundException(TouchSocketCoreResource.MessageNotFound.GetDescription(cancellationToken));
}
}
});
}
/// <summary>
/// 发送消息,当多播时,只返回最后一个返回值
/// </summary>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="cancellationToken"></param>
/// <param name="parameters"></param>
/// <returns></returns>
/// <exception cref="MessageNotFoundException"></exception>
public Task<T> SendAsync<T>(string cancellationToken, params object[] parameters)
{
return Task.Run(() =>
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
if (this.m_tokenAndInstance.TryGetValue(cancellationToken, out var list))
{
T result = default;
var clear = new List<MessageInstance>();
for (var i = 0; i < list.Count; i++)
{
var item = list[i];
if (!item.Info.IsStatic && !item.WeakReference.TryGetTarget(out _))
{
clear.Add(item);
continue;
}
try
{
if (i == list.Count - 1)
{
result = (T)item.Invoke(item.MessageObject, parameters);
}
else
{
item.Invoke(item.MessageObject, parameters);
}
}
catch
{
}
}
foreach (var item in clear)
{
list.Remove(item);
}
return result;
}
else
{
throw new MessageNotFoundException(TouchSocketCoreResource.MessageNotFound.GetDescription(cancellationToken));
}
}
});
}
}
}

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
{
/// <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,94 +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)}");
}
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,391 +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.Dmtp
{
/// <summary>
/// HttpDmtpClient
/// </summary>
public partial class HttpDmtpClient : HttpClientBase, IHttpDmtpClient
{
#region
private bool m_allowRoute;
private Func<string, IDmtpActor> m_findDmtpActor;
private DmtpActor m_smtpActor;
private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
#endregion
/// <inheritdoc cref="IDmtpActor.Id"/>
public string Id => this.DmtpActor.Id;
/// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
/// <inheritdoc/>
public IDmtpActor DmtpActor { get => this.m_smtpActor; }
#region
/// <summary>
/// 建立Tcp连接并且执行握手。
/// </summary>
/// <param name="timeout"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public override ITcpClient Connect(int timeout = 5000)
{
lock (this.SyncRoot)
{
if (this.IsHandshaked)
{
return this;
}
if (!this.Online)
{
base.Connect(timeout);
}
var request = new HttpRequest()
.SetHost(this.RemoteIPHost.Host);
request.Headers.Add(HttpHeaders.Connection, "upgrade");
request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower());
request.AsMethod(DmtpUtility.Dmtp);
var response = this.RequestContent(request);
if (response.StatusCode == 101)
{
this.SwitchProtocolToDmtp();
this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None);
return this;
}
else
{
throw new Exception(response.StatusMessage);
}
}
}
/// <inheritdoc/>
public virtual IHttpDmtpClient Connect(CancellationToken cancellationToken, int timeout = 5000)
{
lock (this.SyncRoot)
{
if (this.IsHandshaked)
{
return this;
}
if (!this.Online)
{
base.Connect(timeout);
}
var request = new HttpRequest()
.SetHost(this.RemoteIPHost.Host);
request.Headers.Add(HttpHeaders.Connection, "upgrade");
request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower());
request.AsMethod(DmtpUtility.Dmtp);
var response = this.RequestContent(request, timeout: timeout, cancellationToken: cancellationToken);
if (response.StatusCode == 101)
{
this.SwitchProtocolToDmtp();
this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), cancellationToken);
return this;
}
else
{
throw new Exception(response.StatusMessage);
}
}
}
/// <summary>
/// 建立Tcp连接并且执行握手。
/// </summary>
/// <param name="timeout"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public override async Task<ITcpClient> ConnectAsync(int timeout = 5000)
{
try
{
await this.m_semaphore.WaitAsync();
if (this.IsHandshaked)
{
return this;
}
if (!this.Online)
{
await base.ConnectAsync(timeout);
}
var request = new HttpRequest()
.SetHost(this.RemoteIPHost.Host);
request.Headers.Add(HttpHeaders.Connection, "upgrade");
request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower());
request.AsMethod(DmtpUtility.Dmtp);
var response = this.RequestContent(request);
if (response.StatusCode == 101)
{
this.SwitchProtocolToDmtp();
await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None);
return this;
}
else
{
throw new Exception(response.StatusMessage);
}
}
finally
{
this.m_semaphore.Release();
}
}
/// <inheritdoc/>
public virtual async Task<IHttpDmtpClient> ConnectAsync(CancellationToken cancellationToken, int timeout = 5000)
{
try
{
await this.m_semaphore.WaitAsync();
if (this.IsHandshaked)
{
return this;
}
if (!this.Online)
{
await base.ConnectAsync(timeout);
}
var request = new HttpRequest()
.SetHost(this.RemoteIPHost.Host);
request.Headers.Add(HttpHeaders.Connection, "upgrade");
request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower());
request.AsMethod(DmtpUtility.Dmtp);
var response = this.RequestContent(request, timeout: timeout, cancellationToken: cancellationToken);
if (response.StatusCode == 101)
{
this.SwitchProtocolToDmtp();
await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), cancellationToken);
return this;
}
else
{
throw new Exception(response.StatusMessage);
}
}
finally
{
this.m_semaphore.Release();
}
}
#endregion
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
this.DmtpActor.SafeDispose();
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
if (this.Protocol == DmtpUtility.DmtpProtocol && requestInfo is DmtpMessage message)
{
if (!this.m_smtpActor.InputReceivedData(message))
{
if (this.PluginsManager.Enable)
{
this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
}
}
return false;
}
return base.HandleReceivedData(byteBlock, requestInfo);
}
/// <inheritdoc/>
protected override void LoadConfig(TouchSocketConfig config)
{
base.LoadConfig(config);
if (this.Container.IsRegistered(typeof(IDmtpRouteService)))
{
this.m_allowRoute = true;
this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor;
}
}
/// <inheritdoc/>
protected override void OnDisconnected(DisconnectEventArgs e)
{
base.OnDisconnected(e);
this.DmtpActor.Close(false, e.Message);
}
#region ResetId
///<inheritdoc cref="IDmtpActor.ResetId(string)"/>
public void ResetId(string id)
{
this.m_smtpActor.ResetId(id);
}
///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/>
public Task ResetIdAsync(string newId)
{
return this.m_smtpActor.ResetIdAsync(newId);
}
#endregion ResetId
private void SwitchProtocolToDmtp()
{
this.Protocol = DmtpUtility.DmtpProtocol;
this.SetDataHandlingAdapter(new TcpDmtpAdapter());
this.m_smtpActor = new SealedDmtpActor(this.m_allowRoute)
{
OutputSend = DmtpActorSend,
OnRouting = OnDmtpActorRouting,
OnHandshaking = this.OnDmtpActorHandshaking,
OnHandshaked = OnDmtpActorHandshaked,
OnClose = OnDmtpActorClose,
OnCreateChannel = this.OnDmtpActorCreateChannel,
Logger = this.Logger,
Client = this,
OnFindDmtpActor = this.m_findDmtpActor
};
}
#region
private void OnDmtpActorClose(DmtpActor actor, string msg)
{
base.Close(msg);
}
private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
{
this.OnCreateChannel(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
}
private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
{
this.OnHandshaked(e);
if (e.Handled)
{
return;
}
if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e))
{
return;
}
}
private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
{
this.OnHandshaking(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
}
private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
{
this.OnRouting(e);
if (e.Handled)
{
return;
}
if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e))
{
return;
}
}
private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
{
base.Send(transferBytes);
}
#endregion
#region
/// <summary>
/// 当创建通道
/// </summary>
/// <param name="e"></param>
protected virtual void OnCreateChannel(CreateChannelEventArgs e)
{
}
/// <summary>
/// 在完成握手连接时
/// </summary>
/// <param name="e"></param>
protected virtual void OnHandshaked(DmtpVerifyEventArgs e)
{
}
/// <summary>
/// 即将握手连接时
/// </summary>
/// <param name="e">参数</param>
protected virtual void OnHandshaking(DmtpVerifyEventArgs e)
{
}
/// <summary>
/// 当需要转发路由包时
/// </summary>
/// <param name="e"></param>
protected virtual void OnRouting(PackageRouterEventArgs e)
{
}
#endregion
}
}

View File

@@ -1,245 +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.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="cancellationToken"><inheritdoc/></param>
/// <returns></returns>
public HttpResponse Request(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken cancellationToken = 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(cancellationToken);
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="cancellationToken"></param>
/// <returns></returns>
public HttpResponse RequestContent(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken cancellationToken = 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(cancellationToken);
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);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
if (requestInfo is HttpResponse response)
{
if (this.m_getContent)
{
response.TryGetContent(out _);
}
this.m_waitData.Set(response);
}
return false;
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="e"></param>
protected override void OnConnecting(ConnectingEventArgs e)
{
this.Protocol = Protocol.Http;
this.SetDataHandlingAdapter(new HttpClientDataHandlingAdapter());
base.OnConnecting(e);
}
}
}

View File

@@ -1,93 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//using System.Threading.Tasks;
//using ThingsGateway.Foundation;
//namespace ThingsGateway.Foundation.Http.WebSockets
//{
// public class WebSocket : IWebSocket
// {
// private readonly IHttpClientBase m_client;
// private readonly bool m_isServer;
// public WebSocket(IHttpClientBase client, bool isServer)
// {
// this.m_client = client;
// this.m_isServer = isServer;
// }
// public bool IsHandshaked => this.m_client.GetHandshaked();
// public void Close(string msg)
// {
// using (var frame = new WSDataFrame() { FIN = true, Opcode = WSDataType.Close }.AppendText(msg))
// {
// this.Send(frame);
// }
// }
// public void Ping()
// {
// using (var frame = new WSDataFrame() { FIN = true, Opcode = WSDataType.Ping })
// {
// this.Send(frame);
// }
// }
// public void Pong()
// {
// using (var frame = new WSDataFrame() { FIN = true, Opcode = WSDataType.Pong })
// {
// this.Send(frame);
// }
// }
// public void Send(WSDataFrame dataFrame)
// {
// using (var byteBlock = new ByteBlock(dataFrame.PayloadLength + 1024))
// {
// if (this.m_isServer)
// {
// dataFrame.BuildResponse(byteBlock);
// }
// else
// {
// dataFrame.BuildRequest(byteBlock);
// }
// this.m_client.DefaultSend(byteBlock.Buffer, 0, byteBlock.Len);
// }
// }
// /// <summary>
// /// 采用WebSocket协议发送WS数据。
// /// </summary>
// /// <param name="dataFrame"></param>
// public Task SendAsync(WSDataFrame dataFrame)
// {
// using (var byteBlock = new ByteBlock(dataFrame.PayloadLength + 1024))
// {
// if (this.m_isServer)
// {
// dataFrame.BuildResponse(byteBlock);
// }
// else
// {
// dataFrame.BuildRequest(byteBlock);
// }
// return this.m_client.DefaultSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
// }
// }
// }
//}

View File

@@ -1,62 +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;
//using System.Collections.Generic;
//using System.Linq;
//using System.Net.WebSockets;
//using System.Text;
//using System.Threading.Tasks;
//using ThingsGateway.Foundation;
//namespace ThingsGateway.Foundation.Http.WebSockets
//{
// /// <summary>
// /// IWebSocket
// /// </summary>
// public interface IWebSocket
// {
// /// <summary>
// /// 表示当前WebSocket是否已经完成连接。
// /// </summary>
// bool IsHandshaked { get; }
// /// <summary>
// /// 发送Close报文。
// /// </summary>
// /// <param name="msg"></param>
// void Close(string msg);
// /// <summary>
// /// 发送Ping报文。
// /// </summary>
// void Ping();
// /// <summary>
// /// 发送Pong报文。
// /// </summary>
// void Pong();
// /// <summary>
// /// 采用WebSocket协议发送WS数据。发送结束后请及时释放<see cref="WSDataFrame"/>
// /// </summary>
// /// <param name="dataFrame"></param>
// void Send(WSDataFrame dataFrame);
// /// <summary>
// /// 采用WebSocket协议发送WS数据。发送结束后请及时释放<see cref="WSDataFrame"/>
// /// </summary>
// /// <param name="dataFrame"></param>
// /// <returns></returns>
// Task SendAsync(WSDataFrame dataFrame);
// }
//}

View File

@@ -1,5 +0,0 @@
该文件夹下的代码全部来自于ThingsGateway.Foundation
摘自 ThingsGateway.Foundation [Pages](http://rrqm_home.gitee.io/touchsocket/)

View File

@@ -1,94 +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>
/// 代码生成标识
/// </summary>
[Flags]
public enum CodeGeneratorFlag
{
/// <summary>
/// 生成同步代码(源代码生成无效)
/// </summary>
[Obsolete("该值已被弃用,请使用颗粒度更小的配置", true)]
Sync = 1,
/// <summary>
/// 生成异步代码(源代码生成无效)
/// </summary>
[Obsolete("该值已被弃用,请使用颗粒度更小的配置", true)]
Async = 2,
/// <summary>
/// 生成扩展同步代码
/// </summary>
ExtensionSync = 4,
/// <summary>
/// 生成扩展异步代码
/// </summary>
ExtensionAsync = 8,
/// <summary>
/// 包含接口(源代码生成无效)
/// </summary>
[Obsolete("该值已被弃用,请使用颗粒度更小的配置", true)]
IncludeInterface = 16,
/// <summary>
/// 包含实例(源代码生成无效)
/// </summary>
[Obsolete("该值已被弃用,请使用颗粒度更小的配置", true)]
IncludeInstance = 32,
/// <summary>
/// 包含扩展(源代码生成无效)
/// </summary>
[Obsolete("该值已被弃用,请使用颗粒度更小的配置", true)]
IncludeExtension = 64,
/// <summary>
/// 生成实例类同步代码(源代码生成无效)
/// </summary>
InstanceSync = 128,
/// <summary>
/// 生成实例类异步代码(源代码生成无效)
/// </summary>
InstanceAsync = 256,
/// <summary>
/// 生成接口同步代码
/// </summary>
InterfaceSync = 512,
/// <summary>
/// 生成接口异步代码
/// </summary>
InterfaceAsync = 1024,
}
}

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,35 +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 interface ISerial : IDisposable
{
/// <summary>
/// 发送缓存区大小。最小值=1024。
/// </summary>
int SendBufferSize { get; set; }
/// <summary>
/// 接收缓存区大小。最小值=1024。
/// </summary>
int ReceiveBufferSize { get; set; }
/// <summary>
/// 日志记录器
/// </summary>
ILog Logger { get; set; }
}

View File

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

View File

@@ -1,941 +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.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
/// <inheritdoc cref="SerialSessionBase"/>
public class SerialSession : SerialSessionBase
{
/// <summary>
/// 接收到数据
/// </summary>
public ReceivedEventHandler<SerialSession> Received { get; set; }
/// <summary>
/// 接收数据
/// </summary>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
this.Received?.Invoke(this, byteBlock, requestInfo);
return false;
}
}
/// <summary>
/// 串口管理
/// </summary>
public class SerialSessionBase : BaseSerial, ISerialSession
{
static readonly Protocol SerialPort = new("SerialSession");
/// <summary>
/// 构造函数
/// </summary>
public SerialSessionBase()
{
this.Protocol = SerialPort;
this.m_receiveCounter = new ValueCounter
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnReceivePeriod
};
this.m_sendCounter = new ValueCounter
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnSendPeriod
};
}
#region
private DelaySender m_delaySender;
private long m_bufferRate = 1;
private bool m_online => MainSerialPort?.IsOpen == true;
ValueCounter m_receiveCounter;
ValueCounter m_sendCounter;
#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 void PrivateOnConnected(object o)
{
var e = (ConnectedEventArgs)o;
this.OnConnected(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(ITcpConnectedPlugin.OnTcpConnected), this, e);
}
/// <summary>
/// 已经建立Tcp连接
/// </summary>
/// <param name="e"></param>
protected virtual void OnConnected(ConnectedEventArgs e)
{
try
{
this.Connected?.Invoke(this, e);
}
catch (System.Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.Connected)}中发生错误。", ex);
}
}
private void PrivateOnConnecting(SerialConnectingEventArgs e)
{
if (this.CanSetDataHandlingAdapter)
{
this.SetDataHandlingAdapter(this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty).Invoke());
}
this.OnConnecting(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(ITcpConnectingPlugin.OnTcpConnecting), this, e);
}
/// <summary>
/// 准备连接的时候此时已初始化Socket但是并未建立Tcp连接
/// </summary>
/// <param name="e"></param>
protected virtual void OnConnecting(SerialConnectingEventArgs e)
{
try
{
this.Connecting?.Invoke(this, e);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.OnConnecting)}中发生错误。", ex);
}
}
private void PrivateOnDisconnected(DisconnectEventArgs e)
{
this.OnDisconnected(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(ITcpDisconnectedPlugin.OnTcpDisconnected), this, e);
}
/// <summary>
/// 断开连接。在客户端未设置连接状态时,不会触发
/// </summary>
/// <param name="e"></param>
protected virtual void OnDisconnected(DisconnectEventArgs e)
{
try
{
this.Disconnected?.Invoke(this, e);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.Disconnected)}中发生错误。", ex);
}
}
private void PrivateOnDisconnecting(DisconnectEventArgs e)
{
this.OnDisconnecting(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(ITcpDisconnectingPlugin.OnTcpDisconnecting), this, e);
}
/// <summary>
/// 即将断开连接(仅主动断开时有效)。
/// <para>
/// 当主动调用Close断开时。
/// </para>
/// </summary>
/// <param name="e"></param>
protected virtual void OnDisconnecting(DisconnectEventArgs e)
{
try
{
this.Disconnecting?.Invoke(this, e);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, $"在事件{nameof(this.Disconnecting)}中发生错误。", ex);
}
}
#endregion
#region
/// <inheritdoc/>
public DateTime LastReceivedTime => this.m_receiveCounter.LastIncrement;
/// <inheritdoc/>
public DateTime LastSendTime => this.m_sendCounter.LastIncrement;
/// <inheritdoc/>
public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
/// <inheritdoc/>
public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
/// <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; }
/// <summary>
/// <inheritdoc/>
/// </summary>
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 ReceiveType ReceiveType { get; private set; }
/// <inheritdoc/>
public Protocol Protocol { get; set; }
#endregion
#region
/// <inheritdoc/>
public override string ToString()
{
return SerialProperty?.ToString();
}
/// <inheritdoc/>
public virtual void Close(string msg = TouchSocketCoreUtility.Empty)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
this.PrivateOnDisconnecting(new DisconnectEventArgs(true, msg));
this.MainSerialPort.TryClose();
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
this.PrivateOnDisconnected(new DisconnectEventArgs(true, msg));
}
}
}
private void BreakOut(string msg)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
this.PrivateOnDisconnected(new DisconnectEventArgs(false, msg));
}
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
this.MainSerialPort.TryClose();
this.PrivateOnDisconnecting(new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
this.PluginsManager.SafeDispose();
this.PrivateOnDisconnected(new DisconnectEventArgs(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("配置文件不能为空。");
}
var serialProperty = this.Config.GetValue(SerialConfigExtension.SerialProperty) ?? throw new ArgumentNullException("串口配置不能为空。");
this.MainSerialPort.SafeDispose();
var serialPort = this.CreateSerial(serialProperty);
var args = new SerialConnectingEventArgs(this.MainSerialPort);
this.PrivateOnConnecting(args);
serialPort.Open();
this.SetSerialPort(serialPort);
this.BeginReceive();
this.PrivateOnConnected(new ConnectedEventArgs());
}
}
/// <inheritdoc/>
public virtual ISerialSession Connect()
{
this.Open();
return this;
}
/// <inheritdoc/>
public Task<ISerialSession> ConnectAsync()
{
return Task.Run(() =>
{
return this.Connect();
});
}
#endregion
private void OnReceivePeriod(long value)
{
this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value);
}
private void OnSendPeriod(long value)
{
this.SendBufferSize = TouchSocketUtility.HitBufferLength(value);
}
/// <inheritdoc/>
public override int ReceiveBufferSize
{
get => base.ReceiveBufferSize;
set
{
base.ReceiveBufferSize = value;
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.ReadBufferSize = base.ReceiveBufferSize;
}
}
}
/// <inheritdoc/>
public override int SendBufferSize
{
get => base.SendBufferSize;
set
{
base.SendBufferSize = value;
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.WriteBufferSize = base.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.OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false)
{
return;
}
if (this.HandleReceivedData(byteBlock, requestInfo))
{
return;
}
if (this.PluginsManager.Enable)
{
var args = new ReceivedDataEventArgs(byteBlock, requestInfo);
this.PluginsManager.Raise(nameof(ITcpReceivedPlugin.OnTcpReceived), this, args);
}
}
/// <summary>
/// 处理已接收到的数据。
/// </summary>
/// <param name="byteBlock">以二进制流形式传递</param>
/// <param name="requestInfo">以解析的数据对象传递</param>
/// <returns>如果返回<see langword="true"/>则表示数据已被处理,且不会再向下传递。</returns>
protected virtual bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
return false;
}
/// <summary>
/// 当即将发送时,如果覆盖父类方法,则不会触发插件。
/// </summary>
/// <param name="buffer">数据缓存区</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
/// <returns>返回值表示是否允许发送</returns>
protected virtual bool HandleSendingData(byte[] buffer, int offset, int length)
{
if (this.PluginsManager.Enable)
{
var args = new SendingEventArgs(buffer, offset, length);
this.PluginsManager.Raise(nameof(ITcpSendingPlugin.OnTcpSending), this, args);
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>();
this.ReceiveType = config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty);
}
/// <summary>
/// 在延迟发生错误
/// </summary>
/// <param name="ex"></param>
protected virtual void OnDelaySenderError(Exception ex)
{
this.Logger.Log(LogLevel.Error, this, "发送错误", ex);
}
/// <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;
this.DataHandlingAdapter = adapter;
}
private void BeginReceive()
{
if (this.ReceiveType == ReceiveType.Iocp)
{
SerialReceivedEventArgs eventArgs = new();
var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize);
byteBlock.SetLength(0);
eventArgs.UserToken = byteBlock;
if (this.MainSerialPort.BytesToRead > 0)
{
this.ProcessReceived(eventArgs);
}
MainSerialPort.DataReceived += this.EventArgs_Completed;
}
else if (this.ReceiveType == ReceiveType.Bio)
{
new Thread(BeginBio)
{
IsBackground = true
}
.Start();
}
}
private SerialPort CreateSerial(SerialProperty serialProperty)
{
SerialPort serialPort = new(serialProperty.PortName, serialProperty.BaudRate, serialProperty.Parity, serialProperty.DataBits, serialProperty.StopBits)
{
DtrEnable = true,
RtsEnable = true
};
return serialPort;
}
private void EventArgs_Completed(object sender, SerialDataReceivedEventArgs e)
{
try
{
this.m_bufferRate = 1;
SerialReceivedEventArgs eventArgs = new();
var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength));
newByteBlock.SetLength(0);
eventArgs.UserToken = newByteBlock;
if (MainSerialPort.BytesToRead > 0)
{
this.ProcessReceived(eventArgs);
}
}
catch (Exception ex)
{
this.BreakOut(ex.Message);
}
}
private void BeginBio()
{
while (true)
{
var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize);
try
{
int r = MainSerialPort.Read(byteBlock.Buffer, 0, MainSerialPort.BytesToRead);
if (r == 0)
{
this.BreakOut("远程终端主动关闭");
return;
}
byteBlock.SetLength(r);
this.HandleBuffer(byteBlock);
}
catch (Exception ex)
{
this.BreakOut(ex.Message);
return;
}
}
}
private void ProcessReceived(SerialReceivedEventArgs e)
{
if (!this.m_online)
{
e.UserToken.SafeDispose();
return;
}
if (MainSerialPort.BytesToRead > 0)
{
byte[] buffer = new byte[2048];
var byteBlock = (ByteBlock)e.UserToken;
int num = MainSerialPort.Read(buffer, 0, MainSerialPort.BytesToRead);
byteBlock.Write(buffer, 0, num);
this.HandleBuffer(byteBlock);
try
{
var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength));
newByteBlock.SetLength(num);
e.UserToken = newByteBlock;
if (MainSerialPort.BytesToRead > 0)
{
this.m_bufferRate += 2;
this.ProcessReceived(e);
}
}
catch (Exception ex)
{
e.UserToken.SafeDispose();
this.BreakOut(ex.Message);
}
}
else
{
e.UserToken.SafeDispose();
this.BreakOut("远程终端主动关闭");
}
}
private void SetSerialPort(SerialPort serialPort)
{
if (serialPort == null)
{
return;
}
this.MainSerialPort = serialPort;
var delaySenderOption = this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty);
if (delaySenderOption != null)
{
this.m_delaySender = new DelaySender(delaySenderOption, this.MainSerialPort.AbsoluteSend);
}
}
/// <summary>
/// 处理数据
/// </summary>
private void HandleBuffer(ByteBlock byteBlock)
{
try
{
this.m_receiveCounter.Increment(byteBlock.Length);
if (this.OnHandleRawBuffer?.Invoke(byteBlock) == false)
{
return;
}
if (this.DisposedValue)
{
return;
}
if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(ITcpReceivingPlugin.OnTcpReceiving), this, new ByteBlockEventArgs(byteBlock)))
{
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);
}
finally
{
byteBlock.Dispose();
}
}
#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"><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 Task SendAsync(byte[] buffer, int offset, int length)
{
return Task.Run(() =>
{
this.Send(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)
{
return Task.Run(() =>
{
this.Send(requestInfo);
});
}
/// <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 Task SendAsync(IList<ArraySegment<byte>> transferBytes)
{
return Task.Run(() =>
{
this.Send(transferBytes);
});
}
#endregion
/// <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 void DefaultSend(byte[] buffer, int offset, int length)
{
if (!this.m_online)
{
throw new NotConnectedException(TouchSocketResource.NotConnected.GetDescription());
}
if (this.HandleSendingData(buffer, offset, length))
{
if (this.m_delaySender != null && length < m_delaySender.DelayLength)
{
this.m_delaySender.Send(QueueDataBytes.CreateNew(buffer, offset, length));
}
else
{
this.MainSerialPort.AbsoluteSend(buffer, offset, length);
}
this.m_sendCounter.Increment(length);
}
}
/// <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 Task DefaultSendAsync(byte[] buffer, int offset, int length)
{
return Task.Run(() =>
{
this.DefaultSend(buffer, offset, length);
});
}
#endregion
}

View File

@@ -1,392 +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.Net.Security;
using System.Net.Sockets;
namespace ThingsGateway.Foundation.Sockets
{
/// <summary>
/// Tcp核心
/// </summary>
public class TcpCore : SocketAsyncEventArgs, IDisposable
{
private const string m_msg1 = "远程终端主动关闭";
#region
private long m_bufferRate;
private bool m_disposedValue;
private int m_receiveBufferSize = 64 * 1024;
private ValueCounter m_receiveCounter;
private int m_sendBufferSize = 1024 * 64;
private ValueCounter m_sendCounter;
private Stream m_workStream;
#endregion
/// <summary>
/// 创建一个Tcp核心
/// </summary>
/// <param name="socket"></param>
public TcpCore(Socket socket)
{
this.Socket = socket;
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>
~TcpCore()
{
this.Dispose(disposing: false);
}
/// <summary>
/// 当关闭的时候
/// </summary>
public Action<TcpCore, string> OnClose { get; set; }
/// <summary>
/// 当发生异常的时候
/// </summary>
public Action<TcpCore, Exception> OnException { get; set; }
/// <summary>
/// 当收到数据的时候
/// </summary>
public Action<TcpCore, ByteBlock> OnReceived { get; set; }
/// <summary>
/// 接收缓存池(可以设定初始值,运行时的值会根据流速自动调整)
/// </summary>
public int ReceiveBufferSize
{
get => m_receiveBufferSize;
set
{
m_receiveBufferSize = value;
this.Socket.ReceiveBufferSize = value;
}
}
/// <summary>
/// 发送缓存池(可以设定初始值,运行时的值会根据流速自动调整)
/// </summary>
public int SendBufferSize
{
get => this.m_sendBufferSize;
set
{
this.m_sendBufferSize = value;
this.Socket.SendBufferSize = value;
}
}
/// <summary>
/// Socket
/// </summary>
public Socket Socket { get; }
/// <summary>
/// 是否启用了Ssl
/// </summary>
public bool UseSsl { get; private set; }
/// <summary>
/// 以Ssl服务器模式授权
/// </summary>
/// <param name="sslOption"></param>
public virtual void Authenticate(ServiceSslOption sslOption)
{
var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false);
sslStream.AuthenticateAsServer(sslOption.Certificate);
this.m_workStream = sslStream;
this.UseSsl = true;
}
/// <summary>
/// 以Ssl客户端模式授权
/// </summary>
/// <param name="sslOption"></param>
public virtual void Authenticate(ClientSslOption sslOption)
{
var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false);
if (sslOption.ClientCertificates == null)
{
sslStream.AuthenticateAsClient(sslOption.TargetHost);
}
else
{
sslStream.AuthenticateAsClient(sslOption.TargetHost, sslOption.ClientCertificates, sslOption.SslProtocols, sslOption.CheckCertificateRevocation);
}
this.m_workStream = sslStream;
this.UseSsl = true;
}
/// <summary>
/// 以Ssl服务器模式授权
/// </summary>
/// <param name="sslOption"></param>
/// <returns></returns>
public virtual async Task AuthenticateAsync(ServiceSslOption sslOption)
{
var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false);
await sslStream.AuthenticateAsServerAsync(sslOption.Certificate);
this.m_workStream = sslStream;
this.UseSsl = true;
}
/// <summary>
/// 以Ssl客户端模式授权
/// </summary>
/// <param name="sslOption"></param>
/// <returns></returns>
public virtual async Task AuthenticateAsync(ClientSslOption sslOption)
{
var sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.Socket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.Socket, false), false);
if (sslOption.ClientCertificates == null)
{
await sslStream.AuthenticateAsClientAsync(sslOption.TargetHost);
}
else
{
await sslStream.AuthenticateAsClientAsync(sslOption.TargetHost, sslOption.ClientCertificates, sslOption.SslProtocols, sslOption.CheckCertificateRevocation);
}
this.m_workStream = sslStream;
this.UseSsl = true;
}
/// <summary>
/// 开始以Iocp方式接收
/// </summary>
public virtual void BeginIocpReceive()
{
var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize);
this.UserToken = byteBlock;
this.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity);
if (!this.Socket.ReceiveAsync(this))
{
this.ProcessReceived(this);
}
}
/// <summary>
/// 开始以Ssl接收。
/// <para>
/// 注意,使用该方法时,应先完成授权。
/// </para>
/// </summary>
/// <returns></returns>
public async Task BeginSslReceive()
{
if (!this.UseSsl)
{
throw new Exception("请先完成Ssl验证授权");
}
while (true)
{
var byteBlock = new ByteBlock(this.ReceiveBufferSize);
try
{
var r = await Task<int>.Factory.FromAsync(this.m_workStream.BeginRead, this.m_workStream.EndRead, byteBlock.Buffer, 0, byteBlock.Capacity, default);
if (r == 0)
{
this.Close(m_msg1);
return;
}
byteBlock.SetLength(r);
this.HandleBuffer(byteBlock);
}
catch (Exception ex)
{
byteBlock.Dispose();
this.Close(ex.Message);
}
}
}
/// <summary>
/// 释放对象
/// </summary>
public new void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
this.Dispose(disposing: true);
GC.SuppressFinalize(this);
}
/// <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)
{
if (this.UseSsl)
{
this.m_workStream.Write(buffer, offset, length);
}
else
{
this.Socket.AbsoluteSend(buffer, offset, length);
}
this.m_sendCounter.Increment(length);
}
/// <summary>
/// 当关闭的时候
/// </summary>
/// <param name="msg"></param>
protected virtual void Close(string msg)
{
this.OnClose?.Invoke(this, msg);
}
/// <summary>
/// 释放对象
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!m_disposedValue)
{
if (disposing)
{
}
this.m_disposedValue = true;
}
base.Dispose();
}
/// <summary>
/// 当发生异常的时候
/// </summary>
/// <param name="ex"></param>
protected virtual void Exception(Exception ex)
{
this.OnException?.Invoke(this, ex);
}
/// <inheritdoc/>
protected override sealed void OnCompleted(SocketAsyncEventArgs e)
{
if (e.LastOperation == SocketAsyncOperation.Receive)
{
try
{
this.m_bufferRate = 1;
this.ProcessReceived(e);
}
catch (Exception ex)
{
e.SafeDispose();
this.Close(ex.Message);
}
}
}
/// <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.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value);
}
private void OnSendPeriod(long value)
{
this.SendBufferSize = TouchSocketUtility.HitBufferLength(value);
}
private void ProcessReceived(SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
e.SafeDispose();
this.Close(e.SocketError.ToString());
return;
}
else if (e.BytesTransferred > 0)
{
var byteBlock = (ByteBlock)e.UserToken;
byteBlock.SetLength(e.BytesTransferred);
this.HandleBuffer(byteBlock);
try
{
var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength));
e.UserToken = newByteBlock;
e.SetBuffer(newByteBlock.Buffer, 0, newByteBlock.Capacity);
if (!this.Socket.ReceiveAsync(e))
{
this.m_bufferRate += 2;
this.ProcessReceived(e);
}
}
catch (Exception ex)
{
e.SafeDispose();
this.Close(ex.Message);
}
}
else
{
e.SafeDispose();
this.Close(m_msg1);
}
}
}
}

View File

@@ -1,88 +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.Net;
/// <summary>
/// 显示信息
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate void MessageEventHandler<TClient>(TClient client, MsgPermitEventArgs e);
/// <summary>
/// 普通通知
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate void TouchSocketEventHandler<TClient>(TClient client, PluginEventArgs e);
/// <summary>
/// Id修改通知
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate void IdChangedEventHandler<TClient>(TClient client, IdChangedEventArgs e);
/// <summary>
/// Connecting
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate void ConnectingEventHandler<TClient>(TClient client, ConnectingEventArgs e);
/// <summary>
/// Connected
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate void ConnectedEventHandler<TClient>(TClient client, ConnectedEventArgs e);
/// <summary>
/// 客户端断开连接
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate void DisconnectEventHandler<TClient>(TClient client, DisconnectEventArgs e);
/// <summary>
/// 接收数据
/// </summary>
/// <param name="client"></param>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
public delegate void ReceivedEventHandler<TClient>(TClient client, ByteBlock byteBlock, IRequestInfo requestInfo);
/// <summary>
/// UDP接收
/// </summary>
/// <param name="endpoint"></param>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
public delegate void UdpReceivedEventHandler(EndPoint endpoint, ByteBlock byteBlock, IRequestInfo requestInfo);

View File

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

View File

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

View File

@@ -1,362 +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.Sockets;
internal class WaitingClient<TClient> : DisposableObject, IWaitingClient<TClient> where TClient : IClient, IDefaultSender, ISender
{
private readonly Func<ResponsedData, bool> m_func;
private readonly EasyLock easyLock = new();
private readonly WaitData<ResponsedData> m_waitData = new();
private readonly WaitDataAsync<ResponsedData> m_waitDataAsync = new();
private volatile bool m_breaked;
public WaitingClient(TClient client, WaitingOptions waitingOptions, Func<ResponsedData, bool> func)
{
this.Client = client ?? throw new ArgumentNullException(nameof(client));
this.WaitingOptions = waitingOptions;
this.m_func = func;
}
public WaitingClient(TClient client, WaitingOptions waitingOptions)
{
this.Client = client ?? throw new ArgumentNullException(nameof(client));
this.WaitingOptions = waitingOptions;
}
public bool CanSend
{
get
{
return this.Client is ITcpClientBase tcpClient ? tcpClient.CanSend : this.Client is IUdpSession;
}
}
public TClient Client { get; private set; }
public WaitingOptions WaitingOptions { get; set; }
protected override void Dispose(bool disposing)
{
this.Client = default;
this.m_waitData.SafeDispose();
this.m_waitDataAsync.SafeDispose();
base.Dispose(disposing);
}
private void Cancel()
{
this.m_waitData.Cancel();
this.m_waitDataAsync.Cancel();
}
private void OnDisconnected(ITcpClientBase client, DisconnectEventArgs e)
{
this.m_breaked = true;
this.Cancel();
}
private void OnSerialSessionDisconnected(ISerialSessionBase client, DisconnectEventArgs e)
{
this.m_breaked = true;
this.Cancel();
}
private bool OnHandleRawBuffer(ByteBlock byteBlock)
{
var responsedData = new ResponsedData(byteBlock.ToArray(), null, true);
if (this.m_func == null || this.m_func.Invoke(responsedData))
{
return !this.Set(responsedData);
}
else
{
return true;
}
}
private bool OnHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
ResponsedData responsedData;
if (byteBlock != null)
{
responsedData = new ResponsedData(byteBlock.ToArray(), requestInfo, false);
}
else
{
responsedData = new ResponsedData(null, requestInfo, false);
}
if (this.m_func == null || this.m_func.Invoke(responsedData))
{
return !this.Set(responsedData);
}
else
{
return true;
}
}
private void Reset()
{
this.m_waitData.Reset();
this.m_waitDataAsync.Reset();
}
#region Response
public ResponsedData SendThenResponse(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
try
{
easyLock.Wait();
this.m_breaked = false;
this.Reset();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
{
tcpClient.Disconnected += this.OnDisconnected;
}
if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
{
serialSession.Disconnected += this.OnSerialSessionDisconnected;
}
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
{
this.Client.OnHandleReceivedData += this.OnHandleReceivedData;
}
else
{
this.Client.OnHandleRawBuffer += this.OnHandleRawBuffer;
}
if (this.WaitingOptions.RemoteIPHost != null && this.Client is IUdpSession session)
{
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
{
session.Send(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
}
else
{
session.DefaultSend(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
}
}
else
{
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
{
this.Client.Send(buffer, offset, length);
}
else
{
this.Client.DefaultSend(buffer, offset, length);
}
}
this.m_waitData.SetCancellationToken(cancellationToken);
switch (this.m_waitData.Wait(timeout))
{
case WaitDataStatus.SetRunning:
return this.m_waitData.WaitResult;
case WaitDataStatus.Overtime:
throw new TimeoutException();
case WaitDataStatus.Canceled:
{
return this.WaitingOptions.ThrowBreakException && this.m_breaked ? throw new Exception("等待已终止。可能是客户端已掉线,或者被注销。") : (ResponsedData)default;
}
case WaitDataStatus.Default:
case WaitDataStatus.Disposed:
default:
throw new Exception("未知错误");
}
}
finally
{
easyLock.Release();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
{
tcpClient.Disconnected -= this.OnDisconnected;
}
if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
{
serialSession.Disconnected -= this.OnSerialSessionDisconnected;
}
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
{
this.Client.OnHandleReceivedData -= this.OnHandleReceivedData;
}
else
{
this.Client.OnHandleRawBuffer -= this.OnHandleRawBuffer;
}
}
}
public ResponsedData SendThenResponse(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return this.SendThenResponse(buffer, 0, buffer.Length, timeout, cancellationToken);
}
public ResponsedData SendThenResponse(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return this.SendThenResponse(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken);
}
#endregion Response
#region Response异步
public async Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
try
{
await easyLock.WaitAsync();
this.m_breaked = false;
this.Reset();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
{
tcpClient.Disconnected += this.OnDisconnected;
}
if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
{
serialSession.Disconnected += this.OnSerialSessionDisconnected;
}
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
{
this.Client.OnHandleReceivedData += this.OnHandleReceivedData;
}
else
{
this.Client.OnHandleRawBuffer += this.OnHandleRawBuffer;
}
if (this.WaitingOptions.RemoteIPHost != null && this.Client is IUdpSession session)
{
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
{
session.Send(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
}
else
{
session.DefaultSend(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
}
}
else
{
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
{
this.Client.Send(buffer, offset, length);
}
else
{
this.Client.DefaultSend(buffer, offset, length);
}
}
this.m_waitDataAsync.SetCancellationToken(cancellationToken);
switch (await this.m_waitDataAsync.WaitAsync(timeout))
{
case WaitDataStatus.SetRunning:
return this.m_waitData.WaitResult;
case WaitDataStatus.Overtime:
throw new TimeoutException();
case WaitDataStatus.Canceled:
{
return this.WaitingOptions.ThrowBreakException && this.m_breaked ? throw new Exception("等待已终止。可能是客户端已掉线,或者被注销。") : (ResponsedData)default;
}
case WaitDataStatus.Default:
case WaitDataStatus.Disposed:
default:
throw new Exception("未知错误");
}
}
finally
{
easyLock.Release();
if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
{
tcpClient.Disconnected -= this.OnDisconnected;
}
if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
{
serialSession.Disconnected -= this.OnSerialSessionDisconnected;
}
if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
{
this.Client.OnHandleReceivedData -= this.OnHandleReceivedData;
}
else
{
this.Client.OnHandleRawBuffer -= this.OnHandleRawBuffer;
}
}
}
public Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return this.SendThenResponseAsync(buffer, 0, buffer.Length, timeout, cancellationToken);
}
public Task<ResponsedData> SendThenResponseAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return this.SendThenResponseAsync(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken);
}
#endregion Response异步
#region
public byte[] SendThenReturn(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return this.SendThenResponse(buffer, offset, length, timeout, cancellationToken).Data;
}
public byte[] SendThenReturn(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return this.SendThenReturn(buffer, 0, buffer.Length, timeout, cancellationToken);
}
public byte[] SendThenReturn(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return this.SendThenReturn(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken);
}
#endregion
#region
public async Task<byte[]> SendThenReturnAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return (await this.SendThenResponseAsync(buffer, offset, length, timeout, cancellationToken)).Data;
}
public async Task<byte[]> SendThenReturnAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return (await this.SendThenResponseAsync(buffer, 0, buffer.Length, timeout, cancellationToken)).Data;
}
public async Task<byte[]> SendThenReturnAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
{
return (await this.SendThenResponseAsync(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken)).Data;
}
#endregion
private bool Set(ResponsedData responsedData)
{
this.m_waitData.Set(responsedData);
this.m_waitDataAsync.Set(responsedData);
return true;
}
}

View File

@@ -1,45 +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.Sockets;
/// <summary>
/// WaitingClientExtensions
/// </summary>
public static class WaitingClientExtension
{
/// <summary>
/// 获取筛选条件的可等待的客户端。
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="waitingOptions"></param>
/// <param name="func">当条件成立时返回</param>
/// <returns></returns>
public static IWaitingClient<TClient> GetWaitingClientEx<TClient>(this TClient client, WaitingOptions waitingOptions, Func<ResponsedData, bool> func) where TClient : IClient, IDefaultSender, ISender
{
return new WaitingClient<TClient>(client, waitingOptions, func);
}
/// <summary>
/// 获取可等待的客户端。
/// </summary>
/// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="waitingOptions"></param>
/// <returns></returns>
public static IWaitingClient<TClient> GetWaitingClientEx<TClient>(this TClient client, WaitingOptions waitingOptions) where TClient : IClient, IDefaultSender, ISender
{
var waitingClient = new WaitingClient<TClient>(client, waitingOptions);
return waitingClient;
}
}

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,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;
@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, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
else
{
if (exVariableTimerTick.IsTickHappen())
{
try
{
var varList = _uploadVariables.Adapt<List<VariableData>>();
if (varList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = varList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in varData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await KafKaUp(driverPropertys.VariableTopic, item.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage.LogWarning(ex, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
if (!driverPropertys.IsInterval)
{
////变化推送
var devList = _collectDeviceRunTimes.ToListWithDequeue();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await KafKaUp(driverPropertys.DeviceTopic, item.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
else
{
if (exDeviceTimerTick.IsTickHappen())
{
var devList = _collectDevice.Adapt<List<DeviceData>>();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var devData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in devData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
await KafKaUp(driverPropertys.DeviceTopic, item.ToJsonString(), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
if (isSuccess)
producer.Flush(cancellationToken);
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override bool IsConnected() => isSuccess;
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_collectDevice.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ForEach(a =>
{
a.DeviceStatusChange -= DeviceStatusChange;
});
_uploadVariables?.ForEach(a =>
{
a.VariableValueChange -= VariableValueChange;
});
producer?.Dispose();
_uploadVariables = null;
_collectDeviceRunTimes.Clear();
_collectVariableRunTimes.Clear();
base.Dispose(disposing);
}
private List<CollectDeviceRunTime> _collectDevice;
/// <summary>
/// 初始化
/// </summary>
/// <param name="device"></param>
protected override void Init(UploadDeviceRunTime device)
{
#region Kafka
//1、生产者配置
producerconfig = new ProducerConfig
{
BootstrapServers = driverPropertys.BootStrapServers,
ClientId = driverPropertys.ClientId,
};
//2、创建生产者
producerBuilder = new ProducerBuilder<Null, string>(producerconfig);
//3、错误日志监视
producerBuilder.SetErrorHandler((p, msg) =>
{
isSuccess = false;
LogMessage?.LogWarning(msg.Reason);
});
//kafka
try
{
producer = producerBuilder.Build();
}
catch (DllNotFoundException)
{
if (!Library.IsLoaded)
{
string fileEx = ".dll";
string osStr = "win-";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
osStr = "win-";
fileEx = ".dll";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
osStr = "linux-";
fileEx = ".so";
}
else
{
osStr = "osx-";
fileEx = ".dylib";
}
osStr += RuntimeInformation.ProcessArchitecture.ToString().ToLower();
var pathToLibrd = System.IO.Path.Combine(AppContext.BaseDirectory, "Plugins", "ThingsGateway.Plugin.Kafka", "runtimes", osStr, "native", $"librdkafka{fileEx}");
Library.Load(pathToLibrd);
}
producer = producerBuilder.Build();
}
#endregion
_globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).GetBoolValue()).ToList();
_uploadVariables = tags;
_collectDevice = _globalDeviceData.CollectDevices.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ToList();
_collectDevice.ForEach(a =>
{
a.DeviceStatusChange += DeviceStatusChange;
});
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
if (driverPropertys.UploadInterval <= 1000) driverPropertys.UploadInterval = 1000;
exVariableTimerTick = new(driverPropertys.UploadInterval);
exDeviceTimerTick = new(driverPropertys.UploadInterval);
}
private void DeviceStatusChange(CollectDeviceRunTime collectDeviceRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectDeviceRunTimes.Enqueue(collectDeviceRunTime.Adapt<DeviceData>());
}
private async Task KafKaUp(string topic, string payLoad, CancellationToken cancellationToken)
{
try
{
using CancellationTokenSource cancellationTokenSource = new();
using CancellationTokenSource stoppingToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, cancellationToken);
Task<DeliveryResult<Null, string>> resultTask = producer.ProduceAsync(topic, new Message<Null, string> { Value = payLoad }, stoppingToken.Token);
var timeOutResult = await Task.WhenAny(resultTask, Task.Delay(driverPropertys.TimeOut, stoppingToken.Token));
if (timeOutResult == resultTask)
{
var result = (timeOutResult as Task<DeliveryResult<Null, string>>).Result;
if (result.Status != PersistenceStatus.Persisted)
{
isSuccess = false;
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
else
{
isSuccess = true;
//连接成功时补发缓存数据
var cacheData = await CacheDb.GetCacheData();
foreach (var item in cacheData)
{
var cacheResult = await producer.ProduceAsync(item.Topic, new Message<Null, string> { Value = item.CacheStr }, stoppingToken.Token);
if (cacheResult.Status == PersistenceStatus.Persisted)
{
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{item.Topic}{Environment.NewLine}负载:{item.CacheStr}");
await CacheDb.DeleteCacheData(item.Id);
}
}
LogMessage.Trace($"{FoundationConst.LogMessageHeader}主题:{topic}{Environment.NewLine}负载:{payLoad}");
}
}
else
{
isSuccess = false;
stoppingToken.Cancel();
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
await CacheDb.AddCacheData(topic, payLoad, driverPropertys.CacheMaxCount);
}
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (driverPropertys?.IsInterval != true)
_collectVariableRunTimes.Enqueue(collectVariableRunTime.Adapt<VariableData>());
}
}

View File

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

View File

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

View File

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

View File

@@ -1,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
using Furion;
using Microsoft.Extensions.Logging;
using SqlSugar;
using System.Collections.Concurrent;
using ThingsGateway.Foundation.Adapter.Modbus;
using ThingsGateway.Foundation.Extension;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
public class ModbusSerialServer : UpLoadBase
{
private readonly ModbusSerialServerProperty driverPropertys = new();
private readonly ModbusSerialServerVariableProperty variablePropertys = new();
private Dictionary<ModbusAddress, DeviceVariableRunTime> _ModbusTags;
private ThingsGateway.Foundation.Adapter.Modbus.ModbusSerialServer _plc;
private ConcurrentQueue<(string, DeviceVariableRunTime)> Values = new();
/// <inheritdoc/>
public override Type DriverDebugUIType => typeof(ModbusSerialServerDebugPage);
/// <inheritdoc/>
public override UpDriverPropertyBase DriverPropertys => driverPropertys;
/// <inheritdoc/>
public override List<DeviceVariableRunTime> UploadVariables => _ModbusTags?.Values.ToList();
/// <inheritdoc/>
public override VariablePropertyBase VariablePropertys => variablePropertys;
RpcSingletonService RpcCore { get; set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task BeforStartAsync(CancellationToken cancellationToken)
{
return _plc?.ConnectAsync(cancellationToken);
}
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var list = Values.ToListWithDequeue();
foreach (var item in list)
{
if (cancellationToken.IsCancellationRequested)
break;
var type = GetPropertyValue(item.Item2, nameof(ModbusSerialServerVariableProperty.ModbusType));
if (Enum.TryParse<DataTypeEnum>(type, out DataTypeEnum result))
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, result, cancellationToken);
}
else
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, item.Item2.DataTypeEnum, cancellationToken);
}
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <inheritdoc/>
public override bool IsConnected()
{
return _plc?.SerialSession?.CanSend == true;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
_ModbusTags?.Values?.ToList()?.ForEach(a => a.VariableValueChange -= VariableValueChange);
if (_plc != null)
_plc.WriteData -= WriteData;
_plc?.Disconnect();
_plc?.SafeDispose();
_ModbusTags?.Clear();
_ModbusTags = null;
Values?.Clear();
Values = null;
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(UploadDeviceRunTime device)
{
var service = new SerialSession();
FoundataionConfig.SetSerialProperty(new()
{
PortName = driverPropertys.PortName,
BaudRate = driverPropertys.BaudRate,
DataBits = driverPropertys.DataBits,
Parity = driverPropertys.Parity,
StopBits = driverPropertys.StopBits,
})
;
service = new SerialSession();
((SerialSession)service).Setup(FoundataionConfig);
//载入配置
_plc = new(service)
{
DataFormat = driverPropertys.DataFormat,
Station = driverPropertys.Station,
CacheTimeout = driverPropertys.CacheTimeout,
MulStation = driverPropertys.MulStation
};
var _globalDeviceData = App.GetService<GlobalDeviceData>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => !string.IsNullOrEmpty(GetPropertyValue(b, nameof(variablePropertys.ServiceAddress))))
.ToList();
tags.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
VariableValueChange(a);
});
_plc.WriteData += WriteData;
try
{
_ModbusTags = tags.ToDictionary(a =>
{
ModbusAddress address = ModbusAddress.ParseFrom(
GetPropertyValue(a, nameof(variablePropertys.ServiceAddress))
, driverPropertys.Station);
return address;
});
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
tags.ForEach(a =>
{
a.VariableValueChange -= VariableValueChange;
});
_plc.WriteData -= WriteData;
}
RpcCore = App.GetService<RpcSingletonService>();
}
/// <inheritdoc/>
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
var address = GetPropertyValue(collectVariableRunTime, nameof(variablePropertys.ServiceAddress));
if (address != null && collectVariableRunTime.Value != null)
{
Values?.Enqueue((address, collectVariableRunTime));
}
}
/// <summary>
/// RPC写入
/// </summary>
/// <param name="address"></param>
/// <param name="bytes"></param>
/// <param name="thingsGatewayBitConverter"></param>
/// <param name="client"></param>
/// <returns></returns>
private 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 resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusSerialServer)}-{CurrentDevice.Name}",
new Dictionary<string, string>
{
{
tag.Value.Name,
thingsGatewayBitConverter.GetDataFormBytes(addressStr , bytes,result).ToString()
},
}
);
var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult();
return result1.FirstOrDefault().Value;
}
else
{
var resultTask1 = RpcCore.InvokeDeviceMethodAsync($"{nameof(ModbusSerialServer)}-{CurrentDevice.Name}",
new Dictionary<string, string>
{
{
tag.Value.Name,
thingsGatewayBitConverter.GetDataFormBytes(addressStr , bytes,result).ToString()
},
}
);
var result1 = resultTask1.ConfigureAwait(true).GetAwaiter().GetResult();
return result1.FirstOrDefault().Value;
}
}
catch (Exception ex)
{
return new OperResult(ex.Message);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,59 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/ModbusRtu"
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation;
@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,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;
@using ThingsGateway.Foundation.Extension.String;
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Core;
@using ThingsGateway.Gateway.Application;
@using ThingsGateway.Gateway.Core;

View File

@@ -1,18 +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 ThingsGateway.Components;
global using ThingsGateway.Foundation;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;
global using ThingsGateway.Gateway.Application;
global using ThingsGateway.Gateway.Core;

View File

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

View File

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

View File

@@ -1,364 +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.Internal;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System.Collections.Concurrent;
using System.Net;
using System.Text;
using ThingsGateway.Admin.Application;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.Generic;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.Mqtt;
/// <summary>
/// MqttServer
/// </summary>
public class MqttServer : UpLoadBase
{
private readonly MqttServerProperty driverPropertys = new();
private readonly MqttClientVariableProperty variablePropertys = new();
private ConcurrentQueue<DeviceData> _collectDeviceRunTimes = new();
private ConcurrentQueue<VariableData> _collectVariableRunTimes = new();
private GlobalDeviceData _globalDeviceData;
private MQTTnet.Server.MqttServer _mqttServer;
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;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override Task AfterStopAsync()
{
return Task.CompletedTask;
}
/// <inheritdoc/>
public override async Task BeforStartAsync(CancellationToken cancellationToken)
{
if (_mqttServer != null)
{
_mqttServer.ValidatingConnectionAsync += MqttServer_ValidatingConnectionAsync;
_mqttServer.InterceptingPublishAsync += MqttServer_InterceptingPublishAsync;
_mqttServer.LoadingRetainedMessageAsync += MqttServer_LoadingRetainedMessageAsync;
_mqttServer.InterceptingSubscriptionAsync += MqttServer_InterceptingSubscriptionAsync; ;
await _mqttServer.StartAsync();
}
}
/// <inheritdoc/>
public override async Task ExecuteAsync(CancellationToken cancellationToken)
{
try
{
////变化推送
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)
{
var message = new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.VariableTopic}")
.WithPayload(item.GetSciptListValue(driverPropertys.BigTextScriptVariableModel)).Build();
await _mqttServer.InjectApplicationMessage(
new InjectedMqttApplicationMessage(message), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
////变化推送
var devList = _collectDeviceRunTimes.ToListWithDequeue();
if (devList?.Count != 0)
{
//分解List避免超出mqtt字节大小限制
var varData = devList.ChunkTrivialBetter(driverPropertys.SplitSize);
foreach (var item in varData)
{
try
{
if (!cancellationToken.IsCancellationRequested)
{
var message = new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.DeviceTopic}")
.WithPayload(item.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel)).Build();
await _mqttServer.InjectApplicationMessage(
new InjectedMqttApplicationMessage(message), cancellationToken);
}
else
{
break;
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
}
}
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
if (driverPropertys.CycleInterval > UploadDeviceThread.CycleInterval + 50)
{
try
{
await Task.Delay(driverPropertys.CycleInterval - UploadDeviceThread.CycleInterval, cancellationToken);
}
catch
{
}
}
else
{
}
}
/// <inheritdoc/>
public override bool IsConnected() => _mqttServer?.IsStarted == true;
/// <inheritdoc/>
public override string ToString()
{
return $" {nameof(MqttServer)} IP:{driverPropertys.IP} Port:{driverPropertys.Port}";
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (_mqttServer != null)
{
_mqttServer.ValidatingConnectionAsync -= MqttServer_ValidatingConnectionAsync;
_mqttServer.InterceptingPublishAsync -= MqttServer_InterceptingPublishAsync;
_mqttServer.LoadingRetainedMessageAsync -= MqttServer_LoadingRetainedMessageAsync;
_mqttServer.InterceptingSubscriptionAsync -= MqttServer_InterceptingSubscriptionAsync; ;
_mqttServer?.SafeDispose();
}
_globalDeviceData?.AllVariables?.ForEach(a => a.VariableValueChange -= VariableValueChange);
_globalDeviceData?.CollectDevices?.ForEach(a =>
{
a.DeviceStatusChange -= DeviceStatusChange;
});
_uploadVariables = null;
_collectDeviceRunTimes.Clear();
_collectVariableRunTimes.Clear();
_collectDeviceRunTimes = null;
_collectVariableRunTimes = null;
base.Dispose(disposing);
}
/// <inheritdoc/>
protected override void Init(UploadDeviceRunTime device)
{
var mqttFactory = new MqttFactory(new PrivateLogger(LogMessage));
var mqttServerOptions = mqttFactory.CreateServerOptionsBuilder()
.WithDefaultEndpointBoundIPAddress(string.IsNullOrEmpty(driverPropertys.IP) ? null : IPAddress.Parse(driverPropertys.IP))
.WithDefaultEndpointPort(driverPropertys.Port)
.WithDefaultEndpoint()
.Build();
_mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions);
_globalDeviceData = App.GetService<GlobalDeviceData>();
_rpcCore = App.GetService<RpcSingletonService>();
var tags = _globalDeviceData.AllVariables.Where(a => a.VariablePropertys.ContainsKey(device.Id))
.Where(b => GetPropertyValue(b, nameof(variablePropertys.Enable)).GetBoolValue())
.ToList();
_uploadVariables = tags;
_globalDeviceData.CollectDevices.Where(a => _uploadVariables.Select(b => b.DeviceId).Contains(a.Id)).ForEach(a =>
{
a.DeviceStatusChange += DeviceStatusChange;
});
_uploadVariables.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
});
}
private void DeviceStatusChange(CollectDeviceRunTime collectDeviceRunTime)
{
_collectDeviceRunTimes.Enqueue(collectDeviceRunTime.Adapt<DeviceData>());
}
private async Task MqttServer_InterceptingPublishAsync(InterceptingPublishEventArgs arg)
{
if (!driverPropertys.DeviceRpcEnable || string.IsNullOrEmpty(arg.ClientId))
return;
if (arg.ApplicationMessage.Topic != driverPropertys.RpcWriteTopic)
return;
var rpcDatas = Encoding.UTF8.GetString(arg.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 OperResult("权限不足,变量不支持写入"));
}
}
else
{
mqttRpcResult.Success = false;
mqttRpcResult.Message.Add(rpcData.Key, new OperResult("不存在该变量"));
}
}
var result = await _rpcCore.InvokeDeviceMethodAsync(ToString() + "-" + arg.ClientId,
rpcDatas.WriteInfos.Where(
a => !mqttRpcResult.Message.Any(b => b.Key == a.Key)).ToDictionary(a => a.Key, a => a.Value));
mqttRpcResult.Message.AddRange(result);
mqttRpcResult.Success = !mqttRpcResult.Message.Any(a => !a.Value.IsSuccess);
}
catch (Exception ex)
{
LogMessage?.LogWarning(ex, ToString());
}
try
{
var variableMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.RpcSubTopic}")
.WithPayload(mqttRpcResult.ToJsonString()).Build();
await _mqttServer.InjectApplicationMessage(
new InjectedMqttApplicationMessage(variableMessage));
}
catch
{
}
}
private Task MqttServer_InterceptingSubscriptionAsync(InterceptingSubscriptionEventArgs arg)
{
if (arg.TopicFilter.Topic == driverPropertys.RpcWriteTopic)
{
arg.Response.ReasonCode = MqttSubscribeReasonCode.UnspecifiedError;
}
return CompletedTask.Instance;
}
private Task MqttServer_LoadingRetainedMessageAsync(LoadingRetainedMessagesEventArgs arg)
{
//首次连接时的保留消息
//分解List避免超出mqtt字节大小限制
var varData = _globalDeviceData.AllVariables.Adapt<List<VariableData>>().ChunkTrivialBetter(driverPropertys.SplitSize);
var devData = _globalDeviceData.AllVariables.Adapt<List<DeviceData>>().ChunkTrivialBetter(driverPropertys.SplitSize);
List<MqttApplicationMessage> Messages = new();
foreach (var item in varData)
{
Messages.Add(new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.VariableTopic}")
.WithPayload(item.GetSciptListValue(driverPropertys.BigTextScriptVariableModel)).Build());
}
foreach (var item in devData)
{
Messages.Add(new MqttApplicationMessageBuilder()
.WithTopic($"{driverPropertys.DeviceTopic}")
.WithPayload(item.GetSciptListValue(driverPropertys.BigTextScriptDeviceModel)).Build());
}
arg.LoadedRetainedMessages = Messages;
return CompletedTask.Instance;
}
private async Task MqttServer_ValidatingConnectionAsync(ValidatingConnectionEventArgs arg)
{
if (!arg.ClientId.StartsWith(driverPropertys.StartWithId))
{
arg.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid;
return;
}
var _openApiUserService = App.GetService<IOpenApiUserService>();
var userInfo = await _openApiUserService.GetUserByAccountAsync(arg.UserName);//获取用户信息
if (userInfo == null)
{
arg.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
return;
}
if (userInfo.Password != arg.Password)
{
arg.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
return;
}
LogMessage?.LogInformation($"{ToString()}-{arg.ClientId}-客户端已连接成功");
}
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
_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;
@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,154 +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]
private InitTimezone InitTimezone { get; set; }
[Inject]
IPopupService PopupService { get; set; }
/// <inheritdoc/>
public void Dispose()
{
mqttClientPage.SafeDispose();
}
/// <inheritdoc/>
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
if (mqttClientPage != null)
{
mqttClientPage.LogAction = driverDebugUIPage.LogOut;
}
//初始化
driverDebugUIPage.Address = "ThingsGateway/Variable";
driverDebugUIPage.WriteValue = new MqttRpcNameVaueWithId()
{
RpcId = Guid.NewGuid().ToString(),
WriteInfos = new Dictionary<string, string>()
{
{ "tag1", "123" }
}
}.ToJsonString();
;
mqttClientPage.IP = "127.0.0.1";
mqttClientPage.Port = 1883;
mqttClientPage.UserName = "admin";
mqttClientPage.Password = "111111";
mqttClientPage.StateHasChangedAsync();
//载入配置
StateHasChanged();
driverDebugUIPage.Sections.Clear();
}
base.OnAfterRender(firstRender);
}
private async Task SubscribeAsync()
{
try
{
var mqttSubscribeOptions = mqttClientPage.MqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic(driverDebugUIPage.Address);
})
.Build();
await mqttClientPage.MqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + $"订阅{driverDebugUIPage.Address}成功"));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
private async Task UnsubscribeAsync()
{
try
{
var mqttSubscribeOptions = mqttClientPage.MqttFactory.CreateUnsubscribeOptionsBuilder()
.WithTopicFilter(driverDebugUIPage.Address)
.Build();
await mqttClientPage.MqttClient.UnsubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + $"取消订阅{driverDebugUIPage.Address}成功"));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
string PublishTopic;
string PublishValue;
private async Task PublishAsync()
{
try
{
var devMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{PublishTopic}")
.WithPayload(PublishValue).Build();
await mqttClientPage.MqttClient.PublishAsync(devMessage, CancellationToken.None);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + $"发布{PublishTopic}成功"));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
MqttRpcTopicPair MqttRpcTopicPair = new() { RequestTopic = "ThingsGateway/RpcWrite", ResponseTopic = "ThingsGateway/RpcSub" };
private async Task RpcExecuteAsync()
{
try
{
using MqttRpcClient mqttRpcClient = new(mqttClientPage.MqttClient);
var data = await mqttRpcClient.ExecuteAsync(MqttRpcTopicPair, driverDebugUIPage.WriteValue, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce, TimeSpan.FromSeconds(10));
var str = Encoding.UTF8.GetString(data);
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + str));
}
catch (Exception ex)
{
driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(driverDebugUIPage.InitTimezone.TimezoneOffset) + " - " + ex.Message));
}
}
}

View File

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

View File

@@ -1,51 +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;
using ThingsGateway.Foundation;
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,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;
@using ThingsGateway.Foundation.Extension.String;
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Core;
@using ThingsGateway.Gateway.Application;
@using ThingsGateway.Gateway.Core;

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;
@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,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;
@using ThingsGateway.Foundation.Extension.String;
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Core;
@using ThingsGateway.Gateway.Application;
@using ThingsGateway.Gateway.Core;

View File

@@ -1,18 +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 ThingsGateway.Components;
global using ThingsGateway.Foundation;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;
global using ThingsGateway.Gateway.Application;
global using ThingsGateway.Gateway.Core;

View File

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

View File

@@ -1,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;
@using ThingsGateway.Foundation.Extension.String;
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Core;
@using ThingsGateway.Gateway.Application;
@using ThingsGateway.Gateway.Core;

View File

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

View File

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

View File

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

View File

@@ -1,68 +0,0 @@
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@
@page "/S7_200SMART"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation;
@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;
@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_400"
@namespace ThingsGateway.Foundation.Demo
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation.Adapter.Siemens;
@using ThingsGateway.Foundation;
@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;
@using ThingsGateway.Foundation.Extension.String;
@using ThingsGateway.Admin.Application;
@using ThingsGateway.Core;
@using ThingsGateway.Gateway.Application;
@using ThingsGateway.Gateway.Core;

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command=" set dir=&quot;$(SolutionDir)Web\ThingsGateway.Web.Entry\bin\$(Configuration)\$(TargetFramework)\&quot;&#xD;&#xA; if not exist %25dir%25 md %25dir%25 &#xD;&#xA;copy &quot;$(TargetDir)*DLT645*.dll&quot; %25dir%25&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" />
</Target>
</Project>

View File

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

View File

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

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