public void Initialize(ChannelConnectionOptions channelOptions) { _hostDevice = DeviceFactory.CreateHostDevice("lightbulb", "Colorful lightbulb"); #region General node _hostDevice.UpdateNodeInfo("general", "General information and properties", "no-type"); // I think properties are pretty much self-explanatory in this producer. _color = _hostDevice.CreateHostColorProperty(PropertyType.Parameter, "general", "color", "Color", ColorFormat.Rgb); _color.PropertyChanged += (sender, e) => { _log.Info($"Color changed to {_color.Value.ToRgbString()}"); }; _onOffSwitch = _hostDevice.CreateHostChoiceProperty(PropertyType.Parameter, "general", "is-on", "Is on", new[] { "OFF", "ON" }, "OFF"); _onOffSwitch.PropertyChanged += (sender, e) => { // Simulating some lamp behaviour. if (_onOffSwitch.Value == "ON") { _intensity.Value = 50; } else { _intensity.Value = 0; } }; _intensity = _hostDevice.CreateHostNumberProperty(PropertyType.Parameter, "general", "intensity", "Intensity", 0, "%"); #endregion _broker.Initialize(channelOptions); _hostDevice.Initialize(_broker); }
public void CreateHostDeviceWithIncorrectId() { foreach (var badTopicLevel in CommonStuff.BadTopicLevels) { Assert.That(() => DeviceFactory.CreateHostDevice(badTopicLevel, "some friendly name"), Throws.ArgumentException); } foreach (var goodTopicLevel in CommonStuff.GoodTopicLevels) { Assert.DoesNotThrow(() => DeviceFactory.CreateHostDevice(goodTopicLevel, "some friendly name")); } }
public void Initialize(string brokerIp, AddToLogDelegate addToLog) { MqttBrokerIp = brokerIp; _hostDevice = DeviceFactory.CreateHostDevice("si7020", "Si7020 on ESP32"); _hostDevice.UpdateNodeInfo("general", "General information and properties", "no-type"); _temperature = _hostDevice.CreateHostNumberProperty(PropertyType.State, "general", "temperature", "Measured temperature", 0.00f, "°C"); _humidity = _hostDevice.CreateHostNumberProperty(PropertyType.State, "general", "humidity", "Measured humidity", 0.00f, "%"); _broker.Initialize(MqttBrokerIp, (severity, message) => addToLog(severity, "Broker:" + message)); _hostDevice.Initialize(_broker, (severity, message) => addToLog(severity, message)); var gettingValues = new Thread(GetTemperatureAndHumidityValues); gettingValues.Start(); }
public void Initialize() { _mqttClient.Connect(MqttClientGuid); _hostDevice = DeviceFactory.CreateHostDevice("lightbulb", "Colorful lightbulb on ESP32"); _hostDevice.UpdateNodeInfo("general", "General information and properties", "no-type"); _color = _hostDevice.CreateHostColorProperty(PropertyType.Parameter, "general", "color", "Color", ColorFormat.Rgb); _color.PropertyChanged += HandleColorPropertyChanged; _onOffSwitch = _hostDevice.CreateHostBooleanProperty(PropertyType.Parameter, "general", "turn-on-off", "Turn device on or off"); _onOffSwitch.PropertyChanged += HandleOnOffSwitchPropertyChanged; _intensity = _hostDevice.CreateHostIntegerProperty(PropertyType.Parameter, "general", "intensity", "Intensity", 0, "%"); _intensity.PropertyChanged += HandleIntensityPropertyChanged; _hostDevice.Initialize((topic, value, qosLevel, isRetained) => { _mqttClient.Publish(topic, Encoding.UTF8.GetBytes(value), 1, true); }, topic => { _mqttClient.Subscribe(new string[] { topic }, new byte[] { 1 }); }); }
public void Setup() { DeviceFactory.Initialize(); _hostDevice = DeviceFactory.CreateHostDevice("test-device", ""); }
public void Initialize(ChannelConnectionOptions channelOptions, string modBusIp) { Log.Info($"Creating Homie properties."); _device = DeviceFactory.CreateHostDevice("recuperator", "Domekt 200"); // General section. _device.UpdateNodeInfo("general", "General information", "no-type"); ActualState = _device.CreateHostChoiceProperty(PropertyType.State, "general", "actual-state", "Actual state", new[] { "UNKNOWN", "OFF", "STARTING", "ON-AUTO", "ON-LOW", "ON-MEDIUM", "ON-HIGH" }, "OFF"); _targetState = _device.CreateHostChoiceProperty(PropertyType.Command, "general", "target-state", "Target state", new[] { "OFF", "ON-AUTO", "ON-LOW", "ON-MEDIUM", "ON-HIGH" }, "OFF"); _targetState.PropertyChanged += (sender, e) => { switch (_targetState.Value) { case "OFF": _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.StartStop, 0); break; case "ON-AUTO": if (ActualState.Value == "OFF") { _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.StartStop, 1); Thread.Sleep(100); } _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.ModeAutoManual, 1); break; case "ON-LOW": if (ActualState.Value == "OFF") { _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.StartStop, 1); Thread.Sleep(100); } _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.ModeAutoManual, 0); Thread.Sleep(100); _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.VentilationLevelManual, 1); break; case "ON-MEDIUM": if (ActualState.Value == "OFF") { _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.StartStop, 1); Thread.Sleep(100); } _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.ModeAutoManual, 0); Thread.Sleep(100); _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.VentilationLevelManual, 2); break; case "ON-HIGH": if (ActualState.Value == "OFF") { _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.StartStop, 1); Thread.Sleep(100); } _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.ModeAutoManual, 0); Thread.Sleep(100); _reliableModbus.TryWriteModbusRegister(KomfoventRegisters.VentilationLevelManual, 3); break; } }; _actualModbusConnectionState = _device.CreateHostChoiceProperty(PropertyType.State, "general", "modbus-state", "Modbus state", new[] { "OK", "DISCONNECTED" }); // Ventilation section. _device.UpdateNodeInfo("ventilation", "Ventilation related properties", "no-type"); ActualVentilationLevelProperty = _device.CreateHostChoiceProperty(PropertyType.State, "ventilation", "actual-level", "Actual level", new[] { "OFF", "LOW", "MEDIUM", "HIGH" }); // Temperatures section. _device.UpdateNodeInfo("temperatures", "Various temperatures", "no-type"); SupplyAirTemperatureProperty = _device.CreateHostNumberProperty(PropertyType.State, "temperatures", "supply-air-temperature", "Supply air temperature", 16, "°C"); // System section. _device.UpdateNodeInfo("system", "System", "no-type"); _actualDateTimeProperty = _device.CreateHostTextProperty(PropertyType.State, "system", "date-time", "Current date ant time.", ""); _systemUptime = _device.CreateHostNumberProperty(PropertyType.State, "system", "uptime", "Uptime", 0, "h"); _disconnectCount = _device.CreateHostNumberProperty(PropertyType.State, "system", "disconnect-count", "Modbus disconnect count", decimalPlaces: 0); // Now starting up everything. Log.Info($"Initializing Homie entities."); _reliableModbus.Initialize(modBusIp); _broker.Initialize(channelOptions); _device.Initialize(_broker); // Spinning up spinners. Task.Run(async() => await PollDomektOverModbusContinuouslyAsync(new CancellationToken())); Task.Run(async() => { while (true) { _systemUptime.Value = (float)(DateTime.Now - _startTime).TotalHours; await Task.Delay(5000); } }); Task.Run(async() => { var cachedState = true; while (true) { if ((_reliableModbus.IsConnected == false) && (cachedState == true)) { _actualModbusConnectionState.Value = "DISCONNECTED"; _disconnectCount.Value = _reliableModbus.DisconnectCount; } if ((_reliableModbus.IsConnected == true) && (cachedState == false)) { _actualModbusConnectionState.Value = "OK"; } cachedState = _reliableModbus.IsConnected; await Task.Delay(10); } }); }
public void Initialize(ChannelConnectionOptions channelOptions) { _hostDevice = DeviceFactory.CreateHostDevice("air-conditioner", "Air conditioning unit"); #region General node _hostDevice.UpdateNodeInfo("general", "General information and properties", "no-type"); // Temperatures. These are pretty self-explanatory, right? _actualAirTemperature = _hostDevice.CreateHostNumberProperty(PropertyType.State, "general", "actual-air-temperature", "Actual measured air temperature", 18, "°C"); _targetAirTemperature = _hostDevice.CreateHostNumberProperty(PropertyType.Parameter, "general", "target-air-temperature", "Target air temperature", 23, "°C"); // Besides obvious ON and OFF states, there's a transient STARTING state. This simulated the non-instant startup of the device. _actualState = _hostDevice.CreateHostChoiceProperty(PropertyType.State, "general", "actual-state", "Actual power state", new[] { "ON", "OFF", "STARTING" }, "OFF"); // Creating a switch. It also simulates startup sequence ON -> STARTING -> OFF. Shutdown sequence is instant ON -> OFF. _onOffSwitch = _hostDevice.CreateHostChoiceProperty(PropertyType.Command, "general", "turn-on-off", "Turn device on or off", new[] { "ON", "OFF" }); _onOffSwitch.PropertyChanged += (sender, e) => { if ((_actualState.Value == "ON") && (_onOffSwitch.Value == "OFF")) { // This is the shutdown sequence. _actualState.Value = "OFF"; } if ((_actualState.Value == "OFF") && (_onOffSwitch.Value == "ON")) { // This is the startup sequence. _actualState.Value = "STARTING"; Task.Run(async() => { await Task.Delay(3000); _actualState.Value = "ON"; }); } _log.Info($"Actual state changed to: {_actualState.Value}"); }; #endregion #region Ventilation node _hostDevice.UpdateNodeInfo("ventilation", "Ventilation information and properties", "no-type"); // Allows user to set ventilation level (or power). This will actually be used in simulation loop. _ventilationLevel = _hostDevice.CreateHostNumberProperty(PropertyType.Parameter, "ventilation", "level", "Level of ventilation", 50, "%"); #endregion #region Service node _hostDevice.UpdateNodeInfo("service", "Service related properties", "no-type"); // Previous and next service dates. These are read-only properties. They are changed by "perform service" command. _previousServiceDate = _hostDevice.CreateHostDateTimeProperty(PropertyType.State, "service", "previous-service-date", "Date of the last service", DateTime.Now.AddMonths(3)); _nextServiceDate = _hostDevice.CreateHostDateTimeProperty(PropertyType.State, "service", "next-service-date", "Date for the next service", DateTime.Now); // This is a write-only property, that is — a command. It sets last service date to actual datetime, and also sets next service date to some time in the future. // Popular automation software have lots of problems with this kind of workflow, when there's a command that doesn't really have a state register. // As of 2021-03-12, openHAB and HomeAssistant and HoDD can't really deal with it. Which is a bummer, as it a pretty common workflow in real life! _performServiceCommand = _hostDevice.CreateHostChoiceProperty(PropertyType.Command, "service", "perform-service", "Perform service", new[] { "STOP", "START" }); _performServiceCommand.PropertyChanged += (sender, e) => { if (_performServiceCommand.Value == "START") { _previousServiceDate.Value = _nextServiceDate.Value; _nextServiceDate.Value = DateTime.Now.AddMinutes(1); } }; // Knowing system uptime is always useful. _systemUptime = _hostDevice.CreateHostNumberProperty(PropertyType.State, "service", "system-uptime", "Uptime", 0, "h", 3); #endregion // This builds topic trees and subscribes to everything. _broker.Initialize(channelOptions); _hostDevice.Initialize(_broker); // Finally, running the simulation loop. We're good to go! Task.Run(async() => await RunSimulationLoopContinuously(new CancellationToken())); }