|
|
@@ -28,6 +28,7 @@
|
|
|
2. 数据结构
|
|
|
3. 接口
|
|
|
4. 枚举
|
|
|
+5. 模型工具
|
|
|
|
|
|
## 扩展工具
|
|
|
1. [ YSAI.Rpc ]基于DotNetty实现的RPC(远程过程调用) 支持一对多,支持身份验证
|
|
|
@@ -48,7 +49,7 @@
|
|
|
10. Mewtocol(松下) [Tcp、Serial]
|
|
|
|
|
|
```sharp
|
|
|
-namespace YSAI.Core.@interface
|
|
|
+namespace YSAI.Model.@interface
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 数采接口
|
|
|
@@ -66,7 +67,7 @@ namespace YSAI.Core.@interface
|
|
|
5. NetMQ [Publish、Subscribe]
|
|
|
|
|
|
```sharp
|
|
|
-namespace YSAI.Core.@interface
|
|
|
+namespace YSAI.Model.@interface
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 转发接口
|
|
|
@@ -76,229 +77,230 @@ namespace YSAI.Core.@interface
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-## 应用
|
|
|
-```sharp
|
|
|
-
|
|
|
-1.上 NUGET 搜索 YSAI
|
|
|
-2.安装对应的协议包
|
|
|
-3.应用代码如下
|
|
|
-4.协议包内还有内部公共方法,请自行研究使用
|
|
|
-
|
|
|
-------------------------------------------------------
|
|
|
+## 协议服务端(用于数据模拟)
|
|
|
+1. Mqtt服务端
|
|
|
+2. MqttWebSocket服务端
|
|
|
+3. OpcUa服务端
|
|
|
+4. Socket服务端
|
|
|
+5. WebSocket服务端
|
|
|
|
|
|
+## 创建实例合集
|
|
|
+```sharp
|
|
|
//实例创建的几种方式
|
|
|
-
|
|
|
-//第一种方式
|
|
|
-BeckhoffOperate beckhoffOperate1 = new BeckhoffOperate();
|
|
|
-
|
|
|
-//第二种方式(单例模式)
|
|
|
-BeckhoffOperate? beckhoffOperate2 = new BeckhoffOperate().CreateInstance(new BeckhoffData.Basics()).GetRData<BeckhoffOperate>();
|
|
|
-
|
|
|
-//第三种方式(单例模式)
|
|
|
-BeckhoffOperate beckhoffOperate3 = BeckhoffOperate.Instance(new BeckhoffData.Basics());
|
|
|
-
|
|
|
-//第四种方式
|
|
|
-IDaq daq1 = new BeckhoffOperate(new BeckhoffData.Basics());
|
|
|
-
|
|
|
-//第五种方式
|
|
|
-IDaq daq2 = BeckhoffOperate.Instance(new BeckhoffData.Basics());
|
|
|
-
|
|
|
-//第六种方式
|
|
|
-using (BeckhoffOperate beckhoffOperate4 = new BeckhoffOperate())
|
|
|
+//以OPCUA 采集协议为例
|
|
|
+using YSAI.Model.@interface;
|
|
|
+using YSAI.Opc.ua.client;
|
|
|
+
|
|
|
+OpcUaClientOperate? operate = null;
|
|
|
+IDaq? daq = null;
|
|
|
+
|
|
|
+//无参实例
|
|
|
+operate = new OpcUaClientOperate();
|
|
|
+//无参实例调函数创建实例,与无参实例配合使用
|
|
|
+operate = new OpcUaClientOperate().CreateInstance(new OpcUaClientData.Basics()).GetRData<OpcUaClientOperate>();
|
|
|
+//有参实例
|
|
|
+operate = new OpcUaClientOperate(new OpcUaClientData.Basics());
|
|
|
+//有参单例
|
|
|
+operate = OpcUaClientOperate.Instance(new OpcUaClientData.Basics());
|
|
|
+//接口 - 无参实例
|
|
|
+daq = new OpcUaClientOperate();
|
|
|
+//接口 - 无参实例调函数创建实例,与无参实例配合使用
|
|
|
+daq = new OpcUaClientOperate().CreateInstance(new OpcUaClientData.Basics()).GetRData<OpcUaClientOperate>();
|
|
|
+//接口 - 有参实例
|
|
|
+daq = new OpcUaClientOperate(new OpcUaClientData.Basics());
|
|
|
+//接口 - 有参单例
|
|
|
+daq = OpcUaClientOperate.Instance(new OpcUaClientData.Basics());
|
|
|
+
|
|
|
+using (operate)
|
|
|
{
|
|
|
//使用完直接释放
|
|
|
}
|
|
|
|
|
|
-//第七种方式
|
|
|
-using (BeckhoffOperate beckhoffOperate5 = BeckhoffOperate.Instance(new BeckhoffData.Basics()))
|
|
|
-{
|
|
|
- //使用完直接释放这个单例
|
|
|
-}
|
|
|
-
|
|
|
-//第八种方式
|
|
|
-using (BeckhoffOperate? beckhoffOperate6 = new BeckhoffOperate().CreateInstance(new BeckhoffData.Basics()).GetRData<BeckhoffOperate>())
|
|
|
-{
|
|
|
- //使用完直接释放这个单例
|
|
|
-}
|
|
|
-
|
|
|
-//第九种方式
|
|
|
-using (IDaq daq3 = new BeckhoffOperate(new BeckhoffData.Basics()))
|
|
|
+using (daq)
|
|
|
{
|
|
|
//使用完直接释放
|
|
|
}
|
|
|
|
|
|
-//第十种方式
|
|
|
-using (IDaq daq4 = BeckhoffOperate.Instance(new BeckhoffData.Basics()))
|
|
|
-{
|
|
|
- //使用完直接释放这个单例
|
|
|
-}
|
|
|
-
|
|
|
-//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
|
|
-//第一种的应用场景是获取库参数信息时当这个对象已经实例化了,但是实际功能无法使用,就可以直接使用 CreateInstance 创建一个单例模式
|
|
|
-//先获取参数
|
|
|
-beckhoffOperate1.GetParam();
|
|
|
-//在生成单例后赋值,这样当前实例就已经可以使用所有功能,并且是单例的存在
|
|
|
-beckhoffOperate1 = beckhoffOperate1.CreateInstance(new BeckhoffData.Basics()).GetRData<BeckhoffOperate>();
|
|
|
-//第二种与第三种就是直接创建单例模式,但第二种是为了在反射的情况下使用单例模式,第二种也是为第一种情况而产生
|
|
|
+```
|
|
|
|
|
|
-------------------------------------------------------
|
|
|
+## 采集应用
|
|
|
+1. 上 “NUGET” 搜索
|
|
|
+2. 安装对应的协议包
|
|
|
+3. 应用代码如下
|
|
|
+4. 协议包内还有内部公共方法,请自行研究使用
|
|
|
|
|
|
+```sharp
|
|
|
//采集协议
|
|
|
-using (类 operate = new 类(new 类数据.Basics
|
|
|
+//以OPCUA 采集协议为例
|
|
|
+using System.Collections.Concurrent;
|
|
|
+using YSAI.Core.script;
|
|
|
+using YSAI.Log;
|
|
|
+using YSAI.Model.data;
|
|
|
+using YSAI.Model.@enum;
|
|
|
+using YSAI.Opc.ua.client;
|
|
|
+using YSAI.Unility;
|
|
|
+
|
|
|
+using (OpcUaClientOperate operate = new OpcUaClientOperate(new OpcUaClientData.Basics
|
|
|
{
|
|
|
-
|
|
|
- //采集对象参数
|
|
|
-
|
|
|
+ ServerUrl = "opc.tcp://127.0.0.1:6688",
|
|
|
+ UserName = "user",
|
|
|
+ Password = "password",
|
|
|
}))
|
|
|
{
|
|
|
- //打开
|
|
|
- OperateResult result = operate.On();
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
-
|
|
|
//点位地址
|
|
|
Address address = new Address();
|
|
|
address.SN = Guid.NewGuid().ToString();
|
|
|
address.CreationTime = DateTime.Now.ToLocalTime();
|
|
|
address.AddressArray = new List<AddressDetails>
|
|
|
{
|
|
|
- new AddressDetails()//S7点位地址
|
|
|
- {
|
|
|
- SN=$"{Guid.NewGuid().ToNString()} - Factory",
|
|
|
- AddressName = "DB71.DBD4",
|
|
|
- AddressDataType = YSAI.Core.@enum.DataType.Float
|
|
|
- },
|
|
|
- new AddressDetails()//OpcUa点位地址
|
|
|
- {
|
|
|
- SN=$"{Guid.NewGuid().ToNString()} - Factory",
|
|
|
- AddressName = "ns=2;s=Scalar_Simulation_Float",
|
|
|
- AddressDataType = YSAI.Core.@enum.DataType.Float
|
|
|
- },
|
|
|
- new AddressDetails()//OpcDa点位地址
|
|
|
+ new AddressDetails() //地址详情参数介绍
|
|
|
{
|
|
|
- SN=$"{Guid.NewGuid().ToNString()} - Factory",
|
|
|
- AddressName = "a.a.a",
|
|
|
- AddressDataType = YSAI.Core.@enum.DataType.Float
|
|
|
- },
|
|
|
- new AddressDetails()//Modbus点位地址
|
|
|
- {
|
|
|
- SN=$"{Guid.NewGuid().ToNString()} - Factory",
|
|
|
- AddressName = "0,2",
|
|
|
- AddressDataType = YSAI.Core.@enum.DataType.Float
|
|
|
- },
|
|
|
- new AddressDetails() //DB点位地址
|
|
|
- {
|
|
|
- SN=$"{Guid.NewGuid().ToNString()} - Factory",
|
|
|
- AddressName = "数据库采集",
|
|
|
- AddressDataType = YSAI.Core.@enum.DataType.String,
|
|
|
- AddressExtendParam=new DBData.ExtendParam.Read()
|
|
|
+ SN=$"", //可以理解成唯一标识符(可以存机台号、组名、车间、厂)
|
|
|
+ AddressAnotherName="", //地址别名
|
|
|
+ AddressDataType=DataType.String, //数据类型
|
|
|
+ AddressDescribe="", //地址描述
|
|
|
+ AddressExtendParam=new object(), //扩展数据
|
|
|
+ AddressName="", //脚本地址
|
|
|
+ AddressPropertyName="", //地址别名
|
|
|
+ AddressType=AddressType.Reality, //地址类型
|
|
|
+ IsEnable=true, //是否启用
|
|
|
+ AddressRelayParam=new AddressRelay //转发参数
|
|
|
{
|
|
|
- Sql = @"SELECT A,B,C,D FORM TABLE ORDER BY YPBH DESC LIMIT 0,1",
|
|
|
- ColumnName = new List<string>() { "A", "B", "C", "D"}
|
|
|
- }
|
|
|
- },
|
|
|
- new AddressDetails() //OpcDaHttp点位地址
|
|
|
- {
|
|
|
- SN=$"{Guid.NewGuid().ToNString()} - Factory",
|
|
|
- AddressName = "a.a.a",
|
|
|
- AddressDataType = YSAI.Core.@enum.DataType.String,
|
|
|
- AddressExtendParam=new OpcDaHttpData.ExtendParam.Read()
|
|
|
+ ISns = new List<string> { "ISN1", "ISN2" }, //实例SN
|
|
|
+ Topic = $"topic", //主题
|
|
|
+ ContentFormat="Value:{0}" //内容格式
|
|
|
+ },
|
|
|
+ AddressParseParam=new AddressParse //脚本解析实例
|
|
|
{
|
|
|
- GroupName="YF75ZDHPJ",
|
|
|
- ReadInterval=1000,
|
|
|
- ServerName="OPC.SimaticNET.1"
|
|
|
- }
|
|
|
- },
|
|
|
- new AddressDetails() //地址详情参数介绍
|
|
|
- {
|
|
|
- SN=$"A88", //可以理解成唯一标识符(可以存机台号、组名、车间、厂)
|
|
|
- AddressAnotherName="A_Name", //地址别名
|
|
|
- AddressDataType=YSAI.Core.@enum.DataType.Float, //数据类型
|
|
|
- AddressDescribe="NameDescribe", //地址描述
|
|
|
- AddressExtendParam=new object(), //扩展数据
|
|
|
- AddressName="Name", //地址名称
|
|
|
- //AddressParseParam=new AddressParse //地址解析参数
|
|
|
- //{
|
|
|
- // ParseType=ParseType.ScriptAnalysis, //解析类型
|
|
|
- // Script=new YSAI.Core.script.ScriptData.Basics //脚本解析数据
|
|
|
+ ScriptParam=new ScriptData.Basics //脚本解析基础数据
|
|
|
+ {
|
|
|
+ ScriptCode = @"function Convert(addressname,value) { return '【这是调用脚本解析】传入的地址是:'+ addressname + '----传入的参数是:' + value; }", //脚本代码
|
|
|
+ ScriptFunction = "Convert", //脚本入口
|
|
|
+ ScriptType = ScriptData.ScriptType.JavaScript //脚本类型
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //AddressParseParam = new AddressParse //反射解析
|
|
|
+ //{
|
|
|
+ // ReflectionParam = new object[] //反射解析的参数
|
|
|
// {
|
|
|
+ // new ReflectionData.Basics //反射解析基础数据
|
|
|
+ // {
|
|
|
+ // //反射解析的基础数据
|
|
|
+ // },
|
|
|
+ // "SN" //反射解析的SN
|
|
|
// }
|
|
|
- //},
|
|
|
- AddressParseParam=new AddressParse //地址解析参数
|
|
|
- {
|
|
|
- ParseType=ParseType.MethodAnalysis, //解析类型
|
|
|
- ReflectionSN="反射SN"
|
|
|
- },
|
|
|
- AddressPropertyName="Name1", //地址别名
|
|
|
- AddressType=AddressType.Reality, //地址类型
|
|
|
- IsEnable=true //是否启用
|
|
|
+ // },
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ #region 打开
|
|
|
+ OperateResult result = operate.On();
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 打开
|
|
|
+
|
|
|
+ #region 读取
|
|
|
//读取
|
|
|
result = operate.Read(address);
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 读取
|
|
|
|
|
|
- //订阅
|
|
|
+ #region 订阅
|
|
|
operate.OnEvent += delegate (object? sender, EventResult e)
|
|
|
- {
|
|
|
- LogHelper.Info(e.ToJson().JsonFormatting());
|
|
|
- };
|
|
|
+{
|
|
|
+ LogHelper.Info(e.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+};
|
|
|
result = operate.Subscribe(address);
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 订阅
|
|
|
|
|
|
- //写入
|
|
|
- ConcurrentDictionary<string, string> value = new ConcurrentDictionary<string, string>
|
|
|
+ #region 写入
|
|
|
+ ConcurrentDictionary<string, object> value = new ConcurrentDictionary<string, object>
|
|
|
{
|
|
|
- ["地址"] = "值"
|
|
|
+ ["地址"] = "string 值",
|
|
|
+ ["地址"] = (float)1.1f,
|
|
|
+ ["地址"] = (double)2.2d,
|
|
|
+ ["地址"] = (int)3,
|
|
|
+ ["地址"] = true
|
|
|
};
|
|
|
result = operate.Write(value);
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 写入
|
|
|
|
|
|
- //关闭
|
|
|
+ #region 关闭
|
|
|
result = operate.Off();
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 关闭
|
|
|
+
|
|
|
+ #region 获取状态
|
|
|
+ result = operate.GetStatus();
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 获取状态
|
|
|
+
|
|
|
+ #region 获取参数
|
|
|
+ result = operate.GetParam();
|
|
|
+ LogHelper.Info(result.GetRData<ParamStructure>().ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 获取参数
|
|
|
}
|
|
|
+````
|
|
|
|
|
|
-------------------------------------------------------
|
|
|
+## 转发应用
|
|
|
+1. 上 “NUGET” 搜索
|
|
|
+2. 安装对应的协议包
|
|
|
+3. 应用代码如下
|
|
|
+4. 协议包内还有内部公共方法,请自行研究使用
|
|
|
|
|
|
+```sharp
|
|
|
//转发协议
|
|
|
-using (类 operate = new 类(new 类数据.Basics
|
|
|
-{
|
|
|
-
|
|
|
- //转发对象参数
|
|
|
+//以MQTT为例
|
|
|
+using YSAI.Log;
|
|
|
+using YSAI.Model.data;
|
|
|
+using YSAI.Mqtt.client;
|
|
|
+using YSAI.Unility;
|
|
|
|
|
|
+using (MqttClientOperate operate = new MqttClientOperate(new MqttClientData.Basics
|
|
|
+{
|
|
|
+ Ip = "127.0.0.1",
|
|
|
+ Port = 11819,
|
|
|
+ UserName = "user",
|
|
|
+ Password = "password"
|
|
|
}))
|
|
|
{
|
|
|
- //打开
|
|
|
+ #region 打开
|
|
|
OperateResult result = operate.On();
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 打开
|
|
|
|
|
|
- //生产
|
|
|
+ #region 生产
|
|
|
result = operate.Produce("主题", "内容");
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 生产
|
|
|
|
|
|
- //消费
|
|
|
+ #region 消费
|
|
|
operate.OnEvent += delegate (object? sender, EventResult e)
|
|
|
{
|
|
|
- LogHelper.Info(e.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(e.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
};
|
|
|
result = operate.Subscribe("主题");
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 消费
|
|
|
|
|
|
- //关闭
|
|
|
+ #region 关闭
|
|
|
result = operate.Off();
|
|
|
- LogHelper.Info(result.ToJson().JsonFormatting());
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 关闭
|
|
|
+
|
|
|
+ #region 获取状态
|
|
|
+ result = operate.GetStatus();
|
|
|
+ LogHelper.Info(result.ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 获取状态
|
|
|
+
|
|
|
+ #region 获取参数
|
|
|
+ result = operate.GetParam();
|
|
|
+ LogHelper.Info(result.GetRData<ParamStructure>().ToJson().JsonFormatting()); //转成JSON.JSON格式化
|
|
|
+ #endregion 获取参数
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
-## 协议服务端(用于数据模拟)
|
|
|
-1. Mqtt服务端
|
|
|
-2. MqttWebSocket服务端
|
|
|
-3. OpcUa服务端
|
|
|
-4. Socket服务端
|
|
|
-5. WebSocket服务端
|
|
|
-
|
|
|
## 更新表
|
|
|
|
|
|
#### 2023-02-15
|
|
|
@@ -510,4 +512,6 @@ while(true)
|
|
|
3. OPCUA 新增当订阅的地址点没有在服务器创建订阅,则重新订阅
|
|
|
|
|
|
#### 2023-11-30
|
|
|
-1. 修改所有协议的函数开始返回的SN
|
|
|
+1. 修改所有协议的函数开始返回的SN
|
|
|
+2. 优化解析,当解析失败异常,则返回空数据,为了更好的判断数据质量
|
|
|
+3. OPCUA新增是否重连,重连间隔参数
|