/// /// Copyright (c) 2018 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using log4net; using TBF.BenchControl.Generic; using TBF.Boxes; using Config.Entities; using System.Diagnostics; namespace TBF.BenchControl.Modbus.UltrasoundLevelMeter { public class LevelMeter : ComponentBase, GenericDevices.ILevelMeter, GenericDevices.IVolumeMeter, GenericDevices.ITempMeter, IDevice { private static readonly ILog log = LogManager.GetLogger(typeof(LevelMeter)); public override string ToString() { return string.Format("LevelMeter({0})", Cfg.ToString(1)); } readonly LevelMeterCfg myCfg; readonly GenericDevices.IModbus modbus; /// The state of the measurement MsrmntState msrmntState; /// /// Measured values when MsrmntState == MsrmntState.Valid /// double distance; /// [mm] double level; /// [mm] double percentage; /// [%] double volume; /// [l] double temperature; /// [°C] ushort state; /// Measurement time stamp when MsrmntState == MsrmntState.Valid int msrmntTimeStamp; public LevelMeter() { } public LevelMeter(Generic.IComponentCfg cfg, IList components) : base(cfg) { myCfg = cfg as LevelMeterCfg; modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components); if (modbus == null) throw new Exception("Cannot find " + Name + " parent"); /// Connect to handler //ModbusAddress.MeretRS485Address[Idx0] = ModbusAddress; log.Debug(this.ToString()); } /// Initialize this device public void Initialize() { if (myCfg.DebugLevel == DebugMode.Simulate) { distance = 200.0; level = 0; percentage = 0; volume = 0; temperature = 20.0; state = 0; msrmntTimeStamp = StateMachine.Time; msrmntState = MsrmntState.Valid; return; } msrmntState = MsrmntState.Busy; log.FatalFormat("Successfully initialized device {0}", ToString()); } public double ReadLevel() { return level; } /// Returns water level in mm public double ReadVolume() { return volume; } /// Returns volume in l public double ReadTemperature() { return temperature; } /// Returns temperature in °C public IOperation ReadLevelOp(ref DoubleBox level) { return new ReadLevelOp(this, ref level); } public IOperation ReadVolumeOp(ref DoubleBox volume) { return new ReadVolumeOp(this, ref volume); } public IOperation ReadTempOp(ref DoubleBox temperature) { return new ReadTempOp(this, ref temperature); } public IOperation ReadLevelOp(ref DoubleBox level, Event eventDone) { return new ReadLevelOp(this, ref level, eventDone); } public IOperation ReadVolumeOp(ref DoubleBox volume, Event eventDone) { return new ReadVolumeOp(this, ref volume, eventDone); } public IOperation ReadTempOp(ref DoubleBox temperature, Event eventDone) { return new ReadTempOp(this, ref temperature, eventDone); } /// Run this device public void RunDeviceBefore() { if (myCfg.DebugLevel == Config.Entities.DebugMode.Simulate || myCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation) { msrmntTimeStamp = StateMachine.Time; return; } if (modbus.ReceivedTelegrams[myCfg.ModbusAddress].Count > 0) { byte[] telegram = modbus.ReceivedTelegrams[myCfg.ModbusAddress].Dequeue(); if (telegram.Length == 15 && telegram[1] == 3 && telegram[2] == 10) { distance = (double)(256 * telegram[3] + telegram[4]); level = (double)(256 * telegram[5] + telegram[6]); percentage = (double)(256 * telegram[7] + telegram[8]); temperature = (double)256 * telegram[9] + telegram[10]; state = (ushort)(256 * telegram[11] + telegram[12]); volume = 0; /// TODO string line = string.Format("dist={0} mm level={1} mm, %={2} %, temp={3} °C, volume={4} l, state={5}", distance, level, percentage, temperature, volume, state); log.Debug(line); Debug.WriteLine(line); } } byte[] msg = new byte[8]; /// Buffer for data to send if ((StateMachine.Time % 3) == 0) /// Each 3 seconds { /// /// Read distance, level, quantity, percentage and temperature in IEEE754 (DWORD-s) /// UInt16 regAddr = 100; UInt16 count = 5; /// Prepare data to be sent msg[0] = myCfg.ModbusAddress; msg[1] = 3; /// CMD = 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); } else if ((StateMachine.Time % 3) == 1) /// Each 3 seconds { ///// ///// Read STATUS1 ///// //UInt16 regAddr = 104; //UInt16 count = 1; ///// Prepare data to be sent //msg[0] = myCfg.ModbusAddress; //msg[1] = 3; /// CMD = //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); } else if ((StateMachine.Time % 3) == 2) /// Each 3 seconds { ///// ///// Read distance, level, quantity, percentage and temperature in IEEE754 (DWORD-s) ///// //UInt16 regAddr = 300; //UInt16 count = 10; ///// Prepare data to be sent //msg[0] = myCfg.ModbusAddress; //msg[1] = 3; /// CMD = //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() { } } }