Refactorization : BenchControl -> Rig
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Modbus.UltrasoundLevelMeter
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { LevelMeter.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new LevelMeter(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new LevelMeter(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new LevelMeterCfg(this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(LevelMeterCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Boxes;
|
||||
using Config.Entities;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TBF.Rig.Modbus.UltrasoundLevelMeter
|
||||
{
|
||||
public class LevelMeter : ComponentBase, GenericDevices.ILevelMeter, 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;
|
||||
|
||||
/// <summary>The state of the measurement</summary>
|
||||
MsrmntState msrmntState;
|
||||
|
||||
///
|
||||
/// Measured values when MsrmntState == MsrmntState.Valid
|
||||
///
|
||||
double distance; /// [mm]
|
||||
double level; /// [mm]
|
||||
double percentage; /// [%]
|
||||
double temperature; /// [°C]
|
||||
ushort state;
|
||||
|
||||
public double Level { get { return level; } }
|
||||
|
||||
/// <summary>Measurement time stamp when MsrmntState == MsrmntState.Valid</summary>
|
||||
int msrmntTimeStamp;
|
||||
|
||||
|
||||
public LevelMeter()
|
||||
{
|
||||
}
|
||||
|
||||
public LevelMeter(Generic.IComponentCfg cfg, IList<Generic.IComponent> 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.Warn(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Initialize this device</summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (myCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
distance = 200.0;
|
||||
level = 0;
|
||||
percentage = 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 ReadTemperature() { return temperature; } /// Returns temperature in °C
|
||||
|
||||
public IOperation ReadLevelOp(ref DoubleBox level) { return new ReadLevelOp(this, ref level); }
|
||||
public IOperation ReadStableLevelOp(ref DoubleBox level, double sdev) { return new ReadStableLevelOp(this, ref level, sdev); }
|
||||
public IOperation ManualReadLevelOp(ref DoubleBox level) { return null; }
|
||||
public IOperation ReadTempOp(ref DoubleBox temperature) { return new ReadTempOp(this, ref temperature); }
|
||||
public IOperation ReadTempOp(ref DoubleBox temperature, Event eventDone) { return new ReadTempOp(this, ref temperature, eventDone); }
|
||||
|
||||
|
||||
/// <summary>Run this device</summary>
|
||||
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)
|
||||
{
|
||||
double _distance = (double)(256 * telegram[3] + telegram[4]); /// [mm]
|
||||
double _level = (double)(256 * telegram[5] + telegram[6]); /// [mm]
|
||||
double _percentage = (double)(256 * telegram[7] + telegram[8]); /// [%]
|
||||
double _temperature = (double)(256 * telegram[9] + telegram[10]); /// [°C]
|
||||
ushort _state = (ushort)(256 * telegram[11] + telegram[12]);
|
||||
|
||||
string line = string.Format("dist={0} mm level={1} mm, %={2} %, temp={3} °C, state={4}",
|
||||
_distance, _level, _percentage, _temperature, _state);
|
||||
if (_distance > 0)
|
||||
{
|
||||
distance = _distance;
|
||||
level = _level;
|
||||
percentage = _percentage;
|
||||
temperature = _temperature;
|
||||
state = _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() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Modbus.UltrasoundLevelMeter
|
||||
{
|
||||
public class LevelMeterCfg : ComponentCfgBase, Generic.IChildComponentCfg, Config.Entities.IParamsProvider
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(LevelMeterCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities)
|
||||
{
|
||||
var parents = cmpntEntities.Where(x => x.ClassName == "Modbus.Common");
|
||||
return new Configs.ParamsProvider.ComponentCfgCtrl(this, parents);
|
||||
}
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public byte ModbusAddress; /// 1..247
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
LevelMeterCfg() {}
|
||||
|
||||
public LevelMeterCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Factory = factory;
|
||||
Name = "ULM";
|
||||
ParentName = "Modbus";
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
ModbusAddress = 1;
|
||||
}
|
||||
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Modbus address",
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
public ICollection<string> ParamValues(int i) { return null; }
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return string.Format("ModbusAddr={0}", ModbusAddress);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: return ModbusAddress.ToString();
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
byte addr = byte.Parse(strValue);
|
||||
if (ModbusAddress != addr)
|
||||
{
|
||||
ModbusAddress = addr;
|
||||
return CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CfgUpdateFlags.None;
|
||||
}
|
||||
|
||||
default:
|
||||
return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
int dummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (int.TryParse(strValue, out dummy) && dummy >= 1 && dummy <= 247) return true;
|
||||
message = ParamName(i) + " is invalid. Address range is 1 .. 247";
|
||||
return false;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(LevelMeterCfg prms)
|
||||
{
|
||||
prms.ParentName = this.ParentName;
|
||||
prms.ModbusAddress = this.ModbusAddress;
|
||||
}
|
||||
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
LevelMeterCfg pars = new LevelMeterCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Modbus.UltrasoundLevelMeter
|
||||
{
|
||||
public class ReadLevelOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ReadLevelOp));
|
||||
public override string ToString() { return string.Format("ReadLevelOp(.,.)"); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly LevelMeter levelMeter;
|
||||
|
||||
/// Measured value
|
||||
DoubleBox level;
|
||||
|
||||
/// <summary>
|
||||
/// Events: LevelDone or Error
|
||||
/// </summary>
|
||||
/// <param name="levelMeter">Water level meter reference</param>
|
||||
/// <param name="level">Reference to the measured level variable, value is in mm</param>
|
||||
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
|
||||
public ReadLevelOp(LevelMeter levelMeter, ref DoubleBox level)
|
||||
{
|
||||
if (levelMeter == null) throw new ArgumentNullException("levelMeter");
|
||||
this.levelMeter = levelMeter;
|
||||
this.level = level;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
level.Val = levelMeter.ReadLevel();
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.LevelDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
level.Val = levelMeter.ReadLevel();
|
||||
return Event.LevelDone;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Modbus.UltrasoundLevelMeter
|
||||
{
|
||||
public class ReadStableLevelOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ReadLevelOp));
|
||||
public override string ToString() { return string.Format("ReadLevelOp(.,.)"); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly LevelMeter levelMeter;
|
||||
readonly DoubleBox level;
|
||||
readonly double sdev;
|
||||
|
||||
/// <summary>
|
||||
/// Events: LevelDone or Error
|
||||
/// </summary>
|
||||
/// <param name="levelMeter">Water level meter reference</param>
|
||||
/// <param name="level">Reference to the measured level variable, value is in mm</param>
|
||||
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
|
||||
public ReadStableLevelOp(LevelMeter levelMeter, ref DoubleBox level, double sdev)
|
||||
{
|
||||
if (levelMeter == null) throw new ArgumentNullException("levelMeter");
|
||||
this.levelMeter = levelMeter;
|
||||
this.level = level;
|
||||
this.sdev = sdev;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
level.Val = levelMeter.ReadLevel();
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.LevelDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
level.Val = levelMeter.ReadLevel();
|
||||
return Event.LevelDone;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Modbus.UltrasoundLevelMeter
|
||||
{
|
||||
public class ReadTempOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ReadTempOp));
|
||||
public override string ToString() { return string.Format("ReadTempOp(.,{0},.)", eventDone); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly LevelMeter levelMeter;
|
||||
readonly Event eventDone;
|
||||
|
||||
/// Measured value
|
||||
DoubleBox temperature;
|
||||
|
||||
/// <summary>
|
||||
/// Events: eventDone or Error
|
||||
/// </summary>
|
||||
/// <param name="levelMeter">Water temperature meter reference</param>
|
||||
/// <param name="temperature">Reference to the measured temperature variable, value is in l</param>
|
||||
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
|
||||
public ReadTempOp(LevelMeter levelMeter, ref DoubleBox temperature, Event eventDone)
|
||||
{
|
||||
if (levelMeter == null) throw new ArgumentNullException("levelMeter");
|
||||
this.levelMeter = levelMeter;
|
||||
this.temperature = temperature;
|
||||
this.eventDone = eventDone;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
public ReadTempOp(LevelMeter levelMeter, ref DoubleBox temperature)
|
||||
: this(levelMeter, ref temperature, Event.TempDone)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
temperature.Val = levelMeter.ReadTemperature();
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.temperatureDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
temperature.Val = levelMeter.ReadTemperature();
|
||||
return eventDone;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user