Compare commits

...

11 Commits

Author SHA1 Message Date
vits71 d29148eec9
Merge e233233b94 into dbe19a5616 2024-11-18 10:56:49 -05:00
Kyle Schwarz dbe19a5616 Bindings: Python: Add MDIOMessage 2024-11-08 15:06:45 -05:00
Kyle Schwarz e5d7a38160 CI: Fix push command 2024-11-05 16:00:30 -05:00
Kyle Schwarz d714b620c4 CI: Add GitHub auto-push 2024-11-05 14:58:54 -05:00
Kyle Schwarz 10d2625cb6 Bindings: Python: Add get_tc10_status 2024-11-05 14:30:53 -05:00
Kyle Schwarz b9cfa85009 Docs: Add GitHub link 2024-11-05 12:56:27 -05:00
Kyle Schwarz 776d14bb3e Docs: Fix RTD requirements path 2024-11-04 18:05:24 -05:00
Kyle Schwarz 648fb2502f Docs: Refactor 2024-11-04 18:01:28 -05:00
Kyle Schwarz 008a0e4057 CI: Add needs section 2024-11-01 21:26:45 -04:00
Kyle Schwarz 3787bc27a2 Add Python bindings and the icsneopy package 2024-11-02 01:14:15 +00:00
Vít Šembera e233233b94 Fixed Npcap related errors in PCAPDLL::PCAPDLL() 2024-07-18 13:26:39 +02:00
50 changed files with 4963 additions and 1048 deletions

2
.gitignore vendored
View File

@ -14,4 +14,4 @@ third-party/concurrentqueue/tests
*.orig
examples/csharp/bin
examples/csharp/obj
test/system
test/system

View File

