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
148 changes: 59 additions & 89 deletions can/interfaces/neousys/neousys.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@
# pylint: disable=too-few-public-methods
# pylint: disable=too-many-instance-attributes
# pylint: disable=wrong-import-position
# pylint: disable=method-hidden
# pylint: disable=unused-import

import warnings
import queue
import logging
import platform
import time
from time import time

from ctypes import (
byref,
Expand All @@ -33,11 +30,17 @@
Structure,
)

if platform.system() == "Windows":
try:
from ctypes import WinDLL
else:
except ImportError:
from ctypes import CDLL

from can import BusABC, Message
from ...exceptions import (
CanInitializationError,
CanOperationError,
CanInterfaceNotImplementedError,
)


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -126,111 +129,87 @@ class NeousysCanBitClk(Structure):
NEOUSYS_CANLIB = WinDLL("./WDT_DIO.dll")
else:
NEOUSYS_CANLIB = CDLL("libwdt_dio.so")
logger.info("Loaded Neousys WDT_DIO Can driver")
logger.info("Loaded Neousys WDT_DIO Can driver")
except OSError as error:
logger.info("Cannot Neousys CAN bus dll or share object: %d", format(error))
# NEOUSYS_CANLIB = None
logger.info("Cannot load Neousys CAN bus dll or shared object: %d", format(error))


class NeousysBus(BusABC):
""" Neousys CAN bus Class"""
"""Neousys CAN bus Class"""

def __init__(self, channel, device=0, bitrate=500000, **kwargs):
"""
:param channel: channel number
:param device: device number
:param bitrate: bit rate. Renamed to bitrate in next release.
:param bitrate: bit rate.
"""
super().__init__(channel, **kwargs)

if NEOUSYS_CANLIB is not None:
self.channel = channel

self.device = device
if NEOUSYS_CANLIB is None:
raise CanInterfaceNotImplementedError("Neousys WDT_DIO Can driver missing")

self.channel_info = "Neousys Can: device {}, channel {}".format(
self.device, self.channel
)
self.channel = channel
self.device = device
self.channel_info = f"Neousys Can: device {self.device}, channel {self.channel}"

self.queue = queue.Queue()
self.queue = queue.Queue()

# Init with accept all and wanted bitrate
self.init_config = NeousysCanSetup(
bitrate, NEOUSYS_CAN_MSG_USE_ID_FILTER, 0, 0
)
# Init with accept all and wanted bitrate
self.init_config = NeousysCanSetup(bitrate, NEOUSYS_CAN_MSG_USE_ID_FILTER, 0, 0)

self._neousys_recv_cb = NEOUSYS_CAN_MSG_CALLBACK(self._neousys_recv_cb)
self._neousys_status_cb = NEOUSYS_CAN_STATUS_CALLBACK(
self._neousys_status_cb
)
self._neousys_recv_cb = NEOUSYS_CAN_MSG_CALLBACK(self._neousys_recv_cb)
self._neousys_status_cb = NEOUSYS_CAN_STATUS_CALLBACK(self._neousys_status_cb)

if NEOUSYS_CANLIB.CAN_RegisterReceived(0, self._neousys_recv_cb) == 0:
logger.error("Neousys CAN bus Setup receive callback")
if NEOUSYS_CANLIB.CAN_RegisterReceived(0, self._neousys_recv_cb) == 0:
raise CanInitializationError("Neousys CAN bus Setup receive callback")

if NEOUSYS_CANLIB.CAN_RegisterStatus(0, self._neousys_status_cb) == 0:
logger.error("Neousys CAN bus Setup status callback")
if NEOUSYS_CANLIB.CAN_RegisterStatus(0, self._neousys_status_cb) == 0:
raise CanInitializationError("Neousys CAN bus Setup status callback")

if (
NEOUSYS_CANLIB.CAN_Setup(
channel, byref(self.init_config), sizeof(self.init_config)
)
== 0
):
logger.error("Neousys CAN bus Setup Error")
if (
NEOUSYS_CANLIB.CAN_Setup(
channel, byref(self.init_config), sizeof(self.init_config)
)
== 0
):
raise CanInitializationError("Neousys CAN bus Setup Error")

if NEOUSYS_CANLIB.CAN_Start(channel) == 0:
logger.error("Neousys CAN bus Start Error")
if NEOUSYS_CANLIB.CAN_Start(channel) == 0:
raise CanInitializationError("Neousys CAN bus Start Error")

def send(self, msg, timeout=None):
def send(self, msg, timeout=None) -> None:
"""
:param msg: message to send
:param timeout: timeout is not used here
:return:
"""

