Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 19 additions & 89 deletions can/interfaces/ics_neovi/neovi_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ class ICSApiError(CanError):
# An error which probably does not need attention.
ICS_SPY_ERR_INFORMATION = 0x40

def __init__(self, error_number, description_short, description_long,
severity, restart_needed):
def __init__(
self, error_number, description_short, description_long,
severity, restart_needed
):
super(ICSApiError, self).__init__(description_short)
self.error_number = error_number
self.description_short = description_short
Expand All @@ -59,23 +61,6 @@ def is_critical(self):
return self.severity == self.ICS_SPY_ERR_CRITICAL


BAUDRATE_SETTING = {
20000: 0,
33333: 1,
50000: 2,
62500: 3,
83333: 4,
100000: 5,
125000: 6,
250000: 7,
500000: 8,
800000: 9,
1000000: 10,
}
VALID_BITRATES = list(BAUDRATE_SETTING.keys())
VALID_BITRATES.sort()


class NeoViBus(BusABC):
"""
The CAN Bus implemented for the python_ics interface
Expand All @@ -84,6 +69,7 @@ class NeoViBus(BusABC):

def __init__(self, channel, can_filters=None, **config):
"""

:param int channel:
The Channel id to create this bus with.
:param list can_filters:
Expand All @@ -102,14 +88,15 @@ def __init__(self, channel, can_filters=None, **config):
if ics is None:
raise ImportError('Please install python-ics')

super(NeoViBus, self).__init__(channel=channel, can_filters=can_filters, **config)
super(NeoViBus, self).__init__(
channel=channel, can_filters=can_filters, **config)

logger.info("CAN Filters: {}".format(can_filters))
logger.info("Got configuration of: {}".format(config))

self._use_system_timestamp = bool(config.get('use_system_timestamp', False))

# TODO: Add support for multiple channels
self._use_system_timestamp = bool(
config.get('use_system_timestamp', False)
)
try:
channel = int(channel)
except ValueError:
Expand All @@ -120,30 +107,8 @@ def __init__(self, channel, can_filters=None, **config):
self.dev = self._find_device(type_filter, serial)
ics.open_device(self.dev)

bitrate = config.get('bitrate')

# Default auto baud setting
settings = {
'SetBaudrate': ics.AUTO,
'Baudrate': BAUDRATE_SETTING[500000], # Default baudrate setting
'auto_baud': 1
}

if bitrate is not None:
bitrate = int(bitrate)
if bitrate not in VALID_BITRATES:
raise ValueError(
'Invalid bitrate. Valid bitrates are {}'.format(
VALID_BITRATES
)
)
baud_rate_setting = BAUDRATE_SETTING[bitrate]
settings = {
'SetBaudrate': ics.AUTO,
'Baudrate': baud_rate_setting,
'auto_baud': 0,
}
self._set_can_settings(channel, settings)
if 'bitrate' in config:
ics.set_bit_rate(self.dev, config.get('bitrate'), channel)

self.channel_info = '%s %s CH:%s' % (
self.dev.Name,
Expand All @@ -153,15 +118,8 @@ def __init__(self, channel, can_filters=None, **config):
logger.info("Using device: {}".format(self.channel_info))

self.rx_buffer = deque()
self.opened = True

self.network = channel if channel is not None else None

# TODO: Change the scaling based on the device type
self.ts_scaling = (
ics.NEOVI6_VCAN_TIMESTAMP_1, ics.NEOVI6_VCAN_TIMESTAMP_2
)

@staticmethod
def get_serial_number(device):
"""Decode (if needed) and return the ICS device serial string
Expand All @@ -177,7 +135,6 @@ def get_serial_number(device):

def shutdown(self):
super(NeoViBus, self).shutdown()
self.opened = False
ics.close_device(self.dev)

def _find_device(self, type_filter=None, serial=None):
Expand All @@ -201,29 +158,7 @@ def _find_device(self, type_filter=None, serial=None):
raise Exception(' '.join(msg))
return dev

def _get_can_settings(self, channel):
"""Return the CanSettings for channel

:param channel: can channel number
:return: ics.CanSettings
"""
device_settings = ics.get_device_settings(self.dev)
return getattr(device_settings, 'can{}'.format(channel))

def _set_can_settings(self, channel, setting):
"""Applies can settings to channel

:param channel: can channel number
:param setting: settings dictionary (only the settings to update)
:return: None
"""
device_settings = ics.get_device_settings(self.dev)
channel_settings = getattr(device_settings, 'can{}'.format(channel))
for setting, value in setting.items():
setattr(channel_settings, setting, value)
ics.set_device_settings(self.dev, device_settings)

def _process_msg_queue(self, timeout):
def _process_msg_queue(self, timeout=0.1):
try:
messages, errors = ics.get_messages(self.dev, False, timeout)
except ics.RuntimeError:
Expand Down Expand Up @@ -257,11 +192,7 @@ def _get_timestamp_for_msg(self, ics_msg):
return ics_msg.TimeSystem
else:
# This is the hardware time stamp.
# The TimeStamp is reset to zero every time the OpenPort method is
# called.
return \
float(ics_msg.TimeHardware2) * self.ts_scaling[1] + \
float(ics_msg.TimeHardware) * self.ts_scaling[0]
return ics.get_timestamp_for_msg(self.dev, ics_msg)

def _ics_msg_to_message(self, ics_msg):
return Message(
Expand All @@ -278,20 +209,19 @@ def _ics_msg_to_message(self, ics_msg):
channel=ics_msg.NetworkID
)

def _recv_internal(self, timeout):
def _recv_internal(self, timeout=0.1):
if not self.rx_buffer:
self._process_msg_queue(timeout)
self._process_msg_queue(timeout=timeout)
try:
ics_msg = self.rx_buffer.popleft()
msg = self._ics_msg_to_message(ics_msg)
except IndexError:
return None, False
else:
return msg, False
return msg, False

def send(self, msg, timeout=None):
if not self.opened:
raise CanError("bus not yet opened")
if not self.dev.IsOpen:
raise CanError("bus not open")

flags = 0
if msg.is_extended_id:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
] + (['subprocess32 ~= 3.2.7'] if version_info.major < 3 else []),
extras_require={
'serial': ['pyserial >= 3.0'],
'neovi': ['python-ics >= 2.8'],
'neovi': ['python-ics >= 2.12'],
'test': tests_require
},

Expand Down