Hard code the lights controlled by the remote

This commit is contained in:
Sven van Heugten 2026-02-27 17:59:25 +01:00
parent 50c8a413a6
commit 3855439d82
5 changed files with 40 additions and 37 deletions

View file

@ -149,12 +149,15 @@ type FakeHome with
member this.NonRemotelyControlledLightStates = member this.NonRemotelyControlledLightStates =
this.LightStates this.LightStates
|> Seq.filter (fst >> lightProps >> _.ControlledWithRemote >> (=) NonRemote) |> Seq.filter (fun (light, _) ->
light = VardagsrumVagglampa
|| light = VardagsrumGolvlampa
|| light = BadrumTaklampa)
|> Seq.toList |> Seq.toList
member this.RemotelyControlledLightStates = member this.RemotelyControlledLightStates =
this.LightStates this.LightStates
|> Seq.filter (fst >> lightProps >> _.ControlledWithRemote >> (<>) NonRemote) |> Seq.filter (fun (light, _) -> light = VardagsrumFonsterlampa || light = SovrumNattduksbordlampa)
|> Seq.toList |> Seq.toList
member this.Label = member this.Label =

View file

@ -9,27 +9,30 @@ type ArbitraryLight =
type ArbitraryNonRemotelyControlledLight = type ArbitraryNonRemotelyControlledLight =
static member Light() = static member Light() =
lights lights
|> Seq.filter (fun light -> (lightProps light).ControlledWithRemote.IsNonRemote) |> Seq.filter (fun light ->
light = VardagsrumVagglampa
|| light = VardagsrumGolvlampa
|| light = BadrumTaklampa)
|> Gen.elements |> Gen.elements
|> Arb.fromGen |> Arb.fromGen
type ArbitraryLeftRemotelyControlledLight = type ArbitraryLeftRemotelyControlledLight =
static member Light() = static member Light() =
lights lights
|> Seq.filter (fun light -> (lightProps light).ControlledWithRemote.IsRemoteLeft) |> Seq.filter (fun light -> light = SovrumNattduksbordlampa)
|> Gen.elements |> Gen.elements
|> Arb.fromGen |> Arb.fromGen
type ArbitraryRightRemotelyControlledLight = type ArbitraryRightRemotelyControlledLight =
static member Light() = static member Light() =
lights lights
|> Seq.filter (fun light -> (lightProps light).ControlledWithRemote.IsRemoteRight) |> Seq.filter (fun light -> light = VardagsrumFonsterlampa)
|> Gen.elements |> Gen.elements
|> Arb.fromGen |> Arb.fromGen
type ArbitraryRemotelyControlledLight = type ArbitraryRemotelyControlledLight =
static member Light() = static member Light() =
lights lights
|> Seq.filter (fun light -> (lightProps light).ControlledWithRemote.IsNonRemote |> not) |> Seq.filter (fun light -> light = VardagsrumFonsterlampa || light = SovrumNattduksbordlampa)
|> Gen.elements |> Gen.elements
|> Arb.fromGen |> Arb.fromGen

View file

