Merge branch 'main' into configuration_json

This commit is contained in:
Stoyan Zlatev 2023-09-13 10:41:10 +02:00
commit b7d63b0aac
29 changed files with 17698 additions and 1275 deletions

View File

@ -155,7 +155,7 @@
</site>
<site name="MeterProcessState" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\Users\SZLATEV\source\repos\laa_production\Common\Service\MeterProcessState" />
<virtualDirectory path="/" physicalPath="D:\Projekte\SENSUS_GitLab\laa_production\Common\Service\MeterProcessState" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:56011:localhost" />

View File

@ -35,6 +35,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Drabesch/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Drahbesch/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=EMEA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=endian/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FFFF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Flexnet/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLEXNETVERSION/@EntryIndexedValue">True</s:Boolean>

View File

@ -20,11 +20,11 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
public abstract void SetDefaultResponseTimeout();
public abstract List<Byte> DecodeDataForPhysicalLayer(Byte command, Byte[] payload, Boolean hideDateInLog = false);
public abstract List<Byte> DecodeDataForPhysicalLayer(String ident, Byte command, Byte[] payload, Boolean hideDataInLog = false);
public abstract List<Byte> DecodeDataForLogicLayer(List<Byte> rawData);
public abstract List<Byte> DecodeDataForLogicLayer(String ident, List<Byte> rawData, Boolean hideDataInLog = false);
public abstract List<Byte> DecodeDataForPhysicalLayerUI1236(Byte[] payload);
public abstract List<Byte> DecodeDataForPhysicalLayerUI1236(String ident, Byte[] payload, Boolean hideDataInLog = false);
}

View File

@ -23,16 +23,16 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
void SetDefaultResponseTimeout();
// ReSharper disable once InconsistentNaming UI1236 is a naming forced by the caller
List<Byte> DecodeDataForPhysicalLayerUI1236(Byte[] payload);
List<Byte> DecodeDataForPhysicalLayerUI1236(String ident, Byte[] payload, Boolean hideDataInLog = false);
/// <summary>
/// Send out data (including transport protocol specific data like CRC) to physical port (like UART or IrDA)
/// </summary>
List<Byte> DecodeDataForPhysicalLayer(Byte command , Byte[] payload, Boolean hideDateInLog = false);
List<Byte> DecodeDataForPhysicalLayer(String ident, Byte command , Byte[] payload, Boolean hideDataInLog = false);
/// <summary>
/// Received data have to be checked and converted to request protocol
/// </summary>
List<Byte> DecodeDataForLogicLayer(List<Byte> rawData);
List<Byte> DecodeDataForLogicLayer(String ident, List<Byte> rawData, Boolean hideDateInLog = false);
}
}

View File

@ -90,9 +90,15 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
/// - Wakeup message detection reported to log-file,
/// - Message error text changed.
/// </remarks>
public override List<Byte> DecodeDataForLogicLayer(List<Byte> irdaRecord)
/// <remarks date="2023-Sep-01" author="T.Wiedebusch">
/// - Hide data in log introduced.
/// </remarks>
public override List<Byte> DecodeDataForLogicLayer(String ident, List<Byte> irdaRecord, Boolean hideDataInLog = false)
{
Logger.Info($"DecodeDataForPhysicalLayer Cordonel->PC({BitConverter.ToString(irdaRecord.ToArray())})");
// avoid logging of passwords or other sensitive data
Logger.Info(hideDataInLog
? $"{ident} DecodeDataForLogicalLayer Cordonel->PC(*****)"
: $"{ident} DecodeDataForLogicalLayer Cordonel->PC({BitConverter.ToString(irdaRecord.ToArray())})");
// check the record length and start of frame information
if (irdaRecord.Count < IrdaProtocolFrameLength + irdaRecord[IrdaPayLoadLengthIndex]
@ -102,7 +108,7 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
|| ((irdaRecord[IrdaMessageIndex] != IrdaMessageId)
&& irdaRecord[IrdaMessageIndex] != IrdaWakeupId)))
{
var error = new ApplicationException("Reply from IrDA is invalid.");
var error = new ApplicationException($"{ident} Reply from IrDA is invalid.");
Logger.Error(error.Message, error);
return new List<Byte>();
@ -123,7 +129,7 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
if (receivedCrc != calculatedCrc)
{
var error = new ApplicationException("Reply CRC failure. Decoding of transmit layer failed.");
var error = new ApplicationException($"{ident} Reply CRC failure. Decoding of transmit layer failed.");
Logger.Error(error.Message, error);
return new List<Byte>();
}
@ -142,8 +148,8 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
/// <remarks date="2023-Mai-16" author="T.Wiedebusch">
/// - Hide data in log forwarded to DecodeDateForPhysicalLayer to hide passwords in log files.
/// </remarks>
public override List<Byte> DecodeDataForPhysicalLayer(Byte requestProtocolCommand, Byte[] requestProtocolPayload,
Boolean hideDateInLog = false)
public override List<Byte> DecodeDataForPhysicalLayer(String ident, Byte requestProtocolCommand, Byte[] requestProtocolPayload,
Boolean hideDataInLog = false)
{
var irdaCrcInputBuffer = new List<Byte>
{
@ -170,9 +176,9 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
irdaRecord.Add((Byte)(crcResult >> 8));
// avoid logging of passwords or other sensitive data
Logger.Info(hideDateInLog
? "DecodeDataForPhysicalLayer PC->Cordonel(*******************)"
: $"DecodeDataForPhysicalLayer PC->Cordonel({BitConverter.ToString(irdaRecord.ToArray())})");
Logger.Info(hideDataInLog
? $"{ident} DecodeDataForPhysicalLayer PC->Cordonel(*****)"
: $"{ident} DecodeDataForPhysicalLayer PC->Cordonel({BitConverter.ToString(irdaRecord.ToArray())})");
return irdaRecord;
}
@ -181,7 +187,8 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
/// <remarks date="2022-Aug-24" author="R.Drabesch">
/// - Initial
/// </remarks>
public override List<Byte> DecodeDataForPhysicalLayerUI1236(Byte[] requestProtocolPayload)
public override List<Byte> DecodeDataForPhysicalLayerUI1236(String ident, Byte[] requestProtocolPayload,
Boolean hideDataInLog = false)
{
var collection = new List<Byte>
{
@ -197,7 +204,10 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
byteList.AddRange(collection);
byteList.Add((Byte)(crcResult & 0xFF));
byteList.Add((Byte)(crcResult >> 8));
Logger.Info("DecodeDataForPhysicalLayerUI1236 PC->Cordonel(" + BitConverter.ToString(byteList.ToArray()) + ")");
// avoid logging of passwords or other sensitive data
Logger.Info(hideDataInLog
? $"{ident} DecodeDataForPhysicalLayerUI1236 PC->Cordonel(*****)"
: $"{ident} DecodeDataForPhysicalLayerUI1236 PC->Cordonel({BitConverter.ToString(byteList.ToArray())})");
return byteList;
}
}

View File

@ -37,17 +37,18 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
}
/// <inheritdoc />
public override List<Byte> DecodeDataForPhysicalLayer(Byte command, Byte[] payload, Boolean hideDateInLog = false)
public override List<Byte> DecodeDataForPhysicalLayer(String ident, Byte command, Byte[] payload, Boolean hideDataInLog = false)
{
throw new ApplicationException("Streaming port cannot send data");
}
/// <inheritdoc />
public override List<Byte> DecodeDataForLogicLayer(List<Byte> rawData)
public override List<Byte> DecodeDataForLogicLayer(String ident, List<Byte> rawData, Boolean hideDataInLog = false)
{
return rawData;
}
public override List<Byte> DecodeDataForPhysicalLayerUI1236(Byte[] payload) => throw new ApplicationException("Streaming port cannot send data");
public override List<Byte> DecodeDataForPhysicalLayerUI1236(String ident, Byte[] payload, Boolean hideDataInLog = false)
=> throw new ApplicationException("Streaming port cannot send data");
}
}

View File

