pyren/pyren/mod_term.py
2018-10-27 08:03:05 +00:00

327 lines
7.7 KiB
Python
Executable File

#!/usr/bin/env python
import sys, os, re
import mod_globals
import mod_elm
try:
import readline
except:
pass
os.chdir (os.path.dirname (os.path.realpath (sys.argv[0])))
macro = {}
var = {}
stack = []
auto_macro = ""
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='' ):
"""
dynamicly loaded macro should have .txt extension and plased in ./macro directory
"""
if mf=='' :
for root, dirs, files in os.walk("./macro"):
for mfile in files:
full_path = os.path.join("./macro/", mfile)
pars_macro(full_path)
else:
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():
"""
[h]elp - this help
[q]uit, [e]xit, end - exit from terminal
"""
global var
global macro
print print_help.__doc__
print 'Variables:'
for v in var.keys():
print ' '+v+' = '+var[v]
print
print 'Macros:'
for m in 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
parser = argparse.ArgumentParser(
#usage = "%prog -p <port> [options]",
version="pyRen terminal Version 0.9.k",
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")
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.decode("windows-1251"),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
def main():
global macro
global var
init_macro()
init_var()
load_macro()
optParser()
# disable CAN auto-formatting
mod_globals.opt_cfc0 = True
print 'Opening ELM'
elm = mod_elm.ELM( mod_globals.opt_port, mod_globals.opt_speed, True )
elm.currentaddress = '7A'
elm.currentprotocol = 'can'
if auto_macro!='':
if auto_macro in macro.keys():
play_macro( auto_macro, elm )
else:
print 'Error: unknown macro mane:', auto_macro
while True:
l = raw_input(var['$addr']+':'+var['$txa']+':'+var['$prompt'] + '#').lower()
l = l.strip()
if l in ['q', 'quit', 'e', 'exit', 'end']:
break
if l in ['h', 'help', '?']:
print_help ()
continue
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__':
main()