diff --git a/Common/Hardware/Interfaces/Ports/PortCore/TransmitPortSettings.cs b/Common/Hardware/Interfaces/Ports/PortCore/TransmitPortSettings.cs index 5f772635..d53f5b43 100644 --- a/Common/Hardware/Interfaces/Ports/PortCore/TransmitPortSettings.cs +++ b/Common/Hardware/Interfaces/Ports/PortCore/TransmitPortSettings.cs @@ -1,4 +1,5 @@ using System; +using System.IO.Ports; namespace Xylem.Common.Hardware.Interfaces.Ports.PortCore { @@ -8,7 +9,7 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.PortCore public struct TransmitPortSettings { /// - /// The transmission protocol needs to inform the communication port how to setup, + /// The transmission protocol needs to inform the communication port how to set up, /// this is the data container. /// /// @@ -18,8 +19,17 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.PortCore /// /// /// - public TransmitPortSettings(Byte? protSyncByte, UInt16? protLengthIndex, UInt16 protAddLength, Int32 responseTimeoutMs, UInt32 baudRate, - UInt32? receiveBufferFlushThreshold, Boolean doubleSyncByte = false) + /// + /// + /// + /// + /// - String delimiter for ASCII to support others than LF "\n", + /// - Flexible DataBits, + /// - Flexible parity. + /// + public TransmitPortSettings(Byte? protSyncByte, UInt16? protLengthIndex, UInt16 protAddLength, Int32 responseTimeoutMs, + UInt32 baudRate, UInt32? receiveBufferFlushThreshold, Boolean doubleSyncByte = false, Char stringDelimiter = '\n', + Int32 dataBits = 8, Parity parity = Parity.None ) { ProtSyncByte = protSyncByte; ProtLengthIndex = protLengthIndex; @@ -28,7 +38,25 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.PortCore BaudRate = baudRate; ReceiveBufferFlushThreshold = receiveBufferFlushThreshold; DoubleSyncByte = doubleSyncByte; + StringDelimiter = stringDelimiter; + DataBits = dataBits; + Parity = parity; } + /// + /// String delimiter for ASCII to support others than LF "\n" + /// + public readonly Char StringDelimiter; + + /// + /// Flexible DataBits to support 7 bits. + /// + public readonly Int32 DataBits; + + /// + /// Flexible parity + /// + public readonly Parity Parity; + /// /// start of receiving synchronization byte at byte receive routine /// syncByte == null: use the readLine routine (ASCII) and NOT the BYTE routine, @@ -76,6 +104,6 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.PortCore /// /// a special implementation may require the doubling of the sync byte to re-synchronize /// - public Boolean DoubleSyncByte; + public readonly Boolean DoubleSyncByte; } } diff --git a/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs b/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs index db7501b0..ea3f43c0 100644 --- a/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs +++ b/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs @@ -294,7 +294,7 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts //put the actual time stamp to this record being able to assign it correctly //even if the decoding is delayed. This time stamp will be used to do the first - //synchronization at start and stop of the measurement. Therefore the serial buffer + //synchronization at start and stop of the measurement. Therefore, the serial buffer //has to be flushed in advance to avoid wrong time stamp to "old" records _receiveTimeStampPc = DateTimeOffset.UtcNow; @@ -426,6 +426,9 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts /// /// - Dispose procedure changed. /// + /// + /// - Replaced 'ReadLine' with 'ReadTo' using a string delimiter to support others than LF "\n". + /// private void ReadingThreadLoop() { //put the receive thread to JoinWaitSleep to avoid reading and logger output for timeout on diff --git a/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs b/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs index 4a8023bb..06fd805f 100644 --- a/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs +++ b/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs @@ -618,6 +618,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol /// - Removed useless too short comments as every string is going to be delimited by a 0 and usually won't match /// to a 4 byte chunk. /// + /// + /// - Removed redundant 'return cRecord'. + /// public RequestRecord CommandToMeter(Byte command, RegisterDefinition meterRegister = null, Byte[] payload = null, Int32? expectedLength = null, Boolean hideDataInLog = false, UInt16 skipRetryErrorCode = CommunicationConfig.SkipRetryErrorCode) @@ -638,8 +641,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol cRecord.ResponsePayload = completeResponse; OnMeterRegisterUpdated?.Invoke(this, new RegisterUpdatedEventArgs(meterRegister, completeResponse.ToArray())); - - return cRecord; } return cRecord; diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs index 1cfac375..8753658e 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs @@ -34,8 +34,9 @@ //using NLog; using System; using System.IO.Ports; -using System.Threading; +using System.Threading.Tasks; using Xylem.Common.CommonCore.Consts; +using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments; namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core @@ -44,8 +45,20 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// public class FM2014 : IFM2014 { + #region events + /// + public virtual event EventHandler OnRawRecordReceived; + #endregion + #region properties + /// + public Boolean ReceiveTaskIsActive + { + get; + internal set; + } + /// /// Logger for raw data output /// @@ -164,6 +177,43 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core return true; } + public Boolean ManualRefCalibration() + { + if (SerialPort == null || !SerialPort.IsOpen) + { + return false; + } + + // Stop receive task + if (ReceiveTaskIsActive) + { + ReceiveTaskIsActive = false; + return true; + } + + ReceiveTaskIsActive = true; + Task.Run(() => + { + var ctr = 0; + do + { + SerialPort.Write("#\r"); + SerialNumber = SerialPort.ReadTo("\r"); + if (ctr++ >= 100) + { + ReceiveTaskIsActive = false; + } + + OnRawRecordReceived?.Invoke(this, new StringPortDataEventArgs($"{ctr:D3}")); + + } while (ReceiveTaskIsActive); + + ReceiveTaskIsActive = false; + }); + + return true; + } + /// public Boolean Login() { diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014Core.csproj b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014Core.csproj index fa7e8a4e..ada2c4f1 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014Core.csproj +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014Core.csproj @@ -303,6 +303,10 @@ {1B02C79E-0B19-43E2-8F6B-71EF0C786C97} CommonCore + + {2e139f63-b6fe-4ea9-a098-85364fe9b26c} + PortCore + {3862d89c-e32d-4182-bb58-38777d43edd9} FM2014Config diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs index b5b64e36..ce7308dc 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/IFM2014.cs @@ -35,6 +35,7 @@ using System; using System.IO.Ports; //using NLog; using Xylem.Common.CommonCore.Consts; +using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments; namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { @@ -46,8 +47,23 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// public interface IFM2014 { + #region events + /// + /// String data feedback + /// + event EventHandler OnRawRecordReceived; + #endregion + #region properties /// + /// Receive task is active: + /// Used to mark this event and to kill ongoing task if set inactive. + /// + Boolean ReceiveTaskIsActive + { + get; + } + /// /// Serial number of the FM2014 /// String SerialNumber diff --git a/MiniPrf/MiniPrf.sln b/MiniPrf/MiniPrf.sln index f5fe3d1a..12955427 100644 --- a/MiniPrf/MiniPrf.sln +++ b/MiniPrf/MiniPrf.sln @@ -36,6 +36,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utils", "Utils", "{755396FE EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logging", "..\Common\Utils\Logging\Logging.csproj", "{4B88B0D3-E791-4774-9521-EABEACDC420E}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interfaces", "Interfaces", "{14FE7B6A-2029-4DCD-AD07-2BDF77D42D94}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ports", "Ports", "{83A52B6E-DB81-4B43-B5C1-F9B637D135BE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Protocols", "Protocols", "{4E27EA04-8B52-4681-BB5E-4658BC3FF9A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortCore", "..\Common\Hardware\Interfaces\Ports\PortCore\PortCore.csproj", "{2E139F63-B6FE-4EA9-A098-85364FE9B26C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -62,6 +70,10 @@ Global {4B88B0D3-E791-4774-9521-EABEACDC420E}.Debug|Any CPU.Build.0 = Debug|Any CPU {4B88B0D3-E791-4774-9521-EABEACDC420E}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B88B0D3-E791-4774-9521-EABEACDC420E}.Release|Any CPU.Build.0 = Release|Any CPU + {2E139F63-B6FE-4EA9-A098-85364FE9B26C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E139F63-B6FE-4EA9-A098-85364FE9B26C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E139F63-B6FE-4EA9-A098-85364FE9B26C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E139F63-B6FE-4EA9-A098-85364FE9B26C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -78,6 +90,10 @@ Global {0B205BE7-90CD-4C3A-8EBD-1E414E39528A} = {02CE88CB-677E-45A7-9B33-5028110379E5} {755396FE-7AD3-4D4A-9416-4C212A3BEF19} = {1C6D29D2-AC0D-48B2-932A-C9B94C3562F6} {4B88B0D3-E791-4774-9521-EABEACDC420E} = {755396FE-7AD3-4D4A-9416-4C212A3BEF19} + {14FE7B6A-2029-4DCD-AD07-2BDF77D42D94} = {2C357743-AB88-48BF-805A-5DEED44934A3} + {83A52B6E-DB81-4B43-B5C1-F9B637D135BE} = {14FE7B6A-2029-4DCD-AD07-2BDF77D42D94} + {4E27EA04-8B52-4681-BB5E-4658BC3FF9A6} = {14FE7B6A-2029-4DCD-AD07-2BDF77D42D94} + {2E139F63-B6FE-4EA9-A098-85364FE9B26C} = {83A52B6E-DB81-4B43-B5C1-F9B637D135BE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B72A8444-29F9-4FA4-82BE-B6E230750911} diff --git a/MiniPrf/Ui/FrmMainMiniPrf.Designer.cs b/MiniPrf/Ui/FrmMainMiniPrf.Designer.cs index 8d6e3784..155f4f6e 100644 --- a/MiniPrf/Ui/FrmMainMiniPrf.Designer.cs +++ b/MiniPrf/Ui/FrmMainMiniPrf.Designer.cs @@ -514,6 +514,7 @@ this.btnManualRefCalibration.TabIndex = 38; this.btnManualRefCalibration.Text = "Start Calibration"; this.btnManualRefCalibration.UseVisualStyleBackColor = true; + this.btnManualRefCalibration.Click += new System.EventHandler(this.btnManualRefCalibration_Click); // // gbxDutToRefRegulation // diff --git a/MiniPrf/Ui/FrmMainMiniPrf.cs b/MiniPrf/Ui/FrmMainMiniPrf.cs index 8bc0be46..7d288e54 100644 --- a/MiniPrf/Ui/FrmMainMiniPrf.cs +++ b/MiniPrf/Ui/FrmMainMiniPrf.cs @@ -35,6 +35,7 @@ using Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Config; using Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core; +using Sensus.MiniPrf.Ui.Properties; using System; using System.Drawing; using System.IO; @@ -43,7 +44,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; -using Sensus.MiniPrf.Ui.Properties; +using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments; namespace Sensus.MiniPrf.Ui { @@ -109,9 +110,15 @@ namespace Sensus.MiniPrf.Ui /// /// Clear data table and set genesis to not connected /// + /// + /// - Initial. + /// private void Init() { ViewProcessControl(false); + btnManualRefCalibration.Enabled = false; + btnDutToRefRegulation.Enabled = false; + // Load the configuration from the local file stored in AppData\FM2014 _fm2014Config.ReadFM2014Config(); @@ -202,6 +209,7 @@ namespace Sensus.MiniPrf.Ui lblWaitingForMeterResponse.Visible = false; SetFM2014AccessLocked(); + btnFM2014Connect.Enabled = true; btnFM2014Connect.Focus(); } @@ -276,33 +284,13 @@ namespace Sensus.MiniPrf.Ui #endregion TimerControls #region ActivationControls - /// - /// Disable all buttons except the connect button - /// - private void DisableToolButtons() - { - btnSaveRegulationSetup.Enabled = false; - btnManualRefCalibration.Enabled = false; - btnDutToRefRegulation.Enabled = false; - } - - /// - /// Enable all buttons except the connect button - /// - private void EnableToolButtons() - { - btnSaveRegulationSetup.Enabled = true; - btnManualRefCalibration.Enabled = true; - btnDutToRefRegulation.Enabled = true; - } - /// /// Lock all buttons, enable the connect button /// private void SetFM2014AccessLocked() { - btnFM2014Connect.Enabled = true; - DisableToolButtons(); + btnSaveRegulationSetup.Enabled = false; + btnFM2014Connect.Enabled = false; } /// @@ -310,8 +298,12 @@ namespace Sensus.MiniPrf.Ui /// private void SetFM2014AccessEnabled() { + btnSaveRegulationSetup.Enabled = true; + btnManualRefCalibration.Enabled = true; + btnDutToRefRegulation.Enabled = true; btnFM2014Connect.Enabled = true; - EnableToolButtons(); + btnManualRefCalibration.Text = Resources.StrBtnStartCalibration; + btnDutToRefRegulation.Text = Resources.StrBtnStartRegulation; } /// @@ -327,7 +319,7 @@ namespace Sensus.MiniPrf.Ui SetFM2014AccessEnabled(); } - #endregion ACtivationControls + #endregion ActivationControls #region BoardControls @@ -358,12 +350,17 @@ namespace Sensus.MiniPrf.Ui ActionControl(true); - _fm2014?.Dispose(); - //dispose old meter - _fm2014 = null; + if (_fm2014 != null) + { + _fm2014.OnRawRecordReceived -= DataReceived_Handler; + _fm2014.Dispose(); + //dispose old meter + _fm2014 = null; + } //assign new meter _fm2014 = new FM2014(); + _fm2014.OnRawRecordReceived += DataReceived_Handler; if (int.TryParse(cbxFM2014Address.SelectedItem.ToString(), out var address)) { _fm2014.Address = address; @@ -434,6 +431,11 @@ namespace Sensus.MiniPrf.Ui _fm2014?.Dispose(); } } + + private void _fm2014_OnRawRecordReceived(object sender, StringPortDataEventArgs e) + { + throw new NotImplementedException(); + } #endregion BoardControls #region ProcessControls @@ -610,15 +612,38 @@ namespace Sensus.MiniPrf.Ui #region Buttons and Controls private void btnConnect_Click(Object sender, EventArgs e) { - if (_resetTimeMeasurement) - { - _startTime = DateTimeOffset.UtcNow; - _resetTimeMeasurement = false; - } + //if (_resetTimeMeasurement) + //{ + _startTime = DateTimeOffset.UtcNow; + _resetTimeMeasurement = false; + //} Connect(); } + private void btnManualRefCalibration_Click(object sender, EventArgs e) + { + if (!_fm2014.ReceiveTaskIsActive) + { + _startTime = DateTimeOffset.UtcNow; + _resetTimeMeasurement = true; + ActionControl(true); + btnDutToRefRegulation.Enabled = false; + if (_fm2014.ManualRefCalibration()) + { + btnManualRefCalibration.Text = Resources.StrBtnStopCalibration; + } + } + else + { + if (_fm2014.ManualRefCalibration()) + { + ActionControl(false); + btnManualRefCalibration.Text = Resources.StrBtnStartCalibration; + } + } + } + private void cbxFM2014ComPort_SelectedValueChanged(Object sender, EventArgs e) { if (_toleranceIdx != cbxFM2014TolerancePercent.SelectedIndex || @@ -632,5 +657,18 @@ namespace Sensus.MiniPrf.Ui } } #endregion Buttons and Controls + #region Event handler + + private void DataReceived_Handler(Object sender, BasePortDataEventArgs e) + { + LogText(e.GetData().ToString()); + + // Return to standby + if (!_fm2014.ReceiveTaskIsActive) + { + ActionControl(false); + } + } + #endregion } } diff --git a/MiniPrf/Ui/MiniPrf.csproj b/MiniPrf/Ui/MiniPrf.csproj index 89a633ad..7425c76b 100644 --- a/MiniPrf/Ui/MiniPrf.csproj +++ b/MiniPrf/Ui/MiniPrf.csproj @@ -109,6 +109,10 @@ + + {2e139f63-b6fe-4ea9-a098-85364fe9b26c} + PortCore + {3862D89C-E32D-4182-BB58-38777D43EDD9} FM2014Config diff --git a/MiniPrf/Ui/Properties/Resources.de.resx b/MiniPrf/Ui/Properties/Resources.de.resx index 8811673c..34775575 100644 --- a/MiniPrf/Ui/Properties/Resources.de.resx +++ b/MiniPrf/Ui/Properties/Resources.de.resx @@ -221,6 +221,6 @@ Zeit [min:s]: - Datum und -zeit [min:s]: + Datum und Zeit [min:s]: \ No newline at end of file