diff --git a/NightLight.Core.Tests/FakeHome.fs b/NightLight.Core.Tests/FakeHome.fs index 54bcb7a..bf7aa6c 100644 --- a/NightLight.Core.Tests/FakeHome.fs +++ b/NightLight.Core.Tests/FakeHome.fs @@ -43,8 +43,8 @@ type FakeLight(light: Light) = if hasPower then color <- newColor -type FakeHome(now: DateTime) = - let mutable nightLightStateMachine = NightLightStateMachine now +type FakeHome() = + let mutable nightLightStateMachine = NightLightStateMachine() let assertIsOkAndGet result = match result with diff --git a/NightLight.Core.Tests/NightLightTests.fs b/NightLight.Core.Tests/NightLightTests.fs index e1243ba..612ad49 100644 --- a/NightLight.Core.Tests/NightLightTests.fs +++ b/NightLight.Core.Tests/NightLightTests.fs @@ -27,22 +27,22 @@ module InteractionsHelpers = [ |])>] type NightLightTests() = [] - let ``Brightness should always be under 255`` (now: DateTime) (interactions: Interaction list) = - let fakeHome = FakeHome now + let ``Brightness should always be under 255`` (interactions: Interaction list) = + let fakeHome = FakeHome() fakeHome.Interact interactions fakeHome.ForAllLightsThatAreOn(fun (_, brightness, _) -> brightness < 255uy) [] - let ``Lights should be red during the night`` (now: DateTime) (interactions: Interaction list) = - let fakeHome = FakeHome now + let ``Lights should be red during the night`` (interactions: Interaction list) = + let fakeHome = FakeHome() fakeHome.Interact interactions InteractionsHelpers.isNightAfter interactions ==> fakeHome.ForAllLightsThatAreOn(fun (_, _, color) -> color = Red) [] - let ``Lights should be white or yellow during the day`` (now: DateTime) (interactions: Interaction list) = - let fakeHome = FakeHome now + let ``Lights should be white or yellow during the day`` (interactions: Interaction list) = + let fakeHome = FakeHome() fakeHome.Interact interactions InteractionsHelpers.isDayAfter interactions diff --git a/NightLight.Core/Models.fs b/NightLight.Core/Models.fs index 0d40ef0..7452f6e 100644 --- a/NightLight.Core/Models.fs +++ b/NightLight.Core/Models.fs @@ -17,7 +17,9 @@ type ParseZigbeeEventError = | InvalidFriendlyNameField | UnknownType -type ParseEventError = ParseZigbeeEventError of ParseZigbeeEventError +type OnEventReceivedError = + | ParseZigbeeEventError of ParseZigbeeEventError + | TimeIsUnknown type Room = | Bathroom diff --git a/NightLight.Core/NightLightStateMachine.fs b/NightLight.Core/NightLightStateMachine.fs index 02590e5..f1d5d54 100644 --- a/NightLight.Core/NightLightStateMachine.fs +++ b/NightLight.Core/NightLightStateMachine.fs @@ -17,13 +17,15 @@ let internal generateZigbeeCommandToFixLight partOfDay light = generateZigbeeCommand light.FriendlyName color brightness -type NightLightStateMachine(time: DateTime) = - member this.OnEventReceived(event: Event) : Result = - result { - let partOfDay = getPartOfDay time +type NightLightStateMachine private (maybeTime: DateTime option) = + new() = NightLightStateMachine None - match event with - | ReceivedZigbeeEvent payload -> + member this.OnEventReceived(event: Event) : Result = + result { + let maybePartOfDay = maybeTime |> Option.map getPartOfDay + + match event, maybePartOfDay with + | ReceivedZigbeeEvent payload, Some partOfDay -> let! zigbeeEvent = parseZigbeeEvent payload |> Result.mapError ParseZigbeeEventError return @@ -35,14 +37,15 @@ type NightLightStateMachine(time: DateTime) = match maybeLight with | Some light -> generateZigbeeCommandToFixLight partOfDay light |> Seq.singleton | None -> Seq.empty - | TimeChanged newTime -> - let newState = NightLightStateMachine newTime + | TimeChanged newTime, maybePartOfDay -> + let newState = NightLightStateMachine(Some newTime) let newPartOfDay = getPartOfDay newTime return newState, - if partOfDay <> newPartOfDay then + if maybePartOfDay <> Some newPartOfDay then lights |> Seq.map (generateZigbeeCommandToFixLight newPartOfDay) else Seq.empty + | _, None -> return! Error TimeIsUnknown } diff --git a/NightLight/Program.fs b/NightLight/Program.fs index 90ebd12..04b900f 100644 --- a/NightLight/Program.fs +++ b/NightLight/Program.fs @@ -77,7 +77,14 @@ let mainAsync _ = let mqttClientOptions = MqttClientOptionsBuilder().WithTcpServer(server).Build() let stateLock = new SemaphoreSlim(1, 1) - let mutable state = NightLightStateMachine DateTime.Now + + let! initialState = + let emptyNightLightStateMachine = NightLightStateMachine() + + TimeChanged DateTime.Now + |> handleEvent mqttClient logger emptyNightLightStateMachine + + let mutable state = initialState mqttClient.add_ApplicationMessageReceivedAsync (fun e -> async {