/// /// Copyright (c) 2013-2016 Sensus Metering Systems /// using System; using System.Collections.Generic; using log4net; using Dirichlet.Numerics; using TBF.BenchControl.Generic; namespace TBF.BenchControl.Elde.Diverter { public class Diverter : ComponentBase, IDevice, GenericDevices.IDiverter { private static readonly ILog log = LogManager.GetLogger(typeof(Diverter)); public override string ToString() { return string.Format("Diverter({0})", Cfg.ToString(1)); } /// /// Enumeration of balances via static fields and methods /// static int nextIdx = 0; public static new void ResetStaticProperties() { nextIdx = 0; } public static int DivertersCount { get { return nextIdx; } } public static GenericDevices.IDiverter[] Diverters; public static int[] DivStartingLevelPct; public static int[] DivStoppingLevelPct; protected int diverterNr; /// 0-based diverter number readonly DiverterCfg diverterCfg; readonly ControlBoardDev controlBoard; readonly UInt128 mask; /// derived from bitPosition in the constructor public int AdcNr { get { return diverterCfg.AdcNr; } } public bool State { get { return (controlBoard.Route & mask) != 0; } } public Diverter() { } public Diverter(Generic.IComponentCfg cfg, IList components) : base(cfg) { diverterCfg = cfg as DiverterCfg; controlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent"); if (diverterCfg.BitPosition < 0 || diverterCfg.BitPosition >= 64) throw new ArgumentOutOfRangeException("position"); this.mask = (((UInt128)1) << diverterCfg.BitPosition); diverterNr = nextIdx++; /// if (Diverters == null || Diverters.Length < nextIdx) { GenericDevices.IDiverter[] divertersSoFar = Diverters; int[] startingLevelsSoFar = DivStartingLevelPct; int[] stoppingLevelsSoFar = DivStoppingLevelPct; Diverters = new GenericDevices.IDiverter[nextIdx]; DivStartingLevelPct = new int[nextIdx]; DivStoppingLevelPct = new int[nextIdx]; if (divertersSoFar != null) { for (int i = 0; i < divertersSoFar.Length; i++) { Diverters[i] = divertersSoFar[i]; DivStartingLevelPct[i] = startingLevelsSoFar[i]; DivStoppingLevelPct[i] = stoppingLevelsSoFar[i]; } } Diverters[nextIdx - 1] = this; DivStartingLevelPct[nextIdx - 1] = diverterCfg.StartingLevel; DivStoppingLevelPct[nextIdx - 1] = diverterCfg.StoppingLevel; } /// Prepare arguments of SendCalibData() if (diverterCfg.AdcNr >= 0 && diverterCfg.AdcNr < controlBoard.RegValveCalib.GetLength(0)) { controlBoard.RegValveCalib[diverterCfg.AdcNr, 0] = (uint)diverterCfg.AdcValueToSink; controlBoard.RegValveCalib[diverterCfg.AdcNr, 1] = (uint)diverterCfg.AdcValueToTank; } else { log.ErrorFormat("Unable to set {0} ADC levels: RegValveCalib array size={1}, diverter AdcNr={2}", Name, controlBoard.RegValveCalib.GetLength(0), diverterCfg.AdcNr); } log.Debug(this.ToString()); } /// /// IDevice interface implementation /// public void Initialize() { } public void RunDeviceBefore() { int adc = (int)StateMachine.ControlBoard.AnalogInputRaw(diverterCfg.AdcNr, 0); Handlers.OnAdcChanged(this, new CmdResponseArgs(CfgChangeCmd.GetAdc, diverterCfg.BitPosition, adc)); } public void RunDeviceAfter() { } public void StopDevice() { } #region Configuration Change Handling public static void OnCfgChange(object sender, CfgChangeArgs args) { if (CfgChangeHandler == null) return; try { CfgChangeHandler(sender, args); } catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); } } public static event EventHandler CfgChangeHandler; public override void StartChangeHandler() { CfgChangeHandler += delegate(object sender, CfgChangeArgs args) { DiverterCfg tmpcfg = args.Cfg as DiverterCfg; if (tmpcfg != null && tmpcfg.Name.Equals(Name)) { if (args.Command == CfgChangeCmd.CfgChange) { } else if (args.Command == CfgChangeCmd.GetAdc1 || args.Command == CfgChangeCmd.GetAdc2) { int adc = (int)controlBoard.AnalogInputRaw(diverterCfg.AdcNr, 0); // TOTEST DiverterCfgCtrl.OnCmdResponse(this, new CmdResponseArgs(args.Command, diverterCfg.BitPosition, adc)); } else if (args.Command == CfgChangeCmd.DivToTank) { if (Name.Contains("1")) /// TODO: Put flowmeter# into config { controlBoard.DiverterToTank(1); } else { controlBoard.DiverterToTank(3); } } else if (args.Command == CfgChangeCmd.DivToSink) { if (Name.Contains("1")) /// TODO: Put flowmeter# into config { controlBoard.DiverterToSink(1); } else { controlBoard.DiverterToSink(3); } } else if (args.Command == CfgChangeCmd.ReadDivTransition) { if (Name.Contains("1")) /// TODO: Put flowmeter# into config { controlBoard.ReadDiverterTransition(1); } else { controlBoard.ReadDiverterTransition(3); } } } }; } #endregion Configuration Change Handling } }