-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOutageDetection.elm
71 lines (63 loc) · 2.46 KB
/
OutageDetection.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module OutageDetection exposing (NodeOutage, detectAllOutages)
import DataDecoding exposing (SensorMeasurement)
import DateTime exposing (DateTime)
import Maybe.Extra
import Time exposing (Posix)
import Dict
import Dict.Extra
type alias NodeOutage = {
affectedNodeId : String,
startTimestamp : DateTime,
duration : Posix
}
-- ASSUMPTION: we will detect only temperature outages
detectAllOutages : Int -> List SensorMeasurement -> List NodeOutage
detectAllOutages minOutageLength allSensorMeasurements =
let
temperatureMeasurements = allSensorMeasurements
|> List.filter (\sm -> sm.parameter == "temperature")
measurementsByNodes = groupMeasurementByNodes temperatureMeasurements
outagesByNodes = measurementsByNodes |>
Dict.map (\_ nodeMeasurements ->
let
sortedNodeMeasurements =
nodeMeasurements |> List.sortWith (\sm1 sm2 -> DateTime.compare sm1.timestamp sm2.timestamp)
in
detectSingleNodeOutages (outageDuration minOutageLength) sortedNodeMeasurements []
)
in
outagesByNodes
|> Dict.toList
|> List.concatMap Tuple.second
groupMeasurementByNodes : List SensorMeasurement -> Dict.Dict String (List SensorMeasurement)
groupMeasurementByNodes measurements =
Dict.Extra.groupBy .nodeId measurements
detectSingleNodeOutages : Posix -> List SensorMeasurement -> List NodeOutage -> List NodeOutage
detectSingleNodeOutages minOutageDuration singleNodeMeasurements acc =
case singleNodeMeasurements of
sm1 :: sm2 :: rest ->
let
maybeOutage = detectDiff sm1 sm2 minOutageDuration
maybeOutageList = Maybe.Extra.toList maybeOutage
in
detectSingleNodeOutages minOutageDuration (sm2 :: rest) (maybeOutageList ++ acc)
_ ->
acc
detectDiff : SensorMeasurement -> SensorMeasurement -> Posix -> Maybe NodeOutage
detectDiff sm1 sm2 minOutageDuration =
let
t1 = DateTime.toPosix sm1.timestamp
t2 = DateTime.toPosix sm2.timestamp
diffMs = Time.posixToMillis t2 - Time.posixToMillis t1
in
if diffMs > Time.posixToMillis minOutageDuration then
Just {
affectedNodeId = sm1.nodeId,
startTimestamp = sm1.timestamp,
duration = Time.millisToPosix diffMs
}
else
Nothing
outageDuration : Int -> Posix
outageDuration minOutageLength =
Time.millisToPosix (1000 * 60 * minOutageLength)