//-----------------------------------------------------------------------
//
// 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 Protocol
{
using System.Collections.Generic;
using global::SharedObjects.Misc;
using global::SharedObjects.Protocol;
///
/// Construct address depending on protocol.
///
public class AddressBuilder
{
///
/// Gets compiled list of destination addresses.
///
public IEnumerable destinationAddresses
{
get
{
return new List(this.destinationAddressList);
}
}
///
/// Gets compiled list of ECUs.
///
public IEnumerable ecus
{
get
{
return new List(this.ecuDataList);
}
}
///
/// Gets default alternative in address list.
///
public string defaultValue { get; private set; }
///
/// Compiled list of destination addresses.
///
private List destinationAddressList = new List();
///
/// Compiled list of ECU addresses.
///
private List ecuDataList = new List();
///
/// If the 29 bit addressing is expected.
///
private bool is29bit;
///
/// Wrapper for current protocol data.
///
private ProtocolItemWrapper currentProtocolItemWrapper;
///
/// Current vehicle.
///
private XmlClass.vehicle vehicle;
///
/// Source address for tester.
///
private uint sourceAddress;
///
/// Initializes a new instance of the class.
///
/// Wrapper for current protocol data.
/// Current vehicle.
/// Source address for tester.
public AddressBuilder(
ProtocolItemWrapper currentProtocolItemWrapper,
XmlClass.vehicle vehicle,
uint sourceAddress)
{
this.currentProtocolItemWrapper = currentProtocolItemWrapper;
this.vehicle = vehicle;
if (this.currentProtocolItemWrapper != null
&& this.currentProtocolItemWrapper.addressData != null)
{
this.is29bit = (this.currentProtocolItemWrapper.addressData.bits == 29);
}
else
{
this.is29bit = false;
}
this.sourceAddress = sourceAddress;
this.buildAddressList();
}
///
/// Load data into the destination address combobox.
///
/// Way too complicated... :(
///
///
private void buildAddressList()
{
this.destinationAddressList.Clear();
this.ecuDataList.Clear();
if (this.is29bit)
{
this.populate29bitDestAddress();
}
else
{
this.populateOtherDestAddresses();
}
if (this.destinationAddressList.Count > 0 && this.destinationAddressList[0] is string)
{
this.defaultValue = (string)this.destinationAddressList[0];
}
}
///
/// All addresses except 29-bit ISO15765.
///
private void populateOtherDestAddresses()
{
if (this.currentProtocolItemWrapper != null
&& this.currentProtocolItemWrapper.addressData != null)
{
if (!string.IsNullOrEmpty(this.currentProtocolItemWrapper.addressData.broadcastAddress))
{
this.destinationAddressList.Add(this.currentProtocolItemWrapper.addressData.broadcastAddress);
}
if (this.vehicle.ecus != null && this.vehicle.ecus.Count > 0)
{
if (!string.IsNullOrEmpty(this.currentProtocolItemWrapper.addressData.baseDestinationAddress))
{
this.destinationAddressList.Add(this.currentProtocolItemWrapper.addressData.baseDestinationAddress);
}
}
else
{
if (this.currentProtocolItemWrapper.addressData.bits == 11)
{
if (!string.IsNullOrEmpty(this.currentProtocolItemWrapper.addressData.baseDestinationAddress))
{
uint baseAddr = Utils.hexParse(this.currentProtocolItemWrapper.addressData.baseDestinationAddress);
for (uint i = 0; i < 7; i++)
{
uint newAddr = (baseAddr | i);
this.destinationAddressList.Add("0x" + newAddr.ToString("x2") + " Raw");
this.addEcu("0x" + newAddr.ToString("x2"));
}
}
}
else
{
if (!string.IsNullOrEmpty(this.currentProtocolItemWrapper.addressData.baseDestinationAddress))
{
foreach (uint addr in Protocols.genericAddressList)
{
this.destinationAddressList.Add("0x" + addr.ToString("x2") + " Generic");
this.addEcu("0x" + addr.ToString("x2"));
}
}
}
}
}
}
///
/// 29-bit ISO15765.
///
private void populate29bitDestAddress()
{
if (this.currentProtocolItemWrapper != null
&& this.currentProtocolItemWrapper.addressData != null
&& this.sourceAddress != 0)
{
this.default29bitDestAddress();
}
else
{
this.fallback29bitDestAddress();
}
}
///
/// When there is address data available and a source address detected we
/// can construct the default 29 bit addresses here.
///
private void default29bitDestAddress()
{
if (!string.IsNullOrEmpty(this.currentProtocolItemWrapper.addressData.broadcastAddress))
{
uint addr = Utils.hexParse(this.currentProtocolItemWrapper.addressData.broadcastAddress);
addr |= this.sourceAddress;
this.destinationAddressList.Add("0x" + addr.ToString("x8") + " Broadcast");
}
if (!string.IsNullOrEmpty(this.currentProtocolItemWrapper.addressData.baseDestinationAddress))
{
uint baseAddr = Utils.hexParse(this.currentProtocolItemWrapper.addressData.baseDestinationAddress);
baseAddr |= this.sourceAddress;
// If the vehicle has a list of ECUs declared we only need one address
// entry and are set with that.
if (this.vehicle.ecus != null && this.vehicle.ecus.Count > 0)
{
this.destinationAddressList.Add("0x" + baseAddr.ToString("x8") + " Template");
}
else
{
// If the selected vehicle is 29 bits and has addresses declared we can use the address list from it.
if (this.vehicle.addressbits == 29 && this.vehicle.txaddrlist.Count > 0)
{
foreach (XmlClass.vehicle.addrlist addr in this.vehicle.txaddrlist)
{
if (!addr.broadcast)
{
uint newAddr = baseAddr;
uint ecuAddr = Utils.hexParse(addr.address) & 0x0000ff00;
newAddr |= ecuAddr;
this.destinationAddressList.Add("0x" + newAddr.ToString("x8") + " Raw");
this.addEcu("0x" + ((ecuAddr >> 8) & 0xff).ToString("x2"));
}
}
}
else
{
// As a last resort fall back to a list of generic ECU addresses.
foreach (uint addr in Protocols.genericAddressList)
{
uint newAddr = baseAddr;
newAddr |= (addr << 8);
this.destinationAddressList.Add("0x" + newAddr.ToString("x8") + " Generic");
this.addEcu("0x" + addr.ToString("x2"));
}
}
}
}
}
///
/// Fallback handling for 29 bit addresses.
///
private void fallback29bitDestAddress()
{
if (this.vehicle.addressbits == 29)
{
foreach (XmlClass.vehicle.addrlist addr in this.vehicle.txaddrlist)
{
if (addr.broadcast)
{
this.destinationAddressList.Add(addr.address + " Broadcast.");
}
}
foreach (XmlClass.vehicle.addrlist addr in this.vehicle.txaddrlist)
{
if (!addr.broadcast)
{
this.destinationAddressList.Add(addr.address + " Raw.");
uint ecuAddr = Utils.hexParse(addr.address) & 0x0000ff00;
this.addEcu("0x" + ((ecuAddr >> 8) & 0xff).ToString("x2"));
}
}
}
else
{
if (this.currentProtocolItemWrapper != null
&& this.currentProtocolItemWrapper.addressData != null)
{
uint baseAddr = Utils.hexParse(this.currentProtocolItemWrapper.addressData.baseDestinationAddress);
baseAddr |= this.sourceAddress;
foreach (uint addr in Protocols.genericAddressList)
{
uint newAddr = baseAddr;
newAddr |= (addr << 8);
this.destinationAddressList.Add("0x" + newAddr.ToString("x8") + " Generic");
this.addEcu("0x" + addr.ToString("x2"));
}
}
}
}
///
/// Add ECU address.
///
/// ECU address string.
private void addEcu(string ecuAddress)
{
XmlClass.vehicle.ecuData ecuItem = new XmlClass.vehicle.ecuData();
ecuItem.id = ecuAddress;
ecuItem.name = string.Empty;
this.ecuDataList.Add(ecuItem);
}
}
}