Compare commits

..

665 Commits

Author SHA1 Message Date
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
Kimdiego2098
24bc60abf0 fix:signalR razor dispose接口 2023-10-09 18:11:23 +08:00
Kimdiego2098
31eee6b009 update uaparser 2023-10-09 10:56:22 +08:00
Kimdiego2098
c5da565a8f 添加MqttRpcDemo 2023-10-07 12:04:17 +08:00
Kimdiego2098
947cd712e1 添加清理日志任务配置参数 2023-10-06 18:28:06 +08:00
Kimdiego2098
edc208f96b update 3.0.0.2 2023-10-05 15:32:50 +08:00
Diego2098
1fb0296ee7 update Directory.Build.props 2023-10-05 15:21:51 +08:00
Kimdiego2098
6488d3df87 修复重启共享通道中的单个设备时,导致通道内其他设备变量异常 2023-10-05 00:34:12 +08:00
Kimdiego2098
56189d78e0 update opcuaclient 2023-10-04 17:12:47 +08:00
Kimdiego2098
bff18127b8 update opcuaclient 2023-10-04 16:59:15 +08:00
Kimdiego2098
363206e0ba update nuget 2023-10-04 02:04:09 +08:00
Kimdiego2098
fd3e378501 update 3.0.0.1 2023-10-04 01:42:27 +08:00
Kimdiego2098
4ba2fe4c9d 实时报警列表线程同步 2023-10-04 01:27:03 +08:00
Kimdiego2098
2c499626ad modbusRtu 适配器 过滤干扰头部数据 2023-10-04 01:26:44 +08:00
Kimdiego2098
2b581a03c3 更新种子数据 2023-10-04 01:24:34 +08:00
Kimdiego2098
450c15210a update windowsService bat 2023-10-03 19:11:42 +08:00
Kimdiego2098
65fed8cc93 update demo 2023-10-03 18:54:01 +08:00
Kimdiego2098
4b64771ea2 rpc调用提示优化 2023-10-03 18:20:39 +08:00
Kimdiego2098
f39977a6ff fix:rpc 特殊方法分类错误 2023-10-03 17:05:49 +08:00
Kimdiego2098
933b535caa update demo 2023-10-02 22:37:50 +08:00
Kimdiego2098
8abc5d2f20 update driverDebugPage 2023-10-02 18:34:55 +08:00
Kimdiego2098
d8783cd994 update opcuaClient 2023-10-02 18:30:58 +08:00
Diego2098
d5d087feb5 add s7 wstring addressSign 2023-10-01 16:54:42 +08:00
Diego2098
6ba3399df7 add s7 wstring addressSign 2023-10-01 16:49:07 +08:00
Diego2098
65124b3aa8 更新demo 2023-10-01 13:33:25 +08:00
Kimdiego2098
98597f4726 update demo csproj 2023-10-01 00:33:33 +08:00
Kimdiego2098
e7981f0d8e add EncodingMapper 2023-10-01 00:25:04 +08:00
Kimdiego2098
cf654427c3 更新文档 2023-09-30 23:28:50 +08:00
Kimdiego2098
ff2f628282 默认不启用远程更新 2023-09-30 23:23:44 +08:00
Kimdiego2098
ae818ca265 更新readme 2023-09-30 23:09:48 +08:00
Kimdiego2098
0f2aed458e 同步3.0.0版本代码 2023-09-30 23:05:53 +08:00
Kimdiego2098
d486c44ff6 更新文档 2023-09-26 20:03:58 +08:00
Kimdiego2098
ca7b9980bf 2.1.0.15 2023-09-20 11:50:06 +08:00
Kimdiego2098
3c71e6a8e3 2.1.0.15 2023-09-20 11:47:10 +08:00
Kimdiego2098
542442864c 添加kafka/mq/iotsharp的间隔上传 2023-09-20 11:46:17 +08:00
Diego2098
5edb64fa85 fix:上传设备选择驱动时没有正确刷新 2023-09-18 00:10:02 +08:00
Kimdiego2098
8dc1c898a3 2.1.0.14 2023-09-15 14:02:15 +08:00
Kimdiego2098
1ed35726b0 ExpressionEvaluator改为多实例 2023-09-15 14:01:54 +08:00
Kimdiego2098
27fae9ebaa 2.1.0.13 2023-09-15 13:23:59 +08:00
Kimdiego2098
b103f25c94 add dispose() 2023-09-15 13:23:39 +08:00
Kimdiego2098
abff450274 2.1.0.12 2023-09-15 13:20:29 +08:00
Kimdiego2098
c260736a11 更新多个依赖包版本 2023-09-15 13:19:04 +08:00
Kimdiego2098
166ac2307a 修复因重复注册cancellationToken.Register导致的内存暴涨! 2023-09-15 13:17:36 +08:00
Kimdiego2098
b21a4e1a4d CancellationToken代替CancellationTokenSource传入 2023-09-15 13:16:56 +08:00
Kimdiego2098
f7dc943fa3 2.1.0.11 2023-09-11 09:35:24 +08:00
Kimdiego2098
bfbd2693ec feat:ManageGatewayWorker part 2023-09-11 09:31:26 +08:00
Kimdiego2098
819e71c993 feat:ManageGatewayWorker part 2023-09-11 09:09:48 +08:00
Kimdiego2098
9fd0b489a2 feat:ManageGatewayWorker part 2023-09-11 09:09:03 +08:00
Kimdiego2098
f5fe9f8dae TGAPPInfp更名APPInfo 2023-09-11 08:57:13 +08:00
Kimdiego2098
f9ffc18145 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-09-11 08:54:01 +08:00
Kimdiego2098
08db5b983a feat:ManageGatewayWorker part 2023-09-11 08:53:52 +08:00
Diego2098
5b3b4c8c50 !7 修复无法修改变量值问题
Merge pull request !7 from 如阳如木/master
2023-09-07 10:14:45 +00:00
如阳如木
73f914ffc4 删除&& LastSetValue?.ToString() != data?.ToString()
Signed-off-by: 如阳如木 <970143933@qq.com>
2023-09-07 08:42:49 +00:00
Kimdiego2098
d6bdd73ed6 ManageGatewayConfig.json 2023-09-06 17:29:58 +08:00
Kimdiego2098
7370ee7349 fix:_mqttServer null error 2023-09-06 17:27:36 +08:00
Kimdiego2098
4574596bac 2.1.0.10 2023-09-06 17:16:28 +08:00
Kimdiego2098
4d16855e36 从数据库取原属性 2023-09-06 17:14:24 +08:00
Kimdiego2098
13a0d4d282 更改变量 最近一次值 为 上次值 2023-09-06 16:44:58 +08:00
Kimdiego2098
b9cd06b829 更改 变量最近一次值 为 上次值 2023-09-06 16:44:42 +08:00
Kimdiego2098
5b460e8fa2 2.1.0.9 2023-09-06 16:30:50 +08:00
Kimdiego2098
41087edf17 fix:串口断连/拔出/断电等情况,重新连接 2023-09-06 16:29:48 +08:00
Kimdiego2098
2afcc38e38 feat:ManageGatewayWorker part 2023-09-06 16:15:38 +08:00
Kimdiego2098
e59ccce25f feat:ManageGatewayWorker part 2023-09-06 16:10:29 +08:00
Kimdiego2098
d7425890e8 feat:ManageGatewayWorker part 2023-09-05 23:59:18 +08:00
Kimdiego2098
a989a837fb feat:ManageGatewayWorker part 2023-09-05 23:37:02 +08:00
Kimdiego2098
db1221da50 feat:ManageGatewayWorker part 2023-09-05 23:33:02 +08:00
Kimdiego2098
cf794569ed 2.1.0.8 2023-09-05 09:19:58 +08:00
Kimdiego2098
51e5bbab0d fix:PeriodicTimer dispose 2023-09-05 09:17:26 +08:00
Kimdiego2098
2c197ed2b2 2.1.0.7 2023-09-05 09:06:39 +08:00
Kimdiego2098
d8fc6665b3 fix:error!the stream dispose 2023-09-05 09:04:34 +08:00
Kimdiego2098
c671a79822 Revert "fix:error!the stearm dispose"
This reverts commit a6d99fe227.
2023-09-05 09:03:49 +08:00
Kimdiego2098
9d93ce4c41 feat:mqttBroker part 2023-09-05 08:58:49 +08:00
Kimdiego2098
a6d99fe227 fix:error!the stearm dispose 2023-09-05 08:57:42 +08:00
Diego2098
923b8bca31 feat:mqttBroker part 2023-09-04 22:34:31 +08:00
Diego2098
e2c30d1c88 fix:uploadDeivce复制多个,ID重复问题 2023-09-04 22:11:50 +08:00
Diego2098
b6d9f2a04e 刷新后选择行清空 2023-09-04 22:09:26 +08:00
Diego2098
57306ea664 fix:采集设备线程初始化时更新活跃时间 2023-09-04 20:13:49 +08:00
Diego2098
cd7f3fd02f fix:特殊情况下无法获取程序集文件修改日期,所以去除 页脚-编译时间显示 2023-09-04 19:49:17 +08:00
Kimdiego2098
0482e077a8 fix:sqlsugar json支持类型改为bigstring 2023-09-04 17:09:38 +08:00
Kimdiego2098
5f986a45ca 更新文档 2023-09-04 15:03:03 +08:00
Kimdiego2098
ca7b49c0d5 恢复Sqlite默认数据库 2023-09-02 19:17:32 +08:00
Kimdiego2098
52dd555e6c fix: page取消注入瞬时服务,改为App.GetService 2023-09-02 19:13:57 +08:00
Kimdiego2098
579b1a59f9 feat:mqttBroker part 2023-09-02 13:55:21 +08:00
Kimdiego2098
5299c5c4be 更新文档 2023-08-31 09:17:59 +08:00
Kimdiego2098
f7756bccef 更新 变量管理-上传设备筛选功能 2023-08-31 08:58:30 +08:00
Kimdiego2098
a6b874d160 2.1.0.6 2023-08-30 17:19:18 +08:00
Kimdiego2098
3e5fb3ddcf add windows service create/delete bat 2023-08-30 17:18:35 +08:00
Kimdiego2098
5e6bcb12d3 update statusPage; 2023-08-30 14:12:50 +08:00
Kimdiego2098
14303f1429 默认检测重连频率为10分钟 2023-08-29 17:56:59 +08:00
Kimdiego2098
96711ba022 2.1.0.5 2023-08-29 17:44:28 +08:00
Kimdiego2098
cbfc0fdbdc 添加报文日志入库选项 2023-08-29 17:42:56 +08:00
Kimdiego2098
6e81886c0e 添加 页脚 编译时间显示 2023-08-29 17:01:46 +08:00
Kimdiego2098
2d976bc132 调整导入excel错误提示 2023-08-29 16:45:54 +08:00
Kimdiego2098
57f6a476af update opcdaclient null error 2023-08-29 15:24:29 +08:00
Kimdiego2098
8491ed296e update GetBoolValue 2023-08-29 12:40:21 +08:00
Kimdiego2098
cd1288afdc 调整种子文件,增加Pro版本种子文件录入 2023-08-29 09:42:54 +08:00
Kimdiego2098
ec6c830cb0 更新2.1.0.4 2023-08-28 19:31:00 +08:00
Kimdiego2098
2f86ccc4bf 修复串口基类 缓存包 失效错误;完善modbusrtu长度校验 2023-08-28 19:25:22 +08:00
Kimdiego2098
8ca445aec0 更新touchsocket版本,更新2.1.0.3 2023-08-28 18:12:18 +08:00
Kimdiego2098
1e1f27c8a5 修复浏览大量节点空间时,BrowseNext方法参数releaseContinuationPoints改为false 2023-08-28 17:44:02 +08:00
Kimdiego2098
2b84bde367 修复调试界面-opcuaclient浏览节点展开逻辑错误 2023-08-28 10:51:35 +08:00
Kimdiego2098
b52e58551d 更新小版本2.1.0.2 2023-08-27 17:17:37 +08:00
Kimdiego2098
9aceed00bf 更新dlt645地址说明 2023-08-27 17:16:59 +08:00
Kimdiego2098
58814f7f74 添加日志查询 时间区间条件 2023-08-27 16:58:45 +08:00
Kimdiego2098
6a70ef9f31 2.1.0.1 2023-08-27 16:31:03 +08:00
Kimdiego2098
82cc4ca500 dlt645添加数据标识校验 2023-08-27 16:30:32 +08:00
Kimdiego2098
4567fa04ed 更新dlt645,添加地址/控制码的校验规则 2023-08-27 16:15:51 +08:00
Kimdiego2098
8b98b5d818 更新touchsocket 2023-08-27 15:59:57 +08:00
Kimdiego2098
176d0351af 更新 Opc.Ua Version="1.4.372.56" 2023-08-27 14:33:24 +08:00
Kimdiego2098
d63dc3384b opcda/ua浏览地址空间 初始只加载首层节点 2023-08-27 14:14:47 +08:00
Kimdiego2098
1ccd704e30 opcuaclient浏览地址空间 初始只加载首层节点 2023-08-27 13:06:03 +08:00
Diego2098
f5d23dbe79 update MqttNetLogger 2023-08-26 21:38:14 +08:00
Diego2098
75bfe53ac3 update MqttNetLogger 2023-08-26 20:40:23 +08:00
Diego2098
3308f916dd 添加在线/离线方法参数 2023-08-26 17:18:47 +08:00
Diego2098
e7140279ca 更新opcuaclient 2023-08-26 15:38:22 +08:00
Diego2098
1034719f5e 更新opcuaclient,添加checkDomain属性,去除多余代码,更新SelectEndpoint方法 2023-08-26 15:33:03 +08:00
Kimdiego2098
2c00043a7f 更新文档 2023-08-25 19:49:02 +08:00
Kimdiego2098
65c695d9ce 更新版本2.1.0 2023-08-25 19:45:28 +08:00
Kimdiego2098
57253fe46a 更新解决方案 2023-08-25 19:38:47 +08:00
Kimdiego2098
4e5c443440 更新DLT645文档 2023-08-25 19:33:33 +08:00
Kimdiego2098
0b3b73d8ec 添加DLT645_2007协议插件 2023-08-25 19:33:08 +08:00
Kimdiego2098
921eabc134 调整Test位置 2023-08-25 19:32:27 +08:00
Kimdiego2098
0faa428751 调整非主从协议的状态判断策略;OPCUA去除主动连接 2023-08-25 17:23:00 +08:00
Kimdiego2098
f71a2fdd63 crc校验优化 2023-08-22 17:01:10 +08:00
Kimdiego2098
4eb9ed8aba OPCUAClient添加是否使用SourceTime的选项 2023-08-22 16:15:34 +08:00
Kimdiego2098
d7b549abb8 更新文档 2023-08-22 12:21:45 +08:00
Kimdiego2098
95d723c578 2.0.9.3 2023-08-22 11:31:36 +08:00
Kimdiego2098
2fcd853e86 去除mqtt throw an _MqttConnectingFailedException_.报错信息 2023-08-22 11:26:22 +08:00
Kimdiego2098
07eef7c812 更新批量写入方法,注意rpc入口参数变化,mqtt等RPC接口参数变化 2023-08-22 11:23:03 +08:00
Kimdiego2098
b01e0757fa 修正部分代码格式 2023-08-21 19:59:07 +08:00
Kimdiego2098
32844a20c6 2.0.9.2 2023-08-19 12:08:49 +08:00
Kimdiego2098
5b6532c601 xml 2023-08-19 11:06:05 +08:00
Kimdiego2098
2c5b4b4027 修复TcpClient重复释放导致锁异常 2023-08-19 11:05:29 +08:00
Kimdiego2098
72d7ecf195 mas1.0.2默认中文 2023-08-18 18:36:30 +08:00
Kimdiego2098
2cfa6b4306 更新masa1.0.2 2023-08-18 13:59:17 +08:00
Kimdiego2098
6f6ffde0ab 2.0.9.1 2023-08-18 13:33:45 +08:00
Kimdiego2098
1694739a16 修改锁为EasyLock 2023-08-18 12:07:01 +08:00
Kimdiego2098
95d1e8bfca 代码文件编码统一utf-8 2023-08-18 09:57:03 +08:00
Kimdiego2098
60dec08e3c 更换DEMO Include为PackageReference 2023-08-17 15:30:35 +08:00
Kimdiego2098
a99d71be93 底层驱动添加netstandard输出 2023-08-17 15:24:07 +08:00
Kimdiego2098
f1331b6a0c 2.0.8 2023-08-17 10:58:48 +08:00
Kimdiego2098
10d66b642b 调整readme,方便copy账密 2023-08-17 10:28:47 +08:00
Kimdiego2098
cd2310e4a8 优化变量地址输入分割方法;s7读写字符串添加默认编码 2023-08-17 09:50:10 +08:00
Kimdiego2098
1b399cf6b0 优化s7读写字符串,更改特殊方法为读写共用 2023-08-16 17:20:20 +08:00
Kimdiego2098
877445bc0a 修复写入返回结果时的解析,0XFF为成功 2023-08-16 15:56:25 +08:00
Kimdiego2098
9a5b345bde 修复s7字符串打包读取 2023-08-16 15:47:37 +08:00
Kimdiego2098
fc9e8ea7b3 修复s7字符串读取 2023-08-16 15:35:15 +08:00
Kimdiego2098
32be6fcfc1 主动释放锁 2023-08-16 14:56:47 +08:00
Kimdiego2098
49847236c2 OPCUA死区不再固定传入 2023-08-16 14:21:19 +08:00
Kimdiego2098
d8424443e6 fix: 优化JsonUtils中的获取type语句顺序 2023-08-16 08:59:18 +08:00
Kimdiego2098
f3b571ec3f OPC系列增加导出excel/导入系统双选项 2023-08-15 17:38:40 +08:00
Kimdiego2098
99318bb5d7 OPCUA采集设备写入字符串,不再需要传入双引号 2023-08-15 14:15:39 +08:00
Kimdiego2098
1aa154c9aa 历史数据/报警 线程初始化时不再阻塞 2023-08-15 12:12:00 +08:00
Kimdiego2098
c65d8a445b 更改ItemGroup Condition条件 2023-08-14 17:36:59 +08:00
Kimdiego2098
80f4f85570 传播token;
更新admin解决方案
2023-08-14 16:43:30 +08:00
Kimdiego2098
5beee43a6b 优化适配器解析代码 2023-08-14 14:21:00 +08:00
Kimdiego2098
8d6ae203a0 2.0.6 2023-08-13 16:57:12 +08:00
Kimdiego2098
4353479a5c OPCUACClient订阅初始化添加trycatch 2023-08-13 16:29:59 +08:00
Kimdiego2098
34d7687f9e Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-08-13 15:53:33 +08:00
Kimdiego2098
b1dc3cf4af 更新opcuaclient,初始读取server类型改为动态读取 2023-08-13 15:50:47 +08:00
Diego2098
6a58b95933 更新nuget包 2023-08-12 12:09:50 +08:00
Kimdiego2098
d3badfd02b 修复批量令牌强退失效 2023-08-11 15:15:50 +08:00
Kimdiego2098
0098be057b 中间变量导入时添加标识 2023-08-11 14:15:22 +08:00
Kimdiego2098
6f972aa515 2.0.5 2023-08-10 18:23:40 +08:00
Kimdiego2098
7407ba6313 去除不需要的模板 2023-08-10 16:28:52 +08:00
Kimdiego2098
1c79de207b 修改详情模板 2023-08-10 11:23:18 +08:00
Kimdiego2098
257c79db92 添加自定义详情模板 2023-08-10 10:35:19 +08:00
Kimdiego2098
9d1934a308 底层修改:如果连接端口断开,停止等待返回 2023-08-10 10:35:01 +08:00
Kimdiego2098
d70f959902 上传DTO添加 单位 参数 2023-08-10 09:09:09 +08:00
Kimdiego2098
e4d810222f 调整调试页面 2023-08-09 23:45:53 +08:00
Kimdiego2098
bc1af4ae07 添加单文件发布配置 2023-08-09 15:12:55 +08:00
Kimdiego2098
6e688ef43f 去除页面多余引号 2023-08-09 13:45:27 +08:00
Kimdiego2098
f0fe1b23dc 更新2.0.4 2023-08-09 13:00:10 +08:00
Kimdiego2098
aaf2006401 更新opcua写入 2023-08-09 12:43:05 +08:00
Kimdiego2098
b821e26935 更新opcua调试页面 2023-08-09 12:01:23 +08:00
Kimdiego2098
7ae4287157 更新opcua 2023-08-09 11:47:04 +08:00
Kimdiego2098
c6fcc38a65 修复中间变量导入错误 2023-08-09 09:00:49 +08:00
Kimdiego2098
ab2d5c8853 修正错误注释 2023-08-08 18:09:23 +08:00
Kimdiego2098
5e557ff0bc opcua添加初始化连接错误重试 2023-08-08 18:04:24 +08:00
Kimdiego2098
918ca449a1 更新readme 2023-08-08 16:14:06 +08:00
Kimdiego2098
8e73368008 优化大量设备线程重启的耗时 2023-08-08 14:02:00 +08:00
Kimdiego2098
f3c1faf672 2.0.3 2023-08-08 12:59:14 +08:00
Kimdiego2098
d6df04dd6a 底层部分方法更改 2023-08-08 12:31:42 +08:00
Kimdiego2098
b1b9e51ab6 报警/历史值查询时区转换 2023-08-08 09:05:15 +08:00
Kimdiego2098
e49d4770ac 时间最小最大值时不再转换时区 2023-08-08 08:39:20 +08:00
Kimdiego2098
8fa1075511 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-08-08 08:28:37 +08:00
Kimdiego2098
9a70169b94 默认不启用单用户登录 2023-08-08 08:28:27 +08:00
Diego2098
fefb928237 更新文档 2023-08-07 22:31:51 +08:00
Diego2098
ad7e700d0d 去除DateTimeOffset类型 2023-08-07 22:30:38 +08:00
Kimdiego2098
1699c69147 更新文档 2023-08-07 17:38:53 +08:00
Kimdiego2098
1695f7cece 更新readme 2023-08-07 17:34:32 +08:00
Kimdiego2098
052c27f907 更新文件 2023-08-07 17:24:28 +08:00
Kimdiego2098
dc46c32b30 更新文件 2023-08-07 17:16:53 +08:00
Kimdiego2098
fa63349bb2 更新文件 2023-08-07 16:56:45 +08:00
Kimdiego2098
ffe26448a6 更新文件 2023-08-07 16:33:36 +08:00
Kimdiego2098
4af51e8a84 更新文件 2023-08-07 16:30:23 +08:00
Kimdiego2098
1e453cf5a5 更新文件 2023-08-07 15:46:30 +08:00
Kimdiego2098
591282b87d 更新文件 2023-08-07 15:36:49 +08:00
Kimdiego2098
e87528d520 去除多余解决方案配置 2023-08-07 15:31:22 +08:00
Kimdiego2098
d79eb0411d 添加发布脚本 2023-08-07 15:23:53 +08:00
Kimdiego2098
ac1e0a4cf7 更新readme 2023-08-07 15:18:42 +08:00
Kimdiego2098
9525eab130 更新readme 2023-08-07 15:13:21 +08:00
Kimdiego2098
89b317496c 更新文档 2023-08-07 15:10:42 +08:00
Kimdiego2098
13be91e78b 2.0.0 2023-08-07 15:09:53 +08:00
Kimdiego2098
f68c1437f3 调试更新Blazor代码时不再跳转登录界面 2023-07-25 22:00:27 +08:00
Kimdiego2098
4c64c969bb 取消不必要的错误日志 2023-07-25 20:50:33 +08:00
Kimdiego2098
b4bf3b5138 变量值更新错误提示; 2023-07-25 20:48:17 +08:00
Kimdiego2098
083bc4b400 优化大批量excel变量表导入效率 2023-07-25 18:26:48 +08:00
Kimdiego2098
e8683c5bcc 删除不必要延时 2023-07-25 16:52:56 +08:00
Kimdiego2098
80e0d1de91 发布1.7.6 2023-07-25 14:22:11 +08:00
Kimdiego2098
dbe841037e 优化导入excel效率 2023-07-25 14:21:17 +08:00
Kimdiego2098
bdd537c33c 添加上传插件获取采集设备属性值的快捷方法 2023-07-23 13:44:37 +08:00
Kimdiego2098
c0c3846094 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-07-23 09:59:11 +08:00
Kimdiego2098
9e8710e7d2 线程完成时不再需要全局数据移除,有可能会导致偶发全局数据丢失 2023-07-23 09:58:43 +08:00
Kimdiego2098
475553fdf6 线程完成时不要需要全局数据移除,有可能会导致偶发全局数据丢失 2023-07-23 09:57:03 +08:00
Kimdiego2098
9d570f5b45 更新icon包版本 2023-07-23 00:03:46 +08:00
Kimdiego2098
af7fafd34f 更新icon包版本 2023-07-22 23:59:03 +08:00
Kimdiego2098
d43130f4fc 修改插件日志为自定义日志 2023-07-22 23:34:09 +08:00
Kimdiego2098
7500194620 更新文档 2023-07-22 20:48:29 +08:00
Kimdiego2098
eb27c29144 发布1.7.4 2023-07-22 20:47:26 +08:00
Kimdiego2098
43260b3e24 修正错误名称 2023-07-22 20:32:34 +08:00
Kimdiego2098
f80713f0aa 添加上传插件最后错误原因 2023-07-22 20:10:45 +08:00
Kimdiego2098
0c4bdc7ad1 修复上传设备暂停按钮失效 2023-07-22 19:56:56 +08:00
Kimdiego2098
811cff7bd0 OPCUAServer 数组维度不再写any;rpc写入添加延时 2023-07-22 17:02:44 +08:00
Kimdiego2098
30269aa75c 更改假死检测间隔5分钟 2023-07-22 11:05:56 +08:00
Kimdiego2098
e345ef7083 添加OPCUAServer线程间隔配置项,优化最后一次错误提示 2023-07-22 11:03:56 +08:00
Kimdiego2098
f559c9b8f7 支持OPCUAServer数组类型,添加缓存文件存在判断 2023-07-21 21:28:39 +08:00
Kimdiego2098
f4af0916b2 去除OPCUA写入数组维度校验 2023-07-20 17:37:49 +08:00
Kimdiego2098
f15f14f28d 更新文档 2023-07-20 12:48:13 +08:00
Kimdiego2098
834f44f58d kafka尝试自动加载c库 2023-07-20 12:40:59 +08:00
Kimdiego2098
b36f45dcf4 修复中间变量Rpc写入 2023-07-20 10:55:37 +08:00
Kimdiego2098
11ba21c9a8 ModbusServer添加自定义循环间隔,修复中间变量写入 2023-07-20 10:55:17 +08:00
Kimdiego2098
b045557ce1 更新文档 2023-07-19 18:02:31 +08:00
Kimdiego2098
0dd251a3f6 更新文档 2023-07-19 15:43:28 +08:00
Kimdiego2098
793acb1725 更改左侧菜单为手风琴效果 2023-07-19 15:00:40 +08:00
Kimdiego2098
921243e8bd 更新文档 2023-07-19 14:34:27 +08:00
Kimdiego2098
bd9d7a90d9 修改OPCUAClient心跳频率默认3s 2023-07-18 14:49:27 +08:00
Kimdiego2098
cc444a4cea 更改OPCUAClient心跳频率为30000 2023-07-18 14:15:02 +08:00
Kimdiego2098
38ca1fa168 更新1.7.3版本 2023-07-18 12:16:33 +08:00
Kimdiego2098
7a552b87ec 更新masa 稳定版以及其他包 2023-07-18 12:11:37 +08:00
Kimdiego2098
36923d3190 修复添加订阅时,值死区过滤逻辑 2023-07-18 11:13:21 +08:00
Kimdiego2098
a9d3017123 修复异步锁上下文切换导致OPCUA 心跳事件出错 2023-07-18 09:58:01 +08:00
Kimdiego2098
313acd4976 修复OPCUAClient调试界面重复输出订阅值 2023-07-18 08:51:27 +08:00
Kimdiego2098
a4c91bb268 修改OPCUAClient的心跳频率配置项 2023-07-18 08:48:18 +08:00
Kimdiego2098
f9b566984b 添加重启锁 2023-07-17 21:40:47 +08:00
2248356998 qq.com
8dd261854d Merge branch 'master' of https://gitee.com/diego2098/thingsgateway-docs 2023-07-17 20:59:53 +08:00
2248356998 qq.com
7351e62d87 更新opcua心跳状态日志 2023-07-17 20:59:32 +08:00
Diego2098
0593ae720b 更新文档 2023-07-16 20:46:16 +08:00
Diego2098
a0a7b08e08 更新授权名单 2023-07-16 20:31:56 +08:00
2248356998 qq.com
9a3bc6b8b3 更新文档 2023-07-16 18:27:22 +08:00
2248356998 qq.com
5acae17f71 更新文档 2023-07-16 18:12:55 +08:00
2248356998 qq.com
f1e5b76ef2 更新文档 2023-07-16 18:07:31 +08:00
2248356998 qq.com
53c628fde9 更新文档 2023-07-16 17:49:33 +08:00
2248356998 qq.com
baca0a70c0 更新文档 2023-07-16 17:48:22 +08:00
2248356998 qq.com
3e8d0af404 更新文档 2023-07-16 17:41:52 +08:00
2248356998 qq.com
cf9a91d9d5 更新文档 2023-07-16 17:35:04 +08:00
2248356998 qq.com
02b9e282c6 更新文档地址 2023-07-16 17:32:49 +08:00
2248356998 qq.com
9ce87f235f 迁移文档 2023-07-16 17:28:26 +08:00
2248356998 qq.com
e329bea1b2 冗余设备删除后会导致后台出错 2023-07-16 11:36:45 +08:00
2248356998 qq.com
8086e7b54d 更新readme 2023-07-16 10:28:43 +08:00
2248356998 qq.com
f7a875606e 删除无用属性 2023-07-16 09:40:00 +08:00
2248356998 qq.com
196eaf85f4 修复1.7.0版本修改导致的mqttrpc映射错误 2023-07-15 22:56:28 +08:00
2248356998 qq.com
876a55668e 增加 上传插件的列表分割大小,因为某些情况下传输字节太大会导致失败 2023-07-15 22:42:34 +08:00
2248356998 qq.com
05bd21bdd5 导入提示的当前行显示未初始 2023-07-15 22:35:12 +08:00
2248356998 qq.com
fb51a08cc6 格式化整理 2023-07-15 22:32:54 +08:00
2248356998 qq.com
dd83d7f4d3 插件报文截取前200字符,防止页面渲染过多 2023-07-15 20:04:14 +08:00
2248356998 qq.com
842a56f7ce kafka插件增加超时选项 2023-07-15 17:27:35 +08:00
2248356998 qq.com
9246a6e797 历史服务修复变量在线状态显示错误 2023-07-15 15:46:39 +08:00
2248356998 qq.com
8ad693f717 发布1.7.2版本 2023-07-15 11:10:29 +08:00
2248356998 qq.com
f4c2ee7cc4 优化OPCUA错误提示 2023-07-14 17:33:11 +08:00
2248356998 qq.com
6043441faa OPCUA在取消订阅时应该走读取方法 2023-07-14 17:22:19 +08:00
2248356998 qq.com
4a065c3710 优化导入excel提示 2023-07-14 16:23:42 +08:00
2248356998 qq.com
0ef800bdd7 优化导入excel提示 2023-07-14 16:23:35 +08:00
2248356998 qq.com
56eaa1910d kafka 插件释放时取消事件注册 2023-07-14 14:35:40 +08:00
2248356998 qq.com
201788e286 更改属性说明 2023-07-14 12:23:46 +08:00
2248356998 qq.com
506e0f144f 添加kafka插件null传播 2023-07-14 10:41:04 +08:00
2248356998 qq.com
72f68bfdd9 opcda JValue转object 2023-07-14 10:14:05 +08:00
2248356998 qq.com
2f9869b11d opcua读取值JValue转为object 2023-07-14 10:04:05 +08:00
2248356998 qq.com
8ffcf6498c RabbitMQ,IotSharp添加离线缓存 2023-07-13 19:54:12 +08:00
2248356998 qq.com
d224ae1923 Variable Value数据类型改为object 2023-07-13 18:18:53 +08:00
2248356998 qq.com
fed2063a19 中间变量页种子ID重复 2023-07-13 17:47:22 +08:00
2248356998 qq.com
db2810cdd7 复制设备没有及时刷新缓存 2023-07-13 17:38:45 +08:00
2248356998 qq.com
4f1a6781ef 发布1.7.1 2023-07-13 11:19:17 +08:00
2248356998 qq.com
beffa5d5a4 代码格式化 2023-07-13 11:18:36 +08:00
2248356998 qq.com
7a20f1de07 OPCDA增加数组支持,增加写入动态类型支持 2023-07-13 11:16:31 +08:00
2248356998 qq.com
cd25cf726b 优化OPCUA数组类型转换 2023-07-13 09:02:36 +08:00
2248356998 qq.com
d6b1bc3842 修复blazor界面null错误 2023-07-12 22:12:11 +08:00
2248356998 qq.com
a4385fb9bb 更新ReadMe 2023-07-12 21:33:05 +08:00
2248356998 qq.com
7045f2b8ea 删除重复文件 2023-07-12 21:30:41 +08:00
2248356998 qq.com
07ca1a4de8 更新nuget包 2023-07-12 21:21:50 +08:00
2248356998 qq.com
24f289e692 V1.7.0发布
1、增加采集通道冗余
2、优化多个界面
3、导出导入功能优化
4、增加中间变量
5、OPCUAClient支持动态类型
6、离线缓存多处覆盖,包含上传插件/历史报警/时序库
7、增加通用调试界面,增加s7调试
8、其他优化
2023-07-12 21:16:38 +08:00
2248356998 qq.com
01bcdaae2d 修复AppDataTable清空MForm模型导致筛选列清空的问题 2023-07-10 13:18:14 +08:00
2248356998 qq.com
55890008d1 修复写入s7协议 bit值 偏移错误(以byte数据块为准) 2023-07-08 17:01:44 +08:00
2248356998 qq.com
5ab9b01879 修复读取s7协议 bit值 偏移错误(以byte数据块为准) 2023-07-08 11:44:57 +08:00
2248356998 qq.com
e4abb333b3 默认添加kafka插件 种子数据 2023-07-07 17:13:00 +08:00
2248356998 qq.com
09f476c745 修复布尔量解析时反转字节导致结果值不符的错误 2023-07-06 14:05:09 +08:00
2248356998 qq.com
8806e68dce null传播 2023-07-03 14:13:00 +08:00
2248356998 qq.com
2ef1e25cd8 添加x86架构 2023-07-03 10:48:52 +08:00
2248356998 qq.com
10e7f202aa 补充插件实例内容 2023-07-02 19:50:09 +08:00
2248356998 qq.com
ccd7000c09 blazor组件初始化并行执行,导致sugar单例DB出现线程偶发错误,暂增加copyNew()解决 2023-06-29 16:42:19 +08:00
2248356998 qq.com
8ee7b798cf blazor组件初始化并行执行,导致sugar单例DB出现线程偶发错误,暂增加copyNew()解决 2023-06-29 16:36:03 +08:00
2248356998 qq.com
7733cf5bf0 sqlsugar偶发线程故障,添加copyNew方法 2023-06-28 18:54:45 +08:00
2248356998 qq.com
a05ce86dd7 登录跳转uri优化 2023-06-28 15:47:35 +08:00
2248356998 qq.com
91f51c32e8 更新开源说明 2023-06-28 10:48:33 +08:00
2248356998 qq.com
f910202bba update openapiUser datatableUI 2023-06-26 19:51:02 +08:00
2248356998 qq.com
6d77194a8f css脚本结果不采用 System.Text.Json.JsonSerializer 2023-06-26 19:44:17 +08:00
2248356998 qq.com
9deb89c15f OPCUAClient修复当变量为string类型时的数值过滤失败导致添加订阅失效 2023-06-26 19:43:00 +08:00
2248356998 qq.com
4b62a092b4 停用采集设备时,变量获取运行态出错 2023-06-26 16:43:48 +08:00
2248356998 qq.com
81c8f626f9 登录后跳转原url 2023-06-26 14:46:24 +08:00
2248356998 qq.com
3e846c42fb cookie授权验证失败时返回登录界面 2023-06-26 14:36:41 +08:00
Diego2098
63ad7fd766 更新nuget类库 2023-06-25 18:59:09 +08:00
2248356998 qq.com
9ff1e9aa34 添加报警事件None枚举 2023-06-20 13:10:58 +08:00
2248356998 qq.com
8d162b6f3d 修复cpu核心等于1时报错,修正登录错误提示 2023-06-20 09:09:08 +08:00
Diego2098
9844d10bef 修复modbusServer 初始化错误 2023-06-17 18:14:13 +08:00
2248356998 qq.com
b908fa8489 sugar添加取消令箭 2023-06-15 17:38:36 +08:00
2248356998 qq.com
15a10643a7 增加变量运行态 CollectVariableRuntime 所在设备属性 2023-06-15 16:50:08 +08:00
2248356998 qq.com
299617aca1 parallel.foreach无序体验不好,退回为foreach 2023-06-14 11:04:09 +08:00
2248356998 qq.com
45647d697a update 1.6.1 version 2023-06-13 22:39:47 +08:00
2248356998 qq.com
48f5105d38 update nuget package 2023-06-13 22:39:25 +08:00
2248356998 qq.com
fe1c741d68 update driver messagesui 2023-06-13 22:26:19 +08:00
2248356998 qq.com
fa42cc1f00 并行关闭线程 2023-06-12 14:41:08 +08:00
2248356998 qq.com
42cf5e7a81 添加mqtt/kafka上传内容显示 2023-06-12 14:40:53 +08:00
2248356998 qq.com
47905e1aa1 优化大量变量excel上传的验证过程 2023-06-12 11:35:27 +08:00
2248356998 qq.com
9a8e907df3 更新文档站点地址 2023-06-11 18:37:50 +08:00
2248356998 qq.com
106fe85582 删除docs 2023-06-11 18:22:15 +08:00
2248356998 qq.com
4b3571bd57 更新1.6.0版本 2023-06-11 17:58:57 +08:00
2248356998 qq.com
96b537401a 缓存最大默认2000 2023-06-11 17:56:34 +08:00
2248356998 qq.com
721c9eb057 添加离线缓存大小限制配置 2023-06-11 17:55:03 +08:00
2248356998 qq.com
51701bf6d6 上传插件线程等待时间改为10ms 2023-06-11 17:47:16 +08:00
2248356998 qq.com
dbde68bd56 导入变量优化 2023-06-11 17:46:23 +08:00
2248356998 qq.com
ad2c9f585a 添加mqttClient离线缓存 2023-06-11 17:45:46 +08:00
2248356998 qq.com
562093c468 添加kafka离线缓存 2023-06-11 17:45:27 +08:00
Diego2098
b0295584a3 !6 部分配置会导致SqlServer自动建库失败
Merge pull request !6 from samisgod/master
2023-06-10 06:55:34 +00:00
samisgod
208c54de98 fix db init for SqlServer 2023-06-10 14:51:29 +08:00
2248356998 qq.com
63e2d941a1 增加pwa 2023-06-09 17:53:41 +08:00
2248356998 qq.com
3956838e9c 修复停用验证码时登录失败显示null报错 2023-06-09 17:09:17 +08:00
2248356998 qq.com
abeee58bb0 统一文件编码 2023-06-09 15:04:54 +08:00
2248356998 qq.com
d5b1b49722 update solution folder 2023-06-09 14:30:53 +08:00
2248356998 qq.com
564ed03ff8 upload deviceStatusPage 2023-06-09 10:32:11 +08:00
2248356998 qq.com
70db4c76b4 update deviceStatusPage 2023-06-09 09:49:03 +08:00
2248356998 qq.com
d059f7975b remove dotNET China declaration 2023-06-09 09:10:30 +08:00
2248356998 qq.com
4e74e6dc2d add dotNET China declaration 2023-06-09 09:02:17 +08:00
Diego2098
b6deb96658 重启线程时增加运行状态界面空传播防止报错 2023-06-08 21:35:07 +08:00
2248356998 qq.com
3839e966be add upload plugin code description 2023-06-08 17:47:53 +08:00
2248356998 qq.com
3dd035849c 迁移导入变量功能到驱动调试内 2023-06-08 15:11:58 +08:00
2248356998 qq.com
3d6532b5d6 plugin unload test,but failed 2023-06-08 10:52:39 +08:00
2248356998 qq.com
bf7c175ee7 更改默认api文档为Knife4j 2023-06-07 20:34:31 +08:00
2248356998 qq.com
f84af35ed6 缓存键增加Type-TypeHandle句柄 2023-06-07 18:42:58 +08:00
2248356998 qq.com
99063b3eb1 修改OPCUA证书路径,增加默认接收不收信任证书与其选项;
OPCDA整理;
2023-06-07 18:03:57 +08:00
2248356998 qq.com
3bec18f28d 重启线程WebApi修改 2023-06-07 11:32:18 +08:00
2248356998 qq.com
15de7a7894 添加注释提示 2023-06-07 11:28:11 +08:00
2248356998 qq.com
e20e04e677 GC策略更改,大量变量实例手动清空以快速内存释放 2023-06-07 11:19:24 +08:00
2248356998 qq.com
5fc6ae2835 上传1.5.1 2023-06-06 19:37:04 +08:00
2248356998 qq.com
7d281b8c96 Merge branch 'master' of https://gitee.com/diego2098/ThingsGateway 2023-06-05 08:33:50 +08:00
Diego2098
4880b801a7 S7-TCP连接修复死锁 2023-06-02 22:20:21 +08:00
2248356998 qq.com
74e354456a 增加KINGVIEW 配置 2023-05-29 01:32:37 +08:00
2248356998 qq.com
af2e03aa36 超管用户名称不可更改 2023-05-26 00:14:05 +08:00
2248356998 qq.com
d8fa660ab6 初步添加OPCUAClient调试界面;更新依赖 2023-05-25 23:41:11 +08:00
2248356998 qq.com
1a62d48297 OPCUA安全策略添加全部选项 2023-05-25 00:59:21 +08:00
2248356998 qq.com
7ba01be13d OPCUA安全策略添加全部选项 2023-05-25 00:58:47 +08:00
2248356998 qq.com
1a83d64db7 添加OPCDAClient调试页面 2023-05-25 00:11:00 +08:00
2248356998 qq.com
5b53014c40 修改程序根目录为文件所在目录 2023-05-24 14:37:45 +08:00
2248356998 qq.com
83685340af 默认添加服务守护支持 2023-05-24 14:32:21 +08:00
2248356998 qq.com
31e0cc4dec ModbusServer添加自定义数据类型;修复发布时静态文件路径错误 2023-05-24 12:31:20 +08:00
2248356998 qq.com
56b87fc1f5 Add copyright notices 2023-05-23 23:54:28 +08:00
2248356998 qq.com
6b956a2dd7 update TGTcpClient 2023-05-23 22:42:48 +08:00
2248356998 qq.com
1937623d7d 添加Modbus系列插件调试页面;添加Modbus组包解析缓存超时时间; 2023-05-23 20:50:44 +08:00
2248356998 qq.com
3b60b10945 update HardwareInfoService 2023-05-23 12:04:04 +08:00
2248356998 qq.com
7173acd350 nuget更新 2023-05-23 11:59:28 +08:00
2248356998 qq.com
6310d87338 硬件界面添加限值防报错 2023-05-23 11:46:19 +08:00
2248356998 qq.com
49a1ed7c18 初步添加插件驱动调试页面 2023-05-22 18:50:30 +08:00
2248356998 qq.com
d426e280d9 初步添加插件驱动调试页面 2023-05-22 18:41:09 +08:00
2248356998 qq.com
6154fb29f1 Razor文件格式化清理 2023-05-22 18:40:50 +08:00
2248356998 qq.com
97d48ef9d6 删除调试代码... 2023-05-22 17:09:21 +08:00
2248356998 qq.com
88992625c4 更改变量读取间隔限制最低为10ms 2023-05-22 15:17:22 +08:00
2248356998 qq.com
bc6eb44218 明确System.Management版本 2023-05-22 14:51:02 +08:00
2248356998 qq.com
cf9ccd799d 硬件信息获取添加异常拦截 2023-05-22 14:33:30 +08:00
2248356998 qq.com
ffa0e4e771 update adapter 2023-05-22 12:42:31 +08:00
2248356998 qq.com
60fa9c196c 代码清理 2023-05-21 22:39:33 +08:00
2248356998 qq.com
df860d22fb 优化opcua质量戳提示;添加数据转换基础方法;TCP等待返回时默认断开连接立即返回 2023-05-21 10:51:56 +08:00
2248356998 qq.com
cb46ff326c modbus 组包优化 2023-05-20 21:41:16 +08:00
2248356998 qq.com
f277a853ef 类型更换 2023-05-20 17:13:14 +08:00
2248356998 qq.com
9ae34f67c3 可指定OPCUA节点数据类型 2023-05-20 15:40:17 +08:00
2248356998 qq.com
c9223218cc 更新文档 2023-05-20 13:52:23 +08:00
2248356998 qq.com
c0dd645aba 添加自定义OPCUAServer数据类型 2023-05-20 12:34:06 +08:00
2248356998 qq.com
2e948eb5b6 导入规则优化,主动抛出名称重复错误 2023-05-19 22:55:53 +08:00
2248356998 qq.com
c3276889cf 更改插件时开启刷新设备属性 2023-05-19 22:26:37 +08:00
2248356998 qq.com
a76ca8282d 判断OPCUAServer状态时增加tryCatch 2023-05-19 21:27:20 +08:00
2248356998 qq.com
8ce6b8362f 判断OPCUAServer状态时增加tryCatch 2023-05-19 21:24:56 +08:00
2248356998 qq.com
842fb12f05 优化tcp拆包组包 2023-05-19 20:28:51 +08:00
2248356998 qq.com
d63e1511af 快捷方式null错误 2023-05-19 16:33:57 +08:00
2248356998 qq.com
278783b8e0 更新依赖包 2023-05-19 16:23:21 +08:00
2248356998 qq.com
d24e3c922d UDP通讯优化 2023-05-19 16:21:42 +08:00
2248356998 qq.com
1d02cd2283 添加链路锁 2023-05-19 14:27:47 +08:00
2248356998 qq.com
8edeb82a87 分包数量显示错误 2023-05-19 10:13:48 +08:00
2248356998 qq.com
146e9279de Modbus读写锁更新 2023-05-19 10:05:54 +08:00
2248356998 qq.com
47105f50a9 Modbus读写锁更新 2023-05-19 09:53:56 +08:00
2248356998 qq.com
16c9c80f37 删除sqlsugar旧版本代码,会导致sqlite不兼容 2023-05-19 09:15:32 +08:00
2248356998 qq.com
8e7e4bc95a 适配mysql;修复写入表达式转换;优化web页面写入体验 2023-05-18 23:38:40 +08:00
2248356998 qq.com
0aa3d2f930 数据库初始化修复 2023-05-18 22:24:27 +08:00
2248356998 qq.com
ce77755a1e 数据库连接自动释放 2023-05-18 21:06:06 +08:00
2248356998 qq.com
0f31f20c87 编辑页面添加 变量 允许远程写入选项 2023-05-18 21:03:44 +08:00
2248356998 qq.com
ee6da2aaa5 修复枚举类型在mysql中类型出错的问题 2023-05-18 20:58:14 +08:00
Diego2098
a35f087cd9 修改文件大小限制 2023-05-17 22:29:59 +08:00
Diego2098
6e029b44dd 更新设备读写锁 2023-05-17 22:05:31 +08:00
2248356998 qq.com
973c0cff34 touchSocket修复UDP在windows下重置连接的问题;更新nuget 2023-05-17 16:54:33 +08:00
2248356998 qq.com
2027eea6ac 代码格式清理 2023-05-17 16:49:25 +08:00
2248356998 qq.com
2f43692f33 修复CancellationTokenSource未释放导致Linux下偶发内存问题 2023-05-17 16:44:52 +08:00
2248356998 qq.com
6d24992f88 OPCUAServer节点数据类型增加在读取表达式转换后的判断 2023-05-16 09:05:58 +08:00
Diego2098
b4388a58d6 ModbusClient添加帧前时间 2023-05-15 22:45:55 +08:00
2248356998 qq.com
158aa05fac 修复using作用域导致获取的服务可能被释放的问题 2023-05-15 19:21:35 +08:00
2248356998 qq.com
f2731bf55e nuget更新 2023-05-15 18:55:27 +08:00
2248356998 qq.com
7304e99fce mqttClient同步间隔上传的实体类 2023-05-12 18:22:06 +08:00
2248356998 qq.com
02700b83eb update mqttClient 2023-05-12 16:40:55 +08:00
2248356998 qq.com
676b25acf9 MqttClient增加间隔上传选项;更改线程循环间隔说明定义 2023-05-12 16:31:57 +08:00
Diego2098
556359ea2d update readme 2023-05-10 21:18:43 +08:00
Diego2098
b72923e0f5 增加api控制采集启停等方法 2023-05-10 21:17:34 +08:00
Diego2098
115ac9f75e 提交kafka插件 2023-05-10 21:17:09 +08:00
2248356998 qq.com
32e36f6708 update readme 2023-05-10 17:49:52 +08:00
2248356998 qq.com
d949b7a4f9 共享链路写入变量修复;Nuget更新 2023-05-10 16:33:59 +08:00
2248356998 qq.com
eae1171ff5 更新文档 2023-05-09 17:51:55 +08:00
2248356998 qq.com
76a1b75a51 更新文档 2023-05-09 17:47:22 +08:00
2248356998 qq.com
8882c0daea OPCUAClient/Server 修改证书有效期为100年 2023-05-09 14:37:18 +08:00
2248356998 qq.com
07ebc16d59 添加控制台logo 2023-05-08 18:10:07 +08:00
2248356998 qq.com
0ceb109964 Code Cleanup 2023-05-08 18:03:32 +08:00
2248356998 qq.com
118b0d0038 add GetSciptValue 2023-05-08 17:45:13 +08:00
2248356998 qq.com
5e87067792 modbus rtu 粘包优化 2023-05-08 15:59:35 +08:00
2248356998 qq.com
c946a252e8 modbus rtu报文粘包优化;共享链路切换延时;上传插件添加报文界面 2023-05-08 15:57:33 +08:00
2248356998 qq.com
f9ad2ba1dd plc read with CancellationToken 2023-05-08 13:33:01 +08:00
2248356998 qq.com
0d0ecd33bd 粘包优化 2023-05-08 10:55:16 +08:00
2248356998 qq.com
e4b98fd05b Rpc条件bug修复 2023-05-07 18:06:27 +08:00
2248356998 qq.com
95a5933303 OPCUAServer修复匿名登录 2023-05-07 18:06:09 +08:00
2248356998 qq.com
da3b55fa64 更新文档 2023-05-07 16:56:41 +08:00
2248356998 qq.com
fbbabfb90e 属性顺序调整 2023-05-05 09:46:11 +08:00
2248356998 qq.com
f13da6830d 更新文档 2023-05-04 22:58:36 +08:00
2248356998 qq.com
f560a8e2f8 update CollectDeviceThread 2023-05-04 10:58:45 +08:00
2248356998 qq.com
56f1139c2f 更新文档 2023-05-02 22:11:55 +08:00
2248356998 qq.com
773bdfc1e2 更新1.5.0 2023-05-02 22:06:09 +08:00
2248356998 qq.com
f449666628 1、共享链路支持;
2、设备报文查看;
3、采集线程重构;
2023-05-02 21:58:11 +08:00
2248356998 qq.com
3f282de0ab mqtt重连锁优化 2023-04-27 11:19:32 +08:00
2248356998 qq.com
440dd8d22f 添加常用转换 2023-04-24 17:54:00 +08:00
2248356998 qq.com
dcff9de2f7 masa更新 2023-04-24 11:16:28 +08:00
2248356998 qq.com
a192866543 更新包 2023-04-24 09:26:47 +08:00
Diego2098
10081416de 报警后台服务去除多余接口
Signed-off-by: Diego2098 <2248356998@qq.com>
2023-04-19 00:48:13 +00:00
2248356998 qq.com
e2bed618f9 添加docker文件 2023-04-17 17:39:12 +08:00
2248356998 qq.com
03ab1f3823 单文件发布 2023-04-17 15:13:40 +08:00
2248356998 qq.com
ac8aeb63d9 update SqlSugarConfig 2023-04-17 11:58:41 +08:00
2248356998 qq.com
2e16d822fa 删除其他信息 2023-04-17 11:05:38 +08:00
2248356998 qq.com
e407d873fa 验证码更新修复 2023-04-17 09:05:44 +08:00
2248356998 qq.com
fd712a1dbe 1、字段null约束修改
2、ModbusServer绑定端口优化
2023-04-16 15:02:09 +08:00
2248356998 qq.com
e9028b40ce 更新readme 2023-04-16 13:34:29 +08:00
2248356998 qq.com
c9da3dee7c 更新1.4.0
注意Excel导入已不适用以前版本
1、去除动态更新插件
2、改用MiniExcel,支持动态导入,excel配置更简单
3、优化多处界面与后台逻辑,部分方法规范更名
4、修复外网地址获取错误等
2023-04-15 20:48:56 +08:00
2248356998 qq.com
c8c224e202 修复报警文本逻辑 2023-04-11 13:40:13 +08:00
2248356998 qq.com
f34559daaf 1,修复控制台报错(echarts.js问题,已删除)2,多处Dispose修正 2023-04-07 08:48:34 +08:00
2248356998 qq.com
9fefbf4c27 过滤 2023-04-06 14:46:24 +08:00
2248356998 qq.com
1af9fd73ea 历史数据库选择为sqlite时查询转换日期错误 2023-04-05 18:04:33 +08:00
2248356998 qq.com
75ef394eff 启用开发环境web详细日志,调整App.Razor位置,添加网页ico 2023-04-05 17:14:26 +08:00
2248356998 qq.com
ec6cc2c63e update console/file datetime format 2023-04-05 15:49:00 +08:00
2248356998 qq.com
06bc2e192b 更新readme 2023-04-04 18:41:56 +08:00
2248356998 qq.com
78701ec7c1 😀版本1.3.1 2023-04-04 17:55:52 +08:00
2248356998 qq.com
c925fab7e4 网关软件时间统一UTC 2023-04-04 17:55:15 +08:00
2248356998 qq.com
42fd72c164 update iotSharpClient 2023-04-04 11:07:05 +08:00
2248356998 qq.com
7fd160e1a2 😀 更新1.3.0 2023-04-04 10:15:34 +08:00
2248356998 qq.com
97a0d940eb update iotSharpClient 2023-04-04 09:25:16 +08:00
2248356998 qq.com
efaa099d81 update iotSharpClient 2023-04-04 09:23:22 +08:00
2248356998 qq.com
47864a804b IosSharpClient Rpc优化 2023-04-04 09:22:22 +08:00
2248356998 qq.com
91136c0e43 IotSharp Rpc方法完善 2023-04-04 09:19:48 +08:00
2248356998 qq.com
28c3b1bd61 添加写入多个变量的api方法 2023-04-04 09:18:58 +08:00
2248356998 qq.com
551352bc40 update IotSharpClient 2023-04-03 20:16:38 +08:00
2248356998 qq.com
e73c24c925 更新种子 2023-04-03 19:34:12 +08:00
2248356998 qq.com
7ec4c286cc 添加IotSharp插件 2023-04-03 19:30:52 +08:00
2248356998 qq.com
6705e2ec4b 分页显示令牌 2023-04-03 15:29:35 +08:00
2248356998 qq.com
6f0373063b 后台启动时Furion RootServices NULL值 2023-04-03 15:19:59 +08:00
2248356998 qq.com
f64eef60b5 修复不存在采集设备时,初始化报警/历史服务bug 2023-04-03 14:12:56 +08:00
2248356998 qq.com
89546bf86b 弹窗消息在SignalR订阅方法中需InvokeAsync 2023-04-03 13:35:14 +08:00
2248356998 qq.com
793678feca 修复规范化结果包装2次导致登录返回结果不正确的问题 2023-04-03 12:45:19 +08:00
2248356998 qq.com
923cc3019a 更新演示地址 2023-04-03 10:47:49 +08:00
2248356998 qq.com
10eb98a5f6 readme 2023-04-02 18:12:18 +08:00
2248356998 qq.com
bd9e89d8dd readme 2023-04-02 18:08:56 +08:00
2248356998 qq.com
1926b4ce73 更新readme 2023-04-02 18:05:54 +08:00
2248356998 qq.com
4ef3062d74 更新readme 2023-04-02 18:05:28 +08:00
2248356998 qq.com
abb6e0f60f 更新包 2023-04-02 17:10:32 +08:00
2248356998 qq.com
f204d8d84e 添加注释 2023-04-02 16:59:46 +08:00
2248356998 qq.com
fa301656f1 调整依赖,添加关系图 2023-04-01 17:28:35 +08:00
2248356998 qq.com
7e1221028f 调整依赖,更新版本1.2.1 2023-04-01 15:45:02 +08:00
2248356998 qq.com
41308cb2dd 整理 2023-04-01 13:57:57 +08:00
2248356998 qq.com
130600521c 😀 OPCUAServer支持历史查询数据 2023-03-31 18:32:55 +08:00
2248356998 qq.com
cd57548a48 添加ThingsGateway.Foundation注释 2023-03-31 16:25:33 +08:00
2248356998 qq.com
efacc99f76 硬件信息获取添加延时 2023-03-30 20:51:08 +08:00
2248356998 qq.com
f0d236e172 脚本显示优化 2023-03-30 19:51:38 +08:00
2248356998 qq.com
a8118bd8c6 更新文档 2023-03-30 19:39:35 +08:00
2248356998 qq.com
0e58f2ef53 mqtt/mq上传 添加上传实体自定义脚本 2023-03-30 19:07:18 +08:00
2248356998 qq.com
f4b22b3a0c 表达式整理 2023-03-30 16:23:03 +08:00
2248356998 qq.com
df5bd281c7 更新版本 2023-03-30 14:12:39 +08:00
2248356998 qq.com
a3f23837ce 更新文档 2023-03-30 14:11:16 +08:00
2248356998 qq.com
612d989b97 readme 2023-03-30 14:06:03 +08:00
2248356998 qq.com
42c01ee9a2 更新readme,nuget 2023-03-30 14:05:00 +08:00
2248356998 qq.com
14074db591 删除多余代码 2023-03-30 13:53:57 +08:00
2248356998 qq.com
43dfdd7942 opcua 写入添加用户名日志 2023-03-30 13:32:32 +08:00
2248356998 qq.com
f397b97ccf 去除ua数据类型验证 2023-03-30 13:20:26 +08:00
2248356998 qq.com
95f8716144 更新readme 2023-03-30 13:13:44 +08:00
2248356998 qq.com
17ba472b2e 类命名错误更改 2023-03-30 13:11:46 +08:00
2248356998 qq.com
42d82571ab 发布文件添加 2023-03-30 13:11:43 +08:00
2248356998 qq.com
9119a28141 添加OPCUAServer插件,修复个别bug 2023-03-30 13:10:31 +08:00
Diego2098
a32263d838 1、OPCUAClient修复客户端证书未自动生成
2、修复异步方法错误使用
2023-03-30 00:15:13 +08:00
2248356998 qq.com
208ae2bb88 添加部分代码注释 2023-03-29 16:22:01 +08:00
2248356998 qq.com
4d85462a85 驱动支持主机名称 2023-03-29 11:07:21 +08:00
2248356998 qq.com
f601aa9ca0 修复初始化失败导致的一系列问题 2023-03-29 10:53:42 +08:00
2248356998 qq.com
8aee3ad455 上传插件间隔时间修正 2023-03-28 16:40:00 +08:00
2248356998 qq.com
6a2a1e9561 历史变量enable失效 2023-03-28 16:38:29 +08:00
2248356998 qq.com
5f8786c9dc 历史报表时间格式改为yyyy-MM-dd HH:mm:ss ffffff 2023-03-28 16:31:53 +08:00
2248356998 qq.com
73f1d3eead 采集设备状态判断错误 2023-03-28 16:21:30 +08:00
2248356998 qq.com
2bf21bb3c3 采集设备状态判断错误 2023-03-28 15:55:01 +08:00
2248356998 qq.com
f80f0dbb11 修复历史保存值 频繁时出现值相同的问题 2023-03-28 15:14:30 +08:00
2248356998 qq.com
37518c70c4 opc 活动时间修正 2023-03-28 14:15:14 +08:00
2248356998 qq.com
e5951b5bef 添加写入采集时间的接口,而不是固定DateTime.Now 2023-03-28 14:03:11 +08:00
2248356998 qq.com
ab320bd90b 更新tcpclient 2023-03-28 13:52:33 +08:00
2248356998 qq.com
7bd36b5371 修复linux 分隔符错误问题 2023-03-28 11:48:16 +08:00
2248356998 qq.com
b882b0f2bc 更改插件文件不存在时的日志信息 2023-03-28 10:21:39 +08:00
2248356998 qq.com
38d7ae73cc 更改项目引用结构 2023-03-28 10:21:23 +08:00
2248356998 qq.com
4527c6ee5d swagger文档 2023-03-27 19:01:04 +08:00
Iot边缘设备
85829e70c1 !5 添加部署文档
* 添加部署文档
2023-03-27 10:22:30 +00:00
2248356998 qq.com
256c08d82a 属性/字段缓存获取只包含public 2023-03-27 14:49:09 +08:00
2248356998 qq.com
c2ce03c047 更新masa-1.0.0-preview.10 2023-03-27 14:27:15 +08:00
2248356998 qq.com
f2af19e198 优化变量上传属性页 2023-03-27 12:00:10 +08:00
2248356998 qq.com
930b7c092d 采集设备活动时间应正常刷新 2023-03-27 10:51:54 +08:00
2248356998 qq.com
00757c69c6 添加设备复制功能 2023-03-27 10:42:02 +08:00
2248356998 qq.com
55f267d0fc update code collation 2023-03-27 08:49:10 +08:00
2248356998 qq.com
6b96aff6e8 update code collation 2023-03-26 19:48:08 +08:00
2248356998 qq.com
32b773a8fa 更新nuget包 2023-03-26 18:52:16 +08:00
2248356998 qq.com
03089adad6 发行1.10版本 2023-03-26 18:10:12 +08:00
2248356998 qq.com
4a1fe746ab 实时数据界面优化 2023-03-26 17:39:05 +08:00
2248356998 qq.com
aa52c05d2c 1、采用异步AutoResetEvent,修复多个设备下采集太慢的问题
2、弃用IntelligentConcurrentQueue(touchsocket集成类)
2023-03-26 17:32:29 +08:00
2248356998 qq.com
26407a43e7 1、优化设备状态页,减少signalr刷新所需包大小
2、日志前置等级添加
2023-03-24 18:32:10 +08:00
2248356998 qq.com
a02934bf19 修复导出表格时,null值报错 2023-03-23 22:09:53 +08:00
2248356998 qq.com
09c65fba09 导入错误时,忽略大于10行的错误信息显示 2023-03-23 20:01:19 +08:00
2248356998 qq.com
4305c727d0 更新readme 2023-03-22 15:29:35 +08:00
2248356998 qq.com
188339897f 优化log等级、json配置注解 2023-03-22 15:26:42 +08:00
2248356998 qq.com
4ecff9a707 OPCUA写入测试 2023-03-22 14:06:32 +08:00
2248356998 qq.com
355aed49c6 设备运行状态页面改为扩展 2023-03-22 13:46:23 +08:00
2248356998 qq.com
4717b6b0f0 更新文档 2023-03-22 10:44:44 +08:00
Diego2098
45ebe9048d rbmq插件优化 2023-03-21 23:38:00 +08:00
Diego2098
b2170c49a3 分包失败提示 2023-03-21 23:28:30 +08:00
Diego2098
dc2f4d6115 设备组列宽调整,补充上传设备组 2023-03-21 23:10:59 +08:00
Diego2098
1eb132440f 1、更新DataTypeEnum
2、OPCUA写入时需实际数据类型
2023-03-21 22:47:10 +08:00
Diego2098
a464bbc37a 更新Tests 2023-03-21 22:46:12 +08:00
2248356998 qq.com
ed995697c2 表格无数据时,修改默认宽度 2023-03-21 18:17:18 +08:00
2248356998 qq.com
163cd84c7b S7nuget版本 2023-03-21 15:44:50 +08:00
2248356998 qq.com
293d7cc292 masa nuget版本更改 2023-03-21 14:31:36 +08:00
2248356998 qq.com
5de1b4e74c GC策略修改 2023-03-21 14:07:17 +08:00
2248356998 qq.com
7b474975da 更新文档 2023-03-21 14:03:49 +08:00
2248356998 qq.com
beab51516b 更新文档 2023-03-21 13:56:14 +08:00
2248356998 qq.com
fe8685a50c 修改s7属性注释 2023-03-21 13:51:05 +08:00
2248356998 qq.com
f9af5d0885 更新readme 2023-03-21 13:49:10 +08:00
2248356998 qq.com
e8136a9720 更新S7协议插件 2023-03-21 13:45:58 +08:00
2248356998 qq.com
531e5d4556 修改S7特殊方法 2023-03-21 13:41:32 +08:00
2248356998 qq.com
e66255963a 修改s7 2023-03-21 13:38:43 +08:00
2248356998 qq.com
246aac8ee4 添加西门子S7协议插件 2023-03-21 13:37:17 +08:00
2248356998 qq.com
23cfeff685 版本恢复 2023-03-21 11:45:18 +08:00
2248356998 qq.com
a5e7e0d126 更新nuget,暂缓链路复用功能 2023-03-20 13:34:59 +08:00
2248356998 qq.com
5bebc30ba0 默认不开启转储 2023-03-20 09:22:11 +08:00
2248356998 qq.com
0e7057f5b9 更新opcda文档 2023-03-19 23:18:24 +08:00
2248356998 qq.com
7c6c365ba4 格式清理 2023-03-19 23:12:58 +08:00
2248356998 qq.com
424c9bb0c5 修复null值报错 2023-03-19 23:02:08 +08:00
2248356998 qq.com
9d0f26594c 添加设备组,变量按设备组别搜索 2023-03-19 22:56:02 +08:00
2248356998 qq.com
99c17de079 更新readme,opcda核心库提示 2023-03-19 20:40:54 +08:00
2248356998 qq.com
b1e3dd0af6 尝试修复中文在mac上乱码 2023-03-19 17:29:01 +08:00
2248356998 qq.com
261cb89530 修正中文在mac上乱码 2023-03-19 16:45:14 +08:00
2248356998 qq.com
ff6773ba37 删除未知文件 2023-03-19 16:35:24 +08:00
2248356998 qq.com
bdfbbfcbbd Merge branch 'master' of https://gitee.com/diego2098/ThingsGateway 2023-03-19 16:34:26 +08:00
2248356998 qq.com
0c4cd56758 添加设备组功能 2023-03-19 16:34:15 +08:00
士心
4a36658321 !4 修复MacOS环境下,数据库报错的问题
* 修复macos环境下,数据库报错
2023-03-19 08:28:54 +00:00
2248356998 qq.com
7aae938685 准备更新设备组/变量组功能 2023-03-19 11:49:06 +08:00
2248356998 qq.com
3723401e7a 更新ReadMe 2023-03-18 17:56:18 +08:00
2248356998 qq.com
70631366a9 1、最后校验失败时应该提示日志
2、暂停时设备状态修正
2023-03-18 17:49:08 +08:00
2248356998 qq.com
0e40bbda3e 更新文档 2023-03-18 16:47:29 +08:00
2248356998 qq.com
e9aa475398 ByteBlock实际长度 2023-03-18 16:45:39 +08:00
2248356998 qq.com
8d2a811184 修正串口描述类ToString 2023-03-18 16:32:15 +08:00
2248356998 qq.com
dd7f5b6700 更新文档 2023-03-18 16:23:23 +08:00
2248356998 qq.com
a4f6277737 更新nuget 2023-03-18 16:16:27 +08:00
2248356998 qq.com
c2bfaacbb7 更新readme 2023-03-18 16:15:14 +08:00
2248356998 qq.com
a17cbfa2d4 添加ModbusRtu种子数据 2023-03-18 16:14:37 +08:00
2248356998 qq.com
fb9a101555 添加ModbusRtu插件 2023-03-18 16:14:25 +08:00
2248356998 qq.com
e319cf0200 添加串口基础类 2023-03-18 16:14:08 +08:00
2248356998 qq.com
0a8395ef6a 更新文档 2023-03-17 18:19:14 +08:00
2248356998 qq.com
38df5e01be 更新文档 2023-03-17 17:52:04 +08:00
2248356998 qq.com
ebd891a868 种子数据更改 2023-03-17 17:51:58 +08:00
2248356998 qq.com
4ab2395cbe 采集检测间隔修改 2023-03-17 17:40:34 +08:00
2248356998 qq.com
5f1f989fc9 上传插件添加循环间隔属性 2023-03-17 17:30:06 +08:00
2248356998 qq.com
44b709eee3 添加rbmq插件种子数据 2023-03-17 16:30:02 +08:00
2248356998 qq.com
d0d7726597 rbmq插件文件夹更名 2023-03-17 16:16:23 +08:00
2248356998 qq.com
054c342aeb 优化内存queue,修复mqtt插件可能超出字节限制的情况 2023-03-17 16:04:24 +08:00
2248356998 qq.com
c79c33baf7 添加rbmq插件 2023-03-17 16:03:44 +08:00
2248356998 qq.com
23b00e35b2 设备禁用时,变量绑定的设备对应选项会显示禁用(灰色) 2023-03-17 11:29:14 +08:00
2248356998 qq.com
fe51079266 更新readme 2023-03-16 17:33:25 +08:00
2248356998 qq.com
0791b0bbee 选择插件时自动更新属性 2023-03-16 17:33:17 +08:00
2248356998 qq.com
dbf04c8eeb 更新赞助名单 2023-03-16 11:35:58 +08:00
2248356998 qq.com
6204256df8 限流服务默认不开启 2023-03-16 09:47:20 +08:00
2248356998 qq.com
93cc8c2327 增加简易定时看板 2023-03-15 16:01:54 +08:00
2248356998 qq.com
68a2e5bbbc 更新历史配置说明 2023-03-15 09:11:33 +08:00
Diego2098
72792153f2 !3 update handbook/docs/05、网关配置/5.5、其他配置.mdx.
Merge pull request !3 from zhubanghao/N/A
2023-03-14 13:39:16 +00:00
zhubanghao
88b6ef1897 update handbook/docs/05、网关配置/5.5、其他配置.mdx.
Signed-off-by: zhubanghao <58813184@qq.com>
2023-03-14 13:05:33 +00:00
1825 changed files with 41709 additions and 36767 deletions

