GTB: - update password restore

This commit is contained in:
Thomas Wiedebusch 2025-10-20 16:48:15 +02:00
parent 8a986de590
commit abe58a2ec8
5 changed files with 171 additions and 82 deletions

View File

@ -145,6 +145,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// </summary>
public Boolean UseOfflinePasswords { set; get; }
/// <summary>
/// Remind the offline password for comparison if this is actively used
/// </summary>
public String OfflinePassword { protected set; get; } = "";
/// <summary>
/// Process configuration
/// </summary>
@ -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;
}
}

View File

@ -70,6 +70,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <summary>
/// List for un-reversed parameters which can be written, all others need to be swapped byte-wise
/// </summary>
//TODO THW take configuration.json and use for String and Array type, see RegisterConverter
private static readonly List<String> _unReversedParameters = new List<String>
{
"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

View File

@ -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]");
}
}
}

View File

@ -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
//

View File

@ -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 = "";