if NEOUSYS_CANLIB is None:
logger.error("Can't send msg as Neousys DLL/SO is not loaded")
else:
tx_msg = NeousysCanMsg(
msg.arbitration_id, 0, 0, msg.dlc, (c_ubyte * 8)(*msg.data)
)
tx_msg = NeousysCanMsg(
msg.arbitration_id, 0, 0, msg.dlc, (c_ubyte * 8)(*msg.data)
)

if (
NEOUSYS_CANLIB.CAN_Send(self.channel, byref(tx_msg), sizeof(tx_msg))
== 0
):
logger.error("Neousys Can can't send message")
if NEOUSYS_CANLIB.CAN_Send(self.channel, byref(tx_msg), sizeof(tx_msg)) == 0:
raise CanOperationError("Neousys Can can't send message")

def _recv_internal(self, timeout):
msg = None

if not self.queue.empty():
msg = self.queue.get()
try:
return self.queue.get(block=True, timeout=timeout), False
except queue.Empty:
return None, False

return msg, False

def _neousys_recv_cb(self, msg, sizeof_msg):
def _neousys_recv_cb(self, msg, sizeof_msg) -> None:
"""
:param msg struct CAN_MSG
:param sizeof_msg message number
:return:
:param msg: struct CAN_MSG
:param sizeof_msg: message number
"""
remote_frame = False
extended_frame = False

msg_bytes = bytearray(msg.contents.data)

if msg.contents.flags & NEOUSYS_CAN_MSG_REMOTE_FRAME:
remote_frame = True

if msg.contents.flags & NEOUSYS_CAN_MSG_EXTENDED_ID:
extended_frame = True
remote_frame = bool(msg.contents.flags & NEOUSYS_CAN_MSG_REMOTE_FRAME)
extended_frame = bool(msg.contents.flags & NEOUSYS_CAN_MSG_EXTENDED_ID)

if msg.contents.flags & NEOUSYS_CAN_MSG_DATA_LOST:
logger.error("_neousys_recv_cb flag CAN_MSG_DATA_LOST")

msg = Message(
timestamp=time.time(),
timestamp=time(),
arbitration_id=msg.contents.id,
is_remote_frame=remote_frame,
is_extended_id=extended_frame,
Expand All @@ -242,30 +221,21 @@ def _neousys_recv_cb(self, msg, sizeof_msg):
# Reading happens in Callback function and
# with Python-CAN it happens polling
# so cache stuff in array to for poll
if not self.queue.full():
try:
self.queue.put(msg)
else:
logger.error("Neousys message Queue is full")
except queue.Full:
raise CanOperationError("Neousys message Queue is full") from None
Comment on lines +226 to +227
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼


def _neousys_status_cb(self, status):
def _neousys_status_cb(self, status) -> None:
"""
:param status BUS Status
:return:
:param status: BUS Status
"""
logger.info("%s _neousys_status_cb: %d", self.init_config, status)

def shutdown(self):
if NEOUSYS_CANLIB is not None:
NEOUSYS_CANLIB.CAN_Stop(self.channel)

def fileno(self):
# Return an invalid file descriptor as not used
return -1
NEOUSYS_CANLIB.CAN_Stop(self.channel)

@staticmethod
def _detect_available_configs():
channels = []

# There is only one channel
channels.append({"interface": "neousys", "channel": 0})
return channels
return [{"interface": "neousys", "channel": 0}]
4 changes: 2 additions & 2 deletions test/test_neousys.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def setUp(self) -> None:
can.interfaces.neousys.neousys.NEOUSYS_CANLIB.CAN_Start = Mock(return_value=1)
can.interfaces.neousys.neousys.NEOUSYS_CANLIB.CAN_Send = Mock(return_value=1)
can.interfaces.neousys.neousys.NEOUSYS_CANLIB.CAN_Stop = Mock(return_value=1)
self.bus = can.Bus(channel=0, bustype="neousys", _testing=True)
self.bus = can.Bus(channel=0, bustype="neousys")

def tearDown(self) -> None:
if self.bus:
Expand Down Expand Up @@ -67,7 +67,7 @@ def test_bus_creation(self) -> None:
)

def test_bus_creation_bitrate(self) -> None:
self.bus = can.Bus(channel=0, bustype="neousys", bitrate=200000, _testing=True)
self.bus = can.Bus(channel=0, bustype="neousys", bitrate=200000)
self.assertIsInstance(self.bus, neousys.NeousysBus)
CAN_Start_args = (
can.interfaces.neousys.neousys.NEOUSYS_CANLIB.CAN_Setup.call_args[0]
Expand Down