Communication: Add EthernetStatusMessage

pull/64/head^2
Kyle Schwarz 2024-12-19 18:06:10 -05:00
parent 87baa97c3f
commit f18aa00322
11 changed files with 210 additions and 23 deletions

View File

@ -247,6 +247,7 @@ set(SRC_FILES
communication/message/livedatamessage.cpp
communication/message/tc10statusmessage.cpp
communication/message/gptpstatusmessage.cpp
communication/message/ethernetstatusmessage.cpp
communication/packet/flexraypacket.cpp
communication/packet/canpacket.cpp
communication/packet/a2bpacket.cpp

View File

@ -18,6 +18,7 @@ pybind11_add_module(icsneopy
icsneopy/communication/message/tc10statusmessage.cpp
icsneopy/communication/message/mdiomessage.cpp
icsneopy/communication/message/gptpstatusmessage.cpp
icsneopy/communication/message/ethernetstatusmessage.cpp
icsneopy/communication/message/callback/messagecallback.cpp
icsneopy/communication/message/filter/messagefilter.cpp
icsneopy/device/device.cpp

View File

@ -0,0 +1,35 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/ethernetstatusmessage.h"
namespace icsneo {
void init_ethernetstatusmessage(pybind11::module_& m) {
pybind11::class_<EthernetStatusMessage, std::shared_ptr<EthernetStatusMessage>, Message> ethernetStatusMessage(m, "EthernetStatusMessage");
pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed")
.value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto)
.value("LinkSpeed10", EthernetStatusMessage::LinkSpeed::LinkSpeed10)
.value("LinkSpeed100", EthernetStatusMessage::LinkSpeed::LinkSpeed100)
.value("LinkSpeed1000", EthernetStatusMessage::LinkSpeed::LinkSpeed1000)
.value("LinkSpeed2500", EthernetStatusMessage::LinkSpeed::LinkSpeed2500)
.value("LinkSpeed5000", EthernetStatusMessage::LinkSpeed::LinkSpeed5000)
.value("LinkSpeed10000", EthernetStatusMessage::LinkSpeed::LinkSpeed10000);
pybind11::enum_<EthernetStatusMessage::LinkMode>(ethernetStatusMessage, "LinkMode")
.value("LinkModeAuto", EthernetStatusMessage::LinkMode::LinkModeAuto)
.value("LinkModeMaster", EthernetStatusMessage::LinkMode::LinkModeMaster)
.value("LinkModeSlave", EthernetStatusMessage::LinkMode::LinkModeSlave)
.value("LinkModeInvalid", EthernetStatusMessage::LinkMode::LinkModeInvalid);
ethernetStatusMessage
.def_readonly("network", &EthernetStatusMessage::network)
.def_readonly("state", &EthernetStatusMessage::state)
.def_readonly("speed", &EthernetStatusMessage::speed)
.def_readonly("duplex", &EthernetStatusMessage::duplex)
.def_readonly("mode", &EthernetStatusMessage::mode);
}
} // namespace icsneo

View File

@ -32,7 +32,8 @@ void init_message(pybind11::module_& m) {
.value("HardwareInfo", Message::Type::HardwareInfo)
.value("TC10Status", Message::Type::TC10Status)
.value("AppError", Message::Type::AppError)
.value("GPTPStatus", Message::Type::GPTPStatus);
.value("GPTPStatus", Message::Type::GPTPStatus)
.value("EthernetStatus", Message::Type::EthernetStatus);
message.def(pybind11::init<Message::Type>());
message.def_readonly("type", &Message::type);

View File

@ -19,12 +19,15 @@ void init_linmessage(pybind11::module_&);
void init_tc10statusmessage(pybind11::module_&);
void init_gptpstatusmessage(pybind11::module_&);
void init_mdiomessage(pybind11::module_&);
void init_ethernetstatusmessage(pybind11::module_&);
void init_device(pybind11::module_&);
void init_messagefilter(pybind11::module_&);
void init_messagecallback(pybind11::module_&);
void init_version(pybind11::module_&);
PYBIND11_MODULE(icsneopy, m) {
pybind11::options options;
options.disable_enum_members_docstring();
m.doc() = "libicsneo Python module";
init_event(m);
@ -41,6 +44,7 @@ PYBIND11_MODULE(icsneopy, m) {
init_tc10statusmessage(m);
init_gptpstatusmessage(m);
init_mdiomessage(m);
init_ethernetstatusmessage(m);
init_messagefilter(m);
init_messagecallback(m);
init_device(m);

View File

@ -21,6 +21,7 @@
#include "icsneo/communication/message/tc10statusmessage.h"
#include "icsneo/communication/message/gptpstatusmessage.h"
#include "icsneo/communication/message/apperrormessage.h"
#include "icsneo/communication/message/ethernetstatusmessage.h"
#include "icsneo/communication/command.h"
#include "icsneo/device/device.h"
#include "icsneo/communication/packet/canpacket.h"
@ -238,21 +239,26 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
return true;
}
result = HardwareCANPacket::DecodeToMessage(packet->data);
if(!result) {
const auto can = std::dynamic_pointer_cast<CANMessage>(HardwareCANPacket::DecodeToMessage(packet->data));
if(!can) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return false; // A nullptr was returned, the packet was malformed
return false;
}
if(can->arbid == 0x162) {
result = EthernetStatusMessage::DecodeToMessage(can->data);
if(!result) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return false;
}
} else {
// TODO: move more handleNeoVIMessage handling here, the Decoder layer will parse the message and the Device layer can cache the values
can->network = packet->network;
result = can;
}
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
// The resolution depends on the device
auto* raw = dynamic_cast<RawMessage*>(result.get());
if(raw == nullptr) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return false; // A nullptr was returned, the packet was malformed
}
raw->timestamp *= timestampResolution;
raw->network = packet->network;
result->timestamp *= timestampResolution;
return true;
}
case Network::NetID::DeviceStatus: {

View File

@ -0,0 +1,57 @@
#include "icsneo/communication/message/ethernetstatusmessage.h"
using namespace icsneo;
#pragma pack(push, 1)
enum LinkSpeed {
ethSpeed10,
ethSpeed100,
ethSpeed1000,
ethSpeedAutoNeg,
ethSpeed2500,
ethSpeed5000,
ethSpeed10000,
};
enum LinkMode {
OPETH_LINK_AUTO,
OPETH_LINK_MASTER,
OPETH_LINK_SLAVE,
OPETH_LINK_INVALID = 255,
};
struct Packet {
uint8_t state;
uint8_t speed;
uint8_t duplex;
uint16_t network;
uint8_t mode;
};
#pragma pack(pop)
std::shared_ptr<Message> EthernetStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
if(bytestream.size() < sizeof(Packet)) {
return nullptr;
}
Packet* packet = (Packet*)bytestream.data();
LinkSpeed speed;
switch(packet->speed) {
case ethSpeed10: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed10; break;
case ethSpeed100: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed100; break;
case ethSpeed1000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed1000; break;
case ethSpeedAutoNeg: speed = EthernetStatusMessage::LinkSpeed::LinkSpeedAuto; break;
case ethSpeed2500: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed2500; break;
case ethSpeed5000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed5000; break;
case ethSpeed10000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed10000; break;
default: return nullptr;
}
LinkMode mode;
switch(packet->mode) {
case OPETH_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
case OPETH_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
case OPETH_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
case OPETH_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
default: return nullptr;
}
return std::make_shared<EthernetStatusMessage>(packet->network, packet->state, speed, packet->duplex, mode);
}

