tbf/TBF/Rig/Network/Comet/Ambient/Ambient.cs

261 lines
8.5 KiB
C#

///
/// 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 TBF.Rig.Generic;
using TBF.Boxes;
namespace TBF.Rig.Network.Comet.Ambient
{
/// <summary>
/// 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.
/// </summary>
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;
IPAddress ipAddress;
int tcpPort;
TcpClient tcpClient;
NetworkStream networkStream;
enum State
{
Idle,
WaitingForTemperature,
WaitingForHumidity,
WaitingForPressure,
};
State state;
///
/// Measured values when MsrmntState == MsrmntState.Valid
///
float temperature; /// [°C]
float pressure; /// [bar]
float humidity; /// [R%]
/// <summary>Measurement time stamp when MsrmntState == MsrmntState.Valid</summary>
int msrmntTimeStamp;
public Ambient() { }
/// <summary>
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
/// </summary>
public Ambient(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
myCfg = cfg as AmbientCfg;
}
public override void Initialize()
{
temperature = 20.0f;
humidity = 40.0f;
pressure = 1.0f;
msrmntTimeStamp = 0;
ipAddress = IPAddress.Parse(myCfg.IPAddress);
tcpPort = myCfg.TcpPort;
state = State.Idle;
if (myCfg.DebugLevel == DebugMode.Normal)
{
tcpClient = new TcpClient();
tcpClient.Connect(ipAddress, tcpPort);
networkStream = tcpClient.GetStream();
log.FatalFormat("{0} initialized: {1}", Name, this);
}
else
{
log.FatalFormat("{0} simulated: {1}", Name, this);
}
}
/// <summary>Run this device</summary>
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 = (float)(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 = (float)(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 = (float)(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);
}
}
}
/// <summary>Run this device</summary>
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);
}
}
}
/// <summary>Stop this device</summary>
public void StopDevice()
{
if (myCfg.DebugLevel != DebugMode.Simulate && myCfg.DebugLevel != DebugMode.FailureDuringOperation)
{
networkStream.Close();
tcpClient.Close();
}
}
public void StopDevice2() { }
void UpdateProcessData(float temperature, float pressure, float 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
///
FloatBox tempBox;
FloatBox pressureBox;
FloatBox humiBox;
public IOperation ReadAmbientOp(FloatBox tempBox, FloatBox pressureBox, FloatBox humiBox)
{
this.tempBox = tempBox;
this.pressureBox = pressureBox;
this.humiBox = humiBox;
return this;
}
/// <summary>Start this operation</summary>
public void Start()
{
if (tempBox != null) tempBox.Val = temperature;
if (pressureBox != null) pressureBox.Val = pressure;
if (humiBox != null) humiBox.Val = humidity;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if (tempBox != null) tempBox.Val = temperature;
if (pressureBox != null) pressureBox.Val = pressure;
if (humiBox != null) humiBox.Val = humidity;
return Event.AmbientDone;
}
/// <summary>Stop this operation</summary>
public void Stop() { }
}
}