Ejemplo n.º 1
0
        public void BeginAutoTopOff(AutoTopOffRequest atoRequest)
        {
            if (Status.PumpRunning)
            {
                throw new Exception($"ATO is currently running...");
            }
            if (CancelToken != null && !CancelToken.IsCancellationRequested)
            {
                _logger.LogInformation("Canceled by new ATO process"); //todo remove all these cancel logs when we solve the issue of random ato cancels
                CancelToken.Cancel();
            }
            var pumpRelaySensor   = GetPumpRelayPin();
            var floatSwitchSensor = GetFloatSensorPin();

            if (pumpRelaySensor == null || floatSwitchSensor == null)
            {
                throw new Exception($"Invalid ATO pins specified (Pump: {pumpRelaySensor} Sensor: {floatSwitchSensor})");
            }

            if (atoRequest.Runtime > 60)
            {
                throw new Exception($"ATO max runtime is larger than maximum allowed (Runtime: {atoRequest.Runtime} Maximum: 60)");
            }

            var currentSensorValue = _gpioService.GetPinValue(floatSwitchSensor);

            if (currentSensorValue == GpioPinValue.Low)
            {
                throw new Exception($"ATO sensor is currently reading maximum water level");
            }



            _logger.LogInformation("[ATOService] Beginning ATO...");
            var maxPumpRuntime = atoRequest.Runtime * 1000 * 60;

            _gpioService.SetPinValue(pumpRelaySensor, PinValue.High);

            //Next run time
            var device = _aquariumAuthService.GetAquarium().Device;
            var task   = device.ScheduleAssignments.Select(assignment =>
                                                           assignment.Schedule.Tasks.Where(t => t.TaskId == Models.ScheduleTaskTypes.StartATO).FirstOrDefault()
                                                           ).FirstOrDefault();
            DateTime?nextRunTime = null;

            if (task != null)
            {
                nextRunTime = task.StartTime.ToUniversalTime();
            }

            var startTime = DateTime.Now.ToUniversalTime();

            Status = new ATOStatus
            {
                StartTime        = startTime,
                EstimatedEndTime = startTime.AddMilliseconds(maxPumpRuntime),
                UpdatedAt        = startTime,
                MaxRuntime       = atoRequest.Runtime,
                RunIndefinitely  = atoRequest.RunIndefinitely,
                PumpRunning      = true,
                Enabled          = true,
                PumpRelaySensor  = pumpRelaySensor,
                FloatSensor      = floatSwitchSensor,
                DeviceId         = device.Id,
                NextRunTime      = nextRunTime,
                FloatSensorValue = currentSensorValue
            };
            DispatchStatus().Wait(); //.ConfigureAwait(false);

            //Apply a max drain time
            CancelToken = new CancellationTokenSource();
            CancellationToken ct = CancelToken.Token;


            var statusId = Status.Id;

            Task.Run(() =>
            {
                var t       = TimeSpan.FromMilliseconds(maxPumpRuntime);
                string time = string.Format("{0:D2}h:{1:D2}m", t.Hours, t.Minutes);
                _logger.LogInformation($"[ATOService] Running (Max run time: {time})");
                Thread.Sleep(maxPumpRuntime);
                //ct.ThrowIfCancellationRequested();
                if (ct.IsCancellationRequested)
                {
                    if (statusId != Status.Id)
                    {
                        _logger.LogError("Attempted to cancel water change. The Status IDs of the water changes do not match!");
                        //so this definitely happens occasionally
                        return;
                    }
                    StopAutoTopOff(AutoTopOffStopReason.Canceled);
                    //_gpioService.SetPinValue(pumpRelaySensor.Pin, PinValue.Low); //maybe enable this in case we run into pin issues
                    return;
                }

                if (Status.PumpRunning)
                {
                    _logger.LogInformation($"[ATOService] Reached maximum run time of {Status.MaxRuntime} minutes.");
                    StopAutoTopOff(AutoTopOffStopReason.MaximumRuntimeReached);
                }
            }).ConfigureAwait(false); //Fire and forget
        }