@ -52,7 +52,7 @@ type NightLightTests() =
&& time <= endOfAlarm && time <= endOfAlarm
let scaledForAlarm light brightness = let scaledForAlarm light brightness =
if (lightProps light).ControlledWithRemote <> NonRemote && alarm then if (light = VardagsrumFonsterlampa || light = SovrumNattduksbordlampa) && alarm then
float brightness * ((time - startOfDay) / (endOfAlarm - startOfDay)) |> byte float brightness * ((time - startOfDay) / (endOfAlarm - startOfDay)) |> byte
else else
brightness brightness
@ -108,8 +108,11 @@ type NightLightTests() =
let allOn (ls: (Light * LightState) seq) = ls |> Seq.forall (snd >> _.IsOn) let allOn (ls: (Light * LightState) seq) = ls |> Seq.forall (snd >> _.IsOn)
let allOff (ls: (Light * LightState) seq) = ls |> Seq.forall (snd >> _.IsOff) let allOff (ls: (Light * LightState) seq) = ls |> Seq.forall (snd >> _.IsOff)
let controlledBy remote ls = let controlledByLeft ls =
ls |> Seq.filter (fst >> lightProps >> _.ControlledWithRemote >> (=) remote) ls |> Seq.filter (fun (light, _) -> light = SovrumNattduksbordlampa)
let controlledByRight ls =
ls |> Seq.filter (fun (light, _) -> light = VardagsrumFonsterlampa)
let maybeLastRemoteInteraction = tryGetLastRemoteInteraction interactions let maybeLastRemoteInteraction = tryGetLastRemoteInteraction interactions
@ -123,8 +126,8 @@ type NightLightTests() =
| Some(_, RemotePressedOnButton) -> remotelyControlledLightsWithPower |> allOn | Some(_, RemotePressedOnButton) -> remotelyControlledLightsWithPower |> allOn
| Some(_, RemotePressedOffButton) -> remotelyControlledLightsWithPower |> allOff | Some(_, RemotePressedOffButton) -> remotelyControlledLightsWithPower |> allOff
| Some(_, RemotePressedLeftButton) -> | Some(_, RemotePressedLeftButton) ->
remotelyControlledLightsWithPower |> controlledBy RemoteLeft |> allOn remotelyControlledLightsWithPower |> controlledByLeft |> allOn
&& remotelyControlledLightsWithPower |> controlledBy RemoteRight |> allOff && remotelyControlledLightsWithPower |> controlledByRight |> allOff
| None -> remotelyControlledLightsWithPower |> allOn | None -> remotelyControlledLightsWithPower |> allOn
|> Prop.collect $"last remote interaction is {maybeLastRemoteInteraction |> Option.map snd}" |> Prop.collect $"last remote interaction is {maybeLastRemoteInteraction |> Option.map snd}"
|> Prop.collect $"{remotelyControlledLightsWithPower.Length} remotely controlled light(s) with power" |> Prop.collect $"{remotelyControlledLightsWithPower.Length} remotely controlled light(s) with power"

View file

