/// /// Copyright (c) 2013-2016 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Globalization; using System.IO.Ports; using System.Text; using log4net; using Common; using Config.Entities; using SchematicDrawing; using TBF.Rig.Generic; using TBF.Boxes; namespace TBF.Rig.Ambient.Greco { /// /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) /// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware. /// public class Ambient : ComponentBase, IDevice, IOperation, GenericDevices.IAmbient, IDrawingItCmpntWithMeasuredVal { private static readonly ILog log = LogManager.GetLogger(typeof(Ambient)); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } private readonly AmbientCfg ambientCfg; /// Unit TempUnit { get { return ambientCfg.TempUnit; } } double TempLimLo { get { return Units.ConvertFrom(TempUnit, ambientCfg.TempLimLo); } } double TempLimHi { get { return Units.ConvertFrom(TempUnit, ambientCfg.TempLimHi); } } double DefaultTemperature { get { return Units.ConvertFrom(TempUnit, ambientCfg.DefaultTemp); } } /// Unit PressureUnit { get { return ambientCfg.PressureUnit; } } double PressureLimLo { get { return Units.ConvertFrom(PressureUnit, ambientCfg.PressureLimLo); } } double PressureLimHi { get { return Units.ConvertFrom(PressureUnit, ambientCfg.PressureLimHi); } } double DefaultPressure { get { return Units.ConvertFrom(PressureUnit, ambientCfg.DefaultPressure); } } /// Unit HumiUnit { get { return ambientCfg.HumiUnit; } } double HumiLimLo { get { return Units.ConvertFrom(HumiUnit, ambientCfg.HumiLimLo); } } double HumiLimHi { get { return Units.ConvertFrom(HumiUnit, ambientCfg.HumiLimHi); } } double DefaultHumidity { get { return Units.ConvertFrom(HumiUnit, ambientCfg.DefaultHumi); } } /// /// IDrawingItCmpntWithMeasuredVal interface /// public IDrawingItem DrawingItem { get { return ambientCfg as IDrawingItem; } } public bool MsrmntAvailable { get { return true; } } public double MeasuredVal { get { return temperature; } } public string AltString { get { return string.Format(ambientCfg.Format, Units.ConvertTo(TempUnit, temperature), Units.ConvertTo(PressureUnit, pressure), Units.ConvertTo(HumiUnit, humidity)); } } /// Private fields SerialPort serialPort; StringBuilder measurementBuilder; /// /// Measured values when MsrmntState == MsrmntState.Valid /// double temperature; /// [°C] double pressure; /// [bar] double humidity; /// [R%] /// Measurement time stamp when MsrmntState == MsrmntState.Valid int msrmntTimeStamp; public Ambient() { } /// /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) /// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware. /// public Ambient(Generic.IComponentCfg cfg) : base(cfg) { ambientCfg = cfg as AmbientCfg; log.Warn(this.ToString()); } public override void Initialize() { temperature = DefaultTemperature; pressure = DefaultPressure; humidity = DefaultHumidity; msrmntTimeStamp = 0; if (ambientCfg.DebugLevel == DebugMode.Normal) { string comPortName = "COM" + ambientCfg.ComPortNr.ToString(); serialPort = new SerialPort(comPortName, ambientCfg.BaudRate, ambientCfg.Parity, ambientCfg.DataBits, ambientCfg.StopBits); serialPort.Handshake = ambientCfg.Handshake; serialPort.Open(); measurementBuilder = new StringBuilder(40); log.FatalFormat("{0} - Device successfully initialized", Name); } else { serialPort = null; log.FatalFormat("{0} - Device simulated", Name); } } /// Run this device public void RunDeviceBefore() { if (ambientCfg.DebugLevel == DebugMode.Simulate || ambientCfg.DebugLevel == DebugMode.FailureDuringOperation) { msrmntTimeStamp = StateMachine.Time; return; } try { measurementBuilder.Append(serialPort.ReadExisting()); int len = measurementBuilder.Length; /// /// Device sends each 20 sec one line of ASCII text with data in the following format: /// (temp) 6 characters, two decimal digits, with leading spaces /// TAB 1 character /// (humi) 6 characters, two decimal digits, with leading spaces /// TAB 1 character /// (pressure) 6 characters, one decimal digits, with leading spaces is LT 1000 /// CR + LF 2 characters /// Example: /// 23.42 38.08 1061.1 /// 23.39 38.04 1060.8 /// 23.39 38.08 1061.4 /// if (len >= 22) { string measurement = measurementBuilder.ToString(); measurementBuilder.Clear(); double t = 0; double h = 0; double p = 0; if (double.TryParse(measurement.Substring(len - 22, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, CultureInfo.InvariantCulture, out t) && measurement[len - 16] == '\t' && double.TryParse(measurement.Substring(len - 15, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, CultureInfo.InvariantCulture, out h) && measurement[len - 9] == '\t' && double.TryParse(measurement.Substring(len - 8, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, CultureInfo.InvariantCulture, out p) && measurement[len - 2] == '\r' && measurement[len - 1] == '\n') { temperature = t; humidity = h; pressure = p / 1000.0; UpdateProcessData(temperature, pressure, humidity); msrmntTimeStamp = StateMachine.Time; log.InfoFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure); } else { log.Warn("Invalid string received: " + measurement); } } } catch (Exception e) { DebugLevel = DebugMode.FailureDuringOperation; serialPort = null; log.FatalFormat("Ambient: Serail port read failure : {0}", e.Message); if (e.InnerException != null) { log.FatalFormat("InnerMessage : {0}", e.InnerException.Message); } } } /// Run this device public void RunDeviceAfter() { } /// Stop this device public void StopDevice() { if (serialPort != null && serialPort.IsOpen) serialPort.Close(); } public void StopDevice2() { } void UpdateProcessData(double temperature, double pressure, double humidity) { TBF.Rig.Sequences.ProcessData.AmbTemp.Val = temperature; TBF.Rig.Sequences.ProcessData.AmbPress.Val = pressure; TBF.Rig.Sequences.ProcessData.AmbHumi.Val = humidity; } /// /// Boxes for the operation result /// DoubleBox tempBox; DoubleBox pressureBox; DoubleBox humiBox; public IOperation ReadAmbientOp(DoubleBox temperature, DoubleBox pressure, DoubleBox humidity) { this.tempBox = temperature; this.pressureBox = pressure; this.humiBox = humidity; return this; } /// Start this operation public void Start() { if (tempBox != null) tempBox.Val = temperature; if (pressureBox != null) pressureBox.Val = pressure; if (humiBox != null) humiBox.Val = humidity; } /// Run this operation /// /// Event.FlowInDone or Event.FlowOutDone /// public Event Run() { if (tempBox != null) tempBox.Val = temperature; if (pressureBox != null) pressureBox.Val = pressure; if (humiBox != null) humiBox.Val = humidity; return Event.AmbientDone; } /// Stop this operation public void Stop() { } } }