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 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()));
        }