diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs index 2dd23f72..c6f5ebd5 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs @@ -59,7 +59,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core private const Char _eos = FM2014CmdDef.END_OF_STRING; /// - public Boolean ReceiveTaskIsActive + public Boolean CyclicReceiveTaskLoopIsActive { get; private set; @@ -94,13 +94,42 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core private set; } + private const Char _adrPre = FM2014CmdDef.ADDR_RECORD_CHAR; + private const Char _adrPost = FM2014CmdDef.ADDR_VALIDATION_CHAR; + + private Int32 _address; /// public Int32 Address + { + get => _address; + set + { + _address = value; + AddressStr = $"{_adrPre}{_adrPre}{Address}{_adrPost}{_eos}"; + } + } + + /// + /// Marker if broadcast connection was last communication + /// + public Boolean BroadcastCommIsActive { get; set; } + /// + /// Broadcast address without answer for all FM2014 + /// + public static readonly String BrodcastAddressStr = $"{_adrPre}{_adrPre}0{_adrPost}{_eos}"; + + /// + public String AddressStr + { + get; + private set; + } + /// public Int32? TolerancePercent { @@ -217,7 +246,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// request to count REF pulses /// request to count DUT pulses /// - /// + /// /// - Initial. /// public Boolean StartPulseCounting(Boolean refCtrOn = true, Boolean dutCtrOn = false) @@ -227,32 +256,41 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core return false; } - ReceiveTaskIsActive = true; var cmdName = FM2014CmdDef.CmdName.CMD_NA; - + // Prepare REF-pulse counter measurement try { - 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; + switch (refCtrOn) + { + case true when dutCtrOn: + cmdName = FM2014CmdDef.CmdName.CMD_REF_DUT_STR_PLS_CTR; + break; + case true: + cmdName = FM2014CmdDef.CmdName.CMD_REF_STR_PLS_CTR; + break; + default: + cmdName = FM2014CmdDef.CmdName.CMD_DUT_STR_PLS_CTR; + break; + } - var cmdCodeChar = FM2014CmdDef.GetCmdChar(cmdName); - SerialPort.Write($"{cmdCodeChar}{_eos}"); + // Start the pulse counter measurement + if (!Write(cmdName)) + { + return false; + } } catch (Exception e) { var response = new FM2014CmdDef.CmdResponse(cmdName, e.Message); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, + OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); } // Measurement Loop Task.Run(() => { + CyclicReceiveTaskLoopIsActive = true; // Get the process information var infoRef = FM2014CmdDef.GetCmdInfo(FM2014CmdDef.CmdName.CMD_REF_GET_PLS_CTR); var cmdCodeRef = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdName.CMD_REF_GET_PLS_CTR); @@ -262,9 +300,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { try { - if (refCtrOn) + if (refCtrOn && Write(FM2014CmdDef.CmdName.CMD_REF_GET_PLS_CTR)) { - SerialPort.Write($"{cmdCodeRef}{_eos}"); var refPulseStr = SerialPort.ReadTo($"{_eos}"); if (int.TryParse(refPulseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var refPulses)) @@ -274,9 +311,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(infoRef, specificInfoObj: response)); } } - if (dutCtrOn) + if (dutCtrOn && Write(FM2014CmdDef.CmdName.CMD_DUT_GET_PLS_CTR)) { - SerialPort.Write($"{cmdCodeDut}{_eos}"); var dutPulseStr = SerialPort.ReadTo($"{_eos}"); if (int.TryParse(dutPulseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var dutPulses)) @@ -290,12 +326,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core catch (Exception e) { var response = new FM2014CmdDef.CmdResponse(cmdName, e.Message); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, + OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); } //Thread.Sleep(500); - } while (ReceiveTaskIsActive); + } while (CyclicReceiveTaskLoopIsActive); }); return true; @@ -321,30 +357,23 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { SerialPort.Open(); - const Char adrPre = FM2014CmdDef.ADDR_RECORD_CHAR; - const Char adrPost = FM2014CmdDef.ADDR_VALIDATION_CHAR; // Establish connection to one specific FM2014 - SerialPort.Write($"{adrPre}{adrPre}{Address}{adrPost}{_eos}"); - FullId = SerialPort.ReadTo($"{_eos}"); - - if (!string.IsNullOrEmpty(FullId)) + if (InitiateIndividualComm()) { - FullId = FullId.Replace($"{adrPre}", ""); - var fields = FullId.Split('.'); - FwVersion = fields[1]; - var cmdCode = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdName.CMD_SERIAL); // Read out the serial number of this FM2014 - SerialPort.Write($"{cmdCode}{_eos}"); - SerialNumber = SerialPort.ReadTo($"{_eos}"); + if (!Write(FM2014CmdDef.CmdName.CMD_SERIAL)) + { + return false; + } + SerialNumber = SerialPort.ReadTo($"{_eos}"); if (!string.IsNullOrEmpty(SerialNumber)) { SerialNumber = SerialNumber.Replace($"{cmdCode}", ""); IsLoggedOn = true; } } - } catch (Exception e) { @@ -353,6 +382,98 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core return IsLoggedOn; } + /// + /// Initiate the broadcast communication + /// + private Boolean InitiateBroadcastComm() + { + if (SerialPort == null || !SerialPort.IsOpen) + { + return false; + } + + // If broadcast communication is already active + if (BroadcastCommIsActive) + { + return true; + } + + // Establish connection to all FM2014s with broadcast address + SerialPort.Write(BrodcastAddressStr); + + BroadcastCommIsActive = true; + return true; + } + + /// + /// Initiate communication to individual node + /// + /// + private Boolean InitiateIndividualComm() + { + if (SerialPort == null || !SerialPort.IsOpen) + { + return false; + } + + // Establish connection to one specific FM2014 + SerialPort.Write(AddressStr); + FullId = SerialPort.ReadTo($"{_eos}"); + + if (!string.IsNullOrEmpty(FullId)) + { + FullId = FullId.Replace($"{_adrPre}", ""); + var fields = FullId.Split('.'); + FwVersion = fields[1]; + BroadcastCommIsActive = false; + return true; + } + + return false; + } + + /// + /// Write command to FM2014: + /// - Select broadcast or individual addressing based on the command table, + /// - Transmits optional data. + /// + /// + /// + /// + public Boolean Write(FM2014CmdDef.CmdName cmdName, Object dataObj = null) + { + if (SerialPort == null || !SerialPort.IsOpen) + { + return false; + } + + // Initiate communication using the individual or broadcast address + var retVal = true; + if (FM2014CmdDef.CmdType.BROADCAST == FM2014CmdDef.GetCmdCmdType(cmdName)) + { + if (!BroadcastCommIsActive) + { + retVal = InitiateBroadcastComm(); + } + } + else + { + if (BroadcastCommIsActive) + { + retVal = InitiateIndividualComm(); + } + } + + if (retVal) + { + // TODO THW Prepare data object + var cmdCodeChar = FM2014CmdDef.GetCmdChar(cmdName); + SerialPort.Write($"{cmdCodeChar}{_eos}"); + } + + return retVal; + } + /// /// Reset the measurement but only if receive task is active. /// @@ -362,19 +483,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// public Boolean ResetMeasurement() { - if (SerialPort == null || !SerialPort.IsOpen) - return false; - - if (!ReceiveTaskIsActive) + if (!CyclicReceiveTaskLoopIsActive) return true; - ReceiveTaskIsActive = false; + CyclicReceiveTaskLoopIsActive = false; // Reset measurement - var cmdCode = FM2014CmdDef.GetCmdChar(FM2014CmdDef.CmdName.CMD_RST_MEAS); var infoStr = FM2014CmdDef.GetCmdInfo(FM2014CmdDef.CmdName.CMD_RST_MEAS); - // Read out the serial number of this FM2014 - SerialPort?.Write($"{cmdCode}{_eos}"); - + if (!Write(FM2014CmdDef.CmdName.CMD_RST_MEAS)) + return false; + // Wait until FM2014 calibration finished var resetDelayCtr_ms = 4000; const Int32 loopTime_ms = 500; diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs index 2579ce9c..e1739fc6 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs @@ -59,7 +59,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// Receive task is active: /// Used to mark this event and to kill ongoing task if set inactive. /// - Boolean ReceiveTaskIsActive + Boolean CyclicReceiveTaskLoopIsActive { get; } @@ -87,13 +87,21 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } /// - /// FM2014 address string + /// FM2014 address /// Int32 Address { get; } + /// + /// FM2014 address string + /// + String AddressStr + { + get; + } + /// /// Tolerance output of current loop in percent: /// - hardware dependent 3% or 5% diff --git a/Common/SoftwareAccessHelper/Access.cs b/Common/SoftwareAccessHelper/Access.cs index 1c4b6d7a..a97673e7 100644 --- a/Common/SoftwareAccessHelper/Access.cs +++ b/Common/SoftwareAccessHelper/Access.cs @@ -44,7 +44,7 @@ namespace Xylem.Common.Logic.SoftwareAccessHelper } var url = $"{ServiceUrls.GetSoftwareStartUpAccessUrl()}?Program={program}&Major={major}&Minor={minor}&Build={build}"; - var requestResponse = LocalWebRequest.GetRequest(url, 1200); + var requestResponse = LocalWebRequest.GetRequest(url, 8000); var ret = bool.Parse(requestResponse.Trim('"')); return ret; diff --git a/MiniPrf/MiniPrf.sln.DotSettings b/MiniPrf/MiniPrf.sln.DotSettings index 74692081..6acc8a8b 100644 --- a/MiniPrf/MiniPrf.sln.DotSettings +++ b/MiniPrf/MiniPrf.sln.DotSettings @@ -1,5 +1,6 @@  True + True True True True diff --git a/MiniPrf/Ui/FrmMainMiniPrf.cs b/MiniPrf/Ui/FrmMainMiniPrf.cs index ff9d9341..45657aeb 100644 --- a/MiniPrf/Ui/FrmMainMiniPrf.cs +++ b/MiniPrf/Ui/FrmMainMiniPrf.cs @@ -624,7 +624,7 @@ namespace Sensus.MiniPrf.Ui /// private void btnManualRefCalibration_Click(Object sender, EventArgs e) { - if (!_fm2014.ReceiveTaskIsActive) + if (!_fm2014.CyclicReceiveTaskLoopIsActive) { _startTime = DateTimeOffset.UtcNow; ActionControl(true); @@ -668,7 +668,7 @@ namespace Sensus.MiniPrf.Ui /// /// Feedback from FM2014. /// - /// + /// /// - Initial. /// private void DataReceived_Handler(Object sender, ProcessExecEventArgs e) @@ -676,7 +676,15 @@ namespace Sensus.MiniPrf.Ui var resp = (FM2014CmdDef.CmdResponse)e.SpecificInfoObj; if (resp.IntValue != null) + { + Invoke(new Action(() => + { + lblActualProcess.Text = resp.AnswerStr; + if (e.ActualProcessPercent != null && !_autoProgressBar && _progressBarOn) + barSingleProgressUpdate.Value = (Int32)e.ActualProcessPercent; + })); LogText($"{resp.AnswerStr}: {resp.IntValue:D}"); + } } #endregion }