5931 lines
270 KiB
C#
5931 lines
270 KiB
C#
using Logic.ProductionToProductMapper.Files.Fw;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using Xylem.Common.CommonCore.Consts;
|
|
using Xylem.Common.CommonCore.ThreadWatcher;
|
|
using Xylem.Common.Cryptology.Security;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
|
using Xylem.Common.Logic.ProductionOrderCore.FW;
|
|
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
|
|
using Xylem.Common.Utils.DateTimeServer;
|
|
using Xylem.Common.Utils.Logging;
|
|
using Xylem.Common.Utils.UiInvoker;
|
|
using Xylem.Common.Utils.UiLanguageControl;
|
|
using Xylem.Common.Utils.FileIo;
|
|
using Xylem.ServiceFwUpdate.Common.FwUpdateConfig.Consts;
|
|
using Xylem.ServiceFwUpdate.Common.FwUpdateDb;
|
|
using Xylem.ServiceFwUpdate.Common.FwUpdateSafe;
|
|
using Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Const;
|
|
using Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Properties;
|
|
using Xylem.Common.Utils.Crc16Ccitt;
|
|
|
|
namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder
|
|
{
|
|
/// <summary>
|
|
/// FW update builder
|
|
/// </summary>
|
|
public partial class FrmFwUpdateBuilder : Form
|
|
{
|
|
#region ------------------------------------------ Variables --------------------------------------------------
|
|
private static readonly Color ColorBackGround = Color.White;
|
|
private static readonly Color ColorDefault = Color.Black;
|
|
private static readonly Color ColorSuccess = Color.Green;
|
|
private static readonly Color ColorProcessWarning = Color.DarkOrange;
|
|
private static readonly Color ColorProcessFailed = Color.Red;
|
|
//private static readonly Color ColorOngoingProcess = Color.Blue;
|
|
//private static readonly Color ColorUnknownStatus = Color.Gray;
|
|
private static readonly Color ColorBkMissing = Color.LightCoral;
|
|
private static readonly Color ColorBkValid = Color.LightGreen;
|
|
//private const String SuccessSign = @"✔";
|
|
//private const String FailedSign = @"✘";
|
|
|
|
private readonly CancellationTokenSource _processToken = new CancellationTokenSource();
|
|
private readonly Thread _fwUpdateBuilderThread;
|
|
// actual process state
|
|
private ProcessState _processState;
|
|
// locker to avoid repeated state execution
|
|
private ProcessState _lastProcessState;
|
|
// reminder for state change to execute e.g. error messaging
|
|
private ProcessState _invokerProcessState;
|
|
|
|
/// <summary>
|
|
/// remind manually changed culture setting
|
|
/// </summary>
|
|
private CultureInfo _cultureInfo;
|
|
private readonly Version _version;
|
|
private readonly String _versionString;
|
|
private readonly AssemblyName _assemblyName;
|
|
private Boolean _licenseUnchecked;
|
|
private DateTimeOffset _licenseValidDateTimeOffset;
|
|
private const Int32 DbLicenseRefreshTimeoutMs = 60000;
|
|
private Int32 _dbLicenseRefreshDelayCtrMs;
|
|
|
|
private readonly ILogger _logger;
|
|
|
|
private const String StrSeparator = "-----------------------------------------------------" +
|
|
"-----------------------------------------------------";
|
|
|
|
/// <summary>
|
|
/// Registered user information read from registration file.
|
|
/// </summary>
|
|
private readonly UserInformation _regUser = new UserInformation();
|
|
|
|
//data grid styles
|
|
private readonly DataGridViewCellStyle _styleValid = new DataGridViewCellStyle();
|
|
private readonly DataGridViewCellStyle _styleInvalid = new DataGridViewCellStyle();
|
|
private readonly DataGridViewCellStyle _styleUnknown = new DataGridViewCellStyle();
|
|
|
|
private readonly DataGridViewCellStyle _styleInstallationApproved = new DataGridViewCellStyle();
|
|
private readonly DataGridViewCellStyle _styleInstallationDenied = new DataGridViewCellStyle();
|
|
private readonly DataGridViewCellStyle _styleInstallationUserApproval = new DataGridViewCellStyle();
|
|
private readonly DataGridViewCellStyle _styleInstallationRemoved = new DataGridViewCellStyle();
|
|
|
|
private DataTable _dataTableFwPackages;
|
|
private DataTable _dataTableSummary;
|
|
private DataTable _dataTableCordonels;
|
|
private DataTable _dataTableUpdateOperators;
|
|
private DataTable _dataTableCustomers;
|
|
private DataTable _dataTableReportFiles;
|
|
private DataTable _dataTableUpdateSafes;
|
|
|
|
|
|
///<summary>
|
|
/// Display of report history.
|
|
/// </summary>
|
|
private readonly FrmHistory _frmFwUpdateReport = new FrmHistory();
|
|
///<summary>
|
|
/// Collection of software needed for the FW-Update safe!
|
|
/// </summary>
|
|
private SoftwareContainer _fwUpdateSwContainer;
|
|
///<summary>
|
|
/// All report files from the DB!
|
|
/// This information will only be used by the FW Update Builder!
|
|
/// </summary>
|
|
private readonly List<FwUpdateReportDb> _fwUpdateReports = new List<FwUpdateReportDb>();
|
|
///<summary>
|
|
/// One selected report file on grid view by the user from the DB!
|
|
/// This information will only be used by the FW Update Builder!
|
|
/// </summary>
|
|
private readonly FwUpdateReportDb _selectedReport = new FwUpdateReportDb();
|
|
///<summary>
|
|
/// All FW update safes from the DB!
|
|
/// This information will only be used by the FW Update Builder!
|
|
/// </summary>
|
|
private readonly List<FwUpdateSafeDb> _fwUpdateSafesInfos = new List<FwUpdateSafeDb>();
|
|
///<summary>
|
|
/// All customer specific production order numbers to search mask from the DB!
|
|
/// This information will only be used by the FW Update Builder!
|
|
/// </summary>
|
|
private readonly List<CordonelCustomerOrderDb> _cordonelCustomerOrdersSearch =
|
|
new List<CordonelCustomerOrderDb>();
|
|
///<summary>
|
|
/// All information acquired from the DB! This information will only be used by the FW Update Builder
|
|
/// as search!
|
|
/// </summary>
|
|
private readonly List<CordonelProductionInfosDb> _cordonelProductionSearchInfos =
|
|
new List<CordonelProductionInfosDb>();
|
|
///<summary>
|
|
/// All information acquired from the DB! This information will only be used by the FW Update Builder
|
|
/// as pre-selection!
|
|
/// </summary>
|
|
private readonly List<CordonelProductionInfosDb> _cordonelProductionPreSelectInfos =
|
|
new List<CordonelProductionInfosDb>();
|
|
///<summary>
|
|
/// The Cordonel device info is all needed information for the FW-Update SW to login, install the password file
|
|
/// and select the required release version to collect it out of the FW-Update packages!
|
|
/// This is the list of already selected Cordonels for the update process! This information will be installed
|
|
/// in the FW-Update Safe and therefore passed to the FW-Update SW.
|
|
/// </summary>
|
|
private readonly List<CordonelDeviceInfo> _cordonelUpdateList = new List<CordonelDeviceInfo>();
|
|
///<summary>
|
|
/// The FW-Update package is a collection of all needed applications and settings to install into the Cordonel!
|
|
/// This information will be passed to the FW-Update SW if any Cordonel requires this package.
|
|
/// </summary>
|
|
private CordonelFirmware _fwUpdatePackage = new CordonelFirmware();
|
|
|
|
///<summary>
|
|
/// All Cordonel FW package information needed to select the right package for installation! This is going to be
|
|
/// filled with information from the read packages from DB.
|
|
/// This information will only be used by the FW Update Builder!
|
|
/// </summary>
|
|
//private readonly List<CordonelFwPackageInfo> _cordonelFwPackageInfoSearch = new List<CordonelFwPackageInfo>();
|
|
|
|
private readonly List<String> _metrologySearchItems = new List<String>();
|
|
private readonly List<String> _coreSearchItems = new List<String>();
|
|
private readonly List<String> _regionSearchItems = new List<String>();
|
|
private readonly List<String> _radioSearchItems = new List<String>();
|
|
private readonly List<String> _sizeSearchItems = new List<String>();
|
|
|
|
///<summary>
|
|
/// The FW-Update update capability is internally used to check core revision, metrology, region, frequency a.s.o.
|
|
/// This information will only be used by the FW Update Builder!
|
|
/// </summary>
|
|
private readonly List<FwUpdateCapability> _fwUpdateCapability = new List<FwUpdateCapability>();
|
|
|
|
private readonly FwUpdateDb _fwUpdateDbAccess = new FwUpdateDb();
|
|
// private readonly UserInformation _userInfo;
|
|
private Byte[] _primaryKey;
|
|
|
|
private readonly DateTimePicker _datePicker = new DateTimePicker();
|
|
private readonly ComboBox _cbxFwReleaseSelection = new ComboBox();
|
|
private Boolean _enableFwSafeUpload;
|
|
private String _fwUpdateSafeName;
|
|
private FwUpdateSafeDb _fwUpdateSafeDb;
|
|
private Int32 _updateOperatorId;
|
|
|
|
/// <summary>
|
|
/// Reminder to avoid repeated reading of DB contents and reset of selection if item has already been assigned
|
|
/// Values have to be preset to avoid a null at first check!!!!!!
|
|
/// </summary>
|
|
private String _customerNumberBeforeLastCordonelDbSearch = "";
|
|
|
|
/// <summary>
|
|
/// Feedback from any task that an update of all tables is required
|
|
/// </summary>
|
|
private Boolean _fwUpdateOperatorsPropertyChanged;
|
|
private Boolean _customersPropertyChanged;
|
|
private Boolean _cordonelsPropertyChanged;
|
|
private Boolean _fwPackagePropertyChanged;
|
|
private Boolean _fwReportsPropertyChanged;
|
|
private Boolean _fwUpdateSafesPropertyChanged;
|
|
private Boolean _preBuildSummaryPropertyChanged;
|
|
|
|
/// <summary>
|
|
/// DB connection retry timer if DB is not connected
|
|
/// </summary>
|
|
private const Int32 DbConnectionRetryDelayMs = 6000;
|
|
/// <summary>
|
|
/// DB connection timeout on active DB connectivity test
|
|
/// </summary>
|
|
private const Int32 DbConnectionTimeoutMs = 5000;
|
|
private Int32 _dbAccessDelayCtrMs;
|
|
|
|
/// <summary>
|
|
/// Project name for the DLL to load:
|
|
/// This is the base for the source folder, the destination folder, the namespace and the form
|
|
/// </summary>
|
|
private const String FwUpdateProjectName = "ServiceFwUpdateSw";
|
|
|
|
/// <summary>
|
|
/// Name for firmware update software including the namespace
|
|
/// </summary>
|
|
private const String FwUpdateSwFullName = "Xylem.ServiceFwUpdate.Ui." + FwUpdateProjectName;
|
|
|
|
/// <summary>
|
|
/// Path for FW-Update safes
|
|
/// </summary>
|
|
private static readonly String FwUpdateSafePath = Path.Combine(Environment.GetFolderPath(
|
|
Environment.SpecialFolder.UserProfile), FwUpdateConfig.DefaultFwUpdateSafePath);
|
|
|
|
/// <summary>
|
|
/// Path to application configuration ../[user]/AppData/Roaming/Genesis/
|
|
/// </summary>
|
|
private static readonly String ApplicationConfigPath = Path.Combine(Environment.GetFolderPath(
|
|
Environment.SpecialFolder.ApplicationData), ProgramConfig.GenesisBaseFolder);
|
|
|
|
/// <summary>
|
|
/// Path and file user NLog configuration
|
|
/// </summary>
|
|
private static readonly String NLogConfigurationDestPathFile = Path.Combine(ApplicationConfigPath,
|
|
ProgramConfig.NlogConfig);
|
|
|
|
/// <summary>
|
|
/// Source folder of software package if taken from local [user]/downloads/ServiceFwUpdateSw
|
|
/// </summary>
|
|
private static readonly String FwUpdateSwSourcePath = Path.Combine(Environment.GetFolderPath(
|
|
Environment.SpecialFolder.UserProfile), FwUpdateConfig.DefaultFwUpdateSwSourcePath);
|
|
#endregion --------------------------------------- Variables --------------------------------------------------
|
|
|
|
#region ------------------------------------------ State Machine ----------------------------------------------
|
|
/// <summary>
|
|
/// State machine for FW update builder:
|
|
/// Will be executed in an endless loop from the "Service FW-Update Thread" until exit. State will be executed
|
|
/// once and then locked for repeated execution. A state change is the reason for reentry.
|
|
/// NOTE:
|
|
/// Change the state immediately before calling any routine to avoid repeated execution of routine!
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-23" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Jun-08" author="Roland Drabesch">
|
|
/// - Sleep on equal process state to force suspend of actual thread.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Added report files and FW-Update safes load from DB.
|
|
/// </remarks>
|
|
private void FwUpdateBuilderStateMachine()
|
|
{
|
|
while (!_processToken.IsCancellationRequested)
|
|
{
|
|
if (_lastProcessState == _processState)
|
|
{
|
|
Thread.Sleep(1);
|
|
// do nothing until state changed
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
_lastProcessState = _processState;
|
|
switch (_processState)
|
|
{
|
|
case ProcessState.Init:
|
|
_processState = ProcessState.Idle;
|
|
break;
|
|
|
|
case ProcessState.Idle:
|
|
// Process state change catcher to leave state as is
|
|
break;
|
|
|
|
case ProcessState.Stop:
|
|
// stop clears all status's and ongoing processes
|
|
StopProcesses();
|
|
break;
|
|
|
|
case ProcessState.Error:
|
|
// stop clears all status's and ongoing processes
|
|
ErrorProcesses();
|
|
break;
|
|
|
|
case ProcessState.ConnectDb:
|
|
EstablishDbConnectionTask();
|
|
break;
|
|
|
|
case ProcessState.GetCustomersFromDb:
|
|
LoadDbCordonelCustomersTask();
|
|
break;
|
|
|
|
case ProcessState.GetReportsFromDb:
|
|
LoadDbReportsTask();
|
|
break;
|
|
|
|
case ProcessState.GetAndDisplaySingleReportFromDb:
|
|
LoadDbReportAndDisplayTask();
|
|
break;
|
|
|
|
case ProcessState.GetFwUpdateSafesInfosFromDb:
|
|
LoadDbFwUpdateSafesInfosTask();
|
|
break;
|
|
|
|
case ProcessState.GetFwUpdateOperatorsFromDb:
|
|
LoadDbFwUpdateOperatorsTask();
|
|
break;
|
|
|
|
case ProcessState.ValidateSoftware:
|
|
CheckLicenseTask();
|
|
break;
|
|
|
|
case ProcessState.BuildFwUpdateSafe:
|
|
BuildFwUpdateSafeTask();
|
|
break;
|
|
|
|
case ProcessState.UploadFwUpdateSafeToDb:
|
|
UploadFwUpdateSafeTask();
|
|
break;
|
|
|
|
case ProcessState.GetCordonelProductionOrdersFromDb:
|
|
LoadDbCordonelProductionOrdersTask();
|
|
break;
|
|
|
|
case ProcessState.GetCordonelSerialNumbersFromDb:
|
|
LoadDbCordonelSerialNumbersTask();
|
|
break;
|
|
|
|
case ProcessState.GetFwPackagesInfosFromDb:
|
|
LoadDbCordonelFwPackagesInfosTask();
|
|
break;
|
|
|
|
case ProcessState.DbAccessLocked:
|
|
// Process state change catcher to leave state as is
|
|
break;
|
|
|
|
case ProcessState.UserRegistration:
|
|
// Process state change catcher to leave state as is
|
|
break;
|
|
|
|
case ProcessState.UpdateDataTables:
|
|
// Process state change catcher to leave state as is
|
|
break;
|
|
|
|
default:
|
|
_processState = ProcessState.Idle;
|
|
break;
|
|
}
|
|
|
|
}
|
|
catch (ThreadAbortException)
|
|
{
|
|
throw;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
if (_fwUpdateBuilderThread.ThreadState == ThreadState.Aborted
|
|
|| _fwUpdateBuilderThread.ThreadState == ThreadState.AbortRequested)
|
|
{
|
|
MessageBoxShow(e.ToString(), Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
//finally
|
|
//{
|
|
//}
|
|
}
|
|
}// state locked against repeated execution
|
|
}
|
|
#endregion --------------------------------------- State Machine ----------------------------------------------
|
|
|
|
#region ------------------------------------------ Timer Controls ---------------------------------------------
|
|
|
|
/// <summary>
|
|
/// The timer for progress bar.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-23" author="Thomas Wiedebusch">
|
|
/// - Changed logic
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Checks exported
|
|
/// </remarks>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Added checks for FW-update safes and report files.
|
|
/// </remarks>
|
|
private void TmrProgressUpdate_Tick(Object sender, EventArgs e)
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
|
|
_dbAccessDelayCtrMs += TmrDbAccess.Interval;
|
|
_dbLicenseRefreshDelayCtrMs += TmrDbAccess.Interval;
|
|
switch (_processState)
|
|
{
|
|
case ProcessState.DbAccessLocked:
|
|
CheckDbConnectivity();
|
|
break;
|
|
case ProcessState.Idle:
|
|
CheckDbConnectivity();
|
|
CheckDataCollectionStatus();
|
|
CheckUpdateOperatorAccountChange();
|
|
CheckCustomerChange();
|
|
CheckCordonelChange();
|
|
CheckFwPackageChange();
|
|
CheckFwUpdateSafesChange();
|
|
CheckReportsChange();
|
|
break;
|
|
case ProcessState.BuildFwUpdateSafe:
|
|
SetStatusProgressBar(ProgressBarStatus.Value + 1 > 100 ? 0 : ProgressBarStatus.Value + 1);
|
|
break;
|
|
case ProcessState.ConnectDb:
|
|
case ProcessState.GetFwUpdateOperatorsFromDb:
|
|
case ProcessState.GetCordonelProductionOrdersFromDb:
|
|
case ProcessState.GetCustomersFromDb:
|
|
case ProcessState.GetFwPackagesInfosFromDb:
|
|
case ProcessState.GetCordonelSerialNumbersFromDb:
|
|
case ProcessState.GetFwUpdateSafesInfosFromDb:
|
|
case ProcessState.GetReportsFromDb:
|
|
case ProcessState.GetAndDisplaySingleReportFromDb:
|
|
case ProcessState.UploadFwUpdateSafeToDb:
|
|
CheckDbConnectionTimeout();
|
|
SetStatusProgressBar(ProgressBarStatus.Value + 1 > 100 ? 0 : ProgressBarStatus.Value + 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion --------------------------------------- Timer Controls ---------------------------------------------
|
|
|
|
#region ------------------------------------------ User Interaction -------------------------------------------
|
|
|
|
/// <summary>
|
|
/// Select all content for quick change
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void tbxCordonelProductionOrdersSearch_Enter(Object sender, EventArgs e)
|
|
{
|
|
tbxCordonelProductionOrdersSearch.Select(0, tbxCordonelProductionOrdersSearch.Text.Length);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Select all content for quick change
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void tbxCordonelProductionOrdersSearch_MouseClick(Object sender, MouseEventArgs e)
|
|
{
|
|
tbxCordonelProductionOrdersSearch.Select(0, tbxCordonelProductionOrdersSearch.Text.Length);
|
|
}
|
|
/// <summary>
|
|
/// Validate input
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void tbxOrderNumber_TextChanged(Object sender, EventArgs e)
|
|
{
|
|
tbxOrderNumber.Text = Regex.Match(tbxOrderNumber.Text, "[0-9]+").Groups[0].Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validate input
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void tbxOrderPosition_TextChanged(Object sender, EventArgs e)
|
|
{
|
|
tbxOrderPosition.Text = Regex.Match(tbxOrderPosition.Text, "[0-9]+").Groups[0].Value;
|
|
}
|
|
/// <summary>
|
|
/// Display Info
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-09" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void infoToolStripMenuItem_Click(Object sender, EventArgs e)
|
|
{
|
|
_processState = ProcessState.UserRegistration;
|
|
var frmRegister = new FrmRegister(_regUser);
|
|
DisableAllControlsInvoked();
|
|
frmRegister.Show();
|
|
frmRegister.Closed += FormRegister_Closed;
|
|
Hide();
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exit of Registration Form.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-04" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void FormRegister_Closed(Object sender, EventArgs e)
|
|
{
|
|
Show();
|
|
Update();
|
|
CheckUserRegistration();
|
|
}
|
|
/// <summary>
|
|
/// Exit the program
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void exitToolStripMenuItem_Click(Object sender, EventArgs e)
|
|
{
|
|
Close();
|
|
}
|
|
/// <summary>
|
|
/// Kick off customer search on key [Enter] pressed
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void tbxCustomerSearchMask_KeyDown(Object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
btnSearchCustomer_Click(this, null);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Kick off Cordonel search on key [Enter] pressed
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void tbxCordonelProductionOrdersSearch_KeyDown(Object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
// Check if the searched serial number is in the download list if ALL have been loaded
|
|
if (!string.IsNullOrEmpty(tbxCordonelProductionOrdersSearch.Text) &&
|
|
_cordonelProductionSearchInfos.Count != 0 &&
|
|
_cordonelProductionSearchInfos.Any(x =>
|
|
x.CustomerSerialNumber.Contains(tbxCordonelProductionOrdersSearch.Text)) &&
|
|
cbxCordonelProductionOrdersSearch.Text == Constants.StrWildcard)
|
|
{
|
|
_cordonelsPropertyChanged = true;
|
|
return;
|
|
}
|
|
|
|
btnCordonelSearch_Click(this, null);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Kick off Cordonel search referenced by order number
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Removed DB access delay.
|
|
/// </remarks>
|
|
private void btnCordonelSearch_Click(Object sender, EventArgs e)
|
|
{
|
|
// reading if customer is selected
|
|
if (string.IsNullOrEmpty(lblCustomerNumber.Text) ||
|
|
string.IsNullOrEmpty(cbxCordonelProductionOrdersSearch.Text) ||
|
|
_fwUpdateDbAccess?.DbCordonelCustomerOrders == null)
|
|
return;
|
|
|
|
try
|
|
{
|
|
|
|
// leave all original orders list intact to keep this information for the next search
|
|
// and clear the search list which will contain the user selected order numbers
|
|
_cordonelCustomerOrdersSearch.Clear();
|
|
|
|
// as the production info is going to fill the grid table view it has to be cleared on every new search
|
|
_cordonelProductionSearchInfos.Clear();
|
|
// remove unselected devices, avoid adding of already included devices
|
|
|
|
|
|
if (cbxCordonelProductionOrdersSearch?.SelectedItem == null ||
|
|
cbxCordonelProductionOrdersSearch.SelectedItem.ToString() == Constants.StrWildcard)
|
|
{
|
|
_cordonelCustomerOrdersSearch.AddRange(_fwUpdateDbAccess.DbCordonelCustomerOrders);
|
|
}
|
|
else
|
|
{
|
|
// format is orderNumber-position e.g. 12345678-10
|
|
var orderText = cbxCordonelProductionOrdersSearch.SelectedItem.ToString();
|
|
orderText = Regex.Replace(orderText, @"[^0-9\-]", "");
|
|
var orderTexts = orderText.Split('-');
|
|
if (Int64.TryParse(orderTexts[0], out var orderNumber) &&
|
|
Int64.TryParse(orderTexts[1], out var orderPosition))
|
|
{
|
|
foreach (var order in _fwUpdateDbAccess.DbCordonelCustomerOrders.Where(order =>
|
|
order.CustomerOrderNumber == orderNumber &&
|
|
order.CustomerOrderPos == orderPosition))
|
|
{
|
|
_cordonelCustomerOrdersSearch.Add(order);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingCordonels);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetCordonelSerialNumbersFromDb;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//nothing to do
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Kick off customer search.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - Clear last search result.
|
|
/// </remarks>
|
|
private void btnSearchCustomer_Click(Object sender, EventArgs e)
|
|
{
|
|
// clear last search result
|
|
_dataTableCustomers?.Rows.Clear();
|
|
_dataTableCustomers?.Columns.Clear();
|
|
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingCustomers);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetCustomersFromDb;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Select DEBUG Cordonels.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void cbxAddDebugCordonels_Click(Object sender, EventArgs e)
|
|
{
|
|
//DebugDeviceAndFwPackageSelection();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Kick off FW-Update package search.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Nov-29" author="Thomas Wiedebusch">
|
|
/// - Single FW-Update package.
|
|
/// </remarks>
|
|
private void btnFwPackageSearch_Click(Object sender, EventArgs e)
|
|
{
|
|
// Load fw packages only if not selected
|
|
if (_fwUpdatePackage?.FwPackageInfo != null)
|
|
return;
|
|
|
|
DisableAllControlsInvoked();
|
|
_dataTableFwPackages?.Clear();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingFwPackages);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetFwPackagesInfosFromDb;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mask already loaded FW-Update packages.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void allFwPackageSearch_Event(Object sender, EventArgs e)
|
|
{
|
|
_fwPackagePropertyChanged = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tab page selection event (replaced of tabPage_Enter event of a selected tab page as this
|
|
/// fires on all data sets copied to it).
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - FW update package selection.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Enable retry if DB connection lost.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-30" author="Thomas Wiedebusch">
|
|
/// - FW packages not loaded if already done on page change.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Set status progress bar active for pre-build summary as this takes a lot of time.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Nov-29" author="Thomas Wiedebusch">
|
|
/// - Single FW-Update package.
|
|
/// </remarks>
|
|
private void tabControlSelection_Selected(Object sender, TabControlEventArgs e)
|
|
{
|
|
_processState = ProcessState.Idle;
|
|
if (e.TabPage == tabPageFwUpdateSafes)
|
|
{
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingFwUpdateSafes);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetFwUpdateSafesInfosFromDb;
|
|
|
|
}
|
|
|
|
if (e.TabPage == tabPageReports)
|
|
{
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingReports);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetReportsFromDb;
|
|
|
|
}
|
|
|
|
if (e.TabPage == tabPageCordonelSelection)
|
|
{
|
|
// avoid reading of DB contents and reset of selection if customer remains identical
|
|
if (!_fwUpdateDbAccess.DbIsConnected)
|
|
_customerNumberBeforeLastCordonelDbSearch = "";
|
|
|
|
if (string.IsNullOrEmpty(lblCustomerNumber.Text) ||
|
|
_customerNumberBeforeLastCordonelDbSearch == lblCustomerNumber.Text)
|
|
return;
|
|
|
|
_customerNumberBeforeLastCordonelDbSearch = lblCustomerNumber.Text;
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingOrderNumbers);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetCordonelProductionOrdersFromDb;
|
|
}
|
|
|
|
if (e.TabPage == tabPageCustomerSelection)
|
|
{
|
|
}
|
|
|
|
if (e.TabPage == tabPagePreBuildSummary)
|
|
{
|
|
gridViewPreBuildSummary.Visible = false;
|
|
_preBuildSummaryPropertyChanged = true;
|
|
}
|
|
|
|
if (e.TabPage == tabPageFwPackageSelection)
|
|
{
|
|
// Load fw packages only if not selected indicated in count
|
|
if (_fwUpdatePackage?.FwPackageInfo != null ||
|
|
(_fwUpdateDbAccess?.DbCordonelFwPackagesInfo != null &&
|
|
_fwUpdateDbAccess.DbCordonelFwPackagesInfo.Count > 0))
|
|
return;
|
|
|
|
DisableAllControlsInvoked();
|
|
_dataTableFwPackages?.Clear();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingFwPackages);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetFwPackagesInfosFromDb;
|
|
}
|
|
|
|
if (e.TabPage == tabPageUpdateOperator)
|
|
{
|
|
// Avoid reading of DB contents and reset of selection if an update operator has already been assigned.
|
|
// If not, an update of the update operators may be sufficient, as the builder operator may call the
|
|
// update operator and require a new registration, so the update may immediately show the new registered
|
|
// or refreshed update operator without program exit and restart
|
|
if (!string.IsNullOrEmpty(lblUpdateOperator.Text))
|
|
return;
|
|
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingUpdateOperators);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetFwUpdateOperatorsFromDb;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upload FW-Update Safe to DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-27" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void btnUploadSafeToDb_Click(Object sender, EventArgs e)
|
|
{
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrFwUpdateSafeUploading);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.UploadFwUpdateSafeToDb;
|
|
}
|
|
|
|
/// <summary>
|
|
/// License the actual FW-Update Builder which is this product!
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Jun-30" author="Thomas Wiedebusch">
|
|
/// - Add 10 years for valid date.
|
|
/// </remarks>
|
|
private void btnLicenseFwUpdateBuilder_Click(Object sender, EventArgs e)
|
|
{
|
|
GetFwUpdateSwLicenseFromDb(_assemblyName.Name, out var fwUpdateBuilderLicenseRead);
|
|
BuildSwLicense(_assemblyName.Name, out var fwUpdateBuilderLicense);
|
|
fwUpdateBuilderLicense.ValidTo = DateTime.Now.AddYears(10);
|
|
SetFwUpdateSwLicenseToDb(fwUpdateBuilderLicense);
|
|
GetFwUpdateSwLicenseFromDb(_assemblyName.Name, out fwUpdateBuilderLicenseRead);
|
|
if (fwUpdateBuilderLicenseRead.Major == fwUpdateBuilderLicense.Major &&
|
|
fwUpdateBuilderLicenseRead.Minor == fwUpdateBuilderLicense.Minor &&
|
|
fwUpdateBuilderLicenseRead.Build == fwUpdateBuilderLicense.Build)
|
|
{
|
|
var msg = "FW-Update Builder Version: " +
|
|
$"{_version.Major}.{_version.Minor}.{_version.Build} {Resources.StrRegistrationSuccess}";
|
|
MessageBoxShow(msg, Resources.StrSuccess);
|
|
}
|
|
else
|
|
{
|
|
var msg = $"FW-Update Builder {Resources.StrRegisteredFailed}";
|
|
MessageBoxShow(msg, Resources.StrError);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// License the actual FW-Update SW.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void btnLicenseFwUpdateSw_Click(Object sender, EventArgs e)
|
|
{
|
|
GetFwUpdateSwLicenseFromDb(FwUpdateSwFullName, out var fwUpdateSwLicenseRead);
|
|
BuildSwLicense(FwUpdateSwFullName, out var fwUpdateSwLicense);
|
|
SetFwUpdateSwLicenseToDb(fwUpdateSwLicense);
|
|
GetFwUpdateSwLicenseFromDb(FwUpdateSwFullName, out fwUpdateSwLicenseRead);
|
|
String msg;
|
|
if (fwUpdateSwLicenseRead != null)
|
|
{
|
|
if (fwUpdateSwLicenseRead.Major == fwUpdateSwLicense.Major &&
|
|
fwUpdateSwLicenseRead.Minor == fwUpdateSwLicense.Minor &&
|
|
fwUpdateSwLicenseRead.Build == fwUpdateSwLicense.Build)
|
|
{
|
|
msg = "FW-Update Software Version: " +
|
|
$"{_version.Major}.{_version.Minor}.{_version.Build} {Resources.StrRegistrationSuccess}";
|
|
MessageBoxShow(msg, Resources.StrSuccess);
|
|
}
|
|
return;
|
|
}
|
|
msg = $"FW-Update Software {Resources.StrRegisteredFailed}";
|
|
MessageBoxShow(msg, Resources.StrError);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build the update safe.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Feb-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-23" author="Thomas Wiedebusch">
|
|
/// - Clear content of FW package to force reload and output of loaded package on rebuild of safe.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Nov-29" author="Thomas Wiedebusch">
|
|
/// - Single FW-Update package.
|
|
/// </remarks>
|
|
private void btnBuildFwUpdateSafe_Click(Object sender, EventArgs e)
|
|
{
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
// clear FW package content to force reload from data base and therefore report generation,
|
|
// this is essential for rebuilding of a safe
|
|
_fwUpdatePackage?.BinaryApplicationFiles?.Clear();
|
|
rtbReport.Clear();
|
|
rtbReport.ForeColor = ColorDefault;
|
|
lblStatusDbConnect.Text = Resources.StrFwUpdateSafeBuilding;
|
|
_processState = ProcessState.BuildFwUpdateSafe;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Close the date picker for the FW-Update validation date.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void datePickerFwUpdateValidationDate_CloseUp(Object sender, EventArgs e)
|
|
{
|
|
// change text two times to include the culture info
|
|
var dateTimeOffset = DateTimeServer.GetDateTimeOffsetFromDateString(_datePicker.Text);
|
|
lblFwUpdateDutyDate.Text = DateTimeServer.GetDateStringFromDateTimeOffset(dateTimeOffset, _cultureInfo);
|
|
HideDatePicker();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Close the date picker for the user validation date.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void datePickerUserValidationDate_CloseUp(Object sender, EventArgs e)
|
|
{
|
|
//_userInfo.ValidDate = DateTimeServer.GetDateTimeOffsetFromDateString(_datePicker.Text);
|
|
_fwUpdateOperatorsPropertyChanged = true;
|
|
HideDatePicker();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Activate date time picker.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void lblFwUpdateDutyDate_Click(Object sender, EventArgs e)
|
|
{
|
|
if (_datePicker.Visible)
|
|
{
|
|
HideDatePicker();
|
|
}
|
|
|
|
// hide the label, only with this the date picker can be seen !!!!
|
|
lblFwUpdateDutyDate.Visible = false;
|
|
var cell = tblPanelSafeInfo.GetCellPosition(lblFwUpdateDutyDate);
|
|
// Adding DateTimePicker control into cell x, y
|
|
tblPanelSafeInfo.Controls.Add(_datePicker, cell.Column, cell.Row);
|
|
|
|
// The final selection of the date
|
|
_datePicker.CloseUp += datePickerFwUpdateValidationDate_CloseUp;
|
|
|
|
// Now make it visible
|
|
_datePicker.Visible = true;
|
|
}
|
|
|
|
#endregion --------------------------------------- User Interaction -------------------------------------------
|
|
|
|
#region ------------------------------------------ Form Load Unload -------------------------------------------
|
|
/// <summary>
|
|
/// Ctor
|
|
/// </summary>
|
|
/// <remarks date="2020-Nov-30" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Invisible progress bar at start.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-25" author="Thomas Wiedebusch">
|
|
/// - Directory for FW-Update Safes created.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Grid color for update capability checks.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Pre-filled FW-Update package search lists.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-30" author="Thomas Wiedebusch">
|
|
/// - MeterFwUpdateRuler.json class changed to nullable DateTime.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Jun-08" author="Thomas Wiedebusch">
|
|
/// - Library added to NLogConfig source path, as this is the release source, copy files only if not
|
|
/// identical.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Nov-29" author="Thomas Wiedebusch">
|
|
/// - Removed FUpdateRuler, all data are going to be taken from DB.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-08" author="Thomas Wiedebusch">
|
|
/// - Culture info fixed to english.
|
|
/// </remarks>
|
|
public FrmFwUpdateBuilder()
|
|
{
|
|
_cultureInfo = Thread.CurrentThread.CurrentCulture;
|
|
var fwUpdateBuilderExePath = AppDomain.CurrentDomain.BaseDirectory;
|
|
//var fwUpdateBuilderLibraryPath = Path.Combine(fwUpdateBuilderExePath, FwUpdateConfig.LibrarySubFolderName);
|
|
var fwUpdateBuilderConfigPath = Path.Combine(fwUpdateBuilderExePath, FwUpdateConfig.ConfigSubFolderName);
|
|
|
|
var nLogConfigSourcePathName = Path.Combine(fwUpdateBuilderConfigPath, ProgramConfig.NlogConfig);
|
|
|
|
// Build the configuration directory and copy at least the NLog config to it
|
|
try
|
|
{
|
|
if (!Directory.Exists(ApplicationConfigPath))
|
|
{
|
|
Directory.CreateDirectory(ApplicationConfigPath);
|
|
}
|
|
|
|
if (!Directory.Exists(FwUpdateSafePath))
|
|
{
|
|
Directory.CreateDirectory(FwUpdateSafePath);
|
|
}
|
|
|
|
// Check for the file in the application exe path and the application configuration path
|
|
if (File.Exists(nLogConfigSourcePathName) && !File.Exists(NLogConfigurationDestPathFile))
|
|
SystemControl.CopyFile(nLogConfigSourcePathName, NLogConfigurationDestPathFile);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
_logger = NLogHelper.CreateOrGetLogger("ServiceFwUpdateBuilder");
|
|
_assemblyName = Assembly.GetExecutingAssembly().GetName();
|
|
_version = _assemblyName.Version;
|
|
_versionString = $"{_assemblyName.Name} Version: {_version.Major}.{_version.Minor}.{_version.Build}.{_version.Revision}";
|
|
_logger.Info(StrSeparator);
|
|
_logger.Info(_versionString);
|
|
_logger.Info(StrSeparator);
|
|
|
|
InitializeComponent();
|
|
|
|
if (_cultureInfo.IetfLanguageTag.Contains("de-"))
|
|
radioBtnGermanLanguage.Checked = true;
|
|
else
|
|
radioBtnEnglishLanguage.Checked = true;
|
|
|
|
RadioBtnEnglishLanguage_Click(this, null);
|
|
|
|
lblFwUpdateInfo.Text = $@"Version: {_version.Major}.{_version.Minor}.{_version.Build}";
|
|
|
|
lblStatusDbConnect.ForeColor = ColorDefault;
|
|
DateTimeServer.SetValidationDate(FwUpdateConfig.ValidDays);
|
|
var dateTime = DateTimeServer.SetValidationDate(FwUpdateConfig.ValidDays).DateTime;
|
|
|
|
_datePicker.Format = DateTimePickerFormat.Short;
|
|
_datePicker.Value = dateTime;
|
|
lblFwUpdateDutyDate.Text = _datePicker.Value.ToShortDateString();
|
|
|
|
_styleValid.BackColor = ColorBackGround;
|
|
_styleValid.ForeColor = ColorSuccess;
|
|
|
|
_styleInvalid.BackColor = ColorBackGround;
|
|
_styleInvalid.ForeColor = ColorProcessFailed;
|
|
|
|
_styleUnknown.BackColor = ColorBackGround;
|
|
_styleUnknown.ForeColor = ColorDefault;
|
|
|
|
_styleInstallationApproved.BackColor = Color.LightGreen;
|
|
_styleInstallationApproved.ForeColor = Color.Black;
|
|
|
|
_styleInstallationDenied.BackColor = Color.LightCoral;
|
|
_styleInstallationDenied.ForeColor = Color.Black;
|
|
|
|
_styleInstallationUserApproval.BackColor = Color.Orange;
|
|
_styleInstallationUserApproval.ForeColor = Color.Black;
|
|
|
|
_styleInstallationRemoved.BackColor = Color.LightGray;
|
|
_styleInstallationRemoved.ForeColor = Color.Gray;
|
|
|
|
// start immediately the connection check
|
|
_dbAccessDelayCtrMs = DbConnectionRetryDelayMs;
|
|
// validate software license as soon as possible
|
|
_dbLicenseRefreshDelayCtrMs = DbLicenseRefreshTimeoutMs;
|
|
|
|
lblUpdateOperator.Text = "";
|
|
btnBuildFwUpdateSafe.Enabled = false;
|
|
btnUploadSafeToDb.Enabled = false;
|
|
|
|
if (System.Diagnostics.Debugger.IsAttached)
|
|
{
|
|
btnLicenseFwUpdateSw.Visible = true;
|
|
btnLicenseFwUpdateBuilder.Visible = true;
|
|
//cbxAddDebugCordonels.Visible = true;
|
|
}
|
|
|
|
cbxAddDebugCordonels.Checked = false;
|
|
btnLicenseFwUpdateSw.Enabled = false;
|
|
btnLicenseFwUpdateBuilder.Enabled = false;
|
|
tbxCustomerName.Text = "";
|
|
lblCustomerNumber.Text = "";
|
|
tbxOrderNumber.Text = @"0001";
|
|
tbxOrderPosition.Text = @"10";
|
|
|
|
var tabControlImages = new ImageList { ColorDepth = ColorDepth.Depth24Bit };
|
|
tabControlImages.Images.Add(Resources.ImageMissingInput);
|
|
tabControlImages.Images.Add(Resources.ImageValidInput);
|
|
tabControlSelection.ImageList = tabControlImages;
|
|
|
|
// set locked repeat initially different from process state to unlock first entry to state machine
|
|
_lastProcessState = ProcessState.Unspecified;
|
|
_processState = ProcessState.Init;
|
|
_invokerProcessState = _processState;
|
|
|
|
// disable all actions until license has been verified
|
|
DisableControlsExceptLanguageInvoked();
|
|
_licenseUnchecked = true;
|
|
|
|
//assign a thread name to observe this
|
|
if (string.IsNullOrEmpty(Thread.CurrentThread.Name))
|
|
Thread.CurrentThread.Name = "Form Service FW-Update Builder thread";
|
|
//assign thread to loop and start thread
|
|
_fwUpdateBuilderThread = new Thread(FwUpdateBuilderStateMachine);
|
|
if (!string.IsNullOrEmpty(_fwUpdateBuilderThread.Name))
|
|
_fwUpdateBuilderThread.Name = "State Machine Service FW-Update Builder thread";
|
|
ThreadWatcher.Instance.Start(_fwUpdateBuilderThread);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exit
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-23" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void FrmFwUpdateBuilder_FormClosing(Object sender, FormClosingEventArgs e)
|
|
{
|
|
_frmFwUpdateReport?.Close();
|
|
_datePicker?.Dispose();
|
|
_cbxFwReleaseSelection?.Dispose();
|
|
_processToken?.Cancel();
|
|
}
|
|
#endregion --------------------------------------- Form Load Unload -------------------------------------------
|
|
|
|
#region ------------------------------------------ Build FW-Update Safe ---------------------------------------
|
|
/// <summary>
|
|
/// Build the firmware update safe and stores it to a file and to the DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Jan-27" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-20" author="Thomas Wiedebusch">
|
|
/// - Logging added.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-23" author="Thomas Wiedebusch">
|
|
/// - FW-Update SW container added.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Order number and customer text added,
|
|
/// - Disable all controls during FW-UpdateSafe build.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-26" author="Thomas Wiedebusch">
|
|
/// - Additional logging.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-30" author="Thomas Wiedebusch">
|
|
/// - Output short file name.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - Action on missing FwUpdateSw.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Error process state introduced.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Replaced _userInfo by lblUpdateOperator.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Taking FW-Update SW license from DB.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-27" author="Thomas Wiedebusch">
|
|
/// - Added FwUpdateSafeDb preparation
|
|
/// </remarks>
|
|
/// <remarks date="2021-Oct-27" author="Thomas Wiedebusch">
|
|
/// - Added BuildFwUpdateSwContainerFromDb, no longer taken from locally file system!
|
|
/// </remarks>
|
|
/// <remarks date="2021-Oct-29" author="Thomas Wiedebusch">
|
|
/// - Skip loading of FW update SW if already done in preceding run.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Jul-02" author="Thomas Wiedebusch">
|
|
/// - Removed special characters (e.g. characters from other language like "Umlaute") from file name,
|
|
/// as DB problems may occur on FwUpdateSafe load, limit customer name length to 45 characters to
|
|
/// keep the file name small.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Nov-29" author="Thomas Wiedebusch">
|
|
/// - New FW-Update safe:
|
|
/// - Simply one FW-update package per safe,
|
|
/// - Register recovery implemented,
|
|
/// - FW information taken from fields instead of the name.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-09" author="Thomas Wiedebusch">
|
|
/// - Check for valid programming parameters.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-13" author="Thomas Wiedebusch">
|
|
/// - Report builder version and safe built date.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-23" author="Thomas Wiedebusch">
|
|
/// - Additional safe information like built date, builder version e.g. for report generation.
|
|
/// </remarks>
|
|
private Boolean BuildFwUpdateSafe()
|
|
{
|
|
if (string.IsNullOrEmpty(lblUpdateOperator.Text))
|
|
return false;
|
|
DisableAllControlsInvoked();
|
|
Invoke(new Action(() =>
|
|
{
|
|
tabControlSelection.SelectTab(tabPageSafeBuildReport);
|
|
tabControlSelection.Refresh();
|
|
}));
|
|
try
|
|
{
|
|
var fwUpdateSafe = new FwUpdateSafe
|
|
{
|
|
Software = new SoftwareContainer(),
|
|
Updates = new UpdateContainer(),
|
|
SafeInfo = new FwUpdateSafeInfo()
|
|
};
|
|
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
|
|
LogText(StrSeparator);
|
|
LogText(_versionString);
|
|
fwUpdateSafe.SafeInfo.FwUpdateBuilderInfo = _versionString;
|
|
LogText(Resources.StrBuilderOperator + @" " + _regUser.FullName);
|
|
fwUpdateSafe.SafeInfo.FwUpdateBuilderOperatorId = _regUser.Id.ToString();
|
|
LogText(StrSeparator);
|
|
LogText(Resources.StrSafeBuiltDate + @" " + $@"{DateTime.UtcNow:dddd, dd-MMM-yyyy HH:mm:ss} UTC");
|
|
fwUpdateSafe.SafeInfo.SafeBuiltDateTime = DateTime.UtcNow;
|
|
LogText(Resources.StrCustomerName + @" " + tbxCustomerName.Text);
|
|
fwUpdateSafe.SafeInfo.CustomerName = tbxCustomerName.Text;
|
|
LogText(Resources.StrCustomerNumber + @" " + lblCustomerNumber.Text);
|
|
fwUpdateSafe.SafeInfo.CustomerNumber = lblCustomerNumber.Text;
|
|
LogText($@"{Resources.StrOrderNumber} {tbxOrderNumber.Text}-{tbxOrderPosition.Text}");
|
|
fwUpdateSafe.SafeInfo.FwUpdateOrderPosition = $"{tbxOrderNumber.Text}-{tbxOrderPosition.Text}";
|
|
LogText(Resources.StrUpdateOperator + @" " + lblUpdateOperator.Text);
|
|
fwUpdateSafe.SafeInfo.FwUpdateFieldOperatorId = _updateOperatorId.ToString();
|
|
|
|
// first replace the underlines as these are used for the file name and later to separate for customer and order number
|
|
var fileName = tbxCustomerName.Text.Replace(FwUpdateConfig.FwUpdateFileFieldSeparator.ToString(), "");
|
|
// remove special multilingual characters as they cause problems in DB, leave numbers, the "-", the "&", the "."
|
|
// and the white space in.
|
|
fileName = Regex.Replace(fileName, @"[^a-zA-Z0-9\-\s\&\.]", "");
|
|
// limit customer name length to 45
|
|
if (fileName.Length > 45)
|
|
{
|
|
fileName = fileName.Substring(0, 45);
|
|
}
|
|
// The safe shall look like "Thames Water_01234567890-10.safe"
|
|
_fwUpdateSafeName = $@"{fileName}{FwUpdateConfig.FwUpdateFileFieldSeparator}" +
|
|
$@"{tbxOrderNumber.Text}-{tbxOrderPosition.Text}" +
|
|
FwUpdateConfig.FwUpdateFileExtension;
|
|
fwUpdateSafe.SafeInfo.FwUpdateSafeName = _fwUpdateSafeName;
|
|
|
|
// Should never occur as [Build FW-Update Safe] is locked if no device is selected
|
|
if (_cordonelUpdateList.Count == 0)
|
|
{
|
|
LogErrorText(Resources.StrCordonelsMissing);
|
|
MessageBoxShow(Resources.StrCordonelsMissing, Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
|
|
GetFwUpdateSwLicenseFromDb(FwUpdateSwFullName, out fwUpdateSafe.License);
|
|
|
|
if (fwUpdateSafe.License == null)
|
|
{
|
|
LogErrorText(Resources.StrSwLicenseMissing);
|
|
MessageBoxShow(Resources.StrSwLicenseMissing, Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
|
|
// overwrite license validation date as operator has selected this
|
|
fwUpdateSafe.License.ValidTo =
|
|
DateTimeServer.GetDateTimeFromDateString(lblFwUpdateDutyDate.Text + " 23:59:59", _cultureInfo);
|
|
|
|
|
|
LogText(Resources.StrValidDate + @" " + $@"{fwUpdateSafe.License.ValidTo:dddd, dd-MMM-yyyy HH:mm:ss} UTC");
|
|
fwUpdateSafe.SafeInfo.FwUpdateValidDate = fwUpdateSafe.License.ValidTo;
|
|
LogText(StrSeparator);
|
|
LogSuccessText($@"{Resources.StrSwLicenseLoadedSuccessfully} {FwUpdateProjectName}" +
|
|
$" {fwUpdateSafe.License.Major}.{fwUpdateSafe.License.Minor}.{fwUpdateSafe.License.Build}");
|
|
|
|
// Skip loading of FW update SW if already done in preceding run
|
|
if (_fwUpdateSwContainer?.RegisterDefinitionFile == null ||
|
|
_fwUpdateSwContainer.SoftwareSetupFile == null ||
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore == null ||
|
|
string.IsNullOrEmpty(_fwUpdateSwContainer.RegisterDefinitionFile.FileName) ||
|
|
string.IsNullOrEmpty(_fwUpdateSwContainer.SoftwareSetupFile.FileName) ||
|
|
string.IsNullOrEmpty(_fwUpdateSwContainer.MeterFilesEraseRestore.FileName) ||
|
|
_fwUpdateSwContainer.SoftwareDynLinkLibs == null ||
|
|
_fwUpdateSwContainer.SoftwareDynLinkLibs.Count == 0)
|
|
{
|
|
// local files: if (!BuildFwUpdateSwContainer(fwUpdateSafe.License) ||
|
|
if (!BuildFwUpdateSwContainerFromDb(fwUpdateSafe.License) ||
|
|
_fwUpdateSwContainer?.RegisterDefinitionFile == null ||
|
|
_fwUpdateSwContainer.SoftwareSetupFile == null ||
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore == null ||
|
|
string.IsNullOrEmpty(_fwUpdateSwContainer.RegisterDefinitionFile.FileName) ||
|
|
string.IsNullOrEmpty(_fwUpdateSwContainer.SoftwareSetupFile.FileName) ||
|
|
string.IsNullOrEmpty(_fwUpdateSwContainer.MeterFilesEraseRestore.FileName) ||
|
|
_fwUpdateSwContainer.SoftwareDynLinkLibs == null ||
|
|
_fwUpdateSwContainer.SoftwareDynLinkLibs.Count == 0)
|
|
{
|
|
LogErrorText(Resources.StrSwContainerCollectionFailed);
|
|
MessageBoxShow(Resources.StrSwContainerCollectionFailed, Resources.StrError,
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
fwUpdateSafe.Software = _fwUpdateSwContainer;
|
|
LogSuccessText(Resources.StrSwContainerCollectionSuccess);
|
|
|
|
CompleteCordonelDeviceInfos();
|
|
if (_cordonelUpdateList.Count == 0)
|
|
{
|
|
LogErrorText(Resources.StrCordonelsMissing);
|
|
MessageBoxShow(Resources.StrCordonelsMissing, Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
|
|
// deny generation of FW update safe as some information couldn't be loaded
|
|
if (_fwUpdateCapability.All(x => x.ReleaseContainerLoaded == false) ||
|
|
_fwUpdateCapability.Any(x => x.RecoveryNotNeededOrLoaded == false) ||
|
|
_fwUpdateCapability.Any(x => x.PowerCorrectionNotNeededOrLoaded == false) ||
|
|
_fwUpdateCapability.Any(x => x.PasswordContainerLoaded == false))
|
|
{
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
|
|
fwUpdateSafe.Updates = new UpdateContainer
|
|
{
|
|
CordonelFwPackage = new CordonelFirmware(),
|
|
CordonelDeviceInfos = new List<CordonelDeviceInfo>()
|
|
};
|
|
fwUpdateSafe.Updates.CordonelFwPackage = _fwUpdatePackage;
|
|
fwUpdateSafe.Updates.CordonelDeviceInfos = _cordonelUpdateList;
|
|
|
|
////TODO THW remove this DEBUG to map from current selection to TEST BOARD
|
|
//_cordonelUpdateList[0].CustomerSerialNumber = "8 SEN20 1975 6272";
|
|
//_cordonelUpdateList[0].PcbId = "182100041";
|
|
//GetPwdFromDb(_cordonelUpdateList[0]);
|
|
//fwUpdateSafe.License.Build = 8;
|
|
//var dateTime = fwUpdateSafe.License.ValidTo.AddDays(-1);
|
|
//fwUpdateSafe.License.ValidTo = dateTime;
|
|
//var addDays = fwUpdateSafe.SafeInfo.FwUpdateValidDate.AddDays(-1);
|
|
//fwUpdateSafe.SafeInfo.FwUpdateValidDate = addDays;
|
|
////TODO THW remove this DEBUG to map from current selection to TEST BOARD
|
|
|
|
var serializedData = JsonConvert.SerializeObject(fwUpdateSafe);
|
|
var asciiStream = Encoding.ASCII.GetBytes(serializedData);
|
|
|
|
// the build primary key
|
|
BuildPrimaryKey(lblUpdateOperator.Text);
|
|
if (_primaryKey == null)
|
|
{
|
|
LogErrorText(Resources.StrUserInformationMissing);
|
|
MessageBoxShow(Resources.StrUserInformationMissing, Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
|
|
var encryptedStream = FwUpdateCrypt.Encrypt(asciiStream, _primaryKey);
|
|
|
|
// prepare FwUpdateSafeDb
|
|
if (string.IsNullOrEmpty(_regUser.FullName))
|
|
_regUser.FullName = "";
|
|
_fwUpdateSafeDb = new FwUpdateSafeDb
|
|
{
|
|
BuilderOperatorName = _regUser.FullName,
|
|
Name = _fwUpdateSafeName,
|
|
UserId = _updateOperatorId,
|
|
Content = encryptedStream,
|
|
ValidDate = new DateTimeOffset(fwUpdateSafe.License.ValidTo)
|
|
};
|
|
|
|
//assign FW update safe
|
|
var fwUpdateSafeFile = Path.Combine(FwUpdateSafePath, _fwUpdateSafeName);
|
|
File.WriteAllBytes(fwUpdateSafeFile, encryptedStream);
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
LogErrorText(Resources.StrFwUpdateSafeBuiltFailed);
|
|
MessageBoxShow(e.ToString(), Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Collect cordonel device info, the user has to input the required pcbIds and release versions in advance!
|
|
/// </summary>
|
|
/// <remarks date="2021-Jan-27" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-02" author="Thomas Wiedebusch">
|
|
/// - Load from DB.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-23" author="Thomas Wiedebusch">
|
|
/// - Kick off DB connection with dummy request.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Password container directly assigned.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-09" author="Thomas Wiedebusch">
|
|
/// - Recovery registers.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-07" author="Thomas Wiedebusch">
|
|
/// - Power correction.
|
|
/// </remarks>
|
|
private void CompleteCordonelDeviceInfos()
|
|
{
|
|
// get the real passwords
|
|
foreach (var cordonelDeviceInfo in _cordonelUpdateList)
|
|
{
|
|
|
|
var fwUpdateCapability = new FwUpdateCapability
|
|
{
|
|
PcbId = cordonelDeviceInfo.PcbId,
|
|
PasswordContainerLoaded = GetPwdFromDb(cordonelDeviceInfo)
|
|
};
|
|
|
|
// stop collection of data if the password container cannot be loaded
|
|
if (!fwUpdateCapability.PasswordContainerLoaded)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// load a single release if not already done
|
|
fwUpdateCapability.ReleaseContainerLoaded = GetFwPackageFromDb(cordonelDeviceInfo.RequiredFwRelease);
|
|
|
|
// load a recovery file
|
|
fwUpdateCapability.RecoveryNotNeededOrLoaded = GetRecoveryRegistersFromDb(cordonelDeviceInfo);
|
|
|
|
// load power correction infos;
|
|
// Installed FW version has to be known in advance and
|
|
// FW package has to be loaded in advance to check for installed versus required FW version as this is the base
|
|
// for the decision of needed power correction.
|
|
if (_fwUpdatePackage.FwPackageInfo.Version != null && cordonelDeviceInfo.InstalledFwVersion != null
|
|
&& ((_fwUpdatePackage.FwPackageInfo.Region ==
|
|
"EMEA" && _fwUpdatePackage.FwPackageInfo.Version >= PowCorrConst.EmeaFwThresholdForPowCorr
|
|
&& cordonelDeviceInfo.InstalledFwVersion < PowCorrConst.EmeaFwThresholdForPowCorr)
|
|
|| (_fwUpdatePackage.FwPackageInfo.Region ==
|
|
"NA" && _fwUpdatePackage.FwPackageInfo.Version >= PowCorrConst.NaFNaFwThresholdForPowCorr
|
|
&& cordonelDeviceInfo.InstalledFwVersion < PowCorrConst.NaFNaFwThresholdForPowCorr)))
|
|
{
|
|
fwUpdateCapability.PowerCorrectionNotNeededOrLoaded = GetPowerCorrectionsFromDb(cordonelDeviceInfo);
|
|
}
|
|
else
|
|
{
|
|
cordonelDeviceInfo.PowerCorrectionValues = null;
|
|
fwUpdateCapability.PowerCorrectionNotNeededOrLoaded = true;
|
|
}
|
|
|
|
// avoid multiple assignments with deviating information before adding the new generated object
|
|
foreach (var x in _fwUpdateCapability.Where(x => x.PcbId == cordonelDeviceInfo.PcbId))
|
|
{
|
|
_fwUpdateCapability.Remove(x);
|
|
break;
|
|
}
|
|
|
|
_fwUpdateCapability.Add(fwUpdateCapability);
|
|
}
|
|
}
|
|
|
|
|
|
#endregion --------------------------------------- Build FW-Update Safe ---------------------------------------
|
|
|
|
#region ------------------------------------------ Checks -----------------------------------------------------
|
|
/// <summary>
|
|
/// Check the user registration from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2024-Apr-11" author="Thomas Wiedebusch">
|
|
/// - Added builder operator id.
|
|
/// </remarks>
|
|
private void CheckUserRegistration()
|
|
{
|
|
if (_fwUpdateDbAccess == null || _regUser == null)
|
|
return;
|
|
_regUser.Domain = CryptInformation.GetSysDomain();
|
|
_regUser.LogInName = CryptInformation.GetSysUserLoginName();
|
|
_fwUpdateDbAccess.GetAllBuilderOperatorsFromDb();
|
|
|
|
// If the connection to the DB cannot be established
|
|
if (!_fwUpdateDbAccess.GetAllBuilderOperatorsFromDb() ||
|
|
_fwUpdateDbAccess.DbAllBuilderOperators == null ||
|
|
_fwUpdateDbAccess.DbAllBuilderOperators.Count == 0)
|
|
return;
|
|
|
|
// search for this system user specified by Domain and LogInName
|
|
foreach (var user in _fwUpdateDbAccess.DbAllBuilderOperators.Where(user => user.Domain == _regUser.Domain &&
|
|
user.LogInName == _regUser.LogInName))
|
|
{
|
|
_regUser.AccountActive = user.AccountActive;
|
|
_regUser.FullName = user.FullName;
|
|
_regUser.Id = user.Id;
|
|
break;
|
|
}
|
|
|
|
if (_regUser.AccountActive)
|
|
{
|
|
EnableInputsInvoked();
|
|
_processState = ProcessState.Idle;
|
|
return;
|
|
}
|
|
DisableControlsExceptLanguageInvoked();
|
|
_processState = ProcessState.DbAccessLocked;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pre-select FW package if not already set.
|
|
/// Uses all information of fw-package-info from DB and cordonel-info from DB.
|
|
/// Presets the Approval or Removal based on the update capability check.
|
|
/// The _fwUpdatePackage information has to be preset in advance.
|
|
/// </summary>
|
|
/// <remarks date="2022-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Dec-01" author="Thomas Wiedebusch">
|
|
/// - Single FW-Update package,
|
|
/// - Used fw update package id instead of name.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Feb-19" author="Thomas Wiedebusch">
|
|
/// - Reason for check error added.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Feb-20" author="Thomas Wiedebusch">
|
|
/// - Extended update capability check.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Feb-24" author="Thomas Wiedebusch">
|
|
/// - Meter size check corrected.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Mar-17" author="Thomas Wiedebusch">
|
|
/// - FW-packages with multiple meter sizes supported in update capability check,
|
|
/// - FW-packages checked for multiple radio frequencies.
|
|
/// </remarks>
|
|
private String PreSelectFwPackages(CordonelProductionInfosDb cordonelDbInfo)
|
|
{
|
|
if (cordonelDbInfo == null)
|
|
return Constants.StrUnknown;
|
|
|
|
// preset to not approved to leave the approval open for user in the "pre-build summary" tab
|
|
cordonelDbInfo.IsRemoved = true;
|
|
cordonelDbInfo.IsApproved = false;
|
|
cordonelDbInfo.RequiredReleaseNameVersion = null;
|
|
cordonelDbInfo.ReasonForUpdateDenial = "";
|
|
|
|
// the _fwUpdatePackage has to be filled with all needed information being able to compare this with
|
|
// the information about the Cordonel which should be updated
|
|
if (_fwUpdatePackage?.FwPackageInfo == null || _fwUpdateDbAccess?.DbCordonelFwPackagesInfo == null)
|
|
{
|
|
return Constants.StrUnknown;
|
|
}
|
|
|
|
// catch all meter sizes of a different entry but the identical FW-package references by name
|
|
var fwMeterSizes = new List<String>();
|
|
// catch multiple radio frequencies
|
|
Int32? fwRadioFrequencyMhz = null;
|
|
Int32? fwCoreRevisionMax = null;
|
|
Int32? fwCoreRevisionMin = null;
|
|
Int32? fwMetrologyVersion = null;
|
|
var fwRegion = "";
|
|
|
|
// search in the list of all FW-packages infos for the user selected Id
|
|
foreach (var fw in _fwUpdateDbAccess.DbCordonelFwPackagesInfo.Where(
|
|
fw => _fwUpdatePackage.FwPackageInfo.Id == fw.Id))
|
|
{
|
|
// From here the FW-package is detected by its Id
|
|
// assign the unique version for all devices, even if these are having a lack of information
|
|
cordonelDbInfo.RequiredReleaseNameVersion = fw.Name;
|
|
fwRadioFrequencyMhz = fw.RadioFrequencyMhz;
|
|
fwCoreRevisionMax = fw.CoreRevisionMax;
|
|
fwCoreRevisionMin = fw.CoreRevisionMin;
|
|
fwMetrologyVersion = fw.MetrologyVersion;
|
|
fwRegion = fw.Region;
|
|
fwMeterSizes.Add(fw.MeterSize);
|
|
// As the first package has been found, the loop can be exited.
|
|
break;
|
|
}
|
|
|
|
// Collect all meter sizes and from identical FW-package(s)
|
|
foreach (var fw in _fwUpdateDbAccess.DbCordonelFwPackagesInfo.Where(
|
|
fw => fw.Name == cordonelDbInfo.RequiredReleaseNameVersion))
|
|
{
|
|
// on a package with multiple frequency support set the frequency to null to skip radio check
|
|
// in the FW-Update SW
|
|
if (fw.RadioFrequencyMhz != fwRadioFrequencyMhz)
|
|
{
|
|
fwRadioFrequencyMhz = null;
|
|
}
|
|
|
|
// check multiple meter sizes in the FW-Update SW
|
|
if (fwMeterSizes.All(size => size != fw.MeterSize))
|
|
{
|
|
fwMeterSizes.Add(fw.MeterSize);
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
var checkPassed = true;
|
|
// if the installed version is unknown or not set, leave the approval to the user
|
|
if (string.IsNullOrEmpty(cordonelDbInfo.CoreRevision) || cordonelDbInfo.CoreRevision == Constants.StrUnknown)
|
|
{
|
|
cordonelDbInfo.ReasonForUpdateDenial = Resources.StrUpdateCapabilityCheckCore;
|
|
checkPassed = false;
|
|
}
|
|
else
|
|
{
|
|
// extract the Cordonel core version and validate it
|
|
var coreVersion = cordonelDbInfo.CoreRevision;
|
|
coreVersion = coreVersion.Replace(".", "");
|
|
Int32.TryParse(coreVersion, out var requiredCoreVersion);
|
|
if (requiredCoreVersion > fwCoreRevisionMax || requiredCoreVersion < fwCoreRevisionMin)
|
|
{
|
|
cordonelDbInfo.ReasonForUpdateDenial = "|";
|
|
cordonelDbInfo.ReasonForUpdateDenial = Resources.StrUpdateCapabilityCheckCore;
|
|
checkPassed = false;
|
|
}
|
|
|
|
}
|
|
|
|
// check the completeness of information in DB of the Cordonel region
|
|
if (string.IsNullOrEmpty(cordonelDbInfo.Region) || cordonelDbInfo.Region != fwRegion)
|
|
{
|
|
cordonelDbInfo.ReasonForUpdateDenial += "|";
|
|
cordonelDbInfo.ReasonForUpdateDenial += Resources.StrUpdateCapabilityCheckRegion;
|
|
checkPassed = false;
|
|
}
|
|
|
|
// check radio but skip check for NA region or if FW-package supports all frequencies indicated
|
|
// by null for the FW-package info frequency field
|
|
if (cordonelDbInfo.Region != "NA" && fwRadioFrequencyMhz != null)
|
|
{
|
|
// check the radio frequencies
|
|
if (string.IsNullOrEmpty(cordonelDbInfo.RadioFrequency)
|
|
|| cordonelDbInfo.RadioFrequency == Constants.StrUnknown
|
|
|| string.IsNullOrEmpty(fwRadioFrequencyMhz.ToString())
|
|
|| cordonelDbInfo.RadioFrequency != fwRadioFrequencyMhz.ToString())
|
|
{
|
|
cordonelDbInfo.ReasonForUpdateDenial += "|";
|
|
cordonelDbInfo.ReasonForUpdateDenial += Resources.StrUpdateCapabilityCheckRadio;
|
|
checkPassed = false;
|
|
}
|
|
}
|
|
|
|
// if meter size does not fit and not for all meter sizes
|
|
if (cordonelDbInfo.Diameter == Constants.StrUnknown
|
|
|| (fwMeterSizes.All(meterSize => meterSize != cordonelDbInfo.Diameter)
|
|
&& fwMeterSizes.Any(meterSize => meterSize != Constants.StrWildcard)))
|
|
{
|
|
cordonelDbInfo.ReasonForUpdateDenial += "|";
|
|
cordonelDbInfo.ReasonForUpdateDenial += Resources.StrUpdateCapabilityCheckMeterSize;
|
|
checkPassed = false;
|
|
}
|
|
|
|
// if the installed version is unknown or not set, leave the approval to the user
|
|
if (string.IsNullOrEmpty(cordonelDbInfo.Metrology) || cordonelDbInfo.Metrology == Constants.StrUnknown)
|
|
{
|
|
cordonelDbInfo.ReasonForUpdateDenial += "|";
|
|
cordonelDbInfo.ReasonForUpdateDenial += Resources.StrUpdateCapabilityCheckMetrokogy;
|
|
checkPassed = false;
|
|
}
|
|
else
|
|
{
|
|
// extract the metrology version and validate it
|
|
var metrologyVersion = cordonelDbInfo.Metrology;
|
|
metrologyVersion = metrologyVersion.Replace(".", "");
|
|
Int32.TryParse(metrologyVersion, out var requiredMetrologyVersion);
|
|
if (requiredMetrologyVersion != fwMetrologyVersion)
|
|
{
|
|
cordonelDbInfo.ReasonForUpdateDenial += "|";
|
|
cordonelDbInfo.ReasonForUpdateDenial += Resources.StrUpdateCapabilityCheckMetrokogy;
|
|
checkPassed = false;
|
|
}
|
|
|
|
}
|
|
if (checkPassed)
|
|
{
|
|
cordonelDbInfo.IsRemoved = false;
|
|
cordonelDbInfo.IsApproved = true;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return Constants.StrUnknown;
|
|
}
|
|
|
|
return cordonelDbInfo.RequiredReleaseNameVersion;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check DB connection timeout during connectivity check
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-09" author="Thomas Wiedebusch">
|
|
/// - Avoid interruption if DB is connected.
|
|
/// </remarks>
|
|
private void CheckDbConnectionTimeout()
|
|
{
|
|
// stop connectivity test after response timeout
|
|
if (_fwUpdateDbAccess == null || _fwUpdateDbAccess.DbIsConnected ||
|
|
_dbAccessDelayCtrMs <= DbConnectionTimeoutMs)
|
|
return;
|
|
|
|
EnableInputsInvoked();
|
|
_dbAccessDelayCtrMs = 0;
|
|
SetStatusProgressBar(0, false);
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check DB license refresh.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void RefreshLicense()
|
|
{
|
|
if (DateTimeOffset.Compare(_licenseValidDateTimeOffset, DateTimeOffset.Now) < 0)
|
|
_licenseUnchecked = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check DB connectivity.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-26" author="Thomas Wiedebusch">
|
|
/// - Progress bar off if connection lost.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - On initialized DB connection fire the tabControl event to update user view,
|
|
/// - dbAccessLocked introduced.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Disabled: On initialized DB connection fire the tabControl event to update user view.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Check for license.
|
|
/// </remarks>
|
|
private void CheckDbConnectivity()
|
|
{
|
|
if (_fwUpdateDbAccess.DbIsConnected)
|
|
{
|
|
// DB is free to use
|
|
|
|
if (_dbLicenseRefreshDelayCtrMs > DbLicenseRefreshTimeoutMs)
|
|
{
|
|
_dbLicenseRefreshDelayCtrMs = 0;
|
|
RefreshLicense();
|
|
if (_licenseUnchecked)
|
|
_processState = ProcessState.ValidateSoftware;
|
|
}
|
|
|
|
// If the progress bar is visible, the DB connection status has just changed from NOT connected
|
|
if (!ProgressBarStatus.Visible && lblStatusDbConnect.Text != Resources.StrNotConnectedToDb)
|
|
return;
|
|
|
|
// Stop connection test
|
|
SetStatusProgressBar(0, false);
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrConnectedToDb);
|
|
|
|
// enable controls only if software license has been checked
|
|
EnableInputsInvoked();
|
|
}
|
|
else
|
|
{
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorProcessFailed, Resources.StrNotConnectedToDb);
|
|
if (ProgressBarStatus.Visible)
|
|
SetStatusProgressBar(0, false);
|
|
|
|
// kick off new connectivity check if retry delay exceeded and DB is NOT connected
|
|
if (_dbAccessDelayCtrMs <= DbConnectionRetryDelayMs)
|
|
return;
|
|
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrConnectingToDb);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
|
|
_processState = ProcessState.ConnectDb;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check all required data needed to input for FW-Update safe and enables/disables the [FW Update] button.
|
|
/// This colors the labels and tabs to inform the user about the lack of data.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-26" author="Thomas Wiedebusch">
|
|
/// - [Build FW-Update Safe] check extended
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-29" author="Thomas Wiedebusch">
|
|
/// - checks extended,
|
|
/// - avoid repeated setup of item if already done.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Added builder license check.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - FW-Update package status added.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Check order numbers.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-09" author="Thomas Wiedebusch">
|
|
/// - Check fw packages.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Lock customer search button if customer is selected to avoid lose of information on new search.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Today is a valid day.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Metrology search items added.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Pre-Build summary check.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-17" author="Thomas Wiedebusch">
|
|
/// - Cordonel selection check moved to production pre select.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-18" author="Thomas Wiedebusch">
|
|
/// - Cordonel selection check and Cordonel approval check differentiate.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-29" author="Thomas Wiedebusch">
|
|
/// - Use selected Cordonels to fill the FW package search infos.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Nov-29" author="Thomas Wiedebusch">
|
|
/// - Single FW-Update package.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Feb-21" author="Thomas Wiedebusch">
|
|
/// - Preselect the search mask with last search items set by Cordonel selection to simplify the initial
|
|
/// FW-package selection.
|
|
/// </remarks>
|
|
private void CheckDataCollectionStatus()
|
|
{
|
|
// Customer Orders ----------------------------------------------------------------------------------------
|
|
// Check the order numbers (add one for the "*" )
|
|
if (_fwUpdateDbAccess?.DbCordonelCustomerOrders != null)
|
|
{
|
|
if (cbxCordonelProductionOrdersSearch.Items.Count !=
|
|
_fwUpdateDbAccess.DbCordonelCustomerOrders.Count + 1)
|
|
{
|
|
cbxCordonelProductionOrdersSearch.Items.Clear();
|
|
cbxCordonelProductionOrdersSearch.Text = Constants.StrWildcard;
|
|
cbxCordonelProductionOrdersSearch.Items.Add(Constants.StrWildcard);
|
|
foreach (var order in _fwUpdateDbAccess.DbCordonelCustomerOrders)
|
|
{
|
|
cbxCordonelProductionOrdersSearch.Items.Add(
|
|
$@"{order.CustomerOrderNumber}-{order.CustomerOrderPos}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update Operator ----------------------------------------------------------------------------------------
|
|
// Set the background color for update operator and use it later for comparison to enable button
|
|
var backGroundColor = string.IsNullOrEmpty(lblUpdateOperator.Text) ? ColorBkMissing : ColorBkValid;
|
|
if (backGroundColor != lblUpdateOperator.BackColor)
|
|
{
|
|
lblUpdateOperator.BackColor = backGroundColor;
|
|
if (backGroundColor == ColorBkMissing)
|
|
{
|
|
tabPageUpdateOperator.ImageIndex = 0;
|
|
}
|
|
else
|
|
tabPageUpdateOperator.ImageIndex = 1;
|
|
}
|
|
|
|
// Validation Time for FW update --------------------------------------------------------------------------
|
|
// Time for update validation has been properly set time including today (offset needed as the time
|
|
// will count up continuously)
|
|
backGroundColor = DateTime.Compare(DateTimeServer.GetDateTimeFromDateString(lblFwUpdateDutyDate.Text +
|
|
" 23:59:59", _cultureInfo), DateTime.Now) > 0 ? ColorBkValid : ColorBkMissing;
|
|
if (backGroundColor != lblFwUpdateDutyDate.BackColor)
|
|
{
|
|
lblFwUpdateDutyDate.BackColor = backGroundColor;
|
|
}
|
|
|
|
// Customer Name ------------------------------------------------------------------------------------------
|
|
backGroundColor = string.IsNullOrEmpty(tbxCustomerName.Text) ? ColorBkMissing : ColorBkValid;
|
|
if (backGroundColor != tbxCustomerName.BackColor)
|
|
{
|
|
tbxCustomerName.BackColor = backGroundColor;
|
|
lblCustomerNumber.BackColor = backGroundColor;
|
|
if (backGroundColor == ColorBkMissing)
|
|
{
|
|
tabPageCustomerSelection.ImageIndex = 0;
|
|
lblInfoSelectCustomer.Visible = true;
|
|
btnSearchCustomer.Enabled = true;
|
|
}
|
|
else
|
|
{
|
|
tabPageCustomerSelection.ImageIndex = 1;
|
|
lblInfoSelectCustomer.Visible = false;
|
|
btnSearchCustomer.Enabled = false;
|
|
}
|
|
}
|
|
|
|
// Customer Cordonels Search for this production number ---------------------------------------------------
|
|
if (tbxCordonelsCustomerCount.Text != _cordonelProductionSearchInfos.Count.ToString())
|
|
tbxCordonelsCustomerCount.Text = _cordonelProductionSearchInfos.Count.ToString();
|
|
backGroundColor = _cordonelProductionSearchInfos.Count == 0 ? ColorBkMissing : ColorBkValid;
|
|
if (backGroundColor != tbxCordonelsCustomerCount.BackColor)
|
|
{
|
|
tbxCordonelsCustomerCount.BackColor = backGroundColor;
|
|
}
|
|
|
|
// Selected Cordonels -------------------------------------------------------------------------------------
|
|
if (lblCordonelsSelectedCount.Text != _cordonelProductionPreSelectInfos.Count.ToString())
|
|
lblCordonelsSelectedCount.Text = _cordonelProductionPreSelectInfos.Count.ToString();
|
|
backGroundColor = _cordonelProductionPreSelectInfos.Count == 0 ? ColorBkMissing : ColorBkValid;
|
|
if (backGroundColor != lblCordonelsSelectedCount.BackColor)
|
|
{
|
|
lblCordonelsSelectedCount.BackColor = backGroundColor;
|
|
}
|
|
|
|
if (_cordonelProductionPreSelectInfos.Count == 0)
|
|
{
|
|
if (tabPageCordonelSelection.ImageIndex != 0)
|
|
tabPageCordonelSelection.ImageIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
if (tabPageCordonelSelection.ImageIndex != 1)
|
|
tabPageCordonelSelection.ImageIndex = 1;
|
|
}
|
|
|
|
// Selected FW-Packages -----------------------------------------------------------------------------------
|
|
// Add fw packages to fw package selection combo box for Cordonel FW to install selection
|
|
if (_fwUpdateDbAccess?.DbCordonelFwPackage != null && _fwUpdatePackage?.FwPackageInfo != null &&
|
|
_cbxFwReleaseSelection != null)
|
|
{
|
|
if (_cbxFwReleaseSelection.Items.Count < 1)
|
|
{
|
|
_cbxFwReleaseSelection.Items.Clear();
|
|
_cbxFwReleaseSelection.Items.Add(_fwUpdatePackage.FwPackageInfo.Name);
|
|
}
|
|
}
|
|
|
|
// Check if FW packages are selected
|
|
if (_fwUpdatePackage?.FwPackageInfo != null && lblSelectedFwPackages.Text != @"1")
|
|
lblSelectedFwPackages.Text = @"1";
|
|
else if (_fwUpdatePackage?.FwPackageInfo == null)
|
|
lblSelectedFwPackages.Text = @"0";
|
|
backGroundColor = _fwUpdatePackage?.FwPackageInfo == null ? ColorBkMissing : ColorBkValid;
|
|
|
|
if (backGroundColor != lblSelectedFwPackages.BackColor)
|
|
{
|
|
lblSelectedFwPackages.BackColor = backGroundColor;
|
|
if (backGroundColor == ColorBkMissing)
|
|
{
|
|
if (!btnFwPackageSearch.Enabled)
|
|
btnFwPackageSearch.Enabled = true;
|
|
tabPageFwPackageSelection.ImageIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
if (btnFwPackageSearch.Enabled)
|
|
btnFwPackageSearch.Enabled = false;
|
|
tabPageFwPackageSelection.ImageIndex = 1;
|
|
}
|
|
}
|
|
|
|
// check if FW packages are loaded from DB and parsed to the search info to extract radio info
|
|
if (_radioSearchItems.Count + 1 != cbxFwPackageRadioMask.Items.Count)
|
|
{
|
|
cbxFwPackageRadioMask.Items.Clear();
|
|
cbxFwPackageRadioMask.Items.Add(Constants.StrWildcard);
|
|
foreach (var item in _radioSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != Constants.StrUnknown)
|
|
cbxFwPackageRadioMask.Items.Add(item);
|
|
}
|
|
var index = cbxFwPackageRadioMask.Items.Count - 1;
|
|
cbxFwPackageRadioMask.Text = cbxFwPackageRadioMask.Items[index].ToString();
|
|
_fwPackagePropertyChanged = true;
|
|
}
|
|
|
|
// check if FW packages are loaded from DB and parsed to the search info to extract region info
|
|
if (_regionSearchItems.Count + 1 != cbxFwPackageRegionMask.Items.Count)
|
|
{
|
|
cbxFwPackageRegionMask.Items.Clear();
|
|
cbxFwPackageRegionMask.Items.Add(Constants.StrWildcard);
|
|
foreach (var item in _regionSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != Constants.StrUnknown)
|
|
cbxFwPackageRegionMask.Items.Add(item);
|
|
}
|
|
var index = cbxFwPackageRegionMask.Items.Count - 1;
|
|
cbxFwPackageRegionMask.Text = cbxFwPackageRegionMask.Items[index].ToString();
|
|
_fwPackagePropertyChanged = true;
|
|
}
|
|
// check if FW packages are loaded from DB and parsed to the search info to extract size info
|
|
if (_sizeSearchItems.Count + 1 != cbxFwPackageSizeMask.Items.Count)
|
|
{
|
|
cbxFwPackageSizeMask.Items.Clear();
|
|
cbxFwPackageSizeMask.Items.Add(Constants.StrWildcard);
|
|
foreach (var item in _sizeSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != Constants.StrUnknown)
|
|
cbxFwPackageSizeMask.Items.Add(item);
|
|
}
|
|
var index = cbxFwPackageSizeMask.Items.Count - 1;
|
|
cbxFwPackageSizeMask.Text = cbxFwPackageSizeMask.Items[index].ToString();
|
|
_fwPackagePropertyChanged = true;
|
|
}
|
|
// check if FW packages are loaded from DB and parsed to the search info to extract metrology info
|
|
if (_metrologySearchItems.Count + 1 != cbxFwPackageMetrologyMask.Items.Count)
|
|
{
|
|
cbxFwPackageMetrologyMask.Items.Clear();
|
|
cbxFwPackageMetrologyMask.Items.Add(Constants.StrWildcard);
|
|
foreach (var item in _metrologySearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != Constants.StrUnknown)
|
|
cbxFwPackageMetrologyMask.Items.Add(item);
|
|
}
|
|
var index = cbxFwPackageMetrologyMask.Items.Count - 1;
|
|
cbxFwPackageMetrologyMask.Text = cbxFwPackageMetrologyMask.Items[index].ToString();
|
|
_fwPackagePropertyChanged = true;
|
|
}
|
|
// check if FW packages are loaded from DB and parsed to the search info to extract core info
|
|
if (_coreSearchItems.Count + 1 != cbxFwPackageCoreMak.Items.Count)
|
|
{
|
|
cbxFwPackageCoreMak.Items.Clear();
|
|
cbxFwPackageCoreMak.Items.Add(Constants.StrWildcard);
|
|
foreach (var item in _coreSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != Constants.StrUnknown)
|
|
cbxFwPackageCoreMak.Items.Add(item);
|
|
}
|
|
var index = cbxFwPackageCoreMak.Items.Count - 1;
|
|
cbxFwPackageCoreMak.Text = cbxFwPackageCoreMak.Items[index].ToString();
|
|
_fwPackagePropertyChanged = true;
|
|
}
|
|
|
|
// FW-Update Order Number ---------------------------------------------------------------------------------
|
|
backGroundColor = string.IsNullOrEmpty(tbxOrderNumber.Text) ? ColorBkMissing : ColorBkValid;
|
|
if (backGroundColor != tbxOrderNumber.BackColor)
|
|
{
|
|
tbxOrderNumber.BackColor = backGroundColor;
|
|
tbxOrderPosition.BackColor = backGroundColor;
|
|
}
|
|
|
|
// FW-Update Safe Upload Capability -----------------------------------------------------------------------
|
|
if (btnUploadSafeToDb.Enabled != _enableFwSafeUpload)
|
|
{
|
|
btnUploadSafeToDb.Enabled = _enableFwSafeUpload;
|
|
}
|
|
|
|
// Pre Build Summary Check --------------------------------------------------------------------------------
|
|
// search for missing approval in production list or missing FW update package
|
|
var updateLocked = (_cordonelProductionPreSelectInfos.Count == 0 ||
|
|
_cordonelProductionPreSelectInfos.Any(prodCord =>
|
|
!prodCord.IsApproved && prodCord.IsSelected)) ||
|
|
_cordonelUpdateList.Any(updCord => string.IsNullOrEmpty(updCord.RequiredFwRelease) ||
|
|
updCord.RequiredFwRelease == Constants.StrUnknown);
|
|
|
|
if (updateLocked)
|
|
{
|
|
if (tabPagePreBuildSummary.ImageIndex != 0)
|
|
tabPagePreBuildSummary.ImageIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
if (tabPagePreBuildSummary.ImageIndex != 1)
|
|
tabPagePreBuildSummary.ImageIndex = 1;
|
|
}
|
|
|
|
// Approved Cordonels -------------------------------------------------------------------------------------
|
|
if (lblCordonelsApprovedCount.Text != _cordonelUpdateList.Count.ToString())
|
|
lblCordonelsApprovedCount.Text = _cordonelUpdateList.Count.ToString();
|
|
backGroundColor = _cordonelUpdateList.Count == 0 ? ColorBkMissing : ColorBkValid;
|
|
if (backGroundColor != lblCordonelsApprovedCount.BackColor)
|
|
{
|
|
lblCordonelsApprovedCount.BackColor = backGroundColor;
|
|
}
|
|
|
|
// Control Activation/ Deactivation -----------------------------------------------------------------------
|
|
if (_fwUpdateDbAccess != null && !_fwUpdateDbAccess.DbIsConnected)
|
|
{
|
|
if (btnBuildFwUpdateSafe.Enabled)
|
|
btnBuildFwUpdateSafe.Enabled = false;
|
|
if (btnLicenseFwUpdateSw.Enabled)
|
|
btnLicenseFwUpdateSw.Enabled = false;
|
|
if (btnLicenseFwUpdateBuilder.Enabled)
|
|
btnLicenseFwUpdateBuilder.Enabled = false;
|
|
if (btnCordonelSearch.Enabled)
|
|
btnCordonelSearch.Enabled = false;
|
|
if (btnSearchCustomer.Enabled)
|
|
btnSearchCustomer.Enabled = false;
|
|
}
|
|
else
|
|
{
|
|
// license can be activated soon the DB is connected
|
|
if (!btnLicenseFwUpdateSw.Enabled)
|
|
btnLicenseFwUpdateSw.Enabled = true;
|
|
if (!btnLicenseFwUpdateBuilder.Enabled)
|
|
btnLicenseFwUpdateBuilder.Enabled = true;
|
|
if (!string.IsNullOrEmpty(lblCustomerNumber.Text) && !btnCordonelSearch.Enabled)
|
|
btnCordonelSearch.Enabled = true;
|
|
if (string.IsNullOrEmpty(lblCustomerNumber.Text) && btnCordonelSearch.Enabled)
|
|
btnCordonelSearch.Enabled = false;
|
|
|
|
// enable FW-Update Safe generation button
|
|
if (lblUpdateOperator.BackColor != ColorBkValid ||
|
|
lblFwUpdateDutyDate.BackColor != ColorBkValid ||
|
|
tbxCustomerName.BackColor != ColorBkValid ||
|
|
tbxOrderNumber.BackColor != ColorBkValid ||
|
|
_fwUpdatePackage == null ||
|
|
_cordonelUpdateList.Count == 0 ||
|
|
updateLocked)
|
|
{
|
|
if (btnBuildFwUpdateSafe.Enabled)
|
|
btnBuildFwUpdateSafe.Enabled = false;
|
|
return;
|
|
}
|
|
|
|
if (!btnBuildFwUpdateSafe.Enabled)
|
|
btnBuildFwUpdateSafe.Enabled = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check for change in user account.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Locked if operators are not loaded.
|
|
/// </remarks>
|
|
private void CheckUpdateOperatorAccountChange()
|
|
{
|
|
if (!_fwUpdateOperatorsPropertyChanged || _fwUpdateDbAccess?.DbFullQualifiedUpdateOperators == null ||
|
|
_fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Count == 0)
|
|
return;
|
|
|
|
_fwUpdateOperatorsPropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithUpdateOperatorInfos();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check for change of customer.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Locked if customers are not loaded.
|
|
/// </remarks>
|
|
private void CheckCustomerChange()
|
|
{
|
|
if (!_customersPropertyChanged || _fwUpdateDbAccess?.DbSearchedCordonelCustomers == null ||
|
|
_fwUpdateDbAccess.DbSearchedCordonelCustomers.Count == 0)
|
|
return;
|
|
|
|
_customersPropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithCustomerInfos();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check for change of Cordonels.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Locked if Cordonels are not loaded.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Added pre build summary.
|
|
/// </remarks>
|
|
private void CheckCordonelChange()
|
|
{
|
|
if (_cordonelsPropertyChanged)
|
|
{
|
|
_cordonelsPropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithCordonelInfos();
|
|
}
|
|
|
|
if (!_preBuildSummaryPropertyChanged)
|
|
return;
|
|
|
|
_preBuildSummaryPropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithPreBuildSummaryInfos();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check for change of FW-Update packages.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Locked if FW-Packages are not loaded.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Dec-01" author="Thomas Wiedebusch">
|
|
/// - Take FW package info.
|
|
/// </remarks>
|
|
private void CheckFwPackageChange()
|
|
{
|
|
if (!_fwPackagePropertyChanged || _fwUpdateDbAccess?.DbCordonelFwPackagesInfo == null ||
|
|
_fwUpdateDbAccess.DbCordonelFwPackagesInfo.Count == 0)
|
|
return;
|
|
|
|
_fwPackagePropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithFwPackageInfos();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check for change of report files.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void CheckReportsChange()
|
|
{
|
|
if (!_fwReportsPropertyChanged)
|
|
return;
|
|
|
|
_fwReportsPropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithReportsInfos();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check for change of Fw update safes.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void CheckFwUpdateSafesChange()
|
|
{
|
|
if (!_fwUpdateSafesPropertyChanged)
|
|
return;
|
|
|
|
_fwUpdateSafesPropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithFwUpdateSafesInfos();
|
|
}
|
|
#endregion --------------------------------------- Checks -----------------------------------------------------
|
|
|
|
#region ------------------------------------------ Tools ------------------------------------------------------
|
|
|
|
///// <summary>
|
|
///// Build the meter file erase restore information and export to MeterFilesConfigFilePathName.
|
|
///// </summary>
|
|
///// <remarks date="2021-Feb-17" author="Thomas Wiedebusch">
|
|
///// - Initial.
|
|
///// </remarks>
|
|
//public void BuildMeterFilesEraseRestoreInfo()
|
|
//{
|
|
// // loading the lists of meter files which shall be erased before the FW-Update and restored after.
|
|
// var meterFilesEraseRestore = new MeterFilesEraseRestore
|
|
// {
|
|
// Erase = new List<String>
|
|
// {
|
|
// "1\\tstfile",
|
|
// "1\\fdrdata",
|
|
// "1\\logdata",
|
|
// "1\\blklist",
|
|
// "1\\mettable",
|
|
// "1\\pulsedbg",
|
|
// "1\\upg*",
|
|
// "1\\img*"
|
|
// }
|
|
// };
|
|
// var meterFileRestore = new MeterFileRestore
|
|
// {
|
|
// Name = "1\\tstfile",
|
|
// ByteSize = 262144,
|
|
// Pattern = null
|
|
// };
|
|
// meterFilesEraseRestore.Restore = new List<MeterFileRestore>
|
|
// {
|
|
// meterFileRestore
|
|
// };
|
|
|
|
// var text = JsonConvert.SerializeObject(meterFilesEraseRestore);
|
|
// var asciiStream = Encoding.UTF8.GetBytes(text);
|
|
// File.WriteAllBytes(FwUpdateConfig.MeterFilesEraseRestoreConfigFileName, asciiStream);
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Error processes.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void ErrorProcesses()
|
|
{
|
|
// take the invoker of the error state to generate the message and / or popup window
|
|
switch (_invokerProcessState)
|
|
{
|
|
default:
|
|
_processState = ProcessState.Idle;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stop all ongoing processes.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void StopProcesses()
|
|
{
|
|
// take the invoker of the error state to generate the message and / or popup window
|
|
switch (_invokerProcessState)
|
|
{
|
|
default:
|
|
_processState = ProcessState.Idle;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common message window.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-29" author="Thomas Wiedebusch">
|
|
/// - Forcing message box being modal and on top.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Nov-14" author="Thomas Wiedebusch">
|
|
/// - Return user selection.
|
|
/// </remarks>
|
|
private static DialogResult MessageBoxShow(String text, String caption,
|
|
MessageBoxButtons buttons = MessageBoxButtons.OK,
|
|
MessageBoxIcon icon = MessageBoxIcon.Asterisk)
|
|
{
|
|
return MessageBox.Show(text, caption, buttons, icon, MessageBoxDefaultButton.Button1,
|
|
MessageBoxOptions.ServiceNotification);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Output exclusively to user update remarks text window.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-26" author="Thomas Wiedebusch">
|
|
/// - Color added.
|
|
/// </remarks>
|
|
private void LogText(String txtHistory)
|
|
{
|
|
InfoWindowColoredText(txtHistory, ColorDefault);
|
|
_logger.Info(txtHistory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Output exclusively to user update remarks text window.
|
|
/// </summary>
|
|
private void LogErrorText(String txtHistory)
|
|
{
|
|
InfoWindowColoredText(txtHistory, ColorProcessFailed);
|
|
_logger.Info(txtHistory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Output exclusively to user update remarks text window.
|
|
/// </summary>
|
|
private void LogWarningText(String txtHistory)
|
|
{
|
|
InfoWindowColoredText(txtHistory, ColorProcessWarning);
|
|
_logger.Info(txtHistory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Output exclusively to user update remarks text window.
|
|
/// </summary>
|
|
private void LogSuccessText(String txtHistory)
|
|
{
|
|
InfoWindowColoredText(txtHistory, ColorSuccess);
|
|
_logger.Info(txtHistory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Output exclusively to user update remarks text window.
|
|
/// </summary>
|
|
private void InfoWindowColoredText(String txtHistory, Color color)
|
|
{
|
|
Invoke(new Action(() =>
|
|
{
|
|
rtbReport.SuspendLayout();
|
|
rtbReport.SelectionStart = rtbReport.Text.Length;
|
|
rtbReport.SelectionLength = 0;
|
|
rtbReport.SelectionColor = color;
|
|
rtbReport.AppendText($"{txtHistory}{Environment.NewLine}");
|
|
rtbReport.SelectionColor = rtbReport.ForeColor;
|
|
rtbReport.ScrollToCaret();
|
|
rtbReport.ResumeLayout();
|
|
}));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Process bar - NOT invoked, just call from Form main thread.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Avoid repeated execution on invisible progress bar.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Thread safe implementation to avoid crash.
|
|
/// </remarks>
|
|
private void SetStatusProgressBar(Int32 value = 0, Boolean visible = true)
|
|
{
|
|
if (ProgressBarStatus == null || (!ProgressBarStatus.Visible && !visible))
|
|
return;
|
|
try
|
|
{
|
|
if (ProgressBarStatus == null)
|
|
return;
|
|
if (value > 100)
|
|
value = 100;
|
|
if (value < 0)
|
|
value = 0;
|
|
ProgressBarStatus.Visible = visible;
|
|
ProgressBarStatus.Value = value;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common routine to hide the data picker and uninstall all events.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Check user input.
|
|
/// </remarks>
|
|
private void HideDatePicker()
|
|
{
|
|
_datePicker.Visible = false;
|
|
_datePicker.CloseUp -= datePickerFwUpdateValidationDate_CloseUp;
|
|
_datePicker.CloseUp -= datePickerUserValidationDate_CloseUp;
|
|
// display the label
|
|
lblFwUpdateDutyDate.Visible = true;
|
|
CheckDataCollectionStatus();
|
|
}
|
|
/// <summary>
|
|
/// Common routine to disable all controls.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - Added new buttons.
|
|
/// </remarks>
|
|
private void DisableAllControlsInvoked()
|
|
{
|
|
UiInvoker.ControlEnableInvoker(grpLanguageSelection, false);
|
|
|
|
UiInvoker.ControlEnableInvoker(btnBuildFwUpdateSafe, false);
|
|
UiInvoker.ControlEnableInvoker(btnUploadSafeToDb, false);
|
|
UiInvoker.ControlEnableInvoker(btnLicenseFwUpdateSw, false);
|
|
UiInvoker.ControlEnableInvoker(btnLicenseFwUpdateBuilder, false);
|
|
UiInvoker.ControlEnableInvoker(lblFwUpdateDutyDate, false);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderNumber, false);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderPosition, false);
|
|
UiInvoker.ControlEnableInvoker(tabControlSelection, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common routine to disable all controls except the language setting.
|
|
/// This should be used, if user is not licensed.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
private void DisableControlsExceptLanguageInvoked()
|
|
{
|
|
UiInvoker.ControlEnableInvoker(grpLanguageSelection, false);
|
|
|
|
UiInvoker.ControlEnableInvoker(btnBuildFwUpdateSafe, false);
|
|
UiInvoker.ControlEnableInvoker(btnUploadSafeToDb, false);
|
|
UiInvoker.ControlEnableInvoker(btnLicenseFwUpdateSw, false);
|
|
UiInvoker.ControlEnableInvoker(btnLicenseFwUpdateBuilder, false);
|
|
UiInvoker.ControlEnableInvoker(lblFwUpdateDutyDate, false);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderNumber, false);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderPosition, false);
|
|
UiInvoker.ControlEnableInvoker(tabControlSelection, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common routine to enable inputs.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Avoid activation on unchecked license.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
private void EnableInputsInvoked()
|
|
{
|
|
if (_licenseUnchecked || _regUser == null || !_regUser.AccountActive)
|
|
return;
|
|
UiInvoker.ControlEnableInvoker(grpLanguageSelection, false);
|
|
UiInvoker.ControlEnableInvoker(lblFwUpdateDutyDate, true);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderNumber, true);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderPosition, true);
|
|
UiInvoker.ControlEnableInvoker(tabControlSelection, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove search items on FW-package pre-selection and deselect FW-package.
|
|
/// </summary>
|
|
/// <remarks date="2023-Mar-17" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void DeselectFwPackageAndSearchMask()
|
|
{
|
|
// clear all search items for FW-Package as all cordonels are removed
|
|
_radioSearchItems.Clear();
|
|
_regionSearchItems.Clear();
|
|
_metrologySearchItems.Clear();
|
|
_coreSearchItems.Clear();
|
|
_sizeSearchItems.Clear();
|
|
// Clear FW-package selection
|
|
if (_fwUpdateDbAccess?.DbCordonelFwPackagesInfo != null)
|
|
{
|
|
foreach (var fw in _fwUpdateDbAccess.DbCordonelFwPackagesInfo)
|
|
fw.IsSelected = false;
|
|
_fwUpdatePackage = null;
|
|
}
|
|
}
|
|
|
|
#endregion --------------------------------------- Tools ------------------------------------------------------
|
|
|
|
#region ------------------------------------------ Threads and Tasks ------------------------------------------
|
|
/// <summary>
|
|
/// Upload FW-Update Safe to DB Task.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-27" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void UploadFwUpdateSafeTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_enableFwSafeUpload = !UploadFwUpdateSafeToDb();
|
|
|
|
}).ContinueWith(delegate
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
if (!_enableFwSafeUpload)
|
|
{
|
|
var msg = $"{Resources.StrFwUpdateSafeUploadSuccessfull} \"{_fwUpdateSafeName}\"";
|
|
LogText(StrSeparator);
|
|
LogSuccessText(msg);
|
|
LogText(StrSeparator);
|
|
MessageBoxShow($"{Resources.StrFwUpdateSafeUploadSuccessfull}\n\n \"{_fwUpdateSafeName}\"",
|
|
Resources.StrSuccess);
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
else
|
|
{
|
|
var msg = $"{Resources.StrFwUpdateSafeUploadFailed}";
|
|
LogText(StrSeparator);
|
|
LogErrorText(msg);
|
|
LogText(StrSeparator);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
}
|
|
EnableInputsInvoked();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Start FW-Update Safe Builder Task.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Error process state introduced.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Nov-14" author="Thomas Wiedebusch">
|
|
/// - Modified message box to upload FW update Safe to DB.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Nov-24" author="Thomas Wiedebusch">
|
|
/// - After message box state change.
|
|
/// </remarks>
|
|
private void BuildFwUpdateSafeTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_enableFwSafeUpload = BuildFwUpdateSafe();
|
|
|
|
}).ContinueWith(delegate
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
if (_enableFwSafeUpload)
|
|
{
|
|
var msg = $"{Resources.StrFwUpdateSafeBuiltSuccessfully} \"{_fwUpdateSafeName}\"";
|
|
LogText(StrSeparator);
|
|
LogSuccessText(msg);
|
|
LogText(StrSeparator);
|
|
var messageBoxButtonReturn = MessageBoxShow(
|
|
$"{Resources.StrFwUpdateSafeBuiltSuccessfully}\n\n \"{_fwUpdateSafeName}\"\n\n" +
|
|
$"{Resources.StrRequestUploadFwUpdateSafeToDb}",
|
|
Resources.StrActionRequest, MessageBoxButtons.YesNo);
|
|
// The btnUploadSafeToDb_Click is going to change the state to UploadFwUpdateSafeToDb
|
|
if (messageBoxButtonReturn == DialogResult.Yes)
|
|
btnUploadSafeToDb_Click(this, null);
|
|
else
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
else
|
|
{
|
|
var msg = $"{Resources.StrFwUpdateSafeBuiltFailed}";
|
|
LogText(StrSeparator);
|
|
LogErrorText(msg);
|
|
LogText(StrSeparator);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
}
|
|
EnableInputsInvoked();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Establish the DB connection.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-23" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - dbAccessLocked introduced.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Error process state introduced.
|
|
/// </remarks>
|
|
private void EstablishDbConnectionTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all FW-Update packages.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - dbAccessLocked introduced.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Error process state introduced.
|
|
/// </remarks>
|
|
private void LoadDbFwUpdateOperatorsTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetAllUpdateOperatorsFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_fwUpdateOperatorsPropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check the software license.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void CheckLicenseTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetLicenseFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
if (_regUser.AccountActive)
|
|
{
|
|
_licenseValidDateTimeOffset = DateTimeServer.GetDateTimeTodayUntilMidnight();
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
else
|
|
_processState = ProcessState.DbAccessLocked;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all FW packages infos from DB.
|
|
/// </summary>
|
|
/// <remarks date="2022-Nov-30" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void LoadDbCordonelFwPackagesInfosTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
// load the packages information
|
|
GetCordonelFwPackagesInfosFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_fwPackagePropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire one report file from DB and display it.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-29" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void LoadDbReportAndDisplayTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetAndDisplaySingleReportFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all report files from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void LoadDbReportsTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetReportsFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_fwReportsPropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all FW-Update safes from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void LoadDbFwUpdateSafesInfosTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetFwUpdateSafesInfosFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_fwUpdateSafesPropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all Customers specified by search mask from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - dbAccessLocked introduced.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Error process state introduced.
|
|
/// </remarks>
|
|
private void LoadDbCordonelCustomersTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetAllCordonelCustomersFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_customersPropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all Cordonel serial numbers of a specific production number.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - dbAccessLocked introduced.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Error process state introduced.
|
|
/// </remarks>
|
|
private void LoadDbCordonelSerialNumbersTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetAllCordonelSerialNumbersOfOrderFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_cordonelsPropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all customer specific production orders from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Error process state introduced.
|
|
/// </remarks>
|
|
private void LoadDbCordonelProductionOrdersTask()
|
|
{
|
|
_invokerProcessState = _processState;
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
try
|
|
{
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
GetAllCordonelOrdersOfCustomerFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_cordonelsPropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
#endregion --------------------------------------- Threads and Tasks ------------------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid FW Packages --------------------------------------
|
|
/// <summary>
|
|
/// Overwrite cell click, because edit of cells is denied (read only == true). This is needed for FW-Update
|
|
/// packages selection. Multiple packages can be selected!
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Search column index starting with 0.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - User search from Cordonel FW-Packages as this contains lot more selected information than the clustered
|
|
/// file.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Simply one unique FW-package allowed to select,
|
|
/// - Reset status of pre-selected Cordonels.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Dec-01" author="Thomas Wiedebusch">
|
|
/// - FW package information from DB used.
|
|
/// </remarks>
|
|
private void gridViewFwPackagesSelection_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// the e.RowIndex is referenced to the (sorted) data grid view
|
|
var fwPackage = new CordonelFirmware
|
|
{
|
|
FwPackageInfo = new CordonelFwPackageInfo()
|
|
};
|
|
|
|
// use the fw update package id for selection
|
|
for (var columnIndex = 0; columnIndex < gridViewFwPackageSelection.ColumnCount; columnIndex++)
|
|
{
|
|
if (gridViewFwPackageSelection.Columns[columnIndex].Name == Resources.StrTableFileId)
|
|
fwPackage.FwPackageInfo.Id =
|
|
(Int32)gridViewFwPackageSelection.Rows[e.RowIndex].Cells[columnIndex].Value;
|
|
}
|
|
|
|
// select FW package
|
|
if (gridViewFwPackageSelection.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// clear FW-packages
|
|
_fwUpdatePackage = null;
|
|
|
|
// reset status of Cordonels being able to auto-assign new FW-package
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
cordonel.IsRemoved = false;
|
|
cordonel.IsApproved = false;
|
|
cordonel.RequiredReleaseNameVersion = null;
|
|
}
|
|
|
|
// reset status of Cordonels being able to auto-assign new FW-package
|
|
foreach (var cordonel in _cordonelUpdateList)
|
|
{
|
|
cordonel.RequiredFwRelease = null;
|
|
}
|
|
|
|
// Search the FW package Id in data table, select if found
|
|
if (_fwUpdateDbAccess?.DbCordonelFwPackagesInfo == null)
|
|
return;
|
|
foreach (var fw in _fwUpdateDbAccess.DbCordonelFwPackagesInfo)
|
|
{
|
|
if (fw.Id == fwPackage.FwPackageInfo.Id)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
if (fw.IsSelected)
|
|
{
|
|
// remove FW package from list
|
|
fw.IsSelected = false;
|
|
}
|
|
else
|
|
{
|
|
// assign FW package
|
|
_fwUpdatePackage = fwPackage;
|
|
// add new FW-package to all Cordonels in update list
|
|
foreach (var cordonel in _cordonelUpdateList)
|
|
{
|
|
cordonel.RequiredFwRelease = fw.Name;
|
|
}
|
|
fw.IsSelected = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fw.IsSelected = false;
|
|
}
|
|
|
|
//search FW package in data table for update
|
|
for (var idx = 0; idx < _dataTableFwPackages.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableFwPackages.Rows[idx];
|
|
if (fw.Id == (Int32)dataRow[Resources.StrTableFileId])
|
|
{
|
|
dataRow[Resources.StrTableSelect] = fw.IsSelected;
|
|
}
|
|
}
|
|
|
|
} // Cordonel search list files
|
|
}
|
|
_fwPackagePropertyChanged = false;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build data grid for FW-Update packages
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - User search from Cordonel FW-Packages as this contains lot more selected information than the clustered
|
|
/// file.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Search extended to metrology.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Dec-01" author="Thomas Wiedebusch">
|
|
/// - FW package information from DB used.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Oct-01" author="Thomas Wiedebusch">
|
|
/// - Avoid unreleased versions.
|
|
/// </remarks>
|
|
private void FillDataGridWithFwPackageInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
_dataTableFwPackages?.Dispose();
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_dataTableFwPackages = new DataTable();
|
|
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableSelect, typeof(Boolean));
|
|
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableCordonelFwToInstall, typeof(String));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableCordonelFwIsReleased, typeof(Boolean));
|
|
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableRegion, typeof(String));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableRadioFrequency, typeof(String));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableCordonelMetrology, typeof(String));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableFwPackageCoreMin, typeof(String));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableFwPackageCoreMax, typeof(String));
|
|
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableCordonelDiameter, typeof(String));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableReleaseDate, typeof(DateTime));
|
|
|
|
//add the fw update package id to simplify selection
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableFileId, typeof(Int32));
|
|
|
|
try
|
|
{
|
|
if (_fwUpdateDbAccess?.DbCordonelFwPackagesInfo == null)
|
|
return;
|
|
foreach (var fw in _fwUpdateDbAccess.DbCordonelFwPackagesInfo)
|
|
{
|
|
// pre-selection of displayed FW packages
|
|
var requiredCoreVersion = 0;
|
|
if (cbxFwPackageCoreMak.Text != Constants.StrWildcard)
|
|
{
|
|
var version = cbxFwPackageCoreMak.Text;
|
|
version = version.Replace(".", "");
|
|
Int32.TryParse(version, out requiredCoreVersion);
|
|
}
|
|
|
|
var requiredMetrologyVersion = 0;
|
|
if (cbxFwPackageMetrologyMask.Text != Constants.StrWildcard)
|
|
{
|
|
var version = cbxFwPackageMetrologyMask.Text;
|
|
version = version.Replace(".", "");
|
|
Int32.TryParse(version, out requiredMetrologyVersion);
|
|
}
|
|
|
|
if ((fw.Region != cbxFwPackageRegionMask.Text && cbxFwPackageRegionMask.Text != Constants.StrWildcard) ||
|
|
(fw.RadioFrequencyMhz.ToString() != cbxFwPackageRadioMask.Text && cbxFwPackageRadioMask.Text != Constants.StrWildcard) ||
|
|
(fw.MeterSize != cbxFwPackageSizeMask.Text && cbxFwPackageSizeMask.Text != Constants.StrWildcard) ||
|
|
(((fw.CoreRevisionMin != null && fw.CoreRevisionMin > requiredCoreVersion) ||
|
|
(fw.CoreRevisionMax != null && requiredCoreVersion > fw.CoreRevisionMax)) &&
|
|
cbxFwPackageCoreMak.Text != Constants.StrWildcard) ||
|
|
(fw.MetrologyVersion != requiredMetrologyVersion &&
|
|
cbxFwPackageMetrologyMask.Text != Constants.StrWildcard) ||
|
|
// Avoid unreleased versions
|
|
!fw.IsReleased)
|
|
continue;
|
|
|
|
var row = _dataTableFwPackages.NewRow();
|
|
row[Resources.StrTableSelect] = fw.IsSelected;
|
|
|
|
row[Resources.StrTableCordonelFwToInstall] = fw.Name;
|
|
row[Resources.StrTableCordonelFwIsReleased] = fw.IsReleased;
|
|
|
|
row[Resources.StrTableRegion] = fw.Region ?? Constants.StrWildcard;
|
|
row[Resources.StrTableRadioFrequency] = fw.RadioFrequencyMhz == null ? Constants.StrWildcard : $@"{fw.RadioFrequencyMhz}";
|
|
row[Resources.StrTableCordonelMetrology] = GenesisMeter.BuildFwVersionStringFromDec(fw.MetrologyVersion);
|
|
row[Resources.StrTableFwPackageCoreMin] = GenesisMeter.BuildFwVersionStringFromDec(fw.CoreRevisionMin);
|
|
row[Resources.StrTableFwPackageCoreMax] = GenesisMeter.BuildFwVersionStringFromDec(fw.CoreRevisionMax);
|
|
|
|
row[Resources.StrTableCordonelDiameter] = fw.MeterSize ?? Constants.StrWildcard;
|
|
if (fw.ReleaseDate != null)
|
|
{
|
|
row[Resources.StrTableReleaseDate] = fw.ReleaseDate;
|
|
}
|
|
row[Resources.StrTableFileId] = fw.Id;
|
|
|
|
_dataTableFwPackages.Rows.Add(row);
|
|
}
|
|
|
|
//output data to data grid view
|
|
gridViewFwPackageSelection.DataSource = _dataTableFwPackages.DefaultView;
|
|
|
|
foreach (DataGridViewColumn column in gridViewFwPackageSelection.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
|
|
if (gridViewFwPackageSelection.Columns[Resources.StrTableCordonelFwVersion] != null)
|
|
gridViewFwPackageSelection.Sort(gridViewFwPackageSelection.Columns[Resources.StrTableCordonelFwVersion],
|
|
ListSortDirection.Descending);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
}
|
|
}
|
|
#endregion --------------------------------------- Data Grid FW Packages ---------------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Update Safes -------------------------------------
|
|
/// <summary>
|
|
/// Build data grid for FW-Update update safes
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-29" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Jun-01" author="Thomas Wiedebusch">
|
|
/// - Removed coloring of safes depending bon valid date as it slows down the program dramatically.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Jun-30" author="Thomas Wiedebusch">
|
|
/// - CHanged date time field to string with yyyy-MM-dd to make it sortable.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
private void FillDataGridWithFwUpdateSafesInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
|
|
_dataTableUpdateSafes?.Dispose();
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_dataTableUpdateSafes = new DataTable();
|
|
|
|
// _dataTableUpdateSafes.Columns.Add(Resources.StrTableUserValidDate, typeof(DateTime));
|
|
_dataTableUpdateSafes.Columns.Add(Resources.StrTableUserValidDate, typeof(String));
|
|
_dataTableUpdateSafes.Columns.Add(Resources.StrTableCordonelPcbId, typeof(String));
|
|
|
|
_dataTableUpdateSafes.Columns.Add(Resources.StrTableCordonelUpdateOrder, typeof(Int64));
|
|
_dataTableUpdateSafes.Columns.Add(Resources.StrTableCordonelProductionPos, typeof(Int64));
|
|
|
|
_dataTableUpdateSafes.Columns.Add(Resources.StrTableCustomerName, typeof(String));
|
|
_dataTableUpdateSafes.Columns.Add(Resources.StrTableUserFullName, typeof(String));
|
|
|
|
try
|
|
{
|
|
foreach (var safeInfo in _fwUpdateSafesInfos)
|
|
{
|
|
|
|
// create one line per PcbId
|
|
foreach (var pcbId in safeInfo.PcbIds)
|
|
{
|
|
try
|
|
{
|
|
var row = _dataTableUpdateSafes.NewRow();
|
|
|
|
//row[Resources.StrTableUserValidDate] = safeInfo.ValidDate.DateTime;
|
|
row[Resources.StrTableUserValidDate] =
|
|
DateTimeServer.GetSortableDateStringFromDateTime(safeInfo.ValidDate.DateTime,
|
|
_cultureInfo);
|
|
row[Resources.StrTableCordonelPcbId] = pcbId;
|
|
|
|
// extract customer name , order and position from file name
|
|
var info = safeInfo.Name.Split(FwUpdateConfig.FwUpdateFileFieldSeparator);
|
|
var replace = info[1].Replace(FwUpdateConfig.FwUpdateFileExtension, "");
|
|
var orderPos = replace.Split(FwUpdateConfig.FwUpdateFileOrderPosSeparator);
|
|
|
|
|
|
row[Resources.StrTableCordonelUpdateOrder] = orderPos[0];
|
|
row[Resources.StrTableCordonelProductionPos] = orderPos[1];
|
|
|
|
row[Resources.StrTableCustomerName] = info[0];
|
|
var userName = Constants.StrUnknown;
|
|
foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Where(user =>
|
|
user.Id == safeInfo.UserId))
|
|
{
|
|
userName = user.FullName;
|
|
break;
|
|
}
|
|
|
|
row[Resources.StrTableUserFullName] = userName;
|
|
_dataTableUpdateSafes.Rows.Add(row);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
}
|
|
|
|
gridViewFwUpdateSafeSelection.DataSource = _dataTableUpdateSafes;
|
|
|
|
foreach (DataGridViewColumn column in gridViewFwUpdateSafeSelection.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
|
|
//TODO THW FwUpdateSafesInfosStyleSet();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
}
|
|
}
|
|
|
|
#endregion --------------------------------------- Data Grid Update Safes --------------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Report Files -------------------------------------
|
|
/// <summary>
|
|
/// Overwrite cell click, because edit of cells is denied (read only == true).
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-22" author="Thomas Wiedebusch">
|
|
/// - Use file ID for reference of report as multiple reports might be generated at the same day.
|
|
/// </remarks>
|
|
private void gridViewFwUpdateReportSelection_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableReportFiles == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (var columnIndex = 0; columnIndex < gridViewFwUpdateReportSelection.ColumnCount; columnIndex++)
|
|
{
|
|
if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == Resources.StrTableFileId)
|
|
_selectedReport.FileId =
|
|
Convert.ToInt32(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value);
|
|
if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == Resources.StrTableUpdateOperatorId)
|
|
_selectedReport.UserId =
|
|
Convert.ToInt32(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value);
|
|
if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == Resources.StrTableDate)
|
|
_selectedReport.Date = Convert.ToDateTime(
|
|
gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value);
|
|
if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == Resources.StrTableCordonelPcbId)
|
|
_selectedReport.PcbId =
|
|
Convert.ToInt64(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value);
|
|
if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name ==
|
|
Resources.StrTableCordonelUpdateOrder)
|
|
_selectedReport.OrderNr =
|
|
Convert.ToInt64(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value);
|
|
if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name ==
|
|
Resources.StrTableCordonelProductionPos)
|
|
_selectedReport.OrderPos =
|
|
Convert.ToInt64(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value);
|
|
}
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingReports);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
|
|
_processState = ProcessState.GetAndDisplaySingleReportFromDb;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build data grid for FW-Update report files
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-30" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-22" author="Thomas Wiedebusch">
|
|
/// - Use file ID for reference of report as multiple reports might be generated at the same day.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Jun-30" author="Thomas Wiedebusch">
|
|
/// - CHanged date time field to string with yyyy-MM-dd to make it sortable.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
private void FillDataGridWithReportsInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
|
|
_dataTableReportFiles?.Dispose();
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_dataTableReportFiles = new DataTable();
|
|
|
|
//_dataTableReportFiles.Columns.Add(Resources.StrTableDate, typeof(DateTime));
|
|
_dataTableReportFiles.Columns.Add(Resources.StrTableDate, typeof(String));
|
|
_dataTableReportFiles.Columns.Add(Resources.StrTableCordonelPcbId, typeof(String));
|
|
|
|
_dataTableReportFiles.Columns.Add(Resources.StrTableCordonelUpdateOrder, typeof(Int64));
|
|
_dataTableReportFiles.Columns.Add(Resources.StrTableCordonelProductionPos, typeof(Int64));
|
|
|
|
_dataTableReportFiles.Columns.Add(Resources.StrTableUserFullName, typeof(String));
|
|
|
|
_dataTableReportFiles.Columns.Add(Resources.StrTableUpdateOperatorId, typeof(Int32));
|
|
_dataTableReportFiles.Columns.Add(Resources.StrTableFileId, typeof(Int32));
|
|
|
|
try
|
|
{
|
|
foreach (var report in _fwUpdateReports)
|
|
{
|
|
|
|
var row = _dataTableReportFiles.NewRow();
|
|
|
|
//row[Resources.StrTableDate] = report.Date.Date;
|
|
row[Resources.StrTableDate] =
|
|
DateTimeServer.GetSortableDateStringFromDateTime(report.Date.Date, _cultureInfo);
|
|
row[Resources.StrTableCordonelPcbId] = report.PcbId;
|
|
|
|
row[Resources.StrTableCordonelUpdateOrder] = report.OrderNr;
|
|
row[Resources.StrTableCordonelProductionPos] = report.OrderPos;
|
|
|
|
var userName = Constants.StrUnknown;
|
|
foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Where(user => user.Id == report.UserId))
|
|
{
|
|
userName = user.FullName;
|
|
break;
|
|
}
|
|
|
|
row[Resources.StrTableUserFullName] = userName;
|
|
row[Resources.StrTableUpdateOperatorId] = report.UserId;
|
|
row[Resources.StrTableFileId] = report.FileId;
|
|
|
|
_dataTableReportFiles.Rows.Add(row);
|
|
}
|
|
|
|
gridViewFwUpdateReportSelection.DataSource = _dataTableReportFiles;
|
|
|
|
foreach (DataGridViewColumn column in gridViewFwUpdateReportSelection.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
}
|
|
}
|
|
|
|
#endregion --------------------------------------- Data Grid Report Files --------------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Pre Build Summary --------------------------------
|
|
/// <summary>
|
|
/// Overwrite cell click, because edit of cells is denied (read only == true). This is needed for
|
|
/// Pre build summary selection. Multiple Cordonels can be selected!
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-17" author="Thomas Wiedebusch">
|
|
/// - Production pre select infos from production search infos.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Removed FW-package combo box as FW-package is one unique one and can only be exchanged in the FW-package
|
|
/// selection tab.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Removed IsApproved or IsRemoved if selection de-selected.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-08" author="Thomas Wiedebusch">
|
|
/// - Selector for register restore.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-08" author="Thomas Wiedebusch">
|
|
/// - Add all known infos of Cordonel on selection.
|
|
/// </remarks>
|
|
private void gridViewPreBuildSummary_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableSummary == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// the e.RowIndex is referenced to the (sorted) data grid view
|
|
var cordonelDeviceInfo = new CordonelDeviceInfo();
|
|
for (var columnIndex = 0; columnIndex < gridViewPreBuildSummary.ColumnCount;
|
|
columnIndex++)
|
|
{
|
|
if (gridViewPreBuildSummary.Columns[columnIndex].Name == Resources.StrTableCordonelPcbId)
|
|
cordonelDeviceInfo.PcbId =
|
|
gridViewPreBuildSummary.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
|
|
// add here the required release
|
|
if (gridViewPreBuildSummary.Columns[columnIndex].Name == Resources.StrTableCordonelFwToInstall)
|
|
cordonelDeviceInfo.RequiredFwRelease =
|
|
gridViewPreBuildSummary.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
}
|
|
|
|
// Select Cordonel
|
|
if (gridViewPreBuildSummary.Columns[e.ColumnIndex].Name == Resources.StrTableApprove)
|
|
{
|
|
// Search the cordonel in the production pre selected list
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
if (cordonel.PcbId == cordonelDeviceInfo.PcbId)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
cordonel.IsApproved = !cordonel.IsApproved;
|
|
cordonel.IsRemoved = !cordonel.IsApproved;
|
|
|
|
//search cordonel in data table for update of "select" checkbox
|
|
for (var idx = 0; idx < _dataTableSummary.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableSummary.Rows[idx];
|
|
if (cordonel.PcbId != (String)dataRow[Resources.StrTableCordonelPcbId])
|
|
continue;
|
|
|
|
dataRow[Resources.StrTableApprove] = cordonel.IsApproved;
|
|
dataRow[Resources.StrTableRemove] = cordonel.IsRemoved;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production list
|
|
}// Approve
|
|
// Remove Cordonel from safe
|
|
if (gridViewPreBuildSummary.Columns[e.ColumnIndex].Name == Resources.StrTableRemove)
|
|
{
|
|
// Search the cordonel in the production list pre selected
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
if (cordonel.PcbId == cordonelDeviceInfo.PcbId)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
cordonel.IsRemoved = !cordonel.IsRemoved;
|
|
cordonel.IsApproved = !cordonel.IsRemoved;
|
|
//search cordonel in data table for update of "select" checkbox
|
|
for (var idx = 0; idx < _dataTableSummary.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableSummary.Rows[idx];
|
|
if (cordonel.PcbId != (String)dataRow[Resources.StrTableCordonelPcbId])
|
|
continue;
|
|
|
|
dataRow[Resources.StrTableApprove] = cordonel.IsApproved;
|
|
dataRow[Resources.StrTableRemove] = cordonel.IsRemoved;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production list
|
|
}// Remove
|
|
// Select Cordonel register restore
|
|
if (gridViewPreBuildSummary.Columns[e.ColumnIndex].Name == Resources.StrTableRegisterRestoreSelect)
|
|
{
|
|
// Search the cordonel in the production list pre selected
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
if (cordonel.PcbId == cordonelDeviceInfo.PcbId)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
cordonel.RegisterRecoveryRequired = !cordonel.RegisterRecoveryRequired;
|
|
//search cordonel in data table for update of "select" checkbox
|
|
for (var idx = 0; idx < _dataTableSummary.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableSummary.Rows[idx];
|
|
if (cordonel.PcbId != (String)dataRow[Resources.StrTableCordonelPcbId])
|
|
continue;
|
|
|
|
dataRow[Resources.StrTableRegisterRestoreSelect] = cordonel.RegisterRecoveryRequired;
|
|
break;
|
|
}
|
|
//_cordonelsPropertyChanged = true;
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production list
|
|
}// Restore registers
|
|
// Select Cordonel
|
|
if (gridViewPreBuildSummary.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// Search the cordonel in the production pre selected list
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
if (cordonel.PcbId == cordonelDeviceInfo.PcbId)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
if (cordonel.IsSelected)
|
|
{
|
|
// remove cordonel from list
|
|
cordonel.IsSelected = false;
|
|
cordonel.IsRemoved = false;
|
|
cordonel.IsApproved = false;
|
|
cordonel.RegisterRecoveryRequired = false;
|
|
}
|
|
else
|
|
{
|
|
cordonel.IsSelected = true;
|
|
}
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production list
|
|
}// Select
|
|
|
|
// Summarize selections amd update contents
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
if (cordonel.PcbId == cordonelDeviceInfo.PcbId)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
if (cordonel.IsSelected)
|
|
{
|
|
cordonelDeviceInfo.RegisterRecoveryRequired = cordonel.RegisterRecoveryRequired;
|
|
cordonelDeviceInfo.CustomerSerialNumber = cordonel.CustomerSerialNumber;
|
|
cordonelDeviceInfo.InstalledFwVersion = cordonel.InstalledFwVersion;
|
|
// remove cordonel from list
|
|
foreach (var x in _cordonelUpdateList.Where(x => x.PcbId == cordonel.PcbId))
|
|
{
|
|
_cordonelUpdateList.Remove(x);
|
|
break;
|
|
}
|
|
// add cordonel to list
|
|
_cordonelUpdateList.Add(cordonelDeviceInfo);
|
|
}
|
|
else
|
|
{
|
|
// remove cordonel from list
|
|
foreach (var x in _cordonelUpdateList.Where(x => x.PcbId == cordonel.PcbId))
|
|
{
|
|
_cordonelUpdateList.Remove(x);
|
|
break;
|
|
}
|
|
}
|
|
//search cordonel in data table for update of "select" checkbox
|
|
for (var idx = 0; idx < _dataTableSummary.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableSummary.Rows[idx];
|
|
if (cordonel.PcbId != (String)dataRow[Resources.StrTableCordonelPcbId])
|
|
continue;
|
|
|
|
dataRow[Resources.StrTableSelect] = cordonel.IsSelected;
|
|
dataRow[Resources.StrTableApprove] = cordonel.IsApproved;
|
|
dataRow[Resources.StrTableRemove] = cordonel.IsRemoved;
|
|
dataRow[Resources.StrTableRegisterRestoreSelect] = cordonel.RegisterRecoveryRequired;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production list
|
|
_cordonelsPropertyChanged = true;
|
|
|
|
PreBuildSummaryInformationStyleSet();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build data grid for pre build summary
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-17" author="Thomas Wiedebusch">
|
|
/// - Production pre select infos from production search infos.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-29" author="Thomas Wiedebusch">
|
|
/// - Fill search masks of FW packages for core revision, diameter, radio, region and metrology based
|
|
/// on selected Cordonels
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Pre-select FW package,
|
|
/// - Unique FW-package support cannot be exchanged here anymore.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Moved masks from PreBuildSummery tab to Cordonel selection tab.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-08" author="Thomas Wiedebusch">
|
|
/// - Selector for register restore.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
private void FillDataGridWithPreBuildSummaryInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
_processState = ProcessState.UpdateDataTables;
|
|
|
|
_dataTableSummary?.Dispose();
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_dataTableSummary = new DataTable();
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableSelect, typeof(Boolean));
|
|
_dataTableSummary.Columns.Add(Resources.StrTableApprove, typeof(Boolean));
|
|
_dataTableSummary.Columns.Add(Resources.StrTableRemove, typeof(Boolean));
|
|
_dataTableSummary.Columns.Add(Resources.StrTableRegisterRestoreSelect, typeof(Boolean));
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableCordonelCustomerSerialNumber, typeof(String));
|
|
_dataTableSummary.Columns.Add(Resources.StrTableCordonelPcbId, typeof(String));
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableCordonelFwToInstall, typeof(String));
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableCordonelMetrology, typeof(String));
|
|
_dataTableSummary.Columns.Add(Resources.StrTableCordonelMetrologyIsUpdateable, typeof(Boolean));
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableCordonelCore, typeof(String));
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableRegion, typeof(String));
|
|
_dataTableSummary.Columns.Add(Resources.StrTableRadioFrequency, typeof(String));
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableCordonelDiameter, typeof(String));
|
|
|
|
_dataTableSummary.Columns.Add(Resources.StrTableReason, typeof(String));
|
|
|
|
gridViewPreBuildSummary.DataSource = _dataTableSummary;
|
|
gridViewPreBuildSummary.Visible = true;
|
|
|
|
try
|
|
{
|
|
// remove all Cordonels from update, this lis will be re-generated
|
|
_cordonelUpdateList.Clear();
|
|
|
|
var dataGridTableRow = 0;
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
var row = _dataTableSummary.NewRow();
|
|
// keep FW-package if already assigned, if NOT, check if the unique package matches the requirements
|
|
// this step has to be executed before filling the SELECT information, because it changes the content
|
|
// to preset the SELECT based on the initial FW-package to Cordonel requirement comparison.
|
|
if (!cordonel.IsRemoved && !cordonel.IsApproved)
|
|
row[Resources.StrTableCordonelFwToInstall] = PreSelectFwPackages(cordonel);
|
|
else
|
|
row[Resources.StrTableCordonelFwToInstall] = cordonel.RequiredReleaseNameVersion ?? Constants.StrUnknown;
|
|
|
|
row[Resources.StrTableSelect] = cordonel.IsSelected;
|
|
row[Resources.StrTableApprove] = cordonel.IsApproved;
|
|
row[Resources.StrTableRemove] = cordonel.IsRemoved;
|
|
row[Resources.StrTableRegisterRestoreSelect] = cordonel.RegisterRecoveryRequired;
|
|
|
|
row[Resources.StrTableCordonelCustomerSerialNumber] = cordonel.CustomerSerialNumber ?? Constants.StrUnknown;
|
|
row[Resources.StrTableCordonelPcbId] = cordonel.PcbId ?? Constants.StrUnknown;
|
|
|
|
|
|
row[Resources.StrTableCordonelMetrology] = cordonel.Metrology ?? Constants.StrUnknown;
|
|
row[Resources.StrTableCordonelMetrologyIsUpdateable] = cordonel.MetrologyIsUpdateable;
|
|
|
|
row[Resources.StrTableCordonelCore] = cordonel.CoreRevision ?? Constants.StrUnknown;
|
|
|
|
row[Resources.StrTableRegion] = cordonel.Region ?? Constants.StrUnknown;
|
|
row[Resources.StrTableRadioFrequency] = cordonel.RadioFrequency ?? Constants.StrUnknown;
|
|
|
|
row[Resources.StrTableCordonelDiameter] = cordonel.Diameter ?? Constants.StrUnknown;
|
|
|
|
row[Resources.StrTableReason] = cordonel.ReasonForUpdateDenial ?? "";
|
|
|
|
_dataTableSummary.Rows.Add(row);
|
|
|
|
// color the results of the compare
|
|
PreBuildSummaryInformationStyleSet(gridViewPreBuildSummary.Rows[dataGridTableRow]);
|
|
dataGridTableRow++;
|
|
|
|
// add approved cordonels to upgrade list, remove the not approved ones
|
|
if (cordonel.IsSelected && _cordonelUpdateList.All(x => x.PcbId != cordonel.PcbId))
|
|
{
|
|
var cordonelDeviceInfo = new CordonelDeviceInfo
|
|
{
|
|
PcbId = cordonel.PcbId,
|
|
CustomerSerialNumber = cordonel.CustomerSerialNumber,
|
|
RegisterRecoveryRequired = cordonel.RegisterRecoveryRequired,
|
|
RequiredFwRelease = cordonel.RequiredReleaseNameVersion,
|
|
InstalledFwVersion = cordonel.InstalledFwVersion
|
|
};
|
|
_cordonelUpdateList.Add(cordonelDeviceInfo);
|
|
}
|
|
|
|
tabControlSelection.Update();
|
|
|
|
}
|
|
|
|
foreach (DataGridViewColumn column in gridViewPreBuildSummary.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
|
|
_processState = ProcessState.Idle;
|
|
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Color the rows depending on the state
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void PreBuildSummaryInformationStyleSet(DataGridViewRow dataGridRow)
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
|
|
// check if selected
|
|
if ((Boolean)dataGridRow.Cells[Resources.StrTableSelect].Value)
|
|
{
|
|
// approved by software or user
|
|
var requiredRelease = (String)dataGridRow.Cells[Resources.StrTableCordonelFwToInstall].Value;
|
|
if ((Boolean)dataGridRow.Cells[Resources.StrTableApprove].Value &&
|
|
!string.IsNullOrEmpty(requiredRelease) && requiredRelease != Constants.StrUnknown)
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationApproved;
|
|
}
|
|
// not approved and not rejected - user has to decide
|
|
else if (!(Boolean)dataGridRow.Cells[Resources.StrTableRemove].Value)
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationUserApproval;
|
|
}
|
|
// not approved but rejected
|
|
else
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationDenied;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationRemoved;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Color the rows depending on the state
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void PreBuildSummaryInformationStyleSet()
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
|
|
foreach (DataGridViewRow dataGridRow in gridViewPreBuildSummary.Rows)
|
|
{
|
|
// check if selected
|
|
if ((Boolean)dataGridRow.Cells[Resources.StrTableSelect].Value)
|
|
{
|
|
// approved by software or user
|
|
var requiredRelease = (String)dataGridRow.Cells[Resources.StrTableCordonelFwToInstall].Value;
|
|
if ((Boolean)dataGridRow.Cells[Resources.StrTableApprove].Value &&
|
|
!string.IsNullOrEmpty(requiredRelease) && requiredRelease != Constants.StrUnknown)
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationApproved;
|
|
}
|
|
// not approved and not rejected - user has to decide
|
|
else if (!(Boolean)dataGridRow.Cells[Resources.StrTableRemove].Value)
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationUserApproval;
|
|
}
|
|
// not approved but rejected
|
|
else
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationDenied;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInstallationRemoved;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// After sort event to update styles
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void gridViewPreBuildSummary_Sorted(Object sender, EventArgs e)
|
|
{
|
|
PreBuildSummaryInformationStyleSet();
|
|
}
|
|
|
|
#endregion --------------------------------------- Data Grid Pre Build Summary --------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Cordonels ----------------------------------------
|
|
/// <summary>
|
|
/// Overwrite cell click, because edit of cells is denied (read only == true). This is needed for
|
|
/// Cordonel selection. Multiple Cordonels can be selected!
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Idx search index started with 0 instead of 1.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - PCB Id may not always be unambiguously (Sensus GmbH Hannover PCB Id 19080071),
|
|
/// - Improved search speed.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - Check data table assignment.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Added FW release picker,
|
|
/// - Search column index starting with 0.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-17" author="Thomas Wiedebusch">
|
|
/// - Production pre select infos from production search infos.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Removed FW-Package selection from Cordonel selection tab.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Moved masks from PreBuildSummery tab to Cordonel selection tab,
|
|
/// - Removed trigger to update PreBuildSummery.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Feb-21" author="Thomas Wiedebusch">
|
|
/// - Search items for FW-Package selection forced to simply have one core version, one meter size,
|
|
/// one region and one metrology version as only identical Cordonels should be placed to one safe
|
|
/// according to the one FW-Package policy.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Mar-03" author="Thomas Wiedebusch">
|
|
/// - Preselect order number and position to last production number to simplify update order generation,
|
|
/// this will cause the update order-pos = production order-pos..
|
|
/// </remarks>
|
|
/// <remarks date="2023-Mar-17" author="Thomas Wiedebusch">
|
|
/// - Clear all search items for FW-package selection and deselect the FW-package if cordonel count is 0.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-08" author="Thomas Wiedebusch">
|
|
/// - Selector for register restore.
|
|
/// </remarks>
|
|
/// <remarks date="2025-Dec-08" author="Thomas Wiedebusch">
|
|
/// - Avoid multiple identical search items.
|
|
/// </remarks>
|
|
private void gridViewCordonelsSelection_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableCordonels == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// the e.RowIndex is referenced to the (sorted) data grid view
|
|
var cordSelect = new CordonelProductionInfosDb();
|
|
for (var columnIndex = 0; columnIndex < gridViewCordonelSelection.ColumnCount;
|
|
columnIndex++)
|
|
{
|
|
if (gridViewCordonelSelection.Columns[columnIndex].Name == Resources.StrTableCordonelPcbId)
|
|
cordSelect.PcbId =
|
|
gridViewCordonelSelection.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
|
|
}
|
|
|
|
// select factory reset
|
|
if (gridViewCordonelSelection.Columns[e.ColumnIndex].Name == Resources.StrTableRegisterRestoreSelect)
|
|
{
|
|
// Search the cordonel in the production search list
|
|
foreach (var cordSearch in _cordonelProductionSearchInfos)
|
|
{
|
|
if (cordSearch.PcbId == cordSelect.PcbId)
|
|
{
|
|
// toggle register restore but only for selected devices
|
|
if (cordSearch.IsSelected)
|
|
{
|
|
cordSearch.RegisterRecoveryRequired = !cordSearch.RegisterRecoveryRequired;
|
|
}
|
|
|
|
//search cordonel in data table for update of "select" and "RegisterRestore" checkbox
|
|
for (var idx = 0; idx < _dataTableCordonels.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableCordonels.Rows[idx];
|
|
if (cordSearch.PcbId != (String)dataRow[Resources.StrTableCordonelPcbId])
|
|
continue;
|
|
|
|
dataRow[Resources.StrTableRegisterRestoreSelect] = cordSearch.RegisterRecoveryRequired;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// select Cordonel
|
|
if (gridViewCordonelSelection.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// Search the cordonel in the production search list
|
|
foreach (var cordSearch in _cordonelProductionSearchInfos)
|
|
{
|
|
if (cordSearch.PcbId == cordSelect.PcbId)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
if (cordSearch.IsSelected)
|
|
{
|
|
// remove cordonel and register restore from list
|
|
cordSearch.IsSelected = false;
|
|
cordSearch.RegisterRecoveryRequired = false;
|
|
foreach (var x in _cordonelProductionPreSelectInfos.Where(x =>
|
|
x.PcbId == cordSelect.PcbId))
|
|
{
|
|
_cordonelProductionPreSelectInfos.Remove(x);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// add cordonel to list
|
|
cordSearch.IsSelected = true;
|
|
cordSearch.IsApproved = false;
|
|
cordSearch.IsRemoved = false;
|
|
// remove it first being able to update all information
|
|
foreach (var x in _cordonelProductionPreSelectInfos.Where(x =>
|
|
x.PcbId == cordSelect.PcbId))
|
|
{
|
|
_cordonelProductionPreSelectInfos.Remove(x);
|
|
break;
|
|
}
|
|
_cordonelProductionPreSelectInfos.Add(cordSearch);
|
|
// fill text box for update order
|
|
if (cordSearch.CustomerOrderNumber > 0)
|
|
{
|
|
tbxOrderNumber.Text = cordSearch.CustomerOrderNumber.ToString();
|
|
}
|
|
// fill text box for update position
|
|
if (cordSearch.CustomerOrderPos > 0)
|
|
{
|
|
tbxOrderPosition.Text = cordSearch.CustomerOrderPos.ToString();
|
|
}
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordSearch.Diameter) &&
|
|
cordSearch.Diameter != Constants.StrUnknown &&
|
|
_sizeSearchItems.All(X => X != cordSearch.Diameter))
|
|
{
|
|
_sizeSearchItems.Add(cordSearch.Diameter);
|
|
}
|
|
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordSearch.RadioFrequency) &&
|
|
cordSearch.RadioFrequency != Constants.StrUnknown &&
|
|
_radioSearchItems.All(x => x != cordSearch.RadioFrequency))
|
|
{
|
|
_radioSearchItems.Add(cordSearch.RadioFrequency);
|
|
}
|
|
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordSearch.Region) &&
|
|
cordSearch.Region != Constants.StrUnknown &&
|
|
_regionSearchItems.All(x => x != cordSearch.Region))
|
|
{
|
|
_regionSearchItems.Add(cordSearch.Region);
|
|
}
|
|
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordSearch.CoreRevision) &&
|
|
cordSearch.CoreRevision != Constants.StrUnknown &&
|
|
_coreSearchItems.All(x => x != cordSearch.CoreRevision))
|
|
{
|
|
_coreSearchItems.Add(cordSearch.CoreRevision);
|
|
}
|
|
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordSearch.Metrology) &&
|
|
cordSearch.Metrology != Constants.StrUnknown &&
|
|
_metrologySearchItems.All(x => x != cordSearch.Metrology))
|
|
{
|
|
_metrologySearchItems.Add(cordSearch.Metrology);
|
|
}
|
|
}
|
|
|
|
//search cordonel in data table for update of "select" and "RegisterRestore" checkbox
|
|
for (var idx = 0; idx < _dataTableCordonels.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableCordonels.Rows[idx];
|
|
if (cordSearch.PcbId != (String)dataRow[Resources.StrTableCordonelPcbId])
|
|
continue;
|
|
|
|
dataRow[Resources.StrTableSelect] = cordSearch.IsSelected;
|
|
dataRow[Resources.StrTableRegisterRestoreSelect] = cordSearch.RegisterRecoveryRequired;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production search list
|
|
}
|
|
|
|
if (_cordonelProductionPreSelectInfos == null || _cordonelProductionPreSelectInfos.Count == 0)
|
|
{
|
|
DeselectFwPackageAndSearchMask();
|
|
}
|
|
|
|
_cordonelsPropertyChanged = false;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Overwrite header cell click to to toggle all Cordonel selections
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2025-Dec-09" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void gridViewCordonelSelection_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
var cordSearchCtr = 0;
|
|
// Toggle all factory resets for every Cordonel
|
|
if (gridViewCordonelSelection.Columns[e.ColumnIndex].Name == Resources.StrTableRegisterRestoreSelect ||
|
|
gridViewCordonelSelection.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// Search the cordonel in the production search list
|
|
foreach (var cordSearch in _cordonelProductionSearchInfos)
|
|
{
|
|
var cellEventArgs = new DataGridViewCellEventArgs(e.ColumnIndex, cordSearchCtr);
|
|
gridViewCordonelsSelection_CellClick(this, cellEventArgs);
|
|
cordSearchCtr++;
|
|
Update();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build data grid for cordonels
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Order position added.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - New data tables, important for language change.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Added region and radio frequency.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Added customer serial number search.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Removed FW-Package selection from Cordonel selection tab.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-08" author="Thomas Wiedebusch">
|
|
/// - Selector for register restore.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Avoid sorting of 'selection' and 'factory reset' columns.
|
|
/// </remarks>
|
|
private void FillDataGridWithCordonelInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
|
|
_dataTableCordonels?.Dispose();
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_dataTableCordonels = new DataTable();
|
|
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableSelect, typeof(Boolean));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableRegisterRestoreSelect, typeof(Boolean));
|
|
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelCustomerSerialNumber, typeof(String));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelPcbId, typeof(String));
|
|
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelInstalledFw, typeof(String));
|
|
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelMetrology, typeof(String));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelMetrologyIsUpdateable, typeof(Boolean));
|
|
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelCore, typeof(String));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableRegion, typeof(String));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableRadioFrequency, typeof(String));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelDiameter, typeof(String));
|
|
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelProductionOrder, typeof(Int64));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelProductionPos, typeof(Int64));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelSize, typeof(String));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelCatalogueNumber, typeof(String));
|
|
|
|
try
|
|
{
|
|
foreach (var cordSearch in _cordonelProductionSearchInfos)
|
|
{
|
|
// pre-selection of displayed production order
|
|
if (!cordSearch.CustomerSerialNumber.Contains(tbxCordonelProductionOrdersSearch.Text)
|
|
&& tbxCordonelProductionOrdersSearch.Text != Constants.StrWildcard)
|
|
continue;
|
|
|
|
// search if this Cordonel is already in production pre select list as this is the marker
|
|
foreach (var cordPre in _cordonelProductionPreSelectInfos.Where(x => x.PcbId == cordSearch.PcbId))
|
|
{
|
|
cordSearch.IsSelected = cordPre.IsSelected;
|
|
cordSearch.IsApproved = cordPre.IsApproved;
|
|
cordSearch.IsRemoved = cordPre.IsRemoved;
|
|
cordSearch.RegisterRecoveryRequired = cordPre.RegisterRecoveryRequired;
|
|
break;
|
|
}
|
|
|
|
var row = _dataTableCordonels.NewRow();
|
|
row[Resources.StrTableSelect] = cordSearch.IsSelected;
|
|
row[Resources.StrTableRegisterRestoreSelect] = cordSearch.RegisterRecoveryRequired;
|
|
|
|
row[Resources.StrTableCordonelCustomerSerialNumber] = cordSearch.CustomerSerialNumber ??
|
|
Constants.StrUnknown;
|
|
row[Resources.StrTableCordonelPcbId] = cordSearch.PcbId ?? Constants.StrUnknown;
|
|
|
|
row[Resources.StrTableCordonelInstalledFw] = cordSearch.InstalledReleaseNameVersion ?? Constants.StrUnknown;
|
|
|
|
row[Resources.StrTableCordonelMetrology] = cordSearch.Metrology ?? Constants.StrUnknown;
|
|
row[Resources.StrTableCordonelMetrologyIsUpdateable] = cordSearch.MetrologyIsUpdateable;
|
|
|
|
row[Resources.StrTableCordonelCore] = cordSearch.CoreRevision ?? Constants.StrUnknown;
|
|
row[Resources.StrTableRegion] = cordSearch.Region ?? Constants.StrUnknown;
|
|
row[Resources.StrTableRadioFrequency] = cordSearch.RadioFrequency ?? Constants.StrUnknown;
|
|
row[Resources.StrTableCordonelDiameter] = cordSearch.Diameter ?? Constants.StrUnknown;
|
|
|
|
row[Resources.StrTableCordonelProductionOrder] = cordSearch.CustomerOrderNumber;
|
|
row[Resources.StrTableCordonelProductionPos] = cordSearch.CustomerOrderPos;
|
|
row[Resources.StrTableCordonelSize] = cordSearch.Length ?? Constants.StrUnknown;
|
|
row[Resources.StrTableCordonelCatalogueNumber] = cordSearch.CatalogNumber ?? Constants.StrUnknown;
|
|
|
|
_dataTableCordonels.Rows.Add(row);
|
|
}
|
|
|
|
gridViewCordonelSelection.DataSource = _dataTableCordonels;
|
|
|
|
foreach (DataGridViewColumn column in gridViewCordonelSelection.Columns)
|
|
{
|
|
if (column.Name != Resources.StrTableRegisterRestoreSelect &&
|
|
column.Name != Resources.StrTableSelect)
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
}
|
|
}
|
|
#endregion --------------------------------------- Data Grid Cordonels ----------------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Controls Update Operators ------------------------
|
|
/// <summary>
|
|
/// Overwrite cell click, because edit of cells is denied (read only == true). This is needed for update user
|
|
/// selection. Exclusively one user can be selected.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Feb-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-10" author="Thomas Wiedebusch">
|
|
/// - Check for e.RowIndex below 0.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
|
|
/// - Removed validation date for user as it should not be set by the FwUpdateBuilder operator,
|
|
/// - Avoid selection of outdated users.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Embedded in try catch block,
|
|
/// - used data grid as cell reference to allow data grid sorting without refresh of data source!
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Idx search index started with 0 instead of 1.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - Check data table assignment.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Removed _userInfo.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Search column index starting with 0.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-27" author="Thomas Wiedebusch">
|
|
/// - Added _updateOperatorId needed to assign the fwUpdateSafeDb.
|
|
/// </remarks>
|
|
private void gridViewFwUpdateOperators_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableUpdateOperators == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// the e.RowIndex is referenced to the (sorted) data grid view
|
|
var updateOperatorName = "";
|
|
var validDate = "";
|
|
for (var columnIndex = 0; columnIndex < gridViewUpdateOperators.ColumnCount; columnIndex++)
|
|
{
|
|
if (gridViewUpdateOperators.Columns[columnIndex].Name == Resources.StrTableUserFullName)
|
|
updateOperatorName = gridViewUpdateOperators.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
if (gridViewUpdateOperators.Columns[columnIndex].Name == Resources.StrTableUserValidDate)
|
|
validDate = gridViewUpdateOperators.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
}
|
|
// select update operator
|
|
if (gridViewUpdateOperators.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// Search the customer name in data table, select if found, set all others to false
|
|
foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators)
|
|
{
|
|
if (user.FullName == updateOperatorName)
|
|
{
|
|
// avoid selection of outdated users
|
|
if (DateTimeOffset.Compare(DateTimeServer.GetDateTimeOffsetFromDateString(validDate),
|
|
DateTimeOffset.Now) < 1 || user.IsSelected || !user.AccountActive)
|
|
{
|
|
lblUpdateOperator.Text = "";
|
|
_updateOperatorId = 0;
|
|
user.IsSelected = false;
|
|
}
|
|
else
|
|
{
|
|
lblUpdateOperator.Text = user.FullName;
|
|
_updateOperatorId = user.Id;
|
|
user.IsSelected = true;
|
|
}
|
|
}
|
|
else
|
|
user.IsSelected = false;
|
|
|
|
//search user in data table for update
|
|
for (var idx = 0; idx < _dataTableUpdateOperators.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableUpdateOperators.Rows[idx];
|
|
if (user.FullName == (String)dataRow[Resources.StrTableUserFullName])
|
|
{
|
|
dataRow[Resources.StrTableSelect] = user.IsSelected;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_fwUpdateOperatorsPropertyChanged = false;
|
|
// select new validation date
|
|
//if (gridViewUsers.Columns[e.ColumnIndex].Name == Resources.StrTableUserValidDate)
|
|
//{
|
|
// // date time picker
|
|
// if (_userInfo != null)
|
|
// {
|
|
// if (_datePicker.Visible)
|
|
// {
|
|
// HideDatePicker();
|
|
// }
|
|
// // Adding DateTimePicker control into DataGridView
|
|
// gridViewUsers.Controls.Add(_datePicker);
|
|
|
|
// // Rectangular area that represents the display area for a cell
|
|
// var location = gridViewUsers.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
|
|
|
|
// // Setting Location and size to fit within the cell
|
|
// _datePicker.Height = location.Height;
|
|
// _datePicker.Width = location.Width;
|
|
// _datePicker.Location = new Point(location.X, location.Y);
|
|
|
|
// // The final selection of the date
|
|
// _datePicker.CloseUp += datePickerUserValidationDate_CloseUp;
|
|
|
|
// // Now make it visible
|
|
// _datePicker.Visible = true;
|
|
// }
|
|
//}
|
|
|
|
//// select activation of account
|
|
//if (gridViewUsers.Columns[e.ColumnIndex].Name == Resources.StrTableUserActive)
|
|
//{
|
|
// // toggle selection
|
|
// dataRow[Resources.StrTableUserActive] = (Boolean)dataRow[Resources.StrTableUserActive] != true;
|
|
// if (_userInfo != null) _userInfo.AccountActive = (Boolean)dataRow[Resources.StrTableUserActive];
|
|
// _userAccountPropertyChanged = true;
|
|
//}
|
|
|
|
// color the results of the compare
|
|
UpdateOperatorsInformationStyleSet();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build data grid for all fully qualified users
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Disable language change during update.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - New data tables, important for language change.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Added PC name.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Registration and valid date to date time.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
private void FillDataGridWithUpdateOperatorInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
|
|
_dataTableUpdateOperators?.Dispose();
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_dataTableUpdateOperators = new DataTable();
|
|
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableSelect, typeof(Boolean));
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableUserFullName, typeof(String));
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableUserDomain, typeof(String));
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableUserLogInName, typeof(String));
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableUserPcName, typeof(String));
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableUserRegDate, typeof(DateTime));
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableUserValidDate, typeof(DateTime));
|
|
_dataTableUpdateOperators.Columns.Add(Resources.StrTableUserActive, typeof(Boolean));
|
|
|
|
try
|
|
{
|
|
|
|
foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators)
|
|
{
|
|
var row = _dataTableUpdateOperators.NewRow();
|
|
//application information read from configuration
|
|
row[Resources.StrTableSelect] = user.IsSelected;
|
|
row[Resources.StrTableUserFullName] = user.FullName;
|
|
row[Resources.StrTableUserDomain] = user.Domain;
|
|
row[Resources.StrTableUserLogInName] = user.LogInName;
|
|
row[Resources.StrTableUserPcName] = CryptInformation.GetPcNameFromHwId(user.HardwareId);
|
|
row[Resources.StrTableUserRegDate] = user.RegisterDate.Date;
|
|
row[Resources.StrTableUserValidDate] = user.ValidDate.Date;
|
|
row[Resources.StrTableUserActive] = user.AccountActive;
|
|
|
|
_dataTableUpdateOperators.Rows.Add(row);
|
|
}
|
|
|
|
//output data to data grid view
|
|
gridViewUpdateOperators.DataSource = _dataTableUpdateOperators.DefaultView;
|
|
|
|
foreach (DataGridViewColumn column in gridViewUpdateOperators.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
|
|
// color the results of the compare
|
|
UpdateOperatorsInformationStyleSet();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Color the rows depending on the state
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-26" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void UpdateOperatorsInformationStyleSet()
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
|
|
foreach (DataGridViewRow dataGridRow in gridViewUpdateOperators.Rows)
|
|
{
|
|
if ((Boolean)dataGridRow.Cells[Resources.StrTableUserActive].Value &&
|
|
DateTimeServer.GetDateTimeOffsetFromDateString(
|
|
dataGridRow.Cells[Resources.StrTableUserValidDate].Value.ToString()) >= DateTimeOffset.Now)
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleValid;
|
|
}
|
|
else
|
|
{
|
|
dataGridRow.DefaultCellStyle = _styleInvalid;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// After sort event to update styles
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void gridViewUpdateOperators_Sorted(Object sender, EventArgs e)
|
|
{
|
|
UpdateOperatorsInformationStyleSet();
|
|
}
|
|
|
|
#endregion --------------------------------------- Data Grid Controls Update Operators ------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Controls Customer --------------------------------
|
|
/// <summary>
|
|
/// Overwrite cell click, because edit of cells is denied (read only == true). This is needed for customer
|
|
/// selection. Exclusively one customer can be selected.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Idx search index started with 0 instead of 1.
|
|
/// - Clear list of cordonels on new customer.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - clear production order numbers.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - Check data table assignment.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Search column index starting with 0.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-17" author="Thomas Wiedebusch">
|
|
/// - Production pre select infos from production search infos.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Mar-17" author="Thomas Wiedebusch">
|
|
/// - Clear all search items for FW-package selection and deselect the FW-package as on customer change
|
|
/// everything needs to be renewed.
|
|
/// </remarks>
|
|
private void gridViewCustomerSelection_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableCustomers == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// remove FW-package on customer change
|
|
DeselectFwPackageAndSearchMask();
|
|
|
|
// the e.RowIndex is referenced to the (sorted) data grid view
|
|
var customerNumber = 0L;
|
|
for (var columnIndex = 0; columnIndex < gridViewCustomerSelection.ColumnCount; columnIndex++)
|
|
{
|
|
if (gridViewCustomerSelection.Columns[columnIndex].Name != Resources.StrTableCustomerNumber)
|
|
continue;
|
|
customerNumber = Convert.ToInt64(gridViewCustomerSelection.Rows[e.RowIndex].Cells[columnIndex].Value);
|
|
break;
|
|
}
|
|
// select customer
|
|
if (gridViewCustomerSelection.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// clear all previously selected Cordonels as a new customer is selected or deselected
|
|
_dataTableCordonels?.Rows.Clear();
|
|
_dataTableCordonels?.Columns.Clear();
|
|
|
|
_fwUpdateCapability.Clear();
|
|
_cordonelUpdateList.Clear();
|
|
|
|
_cordonelProductionSearchInfos.Clear();
|
|
_cordonelProductionPreSelectInfos.Clear();
|
|
|
|
_customerNumberBeforeLastCordonelDbSearch = "";
|
|
|
|
// Search the customer name in data table, select if found, set all others to false
|
|
foreach (var customer in _fwUpdateDbAccess.DbSearchedCordonelCustomers)
|
|
{
|
|
if (customer.CustomerNumber == customerNumber)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
if (customer.IsSelected)
|
|
{
|
|
tbxCustomerName.Text = "";
|
|
lblCustomerNumber.Text = "";
|
|
customer.IsSelected = false;
|
|
}
|
|
else
|
|
{
|
|
tbxCustomerName.Text = customer.CustomerName;
|
|
tbxCustomerName.Focus();
|
|
tbxCustomerName.SelectionStart = 0;
|
|
tbxCustomerName.SelectionLength = 0;
|
|
lblCustomerNumber.Text = customer.CustomerNumber.ToString();
|
|
customer.IsSelected = true;
|
|
}
|
|
}
|
|
else
|
|
customer.IsSelected = false;
|
|
|
|
//search user in data table for update
|
|
for (var idx = 0; idx < _dataTableCustomers.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableCustomers.Rows[idx];
|
|
if (customer.CustomerNumber == (Int64)dataRow[Resources.StrTableCustomerNumber])
|
|
{
|
|
dataRow[Resources.StrTableSelect] = customer.IsSelected;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_customersPropertyChanged = false;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build data grid for selected customers.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - New data tables, important for language change.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Jun-08" author="Thomas Wiedebusch">
|
|
/// - Initially sorted by name.
|
|
/// </remarks>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Disabled language selection, culture info fixed to english.
|
|
/// </remarks>
|
|
private void FillDataGridWithCustomerInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
|
|
_dataTableCustomers?.Dispose();
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
_dataTableCustomers = new DataTable();
|
|
|
|
_dataTableCustomers.Columns.Add(Resources.StrTableSelect, typeof(Boolean));
|
|
_dataTableCustomers.Columns.Add(Resources.StrTableCustomerName, typeof(String));
|
|
_dataTableCustomers.Columns.Add(Resources.StrTableCustomerNumber, typeof(Int64));
|
|
_dataTableCustomers.Columns.Add(Resources.StrTableCustomerLocation, typeof(String));
|
|
|
|
try
|
|
{
|
|
foreach (var customer in _fwUpdateDbAccess.DbSearchedCordonelCustomers)
|
|
{
|
|
var row = _dataTableCustomers.NewRow();
|
|
//application information read from configuration
|
|
row[Resources.StrTableSelect] = customer.IsSelected;
|
|
row[Resources.StrTableCustomerName] = customer.CustomerName;
|
|
row[Resources.StrTableCustomerNumber] = customer.CustomerNumber;
|
|
row[Resources.StrTableCustomerLocation] = customer.CustomerLocation;
|
|
|
|
_dataTableCustomers.Rows.Add(row);
|
|
}
|
|
|
|
//output data to data grid view
|
|
gridViewCustomerSelection.DataSource = _dataTableCustomers.DefaultView;
|
|
|
|
foreach (DataGridViewColumn column in gridViewCustomerSelection.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
|
|
var initialSortColumn = gridViewCustomerSelection.Columns[Resources.StrTableCustomerName];
|
|
if (initialSortColumn != null)
|
|
gridViewCustomerSelection.Sort(initialSortColumn, ListSortDirection.Ascending);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
}
|
|
}
|
|
|
|
#endregion --------------------------------------- Data Grid Controls Customer --------------------------------
|
|
|
|
#region ------------------------------------------ Load DB Contents -------------------------------------------
|
|
/// <summary>
|
|
/// Get the Cordonel customer orders from DB.
|
|
/// </summary>
|
|
/// <returns>true if successful</returns>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-09" author="Thomas Wiedebusch">
|
|
/// - Getting orders directly from DB.
|
|
/// </remarks>
|
|
private void GetAllCordonelOrdersOfCustomerFromDb()
|
|
{
|
|
// get the customer ID
|
|
if (_fwUpdateDbAccess == null || string.IsNullOrEmpty(lblCustomerNumber.Text))
|
|
return;
|
|
|
|
if (Int64.TryParse(lblCustomerNumber.Text, out var customerId))
|
|
{
|
|
_fwUpdateDbAccess.GetAllCordonelCustomerOrdersFromDb(customerId);
|
|
}
|
|
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the Cordonel device information from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - App versions added.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-09" author="Thomas Wiedebusch">
|
|
/// - Size and length applied to DN50, US2, 2" and 220 mm.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Added radio frequency.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-17" author="Thomas Wiedebusch">
|
|
/// - Clear search info on new search.
|
|
/// </remarks>
|
|
/// <remarks date="2024-Apr-30" author="Thomas Wiedebusch">
|
|
/// - order.Length == null taken into account.
|
|
/// </remarks>
|
|
/// <remarks date="2024-Aug-05" author="Thomas Wiedebusch">
|
|
/// - Display correct "USx" meter size from newly added order.CordonelMeterSizeId,
|
|
/// </remarks>
|
|
private void GetAllCordonelSerialNumbersOfOrderFromDb()
|
|
{
|
|
// get the customer ID
|
|
if (_fwUpdateDbAccess == null || string.IsNullOrEmpty(lblCustomerNumber.Text))
|
|
return;
|
|
|
|
// remove last search infos
|
|
_cordonelProductionSearchInfos.Clear();
|
|
|
|
if (_fwUpdateDbAccess.DbCordonelCustomerOrders.Count > 0)
|
|
{
|
|
// Take the pre-processed CustomerOrderSearch-list deviated from CustomerOrder-list
|
|
foreach (var order in _cordonelCustomerOrdersSearch)
|
|
{
|
|
if (_fwUpdateDbAccess.GetAllCordonelSerialNumbersFromDb(order.CustomerOrderNumber,
|
|
order.CustomerOrderPos) && _fwUpdateDbAccess.DbCordonelSerialNumbers.Count > 0)
|
|
{
|
|
foreach (var cordonelSerialNumber in _fwUpdateDbAccess.DbCordonelSerialNumbers)
|
|
{
|
|
// copy all contents to the cordonel device information
|
|
var cordonel = new CordonelProductionInfosDb
|
|
{
|
|
CatalogNumber = order.CatalogNumber,
|
|
CustomerOrderNumber = order.CustomerOrderNumber,
|
|
CustomerOrderPos = order.CustomerOrderPos,
|
|
Diameter = MeterSizeConverter.ConvertMeterSizeEnumToSizeName((MeterSize?)order.CordonelMeterSizeId),
|
|
Length = order.Length == null
|
|
? "?"
|
|
: (order.Length < 150 ? $"{order.Length}\"" : $"{order.Length} mm"),
|
|
PcbId = cordonelSerialNumber.PcbId.ToString(),
|
|
CustomerSerialNumber = cordonelSerialNumber.CustomerSerialNumber,
|
|
SensusSerialNumber = cordonelSerialNumber.SerialNumber.ToString()
|
|
};
|
|
|
|
// read for each Cordonel the AppListVersion
|
|
if (_fwUpdateDbAccess.DownloadCordonelAppVersionsFromDb(cordonel.PcbId, out var cordonelAppVersions))
|
|
{
|
|
foreach (var appVersion in cordonelAppVersions)
|
|
{
|
|
if (appVersion.Id == -1)
|
|
cordonel.CoreRevision = appVersion.Version;
|
|
if (appVersion.Id == -2)
|
|
cordonel.RadioFrequency = appVersion.Version;
|
|
if (appVersion.Id == 0x0F) //GENESISFLOW
|
|
{
|
|
cordonel.Metrology = appVersion.Version;
|
|
cordonel.MetrologyIsUpdateable = appVersion.IsUpdateable;
|
|
}
|
|
|
|
if (appVersion.Id == 0x18) //FLEXNETVERSION
|
|
{
|
|
cordonel.InstalledReleaseNameVersion =
|
|
GenesisMeter.BuildFlexnetFwVersion(out var version, appVersion.Version);
|
|
cordonel.InstalledFwVersion = (Int32?)version;
|
|
}
|
|
}
|
|
}
|
|
|
|
cordonel.Region = string.IsNullOrEmpty(cordonel.RadioFrequency) || cordonel.RadioFrequency == "0" ? "NA" : "EMEA";
|
|
_cordonelProductionSearchInfos.Add(cordonel);
|
|
}
|
|
}
|
|
}
|
|
}// orders from customer could be acquired
|
|
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the Cordonel customers from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-31" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Ape-07" author="Thomas Wiedebusch">
|
|
/// - Search pattern added.
|
|
/// </remarks>
|
|
private void GetAllCordonelCustomersFromDb()
|
|
{
|
|
var searchPattern = tbxCustomerSearchMask.Text.Replace(" ", "");
|
|
_fwUpdateDbAccess?.GetAllCordonelCustomersFromDb(searchPattern);
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Cordonel FW packages information from DB end extract all needed information to select a package to the
|
|
/// CordonelFwPackageInfo search list.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-29" author="Thomas Wiedebusch">
|
|
/// - Meter FW update ruler.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Oct-15" author="Thomas Wiedebusch">
|
|
/// - Configuration files loading from DB: - MeterFwUpdateRuler, configuration.json and MeterEraseRestore.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-27" author="Thomas Wiedebusch">
|
|
/// - Starting with FW 1.2.* all frequencies will be supported, removed frequency check,
|
|
/// - Supported China as new region.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Dec-01" author="Thomas Wiedebusch">
|
|
/// - Removed FUpdateRuler, all data are going to be taken from DB,
|
|
/// - file name no longer used to identify capability of release, all information from DB.
|
|
/// </remarks>
|
|
private void GetCordonelFwPackagesInfosFromDb()
|
|
{
|
|
if (_fwUpdateDbAccess == null)
|
|
return;
|
|
_fwUpdateDbAccess.GetAllCordonelFwPackagesInfoFromDb();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the license information from DB. In DEBUG mode the license of the software will be skipped,
|
|
/// but user license is of importance.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-14" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void GetLicenseFromDb()
|
|
{
|
|
// FW-Update Builder validation with DB access
|
|
var access = false;
|
|
var msg = $"{Resources.StrStartMessageSwLicenseExpired}\n\n{_versionString}";
|
|
try
|
|
{
|
|
// returns true in DEBUG configuration
|
|
access = Xylem.Common.Logic.SoftwareAccessHelper.Access.HasAccess(_assemblyName);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
Close();
|
|
}
|
|
if (!access)
|
|
{
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
Close();
|
|
}
|
|
|
|
_licenseUnchecked = false;
|
|
CheckUserRegistration();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upload the generated FW Update safe to DB.
|
|
/// </summary>
|
|
/// <returns>true if successful</returns>
|
|
/// <remarks date="2021-Apr-27" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private Boolean UploadFwUpdateSafeToDb()
|
|
{
|
|
var pcbIds = _cordonelUpdateList.Select(pcb => pcb.PcbId).ToList();
|
|
return _fwUpdateDbAccess != null && _fwUpdateDbAccess.UploadFwUpdateSafeToDb(_fwUpdateSafeDb, pcbIds);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the content of one selected FW update report from DB.
|
|
/// </summary>
|
|
/// <param name="reportDb">report filled with content</param>
|
|
/// <param name="pcbId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <param name="fileId"></param>
|
|
/// <param name="orderNo"></param>
|
|
/// <param name="position"></param>
|
|
/// <param name="dateTime"></param>
|
|
/// <returns>true if text is set with valid content</returns>
|
|
/// <remarks date="2021-Oct-29" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-22" author="Thomas Wiedebusch">
|
|
/// - File ID added to get the correct file even if multiple files have been reported at the same day (retries).
|
|
/// </remarks>
|
|
private Boolean GetOneSelectedReportFromDb(out FwUpdateReportDb reportDb, Int64 pcbId, Int32 userId, Int32 fileId,
|
|
Int64 orderNo, Int64 position, DateTimeOffset dateTime)
|
|
{
|
|
reportDb = null;
|
|
// The DB access will load a list of all reports assigned to the input.
|
|
if (_fwUpdateDbAccess == null ||
|
|
!_fwUpdateDbAccess.DownloadFwUpdateReportsFromDb(out var fwUpdateReports, pcbId, userId, orderNo))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//The order number has to be extracted and the date has to match!
|
|
foreach (var report in fwUpdateReports.Where(report => report.Date == dateTime &&
|
|
report.OrderPos == position &&
|
|
report.FileId == fileId))
|
|
{
|
|
reportDb = report;
|
|
break;
|
|
}
|
|
|
|
return reportDb != null;
|
|
}
|
|
/// <summary>
|
|
/// Get one selected FW update report from DB and display it.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-29" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void GetAndDisplaySingleReportFromDb()
|
|
{
|
|
//open rich text view with report details
|
|
if (_frmFwUpdateReport == null)
|
|
return;
|
|
Invoke(new Action(() =>
|
|
{
|
|
_frmFwUpdateReport.rtbHistory?.Clear();
|
|
_frmFwUpdateReport.Show();
|
|
}));
|
|
|
|
if (!GetOneSelectedReportFromDb(out var reportDb, _selectedReport.PcbId, _selectedReport.UserId,
|
|
_selectedReport.FileId, _selectedReport.OrderNr, _selectedReport.OrderPos,
|
|
_selectedReport.Date))
|
|
return;
|
|
|
|
//open rich text view with report details
|
|
Invoke(new Action(() =>
|
|
{
|
|
if (_frmFwUpdateReport.rtbHistory != null)
|
|
{
|
|
_frmFwUpdateReport.ApplyLabels(reportDb, _cultureInfo);
|
|
_frmFwUpdateReport.rtbHistory.AppendText(reportDb.Content);
|
|
var fwIsUpToDate = false;
|
|
foreach (var searchString in FwUpdateConfig.FirmwareUpToDateSearchStrings)
|
|
{
|
|
if (reportDb.Content.Contains(searchString))
|
|
fwIsUpToDate = true;
|
|
}
|
|
|
|
_frmFwUpdateReport.rtbHistory.ForeColor = fwIsUpToDate ? ColorSuccess : ColorProcessFailed;
|
|
_frmFwUpdateReport.rtbHistory.ScrollToCaret();
|
|
}
|
|
|
|
}));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get all FW update report files from DB. Loading only the preview (readContent = false as default) to speed up
|
|
/// the access, as the content will only be needed on inspection of the report.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-29" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void GetReportsFromDb()
|
|
{
|
|
if (_fwUpdateDbAccess == null)
|
|
return;
|
|
|
|
_fwUpdateReports.Clear();
|
|
// if the users are not acquired, get these first
|
|
if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null ||
|
|
_fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Count == 0)
|
|
{
|
|
GetAllUpdateOperatorsFromDb();
|
|
}
|
|
|
|
if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null)
|
|
return;
|
|
foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators)
|
|
{
|
|
var fwUpdateReportsOfUser = new List<FwUpdateReportDb>();
|
|
_fwUpdateDbAccess?.DownloadFwUpdateReportsFromDb(out fwUpdateReportsOfUser, userId: user.Id);
|
|
_fwUpdateReports.AddRange(fwUpdateReportsOfUser);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get all active FW update safes from DB. Outdated safes cannot be accessed.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-29" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void GetFwUpdateSafesInfosFromDb()
|
|
{
|
|
if (_fwUpdateDbAccess == null)
|
|
return;
|
|
|
|
_fwUpdateSafesInfos.Clear();
|
|
// if the users are not acquired, get these first
|
|
if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null ||
|
|
_fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Count == 0)
|
|
{
|
|
GetAllUpdateOperatorsFromDb();
|
|
}
|
|
|
|
if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null)
|
|
return;
|
|
foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators)
|
|
{
|
|
_fwUpdateDbAccess.ListAllFwUpdateSafesOfUserFromDb(user.Id, out var fwUpdateSafesOfUser);
|
|
|
|
foreach (var safe in fwUpdateSafesOfUser)
|
|
{
|
|
var pcbIdsOfSafe = _fwUpdateDbAccess.GetFwUpdateSafePcbIdsFromDb(safe.ContainerId);
|
|
var fwUpdateSafe = safe;
|
|
fwUpdateSafe.PcbIds = pcbIdsOfSafe;
|
|
_fwUpdateSafesInfos.Add(fwUpdateSafe);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Get the full qualified user information from DB to generate the primary key for encryption.
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-04" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-11" author="Thomas Wiedebusch">
|
|
/// - DB access.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Call of get all users from DB.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
|
|
/// - Removed DB status.
|
|
/// </remarks>
|
|
private void GetAllUpdateOperatorsFromDb()
|
|
{
|
|
_fwUpdateDbAccess?.GetAllUpdateOperatorsFromDb();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the user information from DB to generate the primary key for encryption.
|
|
/// For this operation only fully qualified users can be used as the primary key needs as input the
|
|
/// HW Id, the domain, the LogInName and the users password hash.
|
|
/// The user registration has to be done in advance in the FW-Update Loader!
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-04" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-11" author="Thomas Wiedebusch">
|
|
/// - Get fully qualified user information from DB searched by the users FullName.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Replaced userInfo by name of update operator.
|
|
/// </remarks>
|
|
private void BuildPrimaryKey(String updateOperator)
|
|
{
|
|
if (_fwUpdateDbAccess == null ||
|
|
!_fwUpdateDbAccess.GetFullQualifiedUserByFullName(updateOperator, out var userInfo))
|
|
{
|
|
return;
|
|
}
|
|
|
|
_primaryKey = FwUpdateCrypt.BuildPrimaryKey(userInfo.HardwareId, userInfo.Domain,
|
|
userInfo.LogInName, userInfo.PasswordHash);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Skip if recovery registers are not needed, else collect all recovery registers from DB.
|
|
/// - To validate the register range, the configuration.json and the list of applications
|
|
/// intended to be installed are needed. Therefore, the <see cref="GetFwPackageFromDb"/>
|
|
/// and <see cref="BuildFwUpdateSwContainerFromDb"/> have to be executed to collect the
|
|
/// information.
|
|
/// - Uses a mockGenesis to extract valid registers based on application versions from
|
|
/// the configuration.json.
|
|
/// </summary>
|
|
/// <param name="cordonel"></param>
|
|
/// <returns>true if successfully loaded or not needed</returns>
|
|
/// <remarks date="2023-Oct-09" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2024-Apr-04" author="Thomas Wiedebusch">
|
|
/// - Added register values with installed or intended to be installed FW to be able to check
|
|
/// limits of registers based on the installed applications and the configuration.json.
|
|
/// </remarks>
|
|
/// <remarks date="2024-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Split downloading of recovery registers and validate range of registers to two separated
|
|
/// functions.
|
|
/// </remarks>
|
|
private Boolean GetRecoveryRegistersFromDb(CordonelDeviceInfo cordonel)
|
|
{
|
|
if (!cordonel.RegisterRecoveryRequired)
|
|
return true;
|
|
var retries = 2;
|
|
var meterApps = new List<MeterApplications>();
|
|
cordonel.RecoveryRegisters?.Clear();
|
|
cordonel.RecoveryRegisters = null;
|
|
cordonel.RecoveryRegisters = new List<RecoveryRegisterItem>();
|
|
var statusReturn = StatusReturn.Okay;
|
|
String msg;
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
// get the programming parameters from DB
|
|
if (_fwUpdateDbAccess != null && _fwUpdateDbAccess.DownloadCordonelRecoveryRegistersFromDb(
|
|
cordonel.PcbId, cordonel.RecoveryRegisters, fieldUpdate: true))
|
|
break;
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
LogErrorText(e.Message);
|
|
}
|
|
|
|
} while (retries-- > 0);
|
|
|
|
// DB download failed
|
|
if (retries <= 0)
|
|
{
|
|
msg = Resources.StrCordonelRecoveryRegisterLoadFailed + " " + cordonel.PcbId + " - " +
|
|
cordonel.CustomerSerialNumber;
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
|
|
return false;
|
|
}
|
|
|
|
// start to build a mock genesis based on the required application versions
|
|
var mockGenesis = new GenesisMeter();
|
|
var configRegisters = new GenesisConfigurationReader();
|
|
var configurationJson = "";
|
|
|
|
// get the configuration.json out of the SW package which has to be downloaded in advance
|
|
if (_fwUpdateSwContainer?.RegisterDefinitionFile?.FileContent?.Length > 0)
|
|
{
|
|
configurationJson = Encoding.Default.GetString(
|
|
_fwUpdateSwContainer.RegisterDefinitionFile.FileContent);
|
|
}
|
|
|
|
// get the application list out of the FW package which has to be downloaded in advance
|
|
if (_fwUpdatePackage?.BinaryApplicationFiles?.Count > 0)
|
|
{
|
|
foreach (var fileApp in _fwUpdatePackage.BinaryApplicationFiles)
|
|
{
|
|
meterApps.Add(new MeterApplications
|
|
{
|
|
AppId = MeterFwUpdate.GetFileAppAppId(fileApp.FileContent),
|
|
Version = MeterFwUpdate.GetFileAppVersion(fileApp.FileContent, out var strVersion),
|
|
StrVersion = strVersion,
|
|
Crc = MeterFwUpdate.GetFileAppCrc(fileApp.FileContent),
|
|
IsInstalled = true
|
|
});
|
|
}
|
|
}
|
|
|
|
// Build a list of all accessible registers if the interface and meter applications are defined on
|
|
// an input of applications and configurationJson as those are from a mock GenesisMeter. If the meterApps
|
|
// and the configurationJson are null, the _currentGenesis is a real device and all valid registers based
|
|
// on the application versions are already defined!
|
|
if (!string.IsNullOrEmpty(configurationJson) && meterApps.Count > 0)
|
|
{
|
|
// read the raw configuration.json to build a register list of ALL registers defined there
|
|
configRegisters.BuildRegisterList(configurationJson);
|
|
// inject registers to mock Genesis
|
|
mockGenesis.SetConfigRegisterDefinitions(configRegisters.ConfigRegistersDefinitions);
|
|
// take the created dictionary to extract the valid registers for the applications
|
|
var configDefRegisters = mockGenesis.GetConfigRegistersDefinitions().MeterRegisterDic.ToList();
|
|
// set the (intended to be) installed applications
|
|
mockGenesis.MeterAppListVersion.AddRange(meterApps);
|
|
// extract the valid meter registers for the target application versions
|
|
mockGenesis.BuildValidMeterRegisters(configDefRegisters);
|
|
}
|
|
|
|
// get the pre-defined dictionary
|
|
var meterRegisters = mockGenesis.GetConfigRegistersDefinitions();
|
|
|
|
foreach (var recReg in cordonel.RecoveryRegisters)
|
|
{
|
|
// if this call does not throw an exception, the register is present
|
|
var regDef = meterRegisters.GetRegisterDefinitionByName(recReg.RegisterIdent);
|
|
|
|
RegisterRestorer.ValidateRegisterRange(recReg, regDef, out var errorMessage);
|
|
if (string.IsNullOrEmpty(errorMessage))
|
|
continue;
|
|
|
|
statusReturn = StatusReturn.Failed;
|
|
LogErrorText(errorMessage);
|
|
}
|
|
|
|
if (statusReturn == StatusReturn.Okay)
|
|
{
|
|
LogSuccessText(Resources.StrCordonelRecoveryRegistersAdded + " " + cordonel.PcbId + " - " +
|
|
cordonel.CustomerSerialNumber);
|
|
return true;
|
|
}
|
|
|
|
msg = Resources.StrCordonelRecoveryRegisterLoadFailed + " " + cordonel.PcbId + " - " +
|
|
cordonel.CustomerSerialNumber;
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Collect all information needed to execute the power correction from DB.
|
|
/// These are the EOL production logging values.
|
|
/// </summary>
|
|
/// <param name="cordonel"></param>
|
|
/// <returns>true if EOL production settings loaded</returns>
|
|
/// <remarks date="2024-May-07" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private Boolean GetPowerCorrectionsFromDb(CordonelDeviceInfo cordonel)
|
|
{
|
|
try
|
|
{
|
|
var reties = 2;
|
|
do
|
|
{
|
|
// get the programming parameters from DB
|
|
if (_fwUpdateDbAccess == null ||
|
|
!_fwUpdateDbAccess.DownloadDbDataAtEol(cordonel.PcbId, ref cordonel.PowerCorrectionValues))
|
|
continue;
|
|
|
|
LogSuccessText(Resources.StrCordonelDbEolDataLoadSucceded + " " + cordonel.PcbId + " - " +
|
|
cordonel.CustomerSerialNumber);
|
|
return true;
|
|
} while (reties-- > 0);
|
|
|
|
var msg = Resources.StrCordonelDbEolDataLoadFailed + " " + cordonel.PcbId + " - " +
|
|
cordonel.CustomerSerialNumber;
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogErrorText(ex.Message);
|
|
MessageBoxShow(ex.Message, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Collect order number, radio address, skeleton key, password hashes and passwords from DB.
|
|
/// </summary>
|
|
/// <param name="cordonel"></param>
|
|
/// <returns>true if password container loaded</returns>
|
|
/// <remarks date="2021-Feb-01" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-02" author="Thomas Wiedebusch">
|
|
/// - Returns bool.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-03" author="Thomas Wiedebusch">
|
|
/// - Check content of password container.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-04" author="Thomas Wiedebusch">
|
|
/// - Using software access helper class.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-15" author="Thomas Wiedebusch">
|
|
/// - Exported base function to FwUpdateDb.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-25" author="Thomas Wiedebusch">
|
|
/// - Retries on missing DB connection or reading of file failed.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Password container directly assigned.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-17" author="Thomas Wiedebusch">
|
|
/// - Password check error messages captured.
|
|
/// </remarks>
|
|
private Boolean GetPwdFromDb(CordonelDeviceInfo cordonel)
|
|
{
|
|
try
|
|
{
|
|
var reties = 2;
|
|
do
|
|
{
|
|
if (_fwUpdateDbAccess == null ||
|
|
!_fwUpdateDbAccess.DownloadCordonelPwdFromDb(cordonel.PcbId, out cordonel.PwdContainer))
|
|
continue;
|
|
|
|
LogSuccessText(Resources.StrCordonelPwdAdded + " " + cordonel.PcbId + " - " + cordonel.CustomerSerialNumber);
|
|
return true;
|
|
} while (reties-- > 0);
|
|
|
|
var msg = Resources.StrCordonelPwdMissing + " " + cordonel.PcbId + " - " + cordonel.CustomerSerialNumber;
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogErrorText(ex.Message);
|
|
MessageBoxShow(ex.Message, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Cordonel FW update configuration files from DB.
|
|
/// The configuration files contain the latest configuration.json
|
|
/// and the latest MeterEraseRestore.json (needed for the FwUpdateSw).
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-27" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2023-Oct-06" author="Thomas Wiedebusch">
|
|
/// - Removed FUpdateRuler, all data are going to be taken from DB.
|
|
/// </remarks>
|
|
private void GetFwUpdateConfigFilesFromDb()
|
|
{
|
|
_fwUpdateDbAccess?.DownloadFwUpdateConfigurationFilesFromDb();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Cordonel SW and configuration files from DB.
|
|
/// The software is a container of dll files, language packages and logging setups.
|
|
/// The configuration files contain the latest MeterFwUpdateRuler.json (needed for the FwUpdateBuilder),
|
|
/// the latest configuration.json and the latest MeterEraseRestore.json (needed for the FwUpdateSw).
|
|
/// Creates License, FileCrc, FileLength and SubDirectories.
|
|
/// </summary>
|
|
/// <param name="fwUpdateSwLicense">license information of valid software</param>
|
|
/// <returns>true if successful</returns>
|
|
/// <remarks date="2021-Oct-27" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private Boolean BuildFwUpdateSwContainerFromDb(SoftwareLicense fwUpdateSwLicense)
|
|
{
|
|
if (_fwUpdateDbAccess?.DbFwUpdateConfigFiles == null ||
|
|
_fwUpdateDbAccess.DbFwUpdateConfigFiles.Count == 0)
|
|
GetFwUpdateConfigFilesFromDb();
|
|
|
|
if (_fwUpdateDbAccess?.DbFwUpdateConfigFiles == null ||
|
|
!_fwUpdateDbAccess.DownloadFwUpdateSwContainerFromDb() ||
|
|
_fwUpdateDbAccess.DbFwUpdateSwPackage.Count == 0 ||
|
|
_fwUpdateDbAccess.DbFwUpdateConfigFiles.Count == 0)
|
|
return false;
|
|
|
|
_fwUpdateSwContainer = new SoftwareContainer
|
|
{
|
|
Major = fwUpdateSwLicense.Major,
|
|
Minor = fwUpdateSwLicense.Minor,
|
|
Build = fwUpdateSwLicense.Build,
|
|
Program = fwUpdateSwLicense.Program,
|
|
SoftwareDynLinkLibs = new List<FilePart>(),
|
|
RegisterDefinitionFile = new FilePart(),
|
|
SoftwareSetupFile = new FilePart(),
|
|
MeterFilesEraseRestore = new FilePart()
|
|
};
|
|
|
|
foreach (var f in _fwUpdateDbAccess.DbFwUpdateConfigFiles)
|
|
{
|
|
// load the register definition
|
|
if (f.FileName == ProgramConfig.RegisterDefinitionFileName)
|
|
{
|
|
f.FileContentLength = f.FileContent.Length;
|
|
f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent);
|
|
_fwUpdateSwContainer.RegisterDefinitionFile = f;
|
|
}
|
|
|
|
// load the meter files to erase and restore
|
|
if (f.FileName == FwUpdateConfig.MeterFilesEraseRestoreConfigFileName)
|
|
{
|
|
f.FileContentLength = f.FileContent.Length;
|
|
f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent);
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore = f;
|
|
}
|
|
}
|
|
|
|
foreach (var f in _fwUpdateDbAccess.DbFwUpdateSwPackage)
|
|
{
|
|
// load the logging configuration
|
|
if (f.FileName == ProgramConfig.NlogConfig)
|
|
{
|
|
f.FileContentLength = f.FileContent.Length;
|
|
f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent);
|
|
_fwUpdateSwContainer.SoftwareSetupFile = f;
|
|
}
|
|
// load the DLLs
|
|
if (f.FileName.EndsWith(".dll"))
|
|
{
|
|
// extract sub-directory from file name in DB for sub-directory creation in FwUpdateLoader
|
|
// supports only depth of one level
|
|
if (f.FileName.Contains("\\"))
|
|
{
|
|
var fileName = f.FileName.Split('\\');
|
|
var subDirectory = fileName[0];
|
|
f.FileName = fileName[fileName.Length - 1];
|
|
f.SubDirectory = subDirectory;
|
|
}
|
|
|
|
f.FileContentLength = f.FileContent.Length;
|
|
f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent);
|
|
_fwUpdateSwContainer.SoftwareDynLinkLibs.Add(f);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build the FW-Update SW container
|
|
/// </summary>
|
|
/// <returns>true if successful</returns>
|
|
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
|
|
/// - Init.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - User license builder.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-02" author="Thomas Wiedebusch">
|
|
/// - Changed return signature.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-29" author="Thomas Wiedebusch">
|
|
/// - Take license from DB.
|
|
/// </remarks>
|
|
// ReSharper disable once UnusedMember.Local
|
|
private Boolean BuildFwUpdateSwContainer(SoftwareLicense fwUpdateSwLicense)
|
|
{
|
|
_fwUpdateSwContainer = new SoftwareContainer
|
|
{
|
|
Major = fwUpdateSwLicense.Major,
|
|
Minor = fwUpdateSwLicense.Minor,
|
|
Build = fwUpdateSwLicense.Build,
|
|
Program = fwUpdateSwLicense.Program,
|
|
SoftwareDynLinkLibs = new List<FilePart>(),
|
|
RegisterDefinitionFile = new FilePart(),
|
|
SoftwareSetupFile = new FilePart(),
|
|
MeterFilesEraseRestore = new FilePart()
|
|
};
|
|
try
|
|
{
|
|
// for debug purposes the locally stored files from download folder are taken
|
|
// copy all elements of software release in the main directory
|
|
var fileList = new List<String>();
|
|
|
|
if (SystemControl.GetFilesOfDirectoryAndSubDirectory(FwUpdateSwSourcePath, fileList))
|
|
return false;
|
|
foreach (var f in fileList)
|
|
{
|
|
// extract the file name
|
|
var fileName = Path.GetFileName(f);
|
|
var subDirectory =
|
|
Path.GetFullPath(f).Replace(FwUpdateSwSourcePath, "").Replace("\\", "").Replace(fileName, "");
|
|
// load the register definition
|
|
if (fileName == ProgramConfig.RegisterDefinitionFileName)
|
|
{
|
|
_fwUpdateSwContainer.RegisterDefinitionFile.FileName = fileName;
|
|
var file = new List<Byte>(File.ReadAllBytes(f));
|
|
_fwUpdateSwContainer.RegisterDefinitionFile.FileContent = new Byte[file.Count];
|
|
_fwUpdateSwContainer.RegisterDefinitionFile.FileContent = file.ToArray();
|
|
_fwUpdateSwContainer.RegisterDefinitionFile.FileContentLength = file.Count;
|
|
_fwUpdateSwContainer.RegisterDefinitionFile.SubDirectory = subDirectory;
|
|
_fwUpdateSwContainer.RegisterDefinitionFile.FileContentCrc16CcittMsb =
|
|
Crc16Ccitt.CalculateMsb1021(_fwUpdateSwContainer.RegisterDefinitionFile.FileContent);
|
|
}
|
|
// load the logging configuration
|
|
if (fileName == ProgramConfig.NlogConfig)
|
|
{
|
|
_fwUpdateSwContainer.SoftwareSetupFile.FileName = fileName;
|
|
var file = new List<Byte>(File.ReadAllBytes(f));
|
|
_fwUpdateSwContainer.SoftwareSetupFile.FileContent = new Byte[file.Count];
|
|
_fwUpdateSwContainer.SoftwareSetupFile.FileContent = file.ToArray();
|
|
_fwUpdateSwContainer.SoftwareSetupFile.FileContentLength = file.Count;
|
|
_fwUpdateSwContainer.SoftwareSetupFile.SubDirectory = subDirectory;
|
|
_fwUpdateSwContainer.SoftwareSetupFile.FileContentCrc16CcittMsb =
|
|
Crc16Ccitt.CalculateMsb1021(_fwUpdateSwContainer.SoftwareSetupFile.FileContent);
|
|
}
|
|
// load the meter files to erase and restore
|
|
if (fileName == FwUpdateConfig.MeterFilesEraseRestoreConfigFileName)
|
|
{
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore.FileName = fileName;
|
|
var file = new List<Byte>(File.ReadAllBytes(f));
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore.FileContent = new Byte[file.Count];
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore.FileContent = file.ToArray();
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore.FileContentLength = file.Count;
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore.SubDirectory = subDirectory;
|
|
_fwUpdateSwContainer.MeterFilesEraseRestore.FileContentCrc16CcittMsb =
|
|
Crc16Ccitt.CalculateMsb1021(_fwUpdateSwContainer.MeterFilesEraseRestore.FileContent);
|
|
}
|
|
// load the DLLs
|
|
if (f.EndsWith(".dll"))
|
|
{
|
|
var filePart = new FilePart { FileName = fileName };
|
|
var file = new List<Byte>(File.ReadAllBytes(f));
|
|
filePart.FileContent = new Byte[file.Count];
|
|
filePart.FileContent = file.ToArray();
|
|
filePart.FileContentLength = file.Count;
|
|
filePart.SubDirectory = subDirectory;
|
|
filePart.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(filePart.FileContent);
|
|
|
|
_fwUpdateSwContainer.SoftwareDynLinkLibs.Add(filePart);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build the license information for any FW.
|
|
/// </summary>
|
|
/// <param name="license"></param>
|
|
/// <param name="swName"></param>
|
|
/// <param name="version"></param>
|
|
/// <remarks date="2021-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
|
|
/// - Software license element naming adapted to DB content.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Software license flexible for different software.
|
|
/// </remarks>
|
|
private void BuildSwLicense(String swName, out SoftwareLicense license, Version version = null)
|
|
{
|
|
// If version is not set, get the actual of this compilation
|
|
if (version == null)
|
|
version = Assembly.GetExecutingAssembly().GetName().Version;
|
|
license = new SoftwareLicense
|
|
{
|
|
Major = version.Major,
|
|
Minor = version.Minor,
|
|
Build = version.Build,
|
|
ValidTo = DateTimeServer.GetDateTimeFromDateString(lblFwUpdateDutyDate.Text + " 23:59:59", _cultureInfo),
|
|
Program = swName,
|
|
Description = "valid",
|
|
ProgramNameIsUnique = true
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the FW-Update SW license information to DB
|
|
/// </summary>
|
|
/// <param name="license"></param>
|
|
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Modified for flexible licenses.
|
|
/// </remarks>
|
|
private void SetFwUpdateSwLicenseToDb(SoftwareLicense license)
|
|
{
|
|
if (_fwUpdateDbAccess != null && _fwUpdateDbAccess.SetSwLicenseToDb(license))
|
|
{
|
|
LogSuccessText($"{Resources.StrSwLicenseSetSuccessfully} {license.Program} " +
|
|
$"{license.Major}.{license.Minor}.{license.Build}");
|
|
return;
|
|
}
|
|
|
|
if (_fwUpdateDbAccess != null && !_fwUpdateDbAccess.DbIsConnected)
|
|
{
|
|
LogErrorText(Resources.StrNotConnectedToDb);
|
|
MessageBoxShow(Resources.StrNotConnectedToDb, Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
lblStatusDbConnect.Text = Resources.StrNotConnectedToDb;
|
|
lblStatusDbConnect.ForeColor = ColorProcessFailed;
|
|
|
|
}
|
|
else
|
|
{
|
|
LogErrorText(Resources.StrSwLicenseSetFailed);
|
|
MessageBoxShow(Resources.StrSwLicenseSetFailed, Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the FW-Update SW license information to DB
|
|
/// </summary>
|
|
/// <param name="programName"></param>
|
|
/// <param name="license"></param>
|
|
/// <remarks date="2021-Jan-28" author="Thomas Wiedebusch">
|
|
/// - Initial with simulated data.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Modified for flexible licenses.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
/// - License assigned in DB access.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-15" author="Thomas Wiedebusch">
|
|
/// - Messages removed.
|
|
/// </remarks>
|
|
private void GetFwUpdateSwLicenseFromDb(String programName, out SoftwareLicense license)
|
|
{
|
|
|
|
if (_fwUpdateDbAccess != null &&
|
|
_fwUpdateDbAccess.GetSwLicenseFromDb(programName, out license))
|
|
return;
|
|
|
|
license = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load a single firmware package from DB. The FW-package infos have to be loaded in advance.
|
|
/// Based on the FW-Packages infos of all released FW versions, the user selected FW-package
|
|
/// will be prepared and downloaded from DB. All information needed for the FW-Update safe will
|
|
/// be copied from the FW-package DB information to the Fw-package information.
|
|
/// </summary>
|
|
/// <param name="releaseName">each Cordonel tells which release to load</param>
|
|
/// <returns>true if succeeded</returns>
|
|
/// <remarks date="2021-Apr-09" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Removed configuration.json from FW package as this is part of the SW package.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Nov-29" author="Thomas Wiedebusch">
|
|
/// - Single FW-Update package.
|
|
/// </remarks>
|
|
private Boolean GetFwPackageFromDb(String releaseName)
|
|
{
|
|
// if this packages has already been downloaded, exit immediately as only one package is needed and
|
|
// allowed for one FW-update safe
|
|
if (_fwUpdatePackage.FwPackageInfo.Name == releaseName &&
|
|
_fwUpdatePackage.BinaryApplicationFiles != null &&
|
|
_fwUpdatePackage.BinaryApplicationFiles.Count > 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
String msg;
|
|
var fileId = 0;
|
|
// extract the clustered file Id from selected fw package and copy the DB information to the
|
|
// FW-package info being used later in the FW-Update safe the single _fwUpdatePackage
|
|
foreach (var packInfo in _fwUpdateDbAccess.DbCordonelFwPackagesInfo)
|
|
{
|
|
// detect the single FW-package selected by the user at the FW package information from DB
|
|
if (!packInfo.IsSelected)
|
|
continue;
|
|
|
|
fileId = packInfo.FileClusterStoreId;
|
|
_fwUpdatePackage.FwPackageInfo.MeterSizes = new List<String> { packInfo.MeterSize };
|
|
_fwUpdatePackage.FwPackageInfo.Name = packInfo.Name;
|
|
_fwUpdatePackage.FwPackageInfo.RadioFrequencyMhz = packInfo.RadioFrequencyMhz;
|
|
_fwUpdatePackage.FwPackageInfo.Region = packInfo.Region;
|
|
_fwUpdatePackage.FwPackageInfo.CoreRevisionMax = packInfo.CoreRevisionMax;
|
|
_fwUpdatePackage.FwPackageInfo.CoreRevisionMin = packInfo.CoreRevisionMin;
|
|
_fwUpdatePackage.FwPackageInfo.MetrologyVersion = packInfo.MetrologyVersion;
|
|
_fwUpdatePackage.FwPackageInfo.Version = packInfo.Version;
|
|
_fwUpdatePackage.FwPackageInfo.FileName = packInfo.FileName;
|
|
break;
|
|
}
|
|
|
|
// search again identical FW-packages by name to set multiple frequencies of sizes
|
|
foreach (var packInfo in _fwUpdateDbAccess.DbCordonelFwPackagesInfo)
|
|
{
|
|
// detect the single FW-package selected by the user at the FW package information from DB
|
|
if (packInfo.Name != _fwUpdatePackage.FwPackageInfo.Name)
|
|
continue;
|
|
|
|
// on a package with multiple frequency support set the frequency to null to skip radio check
|
|
// in the FW-Update SW
|
|
if (packInfo.RadioFrequencyMhz != _fwUpdatePackage.FwPackageInfo.RadioFrequencyMhz)
|
|
_fwUpdatePackage.FwPackageInfo.RadioFrequencyMhz = null;
|
|
|
|
// check multiple meter sizes in the FW-Update SW
|
|
if (_fwUpdatePackage.FwPackageInfo.MeterSizes.All(size => size != packInfo.MeterSize))
|
|
{
|
|
_fwUpdatePackage.FwPackageInfo.MeterSizes.Add(packInfo.MeterSize);
|
|
}
|
|
}
|
|
|
|
// after selection of the FW-package info, the real physical FW-update package has to be downloaded
|
|
// from the DB
|
|
if (_fwUpdateDbAccess.GetCordonelFwPackageFromDb(fileId, out var fwPackage))
|
|
{
|
|
try
|
|
{
|
|
// search the cordonel firmware
|
|
_fwUpdatePackage.PackageDescriptionFile = new FilePart();
|
|
_fwUpdatePackage.BinaryApplicationFiles = new List<FilePart>();
|
|
|
|
foreach (var f in fwPackage)
|
|
{
|
|
// load the ADF (application description file, containing the information of each application)
|
|
if (f.FileName.Contains("product") && f.FileName.EndsWith(".txt"))
|
|
{
|
|
_fwUpdatePackage.PackageDescriptionFile.FileName = f.FileName;
|
|
_fwUpdatePackage.PackageDescriptionFile.FileContent = new Byte[f.FileContent.Length];
|
|
_fwUpdatePackage.PackageDescriptionFile.FileContent = f.FileContent.ToArray();
|
|
}
|
|
|
|
// load the binaries (application files)
|
|
if (f.FileName.Contains("binfile") && f.FileName.EndsWith(".bin"))
|
|
{
|
|
var filePart = new FilePart
|
|
{
|
|
FileName = f.FileName,
|
|
FileContent = new Byte[f.FileContent.Length]
|
|
};
|
|
filePart.FileContent = f.FileContent.ToArray();
|
|
_fwUpdatePackage.BinaryApplicationFiles.Add(filePart);
|
|
}
|
|
}
|
|
|
|
LogSuccessText(Resources.StrFwPackageLoadSuccess + " " + releaseName);
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
msg = Resources.StrFwPackageLoadFailed + @" " + releaseName;
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
MessageBoxShow(e.ToString(), Resources.StrError, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
}
|
|
msg = Resources.StrFwPackageLoadFailed + @" " + releaseName;
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return false;
|
|
}
|
|
|
|
#endregion --------------------------------------- Load DB Contents -------------------------------------------
|
|
|
|
#region ------------------------------------------ Language ---------------------------------------------------
|
|
/// <summary>
|
|
/// Select language at runtime: English
|
|
/// </summary>
|
|
/// <remarks date="2020-Nov-27" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-23" author="Thomas Wiedebusch">
|
|
/// - Change menu.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-26" author="Thomas Wiedebusch">
|
|
/// - Avoid repetition if current culture is equal to required.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Backup duty date for FW-Update during language change.
|
|
/// </remarks>
|
|
private void RadioBtnEnglishLanguage_Click(Object sender, EventArgs e)
|
|
{
|
|
if (Thread.CurrentThread.CurrentCulture.Name == "en-GB")
|
|
{
|
|
return;
|
|
}
|
|
|
|
_cultureInfo = new CultureInfo("en-GB");
|
|
ChangeLanguageControls();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Select language at runtime: German
|
|
/// </summary>
|
|
/// <remarks date="2020-Nov-27" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-23" author="Thomas Wiedebusch">
|
|
/// - Change menu.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Feb-26" author="Thomas Wiedebusch">
|
|
/// - Avoid repetition if current culture is equal to required.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Backup duty date for FW-Update during language change.
|
|
/// </remarks>
|
|
private void RadioBtnGermanLanguage_Click(Object sender, EventArgs e)
|
|
{
|
|
if (Thread.CurrentThread.CurrentCulture.Name == "de-DE")
|
|
{
|
|
return;
|
|
}
|
|
|
|
_cultureInfo = new CultureInfo("de-DE");
|
|
ChangeLanguageControls();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Change language at runtime
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-23" author="Thomas Wiedebusch">
|
|
/// - Initial based on code example
|
|
/// https://stackoverflow.com/questions/52178064/winforms-localization-how-to-change-the-language-of-a-menu.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-02" author="Thomas Wiedebusch">
|
|
/// - Update selected table headers of tab control.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Restore duty date for FW-Update after language change.
|
|
/// </remarks>
|
|
private void ChangeLanguageControls()
|
|
{
|
|
Thread.CurrentThread.CurrentUICulture = _cultureInfo;
|
|
Thread.CurrentThread.CurrentCulture = _cultureInfo;
|
|
var resources = new ComponentResourceManager(typeof(FrmFwUpdateBuilder));
|
|
resources.ApplyResources(this, "$this");
|
|
ControlExtensions.ChangeControlText(resources, Controls);
|
|
|
|
var rm = new ComponentResourceManager(GetType());
|
|
foreach (var control in this.AllControls())
|
|
{
|
|
if (control is ToolStrip)
|
|
{
|
|
var items = ((ToolStrip)control).AllItems().ToList();
|
|
foreach (var item in items)
|
|
{
|
|
rm.ApplyResources(item, item.Name);
|
|
}
|
|
}
|
|
rm.ApplyResources(control, control.Name);
|
|
}
|
|
|
|
if (!_fwUpdateDbAccess.DbIsConnected)
|
|
{
|
|
lblStatusDbConnect.Text = Resources.StrNotConnectedToDb;
|
|
lblStatusDbConnect.ForeColor = ColorProcessFailed;
|
|
}
|
|
else
|
|
{
|
|
lblStatusDbConnect.Text = Resources.StrConnectedToDb;
|
|
lblStatusDbConnect.ForeColor = ColorSuccess;
|
|
}
|
|
|
|
lblFwUpdateInfo.Text = $@"Version: {_version.Major}.{_version.Minor}.{_version.Build}";
|
|
|
|
_fwUpdateOperatorsPropertyChanged = true;
|
|
_customersPropertyChanged = true;
|
|
_cordonelsPropertyChanged = true;
|
|
_fwPackagePropertyChanged = true;
|
|
_fwReportsPropertyChanged = true;
|
|
_fwUpdateSafesPropertyChanged = true;
|
|
_preBuildSummaryPropertyChanged = true;
|
|
|
|
lblFwUpdateDutyDate.Text = _datePicker.Value.ToShortDateString();
|
|
}
|
|
|
|
#endregion --------------------------------------- Language ---------------------------------------------------
|
|
|
|
}
|
|
}
|