Modbus: Data receive improved, Meret.TempMeter, Meret.PressureMeter, Danfoss.VLT added, QuidoRS modified.

This commit is contained in:
Milan Hanajik 2020-05-19 16:33:38 +02:00
parent 767796662e
commit c007bca797
34 changed files with 1686 additions and 224 deletions

View File

@ -662,9 +662,9 @@ namespace DeviceTest
int previousOperation = 0;
if (tbfComponent1forOp is TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter)
if (tbfComponent1forOp is TBF.BenchControl.Modbus.Meret.PressureMeter.PressureMeter)
{
operation1 = (tbfComponent1forOp as TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter).ReadPressureOp(ref floatBox);
operation1 = (tbfComponent1forOp as TBF.BenchControl.Modbus.Meret.PressureMeter.PressureMeter).ReadPressureOp(ref floatBox);
}
else if (tbfComponent1forOp is TBF.BenchControl.Network.Camera.CLP1611.Camera)
{
@ -701,9 +701,9 @@ namespace DeviceTest
}
if (tbfComponent2forOp is TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter)
if (tbfComponent2forOp is TBF.BenchControl.Modbus.Meret.PressureMeter.PressureMeter)
{
operation21 = (tbfComponent2forOp as TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter).ReadPressureOp(ref floatBox);
operation21 = (tbfComponent2forOp as TBF.BenchControl.Modbus.Meret.PressureMeter.PressureMeter).ReadPressureOp(ref floatBox);
}
else if (tbfComponent2forOp is TBF.BenchControl.Network.Camera.CLP1611.Camera)
{
@ -740,9 +740,9 @@ namespace DeviceTest
}
if (tbfComponent3forOp is TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter)
if (tbfComponent3forOp is TBF.BenchControl.Modbus.Meret.PressureMeter.PressureMeter)
{
operation31 = (tbfComponent3forOp as TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter).ReadPressureOp(ref floatBox);
operation31 = (tbfComponent3forOp as TBF.BenchControl.Modbus.Meret.PressureMeter.PressureMeter).ReadPressureOp(ref floatBox);
}
else if (tbfComponent3forOp is TBF.BenchControl.Network.Camera.CLP1611.Camera)
{

View File

@ -13,12 +13,12 @@ namespace TBF.BenchControl.Elde.TempMeter
public override string ToString() { return string.Format("ReadTempOp({0},.,{1})", tempMeter.Name, eventDone); }
/// Set by the constructor
TempMeter tempMeter;
Event eventDone;
DoubleBox temp;
readonly TempMeter tempMeter;
readonly DoubleBox temp; /// Box for the measured value
readonly Event eventDone;
/// <summary>
/// Events: TempInDone, TempOutDone, TempDivDone or Error
/// Events: TempDone or Error
/// </summary>
/// <param name="tempMeter">TempMeter reference</param>
/// <param name="temp">Reference to the variable, value is in degree Celsius</param>
@ -29,6 +29,7 @@ namespace TBF.BenchControl.Elde.TempMeter
this.tempMeter = tempMeter;
this.temp = temp;
this.eventDone = eventDone;
log.Debug(this.ToString());
}
@ -40,7 +41,7 @@ namespace TBF.BenchControl.Elde.TempMeter
/// <summary>Start this operation</summary>
public void Start()
{
temp.Val = tempMeter.ReadTemperature();
if (temp != null) temp.Val = tempMeter.ReadTemperature();
}
/// <summary>Run this operation</summary>
@ -49,7 +50,7 @@ namespace TBF.BenchControl.Elde.TempMeter
/// </returns>
public Event Run()
{
temp.Val = tempMeter.ReadTemperature();
if (temp != null) temp.Val = tempMeter.ReadTemperature();
return eventDone;
}

View File

