#!/usr/bin/env python3 import sys, os, re import string import time import mod_globals import mod_elm import mod_utils try: import readline except: pass os.chdir (os.path.dirname (os.path.realpath (sys.argv[0]))) macro = {} var = {} cmd_delay = 0 stack = [] auto_macro = "" auto_dia = False debug_mode = False key_pressed = '' mod_globals.os = os.name if mod_globals.os == 'nt': import pip try: import serial except ImportError: pip.main(['install', 'pyserial']) try: import colorama except ImportError: pip.main(['install', 'colorama']) try: import colorama except ImportError: print("\n\n\n\t\t\tGive me access to the Internet for download modules\n\n\n") sys.exit() colorama.init() else: # let's try android try: import androidhelper as android mod_globals.os = 'android' except: try: import android mod_globals.os = 'android' except: pass if mod_globals.os != 'android': try: import serial from serial.tools import list_ports except ImportError: print("\n\n\n\tPleas install additional modules") print("\t\t>sudo easy_install pyserial") sys.exit() def init_macro(): global macro macro = {} def init_var(): global var var = {} #predefined variables var['$addr'] = '7A' var['$txa'] = '7E0' var['$rxa'] = '7E8' var['$prompt'] = 'ELM' def pars_macro( file ): global macro global var print('openning file:', file) f = open( file, 'rt' ) lines = f.readlines() f.close() macroname = '' macrostrings = [] line_num = 0 for l in lines: line_num += 1 l = l.split('#')[0] # remove comments l = l.strip() if l == '': continue if '{' in l: if macroname=='': literals = l.split('{') macroname = literals[0].strip() macroname = macroname.replace(' ', '_').replace('\t', '_') macrostrings = [] if len(literals)>1 and literals[1]!='' : macrostrings.append(literals[1]) continue else: print('Error: empty macro name in line:', line_num) macro = {} var = {} return if '}' in l: if macroname!='': literals = l.split('}') cmd = literals[0].strip() if cmd!='': macrostrings.append(cmd) macro[macroname] = macrostrings macroname = '' macrostrings = [] continue else: print('Error: unexpected end of macro in line:', line_num) macro = {} var = {} return m = re.search('\$\S+\s*=\s*\S+', l) if m and macroname=='': #variable definition r = m.group(0).replace(' ', '').replace('\t', '') rl = r.split('=') var[rl[0]]=rl[1] else: macrostrings.append(l) def load_macro( mf='' ): """ dynamically loaded macro should have .txt extension and placed in ./macro directory """ if mf=='' : for root, dirs, files in os.walk("./macro"): for mfile in files: if mfile.endswith('.txt'): full_path = os.path.join("./macro/", mfile) pars_macro(full_path) else: pars_macro(mf) def print_help(): """ [h]elp - this help [q]uit, [e]xit, end - exit from terminal wait|sleep x - wait x seconds """ global var global macro print(print_help.__doc__) print('Variables:') for v in list(var.keys()): print(' '+v+' = '+var[v]) print() print('Macros:') for m in list(macro.keys()): print(' '+m) print() def optParser(): '''Parsing of command line parameters. User should define at least com port name''' import argparse global auto_macro global auto_dia global debug_mode parser = argparse.ArgumentParser( description = "pyRen terminal" ) parser.add_argument('-p', help="ELM327 com port name", dest="port", default="") parser.add_argument("-r", help="com port rate during diagnostic session {38400[default],57600,115200,230400,500000}", dest="rate", default="38400",) parser.add_argument("-m", help="macro file name", dest="macro", default="",) parser.add_argument("--log", help="log file name", dest="logfile", default="") parser.add_argument("--demo", help="for debuging purpose. Work without car and ELM", dest="demo", default=False, action="store_true") parser.add_argument("--si", help="try SlowInit first", dest="si", default=False, action="store_true") parser.add_argument("--cfc", help="turn off automatic FC and do it by script", dest="cfc", default=False, action="store_true") parser.add_argument("--caf", help="turn on CAN Auto Formatting. Available only for OBDLink", dest="caf", default=True, action="store_true") parser.add_argument("--n1c", help="turn off L1 cache", dest="n1c", default=False, action="store_true") parser.add_argument("-vv", "--verbose", help="show verbose output (unused)", dest="verb", default=False, action="store_true") parser.add_argument("--dialog", help="show dialog for selecting macro", dest="dia", default=False, action="store_true") parser.add_argument("--debug", help="for debug purpose only", dest="dbg", default=False, action="store_true") parser.add_argument("--minordtc", help="use to show all DTCs without checking computation formula", dest="minordtc", default=False, action="store_true") options = parser.parse_args() if not options.port and mod_globals.os != 'android': parser.print_help() iterator = sorted(list(list_ports.comports())) print("") print("Available COM ports:") for port, desc, hwid in iterator: print("%-30s \n\tdesc: %s \n\thwid: %s" % (port,desc,hwid)) print("") exit(2) else: mod_globals.opt_port = options.port mod_globals.opt_rate = int(options.rate) mod_globals.opt_speed = int(options.rate) auto_macro = options.macro mod_globals.opt_log = options.logfile mod_globals.opt_demo = options.demo mod_globals.opt_si = options.si mod_globals.opt_cfc0 = options.cfc mod_globals.opt_caf = options.caf mod_globals.opt_n1c = options.n1c mod_globals.opt_minordtc = options.minordtc auto_dia = options.dia debug_mode = options.dbg class FileChooser(): lay = '''