FM2014: - pulse measurements

This commit is contained in:
Thomas Wiedebusch 2026-01-12 16:16:43 +01:00
parent 6d79c03909
commit 963df837dc
6 changed files with 213 additions and 154 deletions

View File

@ -46,7 +46,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <summary>
/// Command definition
/// </summary>
public enum CmdDef
public enum CmdName
{
/// <summary>
///
@ -212,7 +212,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <summary>
///
/// </summary>
CMD_ADDR_PC
CMD_ADDR_PC,
/// <summary>
///
/// </summary>
CMD_NA
}
/// <summary>
@ -224,12 +228,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// Individual addressed command with answer
/// </summary>
INDIVIDUAL_WA,
/// <summary>
/// Individual addressed command without answer
/// </summary>
INDIVIDUAL_NA,
/// <summary>
/// Broadcast command without answer to address 0 or individual without answer
/// </summary>
@ -239,12 +243,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <summary>
/// Assembly of command information and functional code
/// </summary>
public struct CmdTblEntry
public struct Cmd
{
/// <summary>
/// Enumerator of command name acronym
/// </summary>
public readonly CmdDef CmdName;
public readonly CmdName CmdName;
/// <summary>
/// Code being sent to FM2014 as character
@ -268,7 +272,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <param name="cmdCodeChar">Code being sent to FM2014 as character</param>
/// <param name="cmdType">Command type regarding the address (broadcast or individual) and answer</param>
/// <param name="cmdInfoStr">Multilingual command information string</param>
public CmdTblEntry(CmdDef cmdName, Char cmdCodeChar, CmdType cmdType, String cmdInfoStr)
public Cmd(CmdName cmdName, Char cmdCodeChar, CmdType cmdType, String cmdInfoStr)
{
CmdName = cmdName;
CmdCodeChar = cmdCodeChar;
@ -277,6 +281,88 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
}
}
/// <summary>
/// Resolution of FM2014 timer for measurement of pulse width
/// </summary>
public const Double FM2014_TMR_RESOLUTION_s = 334e-6;
/// <summary>
/// FM2014 Ascii string delimiter
/// </summary>
public const Char END_OF_STRING = '\r';
/// <summary>
/// Character for address assignment in advance to the address number
/// </summary>
public const Char ADDR_RECORD_CHAR = '*';
/// <summary>
/// Address assignment validation behind the address number
/// </summary>
public const Char ADDR_VALIDATION_CHAR = '@';
// Unicode chars for command table
private const Char UNICODE_ACK = '\u0006';
private const Char UNICODE_DLE = '\u0010';
private const Char UNICODE_DC1 = '\u0011';
private const Char UNICODE_DC2 = '\u0012';
/// <summary>
/// Complete command table
/// </summary>
public static List<Cmd> CmdTbl = new List<Cmd>
{
// FM2014 control and information
new Cmd(CmdName.CMD_UNLOCK_ERASE, '&', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgUnlockErase),
new Cmd(CmdName.CMD_DEF_MEAS_SETUP, '%', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDefMeasSetup),
new Cmd(CmdName.CMD_BOOT_MODE, '$', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgBootMode),
new Cmd(CmdName.CMD_PRINT_INFO, '?', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgPrintInfo),
new Cmd(CmdName.CMD_BAUDRATE_ALL, '=', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgBaudrateAll),
new Cmd(CmdName.CMD_GET_VIRTUAL_ADDRESS, ' ', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetVirtualAddress),
new Cmd(CmdName.CMD_SERIAL, '#', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgSerial),
new Cmd(CmdName.CMD_GET_STATUS, UNICODE_ACK, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetStatus),
new Cmd(CmdName.CMD_SET_VIRTUAL_ADDRESS, 'N', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgSetVirtualAddress),
new Cmd(CmdName.CMD_PRINT_STATISTICS, '!', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgPrintStatistics),
//measurement reset
new Cmd(CmdName.CMD_RST_MEAS, 'R', CmdType.BROADCAST, Resources.StrCmdMsgRstMeas),
// Double impulse detection settings
new Cmd(CmdName.CMD_SET_DPLS_LOCK_TMR, 'S', CmdType.BROADCAST, Resources.StrCmdMsgDplsLockTmr),
new Cmd(CmdName.CMD_SET_DPLS_LOCK_MULT, 's', CmdType.BROADCAST, Resources.StrCmdMsgDplsLockMult),
new Cmd(CmdName.CMD_SET_DBPL_UNLOCK, 'G', CmdType.BROADCAST, Resources.StrCmdMsgSetDbplUnlock),
// Main measurement pulse settings and readout
new Cmd(CmdName.CMD_DUT_SET_PLS, 'H', CmdType.BROADCAST, Resources.StrCmdMsgDutSetPls),
new Cmd(CmdName.CMD_REF_SET_PLS, 'M', CmdType.BROADCAST, Resources.StrCmdMsgRefSetPls),
new Cmd(CmdName.CMD_DUT_GET_PLS_RMN, 'I', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetPlsRmn),
new Cmd(CmdName.CMD_REF_GET_PLS_RMN, 'J', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetPlsRmn),
// Pulse counters start, readout and backup
new Cmd(CmdName.CMD_REF_STR_PLS_CTR, 'O', CmdType.BROADCAST, Resources.StrCmdMsgRefStrPlsCtr),
new Cmd(CmdName.CMD_DUT_STR_PLS_CTR, 'Q', CmdType.BROADCAST, Resources.StrCmdMsgDutStrPlsCtr),
new Cmd(CmdName.CMD_REF_GET_PLS_CTR, 'L', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetPlsCtr),
new Cmd(CmdName.CMD_DUT_GET_PLS_CTR, 'U', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetPlsCtr),
new Cmd(CmdName.CMD_REF_GET_PLS_CTR_BU, 'l', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetPlsCtrBu),
new Cmd(CmdName.CMD_DUT_GET_PLS_CTR_BU, 'u', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetPlsCtrBu),
new Cmd(CmdName.CMD_REF_DUT_STR_PLS_CTR, 'o', CmdType.BROADCAST, Resources.StrCmdMsgRefDutStrPlsCtr),
new Cmd(CmdName.CMD_REF_DUT_BU_PLS_CTR, 'q', CmdType.BROADCAST, Resources.StrCmdMsgRefDutBuPlsCtr),
// General measurement setup
new Cmd(CmdName.CMD_REF_SET_SCALE, 'K', CmdType.BROADCAST, Resources.StrCmdMsgRefSetScale),
new Cmd(CmdName.CMD_DUT_LPP_SCALE, 'V', CmdType.INDIVIDUAL_NA, Resources.StrCmdMsgDutLppScale),
new Cmd(CmdName.CMD_REF_LPP_SCALE, 'W', CmdType.INDIVIDUAL_NA, Resources.StrCmdMsgRefLppScale),
new Cmd(CmdName.CMD_MEAS_SET_ATTN, 'T', CmdType.BROADCAST, Resources.StrCmdMsgMeasSetAttn),
// Measurement result request
new Cmd(CmdName.CMD_DUT_GET_TMR, 'X', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetTmr),
new Cmd(CmdName.CMD_REF_GET_TMR, 'Y', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetTmr),
new Cmd(CmdName.CMD_GET_UDTLC, 'Z', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetUdtlc),
new Cmd(CmdName.CMD_GET_DTLC, 'z', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetDtlc),
new Cmd(CmdName.CMD_GET_REF_PERIOD, UNICODE_DLE, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetRefPeriod),
new Cmd(CmdName.CMD_GET_DUT_PERIOD, UNICODE_DC1, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetDutPeriod),
new Cmd(CmdName.CMD_GET_REF_FREQU, UNICODE_DC2, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetRefFrequ),
// Adjustment, place here Ids which may represent digital numbers from A to F
new Cmd(CmdName.CMD_COR_CURRENT, 'C', CmdType.BROADCAST, Resources.StrCmdMsgCorCurrent),
new Cmd(CmdName.CMD_SET_XTR_MAX, '+', CmdType.BROADCAST, Resources.StrCmdMsgSetXtrMax),
new Cmd(CmdName.CMD_SET_XTR_MIN, '-', CmdType.BROADCAST, Resources.StrCmdMsgSetXtrMin),
new Cmd(CmdName.CMD_ADDR_PC, 'A', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgAddrPc)
};
/// <summary>
/// Combine constant string returns from FM2014 firmware to multilingual information
/// </summary>
@ -286,7 +372,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// Hard coded return string from FM2014
/// </summary>
public String FM2014ErrorReturnStr;
/// <summary>
/// Multilingual forwarded string to GUI
/// </summary>
@ -307,7 +393,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <summary>
/// Table of error codes received from FM2014
/// </summary>
public static readonly CmdErrorMsg[] CmdErrorCodes =
public static readonly CmdErrorMsg[] CmdErrorCodes =
{
new CmdErrorMsg ("Parameter is out of range!", Resources.StrCmdRespErrorParamOutOfRange),
new CmdErrorMsg ("Command not supported!", Resources.StrCmdRespErrorCmdNotSupported),
@ -325,32 +411,32 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <summary>
/// FM2014 command identifier
/// </summary>
public CmdDef CmdId { get; private set; }
public CmdName CmdId { get; private set; }
/// <summary>
/// Optional raw answer from FM2014
/// </summary>
public String AnswerStr { get; private set; }
/// <summary>
/// Optional integer value
/// </summary>
public Int32? IntValue { get; private set; }
/// <summary>
/// Optional double value
/// </summary>
public Double? DoubleValue { get; private set; }
/// <summary>
/// Measurement SI unit
/// </summary>
public String SiUnit { get; private set; }
/// <summary>
/// Ctor
/// </summary>
public CmdResponse(CmdDef cmdId, String answerStr, Int32? intValue = null, Double? doubleValue = null,
public CmdResponse(CmdName cmdId, String answerStr, Int32? intValue = null, Double? doubleValue = null,
String siUnit = "")
{
CmdId = cmdId;
@ -361,100 +447,6 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
}
}
/// <summary>
/// Resolution of FM2014 timer for measurement of pulse width
/// </summary>
public const Double FM2014_TMR_RESOLUTION_s = 334e-6;
/// <summary>
/// FM2014 Ascii string delimiter
/// </summary>
public const Char END_OF_STRING = '\r';
/// <summary>
/// Character for address assignment in advance to the address number
/// </summary>
public const Char ADDR_RECORD_CHAR = '*';
/// <summary>
/// Address assignment validation behind the address number
/// </summary>
public const Char ADDR_VALIDATION_CHAR = '@';
/// <summary>
/// Complete command table
/// </summary>
public static List<CmdTblEntry> CmdTbl;
// Unicode chars for command table
private const Char UNICODE_ACK = '\u0006';
private const Char UNICODE_DLE = '\u0010';
private const Char UNICODE_DC1 = '\u0011';
private const Char UNICODE_DC2 = '\u0012';
/// <summary>
/// Ctor
/// </summary>
/// <returns>command code to send to the FM2014</returns>
/// <remarks date="2026-Jan-08" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
static FM2014CmdDef()
{
CmdTbl = new List<CmdTblEntry>
{
// FM2014 control and information
new CmdTblEntry(CmdDef.CMD_UNLOCK_ERASE, '&', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgUnlockErase),
new CmdTblEntry(CmdDef.CMD_DEF_MEAS_SETUP, '%', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDefMeasSetup),
new CmdTblEntry(CmdDef.CMD_BOOT_MODE, '$', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgBootMode),
new CmdTblEntry(CmdDef.CMD_PRINT_INFO, '?', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgPrintInfo),
new CmdTblEntry(CmdDef.CMD_BAUDRATE_ALL, '=', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgBaudrateAll),
new CmdTblEntry(CmdDef.CMD_GET_VIRTUAL_ADDRESS, ' ', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetVirtualAddress),
new CmdTblEntry(CmdDef.CMD_SERIAL, '#', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgSerial),
new CmdTblEntry(CmdDef.CMD_GET_STATUS, UNICODE_ACK, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetStatus),
new CmdTblEntry(CmdDef.CMD_SET_VIRTUAL_ADDRESS, 'N', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgSetVirtualAddress),
new CmdTblEntry(CmdDef.CMD_PRINT_STATISTICS, '!', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgPrintStatistics),
//measurement reset
new CmdTblEntry(CmdDef.CMD_RST_MEAS, 'R', CmdType.BROADCAST, Resources.StrCmdMsgRstMeas),
// Double impulse detection settings
new CmdTblEntry(CmdDef.CMD_SET_DPLS_LOCK_TMR, 'S', CmdType.BROADCAST, Resources.StrCmdMsgDplsLockTmr),
new CmdTblEntry(CmdDef.CMD_SET_DPLS_LOCK_MULT, 's', CmdType.BROADCAST, Resources.StrCmdMsgDplsLockMult),
new CmdTblEntry(CmdDef.CMD_SET_DBPL_UNLOCK, 'G', CmdType.BROADCAST, Resources.StrCmdMsgSetDbplUnlock),
// Main measurement pulse settings and readout
new CmdTblEntry(CmdDef.CMD_DUT_SET_PLS, 'H', CmdType.BROADCAST, Resources.StrCmdMsgDutSetPls),
new CmdTblEntry(CmdDef.CMD_REF_SET_PLS, 'M', CmdType.BROADCAST, Resources.StrCmdMsgRefSetPls),
new CmdTblEntry(CmdDef.CMD_DUT_GET_PLS_RMN, 'I', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetPlsRmn),
new CmdTblEntry(CmdDef.CMD_REF_GET_PLS_RMN, 'J', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetPlsRmn),
// Pulse counters start, readout and backup
new CmdTblEntry(CmdDef.CMD_REF_STR_PLS_CTR, 'O', CmdType.BROADCAST, Resources.StrCmdMsgRefStrPlsCtr),
new CmdTblEntry(CmdDef.CMD_DUT_STR_PLS_CTR, 'Q', CmdType.BROADCAST, Resources.StrCmdMsgDutStrPlsCtr),
new CmdTblEntry(CmdDef.CMD_REF_GET_PLS_CTR, 'L', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetPlsCtr),
new CmdTblEntry(CmdDef.CMD_DUT_GET_PLS_CTR, 'U', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetPlsCtr),
new CmdTblEntry(CmdDef.CMD_REF_GET_PLS_CTR_BU, 'l', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetPlsCtrBu),
new CmdTblEntry(CmdDef.CMD_DUT_GET_PLS_CTR_BU, 'u', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetPlsCtrBu),
new CmdTblEntry(CmdDef.CMD_REF_DUT_STR_PLS_CTR, 'o', CmdType.BROADCAST, Resources.StrCmdMsgRefDutStrPlsCtr),
new CmdTblEntry(CmdDef.CMD_REF_DUT_BU_PLS_CTR, 'q', CmdType.BROADCAST, Resources.StrCmdMsgRefDutBuPlsCtr),
// General measurement setup
new CmdTblEntry(CmdDef.CMD_REF_SET_SCALE, 'K', CmdType.BROADCAST, Resources.StrCmdMsgRefSetScale),
new CmdTblEntry(CmdDef.CMD_DUT_LPP_SCALE, 'V', CmdType.INDIVIDUAL_NA, Resources.StrCmdMsgDutLppScale),
new CmdTblEntry(CmdDef.CMD_REF_LPP_SCALE, 'W', CmdType.INDIVIDUAL_NA, Resources.StrCmdMsgRefLppScale),
new CmdTblEntry(CmdDef.CMD_MEAS_SET_ATTN, 'T', CmdType.BROADCAST, Resources.StrCmdMsgMeasSetAttn),
// Measurement result request
new CmdTblEntry(CmdDef.CMD_DUT_GET_TMR, 'X', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgDutGetTmr),
new CmdTblEntry(CmdDef.CMD_REF_GET_TMR, 'Y', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgRefGetTmr),
new CmdTblEntry(CmdDef.CMD_GET_UDTLC, 'Z', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetUdtlc),
new CmdTblEntry(CmdDef.CMD_GET_DTLC, 'z', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetDtlc),
new CmdTblEntry(CmdDef.CMD_GET_REF_PERIOD, UNICODE_DLE, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetRefPeriod),
new CmdTblEntry(CmdDef.CMD_GET_DUT_PERIOD, UNICODE_DC1, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetDutPeriod),
new CmdTblEntry(CmdDef.CMD_GET_REF_FREQU, UNICODE_DC2, CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgGetRefFrequ),
// Adjustment, place here Ids which may represent digital numbers from A to F
new CmdTblEntry(CmdDef.CMD_COR_CURRENT, 'C', CmdType.BROADCAST, Resources.StrCmdMsgCorCurrent),
new CmdTblEntry(CmdDef.CMD_SET_XTR_MAX, '+', CmdType.BROADCAST, Resources.StrCmdMsgSetXtrMax),
new CmdTblEntry(CmdDef.CMD_SET_XTR_MIN, '-', CmdType.BROADCAST, Resources.StrCmdMsgSetXtrMin),
new CmdTblEntry(CmdDef.CMD_ADDR_PC, 'A', CmdType.INDIVIDUAL_WA, Resources.StrCmdMsgAddrPc)
};
}
/// <summary>
/// Get char command code from command name
/// </summary>
@ -463,11 +455,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <remarks date="2026-Jan-08" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static Char GetCmdChar(CmdDef cmdName)
public static Char GetCmdChar(CmdName cmdName)
{
return (from ct in CmdTbl
where ct.CmdName == cmdName
select ct.CmdCodeChar).FirstOrDefault();
where ct.CmdName == cmdName
select ct.CmdCodeChar).FirstOrDefault();
}
/// <summary>
@ -478,11 +470,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <remarks date="2026-Jan-10" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static String GetCmdInfo(CmdDef cmdName)
public static String GetCmdInfo(CmdName cmdName)
{
return (from ct in CmdTbl
where ct.CmdName == cmdName
select ct.CmdInfoStr).FirstOrDefault();
where ct.CmdName == cmdName
select ct.CmdInfoStr).FirstOrDefault();
}
/// <summary>
@ -493,11 +485,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <remarks date="2026-Jan-10" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static CmdType GetCmdCmdType(CmdDef cmdName)
public static CmdType GetCmdCmdType(CmdName cmdName)
{
return (from ct in CmdTbl
where ct.CmdName == cmdName
select ct.CmdType).FirstOrDefault();
where ct.CmdName == cmdName
select ct.CmdType).FirstOrDefault();
}
}
}

