using Newtonsoft.Json; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; using System.Drawing; using System.IO; using System.IO.Ports; using System.Linq; using System.Threading; using System.Windows.Forms; using System.Xml.Linq; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.Interfaces.Ports.PortCore; using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments; using Xylem.Common.Hardware.Interfaces.Ports.SerialPorts; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Utils.Logging; using NLog; using GenesisCordonelInterface.API; namespace GenesisCordonelInterface.UI.LaatzenAPI_GenesisToolBox { /// /// Setup of GTB /// public partial class FrmSetup : Form { private static readonly NLog.ILogger Logger = NLog.LogManager.GetLogger("GenesisCordonelInterface"); private readonly InterfaceGCIToLaatzen interfaceToLaatzen = new InterfaceGCIToLaatzen(); private const String RequestPortString = "RequestPort"; private const String RequestTypeString = "RequestType"; private const String StreamingPortString = "StreamingPort"; private const String SlotTypeString = "RefTemperature"; private const String SlotString = "Slot"; private const String StreamingDetectString = "DetectStreaming"; private const String RequestDetectString = "DetectRequest"; private const String ValueString = "Value"; private const String TextString = "Text"; private String _fileString; private readonly String _serialConfigFilePathName; private readonly String _offlinePwdPathName; private readonly DataTable _slotConfigDataTable = new DataTable(); private readonly SirtConfig _sirtConfig = new SirtConfig(); private readonly ProcessConfig _configuration = new ProcessConfig(); private ConcurrentBag _countRawData = new ConcurrentBag(); private List _listOfOfflinePasswords = new List(); /// /// Ctor /// public FrmSetup() { _serialConfigFilePathName = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Genesis", ProgramConfig.SerialConfigFileName); _offlinePwdPathName = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Genesis", ProgramConfig.OfflineInfoFile); if (!File.Exists(_offlinePwdPathName)) { _listOfOfflinePasswords.Add(new OfflinePasswordItem("", "")); File.WriteAllText(_offlinePwdPathName, JsonConvert.SerializeObject(_listOfOfflinePasswords)); } _slotConfigDataTable.Columns.Add(SlotString, typeof(String)); _slotConfigDataTable.Columns.Add(StreamingPortString, typeof(String)); _slotConfigDataTable.Columns.Add(RequestPortString, typeof(String)); _slotConfigDataTable.Columns.Add(RequestTypeString, typeof(String)); _slotConfigDataTable.Columns.Add(SlotTypeString, typeof(String)); InitializeComponent(); tbcSlot.Name = SlotString; cbcRequestPort.Name = RequestPortString; cbcRequestType.Name = RequestTypeString; cbcStreamingPort.Name = StreamingPortString; cbcSlotType.Name = SlotTypeString; btcDetectStreaming.Name = StreamingDetectString; btcDetectRequest.Name = RequestDetectString; btcDetectStreaming.Name = StreamingDetectString; tbcSlot.HeaderText = SlotString; cbcRequestPort.HeaderText = RequestPortString; cbcRequestType.HeaderText = RequestTypeString; cbcStreamingPort.HeaderText = StreamingPortString; btcDetectRequest.HeaderText = RequestDetectString; btcDetectStreaming.HeaderText = StreamingDetectString; cbcSlotType.HeaderText = SlotTypeString; LoadFromFile(); _configuration.ReadProcessConfig(); cbUseMinMaxCheck.Checked = _configuration.UseMinMaxCheck; cbUseRegisterWatch.Checked = _configuration.UseRegisterWatchService; txtWachSeriveUrl.Text = _configuration.RegisterWatchServiceUrl; cbUpdateFiles.Checked = _configuration.AutoUpdateFiles; cbxProductionMode.Checked = _configuration.ProductionMode; _sirtConfig.ReadSirtConfig(); tbxSirtStationId.Text = _sirtConfig.StationId?.ToString(); tbxSirtBoxNo.Text = _sirtConfig.SirtBoxNo?.ToString(); if (_sirtConfig.SirtComport433MHz != null) cbxSirtComport433MHz.Items.Add(_sirtConfig.SirtComport433MHz); if (_sirtConfig.SirtComport868MHz != null) cbxSirtComport868MHz.Items.Add(_sirtConfig.SirtComport868MHz); var comPorts = SerialPort.GetPortNames().ToList(); foreach (var comPort in comPorts.Where(comPort => !cbxSirtComport433MHz.Items.Contains(comPort))) { cbxSirtComport433MHz.Items.Add(comPort); } foreach (var comPort in comPorts.Where(comPort => !cbxSirtComport868MHz.Items.Contains(comPort))) { cbxSirtComport868MHz.Items.Add(comPort); } if (cbxSirtComport433MHz.Items.Count > 0) cbxSirtComport433MHz.Text = cbxSirtComport433MHz.Items[0].ToString(); if (cbxSirtComport868MHz.Items.Count > 0) cbxSirtComport868MHz.Text = cbxSirtComport868MHz.Items[0].ToString(); if (_sirtConfig.ServiceSirtComport433MHz != null) cbxSirtService433MHz.Items.Add(_sirtConfig.ServiceSirtComport433MHz); if (_sirtConfig.ServiceSirtComport868MHz != null) cbxSirtService868MHz.Items.Add(_sirtConfig.ServiceSirtComport868MHz); foreach (var comPort in comPorts.Where(comPort => !cbxSirtService433MHz.Items.Contains(comPort))) { cbxSirtService433MHz.Items.Add(comPort); } foreach (var comPort in comPorts.Where(comPort => !cbxSirtService868MHz.Items.Contains(comPort))) { cbxSirtService868MHz.Items.Add(comPort); } if (cbxSirtService433MHz.Items.Count > 0) cbxSirtService433MHz.Text = cbxSirtService433MHz.Items[0].ToString(); if (cbxSirtService868MHz.Items.Count > 0) cbxSirtService868MHz.Text = cbxSirtService868MHz.Items[0].ToString(); Logger.Trace("CONFIG: Setup loaded."); } private void BtnReload_Click(Object sender, EventArgs e) { Logger.Trace("CONFIG: Reload setup requested."); LoadFromFile(); LoadOfflineFile(); Logger.Trace("CONFIG: Setup reloaded."); } private void BtnStore_Click(Object sender, EventArgs e) { Logger.Trace("CONFIG: Save setup requested."); StoreToPc(); StoreOfflineFile(); StoreSirtSettings(); Logger.Trace("CONFIG: Setup saved."); } private void StoreSirtSettings() { if (int.TryParse(tbxSirtStationId.Text, out var intNo)) { _sirtConfig.StationId = intNo; } if (int.TryParse(tbxSirtBoxNo.Text, out intNo)) { _sirtConfig.SirtBoxNo = intNo; } _sirtConfig.SirtComport433MHz = cbxSirtComport433MHz.Text; _sirtConfig.SirtComport868MHz = cbxSirtComport868MHz.Text; _sirtConfig.ServiceSirtComport433MHz = cbxSirtService433MHz.Text; _sirtConfig.ServiceSirtComport868MHz = cbxSirtService868MHz.Text; _sirtConfig.Update(); Logger.Trace("CONFIG: SIRT settings stored."); } private void StoreToPc() { Logger.Trace("CONFIG: Storing slot configuration to PC."); var newFileContent = new List(); for (var row = 0; row < dgvConfig.Rows.Count; row++) { var slotStr = (String)dgvConfig.Rows[row].Cells[SlotString].Value; int.TryParse(slotStr, out var slot); var irdaType = typeof(IrdaSerialPort).FullName; if (dgvConfig.Rows[row].Cells[RequestTypeString].Value != null) { irdaType = (String)dgvConfig.Rows[row].Cells[RequestTypeString].Value; } var requestPort = new PortConfig() { PortName = (String)dgvConfig.Rows[row].Cells[RequestPortString].Value, Type = irdaType }; var streamingPort = new PortConfig() { PortName = (String)dgvConfig.Rows[row].Cells[StreamingPortString].Value, Type = typeof(UartSerialPort).FullName }; var slotType = SlotType.DutMeter; if (dgvConfig.Rows[row].Cells[SlotTypeString].Value != null) { var isChecked = dgvConfig.Rows[row].Cells[SlotTypeString].Value.ToString(); if (bool.TrueString == isChecked) { slotType = SlotType.TemperatureMeter; } } if (!string.IsNullOrEmpty(slotStr)) { newFileContent.Add(new SlotConfig() { Slot = slot, Request = requestPort, Streaming = streamingPort, Type = slotType }); } } var text = JsonConvert.SerializeObject(newFileContent); if (text == _fileString) { Logger.Trace("CONFIG: No setup changes detected."); LoadFromFile(); return; } if (File.Exists(_serialConfigFilePathName)) { var backupSerialConfigFile = $"{Path.GetDirectoryName(_serialConfigFilePathName)}\\Backup_{DateTime.Now:yyyyMMdd}_{DateTime.Now:HHmmss}_{ProgramConfig.SerialConfigFileName}"; File.Move(_serialConfigFilePathName, backupSerialConfigFile); } File.WriteAllText(_serialConfigFilePathName, text); LoadFromFile(); LoadOfflineFile(); Logger.Trace("CONFIG: Slot configuration stored."); } private void LoadFromFile() { Logger.Trace("CONFIG: Loading slot configuration from file."); _slotConfigDataTable.Clear(); dgvConfig.Rows.Clear(); if (!File.Exists(_serialConfigFilePathName)) { Logger.Trace("CONFIG: Serial configuration file not found."); return; } SlotConfig[] meterConfigList; using (var tr = new StreamReader(_serialConfigFilePathName)) { _fileString = tr.ReadToEnd(); meterConfigList = JsonConvert.DeserializeObject(_fileString); } foreach (var item in meterConfigList) { var row = _slotConfigDataTable.NewRow(); row[SlotString] = item.Slot; row[RequestPortString] = item.Request.PortName; row[RequestTypeString] = item.Request.Type; row[StreamingPortString] = item.Streaming.PortName; row[SlotTypeString] = item.Type == SlotType.TemperatureMeter; _slotConfigDataTable.Rows.Add(row); } foreach (DataRow row in _slotConfigDataTable.Rows) { dgvConfig.Rows.Add(AddRowToGrid(row)); } Logger.Trace("CONFIG: Slot configuration loaded."); } private DataGridViewRow AddRowToGrid(DataRow row = null) { var newRow = new DataGridViewRow(); var slotCell = new DataGridViewTextBoxCell(); newRow.Cells.Add(slotCell); var requestPortCell = new DataGridViewComboBoxCell { DataSource = GetPorts(), DisplayMember = TextString, ValueMember = ValueString }; newRow.Cells.Add(requestPortCell); var requestTypeCell = new DataGridViewComboBoxCell { DataSource = GetTypes(), DisplayMember = TextString, ValueMember = ValueString }; newRow.Cells.Add(requestTypeCell); var streamingPortCell = new DataGridViewComboBoxCell { DataSource = GetPorts(), DisplayMember = TextString, ValueMember = ValueString }; newRow.Cells.Add(streamingPortCell); var slotTypeCell = new DataGridViewCheckBoxCell(); slotTypeCell.Value = false; if (row == null) { return newRow; } slotCell.Value = row[SlotString]; streamingPortCell.Value = row[StreamingPortString]; requestPortCell.Value = row[RequestPortString]; try { requestTypeCell.Value = row[RequestTypeString]; } catch (Exception ex) { Logger.Error("Failed to set request type in grid: " + ex.Message); } slotTypeCell.Value = row[SlotTypeString]; newRow.Cells.Add(slotTypeCell); return newRow; } private DataTable GetSlotTypes() { var ret = new DataTable(); ret.Columns.Add(TextString); ret.Columns.Add(ValueString, typeof(Int32)); ret.Rows.Add("DutMeter", SlotType.DutMeter.GetHashCode()); ret.Rows.Add("TemperatureMeter", SlotType.TemperatureMeter.GetHashCode()); return ret; } private DataTable GetPorts() { var ret = new DataTable(); ret.Columns.Add(ValueString); ret.Columns.Add(TextString); var portList = SerialPort.GetPortNames().ToList(); foreach (var item in portList) { ret.Rows.Add(item, item); } foreach (DataRow row in _slotConfigDataTable.Rows) { if (portList.All(pl => pl != (String)row[StreamingPortString])) { ret.Rows.Add(row[StreamingPortString].ToString(), BaseSerialPort.PortNotAssigned); } if (portList.All(pl => pl != (String)row[RequestPortString])) { ret.Rows.Add(row[RequestPortString].ToString(), BaseSerialPort.PortNotAssigned); } } return ret; } private static DataTable GetTypes() { var ret = new DataTable(); ret.Columns.Add(ValueString); ret.Columns.Add(TextString); ret.Rows.Add(typeof(UartSerialPort).FullName, nameof(UartSerialPort)); ret.Rows.Add(typeof(RfidSerialPort).FullName, nameof(RfidSerialPort)); ret.Rows.Add(typeof(IrdaSerialPort).FullName, nameof(IrdaSerialPort)); return ret; } private void __DgvConfig_CellContentClick(Object sender, DataGridViewCellEventArgs e) { Logger.Trace("UI-CLICK: FrmSetup: DgvConfig_CellContentClick() use APILaatzen"); if (e.RowIndex < 0 || e.ColumnIndex < 0) { return; } if (!dgvConfig.Columns[e.ColumnIndex].Name.Contains(StreamingDetectString) && !dgvConfig.Columns[e.ColumnIndex].Name.Contains(RequestDetectString)) { return; } StoreToPc(); var slotString = (String)dgvConfig.Rows[e.RowIndex].Cells[SlotString].Value; int.TryParse(slotString, out var slot); using (var mb = new MeterBatch()) { using (var meter = new GenesisMeter()) { meter.SetupFromConfigFile(slot, false); mb.AddMeter(meter); const String checkMark = "\u2714"; if (dgvConfig.Columns[e.ColumnIndex].Name.Contains(StreamingDetectString)) { Logger.Trace("COM: Detecting streaming port for slot " + slot + "..."); _countRawData = new ConcurrentBag(); meter.StreamingPort.OnRawRecordReceived += delegate (Object o, BasePortDataEventArgs rawMsg) { var data = (String)rawMsg.GetData(); _countRawData.Add(data); }; Thread.Sleep(500); if (_countRawData.Any()) { var text = $"SUCCESS\nSlot: {slot}\nStreaming port: {meter.StreamingPort.GetPortName()}\n\n{checkMark}"; MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK); dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Green; Logger.Info("COM: Streaming detection SUCCESS for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + "."); } else { var text = $"FAILED\nSlot: {slot}\nStreaming port: {meter.StreamingPort.GetPortName()}"; MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error); dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Red; Logger.Error("COM: Streaming detection FAILED for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + "."); } _countRawData = new ConcurrentBag(); } else { meter.Logout(); var pcbId = meter.GetPcbId(); if (string.IsNullOrEmpty(pcbId)) { var text = $"FAILED\nSlot: {slot}\nRequest port: {meter.RequestPort.GetPortName()}"; MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error); dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Red; Logger.Info("COM: Streaming detection SUCCESS for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + "."); } else { var text = $"SUCCESS\nSlot: {slot}\nRequest port: {meter.RequestPort.GetPortName()}\n\n{checkMark}"; MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK); dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Green; Logger.Error("COM: Streaming detection FAILED for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + "."); } } } } } private void DgvConfig_CellContentClick(object sender, DataGridViewCellEventArgs e) { Logger.Trace("UI-CLICK: FrmSetup: DgvConfig_CellContentClick() use API2"); if (e.RowIndex < 0 || e.ColumnIndex < 0) return; var columnName = dgvConfig.Columns[e.ColumnIndex].Name; if (!columnName.Contains(StreamingDetectString) && !columnName.Contains(RequestDetectString)) { return; } StoreToPc(); var slotString = (string)dgvConfig.Rows[e.RowIndex].Cells[SlotString].Value; if (!int.TryParse(slotString, out var slot)) return; const string checkMark = "\u2714"; try { if (columnName.Contains(StreamingDetectString)) { Logger.Trace("COM: Detecting streaming port for slot " + slot + "..."); var result = interfaceToLaatzen.DetectStreamingPort(slot); if (result.Success) { var text = $"SUCCESS\nSlot: {result.Slot}\nStreaming port: {result.PortName}\n\n{checkMark}"; MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK); dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Green; Logger.Info("COM: Streaming detection SUCCESS for slot " + result.Slot + ", port " + result.PortName + "."); } else { var text = $"FAILED\nSlot: {result.Slot}\nStreaming port: {result.PortName}"; MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error); dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Red; Logger.Error("COM: Streaming detection FAILED for slot " + result.Slot + ", port " + result.PortName + "."); } } else { var result = interfaceToLaatzen.DetectRequestPort(slot); if (result.Success) { var text = $"SUCCESS\nSlot: {result.Slot}\nRequest port: {result.PortName}\n\n{checkMark}"; MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK); dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Green; Logger.Info("COM: Request detection SUCCESS for slot " + result.Slot + ", port " + result.PortName + "."); } else { var text = $"FAILED\nSlot: {result.Slot}\nRequest port: {result.PortName}"; MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error); dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Red; Logger.Error("COM: Request detection FAILED for slot " + result.Slot + ", port " + result.PortName + "."); } } } catch (Exception ex) { MessageBox.Show(ex.Message, @"ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); Logger.Error(ex); } } private void dgvConfig_DataError(Object sender, DataGridViewDataErrorEventArgs e) { Logger.Error("CONFIG: DataGridView data error."); } private void cbUseRegisterWatch_CheckedChanged(Object sender, EventArgs e) { _configuration.UseRegisterWatchService = cbUseRegisterWatch.Checked; _configuration.Update(); StoreToPc(); Logger.Trace("UseRegisterWatchService changed to " + cbUseRegisterWatch.Checked); } private void cbUseMinMaxCheck_CheckedChanged(Object sender, EventArgs e) { _configuration.UseMinMaxCheck = cbUseMinMaxCheck.Checked; _configuration.Update(); StoreToPc(); Logger.Trace("UseMinMaxCheck changed to " + cbUseMinMaxCheck.Checked); } private void textBox1_TextChanged(Object sender, EventArgs e) { _configuration.RegisterWatchServiceUrl = txtWachSeriveUrl.Text; _configuration.Update(); StoreToPc(); Logger.Trace("RegisterWatchServiceUrl changed."); } private void cbUpdateFiles_CheckedChanged(Object sender, EventArgs e) { _configuration.AutoUpdateFiles = cbUpdateFiles.Checked; _configuration.Update(); StoreToPc(); Logger.Trace("CONFIG: AutoUpdateFiles changed to " + cbUpdateFiles.Checked); } private void FrmSetup_Load(Object sender, EventArgs e) { LoadOfflineFile(); cbxProductionMode.CheckedChanged += cbxProductionMode_CheckedChanged; Logger.Trace("FORM: FrmSetup loaded."); } private void StoreOfflineFile() { try { var listToRemove = _listOfOfflinePasswords.Where(offlinePwd => string.IsNullOrEmpty(offlinePwd.PcbID)).ToList(); foreach (var itemToRemove in listToRemove) { _listOfOfflinePasswords.Remove(itemToRemove); } _listOfOfflinePasswords.Add(new OfflinePasswordItem("", "")); File.WriteAllText(_offlinePwdPathName, JsonConvert.SerializeObject(_listOfOfflinePasswords)); dgvofflinePw.CellValidated -= dgvofflinePw_CellValidated; dgvofflinePw.DataSource = null; dgvofflinePw.DataSource = _listOfOfflinePasswords; dgvofflinePw.CellValidated += dgvofflinePw_CellValidated; Logger.Trace("CONFIG: Offline password file stored."); } catch (Exception ex) { Logger.Error("CONFIG: Failed to store offline password file: " + ex.Message); } } private void LoadOfflineFile() { try { _listOfOfflinePasswords = JsonConvert.DeserializeObject>(File.ReadAllText(_offlinePwdPathName)); } catch (Exception ex) { _listOfOfflinePasswords = new List(); Logger.Error("CONFIG: Failed to load offline password file. New empty list created. " + ex.Message); } finally { if (!_listOfOfflinePasswords.Any()) { _listOfOfflinePasswords.Add(new OfflinePasswordItem("", "")); } dgvofflinePw.CellValidated -= dgvofflinePw_CellValidated; dgvofflinePw.DataSource = null; dgvofflinePw.DataSource = _listOfOfflinePasswords; dgvofflinePw.CellValidated += dgvofflinePw_CellValidated; Logger.Trace("CONFIG: Offline password file loaded."); } } private void dgvofflinePw_CellValidated(Object sender, DataGridViewCellEventArgs e) { StoreOfflineFile(); } private void cmdAddOffline_Click(Object sender, EventArgs e) { _listOfOfflinePasswords.Add(new OfflinePasswordItem("", "")); dgvofflinePw.DataSource = null; dgvofflinePw.DataSource = _listOfOfflinePasswords; Logger.Trace("TABLE: Offline password row added."); } private void cbxProductionMode_CheckedChanged(Object sender, EventArgs e) { if (cbxProductionMode.Checked) { MessageBox.Show(@"Production mode! Configuration.json has to be the latest! "); } else { MessageBox.Show("Developer mode! Configuration.json can be exchanged on individual requirements.\n" + "\nRISK:\n" + "- Register ranges cannot be checked\n" + "- Register may not be able to access"); } _configuration.ProductionMode = cbxProductionMode.Checked; _configuration.Update(); StoreToPc(); Logger.Trace("CHECKBOX: ProductionMode changed to " + cbxProductionMode.Checked); } private void tabPage4_Click(Object sender, EventArgs e) { Logger.Trace("TABPAGE4: Logging tab opened."); try { var path = NLogHelper.GetCurrentApplicationFolder(); var a = XElement.Load(path); lblLocalCurrentPath.Text = a.Elements() .First(s => s.Name.LocalName == "variable") .Attributes() .First(s => s.Value == "BasePath") .NextAttribute.Value; } catch (Exception ex) { lblLocalCurrentPath.Text = ex.Message; Logger.Error("TABPAGE4: Failed to read local NLog path: " + ex.Message); } try { var path = NLogHelper.GetApplicationDataPath(); var b = XElement.Load(path); lblGlobalCurrentPath.Text = b.Elements() .First(s => s.Name.LocalName == "variable") .Attributes() .First(s => s.Value == "BasePath") .NextAttribute.Value; } catch (Exception ex) { lblGlobalCurrentPath.Text = ex.Message; Logger.Error("TABPAGE4: Failed to read global NLog path: " + ex.Message); } } private void Add(String path, String newDest) { try { var a = XElement.Load(path); var firstIsVariable = a.Elements().First(); if (firstIsVariable.Name.LocalName != "variable") { var newElm = new XElement("variable", null); newElm.SetAttributeValue("name", "BasePath"); newElm.SetAttributeValue("value", newDest); a.AddFirst(newElm); } else if (a.Elements().First(b => b.Name.LocalName == "variable").Attributes() .All(s => s.Value != "BasePath")) { var newElm = new XElement("variable", null); newElm.SetAttributeValue("name", "BasePath"); newElm.SetAttributeValue("value", newDest); a.AddFirst(newElm); } else { a.Elements().First(b => b.Name.LocalName == "variable").Attributes() .First(s => s.Value == "BasePath").NextAttribute.Value = newDest; } a.Save(path); tabPage4_Click(this, null); Logger.Trace("Log path updated to: " + newDest); } catch (Exception ex) { Logger.Trace("Failed to update log path: " + ex.Message); } } private void btnLocalDefaultLocal_Click(Object sender, EventArgs e) { Add(NLogHelper.GetCurrentApplicationFolder(), "C:\\GenesisLog\\"); Logger.Trace("Local log path set to default local."); } private void btnLocalDefaultLan_Click(Object sender, EventArgs e) { Add(NLogHelper.GetCurrentApplicationFolder(), "\\\\sla12buma\\cordonelds$\\${machinename}"); Logger.Trace("Local log path set to default LAN."); } private void btnGlobalDefaultLocal_Click(Object sender, EventArgs e) { Add(NLogHelper.GetApplicationDataPath(), "C:\\GenesisLog\\"); Logger.Trace("Global log path set to default local."); } private void btnGlobalDefaultLan_Click(Object sender, EventArgs e) { Add(NLogHelper.GetApplicationDataPath(), "\\\\sla12buma\\cordonelds$\\${{machinename}}"); Logger.Trace("Global log path set to default LAN."); } private void btnGlobalSearch_Click(Object sender, EventArgs e) { var dia = new FolderBrowserDialog(); dia.ShowDialog(); Add(NLogHelper.GetApplicationDataPath(), dia.SelectedPath); Logger.Trace("Global log path selected by search dialog."); } private void btnLocalSearch_Click(Object sender, EventArgs e) { var dia = new FolderBrowserDialog(); dia.ShowDialog(); Add(NLogHelper.GetCurrentApplicationFolder(), dia.SelectedPath); Logger.Trace("Local log path selected by search dialog."); } private void btnAddRow_Click(Object sender, EventArgs e) { dgvConfig.Rows.Add(AddRowToGrid()); Logger.Trace("TABLE: New slot row added."); } public class OfflinePasswordItem { public OfflinePasswordItem() { } public OfflinePasswordItem(String pcbID, String password) { PcbID = pcbID; Password = password; } public String PcbID { get; set; } public String Password { get; set; } } } }