derived parameter support added, small bug fixes, touch ups

git-svn-id: http://svn.3splooges.com/romraider-arch/trunk@282 d2e2e1cd-ba16-0410-be16-b7c4453c7c2d
This commit is contained in:
kascade 2006-09-11 11:06:53 +00:00
parent 4729ec79d8
commit 16ec1ee54a
17 changed files with 734 additions and 474 deletions

View File

@ -1,32 +1,41 @@
<!ELEMENT address ( byte+ ) >
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT byte ( #PCDATA ) >
<!ELEMENT conversion ( metric ) >
<!ELEMENT address ( byte+ ) >
<!ELEMENT logger ( protocols ) >
<!ELEMENT ref EMPTY >
<!ATTLIST ref id IDREF #REQUIRED >
<!ELEMENT metric EMPTY >
<!ATTLIST metric expr CDATA #REQUIRED >
<!ATTLIST metric format ( 0 | 0.0 | 0.00 ) #REQUIRED >
<!ATTLIST metric units CDATA #REQUIRED >
<!ELEMENT depends ( ref+ ) >
<!ELEMENT parameter ( address, conversion ) >
<!ELEMENT conversion EMPTY >
<!ATTLIST conversion expr CDATA #REQUIRED >
<!ATTLIST conversion format ( 0 | 0.0 | 0.00 ) #REQUIRED >
<!ATTLIST conversion units CDATA #REQUIRED >
<!ELEMENT conversions ( conversion+ ) >
<!ELEMENT parameter ( ( address | depends ), conversions ) >
<!ATTLIST parameter desc CDATA #REQUIRED >
<!ATTLIST parameter id CDATA #REQUIRED >
<!ATTLIST parameter name CDATA #REQUIRED >
<!ATTLIST parameter id ID #REQUIRED >
<!ELEMENT parameters ( parameter+ ) >
<!ELEMENT protocol ( parameters*, switches* ) >
<!ATTLIST protocol id CDATA #REQUIRED >
<!ELEMENT protocols ( protocol+ ) >
<!ELEMENT switch EMPTY >
<!ATTLIST switch filelogcontroller ( yes | no ) #IMPLIED >
<!ATTLIST switch bit ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 ) #REQUIRED >
<!ATTLIST switch byte CDATA #REQUIRED >
<!ATTLIST switch desc CDATA #REQUIRED >
<!ATTLIST switch id CDATA #REQUIRED >
<!ATTLIST switch name CDATA #REQUIRED >
<!ATTLIST switch id ID #REQUIRED >
<!ELEMENT switches ( switch+ ) >
<!ELEMENT protocol ( parameters*, switches* ) >
<!ATTLIST protocol id ID #REQUIRED >
<!ELEMENT protocols ( protocol+ ) >
<!ELEMENT logger ( protocols ) >

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ import static javax.swing.JSplitPane.HORIZONTAL_SPLIT;
import static javax.swing.JSplitPane.VERTICAL_SPLIT;
import javax.swing.border.BevelBorder;
import static javax.swing.border.BevelBorder.LOWERED;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import static java.awt.BorderLayout.CENTER;
@ -41,11 +42,13 @@ import java.beans.PropertyChangeListener;
import java.util.List;
/*
TODO: finish multi-conversion support for ecu params (already defined in xml)
TODO: add better debug logging, preferably to a file and switchable (on/off)
TODO: finish dashboard tab
TODO: add configuration screen (log file destination, etc)
TODO: add user definable addresses
TODO: Clean up this class!
So much to do, so little time....
*/
public final class EcuLogger extends JFrame implements WindowListener, PropertyChangeListener, MessageListener {
@ -156,12 +159,21 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
}
private JComponent buildParamListPane(TableModel paramListTableModel, TableModel switchListTableModel) {
JScrollPane paramList = new JScrollPane(new JTable(paramListTableModel), VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
JScrollPane switchList = new JScrollPane(new JTable(switchListTableModel), VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
JSplitPane splitPane1 = new JSplitPane(VERTICAL_SPLIT, paramList, switchList);
splitPane1.setDividerSize(2);
splitPane1.setDividerLocation(300);
return splitPane1;
JScrollPane paramList = new JScrollPane(buildParamListTable(paramListTableModel), VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
JScrollPane switchList = new JScrollPane(buildParamListTable(switchListTableModel), VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
JSplitPane splitPane = new JSplitPane(VERTICAL_SPLIT, paramList, switchList);
splitPane.setDividerSize(2);
splitPane.setDividerLocation(300);
return splitPane;
}
private JTable buildParamListTable(TableModel tableModel) {
JTable paramListTable = new JTable(tableModel);
TableColumn checkBoxColumn = paramListTable.getColumnModel().getColumn(0);
checkBoxColumn.setMinWidth(20);
checkBoxColumn.setMaxWidth(55);
checkBoxColumn.setPreferredWidth(55);
return paramListTable;
}
private JComponent buildStatusBar() {
@ -172,7 +184,6 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
return statusBar;
}
private JSplitPane buildSplitPane(JComponent leftComponent, JComponent rightComponent) {
JSplitPane splitPane = new JSplitPane(HORIZONTAL_SPLIT, leftComponent, rightComponent);
splitPane.setDividerSize(2);

View File

@ -62,7 +62,9 @@ public final class LoggerControllerImpl implements LoggerController {
public synchronized void start() {
if (!started) {
new Thread(queryManager).start();
Thread queryManagerThread = new Thread(queryManager);
queryManagerThread.setDaemon(true);
queryManagerThread.start();
startListeners();
started = true;
}

View File

@ -2,6 +2,8 @@ package enginuity.logger.definition;
public interface EcuData {
String getId();
String getName();
String getDescription();

View File

@ -0,0 +1,7 @@
package enginuity.logger.definition;
public interface EcuDerivedParameterConvertor extends EcuDataConvertor {
void setEcuDatas(EcuData[] ecuDatas);
}

View File

@ -0,0 +1,53 @@
package enginuity.logger.definition;
import static enginuity.util.JEPUtil.evaluate;
import static enginuity.util.ParamChecker.checkNotNullOrEmpty;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
public final class EcuDerivedParameterConvertorImpl implements EcuDerivedParameterConvertor {
private EcuData[] ecuDatas;
private final String units;
private final String expression;
private final DecimalFormat format;
public EcuDerivedParameterConvertorImpl(String units, String expression, String format) {
checkNotNullOrEmpty(units, "units");
checkNotNullOrEmpty(expression, "expression");
checkNotNullOrEmpty(format, "format");
this.units = units;
this.expression = expression;
this.format = new DecimalFormat(format);
}
public double convert(byte[] bytes) {
Map<String, Double> valueMap = new HashMap<String, Double>();
int index = 0;
for (EcuData ecuData : ecuDatas) {
int length = ecuData.getAddresses().length;
byte[] tmp = new byte[length];
System.arraycopy(bytes, index, tmp, 0, length);
valueMap.put(ecuData.getId(), ecuData.getConvertor().convert(tmp));
index += length;
}
System.out.println("valueMap = " + valueMap);
System.out.println("expression = " + expression);
double result = evaluate(expression, valueMap);
return Double.isNaN(result) || Double.isInfinite(result) ? 0.0 : result;
}
public String getUnits() {
return units;
}
public String format(double value) {
return format.format(value);
}
public void setEcuDatas(EcuData[] ecuDatas) {
checkNotNullOrEmpty(ecuDatas, "ecuDatas");
this.ecuDatas = ecuDatas;
}
}

View File

@ -0,0 +1,63 @@
package enginuity.logger.definition;
import static enginuity.logger.definition.EcuDataType.PARAMETER;
import static enginuity.util.ParamChecker.checkNotNull;
import static enginuity.util.ParamChecker.checkNotNullOrEmpty;
public final class EcuDerivedParameterImpl implements EcuParameter {
private final String id;
private final String name;
private final String description;
private final EcuDerivedParameterConvertor convertor;
private final String[] addresses;
public EcuDerivedParameterImpl(String id, String name, String description, EcuData[] ecuDatas, EcuDerivedParameterConvertor convertor) {
checkNotNullOrEmpty(name, "id");
checkNotNullOrEmpty(name, "name");
checkNotNull(description, "description");
checkNotNullOrEmpty(ecuDatas, "ecuDatas");
checkNotNull(convertor, "convertor");
this.id = id;
this.name = name;
this.description = description;
this.convertor = convertor;
this.convertor.setEcuDatas(ecuDatas);
addresses = setAddresses(ecuDatas);
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String[] getAddresses() {
return addresses;
}
public EcuDataConvertor getConvertor() {
return convertor;
}
public EcuDataType getDataType() {
return PARAMETER;
}
private String[] setAddresses(EcuData[] ecuDatas) {
String[] addresses = new String[0];
for (EcuData ecuData : ecuDatas) {
String[] newAddresses = ecuData.getAddresses();
String[] tmp = new String[addresses.length + newAddresses.length];
System.arraycopy(addresses, 0, tmp, 0, addresses.length);
System.arraycopy(newAddresses, 0, tmp, addresses.length, newAddresses.length);
addresses = tmp;
}
return addresses;
}
}

View File

@ -22,7 +22,8 @@ public final class EcuParameterConvertorImpl implements EcuDataConvertor {
public double convert(byte[] bytes) {
double value = (double) asInt(bytes);
return evaluate(expression, value);
double result = evaluate(expression, value);
return Double.isNaN(result) || Double.isInfinite(result) ? 0.0 : result;
}
public String getUnits() {

View File

@ -5,22 +5,29 @@ import static enginuity.util.ParamChecker.checkNotNull;
import static enginuity.util.ParamChecker.checkNotNullOrEmpty;
public final class EcuParameterImpl implements EcuParameter {
private String name;
private String description;
private String[] addresses;
private EcuDataConvertor convertor;
private final String id;
private final String name;
private final String description;
private final String[] addresses;
private final EcuDataConvertor convertor;
public EcuParameterImpl(String name, String description, String[] address, EcuDataConvertor convertor) {
public EcuParameterImpl(String id, String name, String description, String[] address, EcuDataConvertor convertor) {
checkNotNullOrEmpty(name, "id");
checkNotNullOrEmpty(name, "name");
checkNotNull(description, "description");
checkNotNullOrEmpty(address, "addresses");
checkNotNull(convertor, "convertor");
this.id = id;
this.name = name;
this.description = description;
this.addresses = address;
this.convertor = convertor;
}
public String getId() {
return id;
}
public String getName() {
return name;
}

View File

@ -13,11 +13,12 @@ public final class EcuSwitchConvertorImpl implements EcuDataConvertor {
}
public String getUnits() {
return "";
return "On/Off";
}
public String format(double value) {
return value > 0 ? "On" : "Off";
//return value > 0 ? "On" : "Off";
return value > 0 ? "1" : "0";
}
private void checkBit(int bit) {

View File

@ -5,17 +5,20 @@ import static enginuity.util.ParamChecker.checkNotNull;
import static enginuity.util.ParamChecker.checkNotNullOrEmpty;
public final class EcuSwitchImpl implements EcuSwitch {
private String name;
private String description;
private String[] addresses;
private EcuDataConvertor convertor;
private boolean fileLogController;
private final String id;
private final String name;
private final String description;
private final String[] addresses;
private final EcuDataConvertor convertor;
private final boolean fileLogController;
public EcuSwitchImpl(String name, String description, String[] address, EcuDataConvertor convertor, boolean fileLogController) {
public EcuSwitchImpl(String id, String name, String description, String[] address, EcuDataConvertor convertor, boolean fileLogController) {
checkNotNullOrEmpty(id, "id");
checkNotNullOrEmpty(name, "name");
checkNotNull(description, "description");
checkNotNullOrEmpty(address, "addresses");
checkNotNull(convertor, "convertor");
this.id = id;
this.name = name;
this.description = description;
this.addresses = address;
@ -23,6 +26,10 @@ public final class EcuSwitchImpl implements EcuSwitch {
this.fileLogController = fileLogController;
}
public String getId() {
return id;
}
public String getName() {
return name;
}

View File

@ -5,18 +5,27 @@ import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
//TODO: Add metric and imperial units and conversions to logger.xml and parse them out. This will need a generic EcuParameterConvertor class.
//TODO: Add support for parsing of multiple convertors (already in xml)
public final class LoggerDefinitionHandler extends DefaultHandler {
private static final String YES = "yes";
private static final String TAG_PROTOCOL = "protocol";
private static final String TAG_PARAMETER = "parameter";
private static final String TAG_METRIC = "metric";
private static final String TAG_ADDRESS = "address";
private static final String TAG_DEPENDS = "depends";
private static final String TAG_CONVERSION = "conversion";
private static final String TAG_BYTE = "byte";
private static final String TAG_REF = "ref";
private static final String TAG_SWITCH = "switch";
private static final String ATTR_ID = "id";
private static final String ATTR_NAME = "name";
private static final String ATTR_DESC = "desc";
private static final String ATTR_UNITS = "units";
private static final String ATTR_EXPRESSION = "expr";
@ -26,12 +35,17 @@ public final class LoggerDefinitionHandler extends DefaultHandler {
private static final String ATTR_FILELOGCONTROLLER = "filelogcontroller";
private List<EcuParameter> params;
private List<EcuSwitch> switches;
private Map<String, EcuData> ecuDataMap;
private String id;
private String name;
private String desc;
private List<String> addressList;
private Set<String> addressList;
private Set<String> dependsList;
private boolean derived;
private int bit;
private boolean fileLogController;
private EcuDataConvertor convertor;
private EcuDerivedParameterConvertor derivedConvertor;
private StringBuilder charBuffer;
private String protocol;
private boolean parseProtocol;
@ -44,6 +58,7 @@ public final class LoggerDefinitionHandler extends DefaultHandler {
public void startDocument() {
params = new ArrayList<EcuParameter>();
switches = new ArrayList<EcuSwitch>();
ecuDataMap = new HashMap<String, EcuData>();
}
public void startElement(String uri, String localName, String qName, Attributes attributes) {
@ -51,16 +66,30 @@ public final class LoggerDefinitionHandler extends DefaultHandler {
parseProtocol = protocol.equalsIgnoreCase(attributes.getValue(ATTR_ID));
} else if (parseProtocol) {
if (TAG_PARAMETER.equals(qName)) {
name = attributes.getValue(ATTR_ID);
id = attributes.getValue(ATTR_ID);
name = attributes.getValue(ATTR_NAME);
desc = attributes.getValue(ATTR_DESC);
addressList = new ArrayList<String>();
} else if (TAG_METRIC.equals(qName)) {
convertor = new EcuParameterConvertorImpl(attributes.getValue(ATTR_UNITS), attributes.getValue(ATTR_EXPRESSION),
attributes.getValue(ATTR_FORMAT));
} else if (TAG_ADDRESS.equals(qName)) {
addressList = new LinkedHashSet<String>();
derived = false;
} else if (TAG_DEPENDS.equals(qName)) {
dependsList = new LinkedHashSet<String>();
derived = true;
} else if (TAG_REF.equals(qName)) {
dependsList.add(attributes.getValue(ATTR_ID));
} else if (TAG_CONVERSION.equals(qName)) {
if (derived) {
derivedConvertor = new EcuDerivedParameterConvertorImpl(attributes.getValue(ATTR_UNITS), attributes.getValue(ATTR_EXPRESSION),
attributes.getValue(ATTR_FORMAT));
} else {
convertor = new EcuParameterConvertorImpl(attributes.getValue(ATTR_UNITS), attributes.getValue(ATTR_EXPRESSION),
attributes.getValue(ATTR_FORMAT));
}
} else if (TAG_SWITCH.equals(qName)) {
name = attributes.getValue(ATTR_ID);
id = attributes.getValue(ATTR_ID);
name = attributes.getValue(ATTR_NAME);
desc = attributes.getValue(ATTR_DESC);
addressList = new ArrayList<String>();
addressList = new HashSet<String>();
addressList.add(attributes.getValue(ATTR_BYTE));
bit = Integer.valueOf(attributes.getValue(ATTR_BIT));
fileLogController = YES.equals(attributes.getValue(ATTR_FILELOGCONTROLLER));
@ -82,15 +111,26 @@ public final class LoggerDefinitionHandler extends DefaultHandler {
if (TAG_BYTE.equals(qName)) {
addressList.add(charBuffer.toString());
} else if (TAG_PARAMETER.equals(qName)) {
String[] addresses = new String[addressList.size()];
addressList.toArray(addresses);
EcuParameter param = new EcuParameterImpl(name, desc, addresses, convertor);
EcuParameter param;
if (derived) {
Set<EcuData> dependencies = new HashSet<EcuData>();
for (String refid : dependsList) {
dependencies.add(ecuDataMap.get(refid));
}
param = new EcuDerivedParameterImpl(id, name, desc, dependencies.toArray(new EcuData[dependencies.size()]), derivedConvertor);
} else {
String[] addresses = new String[addressList.size()];
addressList.toArray(addresses);
param = new EcuParameterImpl(id, name, desc, addresses, convertor);
}
params.add(param);
ecuDataMap.put(param.getId(), param);
} else if (TAG_SWITCH.equals(qName)) {
String[] addresses = new String[addressList.size()];
addressList.toArray(addresses);
EcuSwitch ecuSwitch = new EcuSwitchImpl(name, desc, addresses, new EcuSwitchConvertorImpl(bit), fileLogController);
EcuSwitch ecuSwitch = new EcuSwitchImpl(id, name, desc, addresses, new EcuSwitchConvertorImpl(bit), fileLogController);
switches.add(ecuSwitch);
ecuDataMap.put(ecuSwitch.getId(), ecuSwitch);
}
}
}

View File

@ -1,6 +1,7 @@
package enginuity.logger.ui;
import enginuity.logger.definition.EcuData;
import static enginuity.util.ParamChecker.isNullOrEmpty;
import javax.swing.table.AbstractTableModel;
import static java.util.Collections.synchronizedList;
@ -43,7 +44,9 @@ public final class ParameterListTableModel extends AbstractTableModel {
case 0:
return paramRow.getSelected();
case 1:
return paramRow.getEcuData().getName();
EcuData ecuData = paramRow.getEcuData();
String units = ecuData.getConvertor().getUnits();
return ecuData.getName() + (isNullOrEmpty(units) ? "" : " (" + units + ")");
default:
return "Error!";
}

View File

@ -44,7 +44,7 @@ public final class GraphUpdateHandler implements DataUpdateHandler {
public void handleDataUpdate(EcuData ecuData, byte[] value, long timestamp) {
// update chart
XYSeries series = seriesMap.get(ecuData);
series.add(timestamp / 1000.0, ecuData.getConvertor().convert(value));
series.add(timestamp, ecuData.getConvertor().convert(value));
}
public void deregisterData(EcuData ecuData) {

View File

@ -2,6 +2,8 @@ package enginuity.util;
import org.nfunk.jep.JEP;
import java.util.Map;
public final class JEPUtil {
private JEPUtil() {
@ -14,4 +16,14 @@ public final class JEPUtil {
parser.parseExpression(expression);
return parser.getValue();
}
public static double evaluate(String expression, Map<String, Double> valueMap) {
JEP parser = new JEP();
parser.initSymTab(); // clear the contents of the symbol table
for (String id : valueMap.keySet()) {
parser.addVariable(id, valueMap.get(id));
}
parser.parseExpression(expression);
return parser.getValue();
}
}

View File

@ -20,7 +20,7 @@ public final class ParamChecker {
}
public static void checkNotNullOrEmpty(String param, String paramName) {
if (param == null || param.length() == 0) {
if (isNullOrEmpty(param)) {
throw new IllegalArgumentException("Parameter " + paramName + " must not be null or empty");
}
}
@ -48,4 +48,8 @@ public final class ParamChecker {
throw new IllegalArgumentException("Parameter " + paramName + " must not be null or empty");
}
}
public static boolean isNullOrEmpty(String param) {
return param == null || param.length() == 0;
}
}