编辑
2025-12-24
C#
00

目录

🎯 为什么选择C#构建工业物联网系统?
💪 C#在工业场景的天然优势
🏗️ 系统架构设计:五层架构保证可扩展性
🔧 核心实现:从数据模型到智能分析
📊 步骤1:构建工业设备数据模型
⚡ 步骤2:实现高性能数据采集引擎
🤖 步骤3:集成AI智能分析能力
📈 步骤4:实现预测性维护算法
🚀 实际运行效果展示
💡 开发中的关键技巧和坑点
🔧 性能优化要点
🎯 生产环境部署建议
📚 扩展学习建议
🎉 总结:三个核心收获

在工业4.0浪潮下,设备数字化转型已成为制造业的核心竞争力。想象一下,如果你的工厂设备能像"钢铁侠"的贾维斯一样智能,24小时监控每一个传感器,预测故障,优化维护时间,这将为企业节省多少成本?

今天,我们将用C#从零构建一套完整的工业传感器智能分析系统,涵盖实时数据采集、智能异常检测、预测性维护和AI对话分析。

🎯 为什么选择C#构建工业物联网系统?

💪 C#在工业场景的天然优势

强类型安全:工业数据不容错误,C#的编译时类型检查为数据安全提供了第一道防线。

丰富生态:从底层硬件通信到上层AI分析,.NET生态提供了完整的解决方案。

跨平台部署:支持Windows、Linux部署,适应不同工业环境需求。

🏗️ 系统架构设计:五层架构保证可扩展性

我们的系统采用经典的分层架构:

Markdown
┌─────────────────────────────────────┐ │ AI智能分析层 │ ← Semantic Kernel + OpenAI ├─────────────────────────────────────┤ │ 业务逻辑层 │ ← 告警管理、预测性维护 ├─────────────────────────────────────┤ │ 数据处理层 │ ← 实时分析、异常检测 ├─────────────────────────────────────┤ │ 数据模型层 │ ← 设备、传感器抽象 ├─────────────────────────────────────┤ │ 数据采集层 │ ← 模拟真实传感器数据 └─────────────────────────────────────┘

image.png

🔧 核心实现:从数据模型到智能分析

📊 步骤1:构建工业设备数据模型

首先定义我们的核心数据结构。在工业环境中,数据模型的设计直接影响系统的可维护性:

C#
// 设备状态枚举 public enum DeviceStatus { Running, // 运行中 Idle, // 空闲 Fault, // 故障 Maintenance, // 维护中 Stopped // 停机 } // 传感器类型定义 public enum SensorType { Temperature, // 温度 Pressure, // 压力 Vibration, // 振动 Flow, // 流量 Speed, // 转速 Current, // 电流 Voltage, // 电压 Position, // 位置 Force, // 力 Torque, // 扭矩 Humidity, // 湿度 pH // 酸碱度 } // 设备实体类 public class Device { public string DeviceId { get; set; } public string DeviceName { get; set; } public DeviceType DeviceType { get; set; } public DeviceStatus Status { get; set; } public double OverallHealthScore { get; set; } // 健康度评分 public double OperationHours { get; set; } // 运行小时数 public List<Sensor> Sensors { get; set; } = new(); // 维护相关信息 public DateTime LastMaintenanceDate { get; set; } public string Location { get; set; } }

💡 设计要点:使用强类型枚举避免魔法字符串,OperationHours使用double类型支持精确的时间计算。

⚡ 步骤2:实现高性能数据采集引擎

工业环境对实时性要求极高,我们需要一个高效的数据采集引擎:

