Compare commits

..

38 Commits

Author SHA1 Message Date
Kimdiego2098
f272fb0559 更新版本 2024-02-02 13:00:04 +08:00
Kimdiego2098
bd04e33586 底层通道设备列表更换为线程安全列表 2024-02-02 12:29:19 +08:00
Kimdiego2098
b09b9752ca mqttServer修复客户端连接时,发送初始数据分组错误 2024-02-02 12:16:43 +08:00
Kimdiego2098
a810a48158 更新dockerfile 2024-02-02 08:40:10 +08:00
Kimdiego2098
b4f5792aa8 串口流BeginRead更换为ReadAsync 2024-02-01 16:50:01 +08:00
Kimdiego2098
fdf0330b4f 更新版本 2024-02-01 12:20:11 +08:00
Kimdiego2098
ca73743082 调整服务启动顺序 2024-02-01 12:19:44 +08:00
Kimdiego2098
df0cde2cfd 定长字符串写入时,长度不足也覆盖剩余字节 2024-01-30 17:37:44 +08:00
Kimdiego2098
5a8421e807 更新版本 2024-01-30 14:33:57 +08:00
Kimdiego2098
025ac95d81 修复数据转换无默认构造导致的反序列化错误 2024-01-30 14:27:33 +08:00
Kimdiego2098
71b5824fdc 添加重启事件 2024-01-30 13:52:17 +08:00
Kimdiego2098
1a907c0be7 更新版本 2024-01-30 12:22:43 +08:00
Kimdiego2098
1635cabd32 更新版本 2024-01-30 11:56:58 +08:00
Kimdiego2098
27946a5b0f 调整日志文件路径 2024-01-30 11:56:26 +08:00
Kimdiego2098
e141822fd0 调整sqlsugar 2024-01-30 10:54:35 +08:00
Kimdiego2098
6326828a02 调整依赖 2024-01-30 10:16:35 +08:00
Kimdiego2098
96b5362491 添加modbus的字符串按字反转配置 2024-01-30 10:04:38 +08:00
Kimdiego2098
8ab91a51bc 调整瞬态服务构造 2024-01-30 09:42:15 +08:00
Kimdiego2098
35e7e7af18 更新版本 2024-01-29 18:28:15 +08:00
Kimdiego2098
0e248a7302 更新依赖包 2024-01-29 18:27:58 +08:00
Kimdiego2098
d5ce4d6600 调整代码 2024-01-29 17:55:40 +08:00
Kimdiego2098
2365bb5e87 sqlsugar版本固定5.1.4.122 2024-01-29 16:28:55 +08:00
Kimdiego2098
2230216a7e 调整代码 2024-01-29 14:32:33 +08:00
Kimdiego2098
54f896d25f 调整Task.Delay 2024-01-29 11:28:23 +08:00
Kimdiego2098
e47d239caf 调整种子数据 2024-01-29 09:13:49 +08:00
Kimdiego2098
ac259958d7 更新文档 2024-01-29 08:45:10 +08:00
Diego2098
0505ad88a6 修复mqttRpc写入数组时,字符串解析错误问题 2024-01-27 12:40:48 +08:00
Diego2098
b323de3383 添加属性默认值 2024-01-27 09:57:06 +08:00
Kimdiego2098
c0e023324b 更新文档 2024-01-26 11:51:35 +08:00
Kimdiego2098
495806d5e3 文档添加演示站点 2024-01-26 11:09:13 +08:00
Kimdiego2098
3a9f745a2d 更新Dlt645 nuget包文档 2024-01-26 10:43:19 +08:00
Kimdiego2098
7b15d114a3 适配窗体大小 2024-01-26 10:01:47 +08:00
Kimdiego2098
6ac0f72169 默认开启标签页缓存 2024-01-26 08:52:02 +08:00
Kimdiego2098
ff68030231 添加可空判断方法 2024-01-25 14:02:37 +08:00
Kimdiego2098
d34361b6dd 更新文档 2024-01-25 11:03:46 +08:00
Kimdiego2098
56c6ebe523 修复事务锁异常导致sqlite lock 2024-01-25 11:03:39 +08:00
Kimdiego2098
2c6d2e0eb4 更新文档 2024-01-24 16:56:01 +08:00
Kimdiego2098
8e64196a8f 去除MqttRpc主题的规则限制 2024-01-24 16:51:10 +08:00
178 changed files with 1497 additions and 735 deletions

