diff options
author | CoprDistGit <infra@openeuler.org> | 2023-05-31 07:41:40 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2023-05-31 07:41:40 +0000 |
commit | cc3143495164bde748a3a9c5b18c5c93193a62de (patch) | |
tree | 60fdb4b4e66cdf4b2bd8208b5826c84606abc096 | |
parent | 3836dbfaecccff6054f63e96795f134e6e0a0efc (diff) |
automatic import of python-canalystii
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | python-canalystii.spec | 262 | ||||
-rw-r--r-- | sources | 1 |
3 files changed, 264 insertions, 0 deletions
@@ -0,0 +1 @@ +/canalystii-0.1.tar.gz diff --git a/python-canalystii.spec b/python-canalystii.spec new file mode 100644 index 0000000..c26311d --- /dev/null +++ b/python-canalystii.spec @@ -0,0 +1,262 @@ +%global _empty_manifest_terminate_build 0 +Name: python-canalystii +Version: 0.1 +Release: 1 +Summary: Python userspace driver for Canalyst-II USB CAN analyzer. +License: BSD +URL: https://github.com/projectgus/python-canalystii +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/46/54/8831c2b8fb593eaf6fbc450223f5ed0a208ce0d329ba94946eb06420ad86/canalystii-0.1.tar.gz +BuildArch: noarch + +Requires: python3-pyusb + +%description + +# Canalyst-II Driver for Python + +Unofficial Python userspace driver for the low cost USB analyzer "Canalyst-II" by Chuangxin Technology (创芯科技). + +Uses [pyusb](https://pyusb.github.io/pyusb/) library for USB support on Windows, MacOS and Linux. + +This driver is based on black box reverse engineering of the USB behaviour of the proprietary software, and reading the basic data structure layouts in the original python-can canalystii source. + +Intended for use as a backend driver for [python-can](https://python-can.readthedocs.io/). However it can also be used standalone. + +## Standalone Usage + +```py +import canalystii + +# Connect to the Canalyst-II device +# Passing a bitrate to the constructor causes both channels to be initialized and started. +dev = canalystii.CanalystDevice(bitrate=500000) + +# Receive all pending messages on channel 0 +for msg in dev.receive(0): + print(msg) + +# The canalystii.Message class is a ctypes Structure, to minimize overhead +new_message = canalystii.Message(can_id=0x300, + remote=False, + extended=False, + data_len=8, + data=(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08)) +# Send one copy to channel 1 +dev.send(1, new_message) +# Send 3 copies to channel 0 +# (argument can be an instance of canalystii.Message or a list of instances) +dev.send(0, [new_message] * 3) + +# Stop both channels (need to call start() again to resume capturing or send any messages) +dev.stop(0) +dev.stop(1) +``` + +## Limitations + +Currently, the following things are not supported and may not be possible based on the known USB protocol: + +* CAN bus error conditions. There is a function `get_can_status()` that seems to provide access to some internal device state, not clear if this can be used to determine when errors occured or invalid messages seen. +* Receive buffer hardware overflow detection (see Performance, below). +* ACK status of sent CAN messages. +* Failure status of sent CAN messages. If the device fails to get bus arbitration after some unknown amount of time, it will drop the message silently. +* Hardware filtering of incoming messages. There is a `filter` field of `InitCommand` structure, not clear how it works. +* Configuring whether messages are ACKed by Canalyst-II. This may be possible, see `InitCommand` `acc_code` and `acc_mask`. + +## Performance + +Because the Canalyst-II USB protocol requires polling, the host needs to constantly poll the device to request any new CAN messages. There is a trade-off of CPU usage against both latency and maximum receive throughput. + +The hardware seems able to buffer 1000-2000 messages (possibly a little more) per channel. The maximum number seems to depend on relative timing of the messages. Therefore, if a 1Mbps (maximum speed) CAN channel is receiving the maximum possible ~7800 messages/second then software should call `receive()` at least every 100ms in order to avoid lost messages. It's not possible to tell if any messages in the hardware buffer were lost due to overflow. + +Testing Linux CPython 3.9 on a i7-6500U CPU (~2016 vintage), calling `receive()` in a tight loop while receiving maximum message rate (~7800 messages/sec) on both channels (~15600 messages/sec total) uses approximately 40% of a single CPU. Adding a 50ms delay `time.sleep(0.05)` in the loop drops CPU usage to around 10% without losing any messages. Longer sleep periods in the loop reduce CPU usage further but some messages are dropped. See the `tests/can_spammer_test.py` file for the test code. + +In systems where the CAN message rate is lower than the maximum, `receive()` can be called less frequently without losing messages. In systems where the Python process may be pre-empted, it's possible for messages to be lost anyhow. + + + + +%package -n python3-canalystii +Summary: Python userspace driver for Canalyst-II USB CAN analyzer. +Provides: python-canalystii +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-canalystii + +# Canalyst-II Driver for Python + +Unofficial Python userspace driver for the low cost USB analyzer "Canalyst-II" by Chuangxin Technology (创芯科技). + +Uses [pyusb](https://pyusb.github.io/pyusb/) library for USB support on Windows, MacOS and Linux. + +This driver is based on black box reverse engineering of the USB behaviour of the proprietary software, and reading the basic data structure layouts in the original python-can canalystii source. + +Intended for use as a backend driver for [python-can](https://python-can.readthedocs.io/). However it can also be used standalone. + +## Standalone Usage + +```py +import canalystii + +# Connect to the Canalyst-II device +# Passing a bitrate to the constructor causes both channels to be initialized and started. +dev = canalystii.CanalystDevice(bitrate=500000) + +# Receive all pending messages on channel 0 +for msg in dev.receive(0): + print(msg) + +# The canalystii.Message class is a ctypes Structure, to minimize overhead +new_message = canalystii.Message(can_id=0x300, + remote=False, + extended=False, + data_len=8, + data=(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08)) +# Send one copy to channel 1 +dev.send(1, new_message) +# Send 3 copies to channel 0 +# (argument can be an instance of canalystii.Message or a list of instances) +dev.send(0, [new_message] * 3) + +# Stop both channels (need to call start() again to resume capturing or send any messages) +dev.stop(0) +dev.stop(1) +``` + +## Limitations + +Currently, the following things are not supported and may not be possible based on the known USB protocol: + +* CAN bus error conditions. There is a function `get_can_status()` that seems to provide access to some internal device state, not clear if this can be used to determine when errors occured or invalid messages seen. +* Receive buffer hardware overflow detection (see Performance, below). +* ACK status of sent CAN messages. +* Failure status of sent CAN messages. If the device fails to get bus arbitration after some unknown amount of time, it will drop the message silently. +* Hardware filtering of incoming messages. There is a `filter` field of `InitCommand` structure, not clear how it works. +* Configuring whether messages are ACKed by Canalyst-II. This may be possible, see `InitCommand` `acc_code` and `acc_mask`. + +## Performance + +Because the Canalyst-II USB protocol requires polling, the host needs to constantly poll the device to request any new CAN messages. There is a trade-off of CPU usage against both latency and maximum receive throughput. + +The hardware seems able to buffer 1000-2000 messages (possibly a little more) per channel. The maximum number seems to depend on relative timing of the messages. Therefore, if a 1Mbps (maximum speed) CAN channel is receiving the maximum possible ~7800 messages/second then software should call `receive()` at least every 100ms in order to avoid lost messages. It's not possible to tell if any messages in the hardware buffer were lost due to overflow. + +Testing Linux CPython 3.9 on a i7-6500U CPU (~2016 vintage), calling `receive()` in a tight loop while receiving maximum message rate (~7800 messages/sec) on both channels (~15600 messages/sec total) uses approximately 40% of a single CPU. Adding a 50ms delay `time.sleep(0.05)` in the loop drops CPU usage to around 10% without losing any messages. Longer sleep periods in the loop reduce CPU usage further but some messages are dropped. See the `tests/can_spammer_test.py` file for the test code. + +In systems where the CAN message rate is lower than the maximum, `receive()` can be called less frequently without losing messages. In systems where the Python process may be pre-empted, it's possible for messages to be lost anyhow. + + + + +%package help +Summary: Development documents and examples for canalystii +Provides: python3-canalystii-doc +%description help + +# Canalyst-II Driver for Python + +Unofficial Python userspace driver for the low cost USB analyzer "Canalyst-II" by Chuangxin Technology (创芯科技). + +Uses [pyusb](https://pyusb.github.io/pyusb/) library for USB support on Windows, MacOS and Linux. + +This driver is based on black box reverse engineering of the USB behaviour of the proprietary software, and reading the basic data structure layouts in the original python-can canalystii source. + +Intended for use as a backend driver for [python-can](https://python-can.readthedocs.io/). However it can also be used standalone. + +## Standalone Usage + +```py +import canalystii + +# Connect to the Canalyst-II device +# Passing a bitrate to the constructor causes both channels to be initialized and started. +dev = canalystii.CanalystDevice(bitrate=500000) + +# Receive all pending messages on channel 0 +for msg in dev.receive(0): + print(msg) + +# The canalystii.Message class is a ctypes Structure, to minimize overhead +new_message = canalystii.Message(can_id=0x300, + remote=False, + extended=False, + data_len=8, + data=(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08)) +# Send one copy to channel 1 +dev.send(1, new_message) +# Send 3 copies to channel 0 +# (argument can be an instance of canalystii.Message or a list of instances) +dev.send(0, [new_message] * 3) + +# Stop both channels (need to call start() again to resume capturing or send any messages) +dev.stop(0) +dev.stop(1) +``` + +## Limitations + +Currently, the following things are not supported and may not be possible based on the known USB protocol: + +* CAN bus error conditions. There is a function `get_can_status()` that seems to provide access to some internal device state, not clear if this can be used to determine when errors occured or invalid messages seen. +* Receive buffer hardware overflow detection (see Performance, below). +* ACK status of sent CAN messages. +* Failure status of sent CAN messages. If the device fails to get bus arbitration after some unknown amount of time, it will drop the message silently. +* Hardware filtering of incoming messages. There is a `filter` field of `InitCommand` structure, not clear how it works. +* Configuring whether messages are ACKed by Canalyst-II. This may be possible, see `InitCommand` `acc_code` and `acc_mask`. + +## Performance + +Because the Canalyst-II USB protocol requires polling, the host needs to constantly poll the device to request any new CAN messages. There is a trade-off of CPU usage against both latency and maximum receive throughput. + +The hardware seems able to buffer 1000-2000 messages (possibly a little more) per channel. The maximum number seems to depend on relative timing of the messages. Therefore, if a 1Mbps (maximum speed) CAN channel is receiving the maximum possible ~7800 messages/second then software should call `receive()` at least every 100ms in order to avoid lost messages. It's not possible to tell if any messages in the hardware buffer were lost due to overflow. + +Testing Linux CPython 3.9 on a i7-6500U CPU (~2016 vintage), calling `receive()` in a tight loop while receiving maximum message rate (~7800 messages/sec) on both channels (~15600 messages/sec total) uses approximately 40% of a single CPU. Adding a 50ms delay `time.sleep(0.05)` in the loop drops CPU usage to around 10% without losing any messages. Longer sleep periods in the loop reduce CPU usage further but some messages are dropped. See the `tests/can_spammer_test.py` file for the test code. + +In systems where the CAN message rate is lower than the maximum, `receive()` can be called less frequently without losing messages. In systems where the Python process may be pre-empted, it's possible for messages to be lost anyhow. + + + + +%prep +%autosetup -n canalystii-0.1 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-canalystii -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Wed May 31 2023 Python_Bot <Python_Bot@openeuler.org> - 0.1-1 +- Package Spec generated @@ -0,0 +1 @@ +ed736049c029cadd4de2ffff0578efe3 canalystii-0.1.tar.gz |