using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using RTOverEthernetDevelopmentKit; using System; using System.Linq; using System.Threading; using System.Xml; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps { /// 昂坤Viper-RTC测温数据交互流程简介 /// 1:上位机连接昂坤软件启动的服务器,昂坤服务器启用 工控机的IP + 53888固定端口,上位机连接服务器获取温度数据 /// 2:昂坤软件通过USB线连接主机盒子获取温度,上位机不用干预 /// 3:昂坤通讯特性,上位机发送一条指令后,服务器会一直安装设定频率,一直发送数据,上位机只接受就可以了 /// 4:上位机读取数据,通过昂坤提供的库,调用连接和数据获取方法 /// 5:断联分为昂坤软件服务器、USB两种断联和重连判断,例如:昂坤软件未打开或UBS线松动 /// 6:继承ITempData接口,上层使用接口获取数据,方便以后扩展测温硬件 /// /// 昂坤Viper-RTC测温 /// public class AKunTemp : TempSensorBase { #region Variables private IROverEthernet _ir; /// /// 连接昂坤软件服务器 /// private readonly R_TRIG _trigConnServiceError = new(); /// /// 机箱USB断联 /// private readonly R_TRIG _trigUSBDataError = new(); /// /// 机箱USB重连 /// private readonly R_TRIG _trigUSBDataOK = new(); private int _lastIntegTime; #endregion Variables #region Constructors public AKunTemp(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule) { RTrigs.Add(_trigConnServiceError); RTrigs.Add(_trigUSBDataError); RTrigs.Add(_trigUSBDataOK); } #endregion #region Properties private int Port { get; set; } public override bool IsConnected => _ir.IsConnected; #endregion #region Methods /// /// 获取系统配置中的积分时间。 /// /// private int GetScIntegrationTime() { var integrationTime = SC.GetValue($"{ScBasePath}.{Name}.AverageTime"); // the minimum value should be 10ms. if (integrationTime < 10) integrationTime = 10; return integrationTime; } public override bool Connect() { try { if (IsSimMode) return true; _ir.Init(Address, Port); _ir.StopIR(); _lastIntegTime = GetScIntegrationTime(); _ir.SetIntegrationTime(_lastIntegTime); _ir.StartIR(); return true; } catch (Exception ex) { return false; } } private void Reconnect() { try { if (IsSimMode) return; _ir.Close(); } catch { // ignored } finally { Connect(); } } protected override bool HandleInitialize() { InitAKunController(); return true; } private void InitAKunController() { if (IsSimMode) return; var data = SC.GetStringValue($"{ScBasePath}.{Name}.Address").Split(':'); Address = data[0]; Port = Convert.ToInt32(data[1]); _ir = new IROverEthernet(); _trigUSBDataOK.CLK = true;//初始化重连信号 SC.RegisterValueChangedCallback($"{ScBasePath}.{Name}.ControllerAverageTime", SetControllerAverageTime); } private void SetControllerAverageTime(object time) { if (IsSimMode) return; if (time != null && int.TryParse(time.ToString(), out var avt)) { _ir.StopIR(); _ir.SetIntegrationTime(avt); _ir.StartIR(); } else { LOG.Error($"Unable to set {Name} controller average time, the parameter {time} is not a integer."); } } private int _usbReConnCnt = 0;//接受数据失败次数 private double[] ReadTemp() { try { if (IsSimMode) return null; var allChannel = _ir.GetAllChannel(); //USB线断联和重连逻辑 { //连接时使用次数报警,多次接收到空数据开始报警 ,此时发现正常连接时Count=0会出现,频率是几分钟出现一次 if (allChannel.FirstOrDefault(ch => ch == null || !ch.Any()) != null || // 某个通道没有数据 _ir.Current.Status != 0) //首次打开上位机时,测试昂坤软件打开且未连接USB时,Count一直大于0,所以此处添加厂商提供的属性值判断USB连接 { _usbReConnCnt++; if (_usbReConnCnt <= 10) return null; _trigUSBDataOK.CLK = false; //复位USB重连信号, _trigUSBDataError.CLK = true; if (_trigUSBDataError.Q) TempBasFunction.PM1PM2PostLog( $"Can not connect with {Name} From USB,Status:{_ir.Current.Status}", EV.PostAlarmLog); _usbReConnCnt = 0; TempBasFunction.SetPm1Pm2IoForInterlock(true); return null; } _trigUSBDataOK.CLK = true; if (_trigUSBDataOK.Q) { TempBasFunction.PM1PM2PostLog($"Connect OK with {Name} From USB", EV.PostInfoLog); _trigUSBDataError.RST = true;//复位USB断联信号 TempBasFunction.SetPm1Pm2IoForInterlock(false); } //有数据时必须复位 _usbReConnCnt = 0; } return allChannel.Select(ch => (double)ch.Average()).ToArray(); } catch (Exception ex) { LOG.Write($"{Name} Read controller error, {ex}"); return null; } } protected override double[] HandleReadTemp() { try { //判断昂坤软件服务器断联和重连逻辑 if (_ir.IsConnected) return ReadTemp(); Reconnect(); if (!_ir.IsConnected)//昂坤软件的服务器未打开 { _trigConnServiceError.CLK = true; if (_trigConnServiceError.Q) { Thread.Sleep(2000);//不加延时软件刚启动可能不打印 TempBasFunction.PM1PM2PostLog($"AKun Temp Software Maybe Not Open {Address} {Name}", EV.PostAlarmLog); TempBasFunction.SetPm1Pm2IoForInterlock(true); } } else//连接成功后不会再进入,只会提示一次 { _trigConnServiceError.RST = true; TempBasFunction.PM1PM2PostLog($"Connect OK with AKun Temp Software Form {Address} {Name}", EV.PostInfoLog); TempBasFunction.SetPm1Pm2IoForInterlock(false); } Thread.Sleep(1000); return null; } catch (Exception ex) { if (_trigConnServiceError.Q) { TempBasFunction.PM1PM2PostLog($"{this} Unable to read data from viper RTC, {ex.Message}", EV.PostAlarmLog); } return null; } } public override void Terminate() { try { if (IsSimMode) return; _ir.Close(); } catch (Exception ex) { LOG.Write(ex); } } public override bool Disconnect() { Terminate(); return true; } #endregion } }