/// /// Copyright (c) 2018 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using log4net; using Common; using Config.Entities; using TBF.Rig.Generic; using TBF.Boxes; namespace TBF.Rig.Network.Comet.Ambient { /// /// 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 { private static readonly ILog log = LogManager.GetLogger(typeof(Ambient)); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } readonly AmbientCfg myCfg; readonly IPAddress ipAddress; TcpClient tcpClient; NetworkStream networkStream; enum State { Idle, WaitingForTemperature, WaitingForHumidity, WaitingForPressure, }; State state; /// /// 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) { myCfg = cfg as AmbientCfg; ipAddress = IPAddress.Parse(myCfg.IPAddress); log.Warn(this.ToString()); } public override void Initialize() { if (myCfg.DebugLevel == DebugMode.Simulate) { temperature = 20.0; humidity = 40.0; pressure = 1.0; msrmntTimeStamp = StateMachine.Time; log.FatalFormat("{0} - Device simulated", Name); } else { tcpClient = new TcpClient(); tcpClient.Connect(ipAddress, myCfg.TcpPort); networkStream = tcpClient.GetStream(); state = State.Idle; log.FatalFormat("{0} - Device successfully initialized", Name); } } /// Run this device public void RunDeviceBefore() { if (myCfg.DebugLevel == DebugMode.Simulate || myCfg.DebugLevel == DebugMode.FailureDuringOperation) { msrmntTimeStamp = StateMachine.Time; return; } try { int available = tcpClient.Available; if (available >= 11) { byte[] bytes = new byte[available]; networkStream.Read(bytes, 0, available); log.Debug(Telegram.LogTelegram("Received ", bytes)); int value; if (available == 11 && bytes[0] == 0 && bytes[2] == 0 && bytes[3] == 0 && bytes[4] == 0 && bytes[5] == 5 && bytes[6] == 1 && bytes[7] == 3 && bytes[8] == 2) { switch (state) { case State.WaitingForTemperature: value = (int)bytes[9] * 256 + (int)bytes[10]; temperature = value / 10.0; /// Conversion to °C msrmntTimeStamp = StateMachine.Time; log.InfoFormat("Ambient temperature = {0:F1} C", temperature); state = State.Idle; break; case State.WaitingForHumidity: value = (int)bytes[9] * 256 + (int)bytes[10]; humidity = value / 10.0; /// Conversion to R% msrmntTimeStamp = StateMachine.Time; log.InfoFormat("Ambient humidity = {0:F1} %", humidity); state = State.Idle; break; case State.WaitingForPressure: value = (int)bytes[9] * 256 + (int)bytes[10]; pressure = value / 10000.0; /// Conversion to bar msrmntTimeStamp = StateMachine.Time; log.InfoFormat("Ambient pressure = {0:F0} mbar", 1000 * pressure); state = State.Idle; break; } } else { state = State.Idle; } } UpdateProcessData(temperature, pressure, humidity); log.InfoFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure); } catch (Exception e) { DebugLevel = DebugMode.FailureDuringOperation; 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() { if (myCfg.DebugLevel == DebugMode.Simulate || myCfg.DebugLevel == DebugMode.FailureDuringOperation) { return; } try { /// 20 seconds cycle byte[] message = null; switch (StateMachine.Time % 20) { case 0: state = State.WaitingForTemperature; message = new byte[12] { 0, 0, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x30, 0, 0x01 }; break; case 6: state = State.WaitingForHumidity; message = new byte[12] { 0, 0x02, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x31, 0, 0x01 }; break; case 12: state = State.WaitingForPressure; message = new byte[12] { 0, 0x03, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x33, 0, 0x01 }; break; } if (message != null) { log.Debug(Telegram.LogTelegram("Sending ", message)); networkStream.Write(message, 0, message.Length); /// Read request } } catch (Exception e) { DebugLevel = DebugMode.FailureDuringOperation; log.FatalFormat("TCP/IP write error : {0}", e.Message); if (e.InnerException != null) { log.FatalFormat("InnerMessage : {0}", e.InnerException.Message); } } } /// Stop this device public void StopDevice() { if (myCfg.DebugLevel != DebugMode.Simulate && myCfg.DebugLevel != DebugMode.FailureDuringOperation) { networkStream.Close(); tcpClient.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 tempBox, DoubleBox pressureBox, DoubleBox humiBox) { this.tempBox = tempBox; this.pressureBox = pressureBox; this.humiBox = humiBox; 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() { } } }