//-----------------------------------------------------------------------
//
// Copyright © 2012 Nils Hammar. All rights reserved.
//
//-----------------------------------------------------------------------
/*
* Software to access vehicle information via the OBD-II connector.
*
* Copyright © 2012 Nils Hammar
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Alternative licensing is possible, see the licensing document.
*
* The above text may not be removed or modified.
*/
namespace UserInterface.GUI
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using global::SharedObjects;
using global::SharedObjects.Api;
using global::SharedObjects.DataMgmt;
using global::SharedObjects.Misc;
using global::SharedObjects.Protocol;
///
/// Configuration parameters control
///
public partial class ConfigParams : UserControl
{
///
/// Gets or sets a value indicating whether the readonly flag is set or not.
///
public bool ReadOnly
{
get
{
return this.configDgv.ReadOnly;
}
set
{
this.configDgv.ReadOnly = value;
}
}
///
/// Logging interface.
///
private ILogging iLogging;
///
/// Current device connection.
///
private IPassThruConnection passThruConnection;
///
/// Current protocol.
///
private Protocols protocol;
///
/// Style for a disabled cell.
///
private DataGridViewCellStyle disabledCellStyle;
///
/// Style for a normal enabled cell.
///
private DataGridViewCellStyle normalCellStyle;
///
/// Data source interface instance.
///
private IDataSource iDataSource;
///
/// Current preferences instance.
///
private IPreferences iPreferences;
///
/// Initializes a new instance of the class.
///
public ConfigParams()
{
this.iPreferences = null;
this.InitializeComponent();
}
///
/// Initialize the table.
///
/// Logging interface.
/// Preferences instance.
/// Data source interface instance.
/// Current device connection.
/// Current protocol.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "iPreferences", Justification = "Reviewed, intentional.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "passThruConnection", Justification = "Reviewed, intentional.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "iLogging", Justification = "Reviewed, intentional.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "protocol", Justification = "Reviewed, intentional.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "iDataSource", Justification = "Reviewed, intentional.")]
public void init(ILogging iLogging, IPreferences iPreferences, IDataSource iDataSource, IPassThruConnection passThruConnection, Protocols protocol)
{
this.iLogging = iLogging;
this.iPreferences = iPreferences;
this.iDataSource = iDataSource;
this.passThruConnection = passThruConnection;
this.protocol = protocol;
this.refreshConfigParams();
this.setToolTips();
this.normalCellStyle = this.configDgv.RowsDefaultCellStyle.Clone();
this.disabledCellStyle = this.configDgv.RowsDefaultCellStyle.Clone();
this.normalCellStyle.BackColor = Color.White;
this.disabledCellStyle.BackColor = Color.LightGray;
this.configDgv.RowsDefaultCellStyle = this.disabledCellStyle;
this.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
}
///
/// Refresh the active config parameters.
///
/// 'true' If it shall be possible to edit the parameter values.
public void refreshActiveConfigParams(bool editable)
{
DataGridViewRowCollection configRows = this.configDgv.Rows;
foreach (XmlClass.parameteritem item in this.iDataSource.parameters)
{
foreach (DataGridViewRow configRow in configRows)
{
DataGridViewCellCollection configRowCells = configRow.Cells;
if (configRowCells["configParam"].Value.Equals(item.name))
{
if (item.protocols == null || item.protocols.Length == 0)
{
this.setCellStyle(editable, configRow);
configRow.ReadOnly = !editable;
configRow.Visible = true;
configRowCells["currentValue"].Value = this.getParamValue(item);
}
else
{
configRow.Visible = false;
foreach (int protocolId in item.protocols)
{
if (this.protocol.id == protocolId)
{
this.setCellStyle(editable, configRow);
configRow.ReadOnly = !editable;
configRow.Visible = true;
configRowCells["currentValue"].Value = this.getParamValue(item);
break;
}
}
}
}
}
}
}
///
/// Apply config parameters.
///
public void applyConfigParameters()
{
DataGridViewRowCollection rows = this.configDgv.Rows;
for (int i = 0; i < this.configDgv.Rows.Count; i++)
{
DataGridViewRow row = rows[i];
if (row.Visible)
{
DataGridViewCellCollection rowCells = row.Cells;
string configParamValue = (string)rowCells["configParam"].Value;
foreach (XmlClass.parameteritem item in this.iDataSource.parameters)
{
if (item.name.Equals(configParamValue))
{
string val = (string)rowCells["configValue"].Value;
if (val != null && val.Length > 0)
{
int parsedval = parseValue(val);
this.iLogging.appendText("IoctlSetParameter(" + item.id + ", 0x" + parsedval.ToString("x2") + ").\r\n", LogLevel.LOG_DEBUG);
PassThruConstants.resultCode status = this.passThruConnection.IoctlSetParameter((uint)item.id, (uint)parsedval);
string errTxt = string.Empty;
bool cont = this.iLogging.errTestConnection(this.passThruConnection, status, out errTxt);
this.iLogging.appendText("IoctlSetParameter() status=" + status + ": " + errTxt + ", cont=" + cont + ".\r\n", LogLevel.LOG_DEBUG);
if (!cont)
{
MessageBox.Show(
"IoctlSetParameter(" + item.id + ", 0x" + parsedval.ToString("x2") + ")\r\n" + errTxt,
"Warning",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
throw new Exception("Can't connect.");
}
}
break;
}
}
}
}
}
///
/// Parse a string value to 'int', return -1 on failure.
///
/// Value to parse
/// Parsed value
private static int parseValue(string val)
{
int parsedval = -1; // Negative means failure later on.
try
{
parsedval = Convert.ToInt32(val);
}
catch
{
try
{
parsedval = (int)Utils.hexParse(val);
}
catch
{
}
}
return parsedval;
}
///
/// Set tool tips for items.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "CanApp.CustomToolTip", Justification = "Reviewed, intentional.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed, intentional.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Reviewed.")]
private void setToolTips()
{
this.toolTip1.SetToolTip(
this.configDgv,
"Additional configuration parameters to be used when connecting\r\n"
+ "Empty field means that the parameter will be ignored.\r\n"
+ "\r\n"
+ "Some useful parameters:\r\n"
+ "DATA_RATE: 5 to 1000000\r\n"
+ "LOOPBACK: 0(Off) or 1(On)\r\n"
+ "NODE_ADDRESS: 0x00 to 0xFF for protocol J1850PWM\r\n"
+ "NETWORK_LINE: 0(Bus Normal) 1(Bus Plus) 2(Bus Minus)\r\n"
+ "PARITY: 0(No Parity) 1(Odd Parity) 2(Even Parity)\r\n"
+ "DATA_BITS: 0(8 bits) 1(7 bits)\r\n"
+ "\r\n"
+ "For full description of values see SAE J2534");
}
///
/// Set the style of a cell.
///
/// 'true' if editable.
/// Current data grid view row.
private void setCellStyle(bool editable, DataGridViewRow configRow)
{
foreach (DataGridViewCell cell in configRow.Cells)
{
if (editable)
{
cell.Style = this.normalCellStyle;
}
else
{
cell.Style = this.disabledCellStyle;
}
}
}
///
/// Get current parameter value.
///
/// Parameter item.
/// Parameter value.
private string getParamValue(XmlClass.parameteritem item)
{
uint value = 0;
string valueStr = string.Empty;
if (item != null && this.passThruConnection != null)
{
if (this.passThruConnection.IoctlGetParameter(item.id, out value) == 0)
{
valueStr = value.ToString();
}
}
return valueStr;
}
///
/// Refresh config parameters.
///
private void refreshConfigParams()
{
DataGridViewRowCollection rows = this.configDgv.Rows;
List existing = new List();
int removed = 0;
int added = 0;
int updated = 0;
for (int i = (rows.Count - 1); i >= 0; i--)
{
DataGridViewRow vehicleRow = rows[i];
DataGridViewCellCollection rowCells = vehicleRow.Cells;
XmlClass.parameteritem item = (XmlClass.parameteritem)rowCells["configItem"].Value;
if (!this.iDataSource.parameters.Contains(item))
{
rows.RemoveAt(i);
removed++;
}
else
{
existing.Add(item);
rowCells["configParam"].Value = item.name;
rowCells["currentValue"].Value = this.getParamValue(item);
updated++;
}
}
foreach (XmlClass.parameteritem item in this.iDataSource.parameters)
{
if (!existing.Contains(item))
{
string valueStr = this.getParamValue(item);
int n0 = rows.Add(1);
DataGridViewRow vehicleRow = rows[n0];
DataGridViewCellCollection rowCells = vehicleRow.Cells;
rowCells["configItem"].Value = item;
rowCells["configParam"].Value = item.name; // currentValue
rowCells["currentValue"].Value = valueStr;
if (this.iPreferences != null)
{
switch (item.name)
{
case "ISO15765_BS":
rowCells["configValue"].Value = this.iPreferences.blockSize.ToString();
break;
case "ISO15765_STMIN":
rowCells["configValue"].Value = this.iPreferences.frameSpacing.ToString();
break;
default:
rowCells["configValue"].Value = string.Empty;
break;
}
}
else
{
rowCells["configValue"].Value = string.Empty;
}
added++;
}
}
}
///
/// Validate cell values.
///
/// Sending object.
/// Event data.
private void configDgv_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
DataGridView dataGridView = (DataGridView)sender;
if (dataGridView.Visible)
{
int ix = e.RowIndex;
int ic = e.ColumnIndex;
DataGridViewTextBoxCell cell = dataGridView[ic, ix] as DataGridViewTextBoxCell;
if (cell != null)
{
if (ic == 2)
{
string val = e.FormattedValue.ToString();
if (val.Length > 0)
{
int parsedval = parseValue(val);
if (parsedval >= 0)
{
DataGridViewRowCollection rows = dataGridView.Rows;
DataGridViewRow row = rows[ix];
DataGridViewCellCollection rowCells = row.Cells;
string configParamValue = (string)rowCells["configParam"].Value;
foreach (XmlClass.parameteritem item in this.iDataSource.parameters)
{
if (item.name.Equals(configParamValue))
{
if (parsedval < item.min)
{
MessageBox.Show(
"'" + val + "' is less than permitted minimum of " + item.min,
"Warning",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
e.Cancel = true;
}
else
{
if (parsedval > item.max)
{
MessageBox.Show(
"'" + val + "' is greater than permitted maximum of " + item.max,
"Warning",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
e.Cancel = true;
}
}
break;
}
}
}
else
{
MessageBox.Show(
"'" + val + "' is invalid - cell must be a decimal (NNNN) or hex (0xNNNN) value or be empty.",
"Warning",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
e.Cancel = true;
}
}
}
}
}
}
}
}