Implement FakeHome
This commit is contained in:
parent
83b716a509
commit
fc069edf31
4 changed files with 150 additions and 0 deletions
81
NightLight.Core.Tests/FakeHome.fs
Normal file
81
NightLight.Core.Tests/FakeHome.fs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
namespace NightLight.Core.Tests
|
||||
|
||||
open System
|
||||
open System.Text.RegularExpressions
|
||||
open NightLight.Core.Models
|
||||
open FsToolkit.ErrorHandling
|
||||
open FSharp.Data
|
||||
|
||||
type HumanInteraction =
|
||||
| LightTurnedOn of Light
|
||||
| LightTurnedOff of Light
|
||||
|
||||
type Interaction =
|
||||
| HumanInteraction of HumanInteraction
|
||||
| TimeChanged of DateTime
|
||||
|
||||
type LightState =
|
||||
| Off
|
||||
| On of Brightness: byte
|
||||
|
||||
type FakeLight(light: Light) =
|
||||
let mutable hasPower = false
|
||||
let mutable brightness: byte = 255uy
|
||||
|
||||
member _.LightWithState = light, if hasPower then On brightness else Off
|
||||
|
||||
member _.TurnOn() = hasPower <- true
|
||||
|
||||
member _.TurnOff() = hasPower <- false
|
||||
|
||||
member _.SetBrightness(newBrightness: byte) =
|
||||
if hasPower then
|
||||
brightness <- newBrightness
|
||||
|
||||
type FakeHome(now: DateTime) =
|
||||
let nightLightStateMachine = NightLightStateMachine now
|
||||
|
||||
let friendlyNameToFakeLight =
|
||||
lights
|
||||
|> Seq.map (fun light -> light.FriendlyName, FakeLight light)
|
||||
|> Map.ofSeq
|
||||
|
||||
let processCommand command =
|
||||
option {
|
||||
let! friendlyName =
|
||||
let m = Regex.Match(command.Topic, "^zigbee2mqtt/(.+)/set$")
|
||||
if m.Success then Some m.Groups.[1].Value else None
|
||||
|
||||
let! fakeLight = Map.tryFind friendlyName friendlyNameToFakeLight
|
||||
|
||||
let parsedPayload = JsonValue.Parse command.Payload
|
||||
|
||||
match parsedPayload.TryGetProperty "brightness" with
|
||||
| Some(JsonValue.Number newBrightness) -> fakeLight.SetBrightness(byte newBrightness)
|
||||
| None -> ()
|
||||
| value -> failwith $"Unexpected brightness value {value}"
|
||||
}
|
||||
|> ignore
|
||||
|
||||
member _.LightStates = friendlyNameToFakeLight.Values |> Seq.map _.LightWithState
|
||||
|
||||
member _.Interact(interaction: Interaction) : Result<unit, ParseEventError> =
|
||||
result {
|
||||
match interaction with
|
||||
| HumanInteraction(LightTurnedOn light) ->
|
||||
friendlyNameToFakeLight[light.FriendlyName].TurnOn()
|
||||
|
||||
do!
|
||||
{ Topic = "zigbee2mqtt/bridge/event"
|
||||
Payload =
|
||||
$@"{{
|
||||
""type"": ""device_announce"",
|
||||
""data"": {{ ""friendly_name"": ""{light.FriendlyName}"" }}
|
||||
}}" }
|
||||
|> nightLightStateMachine.SendMessage
|
||||
| HumanInteraction(LightTurnedOff light) -> friendlyNameToFakeLight[light.FriendlyName].TurnOff()
|
||||
| TimeChanged time -> do! nightLightStateMachine.ChangeTime time
|
||||
|
||||
nightLightStateMachine.TransmittedCommands |> Seq.iter processCommand
|
||||
nightLightStateMachine.ClearTransmittedCommands()
|
||||
}
|
||||
27
NightLight.Core.Tests/NightLight.Core.Tests.fsproj
Normal file
27
NightLight.Core.Tests/NightLight.Core.Tests.fsproj
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="NightLightStateMachine.fs" />
|
||||
<Compile Include="FakeHome.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageReference Include="FsCheck" Version="3.3.0" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="3.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NightLight.Core/NightLight.Core.fsproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
28
NightLight.Core.Tests/NightLightStateMachine.fs
Normal file
28
NightLight.Core.Tests/NightLightStateMachine.fs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
namespace NightLight.Core.Tests
|
||||
|
||||
open System
|
||||
open System.Collections.Generic
|
||||
open FsToolkit.ErrorHandling
|
||||
open NightLight.Core.Models
|
||||
open NightLight.Core.Core
|
||||
|
||||
type NightLightStateMachine(now: DateTime) =
|
||||
let mutable state = { Time = now }
|
||||
|
||||
let transmittedCommands = new List<Message>()
|
||||
|
||||
let sendEvent event =
|
||||
result {
|
||||
let! newState, commands = onEventReceived state event
|
||||
state <- newState
|
||||
transmittedCommands.AddRange commands
|
||||
}
|
||||
|
||||
member _.TransmittedCommands = transmittedCommands.AsReadOnly()
|
||||
|
||||
member _.SendMessage message =
|
||||
ReceivedZigbeeEvent message |> sendEvent
|
||||
|
||||
member _.ChangeTime time = TimeChanged time |> sendEvent
|
||||
|
||||
member _.ClearTransmittedCommands() = transmittedCommands.Clear()
|
||||
Loading…
Add table
Add a link
Reference in a new issue