Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f272fb0559 | ||
|
|
bd04e33586 | ||
|
|
b09b9752ca | ||
|
|
a810a48158 | ||
|
|
b4f5792aa8 | ||
|
|
fdf0330b4f | ||
|
|
ca73743082 | ||
|
|
df0cde2cfd | ||
|
|
5a8421e807 | ||
|
|
025ac95d81 | ||
|
|
71b5824fdc | ||
|
|
1a907c0be7 | ||
|
|
1635cabd32 | ||
|
|
27946a5b0f | ||
|
|
e141822fd0 | ||
|
|
6326828a02 | ||
|
|
96b5362491 | ||
|
|
8ab91a51bc | ||
|
|
35e7e7af18 | ||
|
|
0e248a7302 | ||
|
|
d5ce4d6600 | ||
|
|
2365bb5e87 | ||
|
|
2230216a7e | ||
|
|
54f896d25f | ||
|
|
e47d239caf | ||
|
|
ac259958d7 | ||
|
|
0505ad88a6 | ||
|
|
b323de3383 | ||
|
|
c0e023324b | ||
|
|
495806d5e3 | ||
|
|
3a9f745a2d | ||
|
|
7b15d114a3 | ||
|
|
6ac0f72169 | ||
|
|
ff68030231 | ||
|
|
d34361b6dd | ||
|
|
56c6ebe523 | ||
|
|
2c6d2e0eb4 | ||
|
|
8e64196a8f |
10
doc/build/404.html
vendored
10
doc/build/404.html
vendored
File diff suppressed because one or more lines are too long
1
doc/build/assets/js/151b844f.36a86744.js
vendored
Normal file
1
doc/build/assets/js/151b844f.36a86744.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
doc/build/assets/js/151b844f.e187f6e8.js
vendored
1
doc/build/assets/js/151b844f.e187f6e8.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
doc/build/assets/js/81eecd89.9597c29c.js
vendored
Normal file
1
doc/build/assets/js/81eecd89.9597c29c.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
doc/build/assets/js/81eecd89.a0fb557e.js
vendored
1
doc/build/assets/js/81eecd89.a0fb557e.js
vendored
File diff suppressed because one or more lines are too long
1
doc/build/assets/js/8bd707e2.2ab2561a.js
vendored
Normal file
1
doc/build/assets/js/8bd707e2.2ab2561a.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
doc/build/assets/js/8bd707e2.dba00460.js
vendored
1
doc/build/assets/js/8bd707e2.dba00460.js
vendored
@@ -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}}]);
|
||||
1
doc/build/assets/js/8d8968ad.0ae4c5c9.js
vendored
Normal file
1
doc/build/assets/js/8d8968ad.0ae4c5c9.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
doc/build/assets/js/8d8968ad.9b5283ec.js
vendored
1
doc/build/assets/js/8d8968ad.9b5283ec.js
vendored
@@ -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
1
doc/build/assets/js/be30e93d.3dda046a.js
vendored
1
doc/build/assets/js/be30e93d.3dda046a.js
vendored
@@ -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}}]);
|
||||
1
doc/build/assets/js/be30e93d.932062b7.js
vendored
Normal file
1
doc/build/assets/js/be30e93d.932062b7.js
vendored
Normal file
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/docs/1/index.html
vendored
10
doc/build/docs/1/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/100/index.html
vendored
10
doc/build/docs/100/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/1000/index.html
vendored
10
doc/build/docs/1000/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/10001/index.html
vendored
10
doc/build/docs/10001/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/1001/index.html
vendored
10
doc/build/docs/1001/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/1002/index.html
vendored
10
doc/build/docs/1002/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/101/index.html
vendored
10
doc/build/docs/101/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/102/index.html
vendored
10
doc/build/docs/102/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/103/index.html
vendored
10
doc/build/docs/103/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/104/index.html
vendored
10
doc/build/docs/104/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/105/index.html
vendored
10
doc/build/docs/105/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/106/index.html
vendored
10
doc/build/docs/106/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/2/index.html
vendored
10
doc/build/docs/2/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/200/index.html
vendored
10
doc/build/docs/200/index.html
vendored
File diff suppressed because one or more lines are too long
12
doc/build/docs/20001/index.html
vendored
12
doc/build/docs/20001/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/20002/index.html
vendored
10
doc/build/docs/20002/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/20003/index.html
vendored
10
doc/build/docs/20003/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/20004/index.html
vendored
10
doc/build/docs/20004/index.html
vendored
File diff suppressed because one or more lines are too long
12
doc/build/docs/20005/index.html
vendored
12
doc/build/docs/20005/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/201/index.html
vendored
10
doc/build/docs/201/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/202/index.html
vendored
10
doc/build/docs/202/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/203/index.html
vendored
10
doc/build/docs/203/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/204/index.html
vendored
10
doc/build/docs/204/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/205/index.html
vendored
10
doc/build/docs/205/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/206/index.html
vendored
10
doc/build/docs/206/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/301/index.html
vendored
10
doc/build/docs/301/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/302/index.html
vendored
10
doc/build/docs/302/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/303/index.html
vendored
10
doc/build/docs/303/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/304/index.html
vendored
10
doc/build/docs/304/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/305/index.html
vendored
10
doc/build/docs/305/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/306/index.html
vendored
10
doc/build/docs/306/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/307/index.html
vendored
10
doc/build/docs/307/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/308/index.html
vendored
10
doc/build/docs/308/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/309/index.html
vendored
10
doc/build/docs/309/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/400/index.html
vendored
10
doc/build/docs/400/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/401/index.html
vendored
10
doc/build/docs/401/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/402/index.html
vendored
10
doc/build/docs/402/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/403/index.html
vendored
10
doc/build/docs/403/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/404/index.html
vendored
10
doc/build/docs/404/index.html
vendored
File diff suppressed because one or more lines are too long
12
doc/build/docs/501/index.html
vendored
12
doc/build/docs/501/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/502/index.html
vendored
10
doc/build/docs/502/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/601/index.html
vendored
10
doc/build/docs/601/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/602/index.html
vendored
10
doc/build/docs/602/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/index.html
vendored
10
doc/build/docs/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/docs/upgrade/index.html
vendored
10
doc/build/docs/upgrade/index.html
vendored
File diff suppressed because one or more lines are too long
10
doc/build/index.html
vendored
10
doc/build/index.html
vendored
File diff suppressed because one or more lines are too long
2
doc/build/search-index.json
vendored
2
doc/build/search-index.json
vendored
File diff suppressed because one or more lines are too long
10
doc/build/search/index.html
vendored
10
doc/build/search/index.html
vendored
File diff suppressed because one or more lines are too long
@@ -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格式 |
|
||||
|
||||
|
||||
@@ -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从站
|
||||
|
||||
|
||||
@@ -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;
|
||||
```
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
@@ -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外是其他方法 |
|
||||
|
||||
@@ -42,7 +42,11 @@ module.exports = {
|
||||
position: "left",
|
||||
to: "docs/upgrade"
|
||||
},
|
||||
|
||||
{
|
||||
label: "演示",
|
||||
position: "right",
|
||||
href: "http://120.24.62.140:5000",
|
||||
},
|
||||
{
|
||||
label: "源码",
|
||||
position: "right",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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/>
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace ThingsGateway.Admin.Application;
|
||||
/// <summary>
|
||||
/// 会话管理服务
|
||||
/// </summary>
|
||||
public interface ISessionService : ISugarService, ITransient
|
||||
public interface ISessionService : ISugarService, IScoped
|
||||
{
|
||||
/// <summary>
|
||||
/// 会话统计
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);//删除老的
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);//更新角色
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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 标签页/面包屑
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user