View File

@ -35,8 +35,10 @@
using System;
using System.Globalization;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
using Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Consts;
using Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Properties;
using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Utils.ProcessExec.EventArguments;
@ -207,63 +209,89 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
/// <summary>
/// Reference calibration with volume or weight-scale:
/// - Count pulses on REF,
/// - Manual input of volume.
/// Pulse counter measurement:
/// - REF counter,
/// - DUT counter,
/// - REF and DUT counters together.
/// </summary>
/// <param name="refCtrOn">request to count REF pulses</param>
/// <param name="dutCtrOn">request to count DUT pulses</param>
/// <returns></returns>
/// <remarks date="2026-Jan-10" author="Thomas Wiedebusch">
/// <remarks date="2026-Jan-10..12" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public Boolean ManualRefCalibration()
public Boolean StartPulseCounting(Boolean refCtrOn = true, Boolean dutCtrOn = false)
{
if (SerialPort == null || !SerialPort.IsOpen)
if (SerialPort == null || !SerialPort.IsOpen || (!refCtrOn && !dutCtrOn))
{
return false;
}
// Stop receive task
if (ReceiveTaskIsActive)
{
ReceiveTaskIsActive = false;
return true;
}
ReceiveTaskIsActive = true;
var cmdName = FM2014CmdDef.CmdName.CMD_NA;
// Prepare REF-pulse counter measurement
try
{
SerialPort.Write($"{FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdDef.CMD_REF_STR_PLS_CTR)}{_eos}");
if (refCtrOn && dutCtrOn)
cmdName = FM2014CmdDef.CmdName.CMD_REF_DUT_STR_PLS_CTR;
else if (refCtrOn)
cmdName = FM2014CmdDef.CmdName.CMD_REF_STR_PLS_CTR;
else
cmdName = FM2014CmdDef.CmdName.CMD_DUT_STR_PLS_CTR;
var cmdCodeChar = FM2014CmdDef.GetCmdChar(cmdName);
SerialPort.Write($"{cmdCodeChar}{_eos}");
}
catch (Exception e)
{
Console.WriteLine(e);
var response = new FM2014CmdDef.CmdResponse(cmdName, e.Message);
OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response,
statusReturn: StatusReturn.Failed));
}
// Measurement Loop
Task.Run(() =>
{
// Get the process information
var info = FM2014CmdDef.GetCmdInfo(FM2014CmdDef.CmdDef.CMD_REF_GET_PLS_CTR);
var cmdCode = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdDef.CMD_REF_GET_PLS_CTR);
var infoRef = FM2014CmdDef.GetCmdInfo(FM2014CmdDef.CmdName.CMD_REF_GET_PLS_CTR);
var cmdCodeRef = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdName.CMD_REF_GET_PLS_CTR);
var infoDut = FM2014CmdDef.GetCmdInfo(FM2014CmdDef.CmdName.CMD_DUT_GET_PLS_CTR);
var cmdCodeDut = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdName.CMD_DUT_GET_PLS_CTR);
do
{
try
{
SerialPort.Write($"{cmdCode}{_eos}");
var refPulseStr = SerialPort.ReadTo($"{_eos}");
if (int.TryParse(refPulseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var refPulses))
if (refCtrOn)
{
var response = new FM2014CmdDef.CmdResponse(FM2014CmdDef.CmdDef.CMD_REF_GET_PLS_CTR, "",
refPulses);
OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(info, specificInfoObj: response));
SerialPort.Write($"{cmdCodeRef}{_eos}");
var refPulseStr = SerialPort.ReadTo($"{_eos}");
if (int.TryParse(refPulseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var refPulses))
{
var response = new FM2014CmdDef.CmdResponse(FM2014CmdDef.CmdName.CMD_REF_GET_PLS_CTR, "",
refPulses);
OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(infoRef, specificInfoObj: response));
}
}
if (dutCtrOn)
{
SerialPort.Write($"{cmdCodeDut}{_eos}");
var dutPulseStr = SerialPort.ReadTo($"{_eos}");
if (int.TryParse(dutPulseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var dutPulses))
{
var response = new FM2014CmdDef.CmdResponse(FM2014CmdDef.CmdName.CMD_DUT_GET_PLS_CTR, "",
dutPulses);
OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(infoDut, specificInfoObj: response));
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
var response = new FM2014CmdDef.CmdResponse(cmdName, e.Message);
OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response,
statusReturn: StatusReturn.Failed));
}
//Thread.Sleep(500);
@ -305,7 +333,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
var fields = FullId.Split('.');
FwVersion = fields[1];
var cmdCode = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdDef.CMD_SERIAL);
var cmdCode = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdName.CMD_SERIAL);
// Read out the serial number of this FM2014
SerialPort.Write($"{cmdCode}{_eos}");
SerialNumber = SerialPort.ReadTo($"{_eos}");
@ -325,9 +353,36 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
return IsLoggedOn;
}
/// <summary>
/// Reset the measurement but only if receive task is active.
/// </summary>
/// <returns></returns>
/// <remarks date="2026-Jan-12" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public Boolean ResetMeasurement()
{
if (SerialPort == null || !SerialPort.IsOpen)
return false;
if (!ReceiveTaskIsActive)
return true;
ReceiveTaskIsActive = false;
// Reset measurement
var cmdCode = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdName.CMD_RST_MEAS);
// Read out the serial number of this FM2014
SerialPort?.Write($"{cmdCode}{_eos}");
// Wait until FM2014 calibration finished
Thread.Sleep(4000);
return true;
}
/// <inheritdoc/>
public Boolean Logout()
{
ResetMeasurement();
IsLoggedOn = false;
SerialPort?.Close();
return SerialPort != null && !SerialPort.IsOpen;
@ -336,8 +391,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <inheritdoc/>
public void Dispose()
{
IsLoggedOn = false;
SerialPort?.Close();
Logout();
SerialPort?.Dispose();
}
#endregion methods

View File

@ -483,5 +483,14 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr
return ResourceManager.GetString("StrCmdRespErrorRefTimeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ERROR.
/// </summary>
internal static string StrError {
get {
return ResourceManager.GetString("StrError", resourceCulture);
}
}
}
}

