9p add terminal commands

This commit is contained in:
shrlnm 2019-05-02 18:26:44 +03:00
parent ac265af672
commit a2d48215f1
8 changed files with 432 additions and 128 deletions

View File

@ -5,9 +5,14 @@ can500 # init can macro
1003 1003
# check if it is rlink2
exit_if_not F18A 6 4 FFFFFF 434150
# HIGH 1 768x1024 # HIGH 1 768x1024
2E2303032802131303003C000004500014001E001E040011C5002C006967 2E2303032802131303003C000004500014001E001E040011C5002C006967
wait 2 wait 2
# reload rlink2 # reload rlink2
1101 1101
exit

View File

@ -5,9 +5,14 @@ can500 # init can macro
1003 1003
# check if it is rlink2
exit_if_not F18A 6 4 FFFFFF 434150
# HIGH 2 768x1024 # HIGH 2 768x1024
2E2303032802131303003C000004500014001E001E040014E8002C006967 2E2303032802131303003C000004500014001E001E040014E8002C006967
wait 2 wait 2
# reload rlink2 # reload rlink2
1101 1101
exit

View File

@ -5,9 +5,14 @@ can500 # init can macro
1003 1003
# check if it is rlink2
exit_if_not F18A 6 4 FFFFFF 434150
# MID 1 480x800 # MID 1 480x800
2E230301F404080801E03C0000039D000A0005006E03200AD7022C006967 2E230301F404080801E03C0000039D000A0005006E03200AD7022C006967
wait 2 wait 2
# reload rlink2 # reload rlink2
1101 1101
exit

View File

@ -5,9 +5,14 @@ can500 # init can macro
1003 1003
# check if it is rlink2
exit_if_not F18A 6 4 FFFFFF 434150
# MID 2 480x800 # MID 2 480x800
2E2303020D02082301E03C000004200080000A007603200D05062C006967 2E2303020D02082301E03C000004200080000A007603200D05062C006967
wait 2 wait 2
# reload rlink2 # reload rlink2
1101 1101
exit

View File

