- Added Underload measurement state - Detect underload responses from Mettler Toledo scales - Automatically zero the scale after underload detection - Restart mass measurement after successful zeroing - Prevent zeroing response from being used as a valid measurement - Preserve measurement stability by clearing buffered readings after underload
614 lines
25 KiB
C#
614 lines
25 KiB
C#
///
|
|
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
using System.IO.Ports;
|
|
using log4net;
|
|
using Common;
|
|
using Config.Entities;
|
|
using SchematicDrawing;
|
|
using TBF.Rig.Generic;
|
|
using TBF.Rig.GenericDevices;
|
|
using TBF.Boxes;
|
|
using TBF.Resources;
|
|
|
|
namespace TBF.Rig.Scales.MettlerToledo
|
|
{
|
|
public enum Activity
|
|
{
|
|
Idle,
|
|
ImmediateMeasurement,
|
|
RunningOperation,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mettler Toledo ICS4_5 Weighting terminal connected via serial interface (RS232)
|
|
/// </summary>
|
|
/// <note>
|
|
/// Implemented and tested on 15.10.2013 by Milan Hanajik
|
|
/// </note>
|
|
public class Scale : TankDraining, IDevice, GenericDevices.IScale, GenericDevices.IHasCalendarEvents, IDrawingItCmpntWithMeasuredVal
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(Scale));
|
|
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
|
|
|
|
/// Configuration and wrappers
|
|
protected readonly ScaleCfg scaleCfg;
|
|
///
|
|
public double Capacity { get { return scaleCfg.Capacity; } }
|
|
public int EmptyTimeSec { get { return scaleCfg.DrainTimeSec; } }
|
|
public IValve DrainValve2 { get { return null; } }
|
|
public float BuoyancyTemp { get { return scaleCfg.BuoyancyTemp; } }
|
|
public float BuoyancyPress { get { return scaleCfg.BuoyancyPress; } }
|
|
public float BuoyancyHumi { get { return scaleCfg.BuoyancyHumi; } }
|
|
public double WeightStandardDensity { get { return scaleCfg.WeightStandardDensity; } }
|
|
///
|
|
Protocol proto { get { return scaleCfg.Protocol; } }
|
|
///
|
|
public IDrawingItem DrawingItem { get { return scaleCfg as IDrawingItem; } }
|
|
|
|
protected ISerialPort serialPort;
|
|
protected StringBuilder stringBuilder;
|
|
|
|
/// <summary>The state of the mass measurement</summary>
|
|
public Activity Activity;
|
|
public MsrmntState MsrmntState { get { return msrmntState; } set { msrmntState = value; } }
|
|
protected MsrmntState msrmntState;
|
|
|
|
/// <summary>Time since the last serial command in seconds</summary>
|
|
public int MsrmntTime;
|
|
|
|
/// <summary>The mass after StartMassMeasurement() when MsrmntState == MsrmntState.Valid</summary>
|
|
public double Mass { get { return mass; } }
|
|
protected double mass;
|
|
|
|
public bool MsrmntAvailable { get { return true; } }
|
|
public double MeasuredVal { get { return mass; } }
|
|
public string AltString { get { return string.Empty; } }
|
|
|
|
/// <summary>The time stamp after StartMassMeasurement() when MsrmntState == MsrmntState.Valid</summary>
|
|
public int MsrmntTimeStamp { get { return msrmntTimeStamp; } }
|
|
protected int msrmntTimeStamp;
|
|
|
|
public string Format { get { return scaleCfg.MsrdFormat; } }
|
|
|
|
|
|
/// <summary>Serial number after GetSerialNumber() when MsrmntState == MsrmntState.Valid</summary>
|
|
public string SerialNumber { get { return serialNumber; } }
|
|
string serialNumber;
|
|
|
|
|
|
public Scale() { }
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="cfg">Balance properties</param>
|
|
/// <param components="cfg">A list of components loaded so far</param>
|
|
public Scale(Generic.IComponentCfg cfg)
|
|
: base(cfg)
|
|
{
|
|
scaleCfg = cfg as ScaleCfg;
|
|
}
|
|
|
|
public Scale(Generic.IComponentCfg cfg, ISerialPort serialPort)
|
|
: base(cfg)
|
|
{
|
|
scaleCfg = cfg as ScaleCfg;
|
|
this.serialPort = serialPort;
|
|
}
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize(); /// Initializes DrainValve, etc., should be called in DebugMode.Simulate
|
|
|
|
Activity = Activity.Idle;
|
|
msrmntState = MsrmntState.Failed; /// Data not valid yet
|
|
MsrmntTime = 0;
|
|
stringBuilder = new StringBuilder(40);
|
|
|
|
if (scaleCfg.CalibValidDate != DateTime.MinValue && scaleCfg.CalibValidDate.Date < DateTime.Now.Date)
|
|
{
|
|
throw new Exception(string.Format("{0}: {1}", Name, Strings.Calibration_certificate_validity_expired));
|
|
}
|
|
|
|
if (scaleCfg.DebugLevel == DebugMode.Normal)
|
|
{
|
|
string comPortName = "COM" + scaleCfg.ComPortNr.ToString();
|
|
serialPort ??= new SerialPortDevice(comPortName, scaleCfg.BaudRate, scaleCfg.Parity, scaleCfg.DataBits,
|
|
scaleCfg.StopBits);
|
|
serialPort.Handshake = scaleCfg.Handshake;
|
|
serialPort.Open();
|
|
log.FatalFormat("{0} - Device successfully initialized", Name);
|
|
}
|
|
else
|
|
{
|
|
serialPort = null;
|
|
log.FatalFormat("{0} - Device simulated", Name);
|
|
}
|
|
}
|
|
|
|
|
|
public IList<Config.CalendarEvent.ICalendarEvent> GetCalendarEvents()
|
|
{
|
|
DateTime calibrationDue = scaleCfg.CalibValidDate;
|
|
IList<Config.CalendarEvent.ICalendarEvent> calendarEvents = new List<Config.CalendarEvent.ICalendarEvent>();
|
|
|
|
if (calibrationDue > TBF.UI.Constants.MinDate)
|
|
{
|
|
/// Calibration due date calendar event
|
|
calendarEvents.Add(new TBF.UI.Calendar.CalibrationDueDateEvent(calibrationDue.Date, Name,
|
|
string.Format(Strings.Calibration_due_date_is_0,
|
|
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat))));
|
|
if (DateTime.Now.Date <= calibrationDue.AddDays(-7))
|
|
{
|
|
/// Weekly reminders (last 5 weeks)
|
|
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.Date.AddDays(-35), Name,
|
|
string.Format(Strings.Calibration_due_date_is_0,
|
|
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
|
|
false));
|
|
}
|
|
if (DateTime.Now.Date <= calibrationDue.Date)
|
|
{
|
|
/// Daily reminders (last 5 days)
|
|
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.AddDays(-5), Name,
|
|
string.Format(Strings.Calibration_due_date_is_0,
|
|
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
|
|
true));
|
|
}
|
|
}
|
|
return calendarEvents;
|
|
}
|
|
|
|
|
|
public override bool IsEmpty()
|
|
{
|
|
return DrainValve.State ? (mass <= scaleCfg.Empty) : (mass <= scaleCfg.EmptyUp);
|
|
}
|
|
|
|
public override bool ContainsMoreThen(float thld)
|
|
{
|
|
return (mass >= thld);
|
|
}
|
|
|
|
public virtual void SendZeroWhenStableCmd()
|
|
{
|
|
if (scaleCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
if (msrmntState == MsrmntState.Busy)
|
|
{
|
|
log.WarnFormat("{0} - ZeroWhenStable() returns without starting zeroing the scale because measurementState == MeasurementState.Busy", Name);
|
|
return;
|
|
}
|
|
|
|
log.InfoFormat("{0} - SendZeroWhenStableCmd() - 'Z<cr><lf>'", Name);
|
|
|
|
msrmntState = MsrmntState.Busy;
|
|
MsrmntTime = 0;
|
|
stringBuilder.Clear();
|
|
serialPort.Write("Z\r\n");
|
|
}
|
|
|
|
public virtual void SendTaraCmd()
|
|
{
|
|
if (scaleCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
if (msrmntState == MsrmntState.Busy)
|
|
{
|
|
log.WarnFormat("{0} - Taring() returns without starting taring the scale because measurementState == MeasurementState.Busy", Name);
|
|
return;
|
|
}
|
|
|
|
log.InfoFormat("{0} - SendTaraCmd() - 'T<cr><lf>'", Name);
|
|
|
|
msrmntState = MsrmntState.Busy;
|
|
MsrmntTime = 0;
|
|
stringBuilder.Clear();
|
|
serialPort.Write("T\r\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a stable mass measurement
|
|
/// </summary>
|
|
public void SendStableMeasurementCmd()
|
|
{
|
|
if (scaleCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
if (msrmntState == MsrmntState.Busy)
|
|
{
|
|
log.WarnFormat("{0} - GetStableMassMeasurement() returns without starting a measurement because measurementState == MeasurementState.Busy", Name);
|
|
return;
|
|
}
|
|
|
|
log.InfoFormat("{0} - SendStableMeasurementCmd() - 'S<cr><lf>'", Name);
|
|
|
|
msrmntState = MsrmntState.Busy;
|
|
MsrmntTime = 0;
|
|
stringBuilder.Clear();
|
|
serialPort.Write("S\r\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get an immediate mass measurement
|
|
/// </summary>
|
|
public void SendImmediateMeasurementCmd()
|
|
{
|
|
if (scaleCfg.DebugLevel == DebugMode.Simulate || serialPort == null) return;
|
|
|
|
if (msrmntState == MsrmntState.Busy)
|
|
{
|
|
log.WarnFormat("{0} - GetImmediateMassMeasurement() returns without starting a measurement because measurementState == MeasurementState.Busy", Name);
|
|
return;
|
|
}
|
|
|
|
log.InfoFormat("{0} - SendImmediateMeasurementCmd() - 'SI<cr><lf>'", Name);
|
|
|
|
msrmntState = MsrmntState.Busy;
|
|
MsrmntTime = 0;
|
|
stringBuilder.Clear();
|
|
serialPort.Write("SI\r\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the serial number
|
|
/// </summary>
|
|
/// <remarks>After a successful SetUnits(kg) mass is still sent in g. MH 15.10.2013</remarks>
|
|
public void SendSetUnitsCmd(Common.Unit unit)
|
|
{
|
|
if (scaleCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
if (proto == Protocol.SICS)
|
|
{
|
|
/// Set Units command is only supported by SICS protocol
|
|
|
|
if (msrmntState == MsrmntState.Busy)
|
|
{
|
|
log.WarnFormat("{0} - SetUnits() returns without setting the units because measurementState == MeasurementState.Busy", Name);
|
|
return;
|
|
}
|
|
|
|
msrmntState = MsrmntState.Busy;
|
|
stringBuilder.Clear();
|
|
switch (unit)
|
|
{
|
|
case Common.Unit.g:
|
|
log.InfoFormat("{0} - SetUnits({1}) - 'U g<cr><lf>'", Name, unit);
|
|
serialPort.Write("U g\r\n");
|
|
break;
|
|
case Common.Unit.t:
|
|
log.InfoFormat("{0} - SetUnits({1}) - 'U t<cr><lf>'", Name, unit);
|
|
serialPort.Write("U t\r\n");
|
|
break;
|
|
case Common.Unit.lb:
|
|
log.InfoFormat("{0} - SetUnits({1}) - 'U lb<cr><lf>'", Name, unit);
|
|
serialPort.Write("U lb\r\n");
|
|
break;
|
|
case Common.Unit.oz:
|
|
log.InfoFormat("{0} - SetUnits({1}) - 'U oz<cr><lf>'", Name, unit);
|
|
serialPort.Write("U oz\r\n");
|
|
break;
|
|
case Common.Unit.kg:
|
|
default:
|
|
log.InfoFormat("{0} - SetUnits({1}) - 'U kg<cr><lf>'", Name, unit);
|
|
serialPort.Write("U kg\r\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the serial number
|
|
/// </summary>
|
|
public void SendGetSerialNumberCmd()
|
|
{
|
|
if (scaleCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
if (proto == Protocol.SICS)
|
|
{
|
|
/// Get Serial Number command is only supported by SICS protocol
|
|
|
|
if (msrmntState == MsrmntState.Busy)
|
|
{
|
|
log.WarnFormat("{0} - SendGetSerialNumberCmd() returns without getting the s/n because measurementState == MeasurementState.Busy", Name);
|
|
return;
|
|
}
|
|
|
|
log.WarnFormat("{0} - SendGetSerialNumberCmd() - 'I4<cr><lf>'", Name);
|
|
|
|
msrmntState = MsrmntState.Busy;
|
|
stringBuilder.Clear();
|
|
serialPort.Write("I4\r\n");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse characters received from the serial port
|
|
/// </summary>
|
|
public virtual void RunDeviceBefore()
|
|
{
|
|
base.RunBefore();
|
|
|
|
if (scaleCfg.DebugLevel == DebugMode.Simulate)
|
|
{
|
|
mass = 123.456;
|
|
msrmntState = MsrmntState.Valid;
|
|
msrmntTimeStamp = StateMachine.Time;
|
|
return;
|
|
}
|
|
|
|
if (serialPort == null)
|
|
{
|
|
log.ErrorFormat("{0} - RunDevice() - serial port closed", Name);
|
|
return;
|
|
}
|
|
|
|
log.DebugFormat("{0} - RunDeviceBefore()", Name);
|
|
|
|
if (msrmntState != MsrmntState.Busy) return; /// No measurement in progress
|
|
///
|
|
if (Activity == Activity.ImmediateMeasurement)
|
|
{
|
|
Activity = Activity.Idle;
|
|
}
|
|
|
|
string justReceived = serialPort.ReadExisting();
|
|
if (justReceived != null && justReceived.Length > 0)
|
|
{
|
|
log.DebugFormat("{0} - RunDeviceBefore() received '{1}'", Name, justReceived.Replace("\r", "<cr>").Replace("\n", "<lf>"));
|
|
stringBuilder.Append(justReceived);
|
|
|
|
if (stringBuilder.ToString().EndsWith("\r\n"))
|
|
{
|
|
msrmntTimeStamp = StateMachine.Time;
|
|
|
|
string received = stringBuilder.ToString();
|
|
|
|
/// Eliminate double spaces in the received string
|
|
while (true)
|
|
{
|
|
string tmp = received.Replace(" ", " ");
|
|
if (tmp.Length == received.Length) break;
|
|
received = tmp;
|
|
}
|
|
|
|
string[] field = received.Substring(0, received.Length - 2).Split(new char[] { ' ' });
|
|
double m; /// Result of double.TryParse
|
|
|
|
///
|
|
/// Mass measurement
|
|
///
|
|
if (proto == Protocol.SICS && field.Length == 4 && field[0] == "S" && (field[1] == "S" || field[1] == "D")
|
|
&& double.TryParse(field[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
|
|
CultureInfo.InvariantCulture, out m))
|
|
{
|
|
/// Stable (field[1] == "S") or dynamic (field[1] == "D") mass measurement
|
|
mass = Common.Units.ConvertFrom(ParseUnit(field[3]), m);
|
|
msrmntState = MsrmntState.Valid;
|
|
}
|
|
else if (proto == Protocol.ID1 && field.Length >= 3 && (field[0] == "S" || field[0] == "SD")
|
|
&& double.TryParse(field[1], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
|
|
CultureInfo.InvariantCulture, out m))
|
|
{
|
|
/// Stable mass: field[1] = <mass> field[2] = "kg"
|
|
mass = Common.Units.ConvertFrom(ParseUnit(field[2]), m);
|
|
msrmntState = MsrmntState.Valid;
|
|
}
|
|
else if ((proto == Protocol.ID1 && field.Length == 1 && field[0] == "SI-") ||
|
|
(proto == Protocol.SICS && field.Length == 2 && field[0] == "S" && field[1] == "-"))
|
|
{
|
|
/// Invalid value : Scale is in underload range
|
|
mass = 0;
|
|
msrmntState = MsrmntState.Underload;
|
|
}
|
|
else if ((proto == Protocol.ID1 && field.Length == 1 && field[0] == "SI+") ||
|
|
(proto == Protocol.SICS && field.Length == 2 && field[0] == "S" && field[1] == "+") ||
|
|
(proto == Protocol.SICS && field.Length >= 2 && field[0] == "SI" && field[1] == "I"))
|
|
{
|
|
/// Invalid value : Scale is in overload range
|
|
/// "SI I<cr><lf>" received in case of overload -> empty the tank
|
|
mass = scaleCfg.Capacity;
|
|
msrmntState = MsrmntState.Overload;
|
|
}
|
|
else if ((proto == Protocol.ID1 && field.Length == 1 && field[0] == "SI") ||
|
|
(proto == Protocol.SICS && field.Length >= 2 && field[0] == "S" && field[1] == "I"))
|
|
{
|
|
/// Invalid value
|
|
msrmntState = MsrmntState.Failed;
|
|
}
|
|
///
|
|
/// Zero
|
|
///
|
|
else if ((proto == Protocol.ID1 && field.Length == 1 && field[0] == "ZB") ||
|
|
(proto == Protocol.SICS && field.Length == 2 && field[0] == "Z" && field[1] == "A"))
|
|
{
|
|
/// Zero command successful, reading is 0 now
|
|
mass = 0;
|
|
msrmntState = MsrmntState.Valid;
|
|
}
|
|
else if (proto == Protocol.ID1 && field.Length == 1 && field[0] == "Z-")
|
|
{
|
|
/// Zero command cannot be executed : Below lower limit of zero set range
|
|
mass = 0;
|
|
msrmntState = MsrmntState.Failed;
|
|
}
|
|
else if (proto == Protocol.ID1 && field.Length == 1 && field[0] == "Z+")
|
|
{
|
|
/// Zero command cannot be executed : Above upper limit of zero set range
|
|
mass = 0;
|
|
msrmntState = MsrmntState.Overload;
|
|
}
|
|
///
|
|
/// Tare
|
|
///
|
|
else if (proto == Protocol.ID1 && field.Length >= 3 && field[0] == "TB"
|
|
&& double.TryParse(field[1], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
|
|
CultureInfo.InvariantCulture, out m))
|
|
{
|
|
/// Tare command successful : response is "TB value unit\r\n"
|
|
mass = Common.Units.ConvertFrom(ParseUnit(field[2]), m);
|
|
msrmntState = MsrmntState.Valid;
|
|
}
|
|
else if (proto == Protocol.SICS && field.Length == 4 && field[0] == "T" && field[1] == "S"
|
|
&& double.TryParse(field[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
|
|
CultureInfo.InvariantCulture, out m))
|
|
{
|
|
/// Taring, SICS protocol
|
|
mass = Common.Units.ConvertFrom(ParseUnit(field[3]), m);
|
|
msrmntState = MsrmntState.Valid;
|
|
}
|
|
else if (proto == Protocol.ID1 && field.Length == 1 && field[0] == "T-")
|
|
{
|
|
/// Tare command cannot be executed : Below lower limit of zero set range
|
|
msrmntState = MsrmntState.Failed;
|
|
}
|
|
else if ((proto == Protocol.ID1 && field.Length == 1 && field[0] == "T+") ||
|
|
(proto == Protocol.SICS && field.Length >= 2 && field[1] == "I"))
|
|
{
|
|
/// Tare command cannot be executed : Above upper limit of zero set range
|
|
msrmntState = MsrmntState.Overload;
|
|
}
|
|
///
|
|
/// Serial number
|
|
///
|
|
else if (proto == Protocol.SICS && field.Length == 3 && (field[0] == "I4" || field[0] == "IA")
|
|
&& field[1] == "A" && field[2].Length >= 2)
|
|
{
|
|
/// Serial number
|
|
serialNumber = field[2].Substring(1, field[2].Length - 2);
|
|
msrmntState = MsrmntState.Valid;
|
|
}
|
|
///
|
|
/// Units
|
|
///
|
|
else if (proto == Protocol.SICS && field.Length == 2 && field[0] == "U" && field[1] == "A")
|
|
{
|
|
msrmntState = MsrmntState.Valid;
|
|
}
|
|
else
|
|
{
|
|
/// Response was not recognised
|
|
msrmntState = MsrmntState.Failed;
|
|
}
|
|
|
|
/// Logging
|
|
if (field.Length > 0)
|
|
{
|
|
if (msrmntState == MsrmntState.Valid || msrmntState == MsrmntState.Busy)
|
|
{
|
|
log.InfoFormat("{0} - Received '{1}', Mass={2}, MsrmntState={3}",
|
|
Name, received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass, msrmntState);
|
|
}
|
|
else
|
|
{
|
|
log.ErrorFormat("{0} - Received '{1}', Mass={2}, MsrmntState={3}",
|
|
Name, received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass, msrmntState);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Run this device</summary>
|
|
public void RunDeviceAfter()
|
|
{
|
|
if (Activity == Activity.Idle)
|
|
{
|
|
SendImmediateMeasurementCmd();
|
|
Activity = Activity.ImmediateMeasurement;
|
|
}
|
|
base.RunAfter();
|
|
}
|
|
|
|
/// <summary>Stop this device</summary>
|
|
public void StopDevice()
|
|
{
|
|
if ((scaleCfg.DebugLevel != DebugMode.Simulate) && (serialPort != null))
|
|
{
|
|
serialPort.Close();
|
|
serialPort = null;
|
|
}
|
|
}
|
|
|
|
public void StopDevice2() { }
|
|
|
|
/// <summary>
|
|
/// Events: BalanceDone, Error
|
|
/// </summary>
|
|
/// <returns>ZeroOp reference</returns>
|
|
public IOperation ZeroOp()
|
|
{
|
|
switch (scaleCfg.ActionAfter1stDraining)
|
|
{
|
|
case ActionA1D.Zero:
|
|
return new ZeroOp(this);
|
|
case ActionA1D.Tara:
|
|
var dummy = new DoubleBox();
|
|
return new TaringOp(this, ref dummy);
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Events: BalanceDone, Error
|
|
/// </summary>
|
|
/// <param name="result">Reference to a variable for 'tara' in kg</param>
|
|
/// <returns>TaringOp reference</returns>
|
|
public IOperation TaringOp(ref DoubleBox tara)
|
|
{
|
|
return new TaringOp(this, ref tara);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Events: BalanceDone, Error
|
|
/// </summary>
|
|
/// <param name="result">Reference to a variable for the measured mass in kg</param>
|
|
/// <param name="readingsCount">Required mass readings count (>= 3)</param>
|
|
/// <param name="maxSpread">Maximum spread of measurements in kg (otherwise the measurement continues)</param>
|
|
/// <param name="method">Method: false = slow (precise), true = fast (immediate)</param>
|
|
/// <returns>ReadMassAverageOp instance reference casted to IOperaton</returns>
|
|
public IOperation ReadStableMassOp(ref DoubleBox mass, int delayBefore, MassMethod method, int readingsCount, double maxSpread)
|
|
{
|
|
return new ReadStableMassOp(this, ref mass, delayBefore, method, readingsCount, maxSpread);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Events: BalanceDone, Error
|
|
/// </summary>
|
|
/// <param name="serialNumber">Reference to the serialNumber</param>
|
|
/// <returns>GetBalanceSNOp instance reference casted to IOperaton</returns>
|
|
public virtual IOperation GetSerNumOp(ref string serialNumber)
|
|
{
|
|
return (proto == Protocol.SICS) ? new GetSerNumOp(this, ref serialNumber) : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Events: BalanceDone, Error
|
|
/// </summary>
|
|
/// <param name="units"></param>
|
|
/// <returns>SetUnitsOp instance reference casted to IOperaton</returns>
|
|
public IOperation SetUnitsOp(Common.Unit units)
|
|
{
|
|
return (proto == Protocol.SICS) ? new SetUnitsOp(this, units) : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse a string representing mass units.
|
|
/// Defaults to 'kg'in case unitStr not recognized.
|
|
/// </summary>
|
|
/// <param name="unitStr">String: "kg", "g", "t", "lb" or "oz" expected</param>
|
|
/// <returns></returns>
|
|
protected Common.Unit ParseUnit(string unitStr)
|
|
{
|
|
if (unitStr == "g") return Common.Unit.g;
|
|
if (unitStr == "t") return Common.Unit.t;
|
|
if (unitStr == "lb") return Common.Unit.lb;
|
|
if (unitStr == "oz") return Common.Unit.oz;
|
|
return Common.Unit.kg;
|
|
}
|
|
}
|
|
}
|