Merge branch 'pyren3' of https://gitlab.com/py_ren/pyren into pyren3

This commit is contained in:
Marianpol 2023-01-07 12:15:07 +01:00
commit a203c0558d
5 changed files with 157 additions and 31 deletions

70
main.py
View File

@ -6,7 +6,7 @@
################################## ##################################
# # # #
# # # #
# Version: 3.0 (1-Aug-2022) # # Version: 3.1 (2-Jan-2023) #
# Author: Shr-Lnm # # Author: Shr-Lnm #
# # # #
# # # #
@ -16,7 +16,7 @@ __author__ = "Shr-Lnm"
__copyright__ = "Copyright 2018-2022" __copyright__ = "Copyright 2018-2022"
__credits__ = [] __credits__ = []
# __license__ = "GNU" # Unknown licence! # __license__ = "GNU" # Unknown licence!
__version__ = "3.0.0" # python3 maybe ? __version__ = "3.1.0" # python3 maybe ?
__maintainer__ = "Shr-Lnm" __maintainer__ = "Shr-Lnm"
__email__ = "mshkn@inbox.ru" __email__ = "mshkn@inbox.ru"
__status__ = "Beta" __status__ = "Beta"
@ -26,6 +26,7 @@ import shutil
from os import listdir from os import listdir
from os.path import isdir from os.path import isdir
from os.path import isfile from os.path import isfile
import re
import sys import sys
try: try:
@ -244,9 +245,17 @@ def run(s, cmd):
cmdr = __import__('mod_ddt') cmdr = __import__('mod_ddt')
elif cmd == 'term': elif cmd == 'term':
cmdr = __import__('mod_term') cmdr = __import__('mod_term')
elif cmd == 'pids':
cmdr = __import__('mod_ecu')
if s.port.upper() == 'BT' or s.port == '':
s.port = 'bt'
if s.port.upper().endswith(';BT'):
s.port = s.port.split(';')[0]
if s.port.lower() == 'bt' or s.port == '': s.port = 'bt'
sys.argv.append('-p' + s.port) sys.argv.append('-p' + s.port)
if cmd == 'demo': if cmd == 'demo':
sys.argv.append('--demo') sys.argv.append('--demo')
if cmd == 'scan' and cmd != 'term': if cmd == 'scan' and cmd != 'term':
@ -903,6 +912,11 @@ else:
self.droid.fullDismiss() self.droid.fullDismiss()
run(self.save, 'term') run(self.save, 'term')
def cmd_PIDs(self):
self.saveSettings()
self.droid.fullDismiss()
run(self.save, 'pids')
def cmd_Update(self): def cmd_Update(self):
res = update_from_gitlab() res = update_from_gitlab()
if res == 0: if res == 0:
@ -918,9 +932,17 @@ else:
self.save.csvOption = self.csvl[int(self.droid.fullQueryDetail("sp_csv").result['selectedItemPosition'])] self.save.csvOption = self.csvl[int(self.droid.fullQueryDetail("sp_csv").result['selectedItemPosition'])]
if self.droid.fullQueryDetail("rb_bt").result['checked'] == 'false': if self.droid.fullQueryDetail("rb_bt").result['checked'] == 'false':
self.save.port = self.droid.fullQueryDetail("in_wifi").result['text'] self.save.port = '192.168.0.10:3500'
else: else:
self.save.port = 'BT' portName = self.dev_list[int(self.droid.fullQueryDetail("in_wifi").result['selectedItemPosition'])]
upPortName = portName.upper().split(';')[0]
MAC = ''
if re.match (r"^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$", upPortName) or \
re.match (r"^[0-9A-F]{4}.[0-9A-F]{4}.[0-9A-F]{4}$", upPortName) or \
re.match (r"^[0-9A-F]{12}$", upPortName):
upPortName = upPortName.replace(':','').replace('.','')
MAC = ':'.join (a + b for a, b in zip (upPortName[::2], upPortName[1::2]))
self.save.port = MAC + ';' + 'BT'
self.save.speed = '38400' self.save.speed = '38400'
@ -983,15 +1005,23 @@ else:
self.csvl = csvl self.csvl = csvl
if self.save.port == '': if self.save.port == '':
self.save.port = "192.168.0.10:35000" self.save.port = "192.168.0.10:35000;WiFi"
if self.save.port.lower() == 'bt': self.dev_list.append(self.save.port)
if self.save.port.upper().endswith('BT'):
MAC = ""
if ';' in self.save.port:
MAC = self.save.port.split(';')[0]
for d in self.dev_list:
if MAC in d:
self.dev_list.insert(0, self.dev_list.pop(self.dev_list.index(d)))
self.droid.fullSetProperty("rb_bt", "checked", "true") self.droid.fullSetProperty("rb_bt", "checked", "true")
self.droid.fullSetProperty("rb_wifi", "checked", "false") self.droid.fullSetProperty("rb_wifi", "checked", "false")
self.droid.fullSetProperty("in_wifi", "text", "192.168.0.10:35000") self.droid.fullSetList("in_wifi", self.dev_list)
else: else:
self.droid.fullSetProperty("rb_bt", "checked", "false") self.droid.fullSetProperty("rb_bt", "checked", "false")
self.droid.fullSetProperty("rb_wifi", "checked", "true") self.droid.fullSetProperty("rb_wifi", "checked", "true")
self.droid.fullSetProperty("in_wifi", "text", self.save.port) self.droid.fullSetList("in_wifi", self.dev_list)
self.droid.fullSetProperty("in_logname", "text", self.save.logName) self.droid.fullSetProperty("in_logname", "text", self.save.logName)
if self.save.log: if self.save.log:
@ -1096,16 +1126,14 @@ else:
android:checked="false" android:checked="false"
android:text="WiFi" /> android:text="WiFi" />
</RadioGroup> </RadioGroup>
<EditText <Spinner
android:id="@+id/in_wifi" android:id="@+id/in_wifi"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_below="@id/tx_elm" android:layout_below="@id/tx_elm"
android:layout_toRightOf="@id/radioGroup" android:layout_toRightOf="@id/radioGroup"
android:layout_marginLeft="20dp" android:layout_marginLeft="20dp" />
android:ems="10"
android:text="192.168.0.10:35000" />
<TextView <TextView
android:id="@+id/tx_log" android:id="@+id/tx_log"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -1256,6 +1284,13 @@ else:
android:layout_below="@id/bt_start" android:layout_below="@id/bt_start"
android:layout_toLeftOf="@+id/bt_mon" android:layout_toLeftOf="@+id/bt_mon"
android:text="Macro" /> android:text="Macro" />
<Button
android:id="@+id/bt_pids"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/bt_start"
android:layout_toLeftOf="@+id/bt_term"
android:text="PIDs" />
<Button <Button
android:id="@+id/bt_update" android:id="@+id/bt_update"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -1287,6 +1322,8 @@ else:
self.cmd_Mon() self.cmd_Mon()
elif id == "bt_term": elif id == "bt_term":
self.cmd_Term() self.cmd_Term()
elif id == "bt_pids":
self.cmd_PIDs()
elif id == "bt_update": elif id == "bt_update":
self.cmd_Update() self.cmd_Update()
@ -1295,6 +1332,13 @@ else:
try: try:
self.droid = android.Android() self.droid = android.Android()
self.droid.fullShow(self.lay) self.droid.fullShow(self.lay)
self.dev_list = ['192.168.0.10:35000;WiFi']
try:
tmp = self.droid.bluetoothGetBondedDevices().result
for i in range(0, len(tmp), 2):
self.dev_list.append( tmp[i]+';'+tmp[i+1])
except:
pass
self.loadSettings() self.loadSettings()
self.eventloop() self.eventloop()
finally: finally:

