Skip to content

Commit

Permalink
Merge pull request #2 from christoph2/master
Browse files Browse the repository at this point in the history
pull changes from base repo
  • Loading branch information
waszil committed May 22, 2019
2 parents bbc05dd + 2817bd7 commit e41ce52
Show file tree
Hide file tree
Showing 23 changed files with 386 additions and 60 deletions.
17 changes: 0 additions & 17 deletions .codacy.yml

This file was deleted.

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,7 @@ result.xml
/docs/_templates
/docs/_build
/docs/_static

**/*pdf
**/*gz
**/*tar
**/*bz2
13 changes: 13 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

version: 2

sphinx:
configuration: docs/conf.py

formats: all

python:
version: 3.7
install:
- requirements: docs/requirements.txt

1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pyXCP
=====

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3883e9c8dea24ab49121c402d44c656b)](https://www.codacy.com/app/cpu12-gems/pyxcp?utm_source=github.com&utm_medium=referral&utm_content=christoph2/pyxcp&utm_campaign=Badge_Grade)
[![Maintainability](https://api.codeclimate.com/v1/badges/4c639f3695f2725e392a/maintainability)](https://codeclimate.com/github/christoph2/pyxcp/maintainability)
[![Build Status](https://travis-ci.org/christoph2/pyxcp.svg)](https://travis-ci.org/christoph2/pyxcp)
[![Build status](https://ci.appveyor.com/api/projects/status/r00l4i4co095e9ht?svg=true)](https://ci.appveyor.com/project/christoph2/pyxcp)
Expand Down
12 changes: 12 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ after_test:
# 64-bit Python 3.3/3.4. And you need to use %PYTHON% to get the correct
# interpreter
- "%PYTHON%\\python.exe setup.py bdist_wheel"
- "%PYTHON%\\python.exe setup.py sdist --formats=zip,gztar"

artifacts:
# bdist_wheel puts your built wheel in the dist directory
Expand All @@ -56,3 +57,14 @@ on_finish:
- ps: |
$wc = New-Object 'System.Net.WebClient'
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\result.xml))
deploy:
- provider: GitHub
artifact: '*.*'
on:
APPVEYOR_REPO_TAG: true
description: Test release -- do not use
tag: $(APPVEYOR_REPO_TAG_NAME)
draft: false
prerelease: true

1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sphinxcontrib-napoleon
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ home-page = "https://github.com/christoph2/pyxcp"
requires = [
"construct >= 2.9.0",
"mako",
"pyserial"
"pyserial",
"toml"
]
requires-python = ">= 3.4"
description-file = "README.md"
Expand Down
188 changes: 188 additions & 0 deletions pyxcp/cmdline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Parse (transport-layer specific) command line parameters
and create a XCP master instance.
.. note::
There is currently no interface for further customization.
"""

__copyright__ = """
pySART - Simplified AUTOSAR-Toolkit for Python.
(C) 2009-2019 by Christoph Schueler <cpu12.gems@googlemail.com>
All Rights Reserved
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""


import argparse
import json
import pathlib

from pprint import pprint

try:
import toml
except ImportError:
HAS_TOML = False
else:
HAS_TOML = True

from pyxcp.master import Master
from pyxcp.transport import Eth
from pyxcp.transport import SxI


ARGUMENTS = {
"can": ("driver", "loglevel"),
"eth": ("host", "port", "protocol", "ipv6", "loglevel"),
"sxi": ("port", "baudrate", "bytesize", "parity", "stopbits", "loglevel"),
}


def makeNonNullValuesDict(**params):
"""Only add items with non-None values.
"""
return {k: v for k, v in params.items() if not v is None}


def readConfiguration(conf):
"""
"""
if conf:
pth = pathlib.Path(conf.name)
suffix = pth.suffix.lower()
if suffix == '.json':
reader = json
elif suffix == '.toml' and HAS_TOML:
reader = toml
else:
reader = None
if reader:
return reader.loads(conf.read())
else:
return {}
else:
return {}


def mergeParameters(transport, config, params):
"""Merge parameters from config-file and command-line.
The latter have precedence.
"""
args = ARGUMENTS.get(transport)
result = {}
for arg in args:
cvalue = config.get(arg.upper())
if cvalue:
result[arg] = cvalue
pvalue = params.get(arg)
if pvalue:
result[arg] = pvalue
return result


def removeParameters(transport, config):
"""Remove constructor parameters from configuration.
"""
stoplist = [arg.upper() for arg in ARGUMENTS.get(transport)]
return {k: v for k, v in config.items() if not k in stoplist}


class ArgumentParser:
"""
"""

def __init__(self, *args, **kws):
kws.update(formatter_class = argparse.RawDescriptionHelpFormatter)
self.parser = argparse.ArgumentParser(*args, **kws)
subparsers = self.parser.add_subparsers(dest = "transport")
subparsers.help = "Transport layer"
self.parser.add_argument('-c', '--config-file', type=argparse.FileType('r'), dest = "conf",
help = 'File to read (extended) parameters from.')
self.parser.add_argument('-l', '--loglevel', choices = ["ERROR", "WARN", "INFO", "DEBUG"])
self.parser.epilog = "To get specific help on transport layers\nuse <layer> -h, e.g. {} eth -h".format(self.parser.prog)

eth = subparsers.add_parser("eth", description = "XCPonEth specific options:")
eth.set_defaults(eth = True)
sxi = subparsers.add_parser("sxi", description = "XCPonSxI specific options:")
sxi.set_defaults(sxi = True)
can = subparsers.add_parser("can", description = "XCPonCAN specific options:")
can.set_defaults(can = True)

eth.add_argument('-p', '--port', type = int, metavar = "port")
proto = eth.add_mutually_exclusive_group()
proto.add_argument('-t', '--tcp', default = True, const = True, metavar = "tcp", action = "store_const")
proto.add_argument('-u', '--udp', default = False, const = True, metavar = "udp", action = "store_const")

eth.add_argument('-6', '--ipv6', const = True, metavar = "ipv6", action = "store_const")
eth.add_argument('-H', '--host', help = "Host name or IP.")

sxi.add_argument('-p', '--port', help = "Name or number of your serial interface.")
sxi.add_argument('-b', '--baudrate', type = int)
sxi.add_argument('--bytesize', type = int)
sxi.add_argument('--parity', choices = ['N', 'E', 'O'])
sxi.add_argument('--stopbits', type = int, choices = [1, 2])
self._args = []


def run(self):
"""
"""
self._args = self.parser.parse_args()
args = self.args
config = readConfiguration(args.conf)
transport = args.transport
if not transport:
print("missing argument transport: choose from {}".format(['can', 'eth', 'sxi']))
exit(1)
if transport == "eth":
params = makeNonNullValuesDict(
host = args.host,
port = args.port,
protocol = "UDP" if args.udp else "TCP",
ipv6 = args.ipv6,
loglevel = args.loglevel)
Klass = Eth
elif transport == "sxi":
params = makeNonNullValuesDict(
port = args.port,
baudrate = args.baudrate,
bytesize = args.bytesize,
parity = args.parity,
stopbits = args.stopbits,
loglevel = args.loglevel)
klass = SxI
elif transport == "can":
raise NotImplementedError("No CAN support for now.")
params = mergeParameters(transport, config, params)
config = removeParameters(transport, config)
params.update(config = config)
tr = Klass(**params)
return Master(tr)

@property
def args(self):
return self._args
14 changes: 14 additions & 0 deletions pyxcp/examples/conf_can.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"DRIVER": "kvaser",
"KV_CHANNEL": 0,
"CAN_ID_MASTER": 257,
"CAN_ID_SLAVE": 258,
"CAN_ID_BROADCAST": 256,
"MAX_DLC_REQUIRED": false,
"FREQ": 250000,
"BTQ": 16,
"TSEG1": 14,
"TSEG2": 2,
"NOSAMP": 1,
"SJW": 2
}
12 changes: 12 additions & 0 deletions pyxcp/examples/conf_can.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
DRIVER = "kvaser"
KV_CHANNEL = 0
CAN_ID_MASTER = 257
CAN_ID_SLAVE = 258
CAN_ID_BROADCAST = 256
MAX_DLC_REQUIRED = false
FREQ = 250000
BTQ = 16
TSEG1 = 14
TSEG2 = 2
NOSAMP = 1
SJW = 2
6 changes: 6 additions & 0 deletions pyxcp/examples/conf_eth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"HOST": "localhost",
"PORT": 5555,
"PROTOCOL": "TCP",
"IPV6": false
}
4 changes: 4 additions & 0 deletions pyxcp/examples/conf_eth.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
HOST = "localhost"
PORT = 5555
PROTOCOL = "TCP"
IPV6 = false
7 changes: 7 additions & 0 deletions pyxcp/examples/conf_sxi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"PORT": "COM10",
"BAUDRATE": 38400,
"BYTESIZE": 8,
"PARITY": "N",
"STOPBITS": 1
}
5 changes: 5 additions & 0 deletions pyxcp/examples/conf_sxi.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
PORT = "COM10"
BAUDRATE = 38400
PARITY = "N"
BYTESIZE = 8
STOPBITS = 1
46 changes: 46 additions & 0 deletions pyxcp/examples/xcphello.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
"""

__copyright__ = """
pySART - Simplified AUTOSAR-Toolkit for Python.
(C) 2009-2019 by Christoph Schueler <cpu12.gems@googlemail.com>
All Rights Reserved
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""



from pprint import pprint

from pyxcp.cmdline import ArgumentParser

ap = ArgumentParser(description = "pyXCP hello world.")
with ap.run() as x:
x.connect()
if x.slaveProperties.optionalCommMode:
x.getCommModeInfo()
gid = x.getId(0x1)
result = x.fetch(gid.length)
print("ID: '{}'".format(result.decode("utf8")))

x.disconnect()
#print(ap.args)
pprint(x.slaveProperties)
Loading

0 comments on commit e41ce52

Please sign in to comment.