/// /// Copyright (c) 2017 Sensus Metering Systems /// using System; using System.Collections.Generic; using log4net; using TBF.BenchControl.Generic; using TBF.Boxes; using Config.Entities; namespace TBF.BenchControl.Modbus.Easytherm { public class Easytherm : ComponentBase, IDevice, GenericDevices.ITempMeter { private static readonly ILog log = LogManager.GetLogger(typeof(Easytherm)); public override string ToString() { return string.Format("Easytherm({0})", Cfg.ToString(1)); } readonly EasythermCfg easythermCfg; readonly GenericDevices.IModbus modbus; private float temperatureSetPoint; private bool temperatureSetPointValid; private bool temperatureSetPointRequested; public float requiredTemp { get { return easythermCfg.ProcParams.RequiredTemp; } } public Easytherm() { } public Easytherm(Generic.IComponentCfg cfg, IList components) : base(cfg) { easythermCfg = cfg as EasythermCfg; modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components); if (modbus == null) throw new Exception("Cannot find " + Name + " parent"); log.Debug(this.ToString()); } /// Initialize this device public void Initialize() { if (easythermCfg.DebugLevel == DebugMode.Simulate) return; temperatureSetPointValid = false; temperatureSetPointRequested = false; actualTemperatureIsValid = false; } /// Run this device public void RunDeviceBefore() { if (easythermCfg.DebugLevel == DebugMode.Simulate) return; if (modbus.ReceivedTelegrams[easythermCfg.ModbusAddress].Count > 0) { byte[] telegram = modbus.ReceivedTelegrams[easythermCfg.ModbusAddress].Dequeue(); if (telegram.Length == 7 && telegram[1] == (byte)Function.ReadHoldingRegisters && telegram[2] == 2) { ushort value = (ushort)(256 * telegram[3] + telegram[4]); temperatureSetPoint = (float)value * 0.04f; temperatureSetPointValid = true; log.InfoFormat("{0} - Received current temperature setpoint = {1}", Name, temperatureSetPoint); } else if (telegram.Length == 7 && telegram[1] == (byte)Function.ReadInputRegister && telegram[2] == 2) { ushort value = (ushort)(256 * telegram[3] + telegram[4]); actualTemperature = (double)value * 0.04; actualTemperatureIsValid = true; log.InfoFormat("{0} - Received actual temperature = {1}", Name, actualTemperature); if (easythermCfg.ReservoirNr > 0 && easythermCfg.ReservoirNr <= 3) { StateMachine.ControlBoard.SetReservoirTemp(easythermCfg.ReservoirNr, (float)actualTemperature); } } } if (!temperatureSetPointValid && !temperatureSetPointRequested) { RequestTemperatureSetpoint(); temperatureSetPointRequested = true; } else if (temperatureSetPointValid && requiredTemp != temperatureSetPoint) { SetTemperatureSetpoint(requiredTemp); log.InfoFormat("{0} - Set new temperature setpoint = {1}", Name, requiredTemp); } else if ((StateMachine.Time % 10) == (easythermCfg.ModbusAddress % 10)) /// This is to prevent overflow of the Modbus component queue for sending data { RequestActualTemperature(); } } /// Run this device public void RunDeviceAfter() { if (easythermCfg.DebugLevel == DebugMode.Simulate) return; } /// Stop this device public void StopDevice() { if (easythermCfg.DebugLevel == DebugMode.Simulate) return; } /// /// Set Easytherm controller to required temperature procedure parameter /// /// true = OK, false = any error public bool SetTemperatureSetpoint() { return SetTemperatureSetpoint(requiredTemp); } /// /// Set Easytherm controller to specified temperature /// /// Temperature in °C /// true = OK, false = any error public bool SetTemperatureSetpoint(float temperature) { if (temperature != 0 && (temperature < 5 || temperature > 95.0f)) { return false; /// required temperature out of range } if (temperatureSetPointValid && (temperature == temperatureSetPoint)) { return true; /// already set to the required temperature } if (temperature != 0) /// temperature==0 disables sending the setpoint { //ushort temperatureSetpoint = (ushort)temperature; // in °C //ushort destAddress = (ushort)1002; ushort usTempSetpoint = (ushort)((10000.0f / 400.0f) * temperature); // in 0.01% of range (400 °C) ushort destAddress = (ushort)2; /// SendValueToEasytherm(Function.PresetSingleRegister, destAddress, usTempSetpoint); } temperatureSetPoint = temperature; temperatureSetPointValid = true; return true; } public void RequestTemperatureSetpoint() { SendValueToEasytherm(Function.ReadHoldingRegisters, (ushort)2, (ushort)1); // rel.address=2, 1 word } public void RequestActualTemperature() { SendValueToEasytherm(Function.ReadInputRegister, (ushort)0, (ushort)1); // rel.address=x, 1 word } void SendValueToEasytherm(Function function, ushort address, ushort value) { byte[] msg = new byte[8]; msg[0] = easythermCfg.ModbusAddress; msg[1] = (byte)function; msg[2] = (byte)(address >> 8); /// Relative address Hi msg[3] = (byte)(address & 0xFF); /// Relative address Lo msg[4] = (byte)(value >> 8); /// Data Hi msg[5] = (byte)(value & 0xFF); /// Data Lo modbus.SendMessage(msg); } /// /// Operations, etc. /// double actualTemperature; bool actualTemperatureIsValid; public double ReadTemperature() { return actualTemperature; } /// /// Events: SetOpututsDone, Error /// /// SetOutputsOp instance reference casted to IOperaton public IOperation SetRequiredTemperatureOp() { return new SetRequiredTemperatureOp(this); } /// /// Events: SetOpututsDone, Error /// /// Reference to a variable for the pressure in Bar /// SetOutputsOp instance reference casted to IOperaton public IOperation SetTemperatureOp(float temperature) { return new SetTemperatureOp(this, temperature); } public IOperation ReadTempOp(ref DoubleBox temp) { return new ReadTempOp(this, ref temp); } public IOperation ReadTempOp(ref DoubleBox temp, Event eventDone) { return new ReadTempOp(this, ref temp, eventDone); } } }