mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
C2: Add EthernetStatusMessage
This commit is contained in:
committed by
Kyle Schwarz
parent
d86e3164af
commit
9d91524dc0
@@ -271,7 +271,9 @@ static icsneoc2_error_t open_device_with_options(std::shared_ptr<Device> dev, ic
|
|||||||
if(!dev) {
|
if(!dev) {
|
||||||
return icsneoc2_error_invalid_device;
|
return icsneoc2_error_invalid_device;
|
||||||
}
|
}
|
||||||
if(!dev->enableMessagePolling(std::make_optional<MessageFilter>())) {
|
MessageFilter filter;
|
||||||
|
filter.includeInternalInAny = true;
|
||||||
|
if(!dev->enableMessagePolling(std::make_optional(filter))) {
|
||||||
return icsneoc2_error_enable_message_polling_failed;
|
return icsneoc2_error_enable_message_polling_failed;
|
||||||
}
|
}
|
||||||
if(!dev->isOpen() && !dev->open()) {
|
if(!dev->isOpen() && !dev->open()) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "icsneo/communication/message/apperrormessage.h"
|
#include "icsneo/communication/message/apperrormessage.h"
|
||||||
#include "icsneo/communication/message/linmessage.h"
|
#include "icsneo/communication/message/linmessage.h"
|
||||||
#include "icsneo/communication/message/ethernetmessage.h"
|
#include "icsneo/communication/message/ethernetmessage.h"
|
||||||
|
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||||
#include "icsneo/communication/packet/canpacket.h"
|
#include "icsneo/communication/packet/canpacket.h"
|
||||||
|
|
||||||
icsneoc2_error_t icsneoc2_message_is_valid(icsneoc2_message_t* message, bool* is_valid) {
|
icsneoc2_error_t icsneoc2_message_is_valid(icsneoc2_message_t* message, bool* is_valid) {
|
||||||
@@ -670,9 +671,40 @@ icsneoc2_error_t icsneoc2_message_eth_t1s_props_get(icsneoc2_message_t* message,
|
|||||||
}
|
}
|
||||||
|
|
||||||
icsneoc2_error_t icsneoc2_message_is_ethernet(icsneoc2_message_t* message, bool* is_ethernet) {
|
icsneoc2_error_t icsneoc2_message_is_ethernet(icsneoc2_message_t* message, bool* is_ethernet) {
|
||||||
if(!message) {
|
if(!message || !is_ethernet) {
|
||||||
return icsneoc2_error_invalid_parameters;
|
return icsneoc2_error_invalid_parameters;
|
||||||
}
|
}
|
||||||
*is_ethernet = std::dynamic_pointer_cast<EthernetMessage>(message->message) != nullptr;
|
*is_ethernet = std::dynamic_pointer_cast<EthernetMessage>(message->message) != nullptr;
|
||||||
return icsneoc2_error_success;
|
return icsneoc2_error_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_message_is_ethernet_status(icsneoc2_message_t* message, bool* is_ethernet_status) {
|
||||||
|
if(!message || !is_ethernet_status) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
*is_ethernet_status = std::dynamic_pointer_cast<EthernetStatusMessage>(message->message) != nullptr;
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_message_eth_status_props_get(icsneoc2_message_t* message, bool* link_state, bool* duplex, icsneoc2_link_speed_t* link_speed, icsneoc2_link_mode_t* link_mode) {
|
||||||
|
if(!message) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
auto msg = std::dynamic_pointer_cast<EthernetStatusMessage>(message->message);
|
||||||
|
if(!msg) {
|
||||||
|
return icsneoc2_error_invalid_type;
|
||||||
|
}
|
||||||
|
if(link_state) {
|
||||||
|
*link_state = msg->state;
|
||||||
|
}
|
||||||
|
if(duplex) {
|
||||||
|
*duplex = msg->duplex;
|
||||||
|
}
|
||||||
|
if(link_speed) {
|
||||||
|
*link_speed = static_cast<icsneoc2_link_speed_t>(msg->speed);
|
||||||
|
}
|
||||||
|
if(link_mode) {
|
||||||
|
*link_mode = static_cast<icsneoc2_link_mode_t>(msg->mode);
|
||||||
|
}
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
void init_ethernetstatusmessage(pybind11::module_& m) {
|
void init_ethernetstatusmessage(pybind11::module_& m) {
|
||||||
pybind11::classh<EthernetStatusMessage, Message> ethernetStatusMessage(m, "EthernetStatusMessage");
|
pybind11::classh<EthernetStatusMessage, RawMessage> ethernetStatusMessage(m, "EthernetStatusMessage");
|
||||||
|
|
||||||
pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed")
|
pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed")
|
||||||
.value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto)
|
.value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ struct Packet {
|
|||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
std::shared_ptr<Message> EthernetStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
std::shared_ptr<RawMessage> EthernetStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
if(bytestream.size() < sizeof(Packet)) {
|
if(bytestream.size() < sizeof(Packet)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -76,5 +76,5 @@ std::shared_ptr<Message> EthernetStatusMessage::DecodeToMessage(const std::vecto
|
|||||||
break;
|
break;
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
return std::make_shared<EthernetStatusMessage>(packet->network, packet->state, speed, packet->duplex, mode);
|
return std::make_shared<EthernetStatusMessage>(packet->network, packet->state != 0, speed, packet->duplex != 0, mode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,14 @@ Ethernet Receive
|
|||||||
.. literalinclude:: ../../examples/c2/ethernet_receive/src/main.c
|
.. literalinclude:: ../../examples/c2/ethernet_receive/src/main.c
|
||||||
:language: c
|
:language: c
|
||||||
|
|
||||||
|
Ethernet Status
|
||||||
|
===============
|
||||||
|
|
||||||
|
:download:`Download example <../../examples/c2/ethernet_status/src/main.c>`
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/c2/ethernet_status/src/main.c
|
||||||
|
:language: c
|
||||||
|
|
||||||
T1S Loopback
|
T1S Loopback
|
||||||
============
|
============
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ option(LIBICSNEO_BUILD_C2_LIN_EXAMPLE "Build the C2 LIN example." ON)
|
|||||||
option(LIBICSNEO_BUILD_C2_LIN_TRANSMIT_EXAMPLE "Build the C2 LIN transmit example." ON)
|
option(LIBICSNEO_BUILD_C2_LIN_TRANSMIT_EXAMPLE "Build the C2 LIN transmit example." ON)
|
||||||
option(LIBICSNEO_BUILD_C2_ETHERNET_TRANSMIT_EXAMPLE "Build the C2 ethernet transmit example." ON)
|
option(LIBICSNEO_BUILD_C2_ETHERNET_TRANSMIT_EXAMPLE "Build the C2 ethernet transmit example." ON)
|
||||||
option(LIBICSNEO_BUILD_C2_ETHERNET_RECEIVE_EXAMPLE "Build the C2 ethernet receive example." ON)
|
option(LIBICSNEO_BUILD_C2_ETHERNET_RECEIVE_EXAMPLE "Build the C2 ethernet receive example." ON)
|
||||||
|
option(LIBICSNEO_BUILD_C2_ETHERNET_STATUS_EXAMPLE "Build the C2 ethernet status example." ON)
|
||||||
option(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE "Build the C2 RAD-Comet3 T1S loopback example." ON)
|
option(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE "Build the C2 RAD-Comet3 T1S loopback example." ON)
|
||||||
option(LIBICSNEO_BUILD_C2_TC10_EXAMPLE "Build the C2 TC10 example." ON)
|
option(LIBICSNEO_BUILD_C2_TC10_EXAMPLE "Build the C2 TC10 example." ON)
|
||||||
option(LIBICSNEO_BUILD_C2_GPTP_EXAMPLE "Build the C2 gPTP settings example." ON)
|
option(LIBICSNEO_BUILD_C2_GPTP_EXAMPLE "Build the C2 gPTP settings example." ON)
|
||||||
@@ -93,6 +94,10 @@ if(LIBICSNEO_BUILD_C2_ETHERNET_RECEIVE_EXAMPLE)
|
|||||||
add_subdirectory(c2/ethernet_receive)
|
add_subdirectory(c2/ethernet_receive)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(LIBICSNEO_BUILD_C2_ETHERNET_STATUS_EXAMPLE)
|
||||||
|
add_subdirectory(c2/ethernet_status)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE)
|
if(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE)
|
||||||
add_subdirectory(c2/t1s_loopback)
|
add_subdirectory(c2/t1s_loopback)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
add_executable(libicsneoc2-ethernet-status-example src/main.c)
|
||||||
|
target_link_libraries(libicsneoc2-ethernet-status-example icsneoc2-static)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_compile_definitions(libicsneoc2-ethernet-status-example PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
#include <icsneo/icsneoc2.h>
|
||||||
|
#include <icsneo/icsneoc2messages.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void sleep_ms(uint32_t ms) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
Sleep(ms);
|
||||||
|
#else
|
||||||
|
usleep(ms * 1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_error_code(const char* message, icsneoc2_error_t error) {
|
||||||
|
char error_str[64] = {0};
|
||||||
|
size_t error_str_len = sizeof(error_str);
|
||||||
|
icsneoc2_error_t res = icsneoc2_error_code_get(error, error_str, &error_str_len);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
printf("%s: Failed to get string for error code %u with error code %u\n", message, error, res);
|
||||||
|
return (int)res;
|
||||||
|
}
|
||||||
|
printf("%s: \"%s\" (%u)\n", message, error_str, error);
|
||||||
|
return (int)error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_events(void) {
|
||||||
|
icsneoc2_event_t* events[256] = {0};
|
||||||
|
size_t events_count = 256;
|
||||||
|
for(size_t i = 0; i < events_count; ++i) {
|
||||||
|
icsneoc2_error_t res = icsneoc2_event_get(&events[i], NULL);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
(void)print_error_code("\tFailed to get events", res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(events[i] == NULL) {
|
||||||
|
events_count = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < events_count; i++) {
|
||||||
|
char description[255] = {0};
|
||||||
|
size_t description_length = sizeof(description);
|
||||||
|
icsneoc2_error_t res = icsneoc2_event_description_get(events[i], description, &description_length);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
(void)print_error_code("\tFailed to get event description", res);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("\tEvent %zu: %s\n", i, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < events_count; i++) {
|
||||||
|
icsneoc2_event_free(events[i]);
|
||||||
|
}
|
||||||
|
if(events_count > 0) {
|
||||||
|
printf("\tReceived %zu events\n", events_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* link_speed_name(icsneoc2_link_speed_t speed) {
|
||||||
|
switch(speed) {
|
||||||
|
case icsneoc2_link_speed_auto:
|
||||||
|
return "Auto";
|
||||||
|
case icsneoc2_link_speed_10mbps:
|
||||||
|
return "10 Mbps";
|
||||||
|
case icsneoc2_link_speed_100mbps:
|
||||||
|
return "100 Mbps";
|
||||||
|
case icsneoc2_link_speed_1000mbps:
|
||||||
|
return "1000 Mbps";
|
||||||
|
case icsneoc2_link_speed_2500mbps:
|
||||||
|
return "2500 Mbps";
|
||||||
|
case icsneoc2_link_speed_5000mbps:
|
||||||
|
return "5000 Mbps";
|
||||||
|
case icsneoc2_link_speed_10000mbps:
|
||||||
|
return "10000 Mbps";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* link_mode_name(icsneoc2_link_mode_t mode) {
|
||||||
|
switch(mode) {
|
||||||
|
case icsneoc2_link_mode_auto:
|
||||||
|
return "Auto";
|
||||||
|
case icsneoc2_link_mode_master:
|
||||||
|
return "Master";
|
||||||
|
case icsneoc2_link_mode_slave:
|
||||||
|
return "Slave";
|
||||||
|
case icsneoc2_link_mode_invalid:
|
||||||
|
return "Invalid";
|
||||||
|
case icsneoc2_link_mode_none:
|
||||||
|
return "None";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_ethernet_status_message(icsneoc2_message_t* message, size_t index) {
|
||||||
|
icsneoc2_netid_t netid = 0;
|
||||||
|
char netid_name[128] = {0};
|
||||||
|
size_t netid_name_length = sizeof(netid_name);
|
||||||
|
bool link_state = false;
|
||||||
|
bool duplex = false;
|
||||||
|
icsneoc2_link_speed_t link_speed = icsneoc2_link_speed_auto;
|
||||||
|
icsneoc2_link_mode_t link_mode = icsneoc2_link_mode_auto;
|
||||||
|
|
||||||
|
icsneoc2_error_t res = icsneoc2_message_netid_get(message, &netid);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return print_error_code("\tFailed to get Ethernet status netid", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = icsneoc2_netid_name_get(netid, netid_name, &netid_name_length);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return print_error_code("\tFailed to get Ethernet status netid name", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = icsneoc2_message_eth_status_props_get(message, &link_state, &duplex, &link_speed, &link_mode);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return print_error_code("\tFailed to get Ethernet status properties", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\t%zu) Ethernet status on %s (0x%x)\n", index, netid_name, netid);
|
||||||
|
printf("\t Link: %s\n", link_state ? "Up" : "Down");
|
||||||
|
printf("\t Duplex: %s\n", duplex ? "Full" : "Half");
|
||||||
|
printf("\t Speed: %s (%u)\n", link_speed_name(link_speed), link_speed);
|
||||||
|
printf("\t Mode: %s (%u)\n", link_mode_name(link_mode), link_mode);
|
||||||
|
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("Opening first available device offline...\n");
|
||||||
|
icsneoc2_device_t* device = NULL;
|
||||||
|
icsneoc2_open_options_t options = icsneoc2_open_options_default & ~ICSNEOC2_OPEN_OPTIONS_GO_ONLINE;
|
||||||
|
icsneoc2_error_t res = icsneoc2_device_open_first(0, options, &device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return print_error_code("Failed to open first device", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
char description[255] = {0};
|
||||||
|
size_t description_length = sizeof(description);
|
||||||
|
res = icsneoc2_device_description_get(device, description, &description_length);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
return print_error_code("Failed to get device description", res);
|
||||||
|
}
|
||||||
|
printf("Opened device: %s\n", description);
|
||||||
|
|
||||||
|
printf("Going online to trigger Ethernet status broadcast...\n");
|
||||||
|
res = icsneoc2_device_go_online(device, true);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
print_events();
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
return print_error_code("Failed to go online", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int listen_seconds = 6;
|
||||||
|
time_t start_time = time(NULL);
|
||||||
|
size_t status_count = 0;
|
||||||
|
size_t total_count = 0;
|
||||||
|
printf("Listening for Ethernet status messages for %d seconds...\n", listen_seconds);
|
||||||
|
|
||||||
|
while(time(NULL) - start_time < listen_seconds) {
|
||||||
|
icsneoc2_message_t* message = NULL;
|
||||||
|
res = icsneoc2_device_message_get(device, &message, 100);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
print_events();
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
return print_error_code("Failed to get message", res);
|
||||||
|
}
|
||||||
|
if(message == NULL) {
|
||||||
|
sleep_ms(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_count++;
|
||||||
|
bool is_ethernet_status = false;
|
||||||
|
res = icsneoc2_message_is_ethernet_status(message, &is_ethernet_status);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
icsneoc2_message_free(message);
|
||||||
|
print_events();
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
return print_error_code("Failed to check for Ethernet status message", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_ethernet_status) {
|
||||||
|
res = print_ethernet_status_message(message, status_count);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
icsneoc2_message_free(message);
|
||||||
|
print_events();
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
return (int)res;
|
||||||
|
}
|
||||||
|
status_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_message_free(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Received %zu Ethernet status messages out of %zu total messages.\n", status_count, total_count);
|
||||||
|
if(status_count == 0) {
|
||||||
|
printf("No Ethernet status messages were seen. These messages are broadcast when the device goes online and may depend on device Ethernet support.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
print_events();
|
||||||
|
|
||||||
|
printf("Closing device...\n");
|
||||||
|
res = icsneoc2_device_close(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
return print_error_code("Failed to close device", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -176,6 +176,7 @@ int process_message(icsneoc2_message_t** messages, size_t messages_count) {
|
|||||||
// Print the type and bus type of each message
|
// Print the type and bus type of each message
|
||||||
size_t tx_count = 0;
|
size_t tx_count = 0;
|
||||||
size_t can_error_count = 0;
|
size_t can_error_count = 0;
|
||||||
|
size_t internal_count = 0;
|
||||||
icsneoc2_error_t res = icsneoc2_error_success;
|
icsneoc2_error_t res = icsneoc2_error_success;
|
||||||
for(size_t i = 0; i < messages_count; i++) {
|
for(size_t i = 0; i < messages_count; i++) {
|
||||||
icsneoc2_message_t* message = messages[i];
|
icsneoc2_message_t* message = messages[i];
|
||||||
@@ -216,13 +217,21 @@ int process_message(icsneoc2_message_t** messages, size_t messages_count) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This example only cares about bus traffic, so skip internal
|
||||||
|
// device/status messages.
|
||||||
|
icsneoc2_network_type_t internal_check = icsneoc2_network_type_invalid;
|
||||||
|
res = icsneoc2_message_network_type_get(message, &internal_check);
|
||||||
|
if(res == icsneoc2_error_success && internal_check == icsneoc2_network_type_internal) {
|
||||||
|
internal_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_frame = false;
|
bool is_frame = false;
|
||||||
res = icsneoc2_message_is_frame(message, &is_frame);
|
res = icsneoc2_message_is_frame(message, &is_frame);
|
||||||
if(res != icsneoc2_error_success) {
|
if(res != icsneoc2_error_success) {
|
||||||
return print_error_code("\tFailed to check if message is a frame", res);
|
return print_error_code("\tFailed to check if message is a frame", res);
|
||||||
}
|
}
|
||||||
if(!is_frame) {
|
if(!is_frame) {
|
||||||
printf("Ignoring non-frame message at index %zu\n", i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
icsneoc2_network_type_t network_type;
|
icsneoc2_network_type_t network_type;
|
||||||
@@ -296,7 +305,7 @@ int process_message(icsneoc2_message_t** messages, size_t messages_count) {
|
|||||||
printf(" ]\n");
|
printf(" ]\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\tReceived %zu messages total, %zu were TX messages, %zu were CAN errors\n", messages_count, tx_count, can_error_count);
|
printf("\tReceived %zu messages total, %zu were TX messages, %zu were CAN errors, %zu internal (skipped)\n", messages_count, tx_count, can_error_count, internal_count);
|
||||||
|
|
||||||
return icsneoc2_error_success;
|
return icsneoc2_error_success;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ int process_messages(icsneoc2_message_t** messages, size_t messages_count) {
|
|||||||
size_t tx_count = 0;
|
size_t tx_count = 0;
|
||||||
size_t can_error_count = 0;
|
size_t can_error_count = 0;
|
||||||
size_t app_error_count = 0;
|
size_t app_error_count = 0;
|
||||||
|
size_t internal_count = 0;
|
||||||
for(size_t i = 0; i < messages_count; i++) {
|
for(size_t i = 0; i < messages_count; i++) {
|
||||||
icsneoc2_message_t* message = messages[i];
|
icsneoc2_message_t* message = messages[i];
|
||||||
|
|
||||||
@@ -414,13 +415,21 @@ int process_messages(icsneoc2_message_t** messages, size_t messages_count) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This example only cares about bus traffic, so skip internal
|
||||||
|
// device/status messages.
|
||||||
|
icsneoc2_network_type_t internal_check = icsneoc2_network_type_invalid;
|
||||||
|
res = icsneoc2_message_network_type_get(message, &internal_check);
|
||||||
|
if(res == icsneoc2_error_success && internal_check == icsneoc2_network_type_internal) {
|
||||||
|
internal_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_frame = false;
|
bool is_frame = false;
|
||||||
res = icsneoc2_message_is_frame(message, &is_frame);
|
res = icsneoc2_message_is_frame(message, &is_frame);
|
||||||
if(res != icsneoc2_error_success) {
|
if(res != icsneoc2_error_success) {
|
||||||
return print_error_code("\tFailed to check if message is a frame", res);
|
return print_error_code("\tFailed to check if message is a frame", res);
|
||||||
}
|
}
|
||||||
if(!is_frame) {
|
if(!is_frame) {
|
||||||
printf("Ignoring non-frame message at index %zu\n", i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
icsneoc2_network_type_t network_type;
|
icsneoc2_network_type_t network_type;
|
||||||
@@ -494,7 +503,7 @@ int process_messages(icsneoc2_message_t** messages, size_t messages_count) {
|
|||||||
printf(" ]\n");
|
printf(" ]\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\tReceived %zu messages total, %zu were TX messages, %zu were CAN errors, %zu were app errors\n", messages_count, tx_count, can_error_count, app_error_count);
|
printf("\tReceived %zu messages total, %zu were TX messages, %zu were CAN errors, %zu were app errors, %zu internal (skipped)\n", messages_count, tx_count, can_error_count, app_error_count, internal_count);
|
||||||
|
|
||||||
return icsneoc2_error_success;
|
return icsneoc2_error_success;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,37 +4,41 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#include "icsneo/communication/message/message.h"
|
#include "icsneo/communication/message/message.h"
|
||||||
|
#include "icsneo/icsneoc2types.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
class EthernetStatusMessage : public Message {
|
class EthernetStatusMessage : public RawMessage {
|
||||||
public:
|
public:
|
||||||
enum class LinkSpeed {
|
enum class LinkSpeed: icsneoc2_link_speed_t {
|
||||||
LinkSpeedAuto,
|
LinkSpeedAuto = icsneoc2_link_speed_auto,
|
||||||
LinkSpeed10,
|
LinkSpeed10 = icsneoc2_link_speed_10mbps,
|
||||||
LinkSpeed100,
|
LinkSpeed100 = icsneoc2_link_speed_100mbps,
|
||||||
LinkSpeed1000,
|
LinkSpeed1000 = icsneoc2_link_speed_1000mbps,
|
||||||
LinkSpeed2500,
|
LinkSpeed2500 = icsneoc2_link_speed_2500mbps,
|
||||||
LinkSpeed5000,
|
LinkSpeed5000 = icsneoc2_link_speed_5000mbps,
|
||||||
LinkSpeed10000,
|
LinkSpeed10000 = icsneoc2_link_speed_10000mbps,
|
||||||
};
|
};
|
||||||
enum class LinkMode {
|
enum class LinkMode: icsneoc2_link_mode_t {
|
||||||
LinkModeAuto,
|
LinkModeAuto = icsneoc2_link_mode_auto,
|
||||||
LinkModeMaster,
|
LinkModeMaster = icsneoc2_link_mode_master,
|
||||||
LinkModeSlave,
|
LinkModeSlave = icsneoc2_link_mode_slave,
|
||||||
LinkModeInvalid,
|
LinkModeInvalid = icsneoc2_link_mode_invalid,
|
||||||
LinkModeNone,
|
LinkModeNone = icsneoc2_link_mode_none,
|
||||||
};
|
};
|
||||||
EthernetStatusMessage(Network net, bool state, LinkSpeed speed, bool duplex, LinkMode mode) : Message(Type::EthernetStatus),
|
|
||||||
network(net), state(state), speed(speed), duplex(duplex), mode(mode) {}
|
EthernetStatusMessage(Network net, bool state, LinkSpeed speed, bool duplex, LinkMode mode) : RawMessage(Type::EthernetStatus, net),
|
||||||
Network network;
|
state(state), speed(speed), duplex(duplex), mode(mode) {}
|
||||||
|
// Link State: False = Link Down, True = Link Up
|
||||||
bool state;
|
bool state;
|
||||||
LinkSpeed speed;
|
LinkSpeed speed;
|
||||||
|
// Duplex: False = Half, True = Full
|
||||||
bool duplex;
|
bool duplex;
|
||||||
LinkMode mode;
|
LinkMode mode;
|
||||||
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
|
||||||
|
static std::shared_ptr<RawMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace icsneo
|
}; // namespace icsneo
|
||||||
|
|||||||
@@ -298,10 +298,32 @@ icsneoc2_error_t icsneoc2_message_eth_t1s_props_get(icsneoc2_message_t* message,
|
|||||||
*/
|
*/
|
||||||
icsneoc2_error_t icsneoc2_message_is_ethernet(icsneoc2_message_t* message, bool* is_ethernet);
|
icsneoc2_error_t icsneoc2_message_is_ethernet(icsneoc2_message_t* message, bool* is_ethernet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a message is an Ethernet status message
|
||||||
|
*
|
||||||
|
* @param[in] message The message to check.
|
||||||
|
* @param[out] is_ethernet_status Pointer to a bool to copy the Ethernet status of the message into.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_message_is_ethernet_status(icsneoc2_message_t* message, bool* is_ethernet_status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Ethernet status properties from an Ethernet status message
|
||||||
|
*
|
||||||
|
* @param[in] message The message to check.
|
||||||
|
* @param[out] link_state Pointer to a bool to copy the link state into. True if the link is up, false if it's down. If NULL, it's ignored.
|
||||||
|
* @param[out] duplex Pointer to a bool to copy the duplex state into. True if the link is full duplex, false if it's half duplex. If NULL, it's ignored.
|
||||||
|
* @param[out] link_speed Pointer to a icsneoc2_link_speed_t to copy the link speed into. If NULL, it's ignored.
|
||||||
|
* @param[out] link_mode Pointer to a icsneoc2_link_mode_t to copy the link mode into. If NULL, it's ignored.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters, icsneoc2_error_invalid_type otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_message_eth_status_props_get(icsneoc2_message_t* message, bool* link_state, bool* duplex, icsneoc2_link_speed_t* link_speed, icsneoc2_link_mode_t* link_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a message is valid
|
* Check if a message is valid
|
||||||
*
|
*
|
||||||
* @param[in] device The device to check against.
|
|
||||||
* @param[in] message The message to check.
|
* @param[in] message The message to check.
|
||||||
* @param[out] is_valid Pointer to a bool to copy the validity of the message into.
|
* @param[out] is_valid Pointer to a bool to copy the validity of the message into.
|
||||||
*
|
*
|
||||||
@@ -312,7 +334,6 @@ icsneoc2_error_t icsneoc2_message_is_valid(icsneoc2_message_t* message, bool* is
|
|||||||
/**
|
/**
|
||||||
* Check if a message is a raw message (message with data)
|
* Check if a message is a raw message (message with data)
|
||||||
*
|
*
|
||||||
* @param[in] device The device to check against.
|
|
||||||
* @param[in] message The message to check.
|
* @param[in] message The message to check.
|
||||||
* @param[out] is_raw Pointer to a bool to copy the raw status of the message into.
|
* @param[out] is_raw Pointer to a bool to copy the raw status of the message into.
|
||||||
*
|
*
|
||||||
@@ -323,7 +344,6 @@ icsneoc2_error_t icsneoc2_message_is_raw(icsneoc2_message_t* message, bool* is_r
|
|||||||
/**
|
/**
|
||||||
* Check if a message is a frame message (message with data)
|
* Check if a message is a frame message (message with data)
|
||||||
*
|
*
|
||||||
* @param[in] device The device to check against.
|
|
||||||
* @param[in] message The message to check.
|
* @param[in] message The message to check.
|
||||||
* @param[out] is_frame Pointer to a bool to copy the frame status of the message into.
|
* @param[out] is_frame Pointer to a bool to copy the frame status of the message into.
|
||||||
*
|
*
|
||||||
@@ -333,8 +353,7 @@ icsneoc2_error_t icsneoc2_message_is_frame(icsneoc2_message_t* message, bool* is
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a message is a CAN message
|
* Check if a message is a CAN message
|
||||||
*
|
*
|
||||||
* @param[in] device The device to check against.
|
|
||||||
* @param[in] message The message to check.
|
* @param[in] message The message to check.
|
||||||
* @param[out] is_can Pointer to a bool to copy the CAN status of the message into.
|
* @param[out] is_can Pointer to a bool to copy the CAN status of the message into.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -683,6 +683,34 @@ typedef enum _icsneoc2_chip_id_t {
|
|||||||
|
|
||||||
typedef uint8_t icsneoc2_chip_id_t;
|
typedef uint8_t icsneoc2_chip_id_t;
|
||||||
|
|
||||||
|
typedef enum _icsneoc2_link_speed_t {
|
||||||
|
icsneoc2_link_speed_auto = 0,
|
||||||
|
icsneoc2_link_speed_10mbps,
|
||||||
|
icsneoc2_link_speed_100mbps,
|
||||||
|
icsneoc2_link_speed_1000mbps,
|
||||||
|
icsneoc2_link_speed_2500mbps,
|
||||||
|
icsneoc2_link_speed_5000mbps,
|
||||||
|
icsneoc2_link_speed_10000mbps,
|
||||||
|
|
||||||
|
// Must be last entry.
|
||||||
|
icsneoc2_link_speed_maxsize
|
||||||
|
} _icsneoc2_link_speed_t;
|
||||||
|
|
||||||
|
typedef uint8_t icsneoc2_link_speed_t;
|
||||||
|
|
||||||
|
typedef enum _icsneoc2_link_mode_t {
|
||||||
|
icsneoc2_link_mode_auto = 0,
|
||||||
|
icsneoc2_link_mode_master,
|
||||||
|
icsneoc2_link_mode_slave,
|
||||||
|
icsneoc2_link_mode_invalid,
|
||||||
|
icsneoc2_link_mode_none,
|
||||||
|
|
||||||
|
// Must be last entry.
|
||||||
|
icsneoc2_link_mode_maxsize
|
||||||
|
} _icsneoc2_link_mode_t;
|
||||||
|
|
||||||
|
typedef uint8_t icsneoc2_link_mode_t;
|
||||||
|
|
||||||
typedef struct icsneoc2_mac_addr_entry_t icsneoc2_mac_addr_entry_t;
|
typedef struct icsneoc2_mac_addr_entry_t icsneoc2_mac_addr_entry_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <icsneo/communication/message/canmessage.h>
|
#include <icsneo/communication/message/canmessage.h>
|
||||||
#include <icsneo/communication/message/canerrormessage.h>
|
#include <icsneo/communication/message/canerrormessage.h>
|
||||||
#include <icsneo/communication/message/apperrormessage.h>
|
#include <icsneo/communication/message/apperrormessage.h>
|
||||||
|
#include <icsneo/communication/message/ethernetstatusmessage.h>
|
||||||
|
#include <icsneo/communication/message/filter/messagefilter.h>
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -407,6 +409,8 @@ TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device)
|
|||||||
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_eth_t1s_props_set(NULL, NULL, NULL, NULL, NULL));
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_eth_t1s_props_set(NULL, NULL, NULL, NULL, NULL));
|
||||||
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_eth_t1s_props_get(NULL, NULL, NULL, NULL, NULL));
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_eth_t1s_props_get(NULL, NULL, NULL, NULL, NULL));
|
||||||
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_is_ethernet(NULL, NULL));
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_is_ethernet(NULL, NULL));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_is_ethernet_status(NULL, NULL));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_message_eth_status_props_get(NULL, NULL, NULL, NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(icsneoc2, test_icsneoc2_devicetype_t)
|
TEST(icsneoc2, test_icsneoc2_devicetype_t)
|
||||||
@@ -1144,6 +1148,83 @@ TEST(icsneoc2, test_icsneoc2_open_options_default)
|
|||||||
ASSERT_EQ(icsneoc2_open_options_default, expected);
|
ASSERT_EQ(icsneoc2_open_options_default, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(icsneoc2, test_message_filter_c2_includes_internal_messages)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(static_cast<neomessagetype_t>(icsneo::Message::Type::EthernetStatus), 0x8014);
|
||||||
|
|
||||||
|
auto ethernetStatus = std::make_shared<icsneo::EthernetStatusMessage>(
|
||||||
|
icsneo::Network::NetID::ETHERNET_01,
|
||||||
|
true,
|
||||||
|
icsneo::EthernetStatusMessage::LinkSpeed::LinkSpeed1000,
|
||||||
|
true,
|
||||||
|
icsneo::EthernetStatusMessage::LinkMode::LinkModeMaster
|
||||||
|
);
|
||||||
|
auto deviceMessage = std::make_shared<icsneo::RawMessage>(icsneo::Network::NetID::Device);
|
||||||
|
auto deviceStatusMessage = std::make_shared<icsneo::RawMessage>(icsneo::Network::NetID::DeviceStatus);
|
||||||
|
auto internalStatusMessage = std::make_shared<icsneo::Message>(icsneo::Message::Type::TC10Status);
|
||||||
|
auto canMessage = std::make_shared<icsneo::CANMessage>();
|
||||||
|
|
||||||
|
icsneo::MessageFilter defaultFilter;
|
||||||
|
ASSERT_FALSE(defaultFilter.match(ethernetStatus));
|
||||||
|
ASSERT_FALSE(defaultFilter.match(deviceMessage));
|
||||||
|
ASSERT_FALSE(defaultFilter.match(deviceStatusMessage));
|
||||||
|
ASSERT_FALSE(defaultFilter.match(internalStatusMessage));
|
||||||
|
ASSERT_TRUE(defaultFilter.match(canMessage));
|
||||||
|
|
||||||
|
icsneo::MessageFilter c2Filter;
|
||||||
|
c2Filter.includeInternalInAny = true;
|
||||||
|
ASSERT_TRUE(c2Filter.match(ethernetStatus));
|
||||||
|
ASSERT_TRUE(c2Filter.match(deviceMessage));
|
||||||
|
ASSERT_TRUE(c2Filter.match(deviceStatusMessage));
|
||||||
|
ASSERT_TRUE(c2Filter.match(internalStatusMessage));
|
||||||
|
ASSERT_TRUE(c2Filter.match(canMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(icsneoc2, test_icsneoc2_ethernet_status_props_get)
|
||||||
|
{
|
||||||
|
icsneoc2_message_t message;
|
||||||
|
message.message = std::make_shared<icsneo::EthernetStatusMessage>(
|
||||||
|
icsneo::Network::NetID::ETHERNET_01,
|
||||||
|
true,
|
||||||
|
icsneo::EthernetStatusMessage::LinkSpeed::LinkSpeed1000,
|
||||||
|
false,
|
||||||
|
icsneo::EthernetStatusMessage::LinkMode::LinkModeMaster
|
||||||
|
);
|
||||||
|
|
||||||
|
bool isEthernetStatus = false;
|
||||||
|
ASSERT_EQ(icsneoc2_error_success, icsneoc2_message_is_ethernet_status(&message, &isEthernetStatus));
|
||||||
|
ASSERT_TRUE(isEthernetStatus);
|
||||||
|
|
||||||
|
bool linkState = false;
|
||||||
|
bool duplex = true;
|
||||||
|
icsneoc2_link_speed_t linkSpeed = icsneoc2_link_speed_auto;
|
||||||
|
icsneoc2_link_mode_t linkMode = icsneoc2_link_mode_auto;
|
||||||
|
ASSERT_EQ(icsneoc2_error_success, icsneoc2_message_eth_status_props_get(&message, &linkState, &duplex, &linkSpeed, &linkMode));
|
||||||
|
ASSERT_TRUE(linkState);
|
||||||
|
ASSERT_FALSE(duplex);
|
||||||
|
ASSERT_EQ(linkSpeed, icsneoc2_link_speed_1000mbps);
|
||||||
|
ASSERT_EQ(linkMode, icsneoc2_link_mode_master);
|
||||||
|
|
||||||
|
icsneoc2_netid_t netid = icsneoc2_netid_invalid;
|
||||||
|
ASSERT_EQ(icsneoc2_error_success, icsneoc2_message_netid_get(&message, &netid));
|
||||||
|
ASSERT_EQ(netid, icsneoc2_netid_ethernet_01);
|
||||||
|
|
||||||
|
size_t dataLength = 1;
|
||||||
|
ASSERT_EQ(icsneoc2_error_success, icsneoc2_message_data_get(&message, nullptr, &dataLength));
|
||||||
|
ASSERT_EQ(dataLength, 0);
|
||||||
|
|
||||||
|
// A non-Ethernet-status message must be rejected by the props getter and
|
||||||
|
// reported as not-an-Ethernet-status by the predicate.
|
||||||
|
icsneoc2_message_t can_message;
|
||||||
|
can_message.message = std::make_shared<CANMessage>();
|
||||||
|
|
||||||
|
bool isEthernetStatusWrongType = true;
|
||||||
|
ASSERT_EQ(icsneoc2_error_success, icsneoc2_message_is_ethernet_status(&can_message, &isEthernetStatusWrongType));
|
||||||
|
ASSERT_FALSE(isEthernetStatusWrongType);
|
||||||
|
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_type, icsneoc2_message_eth_status_props_get(&can_message, &linkState, &duplex, &linkSpeed, &linkMode));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(icsneoc2, test_icsneoc2_message_is_error)
|
TEST(icsneoc2, test_icsneoc2_message_is_error)
|
||||||
{
|
{
|
||||||
icsneoc2_message_t message;
|
icsneoc2_message_t message;
|
||||||
|
|||||||
Reference in New Issue
Block a user