using System; using System.Threading; using ln.ethercat.controller.drives; using ln.ethercat.controller.remote; using ln.logging; namespace ln.ethercat.controller { public enum CRActions { NONE, // No Action ENABLE, // Enable system (turn on) DISABLE, // Disable system (turn off) CLEARFAULT, // Clear fault state } public abstract class ControllerRemote : IDisposable { protected Controller Controller; public double CycleIntervall { get; set; } public double CycleFrequency { get => 1.0 / CycleIntervall; set => CycleIntervall = 1.0 / value; } public long CycleCounter { get; private set; } public bool IsRunning => threadCycle?.IsAlive ?? false; bool stopCycleThread; Thread threadCycle; public ControllerRemote(Controller controller) { Controller = controller; Controller?.Add(this); } public abstract double[] Targets { get; set; } public abstract FeederOperation FeederOperation { get; } public void Start() { lock (this) { if (threadCycle?.IsAlive ?? false) Stop(); threadCycle = new Thread(CycleThread); threadCycle.Start(); } } public void Stop() { lock (this) { if (threadCycle?.IsAlive ?? false) { stopCycleThread = true; threadCycle.Join(250); if (threadCycle.IsAlive) threadCycle.Abort(); threadCycle = null; } } } public void SetTargetValue(int drive, double targetValue) => Controller.RemoteUpdateTarget( drive, targetValue ); public void Action(CRActions action) => Controller.RemoteAction(action); protected abstract void Initialize(); protected abstract void Cycle(); protected abstract void Shutdown(); public abstract bool IsSafeToEnable(); private void CycleThread() { CycleCounter = 0; Initialize(); DateTime nextCycleRun = DateTime.Now; while (!stopCycleThread) { DateTime currentTime = DateTime.Now; nextCycleRun += TimeSpan.FromSeconds(CycleIntervall); if (currentTime > nextCycleRun) { Logging.Log(LogLevel.WARNING, "ControllerRemote: missed controller cycle"); while (currentTime > nextCycleRun) nextCycleRun += TimeSpan.FromSeconds(CycleIntervall); } TimeSpan timeToNextCycle = nextCycleRun - currentTime; try { Thread.Sleep(timeToNextCycle); CycleCounter++; Cycle(); } catch (Exception e) { Logging.Log(e); } } Shutdown(); } public void Dispose() { Controller?.Remove(this); } } }