@ -1,5 +1,5 @@
///
/// Copyright (c) 2019 Sensus Slovensko a.s.
/// Copyright (c) 2019-2020 Sensus Slovensko a.s.
///
using System;
using TBF.BenchControl.Generic;
@ -8,7 +8,7 @@ namespace TBF.BenchControl.GenericDevices
{
public interface IParallelOutput : IComponent
{
IOperation SetOutputsOp(ushort outValue);
IOperation SetOutputsOp(UInt32 outValue);
IOperation ShowBenchWaitingOp();
IOperation ShowBenchErrorOp();
}

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using Config.Entities;
@ -23,6 +24,8 @@ namespace TBF.BenchControl.Modbus.Common
private static readonly ILog log = LogManager.GetLogger(typeof(Modbus));
public override string ToString() { return string.Format("Modbus({0})", Cfg.ToString(1)); }
const int MinTelegramLen = 4;
private readonly ModbusCfg modbusCommonCfg;
/// Private fields
@ -158,32 +161,43 @@ namespace TBF.BenchControl.Modbus.Common
/// <summary>Run this device</summary>
public void RunDeviceBefore()
{
if (serialPort == null) return;
/// Create 'dataToProcess' buffer with all received bytes
int nrBytes;
if (serialPort == null || (nrBytes = serialPort.BytesToRead) < MinTelegramLen) return;
byte[] dataToProcess = new byte[nrBytes];
serialPort.Read(dataToProcess, 0, nrBytes);
int nrBytes = serialPort.BytesToRead;
if (nrBytes > 0)
{
byte[] buffer = new byte[nrBytes];
serialPort.Read(buffer, 0, nrBytes);
int deviceAddress = (nrBytes >= 1) ? buffer[0] : 0;
int function = (nrBytes >= 2) ? buffer[1] : 0;
if ((nrBytes >= 4) && Telegram.VerifyTelegramCRC(buffer))
{
receivedTelegrams[deviceAddress].Enqueue(buffer);
string s = string.Format("{0} - {1} address={2} count={3}", Name, Telegram.LogTelegram("Telegram received: ", buffer), deviceAddress, receivedTelegrams[deviceAddress].Count);
Debug.WriteLine(s);
log.Debug(s);
}
else
while (dataToProcess.Length >= MinTelegramLen)
{
for (int candidateLen = MinTelegramLen; candidateLen <= dataToProcess.Length; candidateLen++)
{
string s = Telegram.LogTelegram(string.Format("{0} - Invalid data received ", Name), buffer);
Debug.WriteLine(s);
log.Debug(s);
if (Telegram.VerifyTelegramCRC(dataToProcess, candidateLen))
{
/// A valid telegram found in dataToProcess buffer
/// Split data in dataToProcess buffer into the verified telegram and newly created dataToProcess
byte[] receivedTelegram = dataToProcess.Take<byte>(candidateLen).ToArray<byte>();
dataToProcess = dataToProcess.Skip<byte>(candidateLen).ToArray<byte>();
/// Enqueue
int deviceAddress = receivedTelegram[0];
receivedTelegrams[deviceAddress].Enqueue(receivedTelegram);
string s = string.Format("{0} - {1} queue size={2}", Name, Telegram.LogTelegram("Received message ", receivedTelegram), receivedTelegrams[deviceAddress].Count);
Debug.WriteLine(s);
log.Debug(s);
break; /// Quit for loop
}
else if (candidateLen == dataToProcess.Length)
{
/// All bytes considered but no valid telegram found
string s = Telegram.LogTelegram(string.Format("{0} - Invalid data received ", Name), dataToProcess);
Debug.WriteLine(s);
log.Debug(s);
return;
}
}
}
}
}
/// <summary>Run this device</summary>

View File

@ -0,0 +1,26 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.Danfoss.VLT
{
public class Factory : IComponentFactory
{
public string ClassName { get { return this.GetType().Namespace.Substring(17); } }
public void ResetStaticProperties() { Pump.ResetStaticProperties(); }
public IComponent DummyComponent() { return new Pump(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Pump(cfg, components); }
public IComponentCfg DefaultConfig() { return new PumpCfg(this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(PumpCfg.Serializer, component, this);
}
}
}

View File

@ -0,0 +1,289 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using log4net;
using Config.Entities;
using Dirichlet.Numerics;
using TBF.BenchControl.ControlBoard;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.Danfoss.VLT
{
/// <summary>
/// See page 20 of MG10S202 Operational Instructions Modbus RTU
/// </summary>
public enum CW : ushort
{
PresetRefLsb = (1 << 0),
PresetRefMsb = (1 << 1),
Not_DcBraking = (1 << 2),
Not_CoastingStop = (1 << 3),
Not_QuickStop = (1 << 4),
Not_FreezeFreq = (1 << 5),
Start_NotRampStop = (1 << 6),
Reset = (1 << 7),
Jog = (1 << 8),
Ramp2_NotRamp1 = (1 << 9),
DataValid = (1 << 10),
Relay01Activ = (1 << 11),
DOut46Activ = (1 << 12),
SelectSetupLsb = (1 << 13),
SelectSetupMsb = (1 << 14),
Reversing = (1 << 15),
}
/// <summary>
/// See page 22 of MG10S202 Operational Instructions Modbus RTU
/// </summary>
public enum SW : ushort
{
ControlReady = (1 << 0),
DriveReady = (1 << 1),
CoastingStop = (1 << 2),
Trip = (1 << 3),
TripLock = (1 << 6),
Warning = (1 << 7),
SpeedEqRef = (1 << 8),
RemoteCtrl = (1 << 9),
FreqLimitOK = (1 << 10),
MotorRunning = (1 << 11),
VoltageWarn = (1 << 13),
CurrentLimit = (1 << 14),
ThermalWarn = (1 << 15),
}
public enum Function : byte
{
ReadCoilStatus = 0x01,
ForceSingleCoil = 0x05,
ForceMultipleCoils = 0x0F,
ReadHoldingRegisters = 0x03,
PresetSingleRegister = 0x06,
PresetMultipleRegisters = 0x10,
}
public class Pump : ComponentBase, IDevice, IOperation, GenericDevices.IPumpFM, GenericDevices.IValve
{
private static readonly ILog log = LogManager.GetLogger(typeof(Pump));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(1)); }
private readonly PumpCfg pumpCfg;
public int Delay { get { return pumpCfg.Delay; } }
public ValveCategory Category { get { return ValveCategory.Feeding; } } /// Pump category is Feeding
public GenericDevices.IValve CoupledTo { get { return null; } }
public bool InvertCouple { get { return false; } }
public int LagOpening { get { return 0; } }
public int LagClosing { get { return 0; } }
/// <summary>
/// Pump power in [%] in range 0 .. 100.0f
/// </summary>
float power;
public float Power { get { return power; } }
readonly GenericDevices.IModbus modbus;
readonly IControlBoard controlBoard;
readonly int bitPosition; /// 0 .. 63
public readonly UInt128 Mask; /// derived from bitPosition in the constructor
public bool State
{
get { return (controlBoard.Route & Mask) != 0; }
}
public Pump() { }
/// <summary>
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
/// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware.
/// </summary>
public Pump(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
pumpCfg = cfg as PumpCfg;
modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components);
if (modbus == null) throw new Exception("Cannot find " + Name + " parent");
controlBoard = TbfComponents.FindComponent("CB", components) as IControlBoard; /// TODO: replace "CB"
if (controlBoard == null) throw new Exception("Cannot find a control board");
bitPosition = pumpCfg.BitPosition;
Mask = (((UInt128)1) << bitPosition);
log.Debug(this.ToString());
}
///
/// IDevice interface
///
public void Initialize() { }
public void RunDeviceBefore()
{
if (pumpCfg.DebugLevel == Config.Entities.DebugMode.Normal ||
pumpCfg.DebugLevel == Config.Entities.DebugMode.DetectedOn)
{
if (modbus.ReceivedTelegrams[pumpCfg.ModbusAddress].Count > 0)
{
byte[] telegram = modbus.ReceivedTelegrams[pumpCfg.ModbusAddress].Dequeue();
string s = Telegram.LogTelegram(string.Format("Telegram received from {0}: ", Name), telegram);
log.Warn(s);
}
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
/// <summary>
/// Turn the pmp on using Modbus commad, use the variable frequency
/// </summary>
/// <param name="powerArg">Frequency in percent (-200.0 .. 200.0)</param>
public void TurnOn(float powerArg)
{
log.DebugFormat("{0}.TurnOn({1})", Name, powerArg);
UInt16 controlWord = (UInt16)(CW.Not_DcBraking |
CW.Not_CoastingStop |
CW.Not_QuickStop |
CW.Not_FreezeFreq |
CW.Start_NotRampStop |
CW.DataValid);
this.power = powerArg;
UInt16 reference = (UInt16)(Int16)((float)0x4000 * powerArg / 100.0f + 0.5f);
if (pumpCfg.DebugLevel == Config.Entities.DebugMode.Normal ||
pumpCfg.DebugLevel == Config.Entities.DebugMode.DetectedOn)
{
byte[] msg = new byte[13];
msg[0] = (byte)pumpCfg.ModbusAddress;
msg[1] = (byte)Function.ForceMultipleCoils;
msg[2] = 0; /// Data Hi
msg[3] = 0; /// Data Lo
msg[4] = 0; /// Nr. of coils Hi
msg[5] = 0x20; /// Nr. of coils Lo
msg[6] = 4; /// Byte count
msg[7] = (byte)(controlWord & 0xFF); /// Control Word Lo
msg[8] = (byte)(controlWord >> 8); /// Control Word Hi
msg[9] = (byte)(reference & 0xFF); /// Serial Com Reference Lo
msg[10] = (byte)(reference >> 8); /// Serial Com Reference Hi
///
modbus.SendMessage(msg);
}
}
/// <summary>
/// Turn the pmp off using Modbus command
/// </summary>
public void TurnOff()
{
log.DebugFormat("{0}.TurnOff()", Name);
UInt16 controlWord = (UInt16)(CW.Not_DcBraking |
CW.Not_CoastingStop |
CW.Not_QuickStop |
CW.Not_FreezeFreq |
//CW.Start_NotRampStop |
CW.DataValid);
this.power = 0;
UInt16 reference = 0;
if (pumpCfg.DebugLevel == Config.Entities.DebugMode.Normal ||
pumpCfg.DebugLevel == Config.Entities.DebugMode.DetectedOn)
{
byte[] msg = new byte[13];
msg[0] = (byte)pumpCfg.ModbusAddress;
msg[1] = (byte)Function.ForceMultipleCoils;
msg[2] = 0; /// Data Hi
msg[3] = 0; /// Data Lo
msg[4] = 0; /// Nr. of coils Hi
msg[5] = 0x20; /// Nr. of coils Lo
msg[6] = 4; /// Byte count
msg[7] = (byte)(controlWord & 0xFF); /// Control Word Lo
msg[8] = (byte)(controlWord >> 8); /// Control Word Hi
msg[9] = (byte)(reference & 0xFF); /// Serial Com Reference Lo
msg[10] = (byte)(reference >> 8); /// Serial Com Reference Hi
Telegram.UpdateTelegramCRC(msg);
modbus.SendMessage(msg);
}
}
/// <summary>
/// The currently running operation.
/// </summary>
public enum CurrentOp
{
None,
TurnOn,
TurnOff,
}
///
CurrentOp currentOp;
float powerForOp;
/// <summary>
/// Turn the pump frequency inverter on.
/// </summary>
public IOperation TurnOnOp(float powerArg)
{
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.TurnOn;
powerForOp = powerArg;
return this;
}
/// <summary>
/// Turn the pump frequency inverter on.
/// </summary>
public IOperation TurnOffOp()
{
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.TurnOff;
return this;
}
/// <summary>Start the operation</summary>
public void Start()
{
switch (currentOp)
{
case CurrentOp.TurnOn:
TurnOn(powerForOp);
return;
case CurrentOp.TurnOff:
default:
TurnOff();
return;
}
}
/// <summary>Run the operation</summary>
public Event Run()
{
return Event.TurnPumpOnOffDone;
}
/// <summary>Stop the operation</summary>
public void Stop()
{
currentOp = CurrentOp.None;
}
}
}

View File

@ -0,0 +1,50 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.Danfoss.VLT
{
public class PumpCfg : ComponentCfgBase, Generic.IChildComponentCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(PumpCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl() { return new PumpCfgCtrl(); }
///
/// Serialized parameters
///
public int BitPosition;
public int Delay; // Delay of the pump function in [s] (affects the duration of transition sequence steps)
public byte ModbusAddress; /// 1..254
/// Private parameterless constructor invoked by all other (public) constructors
PumpCfg()
{
Name = "P";
ParentName = "Modbus";
BitPosition = 0;
Delay = 1;
ModbusAddress = 49;
}
public PumpCfg(IComponentFactory factory)
: this()
{
this.Factory = factory;
}
public string ToString(int i)
{
return string.Format("name={0} bit={1} delay={2} addr={3} parent={4}",
Name,
BitPosition,
Delay,
ModbusAddress,
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName));
}
}
}

View File

@ -0,0 +1,123 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System;
using System.Windows.Forms;
using Config.Entities;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.Danfoss.VLT
{
public partial class PumpCfgCtrl : UserControl, IComponentCfgCtrl
{
ComponentParametersDlg parent;
public bool ShowMore { get { return false; } }
PumpCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as PumpCfg;
Redraw();
}
}
public PumpCfgCtrl()
{
InitializeComponent();
}
private void PressureMeterCfgCtrl_Load(object sender, EventArgs e)
{
parent = ParentForm as ComponentParametersDlg;
if (parent == null) return;
if (parent.TbfComponents != null)
{
foreach (var cmpnt in parent.TbfComponents)
{
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Modbus.Common.Factory)
{
parentNameComboBox.Items.Add(cmpnt.Name);
}
}
}
Redraw();
}
public void Closing()
{
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
componentNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
bitPositionTextBox.Text = config.BitPosition.ToString();
delayTextBox.Text = config.Delay.ToString();
modbusAddressTextBox.Text = config.ModbusAddress.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
parentNameComboBox.Enabled = true;
bitPositionTextBox.Enabled = true;
delayTextBox.Enabled = true;
modbusAddressTextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
int dummy;
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Parent Name'";
}
if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 128)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Bit Position' should be between 0 and 127";
}
if (!int.TryParse(delayTextBox.Text, out dummy) || dummy < 0 || dummy > 300)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Delay' is not valid";
}
if (!int.TryParse(modbusAddressTextBox.Text, out dummy) || dummy < 0 || dummy > 254)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Modbus Address' should be between 0 and 254";
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
config.Name = nameTextBox.Text;
config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
config.BitPosition = int.Parse(bitPositionTextBox.Text);
config.Delay = int.Parse(delayTextBox.Text);
config.ModbusAddress = (byte)int.Parse(modbusAddressTextBox.Text);
return flags;
}
}
}

