From cf18100ea02ed445d2c27dd9772323f63f133648 Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Sat, 13 Oct 2018 00:22:48 +0200 Subject: [PATCH] Update cellar config. --- .../Cellar/Configuration.cs | 131 ++++++++++++++++-- .../HA4IoT.Contracts.nuget.targets | 2 +- .../Devices/DeviceMessageBrokerService.cs | 12 ++ 3 files changed, 134 insertions(+), 11 deletions(-) diff --git a/Controllers/Examples/HA4IoT.Controller.Main/Cellar/Configuration.cs b/Controllers/Examples/HA4IoT.Controller.Main/Cellar/Configuration.cs index 66edb60e..e0d273e2 100644 --- a/Controllers/Examples/HA4IoT.Controller.Main/Cellar/Configuration.cs +++ b/Controllers/Examples/HA4IoT.Controller.Main/Cellar/Configuration.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.Threading.Tasks; using HA4IoT.Actuators; using HA4IoT.Actuators.Lamps; @@ -7,10 +8,14 @@ using HA4IoT.Automations; using HA4IoT.Components; using HA4IoT.Contracts.Areas; +using HA4IoT.Contracts.Components; using HA4IoT.Contracts.Components.Commands; +using HA4IoT.Contracts.Components.States; using HA4IoT.Contracts.Core; using HA4IoT.Contracts.Hardware; +using HA4IoT.Contracts.Hardware.DeviceMessaging; using HA4IoT.Contracts.Hardware.RaspberryPi; +using HA4IoT.Contracts.Logging; using HA4IoT.Contracts.Messaging; using HA4IoT.Hardware; using HA4IoT.Hardware.Drivers.CCTools.Devices; @@ -28,6 +33,9 @@ internal sealed class Configuration : IConfiguration private readonly SensorFactory _sensorFactory; private readonly AutomationFactory _automationFactory; private readonly IMessageBrokerService _messageBroker; + private readonly IDeviceMessageBrokerService _deviceMessageBrokerService; + + private IArea _area; public Configuration( IDeviceRegistryService deviceRegistryService, @@ -36,12 +44,14 @@ public Configuration( ActuatorFactory actuatorFactory, SensorFactory sensorFactory, AutomationFactory automationFactory, - IMessageBrokerService messageBroker) + IMessageBrokerService messageBroker, + IDeviceMessageBrokerService deviceMessageBrokerService) { _deviceRegistryService = deviceRegistryService ?? throw new ArgumentNullException(nameof(deviceRegistryService)); _gpioService = gpioService ?? throw new ArgumentNullException(nameof(gpioService)); _areaService = areaService ?? throw new ArgumentNullException(nameof(areaService)); _messageBroker = messageBroker ?? throw new ArgumentNullException(nameof(messageBroker)); + _deviceMessageBrokerService = deviceMessageBrokerService ?? throw new ArgumentNullException(nameof(deviceMessageBrokerService)); _actuatorFactory = actuatorFactory ?? throw new ArgumentNullException(nameof(actuatorFactory)); _sensorFactory = sensorFactory ?? throw new ArgumentNullException(nameof(sensorFactory)); _automationFactory = automationFactory ?? throw new ArgumentNullException(nameof(automationFactory)); @@ -52,31 +62,132 @@ public Task ApplyAsync() var hsrt16 = _deviceRegistryService.GetDevice("HSRT16"); var garden = _areaService.RegisterArea("Garden"); + _area = garden; var parkingLotOutput = new LogicalBinaryOutput(hsrt16[HSRT16Pin.Relay6], hsrt16[HSRT16Pin.Relay7], hsrt16[HSRT16Pin.Relay8]); - _actuatorFactory.RegisterLamp(garden, Garden.LampParkingLot, parkingLotOutput); + _actuatorFactory.RegisterLamp(garden, Garden.LampParkingLot, parkingLotOutput).StateChanged += OnStateChanged; // Relay 9 is free. - _actuatorFactory.RegisterSocket(garden, Garden.SocketPavillion, hsrt16[HSRT16Pin.Relay10]); - _actuatorFactory.RegisterLamp(garden, Garden.LampRearArea, hsrt16[HSRT16Pin.Relay11]); - _actuatorFactory.RegisterLamp(garden, Garden.SpotlightRoof, hsrt16[HSRT16Pin.Relay12]); - _actuatorFactory.RegisterLamp(garden, Garden.LampTap, hsrt16[HSRT16Pin.Relay13]); - _actuatorFactory.RegisterLamp(garden, Garden.LampGarage, hsrt16[HSRT16Pin.Relay14]); - _actuatorFactory.RegisterLamp(garden, Garden.LampTerrace, hsrt16[HSRT16Pin.Relay15]); + _actuatorFactory.RegisterSocket(garden, Garden.SocketPavillion, hsrt16[HSRT16Pin.Relay10]).StateChanged += OnStateChanged; + _actuatorFactory.RegisterLamp(garden, Garden.LampRearArea, hsrt16[HSRT16Pin.Relay11]).StateChanged += OnStateChanged; + _actuatorFactory.RegisterLamp(garden, Garden.SpotlightRoof, hsrt16[HSRT16Pin.Relay12]).StateChanged += OnStateChanged; + _actuatorFactory.RegisterLamp(garden, Garden.LampTap, hsrt16[HSRT16Pin.Relay13]).StateChanged += OnStateChanged; + _actuatorFactory.RegisterLamp(garden, Garden.LampGarage, hsrt16[HSRT16Pin.Relay14]).StateChanged += OnStateChanged; + _actuatorFactory.RegisterLamp(garden, Garden.LampTerrace, hsrt16[HSRT16Pin.Relay15]).StateChanged += OnStateChanged; + var stateMachine = _actuatorFactory.RegisterStateMachine(garden, Garden.StateMachine, InitializeStateMachine); - - var button = _sensorFactory.RegisterButton(garden, Garden.Button, _gpioService.GetInput(4, GpioPullMode.High, GpioInputMonitoringMode.Interrupt).WithInvertedState()); + var button = _sensorFactory.RegisterButton(garden, Garden.Button, _gpioService.GetInput(4, GpioPullMode.High, GpioInputMonitoringMode.Interrupt).WithInvertedState()); button.CreatePressedShortTrigger(_messageBroker).Attach(() => stateMachine.TrySetNextState()); button.CreatePressedLongTrigger(_messageBroker).Attach(() => stateMachine.TryTurnOff()); + button.StateChanged += OnStateChanged; _automationFactory.RegisterConditionalOnAutomation(garden, Garden.LampParkingLotAutomation) .WithComponent(garden.GetLamp(Garden.LampParkingLot)) .WithOnAtNightRange() .WithOffBetweenRange(TimeSpan.Parse("22:30:00"), TimeSpan.Parse("05:00:00")); + _deviceMessageBrokerService.MessageReceived += OnMessageReceived; + return Task.FromResult(0); } + private void OnStateChanged(object sender, ComponentFeatureStateChangedEventArgs e) + { + try + { + var topic = "garden_controller/$STATUS/"; + + string payload; + if (e.NewState.Supports()) + { + topic += "button.default"; + payload = e.NewState.Extract().Value == ButtonStateValue.Pressed ? "pressed" : "released"; + } + else if (e.NewState.Supports()) + { + var powerState = e.NewState.Extract(); + payload = powerState.Value == PowerStateValue.On ? "on" : "off"; + } + else + { + return; + } + + var message = new DeviceMessage + { + Topic = topic, + Payload = Encoding.ASCII.GetBytes(payload), + Retain = true + }; + + _deviceMessageBrokerService.Publish(message); + } + catch (Exception exception) + { + Log.Default.Error(exception, "Errow while sending state."); + } + } + + private void OnMessageReceived(object sender, DeviceMessageReceivedEventArgs e) + { + try + { + IComponent component = null; + if (e.Message.Topic == "garden_controller/$PATCH/socket.pavillion") + { + component = _area.GetComponent(Garden.SocketPavillion); + } + else if (e.Message.Topic == "garden_controller/$PATCH/lamp.rear_area") + { + component = _area.GetComponent(Garden.LampRearArea); + } + else if (e.Message.Topic == "garden_controller/$PATCH/lamp.roof") + { + component = _area.GetComponent(Garden.SpotlightRoof); + } + else if (e.Message.Topic == "garden_controller/$PATCH/lamp.tap") + { + component = _area.GetComponent(Garden.LampTap); + } + else if (e.Message.Topic == "garden_controller/$PATCH/lamp.garage") + { + component = _area.GetComponent(Garden.LampGarage); + } + else if (e.Message.Topic == "garden_controller/$PATCH/lamp.terrace") + { + component = _area.GetComponent(Garden.LampTerrace); + } + else if (e.Message.Topic == "garden_controller/$PATCH/lamp.parking_lot") + { + component = _area.GetComponent(Garden.LampParkingLot); + } + + if (component == null) + { + return; + } + + var status = Encoding.UTF8.GetString(e.Message.Payload ?? new byte[0]); + + ICommand command = new TurnOffCommand(); + + if (status == "on") + { + command = new TurnOnCommand(); + } + else if (status == "toggle") + { + command = new TogglePowerStateCommand(); + } + + component.ExecuteCommand(command); + } + catch (Exception exception) + { + Log.Default.Error(exception, "Errow while patching state."); + } + } + private void InitializeStateMachine(StateMachine stateMachine, IArea garden) { var turnOffCommand = new TurnOffCommand(); diff --git a/Core/HA4IoT.Contracts/HA4IoT.Contracts.nuget.targets b/Core/HA4IoT.Contracts/HA4IoT.Contracts.nuget.targets index 58a4b697..51d95e41 100644 --- a/Core/HA4IoT.Contracts/HA4IoT.Contracts.nuget.targets +++ b/Core/HA4IoT.Contracts/HA4IoT.Contracts.nuget.targets @@ -7,7 +7,7 @@ $(UserProfile)\.nuget\packages\ C:\Users\chris\.nuget\packages\ ProjectJson - 4.7.0 + 4.8.1 $(MSBuildAllProjects);$(MSBuildThisFileFullPath) diff --git a/Core/HA4IoT/Devices/DeviceMessageBrokerService.cs b/Core/HA4IoT/Devices/DeviceMessageBrokerService.cs index 304b7366..ef40b2ed 100644 --- a/Core/HA4IoT/Devices/DeviceMessageBrokerService.cs +++ b/Core/HA4IoT/Devices/DeviceMessageBrokerService.cs @@ -58,8 +58,20 @@ public DeviceMessageBrokerService(ILogService logService, IScriptingService scri public event EventHandler MessageReceived; + private bool _isInitialized; + public void Initialize() { + lock (_server) + { + if (_isInitialized) + { + return; + } + + _isInitialized = true; + } + var options = new MqttServerOptionsBuilder() .WithApplicationMessageInterceptor(MessageInterceptor.Intercept) .WithStorage(new Storage())