2
.gitignore vendored
View File

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

103
framework/.editorconfig Normal file
View File

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

63
framework/.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# 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 Normal file
View File

@@ -0,0 +1,364 @@
## 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

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

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,8 +8,9 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
global using System.Threading.Tasks;
global using ThingsGateway.Components;

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,13 +8,10 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Photino.Blazor;
using ThingsGateway.Core;
namespace ThingsGateway.Foundation.Demo;
internal class Program
@@ -30,13 +26,13 @@ internal class Program
appBuilder.RootComponents.Add<App>("#app");
appBuilder.Services.ThingsGatewayComponentsConfigureServices();
appBuilder.Services.ThingsGatewayCoreConfigureServices();
var app = appBuilder.Build();
app.MainWindow.SetTitle("ThingsGateway.Foundation.Demo");
app.MainWindow.SetIconFile("wwwroot/favicon.ico");
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
};
app.Run();
}
}

View File

@@ -2,7 +2,6 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>net6.0;net8.0;</TargetFrameworks>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
@@ -29,18 +28,5 @@
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\favicon.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Microsoft.AspNetCore.Components;
@@ -17,9 +15,7 @@ using Microsoft.AspNetCore.Components;
using ThingsGateway.Components;
namespace ThingsGateway.Foundation.Demo;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
/// <summary>
/// 调试UI
/// </summary>
@@ -38,17 +34,12 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
this.SafeDispose();
}
/// <summary>
/// 变量地址
/// </summary>
public virtual string Address { get; set; } = "40001";
/// <summary>
/// <inheritdoc/>
/// </summary>
[Inject]
public InitTimezone InitTimezone { get; set; }
/// <summary>
/// 长度
/// </summary>
@@ -58,7 +49,6 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
/// 默认读写设备
/// </summary>
public virtual IReadWrite Plc { get; set; }
/// <summary>
/// 写入值
/// </summary>
@@ -69,12 +59,17 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
/// </summary>
protected virtual DataTypeEnum DataTypeEnum { get; set; } = DataTypeEnum.Int16;
/// <summary>
/// <inheritdoc/>
/// </summary>
[Inject]
public InitTimezone InitTimezone { get; set; }
/// <inheritdoc/>
public virtual void Dispose()
{
_periodicTimer?.Dispose();
}
/// <inheritdoc/>
public void LogOut(ThingsGateway.Foundation.Core.LogLevel logLevel, object source, string message, Exception exception)
{
@@ -108,6 +103,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
Messages.Add((LogLevel.Error,
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 错误:{ex}"));
}
}
/// <inheritdoc/>
@@ -140,7 +136,6 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
_ = RunTimerAsync();
base.OnInitialized();
}
private async Task RunTimerAsync()
{
while (await _periodicTimer.WaitForNextTickAsync())
@@ -148,4 +143,6 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
await InvokeAsync(StateHasChanged);
}
}
}
}

