Skip to content

Commit a973d73

Browse files
authored
Merge branch 'develop' into software-filtering
2 parents 288c8b1 + b97a502 commit a973d73

34 files changed

Lines changed: 806 additions & 298 deletions

.appveyor.yml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,31 @@ environment:
66
# http://www.appveyor.com/docs/installed-software#python
77

88
- PYTHON: "C:\\Python27"
9-
- PYTHON: "C:\\Python33"
109
- PYTHON: "C:\\Python34"
1110
- PYTHON: "C:\\Python35"
1211
- PYTHON: "C:\\Python36"
1312
- PYTHON: "C:\\Python27-x64"
14-
- PYTHON: "C:\\Python33-x64"
1513
- PYTHON: "C:\\Python34-x64"
1614
- PYTHON: "C:\\Python35-x64"
1715
- PYTHON: "C:\\Python36-x64"
1816

17+
# officially unsupported
18+
- PYTHON: "C:\\Python33"
19+
- PYTHON: "C:\\Python33-x64"
20+
21+
matrix:
22+
allow_failures:
23+
- PYTHON: "C:\\Python33"
24+
- PYTHON: "C:\\Python33-x64"
25+
1926
install:
20-
# We need our usual libraries
21-
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
2227
# We need to install the python-can library itself
23-
- "%PYTHON%\\python.exe -m pip install ."
28+
- "%PYTHON%\\python.exe -m pip install .[test]"
2429

2530
build: off
2631

2732
test_script:
2833
# Note that you must use the environment variable %PYTHON% to refer to
2934
# the interpreter you're using - Appveyor does not do anything special
3035
# to put the Python version you want to use on PATH.
31-
- "%PYTHON%\\python.exe setup.py test"
36+
- "%PYTHON%\\python.exe setup.py test -v"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ nosetests.xml
4646
coverage.xml
4747
*,cover
4848
.hypothesis/
49+
test.*
4950

5051
# Translations
5152
*.mo

.travis.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ language: python
33
python:
44
# CPython:
55
- "2.7"
6-
- "3.3"
6+
- "3.3" # but allowed to fail
77
- "3.4"
88
- "3.5"
99
- "3.6"
@@ -37,14 +37,18 @@ matrix:
3737
- os: osx
3838
python: "nightly"
3939

40-
# allow all nighly builds to fail, since these python versions might be unstable
41-
# we do not allow dev builds to fail, since these builds are stable enough
4240
allow_failures:
41+
# allow all nighly builds to fail, since these python versions might be unstable
4342
- python: "nightly"
4443

44+
# we do not allow dev builds to fail, since these builds are considered stable enough
45+
46+
# Python 3.3 tests are allowed to fail since Python 3.3 is not offically supported any more
47+
- python: "3.3"
48+
4549
install:
46-
- travis_retry pip install .
47-
- travis_retry pip install -r requirements.txt
50+
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo bash test/open_vcan.sh ; fi
51+
- travis_retry pip install .[test]
4852

4953
script:
5054
- py.test -v

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Python developers; providing `common abstractions to
3030
different hardware devices`, and a suite of utilities for sending and receiving
3131
messages on a can bus.
3232

33-
The library supports Python 2.7, Python 3.3+ as well as PyPy 2 & 3 and runs on Mac, Linux and Windows.
33+
The library supports Python 2.7, Python 3.4+ as well as PyPy 2 & 3 and runs on Mac, Linux and Windows.
3434

3535
You can find more information in the documentation, online at
3636
`python-can.readthedocs.org <https://python-can.readthedocs.org/en/stable/>`__.

can/ctypesutil.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
log = logging.getLogger('can.ctypesutil')
1414

15-
__all__ = ['CLibrary', 'HANDLE', 'PHANDLE']
15+
__all__ = ['CLibrary', 'HANDLE', 'PHANDLE', 'HRESULT']
1616

1717
try:
1818
_LibBase = ctypes.WinDLL
@@ -84,8 +84,13 @@ def function_type(self):
8484

8585
if sys.platform == "win32":
8686
CLibrary = CLibrary_Win32
87+
HRESULT = ctypes.HRESULT
8788
else:
8889
CLibrary = CLibrary_Unix
90+
if sys.platform == "cygwin":
91+
# Define HRESULT for cygwin
92+
class HRESULT(ctypes.c_long):
93+
pass
8994

9095

9196
# Common win32 definitions

can/interfaces/ics_neovi/neovi_bus.py

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ def is_critical(self):
5858
return self.severity == self.ICS_SPY_ERR_CRITICAL
5959