@ -55,13 +55,13 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
_responseTimeoutMs, BaudRate, _receiveBufferFlushThreshold, UartDoubleSyncByte);
}
public override List<Byte> DecodeDataForLogicLayer(List<Byte> uartRecord)
public override List<Byte> DecodeDataForLogicLayer(String ident, List<Byte> uartRecord, Boolean hideDataInLog = false)
{
// check the record length and start of frame information
if (uartRecord.Count < uartRecord[UartLengthIndex] + UartSyncByteLength
|| UartSyncByte != uartRecord[UartSyncByteIndex])
{
var error = new ApplicationException("Reply from UART is invalid. Decoding of transmit layer failed.");
var error = new ApplicationException($"{ident} Reply from UART is invalid. Decoding of transmit layer failed.");
Logger.Error(error.Message, error);
return new List<Byte>();
}
@ -77,7 +77,7 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
if(receivedCrc != calculatedCrc)
{
var error = new ApplicationException("Reply CRC failure. Decoding of transmit layer failed.");
var error = new ApplicationException($"{ident} Reply CRC failure. Decoding of transmit layer failed.");
Logger.Error(error.Message, error);
return new List<Byte>();
}
@ -111,7 +111,7 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
}
/// <inheritdoc />
public override List<Byte> DecodeDataForPhysicalLayer(Byte requestProtocolCommand,
public override List<Byte> DecodeDataForPhysicalLayer(String ident, Byte requestProtocolCommand,
Byte[] requestProtocolPayload, Boolean hideDataInLog = false)
{
var uartHeader = new List<Byte>();
@ -148,7 +148,8 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
/// <remarks date="2022-Aug-24" author="R.Drabesch">
/// - Initial
/// </remarks>
public override List<Byte> DecodeDataForPhysicalLayerUI1236(Byte[] requestProtocolPayload)
public override List<Byte> DecodeDataForPhysicalLayerUI1236(String ident, Byte[] requestProtocolPayload,
Boolean hideDataInLog = false)
{
var uartHeader = new List<Byte>();
var uartPayload = requestProtocolPayload.ToList();

View File

@ -173,6 +173,7 @@
case "enum8": return typeof(Enum8);
case "uint64_t": return typeof(UInt64);
case "uint96_t": return typeof(UInt96);
case "uint128_t": return typeof(UInt128);
case "int8_t": return typeof(sbyte);
case "int32_t": return typeof(Int32);
case "int64_t": return typeof(Int64);

View File

@ -1313,7 +1313,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
//avoid overwriting of list if this already exits
if (MeterAppListVersion.Any())
{
_logger.Warn("Trying to override meter dictionary. Skip read out FW");
_logger.Warn($"Slot:{Slot} - Trying to override meter dictionary. Skip read out FW");
return;
}
@ -1393,29 +1393,29 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
}
//log application information to file
_logger.Info($"PCB ID: {PcbId}");
_logger.Info($"Date time (UTC): {DateTimeOffset.UtcNow}");
_logger.Info($"Slot:{Slot} - PCB ID: {PcbId}");
_logger.Info($"Slot:{Slot} - Date time (UTC): {DateTimeOffset.UtcNow}");
if (CoreRevision != null)
{
_logger.Info("System Core Revision: " + BuildFwVersionString(CoreRevision));
_logger.Info($"Slot:{Slot} - System Core Revision: {BuildFwVersionString(CoreRevision)}");
}
_logger.Info("Region: " + Region);
_logger.Info($"Slot:{Slot} - Region: {Region}");
if (RadioFrequencyMhz != null)
{
_logger.Info($"Radio frequency [MHz]: {RadioFrequencyMhz}");
_logger.Info($"Slot:{Slot} - Radio frequency [MHz]: {RadioFrequencyMhz}");
}
foreach (var fm in MeterAppListVersion.OrderBy(o => o.AppId))
{
var versionString = fm.IsInstalled
? $"V: {fm.StrVersion} - CRC: 0x{fm.Crc:X4}" : "Not installed";
_logger.Info($"AppId: 0x{fm.AppId:X2} - {versionString} - AppName: {fm.AppName}");
_logger.Info($"Slot:{Slot} - AppId: 0x{fm.AppId:X2} - {versionString} - AppName: {fm.AppName}");
}
_logger.Info($"Meter size: {MeterSize}");
_logger.Info($"Upgrade permission: {MetrologyUpgradePermission:X2}");
_logger.Info($"Slot:{Slot} - Meter size: {MeterSize}");
_logger.Info($"Slot:{Slot} - Upgrade permission: {MetrologyUpgradePermission:X2}");
//remove unused registers with invalid version
var tempConfigRegisters = _configRegister.MeterRegisterDic.ToList();
@ -1460,7 +1460,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
catch (Exception ex)
{
_logger.Warn(ex, $"Not able to set minimum list of registers. check json file for {checkMinRegister} ");
_logger.Warn(ex, $"Slot:{Slot} - Not able to set minimum list of registers. check json file for {checkMinRegister} ");
}
}
}
@ -1732,7 +1732,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// - PcbId handling improved,
/// - Removed retries as these are handled by the protocol.
/// </remarks>
public String GetPcbId(Int32 expectedLength = 12)
public String GetPcbId()
{
if (RequestPort == null)
@ -1745,7 +1745,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
_logger.Info($"Slot:{Slot} - Old PCB identification was {PcbId}");
var pcbIdRaw = ReadRegister(Register.Configexchange.PcbSerialNumber, expectedLength);
var pcbIdRaw = ReadRegister(Register.Configexchange.PcbSerialNumber);
if (pcbIdRaw != null)
{
PcbId = Encoding.ASCII.GetString(pcbIdRaw).Split('\0')[0];
@ -1834,16 +1834,18 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
var regDef = _configRegister.GetRegisterDefinitionByName(reg);
var data = RegisterConverter.ConvertFrom(value);
_logger.Info($"Slot:{Slot} - Write register({regDef.RegisterName}), " +
$"record({BitConverter.ToString(data.ToArray())})");
var hideDataInLog = regDef.RegisterName.Contains("EncryptionKey") || regDef.RegisterName.Contains("Password");
var rawMsg = hideDataInLog ? "(*****)" : $"({BitConverter.ToString(data.ToArray())})";
_logger.Info($"Slot:{Slot} - Write register({regDef.GetIdent()}), record({rawMsg})");
PreRegisterWrite(regDef, data);
var command = data.Length > RegisterDefinition.ChunkSize ?
Commands.MultipleWriteData : Commands.WriteData;
var responseRecord = RequestProtocol.CommandToMeter(command, regDef, data,
skipRetryErrorCode: skipRetryErrorCode);
var responseRecord = RequestProtocol.CommandToMeter(command, regDef, data,
hideDataInLog: hideDataInLog, skipRetryErrorCode: skipRetryErrorCode);
if (!waitForResult && !checkRegister)
{
@ -1871,7 +1873,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
}
catch (Exception e)
{
_logger.Error(e);
_logger.Error($"Slot:{Slot} - {e}");
}
return false;
@ -1892,17 +1894,26 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
var regDef = _configRegister.GetRegisterDefinitionByName(reg);
_configRegister.Set(regDef, null);
_logger.Info($"Slot:{Slot} - Read register({regDef.RegisterName})");
_logger.Info($"Slot:{Slot} - Read register({regDef.GetIdent()})");
if (!expectedLength.HasValue || expectedLength.Value <= RegisterDefinition.ChunkSize)
var hideDataInLog = regDef.RegisterName.Contains("EncryptionKey");
// setup length based on data type
if (!expectedLength.HasValue)
{
RequestProtocol?.CommandToMeter(Commands.ReadData, regDef,
expectedLength = RegisterConverter.SizeOf(regDef);
}
var dataLengthPreset = expectedLength.Value;
if (expectedLength.Value <= RegisterDefinition.ChunkSize)
{
RequestProtocol?.CommandToMeter(Commands.ReadData, regDef, hideDataInLog: hideDataInLog,
skipRetryErrorCode: skipRetryErrorCode);
}
else
{
RequestProtocol?.CommandToMeter(Commands.MultipleReadData, regDef, expectedLength: expectedLength,
skipRetryErrorCode: skipRetryErrorCode);
RequestProtocol?.CommandToMeter(Commands.MultipleReadData, regDef, expectedLength: dataLengthPreset,
hideDataInLog: hideDataInLog, skipRetryErrorCode: skipRetryErrorCode);
}
RequestProtocolProcess();
@ -1912,7 +1923,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
}
catch (Exception e)
{
_logger.Error(e);
_logger.Error($"Slot:{Slot} - {e}");
}
return null;
@ -1962,10 +1973,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// - Initial
/// </remarks>
// ReSharper disable once InconsistentNaming UI1236 is a naming forced by the caller
public Byte[] SendUI1236Command(Byte[] ui1236Frame, Boolean waitForResult = true, Boolean checkRegister = false, UInt16 skipRetryErrorCode = 4)
public Byte[] SendUI1236Command(Byte[] ui1236Frame, Boolean waitForResult = true, Boolean checkRegister = false,
UInt16 skipRetryErrorCode = 4)
{
_logger.Info($"Slot:{Slot} - Sending Ui-1236 frame: {ui1236Frame} ");
var sendFifoUi1236 = RequestProtocol.AddRecordToSendFifoUI1236(ui1236Frame);
var requestIdent = $"Slot:{Slot} - Sending Ui-1236 frame";
_logger.Info(requestIdent);
var sendFifoUi1236 = RequestProtocol.AddRecordToSendFifoUI1236(requestIdent, ui1236Frame);
RequestProtocolProcess();
return sendFifoUi1236.ResponsePayload.ToArray();
}
@ -2051,16 +2064,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
public void WriteLog(String text)
{
_logger.Info($"Slot:{Slot} - {text}");
//if (_enableRawDataLogging)
//{
// if (_loggerRawData == null)
// {
// _loggerRawData = NLogHelper.CreateOrGetMultiLogger(
// StreamingPort.GetPortName(), "", "LedRawData", "TargetLedRawDataBase", "LedRawDataBase");
// }
// _loggerRawData.Info($"{text}");
//}
}
/// <inheritdoc />
@ -2210,7 +2213,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
// Wait for storing
Thread.Sleep(500);
//TODO enable this for R1.2.x
//TODO enable this for R1.2.x take the version of FW
if (a.Key.AppName == "SENSUSRADIO" || a.Key.AppName == "NA2WALARMS")
{
done = true;
@ -2307,7 +2310,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
}
catch (Exception ex)
{
_logger.Error(ex, "Can't store at RegisterWatchService");
_logger.Error($"Slot:{Slot} - {ex} - Can't store at RegisterWatchService");
}
}
@ -2337,13 +2340,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
if (!result)
{
_logger.Error(new Exception($"HTTP status not OK"),
_logger.Error(new Exception($"Slot:{Slot} - HTTP status not OK"),
"Can't store at RegisterWatchService");
}
}
catch (Exception ex)
{
_logger.Error(ex, "Can't store at RegisterWatchService");
_logger.Error($"Slot:{Slot} - {ex} - Can't store at RegisterWatchService");
}
}
}
@ -2384,12 +2387,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Accepted)
{
_logger.Error(new Exception($"HTTP status not OK({response.StatusCode})"), "can not store at RegisterWatchService");
_logger.Error(new Exception($"Slot:{Slot} - HTTP status not OK({response.StatusCode})"), "can not store at RegisterWatchService");
}
}
catch (Exception ex)
{
_logger.Error(ex, "can not store at RegisterWatchService");
_logger.Error($"Slot:{Slot} - {ex} - can not store at RegisterWatchService");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -175,7 +175,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// </remarks>
public RequestAcknowledgeState ProcessRecordList()
{
_logger.Trace($" Enry to ProcessRecordList, FIFO contains ({_recordsSendFifo.Count}) records");
_logger.Trace($"{_ident} Entry to ProcessRecordList, FIFO contains ({_recordsSendFifo.Count}) records");
//The inter record send delay has to be hold before trying to communicate again
const Int32 interRecordSendDelayMs = CommunicationConfig.InterRecordSendDelayMs;
@ -188,27 +188,28 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
{
// Starting with record number 1
loopCounter++;
_logger.Trace($"Record({loopCounter}) - Dequeued from FIFO");
_logger.Trace($"{_ident} Record({loopCounter}) - Dequeued from FIFO");
//pointer to new record
_recordInProcess = internalRecord;
if (_recordInProcess == null) return RequestAcknowledgeState.CommandNotAssigned;
if (_recordInProcess == null)
return RequestAcknowledgeState.CommandNotAssigned;
//mark record as answer outstanding
_recordInProcess.Acknowledge = RequestAcknowledgeState.NotDecoded;
do
{
_logger.Trace($"Record({loopCounter}) - Processing");
_logger.Trace($"{_ident} Record({loopCounter}) - Processing");
//log retries
if (_recordInProcess.RetryCtr > 0)
{
_logger.Debug($"{_ident} Retry({_recordInProcess.RetryCtr})");
_logger.Trace($"Record({loopCounter}) - Retry({_recordInProcess.RetryCtr})");
_logger.Trace($"{_ident} Record({loopCounter}) - Retry({_recordInProcess.RetryCtr})");
}
//log request protocol content
_logger.Debug(_recordInProcess.HideDataInLog
? $"{_ident} SentData(*********************************)"
? $"{_ident} SentData(*****)"
: $"{_ident} SentData({BitConverter.ToString(_recordInProcess.RequestProtocolData.ToArray())})");
//remind time for keep-session-active test to deny automatic logout of meter
@ -220,7 +221,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
CommunicationConfig.ResponseTimeoutMs * (_recordInProcess.RetryCtr + 1);
//start initial communication or retry
OnRecordReadyToSend?.Invoke(this, new ListBytePortDataEventArgs(_recordInProcess.EncodedRequestData));
//time reminder of request record
var requestTimeUtc = DateTimeOffset.UtcNow;
Int32 actualResponseWaitTimeMs;
@ -319,7 +320,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
//encode request protocol data with transmit protocol
var transmit = GetTransmitProtocol();
var dataEncodedWithTransmitProtocol = transmit.DecodeDataForPhysicalLayer(cmd, payload, hideDataInLog);
var dataEncodedWithTransmitProtocol = transmit.DecodeDataForPhysicalLayer(_ident, cmd, payload, hideDataInLog);
//remind port specific response timeout
var transmitPortSettings = transmit.GetTransmitPortSettings();
@ -339,13 +340,14 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// <remarks date="2022-Aug-24" author="R.Drabesch">
/// - Initial
/// </remarks>
/// <param name="ident">string for logging of slot</param>
/// <param name="payload">Data package with all details like CRC, etc</param>
/// <param name="register"><see cref="RegisterDefinition" /> which is intend</param>
/// <param name="hideDataInLog">hiding data in log file to avoid spying of passwords</param>
/// <param name="skipRetryErrorCode">error mask to skip retries</param>
/// <returns>the assembled record for the send FIFO</returns>
// ReSharper disable once InconsistentNaming UI1236 is a naming forced by the caller
public RequestRecord AddRecordToSendFifoUI1236(Byte[] payload, RegisterDefinition register = null,
public RequestRecord AddRecordToSendFifoUI1236(String ident, Byte[] payload, RegisterDefinition register = null,
Boolean hideDataInLog = false, UInt16 skipRetryErrorCode = CommunicationConfig.SkipRetryErrorCode)
{
const Byte maxValue = byte.MaxValue;
@ -355,9 +357,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
};
requestProtocolData.AddRange(payload);
var transmitProtocol = GetTransmitProtocol();
var encodedRequestData = transmitProtocol.DecodeDataForPhysicalLayerUI1236(payload);
var encodedRequestData = transmitProtocol.DecodeDataForPhysicalLayerUI1236(ident, payload, hideDataInLog);
var transmitPortSettings = transmitProtocol.GetTransmitPortSettings();
var sendFifoUi1236 = new RequestRecord(maxValue, requestProtocolData, encodedRequestData,
var sendFifoUi1236 = new RequestRecord(maxValue, requestProtocolData, encodedRequestData,
transmitPortSettings.ResponseTimeoutMs, register, hideDataInLog, skipRetryErrorCode);
_recordsSendFifo.Enqueue(sendFifoUi1236);
return sendFifoUi1236;
@ -407,13 +409,18 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// - Wakeup message retries from 5 to 2,
/// - Removed error base from error code decision as error base is only the AppId
/// </remarks>
/// <remarks date="2023-Sep-01" author="T.Wiedebusch">
/// - HideDataInLog.
/// </remarks>
protected override void DecodeRecord(IPortDataEventArgs data)
{
if (_recordInProcess == null) return;
if (_recordInProcess == null)
return;
//new request has to be analyzed
_recordInProcess.Acknowledge = RequestAcknowledgeState.NotDecoded;
//the request response record covers the entire request protocol
var responseRecord = GetTransmitProtocol().DecodeDataForLogicLayer((List<Byte>)data.GetData());
var responseRecord = GetTransmitProtocol().DecodeDataForLogicLayer(_ident, (List<Byte>)data.GetData(),
_recordInProcess.HideDataInLog);
//on protocol decoding failure
if (responseRecord.Count == 0)
@ -442,7 +449,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
{
_recordInProcess.Acknowledge = RequestAcknowledgeState.WakeupMessage;
//initiate a single retry on wakeup message response
if ( _recordInProcess.WakeupMessageRetryCtr < 2)
if (_recordInProcess.WakeupMessageRetryCtr < 2)
{
_recordInProcess.WakeupMessageRetryCtr++;
_logger.Debug($"{_ident} Wakeup message({_recordInProcess.WakeupMessageRetryCtr}) received");
@ -465,7 +472,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
//log request protocol content
_logger.Debug(_recordInProcess.HideDataInLog
? $"{_ident} DecodedRecord(*********************************)"
? $"{_ident} DecodedRecord(*****)"
: $"{_ident} DecodedRecord({BitConverter.ToString(responseRecord.ToArray())})");
//extract information command
@ -586,57 +593,32 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// <remarks date="2019-Jan-18" author="T.Wiedebusch">
/// - Default <see cref="CommunicationConfig.SkipRetryErrorCode"/> set.
/// </remarks>
/// <remarks date="2023-Sep-06" author="T.Wiedebusch">
/// - MultipleReadData based on data size.
/// </remarks>
public RequestRecord CommandToMeter(Byte command, RegisterDefinition meterRegister = null,
Byte[] payload = null, Int32? expectedLength = null, Boolean hideDataInLog = false,
Byte[] payload = null, Int32 expectedLength = 4, Boolean hideDataInLog = false,
UInt16 skipRetryErrorCode = CommunicationConfig.SkipRetryErrorCode)
{
if (command == Commands.MultipleReadData && meterRegister != null && meterRegister.DataType == typeof(String))
{
var completeResponse = new List<Byte>();
//TODO THW check this including the recursive call CommandToMeter
while (true)
while (!completeResponse.Contains(0))
{
var cRecord = CommandToMeter(Commands.ReadData, meterRegister, payload, expectedLength,
hideDataInLog, skipRetryErrorCode);
var cRecord = CommandToMeter(Commands.ReadData, meterRegister, payload, 4, hideDataInLog,
skipRetryErrorCode);
var rest = ProcessRecordList();
if (rest == RequestAcknowledgeState.Ok && cRecord != null && cRecord.ResponsePayload != null)
if (rest == RequestAcknowledgeState.Ok && cRecord?.ResponsePayload != null)
{
completeResponse.AddRange(cRecord.ResponsePayload);
if (cRecord.ResponsePayload.Contains(0))
{
cRecord.ResponsePayload = completeResponse;
OnMeterRegisterUpdated?.Invoke(this, new RegisterUpdatedEventArgs(meterRegister, completeResponse.ToArray()));
if (expectedLength.HasValue && completeResponse.Count < expectedLength.Value)
{
_logger.Debug("Too Short. Payload contains zero");
}
OnMeterRegisterUpdated?.Invoke(this,
new RegisterUpdatedEventArgs(meterRegister, completeResponse.ToArray()));
return cRecord;
}
}
else
{
if (expectedLength.HasValue && completeResponse.Any() && completeResponse.Count < expectedLength.Value)
{
if (rest != RequestAcknowledgeState.Ok)
{
_logger.Debug($"Too Short.Request Acknowledge State is {rest}");
}
else if (cRecord == null)
{
_logger.Debug("Too Short.Record is empty or null");
}
else if (cRecord.ResponsePayload == null)
{
_logger.Debug("Too Short.ResponsePayload is empty or null");
}
else
{
_logger.Debug("Too Short.Unkown reason");
}
}
return cRecord;
}
}
}
//the minimum payload is one 4 byte chunk
@ -681,20 +663,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
if (command == Commands.MultipleReadData)
{
//TODO THW create expected size out of meterRegister.DataType
if (!expectedLength.HasValue)
{
if ((meterRegister.DataType == typeof(UInt64) || meterRegister.DataType == typeof(Int64)))
{
expectedLength = 8;
}
else
{
expectedLength = 24;
}
}
var numberOfChunks = (UInt16)(expectedLength.Value / chunkSize);
var numberOfChunks = (UInt16)(expectedLength / chunkSize);
if (expectedLength % chunkSize != 0)
numberOfChunks++;
requestProtocol.Add((Byte)(numberOfChunks & 0xFF));
@ -753,7 +722,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// <returns></returns>
public Boolean ContainsRegisterIdent(String registerName)
{
return _recordsSendFifo.Any(a => string.Equals(a.Register.GetIdent(),
return _recordsSendFifo.Any(a => string.Equals(a.Register.GetIdent(),
registerName, StringComparison.CurrentCultureIgnoreCase));
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes
{
public struct UInt128
{
}
}

View File

@ -1,6 +1,8 @@
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes
using System;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes
{
public class UInt96
public struct UInt96
{
}
}

View File

@ -12,31 +12,46 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
public static class RegisterConverter
{
/// <summary>
/// Convert single register from Genesis and return a message of the result.
/// Convert single register from Genesis and return a message of the result. The value input is a byte array
/// with the LSB at the index 0 and the MSB at the highest index. A string is sorted with the first character
/// at index 0, this does not need to be reversed as it is readable by default.
/// The raw value is swapped byte-wise to get a human readable value with MSB at leftmost and LSB at rightmost.
/// The message contains the swapped raw value and the converted value.
/// The message contains the register name, the swapped raw value and on the converted value.
/// </summary>
/// <returns>message with register name, swapped raw value and converted value to use for logging</returns>
/// <param name="registerDefinition"></param>
/// <param name="regRawByteArray">the raw byte array is always % 4 0 padded for unused elements, the LSB is
/// on index 0 (little endian, LSB first)</param>
/// <returns>message with register name, swapped raw value and converted value</returns>
/// <remarks date="2023-Jul-19" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static String GetRegisterParameterInfo(MeterRegisters registersDefinitions, String registerName,
Byte[] registerValue)
/// <remarks date="2023-Sep-05" author="Thomas Wiedebusch">
/// - Reworked.
/// </remarks>
public static String GetRegisterContent(RegisterDefinition registerDefinition, Byte[] regRawByteArray)
{
String msg;
var strValueResult = "?";
var strRawResult = "?";
try
{
// build value for logging
var regDef = registersDefinitions.GetRegisterDefinitionByName(registerName);
var strValue = ConvertToText(registerValue, regDef.DataType);
// remove non printable char
// getting a result value as text of the data type e.g. UInt32
var strValue = ConvertToText(regRawByteArray, registerDefinition.DataType);
// remove non printable char of the converted result
strValueResult = Regex.Replace(strValue, @"\p{C}+", string.Empty);
// inverse the raw value to get a readable byte order MSB left and LSB last right position
var tmpList = registerValue.ToList();
tmpList.Reverse();
var tmpList = regRawByteArray.ToList();
// reverse the list if it is not a string or the UInt96 or UInt128 which will be used as
// placeholder for a string
if (registerDefinition.DataType != typeof(String) &&
registerDefinition.DataType != typeof(UInt96) &&
registerDefinition.DataType != typeof(UInt128))
{
tmpList.Reverse();
}
strRawResult = BitConverter.ToString(tmpList.ToArray());
}
@ -46,7 +61,51 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
}
finally
{
msg = $"{registerName} - {strRawResult} - {strValueResult}";
msg = $"{registerDefinition.GetIdent()} - {strRawResult} - {strValueResult}";
}
return msg;
}
/// <summary>
/// Convert single register from Genesis and return a message of the result. The value input is a byte array
/// with the LSB at the index 0 and the MSB at the highest index. A string is sorted with the first character
/// at index 0, this does not need to be reversed as it is readable by default.
/// The raw value is swapped byte-wise to get a human readable value with MSB at leftmost and LSB at rightmost.
/// The message contains the swapped raw value.
/// </summary>
/// <param name="registerDefinition"></param>
/// <param name="regRawByteArray">the raw byte array is always % 4 0 padded for unused elements, the LSB is
/// on index 0 (little endian, LSB first)</param>
/// <returns>message with swapped raw value</returns>
/// <remarks date="2023-Sep-05" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static String GetRegisterRawText(RegisterDefinition registerDefinition, Byte[] regRawByteArray)
{
String msg;
var strRawResult = "?";
try
{
// inverse the raw value to get a readable byte order MSB left and LSB last right position
var tmpList = regRawByteArray.ToList();
// reverse the list if it is not a string or the UInt96 or UInt128 which will be used as
// placeholder for a string
if (registerDefinition.DataType != typeof(String) &&
registerDefinition.DataType != typeof(UInt96) &&
registerDefinition.DataType != typeof(UInt128))
{
tmpList.Reverse();
}
strRawResult = BitConverter.ToString(tmpList.ToArray());
}
catch (Exception)
{
// nothing to do
}
finally
{
msg = $"{strRawResult}";
}
return msg;
@ -150,10 +209,69 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
}
/// <summary>
/// Giving types not generic and returns string
/// Get size of type
/// </summary>
/// <param name="value">byte value for conversion</param>
/// <param name="type">Type to cast from</param>
/// <param name="registerDefinition"></param>
/// <returns>size in bytes</returns>
/// <remarks date="2023-Sep-05" author="Thomas Wiedebusch">
/// - Init.
/// </remarks>
public static Int32 SizeOf(RegisterDefinition registerDefinition)
{
var size = 4;
if (registerDefinition.DataType == typeof(Boolean))
{
size = sizeof(Boolean);
}
if (registerDefinition.DataType == typeof(Byte) ||
registerDefinition.DataType == typeof(SByte) ||
registerDefinition.DataType == typeof(Char) ||
registerDefinition.DataType == typeof(Enum8) )
{
size = sizeof(Byte);
}
else if (registerDefinition.DataType == typeof(Int16) ||
registerDefinition.DataType == typeof(UInt16))
{
size = sizeof(Int16);
}
else if (registerDefinition.DataType == typeof(Int32) ||
registerDefinition.DataType == typeof(UInt32) ||
registerDefinition.DataType == typeof(TimeT))
{
size = sizeof(Int32);
}
else if (registerDefinition.DataType == typeof(Int64) ||
registerDefinition.DataType == typeof(UInt64))
{
size = sizeof(Int64);
}
else if (registerDefinition.DataType == typeof(UInt96))
{
size = 3 * 4;
}
else if (registerDefinition.DataType == typeof(UInt128))
{
size = 4 * 4;
}
else if (registerDefinition.DataType == typeof(String))
{
size = 6 * 4;
}
return size;
}
/// <summary>
/// Build the result of the array as text.
/// </summary>
/// <param name="rawByteArray">byte value for conversion</param>
/// <param name="type">type of the result</param>
/// <returns></returns>
/// <remarks date="????" author="Roland Drabesch">
/// - Init.
@ -162,61 +280,62 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
/// - Used <see cref="TimeT"/> to calculate time in UTC based on 01. Jan 2000
/// and the given offset in seconds.
/// </remarks>
public static String ConvertToText(Byte[] value, Type type)
public static String ConvertToText(Byte[] rawByteArray, Type type)
{
try
{
if (type == typeof(Boolean))
{
return ConvertTo<Boolean>(value).ToString();
return ConvertTo<Boolean>(rawByteArray).ToString();
}
if (type == typeof(TimeT))
{
var teaTime = ConvertTo<TimeT>(value);
var teaTime = ConvertTo<TimeT>(rawByteArray);
return teaTime.ToString();
}
if (type == typeof(UInt16))
{
return ConvertTo<UInt16>(value).ToString();
return ConvertTo<UInt16>(rawByteArray).ToString();
}
if (type == typeof(UInt32))
{
return ConvertTo<UInt32>(value).ToString();
return ConvertTo<UInt32>(rawByteArray).ToString();
}
if (type == typeof(UInt64))
{
return ConvertTo<UInt64>(value).ToString();
return ConvertTo<UInt64>(rawByteArray).ToString();
}
if (type == typeof(Int16))
{
return ConvertTo<Int16>(value).ToString();
return ConvertTo<Int16>(rawByteArray).ToString();
}
if (type == typeof(Int32))
{
return ConvertTo<Int32>(value).ToString();
return ConvertTo<Int32>(rawByteArray).ToString();
}
if (type == typeof(Int64))
{
return ConvertTo<Int64>(value).ToString();
return ConvertTo<Int64>(rawByteArray).ToString();
}
if (type == typeof(Byte) || type == typeof(Enum8))
{
return ConvertTo<Byte>(value).ToString();
return ConvertTo<Byte>(rawByteArray).ToString();
}
if (type == typeof(UInt96))
{
return "";
}
if (type == typeof(UInt128))
{
return "";
}
if (type == typeof(SByte))
{
return ConvertTo<SByte>(value).ToString();
return ConvertTo<SByte>(rawByteArray).ToString();
}
return ConvertTo<String>(value);
return ConvertTo<String>(rawByteArray);
}
catch (Exception)
{
@ -230,7 +349,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
/// convert form byte (meter) to data type
/// </summary>
/// <typeparam name="T">Type to cast in</typeparam>
/// <param name="value">byte value for conversion</param>
/// <param name="rawByteArray">byte value for conversion</param>
/// <returns>converted value</returns>
/// <remarks date="????" author="Roland Drabesch">
/// - Init.
@ -240,7 +359,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
/// and the given offset in seconds.
/// - String removed from first zero in string until the end to avoid ghost signs!
/// </remarks>
public static T ConvertTo<T>(Byte[] value)
public static T ConvertTo<T>(Byte[] rawByteArray)
{
try
{
@ -249,58 +368,65 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
if (type == typeof(Boolean))
{
convertedObj = BitConverter.ToBoolean(value, 0);
convertedObj = BitConverter.ToBoolean(rawByteArray, 0);
}
else if (type == typeof(UInt16))
{
convertedObj = BitConverter.ToUInt16(value, 0);
convertedObj = BitConverter.ToUInt16(rawByteArray, 0);
}
else if (type == typeof(UInt32))
{
convertedObj = BitConverter.ToUInt32(value, 0);
convertedObj = BitConverter.ToUInt32(rawByteArray, 0);
}
else if (type == typeof(UInt64))
{
convertedObj = BitConverter.ToUInt64(value, 0);
convertedObj = BitConverter.ToUInt64(rawByteArray, 0);
}
else if (type == typeof(UInt96))
{
return default(T);
}
else if (type == typeof(UInt128))
{
return default(T);
}
else if (type == typeof(Int16))
{
convertedObj = BitConverter.ToInt16(value, 0);
convertedObj = BitConverter.ToInt16(rawByteArray, 0);
}
else if (type == typeof(Int32))
{
convertedObj = BitConverter.ToInt32(value, 0);
convertedObj = BitConverter.ToInt32(rawByteArray, 0);
}
else if (type == typeof(Int64))
{
convertedObj = BitConverter.ToInt64(value, 0);
convertedObj = BitConverter.ToInt64(rawByteArray, 0);
}
else if (type == typeof(Byte) || type == typeof(Enum8))
{
convertedObj = value[0];
convertedObj = rawByteArray[0];
}
else if (type == typeof(SByte))
{
// set all others to 0 as only the LSB is of interest
for (var idx = 1; idx < value.Length; idx++)
value[idx] = 0;
convertedObj = Convert.ToSByte((SByte)value[0]);
for (var idx = 1; idx < rawByteArray.Length; idx++)
rawByteArray[idx] = 0;
convertedObj = Convert.ToSByte((SByte)rawByteArray[0]);
}
else if (type == typeof(Boolean))
{
convertedObj = Convert.ToBoolean(value[0]);
convertedObj = Convert.ToBoolean(rawByteArray[0]);
}
else if (type == typeof(String))
{
// the value may contain zeros at the beginning of the value-record, these have to be removed
var zeroPaddingCounter = 0;
while (value.Length > zeroPaddingCounter && value[zeroPaddingCounter] == 0)
while (rawByteArray.Length > zeroPaddingCounter && rawByteArray[zeroPaddingCounter] == 0)
zeroPaddingCounter += 1;
var trimmedValue = new Byte[value.Length - zeroPaddingCounter];
var trimmedValue = new Byte[rawByteArray.Length - zeroPaddingCounter];
Int32 i;
for (i = 0; i < value.Length - zeroPaddingCounter; i++)
trimmedValue[i] = value[i + zeroPaddingCounter];
for (i = 0; i < rawByteArray.Length - zeroPaddingCounter; i++)
trimmedValue[i] = rawByteArray[i + zeroPaddingCounter];
// as a string is terminated with a zero all following elements after including the initial
// zero have to be removed. This is caused due to the 4 byte chunks which will be sent.
@ -325,7 +451,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
else if (type == typeof(TimeT))
{
// the value contains always the seconds since 01.Jan 2000
var teaTime = new TimeT { SecondsSince2000 = ConvertTo<Int32>(value) };
var teaTime = new TimeT { SecondsSince2000 = ConvertTo<Int32>(rawByteArray) };
return (T)Convert.ChangeType(teaTime, typeof(TimeT));
}
else

View File

@ -26,6 +26,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>7.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -35,6 +36,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>7.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == '_MANUAL_CONTROL|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
@ -45,6 +47,7 @@
<LangVersion>7.0</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
@ -55,6 +58,7 @@
<LangVersion>7.0</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
@ -65,6 +69,7 @@
<LangVersion>7.0</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == '_MANUAL_CONTROL|x64'">
<DebugSymbols>true</DebugSymbols>
@ -75,6 +80,7 @@
<LangVersion>7.0</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
@ -101,6 +107,7 @@
<Compile Include="DataTypes\st_radio_dewa.cs" />
<Compile Include="DataTypes\st_radio_tfx.cs" />
<Compile Include="DataTypes\TimeT.cs" />
<Compile Include="DataTypes\UInt128.cs" />
<Compile Include="DataTypes\UInt96.cs" />
<Compile Include="Json\AppSection.cs" />
<Compile Include="Json\FwVersion.cs" />

View File

@ -986,7 +986,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore
/// <inheritdoc/>>
public String GetPcbId(Int32 expectedLength = 12)
public String GetPcbId()
{
if (!string.IsNullOrEmpty(PcbId) && !string.Equals("?", PcbId))
{

View File

@ -100,9 +100,8 @@ namespace Xylem.Common.Hardware.WaterMeter.WaterMeterCore
/// <summary>
/// Read the PcbId from IMeter, if device has no readable PcbId simulate one
/// </summary>
/// <param name="expectedLength"></param>
/// <returns></returns>
String GetPcbId(Int32 expectedLength = 12);
String GetPcbId();
/// <summary>
/// Open Com ports, try some communication, login

View File

@ -1 +1 @@
89102b0142e574de38a9f47d370f3334e5e6c268
bf6bb8fceb3db5a9977dadc407cf576684bf7127

View File

@ -80,7 +80,7 @@ namespace ProductionUiCordonel.ProductionProcesses.Actions
try
{
//var url = $"http://localhost:56011/api/FinalCheck/GetProgrammingParameters?PcbID={base.Meter.PcbId}";
var url = $"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetProgrammingParametersFixNa";
var url = $"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetProgrammingParameters?PcbID={base.Meter.PcbId}";
var csdRet = LocalWebRequest.GetRequest(url, 80000);

View File

@ -226,6 +226,12 @@ namespace ProductionUiCordonel.ProductionProcesses.Actions
}
}
Meter.ResetAlarm(GenesisMeter.Alarm.ALL);//(true, new byte[] { 0x00, 0x00, 0x00, 0x01 });
Meter.SetLcdText(true, new Byte[] { 0x00, 0x00, 0x00, 0x01 });
Meter.ResetAlarm(GenesisMeter.Alarm.EMPTY_PIPE);//(true, new byte[] { 0x00, 0x00, 0x00, 0x01 });
if (rebootSucceeded && hasDiffrences.HasValue && !hasDiffrences.Value)
{
currentProcessState = ProductionProcessState.Done;

View File

@ -83,7 +83,14 @@
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<SignManifests>true</SignManifests>
<SignManifests>false</SignManifests>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
@ -138,7 +145,6 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<None Include="TempFlansh_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />

View File

@ -1 +1 @@
338bdd8d71c148c9df0972f903098eb23eacf0c9
247396738e2c5d26ac00f9df05c0cc5c61d7f33a

View File

@ -1,4 +1,7 @@
using System;
using Logic.ProductionToProductMapper.Cordonel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
@ -9,15 +12,13 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Logic.ProductionToProductMapper.Cordonel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Logic.SoftwareAccessHelper;
using Xylem.Common.Utils.ProcessExec.EventArguments;
using String = System.String;
@ -223,7 +224,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void SetControlsLowLevelOpIsFinished()
{
if (_currentGenesis != null)
{
_currentGenesis.RequestProtocol.AdditionalRetryTimeoutMs = 0;
}
SetCordonelAccessEnabled();
}
@ -507,7 +511,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void LogInstalledMeterFw()
{
if (_currentGenesis == null)
{
return;
}
LogText(StrSeparator);
LogText($"PCB ID: {_currentGenesis.PcbId}");
LogText($"Core Version: {GenesisMeter.BuildFwVersionString(_currentGenesis.CoreRevision)}");
@ -545,7 +552,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void LogPcAndCordonelTime()
{
if (_currentGenesis == null)
{
return;
}
_currentGenesis.ReLogin();
var dt = DateTime.UtcNow;
@ -591,8 +601,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
_frmHistory.rtbHistory.Invoke(new Action(() => { _frmHistory.rtbHistory.Clear(); }));
}
else
{
_frmHistory?.rtbHistory.Clear();
}
}
/// <summary>
@ -648,7 +659,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void InfoWindowColoredText(String txtHistory, Color color)
{
if (_frmHistory?.rtbHistory == null)
{
return;
}
Invoke(new Action(() =>
{
_frmHistory.rtbHistory.SuspendLayout();
@ -721,7 +735,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
return fileNames;
}
/// <summary>
/// Read engineering log files from meter and analyzes the contents.
/// </summary>
@ -731,20 +745,29 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void ReadLogFiles(String logFileName = null)
{
if (_currentGenesis == null)
{
return;
}
if (_meterFile == null)
{
_meterFile = new MeterFile(_currentGenesis);
}
var statusMap = new Dictionary<Int32, String>();
if (File.Exists("Status.json"))
{
var dict = JsonConvert.DeserializeObject<Dictionary<String, JObject>>(File.ReadAllText("Status.json"));
if (dict != null)
{
foreach (var item in dict)
{
if (item.Value.First != null)
{
statusMap.Add(int.Parse(item.Value.First.Values().First().ToString()), item.Key);
}
}
}
}
Task.Factory.StartNew(() =>
@ -814,7 +837,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
ctr += (5 + extraDataSize);
//exit if index for next run is out of range
if (ctr + 5 >= data.Count)
{
break;
}
}
}
else
@ -831,7 +856,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
});
}
/// <summary>
/// <summary>
/// List all meter log files covered by the log index file
/// </summary>
/// <remarks date="2023-Jan-14" author="Thomas Wiedebusch">
@ -877,7 +902,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void AnalyzeMeterFiles(List<String> meterFiles)
{
if (meterFiles.Count == 0)
{
return;
}
LogText("Analyzing meter files");
foreach (var fileName in meterFiles)
@ -889,7 +916,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
? $@"File name: {fileName}, File size: {fileSize} byte"
: $@"File name: {fileName} Unable to access file");
if (success)
{
continue;
}
_currentGenesis.Logout();
_currentGenesis.ReLogin();
}
@ -1027,7 +1057,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnClearDisplay_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
SetActualProcessAndLog(@"Set display of meter to normal operation");
@ -1055,7 +1087,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnFixBattery_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
@ -1102,7 +1136,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnStoreConfiguration_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
@ -1181,9 +1217,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
if (_currentGenesis == null)
{
return;
}
if (_meterFile == null)
{
_meterFile = new MeterFile(_currentGenesis);
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
@ -1211,7 +1252,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
var fs = new FileStream(saveConfigFile.FileName, FileMode.OpenOrCreate);
var bw = new BinaryWriter(fs);
foreach (var t in rawData)
{
bw.Write(t);
}
fs.Close();
}
}));
@ -1234,7 +1278,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnSetDateTime_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
var msg = @"Set actual PC date and time in UTC";
LogText(msg);
@ -1280,9 +1326,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnReadLogFiles_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
if (_meterFile == null)
{
_meterFile = new MeterFile(_currentGenesis);
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
@ -1306,15 +1357,21 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnReadLogFilesBattery_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
if (_meterFile == null)
{
_meterFile = new MeterFile(_currentGenesis);
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
LowLevelActionControl(true);
var msg = @"Collect all information";
LogText(msg);
lblOverall.Text = msg;
@ -1345,13 +1402,37 @@ namespace Xylem.Common.Ui.GenesisToolBox
sbMSG.AppendLine($"Remaining life time in years {genesisStatus.RemainingLifeTimeYears:F2}");
sbMSG.AppendLine($"Totally drained battery load in % {genesisStatus.DrainedBatteryLoadPercent:F2}");
MessageBox.Show(sbMSG.ToString(), $"Battery for {_currentGenesis.PcbId} has remaining life " +
$"time of {genesisStatus.RemainingLifeTimeYears:F2} years");
LogText(sbMSG.ToString(), filename);
}
ReadLogFiles(filename);
var resp = LocalWebRequest.GetRequest($"http://10.49.40.25/MeterProcessState/api/FinalCheck/GetKitronProductionResults?PcbID={_currentGenesis.PcbId}", 8000);
LogText(resp, filename);
var sbRegister = new StringBuilder();
var Ledmode = RegisterConverter.ConvertTo<UInt16>(_currentGenesis.ReadRegister("GENESISFLOW_LedMode"));
var SampleRate = RegisterConverter.ConvertTo<UInt16>(_currentGenesis.ReadRegister("GENESISFLOW_SampleRate"));
sbRegister.AppendLine($"LedMode is {Ledmode}");
sbRegister.AppendLine($"SampelRate is {SampleRate}");
if (Ledmode != 0)
{
_currentGenesis.WriteRegister("GENESISFLOW_LedMode", 0);
sbRegister.AppendLine($"Change Led mode to Customermode (0)");
}
if (SampleRate != 2)
{
_currentGenesis.WriteRegister("GENESISFLOW_SampleRate", 2);
sbRegister.AppendLine($"Change SampleRate mode to Customermode (2)");
}
}
@ -1364,9 +1445,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnListFileDetails_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
if (_meterFile == null)
{
_meterFile = new MeterFile(_currentGenesis);
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
@ -1407,9 +1493,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnTidyFile_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
if (_meterFile == null)
{
_meterFile = new MeterFile(_currentGenesis);
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
@ -1463,7 +1554,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
foreach (var fileToKeep in filesToKeep)
{
if (meterFile.Contains(fileToKeep))
{
fileEraseCandidates.Remove(meterFile);
}
}
}
// check if something to clean
@ -1486,7 +1579,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
: $@"File {fileToErase} erasure failed");
if (success)
{
continue;
}
_currentGenesis.Logout();
_currentGenesis.ReLogin();
}
@ -1516,9 +1612,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnEraseFile_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
if (_meterFile == null)
{
_meterFile = new MeterFile(_currentGenesis);
}
//reset timer
_startTime = DateTimeOffset.UtcNow;
@ -1576,7 +1677,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void btnPulseModeOff_Click(Object sender, EventArgs e)
{
if (_currentGenesis == null)
{
return;
}
//reset timer
_startTime = DateTimeOffset.UtcNow;

View File

@ -41,7 +41,7 @@
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>7.0</LangVersion>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Xylem.Common.Ui.GenesisToolBox.xml</DocumentationFile>
<NoWarn>0003;1591;</NoWarn>
</PropertyGroup>
@ -55,6 +55,7 @@
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>7.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PerformTest|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
@ -66,6 +67,7 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
<LangVersion>7.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == '_MANUAL_CONTROL|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
@ -77,6 +79,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>14673934DFE995F28E9579F4A18DBDA05F7C1AFE</ManifestCertificateThumbprint>
@ -129,6 +132,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PerformTest|x64'">
<DebugSymbols>true</DebugSymbols>
@ -140,6 +144,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == '_MANUAL_CONTROL|x64'">
<DebugSymbols>true</DebugSymbols>
@ -151,6 +156,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="ConfigurationJson, Version=1.0.2.0, Culture=neutral, processorArchitecture=MSIL">

View File

@ -59,6 +59,11 @@
{
UserName = $"{model.FirstName} {model.LastName}";
}
if (string.IsNullOrWhiteSpace(UserName))
{
UserName = "Options";
}
}
/// <summary>
@ -99,6 +104,11 @@
}
}
if (string.IsNullOrWhiteSpace(UserName))
{
UserName = "Options";
}
return HasUser;
}

View File

@ -41,7 +41,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
private MeterBatch _meterBatch = new MeterBatch();
private readonly ILogger logger = NLogHelper.CreateOrGetLogger("GenesisFwLogger");
public Boolean IsBusy { get; private set; }
public Boolean IsBusy
{
get; private set;
}
public FrmRegisterStore()
{
@ -220,14 +223,15 @@ namespace Xylem.Common.Ui.GenesisToolBox
registerGridView.Sort(registerGridView.Columns["isChecked"],
ListSortDirection.Descending);
registerGridView.Columns["RawValueFile"].Visible = false;
registerGridView.Sort(registerGridView.Columns["Name"],
ListSortDirection.Ascending);
var btnHistory = new DataGridViewButtonColumn();
btnHistory.Name = "btnHistory";
btnHistory.DataPropertyName = "btnHistoryText";
this.registerGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { btnHistory });
registerGridView.Columns.AddRange(new DataGridViewColumn[] { btnHistory });
//foreach (DataGridViewRow row in registerGridView.Rows)
@ -270,14 +274,20 @@ namespace Xylem.Common.Ui.GenesisToolBox
Console.WriteLine(value);
Task.Factory.StartNew(() => { read(); }).ContinueWith(delegate { SetBusy(false); });
Task.Factory.StartNew(() => { read(); }).ContinueWith(delegate
{
SetBusy(false);
});
}
private void btnStore_Click(Object sender, EventArgs e)
{
SetBusy(true, "Store to file");
Task.Factory.StartNew(() => { store(); }).ContinueWith(delegate { SetBusy(false); });
Task.Factory.StartNew(() => { store(); }).ContinueWith(delegate
{
SetBusy(false);
});
}
private void btnFileToMeter_Click(Object sender, EventArgs e)
@ -293,7 +303,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
var filename = openFileDialog.FileName;
Task.Factory.StartNew(() => { load(filename); }).ContinueWith(delegate { SetBusy(false); });
Task.Factory.StartNew(() => { load(filename); }).ContinueWith(delegate
{
SetBusy(false);
});
}
}
@ -304,7 +317,10 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
SetBusy(true, "writing register to meter");
Task.Factory.StartNew(() => { WriteRegister(e); }).ContinueWith(delegate { SetBusy(false); });
Task.Factory.StartNew(() => { WriteRegister(e); }).ContinueWith(delegate
{
SetBusy(false);
});
}
}
@ -329,11 +345,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
array[i] = Convert.ToByte(arr[i], 16);
}
array = array.Reverse().ToArray();
// currentGenesis.WriteRegister(Register.Genesisflow.LedMode, (Byte)Ledmode.FlowTestAndCalibData, checkRegister: true);
var regdef =
(String)registerGridView.Rows[e.RowIndex].Cells[0].Value;
_currentGenesis.WriteRegister(regdef, array, checkRegister: true);
var reg = (String)registerGridView.Rows[e.RowIndex].Cells[0].Value;
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
var regDef = meterRegisters.GetRegisterDefinitionByName(reg);
if (regDef.DataType != typeof(String))
array = array.Reverse().ToArray();
_currentGenesis.WriteRegister(reg, array, checkRegister: true);
//_currentGenesis.Logout();
//var funkadresse = new List<byte>();
@ -384,7 +403,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
_meterBatch = new MeterBatch();
var configfile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(Xylem.Common.Hardware.WaterMeter.Genesis), ProgramConfig.SerialConfigFileName);
var configfile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(Hardware.WaterMeter.Genesis), ProgramConfig.SerialConfigFileName);
if (!File.Exists(configfile))
{
@ -432,7 +451,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
Logger.Value.Error(ex, $"Slot #{slotNR} failed: {ex.Message}");
}
_currentGenesis.Login("B507CC0978D6");
_currentGenesis.Login();
_currentPcbId = _currentGenesis.PcbId;
@ -472,7 +491,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
((DataRow)rowItem)["isChecked"] = false;
}
@ -484,7 +503,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
case "All":
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
((DataRow)rowItem)["isChecked"] = true;
}
@ -494,7 +513,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
case "Ampl. Test":
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
if (preSetAmplTest.Any(p => p.Equals(((DataRow)rowItem)["Name"].ToString())))
{
@ -512,7 +531,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
case "Temp. Calibration":
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
if (preSetTempCal.Any(p => p.Equals(((DataRow)rowItem)["Name"].ToString())))
{
@ -530,7 +549,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
case "Zero Flow":
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
if (preSetZeroFlow.Any(p => p.Equals(((DataRow)rowItem)["Name"].ToString())))
{
@ -548,7 +567,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
case "Flow Calibration":
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
if (preSetFlowCalibration.Any(p => p.Equals(((DataRow)rowItem)["Name"].ToString())))
{
@ -565,7 +584,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
case "All Meteorological":
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
if (preSetAllMeteorological.Any(p => p.Equals(((DataRow)rowItem)["Name"].ToString())))
{
@ -583,7 +602,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
case "None":
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
((DataRow)rowItem)["isChecked"] = false;
}
@ -633,11 +652,13 @@ namespace Xylem.Common.Ui.GenesisToolBox
private void read()
{
regsToStore = new regStore()
{ PcbId = _currentPcbId, created = DateTimeOffset.Now, keyValues = new List<regDefValue>() };
{
PcbId = _currentPcbId, created = DateTimeOffset.Now, keyValues = new List<regDefValue>()
};
var total = 0;
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
if ((Boolean)((DataRow)rowItem)["isChecked"])
{
@ -649,7 +670,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
var done = 0;
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
if ((Boolean)((DataRow)rowItem)["isChecked"])
{
@ -658,7 +679,6 @@ namespace Xylem.Common.Ui.GenesisToolBox
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
var regDef = meterRegisters.GetRegisterDefinitionByName(reg);
//var regDef = _currentGenesis.GetRegisterDefinitionByName(reg);
SetProgreess($"Read Register {regDef.RegisterName}", total, done + 1);
if (regDef.RegisterDetail != null && (
regDef.RegisterDetail.Privilege.Lvl8 == Access.RO ||
@ -667,25 +687,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
try
{
Byte[] rawRegister;
if (regDef.DataType == typeof(String) || regDef.DataType == typeof(Int64) ||
regDef.DataType == typeof(UInt64))
{
rawRegister = _currentGenesis.ReadRegister(reg, 8);
}
else
{
rawRegister = _currentGenesis.ReadRegister(reg);
}
rawRegister = _currentGenesis.ReadRegister(reg);
var tmpList = rawRegister.ToList();
tmpList.Reverse();
if (rawRegister != null)
//var temp = RegisterConverter.GetRegisterContent(regDef, rawRegister);
((DataRow)rowItem)["RawValue"] = RegisterConverter.GetRegisterRawText(regDef, rawRegister);
regsToStore.keyValues.Add(new regDefValue
{
((DataRow)rowItem)["RawValue"] = BitConverter.ToString(tmpList.ToArray());
regsToStore.keyValues.Add(new regDefValue()
{ def = regDef, value = BitConverter.ToString(rawRegister) });
}
def = regDef, value = BitConverter.ToString(rawRegister)
});
try
{
@ -732,14 +741,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
SetProgreess($"Read File {filename}");
var text = File.ReadAllText(filename);
var loadedRegStore = Newtonsoft.Json.JsonConvert.DeserializeObject<regStore>(text);
var loadedRegStore = JsonConvert.DeserializeObject<regStore>(text);
var done = 1;
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
SetProgreess($"Read file", loadedRegStore.keyValues.Count, done);
@ -747,7 +756,6 @@ namespace Xylem.Common.Ui.GenesisToolBox
var reg = ((DataRow)rowItem)["Name"].ToString();
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
var regDef = meterRegisters.GetRegisterDefinitionByName(reg);
//var regDef = _currentGenesis.GetRegisterDefinitionByName(reg);
var keyValue =
loadedRegStore.keyValues.FirstOrDefault(f => f.def.RegisterName.Equals(regDef.RegisterName));
@ -759,23 +767,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
regDef.RegisterDetail.Privilege.Lvl8 == Access.RW)
{
Byte[] rawRegister;
if (regDef.DataType == typeof(String) || regDef.DataType == typeof(Int64) ||
regDef.DataType == typeof(UInt64))
{
rawRegister = _currentGenesis.ReadRegister(reg, 12);
}
else
{
rawRegister = _currentGenesis.ReadRegister(reg);
}
rawRegister = _currentGenesis.ReadRegister(reg);
var tmpList = rawRegister.ToList();
tmpList.Reverse();
if (rawRegister != null)
//var temp = RegisterConverter.GetRegisterContent(regDef, rawRegister);
((DataRow)rowItem)["RawValue"] = RegisterConverter.GetRegisterRawText(regDef, rawRegister);
regsToStore.keyValues.Add(new regDefValue
{
((DataRow)rowItem)["RawValue"] = BitConverter.ToString(tmpList.ToArray());
}
def = regDef, value = BitConverter.ToString(rawRegister)
});
try
{
@ -842,14 +841,14 @@ namespace Xylem.Common.Ui.GenesisToolBox
SetProgreess($"Read File {filename}");
var text = File.ReadAllText(filename);
var loadedRegStore = Newtonsoft.Json.JsonConvert.DeserializeObject<regStore>(text);
var loadedRegStore = JsonConvert.DeserializeObject<regStore>(text);
var done = 1;
foreach (var rowItem in _dataTable.Rows)
{
if (rowItem is System.Data.DataRow)
if (rowItem is DataRow)
{
SetProgreess($"Compare file", loadedRegStore.keyValues.Count, done);
@ -1072,7 +1071,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
if (_currentGenesis != null)
{
_currentGenesis.ResetAlarm(GenesisMeter.Alarm.EMPTY_PIPE);
_currentGenesis.ResetAlarm(Alarm.EMPTY_PIPE);
}
}
@ -1081,7 +1080,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
if (_currentGenesis != null)
{
MessageBox.Show(
$@"Check alarm EMPTY_PIPE = {_currentGenesis.HasAlarms(GenesisMeter.Alarm.EMPTY_PIPE)}");
$@"Check alarm EMPTY_PIPE = {_currentGenesis.HasAlarms(Alarm.EMPTY_PIPE)}");
}
}
@ -1092,7 +1091,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
var sb = new StringBuilder();
sb.AppendLine($"PCBID: {_currentGenesis.PcbId}");
sb.AppendLine($"Date: {DateTimeOffset.UtcNow}");
sb.AppendLine($"System Core Revision: {GenesisMeter.BuildFwVersionString(_currentGenesis.CoreRevision)}");
sb.AppendLine($"System Core Revision: {BuildFwVersionString(_currentGenesis.CoreRevision)}");
foreach (var fm in _currentGenesis.MeterAppListVersion.OrderBy(o => o.AppId))
{
var versionString = fm.IsInstalled
@ -1599,9 +1598,19 @@ namespace Xylem.Common.Ui.GenesisToolBox
}
}
private String _preSelectReminder = "None";
private void lblState_Click(Object sender, EventArgs e)
{
selectPreset("All");
if (_preSelectReminder.Contains("None"))
{
_preSelectReminder = "All";
selectPreset("All");
}
else
{
_preSelectReminder = "None";
selectPreset("None");
}
}
private void button1_Click_3(Object sender, EventArgs e)
@ -1915,7 +1924,7 @@ namespace Xylem.Common.Ui.GenesisToolBox
{
getPcbId(slotNR);
var str = Logic.SoftwareAccessHelper.LocalWebRequest.GetRequest($"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetPossibleRadioLengths?CheckPcbId={_currentPcbId}", 15000);
var str = LocalWebRequest.GetRequest($"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetPossibleRadioLengths?CheckPcbId={_currentPcbId}", 15000);
MessageBox.Show(str);
}).ContinueWith(delegate
{

View File

@ -43,7 +43,7 @@ namespace Xylem.Common.Ui.IrdaFunctionalTestApp
Byte command = 0x09;
Byte []payload = {0x0D, 0x0F, 0x00, 0x00, 0x00, 0x00 };
var txBuffer = transmit.DecodeDataForPhysicalLayer(command, payload);
var txBuffer = transmit.DecodeDataForPhysicalLayer(Ident, command, payload);
_irdaComPort.Open();

View File

@ -17,6 +17,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=DNMAX/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Drabesch/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=EMEA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=endian/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLEXNETVERSION/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=GENESISFLOW/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Hannover/@EntryIndexedValue">True</s:Boolean>