@ -5,6 +5,7 @@ stages:
- build
- unit_test
- hardware_test
- deploy
#-------------------------------------------------------------------------------
# Windows
@ -318,6 +319,7 @@ unit_test linux/fedora/39/amd64/clang:
- /opt/libvirt-driver/run.sh
after_script:
- /opt/libvirt-driver/cleanup.sh
allow_failure: true
.fedora38_needs: &fedora38_needs
needs:
@ -416,4 +418,114 @@ hardware_test win10-vcan42-EL:
<<: *win10_needs
variables:
GUEST_OS_TAG: win10
DEVICE_PORT: USB_C
DEVICE_PORT: USB_C
#-------------------------------------------------------------------------------
# Python Module
#-------------------------------------------------------------------------------
build python/linux/amd64:
stage: build
tags:
- linux-build
image: python:3.12
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
CIBW_BEFORE_ALL: yum install -y flex && sh ci/bootstrap-libpcap.sh && sh ci/bootstrap-libusb.sh
CIBW_BUILD: "*manylinux*" # no musl
CIBW_ARCHS: x86_64
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
CIBW_ENVIRONMENT: CMAKE_PREFIX_PATH=/project/libpcap/install:/project/libusb/install
script:
- curl -sSL https://get.docker.com/ | sh
- sh ci/build-wheel-posix.sh
artifacts:
paths:
- wheelhouse
build python/linux/arm64:
stage: build
tags:
- arm64-linux-build
variables:
CIBW_BEFORE_ALL: yum install -y flex && sh ci/bootstrap-libpcap.sh && sh ci/bootstrap-libusb.sh
CIBW_BUILD: "*manylinux*" # no musl
CIBW_ARCHS: aarch64
CIBW_ENVIRONMENT: CMAKE_PREFIX_PATH=/project/libpcap/install:/project/libusb/install
script:
- sh ci/build-wheel-posix.sh
artifacts:
paths:
- wheelhouse
build python/macos:
stage: build
tags:
- macos-arm64
variables:
CIBW_BEFORE_ALL: sh ci/bootstrap-libpcap.sh && sh ci/bootstrap-libusb.sh
CIBW_ARCHS: arm64
CIBW_ENVIRONMENT: CMAKE_PREFIX_PATH=$CI_PROJECT_DIR/libpcap/install:$CI_PROJECT_DIR/libusb/install
MACOSX_DEPLOYMENT_TARGET: 10.14
script:
- sh ci/build-wheel-posix.sh
artifacts:
paths:
- wheelhouse
build python/windows:
stage: build
tags:
- libicsneo-win-x64
variables:
CIBW_ARCHS: AMD64
CIBW_ENVIRONMENT: CMAKE_GENERATOR=Ninja
script:
- cmd /c ci\build-wheel-windows.bat
artifacts:
paths:
- wheelhouse
deploy python/pypi:
stage: deploy
variables:
TWINE_USERNAME: __token__
TWINE_PASSWORD: $PYPI_TOKEN
tags:
- linux-build
image: python:3.12
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script:
- python3 -m pip install -U twine
- twine upload wheelhouse/*
dependencies:
- build python/linux/amd64
- build python/linux/arm64
- build python/macos
- build python/windows
needs:
- build python/linux/amd64
- build python/linux/arm64
- build python/macos
- build python/windows
push github:
stage: deploy
tags:
- linux-build
image: alpine:latest
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
dependencies:
- deploy python/pypi
needs:
- deploy python/pypi
script:
- apk add git
- git push https://$LIBICSNEO_GITHUB_USERNAME:$LIBICSNEO_GITHUB_TOKEN@github.com/intrepidcs/libicsneo.git HEAD:master

15
.readthedocs.yaml 100644
View File

@ -0,0 +1,15 @@
version: 2
build:
os: "ubuntu-24.04"
tools:
python: "3.12"
apt_packages:
- doxygen
python:
install:
- requirements: docs/requirements.txt
sphinx:
configuration: docs/conf.py

View File

@ -14,7 +14,7 @@ option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C library" ON)
option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C library" ON)
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" ON)
option(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC "Build static icsnVC40 compatibility library" ON)
set(LIBICSNEO_NPCAP_INCLUDE_DIR "" CACHE STRING "Npcap include directory; set to build with Npcap")
set(LIBICSNEO_NPCAP_INCLUDE_DIR "C:/Users/Vit/source/repos/npcap-sdk-1.13/Include" CACHE STRING "Npcap include directory; set to build with Npcap")
# Device Drivers
# You almost certainly don't want firmio for your build,
@ -27,6 +27,8 @@ option(LIBICSNEO_ENABLE_FTDI "Enable devices which communicate over USB FTDI2XX"
option(LIBICSNEO_ENABLE_TCP "Enable devices which communicate over TCP" OFF)
option(LIBICSNEO_ENABLE_FTD3XX "Enable devices which communicate over USB FTD3XX" ON)
option(LIBICSNEO_ENABLE_BINDINGS_PYTHON "Enable Python library" OFF)
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
endif()
@ -494,6 +496,8 @@ if(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC)
target_compile_definitions(icsneolegacy-static PUBLIC ICSNEOC_BUILD_STATIC)
endif()
add_subdirectory(bindings)
# googletest
if(LIBICSNEO_BUILD_UNIT_TESTS)
if(WIN32)

View File

@ -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
View File

@ -1,176 +1,42 @@
# 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
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.
### Integration with CMake (Static Linking)
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.
- [C++](https://libicsneo.readthedocs.io/en/latest/icsneocpp/)
- [Python](https://libicsneo.readthedocs.io/en/latest/icsneopy/)
- [C](https://libicsneo.readthedocs.io/en/latest/icsneoc/)
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)
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.
1. Add this repository's `/include` to your include path
2. Add `#define ICSNEOC_DYNAMICLOAD` to the top of your source file
2. Add `#import <icsneo/icsneoc.h>` below that line
3. Call `icsneo_init();` to import the library before using any other libicsneo functions.
4. Use the library as normal.
5. Call `icsneo_close();` to unload the library.
- EtherBADGE
- neoVI Connect
- neoVI FIRE
- neoVI FIRE 2
- neoVI FIRE 3
- neoVI ION
- neoVI PLASMA
- 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
### 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.
## License
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.
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
```
libicsneo is licensed as BSD-3 with an extra clause, see [LICENSE](LICENSE)
for more details.

View File

@ -0,0 +1,3 @@
if(LIBICSNEO_ENABLE_BINDINGS_PYTHON)
add_subdirectory(python)
endif()

View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.20)
set(PYBIND11_FINDPYTHON ON)
find_package(pybind11 CONFIG REQUIRED)
pybind11_add_module(icsneopy
icsneopy/api/event.cpp
icsneopy/api/eventcallback.cpp
icsneopy/api/eventmanager.cpp
icsneopy/api/version.cpp
icsneopy/device/devicetype.cpp
icsneopy/communication/network.cpp
icsneopy/communication/message/message.cpp
icsneopy/communication/message/canmessage.cpp
icsneopy/communication/message/ethernetmessage.cpp
icsneopy/communication/message/tc10statusmessage.cpp
icsneopy/communication/message/mdiomessage.cpp
icsneopy/communication/message/callback/messagecallback.cpp
icsneopy/communication/message/filter/messagefilter.cpp
icsneopy/device/device.cpp
icsneopy/icsneocpp.cpp
)
target_link_libraries(icsneopy PRIVATE icsneocpp)
install(TARGETS icsneopy LIBRARY DESTINATION .)

View File

@ -0,0 +1,170 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/api/event.h"
namespace icsneo {
void init_event(pybind11::module_& m) {
pybind11::class_<APIEvent, std::shared_ptr<APIEvent>> apiEvent(m, "APIEvent");
pybind11::enum_<APIEvent::Type>(apiEvent, "Type")
.value("Any", APIEvent::Type::Any)
.value("InvalidNeoDevice", APIEvent::Type::InvalidNeoDevice)
.value("RequiredParameterNull", APIEvent::Type::RequiredParameterNull)
.value("BufferInsufficient", APIEvent::Type::BufferInsufficient)
.value("OutputTruncated", APIEvent::Type::OutputTruncated)
.value("ParameterOutOfRange", APIEvent::Type::ParameterOutOfRange)
.value("DeviceCurrentlyOpen", APIEvent::Type::DeviceCurrentlyOpen)
.value("DeviceCurrentlyClosed", APIEvent::Type::DeviceCurrentlyClosed)
.value("DeviceCurrentlyOnline", APIEvent::Type::DeviceCurrentlyOnline)
.value("DeviceCurrentlyOffline", APIEvent::Type::DeviceCurrentlyOffline)
.value("DeviceCurrentlyPolling", APIEvent::Type::DeviceCurrentlyPolling)
.value("DeviceNotCurrentlyPolling", APIEvent::Type::DeviceNotCurrentlyPolling)
.value("UnsupportedTXNetwork", APIEvent::Type::UnsupportedTXNetwork)
.value("MessageMaxLengthExceeded", APIEvent::Type::MessageMaxLengthExceeded)
.value("ValueNotYetPresent", APIEvent::Type::ValueNotYetPresent)
.value("Timeout", APIEvent::Type::Timeout)
.value("WiVINotSupported", APIEvent::Type::WiVINotSupported)
.value("RestrictedEntryFlag", APIEvent::Type::RestrictedEntryFlag)
.value("NotSupported", APIEvent::Type::NotSupported)
.value("PollingMessageOverflow", APIEvent::Type::PollingMessageOverflow)
.value("NoSerialNumber", APIEvent::Type::NoSerialNumber)
.value("IncorrectSerialNumber", APIEvent::Type::IncorrectSerialNumber)
.value("SettingsReadError", APIEvent::Type::SettingsReadError)
.value("SettingsVersionError", APIEvent::Type::SettingsVersionError)
.value("SettingsLengthError", APIEvent::Type::SettingsLengthError)
.value("SettingsChecksumError", APIEvent::Type::SettingsChecksumError)
.value("SettingsNotAvailable", APIEvent::Type::SettingsNotAvailable)
.value("SettingsReadOnly", APIEvent::Type::SettingsReadOnly)
.value("CANSettingsNotAvailable", APIEvent::Type::CANSettingsNotAvailable)
.value("CANFDSettingsNotAvailable", APIEvent::Type::CANFDSettingsNotAvailable)
.value("LSFTCANSettingsNotAvailable", APIEvent::Type::LSFTCANSettingsNotAvailable)
.value("SWCANSettingsNotAvailable", APIEvent::Type::SWCANSettingsNotAvailable)
.value("BaudrateNotFound", APIEvent::Type::BaudrateNotFound)
.value("UnexpectedNetworkType", APIEvent::Type::UnexpectedNetworkType)
.value("DeviceFirmwareOutOfDate", APIEvent::Type::DeviceFirmwareOutOfDate)
.value("SettingsStructureMismatch", APIEvent::Type::SettingsStructureMismatch)
.value("SettingsStructureTruncated", APIEvent::Type::SettingsStructureTruncated)
.value("NoDeviceResponse", APIEvent::Type::NoDeviceResponse)
.value("MessageFormattingError", APIEvent::Type::MessageFormattingError)
.value("CANFDNotSupported", APIEvent::Type::CANFDNotSupported)
.value("RTRNotSupported", APIEvent::Type::RTRNotSupported)
.value("DeviceDisconnected", APIEvent::Type::DeviceDisconnected)
.value("OnlineNotSupported", APIEvent::Type::OnlineNotSupported)
.value("TerminationNotSupportedDevice", APIEvent::Type::TerminationNotSupportedDevice)
.value("TerminationNotSupportedNetwork", APIEvent::Type::TerminationNotSupportedNetwork)
.value("AnotherInTerminationGroupEnabled", APIEvent::Type::AnotherInTerminationGroupEnabled)
.value("NoSerialNumberFW", APIEvent::Type::NoSerialNumberFW)
.value("NoSerialNumber12V", APIEvent::Type::NoSerialNumber12V)
.value("NoSerialNumberFW12V", APIEvent::Type::NoSerialNumberFW12V)
.value("EthPhyRegisterControlNotAvailable", APIEvent::Type::EthPhyRegisterControlNotAvailable)
.value("DiskNotSupported", APIEvent::Type::DiskNotSupported)
.value("EOFReached", APIEvent::Type::EOFReached)
.value("SettingsDefaultsUsed", APIEvent::Type::SettingsDefaultsUsed)
.value("AtomicOperationRetried", APIEvent::Type::AtomicOperationRetried)
.value("AtomicOperationCompletedNonatomically", APIEvent::Type::AtomicOperationCompletedNonatomically)
.value("WiVIStackRefreshFailed", APIEvent::Type::WiVIStackRefreshFailed)
.value("WiVIUploadStackOverflow", APIEvent::Type::WiVIUploadStackOverflow)
.value("I2CMessageExceedsMaxLength", APIEvent::Type::I2CMessageExceedsMaxLength)
.value("A2BMessageIncompleteFrame", APIEvent::Type::A2BMessageIncompleteFrame)
.value("CoreminiUploadVersionMismatch", APIEvent::Type::CoreminiUploadVersionMismatch)
.value("DiskNotConnected", APIEvent::Type::DiskNotConnected)
.value("UnexpectedResponse", APIEvent::Type::UnexpectedResponse)
.value("LiveDataInvalidHandle", APIEvent::Type::LiveDataInvalidHandle)
.value("LiveDataInvalidCommand", APIEvent::Type::LiveDataInvalidCommand)
.value("LiveDataInvalidArgument", APIEvent::Type::LiveDataInvalidArgument)
.value("LiveDataVersionMismatch", APIEvent::Type::LiveDataVersionMismatch)
.value("LiveDataNoDeviceResponse", APIEvent::Type::LiveDataNoDeviceResponse)
.value("LiveDataMaxSignalsReached", APIEvent::Type::LiveDataMaxSignalsReached)
.value("LiveDataCommandFailed", APIEvent::Type::LiveDataCommandFailed)
.value("LiveDataEncoderError", APIEvent::Type::LiveDataEncoderError)
.value("LiveDataDecoderError", APIEvent::Type::LiveDataDecoderError)
.value("LiveDataNotSupported", APIEvent::Type::LiveDataNotSupported)
.value("LINSettingsNotAvailable", APIEvent::Type::LINSettingsNotAvailable)
.value("ModeNotFound", APIEvent::Type::ModeNotFound)
.value("AppErrorParsingFailed", APIEvent::Type::AppErrorParsingFailed)
.value("FailedToRead", APIEvent::Type::FailedToRead)
.value("FailedToWrite", APIEvent::Type::FailedToWrite)
.value("DriverFailedToOpen", APIEvent::Type::DriverFailedToOpen)
.value("DriverFailedToClose", APIEvent::Type::DriverFailedToClose)
.value("PacketChecksumError", APIEvent::Type::PacketChecksumError)
.value("TransmitBufferFull", APIEvent::Type::TransmitBufferFull)
.value("DeviceInUse", APIEvent::Type::DeviceInUse)
.value("PCAPCouldNotStart", APIEvent::Type::PCAPCouldNotStart)
.value("PCAPCouldNotFindDevices", APIEvent::Type::PCAPCouldNotFindDevices)
.value("PacketDecodingError", APIEvent::Type::PacketDecodingError)
.value("SocketFailedToOpen", APIEvent::Type::SocketFailedToOpen)
.value("FailedToBind", APIEvent::Type::FailedToBind)
.value("ErrorSettingSocketOption", APIEvent::Type::ErrorSettingSocketOption)
.value("GetIfAddrsError", APIEvent::Type::GetIfAddrsError)
.value("SendToError", APIEvent::Type::SendToError)
.value("MDIOMessageExceedsMaxLength", APIEvent::Type::MDIOMessageExceedsMaxLength)
.value("FTOK", APIEvent::Type::FTOK)
.value("FTInvalidHandle", APIEvent::Type::FTInvalidHandle)
.value("FTDeviceNotFound", APIEvent::Type::FTDeviceNotFound)
.value("FTDeviceNotOpened", APIEvent::Type::FTDeviceNotOpened)
.value("FTIOError", APIEvent::Type::FTIOError)
.value("FTInsufficientResources", APIEvent::Type::FTInsufficientResources)
.value("FTInvalidParameter", APIEvent::Type::FTInvalidParameter)
.value("FTInvalidBaudRate", APIEvent::Type::FTInvalidBaudRate)
.value("FTDeviceNotOpenedForErase", APIEvent::Type::FTDeviceNotOpenedForErase)
.value("FTDeviceNotOpenedForWrite", APIEvent::Type::FTDeviceNotOpenedForWrite)
.value("FTFailedToWriteDevice", APIEvent::Type::FTFailedToWriteDevice)
.value("FTEEPROMReadFailed", APIEvent::Type::FTEEPROMReadFailed)
.value("FTEEPROMWriteFailed", APIEvent::Type::FTEEPROMWriteFailed)
.value("FTEEPROMEraseFailed", APIEvent::Type::FTEEPROMEraseFailed)
.value("FTEEPROMNotPresent", APIEvent::Type::FTEEPROMNotPresent)
.value("FTEEPROMNotProgrammed", APIEvent::Type::FTEEPROMNotProgrammed)
.value("FTInvalidArgs", APIEvent::Type::FTInvalidArgs)
.value("FTNotSupported", APIEvent::Type::FTNotSupported)
.value("FTNoMoreItems", APIEvent::Type::FTNoMoreItems)
.value("FTTimeout", APIEvent::Type::FTTimeout)
.value("FTOperationAborted", APIEvent::Type::FTOperationAborted)
.value("FTReservedPipe", APIEvent::Type::FTReservedPipe)
.value("FTInvalidControlRequestDirection", APIEvent::Type::FTInvalidControlRequestDirection)
.value("FTInvalidControlRequestType", APIEvent::Type::FTInvalidControlRequestType)
.value("FTIOPending", APIEvent::Type::FTIOPending)
.value("FTIOIncomplete", APIEvent::Type::FTIOIncomplete)
.value("FTHandleEOF", APIEvent::Type::FTHandleEOF)
.value("FTBusy", APIEvent::Type::FTBusy)
.value("FTNoSystemResources", APIEvent::Type::FTNoSystemResources)
.value("FTDeviceListNotReady", APIEvent::Type::FTDeviceListNotReady)
.value("FTDeviceNotConnected", APIEvent::Type::FTDeviceNotConnected)
.value("FTIncorrectDevicePath", APIEvent::Type::FTIncorrectDevicePath)
.value("FTOtherError", APIEvent::Type::FTOtherError)
.value("VSABufferCorrupted", APIEvent::Type::VSABufferCorrupted)
.value("VSATimestampNotFound", APIEvent::Type::VSATimestampNotFound)
.value("VSABufferFormatError", APIEvent::Type::VSABufferFormatError)
.value("VSAMaxReadAttemptsReached", APIEvent::Type::VSAMaxReadAttemptsReached)
.value("VSAByteParseFailure", APIEvent::Type::VSAByteParseFailure)
.value("VSAExtendedMessageError", APIEvent::Type::VSAExtendedMessageError)
.value("VSAOtherError", APIEvent::Type::VSAOtherError)
.value("NoErrorFound", APIEvent::Type::NoErrorFound)
.value("TooManyEvents", APIEvent::Type::TooManyEvents)
.value("Unknown", APIEvent::Type::Unknown);
pybind11::enum_<APIEvent::Severity>(apiEvent, "Severity")
.value("Any", APIEvent::Severity::Any)
.value("EventInfo", APIEvent::Severity::EventInfo)
.value("EventWarning", APIEvent::Severity::EventWarning)
.value("Error", APIEvent::Severity::Error);
apiEvent
.def("get_type", &APIEvent::getType)
.def("get_severity", &APIEvent::getSeverity)
.def("get_description", &APIEvent::getDescription)
.def("describe", &APIEvent::describe)
.def("__repr__", &APIEvent::describe);
pybind11::class_<EventFilter, std::shared_ptr<EventFilter>>(m, "EventFilter")
.def(pybind11::init())
.def(pybind11::init<APIEvent::Type>())
.def(pybind11::init<APIEvent::Severity>())
.def_readwrite("type", &EventFilter::type)
.def_readwrite("severity", &EventFilter::severity)
.def_readwrite("serial", &EventFilter::serial);
}
} // namespace icsneo

View File

@ -0,0 +1,16 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/api/eventcallback.h"
namespace icsneo {
void init_eventcallback(pybind11::module_& m) {
pybind11::class_<EventCallback>(m, "EventCallback")
.def(pybind11::init<EventCallback::fn_eventCallback, EventFilter>())
.def(pybind11::init<EventCallback::fn_eventCallback>());
}
} // namespace icsneo

View File

@ -0,0 +1,18 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/api/eventmanager.h"
namespace icsneo {
void init_eventmanager(pybind11::module_& m) {
pybind11::class_<EventManager>(m, "EventManager")
.def_static("get_instance", &EventManager::GetInstance, pybind11::return_value_policy::reference)
.def("add_event_callback", &EventManager::addEventCallback)
.def("remove_event_callback", &EventManager::removeEventCallback)
.def("get_last_error", &EventManager::getLastError);
}
} // namespace icsneo

View File

@ -0,0 +1,28 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/api/version.h"
#include <sstream>
namespace icsneo {
void init_version(pybind11::module_& m) {
pybind11::class_<neoversion_t>(m, "NeoVersion")
.def_readonly("major", &neoversion_t::major)
.def_readonly("minor", &neoversion_t::minor)
.def_readonly("patch", &neoversion_t::patch)
.def_readonly("metadata", &neoversion_t::metadata)
.def_readonly("buildBranch", &neoversion_t::buildBranch)
.def_readonly("buildTag", &neoversion_t::buildTag)
.def("__repr__", [](const neoversion_t& self) -> std::string {
std::stringstream ss;
ss << self;
return ss.str();
});
m.def("get_version", &GetVersion);
}
} // namespace icsneo

View File

@ -0,0 +1,15 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/callback/messagecallback.h"
namespace icsneo {
void init_messagecallback(pybind11::module_& m) {
pybind11::class_<MessageCallback, std::shared_ptr<MessageCallback>>(m, "MessageCallback")
.def(pybind11::init<MessageCallback::fn_messageCallback, std::shared_ptr<MessageFilter>>());
}
} // namespace icsneo

View File

@ -0,0 +1,22 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/canmessage.h"
namespace icsneo {
void init_canmessage(pybind11::module_& m) {
pybind11::class_<CANMessage, std::shared_ptr<CANMessage>, Frame>(m, "CANMessage")
.def(pybind11::init())
.def_readwrite("arbid", &CANMessage::arbid)
.def_readwrite("dlcOnWire", &CANMessage::dlcOnWire)
.def_readwrite("isRemote", &CANMessage::isRemote)
.def_readwrite("isExtended", &CANMessage::isExtended)
.def_readwrite("isCANFD", &CANMessage::isCANFD)
.def_readwrite("baudrateSwitch", &CANMessage::baudrateSwitch)
.def_readwrite("errorStateIndicator", &CANMessage::errorStateIndicator);
}
} // namespace icsneo

View File

@ -0,0 +1,27 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/ethernetmessage.h"
namespace icsneo {
void init_ethernetmessage(pybind11::module_& m) {
pybind11::class_<MACAddress>(m, "MACAddress")
.def("to_string", &MACAddress::toString)
.def("__repr__", &MACAddress::toString);
pybind11::class_<EthernetMessage, std::shared_ptr<EthernetMessage>, Frame>(m, "EthernetMessage")
.def(pybind11::init())
.def_readwrite("preemptionEnabled", &EthernetMessage::preemptionEnabled)
.def_readwrite("preemptionFlags", &EthernetMessage::preemptionFlags)
.def_readwrite("fcsAvailable", &EthernetMessage::fcsAvailable)
.def_readwrite("frameTooShort", &EthernetMessage::frameTooShort)
.def_readwrite("noPadding", &EthernetMessage::noPadding)
.def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference)
.def("get_source_mac", &EthernetMessage::getSourceMAC, pybind11::return_value_policy::reference)
.def("get_ether_type", &EthernetMessage::getEtherType);
}
} // namespace icsneo

View File

@ -0,0 +1,15 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/filter/messagefilter.h"
namespace icsneo {
void init_messagefilter(pybind11::module_& m) {
pybind11::class_<MessageFilter, std::shared_ptr<MessageFilter>>(m, "MessageFilter")
.def(pybind11::init<Network::NetID>());
}
} // namespace icsneo

View File

@ -0,0 +1,35 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/mdiomessage.h"
namespace icsneo {
void init_mdiomessage(pybind11::module_& m) {
pybind11::class_<MDIOMessage, std::shared_ptr<MDIOMessage>, Frame> mdioMessage(m, "MDIOMessage");
pybind11::enum_<MDIOMessage::Clause>(mdioMessage, "Clause")
.value("Clause45", MDIOMessage::Clause::Clause45)
.value("Clause22", MDIOMessage::Clause::Clause22);
pybind11::enum_<MDIOMessage::Direction>(mdioMessage, "Direction")
.value("Write", MDIOMessage::Direction::Write)
.value("Read", MDIOMessage::Direction::Read);
mdioMessage
.def(pybind11::init())
.def_readwrite("isTXMsg", &MDIOMessage::isTXMsg)
.def_readwrite("txTimeout", &MDIOMessage::txTimeout)
.def_readwrite("txAborted", &MDIOMessage::txAborted)
.def_readwrite("txInvalidBus", &MDIOMessage::txInvalidBus)
.def_readwrite("txInvalidPhyAddr", &MDIOMessage::txInvalidPhyAddr)
.def_readwrite("txInvalidRegAddr", &MDIOMessage::txInvalidRegAddr)
.def_readwrite("txInvalidClause", &MDIOMessage::txInvalidClause)
.def_readwrite("txInvalidOpcode", &MDIOMessage::txInvalidOpcode)
.def_readwrite("phyAddress", &MDIOMessage::phyAddress)
.def_readwrite("devAddress", &MDIOMessage::devAddress)
.def_readwrite("regAddress", &MDIOMessage::regAddress)
.def_readwrite("direction", &MDIOMessage::direction)
.def_readwrite("clause", &MDIOMessage::clause);
}
} // namespace icsneo

View File

@ -0,0 +1,51 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/message.h"
namespace icsneo {
void init_message(pybind11::module_& m) {
pybind11::class_<Message, std::shared_ptr<Message>> message(m, "Message");
pybind11::enum_<Message::Type>(message, "Type")
.value("Frame", Message::Type::Frame)
.value("CANErrorCount", Message::Type::CANErrorCount)
.value("LINHeaderOnly", Message::Type::LINHeaderOnly)
.value("LINBreak", Message::Type::LINBreak)
.value("Invalid", Message::Type::Invalid)
.value("RawMessage", Message::Type::RawMessage)
.value("ReadSettings", Message::Type::ReadSettings)
.value("ResetStatus", Message::Type::ResetStatus)
.value("DeviceVersion", Message::Type::DeviceVersion)
.value("Main51", Message::Type::Main51)
.value("FlexRayControl", Message::Type::FlexRayControl)
.value("EthernetPhyRegister", Message::Type::EthernetPhyRegister)
.value("LogicalDiskInfo", Message::Type::LogicalDiskInfo)
.value("ExtendedResponse", Message::Type::ExtendedResponse)
.value("WiVICommandResponse", Message::Type::WiVICommandResponse)
.value("ScriptStatus", Message::Type::ScriptStatus)
.value("ComponentVersions", Message::Type::ComponentVersions)
.value("SupportedFeatures", Message::Type::SupportedFeatures)
.value("GenericBinaryStatus", Message::Type::GenericBinaryStatus)
.value("LiveData", Message::Type::LiveData)
.value("HardwareInfo", Message::Type::HardwareInfo)
.value("TC10Status", Message::Type::TC10Status)
.value("AppError", Message::Type::AppError);
message.def(pybind11::init<Message::Type>());
message.def_readonly("type", &Message::type);
message.def_readwrite("timestamp", &Message::timestamp);
pybind11::class_<RawMessage, std::shared_ptr<RawMessage>, Message>(m, "RawMessage")
.def_readwrite("network", &RawMessage::network)
.def_readwrite("data", &RawMessage::data);
pybind11::class_<Frame, std::shared_ptr<Frame>, RawMessage>(m, "Frame")
.def_readwrite("description", &Frame::description)
.def_readwrite("transmitted", &Frame::transmitted)
.def_readwrite("error", &Frame::error);
}
} // namespace icsneo

View File

@ -0,0 +1,25 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/tc10statusmessage.h"
namespace icsneo {
void init_tc10statusmessage(pybind11::module_& m) {
pybind11::enum_<TC10WakeStatus>(m, "TC10WakeStatus")
.value("NoWakeReceived", TC10WakeStatus::NoWakeReceived)
.value("WakeReceived", TC10WakeStatus::WakeReceived);
pybind11::enum_<TC10SleepStatus>(m, "TC10SleepStatus")
.value("NoSleepReceived", TC10SleepStatus::NoSleepReceived)
.value("SleepReceived", TC10SleepStatus::SleepReceived)
.value("SleepFailed", TC10SleepStatus::SleepFailed)
.value("SleepAborted", TC10SleepStatus::SleepAborted);
pybind11::class_<TC10StatusMessage, std::shared_ptr<TC10StatusMessage>, Message>(m, "TC10StatusMessage")
.def_readonly("wakeStatus", &TC10StatusMessage::wakeStatus)
.def_readonly("sleepStatus", &TC10StatusMessage::sleepStatus);
}
} // namespace icsneo

View File

@ -0,0 +1,174 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/network.h"
namespace icsneo {
void init_network(pybind11::module_& m) {
pybind11::class_<Network> network(m, "Network");
pybind11::enum_<Network::NetID>(network, "NetID")
.value("Device", Network::NetID::Device)
.value("HSCAN", Network::NetID::HSCAN)
.value("MSCAN", Network::NetID::MSCAN)
.value("SWCAN", Network::NetID::SWCAN)
.value("LSFTCAN", Network::NetID::LSFTCAN)
.value("FordSCP", Network::NetID::FordSCP)
.value("J1708", Network::NetID::J1708)
.value("Aux", Network::NetID::Aux)
.value("J1850VPW", Network::NetID::J1850VPW)
.value("ISO9141", Network::NetID::ISO9141)
.value("DiskData", Network::NetID::DiskData)
.value("Main51", Network::NetID::Main51)
.value("RED", Network::NetID::RED)
.value("SCI", Network::NetID::SCI)
.value("ISO9141_2", Network::NetID::ISO9141_2)
.value("ISO14230", Network::NetID::ISO14230)
.value("LIN", Network::NetID::LIN)
.value("OP_Ethernet1", Network::NetID::OP_Ethernet1)
.value("OP_Ethernet2", Network::NetID::OP_Ethernet2)
.value("OP_Ethernet3", Network::NetID::OP_Ethernet3)
.value("RED_EXT_MEMORYREAD", Network::NetID::RED_EXT_MEMORYREAD)
.value("RED_INT_MEMORYREAD", Network::NetID::RED_INT_MEMORYREAD)
.value("RED_DFLASH_READ", Network::NetID::RED_DFLASH_READ)
.value("NeoMemorySDRead", Network::NetID::NeoMemorySDRead)
.value("CAN_ERRBITS", Network::NetID::CAN_ERRBITS)
.value("NeoMemoryWriteDone", Network::NetID::NeoMemoryWriteDone)
.value("RED_WAVE_CAN1_LOGICAL", Network::NetID::RED_WAVE_CAN1_LOGICAL)
.value("RED_WAVE_CAN2_LOGICAL", Network::NetID::RED_WAVE_CAN2_LOGICAL)
.value("RED_WAVE_LIN1_LOGICAL", Network::NetID::RED_WAVE_LIN1_LOGICAL)
.value("RED_WAVE_LIN2_LOGICAL", Network::NetID::RED_WAVE_LIN2_LOGICAL)
.value("RED_WAVE_LIN1_ANALOG", Network::NetID::RED_WAVE_LIN1_ANALOG)
.value("RED_WAVE_LIN2_ANALOG", Network::NetID::RED_WAVE_LIN2_ANALOG)
.value("RED_WAVE_MISC_ANALOG", Network::NetID::RED_WAVE_MISC_ANALOG)
.value("RED_WAVE_MISCDIO2_LOGICAL", Network::NetID::RED_WAVE_MISCDIO2_LOGICAL)
.value("RED_NETWORK_COM_ENABLE_EX", Network::NetID::RED_NETWORK_COM_ENABLE_EX)
.value("RED_NEOVI_NETWORK", Network::NetID::RED_NEOVI_NETWORK)
.value("RED_READ_BAUD_SETTINGS", Network::NetID::RED_READ_BAUD_SETTINGS)
.value("RED_OLDFORMAT", Network::NetID::RED_OLDFORMAT)
.value("RED_SCOPE_CAPTURE", Network::NetID::RED_SCOPE_CAPTURE)
.value("RED_HARDWARE_EXCEP", Network::NetID::RED_HARDWARE_EXCEP)
.value("RED_GET_RTC", Network::NetID::RED_GET_RTC)
.value("ISO9141_3", Network::NetID::ISO9141_3)
.value("HSCAN2", Network::NetID::HSCAN2)
.value("HSCAN3", Network::NetID::HSCAN3)
.value("OP_Ethernet4", Network::NetID::OP_Ethernet4)
.value("OP_Ethernet5", Network::NetID::OP_Ethernet5)
.value("ISO9141_4", Network::NetID::ISO9141_4)
.value("LIN2", Network::NetID::LIN2)
.value("LIN3", Network::NetID::LIN3)
.value("LIN4", Network::NetID::LIN4)
.value("RED_App_Error", Network::NetID::RED_App_Error)
.value("CGI", Network::NetID::CGI)
.value("Reset_Status", Network::NetID::Reset_Status)
.value("FB_Status", Network::NetID::FB_Status)
.value("App_Signal_Status", Network::NetID::App_Signal_Status)
.value("Read_Datalink_Cm_Tx_Msg", Network::NetID::Read_Datalink_Cm_Tx_Msg)
.value("Read_Datalink_Cm_Rx_Msg", Network::NetID::Read_Datalink_Cm_Rx_Msg)
.value("Logging_Overflow", Network::NetID::Logging_Overflow)
.value("ReadSettings", Network::NetID::ReadSettings)
.value("HSCAN4", Network::NetID::HSCAN4)
.value("HSCAN5", Network::NetID::HSCAN5)
.value("RS232", Network::NetID::RS232)
.value("UART", Network::NetID::UART)
.value("UART2", Network::NetID::UART2)
.value("UART3", Network::NetID::UART3)
.value("UART4", Network::NetID::UART4)
.value("SWCAN2", Network::NetID::SWCAN2)
.value("Ethernet_DAQ", Network::NetID::Ethernet_DAQ)
.value("Data_To_Host", Network::NetID::Data_To_Host)
.value("TextAPI_To_Host", Network::NetID::TextAPI_To_Host)
.value("SPI1", Network::NetID::SPI1)
.value("OP_Ethernet6", Network::NetID::OP_Ethernet6)
.value("Red_VBat", Network::NetID::Red_VBat)
.value("OP_Ethernet7", Network::NetID::OP_Ethernet7)
.value("OP_Ethernet8", Network::NetID::OP_Ethernet8)
.value("OP_Ethernet9", Network::NetID::OP_Ethernet9)
.value("OP_Ethernet10", Network::NetID::OP_Ethernet10)
.value("OP_Ethernet11", Network::NetID::OP_Ethernet11)
.value("FlexRay1a", Network::NetID::FlexRay1a)
.value("FlexRay1b", Network::NetID::FlexRay1b)
.value("FlexRay2a", Network::NetID::FlexRay2a)
.value("FlexRay2b", Network::NetID::FlexRay2b)
.value("LIN5", Network::NetID::LIN5)
.value("FlexRay", Network::NetID::FlexRay)
.value("FlexRay2", Network::NetID::FlexRay2)
.value("OP_Ethernet12", Network::NetID::OP_Ethernet12)
.value("I2C", Network::NetID::I2C)
.value("MOST25", Network::NetID::MOST25)
.value("MOST50", Network::NetID::MOST50)
.value("MOST150", Network::NetID::MOST150)
.value("Ethernet", Network::NetID::Ethernet)
.value("GMFSA", Network::NetID::GMFSA)
.value("TCP", Network::NetID::TCP)
.value("HSCAN6", Network::NetID::HSCAN6)
.value("HSCAN7", Network::NetID::HSCAN7)
.value("LIN6", Network::NetID::LIN6)
.value("LSFTCAN2", Network::NetID::LSFTCAN2)
.value("LogicalDiskInfo", Network::NetID::LogicalDiskInfo)
.value("WiVICommand", Network::NetID::WiVICommand)
.value("ScriptStatus", Network::NetID::ScriptStatus)
.value("EthPHYControl", Network::NetID::EthPHYControl)
.value("ExtendedCommand", Network::NetID::ExtendedCommand)
.value("ExtendedData", Network::NetID::ExtendedData)
.value("FlexRayControl", Network::NetID::FlexRayControl)
.value("CoreMiniPreLoad", Network::NetID::CoreMiniPreLoad)
.value("HW_COM_Latency_Test", Network::NetID::HW_COM_Latency_Test)
.value("DeviceStatus", Network::NetID::DeviceStatus)
.value("UDP", Network::NetID::UDP)
.value("ForwardedMessage", Network::NetID::ForwardedMessage)
.value("I2C2", Network::NetID::I2C2)
.value("I2C3", Network::NetID::I2C3)
.value("I2C4", Network::NetID::I2C4)
.value("Ethernet2", Network::NetID::Ethernet2)
.value("A2B1", Network::NetID::A2B1)
.value("A2B2", Network::NetID::A2B2)
.value("Ethernet3", Network::NetID::Ethernet3)
.value("WBMS", Network::NetID::WBMS)
.value("DWCAN9", Network::NetID::DWCAN9)
.value("DWCAN10", Network::NetID::DWCAN10)
.value("DWCAN11", Network::NetID::DWCAN11)
.value("DWCAN12", Network::NetID::DWCAN12)
.value("DWCAN13", Network::NetID::DWCAN13)
.value("DWCAN14", Network::NetID::DWCAN14)
.value("DWCAN15", Network::NetID::DWCAN15)
.value("DWCAN16", Network::NetID::DWCAN16)
.value("LIN7", Network::NetID::LIN7)
.value("LIN8", Network::NetID::LIN8)
.value("SPI2", Network::NetID::SPI2)
.value("MDIO1", Network::NetID::MDIO1)
.value("MDIO2", Network::NetID::MDIO2)
.value("MDIO3", Network::NetID::MDIO3)
.value("MDIO4", Network::NetID::MDIO4)
.value("MDIO5", Network::NetID::MDIO5)
.value("MDIO6", Network::NetID::MDIO6)
.value("MDIO7", Network::NetID::MDIO7)
.value("MDIO8", Network::NetID::MDIO8)
.value("OP_Ethernet13", Network::NetID::OP_Ethernet13)
.value("OP_Ethernet14", Network::NetID::OP_Ethernet14)
.value("OP_Ethernet15", Network::NetID::OP_Ethernet15)
.value("OP_Ethernet16", Network::NetID::OP_Ethernet16)
.value("SPI3", Network::NetID::SPI3)
.value("SPI4", Network::NetID::SPI4)
.value("SPI5", Network::NetID::SPI5)
.value("SPI6", Network::NetID::SPI6)
.value("SPI7", Network::NetID::SPI7)
.value("SPI8", Network::NetID::SPI8)
.value("LIN9", Network::NetID::LIN9)
.value("LIN10", Network::NetID::LIN10)
.value("LIN11", Network::NetID::LIN11)
.value("LIN12", Network::NetID::LIN12)
.value("LIN13", Network::NetID::LIN13)
.value("LIN14", Network::NetID::LIN14)
.value("LIN15", Network::NetID::LIN15)
.value("LIN16", Network::NetID::LIN16)
.value("Any", Network::NetID::Any)
.value("Invalid", Network::NetID::Invalid);
network.def(pybind11::init<Network::NetID>());
}
} // namespace icsneo

View File

@ -0,0 +1,44 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/device/device.h"
namespace icsneo {
void init_device(pybind11::module_& m) {
pybind11::class_<Device, std::shared_ptr<Device>>(m, "Device")
.def("get_type", &Device::getType)
.def("get_serial", &Device::getSerial)
.def("get_serial_number", &Device::getSerialNumber)
.def("get_product_name", &Device::getProductName)
.def("open", [](Device& device) { return device.open(); })
.def("close", &Device::close)
.def("is_open", &Device::isOpen)
.def("go_online", &Device::goOnline)
.def("go_offline", &Device::goOffline)
.def("is_online", &Device::isOnline).def("enable_message_polling", &Device::enableMessagePolling)
.def("disable_message_polling", &Device::disableMessagePolling)
.def("is_message_polling_enabled", &Device::isMessagePollingEnabled)
.def("get_messages", [](Device& device) { return device.getMessages(); })
.def("get_current_message_count", &Device::getCurrentMessageCount)
.def("get_polling_message_limit", &Device::getPollingMessageLimit)
.def("set_polling_message_limit", &Device::setPollingMessageLimit)
.def("add_message_callback", &Device::addMessageCallback)
.def("remove_message_callback", &Device::removeMessageCallback)
.def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit))
.def("get_supported_rx_networks", &Device::getSupportedRXNetworks, pybind11::return_value_policy::reference)
.def("get_supported_tx_networks", &Device::getSupportedTXNetworks, pybind11::return_value_policy::reference)
.def("get_rtc", &Device::getRTC)
.def("set_rtc", &Device::setRTC)
.def("describe", &Device::describe)
.def("is_online_supported", &Device::isOnlineSupported)
.def("supports_tc10", &Device::supportsTC10)
.def("request_tc10_wake", &Device::requestTC10Wake)
.def("request_tc10_sleep", &Device::requestTC10Sleep)
.def("get_tc10_status", &Device::getTC10Status)
.def("__repr__", &Device::describe);
}
} // namespace icsneo

View File

@ -0,0 +1,75 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/device/devicetype.h"
namespace icsneo {
void init_devicetype(pybind11::module_& m) {
pybind11::class_<DeviceType> deviceType(m, "DeviceType");
pybind11::enum_<DeviceType::Enum>(deviceType, "Enum")
.value("Unknown", DeviceType::Enum::Unknown)
.value("BLUE", DeviceType::Enum::BLUE)
.value("ECU_AVB", DeviceType::Enum::ECU_AVB)
.value("RADSupermoon", DeviceType::Enum::RADSupermoon)
.value("DW_VCAN", DeviceType::Enum::DW_VCAN)
.value("RADMoon2", DeviceType::Enum::RADMoon2)
.value("RADMars", DeviceType::Enum::RADMars)
.value("VCAN4_1", DeviceType::Enum::VCAN4_1)
.value("FIRE", DeviceType::Enum::FIRE)
.value("RADPluto", DeviceType::Enum::RADPluto)
.value("VCAN4_2EL", DeviceType::Enum::VCAN4_2EL)
.value("RADIO_CANHUB", DeviceType::Enum::RADIO_CANHUB)
.value("NEOECU12", DeviceType::Enum::NEOECU12)
.value("OBD2_LCBADGE", DeviceType::Enum::OBD2_LCBADGE)
.value("RADMoonDuo", DeviceType::Enum::RADMoonDuo)
.value("FIRE3", DeviceType::Enum::FIRE3)
.value("VCAN3", DeviceType::Enum::VCAN3)
.value("RADJupiter", DeviceType::Enum::RADJupiter)
.value("VCAN4_IND", DeviceType::Enum::VCAN4_IND)
.value("RADGigastar", DeviceType::Enum::RADGigastar)
.value("RED2", DeviceType::Enum::RED2)
.value("EtherBADGE", DeviceType::Enum::EtherBADGE)
.value("RAD_A2B", DeviceType::Enum::RAD_A2B)
.value("RADEpsilon", DeviceType::Enum::RADEpsilon)
.value("RADMoon3", DeviceType::Enum::RADMoon3)
.value("RADComet", DeviceType::Enum::RADComet)
.value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay)
.value("Connect", DeviceType::Enum::Connect)
.value("RADComet3", DeviceType::Enum::RADComet3)
.value("RADMoonT1S", DeviceType::Enum::RADMoonT1S)
.value("RADGigastar2", DeviceType::Enum::RADGigastar2)
.value("RED", DeviceType::Enum::RED)
.value("ECU", DeviceType::Enum::ECU)
.value("IEVB", DeviceType::Enum::IEVB)
.value("Pendant", DeviceType::Enum::Pendant)
.value("OBD2_PRO", DeviceType::Enum::OBD2_PRO)
.value("ECUChip_UART", DeviceType::Enum::ECUChip_UART)
.value("PLASMA", DeviceType::Enum::PLASMA)
.value("DONT_REUSE0", DeviceType::Enum::DONT_REUSE0)
.value("NEOAnalog", DeviceType::Enum::NEOAnalog)
.value("CT_OBD", DeviceType::Enum::CT_OBD)
.value("DONT_REUSE1", DeviceType::Enum::DONT_REUSE1)
.value("DONT_REUSE2", DeviceType::Enum::DONT_REUSE2)
.value("ION", DeviceType::Enum::ION)
.value("RADStar", DeviceType::Enum::RADStar)
.value("DONT_REUSE3", DeviceType::Enum::DONT_REUSE3)
.value("VCAN4_4", DeviceType::Enum::VCAN4_4)
.value("VCAN4_2", DeviceType::Enum::VCAN4_2)
.value("CMProbe", DeviceType::Enum::CMProbe)
.value("EEVB", DeviceType::Enum::EEVB)
.value("VCANrf", DeviceType::Enum::VCANrf)
.value("FIRE2", DeviceType::Enum::FIRE2)
.value("Flex", DeviceType::Enum::Flex)
.value("RADGalaxy", DeviceType::Enum::RADGalaxy)
.value("RADStar2", DeviceType::Enum::RADStar2)
.value("VividCAN", DeviceType::Enum::VividCAN)
.value("OBD2_SIM", DeviceType::Enum::OBD2_SIM);
deviceType.def(pybind11::init<DeviceType::Enum>());
deviceType.def("get_device_type", &DeviceType::getDeviceType);
deviceType.def("get_generic_product_name", &DeviceType::getGenericProductName);
}
} // namespace icsneo

View File

@ -0,0 +1,47 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/icsneocpp.h"
namespace icsneo {
void init_event(pybind11::module_&);
void init_eventcallback(pybind11::module_&);
void init_eventmanager(pybind11::module_&);
void init_network(pybind11::module_&);
void init_devicetype(pybind11::module_&);
void init_message(pybind11::module_&);
void init_canmessage(pybind11::module_&);
void init_ethernetmessage(pybind11::module_&);
void init_tc10statusmessage(pybind11::module_&);
void init_mdiomessage(pybind11::module_&);
void init_device(pybind11::module_&);
void init_messagefilter(pybind11::module_&);
void init_messagecallback(pybind11::module_&);
void init_version(pybind11::module_&);
PYBIND11_MODULE(icsneopy, m) {
m.doc() = "libicsneo Python module";
init_event(m);
init_eventcallback(m);
init_eventmanager(m);
init_version(m);
init_devicetype(m);
init_network(m);
init_message(m);
init_canmessage(m);
init_ethernetmessage(m);
init_tc10statusmessage(m);
init_mdiomessage(m);
init_messagefilter(m);
init_messagecallback(m);
init_device(m);
m.def("find_all_devices", &FindAllDevices);
m.def("get_supported_devices", &GetSupportedDevices);
m.def("get_last_error", &GetLastError);
}
} // namespace icsneo

View File

@ -0,0 +1,18 @@
#!/bin/sh
VERSION="1.10.5"
ROOT="$PWD/libpcap"
SOURCE="$ROOT/source"
BUILD="$ROOT/build"
INSTALL="$ROOT/install"
mkdir -p "$ROOT"
cd "$ROOT" || exit 1
curl -LO "https://www.tcpdump.org/release/libpcap-$VERSION.tar.xz" || exit 1
tar -xf "libpcap-$VERSION.tar.xz" || exit 1
mv "libpcap-$VERSION" "$SOURCE" || exit 1
cmake -D CMAKE_POSITION_INDEPENDENT_CODE=ON -D CMAKE_INSTALL_PREFIX="$INSTALL" -D BUILD_SHARED_LIBS=OFF -D BUILD_WITH_LIBNL=OFF -D DISABLE_DBUS=ON -D DISABLE_LINUX_USBMON=ON -D DISABLE_BLUETOOTH=ON -D DISABLE_NETMAP=ON -D DISABLE_DPDK=ON -D DISABLE_RDMA=ON -D DISABLE_DAG=ON -D DISABLE_SEPTEL=ON -D DISABLE_SNF=ON -D DISABLE_TC=ON -B "$BUILD" -S "$SOURCE" || exit 1
cmake --build "$BUILD" || exit 1
cmake --install "$BUILD" || exit 1

View File

@ -0,0 +1,21 @@
#!/bin/sh
VERSION="1.0.27"
ROOT="$PWD/libusb"
SOURCE="$ROOT/source"
BUILD="$ROOT/build"
INSTALL="$ROOT/install"
mkdir -p "$ROOT"
cd "$ROOT" || exit 1
curl -LO "https://github.com/libusb/libusb/releases/download/v$VERSION/libusb-$VERSION.tar.bz2" || exit 1
tar -xf "libusb-$VERSION.tar.bz2" || exit 1
mv "libusb-$VERSION" "$SOURCE" || exit 1
mkdir "$BUILD" || exit 1
cd "$BUILD" || exit 1
"$SOURCE/configure" --prefix="$INSTALL" --disable-shared --disable-udev --disable-eventfd --disable-timerfd --with-pic || exit 1
make || exit 1
make install || exit 1

View File

@ -0,0 +1,7 @@
#!/bin/sh
python3 -m venv env || exit 1
. env/bin/activate || exit 1
python3 -m pip install cibuildwheel || exit 1
python3 -m cibuildwheel --output-dir wheelhouse || exit 1

View File

@ -0,0 +1,9 @@
@setlocal
@echo off
call "%VCVARS64_2022%"
python.exe -m venv env || exit /b 1
call env\Scripts\Activate.bat || exit /b 1
python.exe -m pip install cibuildwheel || exit /b 1
python.exe -m cibuildwheel --output-dir wheelhouse --platform windows || exit /b 1

View File

@ -1,188 +1,36 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Configuration file for the Sphinx documentation builder.
#
# 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.
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# 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('.'))
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'
copyright = '2018-2024, Intrepid Control Systems, Inc.'
copyright = '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 = '0.2.0'
# The full version, including alpha/beta/rc tags.
release = '0.2.0 '
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
# 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
extensions = ['breathe', 'sphinx.ext.autodoc']
# 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
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
breathe_projects = {
'icsneocpp': 'icsneocpp/doxygen/xml',
'icsneoc': 'icsneoc/doxygen/xml',
}
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
breathe_default_project = 'icsneocpp'
# -- 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'
# 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'),
]

View File

@ -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'),
]

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -0,0 +1,9 @@
icsneoc
=======
.. toctree::
:maxdepth: 2
installation
examples
api

View File

@ -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.

View File

@ -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

View File

@ -0,0 +1,8 @@
=======
C++ API
=======
.. doxygennamespace:: icsneo
:members:
:undoc-members:
:content-only:

View File

@ -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.

View File

@ -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
================
===============
Open/Close Status
~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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();

View File

@ -0,0 +1,11 @@
icsneocpp
=========
.. toctree::
:maxdepth: 2
installation
deviceconcepts
apiconcepts
examples
api

View File

@ -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/``

View File

@ -0,0 +1,9 @@
==========
Python API
==========
.. automodule:: icsneopy
:members:
:undoc-members:
:show-inheritance:
:special-members: __init__

View File

@ -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)

View File

@ -0,0 +1,9 @@
========
icsneopy
========
.. toctree::
:maxdepth: 2
examples
api

View File

@ -1,10 +1,15 @@
Welcome to libicsneo's documentation!
=======================================
=========
libicsneo
=========
libicsneo is the `Intrepid Control Systems <https://intrepidcs.com/>`_ device
communication library. The source code for libicsneo can be found on GitHub:
`https://github.com/intrepidcs/libicsneo <https://github.com/intrepidcs/libicsneo>`_
.. toctree::
:maxdepth: 3
:maxdepth: 1
:caption: Documentation
Usage
icsneocpp
icsneoc
icsneocpp/index
icsneopy/index
icsneoc/index

View File

@ -1 +1,4 @@
breathe==4.12.0
sphinx
icsneopy
breathe
sphinx_rtd_theme

View File

@ -34,9 +34,12 @@ PCAPDLL::PCAPDLL()
int len = GetSystemDirectory(dllPath, 480); // be safe
if (len) {
_tcscat_s(dllPath, 512, TEXT("\\Npcap"));
cookie = AddDllDirectory(dllPath);
WCHAR dllPath_w[512] = { 0 };
if (mbstowcs(dllPath_w, dllPath, 512)) {
cookie = AddDllDirectory(dllPath_w);
}
}
dll = LoadLibraryEx(TEXT("wpcap.dll"), nullptr, LOAD_LIBRARY_SEARCH_USER_DIRS);
dll = LoadLibraryEx(TEXT("wpcap.dll"), nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
if (cookie)
RemoveDllDirectory(cookie);

49
pyproject.toml 100644
View File

@ -0,0 +1,49 @@
[build-system]
requires = ["scikit-build-core", "pybind11", "setuptools>=64", "setuptools-scm>=8"]
build-backend = "scikit_build_core.build"
[project]
name = "icsneopy"
dynamic = ["version"]
requires-python = ">=3.9"
readme = "README.md"
authors = [{name = "Intrepid Control Systems, Inc."}]
maintainers = [
{name = "Kyle Schwarz", email="kschwarz@intrepidcs.com"},
]
license = {file = "LICENSE"}
classifiers = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Programming Language :: C',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: Implementation :: CPython',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Operating System :: Unix',
'Operating System :: MacOS',
]
[project.urls]
homepage = "https://github.com/intrepidcs/libicsneo"
documentation = "https://libicsneo.readthedocs.io"
source = "https://github.com/intrepidcs/libicsneo"
tracker = "https://github.com/intrepidcs/libicsneo/issues"
[tool.scikit-build]
metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
[tool.setuptools_scm]
version_scheme = "no-guess-dev"
local_scheme = "no-local-version"
[tool.scikit-build.cmake.define]
LIBICSNEO_ENABLE_BINDINGS_PYTHON = true
LIBICSNEO_ENABLE_TCP = true