| | | 1 | | using Intentum.Core.Behavior; |
| | | 2 | | using Intentum.Core.Models; |
| | | 3 | | |
| | | 4 | | namespace Intentum.Core.IoT; |
| | | 5 | | |
| | | 6 | | public static class IoTRules |
| | | 7 | | { |
| | | 8 | | public static Func<BehaviorSpace, RuleMatch?> DeviceFailure( |
| | 4 | 9 | | double confidence = 0.9) => space => |
| | 3 | 10 | | { |
| | 3 | 11 | | var errors = space.Events.Count(e => |
| | 8 | 12 | | e.Action.Contains("error", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 13 | | var gaps = space.Events.Count(e => |
| | 8 | 14 | | e.Action.Contains("telemetry.gap", StringComparison.OrdinalIgnoreCase)); |
| | 4 | 15 | | |
| | 3 | 16 | | if (errors >= 1 && gaps >= 1) |
| | 1 | 17 | | return new RuleMatch("DeviceFailure", confidence, |
| | 1 | 18 | | $"Errors: {errors}, telemetry gaps: {gaps}"); |
| | 2 | 19 | | if (errors >= 3) |
| | 1 | 20 | | return new RuleMatch("DeviceFailure", confidence * 0.7, |
| | 1 | 21 | | $"Multiple errors: {errors}, no gaps detected"); |
| | 1 | 22 | | return null; |
| | 7 | 23 | | }; |
| | | 24 | | |
| | | 25 | | public static Func<BehaviorSpace, RuleMatch?> SecurityBreach( |
| | 3 | 26 | | double confidence = 0.95) => space => |
| | 2 | 27 | | { |
| | 2 | 28 | | var signals = space.Events.Count(e => |
| | 5 | 29 | | e.Action.Contains("access.unauthorized", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 30 | | e.Action.Contains("location.anomaly", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 31 | | e.Action.Contains("firmware.unauthorized", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 32 | | e.Action.Contains("port.scan.detected", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 33 | | |
| | 2 | 34 | | if (signals >= 2) |
| | 1 | 35 | | return new RuleMatch("SecurityBreach", confidence, |
| | 1 | 36 | | $"Security signals: {signals}"); |
| | 1 | 37 | | return null; |
| | 5 | 38 | | }; |
| | | 39 | | |
| | | 40 | | public static Func<BehaviorSpace, RuleMatch?> MaintenanceRequired( |
| | 3 | 41 | | double confidence = 0.85) => space => |
| | 2 | 42 | | { |
| | 2 | 43 | | var signals = space.Events.Count(e => |
| | 5 | 44 | | e.Action.Contains("performance.degrading", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 45 | | e.Action.Contains("usage.threshold.exceeded", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 46 | | e.Action.Contains("temperature.high", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 47 | | e.Action.Contains("battery.low", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 48 | | |
| | 2 | 49 | | if (signals >= 2) |
| | 1 | 50 | | return new RuleMatch("MaintenanceRequired", confidence, |
| | 1 | 51 | | $"Maintenance signals: {signals}"); |
| | 1 | 52 | | return null; |
| | 5 | 53 | | }; |
| | | 54 | | |
| | | 55 | | public static Func<BehaviorSpace, RuleMatch?> AnomalousSensorReading( |
| | 3 | 56 | | double confidence = 0.8) => space => |
| | 2 | 57 | | { |
| | 2 | 58 | | var anomalies = space.Events.Count(e => |
| | 5 | 59 | | e.Action.Contains("reading.outlier", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 60 | | e.Action.Contains("reading.rapid.change", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 61 | | e.Action.Contains("reading.calibration.off", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 62 | | |
| | 2 | 63 | | if (anomalies >= 2) |
| | 1 | 64 | | return new RuleMatch("AnomalousSensorReading", confidence, |
| | 1 | 65 | | $"Anomalous readings: {anomalies}"); |
| | 1 | 66 | | return null; |
| | 5 | 67 | | }; |
| | | 68 | | |
| | | 69 | | public static Func<BehaviorSpace, RuleMatch?> FirmwareOutdated( |
| | 3 | 70 | | double confidence = 0.8) => space => |
| | 2 | 71 | | { |
| | 2 | 72 | | var signals = space.Events.Count(e => |
| | 3 | 73 | | e.Action.Contains("firmware.version.mismatch", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 74 | | e.Action.Contains("firmware.update.failed", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 75 | | e.Action.Contains("firmware.deprecated", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 76 | | e.Action.Contains("security.patch.missing", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 77 | | |
| | 2 | 78 | | if (signals >= 1) |
| | 1 | 79 | | return new RuleMatch("FirmwareOutdated", confidence, |
| | 1 | 80 | | $"Firmware signals: {signals}"); |
| | 1 | 81 | | return null; |
| | 5 | 82 | | }; |
| | | 83 | | |
| | | 84 | | public static Func<BehaviorSpace, RuleMatch?> NetworkCongestion( |
| | 3 | 85 | | double confidence = 0.85) => space => |
| | 2 | 86 | | { |
| | 2 | 87 | | var signals = space.Events.Count(e => |
| | 5 | 88 | | e.Action.Contains("network.latency.spike", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 89 | | e.Action.Contains("network.packet.loss", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 90 | | e.Action.Contains("network.throughput.drop", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 91 | | e.Action.Contains("network.connection.intermittent", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 92 | | |
| | 2 | 93 | | if (signals >= 2) |
| | 1 | 94 | | return new RuleMatch("NetworkCongestion", confidence, |
| | 1 | 95 | | $"Network signals: {signals}"); |
| | 1 | 96 | | return null; |
| | 5 | 97 | | }; |
| | | 98 | | |
| | | 99 | | public static Func<BehaviorSpace, RuleMatch?> PowerFluctuation( |
| | 3 | 100 | | double confidence = 0.8) => space => |
| | 2 | 101 | | { |
| | 2 | 102 | | var signals = space.Events.Count(e => |
| | 3 | 103 | | e.Action.Contains("power.voltage.anomaly", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 104 | | e.Action.Contains("power.battery.drain", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 105 | | e.Action.Contains("power.surge.detected", StringComparison.OrdinalIgnoreCase) || |
| | 3 | 106 | | e.Action.Contains("power.brownout", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 107 | | |
| | 2 | 108 | | if (signals >= 1) |
| | 1 | 109 | | return new RuleMatch("PowerFluctuation", confidence, |
| | 1 | 110 | | $"Power signals: {signals}"); |
| | 1 | 111 | | return null; |
| | 5 | 112 | | }; |
| | | 113 | | |
| | | 114 | | public static Func<BehaviorSpace, RuleMatch?> ConfigurationDrift( |
| | 3 | 115 | | double confidence = 0.85) => space => |
| | 2 | 116 | | { |
| | 2 | 117 | | var signals = space.Events.Count(e => |
| | 5 | 118 | | e.Action.Contains("config.setting.changed", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 119 | | e.Action.Contains("config.compliance.violation", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 120 | | e.Action.Contains("config.unexpected.change", StringComparison.OrdinalIgnoreCase) || |
| | 5 | 121 | | e.Action.Contains("config.rollback", StringComparison.OrdinalIgnoreCase)); |
| | 3 | 122 | | |
| | 2 | 123 | | if (signals >= 2) |
| | 1 | 124 | | return new RuleMatch("ConfigurationDrift", confidence, |
| | 1 | 125 | | $"Configuration signals: {signals}"); |
| | 1 | 126 | | return null; |
| | 5 | 127 | | }; |
| | | 128 | | |
| | | 129 | | public static IReadOnlyList<Func<BehaviorSpace, RuleMatch?>> AllRules() => |
| | 1 | 130 | | [ |
| | 1 | 131 | | SecurityBreach(), |
| | 1 | 132 | | DeviceFailure(), |
| | 1 | 133 | | MaintenanceRequired(), |
| | 1 | 134 | | AnomalousSensorReading(), |
| | 1 | 135 | | FirmwareOutdated(), |
| | 1 | 136 | | NetworkCongestion(), |
| | 1 | 137 | | PowerFluctuation(), |
| | 1 | 138 | | ConfigurationDrift() |
| | 1 | 139 | | ]; |
| | | 140 | | } |