View File

@@ -47,7 +47,7 @@
<MRow Class="my-1" Justify="JustifyTypes.Start" Align="AlignTypes.Start" NoGutters>
<MTextField Class="mx-1 my-1" Style="max-width:200px" Label="读取长度" Dense Outlined HideDetails="@("auto")" @bind-Value=@Length />
<MSelect Class="mx-1 my-1" Style="max-width:200px" @bind-Value="DataTypeEnum" Outlined Label="数据类型"
Items=@(typeof(DataTypeEnum).GetEnumList())
Items=@(typeof(DataTypeEnum).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataTypeEnum)u.Value)
@@ -87,9 +87,9 @@
@foreach (var item in DeviceVariableRunTimes)
{
<MRow Dense Align="AlignTypes.Center">
<MTextField Class="ma-1" Outlined Style="min-width:100px" Label=@(item.Description(x => x.Address)) Dense HideDetails="@("auto")" @bind-Value=@item.Address></MTextField>
<MSelect Class="mx-1 my-1" Style="max-width:120px" @bind-Value="item.DataTypeEnum" Outlined Label=@(item.Description(x => x.DataTypeEnum))
Items=@(typeof(DataTypeEnum).GetEnumList())
<MTextField Class="ma-1" Outlined Style="min-width:100px" Label=@(item.DescriptionWithOutSugar(x => x.VariableAddress)) Dense HideDetails="@("auto")" @bind-Value=@item.VariableAddress></MTextField>
<MSelect Class="mx-1 my-1" Style="max-width:120px" @bind-Value="item.DataTypeEnum" Outlined Label=@(item.DescriptionWithOutSugar(x => x.DataTypeEnum))
Items=@(typeof(DataTypeEnum).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(DataTypeEnum)u.Value)
@@ -97,7 +97,7 @@
Dense>
</MSelect>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(item.Description(x => x.IntervalTime)) Dense HideDetails="@("auto")" @bind-Value=@item.IntervalTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(item.DescriptionWithOutSugar(x => x.IntervalTime)) Dense HideDetails="@("auto")" @bind-Value=@item.IntervalTime></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=实时值 Readonly ClearIcon="" Dense HideDetails="@("auto")" Value=item.Value?.ToJsonString()></MTextField>

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,15 +8,17 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using BlazorComponent;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class DriverDebugUIPage : DriverDebugUIBase
{
@@ -25,43 +26,39 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
/// DeviceVariableRunTimes
/// </summary>
public List<DeviceVariableRunTime> DeviceVariableRunTimes;
/// <summary>
/// MaxPack
/// </summary>
public int MaxPack = 100;
private StringNumber _selected = 0;
/// <inheritdoc/>
~DriverDebugUIPage()
/// <summary>
/// MulReadAsync
/// </summary>
/// <returns></returns>
public async Task MulReadAsync()
{
this.SafeDispose();
var deviceVariableSourceReads = Plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(DeviceVariableRunTimes, MaxPack);
foreach (var item in deviceVariableSourceReads)
{
var result = await Plc.ReadAsync(item.VariableAddress, item.Length);
if (result.IsSuccess)
{
try
{
item.DeviceVariableRunTimes.PraseStructContent(Plc, result.Content);
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + result.Content.ToHexString(' ')));
}
catch (Exception ex)
{
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + ex));
}
}
else
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + result.Message));
}
}
/// <summary>
/// 自定义模板
/// </summary>
[Parameter]
public RenderFragment CodeContent { get; set; }
/// <summary>
/// 自定义模板
/// </summary>
[Parameter]
public RenderFragment OtherContent { get; set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
public override IReadWrite Plc { get; set; }
/// <summary>
/// 自定义模板
/// </summary>
[Parameter]
public RenderFragment ReadWriteContent { get; set; }
private StringNumber _selected = 0;
/// <summary>
/// Sections
/// </summary>
@@ -74,48 +71,6 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
[Parameter]
public bool ShowDefaultOtherContent { get; set; } = true;
/// <inheritdoc/>
public override void Dispose()
{
Plc?.SafeDispose();
base.Dispose();
}
/// <summary>
/// MulReadAsync
/// </summary>
/// <returns></returns>
public async Task MulReadAsync()
{
var deviceVariableSourceReads = Plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(DeviceVariableRunTimes, MaxPack, 1000);
foreach (var item in deviceVariableSourceReads)
{
var result = await Plc.ReadAsync(item.Address, item.Length);
if (result.IsSuccess)
{
try
{
item.DeviceVariableRunTimes.PraseStructContent(Plc, result.Content);
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + result.Content.ToHexString(' ')));
}
catch (Exception ex)
{
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + ex));
}
}
else
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + result.Message));
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
}
/// <inheritdoc/>
protected override void OnInitialized()
@@ -125,25 +80,25 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40001",
VariableAddress="40001",
IntervalTime=1000,
},
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40011",
VariableAddress="40011",
IntervalTime=1000,
},
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40031",
VariableAddress="40031",
IntervalTime=1000,
},
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40101",
VariableAddress="40101",
IntervalTime=1000,
},
};
@@ -155,7 +110,7 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
/// <inheritdoc/>
public TimerTick TimerTick { get; set; }
/// <inheritdoc/>
public string Address { get; set; }
public string VariableAddress { get; set; }
/// <inheritdoc/>
public int Length { get; set; }
/// <inheritdoc/>
@@ -169,7 +124,7 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
public int IntervalTime { get; set; }
/// <inheritdoc/>
[Description("变量地址")]
public string Address { get; set; }
public string VariableAddress { get; set; }
/// <inheritdoc/>
public int Index { get; set; }
/// <inheritdoc/>
@@ -188,7 +143,7 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
}
}
public List<DeviceVariableRunTime> DeviceVariableRunTimes;
private static async Task ModbusClientAsync(IReadWrite plc)
{
DeviceVariableRunTimes = new()
@@ -196,45 +151,86 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40001",
VariableAddress="40001",
IntervalTime=1000,
},
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40011",
VariableAddress="40011",
IntervalTime=1000,
},
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40031",
VariableAddress="40031",
IntervalTime=1000,
},
new DeviceVariableRunTime()
{
DataTypeEnum=DataTypeEnum.Int16,
Address="40101",
VariableAddress="40101",
IntervalTime=1000,
},
};
#region
var deviceVariableSourceReads = Plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(DeviceVariableRunTimes, MaxPack);
foreach (var item in deviceVariableSourceReads)
{
var result = await Plc.ReadAsync(item.Address, item.Length);
var result = await Plc.ReadAsync(item.VariableAddress, item.Length);
if (result.IsSuccess)
{
item.DeviceVariableRunTimes.PraseStructContent(result.Content);
}
}
#endregion
}
}
""", "csharp"));
base.OnInitialized();
}
/// <summary>
/// 自定义模板
/// </summary>
[Parameter]
public RenderFragment ReadWriteContent { get; set; }
/// <summary>
/// 自定义模板
/// </summary>
[Parameter]
public RenderFragment OtherContent { get; set; }
/// <summary>
/// 自定义模板
/// </summary>
[Parameter]
public RenderFragment CodeContent { get; set; }
/// <inheritdoc/>
~DriverDebugUIPage()
{
this.SafeDispose();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
public override IReadWrite Plc { get; set; }
/// <inheritdoc/>
public override void Dispose()
{
Plc?.SafeDispose();
base.Dispose();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
}
}

View File

@@ -15,22 +15,22 @@
@using Microsoft.AspNetCore.Components.Web;
@using System.IO.Ports;
@using Masa.Blazor
<MCard Flat Class="pa-2 my-1" Style="width:100%">
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">通道配置</div>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(_serialPortOption.Description(x => x.PortName)) Dense HideDetails="@("auto")" @bind-Value=@_serialPortOption.PortName />
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(_serialPortOption.Description(x => x.BaudRate)) Dense HideDetails="@("auto")" @bind-Value=@_serialPortOption.BaudRate />
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(_serialPortOption.Description(x => x.DataBits)) Dense HideDetails="@("auto")" @bind-Value=@_serialPortOption.DataBits />
<MSelect Class="ma-1 " Style="max-width:200px" Outlined @bind-Value="_serialPortOption.Parity" Label="@(_serialPortOption.Description(x => x.Parity))"
Items=@(typeof(Parity).GetEnumList())
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(serialProperty.DescriptionWithOutSugar(x => x.PortName)) Dense HideDetails="@("auto")" @bind-Value=@serialProperty.PortName />
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(serialProperty.DescriptionWithOutSugar(x => x.BaudRate)) Dense HideDetails="@("auto")" @bind-Value=@serialProperty.BaudRate />
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(serialProperty.DescriptionWithOutSugar(x => x.DataBits)) Dense HideDetails="@("auto")" @bind-Value=@serialProperty.DataBits />
<MSelect Class="ma-1 " Style="max-width:200px" Outlined @bind-Value="serialProperty.Parity" Label="@(serialProperty.DescriptionWithOutSugar(x => x.Parity))"
Items=@(typeof(Parity).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(Parity)u.Value)
HideDetails=@("auto") Height="30"
Dense>
</MSelect>
<MSelect Class="ma-1 " Style="max-width:200px" Outlined @bind-Value="_serialPortOption.StopBits" Label="@(_serialPortOption.Description(x => x.StopBits))"
Items=@(typeof(StopBits).GetEnumList())
<MSelect Class="ma-1 " Style="max-width:200px" Outlined @bind-Value="serialProperty.StopBits" Label="@(serialProperty.DescriptionWithOutSugar(x => x.StopBits))"
Items=@(typeof(StopBits).GetEnumListWithOutSugar())
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
ItemText=@((u) =>u.Description)
ItemValue=@(u =>(StopBits)u.Value)

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,52 +8,73 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class SerialPortClientPage : IDisposable
public partial class SerialSessionPage : IDisposable
{
/// <summary>
/// 日志输出
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
private readonly SerialPortOption _serialPortOption = new();
private TouchSocketConfig _config;
private SerialPortClient _serialPortClient { get; set; } = new();
private TouchSocketConfig config;
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
{
_serialPortClient.SafeDispose();
}
private readonly SerialProperty serialProperty = new();
private SerialSession SerialSession { get; set; } = new();
/// <summary>
/// 获取对象
/// </summary>
/// <returns></returns>
public SerialPortClient GetSerialPortClient()
public SerialSession GetSerialSession()
{
_config ??= new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_config.SetSerialPortOption(_serialPortOption);
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetSerialProperty(serialProperty);
//载入配置
_serialPortClient.Setup(_config);
return _serialPortClient;
SerialSession.Setup(config);
return SerialSession;
}
private async Task ConnectAsync()
{
try
{
SerialSession.Close();
await GetSerialSession().ConnectAsync();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
SerialSession.Close();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
internal void StateHasChangedAsync()
/// <inheritdoc/>
protected override void OnInitialized()
{
StateHasChanged();
config ??= new TouchSocketConfig();
base.OnInitialized();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
@@ -65,44 +85,22 @@ public partial class SerialPortClientPage : IDisposable
{
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_serialPortClient.Setup(_config);
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
SerialSession.Setup(config);
}
base.OnAfterRender(firstRender);
}
/// <inheritdoc/>
protected override void OnInitialized()
{
_config ??= new TouchSocketConfig();
base.OnInitialized();
}
private async Task ConnectAsync()
{
try
{
_serialPortClient.Close();
await GetSerialPortClient().ConnectAsync();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
_serialPortClient.Close();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
{
SerialSession.SafeDispose();
}
internal void StateHasChangedAsync()
{
StateHasChanged();
}
}

View File

@@ -17,12 +17,12 @@
@using System.Collections.Concurrent;
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor
<MCard Flat Class="pa-2 my-1" Style="width:100%">
<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" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@_ip />
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@_port />
<MTextField Class="ma-1" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@IP />
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@Port />
<MButton Class="ma-1" OnClick=@ConnectAsync Color="primary">
连接

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Demo;
@@ -22,47 +20,66 @@ public partial class TcpClientPage : IDisposable
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
private TouchSocketConfig _config;
private TouchSocketConfig config;
/// <summary>
/// IP
/// </summary>
private string _ip = "127.0.0.1";
private string IP = "127.0.0.1";
/// <summary>
/// Port
/// </summary>
public int _port { get; set; } = 502;
public int Port { get; set; } = 502;
private TcpClient _tcpClient { get; set; } = new();
private TcpClient TcpClient { get; set; } = new();
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
private async Task ConnectAsync()
{
_tcpClient.SafeDispose();
}
try
{
TcpClient.Close();
await GetTcpClient().ConnectAsync();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
TcpClient.Close();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
/// <summary>
/// 获取对象
/// </summary>
/// <returns></returns>
public TcpClient GetTcpClient()
{
_config ??= new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_config.SetRemoteIPHost(new IPHost(_ip + ":" + _port));
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
//载入配置
_tcpClient.Setup(_config);
return _tcpClient;
TcpClient.Setup(config);
return TcpClient;
}
internal void StateHasChangedAsync()
/// <inheritdoc/>
protected override void OnInitialized()
{
StateHasChanged();
config ??= new TouchSocketConfig();
base.OnInitialized();
}
/// <summary>
@@ -75,45 +92,25 @@ public partial class TcpClientPage : IDisposable
{
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_config.SetRemoteIPHost(new IPHost(_ip + ":" + _port));
_tcpClient.Setup(_config);
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
TcpClient.Setup(config);
}
base.OnAfterRender(firstRender);
}
/// <inheritdoc/>
protected override void OnInitialized()
{
_config ??= new TouchSocketConfig();
base.OnInitialized();
}
private async Task ConnectAsync()
{
try
{
_tcpClient.Close();
await GetTcpClient().ConnectAsync();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
_tcpClient.Close();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
{
TcpClient.SafeDispose();
}
internal void StateHasChangedAsync()
{
StateHasChanged();
}
}

View File

@@ -18,18 +18,18 @@
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor
<MCard Flat Class="pa-2 my-1" Style="width:100%">
<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" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@_ip />
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@_port />
<MTextField Class="ma-1" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@ip />
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@port />
<MButton Class="ma-1" OnClick=@Connect Color="primary">
启动
连接
</MButton>
<MButton Class="ma-1" OnClick=@DisConnect Color="red">
停止
断开
</MButton>

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Demo;
@@ -22,43 +20,62 @@ public partial class TcpServerPage : IDisposable
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
private TouchSocketConfig _config;
private TouchSocketConfig config;
private string _ip = "127.0.0.1";
private string ip = "127.0.0.1";
private int _port = 502;
private int port = 502;
private TcpService _tcpServer { get; set; } = new();
private TcpService TcpServer { get; set; } = new();
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
private void Connect()
{
_tcpServer.SafeDispose();
}
try
{
TcpServer.Stop();
GetTcpServer().Start();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
TcpServer.Stop();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
/// <summary>
/// 获取对象
/// </summary>
/// <returns></returns>
public TcpService GetTcpServer()
{
_config ??= new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_config.SetListenIPHosts(new IPHost[] { new IPHost(_ip + ":" + _port) });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) });
//载入配置
_tcpServer.Setup(_config);
return _tcpServer;
TcpServer.Setup(config);
return TcpServer;
}
internal void StateHasChangedAsync()
/// <inheritdoc/>
protected override void OnInitialized()
{
StateHasChanged();
}
config ??= new TouchSocketConfig();
base.OnInitialized();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
@@ -69,45 +86,23 @@ public partial class TcpServerPage : IDisposable
{
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_config.SetListenIPHosts(new IPHost[] { new IPHost(_ip + ":" + _port) });
_tcpServer.Setup(_config);
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) });
TcpServer.Setup(config);
}
base.OnAfterRender(firstRender);
}
/// <inheritdoc/>
protected override void OnInitialized()
{
_config ??= new TouchSocketConfig();
base.OnInitialized();
}
private void Connect()
{
try
{
_tcpServer.Stop();
GetTcpServer().Start();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
_tcpServer.Stop();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
{
TcpServer.SafeDispose();
}
internal void StateHasChangedAsync()
{
StateHasChanged();
}
}

View File

@@ -18,12 +18,12 @@
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor
<MCard Flat Class="pa-2 my-1" Style="width:100%">
<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" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@_ip />
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@_port />
<MTextField Class="ma-1" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@IP />
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@Port />
<MButton Class="ma-1" OnClick=Connect Color="primary">
连接

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Demo;
@@ -17,54 +15,71 @@ namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public partial class UdpSessionPage : IDisposable
{
/// <summary>
/// IP
/// </summary>
public string _ip = "127.0.0.1";
/// <summary>
/// Port
/// </summary>
public int _port = 502;
/// <summary>
/// 日志输出
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
private TouchSocketConfig _config;
private UdpSession _udpSession { get; set; } = new();
private TouchSocketConfig config;
/// <summary>
/// <inheritdoc/>
/// IP
/// </summary>
public void Dispose()
{
_udpSession.SafeDispose();
}
public string IP = "127.0.0.1";
/// <summary>
/// Port
/// </summary>
public int Port = 502;
private UdpSession UdpSession { get; set; } = new();
private void Connect()
{
try
{
UdpSession.Stop();
GetUdpSession().Start();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
UdpSession.Stop();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
/// <summary>
/// 获取对象
/// </summary>
/// <returns></returns>
public UdpSession GetUdpSession()
{
_config ??= new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_config.SetRemoteIPHost(new IPHost(_ip + ":" + _port));
_config.SetBindIPHost(new IPHost(0));
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
config.SetBindIPHost(new IPHost(0));
//载入配置
_udpSession.Setup(_config);
return _udpSession;
UdpSession.Setup(config);
return UdpSession;
}
internal void StateHasChangedAsync()
/// <inheritdoc/>
protected override void OnInitialized()
{
StateHasChanged();
}
config ??= new TouchSocketConfig();
base.OnInitialized();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
@@ -75,46 +90,24 @@ public partial class UdpSessionPage : IDisposable
{
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
_config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
_config.SetRemoteIPHost(new IPHost(_ip + ":" + _port));
_config.SetBindIPHost(new IPHost(0));
_udpSession.Setup(_config);
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
config.SetBindIPHost(new IPHost(0));
UdpSession.Setup(config);
}
base.OnAfterRender(firstRender);
}
/// <inheritdoc/>
protected override void OnInitialized()
{
_config ??= new TouchSocketConfig();
base.OnInitialized();
}
private void Connect()
{
try
{
_udpSession.Stop();
GetUdpSession().Start();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void DisConnect()
{
try
{
_udpSession.Stop();
}
catch (Exception ex)
{
LogAction?.Invoke(LogLevel.Error, null, null, ex);
}
}
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
{
UdpSession.SafeDispose();
}
internal void StateHasChangedAsync()
{
StateHasChanged();
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
@@ -21,34 +19,24 @@ public class DeviceVariableRunTime : IDeviceVariableRunTime
{
/// <inheritdoc/>
[Description("读取间隔")]
public int? IntervalTime { get; set; }
public int IntervalTime { get; set; }
/// <inheritdoc/>
[Description("变量地址")]
public string Address { get; set; }
public string VariableAddress { get; set; }
/// <inheritdoc/>
public int Index { get; set; }
/// <inheritdoc/>
public IThingsGatewayBitConverter ThingsGatewayBitConverter { get; set; }
/// <inheritdoc/>
[Description("数据类型")]
public DataTypeEnum DataTypeEnum { get; set; }
/// <inheritdoc/>
[Description("实时值")]
public object Value { get; set; }
public bool IsOnline { get; set; }
public string LastErrorMessage { get; set; }
/// <inheritdoc/>
public OperResult SetValue(object value, DateTime dateTime = default, string lastErrorMessage = null)
public OperResult SetValue(object value, DateTime dateTime = default, bool isOnline = true)
{
Value = value;
return OperResult.CreateSuccessResult();
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,23 +8,21 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
namespace ThingsGateway.Foundation.Demo;
/// <inheritdoc/>
public class DeviceVariableSourceRead : IDeviceVariableSourceRead<IDeviceVariableRunTime>
{
/// <inheritdoc/>
public TimerTick IntervalTimeTick { get; set; }
public TimerTick TimerTick { get; set; }
/// <inheritdoc/>
public string Address { get; set; }
public string VariableAddress { get; set; }
/// <inheritdoc/>
public int Length { get; set; }
/// <inheritdoc/>
public List<IDeviceVariableRunTime> DeviceVariableRunTimes { get; set; } = new List<IDeviceVariableRunTime>();
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
@@ -18,5 +16,6 @@ global using System.Threading.Tasks;
global using ThingsGateway.Components;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.SerialPorts;
global using ThingsGateway.Foundation.Sockets;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -24,7 +24,7 @@
<Logo CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_TITLE=@CONFIG_TITLE HeightInt=@(IsMobile?BlazorResourceConst.AppBarHeight:BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight) />
<AppList ClassString="overflow-y-auto" Routable
StyleString=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight}px);")
Items="_navs" />
Items="Navs" />
</MNavigationDrawer>
<MAppBar Color="barcolor" Style=@($"{(!(IsMobile||_drawerOpen!=true)? "left:200px;":"")}") Elevation="1" App Flat ClippedRight Dense ElevateOnScroll
@@ -37,7 +37,7 @@
<MMain Style=@($"{(!(IsMobile||_drawerOpen!=true)? "padding-left:200px;":"")}")>
<div class="full-width">
<PageTabs @ref="_pageTabs" PageTabItems="_pageTabItems" />
<PageTabs @ref="_pageTabs" PageTabItems="pageTabItems" />
</div>
<MDivider Center></MDivider>
<MCard Flat Class="overflow-y-auto overflow-x-hidden ma-auto pa-0 rounded-0" Style=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight+BlazorResourceConst.FooterHeight}px);")>

View File

@@ -1,24 +1,24 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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;
namespace ThingsGateway.Foundation.Demo;
public partial class MainLayout
{
private List<NavItem> _navs { get; set; } = new();
private List<PageTabItem> _pageTabItems { get; set; } = new();
private List<NavItem> Navs { get; set; } = new();
private List<PageTabItem> pageTabItems { get; set; } = new();
protected override void OnInitialized()
{
var dataString =
@@ -26,7 +26,7 @@ public partial class MainLayout
[
{
"Href": "/index",
"Title": "首页"
"Title": "首页"
},
{
"Title": "Modbus",
@@ -69,8 +69,28 @@ public partial class MainLayout
"Title": "Siemens",
"Children": [
{
"Href": "/Siemens",
"Title": "Siemens"
"Href": "/S7_1500",
"Title": "S7_1500"
},
{
"Href": "/S7_1200",
"Title": "S7_1200"
},
{
"Href": "/S7_200",
"Title": "S7_200"
},
{
"Href": "/S7_200SMART",
"Title": "S7_200SMART"
},
{
"Href": "/S7_300",
"Title": "S7_400"
},
{
"Href": "/S7_400",
"Title": "S7_400"
}
]
},
@@ -104,20 +124,21 @@ public partial class MainLayout
"Title": "OPCUAClient"
}
]
},
{
"Title": "Mqtt",
"Children": [
{
"Href": "/MqttClient",
"Title": "MqttClient"
}
]
}
//{
// "Title": "Mqtt",
// "Children": [
// {
// "Href": "/MqttClient",
// "Title": "MqttClient"
// }
// ]
//}
]
""";
_navs = dataString.FromJsonString<List<NavItem>>();
Navs = dataString.FromJsonString<List<NavItem>>();
#if Pro
var dataStringPro =
@@ -186,46 +207,26 @@ public partial class MainLayout
]
},
{
"Title": "HZW_QTJC_01",
"Title": "GasCustom",
"Children": [
{
"Href": "/HZW_QTJC_01Serial",
"Title": "HZW_QTJC_01Serial"
"Href": "/GasCustomSerial",
"Title": "GasCustomSerial"
},
{
"Href": "/HZW_QTJC_01SerialOverTcp",
"Title": "HZW_QTJC_01SerialOverTcp"
"Href": "/GasCustomSerialOverTcp",
"Title": "GasCustomSerialOverTcp"
}
]
},
{
"Title": "LQTCP",
"Children": [
{
"Href": "/LQTCP",
"Title": "LQTCP"
}
]
},
{
"Title": "KELID2008",
"Children": [
{
"Href": "/KELID2008",
"Title": "KELID2008"
},
{
"Href": "/KELID2008OverTcp",
"Title": "KELID2008OverTcp"
}
]
},
}
]
""";
Navs.AddRange(dataStringPro.FromJsonString<List<NavItem>>());
#endif
_pageTabItems = _navs.PasePageTabItem();
pageTabItems = Navs.PasePageTabItem();
base.OnInitialized();
}
}

View File

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

View File

@@ -25,5 +25,5 @@
@using System.Net.Http.Json
@using System.IO;
@using System.Text.Json;
@using ThingsGateway.Foundation.SerialPorts;
@using ThingsGateway.Foundation.Serial;
@using ThingsGateway.Foundation.Sockets;

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -8,6 +8,7 @@
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link href="_content/Masa.Blazor/css/masa-blazor.min.css" rel="stylesheet" />
<link href="_content/ThingsGateway.Components/css/materialdesign/v7.1.96/css/materialdesignicons.min.css" rel="stylesheet">
<link href="_content/ThingsGateway.Components/css/material/icons.css" rel="stylesheet">

View File

@@ -1,14 +1,16 @@
<Project>
<Import Project="$(SolutionDir)\Directory.Build.props" />
<!--如果编译net45报错无支持用一下方法添加net45包-->
<!--VS顶部菜单栏 -> 视图 -> 其他 -> 程序包控制台
Install-Package Microsoft.NETFramework.ReferenceAssemblies.net45
-->
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0;net6.0;net8.0;</TargetFrameworks>
<Version>3.0.0.22</Version>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
<Description>
ThingsGateway.Foundation是工业设备通讯类库归属于ThingsGateway边缘网关项目说明文档https://diego2098.gitee.io/thingsgateway-docs/
</Description>
<Authors>Diego</Authors>
<Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright>
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSource>true</EmbedUntrackedSource>
<EmbedAllSources>true</EmbedAllSources>
@@ -20,11 +22,17 @@
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://diego2098.gitee.io/thingsgateway-docs/</PackageProjectUrl>
<PackageTags>ThingsGateway;Diego;dotNET China;Blazor;设备采集;边缘网关</PackageTags>
<PackageOutputPath>..\..\nupkgs</PackageOutputPath>
<AssemblyOriginatorKeyFile>..\..\..\snks/ThingsGateway.snk</AssemblyOriginatorKeyFile>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<SignAssembly>True</SignAssembly>
<DelaySign>False</DelaySign>
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
<PackageOutputPath>../../nupkgs</PackageOutputPath>
<AssemblyOriginatorKeyFile>../../../snks/ThingsGateway.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.DLT645;
@@ -17,48 +15,40 @@ namespace ThingsGateway.Foundation.Adapter.DLT645;
/// <summary>
/// 控制码
/// </summary>
internal enum ControlCode : byte
public enum ControlCode : byte
{
/// <summary>
/// 读数据
/// </summary>
Read = 0x11,
/// <summary>
/// 读后续数据
/// </summary>
ReadSub = 0x12,
/// <summary>
/// 读站号
/// </summary>
ReadStation = 0x13,
/// <summary>
/// 写数据
/// </summary>
Write = 0x14,
/// <summary>
/// 写站号
/// </summary>
WriteStation = 0x15,
/// <summary>
/// 广播校时
/// </summary>
BroadcastTime = 0x08,
/// <summary>
/// 冻结
/// </summary>
Freeze = 0x16,
/// <summary>
/// 更新波特率
/// </summary>
WriteBaudRate = 0x17,
/// <summary>
/// 更新密码
/// </summary>

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Text;
@@ -17,30 +15,33 @@ using System.Text;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.DLT645;
/// <summary>
/// 解析参数
/// </summary>
internal class DataInfo
public class DataInfo
{
/// <summary>
/// 解析长度
/// </summary>
public int ByteLength { get; set; }
/// <summary>
/// 小数位
/// </summary>
public int Digtal { get; set; }
/// <summary>
/// 有符号解析
/// </summary>
public bool IsSigned { get; set; }
}
internal static class DLT645Helper
{
internal static byte[] BytesAdd(this byte[] bytes, int value)
{
for (int index = 0; index < bytes.Length; ++index)
bytes[index] = (byte)(bytes[index] + value);
return bytes;
}
internal static string Get2007ErrorMessage(byte buffer)
{
string error = buffer switch
@@ -80,7 +81,6 @@ internal static class DLT645Helper
new(){ ByteLength=4,Digtal=2,IsSigned=true},
});
break;
default:
//正向有功总电能
//反向有功总电能
@@ -104,7 +104,6 @@ internal static class DLT645Helper
new(){ ByteLength=5,Digtal=0,IsSigned=false},
});
break;
default:
dataInfos.AddRange(new DataInfo[]
{
@@ -127,14 +126,12 @@ internal static class DLT645Helper
});
break;
case 2://电流
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=3,Digtal=3,IsSigned=true},
});
break;
case < 6:
//瞬时总有功功率
//瞬时A相有功功率
@@ -157,14 +154,12 @@ internal static class DLT645Helper
});
break;
case 6://功率因数
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=2,Digtal=3,IsSigned=true},
});
break;
case 7://相角
dataInfos.AddRange(new DataInfo[]
@@ -172,8 +167,8 @@ internal static class DLT645Helper
new(){ ByteLength=2,Digtal=1,IsSigned=false},
});
break;
break;
case < 0x80:
{
//A相电压波形失真度
@@ -226,21 +221,18 @@ internal static class DLT645Helper
new(){ ByteLength=3,Digtal=3,IsSigned=true},
});
break;
case 2://电网频率
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=2,Digtal=2,IsSigned=false},
});
break;
case 3://一分钟有功总平均功率
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=3,Digtal=4,IsSigned=false},
});
break;
case 4://当前有功需量
case 5://当前无功需量
case 6://当前视在需量
@@ -249,14 +241,12 @@ internal static class DLT645Helper
new(){ ByteLength=3,Digtal=4,IsSigned=true},
});
break;
case 7://表内温度
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=2,Digtal=1,IsSigned=false},
});
break;
case 8://时钟电池电压(内部)
case 9://停电抄表电池电压(外部)
dataInfos.AddRange(new DataInfo[]
@@ -264,14 +254,12 @@ internal static class DLT645Helper
new(){ ByteLength=2,Digtal=2,IsSigned=false},
});
break;
case 10://内部电池工作时间
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=4,Digtal=0,IsSigned=false},
});
break;
case 11://当前阶梯电价
dataInfos.AddRange(new DataInfo[]
{
@@ -280,7 +268,6 @@ internal static class DLT645Helper
break;
}
break;
default:
break;
}
@@ -344,8 +331,10 @@ internal static class DLT645Helper
new DataInfo() { ByteLength = 4, Digtal = 2},
new DataInfo() { ByteLength = 4, Digtal = 2},
new DataInfo() { ByteLength = 4, Digtal = 2},
});
break;
}
case 5://全失压总次数,总累计时间
@@ -368,10 +357,13 @@ internal static class DLT645Helper
});
break;
}
break;
case 6://辅助电源失电总次数,总累计时间
if (buffer[1] == 0 && buffer[0] == 0)
@@ -392,10 +384,10 @@ internal static class DLT645Helper
new(){ ByteLength=6,Digtal=0,IsSigned=false},
});
break;
}
break;
case 7://电压逆相序总次数,总累计时间
case 8://电流逆相序总次数,总累计时间
if (buffer[1] == 0 && buffer[0] == 0)
@@ -423,10 +415,11 @@ internal static class DLT645Helper
});
}
break;
}
break;
break;
case 9://电压不平衡总次数,总累计时间
case 0x0A://电流不平衡总次数,总累计时间
if (buffer[1] == 0 && buffer[0] == 0)
@@ -446,6 +439,7 @@ internal static class DLT645Helper
new DataInfo(){ByteLength=6, Digtal=0},
new DataInfo(){ByteLength=2, Digtal=2},
new DataInfo(){ByteLength=2, Digtal=2},
});
for (int i = 0; i < 16; i++)
{
@@ -455,8 +449,10 @@ internal static class DLT645Helper
});
}
break;
}
break;
case 0x0B:
@@ -512,8 +508,10 @@ internal static class DLT645Helper
new DataInfo(){ByteLength=3, Digtal=4},
new DataInfo(){ByteLength=3, Digtal=4},
new DataInfo(){ByteLength=2, Digtal=3},
});
break;
}
case 0x0E:
@@ -537,6 +535,7 @@ internal static class DLT645Helper
{
new DataInfo(){ByteLength=6, Digtal=0},
new DataInfo(){ByteLength=6, Digtal=0},
});
for (int i = 0; i < 16; i++)
{
@@ -546,6 +545,7 @@ internal static class DLT645Helper
});
}
break;
}
case 0x10:
@@ -560,9 +560,11 @@ internal static class DLT645Helper
new DataInfo(){ByteLength=4, Digtal=0},
new DataInfo(){ByteLength=2, Digtal=1},
new DataInfo(){ByteLength=4, Digtal=0},
});
break;
case 0x11:
if (buffer[1] == 0 && buffer[0] == 0)
{
@@ -580,9 +582,11 @@ internal static class DLT645Helper
new DataInfo(){ByteLength=6, Digtal=0},
});
break;
}
break;
case 0x12:
if (buffer[1] == 0 && buffer[0] == 0)
{
@@ -608,8 +612,10 @@ internal static class DLT645Helper
new DataInfo(){ByteLength=5, Digtal=0},
});
break;
}
case 0x30:
switch (buffer[1])
@@ -639,7 +645,6 @@ internal static class DLT645Helper
}
break;
case 1://电表清零记录
if (buffer[0] == 0)
@@ -665,7 +670,6 @@ internal static class DLT645Helper
}
}
break;
case 2://编程记录
if (buffer[0] == 0)
@@ -677,6 +681,7 @@ internal static class DLT645Helper
}
else
{
dataInfos.AddRange(new List<DataInfo>()
{
new DataInfo { ByteLength = 6, Digtal = 0 },
@@ -693,7 +698,6 @@ internal static class DLT645Helper
}
}
break;
case 3://事件清零记录
if (buffer[0] == 0)
{
@@ -712,7 +716,6 @@ internal static class DLT645Helper
});
}
break;
case 4://校时记录
if (buffer[0] == 0)
{
@@ -731,7 +734,6 @@ internal static class DLT645Helper
});
}
break;
case 5://时段表编程记录
if (buffer[0] == 0)
{
@@ -756,7 +758,6 @@ internal static class DLT645Helper
}
}
break;
case 6://时区表编程记录
if (buffer[0] == 0)
{
@@ -781,7 +782,6 @@ internal static class DLT645Helper
}
}
break;
case 7://周休日编程记录
if (buffer[0] == 0)
{
@@ -826,7 +826,6 @@ internal static class DLT645Helper
}
}
break;
case 9:
case 10:
case 11://有功组合方式编程记录
@@ -847,7 +846,6 @@ internal static class DLT645Helper
});
}
break;
case 12://结算日编程记录
if (buffer[0] == 0)
{
@@ -868,7 +866,6 @@ internal static class DLT645Helper
});
}
break;
case 13:
case 14:
if (buffer[0] == 0)
@@ -894,8 +891,10 @@ internal static class DLT645Helper
}
}
break;
}
break;
}
break;
@@ -915,55 +914,44 @@ internal static class DLT645Helper
new(){ ByteLength=4,Digtal=0,IsSigned=false},
});
break;
case 2:
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=3,Digtal=0,IsSigned=false},
});
break;
case 3:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 1, Digtal = 0, IsSigned = false } });
break;
case 4:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 1, Digtal = 0, IsSigned = false } });
break;
case 5:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 2, Digtal = 0, IsSigned = false } });
break;
case 6:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 5, Digtal = 0, IsSigned = false } });
break;
case 7:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 5, Digtal = 0, IsSigned = false } });
break;
default:
break;
}
break;
case 2:
switch (buffer[0])
{
case 5:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 2, Digtal = 0, IsSigned = false } });
break;
default:
break;
}
break;
case 3:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 1, Digtal = 0, IsSigned = false } });
break;
case 4:
if (buffer[0] <= 2)
dataInfos.AddRange(new DataInfo[]
@@ -986,27 +974,21 @@ internal static class DLT645Helper
else if (buffer[0] == 13)
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 16, Digtal = -1, IsSigned = false } });
break;
case 5:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 2, Digtal = 0, IsSigned = false } });
break;
case 6:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 1, Digtal = 0, IsSigned = false } });
break;
case 7:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 1, Digtal = 0, IsSigned = false } });
break;
case 8:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 1, Digtal = 0, IsSigned = false } });
break;
case 9:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 1, Digtal = 0, IsSigned = false } });
break;
case 10:
switch (buffer[0])
{
@@ -1016,7 +998,6 @@ internal static class DLT645Helper
new(){ ByteLength=4,Digtal=0,IsSigned=false},
});
break;
default:
dataInfos.AddRange(new DataInfo[]
{
@@ -1025,22 +1006,18 @@ internal static class DLT645Helper
break;
}
break;
case 11:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 2, Digtal = 0, IsSigned = false } });
break;
case 12:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 4, Digtal = 0, IsSigned = false } });
break;
case 13:
dataInfos.AddRange(new DataInfo[]
{
new(){ ByteLength=2,Digtal=3,IsSigned=false},
});
break;
case 14:
if (buffer[0] < 3)
dataInfos.AddRange(new DataInfo[]
@@ -1055,7 +1032,6 @@ internal static class DLT645Helper
break;
}
break;
case 1:
case 2:
if (buffer[1] == 0)
@@ -1066,12 +1042,10 @@ internal static class DLT645Helper
}
}
break;
case 3:
case 4:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 4, Digtal = 0, IsSigned = false } });
break;
case 0x80:
dataInfos.AddRange(new DataInfo[] { new() { ByteLength = 32, Digtal = -1, IsSigned = false } });
break;
@@ -1096,7 +1070,6 @@ internal static class DLT645Helper
break;
}
break;
case 1:
case 2:
case 3:
@@ -1119,7 +1092,6 @@ internal static class DLT645Helper
new(){ ByteLength=5,Digtal=0,IsSigned=false},
});
break;
case 16:
for (int i = 0; i < 8; i++)
{
@@ -1146,7 +1118,6 @@ internal static class DLT645Helper
new(){ ByteLength=1,Digtal=0,IsSigned=false},
});
break;
case 1:
dataInfos.AddRange(new DataInfo[]
{
@@ -1155,7 +1126,6 @@ internal static class DLT645Helper
break;
}
break;
default:
if (buffer[0] == 2)
dataInfos.AddRange(new DataInfo[]
@@ -1170,6 +1140,8 @@ internal static class DLT645Helper
return dataInfos;
}
/// <summary>
/// 获取DLT645报文
/// </summary>
@@ -1239,9 +1211,12 @@ internal static class DLT645Helper
}
}
buffer = buffer.SpliceArray(codes, buffers.ToArray());
}
byte[] stationBytes;
if (operResult.Station.Length == 0)
{
@@ -1256,13 +1231,14 @@ internal static class DLT645Helper
}
return GetDLT645_2007Command(control, buffer, stationBytes);
}
catch (Exception ex)
{
return new(ex);
}
}
}
internal static OperResult<byte[]> GetDLT645_2007Command(byte control, byte[] buffer, byte[] stationBytes)
{
buffer ??= new byte[0];
@@ -1286,4 +1262,4 @@ internal static class DLT645Helper
array[array.Length - 1] = 0x16;// 结束符
return OperResult.CreateSuccessResult(array);
}
}
}

View File

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

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Text;
@@ -28,23 +26,23 @@ public class DLT645_2007Address : DeviceAddressBase
/// </summary>
public DLT645_2007Address()
{
}
/// <summary>
/// 数据标识
/// </summary>
public byte[] DataId { get; set; } = new byte[0];
/// <summary>
/// 反转解析
/// </summary>
public bool Reverse { get; set; } = true;
/// <summary>
/// 站号信息
/// </summary>
public byte[] Station { get; set; } = new byte[0];
/// <summary>
/// 解析地址
/// </summary>
@@ -52,7 +50,7 @@ public class DLT645_2007Address : DeviceAddressBase
/// <returns></returns>
public static DLT645_2007Address ParseFrom(string address)
{
DLT645_2007Address dlt645_2007Address = new();
DLT645_2007Address dLT645_2007Address = new();
byte[] array;
array = new byte[0];
if (address.IndexOf(';') < 0)
@@ -61,7 +59,7 @@ public class DLT645_2007Address : DeviceAddressBase
}
else
{
string[] strArray = address.SplitStringBySemicolon();
string[] strArray = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
for (int index = 0; index < strArray.Length; ++index)
{
@@ -71,11 +69,11 @@ public class DLT645_2007Address : DeviceAddressBase
if (station.IsNullOrEmpty()) station = string.Empty;
if (station.Length < 12)
station = station.PadLeft(12, '0');
dlt645_2007Address.Station = station.ByHexStringToBytes().Reverse().ToArray();
dLT645_2007Address.Station = station.ByHexStringToBytes().Reverse().ToArray();
}
else if (strArray[index].Contains("r="))
{
dlt645_2007Address.Reverse = strArray[index].Substring(2).ToBool(false);
dLT645_2007Address.Reverse = strArray[index].Substring(2).GetBoolValue();
}
else if (!strArray[index].Contains("="))
{
@@ -83,8 +81,9 @@ public class DLT645_2007Address : DeviceAddressBase
}
}
}
dlt645_2007Address.DataId = array;
return dlt645_2007Address;
dLT645_2007Address.DataId = array;
return dLT645_2007Address;
}
/// <inheritdoc/>
@@ -101,8 +100,10 @@ public class DLT645_2007Address : DeviceAddressBase
}
if (!Reverse)
{
stringGeter.Append($"s={Reverse};");
stringGeter.Append($"s={Reverse.ToString()};");
}
return stringGeter.ToString();
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Text;
@@ -17,7 +15,6 @@ using System.Text;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.DLT645;
/// <summary>
/// DLT645_2007
/// </summary>
@@ -30,48 +27,6 @@ public class DLT645_2007BitConverter : ThingsGatewayBitConverter
{
}
/// <inheritdoc/>
public override short ToInt16(byte[] buffer, int offset)
{
return Convert.ToInt16(this.ToString(buffer, offset, buffer.Length));
}
/// <inheritdoc/>
public override ushort ToUInt16(byte[] buffer, int offset)
{
return Convert.ToUInt16(this.ToString(buffer, offset, buffer.Length));
}
/// <inheritdoc/>
public override float ToSingle(byte[] buffer, int offset)
{
return Convert.ToSingle(this.ToString(buffer, offset, buffer.Length));
}
/// <inheritdoc/>
public override long ToInt64(byte[] buffer, int offset)
{
return Convert.ToInt64(this.ToString(buffer, offset, buffer.Length));
}
/// <inheritdoc/>
public override int ToInt32(byte[] buffer, int offset)
{
return Convert.ToInt32(this.ToString(buffer, offset, buffer.Length));
}
/// <inheritdoc/>
public override uint ToUInt32(byte[] buffer, int offset)
{
return Convert.ToUInt32(this.ToString(buffer, offset, buffer.Length));
}
/// <inheritdoc/>
public override ulong ToUInt64(byte[] buffer, int offset)
{
return Convert.ToUInt64(this.ToString(buffer, offset, buffer.Length));
}
/// <summary>
/// DLT645协议转换double
/// </summary>
@@ -96,6 +51,7 @@ public class DLT645_2007BitConverter : ThingsGatewayBitConverter
};
}
/// <inheritdoc/>
public override string ToString(byte[] buffer)
{
@@ -156,4 +112,6 @@ public class DLT645_2007BitConverter : ThingsGatewayBitConverter
}
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
@@ -21,7 +19,7 @@ namespace ThingsGateway.Foundation.Adapter.DLT645;
/// <summary>
/// DLT645_2007DataHandleAdapter
/// </summary>
internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHandleAdapter<DLT645_2007Message>
public class DLT645_2007DataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<DLT645_2007Message>
{
/// <summary>
/// 增加FE FE FE FE的报文头部
@@ -46,6 +44,7 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
return new DLT645_2007Message();
}
/// <inheritdoc/>
protected override FilterResult UnpackResponse(DLT645_2007Message request, byte[] send, byte[] body, byte[] response)
{
@@ -79,6 +78,7 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
if (headCodeIndex < 0 || headCodeIndex + 10 > response.Length)
return FilterResult.Cache;
var len = 10 + response[headCodeIndex + 9] + 2;
if (response.Length - headCodeIndex < len)
@@ -87,6 +87,7 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
}
if (response.Length - headCodeIndex >= len && response[len + headCodeIndex - 1] == 0x16)
{
//检查校验码
int sumCheck = 0;
for (int i = headCodeIndex; i < len + headCodeIndex - 2; i++)
@@ -108,6 +109,7 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
(response[headCodeIndex + 6] != send[sendHeadCodeIndex + 6])
)//设备地址不符合时,返回错误
{
if (
(send[sendHeadCodeIndex + 1] == 0xAA) &&
(send[sendHeadCodeIndex + 2] == 0xAA) &&
@@ -117,6 +119,7 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
(send[sendHeadCodeIndex + 6] == 0xAA)
)//读写通讯地址例外
{
}
else
{
@@ -124,8 +127,11 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
request.ErrorCode = 999;
return FilterResult.Success;
}
}
if ((response[headCodeIndex + 8] != send[sendHeadCodeIndex + 8] + 0x80))//控制码不符合时,返回错误
{
request.Message = $"返回控制码0x{response[headCodeIndex + 8]:X2}请求控制码0x{send[sendHeadCodeIndex + 8]:X2},不符合规则";
@@ -133,6 +139,9 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
return FilterResult.Success;
}
if ((response[headCodeIndex + 8] & 0x40) == 0x40)//控制码bit6为1时返回错误
{
byte byte1 = (byte)(response[headCodeIndex + 10] - 0x33);
@@ -154,6 +163,7 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
(response[headCodeIndex + 13] == send[sendHeadCodeIndex + 13])
)
{
}
else
{
@@ -161,16 +171,21 @@ internal class DLT645_2007DataHandleAdapter : ReadWriteDevicesSingleStreamDataHa
request.ErrorCode = 999;
return FilterResult.Success;
}
}
request.Content = response.RemoveBegin(headCodeIndex + 10).RemoveLast(response.Length + 2 - len - headCodeIndex);
request.ErrorCode = 0;
return FilterResult.Success;
}
else
{
request.ErrorCode = 999;
return FilterResult.Success;
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,15 +8,13 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.DLT645;
/// <summary>
/// <inheritdoc/>
/// </summary>
internal class DLT645_2007Message : MessageBase, IMessage
public class DLT645_2007Message : MessageBase, IMessage
{
/// <inheritdoc/>
public override int HeadBytesLength => -1;
@@ -28,4 +25,7 @@ internal class DLT645_2007Message : MessageBase, IMessage
BodyLength = -1;
return true;
}
}

View File

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

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,43 +8,36 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.DLT645;
internal static class PackHelper
{
/// <summary>
/// 打包变量,添加到<see href="deviceVariableSourceReads"></see>
/// </summary>
/// <param name="device"></param>
/// <param name="deviceVariables"></param>
/// <param name="maxPack">最大打包长度</param>
/// <param name="defaultIntervalTime">默认间隔时间</param>
/// <returns></returns>
public static List<T> LoadSourceRead<T, T2>(IReadWrite device, List<T2> deviceVariables, int maxPack, int defaultIntervalTime) where T : IDeviceVariableSourceRead<IDeviceVariableRunTime>, new() where T2 : IDeviceVariableRunTime, new()
public static List<T> LoadSourceRead<T, T2>(IReadWrite device, List<T2> deviceVariables, int maxPack) where T : IDeviceVariableSourceRead<IDeviceVariableRunTime>, new() where T2 : IDeviceVariableRunTime, new()
{
var byteConverter = device.ThingsGatewayBitConverter;
var result = new List<T>();
//需要先剔除额外信息比如dataformat等
foreach (var item in deviceVariables)
{
var address = item.Address;
var address = item.VariableAddress;
IThingsGatewayBitConverter transformParameter = ByteTransformUtil.GetTransByAddress(ref address, byteConverter);
item.ThingsGatewayBitConverter = transformParameter;
//item.Address = address;
item.Index = device.GetBitOffset(item.Address);
//item.VariableAddress = address;
item.Index = device.GetBitOffset(item.VariableAddress);
result.Add(new()
{
DeviceVariableRunTimes = new() { item },
Address = address,
VariableAddress = address,
Length = 1,
IntervalTimeTick = new(item.IntervalTime ?? defaultIntervalTime)
});
}
return result;
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
@@ -19,5 +17,5 @@ global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.SerialPorts;
global using ThingsGateway.Foundation.Sockets;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
@@ -19,5 +17,5 @@ global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.SerialPorts;
global using ThingsGateway.Foundation.Sockets;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,11 +8,11 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Text;
using ThingsGateway.Foundation.Extension;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Foundation.Adapter.Modbus;
@@ -28,13 +27,12 @@ public class ModbusAddress : DeviceAddressBase
/// </summary>
public ModbusAddress()
{
}
}
/// <summary>
/// 读取功能码
/// </summary>
public ushort AddressStart => Address.ToUShort();
/// <summary>
/// 读取功能码
/// </summary>
@@ -49,16 +47,14 @@ public class ModbusAddress : DeviceAddressBase
/// 写入功能码
/// </summary>
public byte WriteFunction { get; set; }
/// <summary>
/// 打包临时写入,需要读取的字节长度
/// </summary>
public int ByteLength { get; set; }
/// <summary>
/// BitIndex
/// </summary>
public int BitIndex => (int)(Address.SplitStringByDelimiter().LastOrDefault().ToInt());
public int BitIndex => (int)(Address.SplitDot().LastOrDefault().ToInt());
/// <summary>
/// 读取功能码
@@ -69,7 +65,6 @@ public class ModbusAddress : DeviceAddressBase
/// 作为Slave时需提供的SocketId用于分辨Socket客户端通常对比的是初始链接时的注册包
/// </summary>
public string SocketId { get; set; }
/// <summary>
/// 解析地址
/// </summary>
@@ -81,7 +76,6 @@ public class ModbusAddress : DeviceAddressBase
};
return ParseFrom(address, modbusAddress);
}
/// <summary>
/// 解析地址
/// </summary>
@@ -94,7 +88,7 @@ public class ModbusAddress : DeviceAddressBase
}
else
{
string[] strArray = address.SplitStringBySemicolon();
string[] strArray = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
for (int index = 0; index < strArray.Length; ++index)
{
if (strArray[index].ToUpper().StartsWith("S="))
@@ -130,23 +124,23 @@ public class ModbusAddress : DeviceAddressBase
case 0:
modbusAddress.ReadFunction = 1;
break;
case 1:
modbusAddress.ReadFunction = 2;
break;
case 3:
modbusAddress.ReadFunction = 4;
break;
case 4:
modbusAddress.ReadFunction = 3;
break;
}
modbusAddress.Address = (double.Parse(address.Substring(1)) - 1).ToString();
}
}
/// <inheritdoc/>
public override string ToString()
{

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Text;
@@ -26,7 +24,7 @@ internal class ModbusHelper
/// </summary>
internal static byte[] AddCrc(byte[] command)
{
return CRC16Utils.CRC16(command);
return EasyCRC16.CRC16(command);
}
/// <summary>
@@ -62,7 +60,6 @@ internal class ModbusHelper
stringBuilder.AppendLine("写入功能码 比如40001;w=16; 代表保持寄存器第一个寄存器写入值时采用0x10功能码而不是默认的0x06功能码");
return stringBuilder.ToString();
}
/// <summary>
/// 通过错误码来获取到对应的文本消息
/// </summary>
@@ -91,6 +88,7 @@ internal class ModbusHelper
if (response.Length < 3)
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
if (response[1] >= 0x80)//错误码
return new OperResult<byte[], FilterResult>(GetDescriptionByErrorCode(response[2])) { Content2 = FilterResult.Success };
if (response[1] <= 0x05)
@@ -102,6 +100,7 @@ internal class ModbusHelper
{
if ((response.Length < 6))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
}
if (send.Length == 0)
@@ -121,7 +120,6 @@ internal class ModbusHelper
return new OperResult<byte[], FilterResult>(ex) { Content2 = FilterResult.Success };
}
}
/// <summary>
/// 去除Crc返回modbus数据区
/// </summary>
@@ -136,23 +134,25 @@ internal class ModbusHelper
if (response[1] >= 0x80)//错误码
return new OperResult<byte[], FilterResult>(GetDescriptionByErrorCode(response[2])) { Content2 = FilterResult.Success };
if (response[1] <= 0x04)
if (response[1] <= 0x05)
{
if ((response.Length < response[2] + 5))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
}
else
{
if ((response.Length < 8))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
}
var data = response.SelectMiddle(0, response[1] <= 0x04 ? response[2] != 0 ? response[2] + 5 : 8 : 8);
if (crcCheck && !CRC16Utils.CheckCRC16(data))
var data = response.SelectMiddle(0, response[2] != 0 ? response[2] + 5 : 8);
if (crcCheck && !EasyCRC16.CheckCRC16(data))
return new OperResult<byte[], FilterResult>("Crc校验失败" + DataTransUtil.ByteToHexString(data, ' ')) { Content2 = FilterResult.Success };
return GetModbusData(send, data.RemoveLast(2));
}
/// <summary>
/// 获取读取报文
/// </summary>
@@ -168,7 +168,6 @@ internal class ModbusHelper
return new OperResult<byte[]>(ex);
}
}
/// <summary>
/// 获取写入布尔量报文,根据地址识别功能码
/// </summary>
@@ -204,13 +203,13 @@ internal class ModbusHelper
return OperResult.CreateSuccessResult(GetWriteModbusCommand(mAddress, value));
else
return OperResult.CreateSuccessResult(GetWriteOneModbusCommand(mAddress, value));
}
catch (Exception ex)
{
return new OperResult<byte[]>(ex);
}
}
/// <summary>
/// 获取读取报文
/// </summary>
@@ -331,4 +330,5 @@ internal class ModbusHelper
values.CopyTo(numArray, 4);
return numArray;
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,23 +8,22 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// ModbusRtu
/// </summary>
public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
public class ModbusRtu : ReadWriteDevicesSerialSessionBase
{
/// <summary>
/// ModbusRtu
/// </summary>
/// <param name="serialPortClient"></param>
public ModbusRtu(SerialPortClient serialPortClient) : base(serialPortClient)
/// <param name="serialSession"></param>
public ModbusRtu(SerialSession serialSession) : base(serialSession)
{
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
RegisterByteLength = 2;
@@ -43,26 +41,30 @@ public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
[Description("站号")]
public byte Station { get; set; } = 1;
/// <inheritdoc/>
public override string GetAddressDescription()
{
return $"{base.GetAddressDescription()}{Environment.NewLine}{ModbusHelper.GetAddressDescription()}";
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack, int defaultIntervalTime)
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack, defaultIntervalTime);
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
try
{
Connect(cancellationToken);
return ModbusHelper.GetReadModbusCommand(address, length, Station).Then(a => SendThenReturn<ModbusRtuMessage>(a, cancellationToken));
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -77,8 +79,7 @@ public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -87,14 +88,14 @@ public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
}
/// <inheritdoc/>
public override void SetDataAdapter(ISocketClient socketClient = default)
public override void SetDataAdapter(object socketClient = null)
{
ModbusRtuDataHandleAdapter dataHandleAdapter = new()
{
Crc16CheckEnable = Crc16CheckEnable,
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
};
SerialPortClient.SetDataHandlingAdapter(dataHandleAdapter);
SerialSession.SetDataHandlingAdapter(dataHandleAdapter);
}
/// <inheritdoc/>
@@ -104,8 +105,7 @@ public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -120,8 +120,7 @@ public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -136,8 +135,7 @@ public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -152,12 +150,42 @@ public class ModbusRtu : ReadWriteDevicesSerialPortClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
return new OperResult(ex);
}
}
}
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
if (FrameTime != 0)
Thread.Sleep(FrameTime);
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
await Task.Delay(FrameTime, cancellationToken);
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
@@ -19,13 +17,12 @@ namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// Rtu适配器
/// </summary>
internal class ModbusRtuDataHandleAdapter : ReadWriteDevicesSingleStreamDataHandleAdapter<ModbusRtuMessage>
public class ModbusRtuDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusRtuMessage>
{
/// <summary>
/// 检测CRC
/// </summary>
public bool Crc16CheckEnable { get; set; } = true;
/// <summary>
/// <inheritdoc/>
/// </summary>
@@ -42,6 +39,7 @@ internal class ModbusRtuDataHandleAdapter : ReadWriteDevicesSingleStreamDataHand
return new ModbusRtuMessage();
}
/// <inheritdoc/>
protected override FilterResult UnpackResponse(ModbusRtuMessage request, byte[] send, byte[] body, byte[] response)
{
@@ -82,4 +80,6 @@ internal class ModbusRtuDataHandleAdapter : ReadWriteDevicesSingleStreamDataHand
return FilterResult.Success;
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,15 +8,13 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
internal class ModbusRtuMessage : MessageBase, IMessage
public class ModbusRtuMessage : MessageBase, IMessage
{
/// <inheritdoc/>
public override int HeadBytesLength => -1;
@@ -28,4 +25,7 @@ internal class ModbusRtuMessage : MessageBase, IMessage
BodyLength = -1;
return true;
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,16 +8,17 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <inheritdoc/>
public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
{
/// <inheritdoc/>
public ModbusRtuOverTcp(TcpClient tcpClient) : base(tcpClient)
{
@@ -37,13 +37,13 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
/// </summary>
[Description("站号")]
public byte Station { get; set; } = 1;
/// <inheritdoc/>
public override string GetAddressDescription()
{
return $"{base.GetAddressDescription()}{Environment.NewLine}{ModbusHelper.GetAddressDescription()}";
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
@@ -51,8 +51,7 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -67,8 +66,7 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -77,13 +75,14 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack, int defaultIntervalTime)
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack, defaultIntervalTime);
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
public override void SetDataAdapter(ISocketClient socketClient = default)
public override void SetDataAdapter(object socketClient = null)
{
ModbusRtuDataHandleAdapter dataHandleAdapter = new()
{
@@ -100,8 +99,7 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -116,8 +114,7 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -132,8 +129,7 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -148,12 +144,42 @@ public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
return new OperResult(ex);
}
}
}
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
if (FrameTime != 0)
Thread.Sleep(FrameTime);
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
await Task.Delay(FrameTime, cancellationToken);
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
@@ -37,13 +35,11 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
/// </summary>
[Description("站号")]
public byte Station { get; set; } = 1;
/// <inheritdoc/>
public override string GetAddressDescription()
{
return $"{base.GetAddressDescription()}{Environment.NewLine}{ModbusHelper.GetAddressDescription()}";
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
@@ -51,8 +47,7 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -67,8 +62,7 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -77,7 +71,7 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
}
/// <inheritdoc/>
public override void SetDataAdapter(ISocketClient socketClient = default)
public override void SetDataAdapter(object socketClient = null)
{
ModbusRtuOverUdpDataHandleAdapter dataHandleAdapter = new()
{
@@ -91,9 +85,10 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack, int defaultIntervalTime)
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack, defaultIntervalTime);
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
@@ -103,8 +98,7 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -119,8 +113,7 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -135,8 +128,7 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -151,12 +143,42 @@ public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusRtuMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
return new OperResult(ex);
}
}
}
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
if (FrameTime != 0)
Thread.Sleep(FrameTime);
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
await Task.Delay(FrameTime, cancellationToken);
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.Modbus;
@@ -17,7 +15,7 @@ namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
internal class ModbusRtuOverUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter<ModbusRtuMessage>
public class ModbusRtuOverUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter<ModbusRtuMessage>
{
/// <summary>
/// 检测CRC
@@ -42,4 +40,4 @@ internal class ModbusRtuOverUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandle
var result = ModbusHelper.GetModbusRtuData(send, response, Crc16CheckEnable);
return result;
}
}
}

View File

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

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
@@ -17,7 +15,7 @@ using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <inheritdoc/>
internal class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesSingleStreamDataHandleAdapter<ModbusSerialServerMessage>
public class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusSerialServerMessage>
{
private readonly ThingsGatewayBitConverter ThingsGatewayBitConverter = new(EndianType.Big);
@@ -36,7 +34,7 @@ internal class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesSingleStrea
/// </summary>
/// <param name="response">返回数据</param>
/// <returns></returns>
internal OperResult<byte[], FilterResult> GetModbusData(byte[] response)
internal OperResult<byte[]> GetModbusData(byte[] response)
{
try
{
@@ -44,30 +42,22 @@ internal class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesSingleStrea
if (func == 1 || func == 2 || func == 3 || func == 4 || func == 5 || func == 6)
{
if (response.Length == 6)
return OperResult.CreateSuccessResult(response, FilterResult.Success);
return OperResult.CreateSuccessResult(response);
}
else if (func == 15 || func == 16)
{
var length = ThingsGatewayBitConverter.ToByte(response, 6);
if (response.Length == 7 + length)
{
return OperResult.CreateSuccessResult(response, FilterResult.Success);
}
if (response.Length > 7 + length)
{
return new() { Content2 = FilterResult.Success, Message = $"数据长度{response.Length}错误" };
}
else
{
return new() { Content2 = FilterResult.Cache, Message = $"数据长度{response.Length}错误" };
return OperResult.CreateSuccessResult(response);
}
}
return new() { Content2 = FilterResult.Success, Message = $"数据长度{response.Length}错误" };
return new OperResult<byte[]>() { Message = $"数据长度{response.Length}错误" };
}
catch (Exception ex)
{
return new(ex) { Content2 = FilterResult.Success };
return new OperResult<byte[]>(ex);
}
}
@@ -98,7 +88,7 @@ internal class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesSingleStrea
{
if (function > 6)
{
request.ModbusAddress = new ModbusAddress()
request.CurModbusAddress = new ModbusAddress()
{
Station = station,
Address = addressStart.ToString(),
@@ -110,7 +100,7 @@ internal class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesSingleStrea
}
else
{
request.ModbusAddress = new ModbusAddress()
request.CurModbusAddress = new ModbusAddress()
{
Station = station,
Address = addressStart.ToString(),
@@ -123,7 +113,7 @@ internal class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesSingleStrea
}
else
{
request.ModbusAddress = new ModbusAddress()
request.CurModbusAddress = new ModbusAddress()
{
Station = station,
Address = addressStart.ToString(),
@@ -139,12 +129,13 @@ internal class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesSingleStrea
{
request.ErrorCode = result.ErrorCode;
request.Message = result.Message;
return result.Content2;
return FilterResult.Cache;
}
}
else
{
return result1.Content2;
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.Modbus;
@@ -17,12 +15,15 @@ namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
internal class ModbusSerialServerMessage : MessageBase, IMessage, IModbusServerMessage
public class ModbusSerialServerMessage : MessageBase, IMessage
{
/// <inheritdoc/>
public ModbusAddress ModbusAddress { get; set; }
/// <inheritdoc/>
/// <summary>
/// 当前关联的地址
/// </summary>
public ModbusAddress CurModbusAddress { get; set; }
/// <summary>
/// 当前读写的数据长度
/// </summary>
public int Length { get; set; }
/// <inheritdoc/>
@@ -34,4 +35,6 @@ internal class ModbusSerialServerMessage : MessageBase, IMessage, IModbusServerM
BodyLength = -1;
return true;
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,29 +8,26 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <inheritdoc/>
public class ModbusTcp : ReadWriteDevicesTcpClientBase
{
/// <inheritdoc/>
public ModbusTcp(TcpClient tcpClient) : base(tcpClient)
{
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
RegisterByteLength = 2;
}
/// <summary>
/// 检测事务标识符
/// </summary>
[Description("检测事务标识符")]
public bool IsCheckMessageId { get; set; }
/// <summary>
/// 站号
/// </summary>
@@ -41,13 +37,13 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
/// <inheritdoc/>
public override string GetAddressDescription()
{
return $"{base.GetAddressDescription()}{Environment.NewLine}{ModbusHelper.GetAddressDescription()}";
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack, int defaultIntervalTime)
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack, defaultIntervalTime);
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
@@ -57,8 +53,8 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusTcpMessage>(commandResult.Content, cancellationToken);
var data = SendThenReturn(commandResult, cancellationToken);
return data;
}
catch (Exception ex)
{
@@ -74,8 +70,8 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusTcpMessage>(commandResult.Content, cancellationToken);
var data = await SendThenReturnAsync(commandResult, cancellationToken);
return data;
}
catch (Exception ex)
{
@@ -83,8 +79,9 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
}
}
/// <inheritdoc/>
public override void SetDataAdapter(ISocketClient socketClient = default)
public override void SetDataAdapter(object socketClient = null)
{
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
{
@@ -101,8 +98,7 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -117,8 +113,7 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -133,8 +128,7 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -149,12 +143,42 @@ public class ModbusTcp : ReadWriteDevicesTcpClientBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
return new OperResult(ex);
}
}
}
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
if (FrameTime != 0)
Thread.Sleep(FrameTime);
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
await Task.Delay(FrameTime, cancellationToken);
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
@@ -19,9 +17,9 @@ namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// ModbusTcpDataHandleAdapter
/// </summary>
internal class ModbusTcpDataHandleAdapter : ReadWriteDevicesSingleStreamDataHandleAdapter<ModbusTcpMessage>
public class ModbusTcpDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusTcpMessage>
{
private readonly IncrementCount _incrementCount = new(ushort.MaxValue);
private readonly EasyIncrementCount easyIncrementCount = new(ushort.MaxValue);
/// <summary>
/// 检测事务标识符
@@ -41,7 +39,7 @@ internal class ModbusTcpDataHandleAdapter : ReadWriteDevicesSingleStreamDataHand
/// <inheritdoc/>
public override byte[] PackCommand(byte[] command)
{
return ModbusHelper.AddModbusTcpHead(command, (ushort)_incrementCount.GetCurrentValue());
return ModbusHelper.AddModbusTcpHead(command, (ushort)easyIncrementCount.GetCurrentValue());
}
/// <inheritdoc/>
@@ -67,5 +65,6 @@ internal class ModbusTcpDataHandleAdapter : ReadWriteDevicesSingleStreamDataHand
request.Message = result.Message;
}
return result.Content2;
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,24 +8,20 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
internal class ModbusTcpMessage : MessageBase, IMessage
public class ModbusTcpMessage : MessageBase, IMessage
{
/// <inheritdoc/>
public override int HeadBytesLength => 6;
/// <summary>
/// 检测事务标识符
/// </summary>
public bool IsCheckMessageId { get; set; } = false;
/// <inheritdoc/>
public override bool CheckHeadBytes(byte[] heads)
{
@@ -34,7 +29,6 @@ internal class ModbusTcpMessage : MessageBase, IMessage
HeadBytes = heads;
int num = (HeadBytes[4] * 256) + HeadBytes[5];
if (num > 0xff + 3) return false;
BodyLength = num;
if (!IsCheckMessageId)
@@ -42,4 +36,6 @@ internal class ModbusTcpMessage : MessageBase, IMessage
else
return SendBytes[0] == HeadBytes[0] && SendBytes[1] == HeadBytes[1] && HeadBytes[2] == 0 && HeadBytes[3] == 0;
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,22 +8,20 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <inheritdoc/>
public class ModbusDtu : ReadWriteDevicesTcpServerBase
public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
{
/// <inheritdoc/>
public ModbusDtu(TcpService tcpService) : base(tcpService)
public ModbusTcpDtu(TcpService tcpService) : base(tcpService)
{
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
RegisterByteLength = 2;
ModbusDtuPlugin modbusTcpSalvePlugin = new ModbusDtuPlugin();
ModbusTcpDtuPlugin modbusTcpSalvePlugin = new ModbusTcpDtuPlugin();
tcpService.Config.ConfigurePlugins(a =>
{
a.Add(modbusTcpSalvePlugin);
@@ -38,18 +35,6 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
[Description("检测事务标识符")]
public bool IsCheckMessageId { get; set; }
/// <summary>
/// 是否Rtu格式
/// </summary>
[Description("是否Rtu格式")]
public bool IsRtu { get; set; }
/// <summary>
/// Crc校验
/// </summary>
[Description("Crc校验")]
public bool Crc16CheckEnable { get; set; } = true;
/// <summary>
/// 站号
/// </summary>
@@ -59,13 +44,13 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
/// <inheritdoc/>
public override string GetAddressDescription()
{
return $"{base.GetAddressDescription()}{Environment.NewLine}{ModbusHelper.GetAddressDescription()}";
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack, int defaultIntervalTime)
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack, defaultIntervalTime);
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
@@ -76,8 +61,7 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
Connect(cancellationToken);
var mAddress = ModbusAddress.ParseFrom(address, Station);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn(mAddress.SocketId, commandResult.Content, cancellationToken);
return SendThenReturn(mAddress.SocketId, commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -93,8 +77,7 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
await ConnectAsync(cancellationToken);
var mAddress = ModbusAddress.ParseFrom(address, Station);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync(mAddress.SocketId, commandResult.Content, cancellationToken);
return await SendThenReturnAsync(mAddress.SocketId, commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -103,53 +86,27 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
}
/// <inheritdoc/>
public override void SetDataAdapter(ISocketClient socketClient = default)
public override void SetDataAdapter(object socketClient = null)
{
if (socketClient != default)
if (socketClient is SocketClient client)
{
if (!IsRtu)
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
{
IsCheckMessageId = IsCheckMessageId,
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
};
client.SetDataHandlingAdapter(dataHandleAdapter);
}
else
{
foreach (var item in TcpService.GetClients())
{
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
{
IsCheckMessageId = IsCheckMessageId,
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
};
socketClient.SetDataHandlingAdapter(dataHandleAdapter);
}
else
{
ModbusRtuDataHandleAdapter dataHandleAdapter = new()
{
Crc16CheckEnable = Crc16CheckEnable,
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
};
socketClient.SetDataHandlingAdapter(dataHandleAdapter);
}
}
else
{
//只适配第一个
var item = TcpService.GetClients().FirstOrDefault();
if (item != null)
{
if (!IsRtu)
{
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
{
IsCheckMessageId = IsCheckMessageId,
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
};
item.SetDataHandlingAdapter(dataHandleAdapter);
}
else
{
ModbusRtuDataHandleAdapter dataHandleAdapter = new()
{
Crc16CheckEnable = Crc16CheckEnable,
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
};
item.SetDataHandlingAdapter(dataHandleAdapter);
}
item.SetDataHandlingAdapter(dataHandleAdapter);
}
}
}
@@ -162,8 +119,7 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
Connect(cancellationToken);
var mAddress = ModbusAddress.ParseFrom(address, Station);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn(mAddress.SocketId, commandResult.Content, cancellationToken);
return SendThenReturn(mAddress.SocketId, commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -179,8 +135,7 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
Connect(cancellationToken);
var mAddress = ModbusAddress.ParseFrom(address, Station);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn(mAddress.SocketId, commandResult.Content, cancellationToken);
return SendThenReturn(mAddress.SocketId, commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -196,8 +151,7 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
await ConnectAsync(cancellationToken);
var mAddress = ModbusAddress.ParseFrom(address, Station);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync(mAddress.SocketId, commandResult.Content, cancellationToken);
return await SendThenReturnAsync(mAddress.SocketId, commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -213,8 +167,7 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
await ConnectAsync(cancellationToken);
var mAddress = ModbusAddress.ParseFrom(address, Station);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync(mAddress.SocketId, commandResult.Content, cancellationToken);
return await SendThenReturnAsync(mAddress.SocketId, commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -222,41 +175,64 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
}
}
private OperResult<byte[]> SendThenReturn(string id, byte[] command, CancellationToken cancellationToken)
private OperResult<byte[]> SendThenReturn(string id, OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (TcpService.TryGetSocketClient($"ID={id}", out var client))
if (commandResult.IsSuccess)
{
SetDataAdapter(client);
return SendThenReturn<MessageBase>(command, cancellationToken, client);
if (TcpService.TryGetSocketClient($"ID={id}", out var client))
{
SetDataAdapter(client);
var item = commandResult.Content;
if (FrameTime != 0)
Thread.Sleep(FrameTime);
var WaitingClientEx = client.CreateWaitingClient(new() { ThrowBreakException = true });
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>("客户端未连接");
}
}
else
{
return new OperResult<byte[]>("客户端未连接");
return commandResult;
}
}
private async Task<OperResult<byte[]>> SendThenReturnAsync(string id, byte[] command, CancellationToken cancellationToken)
private async Task<OperResult<byte[]>> SendThenReturnAsync(string id, OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (TcpService.TryGetSocketClient($"ID={id}", out var client))
if (commandResult.IsSuccess)
{
SetDataAdapter(client);
return await SendThenReturnAsync<MessageBase>(command, cancellationToken, client);
}
else if (TcpService.SocketClients.Count == 1)
{
var client1 = TcpService.SocketClients.GetClients().FirstOrDefault();
if (client1 != null)
if (TcpService.TryGetSocketClient($"ID={id}", out var client))
{
SetDataAdapter(client1);
return await SendThenReturnAsync<MessageBase>(command, cancellationToken, client1);
SetDataAdapter(client);
var item = commandResult.Content;
await Task.Delay(FrameTime, cancellationToken);
var WaitingClientEx = client.CreateWaitingClient(new() { ThrowBreakException = true });
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>("客户端未连接");
}
}
return new OperResult<byte[]>("客户端未连接");
else
{
return commandResult;
}
}
internal class ModbusDtuPlugin : PluginBase, ITcpReceivingPlugin
internal class ModbusTcpDtuPlugin : PluginBase, ITcpReceivingPlugin
{
public async Task OnTcpReceiving(ITcpClientBase client, ByteBlockEventArgs e)
public Task OnTcpReceiving(ITcpClientBase client, ByteBlockEventArgs e)
{
if (client is ISocketClient socket)
{
@@ -267,7 +243,7 @@ public class ModbusDtu : ReadWriteDevicesTcpServerBase
socket.ResetId(id);
}
}
await e.InvokeNext();//如果本插件无法处理当前数据,请将数据转至下一个插件。
return e.InvokeNext();//如果本插件无法处理当前数据,请将数据转至下一个插件。
}
}
}
}

View File

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

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
@@ -17,7 +15,7 @@ using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <inheritdoc/>
internal class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesSingleStreamDataHandleAdapter<ModbusTcpServerMessage>
public class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusTcpServerMessage>
{
private readonly ThingsGatewayBitConverter ThingsGatewayBitConverter = new(EndianType.Big);
@@ -36,7 +34,7 @@ internal class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesSingleStreamDa
/// </summary>
/// <param name="response">返回数据</param>
/// <returns></returns>
internal OperResult<byte[], FilterResult> GetModbusData(byte[] response)
internal OperResult<byte[]> GetModbusData(byte[] response)
{
try
{
@@ -44,30 +42,22 @@ internal class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesSingleStreamDa
if (func == 1 || func == 2 || func == 3 || func == 4 || func == 5 || func == 6)
{
if (response.Length == 6)
return OperResult.CreateSuccessResult(response, FilterResult.Success);
return OperResult.CreateSuccessResult(response);
}
else if (func == 15 || func == 16)
{
var length = ThingsGatewayBitConverter.ToByte(response, 6);
if (response.Length == 7 + length)
{
return OperResult.CreateSuccessResult(response, FilterResult.Success);
}
if (response.Length > 7 + length)
{
return new() { Content2 = FilterResult.Success, Message = $"数据长度{response.Length}错误" };
}
else
{
return new() { Content2 = FilterResult.Cache, Message = $"数据长度{response.Length}错误" };
return OperResult.CreateSuccessResult(response);
}
}
return new() { Content2 = FilterResult.Success, Message = $"数据长度{response.Length}错误" };
return new OperResult<byte[]>() { Message = $"数据长度{response.Length}错误" };
}
catch (Exception ex)
{
return new(ex) { Content2 = FilterResult.Success };
return new OperResult<byte[]>(ex);
}
}
@@ -95,7 +85,7 @@ internal class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesSingleStreamDa
{
if (function > 6)
{
request.ModbusAddress = new ModbusAddress()
request.CurModbusAddress = new ModbusAddress()
{
Station = station,
Address = addressStart.ToString(),
@@ -107,7 +97,7 @@ internal class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesSingleStreamDa
}
else
{
request.ModbusAddress = new ModbusAddress()
request.CurModbusAddress = new ModbusAddress()
{
Station = station,
Address = addressStart.ToString(),
@@ -120,7 +110,7 @@ internal class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesSingleStreamDa
}
else
{
request.ModbusAddress = new ModbusAddress()
request.CurModbusAddress = new ModbusAddress()
{
Station = station,
Address = addressStart.ToString(),
@@ -136,7 +126,7 @@ internal class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesSingleStreamDa
{
request.ErrorCode = result.ErrorCode;
request.Message = result.Message;
return result.Content2;
return FilterResult.Cache;
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.Modbus
@@ -17,13 +15,12 @@ namespace ThingsGateway.Foundation.Adapter.Modbus
/// <summary>
/// <inheritdoc/>
/// </summary>
internal class ModbusTcpServerMessage : MessageBase, IMessage, IModbusServerMessage
public class ModbusTcpServerMessage : MessageBase, IMessage
{
/// <summary>
/// 当前关联的地址
/// </summary>
public ModbusAddress ModbusAddress { get; set; }
public ModbusAddress CurModbusAddress { get; set; }
/// <summary>
/// 当前读写的数据长度
/// </summary>
@@ -31,7 +28,6 @@ namespace ThingsGateway.Foundation.Adapter.Modbus
/// <inheritdoc/>
public override int HeadBytesLength => 6;
/// <inheritdoc/>
public override bool CheckHeadBytes(byte[] heads)
{

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
@@ -19,6 +17,7 @@ namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <inheritdoc/>
public class ModbusUdp : ReadWriteDevicesUdpSessionBase
{
/// <inheritdoc/>
public ModbusUdp(UdpSession udpSession) : base(udpSession)
{
@@ -26,30 +25,31 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
RegisterByteLength = 2;
}
/// <summary>
/// 检测事务标识符
/// </summary>
[Description("检测事务标识符")]
public bool IsCheckMessageId { get; set; }
/// <summary>
/// 站号
/// </summary>
[Description("站号")]
public byte Station { get; set; } = 1;
/// <inheritdoc/>
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack, int defaultIntervalTime)
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
{
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack, defaultIntervalTime);
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
}
/// <inheritdoc/>
public override string GetAddressDescription()
{
return $"{base.GetAddressDescription()}{Environment.NewLine}{ModbusHelper.GetAddressDescription()}";
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
}
/// <inheritdoc/>
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
{
@@ -57,8 +57,7 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -73,8 +72,7 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -83,7 +81,7 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
}
/// <inheritdoc/>
public override void SetDataAdapter(ISocketClient socketClient = default)
public override void SetDataAdapter(object socketClient = null)
{
ModbusUdpDataHandleAdapter dataHandleAdapter = new()
{
@@ -103,8 +101,7 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -119,8 +116,7 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
{
Connect(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return SendThenReturn<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return SendThenReturn(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -135,8 +131,7 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
@@ -151,12 +146,42 @@ public class ModbusUdp : ReadWriteDevicesUdpSessionBase
{
await ConnectAsync(cancellationToken);
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
if (!commandResult.IsSuccess) return commandResult;
return await SendThenReturnAsync<ModbusTcpMessage>(commandResult.Content, cancellationToken);
return await SendThenReturnAsync(commandResult, cancellationToken);
}
catch (Exception ex)
{
return new OperResult(ex);
}
}
}
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
if (FrameTime != 0)
Thread.Sleep(FrameTime);
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
{
if (commandResult.IsSuccess)
{
var item = commandResult.Content;
await Task.Delay(FrameTime, cancellationToken);
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo;
}
else
{
return new OperResult<byte[]>(commandResult.Message);
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,19 +8,17 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
/// <inheritdoc/>
/// </summary>
internal class ModbusUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter<ModbusTcpMessage>
public class ModbusUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter<ModbusTcpMessage>
{
private readonly IncrementCount _incrementCount = new(ushort.MaxValue);
private readonly EasyIncrementCount easyIncrementCount = new(ushort.MaxValue);
/// <summary>
/// 检测事务标识符
@@ -41,7 +38,7 @@ internal class ModbusUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter
/// <inheritdoc/>
public override byte[] PackCommand(byte[] command)
{
return ModbusHelper.AddModbusTcpHead(command, (ushort)_incrementCount.GetCurrentValue());
return ModbusHelper.AddModbusTcpHead(command, (ushort)easyIncrementCount.GetCurrentValue());
}
/// <inheritdoc/>
@@ -56,4 +53,4 @@ internal class ModbusUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter
var result = ModbusHelper.GetModbusData(send.RemoveBegin(6), response.RemoveBegin(6));
return result;
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
@@ -28,9 +26,8 @@ public class PackHelper
/// <param name="device"></param>
/// <param name="deviceVariables"></param>
/// <param name="maxPack">最大打包长度</param>
/// <param name="defaultIntervalTime">默认间隔时间</param>
/// <returns></returns>
public static List<T> LoadSourceRead<T, T2>(IReadWrite device, List<T2> deviceVariables, int maxPack, int defaultIntervalTime) where T : IDeviceVariableSourceRead<IDeviceVariableRunTime>, new() where T2 : IDeviceVariableRunTime, new()
public static List<T> LoadSourceRead<T, T2>(IReadWrite device, List<T2> deviceVariables, int maxPack) where T : IDeviceVariableSourceRead<IDeviceVariableRunTime>, new() where T2 : IDeviceVariableRunTime, new()
{
if (deviceVariables == null)
throw new ArgumentNullException(nameof(deviceVariables));
@@ -40,13 +37,13 @@ public class PackHelper
//需要先剔除额外信息比如dataformat等
foreach (var item in deviceVariables)
{
var address = item.Address;
var address = item.VariableAddress;
IThingsGatewayBitConverter transformParameter = ByteTransformUtil.GetTransByAddress(ref address, byteConverter);
item.ThingsGatewayBitConverter = transformParameter;
//item.Address = address;
item.Index = device.GetBitOffset(item.Address);
//item.VariableAddress = address;
item.Index = device.GetBitOffset(item.VariableAddress);
}
var deviceVariableRunTimeGroups = deviceVariables.GroupBy(it => it.IntervalTime ?? defaultIntervalTime);
var deviceVariableRunTimeGroups = deviceVariables.GroupBy(it => it.IntervalTime);
foreach (var group in deviceVariableRunTimeGroups)
{
Dictionary<ModbusAddress, T2> map = group.ToDictionary(it =>
@@ -59,7 +56,6 @@ public class PackHelper
case DataTypeEnum.String:
lastLen = it.ThingsGatewayBitConverter.Length == null ? throw new("数据类型为字符串时,必须指定字符串长度,才能进行打包") : it.ThingsGatewayBitConverter.Length.Value;
break;
default:
lastLen = 2;
break;
@@ -70,10 +66,10 @@ public class PackHelper
lastLen *= it.ThingsGatewayBitConverter.Length.Value;
}
var address = it.Address;
var address = it.VariableAddress;
if (address.IndexOf('.') > 0)
{
var addressSplits = address.SplitStringByDelimiter();
var addressSplits = address.SplitDot();
address = addressSplits.RemoveLast(1).ArrayToString(".");
}
var result = ModbusAddress.ParseFrom(address);
@@ -100,6 +96,7 @@ public class PackHelper
deviceVariableSourceReads.AddRange(tempResult);
}
}
}
return deviceVariableSourceReads;
@@ -126,6 +123,7 @@ public class PackHelper
readLength = maxPack * 8 * 2;
}
//获取当前的一组打包地址信息,
var tempAddressEnd = orderByAddressEnd.Where(t => t.AddressEnd <= minAddress + readLength).ToList();
//起始地址
@@ -135,9 +133,9 @@ public class PackHelper
T sourceRead = new()
{
IntervalTimeTick = new TimerTick(intervalTime),
TimerTick = new TimerTick(intervalTime),
//这里只需要根据地址排序的第一个地址,作为实际打包报文中的起始地址
Address = startAddress.ToString(),
VariableAddress = startAddress.ToString(),
Length = sourceLen
};
foreach (var item in tempAddressEnd)
@@ -167,4 +165,5 @@ public class PackHelper
}
return sourceReads;
}
}
}

View File

@@ -11,7 +11,7 @@
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.#ctor">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.AddressStart">
@@ -45,7 +45,7 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.Parse(System.String)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ParseFrom(System.String,System.Byte)">
<summary>
@@ -58,7 +58,7 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ToString">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.AddCrc(System.Byte[])">
<summary>
@@ -144,10 +144,10 @@
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.#ctor(ThingsGateway.Foundation.Sockets.TcpClient)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Crc16CheckEnable">
<summary>
@@ -160,37 +160,37 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.GetAddressDescription">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.SetDataAdapter(System.Object)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.#ctor(ThingsGateway.Foundation.Sockets.UdpSession)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Crc16CheckEnable">
<summary>
@@ -203,35 +203,35 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.GetAddressDescription">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.SetDataAdapter(System.Object)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.Crc16CheckEnable">
@@ -240,24 +240,24 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.PackCommand(System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.GetInstance">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.UnpackResponse(System.Byte[],System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu">
<summary>
ModbusRtu
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.#ctor(ThingsGateway.Foundation.SerialPorts.SerialPortClient)">
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.#ctor(ThingsGateway.Foundation.Serial.SerialSession)">
<summary>
ModbusRtu
</summary>
<param name="serialPortClient"></param>
<param name="serialSession"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Crc16CheckEnable">
<summary>
@@ -270,31 +270,31 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.GetAddressDescription">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Read(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.SetDataAdapter(System.Object)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter">
<summary>
@@ -308,34 +308,34 @@
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter.PackCommand(System.Byte[])">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
<param name="command"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter.GetInstance">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage,System.Byte[],System.Byte[],System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage.HeadBytesLength">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage.CheckHeadBytes(System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage.SendBytesThen">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.ModbusServer01ByteBlocks">
@@ -364,7 +364,7 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.#ctor(ThingsGateway.Foundation.Sockets.TcpService)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.MulStation">
<summary>
@@ -377,44 +377,44 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Dispose">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.GetAddressDescription">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Read(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.SetDataAdapter(System.Object)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Received(ThingsGateway.Foundation.Sockets.SocketClient,ThingsGateway.Foundation.Core.IRequestInfo)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter.PackCommand(System.Byte[])">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
<param name="command"></param>
<returns></returns>
@@ -427,14 +427,14 @@
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter.GetInstance">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage,System.Byte[],System.Byte[],System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage.CurModbusAddress">
@@ -448,16 +448,16 @@
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage.HeadBytesLength">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage.CheckHeadBytes(System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.#ctor(ThingsGateway.Foundation.Sockets.TcpClient)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.IsCheckMessageId">
<summary>
@@ -470,31 +470,31 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.GetAddressDescription">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.SetDataAdapter(System.Object)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter">
<summary>
@@ -507,21 +507,21 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.PackCommand(System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.GetInstance">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage,System.Byte[],System.Byte[],System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage.HeadBytesLength">
<inheritdoc />
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage.IsCheckMessageId">
<summary>
@@ -529,13 +529,13 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage.CheckHeadBytes(System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.#ctor(ThingsGateway.Foundation.Sockets.UdpSession)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.IsCheckMessageId">
<summary>
@@ -548,35 +548,35 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.GetAddressDescription">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.SetDataAdapter(System.Object)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter">
<summary>
<inheritdoc />
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.IsCheckMessageId">
@@ -585,13 +585,13 @@
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.PackCommand(System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.GetInstance">
<inheritdoc />
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.UnpackResponse(System.Byte[],System.Byte[])">
<inheritdoc />
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.PackHelper">
<summary>
@@ -608,4 +608,4 @@
<returns></returns>
</member>
</members>
</doc>
</doc>

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Runtime.InteropServices;
@@ -35,7 +33,6 @@ internal class ComInterop
private const uint EOAC_NONE = 0x00;
private const uint EOAC_SECURE_REFS = 0x02;
private const uint EOAC_STATIC_CLOAKING = 0x20;
/// <summary>
/// The WIN32 system default locale.
/// </summary>
@@ -74,7 +71,6 @@ internal class ComInterop
private const uint RPC_C_IMP_LEVEL_DELEGATE = 4;
private const uint RPC_C_IMP_LEVEL_IDENTIFY = 2;
private const uint RPC_C_IMP_LEVEL_IMPERSONATE = 3;
#endregion const
#region struct
@@ -151,7 +147,6 @@ internal class ComInterop
[DllImport("Kernel32.dll")]
private static extern int GetUserDefaultLangID();
#endregion win32 api
/// <summary>
@@ -261,7 +256,6 @@ internal class ComInterop
throw new ExternalException("COM初始化安全: " + GetSystemMessage(error), error);
}
}
/// <summary>
/// 从枚举器读取guid。
/// </summary>

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.OPCDA.Comn;
@@ -56,7 +54,6 @@ internal static class Convert
throw new NotSupportedException("Object cannot be cloned.");
}
}
internal static DateTime FileTimeToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME filetime)
{
long num = filetime.dwHighDateTime;
@@ -83,4 +80,4 @@ internal static class Convert
DateTime fILETIME_BaseTime2 = FILETIME_BaseTime;
return fILETIME_BaseTime2.Add(new TimeSpan(num2)).ToLocalTime();
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
@@ -19,19 +17,16 @@ namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
/// </summary>
/// <param name="opcItems"></param>
public delegate void OnDataChangedHandler(List<ItemReadResult> opcItems);
/// <summary>
/// 读取
/// </summary>
/// <param name="opcItems"></param>
public delegate void OnReadCompletedHandler(List<ItemReadResult> opcItems);
/// <summary>
/// 写入
/// </summary>
/// <param name="opcItems"></param>
internal delegate void OnWriteCompletedHandler(List<ItemWriteResult> opcItems);
/// <summary>
/// 返回结果
/// </summary>
@@ -41,17 +36,14 @@ public class ItemReadResult
/// ID
/// </summary>
public string Name { get; set; } = "";
/// <summary>
/// Quality
/// </summary>
public short Quality { get; set; }
/// <summary>
/// TimeStamp
/// </summary>
public DateTime TimeStamp { get; set; }
/// <summary>
/// Value
/// </summary>
@@ -62,4 +54,4 @@ internal class ItemWriteResult
{
internal int Exception { get; set; } = 0;
internal string Name { get; set; } = "";
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Runtime.InteropServices;
@@ -37,7 +35,6 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
private IOPCSyncIO m_SyncIO = null;
private GCHandle percendDeadBand = GCHandle.Alloc(0, GCHandleType.Pinned);
private GCHandle timeBias = GCHandle.Alloc(0, GCHandleType.Pinned);
internal OpcGroup(string name)
{
Name = name;
@@ -81,7 +78,6 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
internal object GroupPointer => groupPointer;
internal bool IsActive { get; set; } = true;
internal int LCID
{
get => lcid;
@@ -90,7 +86,6 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
internal string Name { get; private set; } = string.Empty;
internal List<OpcItem> OpcItems { get; private set; } = new List<OpcItem> { };
internal GCHandle PercendDeadBand
{
get => percendDeadBand;
@@ -100,13 +95,11 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
internal int RequestUpdateRate { get; set; } = 1000;
internal int RevisedUpdateRate => revisedUpdateRate;
internal int ServerGroupHandle => serverGroupHandle;
internal GCHandle TimeBias
{
get => timeBias;
set => timeBias = value;
}
public void Dispose()
{
Dispose(disposing: true);
@@ -271,7 +264,6 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
}
}
}
/// <summary>
/// 建立连接
/// </summary>
@@ -289,7 +281,6 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
//创建客户端与服务端之间的连接
m_ConnectionPoint.Advise(this, out m_connectionpoint_cookie);
}
/// <summary>
/// 组读取
/// </summary>
@@ -362,6 +353,7 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
return results;
}
internal List<Tuple<int, int>> Write(object[] values, int[] serverHandle)
{
IntPtr pErrors = IntPtr.Zero;
@@ -393,7 +385,6 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
else
throw new("连接无效");
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
@@ -463,4 +454,4 @@ internal class OpcGroup : IOPCDataCallback, IDisposable
hActive.Free();
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,20 +8,17 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
/// <summary>
/// OpcItem
/// </summary>
public class OpcItem
{
private static int _hanle = 0;
/// <summary>
/// OpcItem
/// </summary>
@@ -32,22 +28,18 @@ public class OpcItem
ItemID = itemId;
ClientHandle = ++_hanle;
}
/// <summary>
/// AccessPath
/// </summary>
public string AccessPath { get; private set; } = "";
/// <summary>
/// Blob
/// </summary>
public IntPtr Blob { get; set; } = IntPtr.Zero;
/// <summary>
/// BlobSize
/// </summary>
public int BlobSize { get; set; } = 0;
/// <summary>
/// ClientHandle
/// </summary>
@@ -62,29 +54,24 @@ public class OpcItem
/// 数据项在opc server的完全名称
/// </summary>
public string ItemID { get; private set; } = String.Empty;
/// <summary>
/// Quality
/// </summary>
public int Quality { get; set; } = Qualities.OPC_QUALITY_BAD;
/// <summary>
/// RunTimeDataType
/// </summary>
public short RunTimeDataType { get; set; } = 0;
/// <summary>
/// ServerHandle
/// </summary>
public int ServerHandle { get; set; }
/// <summary>
/// TimeStamp
/// </summary>
public DateTime TimeStamp { get; set; } = new DateTime(0);
/// <summary>
/// Value
/// </summary>
public object Value { get; set; }
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Runtime.InteropServices;
@@ -21,6 +19,7 @@ namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
internal class OpcServer : IDisposable
{
private bool disposedValue;
private IOPCServer m_OpcServer = null;
@@ -83,6 +82,7 @@ internal class OpcServer : IDisposable
throw new("添加OPC组错误OPC服务器返回null");
}
return group;
}
/// <summary>
@@ -110,6 +110,7 @@ internal class OpcServer : IDisposable
new PropertyID(101),
};
var server = m_OpcServer as IOPCBrowse;
server.Browse(
string.IsNullOrEmpty(itemId) ? "" : itemId,
@@ -166,6 +167,7 @@ internal class OpcServer : IDisposable
OPCSERVERSTATUS status;
if (statusPtr != IntPtr.Zero)
{
object o = Marshal.PtrToStructure(statusPtr, typeof(OPCSERVERSTATUS));
Marshal.FreeCoTaskMem(statusPtr);
@@ -188,7 +190,9 @@ internal class OpcServer : IDisposable
{
IsConnected = false;
throw new("未知错误");
}
}
else
{
@@ -204,6 +208,8 @@ internal class OpcServer : IDisposable
IsConnected = false;
ServerStatus = serverStatus;
}
}
internal void RemoveGroup(OpcGroup group)
@@ -226,6 +232,7 @@ internal class OpcServer : IDisposable
}
catch
{
}
if (m_OpcServer != null)
{
@@ -265,4 +272,4 @@ internal class OpcServer : IDisposable
}
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,13 +8,11 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
/// <summary>
/// ServerStatus
/// </summary>
@@ -25,29 +22,24 @@ public class ServerStatus
/// CurrentTime
/// </summary>
public DateTime CurrentTime { get; internal set; } = new DateTime(0);
/// <summary>
/// LastUpdateTime
/// </summary>
public DateTime LastUpdateTime { get; internal set; } = new DateTime(0);
/// <summary>
/// ServerState
/// </summary>
public OPCSERVERSTATE ServerState { get; internal set; } = OPCSERVERSTATE.OPC_STATUS_NOCONFIG;
/// <summary>
/// StartTime
/// </summary>
public DateTime StartTime { get; internal set; } = new DateTime(0);
/// <summary>
/// VendorInfo
/// </summary>
public string VendorInfo { get; internal set; } = "UNKOWN";
/// <summary>
/// Version
/// </summary>
public string Version { get; internal set; } = "UNKOWN";
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections;
@@ -18,11 +16,10 @@ using System.Text;
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
namespace ThingsGateway.Foundation.Adapter.OPCDA.Discovery;
/// <summary>
/// OpcDiscovery
/// </summary>
internal class OpcDiscovery
public class OpcDiscovery
{
private static readonly Guid CATID_OPC_DA10 = new("63D5F430-CFE4-11d1-B2C8-0060083BA1FB");
@@ -31,7 +28,6 @@ internal class OpcDiscovery
private static readonly Guid CATID_OPC_DA30 = new("CC603642-66D7-48f1-B69A-B625E73652D7");
private static readonly Guid OPCEnumCLSID = new("13486D51-4821-11D2-A494-3CB306C10000");
/// <summary>
/// GetOpcServer
/// </summary>
@@ -40,6 +36,7 @@ internal class OpcDiscovery
/// <returns></returns>
internal static ServerInfo GetOpcServer(string serverName, string host)
{
if (string.IsNullOrEmpty(serverName))
{
throw new("检索失败需提供OPCName");
@@ -88,6 +85,7 @@ internal class OpcDiscovery
Comn.ComInterop.RealseComServer(o_Server);
o_Server = null;
}
}
private static void GetIOPCServerList(ref ServerInfo result, ref ServerInfo[] serverInfos, string serverName, string host, IOPCServerList m_server, Guid catid)
@@ -116,6 +114,7 @@ internal class OpcDiscovery
break;
}
}
}
private static void GetIOPCServerList(ref ServerInfo result, ref ServerInfo[] serverInfos, string serverName, string host, IOPCServerList2 m_server, Guid catid)
@@ -144,8 +143,10 @@ internal class OpcDiscovery
break;
}
}
}
private static ServerInfo[] GetServerDetails(Guid[] clsids, string host, IOPCServerList m_server)
{
ArrayList servers = new ArrayList();
@@ -229,8 +230,11 @@ internal class OpcDiscovery
}
return (ServerInfo[])servers.ToArray(typeof(ServerInfo));
}
}
internal class ServerInfo
{
internal Guid CLSID { get; set; }
@@ -249,4 +253,4 @@ internal class ServerInfo
stringBuilder.AppendLine($"{nameof(VerIndProgID)}:{VerIndProgID}");
return stringBuilder.ToString();
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
@@ -84,7 +82,6 @@ public class BrowseElement : ICloneable
m_name = value;
}
}
public ItemProperty[] Properties
{
get

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.
@@ -19,7 +17,6 @@ Runtime.InteropServices;
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
/// <exclude />
[ComImport]
[GuidAttribute("B196B286-BAB4-101A-B69C-00AA00341D07")]
@@ -330,8 +327,7 @@ public interface IOPCShutdown
public struct CONNECTDATA
{
[MarshalAs(UnmanagedType.IUnknown)]
private object pUnk;
object pUnk;
[MarshalAs(UnmanagedType.I4)]
private int dwCookie;
}
int dwCookie;
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,13 +8,13 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.
Runtime.InteropServices;
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
@@ -92,30 +91,25 @@ public enum OPCSERVERSTATE
[ComImport]
[GuidAttribute("63D5F430-CFE4-11d1-B2C8-0060083BA1FB")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface CATID_OPCDAServer10
{ }
public interface CATID_OPCDAServer10 { }
/// <exclude />
[ComImport]
[GuidAttribute("63D5F432-CFE4-11d1-B2C8-0060083BA1FB")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface CATID_OPCDAServer20
{ }
public interface CATID_OPCDAServer20 { }
/// <exclude />
[ComImport]
[GuidAttribute("CC603642-66D7-48f1-B69A-B625E73652D7")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface CATID_OPCDAServer30
{ }
public interface CATID_OPCDAServer30 { }
/// <exclude />
[ComImport]
[GuidAttribute("3098EDA4-A006-48b2-A27F-247453959408")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface CATID_XMLDAServer10
{ }
public interface CATID_XMLDAServer10 { }
/// <exclude />
[ComImport]
[GuidAttribute("39c13a55-011e-11d0-9675-0020afd8adb3")]
@@ -1008,16 +1002,12 @@ public struct OPCBROWSEELEMENT
{
[MarshalAs(UnmanagedType.LPWStr)]
public string szName;
[MarshalAs(UnmanagedType.LPWStr)]
public string szItemID;
[MarshalAs(UnmanagedType.I4)]
public int dwFlagValue;
[MarshalAs(UnmanagedType.I4)]
public int dwReserved;
public OPCITEMPROPERTIES ItemProperties;
}
@@ -1027,16 +1017,12 @@ public struct OPCGROUPHEADER
{
[MarshalAs(UnmanagedType.I4)]
public int dwSize;
[MarshalAs(UnmanagedType.I4)]
public int dwItemCount;
[MarshalAs(UnmanagedType.I4)]
public int hClientGroup;
[MarshalAs(UnmanagedType.I4)]
public int dwTransactionID;
[MarshalAs(UnmanagedType.I4)]
public int hrStatus;
}
@@ -1047,13 +1033,10 @@ public struct OPCGROUPHEADERWRITE
{
[MarshalAs(UnmanagedType.I4)]
public int dwItemCount;
[MarshalAs(UnmanagedType.I4)]
public int hClientGroup;
[MarshalAs(UnmanagedType.I4)]
public int dwTransactionID;
[MarshalAs(UnmanagedType.I4)]
public int hrStatus;
}
@@ -1064,35 +1047,24 @@ public struct OPCITEMATTRIBUTES
{
[MarshalAs(UnmanagedType.LPWStr)]
public string szAccessPath;
[MarshalAs(UnmanagedType.LPWStr)]
public string szItemID;
[MarshalAs(UnmanagedType.I4)]
public int bActive;
[MarshalAs(UnmanagedType.I4)]
public int hClient;
[MarshalAs(UnmanagedType.I4)]
public int hServer;
[MarshalAs(UnmanagedType.I4)]
public int dwAccessRights;
[MarshalAs(UnmanagedType.I4)]
public int dwBlobSize;
public IntPtr pBlob;
[MarshalAs(UnmanagedType.I2)]
public short vtRequestedDataType;
[MarshalAs(UnmanagedType.I2)]
public short vtCanonicalDataType;
public OPCEUTYPE dwEUType;
[MarshalAs(UnmanagedType.Struct)]
public object vEUInfo;
}
@@ -1103,24 +1075,17 @@ public struct OPCITEMDEF
{
[MarshalAs(UnmanagedType.LPWStr)]
public string szAccessPath;
[MarshalAs(UnmanagedType.LPWStr)]
public string szItemID;
[MarshalAs(UnmanagedType.I4)]
public int bActive;
[MarshalAs(UnmanagedType.I4)]
public int hClient;
[MarshalAs(UnmanagedType.I4)]
public int dwBlobSize;
public IntPtr pBlob;
[MarshalAs(UnmanagedType.I2)]
public short vtRequestedDataType;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
};
@@ -1131,16 +1096,12 @@ public struct OPCITEMHEADER1
{
[MarshalAs(UnmanagedType.I4)]
public int hClient;
[MarshalAs(UnmanagedType.I4)]
public int dwValueOffset;
[MarshalAs(UnmanagedType.I2)]
public short wQuality;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
public System.Runtime.InteropServices.ComTypes.FILETIME ftTimeStampItem;
}
@@ -1150,24 +1111,19 @@ public struct OPCITEMHEADER2
{
[MarshalAs(UnmanagedType.I4)]
public int hClient;
[MarshalAs(UnmanagedType.I4)]
public int dwValueOffset;
[MarshalAs(UnmanagedType.I2)]
public short wQuality;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
}
/// <exclude />
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OPCITEMHEADERWRITE
{
[MarshalAs(UnmanagedType.I4)]
public int hClient;
[MarshalAs(UnmanagedType.I4)]
public int dwError;
}
@@ -1178,12 +1134,9 @@ public struct OPCITEMPROPERTIES
{
[MarshalAs(UnmanagedType.I4)]
public int hrErrorID;
[MarshalAs(UnmanagedType.I4)]
public int dwNumProperties;
public IntPtr pItemProperties;
[MarshalAs(UnmanagedType.I4)]
public int dwReserved;
}
@@ -1194,25 +1147,18 @@ public struct OPCITEMPROPERTY
{
[MarshalAs(UnmanagedType.I2)]
public short vtDataType;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
[MarshalAs(UnmanagedType.I4)]
public int dwPropertyID;
[MarshalAs(UnmanagedType.LPWStr)]
public string szItemID;
[MarshalAs(UnmanagedType.LPWStr)]
public string szDescription;
[MarshalAs(UnmanagedType.Struct)]
public object vValue;
[MarshalAs(UnmanagedType.I4)]
public int hrErrorID;
[MarshalAs(UnmanagedType.I4)]
public int dwReserved;
}
@@ -1223,19 +1169,14 @@ public struct OPCITEMRESULT
{
[MarshalAs(UnmanagedType.I4)]
public int hServer;
[MarshalAs(UnmanagedType.I2)]
public short vtCanonicalDataType;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
[MarshalAs(UnmanagedType.I4)]
public int dwAccessRights;
[MarshalAs(UnmanagedType.I4)]
public int dwBlobSize;
public IntPtr pBlob;
}
@@ -1245,15 +1186,11 @@ public struct OPCITEMSTATE
{
[MarshalAs(UnmanagedType.I4)]
public int hClient;
public System.Runtime.InteropServices.ComTypes.FILETIME ftTimeStamp;
[MarshalAs(UnmanagedType.I2)]
public short wQuality;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
[MarshalAs(UnmanagedType.Struct)]
public object vDataValue;
}
@@ -1264,22 +1201,16 @@ public struct OPCITEMVQT
{
[MarshalAs(UnmanagedType.Struct)]
public object vDataValue;
[MarshalAs(UnmanagedType.I4)]
public int bQualitySpecified;
[MarshalAs(UnmanagedType.I2)]
public short wQuality;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
[MarshalAs(UnmanagedType.I4)]
public int bTimeStampSpecified;
[MarshalAs(UnmanagedType.I4)]
public int dwReserved;
public System.Runtime.InteropServices.ComTypes.FILETIME ftTimeStamp;
}
@@ -1291,29 +1222,21 @@ public struct OPCSERVERSTATUS
public System.Runtime.InteropServices.ComTypes.FILETIME ftCurrentTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastUpdateTime;
public OPCSERVERSTATE dwServerState;
[MarshalAs(UnmanagedType.I4)]
public int dwGroupCount;
[MarshalAs(UnmanagedType.I4)]
public int dwBandWidth;
[MarshalAs(UnmanagedType.I2)]
public short wMajorVersion;
[MarshalAs(UnmanagedType.I2)]
public short wMinorVersion;
[MarshalAs(UnmanagedType.I2)]
public short wBuildNumber;
[MarshalAs(UnmanagedType.I2)]
public short wReserved;
[MarshalAs(UnmanagedType.LPWStr)]
public string szVendorInfo;
}
/// <exclude />
public static class Constants
{
@@ -1324,7 +1247,6 @@ public static class Constants
// category description strings.
public const string OPC_CATEGORY_DESCRIPTION_DA10 = "OPC Data Access Servers Version 1.0";
public const string OPC_CATEGORY_DESCRIPTION_DA20 = "OPC Data Access Servers Version 2.0";
public const string OPC_CATEGORY_DESCRIPTION_DA30 = "OPC Data Access Servers Version 3.0";
public const string OPC_CATEGORY_DESCRIPTION_XMLDA10 = "OPC XML Data Access Servers Version 1.0";
@@ -1336,13 +1258,11 @@ public static class Constants
// values for access rights mask.
public const int OPC_READABLE = 0x01;
// well known complex type description systems.
// well known complex type description systems.
public const string OPC_TYPE_SYSTEM_OPCBINARY = "OPCBinary";
public const string OPC_TYPE_SYSTEM_XMLSCHEMA = "XMLSchema";
public const string OPC_WRITE_BEHAVIOR_ALL_OR_NOTHING = "All or Nothing";
// complex data write behavior values.
public const string OPC_WRITE_BEHAVIOR_BEST_EFFORT = "Best Effort";
@@ -1360,7 +1280,7 @@ public static class Qualities
public const short OPC_LIMIT_MASK = 0x03;
// Values for Limit Bitfield
// Values for Limit Bitfield
public const short OPC_LIMIT_OK = 0x00;
// Values for QUALITY_MASK bit field
@@ -1387,7 +1307,6 @@ public static class Qualities
// Values for fields in the quality word
public const short OPC_QUALITY_MASK = 0xC0;
public const short OPC_QUALITY_NOT_CONNECTED = 0x08;
public const short OPC_QUALITY_OUT_OF_SERVICE = 0x1C;
public const short OPC_QUALITY_SENSOR_CAL = 0x50;
@@ -1421,7 +1340,6 @@ public static class Properties
// property ids.
public const int OPC_PROPERTY_DATATYPE = 1;
public const int OPC_PROPERTY_DEADBAND = 306;
public const string OPC_PROPERTY_DESC_ACCESS_RIGHTS = "Item Access Rights";
public const string OPC_PROPERTY_DESC_ALARM_AREA_LIST = "Alarm Area List";
@@ -1432,7 +1350,6 @@ public static class Properties
public const string OPC_PROPERTY_DESC_CONDITION_STATUS = "Condition Status";
public const string OPC_PROPERTY_DESC_CONSISTENCY_WINDOW = "Consistency Window";
public const string OPC_PROPERTY_DESC_DATA_FILTER_VALUE = "Data Filter Value";
// property descriptions.
public const string OPC_PROPERTY_DESC_DATATYPE = "Item Canonical Data Type";
@@ -1462,7 +1379,6 @@ public static class Properties
public const string OPC_PROPERTY_DESC_TIMEZONE = "Item Timezone";
public const string OPC_PROPERTY_DESC_TYPE_DESCRIPTION = "Type Description";
public const string OPC_PROPERTY_DESC_TYPE_ID = "Type ID";
// complex data properties.
public const string OPC_PROPERTY_DESC_TYPE_SYSTEM_ID = "Type System ID";
@@ -1495,7 +1411,6 @@ public static class Properties
public const int OPC_PROPERTY_TIMEZONE = 108;
public const int OPC_PROPERTY_TYPE_DESCRIPTION = 604;
public const int OPC_PROPERTY_TYPE_ID = 602;
// complex data properties.
public const int OPC_PROPERTY_TYPE_SYSTEM_ID = 600;
@@ -1503,4 +1418,4 @@ public static class Properties
public const int OPC_PROPERTY_UNFILTERED_ITEM_ID = 608;
public const int OPC_PROPERTY_VALUE = 2;
public const int OPC_PROPERTY_WRITE_BEHAVIOR = 606;
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections;
@@ -111,7 +109,6 @@ public class Interop
}
return browseElements;
}
internal static ItemProperty[] GetItemProperties(
ref OPCITEMPROPERTIES input,
bool deallocate)
@@ -191,7 +188,6 @@ public class Interop
}
return itemProperty;
}
internal static OPCITEMPROPERTY GetItemProperty(ItemProperty input)
{
OPCITEMPROPERTY itemProperty = new OPCITEMPROPERTY();
@@ -229,302 +225,204 @@ public class Interop
{
case -2147467262:
return new ResultID(ResultID.E_NOTSUPPORTED, (long)input);
case -2147467259:
return new ResultID(ResultID.E_FAIL, (long)input);
case -2147352571:
return new ResultID(ResultID.Da.E_BADTYPE, (long)input);
case -2147352566:
return new ResultID(ResultID.Da.E_RANGE, (long)input);
case -2147217401:
return new ResultID(ResultID.Hda.W_NOFILTER, (long)input);
case -2147024882:
return new ResultID(ResultID.E_OUTOFMEMORY, (long)input);
case -2147024809:
return new ResultID(ResultID.E_INVALIDARG, (long)input);
case -1073479679:
return new ResultID(ResultID.Da.E_INVALIDHANDLE, (long)input);
case -1073479676:
return new ResultID(ResultID.Da.E_BADTYPE, (long)input);
case -1073479673:
return new ResultID(ResultID.Da.E_UNKNOWN_ITEM_NAME, (long)input);
case -1073479672:
return new ResultID(ResultID.Da.E_INVALID_ITEM_NAME, (long)input);
case -1073479671:
return new ResultID(ResultID.Da.E_INVALID_FILTER, (long)input);
case -1073479670:
return new ResultID(ResultID.Da.E_UNKNOWN_ITEM_PATH, (long)input);
case -1073479669:
return new ResultID(ResultID.Da.E_RANGE, (long)input);
case -1073479165:
return new ResultID(ResultID.Da.E_INVALID_PID, (long)input);
case -1073479164:
return new ResultID(ResultID.Ae.E_INVALIDTIME, (long)input);
case -1073479163:
return new ResultID(ResultID.Ae.E_BUSY, (long)input);
case -1073479162:
return new ResultID(ResultID.Ae.E_NOINFO, (long)input);
case -1073478655:
return new ResultID(ResultID.Da.E_NO_ITEM_DEADBAND, (long)input);
case -1073478654:
return new ResultID(ResultID.Da.E_NO_ITEM_BUFFERING, (long)input);
case -1073478653:
return new ResultID(ResultID.Da.E_INVALIDCONTINUATIONPOINT, (long)input);
case -1073478650:
return new ResultID(ResultID.Da.E_NO_WRITEQT, (long)input);
case -1073478649:
return new ResultID(ResultID.Cpx.E_TYPE_CHANGED, (long)input);
case -1073478648:
return new ResultID(ResultID.Cpx.E_FILTER_DUPLICATE, (long)input);
case -1073478647:
return new ResultID(ResultID.Cpx.E_FILTER_INVALID, (long)input);
case -1073478646:
return new ResultID(ResultID.Cpx.E_FILTER_ERROR, (long)input);
case -1073477888:
return new ResultID(ResultID.Dx.E_PERSISTING, (long)input);
case -1073477887:
return new ResultID(ResultID.Dx.E_NOITEMLIST, (long)input);
case -1073477886:
return new ResultID(ResultID.Dx.E_VERSION_MISMATCH, (long)input);
case -1073477885:
return new ResultID(ResultID.Dx.E_VERSION_MISMATCH, (long)input);
case -1073477884:
return new ResultID(ResultID.Dx.E_UNKNOWN_ITEM_PATH, (long)input);
case -1073477883:
return new ResultID(ResultID.Dx.E_UNKNOWN_ITEM_NAME, (long)input);
case -1073477882:
return new ResultID(ResultID.Dx.E_INVALID_ITEM_PATH, (long)input);
case -1073477881:
return new ResultID(ResultID.Dx.E_INVALID_ITEM_NAME, (long)input);
case -1073477880:
return new ResultID(ResultID.Dx.E_INVALID_NAME, (long)input);
case -1073477879:
return new ResultID(ResultID.Dx.E_DUPLICATE_NAME, (long)input);
case -1073477878:
return new ResultID(ResultID.Dx.E_INVALID_BROWSE_PATH, (long)input);
case -1073477877:
return new ResultID(ResultID.Dx.E_INVALID_SERVER_URL, (long)input);
case -1073477876:
return new ResultID(ResultID.Dx.E_INVALID_SERVER_TYPE, (long)input);
case -1073477875:
return new ResultID(ResultID.Dx.E_UNSUPPORTED_SERVER_TYPE, (long)input);
case -1073477874:
return new ResultID(ResultID.Dx.E_CONNECTIONS_EXIST, (long)input);
case -1073477873:
return new ResultID(ResultID.Dx.E_TOO_MANY_CONNECTIONS, (long)input);
case -1073477872:
return new ResultID(ResultID.Dx.E_OVERRIDE_BADTYPE, (long)input);
case -1073477871:
return new ResultID(ResultID.Dx.E_OVERRIDE_RANGE, (long)input);
case -1073477870:
return new ResultID(ResultID.Dx.E_SUBSTITUTE_BADTYPE, (long)input);
case -1073477869:
return new ResultID(ResultID.Dx.E_SUBSTITUTE_RANGE, (long)input);
case -1073477868:
return new ResultID(ResultID.Dx.E_INVALID_TARGET_ITEM, (long)input);
case -1073477867:
return new ResultID(ResultID.Dx.E_UNKNOWN_TARGET_ITEM, (long)input);
case -1073477866:
return new ResultID(ResultID.Dx.E_TARGET_ALREADY_CONNECTED, (long)input);
case -1073477865:
return new ResultID(ResultID.Dx.E_UNKNOWN_SERVER_NAME, (long)input);
case -1073477864:
return new ResultID(ResultID.Dx.E_UNKNOWN_SOURCE_ITEM, (long)input);
case -1073477863:
return new ResultID(ResultID.Dx.E_INVALID_SOURCE_ITEM, (long)input);
case -1073477862:
return new ResultID(ResultID.Dx.E_INVALID_QUEUE_SIZE, (long)input);
case -1073477861:
return new ResultID(ResultID.Dx.E_INVALID_DEADBAND, (long)input);
case -1073477860:
return new ResultID(ResultID.Dx.E_INVALID_CONFIG_FILE, (long)input);
case -1073477859:
return new ResultID(ResultID.Dx.E_PERSIST_FAILED, (long)input);
case -1073477858:
return new ResultID(ResultID.Dx.E_TARGET_FAULT, (long)input);
case -1073477857:
return new ResultID(ResultID.Dx.E_TARGET_NO_ACCESSS, (long)input);
case -1073477856:
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_FAULT, (long)input);
case -1073477855:
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_NO_ACCESSS, (long)input);
case -1073477854:
return new ResultID(ResultID.Dx.E_SUBSCRIPTION_FAULT, (long)input);
case -1073477853:
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_BADRIGHTS, (long)input);
case -1073477852:
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_BAD_QUALITY, (long)input);
case -1073477851:
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_BADTYPE, (long)input);
case -1073477850:
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_RANGE, (long)input);
case -1073477849:
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_NOT_CONNECTED, (long)input);
case -1073477848:
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_TIMEOUT, (long)input);
case -1073477847:
return new ResultID(ResultID.Dx.E_TARGET_ITEM_DISCONNECTED, (long)input);
case -1073477846:
return new ResultID(ResultID.Dx.E_TARGET_NO_WRITES_ATTEMPTED, (long)input);
case -1073477845:
return new ResultID(ResultID.Dx.E_TARGET_ITEM_BADTYPE, (long)input);
case -1073477844:
return new ResultID(ResultID.Dx.E_TARGET_ITEM_RANGE, (long)input);
case -1073475583:
return new ResultID(ResultID.Hda.E_MAXEXCEEDED, (long)input);
case -1073475580:
return new ResultID(ResultID.Hda.E_INVALIDAGGREGATE, (long)input);
case -1073475576:
return new ResultID(ResultID.Hda.E_UNKNOWNATTRID, (long)input);
case -1073475575:
return new ResultID(ResultID.Hda.E_NOT_AVAIL, (long)input);
case -1073475574:
return new ResultID(ResultID.Hda.E_INVALIDDATATYPE, (long)input);
case -1073475573:
return new ResultID(ResultID.Hda.E_DATAEXISTS, (long)input);
case -1073475572:
return new ResultID(ResultID.Hda.E_INVALIDATTRID, (long)input);
case -1073475571:
return new ResultID(ResultID.Hda.E_NODATAEXISTS, (long)input);
case 0:
return new ResultID(ResultID.S_OK, (long)input);
case 262157:
return new ResultID(ResultID.Da.S_UNSUPPORTEDRATE, (long)input);
case 262158:
return new ResultID(ResultID.Da.S_CLAMP, (long)input);
case 262656:
return new ResultID(ResultID.Ae.S_ALREADYACKED, (long)input);
case 262657:
return new ResultID(ResultID.Ae.S_INVALIDBUFFERTIME, (long)input);
case 262658:
return new ResultID(ResultID.Ae.S_INVALIDMAXSIZE, (long)input);
case 262659:
return new ResultID(ResultID.Ae.S_INVALIDKEEPALIVETIME, (long)input);
case 263172:
return new ResultID(ResultID.Da.S_DATAQUEUEOVERFLOW, (long)input);
case 263179:
return new ResultID(ResultID.Cpx.S_FILTER_NO_DATA, (long)input);
case 264064:
return new ResultID(ResultID.Dx.S_TARGET_SUBSTITUTED, (long)input);
case 264065:
return new ResultID(ResultID.Dx.S_TARGET_OVERRIDEN, (long)input);
case 264066:
return new ResultID(ResultID.Dx.S_CLAMP, (long)input);
case 1074008066:
return new ResultID(ResultID.Hda.S_NODATA, (long)input);
case 1074008067:
return new ResultID(ResultID.Hda.S_MOREDATA, (long)input);
case 1074008069:
return new ResultID(ResultID.Hda.S_CURRENTVALUE, (long)input);
case 1074008070:
return new ResultID(ResultID.Hda.S_EXTRADATA, (long)input);
case 1074008078:
return new ResultID(ResultID.Hda.S_INSERTED, (long)input);
case 1074008079:
return new ResultID(ResultID.Hda.S_REPLACED, (long)input);
default:
if ((input & 2147418112) == 65536)
return new ResultID(ResultID.E_NETWORK_ERROR, (long)input);
return input >= 0 ? new ResultID(ResultID.S_FALSE, (long)input) : new ResultID(ResultID.E_FAIL, (long)input);
}
}
internal static int GetResultID(ResultID input)
{
if (input.Name != (XmlQualifiedName)null && input.Name.Namespace == "http://opcfoundation.org/DataAccess/")
@@ -788,106 +686,74 @@ public class Interop
return VarEnum.VT_I2;
return input == typeof(accessRights) || input == typeof(euType) ? VarEnum.VT_I4 : VarEnum.VT_EMPTY;
}
internal static System.Type GetType(VarEnum input)
{
switch (input)
{
case VarEnum.VT_EMPTY:
return (System.Type)null;
case VarEnum.VT_I2:
return typeof(short);
case VarEnum.VT_I4:
return typeof(int);
case VarEnum.VT_R4:
return typeof(float);
case VarEnum.VT_R8:
return typeof(double);
case VarEnum.VT_CY:
return typeof(Decimal);
case VarEnum.VT_DATE:
return typeof(DateTime);
case VarEnum.VT_BSTR:
return typeof(string);
case VarEnum.VT_BOOL:
return typeof(bool);
case VarEnum.VT_I1:
return typeof(sbyte);
case VarEnum.VT_UI1:
return typeof(byte);
case VarEnum.VT_UI2:
return typeof(ushort);
case VarEnum.VT_UI4:
return typeof(uint);
case VarEnum.VT_I8:
return typeof(long);
case VarEnum.VT_UI8:
return typeof(ulong);
case VarEnum.VT_I2 | VarEnum.VT_ARRAY:
return typeof(short[]);
case VarEnum.VT_I4 | VarEnum.VT_ARRAY:
return typeof(int[]);
case VarEnum.VT_R4 | VarEnum.VT_ARRAY:
return typeof(float[]);
case VarEnum.VT_R8 | VarEnum.VT_ARRAY:
return typeof(double[]);
case VarEnum.VT_CY | VarEnum.VT_ARRAY:
return typeof(Decimal[]);
case VarEnum.VT_DATE | VarEnum.VT_ARRAY:
return typeof(DateTime[]);
case VarEnum.VT_BSTR | VarEnum.VT_ARRAY:
return typeof(string[]);
case VarEnum.VT_BOOL | VarEnum.VT_ARRAY:
return typeof(bool[]);
case VarEnum.VT_VARIANT | VarEnum.VT_ARRAY:
return typeof(object[]);
case VarEnum.VT_I1 | VarEnum.VT_ARRAY:
return typeof(sbyte[]);
case VarEnum.VT_UI1 | VarEnum.VT_ARRAY:
return typeof(byte[]);
case VarEnum.VT_UI2 | VarEnum.VT_ARRAY:
return typeof(ushort[]);
case VarEnum.VT_UI4 | VarEnum.VT_ARRAY:
return typeof(uint[]);
case VarEnum.VT_I8 | VarEnum.VT_ARRAY:
return typeof(long[]);
case VarEnum.VT_UI8 | VarEnum.VT_ARRAY:
return typeof(ulong[]);
default:
return Type.ILLEGAL_TYPE;
}
}
internal static object MarshalPropertyValue(PropertyID propertyID, object input)
{
if (input == null)
@@ -902,13 +768,10 @@ public class Interop
{
case accessRights.readable:
return (object)1;
case accessRights.writable:
return (object)2;
case accessRights.readWritable:
return (object)3;
default:
return (object)null;
}
@@ -919,13 +782,10 @@ public class Interop
{
case euType.noEnum:
return (object)OPCEUTYPE.OPC_NOENUM;
case euType.analog:
return (object)OPCEUTYPE.OPC_ANALOG;
case euType.enumerated:
return (object)OPCEUTYPE.OPC_ENUMERATED;
default:
return (object)null;
}
@@ -964,13 +824,10 @@ public class Interop
{
case 1:
return (object)accessRights.readable;
case 2:
return (object)accessRights.writable;
case 3:
return (object)accessRights.readWritable;
default:
return (object)null;
}
@@ -981,13 +838,10 @@ public class Interop
{
case OPCEUTYPE.OPC_NOENUM:
return (object)euType.noEnum;
case OPCEUTYPE.OPC_ANALOG:
return (object)euType.analog;
case OPCEUTYPE.OPC_ENUMERATED:
return (object)euType.enumerated;
default:
return (object)null;
}
@@ -1011,4 +865,4 @@ public class Interop
}
return input;
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Collections;
@@ -17,6 +15,7 @@ using System.Reflection;
using System.Runtime.Serialization;
using System.Xml;
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
@@ -211,7 +210,6 @@ public struct Quality
private limitBits m_limitBits;
private qualityBits m_qualityBits;
private byte m_vendorBits;
public Quality(qualityBits quality)
{
m_qualityBits = quality;
@@ -249,7 +247,6 @@ public struct Quality
m_qualityBits = value;
}
}
public byte VendorBits
{
get
@@ -323,7 +320,6 @@ public struct Quality
m_limitBits = (limitBits)(code & 3);
m_vendorBits = (byte)((code & -253) >> 8);
}
public override string ToString()
{
string text = QualityBits.ToString();
@@ -630,7 +626,6 @@ public struct ResultID : ISerializable
internal const string NAMESPACE = "NS";
}
}
[Serializable]
public class ItemProperty : ICloneable, IResult
{
@@ -642,7 +637,6 @@ public class ItemProperty : ICloneable, IResult
private string m_itemPath;
private ResultID m_resultID = ResultID.S_OK;
private object m_value;
public System.Type DataType
{
get
@@ -690,7 +684,6 @@ public class ItemProperty : ICloneable, IResult
m_id = value;
}
}
public string ItemName
{
get
@@ -747,7 +740,6 @@ public class ItemProperty : ICloneable, IResult
return obj;
}
}
public class Property
{
public static readonly PropertyID ACCESSRIGHTS = new PropertyID("accessRights", 5, "http://opcfoundation.org/DataAccess/");
@@ -796,7 +788,6 @@ public class Property
public static readonly PropertyID VALUE_PRECISION = new PropertyID("valuePrecision", 111, "http://opcfoundation.org/DataAccess/");
public static readonly PropertyID WRITE_BEHAVIOR = new PropertyID("writeBehavior", 606, "http://opcfoundation.org/DataAccess/");
}
public class Type
{
public static System.Type ANY_TYPE = typeof(object);
@@ -831,7 +822,6 @@ public class Type
public static System.Type UINT = typeof(uint);
public static System.Type ULONG = typeof(ulong);
public static System.Type USHORT = typeof(ushort);
public static System.Type[] Enumerate()
{
ArrayList arrayList = new ArrayList();
@@ -844,7 +834,6 @@ public class Type
return (System.Type[])arrayList.ToArray(typeof(System.Type));
}
}
[Serializable]
public class PropertyDescription
{
@@ -896,7 +885,6 @@ public class PropertyDescription
private string m_name;
private System.Type m_type;
public PropertyDescription(PropertyID id, System.Type type, string name)
{
ID = id;
@@ -939,7 +927,6 @@ public class PropertyDescription
m_type = value;
}
}
public static PropertyDescription[] Enumerate()
{
ArrayList arrayList = new ArrayList();

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.OPCDA;
@@ -29,7 +27,6 @@ internal static class CollectionExtensions
@this.Remove(obj);
}
}
/// <summary>
/// 将项目列表分解为特定大小的块
/// </summary>
@@ -48,4 +45,5 @@ internal static class CollectionExtensions
}
return n;
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
@@ -121,6 +119,5 @@ internal static class DictionaryExtension
{
return dictionary.TryGetValue(tkey, out var value) ? value : default;
}
#endregion
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,10 +8,10 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading;
global using System.Threading;

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Runtime.InteropServices;
@@ -24,13 +22,11 @@ using Timer = System.Timers.Timer;
//部分非托管交互代码来自https://gitee.com/Zer0Day/opc-client与OPC基金会opcnet库更改部分逻辑
namespace ThingsGateway.Foundation.Adapter.OPCDA;
/// <summary>
/// 订阅变化项
/// </summary>
/// <param name="values"></param>
public delegate void DataChangedEventHandler(List<ItemReadResult> values);
/// <summary>
/// OPCDAClient
/// </summary>
@@ -46,7 +42,6 @@ public class OPCDAClient : IDisposable
private Timer checkTimer;
private int IsExit = 1;
/// <summary>
/// 当前保存的需订阅列表
/// </summary>
@@ -54,7 +49,6 @@ public class OPCDAClient : IDisposable
private OpcServer m_server;
private bool publicConnect;
/// <summary>
/// <inheritdoc/>
/// </summary>
@@ -82,8 +76,7 @@ public class OPCDAClient : IDisposable
/// <summary>
/// 当前配置
/// </summary>
public OPCDANode OPCNode { get; private set; }
public OPCNode OPCNode { get; private set; }
private List<OpcGroup> Groups => m_server.OpcGroups;
/// <summary>
@@ -205,7 +198,7 @@ public class OPCDAClient : IDisposable
/// 初始化设置
/// </summary>
/// <param name="node"></param>
public void Init(OPCDANode node)
public void Init(OPCNode node)
{
if (node != null)
OPCNode = node;
@@ -271,9 +264,10 @@ public class OPCDAClient : IDisposable
ItemDicts[opcGroup.Name].RemoveWhere(a => tag.Contains(a) && !result.Select(b => b.Item1).Contains(a));
}
}
}
}
/// <inheritdoc/>
public override string ToString()
{
@@ -344,11 +338,11 @@ public class OPCDAClient : IDisposable
}
return results;
}
private void CheckTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (checkLock)
{
if (IsExit == 0)
{
try
@@ -377,6 +371,7 @@ public class OPCDAClient : IDisposable
timeer.Enabled = false;
timeer.Stop();
}
}
}
@@ -391,11 +386,11 @@ public class OPCDAClient : IDisposable
_logAction?.Invoke(3, this, $"添加点位失败:{ex.Message}", ex);
}
}
private void PrivateConnect()
{
lock (this)
{
if (m_server?.IsConnected == true)
{
try
@@ -410,12 +405,15 @@ public class OPCDAClient : IDisposable
}
catch
{
Init(OPCNode);
m_server?.Connect();
_logAction?.Invoke(1, this, $"{m_server.Host} - {m_server.Name} - 连接成功", null);
PrivateAddItems();
}
}
}
else
{
@@ -424,6 +422,7 @@ public class OPCDAClient : IDisposable
_logAction?.Invoke(1, this, $"{m_server.Host} - {m_server.Name} - 连接成功", null);
PrivateAddItems();
}
}
}
@@ -450,9 +449,9 @@ public class OPCDAClient : IDisposable
}
}
}
private void Subscription_OnDataChanged(List<ItemReadResult> values)
{
DataChangedHandler?.Invoke(values);
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,60 +8,51 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.OPCDA;
/// <summary>
/// OPCDA连接配置项
/// </summary>
public class OPCDANode
public class OPCNode
{
/// <summary>
/// 是否订阅
/// </summary>
[Description("订阅")]
public bool ActiveSubscribe { get; set; } = true;
/// <summary>
/// 内部检测重连间隔/min
/// </summary>
[Description("重连间隔/min")]
public int CheckRate { get; set; } = 30;
/// <summary>
/// 死区
/// </summary>
[Description("死区")]
public float DeadBand { get; set; } = 0;
/// <summary>
/// 分组大小
/// </summary>
[Description("分组大小")]
public int GroupSize { get; set; } = 500;
/// <summary>
/// OPCIP
/// </summary>
[Description("OPCIP")]
public string OPCIP { get; set; } = "localhost";
/// <summary>
/// OPCNAME
/// </summary>
[Description("OPCNAME")]
public string OPCName { get; set; } = "Kepware.KEPServerEX.V6";
/// <summary>
/// 订阅间隔
/// </summary>
[Description("订阅间隔")]
public int UpdateRate { get; set; } = 1000;
/// <summary>
/// <inheritdoc/>
/// </summary>
@@ -71,4 +61,4 @@ public class OPCDANode
{
return $"{(string.IsNullOrEmpty(OPCIP) ? "localhost" : OPCIP)}:{OPCName}";
}
}
}

View File

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

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,11 +8,10 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using System.Threading.Tasks;

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,24 +8,21 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.OPCUA;
/// <summary>
/// OPCUAClient配置项
/// </summary>
public class OPCUANode
public class OPCNode
{
/// <summary>
/// OPCUrl
/// </summary>
[Description("OPCUrl")]
public string OPCUrl { get; set; } = "opc.tcp://127.0.0.1:49320";
/// <summary>
/// 登录账号
/// </summary>
@@ -38,7 +34,6 @@ public class OPCUANode
/// </summary>
[Description("登录密码")]
public string Password { get; set; }
/// <summary>
/// 检查域
/// </summary>
@@ -50,46 +45,39 @@ public class OPCUANode
/// </summary>
[Description("更新间隔")]
public int UpdateRate { get; set; } = 1000;
/// <summary>
/// 是否订阅
/// </summary>
[Description("是否订阅")]
public bool ActiveSubscribe { get; set; } = true;
/// <summary>
/// 分组大小
/// </summary>
[Description("分组大小")]
public int GroupSize { get; set; } = 500;
/// <summary>
/// 死区
/// </summary>
[Description("死区")]
public double DeadBand { get; set; } = 0;
/// <summary>
/// KeepAliveInterval/ms
/// </summary>
[Description("KeepAliveInterval/ms")]
public int KeepAliveInterval { get; set; } = 3000;
/// <summary>
/// 安全策略
/// </summary>
[Description("安全策略")]
public bool IsUseSecurity { get; set; } = false;
/// <summary>
/// 加载服务端数据类型
/// </summary>
[Description("加载服务端数据类型")]
public bool LoadType { get; set; } = true;
/// <inheritdoc/>
public override string ToString()
{
return OPCUrl;
}
}
}

View File

@@ -39,7 +39,7 @@ public class OPCUAClient : IDisposable
/// <summary>
/// 当前配置
/// </summary>
public OPCUANode OPCNode;
public OPCNode OPCNode;
/// <summary>
/// ProductUri
@@ -49,7 +49,7 @@ public class OPCUAClient : IDisposable
/// <summary>
/// 当前保存的变量名称列表
/// </summary>
public List<List<string>> Variables = new();
public List<string> Variables = new();
/// <summary>
/// 当前的变量名称/OPC变量节点
@@ -380,6 +380,7 @@ public class OPCUAClient : IDisposable
}
}
}
}
catch (Exception ex)
{
@@ -517,9 +518,9 @@ public class OPCUAClient : IDisposable
/// <summary>
/// 连接到服务器
/// </summary>
public async Task ConnectAsync(CancellationToken cancellationToken)
public async Task ConnectAsync()
{
await ConnectAsync(OPCNode.OPCUrl, cancellationToken);
await ConnectAsync(OPCNode.OPCUrl);
}
/// <summary>
@@ -539,7 +540,7 @@ public class OPCUAClient : IDisposable
/// Creates a new session.
/// </summary>
/// <returns>The new session object.</returns>
private async Task<ISession> ConnectAsync(string serverUrl, CancellationToken cancellationToken)
private async Task<ISession> ConnectAsync(string serverUrl)
{
PrivateDisconnect();
@@ -548,7 +549,6 @@ public class OPCUAClient : IDisposable
throw new ArgumentNullException("未初始化配置");
}
var useSecurity = OPCNode?.IsUseSecurity ?? true;
EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(m_configuration, serverUrl, useSecurity, 10000);
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration);
ConfiguredEndpoint endpoint = new(null, endpointDescription, endpointConfiguration);
@@ -571,8 +571,7 @@ public class OPCUAClient : IDisposable
(string.IsNullOrEmpty(OPCUAName)) ? m_configuration.ApplicationName : OPCUAName,
60000,
userIdentity,
Array.Empty<string>(), cancellationToken
).ConfigureAwait(false);
Array.Empty<string>());
typeSystem = new ComplexTypeSystem(m_session);
m_session.KeepAliveInterval = OPCNode.KeepAliveInterval == 0 ? 60000 : OPCNode.KeepAliveInterval;
@@ -585,12 +584,7 @@ public class OPCUAClient : IDisposable
//如果是订阅模式,连接时添加订阅组
if (OPCNode.ActiveSubscribe)
{
foreach (var item in Variables)
{
await AddSubscriptionAsync(Guid.NewGuid().ToString(), item.ToArray(), OPCNode.LoadType);
}
}
await AddSubscriptionAsync(Guid.NewGuid().ToString(), Variables.ToArray(), OPCNode.LoadType);
return m_session;
}
@@ -598,6 +592,7 @@ public class OPCUAClient : IDisposable
{
bool state = m_session?.Connected == true;
if (m_reConnectHandler != null)
{
try { m_reConnectHandler.Dispose(); } catch { }
@@ -614,6 +609,7 @@ public class OPCUAClient : IDisposable
UpdateStatus(2, DateTime.UtcNow, "Disconnected");
DoConnectComplete(false);
}
}
#endregion
@@ -745,7 +741,7 @@ public class OPCUAClient : IDisposable
NodeId nodeToRead = new(nodeIdStr);
var node = (VariableNode)await m_session.ReadNodeAsync(nodeToRead, NodeClass.Variable, false, cancellationToken);
if (OPCNode.LoadType)
await typeSystem.LoadType(node.DataType).ConfigureAwait(false);
await typeSystem.LoadType(node.DataType);
_variableDicts.AddOrUpdate(nodeIdStr, node);
return node;
}
@@ -785,7 +781,7 @@ public class OPCUAClient : IDisposable
if (StatusCode.IsGood(nodes.Item2[i].StatusCode))
{
var node = ((VariableNode)nodes.Item1[i]);
await typeSystem.LoadType(node.DataType).ConfigureAwait(false);
await typeSystem.LoadType(node.DataType);
_variableDicts.AddOrUpdate(nodeIdStrs[i], node);
}
else
@@ -1221,4 +1217,4 @@ public class OPCUAClient : IDisposable
}
#endregion
}
}

View File

@@ -31,16 +31,15 @@ public class OpcUaStatusEventArgs
/// 不可控中断类日输出Critical = 5,
/// </summary>
public int LogLevel { get; set; }
/// <summary>
/// 时间
/// </summary>
public DateTime Time { get; set; }
/// <summary>
/// 文本
/// </summary>
public string Text { get; set; }
}
/// <summary>

View File

@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48;net6.0;net8.0;</TargetFrameworks>
<TargetFrameworks>net48;net6.0;net7.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.4.372.76" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.76" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.4.372.56" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.56" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Adapter.OPCUA;
@@ -29,7 +27,6 @@ internal static class CollectionExtensions
@this.Remove(obj);
}
}
/// <summary>
/// 异步Select
/// </summary>
@@ -38,8 +35,9 @@ internal static class CollectionExtensions
/// <param name="source"></param>
/// <param name="selector"></param>
/// <returns></returns>
internal static async Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, Task<TResult>> selector)
internal static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, Task<TResult>> selector)
{
return await Task.WhenAll(source.Select(selector));
return Task.WhenAll(source.Select(selector));
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
@@ -121,6 +119,5 @@ internal static class DictionaryExtension
{
return dictionary.TryGetValue(tkey, out var value) ? value : default;
}
#endregion
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Opc.Ua;
@@ -18,7 +16,6 @@ using Opc.Ua.Client;
using System.Text;
namespace ThingsGateway.Foundation.Adapter.OPCUA;
/// <summary>
/// 辅助类
/// </summary>
@@ -62,7 +59,7 @@ public class FormUtils
// check for error.
if (StatusCode.IsBad(results[ii].StatusCode))
{
// this error indicates that the server does not have enough simultaneously active
// this error indicates that the server does not have enough simultaneously active
// continuation points. This request will need to be resent after the other operations
// have been completed and their continuation points released.
if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints)
@@ -185,6 +182,7 @@ public class FormUtils
for (int ii = 0; ii < nodesToBrowse.Count; ii++)
{
// check if all references have been fetched.
if (results[ii].References.Count == 0)
{
@@ -194,7 +192,7 @@ public class FormUtils
// check for error.
if (StatusCode.IsBad(results[ii].StatusCode))
{
// this error indicates that the server does not have enough simultaneously active
// this error indicates that the server does not have enough simultaneously active
// continuation points. This request will need to be resent after the other operations
// have been completed and their continuation points released.
if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints)
@@ -205,10 +203,14 @@ public class FormUtils
continue;
}
// save results.
references.AddRange(results[ii].References);
}
while (continuationPoints.Any())
{
// continue browse operation.
@@ -236,8 +238,12 @@ public class FormUtils
continue;
}
// save results.
references.AddRange(results[ii].References);
}
// check if browsing must continue;
@@ -285,6 +291,7 @@ public class FormUtils
// start the browse operation.
var result = await session.BrowseAsync(
null,
null,
@@ -367,7 +374,7 @@ public class FormUtils
BrowseDirection = BrowseDirection.Inverse,
ReferenceTypeId = ReferenceTypeIds.HasSubtype,
IncludeSubtypes = false, // more efficient to use IncludeSubtypes=False when possible.
NodeClassMask = 0, // the HasSubtype reference already restricts the targets to Types.
NodeClassMask = 0, // the HasSubtype reference already restricts the targets to Types.
ResultMask = (uint)BrowseResultMask.All
};
@@ -564,7 +571,7 @@ public class FormUtils
string discoveryUrl = servers[ii].DiscoveryUrls[jj];
// Many servers will use the '/discovery' suffix for the discovery endpoint.
// The URL without this prefix should be the base URL for the server.
// The URL without this prefix should be the base URL for the server.
if (discoveryUrl.EndsWith("/discovery"))
{
discoveryUrl = discoveryUrl.Substring(0, discoveryUrl.Length - "/discovery".Length);
@@ -726,7 +733,7 @@ public class FormUtils
{
EndpointDescriptionCollection endpoints = client.GetEndpoints(null);
// select the best endpoint to use based on the selected URL and the UseSecurity checkbox.
// select the best endpoint to use based on the selected URL and the UseSecurity checkbox.
for (int ii = 0; ii < endpoints.Count; ii++)
{
EndpointDescription endpoint = endpoints[ii];
@@ -753,7 +760,7 @@ public class FormUtils
// pick the first available endpoint by default.
selectedEndpoint ??= endpoint;
// The security level is a relative measure assigned by the server to the
// The security level is a relative measure assigned by the server to the
// endpoints that it returns. Clients should always pick the highest level
// unless they have a reason not too.
if (endpoint.SecurityLevel > selectedEndpoint.SecurityLevel)
@@ -771,7 +778,7 @@ public class FormUtils
}
// if a server is behind a firewall it may return URLs that are not accessible to the client.
// This problem can be avoided by assuming that the domain in the URL used to call
// This problem can be avoided by assuming that the domain in the URL used to call
// GetEndpoints can be used to access any of the endpoints. This code makes that conversion.
// Note that the conversion only makes sense if discovery uses the same protocol as the endpoint.
@@ -824,6 +831,7 @@ public class FormUtils
// make the call to the server.
var result = await session.TranslateBrowsePathsToNodeIdsAsync(
null,
browsePaths,
@@ -863,7 +871,7 @@ public class FormUtils
continue;
}
// The targetId is an ExpandedNodeId because it could be node in another server.
// The targetId is an ExpandedNodeId because it could be node in another server.
// The ToNodeId function is used to convert a local NodeId stored in a ExpandedNodeId to a NodeId.
nodes.Add(ExpandedNodeId.ToNodeId(target.TargetId, session.NamespaceUris));
}
@@ -1117,4 +1125,4 @@ public class FormUtils
}
return continuationPoints;
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,15 +8,14 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
namespace Opc.Ua
{
public class OPCUAJsonEncoder : IJsonEncoder, IEncoder, IDisposable
@@ -713,15 +711,12 @@ namespace Opc.Ua
case IdType.Numeric:
WriteUInt32("Id", (uint)value.Identifier);
break;
case IdType.String:
WriteString("Id", (string)value.Identifier);
break;
case IdType.Guid:
WriteGuid("Id", (Guid)value.Identifier);
break;
case IdType.Opaque:
WriteByteString("Id", (byte[])value.Identifier);
break;
@@ -1672,103 +1667,78 @@ namespace Opc.Ua
case BuiltInType.Boolean:
WriteBoolean(null, (bool)value);
break;
case BuiltInType.SByte:
WriteSByte(null, (sbyte)value);
break;
case BuiltInType.Byte:
WriteByte(null, (byte)value);
break;
case BuiltInType.Int16:
WriteInt16(null, (short)value);
break;
case BuiltInType.UInt16:
WriteUInt16(null, (ushort)value);
break;
case BuiltInType.Int32:
WriteInt32(null, (int)value);
break;
case BuiltInType.UInt32:
WriteUInt32(null, (uint)value);
break;
case BuiltInType.Int64:
WriteInt64(null, (long)value);
break;
case BuiltInType.UInt64:
WriteUInt64(null, (ulong)value);
break;
case BuiltInType.Float:
WriteFloat(null, (float)value);
break;
case BuiltInType.Double:
WriteDouble(null, (double)value);
break;
case BuiltInType.String:
WriteString(null, (string)value);
break;
case BuiltInType.DateTime:
WriteDateTime(null, (DateTime)value);
break;
case BuiltInType.Guid:
WriteGuid(null, (Uuid)value);
break;
case BuiltInType.ByteString:
WriteByteString(null, (byte[])value);
break;
case BuiltInType.XmlElement:
WriteXmlElement(null, (XmlElement)value);
break;
case BuiltInType.NodeId:
WriteNodeId(null, (NodeId)value);
break;
case BuiltInType.ExpandedNodeId:
WriteExpandedNodeId(null, (ExpandedNodeId)value);
break;
case BuiltInType.StatusCode:
WriteStatusCode(null, (StatusCode)value);
break;
case BuiltInType.QualifiedName:
WriteQualifiedName(null, (QualifiedName)value);
break;
case BuiltInType.LocalizedText:
WriteLocalizedText(null, (LocalizedText)value);
break;
case BuiltInType.ExtensionObject:
WriteExtensionObject(null, (ExtensionObject)value);
break;
case BuiltInType.DataValue:
WriteDataValue(null, (DataValue)value);
break;
case BuiltInType.Enumeration:
WriteEnumerated(null, (Enum)value);
break;
case BuiltInType.DiagnosticInfo:
WriteDiagnosticInfo(null, (DiagnosticInfo)value);
break;
case BuiltInType.Variant:
case BuiltInType.Number:
case BuiltInType.Integer:
@@ -1833,99 +1803,75 @@ namespace Opc.Ua
case BuiltInType.Boolean:
WriteBooleanArray(fieldName, (bool[])array);
break;
case BuiltInType.SByte:
WriteSByteArray(fieldName, (sbyte[])array);
break;
case BuiltInType.Byte:
WriteByteArray(fieldName, (byte[])array);
break;
case BuiltInType.Int16:
WriteInt16Array(fieldName, (short[])array);
break;
case BuiltInType.UInt16:
WriteUInt16Array(fieldName, (ushort[])array);
break;
case BuiltInType.Int32:
WriteInt32Array(fieldName, (int[])array);
break;
case BuiltInType.UInt32:
WriteUInt32Array(fieldName, (uint[])array);
break;
case BuiltInType.Int64:
WriteInt64Array(fieldName, (long[])array);
break;
case BuiltInType.UInt64:
WriteUInt64Array(fieldName, (ulong[])array);
break;
case BuiltInType.Float:
WriteFloatArray(fieldName, (float[])array);
break;
case BuiltInType.Double:
WriteDoubleArray(fieldName, (double[])array);
break;
case BuiltInType.String:
WriteStringArray(fieldName, (string[])array);
break;
case BuiltInType.DateTime:
WriteDateTimeArray(fieldName, (DateTime[])array);
break;
case BuiltInType.Guid:
WriteGuidArray(fieldName, (Uuid[])array);
break;
case BuiltInType.ByteString:
WriteByteStringArray(fieldName, (byte[][])array);
break;
case BuiltInType.XmlElement:
WriteXmlElementArray(fieldName, (XmlElement[])array);
break;
case BuiltInType.NodeId:
WriteNodeIdArray(fieldName, (NodeId[])array);
break;
case BuiltInType.ExpandedNodeId:
WriteExpandedNodeIdArray(fieldName, (ExpandedNodeId[])array);
break;
case BuiltInType.StatusCode:
WriteStatusCodeArray(fieldName, (StatusCode[])array);
break;
case BuiltInType.QualifiedName:
WriteQualifiedNameArray(fieldName, (QualifiedName[])array);
break;
case BuiltInType.LocalizedText:
WriteLocalizedTextArray(fieldName, (LocalizedText[])array);
break;
case BuiltInType.ExtensionObject:
WriteExtensionObjectArray(fieldName, (ExtensionObject[])array);
break;
case BuiltInType.DataValue:
WriteDataValueArray(fieldName, (DataValue[])array);
break;
case BuiltInType.DiagnosticInfo:
WriteDiagnosticInfoArray(fieldName, (DiagnosticInfo[])array);
break;
case BuiltInType.Enumeration:
{
Array array6 = array as Array;
@@ -2100,4 +2046,4 @@ namespace Opc.Ua
m_nestingLevel++;
}
}
}
}

View File

@@ -1,5 +1,4 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
@@ -9,7 +8,6 @@
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Newtonsoft.Json;
@@ -18,11 +16,11 @@ using Newtonsoft.Json.Linq;
using Opc.Ua;
using System.Collections;
using System.IO;
using System.Text;
using System.Xml;
namespace ThingsGateway.Foundation.Adapter.OPCUA;
/// <summary>
/// 扩展方法
/// </summary>
@@ -42,11 +40,13 @@ public static class JsonUtils
JToken json
)
{
var data = DecoderObject(Context, dataTypeId, builtInType, valueRank, json);
var dataValue = new DataValue(new Variant(data));
return dataValue;
}
/// <summary>
/// 解析获取object
/// </summary>
@@ -72,7 +72,6 @@ public static class JsonUtils
}
}.ToJsonString();
break;
case BuiltInType.Variant:
var type = TypeInfo.GetDataTypeId(GetSystemType(json.Type));
newData = new
@@ -82,9 +81,9 @@ public static class JsonUtils
Type = type.Identifier,
Body = json
}
}.ToJsonString();
break;
default:
newData = new
{
@@ -98,6 +97,8 @@ public static class JsonUtils
return data;
}
/// <summary>
/// DecodeRawData
/// </summary>
@@ -151,10 +152,10 @@ public static class JsonUtils
return null;
}
#endregion
#region Encode
/// <summary>
/// OPCUAValue解析为Jtoken
/// </summary>
@@ -192,6 +193,7 @@ public static class JsonUtils
bool includeDefaultNumbers = true
)
{
return new OPCUAJsonEncoder(context, useReversibleEncoding, topLevelIsArray, stream)
{
IncludeDefaultValues = includeDefaultValues,
@@ -306,6 +308,7 @@ public static class JsonUtils
return;
}
case BuiltInType.Guid: { encoder.WriteGuid(fieldName, (Uuid)value); return; }
case BuiltInType.ByteString: { encoder.WriteByteString(fieldName, (byte[])value); return; }
case BuiltInType.XmlElement: { encoder.WriteXmlElement(fieldName, (XmlElement)value); return; }
@@ -355,7 +358,6 @@ public static class JsonUtils
encoder.WriteArray(fieldName, c, c.Rank, builtInType);
}
}
#endregion
#region json
@@ -380,7 +382,6 @@ public static class JsonUtils
}
return numDimensions;
}
private static bool ElementsHasSameType(this JToken[] jTokens)
{
var checkType = jTokens[0].Type == JTokenType.Integer ? JTokenType.Float : jTokens[0].Type;
@@ -395,7 +396,6 @@ public static class JsonUtils
throw new Exception("The array sent must have the same type of element in each dimension");
return jTokens.First().Type;
}
private static Type GetSystemType(JTokenType jsonType)
{
return jsonType switch
@@ -425,7 +425,6 @@ public static class JsonUtils
#endregion
#region Json序列化和反序列化
/// <summary>
/// 从字符串到json
/// </summary>
@@ -530,6 +529,6 @@ public static class JsonUtils
else
return Newtonsoft.Json.JsonConvert.SerializeObject(item);
}
#endregion Json序列化和反序列化
}

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