private void WorkerRun() { while (Enabled) { var now = DateTime.Now; var job = Jobs.OrderBy(x => x.LastExecution).FirstOrDefault(x => x.LastExecution.AddSeconds(x.JobTimeoutSeconds) < now); var sleep = job == null || job.SleepRange == null ? null : job.SleepRange.FindFirst(now); if (sleep != null) { TraceManager.Debug($"Sleep mode [{job}] : [{sleep}]"); job.LastExecution = job.LastExecution.AddSeconds(job.JobTimeoutSeconds); SaveJobs(); } else if (job != null) { TraceManager.Trace($"Starting job [{job}]"); var dtStart = DateTime.Now; var actions = job.Actions.ToList(); TraceManager.Debug( string.Join("\r\n * ", actions.Select(x => $"Job action = {x.Label}, offset = {x.OffsetSeconds}")), TraceManager.LogLevelDebugAll); while (Enabled && actions != null && actions.Count > 0) { var action = actions.OrderBy(x => x.OffsetSeconds).FirstOrDefault(x => dtStart.AddSeconds(x.OffsetSeconds) < DateTime.Now); if (action != null) { TraceManager.Trace($"Executing action [{action.Label}]"); var driver = GetGpioDriver(action.Gpio); driver.Value = action.PinValue; actions.Remove(action); } else { Thread.Sleep(100); } } if (Enabled) { while (job.LastExecution < dtStart.Subtract(new TimeSpan(0, 0, job.JobTimeoutSeconds))) { if (job.LastExecution < dtStart.Subtract(new TimeSpan(0, 0, job.JobTimeoutSeconds * 2))) { TraceManager.Debug($"Ignoring job [{job}] execution of {job.LastExecution}, time's up", TraceManager.LogLevelDebugVerbose); } job.LastExecution = job.LastExecution.AddSeconds(job.JobTimeoutSeconds); } SaveJobs(); TraceManager.Trace($"Job [{job}] complete"); } else { TraceManager.Trace($"Job [{job}] aborded"); } } else { Thread.Sleep(100); } } TraceManager.Trace("Stopping worker"); foreach (var d in gpioDrivers) { TraceManager.Trace($"Disabling driver {d.ToString()}"); d.Value = GpioDriver.GpioValueLow; d.Export = false; } }