4808 lines
217 KiB
C#
4808 lines
217 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 Logic.ProductionToProductMapper.Cordonel;
|
|
using Xylem.Common.CommonCore.Consts;
|
|
using Xylem.Common.CommonCore.ThreadWatcher;
|
|
using Xylem.Common.Cryptology.Security;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile;
|
|
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 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;
|
|
|
|
///<summary>
|
|
/// Collection of software needed for the FW-Update safe!
|
|
/// </summary>
|
|
private SoftwareContainer _fwUpdateSwContainer;
|
|
///<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>();
|
|
private String _fwPackageCordonelPcbId;
|
|
///<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 readonly List<CordonelFirmware> _fwUpdatePackages = new List<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;
|
|
private readonly List<MeterFwUpdateRuler> _meterFwUpdateRuler = new List<MeterFwUpdateRuler>();
|
|
|
|
/// <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 _fwReportFilesPropertyChanged;
|
|
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>
|
|
public 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.GetReportFilesFromDb:
|
|
LoadDbReportFilesTask();
|
|
break;
|
|
|
|
case ProcessState.GetFwUpdateSafesFromDb:
|
|
LoadDbOutstandingFwUpdateSafesTask();
|
|
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.GetFwPackagesFromDb:
|
|
LoadDbCordonelFwPackagesTask();
|
|
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;
|
|
|
|
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();
|
|
CheckReportFilesChange();
|
|
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.GetFwPackagesFromDb:
|
|
case ProcessState.GetCordonelSerialNumbersFromDb:
|
|
case ProcessState.GetFwUpdateSafesFromDb:
|
|
case ProcessState.GetReportFilesFromDb:
|
|
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 == @"*")
|
|
{
|
|
_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() == @"*")
|
|
{
|
|
_cordonelCustomerOrdersSearch.AddRange(_fwUpdateDbAccess.DbCordonelCustomerOrders);
|
|
}
|
|
else
|
|
{
|
|
// format is orderNumber-position e.g. 12345678-10
|
|
var orderText = cbxCordonelProductionOrdersSearch.SelectedItem.ToString().Split('-');
|
|
if (Int64.TryParse(orderText[0], out var orderNumber) &&
|
|
Int64.TryParse(orderText[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>
|
|
private void btnFwPackageSearch_Click(Object sender, EventArgs e)
|
|
{
|
|
// Load fw packages only if not selected indicated in count
|
|
if (_fwUpdatePackages.Count > 0) return;
|
|
|
|
DisableAllControlsInvoked();
|
|
_dataTableFwPackages?.Clear();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingFwPackages);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetFwPackagesFromDb;
|
|
}
|
|
|
|
/// <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>
|
|
private void tabControlSelection_Selected(Object sender, TabControlEventArgs e)
|
|
{
|
|
if (e.TabPage == tabPageFwUpdateSafes)
|
|
{
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingFwUpdateSafes);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetFwUpdateSafesFromDb;
|
|
|
|
}
|
|
|
|
if (e.TabPage == tabPageReports)
|
|
{
|
|
DisableAllControlsInvoked();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingReportFiles);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetReportFilesFromDb;
|
|
|
|
}
|
|
|
|
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)
|
|
{
|
|
_preBuildSummaryPropertyChanged = true;
|
|
}
|
|
|
|
if (e.TabPage == tabPageFwPackageSelection)
|
|
{
|
|
// Load fw packages only if not selected indicated in count
|
|
if (_fwUpdatePackages.Count > 0 ||
|
|
_cordonelFwPackageInfoSearch != null && _cordonelFwPackageInfoSearch.Count > 0) return;
|
|
|
|
DisableAllControlsInvoked();
|
|
_dataTableFwPackages?.Clear();
|
|
UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingFwPackages);
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
_processState = ProcessState.GetFwPackagesFromDb;
|
|
}
|
|
|
|
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>
|
|
private void btnBuildFwUpdateSafe_Click(Object sender, EventArgs e)
|
|
{
|
|
SetStatusProgressBar();
|
|
_dbAccessDelayCtrMs = 0;
|
|
// clear FW packages content to force reload from data base and therefore report generation,
|
|
// this is essential for rebuilding of a safe
|
|
foreach (var package in _fwUpdatePackages)
|
|
{
|
|
package?.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>
|
|
public FrmFwUpdateBuilder()
|
|
{
|
|
var fwUpdateBuilderExePath = AppDomain.CurrentDomain.BaseDirectory;
|
|
var fwUpdateBuilderLibraryPath = Path.Combine(fwUpdateBuilderExePath, "Library");
|
|
var fwUpdateBuilderConfigPath = Path.Combine(fwUpdateBuilderExePath, "Config");
|
|
|
|
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);
|
|
|
|
var rulerPathName = Path.Combine(fwUpdateBuilderLibraryPath,
|
|
FwUpdateConfig.MeterFwUpdateRulerConfigFileName);
|
|
if (!File.Exists(rulerPathName)) rulerPathName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
|
|
FwUpdateConfig.MeterFwUpdateRulerConfigFileName);
|
|
if (File.Exists(rulerPathName))
|
|
{
|
|
var rulerFile = File.ReadAllText(rulerPathName, Encoding.UTF8);
|
|
_meterFwUpdateRuler = JsonConvert.DeserializeObject<List<MeterFwUpdateRuler>>(rulerFile);
|
|
}
|
|
}
|
|
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}";
|
|
_logger.Info(StrSeparator);
|
|
_logger.Info(_versionString);
|
|
_logger.Info(StrSeparator);
|
|
|
|
InitializeComponent();
|
|
|
|
_cultureInfo = Thread.CurrentThread.CurrentCulture;
|
|
radioBtnEnglishLanguage.Checked = true;
|
|
if (_cultureInfo.IetfLanguageTag == "de-DE")
|
|
{
|
|
radioBtnGermanLanguage.Checked = true;
|
|
}
|
|
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 = @"1234567890";
|
|
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)
|
|
{
|
|
_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 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, not longer taken from locally file system!
|
|
/// </remarks>
|
|
public Boolean BuildFwUpdateSafe()
|
|
{
|
|
if (string.IsNullOrEmpty(lblUpdateOperator.Text)) return false;
|
|
DisableAllControlsInvoked();
|
|
Invoke(new Action(() =>
|
|
{
|
|
tabControlSelection.SelectTab(tabPageSafeBuildReport);
|
|
tabControlSelection.Refresh();
|
|
}));
|
|
try
|
|
{
|
|
var fwUpdateSafe = new FwUpdateSafe
|
|
{
|
|
//License = new SoftwareLicense(),
|
|
Software = new SoftwareContainer(),
|
|
Updates = new UpdateContainer()
|
|
};
|
|
|
|
// check DB connection in advance to overcome the timing issues for DB service startup
|
|
_fwUpdateDbAccess.CheckDbConnection();
|
|
|
|
LogText(StrSeparator);
|
|
LogText(Resources.StrCustomerName + @" " + tbxCustomerName.Text);
|
|
LogText(Resources.StrCustomerNumber + @" " + lblCustomerNumber.Text);
|
|
LogText($@"{Resources.StrOrderNumber} {tbxOrderNumber.Text}-{tbxOrderPosition.Text}");
|
|
LogText(Resources.StrBuilderOperator + @" " + _regUser.FullName);
|
|
LogText(Resources.StrUpdateOperator + @" " + lblUpdateOperator.Text);
|
|
LogText(Resources.StrValidDate + @" " + lblFwUpdateDutyDate.Text);
|
|
LogText(StrSeparator);
|
|
|
|
// 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);
|
|
|
|
LogSuccessText($@"{Resources.StrSwLicenseLoadedSuccessfully} {FwUpdateProjectName}" +
|
|
$" {fwUpdateSafe.License.Major}.{fwUpdateSafe.License.Minor}.{fwUpdateSafe.License.Build}");
|
|
|
|
// 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;
|
|
}
|
|
|
|
if (_fwUpdateCapability.All(x => x.ReleaseContainerLoaded == false))
|
|
{
|
|
_processState = ProcessState.Error;
|
|
return false;
|
|
}
|
|
|
|
fwUpdateSafe.Updates = new UpdateContainer
|
|
{
|
|
CordonelFwPackages = new List<CordonelFirmware>(),
|
|
CordonelDeviceInfos = new List<CordonelDeviceInfo>()
|
|
};
|
|
fwUpdateSafe.Updates.CordonelFwPackages = _fwUpdatePackages;
|
|
fwUpdateSafe.Updates.CordonelDeviceInfos = _cordonelUpdateList;
|
|
|
|
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);
|
|
|
|
// 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(), "");
|
|
// leave all word characters (including the umlaut in for multilingual support), numbers the "-" and the white space in
|
|
fileName = Regex.Replace(fileName, @"[^\w\d\-\s]", "");
|
|
|
|
// The safe shall look like "Thames Water_01234567890-10.safe"
|
|
_fwUpdateSafeName = $@"{fileName}{FwUpdateConfig.FwUpdateFileFieldSeparator}" +
|
|
$@"{tbxOrderNumber.Text}-{tbxOrderPosition.Text}" +
|
|
FwUpdateConfig.FwUpdateFileExtension;
|
|
|
|
// prepare FwUpdateSafeDb
|
|
if (string.IsNullOrEmpty(_regUser.FullName)) _regUser.FullName = "";
|
|
_fwUpdateSafeDb = new FwUpdateSafeDb
|
|
{
|
|
OperatorNameBuilder = _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.StrFwUpdateSafeBuildFailed);
|
|
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>
|
|
public void CompleteCordonelDeviceInfos()
|
|
{
|
|
// establish DB connection with dummy request
|
|
_fwUpdateDbAccess?.DownloadCordonelPwdFromDb("0", out _);
|
|
_fwUpdateDbAccess?.DownloadCordonelPwdFromDb("0", out _);
|
|
|
|
// 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.RequiredRelease);
|
|
_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>
|
|
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;
|
|
break;
|
|
}
|
|
|
|
if (_regUser.AccountActive)
|
|
{
|
|
EnableInputsInvoked();
|
|
_processState = ProcessState.Idle;
|
|
return;
|
|
}
|
|
DisableControlsExceptLanguageInvoked();
|
|
_processState = ProcessState.DbAccessLocked;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check the update capability of all selected Cordonels
|
|
/// </summary>
|
|
/// <remarks date="2021-Mar-26" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void CheckUpdateCapability()
|
|
{
|
|
var success = true;
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
// load the actual installed app versions
|
|
// check metrology
|
|
// check core revision
|
|
// check radio frequency
|
|
if (success)
|
|
{
|
|
LogSuccessText(Resources.StrCordonelUpdateCapabilityCheckSuccess + " " + cordonel.PcbId);
|
|
return;
|
|
}
|
|
var msg = Resources.StrCordonelUpdateCapabilityCheckFailed + @" " + cordonel.PcbId;
|
|
LogErrorText(msg);
|
|
MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
/// <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>
|
|
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 = @"*";
|
|
cbxCordonelProductionOrdersSearch.Items.Add("*");
|
|
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?.DbCordonelFwPackages != null && _fwUpdatePackages != null &&
|
|
_cbxFwReleaseSelection != null)
|
|
{
|
|
if (_cbxFwReleaseSelection.Items.Count != _fwUpdatePackages.Count)
|
|
{
|
|
_cbxFwReleaseSelection.Items.Clear();
|
|
foreach (var fw in _fwUpdatePackages)
|
|
{
|
|
_cbxFwReleaseSelection.Items.Add(fw.ReleaseNameVersion);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if FW packages are selected
|
|
if (_fwUpdatePackages != null && lblSelectedFwPackages.Text != _fwUpdatePackages.Count.ToString())
|
|
lblSelectedFwPackages.Text = _fwUpdatePackages.Count.ToString();
|
|
backGroundColor = _fwUpdatePackages != null && _fwUpdatePackages.Count == 0 ? 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.Text = @"*";
|
|
cbxFwPackageRadioMask.Items.Add("*");
|
|
foreach (var item in _radioSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != "?")
|
|
cbxFwPackageRadioMask.Items.Add(item);
|
|
}
|
|
}
|
|
|
|
// 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.Text = @"*";
|
|
cbxFwPackageRegionMask.Items.Add("*");
|
|
foreach (var item in _regionSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != "?")
|
|
cbxFwPackageRegionMask.Items.Add(item);
|
|
}
|
|
}
|
|
// 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.Text = @"*";
|
|
cbxFwPackageSizeMask.Items.Add("*");
|
|
foreach (var item in _sizeSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != "?")
|
|
cbxFwPackageSizeMask.Items.Add(item);
|
|
}
|
|
}
|
|
// check if FW packages are loaded from DB and parsed to the search info to extract metrology info
|
|
if (_metrologySearchItems.Count + 1 != cbxFwPackageSearchMetrology.Items.Count)
|
|
{
|
|
cbxFwPackageSearchMetrology.Items.Clear();
|
|
cbxFwPackageSearchMetrology.Text = @"*";
|
|
cbxFwPackageSearchMetrology.Items.Add("*");
|
|
foreach (var item in _metrologySearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != "?")
|
|
cbxFwPackageSearchMetrology.Items.Add(item);
|
|
}
|
|
}
|
|
// check if FW packages are loaded from DB and parsed to the search info to extract core info
|
|
if (_coreSearchItems.Count + 1 != cbxFwPackageSearchCore.Items.Count)
|
|
{
|
|
cbxFwPackageSearchCore.Items.Clear();
|
|
cbxFwPackageSearchCore.Text = @"*";
|
|
cbxFwPackageSearchCore.Items.Add("*");
|
|
foreach (var item in _coreSearchItems)
|
|
{
|
|
if (!string.IsNullOrEmpty(item) && item != "?")
|
|
cbxFwPackageSearchCore.Items.Add(item);
|
|
}
|
|
}
|
|
|
|
// 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.RequiredRelease) ||
|
|
updCord.RequiredRelease == "?");
|
|
|
|
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 ||
|
|
_fwUpdatePackages.Count == 0 ||
|
|
_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>
|
|
private void CheckFwPackageChange()
|
|
{
|
|
if (!_fwPackagePropertyChanged || _fwUpdateDbAccess?.DbCordonelFwPackages == null ||
|
|
_fwUpdateDbAccess.DbCordonelFwPackages.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 CheckReportFilesChange()
|
|
{
|
|
if (!_fwReportFilesPropertyChanged) return;
|
|
|
|
_fwReportFilesPropertyChanged = false;
|
|
// update output information
|
|
FillDataGridWithReportFilesInfos();
|
|
}
|
|
|
|
/// <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 update ruler to define releases which can be updated to another release.
|
|
///// </summary>
|
|
///// <remarks date="2021-Apr-07" author="Thomas Wiedebusch">
|
|
///// - Initial.
|
|
///// </remarks>
|
|
//public void BuildMeterFwUpdateRulerInfo()
|
|
//{
|
|
// var meterFwUpdateRuler = new List<MeterFwUpdateRuler>();
|
|
// var rule = new MeterFwUpdateRuler
|
|
// {
|
|
// Release = "R1066",
|
|
// Region = "EMEA",
|
|
// RadioFrequencyMhz = "433",
|
|
// CoreVersionMin = "162",
|
|
// CoreVersionMax = "164",
|
|
// MetrologyVersion = "287",
|
|
// MeterSizes = new List<String>
|
|
// {
|
|
// "DN50"
|
|
// },
|
|
// ApproverName = "Ami A Arsalan",
|
|
// ApprovalDate = new DateTime(2020, 12, 31)
|
|
// };
|
|
// meterFwUpdateRuler.Add(rule);
|
|
|
|
// rule = new MeterFwUpdateRuler
|
|
// {
|
|
// Release = "R1100",
|
|
// Region = "EMEA",
|
|
// RadioFrequencyMhz = "433",
|
|
// CoreVersionMin = "162",
|
|
// CoreVersionMax = "167",
|
|
// MetrologyVersion = "287",
|
|
// MeterSizes = null,
|
|
// ApproverName = "Willi Weber",
|
|
// ApprovalDate = new DateTime(2021, 04, 01)
|
|
// };
|
|
// meterFwUpdateRuler.Add(rule);
|
|
|
|
// rule = new MeterFwUpdateRuler
|
|
// {
|
|
// Release = "R106F",
|
|
// Region = "EMEA",
|
|
// RadioFrequencyMhz = "868",
|
|
// CoreVersionMin = "162",
|
|
// CoreVersionMax = "166",
|
|
// MetrologyVersion = "287",
|
|
// MeterSizes = new List<String>
|
|
// {
|
|
// "DN50",
|
|
// "DN60",
|
|
// "DN80",
|
|
// "DN150"
|
|
// },
|
|
// ApproverName = "Oliver Ohlsen",
|
|
// ApprovalDate = new DateTime(2021, 01, 08)
|
|
// };
|
|
// meterFwUpdateRuler.Add(rule);
|
|
|
|
// rule = new MeterFwUpdateRuler
|
|
// {
|
|
// Release = "B1070",
|
|
// Region = "NA",
|
|
// RadioFrequencyMhz = null,
|
|
// CoreVersionMin = "162",
|
|
// CoreVersionMax = "166",
|
|
// MetrologyVersion = "508",
|
|
// MeterSizes = new List<String>
|
|
// {
|
|
// "DN50"
|
|
// },
|
|
// ApproverName = "Mike M Miller",
|
|
// ApprovalDate = new DateTime(2021, 01, 13)
|
|
// };
|
|
// meterFwUpdateRuler.Add(rule);
|
|
|
|
// var text = JsonConvert.SerializeObject(meterFwUpdateRuler);
|
|
// var asciiStream = Encoding.UTF8.GetBytes(text);
|
|
// File.WriteAllBytes(FwUpdateConfig.MeterFwUpdateRulerConfigFileName, asciiStream);
|
|
//}
|
|
|
|
///// <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>
|
|
private static void MessageBoxShow(String text, String caption, MessageBoxButtons buttons = MessageBoxButtons.OK,
|
|
MessageBoxIcon icon = MessageBoxIcon.Asterisk)
|
|
{
|
|
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 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>
|
|
private void SetStatusProgressBar(Int32 value = 0, Boolean visible = true)
|
|
{
|
|
if (ProgressBarStatus == null || ProgressBarStatus.Visible == false && visible == false) return;
|
|
ProgressBarStatus.Value = value;
|
|
ProgressBarStatus.Visible = visible;
|
|
}
|
|
|
|
/// <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>
|
|
private void DisableControlsExceptLanguageInvoked()
|
|
{
|
|
UiInvoker.ControlEnableInvoker(grpLanguageSelection, true);
|
|
|
|
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>
|
|
private void EnableInputsInvoked()
|
|
{
|
|
if (_licenseUnchecked || _regUser == null || !_regUser.AccountActive) return;
|
|
UiInvoker.ControlEnableInvoker(grpLanguageSelection, true);
|
|
UiInvoker.ControlEnableInvoker(lblFwUpdateDutyDate, true);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderNumber, true);
|
|
UiInvoker.ControlEnableInvoker(tbxOrderPosition, true);
|
|
UiInvoker.ControlEnableInvoker(tabControlSelection, true);
|
|
}
|
|
|
|
#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>
|
|
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.StrFwUpdateSafeBuildSuccessfully} \"{_fwUpdateSafeName}\"";
|
|
LogText(StrSeparator);
|
|
LogSuccessText(msg);
|
|
LogText(StrSeparator);
|
|
MessageBoxShow($"{Resources.StrFwUpdateSafeBuildSuccessfully}\n\n \"{_fwUpdateSafeName}\"",
|
|
Resources.StrSuccess);
|
|
_processState = ProcessState.Idle;
|
|
}
|
|
else
|
|
{
|
|
var msg = $"{Resources.StrFwUpdateSafeBuildFailed}";
|
|
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 from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Oct-26" author="Thomas Wiedebusch">
|
|
/// - Load configuration files from DB as the latest MeterFwUpdateRuler.json is needed for the
|
|
/// FwUpdateBuilder FW package check and validation routine! This step has to be done in advance
|
|
/// to the FW package load, as the Builder uses the information of the MeterFwUpdateRuler to
|
|
/// create the package information!
|
|
/// </remarks>
|
|
private void LoadDbCordonelFwPackagesTask()
|
|
{
|
|
_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();
|
|
// has to be done first to extract the MeterFwUpdateRuler
|
|
GetFwUpdateConfigFilesFromDb();
|
|
// load the packages and use the MeterFwUpdateRuler to assign the DN, EMEA, NA, 868, 433..
|
|
GetCordonelFwPackagesFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_fwPackagePropertyChanged = true;
|
|
_processState = ProcessState.Idle;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquire all report files from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private void LoadDbReportFilesTask()
|
|
{
|
|
_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();
|
|
GetReportFilesFromDb();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}).ContinueWith(delegate
|
|
{
|
|
_fwReportFilesPropertyChanged = 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 LoadDbOutstandingFwUpdateSafesTask()
|
|
{
|
|
_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();
|
|
GetOutstandingFwUpdateSafesFromDb();
|
|
}
|
|
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>
|
|
private void gridViewFwPackagesSelection_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0 || _fwUpdatePackages == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// the e.RowIndex is referenced to the (sorted) data grid view
|
|
var fwPackage = new CordonelFirmware();
|
|
for (var columnIndex = 0; columnIndex < gridViewFwPackageSelection.ColumnCount; columnIndex++)
|
|
{
|
|
if (gridViewFwPackageSelection.Columns[columnIndex].Name == Resources.StrTableCordonelFwToInstall)
|
|
fwPackage.ReleaseNameVersion =
|
|
gridViewFwPackageSelection.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
}
|
|
|
|
// select FW package
|
|
if (gridViewFwPackageSelection.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// Search the FW package name in data table, select if found
|
|
foreach (var fw in _cordonelFwPackageInfoSearch)
|
|
{
|
|
if (fw.ReleaseNameVersion == fwPackage.ReleaseNameVersion)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
if (fw.IsSelected)
|
|
{
|
|
// remove FW package from list
|
|
fw.IsSelected = false;
|
|
foreach (var x in _fwUpdatePackages.Where(x => x.ReleaseNameVersion ==
|
|
fw.ReleaseNameVersion))
|
|
{
|
|
_fwUpdatePackages.Remove(x);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// add selected package to list if not already in list
|
|
if (_fwUpdatePackages.All(x => x.ReleaseNameVersion != fw.ReleaseNameVersion))
|
|
_fwUpdatePackages.Add(fwPackage);
|
|
fw.IsSelected = true;
|
|
}
|
|
|
|
//search FW package in data table for update
|
|
for (var idx = 0; idx < _dataTableFwPackages.Rows.Count; idx++)
|
|
{
|
|
var dataRow = _dataTableFwPackages.Rows[idx];
|
|
if (fw.ReleaseNameVersion != (String)dataRow[Resources.StrTableCordonelFwToInstall])
|
|
continue;
|
|
|
|
dataRow[Resources.StrTableSelect] = fw.IsSelected;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
} // FW package found
|
|
} // 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>
|
|
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.StrTableCordonelFwIsLatest, typeof(Boolean));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableCordonelFwIsReleased, typeof(Boolean));
|
|
_dataTableFwPackages.Columns.Add(Resources.StrTableCordonelFwVersion, typeof(String));
|
|
|
|
_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));
|
|
|
|
try
|
|
{
|
|
foreach (var fw in _cordonelFwPackageInfoSearch)
|
|
{
|
|
// pre-selection of displayed FW packages
|
|
var requiredCoreVersion = 0;
|
|
if (cbxFwPackageSearchCore.Text != @"*")
|
|
{
|
|
var version = cbxFwPackageSearchCore.Text;
|
|
version = version.Replace(".", "");
|
|
Int32.TryParse(version, out requiredCoreVersion);
|
|
}
|
|
|
|
if (fw.Region != cbxFwPackageRegionMask.Text && cbxFwPackageRegionMask.Text != @"*" ||
|
|
fw.RadioFrequencyMhz != cbxFwPackageRadioMask.Text && cbxFwPackageRadioMask.Text != @"*" ||
|
|
fw.MeterSize != cbxFwPackageSizeMask.Text && cbxFwPackageSizeMask.Text != @"*" ||
|
|
(fw.CoreVersionMin > requiredCoreVersion || requiredCoreVersion > fw.CoreVersionMax) &&
|
|
cbxFwPackageSearchCore.Text != @"*" ||
|
|
fw.MetrologyVersion != cbxFwPackageSearchMetrology.Text &&
|
|
cbxFwPackageSearchMetrology.Text != @"*") continue;
|
|
|
|
var row = _dataTableFwPackages.NewRow();
|
|
row[Resources.StrTableSelect] = fw.IsSelected;
|
|
|
|
row[Resources.StrTableCordonelFwToInstall] = fw.ReleaseNameVersion;
|
|
row[Resources.StrTableCordonelFwIsLatest] = fw.FileIsLatest;
|
|
row[Resources.StrTableCordonelFwIsReleased] = fw.FwIsReleased;
|
|
row[Resources.StrTableCordonelFwVersion] = fw.ReleaseVersion;
|
|
|
|
row[Resources.StrTableRegion] = fw.Region;
|
|
row[Resources.StrTableRadioFrequency] = fw.RadioFrequencyMhz;
|
|
row[Resources.StrTableCordonelMetrology] = fw.MetrologyVersion;
|
|
row[Resources.StrTableFwPackageCoreMin] = $"{fw.CoreVersionMin / 100}.{fw.CoreVersionMin % 100}";
|
|
row[Resources.StrTableFwPackageCoreMax] = $"{fw.CoreVersionMax / 100}.{fw.CoreVersionMax % 100}";
|
|
|
|
row[Resources.StrTableCordonelDiameter] = fw.MeterSize;
|
|
row[Resources.StrTableReleaseDate] = fw.ReleaseDate.Date;
|
|
|
|
_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 = true;
|
|
}
|
|
}
|
|
#endregion --------------------------------------- Data Grid FW Packages ---------------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Update Safes --------------------------------------
|
|
/// <summary>
|
|
/// Build data grid for FW-Update update safes
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void FillDataGridWithFwUpdateSafesInfos()
|
|
{
|
|
}
|
|
#endregion --------------------------------------- Data Grid Update Safes --------------------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Report Files --------------------------------------
|
|
/// <summary>
|
|
/// Build data grid for FW-Update report files
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void FillDataGridWithReportFilesInfos()
|
|
{
|
|
}
|
|
|
|
#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>
|
|
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.RequiredRelease =
|
|
gridViewPreBuildSummary.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
}
|
|
|
|
// select FW package with combo box
|
|
if (gridViewPreBuildSummary.Columns[e.ColumnIndex].Name == Resources.StrTableCordonelFwToInstall)
|
|
{
|
|
// take the actual cell value as default
|
|
_cbxFwReleaseSelection.Text = cordonelDeviceInfo.RequiredRelease;
|
|
// Adding combo box control into DataGridView
|
|
gridViewPreBuildSummary.Controls.Add(_cbxFwReleaseSelection);
|
|
|
|
// Rectangular area that represents the display area for a cell
|
|
var location = gridViewPreBuildSummary.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
|
|
|
|
// Setting Location and size to fit within the cell
|
|
_cbxFwReleaseSelection.Height = location.Height;
|
|
_cbxFwReleaseSelection.Width = 200;
|
|
_cbxFwReleaseSelection.Location = new Point(location.X, location.Y);
|
|
|
|
// The final selection of the fw package
|
|
_fwPackageCordonelPcbId = cordonelDeviceInfo.PcbId;
|
|
_cbxFwReleaseSelection.DropDownClosed += CbxFwReleaseSelection_DropDownClosed;
|
|
_cbxFwReleaseSelection.Visible = true;
|
|
}
|
|
|
|
// 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;
|
|
// add cordonel to list
|
|
if (cordonel.IsApproved && cordonel.IsSelected &&
|
|
_cordonelUpdateList.All(x => x.PcbId != cordonelDeviceInfo.PcbId))
|
|
_cordonelUpdateList.Add(cordonelDeviceInfo);
|
|
//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
|
|
}
|
|
// select Cordonel
|
|
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
|
|
}
|
|
|
|
// select Cordonel
|
|
if (gridViewPreBuildSummary.Columns[e.ColumnIndex].Name == Resources.StrTableSelect)
|
|
{
|
|
// Search the cordonel in the production pre selected list
|
|
foreach (var cordPre in _cordonelProductionPreSelectInfos)
|
|
{
|
|
if (cordPre.PcbId == cordonelDeviceInfo.PcbId)
|
|
{
|
|
// toggle selection and set information on main screen
|
|
if (cordPre.IsSelected)
|
|
{
|
|
// remove cordonel from list
|
|
cordPre.IsSelected = false;
|
|
foreach (var x in _cordonelUpdateList.Where(x => x.PcbId == cordonelDeviceInfo.PcbId))
|
|
{
|
|
_cordonelUpdateList.Remove(x);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// add cordonel to list
|
|
if (cordPre.IsApproved && _cordonelUpdateList.All(x => x.PcbId != cordonelDeviceInfo.PcbId))
|
|
_cordonelUpdateList.Add(cordonelDeviceInfo);
|
|
cordPre.IsSelected = true;
|
|
}
|
|
//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 (cordPre.PcbId != (String)dataRow[Resources.StrTableCordonelPcbId]) continue;
|
|
|
|
dataRow[Resources.StrTableSelect] = cordPre.IsSelected;
|
|
break;
|
|
}
|
|
|
|
_cordonelsPropertyChanged = true;
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production list
|
|
}
|
|
|
|
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 GFW packages for core revision, diameter, radio, region and metrology based
|
|
/// on selected Cordonels
|
|
/// </remarks>
|
|
private void FillDataGridWithPreBuildSummaryInfos()
|
|
{
|
|
grpLanguageSelection.Enabled = false;
|
|
|
|
_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.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));
|
|
|
|
try
|
|
{
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos)
|
|
{
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordonel.Diameter) && cordonel.Diameter != "?" &&
|
|
!_sizeSearchItems.Contains(cordonel.Diameter))
|
|
{
|
|
_sizeSearchItems.Add(cordonel.Diameter);
|
|
}
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordonel.RadioFrequency) && cordonel.RadioFrequency != "?" &&
|
|
!_radioSearchItems.Contains(cordonel.RadioFrequency))
|
|
{
|
|
_radioSearchItems.Add(cordonel.RadioFrequency);
|
|
}
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordonel.Region) && cordonel.Region != "?" &&
|
|
!_regionSearchItems.Contains(cordonel.Region))
|
|
{
|
|
_regionSearchItems.Add(cordonel.Region);
|
|
}
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordonel.CoreRevision) && cordonel.CoreRevision != "?" &&
|
|
!_coreSearchItems.Contains(cordonel.CoreRevision))
|
|
{
|
|
_coreSearchItems.Add(cordonel.CoreRevision);
|
|
}
|
|
// fill search masks for FW package selection
|
|
if (!string.IsNullOrEmpty(cordonel.Metrology) && cordonel.Metrology != "?" &&
|
|
!_metrologySearchItems.Contains(cordonel.Metrology))
|
|
{
|
|
_metrologySearchItems.Add(cordonel.Metrology);
|
|
}
|
|
|
|
// search if this Cordonel is already in cordonelDeviceInfo list as this is the marker
|
|
// to update it and a new selection may overwrite the update (IsSelected == true) status
|
|
if (_cordonelUpdateList.Any(x => x.PcbId == cordonel.PcbId)) cordonel.IsSelected = true;
|
|
|
|
var row = _dataTableSummary.NewRow();
|
|
row[Resources.StrTableSelect] = cordonel.IsSelected;
|
|
row[Resources.StrTableApprove] = cordonel.IsApproved;
|
|
row[Resources.StrTableRemove] = cordonel.IsRemoved;
|
|
|
|
row[Resources.StrTableCordonelCustomerSerialNumber] = cordonel.CustomerSerialNumber ?? "?";
|
|
row[Resources.StrTableCordonelPcbId] = cordonel.PcbId ?? "?";
|
|
|
|
row[Resources.StrTableCordonelFwToInstall] = cordonel.RequiredReleaseNameVersion ?? "?";
|
|
|
|
row[Resources.StrTableCordonelMetrology] = cordonel.Metrology ?? "?";
|
|
row[Resources.StrTableCordonelMetrologyIsUpdateable] = cordonel.MetrologyIsUpdateable;
|
|
|
|
row[Resources.StrTableCordonelCore] = cordonel.CoreRevision ?? "?";
|
|
|
|
row[Resources.StrTableRegion] = cordonel.Region ?? "?";
|
|
row[Resources.StrTableRadioFrequency] = cordonel.RadioFrequency ?? "?";
|
|
|
|
row[Resources.StrTableCordonelDiameter] = cordonel.Diameter ?? "?";
|
|
|
|
row[Resources.StrTableReason] = cordonel.ReasonForUpdateDenied ?? "";
|
|
|
|
_dataTableSummary.Rows.Add(row);
|
|
}
|
|
|
|
gridViewPreBuildSummary.DataSource = _dataTableSummary;
|
|
|
|
foreach (DataGridViewColumn column in gridViewPreBuildSummary.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
// color the results of the compare
|
|
PreBuildSummaryInformationStyleSet();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = true;
|
|
}
|
|
}
|
|
|
|
/// <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 != "?")
|
|
{
|
|
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>
|
|
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();
|
|
|
|
// add here the required release
|
|
if (gridViewCordonelSelection.Columns[columnIndex].Name == Resources.StrTableCordonelFwToInstall)
|
|
cordSelect.RequiredReleaseNameVersion =
|
|
gridViewCordonelSelection.Rows[e.RowIndex].Cells[columnIndex].Value.ToString();
|
|
}
|
|
|
|
// select FW package with combo box
|
|
if (gridViewCordonelSelection.Columns[e.ColumnIndex].Name == Resources.StrTableCordonelFwToInstall)
|
|
{
|
|
// take the actual cell value as default
|
|
_cbxFwReleaseSelection.Text = cordSelect.RequiredReleaseNameVersion;
|
|
// Adding combo box control into DataGridView
|
|
gridViewCordonelSelection.Controls.Add(_cbxFwReleaseSelection);
|
|
|
|
// Rectangular area that represents the display area for a cell
|
|
var location = gridViewCordonelSelection.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
|
|
|
|
// Setting Location and size to fit within the cell
|
|
_cbxFwReleaseSelection.Height = location.Height;
|
|
_cbxFwReleaseSelection.Width = 200;
|
|
_cbxFwReleaseSelection.Location = new Point(location.X, location.Y);
|
|
|
|
// The final selection of the fw package
|
|
_fwPackageCordonelPcbId = cordSelect.PcbId;
|
|
_cbxFwReleaseSelection.DropDownClosed += CbxFwReleaseSelection_DropDownClosed;
|
|
_cbxFwReleaseSelection.Visible = true;
|
|
}
|
|
|
|
// 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 from list
|
|
cordSearch.IsSelected = 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;
|
|
if (_cordonelProductionPreSelectInfos.All(x => x.PcbId != cordSelect.PcbId))
|
|
_cordonelProductionPreSelectInfos.Add(cordSearch);
|
|
|
|
_preBuildSummaryPropertyChanged = true;
|
|
}
|
|
//search cordonel in data table for update of "select" 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;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}// Cordonel found
|
|
}// Search the cordonel in the production search list
|
|
}
|
|
|
|
_cordonelsPropertyChanged = false;
|
|
// _preBuildSummaryPropertyChanged = false;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event on closing the fw package selection
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2021-Apr-10" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-16" author="Thomas Wiedebusch">
|
|
/// - Pre build summary changed
|
|
/// </remarks>
|
|
/// <remarks date="2021-Apr-17" author="Thomas Wiedebusch">
|
|
/// - Production pre select infos from production search infos.
|
|
/// </remarks>
|
|
private void CbxFwReleaseSelection_DropDownClosed(Object sender, EventArgs e)
|
|
{
|
|
_cbxFwReleaseSelection.DropDownClosed -= CbxFwReleaseSelection_DropDownClosed;
|
|
if (!string.IsNullOrEmpty(_fwPackageCordonelPcbId) && _cbxFwReleaseSelection.SelectedItem != null)
|
|
{
|
|
// attach fw update package name to eventually unselected in production search list Cordonels
|
|
foreach (var cordonel in _cordonelProductionSearchInfos.Where(cordonel =>
|
|
cordonel.PcbId == _fwPackageCordonelPcbId))
|
|
{
|
|
cordonel.RequiredReleaseNameVersion = _cbxFwReleaseSelection.SelectedItem.ToString();
|
|
break;
|
|
}
|
|
// attach fw update package name in production pre selected list Cordonels
|
|
foreach (var cordonel in _cordonelProductionPreSelectInfos.Where(cordonel =>
|
|
cordonel.PcbId == _fwPackageCordonelPcbId))
|
|
{
|
|
cordonel.RequiredReleaseNameVersion = _cbxFwReleaseSelection.SelectedItem.ToString();
|
|
break;
|
|
}
|
|
// attach fw update package name in update list Cordonels
|
|
foreach (var cordonel in _cordonelUpdateList.Where(cordonel =>
|
|
cordonel.PcbId == _fwPackageCordonelPcbId))
|
|
{
|
|
cordonel.RequiredRelease = _cbxFwReleaseSelection.SelectedItem.ToString();
|
|
break;
|
|
}
|
|
}
|
|
_cbxFwReleaseSelection.Visible = false;
|
|
_cordonelsPropertyChanged = true;
|
|
_preBuildSummaryPropertyChanged = true;
|
|
}
|
|
|
|
/// <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>
|
|
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.StrTableCordonelCustomerSerialNumber, typeof(String));
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelPcbId, typeof(String));
|
|
|
|
_dataTableCordonels.Columns.Add(Resources.StrTableCordonelFwToInstall, 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 != @"*") 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;
|
|
break;
|
|
}
|
|
|
|
var row = _dataTableCordonels.NewRow();
|
|
row[Resources.StrTableSelect] = cordSearch.IsSelected;
|
|
|
|
row[Resources.StrTableCordonelCustomerSerialNumber] = cordSearch.CustomerSerialNumber ?? "?";
|
|
row[Resources.StrTableCordonelPcbId] = cordSearch.PcbId ?? "?";
|
|
|
|
row[Resources.StrTableCordonelFwToInstall] = cordSearch.RequiredReleaseNameVersion ?? "?";
|
|
row[Resources.StrTableCordonelInstalledFw] = cordSearch.InstalledReleaseNameVersion ?? "?";
|
|
|
|
row[Resources.StrTableCordonelMetrology] = cordSearch.Metrology ?? "?";
|
|
row[Resources.StrTableCordonelMetrologyIsUpdateable] = cordSearch.MetrologyIsUpdateable;
|
|
|
|
row[Resources.StrTableCordonelCore] = cordSearch.CoreRevision ?? "?";
|
|
row[Resources.StrTableRegion] = cordSearch.Region ?? "?";
|
|
row[Resources.StrTableRadioFrequency] = cordSearch.RadioFrequency ?? "?";
|
|
row[Resources.StrTableCordonelDiameter] = cordSearch.Diameter ?? "?";
|
|
|
|
row[Resources.StrTableCordonelProductionOrder] = cordSearch.CustomerOrderNumber;
|
|
row[Resources.StrTableCordonelProductionPos] = cordSearch.CustomerOrderPos;
|
|
row[Resources.StrTableCordonelSize] = cordSearch.Length ?? "?";
|
|
row[Resources.StrTableCordonelCatalogueNumber] = cordSearch.CatalogNumber ?? "?";
|
|
|
|
_dataTableCordonels.Rows.Add(row);
|
|
}
|
|
|
|
gridViewCordonelSelection.DataSource = _dataTableCordonels;
|
|
|
|
foreach (DataGridViewColumn column in gridViewCordonelSelection.Columns)
|
|
{
|
|
column.SortMode = DataGridViewColumnSortMode.Automatic;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = true;
|
|
}
|
|
}
|
|
#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
|
|
UpdateUpdateOperatorsInformationStyleSet();
|
|
}
|
|
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>
|
|
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
|
|
UpdateUpdateOperatorsInformationStyleSet();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_processState = ProcessState.Error;
|
|
}
|
|
finally
|
|
{
|
|
grpLanguageSelection.Enabled = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Color the rows depending on the state
|
|
/// </summary>
|
|
/// <remarks date="2021-Feb-26" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void UpdateUpdateOperatorsInformationStyleSet()
|
|
{
|
|
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)
|
|
{
|
|
UpdateUpdateOperatorsInformationStyleSet();
|
|
}
|
|
|
|
#endregion --------------------------------------- Data Grid Controls Update Operators ------------------------
|
|
|
|
#region ------------------------------------------ Data Grid Controls Customer Selection ----------------------
|
|
/// <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>
|
|
private void gridViewCustomerSelection_CellClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableCustomers == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 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>
|
|
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 = true;
|
|
}
|
|
}
|
|
|
|
#endregion --------------------------------------- Data Grid Controls Customer Selection ----------------------
|
|
|
|
#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 serial numbers 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>
|
|
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.ConvertOrderSizeNumberToSizeName(order.Diameter),
|
|
Length = 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
|
|
{
|
|
// this is always a number like 1.23 or 10.2D or 60.2D, a msb higher 5 is
|
|
// indicating "B" version
|
|
var msb = appVersion.Version.Substring(0, 1);
|
|
var lsb = appVersion.Version.Substring(1, appVersion.Version.Length - 1);
|
|
if (Int16.TryParse(msb, out var msbNumber))
|
|
{
|
|
if (msbNumber >= 6)
|
|
{
|
|
msbNumber -= 5;
|
|
cordonel.InstalledReleaseNameVersion = $"B{msbNumber}{lsb}";
|
|
}
|
|
else cordonel.InstalledReleaseNameVersion = "R" + appVersion.Version;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
cordonel.Region = string.IsNullOrEmpty(cordonel.RadioFrequency) ? "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 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>
|
|
private void GetCordonelFwPackagesFromDb()
|
|
{
|
|
if (_fwUpdateDbAccess == null || !_fwUpdateDbAccess.GetAllCordonelFwInfoFilesFromDb() ||
|
|
_fwUpdateDbAccess.DbCordonelFwPackages.Count == 0 || _cordonelFwPackageInfoSearch == null)
|
|
return;
|
|
|
|
_cordonelFwPackageInfoSearch.Clear();
|
|
// 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).
|
|
// GetConfigurationFilesFromDb();
|
|
|
|
// Start with the last package, as this will be the latest
|
|
for (var idx = _fwUpdateDbAccess.DbCordonelFwPackages.Count - 1;
|
|
idx > _fwUpdateDbAccess.DbCordonelFwPackages.Count - 40; idx--)
|
|
{
|
|
// read the package without the content, skip all if fwPackageFilesInfo returns null
|
|
var dbCordonelFwFile = _fwUpdateDbAccess.DbCordonelFwPackages[idx];
|
|
var fileId = dbCordonelFwFile.FileId;
|
|
// Split to PROD_EMEA_433_DN50_R101D
|
|
var nameSplit = dbCordonelFwFile.FileName.Split('_');
|
|
if (_fwUpdateDbAccess.GetCordonelFwPackageFromDb(fileId, out var fwPackageFilesInfo, false) &&
|
|
fwPackageFilesInfo != null && fwPackageFilesInfo.Count > 0)
|
|
{
|
|
// parse file information
|
|
if (dbCordonelFwFile.CordonelFwFile_Dn != null)
|
|
{
|
|
var fwPackInfo = new CordonelFwPackageInfo
|
|
{
|
|
ReleaseNameVersion = dbCordonelFwFile.FileName,
|
|
Region = dbCordonelFwFile.FileName.Contains("EMEA") ? "EMEA" : "NA",
|
|
RadioFrequencyMhz = dbCordonelFwFile.FileName.Contains("433") ? "433" :
|
|
dbCordonelFwFile.FileName.Contains("868") ? "868" : "-",
|
|
FileIsLatest = dbCordonelFwFile.FileIsLatest,
|
|
MeterSize = MeterSizeConverter.ConvertOrderSizeNumberToSizeName(
|
|
MeterSizeConverter.ConvertToOrder((MeterSize)dbCordonelFwFile.CordonelFwFile_Dn)),
|
|
ReleaseDate = dbCordonelFwFile.FileDate,
|
|
ReleaseVersion = $"{nameSplit[nameSplit.Length - 1].Substring(0, 3)}." +
|
|
$"{nameSplit[nameSplit.Length - 1].Substring(3, 2)}"
|
|
};
|
|
// the release version is always the last element of the name split
|
|
foreach (var binfile in fwPackageFilesInfo)
|
|
{
|
|
// extract metrology version
|
|
if (binfile.FileName.Contains("binfile0F_"))
|
|
{
|
|
var msb = binfile.FileName.Substring(10, 2);
|
|
// remove leading 0
|
|
var msbMsb = msb.Substring(0, 1);
|
|
if (msbMsb == "0") msb = msb.Remove(0, 1);
|
|
var lsb = binfile.FileName.Substring(12, 2);
|
|
fwPackInfo.MetrologyVersion = $"{msb}.{lsb}";
|
|
break;
|
|
}
|
|
}
|
|
// take the meter fw update ruler to extract core min /max and released
|
|
foreach (var rule in _meterFwUpdateRuler)
|
|
{
|
|
var releaseVersion = $"{rule.Release.Substring(0, 3)}." +
|
|
$"{rule.Release.Substring(3, 2)}";
|
|
if (releaseVersion == fwPackInfo.ReleaseVersion)
|
|
{
|
|
int.TryParse(rule.CoreVersionMin, out var x);
|
|
fwPackInfo.CoreVersionMin = x;
|
|
int.TryParse(rule.CoreVersionMax, out x);
|
|
fwPackInfo.CoreVersionMax = x;
|
|
fwPackInfo.FwIsReleased = !string.IsNullOrEmpty(rule.ApproverName);
|
|
}
|
|
}
|
|
|
|
_cordonelFwPackageInfoSearch.Add(fwPackInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <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
|
|
{
|
|
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 all FW update report files from DB.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void GetReportFilesFromDb()
|
|
{
|
|
var fwUpdateReports = new List<FwUpdateReportDb>();
|
|
_fwUpdateDbAccess?.DownloadFwUpdateReportsFromDb(out fwUpdateReports);
|
|
}
|
|
/// <summary>
|
|
/// Get all active FW update safes from DB. Outdated safes cannot be accessed.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-28" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void GetOutstandingFwUpdateSafesFromDb()
|
|
{
|
|
var fwUpdateSafes= new List<FwUpdateSafeDb>();
|
|
if (_fwUpdateDbAccess != null)
|
|
{
|
|
foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators)
|
|
{
|
|
_fwUpdateDbAccess.ListAllFwUpdateSafesOfUserFromDb(user.Id, out var fwUpdateSafesOfUser);
|
|
fwUpdateSafes.AddRange(fwUpdateSafesOfUser);
|
|
}
|
|
}
|
|
}
|
|
/// <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>
|
|
/// Collect order number, radio address, skeleton key, password hashes and passwords from DB.
|
|
/// </summary>
|
|
/// <param name="cordonel"></param>
|
|
/// <returns>password container</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>
|
|
private Boolean GetPwdFromDb(CordonelDeviceInfo cordonel)
|
|
{
|
|
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);
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Cordonel Fa update configuration files from DB.
|
|
/// 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).
|
|
/// Copies the MeterFwUpdateRuler.json to the [exe-root] or [exe-root]/Library of the FwUpdateBuilder.
|
|
/// </summary>
|
|
/// <remarks date="2021-Oct-27" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
private void GetFwUpdateConfigFilesFromDb()
|
|
{
|
|
if (_fwUpdateDbAccess == null ||
|
|
!_fwUpdateDbAccess.DownloadFwUpdateConfigurationFilesFromDb() ||
|
|
_fwUpdateDbAccess.DbFwUpdateConfigFiles.Count == 0)
|
|
return;
|
|
|
|
try
|
|
{
|
|
// extract the MeterFwUpdateRuler
|
|
foreach (var f in _fwUpdateDbAccess.DbFwUpdateConfigFiles)
|
|
{
|
|
if (f.FileName == FwUpdateConfig.MeterFwUpdateRulerConfigFileName)
|
|
{
|
|
// Copy MeterFwUpdateRuler either to exe-path or if existing to Library-subfolder
|
|
var fwUpdateBuilderExePath = AppDomain.CurrentDomain.BaseDirectory;
|
|
var fwUpdateBuilderLibraryPath = Path.Combine(fwUpdateBuilderExePath,
|
|
FwUpdateConfig.LibrarySubFolderName);
|
|
|
|
// check the Library path existence (will be used in Release build)
|
|
var meterFwUpdateRulerPath = Directory.Exists(fwUpdateBuilderLibraryPath) ?
|
|
fwUpdateBuilderLibraryPath : fwUpdateBuilderExePath;
|
|
|
|
var sourceFile = Path.Combine(meterFwUpdateRulerPath, f.FileName);
|
|
var fs = File.Open(sourceFile, FileMode.Create);
|
|
fs.Write(f.FileContent, 0, f.FileContent.Length);
|
|
fs.Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
catch (Exception)
|
|
{
|
|
// nothing to do
|
|
}
|
|
}
|
|
|
|
/// <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 SubDiractories.
|
|
/// </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.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.
|
|
/// </summary>
|
|
/// <param name="releaseName">each Cordonel tells wich 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>
|
|
private Boolean GetFwPackageFromDb(String releaseName)
|
|
{
|
|
// if this packages has already been loaded, exit immediately
|
|
if (_fwUpdatePackages.Any(package => package.ReleaseNameVersion == releaseName &&
|
|
package.BinaryApplicationFiles != null &&
|
|
package.BinaryApplicationFiles.Count > 0))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
String msg;
|
|
// search file id in ClusteredFiles but as the name in unambiguous and files are stored several times
|
|
// with this file name, the last and therefor latest item has to be taken
|
|
if (_fwUpdateDbAccess?.DbCordonelFwPackages != null)
|
|
{
|
|
var fileId = (from cu in _fwUpdateDbAccess.DbCordonelFwPackages
|
|
where cu.FileName == releaseName
|
|
select cu.FileId).LastOrDefault();
|
|
|
|
if (_fwUpdateDbAccess.GetCordonelFwPackageFromDb(fileId, out var fwPackage))
|
|
{
|
|
try
|
|
{
|
|
// search the cordonel firmware
|
|
foreach (var fw in _fwUpdatePackages.Where(fw => fw.ReleaseNameVersion == releaseName))
|
|
{
|
|
fw.PackageDescriptionFile = new FilePart();
|
|
fw.BinaryApplicationFiles = new List<FilePart>();
|
|
|
|
foreach (var f in fwPackage)
|
|
{
|
|
// load the ADF
|
|
if (f.FileName.Contains("product") && f.FileName.EndsWith(".txt"))
|
|
{
|
|
fw.PackageDescriptionFile.FileName = f.FileName;
|
|
fw.PackageDescriptionFile.FileContent = new Byte[f.FileContent.Length];
|
|
fw.PackageDescriptionFile.FileContent = f.FileContent.ToArray();
|
|
}
|
|
|
|
// load the binaries
|
|
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();
|
|
fw.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(this.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;
|
|
_fwReportFilesPropertyChanged = true;
|
|
_fwUpdateSafesPropertyChanged = true;
|
|
_preBuildSummaryPropertyChanged = true;
|
|
|
|
lblFwUpdateDutyDate.Text = _datePicker.Value.ToShortDateString();
|
|
}
|
|
|
|
#endregion --------------------------------------- Language ---------------------------------------------------
|
|
|
|
}
|
|
}
|