mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
Move examples into tree
See history at https://github.com/intrepidcs/libicsneo-examples/tree/v0.2.0-dev
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(libicsneocpp-interactive-example VERSION 0.2.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Add an include directory like so if desired
|
||||
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Enable Warnings
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
|
||||
endif()
|
||||
|
||||
# Add libicsneo, usually a git submodule within your project works well
|
||||
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
|
||||
|
||||
add_executable(libicsneocpp-interactive-example src/InteractiveExample.cpp)
|
||||
target_link_libraries(libicsneocpp-interactive-example icsneocpp)
|
||||
@@ -0,0 +1,48 @@
|
||||
# libicsneo C++ Example
|
||||
|
||||
This is an example console application which uses libicsneo to connect to an Intrepid Control Systems hardware device. It has both interactive and simple examples for sending and receiving CAN & CAN FD traffic.
|
||||
|
||||
## Building
|
||||
|
||||
This example shows how to use the C++ version of libicsneo with CMake. It will build libicsneo along with your project.
|
||||
|
||||
First, you need to clone the repository onto your local machine. Run:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/intrepidcs/libicsneo-examples --recursive
|
||||
```
|
||||
|
||||
Alternatively, if you cloned without the `--recursive flag`, you must enter the `libicsneo-examples` folder and run the following:
|
||||
|
||||
```shell
|
||||
git submodule update --recursive --init
|
||||
```
|
||||
|
||||
If you haven't done this, `third-party/libicsneo` will be empty and you won't be able to build!
|
||||
|
||||
### Windows using Visual Studio 2017+
|
||||
|
||||
1. Launch Visual Studio and open the `libicsneo-examples` folder.
|
||||
2. Choose `File->Open->CMake...`
|
||||
3. Navigate to the `libicsneocpp-example` folder and select the `CMakeLists.txt` there.
|
||||
4. Visual Studio will process the CMake project.
|
||||
5. Choose the dropdown attached to the green play button (labelled "select startup item...") in the toolbar.
|
||||
6. Select `libicsneocpp-interactive-example.exe` or `libicsneocpp-simple-example.exe`
|
||||
7. Press the green play button to compile and run the example.
|
||||
|
||||
### Ubuntu 18.04 LTS
|
||||
|
||||
1. Install dependencies with `sudo apt update` then `sudo apt install build-essential cmake libusb-1.0-0-dev libpcap0.8-dev`
|
||||
2. Change directories to your `libicsneo-examples/libicsneocpp-example` folder and create a build directory by running `mkdir -p build`
|
||||
3. Enter the build directory with `cd build`
|
||||
4. Run `cmake ..` to generate your Makefile.
|
||||
* Hint! Running `cmake -DCMAKE_BUILD_TYPE=Debug ..` will generate the proper scripts to build debug, and `cmake -DCMAKE_BUILD_TYPE=Release ..` will generate the proper scripts to build with all optimizations on.
|
||||
5. Run `make libicsneocpp-interactive-example` to build.
|
||||
* Hint! Speed up your build by using multiple processors! Use `make libicsneocpp-interactive-example -j#` where `#` is the number of cores/threads your system has plus one. For instance, on a standard 8 thread Intel i7, you might use `-j9` for an ~8x speedup.
|
||||
6. Now run `sudo ./libicsneocpp-interactive-example` to run the example.
|
||||
* Hint! In order to run without sudo, you will need to set up the udev rules. Copy `libicsneo-examples/third-party/libicsneo/99-intrepidcs.rules` to `/etc/udev/rules.d`, then run `udevadm control --reload-rules && udevadm trigger` afterwards. While the program will still run without setting up these rules, it will fail to open any devices.
|
||||
7. If you wish to run the simple example instead, replace any instances of "interactive" with "simple" in steps 5 and 6.
|
||||
|
||||
### macOS
|
||||
|
||||
Instructions coming soon™
|
||||
@@ -0,0 +1,618 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <ctype.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// Include icsneo/icsneocpp.h to access library functions
|
||||
#include "icsneo/icsneocpp.h"
|
||||
|
||||
/**
|
||||
* \brief Prints all current known devices to output in the following format:
|
||||
* [num] DeviceType SerialNum Connected: Yes/No Online: Yes/No Msg Polling: On/Off
|
||||
*
|
||||
* If any devices could not be described due to an error, they will appear in the following format:
|
||||
* Description for device num not available!
|
||||
*/
|
||||
void printAllDevices(const std::vector<std::shared_ptr<icsneo::Device>>& devices) {
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
for(auto device : devices) {
|
||||
std::cout << "[" << index << "] " << device->describe() << "\tConnected: " << (device->isOpen() ? "Yes\t" : "No\t");
|
||||
std::cout << "Online: " << (device->isOnline() ? "Yes\t" : "No\t");
|
||||
std::cout << "Msg Polling: " << (device->isMessagePollingEnabled() ? "On" : "Off") << std::endl;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the main menu options to output
|
||||
void printMainMenu() {
|
||||
std::cout << "Press the letter next to the function you want to use:" << std::endl;
|
||||
std::cout << "A - List all devices" << std::endl;
|
||||
std::cout << "B - Find all devices" << std::endl;
|
||||
std::cout << "C - Open/close" << std::endl;
|
||||
std::cout << "D - Go online/offline" << std::endl;
|
||||
std::cout << "E - Enable/disable message polling" << std::endl;
|
||||
std::cout << "F - Get messages" << std::endl;
|
||||
std::cout << "G - Send messages" << std::endl;
|
||||
std::cout << "H - Get events" << std::endl;
|
||||
std::cout << "I - Set HS CAN to 250K" << std::endl;
|
||||
std::cout << "J - Set LSFT CAN to 250K" << std::endl;
|
||||
std::cout << "K - Add/Remove a message callback" << std::endl;
|
||||
std::cout << "X - Exit" << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gets all current API events (info and warning level) and prints them to output
|
||||
* Flushes all current API events, meaning future calls (barring any new events) will not detect any further API events
|
||||
*/
|
||||
void printAPIEvents() {
|
||||
// Match all events
|
||||
auto events = icsneo::GetEvents(icsneo::EventFilter());
|
||||
|
||||
if(events.size() == 1) {
|
||||
std::cout << "1 API event found!" << std::endl;
|
||||
} else {
|
||||
std::cout << events.size() << " API events found!" << std::endl;
|
||||
}
|
||||
|
||||
for(auto event : events) {
|
||||
std::cout << event << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gets all current API warnings and prints them to output
|
||||
* Flushes all current API warnings, meaning future calls (barring any new warnings) will not detect any further API warnings
|
||||
*/
|
||||
void printAPIWarnings() {
|
||||
// Match all warning events, regardless of device
|
||||
auto warnings = icsneo::GetEvents(icsneo::EventFilter(nullptr, icsneo::APIEvent::Severity::EventWarning));
|
||||
|
||||
if(warnings.size() == 1) {
|
||||
std::cout << "1 API warning found!" << std::endl;
|
||||
} else {
|
||||
std::cout << warnings.size() << " API warnings found!" << std::endl;
|
||||
}
|
||||
|
||||
for(auto warning : warnings) {
|
||||
std::cout << warning << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gets all current device events and prints them to output.
|
||||
* Flushes all current device events, meaning future calls (barring any new events) will not detect any further device events for this device
|
||||
*/
|
||||
void printDeviceEvents(std::shared_ptr<icsneo::Device> device) {
|
||||
// Match all events for the specified device
|
||||
auto events = icsneo::GetEvents(icsneo::EventFilter(device.get()));
|
||||
|
||||
if(events.size() == 1) {
|
||||
std::cout << "1 device event found!" << std::endl;
|
||||
} else {
|
||||
std::cout << events.size() << " device events found!" << std::endl;
|
||||
}
|
||||
|
||||
for(auto event : events) {
|
||||
std::cout << event << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gets all current device warnings and prints them to output.
|
||||
* Flushes all current device warnings, meaning future calls (barring any new warnings) will not detect any further device warnings for this device
|
||||
*/
|
||||
void printDeviceWarnings(std::shared_ptr<icsneo::Device> device) {
|
||||
// Match all warning events for the specified device
|
||||
auto events = icsneo::GetEvents(icsneo::EventFilter(device.get(), icsneo::APIEvent::Severity::EventWarning));
|
||||
|
||||
if(events.size() == 1) {
|
||||
std::cout << "1 device warning found!" << std::endl;
|
||||
} else {
|
||||
std::cout << events.size() << " device warnings found!" << std::endl;
|
||||
}
|
||||
|
||||
for(auto event : events) {
|
||||
std::cout << event << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Used to check character inputs for correctness (if they are found in an expected list)
|
||||
* \param[in] numArgs the number of possible options for the expected character
|
||||
* \param[in] ... the possible options for the expected character
|
||||
* \returns the entered character
|
||||
*
|
||||
* This function repeatedly prompts the user for input until a matching input is entered
|
||||
* Example usage:
|
||||
* char input = getCharInput(std::vector<char> {'F', 'u', 'b', 'a', 'r'});
|
||||
*/
|
||||
char getCharInput(std::vector<char> allowed) {
|
||||
bool found = false;
|
||||
std::string input;
|
||||
|
||||
while(!found) {
|
||||
std::cin >> input;
|
||||
|
||||
if(input.length() == 1) {
|
||||
for(char compare : allowed) {
|
||||
if(compare == input.c_str()[0]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
std::cout << "Input did not match expected options. Please try again." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return input.c_str()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Prompts the user to select a device from the list of currently known devices
|
||||
* \returns a pointer to the device in devices[] selected by the user
|
||||
* Requires an input from 1-9, so a maximum of 9 devices are supported
|
||||
*/
|
||||
std::shared_ptr<icsneo::Device> selectDevice(const std::vector<std::shared_ptr<icsneo::Device>>& from) {
|
||||
printf("Please select a device:\n");
|
||||
printAllDevices(from);
|
||||
printf("\n");
|
||||
|
||||
int selectedDeviceNum = 10;
|
||||
|
||||
while((size_t) selectedDeviceNum > from.size()) {
|
||||
char deviceSelection = getCharInput(std::vector<char> {'1', '2', '3', '4', '5', '6', '7', '8', '9'});
|
||||
selectedDeviceNum = deviceSelection - '0';
|
||||
if((size_t) selectedDeviceNum > from.size()) {
|
||||
std::cout << "Selected device out of range!" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return from.at(selectedDeviceNum - 1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl << std::endl;
|
||||
|
||||
size_t msgLimit = 50000;
|
||||
std::vector<std::shared_ptr<icsneo::Device>> devices;
|
||||
std::map<std::shared_ptr<icsneo::Device>, std::vector<int>> callbacks;
|
||||
std::shared_ptr<icsneo::Device> selectedDevice;
|
||||
|
||||
while(true) {
|
||||
printMainMenu();
|
||||
std::cout << std::endl;
|
||||
char input = getCharInput(std::vector<char> {'A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h', 'I', 'i', 'J', 'j', 'K', 'k', 'X', 'x'});
|
||||
std::cout << std::endl;
|
||||
|
||||
switch(input) {
|
||||
// List current devices
|
||||
case 'A':
|
||||
case 'a':
|
||||
printAllDevices(devices);
|
||||
std::cout << std::endl;
|
||||
break;
|
||||
// Find all devices
|
||||
case 'B':
|
||||
case 'b':
|
||||
{
|
||||
devices = icsneo::FindAllDevices();
|
||||
|
||||
for(auto device : devices) {
|
||||
callbacks.insert({device, std::vector<int>()});
|
||||
}
|
||||
|
||||
if(devices.size() == 1) {
|
||||
std::cout << "1 device found!" << std::endl;
|
||||
} else {
|
||||
std::cout << devices.size() << " devices found!" << std::endl;
|
||||
}
|
||||
printAllDevices(devices);
|
||||
std::cout << std::endl;
|
||||
break;
|
||||
}
|
||||
// Open/Close
|
||||
case 'C':
|
||||
case 'c':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
std::cout << "Would you like to open or close " << selectedDevice->describe() << "?" << std::endl;
|
||||
std::cout << "[1] Open" << std::endl << "[2] Close" << std::endl << "[3] Cancel" << std::endl << std::endl;
|
||||
char selection = getCharInput(std::vector<char> {'1', '2', '3'});
|
||||
std::cout << std::endl;
|
||||
|
||||
switch(selection) {
|
||||
case '1':
|
||||
if(selectedDevice->open()) {
|
||||
std::cout << selectedDevice->describe() << " successfully opened!" << std::endl << std::endl;
|
||||
} else {
|
||||
std::cout << selectedDevice->describe() << " failed to open!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
break;
|
||||
case '2':
|
||||
// Attempt to close the device
|
||||
if(selectedDevice->close()) {
|
||||
std::cout << "Successfully closed " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
selectedDevice = NULL;
|
||||
} else {
|
||||
std::cout << "Failed to close " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
std::cout << "Canceling!" << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Go online/offline
|
||||
case 'D':
|
||||
case 'd':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
std::cout << "Would you like to have " << selectedDevice->describe() << " go online or offline?" << std::endl;
|
||||
std::cout << "[1] Online" << std::endl << "[2] Offline" << std::endl << "[3] Cancel" << std::endl << std::endl;
|
||||
char selection = getCharInput(std::vector<char> {'1', '2', '3'});
|
||||
std::cout << std::endl;
|
||||
|
||||
switch(selection) {
|
||||
case '1':
|
||||
// Attempt to have the selected device go online
|
||||
if(selectedDevice->goOnline()) {
|
||||
std::cout << selectedDevice->describe() << " successfully went online!" << std::endl << std::endl;
|
||||
} else {
|
||||
std::cout << selectedDevice->describe() << " failed to go online!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
// Attempt to go offline
|
||||
if(selectedDevice->goOffline()) {
|
||||
std::cout << selectedDevice->describe() << " successfully went offline!" << std::endl << std::endl;
|
||||
} else {
|
||||
std::cout << selectedDevice->describe() << " failed to go offline!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::cout << "Canceling!" << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Enable/disable message polling
|
||||
case 'E':
|
||||
case 'e':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
std::cout << "Would you like to enable or disable message polling for " << selectedDevice->describe() << "?" << std::endl;
|
||||
std::cout << "[1] Enable" << std::endl << "[2] Disable" << std::endl << "[3] Cancel" << std::endl << std::endl;
|
||||
char selection = getCharInput(std::vector<char> {'1', '2', '3'});
|
||||
std::cout << std::endl;
|
||||
|
||||
switch(selection) {
|
||||
case '1':
|
||||
// Attempt to enable message polling
|
||||
if(selectedDevice->enableMessagePolling()) {
|
||||
std::cout << "Successfully enabled message polling for " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to enable message polling for " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
// Manually setting the polling message limit as done below is optional
|
||||
// It will default to 20k if not set
|
||||
selectedDevice->setPollingMessageLimit(50000);
|
||||
if(selectedDevice->getPollingMessageLimit() == 50000) {
|
||||
std::cout << "Successfully set polling message limit for " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to set polling message limit for " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
// Attempt to disable message polling
|
||||
if(selectedDevice->disableMessagePolling()) {
|
||||
std::cout << "Successfully disabled message polling for " << selectedDevice->describe() << "!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to disable message polling for " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::cout << "Canceling!" << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Get messages
|
||||
case 'F':
|
||||
case 'f':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
std::vector<std::shared_ptr<icsneo::Message>> msgs;
|
||||
|
||||
// Attempt to get messages, limiting the number of messages at once to 50,000
|
||||
// A third parameter of type std::chrono::milliseconds is also accepted if a timeout is desired
|
||||
if(!selectedDevice->getMessages(msgs, msgLimit)) {
|
||||
std::cout << "Failed to get messages for " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
std::cout << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if(msgs.size() == 1) {
|
||||
std::cout << "1 message received from " << selectedDevice->describe() << "!" << std::endl;
|
||||
} else {
|
||||
std::cout << msgs.size() << " messages received from " << selectedDevice->describe() << "!" << std::endl;
|
||||
}
|
||||
|
||||
// Print out the received messages
|
||||
for(auto msg : msgs) {
|
||||
switch(msg->network.getType()) {
|
||||
case icsneo::Network::Type::CAN:
|
||||
{
|
||||
// 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);
|
||||
std::cout << "\t0x" << std::setfill('0') << std::setw(3) << std::hex << (int) canMsg->arbid << " [" << canMsg->data.size() << "] " << std::dec;
|
||||
|
||||
for(auto data : canMsg->data) {
|
||||
std::cout << std::setfill('0') << std::setw(2) << std::hex << (int) data << " " << std::dec;
|
||||
}
|
||||
|
||||
std::cout << canMsg->timestamp << std::endl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if(msg->network.getNetID() != icsneo::Network::NetID::Device) {
|
||||
std::cout << "\tMessage on netid " << msg->network.GetNetIDString(msg->network.getNetID()) << " with length " << msg->data.size() << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
break;
|
||||
// Send messages
|
||||
case 'G':
|
||||
case 'g':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
std::cout << "Transmitting a normal CAN frame..." << std::endl;
|
||||
auto msg = std::make_shared<icsneo::CANMessage>();
|
||||
msg->network = icsneo::Network::NetID::HSCAN;
|
||||
msg->arbid = 0x120;
|
||||
msg->data.insert(msg->data.end(), {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff});
|
||||
msg->isExtended = false;
|
||||
msg->isCANFD = false;
|
||||
|
||||
// Attempt to transmit the sample msg
|
||||
if(selectedDevice->transmit(msg)) {
|
||||
std::cout << "Message transmit successful!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to transmit message to " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
}
|
||||
|
||||
/** Example of CAN FD
|
||||
std::cout << "Transmitting an extended CAN FD frame... " << std::endl;
|
||||
auto txMessage = std::make_shared<icsneo::CANMessage>();
|
||||
txMessage->network = icsneo::Network::NetID::HSCAN;
|
||||
txMessage->arbid = 0x1C5001C5;
|
||||
txMessage->data.insert(txMessage->data.end(), {0xaa, 0xbb, 0xcc});
|
||||
// The DLC will come from the length of the data vector
|
||||
txMessage->isExtended = true;
|
||||
txMessage->isCANFD = true;
|
||||
|
||||
// Attempt to transmit the sample msg
|
||||
if(selectedDevice->transmit(txMessage)) {
|
||||
std::cout << "Extended CAN FD frame transmit successful!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to transmit extended CAN FD frame to " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
}
|
||||
*/
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
// Get events
|
||||
case 'H':
|
||||
case 'h':
|
||||
{
|
||||
// Prints all events
|
||||
printAPIEvents();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
// Set HS CAN to 250k
|
||||
case 'I':
|
||||
case 'i':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
// Attempt to set baudrate and apply settings
|
||||
if(selectedDevice->settings->setBaudrateFor(icsneo::Network::NetID::HSCAN, 250000) && selectedDevice->settings->apply()) {
|
||||
std::cout << "Successfully set HS CAN baudrate for " << selectedDevice->describe() << " to 250k!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to set HS CAN baudrate for " << selectedDevice->describe() << " to 250k!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
// Set LSFT CAN to 250k
|
||||
case 'J':
|
||||
case 'j':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
// Attempt to set baudrate and apply settings
|
||||
if(selectedDevice->settings->setBaudrateFor(icsneo::Network::NetID::LSFTCAN, 250000) && selectedDevice->settings->apply()) {
|
||||
std::cout << "Successfully set LSFT CAN baudrate for " << selectedDevice->describe() << " to 250k!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to set LSFT CAN baudrate for " << selectedDevice->describe() << " to 250k!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
break;
|
||||
// Add/Remove a message callback
|
||||
case 'K':
|
||||
case 'k':
|
||||
{
|
||||
// Select a device and get its description
|
||||
if(devices.size() == 0) {
|
||||
std::cout << "No devices found! Please scan for new devices." << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
selectedDevice = selectDevice(devices);
|
||||
|
||||
std::cout << "Would you like to add or remove a message callback for " << selectedDevice->describe() << "?" << std::endl;
|
||||
std::cout << "[1] Add" << std::endl << "[2] Remove" << std::endl << "[3] Cancel" << std::endl << std::endl;
|
||||
char selection = getCharInput(std::vector<char> {'1', '2', '3'});
|
||||
std::cout << std::endl;
|
||||
|
||||
switch(selection) {
|
||||
case '1':
|
||||
{
|
||||
// Shameless copy-paste from get messages above, demonstrating a callback
|
||||
int callbackID = selectedDevice->addMessageCallback(icsneo::MessageCallback([](std::shared_ptr<icsneo::Message> msg){
|
||||
switch(msg->network.getType()) {
|
||||
case icsneo::Network::Type::CAN:
|
||||
{
|
||||
// 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);
|
||||
std::cout << "\t0x" << std::setfill('0') << std::setw(3) << std::hex << (int) canMsg->arbid << " [" << canMsg->data.size() << "] " << std::dec;
|
||||
|
||||
for(auto data : canMsg->data) {
|
||||
std::cout << std::setfill('0') << std::setw(2) << std::hex << (int) data << " " << std::dec;
|
||||
}
|
||||
|
||||
std::cout << canMsg->timestamp << std::endl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if(msg->network.getNetID() != icsneo::Network::NetID::Device) {
|
||||
std::cout << "\tMessage on netid " << msg->network.GetNetIDString(msg->network.getNetID()) << " with length " << msg->data.size() << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
if(callbackID != -1) {
|
||||
std::cout << "Successfully added message callback to " << selectedDevice->describe() << "!" << std::endl;
|
||||
callbacks.find(selectedDevice)->second.push_back(callbackID);
|
||||
} else {
|
||||
std::cout << "Failed to add message callback to " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
{
|
||||
if(callbacks.find(selectedDevice)->second.size() == 0) {
|
||||
std::cout << "No callbacks found for " << selectedDevice->describe() << "!" << std::endl;
|
||||
break;
|
||||
} else {
|
||||
std::vector<char> allowed;
|
||||
|
||||
std::cout << "Which id would you like to remove?" << std::endl;
|
||||
for(int id : callbacks.find(selectedDevice)->second) {
|
||||
allowed.push_back(static_cast<char>(id) + '0');
|
||||
std::cout << "[" << id << "]" << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
int removeID = getCharInput(allowed) - '0';
|
||||
std::cout << std::endl;
|
||||
|
||||
if(selectedDevice->removeMessageCallback(removeID)) {
|
||||
std::cout << "Successfully removed callback id " << removeID << " from " << selectedDevice->describe() << "!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to remove message callback id " << removeID << " from " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::cout << "Canceling!" << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Exit
|
||||
case 'X':
|
||||
case 'x':
|
||||
printf("Exiting program\n");
|
||||
return 0;
|
||||
default:
|
||||
printf("Unexpected input, exiting!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(libicsneocpp-simple-example VERSION 0.2.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Add an include directory like so if desired
|
||||
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Enable Warnings
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
|
||||
endif()
|
||||
|
||||
# Add libicsneo, usually a git submodule within your project works well
|
||||
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
|
||||
|
||||
add_executable(libicsneocpp-simple-example src/SimpleExample.cpp)
|
||||
target_link_libraries(libicsneocpp-simple-example icsneocpp)
|
||||
@@ -0,0 +1,48 @@
|
||||
# libicsneo C++ Example
|
||||
|
||||
This is an example console application which uses libicsneo to connect to an Intrepid Control Systems hardware device. It has both interactive and simple examples for sending and receiving CAN & CAN FD traffic.
|
||||
|
||||
## Building
|
||||
|
||||
This example shows how to use the C++ version of libicsneo with CMake. It will build libicsneo along with your project.
|
||||
|
||||
First, you need to clone the repository onto your local machine. Run:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/intrepidcs/libicsneo-examples --recursive
|
||||
```
|
||||
|
||||
Alternatively, if you cloned without the `--recursive flag`, you must enter the `libicsneo-examples` folder and run the following:
|
||||
|
||||
```shell
|
||||
git submodule update --recursive --init
|
||||
```
|
||||
|
||||
If you haven't done this, `third-party/libicsneo` will be empty and you won't be able to build!
|
||||
|
||||
### Windows using Visual Studio 2017+
|
||||
|
||||
1. Launch Visual Studio and open the `libicsneo-examples` folder.
|
||||
2. Choose `File->Open->CMake...`
|
||||
3. Navigate to the `libicsneocpp-example` folder and select the `CMakeLists.txt` there.
|
||||
4. Visual Studio will process the CMake project.
|
||||
5. Choose the dropdown attached to the green play button (labelled "select startup item...") in the toolbar.
|
||||
6. Select `libicsneocpp-simple-example.exe`
|
||||
7. Press the green play button to compile and run the example.
|
||||
|
||||
### Ubuntu 18.04 LTS
|
||||
|
||||
1. Install dependencies with `sudo apt update` then `sudo apt install build-essential cmake libusb-1.0-0-dev libpcap0.8-dev`
|
||||
2. Change directories to your `libicsneo-examples/libicsneocpp-example` folder and create a build directory by running `mkdir -p build`
|
||||
3. Enter the build directory with `cd build`
|
||||
4. Run `cmake ..` to generate your Makefile.
|
||||
* Hint! Running `cmake -DCMAKE_BUILD_TYPE=Debug ..` will generate the proper scripts to build debug, and `cmake -DCMAKE_BUILD_TYPE=Release ..` will generate the proper scripts to build with all optimizations on.
|
||||
5. Run `make libicsneocpp-interactive-example` to build.
|
||||
* Hint! Speed up your build by using multiple processors! Use `make libicsneocpp-interactive-example -j#` where `#` is the number of cores/threads your system has plus one. For instance, on a standard 8 thread Intel i7, you might use `-j9` for an ~8x speedup.
|
||||
6. Now run `sudo ./libicsneocpp-interactive-example` to run the example.
|
||||
* Hint! In order to run without sudo, you will need to set up the udev rules. Copy `libicsneo-examples/third-party/libicsneo/99-intrepidcs.rules` to `/etc/udev/rules.d`, then run `udevadm control --reload-rules && udevadm trigger` afterwards. While the program will still run without setting up these rules, it will fail to open any devices.
|
||||
7. If you wish to run the simple example instead, replace any instances of "interactive" with "simple" in steps 5 and 6.
|
||||
|
||||
### macOS
|
||||
|
||||
Instructions coming soon™
|
||||
@@ -0,0 +1,248 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "icsneo/icsneocpp.h"
|
||||
|
||||
int main() {
|
||||
// Print version
|
||||
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl;
|
||||
|
||||
std::cout<< "Supported devices:" << std::endl;
|
||||
for(auto& dev : icsneo::GetSupportedDevices())
|
||||
std::cout << '\t' << dev << std::endl;
|
||||
|
||||
std::cout << "\nFinding devices... " << std::flush;
|
||||
auto devices = icsneo::FindAllDevices(); // This is type std::vector<std::shared_ptr<icsneo::Device>>
|
||||
// You now hold the shared_ptrs for these devices, you are considered to "own" these devices from a memory perspective
|
||||
std::cout << "OK, " << devices.size() << " device" << (devices.size() == 1 ? "" : "s") << " found" << std::endl;
|
||||
|
||||
// List off the devices
|
||||
for(auto& device : devices)
|
||||
std::cout << '\t' << device->getType() << " - " << device->getSerial() << " @ Handle " << device->getNeoDevice().handle << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
for(auto& device : devices) {
|
||||
std::cout << "Connecting to " << device->getType() << ' ' << device->getSerial() << "... ";
|
||||
bool ret = device->open();
|
||||
if(!ret) { // Failed to open
|
||||
std::cout << "FAIL" << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl << std::endl;
|
||||
continue;
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
std::cout << "\tGetting HSCAN Baudrate... ";
|
||||
int64_t baud = device->settings->getBaudrateFor(icsneo::Network::NetID::HSCAN);
|
||||
if(baud < 0)
|
||||
std::cout << "FAIL" << std::endl;
|
||||
else
|
||||
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
||||
|
||||
std::cout << "\tSetting HSCAN to operate at 125kbit/s... ";
|
||||
ret = device->settings->setBaudrateFor(icsneo::Network::NetID::HSCAN, 125000);
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
// Changes to the settings do not take affect until you call settings->apply()!
|
||||
// When you get the baudrate here, you're reading what the device is currently operating on
|
||||
std::cout << "\tGetting HSCAN Baudrate... (expected to be unchanged) ";
|
||||
baud = device->settings->getBaudrateFor(icsneo::Network::NetID::HSCAN);
|
||||
if(baud < 0)
|
||||
std::cout << "FAIL" << std::endl;
|
||||
else
|
||||
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
||||
|
||||
std::cout << "\tGetting HSCANFD Baudrate... ";
|
||||
baud = device->settings->getFDBaudrateFor(icsneo::Network::NetID::HSCAN);
|
||||
if(baud < 0)
|
||||
std::cout << "FAIL" << std::endl;
|
||||
else
|
||||
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
||||
|
||||
std::cout << "\tSetting HSCANFD to operate at 8Mbit/s... ";
|
||||
ret = device->settings->setFDBaudrateFor(icsneo::Network::NetID::HSCAN, 8000000);
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
std::cout << "\tGetting HSCANFD Baudrate... (expected to be unchanged) ";
|
||||
baud = device->settings->getFDBaudrateFor(icsneo::Network::NetID::HSCAN);
|
||||
if(baud < 0)
|
||||
std::cout << "FAIL" << std::endl;
|
||||
else
|
||||
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
||||
|
||||
// Setting settings temporarily does not need to be done before committing to device EEPROM
|
||||
// It's done here to test both functionalities
|
||||
// Setting temporarily will keep these settings until another send/commit is called or a power cycle occurs
|
||||
std::cout << "\tSetting settings temporarily... ";
|
||||
ret = device->settings->apply(true);
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
// Now that we have applied, we expect that our operating baudrates have changed
|
||||
std::cout << "\tGetting HSCAN Baudrate... ";
|
||||
baud = device->settings->getBaudrateFor(icsneo::Network::NetID::HSCAN);
|
||||
if(baud < 0)
|
||||
std::cout << "FAIL" << std::endl;
|
||||
else
|
||||
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
||||
|
||||
std::cout << "\tGetting HSCANFD Baudrate... ";
|
||||
baud = device->settings->getFDBaudrateFor(icsneo::Network::NetID::HSCAN);
|
||||
if(baud < 0)
|
||||
std::cout << "FAIL" << std::endl;
|
||||
else
|
||||
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
||||
|
||||
std::cout << "\tSetting settings permanently... ";
|
||||
ret = device->settings->apply();
|
||||
std::cout << (ret ? "OK\n\n" : "FAIL\n\n");
|
||||
|
||||
// The concept of going "online" tells the connected device to start listening, i.e. ACKing traffic and giving it to us
|
||||
std::cout << "\tGoing online... ";
|
||||
ret = device->goOnline();
|
||||
if(!ret) {
|
||||
std::cout << "FAIL" << std::endl;
|
||||
device->close();
|
||||
continue;
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
// A real application would just check the result of icsneo_goOnline() rather than calling this
|
||||
// This function is intended to be called later on if needed
|
||||
std::cout << "\tChecking online status... ";
|
||||
ret = device->isOnline();
|
||||
if(!ret) {
|
||||
std::cout << "FAIL\n" << std::endl;
|
||||
device->close();
|
||||
continue;
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
// Now we can either register a handler (or multiple) for messages coming in
|
||||
// or we can enable message polling, and then call device->getMessages periodically
|
||||
|
||||
// We're actually going to do both here, so first enable message polling
|
||||
device->enableMessagePolling();
|
||||
device->setPollingMessageLimit(100000); // Feel free to set a limit if you like, the default is a conservative 20k
|
||||
// Keep in mind that 20k messages comes quickly at high bus loads!
|
||||
|
||||
// We can also register a handler
|
||||
std::cout << "\tStreaming messages in for 3 seconds... " << std::endl;
|
||||
// MessageCallbacks are powerful, and can filter on things like ArbID for you. See the documentation
|
||||
auto handler = device->addMessageCallback(icsneo::MessageCallback([](std::shared_ptr<icsneo::Message> message) {
|
||||
switch(message->network.getType()) {
|
||||
case icsneo::Network::Type::CAN: {
|
||||
// A message of type CAN is guaranteed to be a CANMessage, so we can static cast safely
|
||||
auto canMessage = std::static_pointer_cast<icsneo::CANMessage>(message);
|
||||
|
||||
std::cout << "\t\tCAN ";
|
||||
if(canMessage->isCANFD) {
|
||||
std::cout << "FD ";
|
||||
if(!canMessage->baudrateSwitch)
|
||||
std::cout << "(No BRS) ";
|
||||
}
|
||||
|
||||
// Print the Arbitration ID
|
||||
std::cout << "0x" << std::hex << std::setw(canMessage->isExtended ? 8 : 3) << std::setfill('0') << canMessage->arbid;
|
||||
|
||||
// Print the DLC
|
||||
std::cout << std::dec << " [" << canMessage->data.size() << "] ";
|
||||
|
||||
// Print the data
|
||||
for(auto& databyte : canMessage->data)
|
||||
std::cout << std::hex << std::setw(2) << (uint32_t)databyte << ' ';
|
||||
|
||||
// Print the timestamp
|
||||
std::cout << std::dec << '(' << canMessage->timestamp << " ns since 1/1/2007)\n";
|
||||
break;
|
||||
}
|
||||
case icsneo::Network::Type::Ethernet: {
|
||||
auto ethMessage = std::static_pointer_cast<icsneo::EthernetMessage>(message);
|
||||
|
||||
std::cout << "\t\t" << ethMessage->network << " Frame - " << std::dec << ethMessage->data.size() << " bytes on wire\n";
|
||||
std::cout << "\t\t Timestamped:\t"<< ethMessage->timestamp << " ns since 1/1/2007\n";
|
||||
|
||||
// The MACAddress may be printed directly or accessed with the `data` member
|
||||
std::cout << "\t\t Source:\t" << ethMessage->getSourceMAC() << "\n";
|
||||
std::cout << "\t\t Destination:\t" << ethMessage->getDestinationMAC();
|
||||
|
||||
// Print the data
|
||||
for(size_t i = 0; i < ethMessage->data.size(); i++) {
|
||||
if(i % 8 == 0)
|
||||
std::cout << "\n\t\t " << std::hex << std::setw(4) << std::setfill('0') << i << '\t';
|
||||
std::cout << std::hex << std::setw(2) << (uint32_t)ethMessage->data[i] << ' ';
|
||||
}
|
||||
|
||||
std::cout << std::dec << std::endl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Ignoring non-network messages
|
||||
break;
|
||||
}
|
||||
}));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
device->removeMessageCallback(handler); // Removing the callback means it will not be called anymore
|
||||
|
||||
// Since we're using message polling, we can also get the messages which have come in for the past 3 seconds that way
|
||||
// We could simply call getMessages and it would return a vector of message pointers to us
|
||||
//auto messages = device->getMessages();
|
||||
|
||||
// For speed when calling repeatedly, we can also preallocate and continually reuse a vector
|
||||
std::vector<std::shared_ptr<icsneo::Message>> messages;
|
||||
messages.reserve(100000);
|
||||
device->getMessages(messages);
|
||||
std::cout << "\t\tGot " << messages.size() << " messages while polling" << std::endl;
|
||||
|
||||
// If we wanted to make sure it didn't grow and reallocate, we could also pass in a limit
|
||||
// If there are more messages than the limit, we can call getMessages repeatedly
|
||||
//device->getMessages(messages, 100);
|
||||
|
||||
// You are now the owner (or one of the owners, if multiple handlers are registered) of the shared_ptrs to the messages
|
||||
// This means that when you let them go out of scope or reuse the vector, the messages will be freed automatically
|
||||
|
||||
// We can transmit messages
|
||||
std::cout << "\tTransmitting an extended CAN FD frame... ";
|
||||
auto txMessage = std::make_shared<icsneo::CANMessage>();
|
||||
txMessage->network = icsneo::Network::NetID::HSCAN;
|
||||
txMessage->arbid = 0x1C5001C5;
|
||||
txMessage->data.insert(txMessage->data.end(), {0xaa, 0xbb, 0xcc});
|
||||
// The DLC will come from the length of the data vector
|
||||
txMessage->isExtended = true;
|
||||
txMessage->isCANFD = true;
|
||||
ret = device->transmit(txMessage); // This will return false if the device does not support CAN FD, or does not have HSCAN
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
std::cout << "\tTransmitting an ethernet frame on OP (BR) Ethernet 2... ";
|
||||
auto ethTxMessage = std::make_shared<icsneo::EthernetMessage>();
|
||||
ethTxMessage->network = icsneo::Network::NetID::OP_Ethernet2;
|
||||
ethTxMessage->data.insert(ethTxMessage->data.end(), {
|
||||
0x00, 0xFC, 0x70, 0x00, 0x01, 0x02, /* Destination MAC */
|
||||
0x00, 0xFC, 0x70, 0x00, 0x01, 0x01, /* Source MAC */
|
||||
0x00, 0x00, /* Ether Type */
|
||||
0x01, 0xC5, 0x01, 0xC5 /* Payload (will automatically be padded on transmit unless you set `ethTxMessage->noPadding`) */
|
||||
});
|
||||
ret = device->transmit(ethTxMessage); // This will return false if the device does not support OP (BR) Ethernet 2
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
|
||||
// Go offline, stop sending and receiving traffic
|
||||
std::cout << "\tGoing offline... ";
|
||||
ret = device->goOffline();
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
// Apply default settings
|
||||
std::cout << "\tSetting default settings... ";
|
||||
ret = device->settings->applyDefaults(); // This will also write to the device
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
std::cout << "\tDisconnecting... ";
|
||||
ret = device->close();
|
||||
std::cout << (ret ? "OK\n" : "FAIL\n") << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Press any key to continue..." << std::endl;
|
||||
std::cin.get();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user