Skip to content

Commit fe48ec7

Browse files
committed
Merge branch 'develop' into feature-periodic-send-api
# Conflicts: # can/__init__.py # can/interfaces/interface.py # can/interfaces/remote/server.py # doc/interfaces/remote.rst
2 parents b3aa245 + 61e2425 commit fe48ec7

54 files changed

Lines changed: 1909 additions & 1257 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
python-can
22
==========
33

4-
|release| |docs| |build|
4+
|release| |docs| |build|
55

66
.. |release| image:: https://img.shields.io/pypi/v/python-can.svg
77
:target: https://pypi.python.org/pypi/python-can/
88
:alt: Latest Version
99

10-
.. |docs| image:: https://readthedocs.org/projects/python-can/badge/?version=latest
11-
:target: http://python-can.readthedocs.org/en/latest/?badge=latest
10+
.. |docs| image:: https://readthedocs.org/projects/python-can/badge/?version=stable
11+
:target: https://python-can.readthedocs.io/en/stable/
1212
:alt: Documentation Status
1313

14-
.. |build| image:: https://drone.io/github.com/hardbyte/python-can/status.png
15-
:target: https://drone.io/github.com/hardbyte/python-can/latest
14+
.. |build| image:: https://travis-ci.org/hardbyte/python-can.svg?branch=master
15+
:target: https://travis-ci.org/hardbyte/python-can
1616
:alt: CI Server
1717

1818

@@ -45,4 +45,4 @@ mailing list for development discussion.
4545
questions and answers tagged with ``python+can``.
4646

4747
Wherever we interact, we strive to follow the
48-
`Python Community Code of Conduct <https://www.python.org/psf/codeofconduct/>`__.
48+
`Python Community Code of Conduct <https://www.python.org/psf/codeofconduct/>`__.

bin/can_player.py

Lines changed: 0 additions & 72 deletions
This file was deleted.

can/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
can is an object-orient Controller Area Network interface module.
33
"""
44
import logging
5+
6+
__version__ = "2.0.0-alpha.2"
7+
58
log = logging.getLogger('can')
69

7-
rc = dict(channel=0)
10+
rc = dict()
811

912

1013
class CanError(IOError):
@@ -23,10 +26,11 @@ class CanError(IOError):
2326
from can.message import Message
2427
from can.bus import BusABC
2528
from can.notifier import Notifier
29+
from can.interfaces import VALID_INTERFACES
30+
from . import interface
31+
2632
from can.broadcastmanager import send_periodic, \
2733
CyclicSendTaskABC, \
2834
LimitedDurationCyclicSendTaskABC, \
2935
MultiRateCyclicSendTaskABC, \
3036
RestartableCyclicTaskABC
31-
32-
from can.interfaces import interface

can/bus.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99

1010
class BusABC(object):
11-
1211
"""CAN Bus Abstract Base Class
1312
1413
Concrete implementations must implement the following methods:
@@ -30,9 +29,10 @@ def __init__(self, channel=None, can_filters=None, **config):
3029
The can interface identifier. Expected type is backend dependent.
3130
3231
:param list can_filters:
33-
A list of dictionaries each containing a "can_id" and a "can_mask".
32+
A list of dictionaries each containing a "can_id", a "can_mask",
33+
and an "extended" key.
3434
35-
>>> [{"can_id": 0x11, "can_mask": 0x21}]
35+
>>> [{"can_id": 0x11, "can_mask": 0x21, "extended": False}]
3636
3737
A filter matches, when ``<received_can_id> & can_mask == can_id & can_mask``
3838
@@ -52,11 +52,15 @@ def recv(self, timeout=None):
5252
raise NotImplementedError("Trying to read from a write only bus?")
5353

5454
@abc.abstractmethod
55-
def send(self, msg):
55+
def send(self, msg, timeout=None):
5656
"""Transmit a message to CAN bus.
5757
Override this method to enable the transmit path.
5858
5959
:param msg: A :class:`can.Message` object.
60+
:param float timeout:
61+
If > 0, wait up to this many seconds for message to be ACK:ed.
62+
If timeout is exceeded, an exception will be raised.
63+
Might not be supported by all interfaces.
6064
6165
:raise: :class:`can.CanError`
6266
if the message could not be written.
@@ -116,8 +120,7 @@ def set_filters(self, can_filters=None):
116120
raise NotImplementedError("Trying to set_filters on unsupported bus")
117121

118122
def flush_tx_buffer(self):
119-
"""Used for CAN interfaces which need to flush their transmit buffer.
120-
123+
"""Discard every message that may be queued in the output buffer(s).
121124
"""
122125
pass
123126

