#!/usr/bin/python3
# -*- coding: utf-8 -*-
import codecs
import copy
import math
import string
import ecu
import options
import version
hex_decoder = codecs.getdecoder("hex_codec")
import PyQt5.QtGui as gui
import PyQt5.QtCore as core
import PyQt5.QtWidgets as widgets
_ = options.translator('ddt4all')
def decode_hex(string):
return hex_decoder(string)[0]
class Bit_container(widgets.QFrame):
def __init__(self, data, num, parent=None):
super(Bit_container, self).__init__(parent)
self.data = data
self.setFrameStyle(widgets.QFrame.Sunken)
self.setFrameShape(widgets.QFrame.Box)
self.setFixedWidth(140)
self.layout = widgets.QVBoxLayout()
cblayout = widgets.QHBoxLayout()
cblayout.setContentsMargins(0, 0, 0, 0)
cblayout.setSpacing(0)
data = int("0x" + data, 16)
databin = bin(data)[2:].zfill(8)
self.checkboxes = []
for i in range(8):
cb = widgets.QCheckBox()
cb.setEnabled(False)
if databin[i] == "1":
cb.setChecked(True)
self.checkboxes.append(cb)
cblayout.addWidget(cb)
cb.setStyleSheet("color: green")
label = widgets.QLabel(str(num + 1).zfill(2))
label.setAlignment(core.Qt.AlignHCenter | core.Qt.AlignVCenter)
self.labelvaluehex = widgets.QLabel("$00")
self.labelvaluehex.setAlignment(core.Qt.AlignHCenter | core.Qt.AlignVCenter)
self.layout.addWidget(label)
self.layout.addWidget(self.labelvaluehex)
self.layout.addLayout(cblayout)
self.setLayout(self.layout)
def set_value_hex(self, val):
char = decode_hex(val)
repr = ""
if ord(char) < 127 and str(char) in string.printable:
repr = " [" + char + "]"
self.labelvaluehex.setText("$" + val.zfill(2) + repr + "")
def set_byte_value(self, byte):
if 'L' in byte:
byte = byte.replace('L', '')
binary = bin(int("0x" + byte, 16))[2:].zfill(8)
for i in range(8):
if binary[i] == "1":
self.checkboxes[i].setChecked(True)
else:
self.checkboxes[i].setChecked(False)
self.set_value_hex(byte)
def set_byte(self, byte):
if 'L' in byte:
byte = byte.replace('L', '')
binary = bin(int("0x" + byte, 16))[2:].zfill(8)
for i in range(8):
if binary[i] == "1":
self.checkboxes[i].setStyleSheet("border: 1px solid #00FF00;")
else:
self.checkboxes[i].setStyleSheet("border: 1px solid #FFFFFF;")
class Bit_viewer(widgets.QScrollArea):
def __init__(self, parent=None):
super(Bit_viewer, self).__init__(parent)
self.bc = []
self.mainwidget = None
def init(self, num):
if self.mainwidget:
self.mainwidget.setParent(None)
self.mainwidget.deleteLater()
self.mainwidget = widgets.QWidget()
self.layout = widgets.QHBoxLayout()
self.layout.setSpacing(2)
self.bc = []
for i in range(num):
bc = Bit_container("00", i)
self.bc.append(bc)
self.layout.addWidget(bc)
self.mainwidget.setLayout(self.layout)
self.setWidget(self.mainwidget)
def set_bytes_value(self, byte_list):
num = len(byte_list)
for i in range(num):
if i >= len(self.bc):
break
self.bc[i].set_byte_value(byte_list[i])
for i in range(num, len(self.bc)):
self.bc[i].set_byte_value("00")
def set_bytes(self, byte_list):
num = len(byte_list)
for i in range(num):
if i >= len(self.bc):
break
self.bc[i].set_byte(byte_list[i])
for i in range(num, len(self.bc)):
self.bc[i].set_byte("00")
class checkBox(widgets.QCheckBox):
def __init__(self, data, parent=None):
super(checkBox, self).__init__(parent)
self.data = data
if data.manualsend:
self.setChecked(True)
else:
self.setChecked(False)
self.stateChanged.connect(self.change)
def change(self, state):
if state:
self.data.manualsend = True
else:
self.data.manualsend = False
class dataTable(widgets.QTableWidget):
gotoitem = core.pyqtSignal(object)
removeitem = core.pyqtSignal(object)
def __init__(self, parent=None):
super(dataTable, self).__init__(parent)
self.issend = None
self.requestname = None
def goto_item(self, item):
self.gotoitem.emit(item)
def remove_item(self, item):
self.removeitem.emit(item)
def add_to_screen(self, name, item):
if not options.main_window.paramview:
return
itemtext = item
options.main_window.paramview.addParameter(self.requestname, self.issend, name, itemtext)
def init(self, issend, requestname):
self.issend = issend
self.requestname = requestname
def contextMenuEvent(self, event):
pos = event.pos()
index = self.indexAt(pos)
menu = widgets.QMenu()
if index.column() == 0:
item_name = self.itemAt(pos).text()
if not item_name:
return
action_goto = widgets.QAction(_("Goto data"), menu)
action_remove = widgets.QAction(_("Remove"), menu)
action_goto.triggered.connect(lambda state, it=item_name: self.goto_item(it))
action_remove.triggered.connect(lambda state, it=item_name: self.remove_item(it))
screenMenu = widgets.QMenu(_("Add to screen"))
for sn in options.main_window.screennames:
sa = widgets.QAction(sn, screenMenu)
sa.triggered.connect(lambda state, name=sn, it=item_name: self.add_to_screen(name, it))
screenMenu.addAction(sa)
menu.addActions([action_goto, action_remove])
menu.addMenu(screenMenu)
menu.exec_(event.globalPos())
event.accept()
class requestTable(widgets.QTableWidget):
def __init__(self, parent=None):
super(requestTable, self).__init__(parent)
self.ecureq = None
self.sendbyteeditor = None
self.rcvbyteeditor = None
self.reqs = []
self.setFixedWidth(350)
self.setSelectionBehavior(widgets.QAbstractItemView.SelectRows)
self.setSelectionMode(widgets.QAbstractItemView.SingleSelection)
self.verticalHeader().hide()
# self.setShowGrid(False)
self.currentreq = None
self.sdsupdate = True
def cellModified(self, r, c):
if not self.ecureq:
return
if c == 0:
newname = self.item(r, c).text()
# Avoid name clashes
while newname in self.ecureq:
newname += u"_"
oldname = self.ecureq[self.currentreq].name
self.ecureq[self.currentreq].name = newname
self.ecureq[newname] = self.ecureq.pop(self.currentreq)
self.init(self.ecureq)
options.main_window.paramview.requestNameChanged(oldname, newname)
self.select(newname)
def update_sds(self, req):
self.sdsupdate = False
self.parent().init_sds(req)
self.sdsupdate = True
def set_sds(self, view):
if not self.sdsupdate:
return
if not self.ecureq or self.currentreq is None:
return
self.ecureq[self.currentreq].sds['nosds'] = view.checknosds.isChecked()
self.ecureq[self.currentreq].sds['plant'] = view.checkplant.isChecked()
self.ecureq[self.currentreq].sds['aftersales'] = view.checkaftersales.isChecked()
self.ecureq[self.currentreq].sds['engineering'] = view.checkengineering.isChecked()
self.ecureq[self.currentreq].sds['supplier'] = view.checksupplier.isChecked()
def select(self, name):
items = self.findItems(name, core.Qt.MatchExactly)
if len(items):
self.selectRow(items[0].row())
def setSendByteEditor(self, sbe):
self.sendbyteeditor = sbe
self.itemSelectionChanged.connect(self.onCellChanged)
def setReceiveByteEditor(self, rbe):
self.rcvbyteeditor = rbe
self.itemSelectionChanged.connect(self.onCellChanged)
def onCellChanged(self):
if len(self.selectedItems()) == 0:
return
currentItem = self.selectedItems()[0]
if not currentItem:
return
currenttext = currentItem.text()
self.currentreq = currenttext
if not currenttext:
return
self.sendbyteeditor.set_request(self.ecureq[currenttext])
self.rcvbyteeditor.set_request(self.ecureq[currenttext])
self.update_sds(self.ecureq[currenttext])
def init(self, ecureq):
try:
self.cellChanged.disconnect()
except:
pass
self.clear()
self.ecureq = ecureq
requestsk = self.ecureq.keys()
numrows = len(requestsk)
self.setRowCount(numrows)
self.setColumnCount(3)
self.setHorizontalHeaderLabels(_("Request name;Bytes;Manual").split(";"))
count = 0
for req in requestsk:
request_inst = self.ecureq[req]
manual = checkBox(request_inst)
self.setItem(count, 0, widgets.QTableWidgetItem(req))
sbtext = request_inst.sentbytes
if len(sbtext) > 10:
sbtext = sbtext[0:10] + "..."
self.setItem(count, 1, widgets.QTableWidgetItem(sbtext))
self.setCellWidget(count, 2, manual)
count += 1
self.sortItems(0, core.Qt.AscendingOrder)
self.resizeColumnsToContents()
self.resizeRowsToContents()
self.cellChanged.connect(self.cellModified)
class paramEditor(widgets.QFrame):
"""Manages send/receive requests"""
def __init__(self, issend=True, parent=None):
super(paramEditor, self).__init__(parent)
self.send = issend
self.currentdataitem = None
self.setFrameStyle(widgets.QFrame.Sunken)
self.setFrameShape(widgets.QFrame.Box)
self.layoutv = widgets.QVBoxLayout()
add_layout = widgets.QHBoxLayout()
self.data_list = widgets.QComboBox()
self.button_add = widgets.QPushButton(_("Add"))
self.button_add.setFixedWidth(50)
add_layout.addWidget(self.data_list)
add_layout.addWidget(self.button_add)
if issend:
self.labelreq = widgets.QLabel(_("Send request bytes (HEX)"))
else:
self.labelreq = widgets.QLabel(_("Receive bytes (HEX)"))
self.inputreq = widgets.QLineEdit()
self.inputreq.textChanged.connect(self.request_changed)
self.button_add.clicked.connect(self.add_data)
self.layoutv.addLayout(add_layout)
self.layoutv.addWidget(self.labelreq)
self.layoutv.addWidget(self.inputreq)
if not issend:
rcv_lay = widgets.QHBoxLayout()
self.label_data_len = widgets.QLabel(_("Data length"))
self.spin_data_len = widgets.QSpinBox()
self.label_shift_bytes = widgets.QLabel(_("Shift byte count"))
self.spin_shift_byte = widgets.QSpinBox()
rcv_lay.addWidget(self.label_data_len)
rcv_lay.addWidget(self.spin_data_len)
rcv_lay.addWidget(self.label_shift_bytes)
rcv_lay.addWidget(self.spin_shift_byte)
self.layoutv.addLayout(rcv_lay)
self.spin_shift_byte.valueChanged.connect(self.shift_bytes_change)
self.spin_data_len.valueChanged.connect(self.data_len_change)
self.setLayout(self.layoutv)
self.table = dataTable()
self.table.gotoitem.connect(self.gotoitem)
self.table.removeitem.connect(self.removeitem)
self.table.setRowCount(50)
self.table.setColumnCount(5)
self.table.verticalHeader().hide()
self.table.setSelectionBehavior(widgets.QAbstractItemView.SelectRows)
self.table.setSelectionMode(widgets.QAbstractItemView.SingleSelection)
# self.table.setShowGrid(False)
self.layoutv.addWidget(self.table)
self.ecufile = None
self.current_request = None
self.table.itemSelectionChanged.connect(self.cell_clicked)
self.bitviewer = Bit_viewer()
self.bitviewer.setFixedHeight(110)
self.layoutv.addWidget(self.bitviewer)
def refresh_combo(self):
self.data_list.clear()
for k in sorted(self.ecufile.data):
self.data_list.addItem(k)
def add_data(self):
current_data_name = self.data_list.currentText()
data = {}
data['firstbyte'] = 2
data['bitoffset'] = 0
data['ref'] = False
data['endian'] = ''
if self.send:
self.current_request.sendbyte_dataitems[current_data_name] = ecu.Data_item(data, '', current_data_name)
else:
self.current_request.dataitems[current_data_name] = ecu.Data_item(data, '', current_data_name)
self.init(self.current_request)
def removeitem(self, name):
if self.send:
self.current_request.sendbyte_dataitems.pop(name)
else:
self.current_request.dataitems.pop(name)
self.init(self.current_request)
def gotoitem(self, name):
options.main_window.showDataTab(name)
def cell_clicked(self):
if len(self.table.selectedItems()) == 0:
return
r = self.table.selectedItems()[-1].row()
item = self.table.item(r, 0)
if not item: return
dataname = item.text()
self.currentdataitem = dataname
self.update_bitview(dataname)
self.update_bitview_value(dataname)
def update_bitview(self, dataname):
bytes = self.current_request.minbytes
if self.send:
dataitem = self.current_request.sendbyte_dataitems[dataname]
else:
dataitem = self.current_request.dataitems[dataname]
ecudata = self.ecufile.data[dataname]
minbytes = dataitem.firstbyte + ecudata.bytescount
if bytes < minbytes:
bytes = minbytes
bitscount = ecudata.bitscount
valuetosend = hex(int("0b" + str("1" * bitscount), 2))[2:]
valuetosend = valuetosend.replace("L", "")
bytesarray = ["00" for a in range(bytes)]
bytesarray = ecudata.setValue(valuetosend, bytesarray, dataitem, self.current_request.ecu_file.endianness, True)
self.bitviewer.set_bytes(bytesarray)
def update_bitview_value(self, dataname):
bytestosend = str(self.inputreq.text())
byteslisttosend = [bytestosend[a * 2:a * 2 + 2] for a in range(len(bytestosend) // 2)]
self.bitviewer.set_bytes_value(byteslisttosend)
def set_ecufile(self, ef):
self.current_request = None
self.ecufile = ef
self.table.clear()
self.inputreq.clear()
def set_request(self, req):
self.current_request = req
self.init(req)
def refresh_data(self):
if self.current_request:
self.init(self.current_request)
def init(self, req):
self.table.clear()
self.data_list.clear()
self.currentdataitem = None
if self.send:
self.inputreq.setText(req.sentbytes)
else:
self.inputreq.setText(req.replybytes)
if self.send:
data = req.sendbyte_dataitems
else:
data = req.dataitems
datak = data.keys()
for k in sorted(self.ecufile.data):
self.data_list.addItem(k)
if not self.send:
self.spin_shift_byte.setValue(req.shiftbytescount)
self.spin_data_len.setValue(req.minbytes)
headerstrings = _("Data name;Start byte;Bit offset;Bit count;Endianess").split(";")
self.table.setHorizontalHeaderLabels(headerstrings)
self.table.init(self.send, self.current_request.name)
bytescount = 0
self.table.setRowCount(len(datak))
count = 0
for k in datak:
dataitem = data[k]
ecudata = self.ecufile.data[dataitem.name]
endian = dataitem.endian
ln = dataitem.firstbyte + math.ceil(float(ecudata.bitscount) / 8.)
if ln > bytescount:
bytescount = ln
endian_combo = widgets.QComboBox()
endian_combo.addItem(_("Little"))
endian_combo.addItem(_("Big"))
endian_combo.addItem(_("Inherits globals"))
if endian == "Big":
endian_combo.setCurrentIndex(1)
elif endian == "Little":
endian_combo.setCurrentIndex(0)
else:
endian_combo.setCurrentIndex(2)
item_sb = widgets.QSpinBox()
item_sb.setRange(1, 100000)
item_sb.setValue(dataitem.firstbyte)
item_boff = widgets.QSpinBox()
item_boff.setRange(0, 7)
item_boff.setValue(dataitem.bitoffset)
item_bc = widgets.QTableWidgetItem(str(ecudata.bitscount))
item_name = widgets.QTableWidgetItem(dataitem.name)
item_name.setFlags(item_name.flags() ^ core.Qt.ItemIsEditable)
item_bc.setFlags(item_bc.flags() ^ core.Qt.ItemIsEditable)
item_bc.setTextAlignment(int(core.Qt.AlignHCenter) | int(core.Qt.AlignVCenter))
item_sb.valueChanged.connect(lambda state,
di=dataitem, slf=item_sb: self.start_byte_changed(di, slf))
item_boff.valueChanged.connect(lambda state,
di=dataitem, slf=item_boff: self.bit_offset_changed(di, slf))
endian_combo.activated.connect(lambda state,
di=dataitem, slf=endian_combo: self.endian_changed(di, slf))
self.table.setItem(count, 0, item_name)
self.table.setItem(count, 1, widgets.QTableWidgetItem(str(dataitem.firstbyte).zfill(5)))
self.table.setCellWidget(count, 1, item_sb)
self.table.setCellWidget(count, 2, item_boff)
self.table.setItem(count, 3, item_bc)
self.table.setCellWidget(count, 4, endian_combo)
count += 1
self.table.resizeColumnsToContents()
self.table.resizeRowsToContents()
self.table.sortItems(1)
self.bitviewer.init(int(bytescount) + 2)
def shift_bytes_change(self):
if not self.current_request:
return
self.current_request.shiftbytescount = self.spin_shift_byte.value()
def data_len_change(self):
if not self.current_request:
return
self.current_request.minbytes = self.spin_data_len.value()
def endian_changed(self, di, slf):
if slf.currentText() == _("Inherits globals"):
di.endian = ""
elif slf.currentText() == _("Little"):
di.endian = "Little"
elif slf.currentText() == _("Big"):
di.endian = "Big"
self.currentdataitem = di.name
self.update_bitview(self.currentdataitem)
self.update_bitview_value(self.currentdataitem)
def start_byte_changed(self, di, slf):
di.firstbyte = slf.value()
self.currentdataitem = di.name
self.update_bitview(self.currentdataitem)
self.update_bitview_value(self.currentdataitem)
def bit_offset_changed(self, di, slf):
di.bitoffset = slf.value()
self.currentdataitem = di.name
self.update_bitview(self.currentdataitem)
self.update_bitview_value(self.currentdataitem)
def request_changed(self):
if not self.current_request:
return
self.inputreq.setStyleSheet("background-color: red")
try:
text = str(self.inputreq.text())
except:
return
if not all(c in string.hexdigits for c in text):
return
if len(text) % 2 == 1:
return
if self.currentdataitem:
self.update_bitview_value(self.currentdataitem)
self.inputreq.setStyleSheet("background-color: green")
if self.send:
self.current_request.sentbytes = text
else:
self.current_request.replybytes = text
class requestEditor(widgets.QWidget):
"""Main container for reauest editor"""
def __init__(self, parent=None):
super(requestEditor, self).__init__(parent)
self.ecurequestsparser = None
layoutsss = widgets.QHBoxLayout()
self.checknosds = widgets.QCheckBox(_("No SDS"))
self.checkplant = widgets.QCheckBox(_("Plant"))
self.checkaftersales = widgets.QCheckBox(_("After Sale"))
self.checkengineering = widgets.QCheckBox(_("Engineering"))
self.checksupplier = widgets.QCheckBox(_("Supplier"))
self.checknosds.toggled.connect(self.sdschanged)
self.checkplant.toggled.connect(self.sdschanged)
self.checkaftersales.toggled.connect(self.sdschanged)
self.checkengineering.toggled.connect(self.sdschanged)
self.checksupplier.toggled.connect(self.sdschanged)
layoutsss.addWidget(self.checknosds)
layoutsss.addWidget(self.checkplant)
layoutsss.addWidget(self.checkaftersales)
layoutsss.addWidget(self.checkengineering)
layoutsss.addWidget(self.checksupplier)
layout_action = widgets.QHBoxLayout()
button_reload = widgets.QPushButton(_("Reload requests"))
button_add = widgets.QPushButton(_("Add request"))
layout_action.addWidget(button_reload)
layout_action.addWidget(button_add)
layout_action.addStretch()
button_reload.clicked.connect(self.reload)
button_add.clicked.connect(self.add_request)
self.layh = widgets.QHBoxLayout()
self.requesttable = requestTable()
self.layh.addWidget(self.requesttable)
self.layv = widgets.QVBoxLayout()
self.sendbyteeditor = paramEditor()
self.receivebyteeditor = paramEditor(False)
self.tabs = widgets.QTabWidget()
self.tabs.addTab(self.sendbyteeditor, _("Send bytes"))
self.tabs.addTab(self.receivebyteeditor, _("Receive bytes"))
self.layv.addLayout(layout_action)
self.layv.addLayout(layoutsss)
self.layv.addWidget(self.tabs)
self.layh.addLayout(self.layv)
self.setLayout(self.layh)
self.requesttable.setSendByteEditor(self.sendbyteeditor)
self.requesttable.setReceiveByteEditor(self.receivebyteeditor)
self.enable_view(False)
def refresh_data(self):
self.sendbyteeditor.refresh_combo()
self.receivebyteeditor.refresh_combo()
def enable_view(self, enable):
children = self.children()
for c in children:
if isinstance(c, widgets.QWidget):
c.setEnabled(enable)
def add_request(self):
ecu_datareq = {}
ecu_datareq['minbytes'] = 2
ecu_datareq['shiftbytescount'] = 0
ecu_datareq['replybytes'] = ''
ecu_datareq['manualsend'] = False
ecu_datareq['sentbytes'] = ''
ecu_datareq['endian'] = ''
ecu_datareq['name'] = u'New request'
self.ecurequestsparser.requests[ecu_datareq['name']] = ecu.Ecu_request(ecu_datareq, self.ecurequestsparser)
self.init()
self.requesttable.select(ecu_datareq['name'])
def sdschanged(self):
if not self.ecurequestsparser:
return
self.requesttable.set_sds(self)
def reload(self):
if not self.ecurequestsparser:
return
self.init()
def init(self):
self.requesttable.init(self.ecurequestsparser.requests)
self.sendbyteeditor.set_ecufile(self.ecurequestsparser)
self.receivebyteeditor.set_ecufile(self.ecurequestsparser)
def init_sds(self, req):
self.checknosds.setChecked(req.sds['nosds'])
self.checkplant.setChecked(req.sds['plant'])
self.checkaftersales.setChecked(req.sds['aftersales'])
self.checkengineering.setChecked(req.sds['engineering'])
self.checksupplier.setChecked(req.sds['supplier'])
def set_ecu(self, ecu):
self.ecurequestsparser = ecu
self.init()
self.enable_view(True)
class numericListPanel(widgets.QFrame):
def __init__(self, dataitem, parent=None):
super(numericListPanel, self).__init__(parent)
self.setFrameStyle(widgets.QFrame.Sunken)
self.setFrameShape(widgets.QFrame.Box)
self.data = dataitem
layoutv = widgets.QVBoxLayout()
layout = widgets.QGridLayout()
labelnob = widgets.QLabel(_("Number of bits"))
lablelsigned = widgets.QLabel(_("Signed"))
newitem = widgets.QPushButton(_("Add item"))
delitem = widgets.QPushButton(_("Del item"))
newitem.clicked.connect(self.add_item)
delitem.clicked.connect(self.def_item)
layout.addWidget(labelnob, 0, 0)
layout.addWidget(lablelsigned, 1, 0)
layout.addWidget(newitem, 2, 0)
layout.addWidget(delitem, 2, 1)
self.inputnob = widgets.QSpinBox()
self.inputnob.setRange(1, 32)
self.inputsigned = widgets.QCheckBox()
layout.addWidget(self.inputnob, 0, 1)
layout.addWidget(self.inputsigned, 1, 1)
layoutv.addLayout(layout)
self.itemtable = widgets.QTableWidget()
self.itemtable.setRowCount(1)
self.itemtable.setColumnCount(2)
self.itemtable.verticalHeader().hide()
self.itemtable.setSelectionBehavior(widgets.QAbstractItemView.SelectRows)
self.itemtable.setSelectionMode(widgets.QAbstractItemView.SingleSelection)
layoutv.addWidget(self.itemtable)
self.setLayout(layoutv)
self.init()
def add_item(self):
value = -999
self.itemtable.setRowCount(self.itemtable.rowCount() + 1)
newrow = self.itemtable.rowCount() - 1
spinvalue = widgets.QSpinBox()
spinvalue.setRange(-1000000, 1000000)
spinvalue.setValue(value)
self.itemtable.setCellWidget(newrow, 0, spinvalue)
self.itemtable.setItem(newrow, 1, widgets.QTableWidgetItem(_("New item")))
self.itemtable.setItem(newrow, 0, widgets.QTableWidgetItem(str(value).zfill(5)))
self.itemtable.resizeRowsToContents()
self.itemtable.resizeColumnsToContents()
def def_item(self):
currentrow = self.itemtable.currentRow()
if currentrow < 0:
return
self.itemtable.removeRow(currentrow)
def validate(self):
self.data.scaled = False
self.data.bitscount = self.inputnob.value()
self.data.unit = ""
self.data.signed = self.inputsigned.isChecked()
self.data.format = ""
self.data.step = 1
self.data.offset = 0
self.data.divideby = 1
self.data.bytesascii = False
self.data.items = {}
self.data.lists = {}
for i in range(self.itemtable.rowCount()):
key = self.itemtable.item(i, 1).text()
val = self.itemtable.cellWidget(i, 0).value()
while key in self.data.items:
key += u"_"
self.data.items[key] = val
self.data.lists[val] = key
def init(self):
if not self.data:
return
self.itemtable.clear()
keys = self.data.items.keys()
self.itemtable.setRowCount(len(keys))
self.inputsigned.setChecked(self.data.signed)
self.inputnob.setValue(self.data.bitscount)
count = 0
for k, v in self.data.items.items():
spinvalue = widgets.QSpinBox()
spinvalue.setRange(-1000000, 1000000)
spinvalue.setValue(int(v))
self.itemtable.setCellWidget(count, 0, spinvalue)
self.itemtable.setItem(count, 0, widgets.QTableWidgetItem(str(v).zfill(5)))
self.itemtable.setItem(count, 1, widgets.QTableWidgetItem(k))
count += 1
headerstrings = _("Value;Text").split(";")
self.itemtable.setHorizontalHeaderLabels(headerstrings)
self.itemtable.resizeColumnsToContents()
self.itemtable.resizeRowsToContents()
self.itemtable.sortItems(0, core.Qt.AscendingOrder)
# self.itemtable.setSortingEnabled(True)
class otherPanel(widgets.QFrame):
def __init__(self, dataitem, parent=None):
super(otherPanel, self).__init__(parent)
self.setFrameStyle(widgets.QFrame.Sunken)
self.setFrameShape(widgets.QFrame.Box)
self.data = dataitem
layout = widgets.QGridLayout()
labelnob = widgets.QLabel(_("Number of bytes"))
lableunit = widgets.QLabel(_("Unit"))
layout.addWidget(labelnob, 0, 0)
layout.addWidget(lableunit, 1, 0)
layout.setRowStretch(2, 1)
self.inputnob = widgets.QSpinBox()
self.inputnob.setRange(1, 10240)
self.inputtype = widgets.QComboBox()
self.inputtype.addItem("ASCII")
self.inputtype.addItem("BCD/HEX")
layout.addWidget(self.inputnob, 0, 1)
layout.addWidget(self.inputtype, 1, 1)
self.setLayout(layout)
self.init()
def validate(self):
type = self.inputtype.currentIndex()
self.data.scaled = False
self.data.bytescount = self.inputnob.value()
self.data.bitscount = self.data.bytescount * 8
self.data.unit = ""
self.data.signed = False
self.data.format = ""
self.data.step = 1
self.data.offset = 0
self.data.divideby = 1
if type == 0:
self.data.bytesascii = True
else:
self.data.bytesascii = False
self.data.items = {}
self.data.lists = {}
def init(self):
if self.data is None:
return
self.inputnob.setValue(self.data.bytescount)
if self.data.bytesascii:
self.inputtype.setCurrentIndex(0)
else:
self.inputtype.setCurrentIndex(1)
class numericPanel(widgets.QFrame):
def __init__(self, dataitem, parent=None):
super(numericPanel, self).__init__(parent)
self.setFrameStyle(widgets.QFrame.Sunken)
self.setFrameShape(widgets.QFrame.Box)
self.data = dataitem
layout = widgets.QGridLayout()
labelnob = widgets.QLabel(_("Number of bit"))
lableunit = widgets.QLabel(_("Unit"))
labelsigned = widgets.QLabel(_("Signed"))
labelformat = widgets.QLabel(_("Format"))
labeldoc = widgets.QLabel(_("Value = (AX+B) / C"))
labela = widgets.QLabel("A")
labelb = widgets.QLabel("B")
labelc = widgets.QLabel("C")
layout.addWidget(labelnob, 0, 0)
layout.addWidget(lableunit, 1, 0)
layout.addWidget(labelsigned, 2, 0)
layout.addWidget(labelformat, 3, 0)
layout.addWidget(labeldoc, 4, 0)
layout.addWidget(labela, 5, 0)
layout.addWidget(labelb, 6, 0)
layout.addWidget(labelc, 7, 0)
layout.setRowStretch(8, 1)
self.inputnob = widgets.QSpinBox()
self.inputnob.setRange(1, 32)
self.inputunit = widgets.QLineEdit()
self.inputsigned = widgets.QCheckBox()
self.inputformat = widgets.QLineEdit()
self.inputa = widgets.QDoubleSpinBox()
self.inputb = widgets.QDoubleSpinBox()
self.inputc = widgets.QDoubleSpinBox()
self.inputc.setRange(-1000000, 1000000)
self.inputb.setRange(-1000000, 1000000)
self.inputa.setRange(-1000000, 1000000)
self.inputa.setDecimals(4)
self.inputb.setDecimals(4)
self.inputc.setDecimals(4)
layout.addWidget(self.inputnob, 0, 1)
layout.addWidget(self.inputunit, 1, 1)
layout.addWidget(self.inputsigned, 2, 1)
layout.addWidget(self.inputformat, 3, 1)
layout.addWidget(self.inputa, 5, 1)
layout.addWidget(self.inputb, 6, 1)
layout.addWidget(self.inputc, 7, 1)
self.setLayout(layout)
self.init()
def validate(self):
self.data.scaled = True
self.data.bitscount = self.inputnob.value()
self.data.unit = self.inputunit.text()
self.data.signed = self.inputsigned.isChecked()
self.data.format = self.inputformat.text()
self.data.step = self.inputa.value()
self.data.offset = self.inputb.value()
self.data.divideby = self.inputc.value()
self.data.bytesascii = False
self.data.items = {}
self.data.lists = {}
def init(self):
if self.data is None:
return
self.inputnob.setValue(self.data.bitscount)
self.inputunit.setText(self.data.unit)
self.inputsigned.setChecked(self.data.signed)
self.inputformat.setText(self.data.format)
self.inputa.setValue(self.data.step)
self.inputb.setValue(self.data.offset)
self.inputc.setValue(self.data.divideby)
class dataEditor(widgets.QWidget):
"""Main container for data item editor"""
def __init__(self, parent=None):
super(dataEditor, self).__init__(parent)
self.ecurequestsparser = None
self.currentecudata = None
layout_action = widgets.QHBoxLayout()
button_new = widgets.QPushButton(_("New"))
button_duplicate = widgets.QPushButton(_("Duplicate selected"))
button_remove = widgets.QPushButton(_("Remove selected"))
button_reload = widgets.QPushButton(_("Reload"))
button_validate = widgets.QPushButton(_("Validate changes"))
layout_action.addWidget(button_new)
layout_action.addWidget(button_duplicate)
layout_action.addWidget(button_remove)
layout_action.addWidget(button_reload)
layout_action.addWidget(button_validate)
layout_action.addStretch()
button_new.clicked.connect(self.new_request)
button_reload.clicked.connect(self.reload)
button_validate.clicked.connect(self.validate)
button_duplicate.clicked.connect(self.duplicate_selected)
button_remove.clicked.connect(self.remove_selected)
self.layouth = widgets.QHBoxLayout()
self.datatable = widgets.QTableWidget()
self.datatable.setFixedWidth(350)
self.datatable.setRowCount(1)
self.datatable.setColumnCount(2)
self.datatable.verticalHeader().hide()
self.datatable.setSelectionBehavior(widgets.QAbstractItemView.SelectRows)
self.datatable.setSelectionMode(widgets.QAbstractItemView.SingleSelection)
# self.datatable.setShowGrid(False)
self.layouth.addWidget(self.datatable)
self.editorcontent = widgets.QFrame()
self.editorcontent.setFrameStyle(widgets.QFrame.Sunken)
self.editorcontent.setFrameShape(widgets.QFrame.Box)
self.layoutv = widgets.QVBoxLayout()
self.layouth.addLayout(self.layoutv)
self.layoutv.addLayout(layout_action)
desclayout = widgets.QHBoxLayout()
labeldescr = widgets.QLabel(_("Description"))
self.descpriptioneditor = widgets.QLineEdit()
desclayout.addWidget(labeldescr)
desclayout.addWidget(self.descpriptioneditor)
typelayout = widgets.QHBoxLayout()
typelabel = widgets.QLabel(_("Data type"))
self.typecombo = widgets.QComboBox()
self.typecombo.addItem(_("Numeric"))
self.typecombo.addItem(_("Numeric items"))
self.typecombo.addItem(_("Hex"))
typelayout.addWidget(typelabel)
typelayout.addWidget(self.typecombo)
self.layoutv.addLayout(desclayout)
self.layoutv.addLayout(typelayout)
self.nonePanel = widgets.QWidget()
self.layoutv.addWidget(self.nonePanel)
self.currentWidget = self.nonePanel
self.setLayout(self.layouth)
self.typecombo.currentIndexChanged.connect(self.switchType)
self.datatable.itemSelectionChanged.connect(self.changeData)
self.enable_view(False)
def remove_selected(self):
if len(self.datatable.selectedItems()) == 0:
return
r = self.datatable.selectedItems()[-1].row()
dataname = self.datatable.item(r, 0).text()
# Check if data needed by request
for reqname, request in self.ecurequestsparser.requests.items():
for rcvname, rcvdi in request.dataitems.items():
if rcvname == dataname:
msgbox = widgets.QMessageBox()
appIcon = gui.QIcon("dtt4all_data/icons/obd.png")
msgbox.setWindowIcon(appIcon)
msgbox.setWindowTitle(version.__appname__)
msgbox.setText(_("Data is used by request %s") % reqname)
msgbox.exec_()
return
for sndname, snddi in request.sendbyte_dataitems.items():
if sndname == dataname:
msgbox = widgets.QMessageBox()
appIcon = gui.QIcon("dtt4all_data/icons/obd.png")
msgbox.setWindowIcon(appIcon)
msgbox.setWindowTitle(version.__appname__)
msgbox.setText(_("Data is used by request %s") % reqname)
msgbox.exec_()
return
self.ecurequestsparser.data.pop(dataname)
self.reload()
def duplicate_selected(self):
if len(self.datatable.selectedItems()) == 0:
return
r = self.datatable.selectedItems()[-1].row()
dataname = self.datatable.item(r, 0).text()
self.currentecudata = self.ecurequestsparser.data[dataname]
new_data_name = dataname
while new_data_name in self.ecurequestsparser.data:
new_data_name += u"_copy"
deep_data_copy = copy.deepcopy(self.currentecudata)
deep_data_copy.name = new_data_name
self.ecurequestsparser.data[new_data_name] = deep_data_copy
self.reload()
copied_item = self.datatable.findItems(new_data_name, core.Qt.MatchExactly)
self.datatable.selectRow(copied_item[0].row())
options.main_window.requesteditor.init()
def enable_view(self, enable):
children = self.children()
for c in children:
if isinstance(c, widgets.QWidget):
c.setEnabled(enable)
def edititem(self, name):
items = self.datatable.findItems(name, core.Qt.MatchExactly)
if len(items):
self.datatable.selectRow(items[0].row())
self.changeData()
def new_request(self):
if not self.ecurequestsparser:
return
new_data_name = _("New data")
while new_data_name in self.ecurequestsparser.data.keys():
new_data_name += "_"
new_data = ecu.Ecu_data(None, new_data_name)
new_data.comment = _("Replace me with request description")
self.ecurequestsparser.data[new_data_name] = new_data
self.reload()
new_item = self.datatable.findItems(new_data_name, core.Qt.MatchExactly)
self.datatable.selectRow(new_item[0].row())
# Refresh request data combo
options.main_window.requesteditor.refresh_data()
def cellModified(self, r, c):
if c != 0:
return
currentecudata = self.currentecudata
oldname = currentecudata.name
self.ecurequestsparser.data.pop(oldname)
item = self.datatable.item(r, c)
newname = item.text()
currentecudata.name = newname
self.ecurequestsparser.data[newname] = currentecudata
# Change requests data items name too
for reqk, req in self.ecurequestsparser.requests.items():
sbdata = req.sendbyte_dataitems
rbdata = req.dataitems
if oldname in sbdata.keys():
sbdata[oldname].name = newname
sbdata[newname] = sbdata.pop(oldname)
if oldname in rbdata.keys():
rbdata[oldname].name = newname
rbdata[newname] = rbdata.pop(oldname)
options.main_window.paramview.dataNameChanged(oldname, newname)
options.main_window.requesteditor.refresh_data()
def clear(self):
self.datatable.clear()
self.switchType(3)
def reload(self):
self.init_table()
def validate(self):
if "validate" not in dir(self.currentWidget):
return
comment = self.descpriptioneditor.text()
self.currentecudata.comment = comment
self.currentWidget.validate()
options.main_window.requesteditor.refresh_data()
# Update table entry
if len(self.datatable.selectedItems()) == 0:
return
r = self.datatable.selectedItems()[-1].row()
self.datatable.item(r, 1).setText(comment)
def changeData(self):
if len(self.datatable.selectedItems()) == 0:
return
r = self.datatable.selectedItems()[-1].row()
dataname = self.datatable.item(r, 0).text()
self.currentecudata = self.ecurequestsparser.data[dataname]
self.descpriptioneditor.setText(self.currentecudata.comment)
if self.currentecudata.scaled:
self.switchType(0)
elif len(self.currentecudata.items):
self.switchType(1)
else:
self.switchType(2)
def switchType(self, num):
self.descpriptioneditor.setEnabled(True)
self.typecombo.setEnabled(True)
if num == 0:
self.typecombo.setCurrentIndex(0)
self.layoutv.removeWidget(self.currentWidget)
self.currentWidget.hide()
self.currentWidget.destroy()
self.currentWidget = numericPanel(self.currentecudata)
self.layoutv.addWidget(self.currentWidget)
if num == 1:
self.typecombo.setCurrentIndex(1)
self.layoutv.removeWidget(self.currentWidget)
self.currentWidget.hide()
self.currentWidget.destroy()
self.currentWidget = numericListPanel(self.currentecudata)
self.layoutv.addWidget(self.currentWidget)
if num == 2:
self.typecombo.setCurrentIndex(2)
self.layoutv.removeWidget(self.currentWidget)
self.currentWidget.hide()
self.currentWidget.destroy()
self.currentWidget = otherPanel(self.currentecudata)
self.layoutv.addWidget(self.currentWidget)
if num == 3:
self.layoutv.removeWidget(self.currentWidget)
self.currentWidget.hide()
self.currentWidget.destroy()
self.currentWidget = widgets.QWidget()
self.layoutv.addWidget(self.currentWidget)
self.descpriptioneditor.setEnabled(False)
self.typecombo.setEnabled(False)
def disconnect_table(self):
try:
self.datatable.cellChanged.disconnect()
except:
pass
def connect_table(self):
self.datatable.cellChanged.connect(self.cellModified)
def init_table(self):
self.disconnect_table()
self.datatable.clear()
dataItems = self.ecurequestsparser.data.keys()
self.datatable.setRowCount(len(dataItems))
count = 0
for k in dataItems:
data = self.ecurequestsparser.data[k]
itemk = widgets.QTableWidgetItem(k)
itemc = widgets.QTableWidgetItem(data.comment)
itemc.setFlags(itemc.flags() ^ core.Qt.ItemIsEditable)
self.datatable.setItem(count, 0, itemk)
self.datatable.setItem(count, 1, itemc)
count += 1
self.datatable.sortItems(0, core.Qt.AscendingOrder)
headerstrings = _("Data name;Description").split(";")
self.datatable.setHorizontalHeaderLabels(headerstrings)
self.datatable.resizeColumnsToContents()
self.datatable.resizeRowsToContents()
self.datatable.sortByColumn(0, core.Qt.AscendingOrder)
self.connect_table()
def set_ecu(self, ecu):
self.ecurequestsparser = ecu
self.switchType(3)
self.init_table()
self.enable_view(True)
class buttonData(widgets.QFrame):
def __init__(self, parent=None):
super(buttonData, self).__init__(parent)
self.setFrameStyle(widgets.QFrame.Sunken)
self.setFrameShape(widgets.QFrame.Box)
self.buttonlayout = None
self.ecurequests = None
self.currentbuttonparams = None
self.currentbuttonuniquename = None
self.is_screen = None
self.layout = None
layout = widgets.QVBoxLayout()
self.requesttable = widgets.QTableWidget()
layout.addWidget(self.requesttable)
layoutbar = widgets.QHBoxLayout()
self.delaybox = widgets.QSpinBox()
self.delaybox.setRange(0, 100000)
self.delaybox.setSingleStep(50)
self.delaybox.setFixedWidth(80)
self.requestcombo = widgets.QComboBox()
self.requestaddbutton = widgets.QPushButton(_("Add"))
self.requestdelbutton = widgets.QPushButton(_("Del"))
self.requestrefbutton = widgets.QPushButton(_("Refresh"))
self.requestmoveupbutton = widgets.QPushButton(_("Move up"))
self.requestcheckbutton = widgets.QPushButton(_("Check"))
layoutbar.addWidget(self.delaybox)
layoutbar.addWidget(self.requestcombo)
layoutbar.addWidget(self.requestmoveupbutton)
layoutbar.addWidget(self.requestaddbutton)
layoutbar.addWidget(self.requestdelbutton)
layoutbar.addWidget(self.requestrefbutton)
layoutbar.addWidget(self.requestcheckbutton)
self.requestrefbutton.setFixedWidth(80)
self.requestdelbutton.setFixedWidth(60)
self.requestaddbutton.setFixedWidth(60)
self.requestmoveupbutton.setFixedWidth(70)
self.requestcheckbutton.setFixedWidth(80)
self.requestrefbutton.clicked.connect(self.refresh_request)
self.requestdelbutton.clicked.connect(self.delete_request)
self.requestaddbutton.clicked.connect(self.add_request)
self.requestmoveupbutton.clicked.connect(self.move_up)
self.requestcheckbutton.clicked.connect(self.check_data)
layout.addLayout(layoutbar)
self.setLayout(layout)
self.requesttable.setColumnCount(2)
self.requesttable.verticalHeader().hide()
self.requesttable.setSelectionBehavior(widgets.QAbstractItemView.SelectRows)
self.requesttable.setSelectionMode(widgets.QAbstractItemView.SingleSelection)
# self.requesttable.setShowGrid(False)
def check_data(self):
if not self.ecurequests or not self.buttonlayout:
return
items = self.requesttable.selectedItems()
if len(items) == 0:
return
currentrowidx = items[-1].row()
requestname = self.currentbuttonparams[currentrowidx]['RequestName']
if requestname not in self.ecurequests.requests.keys():
options.main_window.logview.append(_("Request %s not found") % requestname)
return
request = self.ecurequests.requests[requestname]
datasenditems = request.sendbyte_dataitems
inputlayout = self.layout['inputs']
itemsfound = {}
numfound = 0
for dataitemname in datasenditems.keys():
for inp in inputlayout:
itemsfound[dataitemname] = False
if dataitemname == inp['text']:
if requestname == inp['request']:
itemsfound[dataitemname] = True
numfound += 1
break
if len(itemsfound) == numfound:
options.main_window.logview.append(
_("Request '%s' has no missing input values") % requestname)
return
options.main_window.logview.append(
_("Request '%s' has missing inputs :") % requestname)
for k, v in itemsfound.items():
if not v:
options.main_window.logview.append(_(" - '%s'") % k)
def clear(self):
self.requesttable.clear()
def refresh_request(self):
if not self.ecurequests or not self.buttonlayout:
return
self.init(self.ecurequests, self.layout)
def init(self, ecureq, layout):
self.buttonlayout = layout['buttons']
self.layout = layout
self.ecurequests = ecureq
self.requestcombo.clear()
for req in sorted(ecureq.requests.keys()):
if ecureq.requests[req].manualsend:
self.requestcombo.addItem(req)
def move_up(self):
items = self.requesttable.selectedItems()
if len(items) == 0:
return
currentrowidx = items[-1].row()
if currentrowidx < 1:
return
params = self.currentbuttonparams.pop(currentrowidx)
self.currentbuttonparams.insert(currentrowidx - 1, params)
self.init_table(self.currentbuttonuniquename, self.is_screen)
self.requesttable.selectRow(currentrowidx - 1)
def delete_request(self):
items = self.requesttable.selectedItems()
if len(items) == 0:
return
currentrowidx = items[-1].row()
self.currentbuttonparams.pop(currentrowidx)
self.init_table(self.currentbuttonuniquename, self.is_screen)
def add_request(self):
if self.currentbuttonparams is None:
return
delay = self.delaybox.value()
request = self.requestcombo.currentText()
smap = {
'Delay': str(delay),
'RequestName': request
}
self.currentbuttonparams.append(smap)
self.init_table(self.currentbuttonuniquename, self.is_screen)
def init_table(self, itemname, is_screen):
self.is_screen = is_screen
self.requesttable.clearSelection()
self.requesttable.clear()
self.currentbuttonparams = None
self.currentbuttonuniquename = None
if not self.is_screen:
count = 0
for butreq in self.buttonlayout:
if butreq['uniquename'] == itemname:
self.currentbuttonuniquename = itemname
if 'send' not in butreq:
continue
sendparams = butreq['send']
self.requesttable.setRowCount(len(sendparams))
self.currentbuttonparams = sendparams
for sendparam in sendparams:
itemreq = widgets.QTableWidgetItem(sendparam['RequestName'])
itemdelay = widgets.QTableWidgetItem(sendparam['Delay'])
self.requesttable.setItem(count, 1, itemreq)
self.requesttable.setItem(count, 0, itemdelay)
itemreq.setFlags(core.Qt.ItemIsSelectable | core.Qt.ItemIsEnabled)
itemdelay.setFlags(core.Qt.ItemIsSelectable | core.Qt.ItemIsEnabled)
count += 1
else:
count = 0
sendparams = self.layout['presend']
self.requesttable.setRowCount(len(sendparams))
self.currentbuttonparams = sendparams
for sendparam in sendparams:
itemreq = widgets.QTableWidgetItem(sendparam['RequestName'])
itemdelay = widgets.QTableWidgetItem(sendparam['Delay'])
self.requesttable.setItem(count, 1, itemreq)
self.requesttable.setItem(count, 0, itemdelay)
itemreq.setFlags(core.Qt.ItemIsSelectable | core.Qt.ItemIsEnabled)
itemdelay.setFlags(core.Qt.ItemIsSelectable | core.Qt.ItemIsEnabled)
count += 1
headerstrings = _("Delay;Request").split(";")
self.requesttable.setHorizontalHeaderLabels(headerstrings)
self.requesttable.resizeColumnsToContents()
self.requesttable.resizeRowsToContents()
class buttonEditor(widgets.QWidget):
"""Main container for button editor"""
def __init__(self, parent=None):
super(buttonEditor, self).__init__(parent)
self.ecurequestsparser = None
self.layout = None
self.layouth = widgets.QHBoxLayout()
self.buttontable = widgets.QTableWidget()
self.layoutv = widgets.QVBoxLayout()
self.layouth.addWidget(self.buttontable)
self.layouth.addLayout(self.layoutv)
self.buttondata = buttonData()
self.layoutv.addWidget(self.buttondata)
self.setLayout(self.layouth)
self.buttontable.setFixedWidth(250)
self.buttontable.setColumnCount(2)
self.buttontable.verticalHeader().hide()
self.buttontable.setSelectionBehavior(widgets.QAbstractItemView.SelectRows)
self.buttontable.setSelectionMode(widgets.QAbstractItemView.SingleSelection)
# self.buttontable.setShowGrid(False)
self.buttontable.itemSelectionChanged.connect(self.selection_changed)
self.enable_view(False)
def name_changed(self, r, c):
if r == 0:
return
currentitem = self.buttontable.item(r, 0)
if not currentitem:
return
idx = currentitem.row() - 1
buttondata = self.layout['buttons'][idx]
textdata = currentitem.text()
buttondata['text'] = textdata
buttondata['uniquename'] = textdata + u"_" + str(idx)
self.init()
if options.main_window:
options.main_window.paramview.reinitScreen()
def selection_changed(self):
selitems = self.buttontable.selectedItems()
if not len(selitems):
return
current_row = selitems[-1].row()
is_screen = current_row == 0
current_item_name = self.buttontable.item(current_row, 1).text()
self.buttondata.init_table(current_item_name, is_screen)
def set_ecu(self, ecu):
self.ecurequestsparser = ecu
self.enable_view(True)
def enable_view(self, enable):
children = self.children()
for c in children:
if isinstance(c, widgets.QWidget):
c.setEnabled(enable)
def set_layout(self, layout):
self.layout = layout
self.init()
def init(self):
try:
self.buttontable.cellChanged.disconnect(self.name_changed)
except:
pass
self.buttontable.clearSelection()
self.buttondata.clear()
if self.ecurequestsparser:
self.buttondata.init(self.ecurequestsparser, self.layout)
num_buttons = len(self.layout['buttons'])
self.buttontable.setRowCount(num_buttons + 1)
scitem = widgets.QTableWidgetItem(_("Screen initialization"))
noitem = widgets.QTableWidgetItem(_("Requests to send before screen drawing"))
self.buttontable.setItem(0, 0, scitem)
self.buttontable.setItem(0, 1, noitem)
scitem.setFlags(core.Qt.ItemIsSelectable | core.Qt.ItemIsEnabled)
noitem.setFlags(core.Qt.ItemIsSelectable | core.Qt.ItemIsEnabled)
count = 1
for button in self.layout['buttons']:
uniquenameitem = widgets.QTableWidgetItem(button['uniquename'])
self.buttontable.setItem(count, 0, widgets.QTableWidgetItem(button['text']))
self.buttontable.setItem(count, 1, uniquenameitem)
uniquenameitem.setFlags(core.Qt.ItemIsSelectable | core.Qt.ItemIsEnabled)
count += 1
headerstrings = _("Button name;Unique name").split(";")
self.buttontable.setHorizontalHeaderLabels(headerstrings)
self.buttontable.resizeColumnsToContents()
self.buttontable.resizeRowsToContents()
self.buttontable.selectRow(0)
self.buttontable.cellChanged.connect(self.name_changed)
class hexLineEdit(widgets.QLineEdit):
def __init__(self, num, alpha):
widgets.QLineEdit.__init__(self)
if not alpha:
self.setInputMask("H" * num)
else:
self.setInputMask("N" * num)
class hexSpinBox(widgets.QSpinBox):
def __init__(self, iscan=True):
widgets.QSpinBox.__init__(self)
self.set_can(iscan)
def set_can(self, iscan):
if iscan:
self.setRange(0, 0x7FF)
self.can = True
else:
self.setRange(0, 0xFF)
self.can = False
def textFromValue(self, value):
if self.can:
return "%03X" % value
else:
return "%02X" % value
def valueFromText(self, text):
if len(text) == 0:
return 0
return int("0x" + str(text), 16)
def validate(self, input, pos):
if len(str(input)) == 0:
return (gui.QValidator.Acceptable, input, pos)
try:
value = int("0x" + str(input)[pos - 1], 16)
except:
return (gui.QValidator.Invalid, input, pos)
return (gui.QValidator.Acceptable, input, pos)
class ecuParamEditor(widgets.QFrame):
def __init__(self, parent=None):
super(ecuParamEditor, self).__init__(parent)
self.ecurequestsparser = None
self.targets = None
layoutv = widgets.QVBoxLayout()
self.setLayout(layoutv)
gridlayout = widgets.QGridLayout()
self.protocolcombo = widgets.QComboBox()
self.funcadressedit = hexSpinBox(False)
self.protocolcombo.addItem("CAN")
self.protocolcombo.addItem("KWP2000 Slow Init")
self.protocolcombo.addItem("KWP2000 Fast Init")
self.protocolcombo.addItem("ISO8")
gridlayout.addWidget(widgets.QLabel(_("ECU Function address")), 0, 0)
gridlayout.addWidget(self.funcadressedit, 0, 1)
gridlayout.addWidget(widgets.QLabel(_("ECU Protocol")), 4, 0)
gridlayout.addWidget(self.protocolcombo, 4, 1)
self.addr1label = widgets.QLabel(_("Tool > Ecu ID (Hex)"))
gridlayout.addWidget(self.addr1label, 1, 0)
self.addr2label = widgets.QLabel(_("Ecu > Tool ID (Hex)"))
gridlayout.addWidget(self.addr2label, 2, 0)
gridlayout.addWidget(widgets.QLabel(_("Coding")), 3, 0)
self.toolecuidbox = hexSpinBox()
self.ecutoolidbox = hexSpinBox()
self.codingcombo = widgets.QComboBox()
self.codingcombo.addItem(_("Big Endian"))
self.codingcombo.addItem(_("Little Endian"))
gridlayout.addWidget(self.toolecuidbox, 1, 1)
gridlayout.addWidget(self.ecutoolidbox, 2, 1)
gridlayout.addWidget(self.codingcombo, 3, 1)
gridlayout.setColumnStretch(3, 1)
layoutv.addLayout(gridlayout)
autoident_label = widgets.QLabel(_("ECU Auto identification"))
autoident_label.setAlignment(core.Qt.AlignCenter)
self.identtable = widgets.QTableWidget()
self.identtable.setColumnCount(4)
self.identtable.verticalHeader().hide()
self.identtable.setSelectionBehavior(widgets.QAbstractItemView.SelectRows)
self.identtable.setSelectionMode(widgets.QAbstractItemView.SingleSelection)
self.identtable.itemSelectionChanged.connect(self.selection_changed)
layoutv.addWidget(autoident_label)
layoutv.addWidget(self.identtable)
headerstrings = _("Diag version;Supplier;Soft;Version").split(";")
self.identtable.setHorizontalHeaderLabels(headerstrings)
inputayout = widgets.QHBoxLayout()
self.inputdiag = hexLineEdit(2, False)
self.inputsupplier = hexLineEdit(6, True)
self.inputsoft = hexLineEdit(4, False)
self.inputversion = hexLineEdit(4, False)
self.addbutton = widgets.QPushButton(_("Add new"))
self.delbutton = widgets.QPushButton(_("Delete selected"))
inputayout.addWidget(widgets.QLabel(_("Diag version")))
inputayout.addWidget(self.inputdiag)
inputayout.addWidget(widgets.QLabel(_("Supplier")))
inputayout.addWidget(self.inputsupplier)
inputayout.addWidget(widgets.QLabel(_("Soft")))
inputayout.addWidget(self.inputsoft)
inputayout.addWidget(widgets.QLabel(_("Version")))
inputayout.addWidget(self.inputversion)
inputayout.addWidget(self.addbutton)
inputayout.addWidget(self.delbutton)
layoutv.addLayout(inputayout)
self.toolecuidbox.valueChanged.connect(self.toolecu_changed)
self.ecutoolidbox.valueChanged.connect(self.ecutool_changed)
self.codingcombo.activated.connect(self.coding_changed)
self.protocolcombo.activated.connect(self.protcol_changed)
self.addbutton.clicked.connect(self.add_ident)
self.delbutton.clicked.connect(self.del_ident)
self.funcadressedit.valueChanged.connect(self.funcadress_changed)
self.enable_view(False)
def funcadress_changed(self):
self.ecurequestsparser.funcaddr = hex(self.funcadressedit.value())[2:]
def del_ident(self):
selitems = self.identtable.selectedItems()
if not len(selitems):
return
current_row = selitems[-1].row()
if len(self.targets):
self.targets.pop(current_row)
self.init()
def add_ident(self):
diagversion = self.inputdiag.text()
suppliercode = self.inputsupplier.text()
soft = self.inputsoft.text()
version = self.inputversion.text()
protocol = "Undefined"
if self.protocolcombo.currentIndex() == 0:
protocol = u"DiagOnCAN"
elif self.protocolcombo.currentIndex() == 1:
protocol = u"KWP2000 FastInit MonoPoint"
elif self.protocolcombo.currentIndex() == 2:
protocol = u"KWP2000 Init 5 Baud Type I and II"
elif self.protocolcombo.currentIndex() == 3:
protocol = u"ISO8"
ident = {
"diagnotic_version": diagversion,
"supplier_code": suppliercode,
"protocol": protocol,
"soft_version": soft,
"version": version,
"address": "",
"group": "",
"projects": []
}
self.targets.append(ident)
self.init()
def coding_changed(self):
if self.codingcombo.currentIndex() == 0:
self.ecurequestsparser.endianness = 'Big'
else:
self.ecurequestsparser.endianness = 'Little'
self.init()
def protcol_changed(self):
if self.protocolcombo.currentIndex() == 0:
self.ecurequestsparser.ecu_protocol = "CAN"
self.toolecuidbox.set_can(True)
self.ecutoolidbox.set_can(True)
self.addr1label.setText(_("Tool > Ecu ID (Hex)"))
self.addr2label.setText(_("Ecu > Tool ID (Hex)"))
elif self.protocolcombo.currentIndex() == 1:
self.ecurequestsparser.ecu_protocol = "KWP2000"
self.ecurequestsparser.fastinit = False
self.toolecuidbox.set_can(False)
self.ecutoolidbox.set_can(False)
self.addr1label.setText("KW1")
self.addr2label.setText("KW2")
elif self.protocolcombo.currentIndex() == 2:
self.ecurequestsparser.ecu_protocol = "KWP2000"
self.ecurequestsparser.fastinit = True
self.addr1label.setText("KW1")
self.addr2label.setText("KW2")
self.toolecuidbox.set_can(False)
self.ecutoolidbox.set_can(False)
elif self.protocolcombo.currentIndex() == 3:
self.ecurequestsparser.ecu_protocol = "ISO8"
self.ecurequestsparser.fastinit = False
self.addr1label.setText("KW1")
self.addr2label.setText("KW2")
self.toolecuidbox.set_can(False)
self.ecutoolidbox.set_can(False)
def toolecu_changed(self):
if self.ecurequestsparser.ecu_protocol == "CAN":
self.ecurequestsparser.ecu_send_id = hex(self.toolecuidbox.value())[2:]
else:
self.ecurequestsparser.kw1 = hex(self.toolecuidbox.value())[2:]
def ecutool_changed(self):
if self.ecurequestsparser.ecu_protocol == "CAN":
self.ecurequestsparser.ecu_recv_id = hex(self.ecutoolidbox.value())[2:]
else:
self.ecurequestsparser.kw2 = hex(self.ecutoolidbox.value())[2:]
def set_ecu(self, ecu):
self.ecurequestsparser = ecu
self.enable_view(True)
self.init()
def enable_view(self, enable):
children = self.children()
for c in children:
if isinstance(c, widgets.QWidget):
c.setEnabled(enable)
def set_targets(self, targets):
self.targets = targets
self.init()
def selection_changed(self):
selitems = self.identtable.selectedItems()
if not len(selitems):
return
current_row = selitems[-1].row()
diagversion = self.identtable.item(current_row, 0).text()
suppliercode = self.identtable.item(current_row, 1).text()
soft = self.identtable.item(current_row, 2).text()
version = self.identtable.item(current_row, 3).text()
self.inputdiag.setText(diagversion)
self.inputsupplier.setText(suppliercode)
self.inputsoft.setText(soft)
self.inputversion.setText(version)
def init(self):
if self.targets is None:
return
if not self.ecurequestsparser:
return
if self.ecurequestsparser.ecu_protocol == "CAN":
self.toolecuidbox.set_can(True)
self.ecutoolidbox.set_can(True)
self.protocolcombo.setCurrentIndex(0)
elif self.ecurequestsparser.ecu_protocol == "KWP2000":
self.toolecuidbox.set_can(False)
self.ecutoolidbox.set_can(False)
if self.ecurequestsparser.fastinit:
self.protocolcombo.setCurrentIndex(2)
else:
self.protocolcombo.setCurrentIndex(1)
elif self.ecurequestsparser.ecu_protocol == "ISO8":
self.toolecuidbox.set_can(False)
self.ecutoolidbox.set_can(False)
self.protocolcombo.setCurrentIndex(3)
self.protcol_changed()
self.funcadressedit.setValue(int("0x" + self.ecurequestsparser.funcaddr, 16))
if self.ecurequestsparser.endianness == 'Little':
self.codingcombo.setCurrentIndex(1)
else:
self.codingcombo.setCurrentIndex(0)
if self.ecurequestsparser.ecu_protocol == "CAN":
self.toolecuidbox.setValue(int("0x" + str(self.ecurequestsparser.ecu_send_id), 16))
self.ecutoolidbox.setValue(int("0x" + str(self.ecurequestsparser.ecu_recv_id), 16))
else:
self.toolecuidbox.setValue(int("0x" + str(self.ecurequestsparser.kw1), 16))
self.ecutoolidbox.setValue(int("0x" + str(self.ecurequestsparser.kw2), 16))
self.identtable.clearContents()
count = 0
self.identtable.setRowCount(len(self.targets))
for target in self.targets:
if 'diagnostic_version' in target:
self.identtable.setItem(count, 0, widgets.QTableWidgetItem(target['diagnostic_version']))
else:
self.identtable.setItem(count, 0, widgets.QTableWidgetItem(target['diagnotic_version']))
self.identtable.setItem(count, 1, widgets.QTableWidgetItem(target['supplier_code']))
self.identtable.setItem(count, 2, widgets.QTableWidgetItem(target['soft_version']))
self.identtable.setItem(count, 3, widgets.QTableWidgetItem(target['version']))
count += 1
self.identtable.resizeColumnsToContents()
self.identtable.resizeRowsToContents()
self.identtable.selectRow(0)