Communication: Add EthernetStatusMessage
parent
87baa97c3f
commit
f18aa00322
|
|
@ -247,6 +247,7 @@ set(SRC_FILES
|
||||||
communication/message/livedatamessage.cpp
|
communication/message/livedatamessage.cpp
|
||||||
communication/message/tc10statusmessage.cpp
|
communication/message/tc10statusmessage.cpp
|
||||||
communication/message/gptpstatusmessage.cpp
|
communication/message/gptpstatusmessage.cpp
|
||||||
|
communication/message/ethernetstatusmessage.cpp
|
||||||
communication/packet/flexraypacket.cpp
|
communication/packet/flexraypacket.cpp
|
||||||
communication/packet/canpacket.cpp
|
communication/packet/canpacket.cpp
|
||||||
communication/packet/a2bpacket.cpp
|
communication/packet/a2bpacket.cpp
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ pybind11_add_module(icsneopy
|
||||||
icsneopy/communication/message/tc10statusmessage.cpp
|
icsneopy/communication/message/tc10statusmessage.cpp
|
||||||
icsneopy/communication/message/mdiomessage.cpp
|
icsneopy/communication/message/mdiomessage.cpp
|
||||||
icsneopy/communication/message/gptpstatusmessage.cpp
|
icsneopy/communication/message/gptpstatusmessage.cpp
|
||||||
|
icsneopy/communication/message/ethernetstatusmessage.cpp
|
||||||
icsneopy/communication/message/callback/messagecallback.cpp
|
icsneopy/communication/message/callback/messagecallback.cpp
|
||||||
icsneopy/communication/message/filter/messagefilter.cpp
|
icsneopy/communication/message/filter/messagefilter.cpp
|
||||||
icsneopy/device/device.cpp
|
icsneopy/device/device.cpp
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -32,7 +32,8 @@ void init_message(pybind11::module_& m) {
|
||||||
.value("HardwareInfo", Message::Type::HardwareInfo)
|
.value("HardwareInfo", Message::Type::HardwareInfo)
|
||||||
.value("TC10Status", Message::Type::TC10Status)
|
.value("TC10Status", Message::Type::TC10Status)
|
||||||
.value("AppError", Message::Type::AppError)
|
.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(pybind11::init<Message::Type>());
|
||||||
message.def_readonly("type", &Message::type);
|
message.def_readonly("type", &Message::type);
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,15 @@ void init_linmessage(pybind11::module_&);
|
||||||
void init_tc10statusmessage(pybind11::module_&);
|
void init_tc10statusmessage(pybind11::module_&);
|
||||||
void init_gptpstatusmessage(pybind11::module_&);
|
void init_gptpstatusmessage(pybind11::module_&);
|
||||||
void init_mdiomessage(pybind11::module_&);
|
void init_mdiomessage(pybind11::module_&);
|
||||||
|
void init_ethernetstatusmessage(pybind11::module_&);
|
||||||
void init_device(pybind11::module_&);
|
void init_device(pybind11::module_&);
|
||||||
void init_messagefilter(pybind11::module_&);
|
void init_messagefilter(pybind11::module_&);
|
||||||
void init_messagecallback(pybind11::module_&);
|
void init_messagecallback(pybind11::module_&);
|
||||||
void init_version(pybind11::module_&);
|
void init_version(pybind11::module_&);
|
||||||
|
|
||||||
PYBIND11_MODULE(icsneopy, m) {
|
PYBIND11_MODULE(icsneopy, m) {
|
||||||
|
pybind11::options options;
|
||||||
|
options.disable_enum_members_docstring();
|
||||||
m.doc() = "libicsneo Python module";
|
m.doc() = "libicsneo Python module";
|
||||||
|
|
||||||
init_event(m);
|
init_event(m);
|
||||||
|
|
@ -41,6 +44,7 @@ PYBIND11_MODULE(icsneopy, m) {
|
||||||
init_tc10statusmessage(m);
|
init_tc10statusmessage(m);
|
||||||
init_gptpstatusmessage(m);
|
init_gptpstatusmessage(m);
|
||||||
init_mdiomessage(m);
|
init_mdiomessage(m);
|
||||||
|
init_ethernetstatusmessage(m);
|
||||||
init_messagefilter(m);
|
init_messagefilter(m);
|
||||||
init_messagecallback(m);
|
init_messagecallback(m);
|
||||||
init_device(m);
|
init_device(m);
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||||
#include "icsneo/communication/message/gptpstatusmessage.h"
|
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||||
#include "icsneo/communication/message/apperrormessage.h"
|
#include "icsneo/communication/message/apperrormessage.h"
|
||||||
|
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||||
#include "icsneo/communication/command.h"
|
#include "icsneo/communication/command.h"
|
||||||
#include "icsneo/device/device.h"
|
#include "icsneo/device/device.h"
|
||||||
#include "icsneo/communication/packet/canpacket.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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = HardwareCANPacket::DecodeToMessage(packet->data);
|
const auto can = std::dynamic_pointer_cast<CANMessage>(HardwareCANPacket::DecodeToMessage(packet->data));
|
||||||
if(!result) {
|
if(!can) {
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
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
|
result->timestamp *= timestampResolution;
|
||||||
// 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;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::NetID::DeviceStatus: {
|
case Network::NetID::DeviceStatus: {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -1729,15 +1729,6 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
|
||||||
case Message::Type::RawMessage: {
|
case Message::Type::RawMessage: {
|
||||||
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
|
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
|
||||||
switch(rawMessage->network.getNetID()) {
|
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:
|
case Network::NetID::DeviceStatus:
|
||||||
// Device Status format is unique per device, so the devices need to decode it themselves
|
// Device Status format is unique per device, so the devices need to decode it themselves
|
||||||
handleDeviceStatus(rawMessage);
|
handleDeviceStatus(rawMessage);
|
||||||
|
|
@ -1747,6 +1738,15 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
|
||||||
}
|
}
|
||||||
break;
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,41 @@ Receive CAN frames on HSCAN
|
||||||
|
|
||||||
# rx for 10s
|
# rx for 10s
|
||||||
time.sleep(10)
|
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()
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
@ -41,7 +41,8 @@ public:
|
||||||
HardwareInfo = 0x8010,
|
HardwareInfo = 0x8010,
|
||||||
TC10Status = 0x8011,
|
TC10Status = 0x8011,
|
||||||
AppError = 0x8012,
|
AppError = 0x8012,
|
||||||
GPTPStatus = 0x8013
|
GPTPStatus = 0x8013,
|
||||||
|
EthernetStatus = 0x8014,
|
||||||
};
|
};
|
||||||
|
|
||||||
Message(Type t) : type(t) {}
|
Message(Type t) : type(t) {}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue