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,7 +685,146 @@ class DDTECU():
return hexval return hexval
def packValues( self, requestName, iValues ): 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 ):
''' pack values from iValues to command ''' ''' pack values from iValues to command '''
''' return string ''' ''' return string '''
''' if cathe the error then return string begining with ERROR: word''' ''' if cathe the error then return string begining with ERROR: word'''
@ -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

@ -854,14 +854,17 @@ class DDTScreen (tk.Frame):
closest = tag closest = tag
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

@ -1142,9 +1142,13 @@ 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 = []
@ -1453,9 +1461,13 @@ class ELM:
def send_can_cfc0(self, command): def send_can_cfc0(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 = []

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
@ -210,7 +167,6 @@ def print_help():
for m in macro.keys(): for m in macro.keys():
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,53 +665,14 @@ 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()