View File

@ -107,6 +107,8 @@ def acf_MTC_generateDefaults( m, mtc ):
if ddtxml.upper().endswith('.XML'): if ddtxml.upper().endswith('.XML'):
ddtxml = ddtxml[:-4] ddtxml = ddtxml[:-4]
ddtxml = ddtxml.replace('\\', '_')
if m['ecuname']=='': if m['ecuname']=='':
m['ecuname'] = m['dst'] m['ecuname'] = m['dst']

View File

@ -237,7 +237,7 @@ class DDTECU():
''' 0 1 2 3 4 5 6 7 ''' ''' 0 1 2 3 4 5 6 7 '''
''' 01234567890123456789012345678901234567890123456789012345678901234567890123456''' ''' 01234567890123456789012345678901234567890123456789012345678901234567890123456'''
#IdRsp = '61 80 34 36 33 32 52 45 34 42 45 30 30 33 37 52 00 83 9D 00 1A 90 01 01 00 88 AA' #IdRsp = '61 80 82 00 41 86 46 04 41 46 4A 82 00 41 86 46 D1 00 30 00 00 48 00 05 09 05'
''' -- -------- ----- ----- ''' ''' -- -------- ----- ----- '''
''' DiagVersion--+ | | +--Version ''' ''' DiagVersion--+ | | +--Version '''
''' Supplier--+ +--Soft ''' ''' Supplier--+ +--Soft '''
@ -297,6 +297,8 @@ class DDTECU():
fname = mod_globals.opt_ddtxml fname = mod_globals.opt_ddtxml
self.ecufname = mod_globals.ddtroot+'/ecus/'+fname self.ecufname = mod_globals.ddtroot+'/ecus/'+fname
else: else:
#vehTypeCode = 'x81'
#Address = '0D'
problist = ecuSearch(vehTypeCode, Address, DiagVersion, Supplier, Soft, Version, eculist) problist = ecuSearch(vehTypeCode, Address, DiagVersion, Supplier, Soft, Version, eculist)
while 1: while 1:
@ -1130,6 +1132,52 @@ def minDist(a, b):
return d return d
def distance( a, b ):
""" calculate distance between strings """
""" normalized to length of string """
""" a - readen value """
""" b - pattern from eculist """
d = 0
# align length
if len( a ) < len( b ):
a = a + ' ' * ( len( b ) - len( a ))
else:
b = b + ' ' * ( len( a ) - len( b ))
# humming distance
l = len(a)
for i in range(0, l):
if b[i] != '?' and ord(a[i]) != ord(b[i]):
d = d + 1
# normalize to length of string
if d:
d = d / l
return d
def AutoIdents_distance( DiagVersion, Supplier, Soft, Version, ai ):
#normalize supplier in such cases
#DiagVersion="12" Supplier="746" Soft="2470" Version="A600"
#DiagVersion="12" Supplier="39324d" Soft="0052" Version="0400"
try:
if len( ai['Supplier'] ) == 6 and \
len( ai['Soft'] ) == 4 and \
len( ai['Version'] ) == 4:
ai['Supplier'] = bytes.fromhex(ai['Supplier']).decode('utf-8')
except:
#catch not hex supplier with len 6
pass
d = distance( DiagVersion, ai['DiagVersion']) * 0.25
d = d + distance( Supplier, ai['Supplier']) * 0.25
d = d + distance( Soft, ai['Soft']) * 0.25
d = d + distance( Version, ai['Version']) * 0.25
return round( d, 4 )
def ecuSearch(vehTypeCode, Address, DiagVersion, Supplier, Soft, Version, el, interactive = True): def ecuSearch(vehTypeCode, Address, DiagVersion, Supplier, Soft, Version, el, interactive = True):
@ -1148,13 +1196,14 @@ def ecuSearch(vehTypeCode, Address, DiagVersion, Supplier, Soft, Version, el, in
for k in list(t.keys()): for k in list(t.keys()):
for ai in t[k]['AutoIdents']: for ai in t[k]['AutoIdents']:
dist = 0 #dist = 0
dist = dist + minDist(DiagVersion, ai['DiagVersion']) * 1000 # weight #dist = dist + minDist(DiagVersion, ai['DiagVersion']) * 1000 # weight
dist = dist + minDist(Supplier, ai['Supplier']) * 1 # weight #dist = dist + minDist(Supplier, ai['Supplier']) * 1 # weight
dist = dist + minDist(Soft, ai['Soft']) * 1 # weight #dist = dist + minDist(Soft, ai['Soft']) * 1 # weight
dist = dist + minDist(Version, ai['Version']) * 1 # weight #dist = dist + minDist(Version, ai['Version']) * 1 # weight
dist = AutoIdents_distance( DiagVersion, Supplier, Soft, Version, ai )
if vehTypeCode in t[k]['Projects'] or dist == 0: if vehTypeCode.upper() in t[k]['Projects'] or dist == 0:
if k not in list(cand.keys()): cand[k] = 0xFFFFFFFF if k not in list(cand.keys()): cand[k] = 0xFFFFFFFF
if dist < cand[k]: cand[k] = dist if dist < cand[k]: cand[k] = dist
if dist < min: min = dist if dist < min: min = dist

View File

@ -1275,6 +1275,7 @@ def main():
ecuid = input('Enetr ECU ID:') ecuid = input('Enetr ECU ID:')
lanid = input('Language [RU]:') lanid = input('Language [RU]:')
if len(lanid)<2: lanid = 'RU' if len(lanid)<2: lanid = 'RU'
sys.argv = sys.argv[:1]
sys.argv.append(ecuid) sys.argv.append(ecuid)
sys.argv.append(lanid) sys.argv.append(lanid)
sys.argv.append('TORQ') sys.argv.append('TORQ')
@ -1386,8 +1387,11 @@ def main():
ddd = '82'+F2A[family]+'F1' ddd = '82'+F2A[family]+'F1'
filename = "PR_"+F2A[family]+"_"+eindex+"_"+sys.argv[2]+".csv" filename = "PR_"+F2A[family]+"_"+eindex+"_"+sys.argv[2]+".csv"
if mod_globals.os=='android' and os.path.exists('/sdcard/.torque/extendedpids'): ext_path = '/storage/emulated/0/.torque/extendedpids/'
filename = '/sdcard/.torque/extendedpids/'+filename if mod_globals.os=='android':
if not os.path.exists(ext_path):
os.makedirs( ext_path, exist_ok=True )
filename = ext_path+filename
cf = open( filename, "w") cf = open( filename, "w")
@ -1496,8 +1500,11 @@ def main():
# make profile for torque # make profile for torque
profilename = str(int(time.time()))+'.tdv' profilename = str(int(time.time()))+'.tdv'
if mod_globals.os=='android' and os.path.exists('/sdcard/.torque/vehicles'): veh_path = '/storage/emulated/0/.torque/vehicles/'
profilename = '/sdcard/.torque/vehicles/'+str(int(time.time()))+'.tdv' if mod_globals.os=='android':
if not os.path.exists(veh_path):
os.makedirs( veh_path, exist_ok=True )
profilename = veh_path+str(int(time.time()))+'.tdv'
prn = open( profilename, "w") prn = open( profilename, "w")
prn.write( '#This is an ECU profile generated by pyren\n' ) prn.write( '#This is an ECU profile generated by pyren\n' )

View File

@ -158,9 +158,17 @@ class Port:
self.portTimeout = portTimeout self.portTimeout = portTimeout
portName = portName.strip () portName = portName.strip()
if re.match (r"^[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}$", portName): MAC = None
upPortName = portName.upper()
if re.match (r"^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$", upPortName) or \
re.match (r"^[0-9A-F]{4}.[0-9A-F]{4}.[0-9A-F]{4}$", upPortName) or \
re.match (r"^[0-9A-F]{12}$", upPortName):
upPortName = upPortName.replace(':','').replace('.','')
MAC = ':'.join (a + b for a, b in zip (upPortName[::2], upPortName[1::2]))
if mod_globals.os != 'android' and MAC:
try: try:
self.macaddr = portName self.macaddr = portName
self.channel = 1 self.channel = 1
@ -187,16 +195,22 @@ class Port:
print(" \n\nERROR: Can't connect to WiFi ELM\n\n") print(" \n\nERROR: Can't connect to WiFi ELM\n\n")
mod_globals.opt_demo = True mod_globals.opt_demo = True
sys.exit() sys.exit()
elif mod_globals.os == 'android' and portName == 'bt': elif mod_globals.os == 'android' and ( portName == 'bt' or MAC != None ):
self.portType = 2 self.portType = 2
self.droid = android.Android () self.droid = android.Android ()
self.droid.toggleBluetoothState (True) if self.droid:
print('SL4A loaded')
print( 'BT is enabled:', self.droid.toggleBluetoothState (True).result)
print( 'BT discovery canceled:', self.droid.bluetoothDiscoveryCancel().result)
retry = 0 retry = 0
while 1: while 1:
time.sleep(1) time.sleep(1)
retry = retry + 1 retry = retry + 1
try: try:
self.btcid = self.droid.bluetoothConnect ('00001101-0000-1000-8000-00805F9B34FB').result if MAC == None:
self.btcid = self.droid.bluetoothConnect ('00001101-0000-1000-8000-00805F9B34FB').result
else:
self.btcid = self.droid.bluetoothConnect (uuid='00001101-0000-1000-8000-00805F9B34FB', address=MAC).result
except: except:
pass pass
print( 'Try ',retry, ":", self.btcid ) print( 'Try ',retry, ":", self.btcid )
@ -1327,6 +1341,8 @@ class ELM:
self.l1_cache[command] = str(hex(nframes))[2:].upper() self.l1_cache[command] = str(hex(nframes))[2:].upper()
if len (result) // 2 >= nbytes and noerrors: if len (result) // 2 >= nbytes and noerrors:
# trim padding
result = result[:nbytes*2]
# split by bytes and return # split by bytes and return
result = ' '.join (a + b for a, b in zip (result[::2], result[1::2])) result = ' '.join (a + b for a, b in zip (result[::2], result[1::2]))
return result return result
@ -1540,11 +1556,13 @@ class ELM:
if responses[0][:1] == '0': # single frame (sf) if responses[0][:1] == '0': # single frame (sf)
nBytes = int(responses[0][1:2], 16) nBytes = int(responses[0][1:2], 16)
rspLen = nBytes
nFrames = 1 nFrames = 1
result = responses[0][2:2 + nBytes * 2] result = responses[0][2:2 + nBytes * 2]
elif responses[0][:1] == '1': # first frame (ff) elif responses[0][:1] == '1': # first frame (ff)
nBytes = int(responses[0][1:4], 16) nBytes = int(responses[0][1:4], 16)
rspLen = nBytes
nBytes = nBytes - 6 # we assume that it should be more then 7 nBytes = nBytes - 6 # we assume that it should be more then 7
nFrames = 1 + nBytes // 7 + bool(nBytes % 7) nFrames = 1 + nBytes // 7 + bool(nBytes % 7)
cFrame = 1 cFrame = 1
@ -1592,6 +1610,8 @@ class ELM:
self.l1_cache[init_command] = str(nFrames) self.l1_cache[init_command] = str(nFrames)
if noerrors and len(result) // 2 >= nBytes: if noerrors and len(result) // 2 >= nBytes:
# trim padding
result = result[:rspLen*2]
# split by bytes and return # split by bytes and return
result = ' '.join(a + b for a, b in zip(result[::2], result[1::2])) result = ' '.join(a + b for a, b in zip(result[::2], result[1::2]))
return result return result
@ -1758,11 +1778,13 @@ class ELM:
if responses[0][:1] == '0': # single frame (sf) if responses[0][:1] == '0': # single frame (sf)
nBytes = int (responses[0][1:2], 16) nBytes = int (responses[0][1:2], 16)
rspLen = nBytes
nFrames = 1 nFrames = 1
result = responses[0][2:2 + nBytes * 2] result = responses[0][2:2 + nBytes * 2]
elif responses[0][:1] == '1': # first frame (ff) elif responses[0][:1] == '1': # first frame (ff)
nBytes = int (responses[0][1:4], 16) nBytes = int (responses[0][1:4], 16)
rspLen = nBytes
nBytes = nBytes - 6 # we assume that it should be more then 7 nBytes = nBytes - 6 # we assume that it should be more then 7
nFrames = 1 + nBytes//7 + bool(nBytes%7) nFrames = 1 + nBytes//7 + bool(nBytes%7)
cFrame = 1 cFrame = 1
@ -1811,6 +1833,8 @@ class ELM:
noErrors = False noErrors = False
if len (result) // 2 >= nBytes and noErrors and result[:2] != '7F': if len (result) // 2 >= nBytes and noErrors and result[:2] != '7F':
# trim padding
result = result[:rspLen*2]
# split by bytes and return # split by bytes and return
result = ' '.join (a + b for a, b in zip (result[::2], result[1::2])) result = ' '.join (a + b for a, b in zip (result[::2], result[1::2]))
return result return result