@ -685,6 +685,145 @@ class DDTECU():
return hexval return hexval
def getParamExtr(self, parName, iValues, dValues ):
result = '\nTerminal command hint\n\n'
# get DataItem instance
if parName not in self.datas.keys():
return 'Error finding datas'
# get data
d = self.datas[parName]
# finding read request
rr = None
for r in self.requests.values():
if parName in r.ReceivedDI.keys() and r.SentBytes[:2] in ['21','22']:
rr = r
break
rcm = rr.SentBytes[:2]
lid = r.SentBytes[2:].upper()
if rcm == '21':
wcm = '3B' + lid
else:
wcm = '2E' + lid
# finding write request
wr = None
for r in self.requests.values():
if parName in r.SentDI.keys() and r.SentBytes.upper().startswith(wcm):
wr = r
break
if rr==None:
return "Didn't find command for DataRead"
if wr==None:
result += "Didn't find command for DataWrite\n\n"
rdi = rr.ReceivedDI[parName]
if wr!=None:
sdi = wr.SentDI[parName]
if rr.MinBytes != len(wr.SentBytes) / 2:
result += "Commands for DataRead and DataWrite have different length"
if rdi.FirstByte!=sdi.FirstByte or rdi.BitOffset!=sdi.BitOffset or rdi.Endian!=sdi.Endian:
result += "Data not in the same place in DataRead and DataWrite"
# get value
if d.Name in iValues.keys():
value = iValues[d.Name].get().strip()
elif d.Name in dValues.keys():
value = dValues[d.Name].get().strip()
else:
value = 0
value = self.getValueFromInput(d, value)
# prepare parameters for extraction
littleEndian = True if rdi.Endian == "Little" else False
sb = rdi.FirstByte - 1
bits = d.BitsCount
sbit = rdi.BitOffset
bytes = (bits + sbit - 1) / 8 + 1
if littleEndian:
lshift = sbit
else:
lshift = ((bytes + 1) * 8 - (bits + sbit)) % 8
# shift value on bit offset
try:
val = int(value, 16)
except:
return 'ERROR: Wrong HEX value in parametr (%s) : "%s"' % (d.Name, value)
val = (val & (2 ** bits - 1)) << lshift
value = hex(val)[2:]
# remove 'L'
if value[-1:].upper() == 'L':
value = value[:-1]
# add left zero if need
if len(value) % 2:
value = '0' + value
# check hex
if value.upper().startswith('0X'): value = value[2:]
value = value.zfill(bytes * 2).upper()
if not all(c in string.hexdigits for c in value) and len(value) == bytes * 2:
return 'ERROR: Wrong value in parametr:%s (it should have %d bytes)' % (d.Name, d.BytesCount)
mask = (2 ** bits - 1) << lshift
# remove '0x'
hmask = hex(mask)[2:].upper()
# remove 'L'
if hmask[-1:].upper() == 'L':
hmask = hmask[:-1]
hmask = hmask[-bytes * 2:].zfill(bytes * 2)
func_params = ' ' + lid + ' ' + str(rr.MinBytes) + ' ' + str(rdi.FirstByte) + ' ' + hmask + ' ' + value + '\n'
for f in ['exit_if','exit_if_not']:
result += (f + func_params)
if wr!=None:
for f in ['set_bits', 'xor_bits']:
result += (f + func_params)
return result
def getValueFromInput(self, d, value ):
# list
if len(d.List.keys()) and ':' in value:
value = value.split(':')[0]
# scaled
if d.Scaled:
# if there is units then remove them
if ' ' in value:
value = value.split(' ')[0]
# check 0x
if value.upper().startswith('0X'):
value = value[2:]
else: # calculate reverse formula
if not all((c in string.digits or c == '.' or c == ',' or c == '-' or c == 'e' or c == 'E') for c in value):
return 'ERROR: Wrong value in parametr:%s (it should have %d bytes), be decimal or starts with 0x for hex' % (
d.Name, d.BytesCount)
flv = (float(value) * float(d.DivideBy) - float(d.Offset)) / float(d.Step)
value = hex(int(flv))
# ascii
if d.BytesASCII:
hst = ''
if len(value)<(d.BitsCount/8):
value += ' '*(d.BitsCount/8 - len(value))
for c in value:
hst = hst + hex(ord(c))[2:].zfill(2)
value = hst
return value
def packValues( self, requestName, iValues ): def packValues( self, requestName, iValues ):
''' pack values from iValues to command ''' ''' pack values from iValues to command '''
''' return string ''' ''' return string '''
@ -709,31 +848,32 @@ class DDTECU():
#get value #get value
value = iValues[d.Name].get().strip() value = iValues[d.Name].get().strip()
value = self.getValueFromInput( d, value )
# list ## list
if len(d.List.keys()) and ':' in value: #if len(d.List.keys()) and ':' in value:
value = value.split(':')[0] # value = value.split(':')[0]
#
# scaled ## scaled
if d.Scaled: #if d.Scaled:
#if there is units then remove them # #if there is units then remove them
if ' ' in value: # if ' ' in value:
value = value.split(' ')[0] # value = value.split(' ')[0]
#check 0x # #check 0x
if value.upper().startswith('0X'): # if value.upper().startswith('0X'):
value = value[2:] # value = value[2:]
else: #calculate reverse formula # else: #calculate reverse formula
if not all((c in string.digits or c=='.' or c==',' or c=='-' or c=='e' or c=='E') for c in value): # if not all((c in string.digits or c=='.' or c==',' or c=='-' or c=='e' or c=='E') for c in value):
return 'ERROR: Wrong value in parametr:%s (it should have %d bytes), be decimal or starts with 0x for hex' % (d.Name, d.BytesCount) # return 'ERROR: Wrong value in parametr:%s (it should have %d bytes), be decimal or starts with 0x for hex' % (d.Name, d.BytesCount)
flv = (float( value )*float(d.DivideBy) - float(d.Offset))/float(d.Step) # flv = (float( value )*float(d.DivideBy) - float(d.Offset))/float(d.Step)
value = hex(int(flv)) # value = hex(int(flv))
#
# ascii ## ascii
if d.BytesASCII: #if d.BytesASCII:
hst = '' # hst = ''
for c in value: # for c in value:
hst = hst + hex(ord(c))[2:].zfill(2) # hst = hst + hex(ord(c))[2:].zfill(2)
value = hst # value = hst
#prepare parameters for extraction #prepare parameters for extraction
littleEndian = True if sdi.Endian=="Little" else False littleEndian = True if sdi.Endian=="Little" else False

View File

