在工业4.0浪潮下,设备数字化转型已成为制造业的核心竞争力。想象一下,如果你的工厂设备能像"钢铁侠"的贾维斯一样智能,24小时监控每一个传感器,预测故障,优化维护时间,这将为企业节省多少成本?
今天,我们将用C#从零构建一套完整的工业传感器智能分析系统,涵盖实时数据采集、智能异常检测、预测性维护和AI对话分析。
强类型安全:工业数据不容错误,C#的编译时类型检查为数据安全提供了第一道防线。
丰富生态:从底层硬件通信到上层AI分析,.NET生态提供了完整的解决方案。
跨平台部署:支持Windows、Linux部署,适应不同工业环境需求。
我们的系统采用经典的分层架构:
Markdown┌─────────────────────────────────────┐ │ AI智能分析层 │ ← Semantic Kernel + OpenAI ├─────────────────────────────────────┤ │ 业务逻辑层 │ ← 告警管理、预测性维护 ├─────────────────────────────────────┤ │ 数据处理层 │ ← 实时分析、异常检测 ├─────────────────────────────────────┤ │ 数据模型层 │ ← 设备、传感器抽象 ├─────────────────────────────────────┤ │ 数据采集层 │ ← 模拟真实传感器数据 └─────────────────────────────────────┘

首先定义我们的核心数据结构。在工业环境中,数据模型的设计直接影响系统的可维护性:
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类型支持精确的时间计算。
工业环境对实时性要求极高,我们需要一个高效的数据采集引擎:
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。
这是整个系统的亮点 - 让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.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);
}
💰 商业价值:通过准确的故障预测,企业可以从"被动维修"转向"主动维护",显著降低停机成本。
启动系统后,你将看到:


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简化部署流程
这套系统不仅展示了C#在工业物联网领域的技术实力,更重要的是提供了一个可扩展的架构模板。无论你是在做设备监控、智能制造还是数字化转型项目,这些代码模式都能直接应用。
互动时间:
觉得这个工业4.0解决方案对你有启发吗?请转发给更多正在做物联网开发的同行,让我们一起推动C#在工业智能化领域的应用!
相关信息
通过网盘分享的文件:AppAiIndustrialSensorAnalyzer.zip 链接: https://pan.baidu.com/s/194Yz5-gaXaecj3KEiV04gA?pwd=tuxr 提取码: tuxr --来自百度网盘超级会员v9的分享
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!