can/interface.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import can
2+
import importlib
3+
4+
from can.broadcastmanager import CyclicSendTaskABC, MultiRateCyclicSendTaskABC
5+
from can.util import load_config
6+
7+
# interface_name => (module, classname)
8+
BACKENDS = {
9+
'kvaser': ('can.interfaces.kvaser', 'KvaserBus'),
10+
'socketcan_ctypes': ('can.interfaces.socketcan', 'SocketcanCtypes_Bus'),
11+
'socketcan_native': ('can.interfaces.socketcan', 'SocketcanNative_Bus'),
12+
'serial': ('can.interfaces.serial.serial_can', 'SerialBus'),
13+
'pcan': ('can.interfaces.pcan', 'PcanBus'),
14+
'usb2can': ('can.interfaces.usb2can', 'Usb2canBus'),
15+
'ixxat': ('can.interfaces.ixxat', 'IXXATBus'),
16+
'nican': ('can.interfaces.nican', 'NicanBus'),
17+
'remote': ('can.interfaces.remote', 'RemoteBus'),
18+
'virtual': ('can.interfaces.virtual', 'VirtualBus'),
19+
'neovi': ('can.interfaces.neovi_api', 'NeoVIBus')
20+
}
21+
22+
class Bus(object):
23+
"""
24+
Instantiates a CAN Bus of the given `bustype`, falls back to reading a
25+
configuration file from default locations.
26+
"""
27+
28+
@classmethod
29+
def __new__(cls, other, channel=None, *args, **kwargs):
30+
"""
31+
Takes the same arguments as :class:`can.BusABC` with the addition of:
32+
33+
:param kwargs:
34+
Should contain a bustype key with a valid interface name.
35+
36+
:raises:
37+
NotImplementedError if the bustype isn't recognized
38+
:raises:
39+
ValueError if the bustype or channel isn't either passed as an argument
40+
or set in the can.rc config.
41+
42+
"""
43+
config = load_config(config={
44+
'interface': kwargs.get('bustype'),
45+
'channel': channel
46+
})
47+
48+
if 'bustype' in kwargs:
49+
# remove the bustype so it doesn't get passed to the backend
50+
del kwargs['bustype']
51+
interface = config['interface']
52+
channel = config['channel']
53+
54+
# Import the correct Bus backend
55+
try:
56+
(module_name, class_name) = BACKENDS[interface]
57+
except KeyError:
58+
raise NotImplementedError("CAN interface '{}' not supported".format(interface))
59+
60+
try:
61+
module = importlib.import_module(module_name)
62+
except Exception as e:
63+
raise ImportError(
64+
"Cannot import module {} for CAN interface '{}': {}".format(module_name, interface, e)
65+
)
66+
try:
67+
cls = getattr(module, class_name)
68+
except Exception as e:
69+
raise ImportError(
70+
"Cannot import class {} from module {} for CAN interface '{}': {}".format(
71+
class_name, module_name, interface, e
72+
)
73+
)
74+
75+
return cls(channel, **kwargs)
76+
77+
78+
class CyclicSendTask(CyclicSendTaskABC):
79+
80+
@classmethod
81+
def __new__(cls, other, channel, *args, **kwargs):
82+
83+
config = load_config(config={'channel': channel})
84+
85+
# Import the correct implementation of CyclicSendTask
86+
if config['interface'] == 'socketcan_ctypes':
87+
from can.interfaces.socketcan.socketcan_ctypes import CyclicSendTask as _ctypesCyclicSendTask
88+
cls = _ctypesCyclicSendTask
89+
elif config['interface'] == 'socketcan_native':
90+
from can.interfaces.socketcan.socketcan_native import CyclicSendTask as _nativeCyclicSendTask
91+
cls = _nativeCyclicSendTask
92+
# CyclicSendTask has not been fully implemented on remote interface yet.
93+
# Waiting for issue #80 which will change the API to make it easier for
94+
# interfaces other than socketcan to implement it
95+
#elif can.rc['interface'] == 'remote':
96+
# from can.interfaces.remote import CyclicSendTask as _remoteCyclicSendTask
97+
# cls = _remoteCyclicSendTask
98+
else:
99+
raise can.CanError("Current CAN interface doesn't support CyclicSendTask")
100+
101+
return cls(config['channel'], *args, **kwargs)
102+
103+
104+
class MultiRateCyclicSendTask(MultiRateCyclicSendTaskABC):
105+
106+
@classmethod
107+
def __new__(cls, other, channel, *args, **kwargs):
108+
109+
config = load_config(config={'channel': channel})
110+
111+
# Import the correct implementation of CyclicSendTask
112+
if config['interface'] == 'socketcan_ctypes':
113+
from can.interfaces.socketcan.socketcan_ctypes import MultiRateCyclicSendTask as _ctypesMultiRateCyclicSendTask
114+
cls = _ctypesMultiRateCyclicSendTask
115+
elif config['interface'] == 'socketcan_native':
116+
from can.interfaces.socketcan.socketcan_native import MultiRateCyclicSendTask as _nativeMultiRateCyclicSendTask
117+
cls = _nativeMultiRateCyclicSendTask
118+
else:
119+
can.log.info("Current CAN interface doesn't support CyclicSendTask")
120+
121+
return cls(config['channel'], *args, **kwargs)

can/interfaces/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
"""
33
Interfaces contain low level implementations that interact with CAN hardware.
44
"""
5+
6+
VALID_INTERFACES = set(['kvaser', 'serial', 'pcan', 'socketcan_native',
7+
'socketcan_ctypes', 'socketcan', 'usb2can', 'ixxat',
8+
'nican', 'remote', 'virtual', 'neovi'])

0 commit comments

Comments
 (0)