@ -855,13 +855,16 @@ class DDTScreen (tk.Frame):
else: else:
closest = self.tObj[self.ddt.find_closest (event.x, event.y)[0]] closest = self.tObj[self.ddt.find_closest (event.x, event.y)[0]]
p = self.decu.getParamExtr(closest, self.iValue, self.dValue )
d = str (self.decu.datas[closest]) d = str (self.decu.datas[closest])
r = '' r = ''
if closest in self.decu.req4data.keys () and \ if closest in self.decu.req4data.keys () and \
self.decu.req4data[closest] in self.decu.requests.keys (): self.decu.req4data[closest] in self.decu.requests.keys ():
r = str (self.decu.requests[self.decu.req4data[closest]]) r = str (self.decu.requests[self.decu.req4data[closest]])
xText = d + '\n' + '*' * 50 + '\n' + r
xText = d + '\n' + '*' * 50 + '\n' + r + '\n' + '*' * 50 + '\n' + p
dialog = InfoDialog (self.root, xText) dialog = InfoDialog (self.root, xText)
self.root.wait_window (dialog.top) self.root.wait_window (dialog.top)

View File

@ -1143,8 +1143,12 @@ class ELM:
def send_can(self, command): def send_can(self, command):
command = command.strip ().replace (' ', '').upper () command = command.strip ().replace (' ', '').upper ()
if len (command) % 2 != 0 or len (command) == 0: return "ODD ERROR" if len(command) == 0:
if not all (c in string.hexdigits for c in command): return "HEX ERROR" return
if len (command) % 2 != 0:
return "ODD ERROR"
if not all (c in string.hexdigits for c in command):
return "HEX ERROR"
# do framing # do framing
raw_command = [] raw_command = []
@ -1260,8 +1264,12 @@ class ELM:
command = command.strip().replace(' ', '').upper() command = command.strip().replace(' ', '').upper()
if len(command) % 2 != 0 or len(command) == 0: return "ODD ERROR" if len(command) == 0:
if not all(c in string.hexdigits for c in command): return "HEX ERROR" return
if len(command) % 2 != 0:
return "ODD ERROR"
if not all(c in string.hexdigits for c in command):
return "HEX ERROR"
# do framing # do framing
raw_command = [] raw_command = []
@ -1454,8 +1462,12 @@ class ELM:
command = command.strip ().replace (' ', '').upper () command = command.strip ().replace (' ', '').upper ()
if len (command) % 2 != 0 or len (command) == 0: return "ODD ERROR" if len(command) == 0:
if not all (c in string.hexdigits for c in command): return "HEX ERROR" return
if len (command) % 2 != 0:
return "ODD ERROR"
if not all (c in string.hexdigits for c in command):
return "HEX ERROR"
# do framing # do framing
raw_command = [] raw_command = []

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys, os, re import sys, os, re
import string
import time import time
import mod_globals import mod_globals
import mod_elm import mod_elm
@ -15,6 +16,7 @@ os.chdir (os.path.dirname (os.path.realpath (sys.argv[0])))
macro = {} macro = {}
var = {} var = {}
cmd_delay = 0
stack = [] stack = []
auto_macro = "" auto_macro = ""
@ -63,7 +65,6 @@ if mod_globals.os != 'android':
print "\t\t>sudo easy_install pyserial" print "\t\t>sudo easy_install pyserial"
sys.exit() sys.exit()
def init_macro(): def init_macro():
global macro global macro
macro = {} macro = {}
@ -147,50 +148,6 @@ def load_macro( mf='' ):
else: else:
pars_macro(mf) pars_macro(mf)
def play_macro( mname, elm ):
global macro
global var
global stack
if mname in stack:
print 'Error: recursion prohibited:', mname
return
else:
stack.append(mname)
for l in macro[mname]:
#find veriable definition
m = re.search('\$\S+\s*=\s*\S+', l)
if m:
r = m.group(0).replace(' ', '').replace('\t', '')
rl = r.split('=')
var[rl[0]]=rl[1]
if rl[0]=='$addr':
if var['$addr'].upper() in mod_elm.dnat.keys():
var['$txa'] = mod_elm.dnat[var['$addr'].upper()]
var['$rxa'] = mod_elm.snat[var['$addr'].upper()]
elm.currentaddress = var['$addr'].upper()
continue
#find veriable usage
m = re.search('\$\S+', l)
while m:
vu = m.group(0)
if vu in var.keys():
l = re.sub("\\"+vu,var[vu], l)
else:
print 'Error: unknown variable',vu,'in',mname
return
m = re.search('\$\S+', l)
if l in macro.keys():
play_macro( l, elm )
continue
print elm.cmd(l)
stack.remove(mname)
def print_help(): def print_help():
""" """
[h]elp - this help [h]elp - this help
@ -211,7 +168,6 @@ def print_help():
print ' '+m print ' '+m
print print
def optParser(): def optParser():
'''Parsing of command line parameters. User should define at least com port name''' '''Parsing of command line parameters. User should define at least com port name'''
@ -299,7 +255,6 @@ def optParser():
mod_globals.opt_n1c = options.n1c mod_globals.opt_n1c = options.n1c
auto_dia = options.dia auto_dia = options.dia
class FileChooser(): class FileChooser():
lay = '''<?xml version="1.0" encoding="utf-8"?> lay = '''<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
@ -444,6 +399,217 @@ class FileChooser():
finally: finally:
self.droid.fullDismiss() self.droid.fullDismiss()
def play_macro(mname, elm):
global macro
global var
global stack
if mname in stack:
print 'Error: recursion prohibited:', mname
return
else:
stack.append(mname)
for l in macro[mname]:
if l in macro.keys():
play_macro(l, elm)
continue
proc_line( l, elm )
stack.remove(mname)
def bit_cmd( l, elm, fnc='set_bits' ):
error_msg = '''ERROR: command should have 5 parameters: <lid> <rsp_len> <offset> <hex mask> <hex value>"
<lid> - ECUs local identifier. Length should be 2 simbols for KWP or 4 for CAN
<rsp_len> - lengt of command response including positive response bytes, equals MinBytes from ddt db
<offset> - offeset in bytes to first changed byte (starts from 1 not 0)
<hex mask> - bit mask for changed bits, 1 - changable, 0 - untachable
<hex value> - bit value
<hex mask> and <hex value> should have equal length
'''
if fnc not in ['set_bits','xor_bits','exit_if','exit_if_not']:
print "\nERROR: Unknown function\n"
return
par = l.strip().split(' ')
if len(par)!=5:
print error_msg
return
try:
lid = par[0].strip()
lng = int(par[1].strip())
off = int(par[2].strip())-1
mask = par[3].strip()
val = par[4].strip()
except:
print error_msg
return
if len(lid) not in [2,4] or (len(mask)!=len(val)) or off<0 or off>lng:
print error_msg
return
if len(lid)==2: #KWP
rcmd = '21'+lid
else: #CAN
rcmd = '22' + lid
rsp = elm.cmd(rcmd)
rsp = rsp.replace(' ','')[:lng*2].upper()
print "read value:",rsp
if len(rsp) != lng * 2:
print '\nERROR: Length is unexpected\n'
return
if not all(c in string.hexdigits for c in rsp):
print '\nERROR: Wrong simbol in response\n'
return
pos_rsp = ('6'+rcmd[1:]).upper()
if not rsp.startswith(pos_rsp):
print '\nERROR: Not positive response\n'
return
diff = 0
i = 0
while i<len(mask)/2:
c_by = int(rsp[(off+i)*2:(off+i)*2+2],16)
c_ma = int(mask[i*2:i*2+2],16)
c_va = int(val[i*2:i*2+2],16)
if fnc == 'xor_bits':
n_by = c_by ^ (c_va & c_ma)
elif fnc == 'set_bits':
n_by = (c_by & ~c_ma) | c_va
else:
if (c_by & c_ma) != (c_va & c_ma):
diff += 1
i += 1
continue
str_n_by = hex(n_by & 0xFF).upper()[2:].zfill(2)
n_rsp = rsp[0:(off+i)*2] + str_n_by + rsp[(off+i+1)*2:]
rsp = n_rsp
i += 1
if fnc == 'exit_if':
if diff==0:
print "\n Match. Exit \n"
sys.exit()
else:
print "\n Not match. Continue \n"
return
if fnc == 'exit_if_not':
if diff!=0:
print "\n Not match. Exit \n"
sys.exit()
else:
print "\n Match. Continue \n"
return
if rsp[:2]=='61':
wcmd = '3B'+rsp[2:]
elif rsp[:2]=='62':
wcmd = '2E'+rsp[2:]
print "write value:", wcmd
print elm.cmd(wcmd)
def proc_line( l, elm ):
global macro
global var
global cmd_delay
if '#' in l:
l = l.split('#')[0]
l = l.strip()
if len(l) == 0:
print
return
if l in ['q', 'quit', 'e', 'exit', 'end']:
sys.exit()
if l in ['h', 'help', '?']:
print_help()
return
if l in macro.keys():
play_macro(l, elm)
return
m = re.search('\$\S+\s*=\s*\S+', l)
if m:
# find variable definition
r = m.group(0).replace(' ', '').replace('\t', '')
rl = r.split('=')
var[rl[0]] = rl[1]
if rl[0] == '$addr':
if var['$addr'].upper() in mod_elm.dnat.keys():
var['$txa'] = mod_elm.dnat[var['$addr'].upper()]
var['$rxa'] = mod_elm.snat[var['$addr'].upper()]
elm.currentaddress = var['$addr'].upper()
return
# find veriable usage
m = re.search('\$\S+', l)
while m:
vu = m.group(0)
if vu in var.keys():
l = re.sub("\\" + vu, var[vu], l)
else:
print 'Error: unknown variable', vu, 'in', mname
return
m = re.search('\$\S+', l)
l_parts = l.split()
if len(l_parts) > 0 and l_parts[0] in ['wait', 'sleep']:
try:
time.sleep(int(l_parts[1]))
return
except:
pass
if len(l_parts) > 0 and l_parts[0] in ['delay']:
cmd_delay = int(l_parts[1])
return
if l.lower().startswith('set_bits'):
bit_cmd( l.lower()[8:], elm, fnc='set_bits' )
return
if l.lower().startswith('xor_bits'):
bit_cmd( l.lower()[8:], elm, fnc='xor_bits' )
return
if l.lower().startswith('exit_if_not'):
bit_cmd( l.lower()[11:], elm, fnc='exit_if_not' )
return
if l.lower().startswith('exit_if'):
bit_cmd( l.lower()[7:], elm, fnc='exit_if' )
return
print elm.cmd(l)
if cmd_delay>0:
print '# delay:', cmd_delay
time.sleep(cmd_delay)
def main(): def main():
@ -463,7 +629,7 @@ def main():
#debug #debug
#mod_globals.opt_demo = True #mod_globals.opt_demo = True
# disable CAN auto-formatting # disable auto flow control
mod_globals.opt_cfc0 = True mod_globals.opt_cfc0 = True
print 'Opening ELM' print 'Opening ELM'
@ -476,6 +642,8 @@ def main():
if auto_dia: if auto_dia:
fname = FileChooser().choose() fname = FileChooser().choose()
#debug
#fname = './macro/test/test.cmd'
if len(fname)>0: if len(fname)>0:
f = open(fname, 'rt') f = open(fname, 'rt')
cmd_lines = f.readlines() cmd_lines = f.readlines()
@ -497,50 +665,11 @@ def main():
l = cmd_lines[cmd_ref].strip() l = cmd_lines[cmd_ref].strip()
cmd_ref += 1 cmd_ref += 1
else: else:
l = "exit" cmd_lines = []
l = "# end of command file"
print l print l
if '#' in l: proc_line( l, elm )
l = l.split('#')[0]
l = l.strip()
if len(l)==0:
continue
if l in ['q', 'quit', 'e', 'exit', 'end']:
break
if l in ['h', 'help', '?']:
print_help ()
continue
l_parts = l.split()
if len(l_parts)>0 and l_parts[0] in ['wait','sleep']:
try:
time.sleep(int(l_parts[1]))
continue
except:
pass
if l in macro.keys():
play_macro( l, elm )
continue
m = re.search('\$\S+\s*=\s*\S+', l)
if m:
# variable definition
r = m.group(0).replace(' ', '').replace('\t', '')
rl = r.split('=')
var[rl[0]]=rl[1]
if rl[0]=='$addr':
if var['$addr'].upper() in mod_elm.dnat.keys():
var['$txa'] = mod_elm.dnat[var['$addr'].upper()]
var['$rxa'] = mod_elm.snat[var['$addr'].upper()]
elm.currentaddress = var['$addr'].upper()
continue
print elm.cmd(l)
if __name__ == '__main__': if __name__ == '__main__':
main() main()