diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs index 8256643e..a3ac134b 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs @@ -145,6 +145,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// public Boolean UseOfflinePasswords { set; get; } + /// + /// Remind the offline password for comparison if this is actively used + /// + public String OfflinePassword { protected set; get; } = ""; + /// /// Process configuration /// @@ -1241,6 +1246,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore { Logger.Info($"Slot:{Slot} - Got password from GenesisPasswordService, " + $"URL({ServiceUrls.GenesisGetPasswordServiceUrl() + PcbId})"); + OfflinePassword = ""; } else { @@ -1261,6 +1267,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore if (!string.IsNullOrEmpty(password)) { Logger.Info($"Slot:{Slot} - Got password for PcbId:{PcbId} from password file!"); + OfflinePassword = password; } } diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs index 7cf28d83..92c9a772 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs @@ -70,6 +70,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// /// List for un-reversed parameters which can be written, all others need to be swapped byte-wise /// + //TODO THW take configuration.json and use for String and Array type, see RegisterConverter private static readonly List _unReversedParameters = new List { "SENSUSRADIO_Authentification", //UInt96 @@ -572,6 +573,23 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore } // Take this parameter as is + //TODO THW take configuration.json and use for String and Array type, see RegisterConverter + //take the register properties from configuration.json + //get the pre-defined dictionary + //var meterRegisters = MockGenesis based on FW version .GetConfigRegistersDefinitions(); + //var regDef = meterRegisters.GetRegisterDefinitionByName(proPar.RegisterName); + //if (regDef.DataType.Name.Equals("Int32")) + //{ + // Add parameter if it is not in the list + //if (sortableProgrammingParameters.All(a => !proPar.RegisterName.Equals(a.RegisterName))) + //{ + // sortableProgrammingParameters.Add(proPar); + // continue; + //} + //} + + + if (_unReversedParameters.Contains(proPar.RegisterName)) { // Add parameter if it is not in the list diff --git a/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs b/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs index ff66f008..a30b219a 100644 --- a/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs +++ b/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs @@ -109,6 +109,7 @@ namespace Xylem.Common.Ui.GenesisToolBox SetCordonelAccessLocked(); tbxPcbId.Visible = false; + btnConnect.Focus(); } private void FrmLowLevelTools_Load(Object sender, EventArgs e) @@ -272,7 +273,7 @@ namespace Xylem.Common.Ui.GenesisToolBox try { var sb = new StringBuilder(); - + Invoke(new Action(() => { Init(); @@ -304,6 +305,8 @@ namespace Xylem.Common.Ui.GenesisToolBox Task.Factory.StartNew(() => { + // The password needs to be cleared for recurrent connections as otherwise the last password will be used. + _currentGenesis.ClearPassword(); _currentGenesis.Login(); if (!_currentGenesis.IsLoggedOn && String.IsNullOrEmpty(_currentGenesis.PcbId)) @@ -315,85 +318,132 @@ namespace Xylem.Common.Ui.GenesisToolBox var retValPwdBuild = MeterPwdHandlerDb.RequestPwdFileFromDb(_currentGenesis.PcbId, out var pwdContainer); - // Login failed and password cannot be acquired + // Login failed and password cannot be acquired, there isn't any chance to login without additional info if (!_currentGenesis.IsLoggedOn && (pwdContainer?.ListOfPasswords == null || pwdContainer.ListOfPasswords.Count < 8 || string.IsNullOrEmpty(pwdContainer.Skeleton))) { LowLevelActionControl(false); - LogErrorText("ERROR: Login failed and password file cannot be acquired from database!"); + LogErrorText("ERROR: Login failed and passwords cannot be acquired from database!"); return; } - //TODO THW check all cases if (_currentGenesis.IsLoggedOn) { - // The login succeeded with the 'SkeletonKey' or the password 'Lvl8' or the 'OfflinePassword' - if (retValPwdBuild) + // The login succeeded with the 'SkeletonKey', the 'Lvl8 password' or the 'offline password' + if (retValPwdBuild) // Passwords exist in database { - if (pwdContainer.Password.Equals(Encoding.UTF8.GetString(pwdContainer.ListOfPasswords.Last()))) + // Remind the 'Lvl8 password' from passwords + var pwdLvl8FromPasswords = Encoding.UTF8.GetString(pwdContainer.ListOfPasswords.Last()); + + // Check if the 'offline password' is in use + if (!string.IsNullOrWhiteSpace(_currentGenesis.OfflinePassword)) { - // CASE 1: - The 'production password' is the 'Lvl8 password' as the login succeeded. - LogText(@"Successfully logged in with password Lvl8 and password file okay!"); - } - else if (pwdContainer.Skeleton.Equals(pwdContainer.Password)) + LogText("Successfully logged in with the 'offline password'"); + + if (_currentGenesis.OfflinePassword.Equals(pwdLvl8FromPasswords)) + { + LogText("The 'offline password' is the 'Lvl8 password'"); + if (pwdLvl8FromPasswords.Equals(pwdContainer.Password)) + { + // CASE 1: - The 'offline password' is valid and equals the 'Lvl8 password' and the + // 'production password' + LogText("The 'production password' is the 'Lvl8 password'\n" + + "Installed password file is valid and compared with database"); + } + else + { + // CASE 2: - The 'offline password' is valid and equals the 'Lvl8 password' but the + // 'production password' is not correctly updated + ShowPasswordRepairMessage( + "The 'production password' is not correctly set to the 'Lvl8 password'\n" + + "Installed password file is valid and compared with database\n" + + "[Repair Password] enabled"); + } + } + // CASE 3: - The 'offline password' is valid and equals the 'SkeletonKey' + else if (_currentGenesis.OfflinePassword.Equals(pwdContainer.Skeleton)) + ShowPasswordRepairMessage( + "The 'offline password' is the 'SkeletonKey'\n" + + "Password exists on database but password file not installed'\n" + + "[Repair Password] enabled"); + }// The 'offline password' is in use + else // The 'production password' is in use { - // CASE 2: - Passwords are generated in database but password file is not installed or doesn't work. - // - The 'production password' is the 'SkeletonKey' as the login succeeded. - // - // If password file is initially not installed and the database password returned the SkeletonKey - // the login has been successfully executed with this SkeletonKey, so a repair of the password - // file needs to be enabled! - ShowPasswordRepairMessage(@"Password exists on database but the SkeletonKey is valid" + - " - [Repair Password] enabled"); + if (pwdContainer.Password.Equals(pwdLvl8FromPasswords)) + { + // CASE 4: - The 'production password' is the 'Lvl8 password' as the login succeeded. + LogText( + "Successfully logged in with the 'production password' which equals the 'Lvl8 password'\n" + + "Installed password file is valid and compared with database"); + } + else if (pwdContainer.Password.Equals(pwdContainer.Skeleton)) + { + // If the 'password file' is initially not installed and the 'production password' returned the + // 'SkeletonKey', then the login has been successfully executed with this 'SkeletonKey', + // a repair of the 'password file' needs to be enabled! + + // CASE 5: - The 'production password' is the 'SkeletonKey' as the login succeeded. + ShowPasswordRepairMessage( + "Successfully logged in with the 'production password' which equals the 'SkeletonKey'\n" + + "Password exists on database but password file not installed'\n" + + "[Repair Password] enabled"); + } } - } + }// Database returned valid passwords else { - // CASE 3: - The login succeeded but the password file request from database failed - LogText(@"Successfully logged in. Password file not generated!"); + // CASE 6: - The login succeeded but the password file request from database failed + LogText("Successfully logged in with the 'offline password'.\n" + + "Passwords cannot be acquired from database and therefore not compared"); } - } + }// Initial login succeeded - if (!_currentGenesis.IsLoggedOn) + // Login can only be tried on valid database collection of passwords + if (!retValPwdBuild) + { + sb.AppendLine(@"Passwords cannot be acquired from database [E0]!"); + } + // As the initial login wasn't successfully, try the acquired combinations from the database passwords + else if (!_currentGenesis.IsLoggedOn) { // This is needed from meter as an unsuccessful login requires a delay for the next trial Thread.Sleep(2000); // Try to log in with password level 8 which may not be published to the database var retVal = _currentGenesis.Login(Encoding.UTF8.GetString(pwdContainer.ListOfPasswords.Last())); - // CASE 4: - Passwords are generated in database and correctly installed. The login check will be done + // CASE 6: - Passwords are generated in database and correctly installed. The login check will be done // with the generated password, but the 'production password' is still the 'SkeletonKey'. // - The database update of the production password went wrong! if (_currentGenesis.IsLoggedOn && retVal) { - ShowPasswordRepairMessage(@"Password file is installed as login Lvl8 works, password in database" + - " not updated - [Repair Password] enabled"); + ShowPasswordRepairMessage("Successfully logged in with 'Lvl8 password'\n" + + "Installed password file is valid and compared with database!\n" + + "'production password' in database not actual, update required\n" + + "[Repair Password] enabled"); } else { - sb.AppendLine("Login with LVL8 failed [M1]!"); + sb.AppendLine("Login with 'LVL8 password' failed [M1]!"); } if (!_currentGenesis.IsLoggedOn) { // This is needed from meter as an unsuccessful login requires a delay for the next trial Thread.Sleep(4000); - // CASE 5: - The production password didn't work, so the SkeletonKey will be tried. + // CASE 7: - The production password didn't work, so the SkeletonKey will be tried. if (_currentGenesis.Login(pwdContainer.Skeleton)) { - ShowPasswordRepairMessage(@"Successfully logged in with SkeletonKey - [Repair Password] enabled"); + ShowPasswordRepairMessage("Successfully logged in with 'SkeletonKey'\n" + + "'production password' in database not actual, update required\n" + + "[Repair Password] enabled"); } else { - sb.AppendLine(@"Login with Skeleton failed [M2]!"); + sb.AppendLine(@"Login with 'SkeletonKey' failed [M2]!"); } - if (!retValPwdBuild) - { - sb.AppendLine(@"Unable to build password file [E0]!"); - } - else if (_currentGenesis.Region.Equals("NA")) + if (_currentGenesis.Region.Equals("NA")) { var url = ServiceUrls.GetExportDataServiceUrl(); var retStr = LocalWebRequest.GetRequestWithError(url + _currentGenesis.PcbId, @@ -422,15 +472,15 @@ namespace Xylem.Common.Ui.GenesisToolBox { if (item.PWD == pwdContainer.Password) { - sb.AppendLine($"{item.ID} is Password LVL 8"); + sb.AppendLine($"{item.ID} is the 'Lvl8 password'"); } else if (item.PWD == pwdContainer.Skeleton) { - sb.AppendLine($"{item.ID} is Skeleton [E3]"); + sb.AppendLine($"{item.ID} is the 'SkeletonKey' [E3]"); } else { - sb.AppendLine($"{item.ID} is not LVL 8 or Skeleton [E3]"); + sb.AppendLine($"{item.ID} is neither the 'Lvl8 password' nor the 'SkeletonKey' [E3]"); } } } diff --git a/Common/Ui/GenesisToolBox/FrmQsTool.Designer.cs b/Common/Ui/GenesisToolBox/FrmQsTool.Designer.cs index c9ad20e4..2c2b9857 100644 --- a/Common/Ui/GenesisToolBox/FrmQsTool.Designer.cs +++ b/Common/Ui/GenesisToolBox/FrmQsTool.Designer.cs @@ -166,6 +166,7 @@ this.cbxUseOfflinePwds.TabIndex = 42; this.cbxUseOfflinePwds.Text = "Use Offline Passwords"; this.cbxUseOfflinePwds.UseVisualStyleBackColor = true; + this.cbxUseOfflinePwds.CheckedChanged += new System.EventHandler(this.cbxUseOfflinePwds_CheckedChanged); // // tbxPcbId // diff --git a/Common/Ui/GenesisToolBox/FrmQsTool.cs b/Common/Ui/GenesisToolBox/FrmQsTool.cs index 39eac73d..70e179ba 100644 --- a/Common/Ui/GenesisToolBox/FrmQsTool.cs +++ b/Common/Ui/GenesisToolBox/FrmQsTool.cs @@ -87,6 +87,7 @@ namespace Xylem.Common.Ui.GenesisToolBox SetCordonelAccessLocked(); tbxPcbId.Visible = false; + btnConnect.Focus(); } private void FrmQsTool_Load(Object sender, EventArgs e) @@ -265,54 +266,66 @@ namespace Xylem.Common.Ui.GenesisToolBox return; } - Invoke(new Action(() => + if (_currentGenesis.IsLoggedOn) { - lblConnectPcb.Text = StrPartPcbConnected; - tbxPcbId.Text = _currentGenesis.PcbId; - tbxPcbId.Visible = true; - tbxMeterFw.Text = _currentGenesis.FwVersion; - tbxMeterMeterSize.Text = _currentGenesis.MeterSize; - tbxMeterLutCrc.Text = _currentGenesis.LutCrc; - tbxRegion.Text = _currentGenesis.Region; - LogText("Meter FW Version:\t" + _currentGenesis.FwVersion); - LogText("Meter LUT CRC:\t" + _currentGenesis.LutCrc); - LogText("Meter Size:\t" + _currentGenesis.MeterSize); - LogText("Meter Region:\t" + _currentGenesis.Region); - if (_currentGenesis.RadioFrequencyMhz != null) + Invoke(new Action(() => { - tbxRadio.Text = $@"{_currentGenesis.RadioFrequencyMhz}"; - LogText("Radio frequency:\t" + $"{_currentGenesis.RadioFrequencyMhz} MHz"); - } + lblConnectPcb.Text = StrPartPcbConnected; + tbxPcbId.Text = _currentGenesis.PcbId; + tbxPcbId.Visible = true; + tbxMeterFw.Text = _currentGenesis.FwVersion; + tbxMeterMeterSize.Text = _currentGenesis.MeterSize; + tbxMeterLutCrc.Text = _currentGenesis.LutCrc; + tbxRegion.Text = _currentGenesis.Region; + LogText("Meter FW Version:\t" + _currentGenesis.FwVersion); + LogText("Meter LUT CRC:\t" + _currentGenesis.LutCrc); + LogText("Meter Size:\t" + _currentGenesis.MeterSize); + LogText("Meter Region:\t" + _currentGenesis.Region); + if (_currentGenesis.RadioFrequencyMhz != null) + { + tbxRadio.Text = $@"{_currentGenesis.RadioFrequencyMhz}"; + LogText("Radio frequency:\t" + $"{_currentGenesis.RadioFrequencyMhz} MHz"); + } - LogText(""); - LogText("'Configuration.json' version: " + _currentGenesis.InterfaceInfo.InterfaceVersion); - lblConfigVersion.Text = @"Interface Version: " + _currentGenesis.InterfaceInfo.InterfaceVersion; - lblConfigVersion.ForeColor = _currentGenesis.InterfaceSupportsFwVersion ? Color.Green : Color.Red; - if (!_currentGenesis.InterfaceSupportsFwVersion) - { - var text = "INTERFACE VERSION OUTDATED!\n" + - "The loaded \'configuration.json\' " + - $"version: {_currentGenesis.InterfaceInfo.InterfaceVersion}\n" + - $"does NOT support the Cordonel FW version: {_currentGenesis.FwVersion}!"; - MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error); - LogText(text); - } - else - { - LogText($"\'Configuration.json\' supports installed FW version: {_currentGenesis.FwVersion}"); - } + LogText(""); + LogText("'Configuration.json' version: " + _currentGenesis.InterfaceInfo.InterfaceVersion); + lblConfigVersion.Text = @"Interface Version: " + _currentGenesis.InterfaceInfo.InterfaceVersion; + lblConfigVersion.ForeColor = _currentGenesis.InterfaceSupportsFwVersion ? Color.Green : Color.Red; + if (!_currentGenesis.InterfaceSupportsFwVersion) + { + var text = "INTERFACE VERSION OUTDATED!\n" + + "The loaded \'configuration.json\' " + + $"version: {_currentGenesis.InterfaceInfo.InterfaceVersion}\n" + + $"does NOT support the Cordonel FW version: {_currentGenesis.FwVersion}!"; + MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error); + LogText(text); + } + else + { + LogText($"\'Configuration.json\' supports installed FW version: {_currentGenesis.FwVersion}"); + } - LogText(""); - lblConnectPcb.ForeColor = Color.Green; - CheckUpdateEnabled(); + LogText(""); + lblConnectPcb.ForeColor = Color.Green; + CheckUpdateEnabled(); - LogPcAndCordonelTime(); - LogInstalledMeterFw(); - })); + LogPcAndCordonelTime(); + LogInstalledMeterFw(); + })); + } }).ContinueWith(delegate { LowLevelActionControl(false); - btnReadLifetime_Click(this, null); + _currentGenesis.ReLogin(); + if (_currentGenesis.IsLoggedOn) + btnReadLifetime_Click(this, null); + else + { + Invoke(new Action(() => + { + Init(); + })); + } }); } catch (Exception ex) @@ -688,13 +701,13 @@ namespace Xylem.Common.Ui.GenesisToolBox tbxDrainedLoad_uAs.Text = $@"{genesisStatus.DrainedBatteryLoad_uAs:N0}"; tbxExpiredLifeTime.Text = $@"{genesisStatus.ExceededLifeTime_s:N0}"; tbxInitialBatteryLoad.Text = $@"{genesisStatus.InitialBatteryLoad_mAh:N0}"; - + tbxDrainedBatteryLoad_percent.Text = $@"{genesisStatus.DrainedBatteryLoadPercent:F2}"; tBxRemainingLifeTimeSw.Text = $@"{genesisStatus.RemainingLifeTimeYears:F2}"; tbxRemainingLifeTimeFw.Text = genesisStatus.FwCalculatedRemainingLifeTimeYears != null ? - $@"{genesisStatus.DrainedBatteryLoadPercent:F2}" : "not supported"; + $@"{genesisStatus.FwCalculatedRemainingLifeTimeYears:F2}" : "not supported"; tbxStorageMonths.Text = $@"{genesisStatus.StorageMonths:F1}"; - } + } else { tbxDrainedBatteryLoad_percent.Text = "";