## 阐述 1. 所有协议公共函数支持同步异步 2. 所有协议读取写入协议参数统一 3. 全部都是统一入参出参 4. 支持多点转发,多点解析 5. 支持快速对接,与配置 6. 支持虚拟点位 7. 所有采集协议支持订阅模式 8. 采集与转发协议接口统一 9. 事件结果统一 ## YSAI.Core 1. Http 2. Tcp客户端 3. Tcp服务端 4. Udp 5. WS客户端 6. WS服务端 7. 串口 8. 脚本 9. Redis 10. 反射 11. 自定义订阅 12. 虚拟点 ## YSAI.Log 1. Verbose [详细信息] 2. Debug [调试] 3. Info [信息] 4. Warning [警告] 5. Error [异常或错误] 6. Fatal [致命错误或异常] ## YSAI.Unility 1. 公共快捷方便方法集合 [字节、枚举、文件、Json、Xml、Ftp、System ...] ## 采集协议 1. OpcUa 2. OpcDa 3. OpcDaHttp 4. Can 5. DB(数据库) [SqlServer、MySql、Oracle、SQLite] 6. Modbus [Rtu、Ascii、Tcp、Udp] 7. S7(西门子) [S7200、Logo0BA8、S7200Smart、S7300、S7400、S71200、S71500] 8. Beckhoff(倍福) [ADS] 9. Mitsubishi(三菱) [A1E、QNA3E] 10. Omron(欧姆龙) [FINS] 11. AllenBradley(罗克韦尔) 12. Mewtocol(松下) [Tcp、Serial] ```sharp namespace YSAI.Core.@interface { /// /// 数采接口 /// public interface IDaq : IOn, IOff, IRead, IWrite, ISubscribe, IGetStatus, IEvent, IGetParam, ICreateInstance, IDisposable { } } ``` ## 转发协议 1. Kafka 2. Mqtt [Client、Service、WSService] 3. RabbitMQ 4. Netty [Client、Service] 5. NetMQ ```sharp namespace YSAI.Core.@interface { /// /// 转发接口 /// public interface IRelay : IOn, IOff, IProducer, IConsumer, IGetStatus, IEvent, IGetParam, ICreateInstance, IDisposable { } } ``` ## 应用 ```sharp 1.上 NUGET 搜索 YSAI 2.安装对应的协议包 3.应用代码如下 4.协议包内还有内部公共方法,请自行研究使用 ------------------------------------------------------ //实例创建的几种方式 //第一种方式 BeckhoffOperate beckhoffOperate1 = new BeckhoffOperate(); //第二种方式(单例模式) BeckhoffOperate? beckhoffOperate2 = new BeckhoffOperate().CreateInstance(new BeckhoffData.Basics()).GetRData(); //第三种方式(单例模式) 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()) { //使用完直接释放这个单例 } //第九种方式 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(); //第二种与第三种就是直接创建单例模式,但第二种是为了在反射的情况下使用单例模式,第二种也是为第一种情况而产生 ------------------------------------------------------ //采集协议 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 { 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() { "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 value = new ConcurrentDictionary { ["地址"] = "值" }; 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()); } ``` ## 协议服务端(用于数据模拟) 1. Mqtt服务端 2. MqttWebSocket服务端 3. OpcUa服务端 4. Socket服务端 5. WebSocket服务端 ## 更新表 #### 2023-02-15 1. 项目启动 2. 库框架搭建 3. 采集订阅流程实现多线程队列形式,处理速度大大提升 ```sharp //更新,无休眠时间 while(true) { //三大步骤 1.优化 2.更新 3.提交 } ``` #### 2023-09-20 1. 采集订阅模式关闭优化 2. 底层通信库性能提升 #### 2023-09-23 1. 日志记录优化,更详细的日志记录 #### 2023-09-24 1. 新增公用库方法 2. 版本更新 3. MqttService参数类型修改 #### 2023-09-25 1. CanLib 文件位置更换 2. Pack 生成位置更换 #### 2023-09-27 1. Mqtt 客户端 修改内部公共方法函数名 2. 转发协议包修改 #### 2023-10-08 1. 反射新增类库,分为内外使用 2. 修改转发库获取不到状态问题 3. 版本更新,提交NUGET 4. 新增边端 结构参数解析JSON #### 2023-10-10 1. 解决OPCUA问题 2. OPCUA版本更新 #### 2023-10-11 ~ 2023-10-12 1. 修改 OPCUA 订阅流程逻辑,解决超时问题 2. 修改 OPCUA 工具显示问题 3. OPCUA 工具新增 导出 Core 地址对象 4. 版本更新 5. 细节更新 6. 结果类型新增 7. 单例模式下新增实例数量限制 #### 2023-10-13 1. 解决RMQ内存增加问题 2. 新增微秒延时 3. 版本更新 4. 新增对象比对方法 5. 修改 override bool Equals 方法 #### 2023-10-15 1. 优化细节 2. 移除 override bool Equals 方法,直接使用对象比对 3. 版本更新 #### 2023-10-16 1. 自定义订阅修改 2. 修改对象比对 3. 版本更新 #### 2023-10-17 1. 订阅函数变化更新 新增订阅源数据比对更新,使比对更合理 2. S7读取修改 #### 2023-10-19 1. 移除多余脚本代码(只做简单脚本计算) 2. 优化OPCUA 3. 版本更新 #### 2023-10-20 ~ 2023-10-23 1. 新增json字符串判断 2. 修改opcua当断线重连自动订阅 3. 修改传输协议的数据格式 4. 新增新的传输协议 Netty 客户端服务端 5. 细节优化 6. 版本更新 #### 2023-10-24 ~ 2023-10-25 1. 新增数据类型DataTime、Time、Date 2. 新增倍福客户端 3. 版本更新,细节优化 #### 2023-10-26 1. 修改CORE的系统与Unility时间工具 2. 整体细节优化 3. 版本更新 #### 2023-10-30 1. 移除S7非标服务端 2. 移除Modbus 非标服务端 3. 底层通信新增字节数从末尾从前移除0x00 4. 多余代码清理 5. 版本更新 #### 2023-10-31 1. OpcUa新增根据设置值自动分配订阅组 2. OpcDa新增根据设置值自动分配订阅组 3. 细节优化 #### 2023-11-01 1. 新增三个特性 单位、验证、展示 2. 新增获取库参数接口方法【GetParam】 3. 移除单独生成库配置文件 4. 细节优化 5. 新增结构参数类 6. 版本更新 #### 2023-11-02 1. 新增创建单例接口方法,为了在反射或获取参数的情况下使用所有功能 #### 2023-11-03 1. 底层通信读取等待结果新增分批读取 2. 新增三菱PLC数据采集 3. 细节优化 4. 版本更新 #### 2023-11-06 1. 三菱PLC采集优化 2. 新增欧姆龙PLC FINS协议采集 3. 版本更新 #### 2023-11-08 1. 新增 NETMQ 传输协议(不保证消息质量模式) 2. 优化函数运行时间,使用 struct 直接操作底层,性能提升 3. 细节优化,版本更新 4. 修改所有协议获取参数重复代码,移植至Core #### 2023-11-09 1. 新增 AllenBradley PLC采集 2. 新增S7类型读取流程 3. 优化CORE内部结构代码 4. 优化所有采集协议的读取代码 5. 修改采集协议的OFF方法,新添加订阅OFF 6. 新增S7、AllenBradley、Mitsubishi、Omron、ModBus 测试服务端(非标准) 7. 版本更新 #### 2023-11-10 1. 自定义订阅细节修改,移除不必要的事件 2. 新增松下PLC 3. 修改获取参数函数细节 4. 移除不必要的事件跳转 5. OpcUa Da 属性BUG修改 #### 2023-11-13 1. 展示特性中新增详细提示字段,方面展示时了解与指导此属性的详情 2. Serilog 更新至最新版本 3. 修改版本规则 ( 年.天.秒 ) ( 23.317.30964 ) -- 23年,第317天,当天的30964秒时生成的版本 4. 生成nuget包位置更新