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);
        }
Example #2
0
        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"));
            }
        }
Example #3
0
        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 });
            });
        }
Example #5
0
        public void Setup()
        {
            DeviceFactory.Initialize();

            _hostDevice = DeviceFactory.CreateHostDevice("test-device", "");
        }
Example #6
0
    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);
            }
        });
    }
Example #7
0
        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()));
        }