6060

61+
BAUDRATE_SETTING = {
62+
20000: 0,
63+
33333: 1,
64+
50000: 2,
65+
62500: 3,
66+
83333: 4,
67+
100000: 5,
68+
125000: 6,
69+
250000: 7,
70+
500000: 8,
71+
800000: 9,
72+
1000000: 10,
73+
}
74+
VALID_BITRATES = list(BAUDRATE_SETTING.keys())
75+
VALID_BITRATES.sort()
76+
77+
6178
class NeoViBus(BusABC):
6279
"""
6380
The CAN Bus implemented for the python_ics interface
@@ -71,12 +88,18 @@ def __init__(self, channel=None, can_filters=None, **config):
7188
The Channel id to create this bus with.
7289
:param list can_filters:
7390
A list of dictionaries each containing a "can_id" and a "can_mask".
91+
92+
>>> [{"can_id": 0x11, "can_mask": 0x21}]
93+
7494
:param use_system_timestamp:
7595
Use system timestamp for can messages instead of the hardware time
7696
stamp
77-
78-
>>> [{"can_id": 0x11, "can_mask": 0x21}]
79-
97+
:param str serial:
98+
Serial to connect (optional, will use the first found if not
99+
supplied)
100+
:param int bitrate:
101+
Channel bitrate in bit/s. (optional, will enable the auto bitrate
102+
feature if not supplied)
80103
"""
81104
super(NeoViBus, self).__init__(channel, can_filters, **config)
82105
if ics is None:
@@ -97,7 +120,32 @@ def __init__(self, channel=None, can_filters=None, **config):
97120

98121
type_filter = config.get('type_filter')
99122
serial = config.get('serial')
100-
self.dev = self._open_device(type_filter, serial)
123+
self.dev = self._find_device(type_filter, serial)
124+
ics.open_device(self.dev)
125+
126+
bitrate = config.get('bitrate')
127+
128+
# Default auto baud setting
129+
settings = {
130+
'SetBaudrate': ics.AUTO,
131+
'Baudrate': BAUDRATE_SETTING[500000], # Default baudrate setting
132+
'auto_baud': 1
133+
}
134+
135+
if bitrate is not None:
136+
if int(bitrate) not in VALID_BITRATES:
137+
raise ValueError(
138+
'Invalid bitrate. Valid bitrates are {}'.format(
139+
VALID_BITRATES
140+
)
141+
)
142+
baud_rate_setting = BAUDRATE_SETTING[int(bitrate)]
143+
settings = {
144+
'SetBaudrate': ics.AUTO,
145+
'Baudrate': baud_rate_setting,
146+
'auto_baud': 0,
147+
}
148+
self._set_can_settings(channel, settings)
101149

102150
self.channel_info = '%s %s CH:%s' % (
103151
self.dev.Name,
@@ -106,8 +154,6 @@ def __init__(self, channel=None, can_filters=None, **config):
106154
)
107155
logger.info("Using device: {}".format(self.channel_info))
108156

