private bool IsPumpRunningAndTdDataUpdated(IRedisClient redisClient, Guid ppGuid) { //判断机泵是否在运行 var isRun = redisClient.IsPumpRunning(ppGuid); Log.Inform(isRun ? $">>>>>>>>> 机组{ppGuid} 正在运行 >>>>>>>>" : $"--------- 机组{ppGuid} 未运行 ---------"); if (!isRun) { return(false); } //找出机泵下所有传感器,检查数据更新状态 //如果都没更新, 那就不进行诊断 //如果存在更新了数据的传感器,那就需要进行诊断 var ppsys = RuntimeRepo.PumpSysList.First(ps => GuidExt.IsSameGuid(ppGuid, ps.Guid)); var hasNewData = false; foreach (var td in ppsys.Transducers) { var isUpdated = redisClient.IsTdDataUpdated(td); hasNewData |= isUpdated; } if (!hasNewData) { Log.Inform($"--------- 机组{ppGuid} 所有传感器未更新数值 ---------"); } return(hasNewData); }
public void RunDiagnose() { foreach (var guid in RuntimeRepo.RunningPumpGuids) { Log.Inform(); Log.Inform($"********* 开始诊断机组:{guid} *********", true); Log.Inform(); var ppsys = RuntimeRepo.PumpSysList.First(ps => GuidExt.IsSameGuid(guid, ps.Guid)); _ctParser.TdUpdateTime = RuntimeRepo.PumpSysTimeDict[guid] ?? DateTime.Now; DiagnoseRunningPump_Round1(ppsys); DiagnoseRunningPump_Round2(ppsys); FindMainVibraSpec(ppsys); #if DEBUG RabbitToPandas(ppsys); #endif Log.Inform(); Log.Inform($"********* 机组:{guid} 诊断结束 ********", true); Log.Inform(); } }
public PumpSystem(Guid ppGuid) { Guid = ppGuid; Log.Inform(); Log.Inform($"--------- 开始构建机泵系统{Guid.ToFormatedString()} ---------"); Log.Inform(); #region 构建机泵部件 //部件部分 Pump = new Component(Guid, CompType.Pump) { NameRemark = "水泵" }; Motor = new Component(Guid, CompType.Motor) { NameRemark = "电机" }; Coupler = new Component(Guid, CompType.Coupler) { NameRemark = "联轴器" }; //振动传感器部分 var vibrasensors = Repo.SensorList.Where(s => GuidExt.IsSameGuid(s.PPGUID, Guid)).ToList(); foreach (var vibrasensor in vibrasensors) { var td = new VibraTransducer(vibrasensor.SSGUID) { Signal = vibrasensor.ITEMCODE, NameRemark = vibrasensor.SSNAME, Position = PubFuncs.FindTdPosFromSignal(vibrasensor.ITEMCODE) }; Transducers.Add(td); Log.Inform($"添加振动传感器({td.NameRemark}): 信号量:{td.Signal} 位置:{td.Position}"); } //非振动部分 foreach (var phydefnovibra in Repo.PhyDefNoVibra.Where(s => GuidExt.IsSameGuid(s.PPGUID, Guid))) { var type = PubFuncs.ParseSignalType(phydefnovibra.ITEMCODE); if (type.HasValue) { var td = new NonVibraTransducer(phydefnovibra.PPGUID, type.Value, phydefnovibra.ID) { Signal = phydefnovibra.ITEMCODE, NameRemark = phydefnovibra.PDNVNAME, Position = PubFuncs.FindTdPosFromSignal(phydefnovibra.ITEMCODE) }; Transducers.Add(td); Log.Inform($"添加非振动传感器({td.NameRemark}): 信号量:{td.Signal} 位置:{td.Position}"); } } //还有一枚单独的转速变送器 var speedTd = new SpeedTransducer(Guid); Transducers.Add(speedTd); Log.Inform($"添加转速传感器({speedTd.NameRemark}): 信号量:{speedTd.Signal} 位置:{speedTd.Position}"); // var ta = Repo.PhyDefNoVibra.Select(p => p.ITEMCODE).ToList(); Add(Pump); Add(Motor); Add(Coupler); AddRange(Transducers); #endregion #region 构建部件间接属性 foreach (DataRow row in PumpSysLib.TableIndirectProperty.Rows) { var prop = new Property { Name = row["PropertyName"].ToString(), Value = row["DefaultValue"].ToString(), Variable = row["Variable"].ToString() }; AllocateProperty(prop, row); } //连接点属性是间接属性的一部分,所以也加入 foreach (DataRow row in PumpSysLib.TableConnectorPointProperty.Rows) { var prop = new Property { Name = row["PropertyName"].ToString(), // Value = row["DefaultValue"].ToString(), Variable = row["Variable"].ToString() }; AllocateProperty(prop, row); } #endregion #region 绑定传感器的自带信号量 foreach (var transducer in Transducers) { transducer.BindSignal(); } #endregion #region 设置振动传感器的图谱的信号量 foreach (var tdv in Transducers.Where(t => t.Type == CompType.Td_V)) { foreach (var gType in Enum.GetNames(typeof(GraphType))) { var prop = tdv.Properties.Find(p => p.Variable == "@" + gType); prop.Value = PubFuncs.FormatGraphSignal(tdv.Code, (GraphType)Enum.Parse(typeof(GraphType), gType)); } } #endregion #region 根据引用属性,将间接属性的值绑定到信号量 foreach (DataRow row in PumpSysLib.TableRefProperty.Rows) { //找到要设置属性值的组件 BaseComponent comp = null; var cpType = Repo.Map.TypeToEnum[row["TypeName"].ToString()]; switch (cpType) { case CompType.Pump: comp = Pump; break; case CompType.Motor: comp = Motor; break; case CompType.Coupler: comp = Coupler; break; } //找到要设置的属性值 var prop = comp?.Properties.Find(p => p.Variable == row["IndirectVariable"].ToString()); if (prop != null) { //先找是哪个类型的传感器 var tdtype = Repo.Map.TypeToEnum[row["RefType"].ToString()]; //再根据位置找到该传感器 var tdpos = (TdPos)Enum.Parse(typeof(TdPos), row["Position"].ToString()); var td = Transducers.Find(t => t.Type == tdtype && t.Position == tdpos); //再找到传感器上的属性 var rp = td?.Properties.Find(p => p.Variable == row["RefVariable"].ToString()); if (rp != null) { prop.Value = rp.Value; } } } #endregion #region 根据水泵guid,设置水泵轴承和电机轴承的各自的4个缺陷频率 foreach (var pumpBrInfo in DataDetailsOp.GetPumpBearingInfos(Guid)) { Pump.Properties.First(p => p.Variable == pumpBrInfo.Key).Value = pumpBrInfo.Value.ToString(); } foreach (var motorBrInfo in DataDetailsOp.GetMotorBearingInfos(Guid)) { Motor.Properties.First(p => p.Variable == motorBrInfo.Key).Value = motorBrInfo.Value.ToString(); } #endregion #region 根据水泵guid,设置水泵叶片数 Pump.Properties.First(p => p.Variable == "@BladeNum").Value = DataDetailsOp.GetPumpFanCount(Guid).ToString(); #endregion Log.Inform(); Log.Inform($"--------- 机泵系统{ppGuid} 构建结束---------"); Log.Inform(); }
/// <summary> /// 机泵实时数据 /// </summary> public void UpdateRtData() { using (var redisClient = RedisManager.GetClient()) { RuntimeRepo.RunningPumpGuids.Clear(); try { RuntimeRepo.RunningPumpGuids.AddRange(Repo.PumpGuids.Where(g => IsPumpRunningAndTdDataUpdated(redisClient, g)).ToList()); } catch (ServiceStack.Redis.RedisException ex) { Log.Error("实时数据更新失败! " + ex.Message); return; } //更新每个ppsys的实时数据时间, 以所有传感器中最新的数据作为该时间 RuntimeRepo.PumpSysTimeDict.Clear(); foreach (var guid in RuntimeRepo.RunningPumpGuids) { var ppsys = RuntimeRepo.PumpSysList.First(ps => GuidExt.IsSameGuid(guid, ps.Guid)); var maxTime = DateTime.MinValue; foreach (var td in ppsys.Transducers) { DateTime?time; if (redisClient.TryGetTdPickTime(td, out time)) { if (time > maxTime) { maxTime = time.Value; } } } RuntimeRepo.PumpSysTimeDict.Add(guid, maxTime); } //构建要获取的实时数据的结构 RuntimeRepo.RtData = new RtData(); Log.Inform("--------------------------读取数据----------------------------"); foreach (var item in RuntimeRepo.RtData.RedisKeyMap) { var value = redisClient.GetValue(item.Key); if (!string.IsNullOrEmpty(value)) { if (item.Value.Contains("$Ua") || item.Value.Contains("$Ub") || item.Value.Contains("$Uc")) // || item.Value.Contains("$P_In") || item.Value.Contains("$P_Out")) { RuntimeRepo.RtData.SpData[item.Value] = Convert.ToDouble(value) * 1000; } else { // if (item.Value.Contains("peed") && Convert.ToDouble(value) < 300) // { // var a = 1; // } RuntimeRepo.RtData.SpData[item.Value] = Convert.ToDouble(value); } } } //[vibration realtime data Example]: var specs = new List <Spectrum>(); RuntimeRepo.SpecAnalyser.Specs.Clear(); foreach (var graph in RuntimeRepo.RtData.Graphs) { // var sgn = "{" + _waveDatasRedisKey[item.DeviceCode].ToUpper() + "}_" + // (item.Type == "spectrum" ? "TimeWave" : "Spectrum"); var value = redisClient.GetValue(graph.Signal); if (string.IsNullOrEmpty(value)) { Log.Warn($"从Redis中获取不到 {graph.Signal} 对应的图谱"); continue; } graph.Time = DateTime.Parse(value.Split('|')[0].Replace(@"""", string.Empty)); var datas = value.Split('[')[1] .Replace(@"\", string.Empty) .Replace(@"""", string.Empty) .Replace("]", string.Empty) .Replace("}", string.Empty) .Split(',') .Select(double.Parse) .ToList(); //不去掉第一个无效值0, 为了保证计算时索引和线保持一致 // if(datas[0] == 0D) // datas.RemoveAt(0); graph.UpdateData(datas.ToArray()); if (graph.Type == GraphType.Spectrum) { var speed = RuntimeRepo.GetSpeed(); specs.Add(new Spectrum(speed, graph.Data, graph.Pos)); } } RuntimeRepo.SpecAnalyser.UpdateSpecs(specs); } }