From e21464f24ef0dcafec02da28d3d29b3b73da9e42 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Wed, 1 Apr 2020 11:59:06 +0200 Subject: [PATCH] Modbus.WaterAnalyzer added, ver.2.26.1447 --- Config/Properties/AssemblyInfo.cs | 4 +- Results/Entities/TestRslt.cs | 10 ++ Results/Mappings/TestRsltMap.cs | 10 +- Results/Properties/AssemblyInfo.cs | 4 +- .../Modbus/WaterAnalyzer/Analyzer.cs | 141 +++++++++++++++++ .../Modbus/WaterAnalyzer/AnalyzerCfg.cs | 146 ++++++++++++++++++ .../Modbus/WaterAnalyzer/Factory.cs | 26 ++++ .../WaterAnalyzer/ReadConductivityOp.cs | 58 +++++++ .../Modbus/WaterAnalyzer/ReadTempOp.cs | 64 ++++++++ TBF/BenchControl/TbfComponents.cs | 3 +- TBF/Properties/AssemblyInfo.cs | 4 +- TBF/TBF.csproj | 5 + 12 files changed, 466 insertions(+), 9 deletions(-) create mode 100644 TBF/BenchControl/Modbus/WaterAnalyzer/Analyzer.cs create mode 100644 TBF/BenchControl/Modbus/WaterAnalyzer/AnalyzerCfg.cs create mode 100644 TBF/BenchControl/Modbus/WaterAnalyzer/Factory.cs create mode 100644 TBF/BenchControl/Modbus/WaterAnalyzer/ReadConductivityOp.cs create mode 100644 TBF/BenchControl/Modbus/WaterAnalyzer/ReadTempOp.cs diff --git a/Config/Properties/AssemblyInfo.cs b/Config/Properties/AssemblyInfo.cs index e55fb988a..517d0e3d8 100644 --- a/Config/Properties/AssemblyInfo.cs +++ b/Config/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.25.1440.0")] -[assembly: AssemblyFileVersion("2.25.1440.0")] +[assembly: AssemblyVersion("2.26.1447.0")] +[assembly: AssemblyFileVersion("2.26.1447.0")] diff --git a/Results/Entities/TestRslt.cs b/Results/Entities/TestRslt.cs index 19ac18a80..577bcc254 100644 --- a/Results/Entities/TestRslt.cs +++ b/Results/Entities/TestRslt.cs @@ -115,6 +115,11 @@ namespace Results.Entities public virtual float FlowEnd { get; set; } /// [m3/h] flow at the end of test from the reference flowmeter public virtual float FlowMin { get; set; } /// [m3/h] public virtual float FlowMax { get; set; } /// [m3/h] + public virtual float ConductMean { get; set; } /// [uS/cm] + public virtual float ConductStart { get; set; } /// [uS/cm] + public virtual float ConductEnd { get; set; } /// [uS/cm] + public virtual float ConductMin { get; set; } /// [uS/cm] + public virtual float ConductMax { get; set; } /// [uS/cm] public virtual float Uncertnt { get; set; } /// [%] Relative error uncertainty public virtual float UncertntScale { get; set; } /// [%] Contribution to uncertainty from scale @@ -331,6 +336,11 @@ namespace Results.Entities FlowEnd = src.FlowEnd; FlowMin = src.FlowMin; FlowMax = src.FlowMax; + ConductMean = src.ConductMean; + ConductStart = src.ConductStart; + ConductEnd = src.ConductEnd; + ConductMin = src.ConductMin; + ConductMax = src.ConductMax; Custom1 = src.Custom1; Custom2 = src.Custom2; diff --git a/Results/Mappings/TestRsltMap.cs b/Results/Mappings/TestRsltMap.cs index 3e33b4121..d7cf3437b 100644 --- a/Results/Mappings/TestRsltMap.cs +++ b/Results/Mappings/TestRsltMap.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2015-2019 Sensus Slovensko a.s. +/// Copyright (c) 2015-2020 Sensus Slovensko a.s. /// using FluentNHibernate.Mapping; using Results.Entities; @@ -102,7 +102,13 @@ namespace Results.Mappings Map(x => x.FlowEnd); Map(x => x.FlowMin); Map(x => x.FlowMax); - +#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL + Map(x => x.ConductMean); + Map(x => x.ConductStart); + Map(x => x.ConductEnd); + Map(x => x.ConductMin); + Map(x => x.ConductMax); +#endif Map(x => x.Uncertnt); Map(x => x.UncertntScale); Map(x => x.UncertntDensity); diff --git a/Results/Properties/AssemblyInfo.cs b/Results/Properties/AssemblyInfo.cs index 80bcb247c..10dc0f906 100644 --- a/Results/Properties/AssemblyInfo.cs +++ b/Results/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.25.1440.0")] -[assembly: AssemblyFileVersion("2.25.1440.0")] +[assembly: AssemblyVersion("2.26.1447.0")] +[assembly: AssemblyFileVersion("2.26.1447.0")] diff --git a/TBF/BenchControl/Modbus/WaterAnalyzer/Analyzer.cs b/TBF/BenchControl/Modbus/WaterAnalyzer/Analyzer.cs new file mode 100644 index 000000000..609daf91b --- /dev/null +++ b/TBF/BenchControl/Modbus/WaterAnalyzer/Analyzer.cs @@ -0,0 +1,141 @@ +/// +/// Copyright (c) 2020 Sensus Slovensko a.s. +/// +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.Generic; +using TBF.Boxes; +using Config.Entities; +using System.Diagnostics; + +namespace TBF.BenchControl.Modbus.WaterAnalyzer +{ + public class Analyzer : ComponentBase, GenericDevices.ITempMeter, IDevice + { + private static readonly ILog log = LogManager.GetLogger(typeof(Analyzer)); + public override string ToString() { return string.Format("Analyzer({0})", Cfg.ToString(1)); } + + readonly AnalyzerCfg myCfg; + readonly GenericDevices.IModbus modbus; + + /// The state of the measurement + MsrmntState msrmntState; + + /// + /// Measured values when MsrmntState == MsrmntState.Valid + /// + double conductivity; /// [???] + double temperature; /// [°C] + + public double Level { get { return conductivity; } } + + /// Measurement time stamp when MsrmntState == MsrmntState.Valid + int msrmntTimeStamp; + + + public Analyzer() + { + } + + public Analyzer(Generic.IComponentCfg cfg, IList components) + : base(cfg) + { + myCfg = cfg as AnalyzerCfg; + + 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() + { + if (myCfg.DebugLevel == DebugMode.Simulate) + { + conductivity = 0.0; + temperature = 0.0; + + msrmntTimeStamp = StateMachine.Time; + msrmntState = MsrmntState.Valid; + return; + } + + msrmntState = MsrmntState.Busy; + + log.FatalFormat("Successfully initialized device {0}", ToString()); + } + + + public double ReadLevel() { return conductivity; } /// Returns water level in mm + public double ReadTemperature() { return temperature; } /// Returns temperature in °C + + public ReadConductivityOp ReadLevelOp(ref DoubleBox level) { return new ReadConductivityOp(this, ref level); } + public IOperation ReadTempOp(ref DoubleBox temperature) { return new ReadTempOp(this, ref temperature); } + public IOperation ReadTempOp(ref DoubleBox temperature, Event eventDone) { return new ReadTempOp(this, ref temperature, eventDone); } + + + /// Run this device + public void RunDeviceBefore() + { + if (myCfg.DebugLevel == Config.Entities.DebugMode.Simulate || + myCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation) + { + msrmntTimeStamp = StateMachine.Time; + return; + } + + if (modbus.ReceivedTelegrams[myCfg.ModbusAddress].Count > 0) + { + byte[] telegram = modbus.ReceivedTelegrams[myCfg.ModbusAddress].Dequeue(); + + if (telegram.Length == 9 && telegram[1] == 3 && telegram[2] == 4) + { + /// + /// Telegram with values + /// + byte[] conductBytes = new byte[] { telegram[4], telegram[3], telegram[6], telegram[5] }; + float _conductivity = System.BitConverter.ToSingle(conductBytes, 0); + string line = string.Format("conductivity = {0} uS/cm", _conductivity); + if (true) + { + conductivity = _conductivity; + } + + log.Debug(line); + Debug.WriteLine(line); + } + } + + + byte[] msg = new byte[8]; /// Buffer for data to send + + if ((StateMachine.Time % 10) == 0) /// Each 10 seconds + { + /// + /// Send command to request 1 float value in 2 registers at addresses 0x50 and 0x51 from Modbus.WaterAnalyzer + /// + UInt16 regAddr = 0x50; + UInt16 count = 2; + + /// Prepare data to be sent + msg[0] = myCfg.ModbusAddress; + msg[1] = 3; /// CMD = + msg[2] = (byte)(regAddr >> 8); /// Control Word Hi + msg[3] = (byte)(regAddr & 0xFF); /// Control Word Lo + msg[4] = (byte)(count >> 8); /// Serial Com Reference Hi + msg[5] = (byte)(count & 0xFF); /// Serial Com Reference Lo + + modbus.SendMessage(msg); + } + } + + public void RunDeviceAfter() { } + public void StopDevice() { } + public void StopDevice2() { } + } +} diff --git a/TBF/BenchControl/Modbus/WaterAnalyzer/AnalyzerCfg.cs b/TBF/BenchControl/Modbus/WaterAnalyzer/AnalyzerCfg.cs new file mode 100644 index 000000000..d5c47c041 --- /dev/null +++ b/TBF/BenchControl/Modbus/WaterAnalyzer/AnalyzerCfg.cs @@ -0,0 +1,146 @@ +/// +/// Copyright (c) 2020 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.WaterAnalyzer +{ + public class AnalyzerCfg : ComponentCfgBase, Generic.IChildComponentCfg, Config.Entities.IParamsProvider + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(AnalyzerCfg) })[0]; + public override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl() + { + IList parents = new List(); + // TODO: + //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); + // } + // } + //} + parents.Add("Modbus"); + parents.Add("ModbusUSB"); + + return new Configs.ParamsProvider.ComponentCfgCtrl(this, parents); + } + + /// + /// Serialized parameters + /// + public byte ModbusAddress; /// 1..247 + + /// Private parameterless constructor invoked by all other (public) constructors + AnalyzerCfg() {} + + public AnalyzerCfg(string name, IComponentFactory factory) + : this() + { + Factory = factory; + Name = name; + ParentName = "ModbusUSB"; + InitializeAll(); + } + + public string ComponentName { get { return Name; } } + + public void InitializeAll() + { + ModbusAddress = 51; + } + + + 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 >= 1 && dummy <= 247) return true; + message = ParamName(i) + " is invalid. Address range is 1 .. 247"; + return false; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + void CopyContentTo(AnalyzerCfg prms) + { + prms.ParentName = this.ParentName; + prms.ModbusAddress = this.ModbusAddress; + } + + + public Config.Entities.IParamsProvider Clone() + { + AnalyzerCfg pars = new AnalyzerCfg(); + CopyContentTo(pars); + return pars; + } + + public bool UpdateEmbeddedDbEntity() + { + return true; /// =OK, do nothing + } + } +} diff --git a/TBF/BenchControl/Modbus/WaterAnalyzer/Factory.cs b/TBF/BenchControl/Modbus/WaterAnalyzer/Factory.cs new file mode 100644 index 000000000..6b948c1be --- /dev/null +++ b/TBF/BenchControl/Modbus/WaterAnalyzer/Factory.cs @@ -0,0 +1,26 @@ +/// +/// Copyright (c) 2020 Sensus Slovensko a.s. +/// +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Modbus.WaterAnalyzer +{ + public class Factory : IComponentFactory + { + public string ClassName { get { return this.GetType().Namespace.Substring(17); } } + + public void ResetStaticProperties() { Analyzer.ResetStaticProperties(); } + + public IComponent DummyComponent() { return new Analyzer(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new Analyzer(cfg, components); } + + public IComponentCfg DefaultConfig() { return new AnalyzerCfg(this.GetType().Namespace.Substring(24), this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(AnalyzerCfg.Serializer, component, this); + } + } +} diff --git a/TBF/BenchControl/Modbus/WaterAnalyzer/ReadConductivityOp.cs b/TBF/BenchControl/Modbus/WaterAnalyzer/ReadConductivityOp.cs new file mode 100644 index 000000000..6111c4b5d --- /dev/null +++ b/TBF/BenchControl/Modbus/WaterAnalyzer/ReadConductivityOp.cs @@ -0,0 +1,58 @@ +/// +/// Copyright (c) 2020 Sensus Slovensko a.s. +/// +using System; +using log4net; +using TBF.Boxes; + +namespace TBF.BenchControl.Modbus.WaterAnalyzer +{ + public class ReadConductivityOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadConductivityOp)); + public override string ToString() { return string.Format("ReadLevelOp(.,.)"); } + + /// Set by the constructor + readonly Analyzer analyzer; + + /// Measured value + DoubleBox conductivity; + + /// + /// Events: LevelDone or Error + /// + /// Water level meter reference + /// Reference to the measured level variable, value is in mm + /// Event to be returned by Run() when completed OK + public ReadConductivityOp(Analyzer analyzer, ref DoubleBox level) + { + if (analyzer == null) throw new ArgumentNullException("analyzer"); + this.analyzer = analyzer; + this.conductivity = level; + + log.Debug(this.ToString()); + } + + + /// Start this operation + public void Start() + { + conductivity.Val = analyzer.ReadLevel(); + } + + /// Run this operation + /// + /// Event.LevelDone + /// + public Event Run() + { + conductivity.Val = analyzer.ReadLevel(); + return Event.LevelDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TBF/BenchControl/Modbus/WaterAnalyzer/ReadTempOp.cs b/TBF/BenchControl/Modbus/WaterAnalyzer/ReadTempOp.cs new file mode 100644 index 000000000..2cedf3e6c --- /dev/null +++ b/TBF/BenchControl/Modbus/WaterAnalyzer/ReadTempOp.cs @@ -0,0 +1,64 @@ +/// +/// Copyright (c) 2020 Sensus Slovensko a.s. +/// +using System; +using log4net; +using TBF.Boxes; + +namespace TBF.BenchControl.Modbus.WaterAnalyzer +{ + public class ReadTempOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadTempOp)); + public override string ToString() { return string.Format("ReadTempOp(.,{0},.)", eventDone); } + + /// Set by the constructor + readonly Analyzer analyzer; + readonly Event eventDone; + + /// Measured value + DoubleBox temperature; + + /// + /// Events: eventDone or Error + /// + /// Water temperature meter reference + /// Reference to the measured temperature variable, value is in l + /// Event to be returned by Run() when completed OK + public ReadTempOp(Analyzer analyzer, ref DoubleBox temperature, Event eventDone) + { + if (analyzer == null) throw new ArgumentNullException("analyzer"); + this.analyzer = analyzer; + this.temperature = temperature; + this.eventDone = eventDone; + + log.Debug(this.ToString()); + } + public ReadTempOp(Analyzer levelMeter, ref DoubleBox temperature) + : this(levelMeter, ref temperature, Event.TempDone) + { + } + + + /// Start this operation + public void Start() + { + temperature.Val = analyzer.ReadTemperature(); + } + + /// Run this operation + /// + /// Event.temperatureDone + /// + public Event Run() + { + temperature.Val = analyzer.ReadTemperature(); + return eventDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TBF/BenchControl/TbfComponents.cs b/TBF/BenchControl/TbfComponents.cs index 4482fa701..68d58a016 100644 --- a/TBF/BenchControl/TbfComponents.cs +++ b/TBF/BenchControl/TbfComponents.cs @@ -120,7 +120,8 @@ namespace TBF.BenchControl 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 Modbus.WaterAnalyzer.Factory()); + Factories.Add(new Network.Adapter.Factory()); Factories.Add(new Network.Camera.CLP1611.Factory()); Factories.Add(new Network.Camera.Display.Factory()); Factories.Add(new Network.Camera.Roi.Factory()); diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index 93e9717ef..75cdf8419 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.25.1440.0")] -[assembly: AssemblyFileVersion("2.25.1440.0")] +[assembly: AssemblyVersion("2.26.1447.0")] +[assembly: AssemblyFileVersion("2.26.1447.0")] diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index 65142a17a..d89bae87d 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -767,6 +767,11 @@ + + + + +