View File

@ -1729,15 +1729,6 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
case Message::Type::RawMessage: {
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
switch(rawMessage->network.getNetID()) {
case Network::NetID::Device: {
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
// if it couldn't be decoded to a CANMessage. We only care about the
// CANMessage decoding right now.
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
if(canmsg)
handleNeoVIMessage(std::move(canmsg));
break;
}
case Network::NetID::DeviceStatus:
// Device Status format is unique per device, so the devices need to decode it themselves
handleDeviceStatus(rawMessage);
@ -1747,6 +1738,15 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
}
break;
}
case Message::Type::Frame: {
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
// if it couldn't be decoded to a CANMessage. We only care about the
// CANMessage decoding right now.
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
if(canmsg)
handleNeoVIMessage(std::move(canmsg));
break;
}
default: break;
}
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {

View File

@ -50,3 +50,41 @@ Receive CAN frames on HSCAN
# rx for 10s
time.sleep(10)
Monitor Ethernet Status
=======================
.. code-block:: python
import icsneopy
import time
def main():
devices = icsneopy.find_all_devices()
if len(devices) == 0:
print("error: no devices found")
return False
device = devices[0]
print(f"info: monitoring Ethernet status on {device}")
def on_message(message):
print(f"info: network: {message.network}, state: {message.state}, speed: {message.speed}, duplex: {message.duplex}, mode: {message.mode}")
filter = icsneopy.MessageFilter(icsneopy.Message.Type.EthernetStatus)
callback = icsneopy.MessageCallback(on_message, filter)
device.add_message_callback(callback)
if not device.open():
print("error: unable to open device")
return False
if not device.go_online():
print("error: unable to go online")
return False
while True:
time.sleep(1)
main()

View File

@ -0,0 +1,43 @@
#ifndef __ETHERNETSTATUSMESSAGE_H__
#define __ETHERNETSTATUSMESSAGE_H__
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include <memory>
namespace icsneo {
class EthernetStatusMessage : public Message {
public:
enum class LinkSpeed {
LinkSpeedAuto,
LinkSpeed10,
LinkSpeed100,
LinkSpeed1000,
LinkSpeed2500,
LinkSpeed5000,
LinkSpeed10000,
};
enum class LinkMode {
LinkModeAuto,
LinkModeMaster,
LinkModeSlave,
LinkModeInvalid,
};
EthernetStatusMessage(Network net, bool state, LinkSpeed speed, bool duplex, LinkMode mode) : Message(Type::EthernetStatus),
network(net), state(state), speed(speed), duplex(duplex), mode(mode) {}
Network network;
bool state;
LinkSpeed speed;
bool duplex;
LinkMode mode;
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
};
}; // namespace icsneo
#endif // __cplusplus
#endif // __ETHERNETSTATUSMESSAGE_H__

View File

@ -41,7 +41,8 @@ public:
HardwareInfo = 0x8010,
TC10Status = 0x8011,
AppError = 0x8012,
GPTPStatus = 0x8013
GPTPStatus = 0x8013,
EthernetStatus = 0x8014,
};
Message(Type t) : type(t) {}