View File

@ -0,0 +1,179 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
namespace TBF.BenchControl.Modbus.Danfoss.VLT
{
partial class PumpCfgCtrl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.parentNameLabel = new System.Windows.Forms.Label();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.componentNameLabel = new System.Windows.Forms.Label();
this.modbusAddressLabel = new System.Windows.Forms.Label();
this.modbusAddressTextBox = new System.Windows.Forms.TextBox();
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
this.bitPositionTextBox = new System.Windows.Forms.TextBox();
this.bitPositionLabel = new System.Windows.Forms.Label();
this.delayTextBox = new System.Windows.Forms.TextBox();
this.delayLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// parentNameLabel
//
this.parentNameLabel.AutoSize = true;
this.parentNameLabel.Location = new System.Drawing.Point(28, 81);
this.parentNameLabel.Name = "parentNameLabel";
this.parentNameLabel.Size = new System.Drawing.Size(69, 13);
this.parentNameLabel.TabIndex = 3;
this.parentNameLabel.Text = "Parent Name";
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(138, 52);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(28, 55);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 1;
this.nameLabel.Text = "Name";
//
// componentNameLabel
//
this.componentNameLabel.AutoSize = true;
this.componentNameLabel.Location = new System.Drawing.Point(135, 28);
this.componentNameLabel.Name = "componentNameLabel";
this.componentNameLabel.Size = new System.Drawing.Size(83, 13);
this.componentNameLabel.TabIndex = 0;
this.componentNameLabel.Text = "ComonentName";
//
// modbusAddressLabel
//
this.modbusAddressLabel.AutoSize = true;
this.modbusAddressLabel.Location = new System.Drawing.Point(28, 157);
this.modbusAddressLabel.Name = "modbusAddressLabel";
this.modbusAddressLabel.Size = new System.Drawing.Size(86, 13);
this.modbusAddressLabel.TabIndex = 7;
this.modbusAddressLabel.Text = "Modbus Address";
//
// modbusAddressTextBox
//
this.modbusAddressTextBox.Enabled = false;
this.modbusAddressTextBox.Location = new System.Drawing.Point(138, 154);
this.modbusAddressTextBox.Name = "modbusAddressTextBox";
this.modbusAddressTextBox.Size = new System.Drawing.Size(46, 20);
this.modbusAddressTextBox.TabIndex = 8;
//
// parentNameComboBox
//
this.parentNameComboBox.Enabled = false;
this.parentNameComboBox.FormattingEnabled = true;
this.parentNameComboBox.Location = new System.Drawing.Point(138, 78);
this.parentNameComboBox.Name = "parentNameComboBox";
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
this.parentNameComboBox.TabIndex = 4;
//
// bitPositionTextBox
//
this.bitPositionTextBox.Enabled = false;
this.bitPositionTextBox.Location = new System.Drawing.Point(138, 104);
this.bitPositionTextBox.Name = "bitPositionTextBox";
this.bitPositionTextBox.Size = new System.Drawing.Size(46, 20);
this.bitPositionTextBox.TabIndex = 22;
//
// bitPositionLabel
//
this.bitPositionLabel.AutoSize = true;
this.bitPositionLabel.Location = new System.Drawing.Point(28, 107);
this.bitPositionLabel.Name = "bitPositionLabel";
this.bitPositionLabel.Size = new System.Drawing.Size(89, 13);
this.bitPositionLabel.TabIndex = 21;
this.bitPositionLabel.Text = "Valve Bit Position";
//
// delayTextBox
//
this.delayTextBox.Enabled = false;
this.delayTextBox.Location = new System.Drawing.Point(138, 129);
this.delayTextBox.Name = "delayTextBox";
this.delayTextBox.Size = new System.Drawing.Size(46, 20);
this.delayTextBox.TabIndex = 24;
//
// delayLabel
//
this.delayLabel.AutoSize = true;
this.delayLabel.Location = new System.Drawing.Point(27, 131);
this.delayLabel.Name = "delayLabel";
this.delayLabel.Size = new System.Drawing.Size(45, 13);
this.delayLabel.TabIndex = 23;
this.delayLabel.Text = "Delay[s]";
//
// PumpCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.delayTextBox);
this.Controls.Add(this.delayLabel);
this.Controls.Add(this.bitPositionTextBox);
this.Controls.Add(this.bitPositionLabel);
this.Controls.Add(this.parentNameComboBox);
this.Controls.Add(this.modbusAddressTextBox);
this.Controls.Add(this.modbusAddressLabel);
this.Controls.Add(this.parentNameLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.componentNameLabel);
this.Name = "PumpCfgCtrl";
this.Size = new System.Drawing.Size(300, 200);
this.Load += new System.EventHandler(this.PressureMeterCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label parentNameLabel;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label componentNameLabel;
private System.Windows.Forms.Label modbusAddressLabel;
private System.Windows.Forms.TextBox modbusAddressTextBox;
private System.Windows.Forms.ComboBox parentNameComboBox;
private System.Windows.Forms.TextBox bitPositionTextBox;
private System.Windows.Forms.Label bitPositionLabel;
private System.Windows.Forms.TextBox delayTextBox;
private System.Windows.Forms.Label delayLabel;
}
}