@ -40,11 +40,6 @@ type DeviceFriendlyName =
match this with match this with
| DeviceFriendlyName deviceFriendlyName -> deviceFriendlyName | DeviceFriendlyName deviceFriendlyName -> deviceFriendlyName
type LightControl =
| NonRemote
| RemoteLeft
| RemoteRight
type Light = type Light =
| VardagsrumFonsterlampa | VardagsrumFonsterlampa
| VardagsrumVagglampa | VardagsrumVagglampa
@ -55,36 +50,30 @@ type Light =
type LightProps = type LightProps =
{ FriendlyName: DeviceFriendlyName { FriendlyName: DeviceFriendlyName
Room: Room Room: Room
Bulb: Bulb Bulb: Bulb }
ControlledWithRemote: LightControl }
let lightProps light = let lightProps light =
match light with match light with
| VardagsrumFonsterlampa -> | VardagsrumFonsterlampa ->
{ FriendlyName = DeviceFriendlyName "Vardagsrum - Fönsterlampa" { FriendlyName = DeviceFriendlyName "Vardagsrum - Fönsterlampa"
Room = Bedroom Room = Bedroom
Bulb = IkeaBulb Bulb = IkeaBulb }
ControlledWithRemote = RemoteRight }
| VardagsrumVagglampa -> | VardagsrumVagglampa ->
{ FriendlyName = DeviceFriendlyName "Vardagsrum - Vägglampa" { FriendlyName = DeviceFriendlyName "Vardagsrum - Vägglampa"
Room = LivingRoom Room = LivingRoom
Bulb = PaulmannBulb Bulb = PaulmannBulb }
ControlledWithRemote = NonRemote }
| VardagsrumGolvlampa -> | VardagsrumGolvlampa ->
{ FriendlyName = DeviceFriendlyName "Vardagsrum - Golvlampa" { FriendlyName = DeviceFriendlyName "Vardagsrum - Golvlampa"
Room = LivingRoom Room = LivingRoom
Bulb = PaulmannBulb Bulb = PaulmannBulb }
ControlledWithRemote = NonRemote }
| BadrumTaklampa -> | BadrumTaklampa ->
{ FriendlyName = DeviceFriendlyName "Badrum - Taklampa" { FriendlyName = DeviceFriendlyName "Badrum - Taklampa"
Room = Bathroom Room = Bathroom
Bulb = IkeaBulb Bulb = IkeaBulb }
ControlledWithRemote = NonRemote }
| SovrumNattduksbordlampa -> | SovrumNattduksbordlampa ->
{ FriendlyName = DeviceFriendlyName "Sovrum - Nattduksbordlampa" { FriendlyName = DeviceFriendlyName "Sovrum - Nattduksbordlampa"
Room = Bedroom Room = Bedroom
Bulb = IkeaBulb Bulb = IkeaBulb }
ControlledWithRemote = RemoteLeft }
let lights = let lights =
[ VardagsrumFonsterlampa [ VardagsrumFonsterlampa

View file

@ -13,11 +13,17 @@ let internal tryFindLight friendlyName =
let internal generateZigbeeCommandsToFixLight (light: Light) (desiredLightState: LightState) = let internal generateZigbeeCommandsToFixLight (light: Light) (desiredLightState: LightState) =
seq { seq {
match (lightProps light).ControlledWithRemote, desiredLightState.State with let isRemoteControlled =
| NonRemote, On -> () light = VardagsrumFonsterlampa || light = SovrumNattduksbordlampa
| NonRemote, Off -> failwith $"Unexpectly trying to turn off {light}. It's not remote-controlled."
| _, On when (lightProps light).Bulb = IkeaBulb -> () // Rely on the brightness command for turning it on if not isRemoteControlled then
| _, _ -> yield generateStateCommand desiredLightState.State light match desiredLightState.State with
| On -> ()
| Off -> failwith $"Unexpectly trying to turn off {light}. It's not remote-controlled."
else if desiredLightState.State = On && (lightProps light).Bulb = IkeaBulb then
() // Rely on the brightness command for turning it on
else
yield generateStateCommand desiredLightState.State light
if desiredLightState.State = On then if desiredLightState.State = On then
yield generateBrightnessCommand light desiredLightState.Brightness yield generateBrightnessCommand light desiredLightState.Brightness
@ -51,7 +57,7 @@ let internal createOrUpdateNightLightState
light, light,
{ Color = color { Color = color
Brightness = Brightness =
if alarm && (lightProps light).ControlledWithRemote <> NonRemote then if alarm && (light = VardagsrumFonsterlampa || light = SovrumNattduksbordlampa) then
brightness.Scale(getAlarmWeight time) brightness.Scale(getAlarmWeight time)
else else
brightness brightness
@ -73,7 +79,7 @@ let internal withStateFor (light: Light) (state: State) (oldNightLightState: Nig
let internal withStateForRemoteControlledLights (state: State) (oldNightLightState: NightLightState) = let internal withStateForRemoteControlledLights (state: State) (oldNightLightState: NightLightState) =
lights lights
|> Seq.filter (fun light -> (lightProps light).ControlledWithRemote.IsNonRemote |> not) |> Seq.filter (fun light -> light = VardagsrumFonsterlampa || light = SovrumNattduksbordlampa)
|> Seq.fold (fun acc light -> acc |> withStateFor light state) oldNightLightState |> Seq.fold (fun acc light -> acc |> withStateFor light state) oldNightLightState
let internal withAlarmOff (oldNightLightState: NightLightState) = let internal withAlarmOff (oldNightLightState: NightLightState) =
@ -114,8 +120,7 @@ type NightLightStateMachine private (maybeState: NightLightState option) =
| PressedOff -> currentState |> withAlarmOff |> withStateForRemoteControlledLights Off | PressedOff -> currentState |> withAlarmOff |> withStateForRemoteControlledLights Off
| PressedLeft -> | PressedLeft ->
let lightThatShouldBeOn = let lightThatShouldBeOn =
lights lights |> Seq.find (fun light -> light = SovrumNattduksbordlampa)
|> Seq.find (fun light -> (lightProps light).ControlledWithRemote = RemoteLeft)
currentState currentState
|> withAlarmOff |> withAlarmOff