/// /// Copyright (c) 2017-2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using log4net; using Config; using Config.Entities; using SchematicDrawing; using TBF.BenchControl.Generic; using TBF.Boxes; namespace TBF.BenchControl.Modbus.Ambient.Comet { /// /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) /// Connection settings: 9600 Bd 8-bits No-parity 2-stop-bits Flow control: none. /// 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("Ambient({0})", Cfg.ToString(1)); } /// /// Configuration and wrappers /// 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 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)); } } readonly GenericDevices.IModbus modbus; /// The state of the measurement MsrmntState msrmntState; /// /// 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) /// public Ambient(Generic.IComponentCfg cfg, IList components) : base(cfg) { ambientCfg = cfg as AmbientCfg; modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components); if (modbus == null) throw new Exception("Cannot find " + Name + " parent"); temperature = DefaultTemperature; pressure = DefaultPressure; humidity = DefaultHumidity; log.Warn(this.ToString()); } public void Initialize() { if (ambientCfg.DebugLevel == DebugMode.Simulate) { msrmntTimeStamp = StateMachine.Time; msrmntState = MsrmntState.Valid; return; } msrmntState = MsrmntState.Busy; log.FatalFormat("Successfully initialized device {0}", ToString()); } /// Run this device public void RunDeviceBefore() { if (ambientCfg.DebugLevel == DebugMode.Simulate || ambientCfg.DebugLevel == DebugMode.FailureDuringOperation) { msrmntTimeStamp = StateMachine.Time; return; } if (modbus.ReceivedTelegrams[ambientCfg.ModbusAddress].Count > 0) { byte[] telegram = modbus.ReceivedTelegrams[ambientCfg.ModbusAddress].Dequeue(); if (telegram.Length == 13 && telegram[1] == 3 && telegram[2] == 8) { int value = (int)telegram[3] * 256 + (int)telegram[4]; temperature = value / 10.0; value = (int)telegram[5] * 256 + (int)telegram[6]; humidity = value / 10.0; value = (int)telegram[9] * 256 + (int)telegram[10]; pressure = value / 10000.0; msrmntTimeStamp = StateMachine.Time; msrmntState = MsrmntState.Valid; UpdateProcessData(temperature, pressure, humidity); log.InfoFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure); } } if ((StateMachine.Time % 10) == (ambientCfg.ModbusAddress % 10)) /// Each 10 seconds { /// Read four registers: 0x31, 0x32, 0x33, 0x34 UInt16 regAddr = 0x0030; /// register addr. = 0x31 (Modbus!) UInt16 count = 4; /// Prepare data to be sent byte[] msg = new byte[8]; msg[0] = (byte)ambientCfg.ModbusAddress; msg[1] = 3; /// CMD = Read registers 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() { } void UpdateProcessData(double temperature, double pressure, double humidity) { TBF.BenchControl.Sequences.ProcessData.AmbTemp.Val = temperature; TBF.BenchControl.Sequences.ProcessData.AmbPress.Val = pressure; TBF.BenchControl.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() { } } }