C#
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AppAiIndustrialSensorAnalyzer { public class SensorDataService : IDisposable { private readonly ConcurrentBag<SensorReading> _sensorReadings; private readonly List<Device> _devices; private readonly ConcurrentBag<SensorAlert> _alerts; private readonly Random _random; private Timer _dataGenerationTimer; private Timer _analysisTimer; private Timer _alertCheckTimer; private object _lockObject = new object(); // 配置参数 private readonly int _maxReadingsInMemory = 50000; private readonly TimeSpan _dataRetentionPeriod = TimeSpan.FromDays(7); private readonly double _samplingIntervalMs = 1000; // 1秒采样一次 public SensorDataService() { _sensorReadings = new ConcurrentBag<SensorReading>(); _devices = new List<Device>(); _alerts = new ConcurrentBag<SensorAlert>(); _random = new Random(); InitializeDevicesAndSensors(); StartRealTimeDataGeneration(); } private void InitializeDevicesAndSensors() { var devices = new[] { // 电机设备 new Device { DeviceId = "MTR-001", DeviceName = "主驱动电机", DeviceType = DeviceType.Motor, Manufacturer = "ABB", Model = "M3BP315SMB", InstallationDate = DateTime.Now.AddYears(-3), LastMaintenanceDate = DateTime.Now.AddMonths(-2), Status = DeviceStatus.Running, Location = "生产线A-区域1", OperationHours = 15000, Sensors = new List<Sensor> { new Sensor { SensorId = "MTR-001-TEMP", SensorName = "电机温度", SensorType = SensorType.Temperature, Unit = "°C", MinValue = 0, MaxValue = 200, NormalRangeMin = 20, NormalRangeMax = 80, Accuracy = 0.1, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "MTR-001-VIB", SensorName = "振动", SensorType = SensorType.Vibration, Unit = "mm/s", MinValue = 0, MaxValue = 50, NormalRangeMin = 0, NormalRangeMax = 10, Accuracy = 0.01, SamplingRate = 10, IsActive = true }, new Sensor { SensorId = "MTR-001-CUR", SensorName = "电流", SensorType = SensorType.Current, Unit = "A", MinValue = 0, MaxValue = 100, NormalRangeMin = 10, NormalRangeMax = 85, Accuracy = 0.1, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "MTR-001-SPD", SensorName = "转速", SensorType = SensorType.Speed, Unit = "RPM", MinValue = 0, MaxValue = 3000, NormalRangeMin = 1400, NormalRangeMax = 1600, Accuracy = 1, SamplingRate = 2, IsActive = true } } }, // 泵设备 new Device { DeviceId = "PMP-001", DeviceName = "冷却水泵", DeviceType = DeviceType.Pump, Manufacturer = "Grundfos", Model = "CR32-4", InstallationDate = DateTime.Now.AddYears(-2), LastMaintenanceDate = DateTime.Now.AddMonths(-1), Status = DeviceStatus.Running, Location = "冷却系统", OperationHours = 12000, Sensors = new List<Sensor> { new Sensor { SensorId = "PMP-001-PRES", SensorName = "出口压力", SensorType = SensorType.Pressure, Unit = "Bar", MinValue = 0, MaxValue = 10, NormalRangeMin = 2, NormalRangeMax = 8, Accuracy = 0.01, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "PMP-001-FLOW", SensorName = "流量", SensorType = SensorType.Flow, Unit = "L/min", MinValue = 0, MaxValue = 500, NormalRangeMin = 100, NormalRangeMax = 400, Accuracy = 0.5, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "PMP-001-TEMP", SensorName = "轴承温度", SensorType = SensorType.Temperature, Unit = "°C", MinValue = 0, MaxValue = 150, NormalRangeMin = 20, NormalRangeMax = 70, Accuracy = 0.1, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "PMP-001-VIB", SensorName = "振动", SensorType = SensorType.Vibration, Unit = "mm/s", MinValue = 0, MaxValue = 30, NormalRangeMin = 0, NormalRangeMax = 8, Accuracy = 0.01, SamplingRate = 10, IsActive = true } } }, // 压缩机设备 new Device { DeviceId = "CMP-001", DeviceName = "空气压缩机", DeviceType = DeviceType.Compressor, Manufacturer = "Atlas Copco", Model = "GA37VSD", InstallationDate = DateTime.Now.AddYears(-4), LastMaintenanceDate = DateTime.Now.AddMonths(-3), Status = DeviceStatus.Running, Location = "动力站", OperationHours = 18000, Sensors = new List<Sensor> { new Sensor { SensorId = "CMP-001-PRES", SensorName = "排气压力", SensorType = SensorType.Pressure, Unit = "MPa", MinValue = 0, MaxValue = 1.2, NormalRangeMin = 0.6, NormalRangeMax = 1.0, Accuracy = 0.001, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "CMP-001-TEMP", SensorName = "排气温度", SensorType = SensorType.Temperature, Unit = "°C", MinValue = 0, MaxValue = 250, NormalRangeMin = 60, NormalRangeMax = 120, Accuracy = 0.5, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "CMP-001-VIB", SensorName = "振动", SensorType = SensorType.Vibration, Unit = "mm/s", MinValue = 0, MaxValue = 40, NormalRangeMin = 0, NormalRangeMax = 12, Accuracy = 0.01, SamplingRate = 10, IsActive = true }, new Sensor { SensorId = "CMP-001-CUR", SensorName = "电流", SensorType = SensorType.Current, Unit = "A", MinValue = 0, MaxValue = 150, NormalRangeMin = 20, NormalRangeMax = 120, Accuracy = 0.1, SamplingRate = 1, IsActive = true } } }, // 工业机器人 new Device { DeviceId = "ROB-001", DeviceName = "焊接机器人", DeviceType = DeviceType.Robot, Manufacturer = "KUKA", Model = "KR150 R3100", InstallationDate = DateTime.Now.AddYears(-1), LastMaintenanceDate = DateTime.Now.AddDays(-30), Status = DeviceStatus.Running, Location = "焊接工位", OperationHours = 6000, Sensors = new List<Sensor> { new Sensor { SensorId = "ROB-001-POS1", SensorName = "关节1位置", SensorType = SensorType.Position, Unit = "degree", MinValue = -170, MaxValue = 170, NormalRangeMin = -160, NormalRangeMax = 160, Accuracy = 0.01, SamplingRate = 20, IsActive = true }, new Sensor { SensorId = "ROB-001-TOR1", SensorName = "关节1扭矩", SensorType = SensorType.Torque, Unit = "Nm", MinValue = 0, MaxValue = 1000, NormalRangeMin = 0, NormalRangeMax = 800, Accuracy = 0.1, SamplingRate = 20, IsActive = true }, new Sensor { SensorId = "ROB-001-TEMP", SensorName = "控制柜温度", SensorType = SensorType.Temperature, Unit = "°C", MinValue = 0, MaxValue = 100, NormalRangeMin = 15, NormalRangeMax = 45, Accuracy = 0.1, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "ROB-001-FORCE", SensorName = "末端力", SensorType = SensorType.Force, Unit = "N", MinValue = 0, MaxValue = 500, NormalRangeMin = 0, NormalRangeMax = 300, Accuracy = 0.1, SamplingRate = 100, IsActive = true } } }, // 储罐设备 new Device { DeviceId = "TNK-001", DeviceName = "化学品储罐", DeviceType = DeviceType.Tank, Manufacturer = "Emerson", Model = "TK-5000", InstallationDate = DateTime.Now.AddYears(-5), LastMaintenanceDate = DateTime.Now.AddMonths(-6), Status = DeviceStatus.Running, Location = "储存区域", OperationHours = 30000, Sensors = new List<Sensor> { new Sensor { SensorId = "TNK-001-LEVEL", SensorName = "液位", SensorType = SensorType.Position, Unit = "%", MinValue = 0, MaxValue = 100, NormalRangeMin = 10, NormalRangeMax = 90, Accuracy = 0.1, SamplingRate = 0.1, IsActive = true }, new Sensor { SensorId = "TNK-001-PRES", SensorName = "内部压力", SensorType = SensorType.Pressure, Unit = "kPa", MinValue = 0, MaxValue = 500, NormalRangeMin = 80, NormalRangeMax = 120, Accuracy = 0.1, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "TNK-001-TEMP", SensorName = "介质温度", SensorType = SensorType.Temperature, Unit = "°C", MinValue = -10, MaxValue = 80, NormalRangeMin = 15, NormalRangeMax = 35, Accuracy = 0.1, SamplingRate = 1, IsActive = true }, new Sensor { SensorId = "TNK-001-PH", SensorName = "pH值", SensorType = SensorType.pH, Unit = "pH", MinValue = 0, MaxValue = 14, NormalRangeMin = 6.5, NormalRangeMax = 8.5, Accuracy = 0.01, SamplingRate = 0.2, IsActive = true } } } }; _devices.AddRange(devices); // 设置设备规格和元数据 foreach (var device in _devices) { device.OverallHealthScore = _random.Next(70, 100); device.Specifications["RatedPower"] = _random.Next(10, 200); device.Specifications["RatedVoltage"] = _random.Next(220, 690); device.Specifications["OperatingPressure"] = _random.NextDouble() * 10; // 设置传感器校准日期 foreach (var sensor in device.Sensors) { sensor.CalibrationDate = DateTime.Now.AddMonths(-_random.Next(1, 12)); } } } private void StartRealTimeDataGeneration() { // 每秒生成传感器数据 _dataGenerationTimer = new Timer(GenerateRealtimeSensorData, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(_samplingIntervalMs)); // 每10秒进行数据分析 _analysisTimer = new Timer(PerformDataAnalysis, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10)); // 每5秒检查告警 _alertCheckTimer = new Timer(CheckAlerts, null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5)); } private void GenerateRealtimeSensorData(object state) { try { var now = DateTime.Now; foreach (var device in _devices) { if (device.Status != DeviceStatus.Running && device.Status != DeviceStatus.Idle) continue; foreach (var sensor in device.Sensors.Where(s => s.IsActive)) { var reading = GenerateSensorReading(device, sensor, now); _sensorReadings.Add(reading); // 检查是否需要生成告警 CheckForAlarms(reading); } } // 定期清理旧数据 if (_random.Next(0, 100) < 2) // 2%概率清理 { CleanupOldReadings(); } } catch (Exception ex) { Console.WriteLine($"生成传感器数据时发生错误: {ex.Message}"); } } private SensorReading GenerateSensorReading(Device device, Sensor sensor, DateTime timestamp) { var baseValue = GenerateRealisticSensorValue(device, sensor); // 添加设备状态相关的变化 baseValue = ApplyDeviceStatusEffects(device, sensor, baseValue); // 添加时间相关的变化(如温度的昼夜变化) baseValue = ApplyTimeBasedEffects(sensor, baseValue, timestamp); // 添加随机噪声 var noise = (_random.NextDouble() - 0.5) * sensor.Accuracy * 2; var finalValue = Math.Max(sensor.MinValue, Math.Min(sensor.MaxValue, baseValue + noise)); var reading = new SensorReading { Timestamp = timestamp, DeviceId = device.DeviceId, DeviceName = device.DeviceName, DeviceType = device.DeviceType, SensorId = sensor.SensorId, SensorName = sensor.SensorName, SensorType = sensor.SensorType, Value = Math.Round(finalValue, 2), Unit = sensor.Unit, MinValue = sensor.MinValue, MaxValue = sensor.MaxValue, NormalRangeMin = sensor.NormalRangeMin, NormalRangeMax = sensor.NormalRangeMax, Location = device.Location, AlarmLevel = DetermineAlarmLevel(finalValue, sensor) }; // 添加元数据 reading.Metadata["DeviceOperationHours"] = device.OperationHours; reading.Metadata["SensorAccuracy"] = sensor.Accuracy; reading.Metadata["LastCalibration"] = sensor.CalibrationDate; reading.Metadata["SamplingRate"] = sensor.SamplingRate; return reading; } private double GenerateRealisticSensorValue(Device device, Sensor sensor) { // 基于传感器类型和设备类型生成真实的基础值 return sensor.SensorType switch { SensorType.Temperature => GenerateTemperatureValue(device, sensor), SensorType.Pressure => GeneratePressureValue(device, sensor), SensorType.Vibration => GenerateVibrationValue(device, sensor), SensorType.Flow => GenerateFlowValue(device, sensor), SensorType.Speed => GenerateSpeedValue(device, sensor), SensorType.Current => GenerateCurrentValue(device, sensor), SensorType.Voltage => GenerateVoltageValue(device, sensor), SensorType.pH => GeneratePHValue(device, sensor), SensorType.Humidity => GenerateHumidityValue(device, sensor), SensorType.Position => GeneratePositionValue(device, sensor), SensorType.Force => GenerateForceValue(device, sensor), SensorType.Torque => GenerateTorqueValue(device, sensor), _ => (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2 }; } private double GenerateTemperatureValue(Device device, Sensor sensor) { var baseTemp = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; // 根据设备运行时间增加温度 var heatFactor = Math.Min(device.OperationHours / 1000.0, 10) * 2; // 根据设备类型调整 var deviceFactor = device.DeviceType switch { DeviceType.Motor => _random.NextDouble() * 15 - 5, // -5 to +10 DeviceType.Compressor => _random.NextDouble() * 20, // 0 to +20 DeviceType.Furnace => _random.NextDouble() * 100 + 200, // 高温设备 _ => _random.NextDouble() * 10 - 5 }; return baseTemp + heatFactor + deviceFactor; } private double GenerateVibrationValue(Device device, Sensor sensor) { var baseVib = sensor.NormalRangeMin + _random.NextDouble() * (sensor.NormalRangeMax - sensor.NormalRangeMin); // 老化设备振动增加 var agingFactor = device.OperationHours / 10000.0 * 3; // 根据设备类型调整 var deviceFactor = device.DeviceType switch { DeviceType.Motor => _random.NextDouble() * 2, DeviceType.Pump => _random.NextDouble() * 1.5, DeviceType.Compressor => _random.NextDouble() * 3, _ => _random.NextDouble() }; return baseVib + agingFactor + deviceFactor; } private double GeneratePressureValue(Device device, Sensor sensor) { var basePressure = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; // 添加周期性变化模拟负载变化 var cycleVariation = Math.Sin(DateTime.Now.Minute / 10.0 * Math.PI) * (sensor.NormalRangeMax - sensor.NormalRangeMin) * 0.1; var randomVariation = (_random.NextDouble() - 0.5) * (sensor.NormalRangeMax - sensor.NormalRangeMin) * 0.2; return basePressure + cycleVariation + randomVariation; } private double GenerateFlowValue(Device device, Sensor sensor) { if (device.DeviceType == DeviceType.Pump) { // 流量与压力相关 var pressureSensor = device.Sensors.FirstOrDefault(s => s.SensorType == SensorType.Pressure); if (pressureSensor != null) { var recentPressureReadings = _sensorReadings .Where(r => r.SensorId == pressureSensor.SensorId && (DateTime.Now - r.Timestamp).TotalSeconds < 10) .ToList(); if (recentPressureReadings.Any()) { var avgPressure = recentPressureReadings.Average(r => r.Value); var flowFactor = avgPressure / pressureSensor.NormalRangeMax; return sensor.NormalRangeMax * flowFactor * (0.8 + _random.NextDouble() * 0.4); } } } return sensor.NormalRangeMin + _random.NextDouble() * (sensor.NormalRangeMax - sensor.NormalRangeMin); } private double GenerateSpeedValue(Device device, Sensor sensor) { if (device.Status == DeviceStatus.Running) { var targetSpeed = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; var variation = (_random.NextDouble() - 0.5) * 50; // ±25 RPM变化 return targetSpeed + variation; } return 0; } private double GenerateCurrentValue(Device device, Sensor sensor) { if (device.Status == DeviceStatus.Running) { var baseCurrent = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; // 负载变化 var loadFactor = 0.7 + _random.NextDouble() * 0.6; // 0.7-1.3倍负载 return baseCurrent * loadFactor; } return 0; } private double GenerateVoltageValue(Device device, Sensor sensor) { // 电压相对稳定,只有小幅波动 var baseVoltage = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; var variation = (_random.NextDouble() - 0.5) * 10; // ±5V变化 return baseVoltage + variation; } private double GeneratePHValue(Device device, Sensor sensor) { var basePH = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; var drift = (_random.NextDouble() - 0.5) * 0.5; // pH漂移 return basePH + drift; } private double GeneratePositionValue(Device device, Sensor sensor) { if (device.DeviceType == DeviceType.Robot) { // 机器人关节位置会有周期性运动 var cycleTime = 30; // 30秒一个周期 var phase = (DateTime.Now.Second % cycleTime) / (double)cycleTime * 2 * Math.PI; var amplitude = (sensor.NormalRangeMax - sensor.NormalRangeMin) * 0.6; var center = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; return center + Math.Sin(phase) * amplitude; } else if (device.DeviceType == DeviceType.Tank && sensor.SensorName.Contains("液位")) { // 储罐液位缓慢变化 var baseLevel = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; var drift = Math.Sin(DateTime.Now.Minute / 60.0 * Math.PI) * 20; return Math.Max(sensor.NormalRangeMin, Math.Min(sensor.NormalRangeMax, baseLevel + drift)); } return sensor.NormalRangeMin + _random.NextDouble() * (sensor.NormalRangeMax - sensor.NormalRangeMin); } private double GenerateForceValue(Device device, Sensor sensor) { if (device.DeviceType == DeviceType.Robot) { // 机器人作业时的力反馈 var workingForce = _random.NextDouble() * sensor.NormalRangeMax * 0.8; var spikes = _random.NextDouble() < 0.1 ? _random.NextDouble() * 100 : 0; // 10%概率出现力尖峰 return workingForce + spikes; } return _random.NextDouble() * sensor.NormalRangeMax * 0.5; } private double GenerateTorqueValue(Device device, Sensor sensor) { if (device.DeviceType == DeviceType.Robot) { // 扭矩与位置和负载相关 var baseTorque = sensor.NormalRangeMax * 0.3; var loadTorque = _random.NextDouble() * sensor.NormalRangeMax * 0.4; return baseTorque + loadTorque; } return _random.NextDouble() * sensor.NormalRangeMax * 0.6; } private double GenerateHumidityValue(Device device, Sensor sensor) { var baseHumidity = (sensor.NormalRangeMin + sensor.NormalRangeMax) / 2; // 时间相关的湿度变化 var timeVariation = Math.Sin(DateTime.Now.Hour / 24.0 * 2 * Math.PI) * 10; var randomVariation = (_random.NextDouble() - 0.5) * 5; return Math.Max(0, Math.Min(100, baseHumidity + timeVariation + randomVariation)); } private double ApplyDeviceStatusEffects(Device device, Sensor sensor, double baseValue) { return device.Status switch { DeviceStatus.Fault => ApplyFaultEffects(sensor, baseValue), DeviceStatus.Maintenance => baseValue * 0.1, // 维护时大部分传感器读数很低 DeviceStatus.Stopped => 0, DeviceStatus.Idle => baseValue * 0.3, // 空闲时部分负载 _ => baseValue }; } private double ApplyFaultEffects(Sensor sensor, double baseValue) { // 不同类型的传感器在故障时有不同表现 return sensor.SensorType switch { SensorType.Temperature => baseValue + _random.NextDouble() * 50, // 温度异常升高 SensorType.Vibration => baseValue + _random.NextDouble() * 20, // 振动异常增大 SensorType.Pressure => baseValue * (0.5 + _random.NextDouble()), // 压力波动 SensorType.Current => baseValue * (1.2 + _random.NextDouble() * 0.5), // 电流异常 _ => baseValue * (0.8 + _random.NextDouble() * 0.4) }; } private double ApplyTimeBasedEffects(Sensor sensor, double baseValue, DateTime timestamp) { // 环境温度的昼夜变化 if (sensor.SensorType == SensorType.Temperature && sensor.SensorName.Contains("环境")) { var hourEffect = Math.Sin((timestamp.Hour - 6) / 24.0 * 2 * Math.PI) * 8; // ±8度日变化 return baseValue + hourEffect; } // 生产负载的班次变化 if (sensor.SensorType == SensorType.Current || sensor.SensorType == SensorType.Flow) { var hour = timestamp.Hour; var shiftFactor = (hour >= 8 && hour <= 16) ? 1.2 : // 白班高负载 (hour >= 16 && hour <= 24) ? 1.0 : // 晚班正常负载 0.6; // 夜班低负载 return baseValue * shiftFactor; } return baseValue; } private AlarmLevel DetermineAlarmLevel(double value, Sensor sensor) { var normalRange = sensor.NormalRangeMax - sensor.NormalRangeMin; var warningThreshold = normalRange * 0.1; var criticalThreshold = normalRange * 0.2; if (value < sensor.NormalRangeMin - criticalThreshold || value > sensor.NormalRangeMax + criticalThreshold) return AlarmLevel.Critical; else if (value < sensor.NormalRangeMin - warningThreshold || value > sensor.NormalRangeMax + warningThreshold) return AlarmLevel.Warning; else if (value < sensor.MinValue || value > sensor.MaxValue) return AlarmLevel.Emergency; else return AlarmLevel.Normal; } private void CheckForAlarms(SensorReading reading) { if (reading.AlarmLevel == AlarmLevel.Normal) return; // 检查是否已存在相同的活跃告警 var existingAlert = _alerts.FirstOrDefault(a => a.SensorId == reading.SensorId && !a.IsResolved && a.Level == reading.AlarmLevel && (DateTime.Now - a.Timestamp).TotalMinutes < 5); if (existingAlert != null) { // 更新现有告警的持续时间 existingAlert.Duration = DateTime.Now - existingAlert.Timestamp; existingAlert.CurrentValue = reading.Value; return; } // 创建新告警 var alert = new SensorAlert { Timestamp = reading.Timestamp, DeviceId = reading.DeviceId, DeviceName = reading.DeviceName, SensorId = reading.SensorId, SensorName = reading.SensorName, SensorType = reading.SensorType, Level = reading.AlarmLevel, CurrentValue = reading.Value, ThresholdValue = reading.AlarmLevel == AlarmLevel.Critical ? (reading.Value > reading.NormalRangeMax ? reading.NormalRangeMax : reading.NormalRangeMin) : (reading.Value > reading.NormalRangeMax ? reading.NormalRangeMax : reading.NormalRangeMin), Message = GenerateAlarmMessage(reading), RecommendedAction = GenerateRecommendedAction(reading), IsAcknowledged = false, IsResolved = false, Duration = TimeSpan.Zero }; _alerts.Add(alert); } private string GenerateAlarmMessage(SensorReading reading) { var direction = reading.Value > reading.NormalRangeMax ? "超出上限" : "低于下限"; var severity = reading.AlarmLevel switch { AlarmLevel.Warning => "轻微异常", AlarmLevel.Critical => "严重异常", AlarmLevel.Emergency => "紧急状况", _ => "异常" }; return $"{reading.DeviceName}{reading.SensorName}{direction},当前值{reading.Value:F2}{reading.Unit}{severity}"; } private string GenerateRecommendedAction(SensorReading reading) { return reading.SensorType switch { SensorType.Temperature when reading.AlarmLevel == AlarmLevel.Critical => "立即检查冷却系统,停机检查是否有过热风险", SensorType.Vibration when reading.AlarmLevel == AlarmLevel.Critical => "停机检查轴承和联轴器,可能需要更换部件", SensorType.Pressure when reading.Value > reading.NormalRangeMax => "检查压力调节阀,释放过压,检查管路是否堵塞", SensorType.Pressure when reading.Value < reading.NormalRangeMin => "检查泄漏点,补充介质,检查泵的工作状态", SensorType.Current when reading.AlarmLevel == AlarmLevel.Critical => "立即停机,检查电气连接和负载情况", SensorType.Flow when reading.Value < reading.NormalRangeMin => "检查管路堵塞,清理过滤器,检查泵运行状态", SensorType.pH when reading.AlarmLevel != AlarmLevel.Normal => "调节pH值,检查化学品投加系统", _ => "联系维护人员进行详细检查,记录异常情况" }; } private void PerformDataAnalysis(object state) { try { foreach (var device in _devices) { AnalyzeDeviceHealth(device); UpdateDeviceOperationHours(device); } } catch (Exception ex) { Console.WriteLine($"数据分析时发生错误: {ex.Message}"); } } private void AnalyzeDeviceHealth(Device device) { var recentReadings = GetRecentReadingsForDevice(device.DeviceId, TimeSpan.FromMinutes(10)); if (!recentReadings.Any()) return; var healthScores = new List<double>(); foreach (var sensor in device.Sensors) { var sensorReadings = recentReadings.Where(r => r.SensorId == sensor.SensorId).ToList(); if (!sensorReadings.Any()) continue; var sensorHealth = CalculateSensorHealthScore(sensor, sensorReadings); healthScores.Add(sensorHealth); } if (healthScores.Any()) { device.OverallHealthScore = healthScores.Average(); // 根据健康度更新设备状态 if (device.OverallHealthScore < 30 && device.Status == DeviceStatus.Running) { device.Status = DeviceStatus.Fault; } else if (device.OverallHealthScore > 70 && device.Status == DeviceStatus.Fault) { device.Status = DeviceStatus.Running; } } } private double CalculateSensorHealthScore(Sensor sensor, List<SensorReading> readings) { var score = 100.0; // 基于正常范围的评分 var outOfRangeCount = readings.Count(r => r.Value < r.NormalRangeMin || r.Value > r.NormalRangeMax); var outOfRangeRatio = (double)outOfRangeCount / readings.Count; score -= outOfRangeRatio * 50; // 基于数据稳定性的评分 if (readings.Count > 5) { var values = readings.Select(r => r.Value).ToArray(); var mean = values.Average(); var variance = values.Select(v => Math.Pow(v - mean, 2)).Average(); var coefficientOfVariation = Math.Sqrt(variance) / Math.Abs(mean); // 变异系数过大扣分 if (coefficientOfVariation > 0.2) { score -= Math.Min(30, coefficientOfVariation * 100); } } // 基于告警频率的评分 var recentAlerts = _alerts.Where(a => a.SensorId == sensor.SensorId && (DateTime.Now - a.Timestamp).TotalHours < 24).Count(); score -= Math.Min(20, recentAlerts * 5); return Math.Max(0, Math.Min(100, score)); } private void UpdateDeviceOperationHours(Device device) { if (device.Status == DeviceStatus.Running) { // 每10秒更新一次,所以每次增加 10/3600 小时 device.OperationHours += 10.0 / 3600.0; } } private void CheckAlerts(object state) { try { var activeAlerts = _alerts.Where(a => !a.IsResolved).ToList(); foreach (var alert in activeAlerts) { // 检查告警是否应该自动解决 var recentReadings = GetRecentReadingsForSensor(alert.SensorId, TimeSpan.FromMinutes(2)); if (recentReadings.Any() && recentReadings.All(r => r.AlarmLevel == AlarmLevel.Normal)) { alert.IsResolved = true; Console.WriteLine($"✅ 告警已自动解决: {alert.Message}"); } else if (recentReadings.Any()) { // 更新告警的当前值和持续时间 alert.CurrentValue = recentReadings.OrderByDescending(r => r.Timestamp).First().Value; alert.Duration = DateTime.Now - alert.Timestamp; } } } catch (Exception ex) { Console.WriteLine($"检查告警时发生错误: {ex.Message}"); } } private void CleanupOldReadings() { var cutoffTime = DateTime.Now - _dataRetentionPeriod; var recentReadings = _sensorReadings .Where(r => r.Timestamp >= cutoffTime) .OrderByDescending(r => r.Timestamp) .Take(_maxReadingsInMemory) .ToList(); lock (_lockObject) { _sensorReadings.Clear(); foreach (var reading in recentReadings) { _sensorReadings.Add(reading); } } Console.WriteLine($"数据清理完成,当前记录数: {_sensorReadings.Count}"); } // 公共方法 public List<SensorReading> GetAllSensorReadings() => _sensorReadings.ToList(); public List<Device> GetAllDevices() => _devices.ToList(); public List<SensorAlert> GetAllAlerts() => _alerts.ToList(); public List<SensorReading> GetRecentReadingsForDevice(string deviceId, TimeSpan timeSpan) { var cutoffTime = DateTime.Now - timeSpan; return _sensorReadings .Where(r => r.DeviceId == deviceId && r.Timestamp >= cutoffTime) .OrderByDescending(r => r.Timestamp) .ToList(); } public List<SensorReading> GetRecentReadingsForSensor(string sensorId, TimeSpan timeSpan) { var cutoffTime = DateTime.Now - timeSpan; return _sensorReadings .Where(r => r.SensorId == sensorId && r.Timestamp >= cutoffTime) .OrderByDescending(r => r.Timestamp) .ToList(); } public List<SensorAlert> GetActiveAlerts() { return _alerts.Where(a => !a.IsResolved).OrderByDescending(a => a.Timestamp).ToList(); } public List<SensorAlert> GetCriticalAlerts() { return _alerts.Where(a => !a.IsResolved && a.Level == AlarmLevel.Critical) .OrderByDescending(a => a.Timestamp).ToList(); } public DeviceHealthReport GenerateDeviceHealthReport(string deviceId) { var device = _devices.FirstOrDefault(d => d.DeviceId == deviceId); if (device == null) return null; var recentReadings = GetRecentReadingsForDevice(deviceId, TimeSpan.FromHours(24)); var activeAlerts = _alerts.Where(a => a.DeviceId == deviceId && !a.IsResolved).ToList(); var report = new DeviceHealthReport { DeviceId = device.DeviceId, DeviceName = device.DeviceName, GeneratedTime = DateTime.Now, OverallHealthScore = device.OverallHealthScore, Status = device.Status, ActiveAlerts = activeAlerts, SensorMetrics = new List<SensorHealthMetric>(), MaintenanceRecommendations = new List<string>() }; // 生成传感器健康指标 foreach (var sensor in device.Sensors) { var sensorReadings = recentReadings.Where(r => r.SensorId == sensor.SensorId).ToList(); if (!sensorReadings.Any()) continue; var values = sensorReadings.Select(r => r.Value).ToArray(); var mean = values.Average(); var stdDev = Math.Sqrt(values.Select(v => Math.Pow(v - mean, 2)).Average()); var metric = new SensorHealthMetric { SensorId = sensor.SensorId, SensorName = sensor.SensorName, SensorType = sensor.SensorType, HealthScore = CalculateSensorHealthScore(sensor, sensorReadings), AverageValue = mean, StandardDeviation = stdDev, TrendSlope = CalculateTrendSlope(values), AnomalyCount = sensorReadings.Count(r => r.AlarmLevel != AlarmLevel.Normal), LastAnomalyTime = sensorReadings.Where(r => r.AlarmLevel != AlarmLevel.Normal) .OrderByDescending(r => r.Timestamp) .FirstOrDefault()?.Timestamp ?? DateTime.MinValue }; report.SensorMetrics.Add(metric); } // 生成维护建议 report.MaintenanceRecommendations = GenerateMaintenanceRecommendations(device, report.SensorMetrics); // 预测下次维护时间 report.PredictedNextMaintenance = PredictNextMaintenanceDate(device, report.SensorMetrics); // 计算剩余使用寿命 report.RemainingUsefulLife = CalculateRemainingUsefulLife(device, report.SensorMetrics); return report; } private double CalculateTrendSlope(double[] values) { if (values.Length < 2) return 0; var n = values.Length; var sumX = 0; var sumY = values.Sum(); var sumXY = 0.0; var sumX2 = 0; for (int i = 0; i < n; i++) { sumX += i; sumXY += i * values[i]; sumX2 += i * i; } return (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX); } private List<string> GenerateMaintenanceRecommendations(Device device, List<SensorHealthMetric> metrics) { var recommendations = new List<string>(); // 基于传感器健康度的建议 var lowHealthSensors = metrics.Where(m => m.HealthScore < 60).ToList(); foreach (var sensor in lowHealthSensors) { recommendations.Add($"传感器{sensor.SensorName}健康度偏低({sensor.HealthScore:F1}),建议进行校准或更换"); } // 基于运行时间的建议 if (device.OperationHours > 20000) { recommendations.Add("设备运行时间较长,建议安排大修维护"); } else if (device.OperationHours > 10000) { recommendations.Add("建议进行中级维护,检查关键部件"); } // 基于设备类型的特定建议 recommendations.AddRange(GetDeviceSpecificRecommendations(device, metrics)); // 基于告警历史的建议 var recentAlerts = _alerts.Where(a => a.DeviceId == device.DeviceId && (DateTime.Now - a.Timestamp).TotalDays < 30).ToList(); if (recentAlerts.Count > 10) { recommendations.Add("近期告警频繁,建议全面检查设备状态"); } if (recommendations.Count == 0) { recommendations.Add("设备状态良好,按计划进行日常维护即可"); } return recommendations; } private List<string> GetDeviceSpecificRecommendations(Device device, List<SensorHealthMetric> metrics) { var recommendations = new List<string>(); switch (device.DeviceType) { case DeviceType.Motor: var vibrationMetric = metrics.FirstOrDefault(m => m.SensorType == SensorType.Vibration); if (vibrationMetric?.AverageValue > 8) { recommendations.Add("电机振动偏高,检查轴承和对中情况"); } var tempMetric = metrics.FirstOrDefault(m => m.SensorType == SensorType.Temperature); if (tempMetric?.AverageValue > 70) { recommendations.Add("电机温度偏高,检查通风和负载情况"); } break; case DeviceType.Pump: var flowMetric = metrics.FirstOrDefault(m => m.SensorType == SensorType.Flow); var pressureMetric = metrics.FirstOrDefault(m => m.SensorType == SensorType.Pressure); if (flowMetric?.TrendSlope < -0.5) { recommendations.Add("泵流量呈下降趋势,可能存在磨损或堵塞"); } if (pressureMetric?.StandardDeviation > 1.0) { recommendations.Add("压力波动较大,检查管路和阀门"); } break; case DeviceType.Compressor: var compTempMetric = metrics.FirstOrDefault(m => m.SensorType == SensorType.Temperature); var compPressureMetric = metrics.FirstOrDefault(m => m.SensorType == SensorType.Pressure); if (compTempMetric?.AverageValue > 110) { recommendations.Add("压缩机排气温度过高,检查冷却系统"); } if (compPressureMetric?.TrendSlope < -0.1) { recommendations.Add("排气压力下降,可能存在内部泄漏"); } break; case DeviceType.Robot: var positionMetrics = metrics.Where(m => m.SensorType == SensorType.Position).ToList(); var torqueMetrics = metrics.Where(m => m.SensorType == SensorType.Torque).ToList(); if (positionMetrics.Any(m => m.StandardDeviation > 1.0)) { recommendations.Add("机器人定位精度下降,需要重新校准"); } if (torqueMetrics.Any(m => m.TrendSlope > 0.5)) { recommendations.Add("关节扭矩增加,检查传动系统磨损"); } break; } return recommendations; } private DateTime PredictNextMaintenanceDate(Device device, List<SensorHealthMetric> metrics) { var baseInterval = device.DeviceType switch { DeviceType.Motor => TimeSpan.FromDays(90), // 3个月 DeviceType.Pump => TimeSpan.FromDays(60), // 2个月 DeviceType.Compressor => TimeSpan.FromDays(45), // 1.5个月 DeviceType.Robot => TimeSpan.FromDays(30), // 1个月 _ => TimeSpan.FromDays(90) }; // 根据健康度调整维护间隔 var avgHealthScore = metrics.Any() ? metrics.Average(m => m.HealthScore) : 80; var healthFactor = avgHealthScore / 100.0; // 健康度低的设备缩短维护间隔 var adjustedInterval = TimeSpan.FromDays(baseInterval.TotalDays * healthFactor); // 最少15天,最多180天 adjustedInterval = TimeSpan.FromDays(Math.Max(15, Math.Min(180, adjustedInterval.TotalDays))); return device.LastMaintenanceDate.Add(adjustedInterval); } private double CalculateRemainingUsefulLife(Device device, List<SensorHealthMetric> metrics) { var baseLife = device.DeviceType switch { DeviceType.Motor => 50000, // 50000小时 DeviceType.Pump => 40000, // 40000小时 DeviceType.Compressor => 35000, // 35000小时 DeviceType.Robot => 30000, // 30000小时 _ => 40000 }; var usedLife = device.OperationHours; var healthFactor = metrics.Any() ? metrics.Average(m => m.HealthScore) / 100.0 : 0.8; // 健康度影响剩余寿命 var remainingLife = (baseLife - usedLife) * healthFactor; return Math.Max(0, remainingLife); } public PredictiveMaintenanceResult PredictDeviceFailure(string deviceId) { var device = _devices.FirstOrDefault(d => d.DeviceId == deviceId); if (device == null) return null; var healthReport = GenerateDeviceHealthReport(deviceId); var recentReadings = GetRecentReadingsForDevice(deviceId, TimeSpan.FromDays(7)); var result = new PredictiveMaintenanceResult { DeviceId = device.DeviceId, DeviceName = device.DeviceName, PredictionTime = DateTime.Now, ContributingFactors = new List<string>(), PreventiveActions = new List<string>() }; // 计算故障概率 var failureProbability = CalculateFailureProbability(device, healthReport, recentReadings); result.FailureProbability = failureProbability; // 预测故障日期 if (failureProbability > 0.1) { var daysToFailure = CalculateDaysToFailure(failureProbability, healthReport); result.PredictedFailureDate = DateTime.Now.AddDays(daysToFailure); } else { result.PredictedFailureDate = DateTime.Now.AddYears(1); // 低风险设备 } // 确定故障模式 result.FailureMode = DetermineFailureMode(device, healthReport); // 识别贡献因素 result.ContributingFactors = IdentifyContributingFactors(device, healthReport); // 生成预防措施 result.PreventiveActions = GeneratePreventiveActions(device, healthReport, result.FailureMode); // 置信水平 result.ConfidenceLevel = CalculateConfidenceLevel(recentReadings.Count, healthReport.SensorMetrics.Count); return result; } private double CalculateFailureProbability(Device device, DeviceHealthReport healthReport, List<SensorReading> recentReadings) { var probability = 0.0; // 基于健康分数 if (healthReport.OverallHealthScore < 50) probability += 0.4; else if (healthReport.OverallHealthScore < 70) probability += 0.2; else if (healthReport.OverallHealthScore < 80) probability += 0.1; // 基于运行时间 var expectedLifespan = device.DeviceType switch { DeviceType.Motor => 50000, DeviceType.Pump => 40000, DeviceType.Compressor => 35000, DeviceType.Robot => 30000, _ => 40000 }; var ageRatio = device.OperationHours / (double)expectedLifespan; if (ageRatio > 0.8) probability += 0.3; else if (ageRatio > 0.6) probability += 0.2; else if (ageRatio > 0.4) probability += 0.1; var recentAlerts = _alerts.Where(a => a.DeviceId == device.DeviceId && (DateTime.Now - a.Timestamp).TotalDays < 30).Count(); if (recentAlerts > 20) probability += 0.3; else if (recentAlerts > 10) probability += 0.2; else if (recentAlerts > 5) probability += 0.1; // 基于传感器趋势 var negativetrends = healthReport.SensorMetrics.Count(m => m.TrendSlope < -0.1); probability += negativetrends * 0.05; // 基于异常频率 var totalAnomalies = healthReport.SensorMetrics.Sum(m => m.AnomalyCount); if (totalAnomalies > 100) probability += 0.2; else if (totalAnomalies > 50) probability += 0.1; return Math.Min(1.0, probability); } private int CalculateDaysToFailure(double failureProbability, DeviceHealthReport healthReport) { // 基础计算:概率越高,预测故障时间越近 var baseDays = (1.0 - failureProbability) * 365; // 根据健康分数调整 var healthFactor = healthReport.OverallHealthScore / 100.0; baseDays *= healthFactor; // 限制在合理范围内 return Math.Max(1, Math.Min(365, (int)baseDays)); } private string DetermineFailureMode(Device device, DeviceHealthReport healthReport) { var failureModes = new List<(string mode, double score)>(); switch (device.DeviceType) { case DeviceType.Motor: var vibMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Vibration); var tempMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Temperature); var currentMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Current); if (vibMetric?.HealthScore < 60) failureModes.Add(("轴承故障", 100 - vibMetric.HealthScore)); if (tempMetric?.HealthScore < 60) failureModes.Add(("过热故障", 100 - tempMetric.HealthScore)); if (currentMetric?.HealthScore < 60) failureModes.Add(("电气故障", 100 - currentMetric.HealthScore)); break; case DeviceType.Pump: var flowMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Flow); var pressureMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Pressure); var pumpVibMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Vibration); if (flowMetric?.TrendSlope < -0.5) failureModes.Add(("叶轮磨损", Math.Abs(flowMetric.TrendSlope) * 100)); if (pressureMetric?.StandardDeviation > 2) failureModes.Add(("密封泄漏", pressureMetric.StandardDeviation * 20)); if (pumpVibMetric?.HealthScore < 60) failureModes.Add(("机械松动", 100 - pumpVibMetric.HealthScore)); break; case DeviceType.Compressor: var compTempMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Temperature); var compPressureMetric = healthReport.SensorMetrics.FirstOrDefault(m => m.SensorType == SensorType.Pressure); if (compTempMetric?.AverageValue > 120) failureModes.Add(("冷却系统故障", compTempMetric.AverageValue - 80)); if (compPressureMetric?.TrendSlope < -0.2) failureModes.Add(("内部泄漏", Math.Abs(compPressureMetric.TrendSlope) * 200)); break; case DeviceType.Robot: var positionMetrics = healthReport.SensorMetrics.Where(m => m.SensorType == SensorType.Position); var torqueMetrics = healthReport.SensorMetrics.Where(m => m.SensorType == SensorType.Torque); if (positionMetrics.Any(m => m.StandardDeviation > 1.5)) failureModes.Add(("编码器故障", positionMetrics.Max(m => m.StandardDeviation) * 30)); if (torqueMetrics.Any(m => m.TrendSlope > 1.0)) failureModes.Add(("减速器磨损", torqueMetrics.Max(m => m.TrendSlope) * 50)); break; } if (failureModes.Any()) { return failureModes.OrderByDescending(f => f.score).First().mode; } return "一般性磨损"; } private static List<string> IdentifyContributingFactors(Device device, DeviceHealthReport healthReport) { var factors = new List<string>(); // 运行时间因素 var expectedLifespan = device.DeviceType switch { DeviceType.Motor => 50000, DeviceType.Pump => 40000, DeviceType.Compressor => 35000, DeviceType.Robot => 30000, _ => 40000 }; var ageRatio = device.OperationHours / (double)expectedLifespan; if (ageRatio > 0.7) factors.Add($"设备运行时间较长({device.OperationHours:N0}小时,已达设计寿命的{ageRatio:P0})"); // 维护间隔因素 var daysSinceLastMaintenance = (DateTime.Now - device.LastMaintenanceDate).TotalDays; if (daysSinceLastMaintenance > 180) factors.Add($"上次维护时间较长({daysSinceLastMaintenance:N0}天前)"); // 传感器健康因素 var unhealthySensors = healthReport.SensorMetrics.Where(m => m.HealthScore < 70).ToList(); if (unhealthySensors.Any()) { factors.Add($"多个传感器健康度偏低: {string.Join(", ", unhealthySensors.Select(s => s.SensorName))}"); } // 环境因素(修正温度判断逻辑) var tempSensors = healthReport.SensorMetrics.Where(m => m.SensorType == SensorType.Temperature); foreach (var tempSensor in tempSensors) { var threshold = tempSensor.SensorName.Contains("环境") ? 35.0 : 80.0; if (tempSensor.AverageValue > threshold) { factors.Add("运行环境温度偏高"); break; // 只添加一次 } } var vibSensors = healthReport.SensorMetrics.Where(m => m.SensorType == SensorType.Vibration); if (vibSensors.Any(v => v.AverageValue > 10)) { factors.Add("设备振动水平超标"); } // 负载因素(修正电流判断逻辑) var currentSensors = healthReport.SensorMetrics.Where(m => m.SensorType == SensorType.Current); foreach (var currentSensor in currentSensors) { var threshold = currentSensor.SensorName.Contains("额定") ? 0.9 : 80.0; if (currentSensor.AverageValue > threshold) { factors.Add("设备长期高负载运行"); break; // 只添加一次 } } // 告警历史因素 var criticalAlerts = healthReport.ActiveAlerts.Count(a => a.Level == AlarmLevel.Critical); if (criticalAlerts > 0) factors.Add($"当前有{criticalAlerts}个严重告警"); if (factors.Count == 0) factors.Add("设备状态相对良好,主要为正常老化"); return factors; } private List<string> GeneratePreventiveActions(Device device, DeviceHealthReport healthReport, string failureMode) { var actions = new List<string>(); // 基于故障模式的预防措施 switch (failureMode) { case "轴承故障": actions.Add("更换轴承或增加润滑频次"); actions.Add("检查轴对中和平衡"); actions.Add("监控振动趋势变化"); break; case "过热故障": actions.Add("清洁冷却系统和通风口"); actions.Add("检查环境温度和通风条件"); actions.Add("降低负载或增加冷却能力"); break; case "叶轮磨损": actions.Add("检查并更换磨损的叶轮"); actions.Add("分析介质腐蚀性和磨损性"); actions.Add("考虑使用耐磨材料"); break; case "密封泄漏": actions.Add("更换密封件"); actions.Add("检查轴向和径向间隙"); actions.Add("调整密封压力"); break; case "冷却系统故障": actions.Add("清洁冷却器和检查冷却液"); actions.Add("检查冷却水流量和温度"); actions.Add("更换冷却系统滤芯"); break; case "编码器故障": actions.Add("校准或更换位置编码器"); actions.Add("检查编码器连接线缆"); actions.Add("清洁编码器光学元件"); break; case "减速器磨损": actions.Add("更换减速器润滑油"); actions.Add("检查齿轮磨损情况"); actions.Add("调整传动间隙"); break; default: actions.Add("进行全面的设备检查"); actions.Add("按计划执行预防性维护"); break; } // 基于健康度的通用措施 if (healthReport.OverallHealthScore < 60) { actions.Add("安排紧急维护检查"); actions.Add("增加监控频率"); actions.Add("准备备件和替换方案"); } else if (healthReport.OverallHealthScore < 80) { actions.Add("安排计划性维护"); actions.Add("监控关键参数趋势"); } // 基于设备类型的特定措施 switch (device.DeviceType) { case DeviceType.Motor: actions.Add("检查电气连接和绝缘"); actions.Add("测试电机气隙和转子平衡"); break; case DeviceType.Pump: actions.Add("检查管路系统和阀门"); actions.Add("分析工艺介质变化"); break; case DeviceType.Compressor: actions.Add("检查进气过滤器"); actions.Add("分析压缩机效率变化"); break; case DeviceType.Robot: actions.Add("进行机器人校准"); actions.Add("检查程序和路径优化"); break; } return actions.Distinct().ToList(); } private double CalculateConfidenceLevel(int dataPointCount, int sensorCount) { // 基于数据量的置信度 var dataConfidence = Math.Min(1.0, dataPointCount / 1000.0); // 基于传感器数量的置信度 var sensorConfidence = Math.Min(1.0, sensorCount / 10.0); // 综合置信度 var overallConfidence = (dataConfidence * 0.6 + sensorConfidence * 0.4) * 100; return Math.Max(50, Math.Min(95, overallConfidence)); // 50%-95%范围 } // 获取实时统计信息 public SensorSystemStatistics GetRealTimeStatistics() { var now = DateTime.Now; var lastMinute = now.AddMinutes(-1); var lastHour = now.AddHours(-1); var last24Hours = now.AddDays(-1); var recentReadings = _sensorReadings.Where(r => r.Timestamp >= lastMinute).ToList(); var hourlyReadings = _sensorReadings.Where(r => r.Timestamp >= lastHour).ToList(); var dailyReadings = _sensorReadings.Where(r => r.Timestamp >= last24Hours).ToList(); var activeAlerts = _alerts.Where(a => !a.IsResolved).ToList(); return new SensorSystemStatistics { Timestamp = now, TotalDevices = _devices.Count, ActiveDevices = _devices.Count(d => d.Status == DeviceStatus.Running), TotalSensors = _devices.SelectMany(d => d.Sensors).Count(), ActiveSensors = _devices.SelectMany(d => d.Sensors).Count(s => s.IsActive), ReadingsLastMinute = recentReadings.Count, ReadingsLastHour = hourlyReadings.Count, ReadingsLast24Hours = dailyReadings.Count, AverageDeviceHealth = _devices.Average(d => d.OverallHealthScore), ActiveAlertsCount = activeAlerts.Count, CriticalAlertsCount = activeAlerts.Count(a => a.Level == AlarmLevel.Critical), WarningAlertsCount = activeAlerts.Count(a => a.Level == AlarmLevel.Warning), DeviceStatusDistribution = _devices.GroupBy(d => d.Status) .ToDictionary(g => g.Key.ToString(), g => g.Count()), SensorTypeDistribution = _devices.SelectMany(d => d.Sensors) .GroupBy(s => s.SensorType) .ToDictionary(g => g.Key.ToString(), g => g.Count()), AlertLevelDistribution = activeAlerts.GroupBy(a => a.Level) .ToDictionary(g => g.Key.ToString(), g => g.Count()), TopAbnormalDevices = _devices .Where(d => d.OverallHealthScore < 80) .OrderBy(d => d.OverallHealthScore) .Take(5) .Select(d => new { d.DeviceName, d.OverallHealthScore, d.Status }) .ToList() }; } // 启动性能监控 public void StartPerformanceMonitoring(Action<string> logCallback = null) { Task.Run(async () => { while (!_disposed) { try { var stats = GetRealTimeStatistics(); var message = $"[{DateTime.Now:HH:mm:ss}] " + $"设备: {stats.ActiveDevices}/{stats.TotalDevices}, " + $"传感器: {stats.ActiveSensors}/{stats.TotalSensors}, " + $"读数/分钟: {stats.ReadingsLastMinute}, " + $"平均健康度: {stats.AverageDeviceHealth:F1}, " + $"告警: {stats.ActiveAlertsCount}({stats.CriticalAlertsCount}严重)"; logCallback?.Invoke(message); // 如果有严重告警,特别标注 if (stats.CriticalAlertsCount > 0) { var criticalAlerts = GetCriticalAlerts(); foreach (var alert in criticalAlerts.Take(3)) // 只显示前3个 { var alertMsg = $"🚨 严重告警: {alert.DeviceName} - {alert.Message}"; logCallback?.Invoke(alertMsg); } } await Task.Delay(15000); // 每15秒输出一次 } catch (Exception ex) { Console.WriteLine($"性能监控错误: {ex.Message}"); } } }); } // 资源清理 private bool _disposed = false; public void Dispose() { if (!_disposed) { _dataGenerationTimer?.Dispose(); _analysisTimer?.Dispose(); _alertCheckTimer?.Dispose(); _disposed = true; Console.WriteLine("传感器数据服务已停止"); } } } // 统计信息类 public class SensorSystemStatistics { public DateTime Timestamp { get; set; } public int TotalDevices { get; set; } public int ActiveDevices { get; set; } public int TotalSensors { get; set; } public int ActiveSensors { get; set; } public int ReadingsLastMinute { get; set; } public int ReadingsLastHour { get; set; } public int ReadingsLast24Hours { get; set; } public double AverageDeviceHealth { get; set; } public int ActiveAlertsCount { get; set; } public int CriticalAlertsCount { get; set; } public int WarningAlertsCount { get; set; } public Dictionary<string, int> DeviceStatusDistribution { get; set; } = new(); public Dictionary<string, int> SensorTypeDistribution { get; set; } = new(); public Dictionary<string, int> AlertLevelDistribution { get; set; } = new(); public object TopAbnormalDevices { get; set; } } }

⚠️ 性能提醒:使用lock保证线程安全,但要注意锁的粒度。在高并发场景下,可考虑使用ConcurrentCollection

🤖 步骤3:集成AI智能分析能力

这是整个系统的亮点 - 让AI理解工业数据:

C#
public class AISensorAnalysisService { private readonly Kernel _kernel; private readonly SensorDataService _sensorService; public AISensorAnalysisService(SensorDataService sensorService) { _sensorService = sensorService; _kernel = InitializeKernel(); RegisterSensorAnalysisPlugins(); } private Kernel InitializeKernel() { var kernelBuilder = Kernel.CreateBuilder(); // 集成DeepSeek API - 成本更低的AI选择 kernelBuilder.AddOpenAIChatCompletion( modelId: "deepseek-chat", apiKey: Environment.GetEnvironmentVariable("DEEPSEEK_API_KEY"), endpoint: new Uri("https://api.deepseek.com/v1") ); return kernelBuilder.Build(); } private void RegisterSensorAnalysisPlugins() { // 🏭 设备状态总览插件 var deviceOverviewFunction = _kernel.CreateFunctionFromMethod( method: () => { var devices = _sensorService.GetAllDevices(); var stats = _sensorService.GetRealTimeStatistics(); return JsonSerializer.Serialize(new { SystemOverview = stats, DeviceDetails = devices.Select(d => new { d.DeviceId, d.DeviceName, d.DeviceType, d.Status, d.OverallHealthScore }) }, new JsonSerializerOptions { WriteIndented = true }); }, functionName: "GetDeviceOverview", description: "获取所有工业设备的状态总览" ); _kernel.ImportPluginFromFunctions("DeviceMonitoring", [deviceOverviewFunction]); } }

🔥 核心优势:通过Semantic Kernel的Function Calling,AI可以直接调用我们的C#方法获取实时数据,实现真正的智能交互。

📈 步骤4:实现预测性维护算法

预测性维护是工业4.0的核心价值之一:

C#
public PredictiveMaintenanceResult PredictDeviceFailure(string deviceId) { var device = _devices.FirstOrDefault(d => d.DeviceId == deviceId); var healthReport = GenerateDeviceHealthReport(deviceId); var result = new PredictiveMaintenanceResult { DeviceId = deviceId, PredictionTime = DateTime.Now }; // 多维度故障概率计算 var failureProbability = CalculateFailureProbability(device, healthReport); result.FailureProbability = failureProbability; // 基于概率预测故障时间 if (failureProbability > 0.1) { var daysToFailure = (1.0 - failureProbability) * 365; result.PredictedFailureDate = DateTime.Now.AddDays(daysToFailure); } return result; } private double CalculateFailureProbability(Device device, DeviceHealthReport healthReport) { var probability = 0.0; // 基于健康分数 if (healthReport.OverallHealthScore < 50) probability += 0.4; else if (healthReport.OverallHealthScore < 70) probability += 0.2; // 基于运行时间(设备老化) var expectedLifespan = device.DeviceType switch { DeviceType.Motor => 50000, DeviceType.Pump => 40000, DeviceType.Compressor => 35000, _ => 40000 }; var ageRatio = device.OperationHours / expectedLifespan; if (ageRatio > 0.8) probability += 0.3; return Math.Min(1.0, probability); }

💰 商业价值:通过准确的故障预测,企业可以从"被动维修"转向"主动维护",显著降低停机成本。

🚀 实际运行效果展示

启动系统后,你将看到:

image.png

image.png

💡 开发中的关键技巧和坑点

🔧 性能优化要点

1. 内存管理

C#
// ❌ 错误:无限制的数据增长 private readonly List<SensorReading> _sensorReadings = new(); // ✅ 正确:定期清理历史数据 private void CleanupOldReadings() { var cutoffTime = DateTime.Now - _dataRetentionPeriod; var recentReadings = _sensorReadings .Where(r => r.Timestamp >= cutoffTime) .OrderByDescending(r => r.Timestamp) .Take(_maxReadingsInMemory) .ToList(); lock (_lockObject) { _sensorReadings.Clear(); _sensorReadings.AddRange(recentReadings); } }

2. 类型转换陷阱

C#
// ❌ 编译错误:不能将double隐式转换为int device.OperationHours += 10.0 / 3600.0; // OperationHours是int类型 // ✅ 解决方案1:修改属性类型 public double OperationHours { get; set; } // 推荐 // ✅ 解决方案2:显式转换 device.OperationHours += (int)(10.0 / 3600.0);

3. 线程安全处理

C#
// ❌ 可能导致数据竞争 _sensorReadings.Add(reading); // ✅ 使用锁保护共享资源 lock (_lockObject) { _sensorReadings.Add(reading); }

🎯 生产环境部署建议

配置管理:使用appsettings.json管理不同环境的配置

日志记录:集成Serilog进行结构化日志记录

监控告警:接入Prometheus + Grafana监控系统性能

容器化:使用Docker简化部署流程

📚 扩展学习建议

  • 工业通信协议:学习Modbus、OPC UA等协议对接真实设备
  • 时序数据库:了解InfluxDB、TimescaleDB处理大规模时序数据
  • 边缘计算:探索在边缘设备部署.NET应用的最佳实践

🎉 总结:三个核心收获

  1. 架构设计:分层架构 + 强类型系统为复杂工业场景提供了坚实基础
  2. AI集成:Semantic Kernel让传统C#应用具备了智能对话能力
  3. 实战价值:从数据采集到预测性维护的完整闭环,直接对应企业级需求

这套系统不仅展示了C#在工业物联网领域的技术实力,更重要的是提供了一个可扩展的架构模板。无论你是在做设备监控、智能制造还是数字化转型项目,这些代码模式都能直接应用。

互动时间

  1. 你的项目中是否遇到过实时数据处理的性能瓶颈?是如何解决的?
  2. 对于工业场景的AI应用,你认为还有哪些创新可能?

觉得这个工业4.0解决方案对你有启发吗?请转发给更多正在做物联网开发的同行,让我们一起推动C#在工业智能化领域的应用!


相关信息

通过网盘分享的文件:AppAiIndustrialSensorAnalyzer.zip 链接: https://pan.baidu.com/s/194Yz5-gaXaecj3KEiV04gA?pwd=tuxr 提取码: tuxr --来自百度网盘超级会员v9的分享

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!