109-
ics.load_default_settings(self.dev)
110-
111157
self.sw_filters = None
112158
self.set_filters(can_filters)
113159
self.rx_buffer = deque()
@@ -128,21 +174,17 @@ def get_serial_number(device):
128174
:return: ics device serial string
129175
:rtype: str
130176
"""
131-
def to_base36(n, alphabet="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
132-
return (to_base36(n // 36) + alphabet[n % 36]).lstrip("0") \
133-
if n > 0 else "0"
134-
135177
a0000 = 604661760
136178
if device.SerialNumber >= a0000:
137-
return to_base36(device.SerialNumber)
179+
return ics.base36enc(device.SerialNumber)
138180
return str(device.SerialNumber)
139181

140182
def shutdown(self):
141183
super(NeoViBus, self).shutdown()
142184
self.opened = False
143185
ics.close_device(self.dev)
144186

145-
def _open_device(self, type_filter=None, serial=None):
187+
def _find_device(self, type_filter=None, serial=None):
146188
if type_filter is not None:
147189
devices = ics.find_devices(type_filter)
148190
else:
@@ -161,9 +203,30 @@ def _open_device(self, type_filter=None, serial=None):
161203
msg.append('with serial {}'.format(serial))
162204
msg.append('found.')
163205
raise Exception(' '.join(msg))
164-
ics.open_device(dev)
165206
return dev
166207

208+
def _get_can_settings(self, channel):
209+
"""Return the CanSettings for channel
210+
211+
:param channel: can channel number
212+
:return: ics.CanSettings
213+
"""
214+
device_settings = ics.get_device_settings(self.dev)
215+
return getattr(device_settings, 'can{}'.format(channel))
216+
217+
def _set_can_settings(self, channel, setting):
218+
"""Applies can settings to channel
219+
220+
:param channel: can channel number
221+
:param setting: settings dictionary (only the settings to update)
222+
:return: None
223+
"""
224+
device_settings = ics.get_device_settings(self.dev)
225+
channel_settings = getattr(device_settings, 'can{}'.format(channel))
226+
for setting, value in setting.items():
227+
setattr(channel_settings, setting, value)
228+
ics.set_device_settings(self.dev, device_settings)
229+
167230
def _process_msg_queue(self, timeout=None):
168231
try:
169232
messages, errors = ics.get_messages(self.dev, False, timeout)

can/interfaces/iscan.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,11 @@ class IscanError(CanError):
152152

153153
def __init__(self, function, error_code, arguments):
154154
super(IscanError, self).__init__()
155-
# Status code
155+
# :Status code
156156
self.error_code = error_code
157-
# Function that failed
157+
# :Function that failed
158158
self.function = function
159-
# Arguments passed to function
159+
# :Arguments passed to function
160160
self.arguments = arguments
161161

162162
def __str__(self):

can/interfaces/ixxat/canlib.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from can import Message
1818
from can.broadcastmanager import (LimitedDurationCyclicSendTaskABC,
1919
RestartableCyclicTaskABC)
20-
from can.ctypesutil import CLibrary, HANDLE, PHANDLE
20+
from can.ctypesutil import CLibrary, HANDLE, PHANDLE, HRESULT as ctypes_HRESULT
2121

2222
from can.interfaces.ixxat import constants, structures
2323

@@ -44,6 +44,11 @@
4444
_canlib = CLibrary("vcinpl")
4545
except Exception as e:
4646
log.warning("Cannot load IXXAT vcinpl library: %s", e)
47+
elif sys.platform == "cygwin":
48+
try:
49+
_canlib = CLibrary("vcinpl.dll")
50+
except Exception as e:
51+
log.warning("Cannot load IXXAT vcinpl library: %s", e)
4752
else:
4853
# Will not work on other systems, but have it importable anyway for
4954
# tests/sphinx
@@ -125,7 +130,7 @@ def __check_status(result, function, arguments):
125130
_canlib.map_symbol("vciInitialize", ctypes.c_long, (), __check_status)
126131

127132
#void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize);
128-
_canlib.map_symbol("vciFormatError", None, (ctypes.HRESULT, ctypes.c_char_p, ctypes.c_uint32))
133+
_canlib.map_symbol("vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32))
129134
# Hack to have vciFormatError as a free function
130135
vciFormatError = functools.partial(__vciFormatError, _canlib)
131136

@@ -309,6 +314,8 @@ def __init__(self, channel, can_filters=None, **config):
309314
else:
310315
if (UniqueHardwareId is None) or (self._device_info.UniqueHardwareId.AsChar == bytes(UniqueHardwareId, 'ascii')):
311316
break
317+
else:
318+
log.debug("Ignoring IXXAT with hardware id '%s'.", self._device_info.UniqueHardwareId.AsChar.decode("ascii"))
312319
_canlib.vciEnumDeviceClose(self._device_handle)
313320
_canlib.vciDeviceOpen(ctypes.byref(self._device_info.VciObjectId), ctypes.byref(self._device_handle))
314321
log.info("Using unique HW ID %s", self._device_info.UniqueHardwareId.AsChar)

can/interfaces/ixxat/structures.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
class LUID(ctypes.Structure):
1313
_fields_ = [
14-
("LowPart", ctypes.c_ulong),
15-
("HighPart", ctypes.c_long),
14+
("LowPart", ctypes.c_uint32),
15+
("HighPart", ctypes.c_int32),
1616
]
1717
PLUID = ctypes.POINTER(LUID)
1818

@@ -27,9 +27,9 @@ class VCIID(ctypes.Union):
2727

2828
class GUID(ctypes.Structure):
2929
_fields_ = [
30-
("Data1", ctypes.c_long),
31-
("Data2", ctypes.c_short),
32-
("Data3", ctypes.c_short),
30+
("Data1", ctypes.c_uint32),
31+
("Data2", ctypes.c_uint16),
32+
("Data3", ctypes.c_uint16),
3333
("Data4", ctypes.c_char * 8),
3434
]
3535

0 commit comments

Comments
 (0)