Compare commits
9 Commits
983552657b
...
63fd8c2f3a
| Author | SHA1 | Date |
|---|---|---|
|
|
63fd8c2f3a | |
|
|
fde2f670b5 | |
|
|
802be13e74 | |
|
|
7dee139217 | |
|
|
fbeea2f79d | |
|
|
a97f3bf297 | |
|
|
fc72d87c76 | |
|
|
76afcb410d | |
|
|
29486df894 |
|
|
@ -12,10 +12,10 @@ option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." O
|
|||
option(LIBICSNEO_BUILD_EXAMPLES "Build examples." ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEO "Build dynamic C library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEO_STATIC "Build static C library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C legacy library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C legacy library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC "Build static icsnVC40 compatibility library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C legacy library" OFF)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C legacy library" OFF)
|
||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" OFF)
|
||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC "Build static icsnVC40 compatibility library" OFF)
|
||||
set(LIBICSNEO_NPCAP_INCLUDE_DIR "" CACHE STRING "Npcap include directory; set to build with Npcap")
|
||||
|
||||
# Device Drivers
|
||||
|
|
@ -437,7 +437,6 @@ endif(LIBICSNEO_ENABLE_RAW_ETHERNET)
|
|||
|
||||
if(LIBICSNEO_BUILD_ICSNEO)
|
||||
add_library(icsneo SHARED api/icsneo/icsneo.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneo/version.rc)
|
||||
|
||||
target_include_directories(icsneo
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
|
|
@ -446,7 +445,14 @@ if(LIBICSNEO_BUILD_ICSNEO)
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
target_link_libraries(icsneo PRIVATE icsneocpp)
|
||||
target_compile_definitions(icsneo PRIVATE ICSNEO_EXPORTS)
|
||||
target_compile_definitions(icsneo
|
||||
PRIVATE
|
||||
ICSNEO_EXPORTS _CRT_SECURE_NO_WARNINGS
|
||||
PUBLIC
|
||||
ICSNEO_IMPORTS _CRT_SECURE_NO_WARNINGS
|
||||
INTERFACE
|
||||
ICSNEO_IMPORTS _CRT_SECURE_NO_WARNINGS
|
||||
)
|
||||
target_compile_features(icsneo PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
endif()
|
||||
|
||||
|
|
@ -461,8 +467,7 @@ if(LIBICSNEO_BUILD_ICSNEO_STATIC)
|
|||
)
|
||||
target_link_libraries(icsneo-static PUBLIC icsneocpp)
|
||||
target_compile_features(icsneo-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
target_compile_definitions(icsneo PRIVATE ICSNEO_EXPORTS)
|
||||
target_compile_definitions(icsneo-static PUBLIC ICSNEOC_BUILD_STATIC)
|
||||
target_compile_definitions(icsneo-static PUBLIC ICSNEO_BUILD_STATIC)
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,20 @@
|
|||
#include <icsneo/device/device.h>
|
||||
#include "icsneo/device/devicefinder.h"
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include "icsneo/communication/message/canmessage.h"
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
#include "icsneo/communication/message/ethernetmessage.h"
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
typedef struct icsneo_device_t {
|
||||
std::shared_ptr<Device> device;
|
||||
std::vector<std::shared_ptr<icsneo_message_t>> messages;
|
||||
|
||||
icsneo_open_options_t options;
|
||||
} icsneo_device_t;
|
||||
|
|
@ -19,8 +25,7 @@ typedef struct icsneo_message_t {
|
|||
} icsneo_message_t;
|
||||
|
||||
|
||||
static std::deque<std::shared_ptr<icsneo_device_t>> g_devices;
|
||||
static std::deque<std::shared_ptr<icsneo_message_t>> g_messages;
|
||||
static std::vector<std::shared_ptr<icsneo_device_t>> g_devices;
|
||||
|
||||
ICSNEO_API icsneo_error_t icsneo_error_code(icsneo_error_t error_code, const char* value, uint32_t* value_length) {
|
||||
if (!value || !value_length) {
|
||||
|
|
@ -153,20 +158,20 @@ ICSNEO_API icsneo_error_t icsneo_open(icsneo_device_t* device) {
|
|||
if (!dev->open()) {
|
||||
return icsneo_error_open_failed;
|
||||
}
|
||||
// Go online
|
||||
if ((device->options & icsneo_open_options_go_online) == icsneo_open_options_go_online && !dev->goOnline()) {
|
||||
// Sync RTC
|
||||
if ((device->options & icsneo_open_options_sync_rtc) == icsneo_open_options_sync_rtc && !dev->setRTC(std::chrono::system_clock::now())) {
|
||||
dev->close();
|
||||
return icsneo_error_go_online_failed;
|
||||
return icsneo_error_sync_rtc_failed;
|
||||
}
|
||||
// Enable message polling
|
||||
if ((device->options & icsneo_open_options_enable_message_polling) == icsneo_open_options_enable_message_polling && !dev->enableMessagePolling()) {
|
||||
dev->close();
|
||||
return icsneo_error_enable_message_polling_failed;
|
||||
}
|
||||
// Sync RTC
|
||||
if ((device->options & icsneo_open_options_sync_rtc) == icsneo_open_options_sync_rtc && !dev->setRTC(std::chrono::system_clock::now())) {
|
||||
// Go online
|
||||
if ((device->options & icsneo_open_options_go_online) == icsneo_open_options_go_online && !dev->goOnline()) {
|
||||
dev->close();
|
||||
return icsneo_error_sync_rtc_failed;
|
||||
return icsneo_error_go_online_failed;
|
||||
}
|
||||
return icsneo_error_success;
|
||||
}
|
||||
|
|
@ -180,6 +185,8 @@ ICSNEO_API icsneo_error_t icsneo_close(icsneo_device_t* device) {
|
|||
return icsneo_error_success;
|
||||
}
|
||||
dev->close();
|
||||
// Clear out old messages
|
||||
device->messages.clear();
|
||||
return icsneo_error_success;
|
||||
}
|
||||
|
||||
|
|
@ -316,11 +323,21 @@ ICSNEO_API icsneo_error_t icsneo_get_timestamp_resolution(icsneo_device_t* devic
|
|||
return icsneo_error_success;
|
||||
}
|
||||
|
||||
ICSNEO_API icsneo_error_t icsneo_get_messages(icsneo_device_t* device, icsneo_message_t** messages, uint32_t* messages_count) {
|
||||
ICSNEO_API icsneo_error_t icsneo_get_messages(icsneo_device_t* device, icsneo_message_t** messages, uint32_t* messages_count, uint32_t timeout_ms) {
|
||||
if (!device || !messages || !messages_count) {
|
||||
return icsneo_error_invalid_parameters;
|
||||
}
|
||||
auto dev = device->device;
|
||||
// Wait for messages
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
while (timeout_ms && std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - start_time)
|
||||
.count() < timeout_ms &&
|
||||
dev->getCurrentMessageCount() == 0) {
|
||||
// Lets make sure we don't busy loop, we don't have any messages yet
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
// Get the messages
|
||||
auto results = dev->getMessages();
|
||||
auto& queried_messages = results.first;
|
||||
|
|
@ -329,27 +346,50 @@ ICSNEO_API icsneo_error_t icsneo_get_messages(icsneo_device_t* device, icsneo_me
|
|||
return icsneo_error_get_messages_failed;
|
||||
}
|
||||
// Find the minimum number of messages
|
||||
uint32_t message_size = std::minmax(static_cast<uint32_t>(queried_messages.size()), *messages_count).first;
|
||||
*messages_count = message_size;
|
||||
uint32_t min_size = std::minmax(static_cast<uint32_t>(queried_messages.size()), *messages_count).first;
|
||||
*messages_count = min_size;
|
||||
|
||||
// Copy the messages into our global message container
|
||||
g_messages.clear();
|
||||
device->messages.clear();
|
||||
for (auto& message : queried_messages) {
|
||||
auto message_t = std::make_shared<icsneo_message_t>();
|
||||
message_t->message = message;
|
||||
g_messages.push_back(message_t);
|
||||
device->messages.push_back(message_t);
|
||||
}
|
||||
|
||||
// Copy the messages into the output array
|
||||
for (uint32_t i = 0; i < min_size; i++) {
|
||||
messages[i] = device->messages[i].get();
|
||||
}
|
||||
|
||||
return icsneo_error_success;
|
||||
}
|
||||
|
||||
ICSNEO_API icsneo_error_t icsneo_is_message_valid(icsneo_message_t* message, bool* is_valid) {
|
||||
ICSNEO_API icsneo_error_t icsneo_is_message_valid(icsneo_device_t* device, icsneo_message_t* message, bool* is_valid) {
|
||||
if (!message || !is_valid) {
|
||||
return icsneo_error_invalid_parameters;
|
||||
}
|
||||
*is_valid = std::find_if(g_messages.begin(), g_messages.end(), [&](const auto& msg) {
|
||||
*is_valid = std::find_if(device->messages.begin(), device->messages.end(), [&](const auto& msg) {
|
||||
return msg->message == message->message;
|
||||
}) == g_messages.end();
|
||||
}) == device->messages.end();
|
||||
|
||||
return icsneo_error_success;
|
||||
}
|
||||
}
|
||||
|
||||
ICSNEO_API icsneo_error_t icsneo_message_get_type(icsneo_device_t* device, icsneo_message_t* message, uint32_t* type) {
|
||||
if (!message || !type) {
|
||||
return icsneo_error_invalid_parameters;
|
||||
}
|
||||
// TODO: Fix this in the core so we actually get the message type from the message
|
||||
if (dynamic_cast<CANMessage*>(message->message.get())) {
|
||||
return 100;
|
||||
} else if (dynamic_cast<LINMessage*>(message->message.get())) {
|
||||
return 200;
|
||||
} else if (dynamic_cast<EthernetMessage*>(message->message.get())) {
|
||||
return 300;
|
||||
} else {
|
||||
return 999;
|
||||
}
|
||||
|
||||
return icsneo_error_success;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
option(LIBICSNEO_BUILD_C_SIMPLE_EXAMPLE "Build the command-line simple C example." ON)
|
||||
option(LIBICSNEO_BUILD_C_LEGACY_INTERACTIVE_EXAMPLE "Build the command-line interactive C example." ON)
|
||||
option(LIBICSNEO_BUILD_C_LEGACY_SIMPLE_EXAMPLE "Build the command-line simple C example." ON)
|
||||
option(LIBICSNEO_BUILD_C_LEGACY_LEGACY_EXAMPLE "Build the command-line simple C example." ON)
|
||||
option(LIBICSNEO_BUILD_C_LEGACY_INTERACTIVE_EXAMPLE "Build the command-line interactive C example." OFF)
|
||||
option(LIBICSNEO_BUILD_C_LEGACY_SIMPLE_EXAMPLE "Build the command-line simple C example." OFF)
|
||||
option(LIBICSNEO_BUILD_C_LEGACY_LEGACY_EXAMPLE "Build the command-line simple C example." OFF)
|
||||
option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_A2B_EXAMPLE "Build the A2B example." ON)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,2 @@
|
|||
add_executable(libicsneo-simple-example src/main.c)
|
||||
if(UNIX)
|
||||
target_link_libraries(libicsneo-simple-example ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
target_link_libraries(libicsneo-simple-example icsneo)
|
||||
target_link_libraries(libicsneo-simple-example icsneo)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,49 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sleeps for a specified number of milliseconds.
|
||||
*
|
||||
* Sleeps for a specified number of milliseconds using Sleep() on Windows and sleep() on *nix.
|
||||
*
|
||||
* @param ms The number of milliseconds to sleep.
|
||||
*/
|
||||
void sleep_ms(uint32_t ms) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
Sleep(ms);
|
||||
#else
|
||||
sleep(ms / 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prints an error message with the given string and error code.
|
||||
*
|
||||
* If the error code is not icsneo_error_success, prints the error string for the given error code
|
||||
* and returns the error code.
|
||||
*
|
||||
* @param message The message to print.
|
||||
* @param error The error code to print.
|
||||
* @return error as int
|
||||
*/
|
||||
int print_error_code(const char* message, icsneo_error_t error) {
|
||||
char error_str[256] = {0};
|
||||
uint32_t error_length = 256;
|
||||
icsneo_error_t res = icsneo_error_code(error, error_str, &error_length);
|
||||
if (res != icsneo_error_success) {
|
||||
printf("%s: Failed to get string for error code %d with error code %d\n", message, error, res);
|
||||
return res;
|
||||
}
|
||||
printf("%s: %s\n", message, error_str);
|
||||
return (int)error;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
(void)argc;
|
||||
|
|
@ -10,9 +53,9 @@ int main(int argc, char* argv[]) {
|
|||
icsneo_device_t* devices[255] = {0};
|
||||
uint32_t devices_count = 255;
|
||||
|
||||
if (icsneo_find(devices, &devices_count, NULL) != icsneo_error_success) {
|
||||
printf("Failed to find devices\n");
|
||||
return 1;
|
||||
icsneo_error_t res = icsneo_find(devices, &devices_count, NULL);
|
||||
if (res != icsneo_error_success) {
|
||||
return print_error_code("Failed to find devices", res);
|
||||
};
|
||||
|
||||
printf("Found %u devices\n", devices_count);
|
||||
|
|
@ -22,38 +65,61 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
const char description[255] = {0};
|
||||
uint32_t description_length = 255;
|
||||
icsneo_error_t res = icsneo_device_describe(device, description, &description_length);
|
||||
res = icsneo_device_describe(device, description, &description_length);
|
||||
if (res != icsneo_error_success) {
|
||||
printf("Failed to get device description %d\n", res);
|
||||
return 1;
|
||||
return print_error_code("Failed to get device description", res);
|
||||
};
|
||||
// Get timestamp resolution of the device
|
||||
uint32_t timestamp_resolution = 0;
|
||||
res = icsneo_get_timestamp_resolution(device, ×tamp_resolution);
|
||||
if (res != icsneo_error_success) {
|
||||
return print_error_code("Failed to get timestamp resolution", res);
|
||||
}
|
||||
printf("%s timestamp resolution: %uns\n", description, timestamp_resolution);
|
||||
|
||||
icsneo_open_options_t options = icsneo_open_options_none;
|
||||
res = icsneo_get_open_options(device, &options);
|
||||
if (res != icsneo_error_success) {
|
||||
printf("Failed to get open options %d\n", res);
|
||||
return 1;
|
||||
return print_error_code("Failed to get open options", res);
|
||||
}
|
||||
// Disable Syncing RTC
|
||||
options &= ~icsneo_open_options_sync_rtc;
|
||||
res = icsneo_set_open_options(device, options);
|
||||
if (res != icsneo_error_success) {
|
||||
printf("Failed to set open options %d\n", res);
|
||||
return 1;
|
||||
return print_error_code("Failed to set open options", res);
|
||||
}
|
||||
|
||||
printf("Opening device: %s...\n", description);
|
||||
res = icsneo_open(device);
|
||||
if (res != icsneo_error_success) {
|
||||
printf("Failed to open device %d\n", res);
|
||||
return 1;
|
||||
return print_error_code("Failed to open device", res);
|
||||
};
|
||||
|
||||
printf("Waiting 1 second for messages...\n");
|
||||
sleep_ms(1000);
|
||||
|
||||
icsneo_message_t* messages[20000] = {0};
|
||||
uint32_t message_count = 20000;
|
||||
printf("Getting messages from device with timeout of 3000ms on %s...\n", description);
|
||||
res = icsneo_get_messages(device, messages, &message_count, 3000);
|
||||
if (res != icsneo_error_success) {
|
||||
return print_error_code("Failed to get messages from device", res);
|
||||
};
|
||||
printf("Received %u messages\n", message_count);
|
||||
|
||||
for (uint32_t i = 0; i < message_count; i++) {
|
||||
icsneo_message_t* message = messages[i];
|
||||
uint32_t type = 0;
|
||||
res = icsneo_message_get_type(device, message, &type);
|
||||
if (res != icsneo_error_success) {
|
||||
return print_error_code("Failed to get message type", res);
|
||||
}
|
||||
printf("%d Message type: %u\n", i, type);
|
||||
}
|
||||
printf("Closing device: %s...\n", description);
|
||||
res = icsneo_close(device);
|
||||
if (res != icsneo_error_success) {
|
||||
printf("Failed to close device %d\n", res);
|
||||
return 1;
|
||||
return print_error_code("Failed to close device", res);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,15 @@ extern "C" {
|
|||
#pragma warning Unknown dynamic link import/export semantics.
|
||||
#endif
|
||||
|
||||
#ifdef ICSNEO_BUILD_STATIC
|
||||
#define ICSNEO_API
|
||||
#else
|
||||
#ifdef ICSNEO_EXPORTS
|
||||
#define ICSNEO_API EXPORT
|
||||
#else
|
||||
#define ICSNEO_API IMPORT
|
||||
#endif
|
||||
#endif // ICSNEO_EXPORTS
|
||||
#endif // ICSNEO_BUILD_STATIC
|
||||
|
||||
/** @brief icsneo_device_t opaque struct definition
|
||||
*
|
||||
|
|
@ -266,19 +270,23 @@ ICSNEO_API icsneo_error_t icsneo_get_timestamp_resolution(icsneo_device_t* devic
|
|||
* @param[out] icsneo_message_t** messages Pointer to an array of icsneo_message_t to copy the messages into.
|
||||
* Undefined behaviour if index is out of range of messages_count.
|
||||
* @param[in,out] uint32_t* messages_count Size of the messages array. Modified with the number of messages found.
|
||||
* @param[in] uint32_t timeout_ms The timeout in milliseconds to wait for messages. A value of 0 indicates a non-blocking call.
|
||||
*
|
||||
* @return icsneo_error_t icsneo_error_success if successful, icsneo_error_invalid_parameters otherwise.
|
||||
*/
|
||||
ICSNEO_API icsneo_error_t icsneo_get_messages(icsneo_device_t* device, icsneo_message_t** messages, uint32_t* messages_count);
|
||||
ICSNEO_API icsneo_error_t icsneo_get_messages(icsneo_device_t* device, icsneo_message_t** messages, uint32_t* messages_count, uint32_t timeout_ms);
|
||||
|
||||
/** @brief Check if a message is valid
|
||||
*
|
||||
* @param[in] icsneo_device_t* device The device to check against.
|
||||
* @param[in] icsneo_message_t* message The message to check.
|
||||
* @param[out] bool* is_valid Pointer to a bool to copy the validity of the message into.
|
||||
*
|
||||
* @return icsneo_error_t icsneo_error_success if successful, icsneo_error_invalid_parameters otherwise.
|
||||
*/
|
||||
ICSNEO_API icsneo_error_t icsneo_is_message_valid(icsneo_message_t* message, bool* is_valid);
|
||||
ICSNEO_API icsneo_error_t icsneo_is_message_valid(icsneo_device_t* device, icsneo_message_t* message, bool* is_valid);
|
||||
|
||||
ICSNEO_API icsneo_error_t icsneo_message_get_type(icsneo_device_t* device, icsneo_message_t* message, uint32_t* type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ typedef uint32_t icsneo_devicetype_t;
|
|||
|
||||
// Make sure icsneo_devicetype_t is never smaller than the actual enum
|
||||
#if __STDC_VERSION__ < 202311L && !defined(__cplusplus)
|
||||
_Static_assert(sizeof(_icsneo_devicetype_t) <= sizeof(icsneo_devicetype_t));
|
||||
_Static_assert(sizeof(_icsneo_devicetype_t) <= sizeof(icsneo_devicetype_t), "icsneo_devicetype_t is too small");
|
||||
#else // C++ or C23
|
||||
static_assert(sizeof(_icsneo_devicetype_t) <= sizeof(icsneo_devicetype_t));
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue