Implement the 'Left' button on the remote

This commit is contained in:
Sven van Heugten 2026-01-14 19:49:34 +01:00
parent 6ecb6d07ac
commit 2950b21488
7 changed files with 91 additions and 19 deletions

View file

@ -9,6 +9,7 @@ open FSharp.Data
type RemoteInteraction =
| RemotePressedOnButton
| RemotePressedOffButton
| RemotePressedLeftButton
type HumanInteraction =
| LightPoweredOn of Light
@ -133,6 +134,11 @@ type FakeHome() =
Payload = @"{ ""action"": ""off"" }" }
|> ReceivedZigbeeEvent
|> onEventPublished.Trigger
| RemoteInteraction RemotePressedLeftButton ->
{ Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}"
Payload = @"{ ""action"": ""arrow_left_click"" }" }
|> ReceivedZigbeeEvent
|> onEventPublished.Trigger
| TimeChanged newTime -> newTime |> Event.TimeChanged |> onEventPublished.Trigger
type FakeHome with

View file

@ -11,7 +11,7 @@ let private genHumanInteraction biasTowardsLight =
|> Gen.map Interaction.HumanInteraction
let private genRemoteInteraction =
Gen.elements [ RemotePressedOnButton; RemotePressedOffButton ]
Gen.elements [ RemotePressedOnButton; RemotePressedOffButton; RemotePressedLeftButton ]
|> Gen.map RemoteInteraction
let private genInteraction biasTowardsLight =

View file

@ -9,10 +9,31 @@ type ArbitraryLight =
type ArbitraryNonRemotelyControlledLight =
static member Light() =
lights
|> Seq.filter (not << _.ControlledWithRemote)
|> Seq.filter _.ControlledWithRemote.IsNonRemote
|> Gen.elements
|> Arb.fromGen
type ArbitraryLeftRemotelyControlledLight =
static member Light() =
lights
|> Seq.filter _.ControlledWithRemote.IsRemoteLeft
|> Gen.elements
|> Arb.fromGen
type ArbitraryRightRemotelyControlledLight =
static member Light() =
lights
|> Seq.filter _.ControlledWithRemote.IsRemoteRight
|> Gen.elements
|> Arb.fromGen
type ArbitraryRemotelyControlledLight =
static member Light() =
lights |> Seq.filter _.ControlledWithRemote |> Gen.elements |> Arb.fromGen
lights
|> Seq.filter (fun light ->
match light.ControlledWithRemote with
| RemoteLeft -> true
| RemoteRight -> true
| NonRemote -> false)
|> Gen.elements
|> Arb.fromGen

View file

@ -128,3 +128,35 @@ type NightLightTests() =
<| fun interactions ->
let fakeHome = createFakeHomeWithNightLightAndInteract interactions
fakeHome.LightShouldHaveState light _.IsOff
[<Property(Arbitrary = [| typeof<ArbitraryLeftRemotelyControlledLight> |])>]
let ``After pressing 'Left' on the remote, if the remote isn't used again, all left-side remotely controlled lights with power should be on``
(light: Light)
=
concatGens
[ genRandomInteractions light
RemoteInteraction RemotePressedLeftButton |> List.singleton |> Gen.constant
genRandomInteractionsExcept light _.IsRemoteInteraction ]
|> ensureStartsWithTimeChanged
|> ensureLightHasPower light
|> Arb.fromGen
|> Prop.forAll
<| fun interactions ->
let fakeHome = createFakeHomeWithNightLightAndInteract interactions
fakeHome.LightShouldHaveState light _.IsOn
[<Property(Arbitrary = [| typeof<ArbitraryRightRemotelyControlledLight> |])>]
let ``After pressing 'Left' on the remote, if the remote isn't used again and a new day doesn't start, all right-side remotely controlled lights should be off``
(light: Light)
=
concatGens
[ genRandomInteractions light
RemoteInteraction RemotePressedLeftButton |> List.singleton |> Gen.constant
genRandomInteractionsExcept light (fun interaction ->
interaction.IsRemoteInteraction || interaction |> isTimeChangedToAnyDayTime) ]
|> ensureStartsWithTimeChanged
|> Arb.fromGen
|> Prop.forAll
<| fun interactions ->
let fakeHome = createFakeHomeWithNightLightAndInteract interactions
fakeHome.LightShouldHaveState light _.IsOff