Docs: Refactor
parent
008a0e4057
commit
648fb2502f
|
|
@ -0,0 +1,15 @@
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
build:
|
||||||
|
os: "ubuntu-24.04"
|
||||||
|
tools:
|
||||||
|
python: "3.12"
|
||||||
|
apt_packages:
|
||||||
|
- doxygen
|
||||||
|
|
||||||
|
python:
|
||||||
|
install:
|
||||||
|
- requirements: docs/icsneopy/requirements.txt
|
||||||
|
|
||||||
|
sphinx:
|
||||||
|
configuration: docs/conf.py
|
||||||
64
HARDWARE.md
64
HARDWARE.md
|
|
@ -1,64 +0,0 @@
|
||||||
# Hardware Support
|
|
||||||
|
|
||||||
- Connecting over Ethernet
|
|
||||||
- neoVI FIRE 2
|
|
||||||
- CAN works
|
|
||||||
- CAN FD works
|
|
||||||
- ValueCAN 4-2EL
|
|
||||||
- CAN works
|
|
||||||
- CAN FD works
|
|
||||||
- Ethernet works
|
|
||||||
- RADGalaxy
|
|
||||||
- CAN works
|
|
||||||
- Ethernet works
|
|
||||||
- RADStar 2
|
|
||||||
- CAN works
|
|
||||||
- Ethernet works
|
|
||||||
- RADA2B
|
|
||||||
- CAN works
|
|
||||||
- Ethernet works
|
|
||||||
- RADComet
|
|
||||||
- CAN works
|
|
||||||
- CAN FD works
|
|
||||||
- Ethernet works
|
|
||||||
- RADComet3
|
|
||||||
- CAN works
|
|
||||||
- Ethernet works
|
|
||||||
- neoVI Connect
|
|
||||||
- CAN works
|
|
||||||
- CAN FD works
|
|
||||||
- Ethernet works
|
|
||||||
- RADGigastar2
|
|
||||||
|
|
||||||
- Connecting over USB
|
|
||||||
- ValueCAN 4 series
|
|
||||||
- CAN works
|
|
||||||
- CAN FD works
|
|
||||||
- Ethernet works (on 4-2EL)
|
|
||||||
- neoOBD2 PRO
|
|
||||||
- CAN works
|
|
||||||
- neoVI FIRE
|
|
||||||
- CAN works
|
|
||||||
- neoVI FIRE 2
|
|
||||||
- CAN works
|
|
||||||
- CAN FD works
|
|
||||||
- Ethernet works
|
|
||||||
- ValueCAN 3
|
|
||||||
- CAN works
|
|
||||||
- RADStar 2
|
|
||||||
- CAN works
|
|
||||||
- Ethernet works
|
|
||||||
- neoVI PLASMA
|
|
||||||
- CAN works
|
|
||||||
- neoVI ION
|
|
||||||
- CAN works
|
|
||||||
- RADA2B
|
|
||||||
- CAN works
|
|
||||||
- Ethernet works
|
|
||||||
- RADMoon3
|
|
||||||
- RADComet3
|
|
||||||
- CAN works
|
|
||||||
- Ethernet works
|
|
||||||
- RADMoonT1S
|
|
||||||
- Ethernet works
|
|
||||||
- RADGigastar2
|
|
||||||
202
README.md
202
README.md
|
|
@ -1,176 +1,42 @@
|
||||||
# libicsneo
|
# libicsneo
|
||||||
### The Intrepid Control Systems Open Source Cross-Platform Device Communication API
|
|
||||||
|
|
||||||
An open source solution to integrate Intrepid Control Systems vehicle networking hardware with your application.
|
libicsneo is the [Intrepid Control Systems](https://intrepidcs.com/) device
|
||||||
|
communication library. Installation and usage documentation can be found within
|
||||||
|
each of the respective APIs.
|
||||||
|
|
||||||
[Read the Full Documentation](https://libicsneo.readthedocs.io/)
|
## Documentation
|
||||||
|
|
||||||
## Getting Started
|
- [C++](https://libicsneo.readthedocs.io/en/latest/icsneocpp/)
|
||||||
There are two major ways to write a new application using libicsneo. You can use the C++ interface, which will be compiled with your project and statically linked, or you can use the C interface, which can be either statically or dynamically linked.
|
- [Python](https://libicsneo.readthedocs.io/en/latest/icsneopy/)
|
||||||
### Integration with CMake (Static Linking)
|
- [C](https://libicsneo.readthedocs.io/en/latest/icsneoc/)
|
||||||
Integrating the library with your current CMake project is extremely easy.
|
|
||||||
1. Checkout the library (or add as a submodule) into a subdirectory of your project.
|
|
||||||
2. Within your `CMakeLists.txt` you can add the line `add_subdirectory("third-party/libicsneo")` to bring in the libicsneo targets. Replace `third-party` with any subdirectory you choose.
|
|
||||||
3. The libicsneo library include paths should automatically be added to your include path.
|
|
||||||
4. Link the library with your target by adding `target_link_libraries(libicsneocpp-example icsneocpp)` after your target, substituting `libicsneocpp-example` with your target application.
|
|
||||||
|
|
||||||
You can now include either the C++ API with `#include <icsneo/icsneocpp.h>` or the C API with `#include <icsneo/icsneoc.h>`
|
## Hardware Support
|
||||||
|
|
||||||
### DLL / SO / DYLIB Releases (Dynamic Linking)
|
- EtherBADGE
|
||||||
It is also possible to use the precompiled binaries with runtime linking. It is not recommended or supported to attempt to use the C++ interface with dynamic linking due to the complexities of C++ compilers.
|
- neoVI Connect
|
||||||
1. Add this repository's `/include` to your include path
|
- neoVI FIRE
|
||||||
2. Add `#define ICSNEOC_DYNAMICLOAD` to the top of your source file
|
- neoVI FIRE 2
|
||||||
2. Add `#import <icsneo/icsneoc.h>` below that line
|
- neoVI FIRE 3
|
||||||
3. Call `icsneo_init();` to import the library before using any other libicsneo functions.
|
- neoVI ION
|
||||||
4. Use the library as normal.
|
- neoVI PLASMA
|
||||||
5. Call `icsneo_close();` to unload the library.
|
- neoVI RED 2
|
||||||
|
- RAD-A2B
|
||||||
|
- RAD-Comet 2
|
||||||
|
- RAD-Comet 3
|
||||||
|
- RAD-Galaxy
|
||||||
|
- RAD-Gigastar
|
||||||
|
- RAD-Gigastar 2
|
||||||
|
- RAD-Moon 2
|
||||||
|
- RAD-Moon 3
|
||||||
|
- RAD-Moon T1S
|
||||||
|
- RAD-Pluto
|
||||||
|
- RAD-Star 2
|
||||||
|
- RAD-SuperMoon
|
||||||
|
- RADComet
|
||||||
|
- ValueCAN 3
|
||||||
|
- ValueCAN 4
|
||||||
|
|
||||||
## Usage
|
## License
|
||||||
### Using the C++ API
|
|
||||||
The C++ API is designed to be modern and easy to use. All library functions and classes are in the namespace `icsneo`. Most applications will start by calling `icsneo::FindAllDevices()`. This will return an `std::vector` of `std::shared_ptr<icsneo::Device>` objects. You will want to keep a copy of the `shared_ptr` to any devices you want to use, as allowing it to go out of scope will automatically close the device and free all memory associated with it.
|
|
||||||
|
|
||||||
Any time you get bus traffic from the API, you will receive it as an `std::shared_ptr<icsneo::Message>`. The message will be valid as long as the `shared_ptr` stays in scope. Checking the type of the message allows you to cast it accordingly and access extra data for certain protocols. For instance, casting an `icsneo::Message` to an `icsneo::CANMessage` allows you to access the arbitration ID.
|
libicsneo is licensed as BSD-3 with an extra clause, see [LICENSE](LICENSE)
|
||||||
|
for more details.
|
||||||
A barebones example is provided. For a more complete example, check the included `examples`.
|
|
||||||
``` c++
|
|
||||||
std::vector<std::shared_ptr<icsneo::Device>> devices = icsneo::FindAllDevices();
|
|
||||||
std::cout << devices.size() << " found!" << std::endl;
|
|
||||||
for(auto& device : devices)
|
|
||||||
std::cout << "Found " << device->describe() << std::endl; // "Found neoVI FIRE 2 CY2345"
|
|
||||||
std::shared_ptr<icsneo::Device> myDevice = devices[0];
|
|
||||||
|
|
||||||
if(!myDevice->open()) // Device tried and failed to open, print the last error
|
|
||||||
std::cout << icsneo::GetLastError() << std::endl;
|
|
||||||
|
|
||||||
myDevice->goOnline(); // Start receiving messages
|
|
||||||
myDevice->enableMessagePolling(); // Allow the use of myDevice->getMessages() later
|
|
||||||
// Alternatively, assign a callback for new messages
|
|
||||||
std::this_thread::wait_for(std::chrono::seconds(5));
|
|
||||||
std::vector<std::shared_ptr<icsneo::Message>> messages = myDevice->getMessages();
|
|
||||||
std::cout << "We got " << messages.size() << " messages!" << std::endl;
|
|
||||||
for(auto& msg : messages) {
|
|
||||||
switch(msg->network.getType()) {
|
|
||||||
case icsneo::Network::Type::CAN:
|
|
||||||
case icsneo::Network::Type::SWCAN:
|
|
||||||
case icsneo::Network::Type::LSFTCAN: {
|
|
||||||
// A message of type CAN is guaranteed to be a CANMessage, so we can static cast safely
|
|
||||||
auto canmsg = std::static_pointer_cast<icsneo::CANMessage>(msg);
|
|
||||||
// canmsg->arbid is valid here
|
|
||||||
// canmsg->data is an std::vector<uint8_t>, you can check .size() for the DLC of the message
|
|
||||||
// canmsg->timestamp is the time recorded by the hardware in nanoseconds since (1/1/2007 12:00:00 GMT)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// Handle others
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myDevice->close();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using the C API
|
|
||||||
The C API is designed to be a robust and fault tolerant interface which allows easy integration with other languages as well as existing C applications. When calling `icsneo_findAllDevices()` you will provide a buffer of `neodevice_t` structures, which will be written with the found devices. These `neodevice_t` structures can be uses to interface with the API from then on. Once you call `icsneo_close()` with a device, that device and all associated memory will be freed. You will need to run `icsneo_findAllDevices()` again to reconnect.
|
|
||||||
|
|
||||||
Messages are passed in the form of `neomessage_t` structures when calling `icsneo_getMessages()`. These structures contain a `uint8_t*` to the payload data, and this pointer will be valid until the next call to `icsneo_getMessages()` or the device is closed.
|
|
||||||
|
|
||||||
A barebones example is provided. For a more complete example, check the included `examples`.
|
|
||||||
``` c
|
|
||||||
size_t deviceCount = 10; // Pre-set to the size of your buffer before the icsneo_findAllDevices() call
|
|
||||||
neodevice_t devices[10];
|
|
||||||
icsneo_findAllDevices(devices, &deviceCount);
|
|
||||||
printf("We found %ull devices\n", deviceCount);
|
|
||||||
for(size_t i = 0; i < deviceCount; i++) {
|
|
||||||
neodevice_t* myDevice = &devices[i];
|
|
||||||
char desc[ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION];
|
|
||||||
size_t sz = ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION;
|
|
||||||
icsneo_describeDevice(myDevice, desc, &sz);
|
|
||||||
printf("Found %s\n", desc); // "Found neoVI FIRE 2 CY2345"
|
|
||||||
}
|
|
||||||
|
|
||||||
neodevice_t* myDevice = &devices[0];
|
|
||||||
if(!icsneo_openDevice(myDevice)) {
|
|
||||||
neoevent_t error;
|
|
||||||
if(icsneo_getLastError(&error))
|
|
||||||
printf("Error! %s\n", error.description);
|
|
||||||
}
|
|
||||||
icsneo_goOnline(myDevice); // Start receiving messages
|
|
||||||
icsneo_enableMessagePolling(myDevice); // Allow the use of icsneo_getMessages() later
|
|
||||||
sleep(5);
|
|
||||||
neomessage_t messages[50];
|
|
||||||
size_t messageCount = 50;
|
|
||||||
icsneo_getMessages(myDevice, messages, &messageCount, 0 /* non-blocking */);
|
|
||||||
printf("We got %ull messages!\n", messageCount);
|
|
||||||
for(size_t i = 0; i < messageCount; i++) {
|
|
||||||
if(messages[i].type == ICSNEO_NETWORK_TYPE_CAN) {
|
|
||||||
// A message of type CAN should be interperated a neomessage_can_t, so we can cast safely
|
|
||||||
neomessage_can_t* canmsg = (neomessage_can_t*)&messages[i];
|
|
||||||
// canmsg->arbid is valid here
|
|
||||||
// canmsg->data is an uint8_t*, you can check canmsg->length for the length of the payload
|
|
||||||
// canmsg->timestamp is the time recorded by the hardware in nanoseconds since (1/1/2007 12:00:00 GMT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
icsneo_closeDevice(myDevice);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debugging
|
|
||||||
|
|
||||||
To enable debug printing set the `LIBICSNEO_PRINT_EVENTS` environmental variable to the desired `APIEvent::Severity` level, all `Event`s greater than or equal to that level will be printed to stderr. For example, to print all warnings and errors: `LIBICSNEO_PRINT_EVENTS=32`.
|
|
||||||
|
|
||||||
## Building from Source
|
|
||||||
### FTD3XX
|
|
||||||
Some devices require FTD3XX for USB communication so the [FTDI D3XX library](https://ftdichip.com/drivers/d3xx-drivers/) will be automatically downloaded and included. If you would like to use a system copy of D3XX instead you can set `FTD3XX_ROOT` to the path containing `f3d3xx.h` (`-DFTD3XX_ROOT=<path to directory containing ftd3xx.h>`).
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
- Open a terminal and install the following:
|
|
||||||
```
|
|
||||||
winget install Microsoft.VisualStudio.2022.Community
|
|
||||||
winget install Kitware.CMake
|
|
||||||
winget install Git.Git
|
|
||||||
winget install Ninja-build.Ninja
|
|
||||||
```
|
|
||||||
- Reboot so cmake is in the system path
|
|
||||||
- Open a developer Powershell for VS2022 and run the following:
|
|
||||||
```
|
|
||||||
git clone https://github.com/intrepidcs/libicsneo
|
|
||||||
cd libicsneo
|
|
||||||
cmake -S . -B build -G "Ninja"
|
|
||||||
cmake --build build
|
|
||||||
# All dlls and libs are now inside the build directory
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Building will require MSVC 2017 version 15.7 or newer and CMake to be installed.
|
|
||||||
### macOS
|
|
||||||
Getting the dependencies is easiest with the Homebrew package manager. You will also need XCode installed. You can then install CMake, an up-to-date version of GCC or Clang, and `libusb-1.0`.
|
|
||||||
### Linux
|
|
||||||
#### General Dependencies
|
|
||||||
- CMake 3.12 or above
|
|
||||||
- GCC 7 or above
|
|
||||||
- `libusb-1.0-0-dev`
|
|
||||||
- `libpcap0.8-dev`
|
|
||||||
- `build-essential` is recommended
|
|
||||||
|
|
||||||
#### Fedora
|
|
||||||
```
|
|
||||||
dnf install git @development-tools gcc-c++ libpcap-devel libusb1-devel cmake
|
|
||||||
```
|
|
||||||
#### Debian/Ubuntu
|
|
||||||
```
|
|
||||||
apt install git build-essential libpcap0.8-dev libusb-1.0-0-dev cmake
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Building
|
|
||||||
```
|
|
||||||
git clone https://github.com/intrepidcs/libicsneo
|
|
||||||
cd libicsneo
|
|
||||||
cmake -S . -B build
|
|
||||||
cmake --build build
|
|
||||||
# Optional: Install globally:
|
|
||||||
cp *.so /usr/local/lib/
|
|
||||||
```
|
|
||||||
|
|
||||||
#### udev
|
|
||||||
If you'd like to be able to run programs that use this library without being root, consider using the included udev rules:
|
|
||||||
|
|
||||||
```
|
|
||||||
cp 99-intrepidcs.rules /etc/udev/rules.d/
|
|
||||||
udevadm control --reload-rules && udevadm trigger
|
|
||||||
```
|
|
||||||
|
|
|
||||||
190
docs/conf.py
190
docs/conf.py
|
|
@ -1,188 +1,36 @@
|
||||||
#!/usr/bin/env python3
|
# Configuration file for the Sphinx documentation builder.
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
#
|
||||||
# NOTE: The conf.py file is automatically updated by CMake when there are
|
# For the full list of built-in configuration values, see the documentation:
|
||||||
# changes to the version. Update the conf.py.template and then build to
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
# propagate changes here. This file should be committed so that
|
|
||||||
# ReadTheDocs can use it.
|
|
||||||
#
|
|
||||||
# This file is execfile()d with the current directory set to its
|
|
||||||
# containing dir.
|
|
||||||
#
|
|
||||||
# Note that not all possible configuration values are present in this
|
|
||||||
# autogenerated file.
|
|
||||||
#
|
|
||||||
# All configuration values have a default; values that are commented out
|
|
||||||
# serve to show the default.
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
#
|
|
||||||
import os
|
|
||||||
import subprocess
|
import subprocess
|
||||||
# import sys
|
|
||||||
# sys.path.insert(0, os.path.abspath('.'))
|
|
||||||
|
|
||||||
|
subprocess.call('cd ..; doxygen docs/icsneocpp/Doxyfile', shell=True)
|
||||||
|
subprocess.call('cd ..; doxygen docs/icsneoc/Doxyfile', shell=True)
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
|
||||||
#
|
|
||||||
# needs_sphinx = '1.0'
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
||||||
# ones.
|
|
||||||
extensions = ['sphinx.ext.imgmath', 'sphinx.ext.todo', 'breathe' ]
|
|
||||||
|
|
||||||
breathe_projects = { "libicsneo": "build/doxygen/xml" }
|
|
||||||
breathe_default_project = "libicsneo"
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.makedirs('build/sphinx')
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
os.makedirs('build/doxygen')
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
subprocess.call('cd ..; doxygen docs/Doxyfile', shell=True)
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix(es) of source filenames.
|
|
||||||
# You can specify multiple suffix as a list of string:
|
|
||||||
#
|
|
||||||
# source_suffix = ['.rst', '.md']
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = 'libicsneo'
|
project = 'libicsneo'
|
||||||
copyright = '2018-2024, Intrepid Control Systems, Inc.'
|
copyright = '2024, Intrepid Control Systems, Inc.'
|
||||||
author = 'Intrepid Control Systems, Inc.'
|
author = 'Intrepid Control Systems, Inc.'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# -- General configuration ---------------------------------------------------
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||||
# built documents.
|
|
||||||
#
|
|
||||||
# The short X.Y version.
|
|
||||||
version = '0.2.0'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = '0.2.0 '
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
extensions = ['breathe', 'sphinx.ext.autodoc']
|
||||||
# for a list of supported languages.
|
|
||||||
#
|
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
|
||||||
# Usually you set "language" from the command line for these cases.
|
|
||||||
language = None
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
templates_path = ['_templates']
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
# This patterns also effect to html_static_path and html_extra_path
|
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
breathe_projects = {
|
||||||
pygments_style = 'sphinx'
|
'icsneocpp': 'icsneocpp/doxygen/xml',
|
||||||
|
'icsneoc': 'icsneoc/doxygen/xml',
|
||||||
|
}
|
||||||
|
|
||||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
breathe_default_project = 'icsneocpp'
|
||||||
todo_include_todos = False
|
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||||
|
|
||||||
# -- Options for HTML output ----------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
#
|
|
||||||
html_theme = 'sphinx_rtd_theme'
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
|
||||||
# further. For a list of options available for each theme, see the
|
|
||||||
# documentation.
|
|
||||||
#
|
|
||||||
html_theme_options = {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# Custom sidebar templates, must be a dictionary that maps document names
|
|
||||||
# to template names.
|
|
||||||
#
|
|
||||||
# This is required for the alabaster theme
|
|
||||||
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
|
||||||
html_sidebars = {
|
|
||||||
'**': [
|
|
||||||
'relations.html', # needs 'show_related': True theme option to display
|
|
||||||
'searchbox.html',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTMLHelp output ------------------------------------------
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = 'libicsneodoc'
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output ---------------------------------------------
|
|
||||||
|
|
||||||
latex_elements = {
|
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
|
||||||
#
|
|
||||||
# 'papersize': 'letterpaper',
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#
|
|
||||||
# 'pointsize': '10pt',
|
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
#
|
|
||||||
# 'preamble': '',
|
|
||||||
|
|
||||||
# Latex figure (float) alignment
|
|
||||||
#
|
|
||||||
# 'figure_align': 'htbp',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
|
||||||
# (source start file, target name, title,
|
|
||||||
# author, documentclass [howto, manual, or own class]).
|
|
||||||
latex_documents = [
|
|
||||||
(master_doc, 'libicsneo.tex', 'libicsneo Documentation',
|
|
||||||
'Intrepid Control Systems, Inc.', 'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ---------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
(master_doc, 'libicsneo', 'libicsneo Documentation',
|
|
||||||
[author], 1)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -------------------------------------------
|
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
|
||||||
# (source start file, target name, title, author,
|
|
||||||
# dir menu entry, description, category)
|
|
||||||
texinfo_documents = [
|
|
||||||
(master_doc, 'libicsneo', 'libicsneo Documentation',
|
|
||||||
author, 'libicsneo', 'One line description of project.',
|
|
||||||
'Miscellaneous'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# NOTE: The conf.py file is automatically updated by CMake when there are
|
|
||||||
# changes to the version. Update the conf.py.template and then build to
|
|
||||||
# propagate changes here. This file should be committed so that
|
|
||||||
# ReadTheDocs can use it.
|
|
||||||
#
|
|
||||||
# This file is execfile()d with the current directory set to its
|
|
||||||
# containing dir.
|
|
||||||
#
|
|
||||||
# Note that not all possible configuration values are present in this
|
|
||||||
# autogenerated file.
|
|
||||||
#
|
|
||||||
# All configuration values have a default; values that are commented out
|
|
||||||
# serve to show the default.
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
#
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
# import sys
|
|
||||||
# sys.path.insert(0, os.path.abspath('.'))
|
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
|
||||||
#
|
|
||||||
# needs_sphinx = '1.0'
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
||||||
# ones.
|
|
||||||
extensions = ['sphinx.ext.imgmath', 'sphinx.ext.todo', 'breathe' ]
|
|
||||||
|
|
||||||
breathe_projects = { "libicsneo": "build/doxygen/xml" }
|
|
||||||
breathe_default_project = "libicsneo"
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.makedirs('build/sphinx')
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
os.makedirs('build/doxygen')
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
subprocess.call('cd ..; doxygen docs/Doxyfile', shell=True)
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix(es) of source filenames.
|
|
||||||
# You can specify multiple suffix as a list of string:
|
|
||||||
#
|
|
||||||
# source_suffix = ['.rst', '.md']
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = 'libicsneo'
|
|
||||||
copyright = '2018-2024, Intrepid Control Systems, Inc.'
|
|
||||||
author = 'Intrepid Control Systems, Inc.'
|
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
|
||||||
# |version| and |release|, also used in various other places throughout the
|
|
||||||
# built documents.
|
|
||||||
#
|
|
||||||
# The short X.Y version.
|
|
||||||
version = '@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = '@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@ @BUILD_METADATA@'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#
|
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
|
||||||
# Usually you set "language" from the command line for these cases.
|
|
||||||
language = None
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
# This patterns also effect to html_static_path and html_extra_path
|
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
|
||||||
todo_include_todos = False
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output ----------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
#
|
|
||||||
html_theme = 'sphinx_rtd_theme'
|
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
|
||||||
# further. For a list of options available for each theme, see the
|
|
||||||
# documentation.
|
|
||||||
#
|
|
||||||
html_theme_options = {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# Custom sidebar templates, must be a dictionary that maps document names
|
|
||||||
# to template names.
|
|
||||||
#
|
|
||||||
# This is required for the alabaster theme
|
|
||||||
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
|
||||||
html_sidebars = {
|
|
||||||
'**': [
|
|
||||||
'relations.html', # needs 'show_related': True theme option to display
|
|
||||||
'searchbox.html',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTMLHelp output ------------------------------------------
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = 'libicsneodoc'
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output ---------------------------------------------
|
|
||||||
|
|
||||||
latex_elements = {
|
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
|
||||||
#
|
|
||||||
# 'papersize': 'letterpaper',
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#
|
|
||||||
# 'pointsize': '10pt',
|
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
#
|
|
||||||
# 'preamble': '',
|
|
||||||
|
|
||||||
# Latex figure (float) alignment
|
|
||||||
#
|
|
||||||
# 'figure_align': 'htbp',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
|
||||||
# (source start file, target name, title,
|
|
||||||
# author, documentclass [howto, manual, or own class]).
|
|
||||||
latex_documents = [
|
|
||||||
(master_doc, 'libicsneo.tex', 'libicsneo Documentation',
|
|
||||||
'Intrepid Control Systems, Inc.', 'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ---------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
(master_doc, 'libicsneo', 'libicsneo Documentation',
|
|
||||||
[author], 1)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -------------------------------------------
|
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
|
||||||
# (source start file, target name, title, author,
|
|
||||||
# dir menu entry, description, category)
|
|
||||||
texinfo_documents = [
|
|
||||||
(master_doc, 'libicsneo', 'libicsneo Documentation',
|
|
||||||
author, 'libicsneo', 'One line description of project.',
|
|
||||||
'Miscellaneous'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
********************
|
|
||||||
**C API** (icsneoc)
|
|
||||||
********************
|
|
||||||
|
|
||||||
.. Usage
|
|
||||||
.. ======
|
|
||||||
|
|
||||||
.. Finding Devices
|
|
||||||
.. ~~~~~~~~~~~~~~~~
|
|
||||||
.. Finding a device is simple
|
|
||||||
|
|
||||||
.. Connecting to Devices
|
|
||||||
.. ~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Reference
|
|
||||||
==========
|
|
||||||
|
|
||||||
Typedefs
|
|
||||||
~~~~~~~~~
|
|
||||||
.. doxygentypedef:: devicehandle_t
|
|
||||||
.. doxygentypedef:: neodevice_handle_t
|
|
||||||
.. doxygentypedef:: devicetype_t
|
|
||||||
|
|
||||||
Structures
|
|
||||||
~~~~~~~~~~~
|
|
||||||
.. doxygenstruct:: neoversion_t
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
|
|
||||||
.. doxygenstruct:: neodevice_t
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
|
|
||||||
.. doxygenstruct:: neomessage_t
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
|
|
||||||
.. doxygenstruct:: neomessage_can_t
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
|
|
||||||
Functions
|
|
||||||
~~~~~~~~~~
|
|
||||||
.. doxygenfile:: icsneoc.h
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,14 @@
|
||||||
|
=====
|
||||||
|
C API
|
||||||
|
=====
|
||||||
|
|
||||||
|
.. doxygenfile:: icsneoc.h
|
||||||
|
:project: icsneoc
|
||||||
|
.. doxygenfile:: device/neodevice.h
|
||||||
|
:project: icsneoc
|
||||||
|
.. doxygenfile:: communication/message/neomessage.h
|
||||||
|
:project: icsneoc
|
||||||
|
.. doxygenfile:: api/version.h
|
||||||
|
:project: icsneoc
|
||||||
|
.. doxygenfile:: api/event.h
|
||||||
|
:project: icsneoc
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
==========
|
||||||
|
C Examples
|
||||||
|
==========
|
||||||
|
|
||||||
|
A variety of examples can be found within ``examples/c``, see below for an
|
||||||
|
example that uses the polling API to receive CAN frames.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
size_t deviceCount = 10; // Pre-set to the size of your buffer before the icsneo_findAllDevices() call
|
||||||
|
neodevice_t devices[10];
|
||||||
|
icsneo_findAllDevices(devices, &deviceCount);
|
||||||
|
printf("We found %ull devices\n", deviceCount);
|
||||||
|
for(size_t i = 0; i < deviceCount; i++) {
|
||||||
|
neodevice_t* myDevice = &devices[i];
|
||||||
|
char desc[ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION];
|
||||||
|
size_t sz = ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION;
|
||||||
|
icsneo_describeDevice(myDevice, desc, &sz);
|
||||||
|
printf("Found %s\n", desc); // "Found neoVI FIRE 2 CY2345"
|
||||||
|
}
|
||||||
|
neodevice_t* myDevice = &devices[0];
|
||||||
|
if(!icsneo_openDevice(myDevice)) {
|
||||||
|
neoevent_t error;
|
||||||
|
if(icsneo_getLastError(&error))
|
||||||
|
printf("Error! %s\n", error.description);
|
||||||
|
}
|
||||||
|
icsneo_goOnline(myDevice); // Start receiving messages
|
||||||
|
icsneo_enableMessagePolling(myDevice); // Allow the use of icsneo_getMessages() later
|
||||||
|
sleep(5);
|
||||||
|
neomessage_t messages[50];
|
||||||
|
size_t messageCount = 50;
|
||||||
|
icsneo_getMessages(myDevice, messages, &messageCount, 0 /* non-blocking */);
|
||||||
|
printf("We got %ull messages!\n", messageCount);
|
||||||
|
for(size_t i = 0; i < messageCount; i++) {
|
||||||
|
if(messages[i].type == ICSNEO_NETWORK_TYPE_CAN) {
|
||||||
|
// A message of type CAN should be interperated a neomessage_can_t, so we can cast safely
|
||||||
|
neomessage_can_t* canmsg = (neomessage_can_t*)&messages[i];
|
||||||
|
// canmsg->arbid is valid here
|
||||||
|
// canmsg->data is an uint8_t*, you can check canmsg->length for the length of the payload
|
||||||
|
// canmsg->timestamp is the time recorded by the hardware in nanoseconds since (1/1/2007 12:00:00 GMT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
icsneo_closeDevice(myDevice);
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
icsneoc
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
installation
|
||||||
|
examples
|
||||||
|
api
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
============
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
The installation steps for the C API are the same as the C++ API as the C API is
|
||||||
|
a wrapper for the C++ library. The ``LIBICSNEO_BUILD_ICSNEOC`` CMake option is
|
||||||
|
default ``ON`` but note that the C API depends on this flag to build.
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
************************
|
|
||||||
**C++ API** (icsneocpp)
|
|
||||||
************************
|
|
||||||
|
|
||||||
.. Usage
|
|
||||||
.. ======
|
|
||||||
|
|
||||||
.. Finding Devices
|
|
||||||
.. ~~~~~~~~~~~~~~~~
|
|
||||||
.. Finding a device is simple
|
|
||||||
|
|
||||||
.. Connecting to Devices
|
|
||||||
.. ~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Reference
|
|
||||||
==========
|
|
||||||
|
|
||||||
.. Classes
|
|
||||||
.. ~~~~~~~~
|
|
||||||
|
|
||||||
.. Structures
|
|
||||||
.. ~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. Functions
|
|
||||||
.. ~~~~~~~~~~
|
|
||||||
|
|
||||||
.. doxygennamespace:: icsneo
|
|
||||||
|
|
||||||
.. doxygenclass:: icsneo::Device
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,8 @@
|
||||||
|
=======
|
||||||
|
C++ API
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. doxygennamespace:: icsneo
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:content-only:
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
============
|
||||||
|
API Concepts
|
||||||
|
============
|
||||||
|
|
||||||
|
Overview
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Events convey information about the API's inner workings to the user. There are 3 severity levels: ``EventInfo``, ``EventWarning``, and ``Error``.
|
||||||
|
**However, the API treats events of severities** ``EventInfo`` **and** ``EventWarning`` **differently than those of severity** ``Error`` **.**
|
||||||
|
From here on out, when we (and the API functions) refer to "events", we refer exclusively to those of severities ``EventInfo`` and ``EventWarning``, which use the events_ system.
|
||||||
|
Those of severity ``Error`` are referred to as "errors", which use a separate errors_ system.
|
||||||
|
|
||||||
|
Events should periodically be read out in order to avoid overflowing, and the last error should be read out immediately after an API function fails.
|
||||||
|
|
||||||
|
Additionally, `event callbacks`_ can be registered, which may remove the need to periodically read events in some cases.
|
||||||
|
|
||||||
|
.. _events:
|
||||||
|
|
||||||
|
Events
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The API stores events in a single buffer that can has a default size of 10,000 events.
|
||||||
|
This limit includes 1 reserved slot at the end of the buffer for a potential Event of type ``TooManyEvents`` and severity ``EventWarning``, which is added when there are too many events for the buffer to hold.
|
||||||
|
This could occur if the events aren't read out by the user often enough, or if the user sets the size of the buffer to a value smaller than the number of existing events.
|
||||||
|
There will only ever be one of these ``TooManyEvents`` events, and it will always be located at the very end of the buffer if it exists.
|
||||||
|
Because of this reserved slot, the buffer by default is able to hold 9,999 events. If capacity is exceeded, the oldest events in the buffer are automatically discarded until the buffer is exactly at capacity again.
|
||||||
|
When events are read out by the user, they are removed from the buffer. If an event filter is used, only the filtered events will be removed from the buffer.
|
||||||
|
|
||||||
|
In a multithreaded environment, all threads will log their events to the same buffer. In this case, the order of events will largely be meaningless, although the behavior of ``TooManyEvents`` is still guaranteed to be as described above.
|
||||||
|
|
||||||
|
.. _event callbacks:
|
||||||
|
|
||||||
|
Event Callbacks
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Users may register event callbacks, which are automatically called whenever a matching event is logged.
|
||||||
|
Message callbacks consist of a user-defined ``std::function< void( std::shared_ptr<APIEvent> ) >`` and optional EventFilter used for matching.
|
||||||
|
If no EventFilter is provided, the default-constructed one will be used, which matches any event.
|
||||||
|
Registering a callback returns an ``int`` representing the id of the callback, which should be stored by the user and later used to remove the callback when desired.
|
||||||
|
Note that this functionality is only available in C and C++. C does not currently support filters.
|
||||||
|
|
||||||
|
Event callbacks are run after the event has been added to the buffer of events. The buffer of events may be safely modified within the callback, such as getting (flushing) the type and severity of the triggering event.
|
||||||
|
Using event callbacks in this manner means that periodically reading events is unnecessary.
|
||||||
|
|
||||||
|
.. _errors:
|
||||||
|
|
||||||
|
Errors
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
The error system is threadsafe and separate from the events_ system.
|
||||||
|
Each thread keeps track of the last error logged on it, and getting the last error will return the last error from the calling thread, removing it in the process.
|
||||||
|
Trying to get the last error when there is none will return an event of type ``NoErrorFound`` and severity ``EventInfo``.
|
||||||
|
|
||||||
|
The API also contains some threads for internal use which may potentially log errors of their own and are inaccessible to the user.
|
||||||
|
These threads have been marked to downgrade any errors that occur on them to severity ``EventWarning`` and will log the corresponding event in the events_ system described above.
|
||||||
|
|
@ -1,64 +1,6 @@
|
||||||
****************
|
===============
|
||||||
**API Usage**
|
|
||||||
****************
|
|
||||||
|
|
||||||
API Concepts
|
|
||||||
================
|
|
||||||
|
|
||||||
Overview
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Events convey information about the API's inner workings to the user. There are 3 severity levels: ``EventInfo``, ``EventWarning``, and ``Error``.
|
|
||||||
**However, the API treats events of severities** ``EventInfo`` **and** ``EventWarning`` **differently than those of severity** ``Error`` **.**
|
|
||||||
From here on out, when we (and the API functions) refer to "events", we refer exclusively to those of severities ``EventInfo`` and ``EventWarning``, which use the events_ system.
|
|
||||||
Those of severity ``Error`` are referred to as "errors", which use a separate errors_ system.
|
|
||||||
|
|
||||||
Events should periodically be read out in order to avoid overflowing, and the last error should be read out immediately after an API function fails.
|
|
||||||
|
|
||||||
Additionally, `event callbacks`_ can be registered, which may remove the need to periodically read events in some cases.
|
|
||||||
|
|
||||||
.. _events:
|
|
||||||
|
|
||||||
Events
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The API stores events in a single buffer that can has a default size of 10,000 events.
|
|
||||||
This limit includes 1 reserved slot at the end of the buffer for a potential Event of type ``TooManyEvents`` and severity ``EventWarning``, which is added when there are too many events for the buffer to hold.
|
|
||||||
This could occur if the events aren't read out by the user often enough, or if the user sets the size of the buffer to a value smaller than the number of existing events.
|
|
||||||
There will only ever be one of these ``TooManyEvents`` events, and it will always be located at the very end of the buffer if it exists.
|
|
||||||
Because of this reserved slot, the buffer by default is able to hold 9,999 events. If capacity is exceeded, the oldest events in the buffer are automatically discarded until the buffer is exactly at capacity again.
|
|
||||||
When events are read out by the user, they are removed from the buffer. If an event filter is used, only the filtered events will be removed from the buffer.
|
|
||||||
|
|
||||||
In a multithreaded environment, all threads will log their events to the same buffer. In this case, the order of events will largely be meaningless, although the behavior of ``TooManyEvents`` is still guaranteed to be as described above.
|
|
||||||
|
|
||||||
.. _event callbacks:
|
|
||||||
|
|
||||||
Event Callbacks
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Users may register event callbacks, which are automatically called whenever a matching event is logged.
|
|
||||||
Message callbacks consist of a user-defined ``std::function< void( std::shared_ptr<APIEvent> ) >`` and optional EventFilter used for matching.
|
|
||||||
If no EventFilter is provided, the default-constructed one will be used, which matches any event.
|
|
||||||
Registering a callback returns an ``int`` representing the id of the callback, which should be stored by the user and later used to remove the callback when desired.
|
|
||||||
Note that this functionality is only available in C and C++. C does not currently support filters.
|
|
||||||
|
|
||||||
Event callbacks are run after the event has been added to the buffer of events. The buffer of events may be safely modified within the callback, such as getting (flushing) the type and severity of the triggering event.
|
|
||||||
Using event callbacks in this manner means that periodically reading events is unnecessary.
|
|
||||||
|
|
||||||
.. _errors:
|
|
||||||
|
|
||||||
Errors
|
|
||||||
~~~~~~~~~
|
|
||||||
|
|
||||||
The error system is threadsafe and separate from the events_ system.
|
|
||||||
Each thread keeps track of the last error logged on it, and getting the last error will return the last error from the calling thread, removing it in the process.
|
|
||||||
Trying to get the last error when there is none will return an event of type ``NoErrorFound`` and severity ``EventInfo``.
|
|
||||||
|
|
||||||
The API also contains some threads for internal use which may potentially log errors of their own and are inaccessible to the user.
|
|
||||||
These threads have been marked to downgrade any errors that occur on them to severity ``EventWarning`` and will log the corresponding event in the events_ system described above.
|
|
||||||
|
|
||||||
Device Concepts
|
Device Concepts
|
||||||
================
|
===============
|
||||||
|
|
||||||
Open/Close Status
|
Open/Close Status
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
============
|
||||||
|
C++ Examples
|
||||||
|
============
|
||||||
|
|
||||||
|
A variety of examples can be found within ``examples/cpp``, see below for an
|
||||||
|
example that uses the polling API to receive CAN frames.
|
||||||
|
|
||||||
|
The C++ API is designed to be modern and easy to use. All library functions and
|
||||||
|
classes are in the namespace ``icsneo``. Most applications will start by calling
|
||||||
|
``icsneo::FindAllDevices()``. This will return an ``std::vector`` of
|
||||||
|
``std::shared_ptr<icsneo::Device>`` objects. You will want to keep a copy of the
|
||||||
|
``shared_ptr`` to any devices you want to use, as allowing it to go out of scope
|
||||||
|
will automatically close the device and free all memory associated with it.
|
||||||
|
|
||||||
|
Any time you get bus traffic from the API, you will receive it as an
|
||||||
|
``std::shared_ptr<icsneo::Message>``. The message will be valid as long as the
|
||||||
|
``shared_ptr`` stays in scope. Checking the type of the message allows you to
|
||||||
|
cast it accordingly and access extra data for certain protocols. For instance,
|
||||||
|
casting an ``icsneo::Message`` to an ``icsneo::CANMessage`` allows you to access
|
||||||
|
the arbitration ID.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<icsneo::Device>> devices = icsneo::FindAllDevices();
|
||||||
|
std::cout << devices.size() << " found!" << std::endl;
|
||||||
|
for(auto& device : devices)
|
||||||
|
std::cout << "Found " << device->describe() << std::endl; // "Found neoVI FIRE 2 CY2345"
|
||||||
|
std::shared_ptr<icsneo::Device> myDevice = devices[0];
|
||||||
|
if(!myDevice->open()) // Device tried and failed to open, print the last error
|
||||||
|
std::cout << icsneo::GetLastError() << std::endl;
|
||||||
|
myDevice->goOnline(); // Start receiving messages
|
||||||
|
myDevice->enableMessagePolling(); // Allow the use of myDevice->getMessages() later
|
||||||
|
// Alternatively, assign a callback for new messages
|
||||||
|
std::this_thread::wait_for(std::chrono::seconds(5));
|
||||||
|
std::vector<std::shared_ptr<icsneo::Message>> messages = myDevice->getMessages();
|
||||||
|
std::cout << "We got " << messages.size() << " messages!" << std::endl;
|
||||||
|
for(auto& msg : messages) {
|
||||||
|
switch(msg->network.getType()) {
|
||||||
|
case icsneo::Network::Type::CAN:
|
||||||
|
case icsneo::Network::Type::SWCAN:
|
||||||
|
case icsneo::Network::Type::LSFTCAN: {
|
||||||
|
// A message of type CAN is guaranteed to be a CANMessage, so we can static cast safely
|
||||||
|
auto canmsg = std::static_pointer_cast<icsneo::CANMessage>(msg);
|
||||||
|
// canmsg->arbid is valid here
|
||||||
|
// canmsg->data is an std::vector<uint8_t>, you can check .size() for the DLC of the message
|
||||||
|
// canmsg->timestamp is the time recorded by the hardware in nanoseconds since (1/1/2007 12:00:00 GMT)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Handle others
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myDevice->close();
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
icsneocpp
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
installation
|
||||||
|
deviceconcepts
|
||||||
|
apiconcepts
|
||||||
|
examples
|
||||||
|
api
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
============
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
============
|
||||||
|
|
||||||
|
The minimum requirements to build libicsneo are:
|
||||||
|
- CMake version 3.12 or newer
|
||||||
|
- A C++17 compiler
|
||||||
|
- libusb and libpcap on Linux and macOS
|
||||||
|
|
||||||
|
|
||||||
|
Building library & examples
|
||||||
|
===========================
|
||||||
|
|
||||||
|
For a list of available configuration options, see the ``option()`` entries in
|
||||||
|
``CMakeLists.txt``.
|
||||||
|
|
||||||
|
To build libicsneo with default options:
|
||||||
|
#. ``cmake -B build``
|
||||||
|
#. ``cmake --build build``
|
||||||
|
|
||||||
|
Adding to existing projects
|
||||||
|
===========================
|
||||||
|
|
||||||
|
libicsneo supports being added as a sub-projects with CMake's
|
||||||
|
``add_subdirectory()``.
|
||||||
|
|
||||||
|
#. Clone libicsneo into the desired location within the project
|
||||||
|
#. Add ``add_subdirectory(path/to/libicsneo)`` to ``CMakeLists.txt``
|
||||||
|
#. Link the project to libicsneo with ``target_link_libraries(app icsneocpp)``
|
||||||
|
|
||||||
|
Linux udev Rules
|
||||||
|
================
|
||||||
|
|
||||||
|
Linux users may want to install the included udev rules to run libicsneo based
|
||||||
|
applications without root, this can be done with:
|
||||||
|
``cp 99-intrepidcs.rules /etc/udev/rules.d/``
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
==========
|
||||||
|
Python API
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. automodule:: icsneopy
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
:special-members: __init__
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
===============
|
||||||
|
Python Examples
|
||||||
|
===============
|
||||||
|
|
||||||
|
Transmit CAN frames on HSCAN
|
||||||
|
============================
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import icsneopy
|
||||||
|
|
||||||
|
devices: list[icsneopy.Device] = icsneopy.find_all_devices()
|
||||||
|
|
||||||
|
# grab the first/only device found
|
||||||
|
device: icsneopy.Device = devices[0]
|
||||||
|
|
||||||
|
message = icsneopy.CANMessage()
|
||||||
|
message.network = icsneopy.Network(icsneopy.Network.NetID.HSCAN)
|
||||||
|
message.arbid = 0x56
|
||||||
|
message.data = (0x11, 0x22, 0x33)
|
||||||
|
|
||||||
|
device.open()
|
||||||
|
|
||||||
|
device.go_online()
|
||||||
|
|
||||||
|
device.transmit(message)
|
||||||
|
|
||||||
|
Receive CAN frames on HSCAN
|
||||||
|
===========================
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import icsneopy
|
||||||
|
import time
|
||||||
|
|
||||||
|
devices: list[icsneopy.Device] = icsneopy.find_all_devices()
|
||||||
|
|
||||||
|
# grab the first/only device found
|
||||||
|
device: icsneopy.Device = devices[0]
|
||||||
|
|
||||||
|
def on_message(message: icsneopy.CANMessage):
|
||||||
|
print(message.arbid, message.data)
|
||||||
|
message_filter = icsneopy.MessageFilter(icsneopy.Network.NetID.HSCAN)
|
||||||
|
callback = icsneopy.MessageCallback(on_message, message_filter)
|
||||||
|
|
||||||
|
device.add_message_callback(callback)
|
||||||
|
|
||||||
|
device.open()
|
||||||
|
device.go_online()
|
||||||
|
|
||||||
|
# rx for 10s
|
||||||
|
time.sleep(10)
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
========
|
||||||
|
icsneopy
|
||||||
|
========
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
examples
|
||||||
|
api
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
Welcome to libicsneo's documentation!
|
libicsneo
|
||||||
=======================================
|
=========
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 3
|
:maxdepth: 1
|
||||||
:caption: Documentation
|
:caption: API Documentation
|
||||||
|
|
||||||
Usage
|
icsneocpp/index
|
||||||
icsneocpp
|
icsneopy/index
|
||||||
icsneoc
|
icsneoc/index
|
||||||
|
|
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
breathe==4.12.0
|
sphinx
|
||||||
|
icsneopy
|
||||||
|
breathe
|
||||||
|
sphinx_rtd_theme
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue