diff --git a/TBF/BenchControl/Modbus/UltrasoundLevelMeter/Factory.cs b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/Factory.cs new file mode 100644 index 000000000..5f69d185c --- /dev/null +++ b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/Factory.cs @@ -0,0 +1,26 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Modbus.UltrasoundLevelMeter +{ + public class Factory : IComponentFactory + { + public string ClassName { get { return this.GetType().Namespace.Substring(17); } } + + public void ResetStaticProperties() { LevelMeter.ResetStaticProperties(); } + + public IComponent DummyComponent() { return new LevelMeter(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new LevelMeter(cfg, components); } + + public IComponentCfg DefaultConfig() { return new LevelMeterCfg(this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(LevelMeterCfg.Serializer, component, this); + } + } +} diff --git a/TBF/BenchControl/Modbus/UltrasoundLevelMeter/LevelMeter.cs b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/LevelMeter.cs new file mode 100644 index 000000000..726741139 --- /dev/null +++ b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/LevelMeter.cs @@ -0,0 +1,119 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.Generic; +using TBF.Boxes; + +namespace TBF.BenchControl.Modbus.UltrasoundLevelMeter +{ + public class LevelMeter : ComponentBase, GenericDevices.IPressureMeter, IDevice + { + private static readonly ILog log = LogManager.GetLogger(typeof(LevelMeter)); + public override string ToString() { return string.Format("LevelMeter({0})", Cfg.ToString(1)); } + + readonly LevelMeterCfg myCfg; + readonly GenericDevices.IModbus modbus; + + private float receivedLevel; + + const ushort WatchdogBitMask = 0x0010; + + public LevelMeter() + { + } + + public LevelMeter(Generic.IComponentCfg cfg, IList components) + : base(cfg) + { + myCfg = cfg as LevelMeterCfg; + + modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components); + if (modbus == null) throw new Exception("Cannot find " + Name + " parent"); + + /// Connect to handler + //ModbusAddress.MeretRS485Address[Idx0] = ModbusAddress; + + log.Debug(this.ToString()); + } + + /// Initialize this device + public void Initialize() + { + } + + + /// + /// Returns the water pressure + /// + /// Pressure in mBar + public float ReadLevel() + { + return (float)Config.Units.ConvertFrom(Config.Unit.mm, receivedLevel); + } + + /// + /// Events: PressureDone, Error + /// + /// Reference to a variable for the pressure in Bar + /// ReadPressureOp instance reference casted to IOperaton + public IOperation ReadPressureOp(ref FloatBox pressure) + { + return new ReadLevelOp(this, ref pressure); + } + + /// + /// Events: pressureDone, Error + /// + /// Reference to a variable for the pressure in Bar + /// Event returned when measurement done + /// ReadPressureOp instance reference casted to IOperaton + public IOperation ReadPressureOp(ref FloatBox pressure, Event pressureDone) + { + return new ReadLevelOp(this, ref pressure, pressureDone); + } + + + /// Run this device + public void RunDeviceBefore() + { + if (myCfg.DebugLevel == Config.Entities.DebugMode.Simulate || + myCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation) + { + return; + } + + if (modbus.ReceivedTelegrams[myCfg.ModbusAddress].Count > 0) + { + byte[] telegram = modbus.ReceivedTelegrams[myCfg.ModbusAddress].Dequeue(); + if (telegram.Length == 9 && telegram[1] == 4 && telegram[2] == 4) + { + /// Swap byte order + byte t1 = telegram[3]; + byte t2 = telegram[4]; + byte t3 = telegram[5]; + byte t4 = telegram[6]; + telegram[3] = t4; + telegram[4] = t3; + telegram[5] = t2; + telegram[6] = t1; + + receivedLevel = System.BitConverter.ToSingle(telegram, 3); + } + } + + if ((StateMachine.Time % 3) == (myCfg.ModbusAddress % 3)) /// Each 3 seconds + { + const byte Function = 4; /// Read input registers + const ushort Address = 0; /// Pressure + modbus.SendMessage(myCfg.ModbusAddress, Function, Address, 2); + } + } + + public void RunDeviceAfter() { } + public void StopDevice() { } + public void StopDevice2() { } + } +} diff --git a/TBF/BenchControl/Modbus/UltrasoundLevelMeter/LevelMeterCfg.cs b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/LevelMeterCfg.cs new file mode 100644 index 000000000..6ff32963f --- /dev/null +++ b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/LevelMeterCfg.cs @@ -0,0 +1,142 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Modbus.UltrasoundLevelMeter +{ + public class LevelMeterCfg : ComponentCfgBase, Generic.IChildComponentCfg, Config.Entities.IParamsProvider + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(LevelMeterCfg) })[0]; + public override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl() + { + IList parents = new List(); + if (StateMachine.Components != null) + { + foreach (var cmpnt in StateMachine.Components) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is TBF.BenchControl.Modbus.Common.Factory) + { + parents.Add(cmpnt.Name); + } + } + } + + return new Configs.ParamsProvider.ComponentCfgCtrl(this, parents); + } + + /// + /// Serialized parameters + /// + public byte ModbusAddress; /// 1..255 + + /// Private parameterless constructor invoked by all other (public) constructors + LevelMeterCfg() {} + + public LevelMeterCfg(IComponentFactory factory) + : this() + { + Factory = factory; + Name = "ULM"; + ParentName = "Modbus"; + InitializeAll(); + } + + public string ComponentName { get { return Name; } } + + public void InitializeAll() + { + ModbusAddress = 49; + } + + + string[] paramNames = new string[] + { + "Modbus address", + }; + public string ParamName(int i) { return paramNames[i]; } + public int ParamsCount() { return paramNames.Length; } + public IList ParamValues(int i) { return null; } + + public string ToString(int i) + { + if (i == -1) + { + return string.Format("ModbusAddr={0}", ModbusAddress); + } + + switch (i) + { + case 0: return ModbusAddress.ToString(); + default: return string.Empty; + } + } + + + public CfgUpdateFlags UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: + byte addr = byte.Parse(strValue); + if (ModbusAddress != addr) + { + ModbusAddress = addr; + return CfgUpdateFlags.RestartRqrd; + } + else + { + return CfgUpdateFlags.None; + } + + default: + return CfgUpdateFlags.None; + } + } + + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + int dummy; + + switch (i) + { + case 0: + if (int.TryParse(strValue, out dummy) && dummy >= 0 && dummy <= 255) return true; + break; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + void CopyContentTo(LevelMeterCfg prms) + { + prms.ParentName = this.ParentName; + prms.ModbusAddress = this.ModbusAddress; + } + + + public Config.Entities.IParamsProvider Clone() + { + LevelMeterCfg pars = new LevelMeterCfg(); + CopyContentTo(pars); + return pars; + } + + public void UpdateEmbeddedDbEntity() + { + /// Do nothing + } + } +} diff --git a/TBF/BenchControl/Modbus/UltrasoundLevelMeter/ReadLevelOp.cs b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/ReadLevelOp.cs new file mode 100644 index 000000000..81c4e8f09 --- /dev/null +++ b/TBF/BenchControl/Modbus/UltrasoundLevelMeter/ReadLevelOp.cs @@ -0,0 +1,64 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System; +using log4net; +using TBF.Boxes; + +namespace TBF.BenchControl.Modbus.UltrasoundLevelMeter +{ + public class ReadLevelOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadLevelOp)); + public override string ToString() { return string.Format("ReadLevelOp(.,{0},.)", eventDone); } + + /// Set by the constructor + readonly LevelMeter levelMeter; + readonly Event eventDone; + + /// Measured value + FloatBox level; + + /// + /// Events: PressureInDone, PressureOutDone or Error + /// + /// Pressure meter reference + /// Reference to the measured pressure variable, value is in bar + /// Event to be returned by Run() when completed OK + public ReadLevelOp(LevelMeter levelMeter, ref FloatBox pressure, Event eventDone) + { + if (levelMeter == null) throw new ArgumentNullException("levelMeter"); + this.levelMeter = levelMeter; + this.level = pressure; + this.eventDone = eventDone; + + log.Debug(this.ToString()); + } + public ReadLevelOp(LevelMeter pressureMeter, ref FloatBox pressure) + : this(pressureMeter, ref pressure, Event.PressureDone) + { + } + + + /// Start this operation + public void Start() + { + level.Val = levelMeter.ReadLevel(); + } + + /// Run this operation + /// + /// Event.PressureInDone or Event.PressureOutDone + /// + public Event Run() + { + level.Val = levelMeter.ReadLevel(); + return eventDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TBF/BenchControl/TbfComponents.cs b/TBF/BenchControl/TbfComponents.cs index 67cc5a20c..8f56ecf64 100644 --- a/TBF/BenchControl/TbfComponents.cs +++ b/TBF/BenchControl/TbfComponents.cs @@ -95,6 +95,7 @@ namespace TBF.BenchControl Factories.Add(new Modbus.PressureMeter.Meret.Factory()); /// Modbus.PressureMeter.Meret - Meret pressure meter connected via modbus Factories.Add(new Modbus.QuidoRS.Factory()); /// Modbus.QuidoRS Factories.Add(new Modbus.TankSelector.Factory()); /// Modbus.TankSelector + Factories.Add(new Modbus.UltrasoundLevelMeter.Factory()); Factories.Add(new Network.Adapter.Factory()); Factories.Add(new Network.Camera.CLP1611.Factory()); Factories.Add(new Network.Camera.Display.Factory()); diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index ede96fc85..b6006e692 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -647,6 +647,10 @@ TankSelectorCfgCtrl.cs + + + +