From 8cde891ba26348fdf0ba822790d476a2763bd687 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Sun, 15 Mar 2026 17:31:50 +0100 Subject: [PATCH] Add second remote --- NightLight.Core.Tests/FakeHome.fs | 15 ++++++++++++++- .../InteractionListGenerators.fs | 6 +++++- NightLight.Core.Tests/NightLightTests.fs | 15 ++++++++++----- NightLight.Core/Models.fs | 2 ++ NightLight.Core/NightLightStateMachine.fs | 8 ++++++++ NightLight.Core/ZigbeeCommands.fs | 3 +-- NightLight.Core/ZigbeeEvents.fs | 9 +++++++++ NightLight/Program.fs | 4 ++-- 8 files changed, 51 insertions(+), 11 deletions(-) diff --git a/NightLight.Core.Tests/FakeHome.fs b/NightLight.Core.Tests/FakeHome.fs index 6642cc3..f7042b7 100644 --- a/NightLight.Core.Tests/FakeHome.fs +++ b/NightLight.Core.Tests/FakeHome.fs @@ -11,7 +11,10 @@ type BedroomControllingRemoteInteraction = | RemotePressedOffButton | RemotePressedLeftButton -type LivingRoomControllingRemoteAction = | RemotePressedRightButton +type LivingRoomControllingRemoteAction = + | RemotePressedRightButton + | LivingRoomRemotePressedOnButton + | LivingRoomRemotePressedOffButton type HumanInteraction = | LightPoweredOn of Light @@ -145,6 +148,16 @@ type FakeHome() = Payload = @"{ ""action"": ""arrow_right_click"" }" } |> ReceivedZigbeeEvent |> onEventPublished.Trigger + | LivingRoomControllingRemoteInteraction LivingRoomRemotePressedOnButton -> + { Topic = $"zigbee2mqtt/{livingRoomRemoteControlFriendlyName.Get}" + Payload = @"{ ""action"": ""on"" }" } + |> ReceivedZigbeeEvent + |> onEventPublished.Trigger + | LivingRoomControllingRemoteInteraction LivingRoomRemotePressedOffButton -> + { Topic = $"zigbee2mqtt/{livingRoomRemoteControlFriendlyName.Get}" + Payload = @"{ ""action"": ""off"" }" } + |> ReceivedZigbeeEvent + |> onEventPublished.Trigger | TimeChanged newTime -> newTime |> Event.TimeChanged |> onEventPublished.Trigger type FakeHome with diff --git a/NightLight.Core.Tests/InteractionListGenerators.fs b/NightLight.Core.Tests/InteractionListGenerators.fs index a0b29df..cdd72d1 100644 --- a/NightLight.Core.Tests/InteractionListGenerators.fs +++ b/NightLight.Core.Tests/InteractionListGenerators.fs @@ -40,7 +40,11 @@ let private genRemoteInteraction = [ Gen.elements [ RemotePressedOnButton; RemotePressedOffButton; RemotePressedLeftButton ] |> Gen.map BedroomControllingRemoteInteraction - Gen.constant (LivingRoomControllingRemoteInteraction RemotePressedRightButton) ] + Gen.elements + [ RemotePressedRightButton + LivingRoomRemotePressedOnButton + LivingRoomRemotePressedOffButton ] + |> Gen.map LivingRoomControllingRemoteInteraction ] let private genInteraction = Gen.frequency [ 4, genTimeChanged; 1, genHumanInteraction; 1, genRemoteInteraction ] diff --git a/NightLight.Core.Tests/NightLightTests.fs b/NightLight.Core.Tests/NightLightTests.fs index f6946c7..6ffcb01 100644 --- a/NightLight.Core.Tests/NightLightTests.fs +++ b/NightLight.Core.Tests/NightLightTests.fs @@ -98,11 +98,16 @@ type NightLightTests() = let livingRoomLightsToggledOn = interactions - |> Seq.filter (function - | Interaction.LivingRoomControllingRemoteInteraction RemotePressedRightButton -> true - | _ -> false) - |> Seq.length - |> fun rightPresses -> rightPresses % 2 = 0 + |> Seq.choose (function + | Interaction.LivingRoomControllingRemoteInteraction interaction -> Some interaction + | _ -> None) + |> Seq.fold + (fun state interaction -> + match interaction with + | RemotePressedRightButton -> not state + | LivingRoomRemotePressedOnButton -> true + | LivingRoomRemotePressedOffButton -> false) + true let isExpectedOn light = match light with diff --git a/NightLight.Core/Models.fs b/NightLight.Core/Models.fs index 122429b..7d03e45 100644 --- a/NightLight.Core/Models.fs +++ b/NightLight.Core/Models.fs @@ -83,6 +83,8 @@ let lights = let remoteControlFriendlyName = DeviceFriendlyName "Fjärrkontroll" +let livingRoomRemoteControlFriendlyName = DeviceFriendlyName "Living Room Remote" + type internal State = | On | Off diff --git a/NightLight.Core/NightLightStateMachine.fs b/NightLight.Core/NightLightStateMachine.fs index a09c418..4ed8d9e 100644 --- a/NightLight.Core/NightLightStateMachine.fs +++ b/NightLight.Core/NightLightStateMachine.fs @@ -111,6 +111,14 @@ type NightLightStateMachine private (maybeState: NightLightState option) = currentState |> withInvertedStateFor LivingRoomWallLamp |> withInvertedStateFor LivingRoomFloorLamp + | PressedLivingRoomOn -> + currentState + |> withStateFor LivingRoomWallLamp On + |> withStateFor LivingRoomFloorLamp On + | PressedLivingRoomOff -> + currentState + |> withStateFor LivingRoomWallLamp Off + |> withStateFor LivingRoomFloorLamp Off NightLightStateMachine(Some newNightLightState), generateZigbeeCommandsForDifference (Some currentState) newNightLightState diff --git a/NightLight.Core/ZigbeeCommands.fs b/NightLight.Core/ZigbeeCommands.fs index dd13aff..9f16656 100644 --- a/NightLight.Core/ZigbeeCommands.fs +++ b/NightLight.Core/ZigbeeCommands.fs @@ -15,8 +15,7 @@ let generateStateCommand state light = | On -> "ON" | Off -> "OFF" - if (lightProps light).Bulb = IkeaBulb then - commandObj["transition"] <- 0 + commandObj["transition"] <- 0 commandObj.ToJsonString() |> toZigbeeCommand light diff --git a/NightLight.Core/ZigbeeEvents.fs b/NightLight.Core/ZigbeeEvents.fs index 13e4301..700df43 100644 --- a/NightLight.Core/ZigbeeEvents.fs +++ b/NightLight.Core/ZigbeeEvents.fs @@ -9,6 +9,8 @@ type Action = | PressedOff | PressedLeft | PressedRight + | PressedLivingRoomOn + | PressedLivingRoomOff type ZigbeeEvent = | DeviceAnnounce of DeviceFriendlyName @@ -41,5 +43,12 @@ let parseZigbeeEvent (message: Message) = | Some(JsonValue.String "arrow_right_click") -> Ok(ButtonPress PressedRight) | Some _ -> Error InvalidActionField | None -> Error MissingActionField + | "zigbee2mqtt/Living Room Remote" -> + return! + match jsonValue.TryGetProperty "action" with + | Some(JsonValue.String "on") -> Ok(ButtonPress PressedLivingRoomOn) + | Some(JsonValue.String "off") -> Ok(ButtonPress PressedLivingRoomOff) + | Some _ -> Error InvalidActionField + | None -> Error MissingActionField | _ -> return! Error <| UnknownTopic message.Topic } diff --git a/NightLight/Program.fs b/NightLight/Program.fs index eecfc4b..e011f3b 100644 --- a/NightLight/Program.fs +++ b/NightLight/Program.fs @@ -1,4 +1,4 @@ -open System +open System open System.Text open System.Threading open System.Threading.Tasks @@ -103,7 +103,7 @@ let mainAsync _ = :> Task) do! - [ "zigbee2mqtt/bridge/event"; $"zigbee2mqtt/{remoteControlFriendlyName.Get}" ] + [ "zigbee2mqtt/bridge/event"; $"zigbee2mqtt/{remoteControlFriendlyName.Get}"; $"zigbee2mqtt/{livingRoomRemoteControlFriendlyName.Get}" ] |> Seq.map (fun topic -> async { return! mqttClient.SubscribeAsync topic |> Async.AwaitTask }) |> Async.Sequential |> Async.Ignore