10
doc/build/404.html vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
"use strict";(self.webpackChunkthingsgateway=self.webpackChunkthingsgateway||[]).push([[9626],{1166:(t,e,a)=>{a.r(e),a.d(e,{assets:()=>r,contentTitle:()=>o,default:()=>p,frontMatter:()=>n,metadata:()=>i,toc:()=>l});var s=a(7462),d=(a(7294),a(3905));a(4996),a(510),a(2969);const n={id:501,title:"\u5e38\u89c1\u95ee\u9898"},o=void 0,i={unversionedId:"501",id:"501",title:"\u5e38\u89c1\u95ee\u9898",description:"1\u3001Modbus\u5730\u5740\u53ef\u4ee5\u53ea\u5199\u5730\u57400\u5417\uff0c\u4e00\u5b9a\u8981\u5199\u6210\u7c7b\u4f3c400001?",source:"@site/docs/501.mdx",sourceDirName:".",slug:"/501",permalink:"/thingsgateway-docs/docs/501",draft:!1,editUrl:"https://gitee.com/diego2098/ThingsGateway/tree/master/doc/docs/501.mdx",tags:[],version:"current",lastUpdatedBy:"Kimdiego2098",lastUpdatedAt:1706078809,formattedLastUpdatedAt:"Jan 24, 2024",frontMatter:{id:"501",title:"\u5e38\u89c1\u95ee\u9898"},sidebar:"docs",previous:{title:"Linux\u670d\u52a1\u90e8\u7f72",permalink:"/thingsgateway-docs/docs/404"},next:{title:"\u811a\u672c\u5e38\u89c1\u95ee\u9898",permalink:"/thingsgateway-docs/docs/502"}},r={},l=[{value:"1\u3001Modbus\u5730\u5740\u53ef\u4ee5\u53ea\u5199\u5730\u57400\u5417\uff0c\u4e00\u5b9a\u8981\u5199\u6210\u7c7b\u4f3c400001?",id:"1modbus\u5730\u5740\u53ef\u4ee5\u53ea\u5199\u5730\u57400\u5417\u4e00\u5b9a\u8981\u5199\u6210\u7c7b\u4f3c400001",level:4},{value:"2\u3001\u6570\u636e\u5982\u4f55\u8bbe\u7f6e\u5c0f\u6570\u4f4d",id:"2\u6570\u636e\u5982\u4f55\u8bbe\u7f6e\u5c0f\u6570\u4f4d",level:4},{value:"3\u3001\u6e90\u7801\u6253\u5f00razor\u6587\u4ef6\u65f6\uff0c\u4e0d\u51fa\u73b0\u667a\u80fd\u63d0\u793a\uff0c\u6709waring\u8b66\u544a(\u6ce2\u6d6a\u7ebf)",id:"3\u6e90\u7801\u6253\u5f00razor\u6587\u4ef6\u65f6\u4e0d\u51fa\u73b0\u667a\u80fd\u63d0\u793a\u6709waring\u8b66\u544a\u6ce2\u6d6a\u7ebf",level:4}],u={toc:l},c="wrapper";function p(t){let{components:e,...a}=t;return(0,d.kt)(c,(0,s.Z)({},u,a,{components:e,mdxType:"MDXLayout"}),(0,d.kt)("h4",{id:"1modbus\u5730\u5740\u53ef\u4ee5\u53ea\u5199\u5730\u57400\u5417\u4e00\u5b9a\u8981\u5199\u6210\u7c7b\u4f3c400001"},"1\u3001Modbus\u5730\u5740\u53ef\u4ee5\u53ea\u5199\u5730\u57400\u5417\uff0c\u4e00\u5b9a\u8981\u5199\u6210\u7c7b\u4f3c400001?"),(0,d.kt)("p",null,"\u6309\u7167PLC Modbus\u5bc4\u5b58\u5668\u7684\u683c\u5f0f\uff0c\u4ee5\u533a\u57df\u53f7\u4e3a\u8d77\u59cb\u5b57\u7b26\uff0c\u540e\u7eed\u52a0\u4e0a\uff08\u5bc4\u5b58\u5668\u5730\u5740+1\uff09",(0,d.kt)("br",{parentName:"p"}),"\n","\u6240\u4ee5\u4e00\u5b9a\u8981\u5199\u6210400001"),(0,d.kt)("h4",{id:"2\u6570\u636e\u5982\u4f55\u8bbe\u7f6e\u5c0f\u6570\u4f4d"},"2\u3001\u6570\u636e\u5982\u4f55\u8bbe\u7f6e\u5c0f\u6570\u4f4d"),(0,d.kt)("p",null,"\u7f51\u5173\u63d0\u4f9b\u7075\u6d3b\u7684\u811a\u672c\u5f0f\u914d\u7f6e\u8f6c\u6362\uff0c\u53ef\u4ee5\u5728\u53d8\u91cf\u7684\u8bfb\u53d6\u8868\u8fbe\u5f0f\u4e2d\u8fdb\u884c\u914d\u7f6e\u8f6c\u6362\n\u5982\u679c\u8981\u8bbe\u7f6e\u5c0f\u6570\u4f4d\u4e3a2\uff0c\u53ef\u4ee5\u586b\u5165 "),(0,d.kt)("pre",null,(0,d.kt)("code",{parentName:"pre"},"Math.Round(raw, 2)\n")),(0,d.kt)("h4",{id:"3\u6e90\u7801\u6253\u5f00razor\u6587\u4ef6\u65f6\u4e0d\u51fa\u73b0\u667a\u80fd\u63d0\u793a\u6709waring\u8b66\u544a\u6ce2\u6d6a\u7ebf"},"3\u3001\u6e90\u7801\u6253\u5f00razor\u6587\u4ef6\u65f6\uff0c\u4e0d\u51fa\u73b0\u667a\u80fd\u63d0\u793a\uff0c\u6709waring\u8b66\u544a(\u6ce2\u6d6a\u7ebf)"),(0,d.kt)("p",null,"VS\u7684bug\u5bfc\u81f4\u7684\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u5347\u7ea7vs\uff0c\u628a\u5de5\u7a0b\u76ee\u5f55\u4e0b\u7684.vs\u6587\u4ef6\u5939\u5df2\u7ecf\u5168\u90e8\u7684bin OR obj \u5220\u9664\u540e\uff0c\u91cd\u65b0\u6253\u5f00\u89e3\u51b3\u65b9\u6848"))}p.isMDXComponent=!0}}]);

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
"use strict";(self.webpackChunkthingsgateway=self.webpackChunkthingsgateway||[]).push([[8976],{137:(t,e,s)=>{s.r(e),s.d(e,{assets:()=>r,contentTitle:()=>o,default:()=>g,frontMatter:()=>i,metadata:()=>n,toc:()=>c});var a=s(7462),d=(s(7294),s(3905));s(4996),s(510),s(2969);const i={id:20005,title:"Dlt645"},o=void 0,n={unversionedId:"20005",id:"20005",title:"Dlt645",description:"",source:"@site/docs/20005.mdx",sourceDirName:".",slug:"/20005",permalink:"/thingsgateway-docs/docs/20005",draft:!1,editUrl:"https://gitee.com/diego2098/ThingsGateway/tree/master/doc/docs/20005.mdx",tags:[],version:"current",lastUpdatedBy:"Kimdiego2098",lastUpdatedAt:1705826523,formattedLastUpdatedAt:"Jan 21, 2024",frontMatter:{id:"20005",title:"Dlt645"},sidebar:"docs",previous:{title:"OpcUa",permalink:"/thingsgateway-docs/docs/20004"},next:{title:"\u8054\u7cfb\u6211\u4eec",permalink:"/thingsgateway-docs/docs/1002"}},r={},c=[],l={toc:c},p="wrapper";function g(t){let{components:e,...s}=t;return(0,d.kt)(p,(0,a.Z)({},l,s,{components:e,mdxType:"MDXLayout"}))}g.isMDXComponent=!0}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
"use strict";(self.webpackChunkthingsgateway=self.webpackChunkthingsgateway||[]).push([[7285],{6067:(t,e,s)=>{s.r(e),s.d(e,{assets:()=>r,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>n,toc:()=>c});var a=s(7462),d=(s(7294),s(3905));s(4996),s(510),s(2969);const o={id:20001,title:"Modbus"},i=void 0,n={unversionedId:"20001",id:"20001",title:"Modbus",description:"",source:"@site/docs/20001.mdx",sourceDirName:".",slug:"/20001",permalink:"/thingsgateway-docs/docs/20001",draft:!1,editUrl:"https://gitee.com/diego2098/ThingsGateway/tree/master/doc/docs/20001.mdx",tags:[],version:"current",lastUpdatedBy:"Kimdiego2098",lastUpdatedAt:1705826523,formattedLastUpdatedAt:"Jan 21, 2024",frontMatter:{id:"20001",title:"Modbus"},sidebar:"docs",previous:{title:"\u4e1a\u52a1\u63d2\u4ef6\u5f00\u53d1",permalink:"/thingsgateway-docs/docs/602"},next:{title:"SiemensS7",permalink:"/thingsgateway-docs/docs/20002"}},r={},c=[],p={toc:c},l="wrapper";function u(t){let{components:e,...s}=t;return(0,d.kt)(l,(0,a.Z)({},p,s,{components:e,mdxType:"MDXLayout"}))}u.isMDXComponent=!0}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10
doc/build/index.html vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -26,6 +26,7 @@ ModbusMatser作为主站主动采集Modbus从站协议的设备
| Modbus协议类型 | modbusTcp/modbusRtu格式报文 | |
| 默认站号 | 默认的mudbus站号id | **变量可单独配置站号** |
| 无交互2min时断开连接 | 没有发送/收到消息 2分钟后断开连接 | 仅适用于TcpService链路DTU模式|
| 心跳检测 | 大写16进制字符串符合心跳内容会自动回应 | 仅适用于TcpService链路DTU模式|
| 读写超时时间 | 读写超时时间 | 3000|
| 连接超时时间 | 建立通讯链路的超时时间 | 3000|
| 发送延时时间 | 在发送请求前的延时时间 | 0|
@@ -67,3 +68,11 @@ Modbus PLC寄存器
| w=15;10001 | 读取02功能码 ,写入15功能码 |
| w=16;40001 | 读取03功能码 ,写入16功能码 |
- 3、Dtu注册(可选)
当需要指定Dtu客户端可使用举例
| 地址 | 说明 |
| ---------------| --------------------------|
| id=12;40001 | 读取03功能码 ,设备地址为默认Dtu注册包为"12",注意是UTF8格式 |

View File

@@ -7,3 +7,90 @@ import useBaseUrl from "@docusaurus/useBaseUrl";
import Tag from "@site/src/components/Tag.js";
import Highlight from '@site/src/components/Highlight.js';
## 定义
程序集:[ThingsGateway.Foundation.Modbus](https://www.nuget.org/packages/ThingsGateway.Foundation.Modbus)
## 一、说明
**ThingsGateway.Foundation.Modbus**是对于Modbus协议的封装类库
支持Tcp/Rtu格式
支持多个通讯链路Tcp/Udp/SerialPort
支持Dtu
## 二、Modbus主站
1、创建ModbusMaster
```
/// <summary>
/// 新建链路
/// </summary>
/// <returns></returns>
public IChannel GetChannel()
{
TouchSocketConfig touchSocketConfig = new TouchSocketConfig();
return touchSocketConfig.GetSerialPortWithOption(new("COM1")); //直接获取串口对象
//return touchSocketConfig.GetChannel(ChannelTypeEnum.SerialPortClient, null, null, new("COM1"));//通过链路枚举获取对象
}
/// <summary>
/// 新建协议对象
/// </summary>
/// <param name="channel"></param>
/// <returns></returns>
public IProtocol GetProtocol(IChannel channel)
{
var client = new ModbusMaster(channel);
return client;
}
```
2、读写操作
```
ModbusMaster modbusMasterTest = new ModbusMaster();
var channel = modbusMasterTest.GetChannel();
var protocol = modbusMasterTest.GetProtocol(channel);
var data = await protocol.ReadDoubleAsync("400001"); //读取保持寄存器地址0
```
`400001`是PLC Modbus的地址表示方式代表保持寄存器地址0### 1、从站地址
- 基本地址
Modbus PLC寄存器
| 地址 | 功能码 | 说明 |
| ---------------| --------------|--------------------------|
| 4xxxxx | 03 | 读取03功能码 |
| 3xxxxx | 04 | 读取04功能码 |
| 1xxxxx | 02 | 读取02功能码 |
| 0xxxxx | 01 | 读取01功能码 |
- 站号(可选)
当需要指定站号地址时可使用,举例:
| 地址 | 说明 |
| ---------------| --------------------------|
| s=2;10001 | 读取02功能码 ,设备地址为2 |
| s=11;40001 | 读取03功能码 ,设备地址为11 |
- Dtu注册(可选)
当需要指定Dtu客户端可使用举例
| 地址 | 说明 |
| ---------------| --------------------------|
| id=12;40001 | 读取03功能码 ,设备地址为默认Dtu注册包为"12",注意是UTF8格式 |
## 三、Modbus从站

View File

@@ -7,3 +7,106 @@ import useBaseUrl from "@docusaurus/useBaseUrl";
import Tag from "@site/src/components/Tag.js";
import Highlight from '@site/src/components/Highlight.js';
## 定义
程序集:[ThingsGateway.Foundation.Dlt645](https://www.nuget.org/packages/ThingsGateway.Foundation.Dlt645)
## 一、说明
**ThingsGateway.Foundation.Dlt645**是对于Dlt645-2007协议的封装类库
支持多个通讯链路Tcp/Udp/SerialPort
## 二、Dlt645-2007主站
1、创建Dlt645Master
```
/// <summary>
/// 新建链路
/// </summary>
/// <returns></returns>
public IChannel GetChannel()
{
TouchSocketConfig touchSocketConfig = new TouchSocketConfig();
return touchSocketConfig.GetSerialPortWithOption(new("COM1")); //直接获取串口对象
//return touchSocketConfig.GetChannel(ChannelTypeEnum.SerialPortClient, null, null, new("COM1"));//通过链路枚举获取对象
}
/// <summary>
/// 新建协议对象
/// </summary>
/// <param name="channel"></param>
/// <returns></returns>
public IProtocol GetProtocol(IChannel channel)
{
var client = new Dlt645_2007Master(channel);
client.Station = "311111111114";//表号
return client;
}
```
2、读写操作
```
Dlt645MasterTest dlt645MasterTest = new Dlt645MasterTest();
var channel = dlt645MasterTest.GetChannel();
var protocol = dlt645MasterTest.GetProtocol(channel);
var data = await protocol.ReadDoubleAsync("02010100"); //读取A相电压
```
`02010100`是Dlt645中的地址表示方式代表A相电压请查看相关协议文档可在源码附件中找到文档
- 基本地址
| 地址 | 说明 |
| ---------------| --------------------------|
| 02010100 | 读取02010100(A相电压) |
参考DLT2007协议文档数据标识可在插件源码中找到附件
- 站号(可选)
当需要指定站号地址时可使用,举例:
| 地址 | 说明 |
| ---------------| --------------------------|
| s=111111111111;02010100 | 读取02010100 ,设备地址为111111111111 |
- Dtu注册(可选)
当需要指定Dtu客户端可使用举例
| 地址 | 说明 |
| ---------------| --------------------------|
| id=12;40001 | 读取03功能码 ,设备地址为默认Dtu注册包为"12",注意是UTF8格式 |
3、其他方法
修改密码
```
var result = await protocol.WritePasswordAsync(level, oldPassword, newPassword);
```
更改表号
```
var result = await protocol.WriteDeviceStationAsync(station);
```
修改波特率
```
var result = await protocol.WriteBaudRateAsync(baudRate);
```
读取表号
```
var result = await protocol.ReadDeviceStationAsync;
```

View File

@@ -22,6 +22,7 @@ Dlt645Master作为主站主动采集Dlt645协议的设备
| 属性 | 说明 | 备注|
| ---------------| --------------------------| ---|
| 无交互2min时断开连接 | 没有发送/收到消息 2分钟后断开连接 | 仅适用于TcpService链路DTU模式|
| 心跳检测 | 大写16进制字符串符合心跳内容会自动回应 | 仅适用于TcpService链路DTU模式|
| 读写超时时间 | 读写超时时间 | 3000|
| 连接超时时间 | 建立通讯链路的超时时间 | 3000|
| 发送延时时间 | 在发送请求前的延时时间 | 0|
@@ -54,6 +55,15 @@ Dlt645Master作为主站主动采集Dlt645协议的设备
| ---------------| --------------------------|
| s=111111111111;02010100 | 读取02010100 ,设备地址为111111111111 |
- 3、Dtu注册(可选)
当需要指定Dtu客户端可使用举例
| 地址 | 说明 |
| ---------------| --------------------------|
| id=12;02010100 | 读取02010100 ,设备地址为默认Dtu注册包为"12",注意是UTF8格式 |
:::tip `说明`
注意DLT645协议中所有的变量都支持String

View File

@@ -25,3 +25,23 @@ Math.Round(raw, 2)
VS的bug导致的可以尝试升级vs把工程目录下的.vs文件夹已经全部的bin OR obj 删除后,重新打开解决方案
#### 4、报警属性中的报警约束如何定义
报警约束和变量表达式类似填入脚本返回值为true时报警生效
```csharp
//新建testInt1,testInt2两个变量
//在testInt1的高高报警值为1开启使能
//在testInt1的高高报警约束中定义testInt2>10
//testInt1为8,testInt2为11时产生testInt1报警
//testInt1为8,testInt2为10时不会产生testInt1报警
```
#### 5、启动项目之后驱动调试页面没有任何信息设备选择插件时也不出现任何选择项
网关插件未编译,需要编译解决方案,查看入门指南;或者插件未能成功拷贝到插件目录(Plugins)

View File

@@ -7,3 +7,32 @@ import useBaseUrl from "@docusaurus/useBaseUrl";
import Tag from "@site/src/components/Tag.js";
import Highlight from '@site/src/components/Highlight.js';
## 说明
ThingsGateway封装了丰富的协议解析方法方便开发多种PLC通讯插件
下面我们以Omron FinsTcp/Udp为例讲解如何基于ThingsGateway开发一个**通用驱动**以及ThingsGateway插件
## 一、协议解析
`Fins` 协议是OSI模型第7层上的应用层报文传输协议我们画一个简单的应用层协议报文解析图
| Fins over TCP | Fins over UDP |
| ---------------| --------------------------|
| FinsTCP Header | None |
| FinsUDP Header | FinsUDP Header |
| Command Data |Command Data |
可以看出基于Tcp的Fins和基于Udp的Fins协议差别只是Tcp连接时会加一个FinsTcp报文头。
下面我们进行每个部分的说明
### 1、FinsTCP Header
FinsTcp头部固定为16个字节
| FinsTCP Header | 说明 |
| ---------------| --------------------------|
| Magic | 固定0x46494E53也就是FINS字符串的ASCII码 |
| Length | 后续全部字节的长度 |
| Command | 0是客户端请求握手1是服务端返回握手信息除0,1外是其他方法 |

View File

@@ -42,7 +42,11 @@ module.exports = {
position: "left",
to: "docs/upgrade"
},
{
label: "演示",
position: "right",
href: "http://120.24.62.140:5000",
},
{
label: "源码",
position: "right",

View File

@@ -6,7 +6,7 @@
<LangVersion>11.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>5.0.0.6</Version>
<Version>5.0.0.11</Version>
<Authors>Diego</Authors>
<Company>Diego</Company>
<Product>Diego</Product>

View File

@@ -43,7 +43,7 @@ public class NoticeEventSubsciber : IEventSubscriber, ISingleton
//客户端ID列表
var clientIds = new List<string>();
//遍历verificat列表获取客户端ID列表
loginEvent.VerificatInfos.ForEach(it =>
loginEvent?.VerificatInfos?.ForEach(it =>
{
clientIds.AddRange(it.ClientIds);
});

View File

@@ -34,16 +34,14 @@ public class AuthService : IAuthService
private readonly IEventPublisher _eventPublisher;
private readonly IConfigService _configService;
private readonly ISysUserService _userService;
private readonly IRoleService _roleService;
public AuthService(ISimpleCacheService simpleCacheService, IEventPublisher eventPublisher, IConfigService configService,
ISysUserService userService, IRoleService roleService)
ISysUserService userService)
{
_simpleCacheService = simpleCacheService;
_eventPublisher = eventPublisher;
_configService = configService;
_userService = userService;
_roleService = roleService;
}
/// <inheritdoc/>

View File

@@ -17,7 +17,7 @@ namespace ThingsGateway.Admin.Application;
/// <summary>
/// 会话管理服务
/// </summary>
public interface ISessionService : ISugarService, ITransient
public interface ISessionService : ISugarService, IScoped
{
/// <summary>
/// 会话统计

View File

@@ -27,13 +27,6 @@ namespace ThingsGateway.Admin.Application;
/// </summary>
public class FileService : IFileService
{
private readonly IConfigService _configService;
public FileService(IConfigService configService)
{
_configService = configService;
}
/// <inheritdoc/>
public async Task<string> UploadFileAsync(string pPath, IBrowserFile file)
{

View File

@@ -17,15 +17,11 @@ namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IRelationService"/>
public class Relationservice : DbRepository<SysRelation>, IRelationService
{
private readonly ILogger<Relationservice> _logger;
private readonly ISimpleCacheService _simpleCacheService;
private readonly IResourceService _resourceService;
public Relationservice(ILogger<Relationservice> logger, ISimpleCacheService simpleCacheService, IResourceService resourceService)
public Relationservice(ISimpleCacheService simpleCacheService)
{
_logger = logger;
_simpleCacheService = simpleCacheService;
_resourceService = resourceService;
}
/// <inheritdoc/>
@@ -119,7 +115,7 @@ public class Relationservice : DbRepository<SysRelation>, IRelationService
});
}
//事务
var result = await NewContent.UseTranAsync(async () =>
var result = await Context.AsTenant().UseTranAsync(async () =>
{
if (clear)
await DeleteAsync(it => it.ObjectId == objectId && it.Category == category);//删除老的
@@ -147,7 +143,7 @@ public class Relationservice : DbRepository<SysRelation>, IRelationService
ExtJson = extJson
};
//事务
var result = await NewContent.UseTranAsync(async () =>
var result = await Context.AsTenant().UseTranAsync(async () =>
{
if (clear)
await DeleteAsync(it => it.ObjectId == objectId && it.Category == category);//删除老的

View File

@@ -27,18 +27,13 @@ namespace ThingsGateway.Admin.Application;
[Injection(Proxy = typeof(OperDispatchProxy))]
public class ButtonService : DbRepository<SysResource>, IButtonService
{
private readonly ILogger<ButtonService> _logger;
private readonly IResourceService _resourceService;
private readonly IRelationService _relationService;
private readonly IEventPublisher _eventPublisher;
public ButtonService(ILogger<ButtonService> logger, IResourceService resourceService, IRelationService relationService,
IEventPublisher eventPublisher)
public ButtonService(IResourceService resourceService, IRelationService relationService)
{
_logger = logger;
_resourceService = resourceService;
_relationService = relationService;
_eventPublisher = eventPublisher;
}
/// <inheritdoc/>
@@ -111,7 +106,7 @@ public class ButtonService : DbRepository<SysResource>, IButtonService
await CheckInput(input);//检查参数
var sysResource = input.Adapt<SysResource>();//实体转换
//事务
var result = await NewContent.UseTranAsync(async () =>
var result = await Context.AsTenant().UseTranAsync(async () =>
{
await UpdateAsync(sysResource);//更新按钮
});
@@ -164,7 +159,7 @@ public class ButtonService : DbRepository<SysResource>, IButtonService
#endregion
//事务
var result = await NewContent.UseTranAsync(async () =>
var result = await Context.AsTenant().UseTranAsync(async () =>
{
await DeleteByIdsAsync(ids.Cast<object>().ToArray());//删除按钮
if (relationList.Count > 0)

View File

@@ -24,13 +24,11 @@ namespace ThingsGateway.Admin.Application;
[Injection(Proxy = typeof(OperDispatchProxy))]
public class MenuService : DbRepository<SysResource>, IMenuService
{
private readonly ILogger<MenuService> _logger;
private readonly IResourceService _resourceService;
private readonly IRelationService _relationService;
public MenuService(ILogger<MenuService> logger, IResourceService resourceService, IRelationService relationService)
public MenuService(IResourceService resourceService, IRelationService relationService)
{
this._logger = logger;
this._resourceService = resourceService;
this._relationService = relationService;
}
@@ -116,7 +114,7 @@ public class MenuService : DbRepository<SysResource>, IMenuService
});
ids.AddRange(resourceIds);//添加到删除ID列表
//事务
var result = await NewContent.UseTranAsync(async () =>
var result = await Context.AsTenant().UseTranAsync(async () =>
{
await DeleteByIdsAsync(ids.Cast<object>().ToArray());//删除菜单和按钮
await Context.Deleteable<SysRelation>()//关系表删除对应SYS_ROLE_HAS_RESOURCE

View File

@@ -24,19 +24,17 @@ namespace ThingsGateway.Admin.Application;
[Injection(Proxy = typeof(OperDispatchProxy))]
public class RoleService : DbRepository<SysRole>, IRoleService
{
private readonly ILogger<RoleService> _logger;
private readonly ISimpleCacheService _simpleCacheService;
private readonly IRelationService _relationService;
private readonly IResourceService _resourceService;
private readonly IEventPublisher _eventPublisher;
public RoleService(ILogger<RoleService> logger,
public RoleService(
ISimpleCacheService simpleCacheService,
IRelationService relationService,
IResourceService resourceService,
IEventPublisher eventPublisher)
{
_logger = logger;
_simpleCacheService = simpleCacheService;
_relationService = relationService;
_resourceService = resourceService;
@@ -113,7 +111,7 @@ public class RoleService : DbRepository<SysRole>, IRoleService
{
var sysRole = input.Adapt<SysRole>();//实体转换
//事务
var result = await NewContent.UseTranAsync(async () =>
var result = await Context.AsTenant().UseTranAsync(async () =>
{
await UpdateAsync(sysRole);//更新角色
});

View File

@@ -28,7 +28,6 @@ namespace ThingsGateway.Admin.Application;
[Injection(Proxy = typeof(OperDispatchProxy))]
public class SysUserService : DbRepository<SysUser>, ISysUserService
{
private readonly ILogger<ILogger> _logger;
private readonly ISimpleCacheService _simpleCacheService;
private readonly IRelationService _relationService;
private readonly IResourceService _resourceService;
@@ -36,13 +35,12 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
private readonly IConfigService _configService;
private readonly IEventPublisher _eventPublisher;
public SysUserService(ILogger<ILogger> logger, ISimpleCacheService simpleCacheService,
public SysUserService(ISimpleCacheService simpleCacheService,
IRelationService relationService,
IResourceService resourceService, IEventPublisher eventPublisher,
IRoleService roleService,
IConfigService configService)
{
_logger = logger;
_simpleCacheService = simpleCacheService;
_relationService = relationService;
_resourceService = resourceService;

View File

@@ -16,7 +16,7 @@
else
{
<MRow NoGutters Style="height:100%">
<MCol Md=7 Sm=12>
<MCol Md=7 Cols=12>
<MSheet Elevation=1 Style="width:100%; height:100%;" Class="d-flex align-start flex-column mb-6">
<div class="d-flex align-center ml-12 mt-12">
<MAvatar Size="40" Color="teal">
@@ -34,8 +34,8 @@ else
</MCol>
<MCol Md=5 Sm=12 Align="AlignTypes.Center">
<MRow Md=6 Sm=12 Justify="JustifyTypes.Center" Align="AlignTypes.Center">
<MCol Md=5 Cols=12 Align="AlignTypes.Center">
<MRow Md=6 Cols=12 Justify="JustifyTypes.Center" Align="AlignTypes.Center">
<MCard Class="px-16 py-12" @onkeydown=Enter>
@GetLoginCore()
</MCard>

View File

@@ -20,7 +20,22 @@
<CascadingValue Value="@AppService.Dark" Name="Dark">
<MNavigationDrawer Color="barcolor" @bind-Value="_drawerOpen" App Width="200">
<Logo Height="AppService.LogoHeight" />
@if (!IsMobile)
{
<Logo Height="AppService.LogoHeight" />
}
else
{
<MRow>
<MSpacer />
@* <ThemeToggle></ThemeToggle> *@
<AppTooltipButton OnClick=ShowAbout LoadingEnable=false
Icon="mdi-information-outline" Path="about">
</AppTooltipButton>
<UserMenu></UserMenu>
</MRow>
}
<AppList ClassString="overflow-y-auto" Routable
StyleString=@($"height: calc(100vh - {AppService.LogoHeight}px);")
Items="UserResoures.UserNavItems.Where(a=>a.Hidden==false).ToList()" />
@@ -31,12 +46,12 @@
<AppTooltipButton Class="mr-0" Icon="mdi-menu" Style="margin-left:-12px;" Path="Menu" LoadingEnable=false OnClick=@(() => _drawerOpen = !_drawerOpen)>
</AppTooltipButton>
<Breadcrumb SysResources="UserResoures.UserNavItems" />
<MSpacer />
@if (!IsMobile)
{
<Breadcrumb SysResources="UserResoures.UserNavItems" />
<MSpacer />
@* <ThemeToggle></ThemeToggle> *@
<AppTooltipButton OnClick=ShowAbout LoadingEnable=false
Icon="mdi-information-outline" Path="about">
@@ -51,6 +66,9 @@
else
{
<Logo Height="AppService.LogoHeight"></Logo>
<AppTooltipButton OnClick=HandleSettingsClick LoadingEnable=false
Icon="mdi-shape-outline" Path="theme">
</AppTooltipButton>
}

View File

@@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Masa.Blazor.SomethingSkia" Version="1.3.2" />
<PackageReference Include="Masa.Blazor.SomethingSkia" Version="1.3.4" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.25" />

View File

@@ -2,14 +2,22 @@
<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.5" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.1" />
<PackageReference Include="MySqlConnector" Version="2.3.5" />
<PackageReference Include="Npgsql" Version="8.0.1" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="3.21.130" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="SqlSugarCore.Dm" Version="1.3.0" />
<PackageReference Include="SqlSugarCore.Kdbndp" Version="7.4.0" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.137" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
<PackageReference Include="System.Text.Json" Version="8.0.1" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.1" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.137" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ThingsGateway.Cache\ThingsGateway.Cache.csproj" />
</ItemGroup>

View File

@@ -2,9 +2,9 @@
<Import Project="$(SolutionDir)PackNuget.props" />
<ItemGroup>
<PackageReference Include="Furion.Pure" Version="4.9.1.24" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.1.24" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.1.24" />
<PackageReference Include="Furion.Pure" Version="4.9.1.28" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.1.28" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.1.28" />
<PackageReference Include="NewLife.Redis" Version="5.6.2024.105" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
<PackageReference Include="LiteDB" Version="5.0.17" />

View File

@@ -362,8 +362,8 @@ public class BlazorAppService : IAsyncDisposable
public async Task InitTabAsync()
{
var isPageTab = await LocalStorage.GetItemAsync<bool>("masablazor@isPageTab");
IsPageTab = isPageTab;
var isPageTab = await LocalStorage.GetItemAsync<bool?>("masablazor@isPageTab");
IsPageTab = isPageTab ?? true;
}
#endregion /

View File

@@ -2,7 +2,7 @@
<Import Project="$(SolutionDir)PackNuget.props" />
<ItemGroup>
<PackageReference Include="Masa.Blazor" Version="1.3.2" />
<PackageReference Include="Masa.Blazor" Version="1.3.4" />
<PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup>

View File

@@ -3,7 +3,7 @@
<ItemGroup>
<PackageReference Include="NewLife.Core" Version="10.6.2024.101" />
<PackageReference Include="NewLife.Core" Version="10.7.2024.202" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

View File

@@ -8,36 +8,18 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<OutputPath>$(SolutionDir)bin\$(Configuration)\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Content Include="favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="6.0.25" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="7.0.14" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ThingsGateway.Demo.Rcl\ThingsGateway.Demo.Rcl.csproj" />
<ProjectReference Include="..\ThingsGateway.Demo.Rcl\ThingsGateway.Demo.Rcl.csproj" />
<PackageReference Include="Photino.NET" Version="2.6.0" />
<PackageReference Include="Photino.Blazor" Version="2.7.0" />

View File

@@ -157,7 +157,8 @@ public partial class AdapterDebugPage : AdapterDebugBase
}
else
{
_ = Task.Run(() =>
await Task.Delay(1000);
await Task.Factory.StartNew(() =>
{
var result = TextFileReader.LastLog(files.FirstOrDefault().FullName, 0);
if (result.IsSuccess)
@@ -169,7 +170,6 @@ public partial class AdapterDebugPage : AdapterDebugBase
Messages = new List<(int, string)>();
}
});
await Task.Delay(1000);
}
}
}

View File

@@ -11,15 +11,15 @@
<MContainer @onkeydown=Enter>
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
<MCol Md=12 Sm=12>
<MCol Md=12 Cols=12>
<MSubheader Style="max-height:24px" Class="font-weight-black text-subtitle-1">
@AppService.I18n.T("基础属性")
</MSubheader>
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MTextField Dense Style="max-width:300px" Outlined HideDetails="@("auto")" Color="primary" @bind-Value=@ChannelData.Name Label="@(ChannelData.Description(x => x.Name))" />
</MCol>
<MCol Md=9 Sm=12>
<MCol Md=9 Cols=12>
<MSelect Items=@(typeof(ChannelTypeEnum).GetEnumList()) Style="max-width:300px;"
@bind-Value=@ChannelData.ChannelType Label=@(ChannelData.Description(x => x.ChannelType))
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
@@ -39,39 +39,39 @@
}
<MRow Class="mt-5" Justify="JustifyTypes.Start" Align="AlignTypes.Center">
<MCol Md=12 Sm=12>
<MCol Md=12 Cols=12>
<MSubheader Style="max-height:24px" Class="font-weight-black text-subtitle-1">
@AppService.I18n.T("通道属性")
</MSubheader>
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MTextField Style="max-width:300px" Disabled=@(!isTcpClient&&!isUdp) Dense Outlined HideDetails="@("auto")"
Label=@AppService.I18n.T("RemoteUrl") @bind-Value=@ChannelData.RemoteUrl />
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MTextField Style="max-width:300px" Disabled=@(!isTcpClient&&!isTcpService&&!isUdp) Dense Outlined HideDetails="@("auto")"
Label=@AppService.I18n.T("BindUrl") @bind-Value=@ChannelData.BindUrl />
</MCol>
</MRow>
<MRow Class="mt-5" Justify="JustifyTypes.Start" Align="AlignTypes.Center">
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MTextField Style="max-width:300px" Disabled=!isSerial Dense Outlined HideDetails="@("auto")"
Label=@AppService.I18n.T("PortName") @bind-Value=@ChannelData.PortName />
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MTextField Type="number" Style="max-width:300px" Disabled=!isSerial Dense Outlined HideDetails="@("auto")"
Label=@AppService.I18n.T("BaudRate") @bind-Value=@ChannelData.BaudRate />
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MTextField Style="max-width:300px" Disabled=!isSerial Dense Outlined HideDetails="@("auto")"
Type="number" Label=@AppService.I18n.T("DataBits") @bind-Value=@ChannelData.DataBits />
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MSelect Style="max-width:300px" Disabled=!isSerial Dense Outlined HideDetails="@("auto")"
Label=@AppService.I18n.T("Parity") @bind-Value=@ChannelData.Parity
Items=@(typeof(Parity).GetEnumList())
@@ -81,7 +81,7 @@
</MSelect>
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MSelect Style="max-width:300px" Disabled=!isSerial Dense Outlined HideDetails="@("auto")"
Label=@AppService.I18n.T("StopBits") @bind-Value=@ChannelData.StopBits
Items=@(typeof(StopBits).GetEnumList())
@@ -91,7 +91,7 @@
</MSelect>
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MSelect Class="" Items=@(new List<bool>(){true,false})
Label=@AppService.I18n.T("DtrEnable") @bind-Value=@ChannelData.DtrEnable
Clearable Style="max-width:300px" Disabled=!isSerial
@@ -102,7 +102,7 @@
Outlined></MSelect>
</MCol>
<MCol Md=3 Sm=12>
<MCol Md=3 Cols=12>
<MSelect Class="" Items=@(new List<bool>(){true,false})
Label=@AppService.I18n.T("RtsEnable") @bind-Value=@ChannelData.RtsEnable
Clearable Style="max-width:300px" Disabled=!isSerial

View File

@@ -58,6 +58,164 @@
</MCard>
}
<AdapterDebugPage LogPath=@LogPath @ref=AdapterDebugPage Height=@($"calc(100vh - {BlazorAppService.DefaultHeight+400}px)")></AdapterDebugPage>
<AdapterDebugPage LogPath=@LogPath @ref=AdapterDebugPage Height=@($"calc(100vh - {BlazorAppService.DefaultHeight+400}px)") ShowDefaultOtherContent=false>
<OtherContent>
<MSubheader>
广播校时
</MSubheader>
<MContainer>
<MRow Dense Align="AlignTypes.Center">
<PDateDigitalClockPicker @bind-Value="dateTime" TimeFormat="TimeFormat.Hr24" ViewType="DateTimePickerViewType.Auto" Context="dateContext">
<ActivatorContent>
<MTextField @bind-Value="dateTime" Style="max-width:200px;" Class="ma-1" Outlined HideDetails=@("auto") Dense Clearable Readonly @attributes="@dateContext.Attrs">
</MTextField>
</ActivatorContent>
</PDateDigitalClockPicker>
<MButton Class="ma-1" Color="primary" OnClick="()=>_plc.BroadcastTime(dateTime)">
校时
</MButton>
</MRow>
</MContainer>
<MSubheader>
冻结
</MSubheader>
<MContainer>
<MRow Dense Align="AlignTypes.Center">
<PDateDigitalClockPicker @bind-Value="dateTime" TimeFormat="TimeFormat.Hr24" ViewType="DateTimePickerViewType.Auto" Context="dateContext">
<ActivatorContent>
<MTextField @bind-Value="dateTime" Style="max-width:200px;" Class="ma-1" Outlined HideDetails=@("auto") Dense Clearable Readonly @attributes="@dateContext.Attrs">
</MTextField>
</ActivatorContent>
</PDateDigitalClockPicker>
<MButton Class="ma-1" Color="primary" OnClick="()=>_plc.FreezeAsync(dateTime)">
冻结
</MButton>
</MRow>
</MContainer>
<MSubheader>
读取通信地址
</MSubheader>
<MContainer>
<MRow Dense Align="AlignTypes.Center">
<MButton Class="ma-1" Color="primary" OnClick="ReadDeviceStationAsync">
读取通信地址
</MButton>
</MRow>
</MContainer>
<MSubheader>
修改波特率
</MSubheader>
<MContainer>
<MRow Dense Align="AlignTypes.Center">
<MTextField Class="ma-1" Outlined Style="max-width:200px" Label=波特率 Clearable Dense HideDetails="@("auto")" @bind-Value=baudRate></MTextField>
<MButton Class="ma-1" Color="primary" OnClick="WriteBaudRateAsync">
修改波特率
</MButton>
</MRow>
</MContainer>
<MSubheader>
更新通信地址
</MSubheader>
<MContainer>
<MRow Dense Align="AlignTypes.Center">
<MTextField Class="ma-1" Outlined Style="max-width:200px" Label=通信地址 Clearable Dense HideDetails="@("auto")" @bind-Value=station></MTextField>
<MButton Class="ma-1" Color="primary" OnClick="WriteDeviceStationAsync">
更新通信地址
</MButton>
</MRow>
</MContainer>
<MSubheader>
修改密码
</MSubheader>
<MContainer>
<MRow Dense Align="AlignTypes.Center">
<MTextField Class="ma-1" Outlined Style="max-width:200px" Label=级别(0-9) Clearable Dense HideDetails="@("auto")" @bind-Value=level></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:200px" Label=旧密码 Clearable Dense HideDetails="@("auto")" @bind-Value=oldPassword></MTextField>
<MTextField Class="ma-1" Outlined Style="max-width:200px" Label=新密码 Clearable Dense HideDetails="@("auto")" @bind-Value=newPassword></MTextField>
<MButton Class="ma-1" Color="primary" OnClick="WritePasswordAsync">
修改密码
</MButton>
</MRow>
</MContainer>
</OtherContent>
</AdapterDebugPage>
@code {
private byte level;
private string oldPassword;
private string newPassword;
private async Task WritePasswordAsync()
{
var result = await _plc.WritePasswordAsync(level, oldPassword, newPassword);
if (result.IsSuccess)
{
_plc.Logger.LogInformation((result.ErrorMessage ?? "SUCCESS"));
}
else
{
_plc.Logger.LogWarning(result.Exception,result.ErrorMessage);
}
}
private string station;
private async Task WriteDeviceStationAsync()
{
var result = await _plc.WriteDeviceStationAsync(station);
if (result.IsSuccess)
{
_plc.Logger.LogInformation((result.ErrorMessage ?? "SUCCESS"));
}
else
{
_plc.Logger.LogWarning(result.Exception,result.ErrorMessage);
}
}
private int baudRate;
private async Task WriteBaudRateAsync()
{
var result = await _plc.WriteBaudRateAsync(baudRate);
if (result.IsSuccess)
{
_plc.Logger.LogInformation((result.ErrorMessage??"SUCCESS"));
}
else
{
_plc.Logger.LogWarning(result.Exception,result.ErrorMessage);
}
}
private async Task ReadDeviceStationAsync()
{
var result = await _plc.ReadDeviceStationAsync();
if (result.IsSuccess)
{
_plc.Logger.LogInformation((result.ErrorMessage??"SUCCESS"));
}
else
{
_plc.Logger.LogWarning(result.Exception,result.ErrorMessage);
}
}
private DateTime dateTime;
}

View File

@@ -76,7 +76,7 @@ namespace ThingsGateway.Demo
{
_plc = new ThingsGateway.Foundation.Dlt645.Dlt645_2007Master(channelData.Channel);
AdapterDebugPage.Plc = _plc;
LogPath = channelData.Name.GetDebugLogPath();
LogPath = channelData.Id.GetDebugLogPath();
}
}
}

View File

@@ -76,7 +76,7 @@ namespace ThingsGateway.Demo
{
_plc = new ThingsGateway.Foundation.Modbus.ModbusMaster(channelData.Channel);
AdapterDebugPage.Plc = _plc;
LogPath = channelData.Name.GetDebugLogPath();
LogPath = channelData.Id.GetDebugLogPath();
}
}
}

View File

@@ -71,7 +71,7 @@ namespace ThingsGateway.Demo
{
_plc = new ThingsGateway.Foundation.Modbus.ModbusSlave(channelData.Channel);
AdapterDebugPage.Plc = _plc;
LogPath = channelData.Name.GetDebugLogPath();
LogPath = channelData.Id.GetDebugLogPath();
}
}
}

View File

@@ -9,7 +9,7 @@
<OpcDaMasterConnectPage @ref=opcDaMasterConnectPage OnConnectClick=OnConnectClick></OpcDaMasterConnectPage>
<AdapterDebugPage LogPath=@(opcDaMasterConnectPage?.Plc?.GetHashCode().ToString().GetDebugLogPath()) @ref=adapterDebugPage Height=@($"calc(100vh - {BlazorAppService.DefaultHeight+400}px)") ShowDefaultOtherContent=false ShowDefaultReadWriteContent=false>
<AdapterDebugPage LogPath=@(opcDaMasterConnectPage?.Plc?.GetHashCode().ToLong().GetDebugLogPath()) @ref=adapterDebugPage Height=@($"calc(100vh - {BlazorAppService.DefaultHeight+400}px)") ShowDefaultOtherContent=false ShowDefaultReadWriteContent=false>
<ReadWriteContent>

View File

@@ -46,7 +46,7 @@ public partial class OpcDaMasterConnectPage : IDisposable
Plc.Init(config);
LogMessage = new TouchSocket.Core.LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Trace };
var logger = TextFileLogger.Create(Plc.GetHashCode().ToString().GetDebugLogPath());
var logger = TextFileLogger.Create(Plc.GetHashCode().ToLong().GetDebugLogPath());
logger.LogLevel = LogLevel.Trace;
LogMessage.AddLogger(logger);

View File

@@ -9,7 +9,7 @@
<OpcUaMasterConnectPage @ref=opcUaMasterConnectPage OnConnectClick=OnConnectClick></OpcUaMasterConnectPage>
<AdapterDebugPage LogPath=@(opcUaMasterConnectPage?.Plc?.GetHashCode().ToString().GetDebugLogPath()) @ref=adapterDebugPage Height=@($"calc(100vh - {BlazorAppService.DefaultHeight+400}px)") ShowDefaultOtherContent=false ShowDefaultReadWriteContent=false>
<AdapterDebugPage LogPath=@(opcUaMasterConnectPage?.Plc?.GetHashCode().ToLong().GetDebugLogPath()) @ref=adapterDebugPage Height=@($"calc(100vh - {BlazorAppService.DefaultHeight+400}px)") ShowDefaultOtherContent=false ShowDefaultReadWriteContent=false>
<ReadWriteContent>

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