Пример #1
0
        public void Write(ControllerState controllerState, bool forceImmidiateAction)
        {
            var now = DateTime.UtcNow;

            foreach (var heater in controllerState.HeaterIdToState.Values)
            {
                PowerZoneState heaterPowerZoneState = null;

                if (heater.Heater.PowerZoneId.HasValue)
                {
                    heaterPowerZoneState = controllerState.PowerZoneIdToState[heater.Heater.PowerZoneId.Value];
                }

                if (CanSwitchState(now, heater, heaterPowerZoneState, forceImmidiateAction) &&
                    StateShouldBeUpdated(heater))
                {
                    _powerOutputProvider.Provide(heater.Heater.DigitalOutput.ProtocolName)
                    .SetState(heater.Heater.DigitalOutput.OutputDescriptor, heater.OutputState);

                    _usageCollector.Collect(heater, controllerState);

                    heater.LastStateChange = now;

                    if (heaterPowerZoneState != null)
                    {
                        heaterPowerZoneState.LastOutputStateChange = now;
                    }
                }
            }
        }
        public void Limit(PowerZoneState powerZoneState, ControllerState controllerState)
        {
            var availablePower = powerZoneState.PowerZone.MaxUsage;

            var requiredHeaterIdToUsage = powerZoneState.PowerZone
                                          .Heaters
                                          .Where(h => controllerState.HeaterIdToState[h.HeaterId].OutputState)
                                          .ToDictionary(h => h.HeaterId,
                                                        h => h.UsagePerHour);

            if (requiredHeaterIdToUsage.Values.Sum(x => x) <= availablePower)
            {
                return;
            }

            var now = DateTime.UtcNow;

            if (powerZoneState.NextIntervalIncrementationDateTime < now)
            {
                unchecked
                {
                    powerZoneState.NextIntervalOffset++;
                }

                powerZoneState.NextIntervalIncrementationDateTime = now.AddMinutes(powerZoneState.PowerZone.RoundRobinIntervalMinutes);
            }

            var heatersThatCantBeDisabled = powerZoneState.PowerZone
                                            .Heaters
                                            .Where(h =>
            {
                var heaterState = controllerState.HeaterIdToState[h.HeaterId];
                return(heaterState.OutputState &&
                       (now - heaterState.LastStateChange).TotalSeconds <= h.MinimumStateChangeIntervalSeconds);
            })
                                            .ToDictionary(h => h.HeaterId);;

            var totalPower = 0m;

            foreach (var heater in heatersThatCantBeDisabled)
            {
                totalPower += heater.Value.UsagePerHour;
            }

            for (var i = 0; i < requiredHeaterIdToUsage.Count; i++)
            {
                var heaterIndex = (i + powerZoneState.NextIntervalOffset) % requiredHeaterIdToUsage.Count;
                var heater      = requiredHeaterIdToUsage.ElementAt(heaterIndex);

                if (totalPower + heater.Value <= availablePower)
                {
                    totalPower += heater.Value;
                }
                else if (!heatersThatCantBeDisabled.ContainsKey(heater.Key))
                {
                    controllerState.HeaterIdToState[heater.Key].OutputState = false;
                }
            }
        }
Пример #3
0
        private static bool CanSwitchState(DateTime now, HeaterState heater, PowerZoneState heaterPowerZoneState, bool forceImmidiateAction)
        {
            if (forceImmidiateAction)
            {
                return(true);
            }

            return((now - heater.LastStateChange).TotalSeconds >= heater.Heater.MinimumStateChangeIntervalSeconds &&
                   (heaterPowerZoneState == null || (now - heaterPowerZoneState.LastOutputStateChange).TotalSeconds >= heaterPowerZoneState.PowerZone.SwitchDelayBetweenOutputsSeconds));
        }
        public void iterates_over_available_heaters(byte iteration, bool state1, bool state2, bool state3, bool state4)
        {
            // Arrange
            var heater1 = new Heater {
                HeaterId = 1, UsagePerHour = 0.9m
            };
            var heater2 = new Heater {
                HeaterId = 2, UsagePerHour = 0.9m
            };
            var heater3 = new Heater {
                HeaterId = 3, UsagePerHour = 0.9m
            };
            var heater4 = new Heater {
                HeaterId = 4, UsagePerHour = 0.9m
            };

            var heaterState1 = new HeaterState {
                Heater = heater1, OutputState = true
            };
            var heaterState2 = new HeaterState {
                Heater = heater2, OutputState = true
            };
            var heaterState3 = new HeaterState {
                Heater = heater3, OutputState = true
            };
            var heaterState4 = new HeaterState {
                Heater = heater4, OutputState = true
            };

            var powerZoneState = new PowerZoneState
            {
                NextIntervalOffset = iteration,
                PowerZone          = new PowerZone
                {
                    MaxUsage = 2.1m,
                    Heaters  = new List <Heater> {
                        heater1, heater2, heater3, heater4
                    }
                }
            };

            var controllerState = new ControllerState
            {
                HeaterIdToState = new Dictionary <int, HeaterState>
                {
                    [1] = heaterState1,
                    [2] = heaterState2,
                    [3] = heaterState3,
                    [4] = heaterState4
                }
            };

            // Act
            var powerZoneOutputAllowanceCalculator = new PowerZoneOutputLimiter();

            powerZoneOutputAllowanceCalculator.Limit(powerZoneState, controllerState);

            // Assert
            Assert.Equal(state1, heaterState1.OutputState);
            Assert.Equal(state2, heaterState2.OutputState);
            Assert.Equal(state3, heaterState3.OutputState);
            Assert.Equal(state4, heaterState4.OutputState);
        }