阐述
- 所有协议公共函数支持同步异步
- 所有协议读取写入协议参数统一
- 全部都是统一入参出参
- 支持多点转发,多点解析
- 支持快速对接,与配置
- 支持虚拟点位
- 所有采集协议支持订阅模式
- 采集与转发协议接口统一
- 事件结果统一
YSAI.Core
- 处理
- 反射
- 转发
- 脚本
- 订阅
- 订阅
- 虚拟地址
- TCP
- UDP
- HTTP
- WS
- 串口
YSAI.Model
- 特性
- 数据结构
- 接口
- 枚举
扩展工具
- [ YSAI.Rpc ]基于DotNetty实现的RPC(远程过程调用) 支持一对多,支持身份验证
- [ YSAI.Redis ]非关系型数据库,用于数据快速出站入站存储
- [ YSAI.Log ]Verbose(详细信息)、Debug(调试)、Info(信息)、Warning(警告)、Error(异常或错误)、Fatal(致命错误或异常)
- [ YSAI.Unility ]公共快捷方便方法集合 (字节、枚举、文件、字符串、验证、比对、转换、反射、扩展、Json、Xml、Ftp、System ...)
采集协议
- Opc(工业标准通信协议) [UA、DA、DAHttp]
- Can(工业标准通信协议)
- DB(数据库) [SqlServer、MySql、Oracle、SQLite]
- Modbus(工业标准通信协议) [Rtu、Ascii、Tcp、Udp]
- S7(西门子) [S7200、Logo0BA8、S7200Smart、S7300、S7400、S71200、S71500]
- Beckhoff(倍福) [ADS]
- Mitsubishi(三菱) [A1E、QNA3E]
- Omron(欧姆龙) [FINS]
- AllenBradley(罗克韦尔)
- Mewtocol(松下) [Tcp、Serial]
namespace YSAI.Core.@interface
{
/// <summary>
/// 数采接口
/// </summary>
public interface IDaq : IOn, IOff, IRead, IWrite, ISubscribe, IGetStatus, IEvent, IGetParam, ICreateInstance, IDisposable
{ }
}
转发协议
- Kafka [AdminClient、Producer、Consumer]
- Mqtt [Client [ Publish、Subscribe ]、Service、WSService]
- RabbitMQ [Publish、Subscribe]
- Netty [Client [ Publish、Subscribe ]、Service]
- NetMQ [Publish、Subscribe]
namespace YSAI.Core.@interface
{
/// <summary>
/// 转发接口
/// </summary>
public interface IRelay : IOn, IOff, IProducer, IConsumer, IGetStatus, IEvent, IGetParam, ICreateInstance, IDisposable
{ }
}
应用
1.上 NUGET 搜索 YSAI
2.安装对应的协议包
3.应用代码如下
4.协议包内还有内部公共方法,请自行研究使用
------------------------------------------------------
//实例创建的几种方式
//第一种方式
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())
{
//使用完直接释放
}
//第七种方式
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 (IDaq daq4 = BeckhoffOperate.Instance(new BeckhoffData.Basics()))
{
//使用完直接释放这个单例
}
//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
//第一种的应用场景是获取库参数信息时当这个对象已经实例化了,但是实际功能无法使用,就可以直接使用 CreateInstance 创建一个单例模式
//先获取参数
beckhoffOperate1.GetParam();
//在生成单例后赋值,这样当前实例就已经可以使用所有功能,并且是单例的存在
beckhoffOperate1 = beckhoffOperate1.CreateInstance(new BeckhoffData.Basics()).GetRData<BeckhoffOperate>();
//第二种与第三种就是直接创建单例模式,但第二种是为了在反射的情况下使用单例模式,第二种也是为第一种情况而产生
------------------------------------------------------
//采集协议
using (类 operate = new 类(new 类数据.Basics
{
//采集对象参数
}))
{
//打开
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点位地址
{
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()
{
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()
{
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 //脚本解析数据
// {
// }
//},
AddressParseParam=new AddressParse //地址解析参数
{
ParseType=ParseType.MethodAnalysis, //解析类型
ReflectionSN="反射SN"
},
AddressPropertyName="Name1", //地址别名
AddressType=AddressType.Reality, //地址类型
IsEnable=true //是否启用
}
};
//读取
result = operate.Read(address);
LogHelper.Info(result.ToJson().JsonFormatting());
//订阅
operate.OnEvent += delegate (object? sender, EventResult e)
{
LogHelper.Info(e.ToJson().JsonFormatting());
};
result = operate.Subscribe(address);
LogHelper.Info(result.ToJson().JsonFormatting());
//写入
ConcurrentDictionary<string, string> value = new ConcurrentDictionary<string, string>
{
["地址"] = "值"
};
result = operate.Write(value);
LogHelper.Info(result.ToJson().JsonFormatting());
//关闭
result = operate.Off();
LogHelper.Info(result.ToJson().JsonFormatting());
}
------------------------------------------------------
//转发协议
using (类 operate = new 类(new 类数据.Basics
{
//转发对象参数
}))
{
//打开
OperateResult result = operate.On();
LogHelper.Info(result.ToJson().JsonFormatting());
//生产
result = operate.Produce("主题", "内容");
LogHelper.Info(result.ToJson().JsonFormatting());
//消费
operate.OnEvent += delegate (object? sender, EventResult e)
{
LogHelper.Info(e.ToJson().JsonFormatting());
};
result = operate.Subscribe("主题");
LogHelper.Info(result.ToJson().JsonFormatting());
//关闭
result = operate.Off();
LogHelper.Info(result.ToJson().JsonFormatting());
}
协议服务端(用于数据模拟)
- Mqtt服务端
- MqttWebSocket服务端
- OpcUa服务端
- Socket服务端
- WebSocket服务端
更新表
2023-02-15
- 项目启动
- 库框架搭建
- 采集订阅流程实现多线程队列形式,处理速度大大提升
//更新,无休眠时间
while(true)
{
//三大步骤
1.优化
2.更新
3.提交
}
2023-09-20
- 采集订阅模式关闭优化
- 底层通信库性能提升
2023-09-23
- 日志记录优化,更详细的日志记录
2023-09-24
- 新增公用库方法
- 版本更新
- MqttService参数类型修改
2023-09-25
- CanLib 文件位置更换
- Pack 生成位置更换
2023-09-27
- Mqtt 客户端 修改内部公共方法函数名
- 转发协议包修改
2023-10-08
- 反射新增类库,分为内外使用
- 修改转发库获取不到状态问题
- 版本更新,提交NUGET
- 新增边端 结构参数解析JSON
2023-10-10
- 解决OPCUA问题
- OPCUA版本更新
2023-10-11 ~ 2023-10-12
- 修改 OPCUA 订阅流程逻辑,解决超时问题
- 修改 OPCUA 工具显示问题
- OPCUA 工具新增 导出 Core 地址对象
- 版本更新
- 细节更新
- 结果类型新增
- 单例模式下新增实例数量限制
2023-10-13
- 解决RMQ内存增加问题
- 新增微秒延时
- 版本更新
- 新增对象比对方法
- 修改 override bool Equals 方法
2023-10-15
- 优化细节
- 移除 override bool Equals 方法,直接使用对象比对
- 版本更新
2023-10-16
- 自定义订阅修改
- 修改对象比对
- 版本更新
2023-10-17
- 订阅函数变化更新 新增订阅源数据比对更新,使比对更合理
- S7读取修改
2023-10-19
- 移除多余脚本代码(只做简单脚本计算)
- 优化OPCUA
- 版本更新
2023-10-20 ~ 2023-10-23
- 新增json字符串判断
- 修改opcua当断线重连自动订阅
- 修改传输协议的数据格式
- 新增新的传输协议 Netty 客户端服务端
- 细节优化
- 版本更新
2023-10-24 ~ 2023-10-25
- 新增数据类型DataTime、Time、Date
- 新增倍福客户端
- 版本更新,细节优化
2023-10-26
- 修改CORE的系统与Unility时间工具
- 整体细节优化
- 版本更新
2023-10-30
- 移除S7非标服务端
- 移除Modbus 非标服务端
- 底层通信新增字节数从末尾从前移除0x00
- 多余代码清理
- 版本更新
2023-10-31
- OpcUa新增根据设置值自动分配订阅组
- OpcDa新增根据设置值自动分配订阅组
- 细节优化
2023-11-01
- 新增三个特性 单位、验证、展示
- 新增获取库参数接口方法【GetParam】
- 移除单独生成库配置文件
- 细节优化
- 新增结构参数类
- 版本更新
2023-11-02
- 新增创建单例接口方法,为了在反射或获取参数的情况下使用所有功能
2023-11-03
- 底层通信读取等待结果新增分批读取
- 新增三菱PLC数据采集
- 细节优化
- 版本更新
2023-11-06
- 三菱PLC采集优化
- 新增欧姆龙PLC FINS协议采集
- 版本更新
2023-11-08
- 新增 NETMQ 传输协议(不保证消息质量模式)
- 优化函数运行时间,使用 struct 直接操作底层,性能提升
- 细节优化,版本更新
- 修改所有协议获取参数重复代码,移植至Core
2023-11-09
- 新增 AllenBradley PLC采集
- 新增S7类型读取流程
- 优化CORE内部结构代码
- 优化所有采集协议的读取代码
- 修改采集协议的OFF方法,新添加订阅OFF
- 新增S7、AllenBradley、Mitsubishi、Omron、ModBus 测试服务端(非标准)
- 版本更新
2023-11-10
- 自定义订阅细节修改,移除不必要的事件
- 新增松下PLC
- 修改获取参数函数细节
- 移除不必要的事件跳转
- OpcUa Da 属性BUG修改
2023-11-13
- 展示特性中新增详细提示字段,方面展示时了解与指导此属性的详情
- Serilog 更新至最新版本
- 修改版本规则 ( 年.天.秒 ) ( 23.317.30964 ) -- 23年,第317天,当天的30964秒时生成的版本
- 生成nuget包位置更新
2023-11-14
- 修改S7库名称,现使用Siemens
- 所有库新增详细描述
- 等待.net8发布,集成.net8
- OPCUA 移除默认XML文件,使用动态创建
- 新增版本更新工具,一键更新版本
2023-11-15
- 所有库 统一更新,支持 net6.0 、net8.0
- mqttwsservice 细节优化
2023-11-16
- RPC远程过程调用工具编写
- 底层SOCKET WEBSOCKET 修改断线重连规则
- 版本更新
2023-11-21
- 新增基于DotNetty实现的RPC(远程过程调用) 支持一对多,支持身份验证
- RabbitMQ 依赖库更新
2023-11-23
- 移除Core中的Redis
- 新增 扩展工具 Redis
- 修改RPC扩展工具细节
- 新增 XML 序列化 反序列化 扩展方法
- 新增HEX扩展转换
- 版本更新
2023-11-24
- 整体框架调整 Core、Model、Extend、Daq、Relay
- 实现底层数据转发功能支持热加载热更新
- 优化数据解析流程,优化转发流程
2023-11-27
- 优化数据结构
- 测试底层转发流程(成功)
- 测试底层解析流程(成功)
- 修改脚本解析默认参数传两个
- 修改反射解析默认参数传两个
- 新增 动态转发 打开失败重试流程
- 版本更新
2023-11-28
- 优化数据类型
- 优化地址处理函数,严格数据质量
- OPCUA 新增当订阅的地址点没有在服务器创建订阅,则重新订阅
2023-11-30
- 修改所有协议的函数开始返回的SN