View File

@ -17,4 +17,9 @@ namespace TBF.BenchControl.Modbus
PresetMultipleRegisters = 0x10,
Identification = 0x11,
}
public static class Constants
{
public const int ModbusPollPeriod = 4;
}
}

View File

@ -1,10 +1,10 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
/// Copyright (c) 2016-2020 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.PressureMeter.Meret
namespace TBF.BenchControl.Modbus.Meret.PressureMeter
{
public class Factory : IComponentFactory
{

View File

@ -0,0 +1,123 @@
///
/// Copyright (c) 2016-2020 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.Generic;
using TBF.Boxes;
namespace TBF.BenchControl.Modbus.Meret.PressureMeter
{
public class PressureMeter : ComponentBase, GenericDevices.IPressureMeter, IDevice
{
private static readonly ILog log = LogManager.GetLogger(typeof(PressureMeter));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(1)); }
readonly PressureMeterCfg pressureMtrCfg;
readonly GenericDevices.IModbus modbus;
double receivedPressure;
public PressureMeter()
{
}
public PressureMeter(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
pressureMtrCfg = cfg as PressureMeterCfg;
modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components);
if (modbus == null) throw new Exception("Cannot find " + Name + " parent");
log.Debug(this.ToString());
}
///
/// IDevice interface
///
public void Initialize() { }
public void RunDeviceBefore()
{
if (pressureMtrCfg.DebugLevel == Config.Entities.DebugMode.Simulate ||
pressureMtrCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation)
{
return;
}
if (modbus.ReceivedTelegrams[pressureMtrCfg.ModbusAddress].Count > 0)
{
byte[] telegram = modbus.ReceivedTelegrams[pressureMtrCfg.ModbusAddress].Dequeue();
if (telegram.Length == 9 && telegram[1] == 4 && telegram[2] == 4)
{
/// Swap byte order
byte t1 = telegram[3];
byte t2 = telegram[4];
byte t3 = telegram[5];
byte t4 = telegram[6];
telegram[3] = t4;
telegram[4] = t3;
telegram[5] = t2;
telegram[6] = t1;
receivedPressure = Config.Units.ConvertFrom(Config.Unit.kPa, System.BitConverter.ToSingle(telegram, 3));
log.WarnFormat("Pressure: {0}={1}bar", Name, receivedPressure.ToString("F3"));
}
}
if ((StateMachine.Time % Constants.ModbusPollPeriod) == (pressureMtrCfg.ModbusAddress % Constants.ModbusPollPeriod)) /// Each 'ModbusDevices' seconds
{
const byte Function = 4; /// Read input registers
const ushort Address = 0; /// Pressure
modbus.SendMessage(pressureMtrCfg.ModbusAddress, Function, Address, 2);
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
/// <summary>
/// Returns the water pressure
/// </summary>
/// <returns>Pressure in mBar</returns>
public float ReadPressure()
{
if (Cfg.DebugLevel == Config.Entities.DebugMode.Normal)
{
return Convert.ToSingle(Config.Formulas.CorrectedValue(receivedPressure, Corrections));
}
else if (Cfg.DebugLevel == Config.Entities.DebugMode.Simulate)
{
return 1.0F;
}
else
{
return 0;
}
}
/// <summary>
/// Events: PressureDone, Error
/// </summary>
/// <param name="pressureBox">Reference to a variable for the pressure in Bar</param>
/// <returns>ReadPressureOp instance reference casted to IOperaton</returns>
public IOperation ReadPressureOp(ref FloatBox pressureBox)
{
return new ReadPressureOp(this, ref pressureBox);
}
/// <summary>
/// Events: pressureDone, Error
/// </summary>
/// <param name="pressureBox">Reference to a variable for the pressure in Bar</param>
/// <param name="pressureDone">Event returned when measurement done</param>
/// <returns>ReadPressureOp instance reference casted to IOperaton</returns>
public IOperation ReadPressureOp(ref FloatBox pressureBox, Event pressureDone)
{
return new ReadPressureOp(this, ref pressureBox, pressureDone);
}
}
}

View File

@ -1,13 +1,11 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
/// Copyright (c) 2016-2020 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.PressureMeter.Meret
namespace TBF.BenchControl.Modbus.Meret.PressureMeter
{
public class PressureMeterCfg : ComponentCfgBase, Generic.IChildComponentCfg
{
@ -37,7 +35,7 @@ namespace TBF.BenchControl.Modbus.PressureMeter.Meret
public string ToString(int i)
{
return string.Format("Name={0}, ModbusAddr={1}, Parent={2}",
return string.Format("name={0} addr={1} parent={2}",
Name,
ModbusAddress,
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName));

View File

@ -1,12 +1,12 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
/// Copyright (c) 2016-2020 Sensus Slovensko a.s.
///
using System;
using System.Windows.Forms;
using Config.Entities;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.PressureMeter.Meret
namespace TBF.BenchControl.Modbus.Meret.PressureMeter
{
public partial class PressureMeterCfgCtrl : UserControl, IComponentCfgCtrl
{

View File

@ -1,7 +1,7 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
/// Copyright (c) 2016-2020 Sensus Slovensko a.s.
///
namespace TBF.BenchControl.Modbus.PressureMeter.Meret
namespace TBF.BenchControl.Modbus.Meret.PressureMeter
{
partial class PressureMeterCfgCtrl
{

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,11 +1,11 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
/// Copyright (c) 2016-2020 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.Modbus.PressureMeter.Meret
namespace TBF.BenchControl.Modbus.Meret.PressureMeter
{
public class ReadPressureOp : IOperation
{
@ -14,13 +14,11 @@ namespace TBF.BenchControl.Modbus.PressureMeter.Meret
/// Set by the constructor
readonly PressureMeter pressureMeter;
readonly Event eventDone;
/// Measured value
FloatBox pressure;
readonly FloatBox pressure; /// Box for the measured value
readonly Event eventDone;
/// <summary>
/// Events: PressureInDone, PressureOutDone or Error
/// Events: PressureDone or Error
/// </summary>
/// <param name="pressureMeter">Pressure meter reference</param>
/// <param name="pressure">Reference to the measured pressure variable, value is in bar</param>
@ -43,7 +41,7 @@ namespace TBF.BenchControl.Modbus.PressureMeter.Meret
/// <summary>Start this operation</summary>
public void Start()
{
pressure.Val = pressureMeter.ReadPressure();
if (pressure != null) pressure.Val = pressureMeter.ReadPressure();
}
/// <summary>Run this operation</summary>
@ -52,7 +50,7 @@ namespace TBF.BenchControl.Modbus.PressureMeter.Meret
/// </returns>
public Event Run()
{
pressure.Val = pressureMeter.ReadPressure();
if (pressure != null) pressure.Val = pressureMeter.ReadPressure();
return eventDone;
}

View File

@ -0,0 +1,26 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.Meret.TempMeter
{
public class Factory : IComponentFactory
{
public string ClassName { get { return this.GetType().Namespace.Substring(17); } }
public void ResetStaticProperties() { TempMeter.ResetStaticProperties(); }
public IComponent DummyComponent() { return new TempMeter(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new TempMeter(cfg, components); }
public IComponentCfg DefaultConfig() { return new TempMeterCfg(this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(TempMeterCfg.Serializer, component, this);
}
}
}

View File

@ -0,0 +1,62 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.Modbus.Meret.TempMeter
{
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 TempMeter tempMeter;
readonly Event eventDone;
readonly DoubleBox temp; /// Box for the measured value
/// <summary>
/// Events: TempDone or Error
/// </summary>
/// <param name="tempMeter">Pressure meter reference</param>
/// <param name="temp">Reference to the measured pressure variable, value is in bar</param>
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
public ReadTempOp(TempMeter tempMeter, ref DoubleBox temp, Event eventDone)
{
if (tempMeter == null) throw new ArgumentNullException("tempMeter");
this.tempMeter = tempMeter;
this.temp = temp;
this.eventDone = eventDone;
log.Debug(this.ToString());
}
public ReadTempOp(TempMeter pressureMeter, ref DoubleBox temp)
: this(pressureMeter, ref temp, Event.TempDone)
{
}
/// <summary>Start this operation</summary>
public void Start()
{
if (temp != null) temp.Val = tempMeter.ReadTemperature();
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.PressureInDone or Event.PressureOutDone
/// </returns>
public Event Run()
{
if (temp != null) temp.Val = tempMeter.ReadTemperature();
return eventDone;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}

View File

@ -0,0 +1,124 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.Generic;
using TBF.Boxes;
namespace TBF.BenchControl.Modbus.Meret.TempMeter
{
public class TempMeter : ComponentBase, GenericDevices.ITempMeter, IDevice
{
private static readonly ILog log = LogManager.GetLogger(typeof(TempMeter));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(1)); }
readonly TempMeterCfg tempMtrCfg;
readonly GenericDevices.IModbus modbus;
double receivedTemp;
public TempMeter()
{
}
public TempMeter(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
tempMtrCfg = cfg as TempMeterCfg;
modbus = TbfComponents.FindComponent(cfg.ParentName, components) as GenericDevices.IModbus;
if (modbus == null) throw new Exception("Cannot find " + Name + " parent");
log.Debug(this.ToString());
}
///
/// IDevice interface
///
public void Initialize() { }
/// <summary>Run this device</summary>
public void RunDeviceBefore()
{
if (tempMtrCfg.DebugLevel == Config.Entities.DebugMode.Simulate ||
tempMtrCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation)
{
return;
}
if (modbus.ReceivedTelegrams[tempMtrCfg.ModbusAddress].Count > 0)
{
byte[] telegram = modbus.ReceivedTelegrams[tempMtrCfg.ModbusAddress].Dequeue();
if (telegram.Length == 9 && telegram[1] == 4 && telegram[2] == 4)
{
/// Swap byte order
byte t1 = telegram[3];
byte t2 = telegram[4];
byte t3 = telegram[5];
byte t4 = telegram[6];
telegram[3] = t4;
telegram[4] = t3;
telegram[5] = t2;
telegram[6] = t1;
receivedTemp = System.BitConverter.ToSingle(telegram, 3);
log.WarnFormat("Temperature: {0}={1}°C", Name, receivedTemp.ToString("F1"));
}
}
if ((StateMachine.Time % Constants.ModbusPollPeriod) == (tempMtrCfg.ModbusAddress % Constants.ModbusPollPeriod)) /// Each 'ModbusDevices' seconds
{
const byte Function = 4; /// Read input registers
const ushort Address = 0; /// Temperature
modbus.SendMessage(tempMtrCfg.ModbusAddress, Function, Address, 2);
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
/// <summary>
/// Returns the water pressure
/// </summary>
/// <returns>Temperature in °C</returns>
public double ReadTemperature()
{
if (Cfg.DebugLevel == Config.Entities.DebugMode.Normal)
{
return Config.Formulas.CorrectedValue(receivedTemp, Corrections);
}
else if (Cfg.DebugLevel == Config.Entities.DebugMode.Simulate)
{
return 20.0;
}
else
{
return 0;
}
}
/// <summary>
/// Events: PressureDone, Error
/// </summary>
/// <param name="tempBox">Reference to a variable for the pressure in Bar</param>
/// <returns>ReadPressureOp instance reference casted to IOperaton</returns>
public IOperation ReadTempOp(ref DoubleBox tempBox)
{
return new ReadTempOp(this, ref tempBox);
}
/// <summary>
/// Events: pressureDone, Error
/// </summary>
/// <param name="tempBox">Reference to a variable for the pressure in Bar</param>
/// <param name="tempDone">Event returned when measurement done</param>
/// <returns>ReadPressureOp instance reference casted to IOperaton</returns>
public IOperation ReadTempOp(ref DoubleBox tempBox, Event tempDone)
{
return new ReadTempOp(this, ref tempBox, tempDone);
}
}
}

View File

@ -0,0 +1,44 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.Meret.TempMeter
{
public class TempMeterCfg : ComponentCfgBase, Generic.IChildComponentCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TempMeterCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl() { return new TempMeterCfgCtrl(); }
///
/// Serialized parameters
///
public byte ModbusAddress; /// 1..254
/// Private parameterless constructor invoked by all other (public) constructors
TempMeterCfg()
{
Name = "T";
ParentName = "Modbus";
ModbusAddress = 49;
}
public TempMeterCfg(IComponentFactory factory)
: this()
{
this.Factory = factory;
}
public string ToString(int i)
{
return string.Format("name={0} addr={1} parent={2}",
Name,
ModbusAddress,
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName));
}
}
}

View File

@ -0,0 +1,104 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
using System;
using System.Windows.Forms;
using Config.Entities;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Modbus.Meret.TempMeter
{
public partial class TempMeterCfgCtrl : UserControl, IComponentCfgCtrl
{
ComponentParametersDlg parent;
public bool ShowMore { get { return false; } }
TempMeterCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as TempMeterCfg;
Redraw();
}
}
public TempMeterCfgCtrl()
{
InitializeComponent();
}
private void PressureMeterCfgCtrl_Load(object sender, EventArgs e)
{
parent = ParentForm as ComponentParametersDlg;
if (parent == null) return;
if (parent.TbfComponents != null)
{
foreach (var cmpnt in parent.TbfComponents)
{
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Modbus.Common.Factory)
{
parentNameComboBox.Items.Add(cmpnt.Name);
}
}
}
Redraw();
}
public void Closing()
{
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
componentNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
modbusAddressTextBox.Text = config.ModbusAddress.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
parentNameComboBox.Enabled = true;
modbusAddressTextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
int dummy;
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Parent Name'";
}
if (!int.TryParse(modbusAddressTextBox.Text, out dummy) || dummy < 0 || dummy > 255)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Modbus Address' should be between 0 and 255";
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
config.Name = nameTextBox.Text;
config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
config.ModbusAddress = (byte)int.Parse(modbusAddressTextBox.Text);
return flags;
}
}
}

View File

@ -0,0 +1,133 @@
///
/// Copyright (c) 2020 Sensus Slovensko a.s.
///
namespace TBF.BenchControl.Modbus.Meret.TempMeter
{
partial class TempMeterCfgCtrl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.parentNameLabel = new System.Windows.Forms.Label();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.componentNameLabel = new System.Windows.Forms.Label();
this.modbusAddressLabel = new System.Windows.Forms.Label();
this.modbusAddressTextBox = new System.Windows.Forms.TextBox();
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// parentNameLabel
//
this.parentNameLabel.AutoSize = true;
this.parentNameLabel.Location = new System.Drawing.Point(28, 81);
this.parentNameLabel.Name = "parentNameLabel";
this.parentNameLabel.Size = new System.Drawing.Size(69, 13);
this.parentNameLabel.TabIndex = 3;
this.parentNameLabel.Text = "Parent Name";
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(138, 52);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(28, 55);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 1;
this.nameLabel.Text = "Name";
//
// componentNameLabel
//
this.componentNameLabel.AutoSize = true;
this.componentNameLabel.Location = new System.Drawing.Point(135, 28);
this.componentNameLabel.Name = "componentNameLabel";
this.componentNameLabel.Size = new System.Drawing.Size(83, 13);
this.componentNameLabel.TabIndex = 0;
this.componentNameLabel.Text = "ComonentName";
//
// modbusAddressLabel
//
this.modbusAddressLabel.AutoSize = true;
this.modbusAddressLabel.Location = new System.Drawing.Point(28, 133);
this.modbusAddressLabel.Name = "modbusAddressLabel";
this.modbusAddressLabel.Size = new System.Drawing.Size(86, 13);
this.modbusAddressLabel.TabIndex = 7;
this.modbusAddressLabel.Text = "Modbus Address";
//
// modbusAddressTextBox
//
this.modbusAddressTextBox.Enabled = false;
this.modbusAddressTextBox.Location = new System.Drawing.Point(138, 130);
this.modbusAddressTextBox.Name = "modbusAddressTextBox";
this.modbusAddressTextBox.Size = new System.Drawing.Size(46, 20);
this.modbusAddressTextBox.TabIndex = 8;
//
// parentNameComboBox
//
this.parentNameComboBox.Enabled = false;
this.parentNameComboBox.FormattingEnabled = true;
this.parentNameComboBox.Location = new System.Drawing.Point(138, 78);
this.parentNameComboBox.Name = "parentNameComboBox";
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
this.parentNameComboBox.TabIndex = 4;
//
// ComponentCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.parentNameComboBox);
this.Controls.Add(this.modbusAddressTextBox);
this.Controls.Add(this.modbusAddressLabel);
this.Controls.Add(this.parentNameLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.componentNameLabel);
this.Name = "ComponentCfgCtrl";
this.Size = new System.Drawing.Size(300, 200);
this.Load += new System.EventHandler(this.PressureMeterCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label parentNameLabel;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label componentNameLabel;
private System.Windows.Forms.Label modbusAddressLabel;
private System.Windows.Forms.TextBox modbusAddressTextBox;
private System.Windows.Forms.ComboBox parentNameComboBox;
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,118 +0,0 @@
///
/// Copyright (c) 2016-2017 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.Generic;
using TBF.Boxes;
namespace TBF.BenchControl.Modbus.PressureMeter.Meret
{
public class PressureMeter : ComponentBase, GenericDevices.IPressureMeter, IDevice
{
private static readonly ILog log = LogManager.GetLogger(typeof(PressureMeter));
public override string ToString() { return string.Format("PressureMeter({0})", Cfg.ToString(1)); }
readonly PressureMeterCfg pressureMtrCfg;
readonly GenericDevices.IModbus modbus;
private float receivedPressure;
const ushort WatchdogBitMask = 0x0010;
public PressureMeter()
{
}
public PressureMeter(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
pressureMtrCfg = cfg as PressureMeterCfg;
modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components);
if (modbus == null) throw new Exception("Cannot find " + Name + " parent");
log.Debug(this.ToString());
}
/// <summary>Initialize this device</summary>
public void Initialize()
{
}
/// <summary>
/// Returns the water pressure
/// </summary>
/// <returns>Pressure in mBar</returns>
public float ReadPressure()
{
double rawPressure = Config.Units.ConvertFrom(Config.Unit.kPa, receivedPressure);
double correctedPressure = Config.Formulas.CorrectedValue(rawPressure, Corrections);
return (float)correctedPressure;
}
/// <summary>
/// Events: PressureDone, Error
/// </summary>
/// <param name="pressure">Reference to a variable for the pressure in Bar</param>
/// <returns>ReadPressureOp instance reference casted to IOperaton</returns>
public IOperation ReadPressureOp(ref FloatBox pressure)
{
return new ReadPressureOp(this, ref pressure);
}
/// <summary>
/// Events: pressureDone, Error
/// </summary>
/// <param name="pressure">Reference to a variable for the pressure in Bar</param>
/// <param name="pressureDone">Event returned when measurement done</param>
/// <returns>ReadPressureOp instance reference casted to IOperaton</returns>
public IOperation ReadPressureOp(ref FloatBox pressure, Event pressureDone)
{
return new ReadPressureOp(this, ref pressure, pressureDone);
}
/// <summary>Run this device</summary>
public void RunDeviceBefore()
{
if (pressureMtrCfg.DebugLevel == Config.Entities.DebugMode.Simulate ||
pressureMtrCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation)
{
return;
}
if (modbus.ReceivedTelegrams[pressureMtrCfg.ModbusAddress].Count > 0)
{
byte[] telegram = modbus.ReceivedTelegrams[pressureMtrCfg.ModbusAddress].Dequeue();
if (telegram.Length == 9 && telegram[1] == 4 && telegram[2] == 4)
{
/// Swap byte order
byte t1 = telegram[3];
byte t2 = telegram[4];
byte t3 = telegram[5];
byte t4 = telegram[6];
telegram[3] = t4;
telegram[4] = t3;
telegram[5] = t2;
telegram[6] = t1;
receivedPressure = System.BitConverter.ToSingle(telegram, 3);
}
}
if ((StateMachine.Time % 3) == (pressureMtrCfg.ModbusAddress % 3)) /// Each 3 seconds
{
const byte Function = 4; /// Read input registers
const ushort Address = 0; /// Pressure
modbus.SendMessage(pressureMtrCfg.ModbusAddress, Function, Address, 2);
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
}
}

View File

@ -21,10 +21,10 @@ namespace TBF.BenchControl.Modbus.QuidoRS
public QuidoVariant Variant { get { return quidoRSCfg.Variant; } }
private ushort currentOutputs;
private UInt32 currentOutputs;
private DateTime lastOutputsChange;
ushort watchdogBitMask;
UInt32 watchdogBitMask;
public QuidoRS()
{
@ -43,12 +43,13 @@ namespace TBF.BenchControl.Modbus.QuidoRS
log.Debug(this.ToString());
}
/// <summary>Initialize this device</summary>
public void Initialize()
{
}
/// <summary>Run this device</summary>
///
/// IDevice interface
///
public void Initialize() { }
/// <summary>
/// Run this device
/// </summary>
public void RunDeviceBefore()
{
if (quidoRSCfg.DebugLevel == Config.Entities.DebugMode.Simulate) return;
@ -77,7 +78,6 @@ namespace TBF.BenchControl.Modbus.QuidoRS
}
}
}
public void RunDeviceAfter() { }
public void StopDevice() { SendOutputs(0); }
public void StopDevice2() { }
@ -87,7 +87,7 @@ namespace TBF.BenchControl.Modbus.QuidoRS
/// Set outputs of QuidoRS board
/// </summary>
/// <param name="outputs">output value</param>
public void SetOutputs(ushort outputs)
public void SetOutputs(UInt32 outputs)
{
lock (this)
{
@ -105,7 +105,7 @@ namespace TBF.BenchControl.Modbus.QuidoRS
/// </summary>
/// <param name="bitMask">Specifies bit(s) to set</param>
/// <param name="outputs">output value</param>
public void SetBit(ushort bitMask)
public void SetBit(UInt32 bitMask)
{
lock (this)
{
@ -123,7 +123,7 @@ namespace TBF.BenchControl.Modbus.QuidoRS
/// </summary>
/// <param name="bitMask">Specifies bit(s) to reset</param>
/// <param name="outputs">output value</param>
public void ResetBit(ushort bitMask)
public void ResetBit(UInt32 bitMask)
{
lock (this)
{
@ -136,18 +136,16 @@ namespace TBF.BenchControl.Modbus.QuidoRS
}
}
private void SendOutputs(ushort outputs)
private void SendOutputs(UInt32 outputs)
{
byte addr = quidoRSCfg.ModbusAddress;
byte cmd = (byte)Function.ForceMultipleCoils;
byte dataLo = (byte)(outputs & 0xFF);
byte dataHi = (byte)(outputs >> 8);
byte data2 = (byte)(outputs >> 8);
byte data3 = (byte)(outputs >> 16);
byte dataHi = (byte)(outputs >> 24);
if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_2_16)
{
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 16, 2, dataLo, dataHi, 0, 0 });
}
else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_4_4)
if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_4_4)
{
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 4, 1, dataLo, 0, 0 });
}
@ -155,6 +153,14 @@ namespace TBF.BenchControl.Modbus.QuidoRS
{
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 8, 1, dataLo, 0, 0 });
}
else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_2_16)
{
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 16, 2, dataLo, data2, 0, 0 });
}
else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_2_32)
{
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 32, 4, dataLo, data2, data3, dataHi, 0, 0 });
}
lastOutputsChange = DateTime.Now;
}
@ -165,7 +171,7 @@ namespace TBF.BenchControl.Modbus.QuidoRS
/// </summary>
/// <param name="outValue">Parallel output data</param>
/// <returns>SetOutputsOp operation casted to IOperaton</returns>
public IOperation SetOutputsOp(ushort outValue)
public IOperation SetOutputsOp(UInt32 outValue)
{
return new SetOutputsOp(this, outValue);
}