View File

@ -259,4 +259,7 @@
<data name="StrCmdMsgPrintStatistics" type="System.Resources.ResXNullRef, System.Windows.Forms">
<value />
</data>
<data name="StrError" xml:space="preserve">
<value>FEHLER</value>
</data>
</root>

View File

@ -258,4 +258,7 @@
<data name="StrCmdMsgPrintStatistics" xml:space="preserve">
<value />
</data>
<data name="StrError" xml:space="preserve">
<value>ERROR</value>
</data>
</root>

View File

@ -254,7 +254,6 @@ namespace Sensus.MiniPrf.Ui
private void FrmMainMiniPrf_FormClosed(Object sender, FormClosedEventArgs e)
{
_frmHistory?.Close();
_fm2014?.Logout();
_fm2014?.Dispose();
Dispose();
}
@ -618,18 +617,17 @@ namespace Sensus.MiniPrf.Ui
_startTime = DateTimeOffset.UtcNow;
ActionControl(true);
btnDutToRefRegulation.Enabled = false;
if (_fm2014.ManualRefCalibration())
if (_fm2014.StartPulseCounting())
{
btnManualRefCalibration.Text = Resources.StrBtnStopCalibration;
}
}
else
{
if (_fm2014.ManualRefCalibration())
{
ActionControl(false);
btnManualRefCalibration.Text = Resources.StrBtnStartCalibration;
}
btnManualRefCalibration.Enabled = false;
_fm2014.ResetMeasurement();
ActionControl(false);
btnManualRefCalibration.Text = Resources.StrBtnStartCalibration;
}
}