View File

@ -1,5 +1,5 @@
///
/// Copyright (c) 2015-2019 Sensus Slovensko a.s.
/// Copyright (c) 2015-2020 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
@ -11,9 +11,10 @@ namespace TBF.BenchControl.Modbus.QuidoRS
{
public enum QuidoVariant
{
QuidoRS_2_16,
QuidoRS_4_4,
QuidoRS_8_8,
QuidoRS_2_16,
QuidoRS_2_32,
Count
}

View File

@ -1,5 +1,5 @@
///
/// Copyright (c) 2015 Sensus Slovensko a.s.
/// Copyright (c) 2015-2020 Sensus Slovensko a.s.
///
using System;
using log4net;
@ -15,7 +15,7 @@ namespace TBF.BenchControl.Modbus.QuidoRS
/// Set by the constructor
readonly QuidoRS quidoRS;
readonly Event eventDone;
ushort outValue;
UInt32 outValue;
/// <summary>
/// Events: PressureInDone, PressureOutDone or Error
@ -23,7 +23,7 @@ namespace TBF.BenchControl.Modbus.QuidoRS
/// <param name="quidoRS">Pressure meter reference</param>
/// <param name="pressure">Reference to the measured pressure variable, value is in bar</param>
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
public SetOutputsOp(QuidoRS quidoRS, ushort outValue, Event eventDone)
public SetOutputsOp(QuidoRS quidoRS, UInt32 outValue, Event eventDone)
{
if (quidoRS == null) throw new ArgumentNullException("quidoRS");
this.quidoRS = quidoRS;
@ -32,7 +32,7 @@ namespace TBF.BenchControl.Modbus.QuidoRS
log.Debug(this.ToString());
}
public SetOutputsOp(QuidoRS quidoRS, ushort outValue)
public SetOutputsOp(QuidoRS quidoRS, UInt32 outValue)
: this(quidoRS, outValue, Event.SetOutputsDone)
{
}

View File

@ -65,7 +65,8 @@ namespace TBF.BenchControl
Factories.Add(new TestMethods.FixedStart.Single.Factory());
Factories.Add(new TestMethods.FixedStart.Compound.Factory());
Factories.Add(new TestMethods.FixedStart.HeatMeters.Factory());
Factories.Add(new TestMethods.FixedStartDeferredEval.Single.Factory());
Factories.Add(new TestMethods.FixedStartAdvanced.Single.Factory());
Factories.Add(new TestMethods.FixedStartDeferredEval.Single.Factory());
Factories.Add(new TestMethods.FixedStartDeferredEval.Compound.Factory());
Factories.Add(new TestMethods.FixedStartDeferredEval.HeatMeters.Factory());
Factories.Add(new TestMethods.FixedStartMassCollection.Single.Factory());
@ -116,11 +117,13 @@ namespace TBF.BenchControl
Factories.Add(new MettlerToledo.Standard.BalanceOldFactory()); /// MettlerToledoBalanceOld
Factories.Add(new MettlerToledo.Standard.BalanceNewFactory()); /// MettlerToledoBalanceSN
Factories.Add(new MettlerToledo.Multi.BalanceFactory()); /// MettlerToledo-Multi
Factories.Add(new Modbus.CometAmbient.Factory()); /// Modbus.CometAmbient.Ambient
Factories.Add(new Modbus.Common.Factory()); /// Modbus
Factories.Add(new Modbus.Easytherm.Factory()); /// Modbus.Easytherm
Factories.Add(new Modbus.PressureMeter.Meret.Factory()); /// Modbus.PressureMeter.Meret - Meret pressure meter connected via modbus
Factories.Add(new Modbus.QuidoRS.Factory()); /// Modbus.QuidoRS
Factories.Add(new Modbus.CometAmbient.Factory()); /// Modbus.CometAmbient.Ambient
Factories.Add(new Modbus.Danfoss.VLT.Factory()); /// Modbus.Danfoss.VLT FM pump control
Factories.Add(new Modbus.Easytherm.Factory()); /// Modbus.Easytherm
Factories.Add(new Modbus.Meret.PressureMeter.Factory()); /// Meret pressure meter connected via modbus on a PC
Factories.Add(new Modbus.Meret.TempMeter.Factory()); /// Meret temperature meter connected via modbus on a PC
Factories.Add(new Modbus.QuidoRS.Factory()); /// Modbus.QuidoRS
Factories.Add(new Modbus.TankSelector.Factory()); /// Modbus.TankSelector
Factories.Add(new Modbus.UltrasoundLevelMeter.Factory());
Factories.Add(new Modbus.WaterAnalyzer.Factory());

View File

@ -39,10 +39,11 @@ namespace TBF.BenchControl
/// </summary>
/// <param name="data">Data telegram</param>
/// <returns>Calculated CRC</returns>
public static UInt16 ClaculateTelegramCRC(byte[] data)
public static UInt16 CalculateTelegramCRC(byte[] data, int enforcedLen = 0)
{
int len = (enforcedLen != 0) ? Math.Min(enforcedLen, data.Length) : data.Length;
UInt16 crc = crcSeed;
for (int i = 0; i < data.Length - 2; i++) UpdateCRC(data[i], ref crc);
for (int i = 0; i < len - 2; i++) UpdateCRC(data[i], ref crc);
return crc;
}
@ -58,7 +59,7 @@ namespace TBF.BenchControl
int len = data.Length;
if (len < 2) return;
UInt16 crc = ClaculateTelegramCRC(data);
UInt16 crc = CalculateTelegramCRC(data);
data[len - 2] = (byte)(crc & 0xFF);
data[len - 1] = (byte)(crc >> 8);
@ -72,12 +73,14 @@ namespace TBF.BenchControl
/// </summary>
/// <param name="data">Data telegram</param>
/// <returns>true if the CRC in the telegram is correct</returns>
public static bool VerifyTelegramCRC(byte[] data)
public static bool VerifyTelegramCRC(byte[] data, int enforcedLen = 0)
{
int len = data.Length;
if (data == null || data.Length == 0 || enforcedLen > data.Length) return false;
int len = (enforcedLen != 0) ? enforcedLen : data.Length;
if (len < 2) return false;
UInt16 crc = ClaculateTelegramCRC(data);
UInt16 crc = CalculateTelegramCRC(data, len);
return (data[len - 2] == (byte)(crc & 0xFF)) && (data[len - 1] == (byte)(crc >> 8));
}

View File

@ -775,6 +775,15 @@
<DependentUpon>AmbientCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\Modbus\CometAmbient\Factory.cs" />
<Compile Include="BenchControl\Modbus\Danfoss\VLT\Pump.cs" />
<Compile Include="BenchControl\Modbus\Danfoss\VLT\Factory.cs" />
<Compile Include="BenchControl\Modbus\Danfoss\VLT\PumpCfg.cs" />
<Compile Include="BenchControl\Modbus\Danfoss\VLT\PumpCfgCtrl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="BenchControl\Modbus\Danfoss\VLT\PumpCfgCtrl.designer.cs">
<DependentUpon>PumpCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\Modbus\Easytherm\Factory.cs" />
<Compile Include="BenchControl\Modbus\Easytherm\Easytherm.cs" />
<Compile Include="BenchControl\Modbus\Easytherm\EasythermCfg.cs" />
@ -798,16 +807,26 @@
<DependentUpon>ModbusCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\Modbus\Common\Factory.cs" />
<Compile Include="BenchControl\Modbus\PressureMeter\Meret\Factory.cs" />
<Compile Include="BenchControl\Modbus\PressureMeter\Meret\PressureMeter.cs" />
<Compile Include="BenchControl\Modbus\PressureMeter\Meret\PressureMeterCfg.cs" />
<Compile Include="BenchControl\Modbus\PressureMeter\Meret\PressureMeterCfgCtrl.cs">
<Compile Include="BenchControl\Modbus\Meret\PressureMeter\Factory.cs" />
<Compile Include="BenchControl\Modbus\Meret\PressureMeter\PressureMeter.cs" />
<Compile Include="BenchControl\Modbus\Meret\PressureMeter\PressureMeterCfg.cs" />
<Compile Include="BenchControl\Modbus\Meret\PressureMeter\PressureMeterCfgCtrl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="BenchControl\Modbus\PressureMeter\Meret\PressureMeterCfgCtrl.designer.cs">
<Compile Include="BenchControl\Modbus\Meret\PressureMeter\PressureMeterCfgCtrl.designer.cs">
<DependentUpon>PressureMeterCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\Modbus\PressureMeter\Meret\ReadPressureOp.cs" />
<Compile Include="BenchControl\Modbus\Meret\PressureMeter\ReadPressureOp.cs" />
<Compile Include="BenchControl\Modbus\Meret\TempMeter\Factory.cs" />
<Compile Include="BenchControl\Modbus\Meret\TempMeter\TempMeter.cs" />
<Compile Include="BenchControl\Modbus\Meret\TempMeter\TempMeterCfg.cs" />
<Compile Include="BenchControl\Modbus\Meret\TempMeter\TempMeterCfgCtrl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="BenchControl\Modbus\Meret\TempMeter\TempMeterCfgCtrl.designer.cs">
<DependentUpon>TempMeterCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\Modbus\Meret\TempMeter\ReadTempOp.cs" />
<Compile Include="BenchControl\Modbus\QuidoRS\ConfirmationForm.cs">
<SubType>Form</SubType>
</Compile>
@ -2889,12 +2908,18 @@
<EmbeddedResource Include="BenchControl\Modbus\Common\ModbusCfgCtrl.resx">
<DependentUpon>ModbusCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\Modbus\Danfoss\VLT\PumpCfgCtrl.resx">
<DependentUpon>PumpCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\Modbus\Easytherm\EasythermCfgCtrl.resx">
<DependentUpon>EasythermCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\Modbus\PressureMeter\Meret\PressureMeterCfgCtrl.resx">
<EmbeddedResource Include="BenchControl\Modbus\Meret\PressureMeter\PressureMeterCfgCtrl.resx">
<DependentUpon>PressureMeterCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\Modbus\Meret\TempMeter\TempMeterCfgCtrl.resx">
<DependentUpon>TempMeterCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\Modbus\QuidoRS\ConfirmationForm.resx">
<DependentUpon>ConfirmationForm.cs</DependentUpon>
</EmbeddedResource>

View File

@ -130,8 +130,8 @@ namespace TBF.UI.Bench.Metrology
/// Tab-pages for pressure meters
if (factory is BenchControl.Elde.PressureMeter.PressureMeterFactory ||
factory is BenchControl.Elde.PressureMeterInternal.PressureMeterFactory ||
factory is BenchControl.Modbus.PressureMeter.Meret.Factory)
{
factory is BenchControl.Modbus.Meret.PressureMeter.Factory)
{
pressMetersCount++;
TabPage tabPage = new TabPage(" " + cmpnt.Name + " ");
MetrologyDlgPressMeterTab uiControl = new MetrologyDlgPressMeterTab();
@ -145,7 +145,9 @@ namespace TBF.UI.Bench.Metrology
/// Tab-pages for temperature meters
if (factory is BenchControl.Elde.TempMeter.TempMeterFactory ||
factory is BenchControl.Elde.TempMeterInternal.TempMeterFactory)
factory is BenchControl.Elde.TempMeterInternal.TempMeterFactory ||
factory is BenchControl.Keithley.TempMeter.Factory ||
factory is BenchControl.Modbus.Meret.TempMeter.Factory)
{
tempMetersCount++;
TabPage tabPage = new TabPage(" " + cmpnt.Name + " ");

View File

@ -119,7 +119,7 @@ namespace TBF.UI.Bench.Uncertainties
/// Tab-pages for pressure meters
if (factory is BenchControl.Elde.PressureMeter.PressureMeterFactory ||
factory is BenchControl.Elde.PressureMeterInternal.PressureMeterFactory ||
factory is BenchControl.Modbus.PressureMeter.Meret.Factory)
factory is BenchControl.Modbus.Meret.PressureMeter.Factory)
{
pressMetersCount++;
TabPage tabPage = new TabPage(" " + cmpnt.Name + " ");
@ -134,7 +134,8 @@ namespace TBF.UI.Bench.Uncertainties
/// Tab-pages for temperature meters (incl. platinum temp. meter with Keithley)
if (factory is BenchControl.Elde.TempMeter.TempMeterFactory ||
factory is BenchControl.Elde.TempMeterInternal.TempMeterFactory ||
factory is BenchControl.Keithley.TempMeter.Factory)
factory is BenchControl.Keithley.TempMeter.Factory ||
factory is BenchControl.Modbus.Meret.TempMeter.Factory)
{
tempMetersCount++;
TabPage tabPage = new TabPage(" " + cmpnt.Name + " ");