From 21bc4eeff2fba0c033d7e7523182f553c0c97dd6 Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Sat, 22 May 2021 01:58:36 -0400 Subject: [PATCH] Message: Create a type system so non-frame data can be represented This change breaks existing code, hence the version bump, but it's going to be much less error prone going forward. --- CMakeLists.txt | 2 +- communication/communication.cpp | 13 +- communication/decoder.cpp | 71 +++--- communication/encoder.cpp | 204 ++++++++++-------- .../flexray/control/flexraycontrolmessage.cpp | 6 +- communication/message/neomessage.cpp | 161 ++++++++------ communication/packet/canpacket.cpp | 113 +++++----- communication/packet/versionpacket.cpp | 4 +- device/device.cpp | 71 +++--- device/extensions/flexray/extension.cpp | 20 +- device/idevicesettings.cpp | 42 ++-- examples/c/interactive/src/main.c | 50 +++-- examples/cpp/interactive/CMakeLists.txt | 2 +- .../interactive/src/InteractiveExample.cpp | 156 +++++++++----- examples/cpp/simple/CMakeLists.txt | 2 +- examples/cpp/simple/src/SimpleExample.cpp | 170 +++++++++------ .../message/canerrorcountmessage.h | 25 +++ .../icsneo/communication/message/canmessage.h | 2 +- .../communication/message/ethernetmessage.h | 2 +- .../message/filter/canmessagefilter.h | 4 +- .../message/filter/main51messagefilter.h | 6 +- .../message/filter/messagefilter.h | 40 +++- .../flexray/control/flexraycontrolmessage.h | 2 +- .../message/flexray/flexraymessage.h | 2 +- .../communication/message/iso9141message.h | 2 +- .../communication/message/main51message.h | 4 +- .../icsneo/communication/message/message.h | 51 ++++- .../icsneo/communication/message/neomessage.h | 65 ++++-- .../message/readsettingsmessage.h | 4 +- .../message/resetstatusmessage.h | 4 +- .../communication/message/versionmessage.h | 11 +- .../icsneo/communication/packet/canpacket.h | 2 +- include/icsneo/device/device.h | 6 +- .../device/extensions/deviceextension.h | 2 +- .../device/extensions/flexray/extension.h | 2 +- .../device/tree/neovifire2/neovifire2.h | 7 +- .../device/tree/neovifire2/neovifire2eth.h | 2 +- include/icsneo/device/tree/plasion/plasion.h | 7 +- .../icsneo/device/tree/radgalaxy/radgalaxy.h | 9 +- .../device/tree/radgigalog/radgigalog.h | 7 +- .../device/tree/radgigalog/radgigalogeth.h | 2 +- .../device/tree/radgigastar/radgigastar.h | 7 +- .../device/tree/radgigastar/radgigastareth.h | 2 +- .../icsneo/device/tree/radstar2/radstar2eth.h | 2 +- .../device/tree/valuecan4/valuecan4-2el.h | 7 +- .../device/tree/valuecan4/valuecan4-2eleth.h | 2 +- .../tree/valuecan4/valuecan4industrialeth.h | 2 +- include/icsneo/icsneocpp.h | 1 + 48 files changed, 853 insertions(+), 527 deletions(-) create mode 100644 include/icsneo/communication/message/canerrorcountmessage.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 23ff690..72b017a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.2) -project(libicsneo VERSION 0.2.0) +project(libicsneo VERSION 0.3.0) option(LIBICSNEO_BUILD_TESTS "Build all tests." OFF) option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF) diff --git a/communication/communication.cpp b/communication/communication.cpp index d1714ac..948349d 100644 --- a/communication/communication.cpp +++ b/communication/communication.cpp @@ -29,7 +29,7 @@ bool Communication::open() { report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error); return false; } - + if(!driver->open()) return false; spawnThreads(); @@ -114,7 +114,7 @@ bool Communication::getSettingsSync(std::vector& data, std::chrono::mil return false; } - data = std::move(msg->data); + data = std::move(gsmsg->data); return true; } @@ -128,7 +128,7 @@ std::shared_ptr Communication::getSerialNumberSync(std::chr auto m51 = std::dynamic_pointer_cast(msg); if(!m51) // Could not upcast for some reason return std::shared_ptr(); - + return std::dynamic_pointer_cast(m51); } @@ -145,7 +145,7 @@ optional< std::vector< optional > > Communication::getVersions if(!ver) // Could not upcast for some reason return nullopt; - if(!ver->MainChip || ver->Versions.size() != 1) + if(ver->ForChip != VersionMessage::MainChip || ver->Versions.size() != 1) return nullopt; ret.push_back(ver->Versions.front()); @@ -155,9 +155,8 @@ optional< std::vector< optional > > Communication::getVersions }, Main51MessageFilter(Command::GetSecondaryVersions), timeout); if(msg) { // This one is allowed to fail ver = std::dynamic_pointer_cast(msg); - if(ver && !ver->MainChip) { + if(ver && ver->ForChip != VersionMessage::MainChip) ret.insert(ret.end(), ver->Versions.begin(), ver->Versions.end()); - } } return ret; @@ -231,7 +230,7 @@ void Communication::readTask() { std::vector readBytes; EventManager::GetInstance().downgradeErrorsOnCurrentThread(); - + while(!closing) { readBytes.clear(); if(driver->readWait(readBytes)) { diff --git a/communication/decoder.cpp b/communication/decoder.cpp index 4cbe7b3..d2538b1 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -3,6 +3,7 @@ #include "icsneo/communication/message/serialnumbermessage.h" #include "icsneo/communication/message/resetstatusmessage.h" #include "icsneo/communication/message/readsettingsmessage.h" +#include "icsneo/communication/message/canerrorcountmessage.h" #include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h" #include "icsneo/communication/command.h" #include "icsneo/device/device.h" @@ -24,7 +25,7 @@ uint64_t Decoder::GetUInt64FromLEBytes(const uint8_t* bytes) { bool Decoder::decode(std::shared_ptr& result, const std::shared_ptr& packet) { switch(packet->network.getType()) { - case Network::Type::Ethernet: + case Network::Type::Ethernet: { result = HardwareEthernetPacket::DecodeToMessage(packet->data, report); if(!result) { report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error); @@ -33,9 +34,11 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrtimestamp *= timestampResolution; - result->network = packet->network; + EthernetMessage& eth = *static_cast(result.get()); + eth.timestamp *= timestampResolution; + eth.network = packet->network; return true; + } case Network::Type::CAN: case Network::Type::SWCAN: case Network::Type::LSFTCAN: { @@ -49,10 +52,28 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrtimestamp *= timestampResolution; - result->network = packet->network; + + switch(result->type) { + case Message::Type::Frame: { + CANMessage& can = *static_cast(result.get()); + can.network = packet->network; + break; + } + case Message::Type::CANErrorCount: { + CANErrorCountMessage& can = *static_cast(result.get()); + can.network = packet->network; + break; + } + default: { + report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error); + return false; // An unknown type was returned, the packet was malformed + } + } + return true; } case Network::Type::FlexRay: { @@ -66,10 +87,12 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrtimestamp *= timestampResolution; - result->network = packet->network; + FlexRayMessage& fr = *static_cast(result.get()); + fr.timestamp *= timestampResolution; + fr.network = packet->network; return true; } case Network::Type::ISO9141: { @@ -84,8 +107,9 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrtimestamp *= timestampResolution; - result->network = packet->network; + ISO9141Message& iso = *static_cast(result.get()); + iso.timestamp *= timestampResolution; + iso.network = packet->network; return true; } case Network::Type::Internal: { @@ -98,7 +122,6 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrdata.data(); auto msg = std::make_shared(); - msg->network = packet->network; msg->mainLoopTime = data->main_loop_time_25ns * 25; msg->maxMainLoopTime = data->max_main_loop_time_25ns * 25; msg->busVoltage = data->busVoltage; @@ -124,9 +147,9 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrdata.size() < 24) { - result = std::make_shared(); - result->network = packet->network; - result->data = packet->data; + auto rawmsg = std::make_shared(Network::NetID::Device); + result = rawmsg; + rawmsg->data = packet->data; return true; } @@ -135,17 +158,21 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrtimestamp *= timestampResolution; - result->network = packet->network; + auto* raw = dynamic_cast(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; } case Network::NetID::DeviceStatus: { - result = std::make_shared(); - result->network = packet->network; // Just pass along the data, the device needs to handle this itself - result->data = packet->data; + result = std::make_shared(packet->network, packet->data); return true; } case Network::NetID::FlexRayControl: { @@ -161,7 +188,6 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrdata[0]) { case Command::RequestSerialNumber: { auto msg = std::make_shared(); - msg->network = packet->network; uint64_t serial = GetUInt64FromLEBytes(packet->data.data() + 1); // The device sends 64-bits of serial number, but we never use more than 32-bits. msg->deviceSerial = Device::SerialNumToString((uint32_t)serial); @@ -194,7 +220,6 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptr(); - msg->network = packet->network; msg->command = Command(packet->data[0]); msg->data.insert(msg->data.begin(), packet->data.begin() + 1, packet->data.end()); result = msg; @@ -218,9 +243,8 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptr(); - msg->network = packet->network; msg->response = ReadSettingsMessage::Response(packet->data[0]); - + if(msg->response == ReadSettingsMessage::Response::OK) { // The global settings structure is the payload of the message in this case msg->data.insert(msg->data.begin(), packet->data.begin() + 10, packet->data.end()); @@ -243,9 +267,6 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptr(); - msg->network = packet->network; - msg->data = packet->data; - result = msg; + result = std::make_shared(packet->network, packet->data); return true; } \ No newline at end of file diff --git a/communication/encoder.cpp b/communication/encoder.cpp index b1d8e20..7f44ec4 100644 --- a/communication/encoder.cpp +++ b/communication/encoder.cpp @@ -9,119 +9,144 @@ using namespace icsneo; bool Encoder::encode(const Packetizer& packetizer, std::vector& result, const std::shared_ptr& message) { bool shortFormat = false; - bool useResultAsBuffer = false; // Otherwise it's expected that we use message->data + std::vector* buffer = &result; + uint16_t netid = 0; result.clear(); - switch(message->network.getType()) { - case Network::Type::Ethernet: { - auto ethmsg = std::dynamic_pointer_cast(message); - if(!ethmsg) { - report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); - return false; // The message was not a properly formed EthernetMessage - } + switch(message->type) { + case Message::Type::Frame: { + auto frame = std::dynamic_pointer_cast(message); - useResultAsBuffer = true; - if(!HardwareEthernetPacket::EncodeFromMessage(*ethmsg, result, report)) - return false; + // Frame uses frame->data as the buffer unless directed otherwise + buffer = &frame->data; + netid = uint16_t(frame->network.getNetID()); + + switch(frame->network.getType()) { + case Network::Type::Ethernet: { + auto ethmsg = std::dynamic_pointer_cast(message); + if(!ethmsg) { + report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); + return false; // The message was not a properly formed EthernetMessage + } + + buffer = &result; + if(!HardwareEthernetPacket::EncodeFromMessage(*ethmsg, result, report)) + return false; + + break; + } // End of Network::Type::Ethernet + case Network::Type::CAN: + case Network::Type::SWCAN: + case Network::Type::LSFTCAN: { + auto canmsg = std::dynamic_pointer_cast(message); + if(!canmsg) { + report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); + return false; // The message was not a properly formed CANMessage + } + + if(!supportCANFD && canmsg->isCANFD) { + report(APIEvent::Type::CANFDNotSupported, APIEvent::Severity::Error); + return false; // This device does not support CAN FD + } + + buffer = &result; + if(!HardwareCANPacket::EncodeFromMessage(*canmsg, result, report)) + return false; // The CANMessage was malformed + + break; + } // End of Network::Type::CAN + case Network::Type::ISO9141: { + auto isomsg = std::dynamic_pointer_cast(message); + if(!isomsg) { + report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); + return false; // The message was not a properly formed ISO9141Message + } + + // Skip the normal message wrapping at the bottom since we need to send multiple + // packets to the device. This function just encodes them back to back into `result` + return HardwareISO9141Packet::EncodeFromMessage(*isomsg, result, report, packetizer); + } // End of Network::Type::ISO9141 + default: + report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error); + return false; + } break; - } // End of Network::Type::Ethernet - case Network::Type::CAN: - case Network::Type::SWCAN: - case Network::Type::LSFTCAN: { - auto canmsg = std::dynamic_pointer_cast(message); - if(!canmsg) { - report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); - return false; // The message was not a properly formed CANMessage - } + } + case Message::Type::RawMessage: { + auto raw = std::dynamic_pointer_cast(message); - if(!supportCANFD && canmsg->isCANFD) { - report(APIEvent::Type::CANFDNotSupported, APIEvent::Severity::Error); - return false; // This device does not support CAN FD - } - - useResultAsBuffer = true; - if(!HardwareCANPacket::EncodeFromMessage(*canmsg, result, report)) - return false; // The CANMessage was malformed + // Raw message uses raw->data as the buffer unless directed otherwise + buffer = &raw->data; + netid = uint16_t(raw->network.getNetID()); - break; - } // End of Network::Type::CAN - case Network::Type::ISO9141: { - auto isomsg = std::dynamic_pointer_cast(message); - if(!isomsg) { - report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); - return false; // The message was not a properly formed ISO9141Message - } - - // Skip the normal message wrapping at the bottom since we need to send multiple - // packets to the device. This function just encodes them back to back into `result` - return HardwareISO9141Packet::EncodeFromMessage(*isomsg, result, report, packetizer); - } // End of Network::Type::ISO9141 - default: - switch(message->network.getNetID()) { + switch(raw->network.getNetID()) { case Network::NetID::Device: shortFormat = true; break; - case Network::NetID::Main51: { - auto m51msg = std::dynamic_pointer_cast(message); - if(!m51msg) { - report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); - return false; // The message was not a properly formed Main51Message - } - - if(!m51msg->forceShortFormat) { - // Main51 can be sent as a long message without setting the NetID to RED first - // Size in long format is the size of the entire packet - // So +1 for AA header, +1 for short format header, and +2 for long format size - uint16_t size = uint16_t(message->data.size()) + 1 + 1 + 2; - size += 1; // Even though we are not including the NetID bytes, the device expects them to be counted in the length - size += 1; // Main51 Command - message->data.insert(message->data.begin(), { - (uint8_t)Network::NetID::Main51, // 0x0B for long message - (uint8_t)size, // Size, little endian 16-bit - (uint8_t)(size >> 8), - (uint8_t)m51msg->command - }); - result = packetizer.packetWrap(message->data, shortFormat); - return true; - } else { - message->data.insert(message->data.begin(), { uint8_t(m51msg->command) }); - shortFormat = true; - } - break; - } case Network::NetID::RED_OLDFORMAT: { // See the decoder for an explanation // We expect the network byte to be populated already in data, but not the length - uint16_t length = uint16_t(message->data.size()) - 1; - message->data.insert(message->data.begin(), {(uint8_t)length, (uint8_t)(length >> 8)}); + uint16_t length = uint16_t(raw->data.size()) - 1; + raw->data.insert(raw->data.begin(), {(uint8_t)length, (uint8_t)(length >> 8)}); break; } default: report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error); return false; } + break; + } + case Message::Type::Main51: { + auto m51msg = std::dynamic_pointer_cast(message); + if(!m51msg) { + report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); + return false; // The message was not a properly formed Main51Message + } + + buffer = &m51msg->data; + netid = uint16_t(Network::NetID::Main51); + + if(!m51msg->forceShortFormat) { + // Main51 can be sent as a long message without setting the NetID to RED first + // Size in long format is the size of the entire packet + // So +1 for AA header, +1 for short format header, and +2 for long format size + uint16_t size = uint16_t(m51msg->data.size()) + 1 + 1 + 2; + size += 1; // Even though we are not including the NetID bytes, the device expects them to be counted in the length + size += 1; // Main51 Command + m51msg->data.insert(m51msg->data.begin(), { + (uint8_t)Network::NetID::Main51, // 0x0B for long message + (uint8_t)size, // Size, little endian 16-bit + (uint8_t)(size >> 8), + (uint8_t)m51msg->command + }); + result = packetizer.packetWrap(m51msg->data, shortFormat); + return true; + } else { + m51msg->data.insert(m51msg->data.begin(), { uint8_t(m51msg->command) }); + shortFormat = true; + } + } + break; } // Early returns may mean we don't reach this far, check the type you're concerned with - auto& buffer = useResultAsBuffer ? result : message->data; - if(shortFormat) { - buffer.insert(buffer.begin(), (uint8_t(buffer.size()) << 4) | uint8_t(message->network.getNetID())); + buffer->insert(buffer->begin(), (uint8_t(buffer->size()) << 4) | uint8_t(netid)); } else { // Size in long format is the size of the entire packet // So +1 for AA header, +1 for short format header, +2 for long format size, and +2 for long format NetID - uint16_t size = uint16_t(buffer.size()) + 1 + 1 + 2 + 2; - buffer.insert(buffer.begin(), { + uint16_t size = uint16_t(buffer->size()) + 1 + 1 + 2 + 2; + buffer->insert(buffer->begin(), { (uint8_t)Network::NetID::RED, // 0x0C for long message (uint8_t)size, // Size, little endian 16-bit (uint8_t)(size >> 8), - (uint8_t)message->network.getNetID(), // NetID, little endian 16-bit - (uint8_t)(uint16_t(message->network.getNetID()) >> 8) + (uint8_t)netid, // NetID, little endian 16-bit + (uint8_t)(netid >> 8) }); } - result = packetizer.packetWrap(buffer, shortFormat); + result = packetizer.packetWrap(*buffer, shortFormat); return true; } @@ -133,20 +158,19 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector& result, * In this case, command 0x06 is SetLEDState. * This old command type is not really used anywhere else. */ - msg = std::make_shared(); + auto canmsg = std::make_shared(Network::NetID::Device); + msg = canmsg; if(arguments.empty()) { report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); return false; } - msg->network = Network::NetID::Device; - msg->data.reserve(3); - msg->data.push_back(0x00); - msg->data.push_back(0x06); // SetLEDState - msg->data.push_back(arguments.at(0)); // See Device::LEDState + canmsg->data.reserve(3); + canmsg->data.push_back(0x00); + canmsg->data.push_back(0x06); // SetLEDState + canmsg->data.push_back(arguments.at(0)); // See Device::LEDState } else { auto m51msg = std::make_shared(); msg = m51msg; - msg->network = Network::NetID::Main51; m51msg->command = cmd; switch(cmd) { case Command::ReadSettings: @@ -161,8 +185,8 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector& result, default: break; } - msg->data.insert(msg->data.end(), std::make_move_iterator(arguments.begin()), std::make_move_iterator(arguments.end())); + m51msg->data.insert(m51msg->data.end(), std::make_move_iterator(arguments.begin()), std::make_move_iterator(arguments.end())); } - + return encode(packetizer, result, msg); } \ No newline at end of file diff --git a/communication/message/flexray/control/flexraycontrolmessage.cpp b/communication/message/flexray/control/flexraycontrolmessage.cpp index 255205f..a51c7c4 100644 --- a/communication/message/flexray/control/flexraycontrolmessage.cpp +++ b/communication/message/flexray/control/flexraycontrolmessage.cpp @@ -64,9 +64,7 @@ std::vector FlexRayControlMessage::BuildWriteMessageBufferArgs( return BuildBaseControlArgs(controller, FlexRay::Opcode::WriteMessageBuffer, args); } -FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message() { - network = Network::NetID::FlexRayControl; - +FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message(Message::Type::FlexRayControl) { if(packet.data.size() < 2) return; // huh? controller = packet.data[0]; @@ -77,7 +75,7 @@ FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message() { opcode = FlexRay::Opcode(packet.data[1]); if(opcode != FlexRay::Opcode::ReadCCRegs && opcode != FlexRay::Opcode::ReadCCStatus) return; - + // Read out registers size_t bytes = packet.data.size() - 2; const size_t count = bytes / sizeof(uint32_t); diff --git a/communication/message/neomessage.cpp b/communication/message/neomessage.cpp index 3262e26..895144a 100644 --- a/communication/message/neomessage.cpp +++ b/communication/message/neomessage.cpp @@ -1,87 +1,116 @@ #include "icsneo/communication/message/neomessage.h" #include "icsneo/communication/message/canmessage.h" #include "icsneo/communication/message/ethernetmessage.h" +#include "icsneo/communication/message/canerrorcountmessage.h" using namespace icsneo; neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr message) { // This function is not responsible for storing the message! // Keep the shared_ptr around for the lifetime of the data access - const auto type = message->network.getType(); neomessage_t neomsg = {}; // Clear out the memory - neomsg.netid = (uint32_t)message->network.getNetID(); - neomsg.type = (uint8_t)type; - neomsg.description = message->description; - neomsg.length = message->data.size(); - neomsg.data = message->data.data(); + neomsg.messageType = (neomessagetype_t)message->type; neomsg.timestamp = message->timestamp; - neomsg.status.globalError = message->error; - neomsg.status.transmitMessage = message->transmitted; + switch (message->type) + { + case Message::Type::Frame: { + neomessage_frame_t& frame = *(neomessage_frame_t*)&neomsg; + auto framemsg = std::static_pointer_cast(message); + const auto netType = framemsg->network.getType(); + frame.netid = (neonetid_t)framemsg->network.getNetID(); + frame.type = (neonettype_t)netType; + frame.description = framemsg->description; + frame.length = framemsg->data.size(); + frame.data = framemsg->data.data(); + frame.timestamp = framemsg->timestamp; + frame.status.globalError = framemsg->error; + frame.status.transmitMessage = framemsg->transmitted; - switch(type) { - case Network::Type::CAN: - case Network::Type::SWCAN: - case Network::Type::LSFTCAN: { - neomessage_can_t& can = *(neomessage_can_t*)&neomsg; - auto canmsg = std::static_pointer_cast(message); - can.arbid = canmsg->arbid; - can.dlcOnWire = canmsg->dlcOnWire; - can.status.extendedFrame = canmsg->isExtended; - can.status.remoteFrame = canmsg->isRemote; - can.status.canfdRTR = canmsg->isRemote; - can.status.canfdFDF = canmsg->isCANFD; - can.status.canfdBRS = canmsg->baudrateSwitch; - can.status.canfdESI = canmsg->errorStateIndicator; - break; + switch(netType) { + case Network::Type::CAN: + case Network::Type::SWCAN: + case Network::Type::LSFTCAN: { + neomessage_can_t& can = *(neomessage_can_t*)&neomsg; + auto canmsg = std::static_pointer_cast(message); + can.arbid = canmsg->arbid; + can.dlcOnWire = canmsg->dlcOnWire; + can.status.extendedFrame = canmsg->isExtended; + can.status.remoteFrame = canmsg->isRemote; + can.status.canfdRTR = canmsg->isRemote; + can.status.canfdFDF = canmsg->isCANFD; + can.status.canfdBRS = canmsg->baudrateSwitch; + can.status.canfdESI = canmsg->errorStateIndicator; + break; + } + case Network::Type::Ethernet: { + neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg; + auto ethmsg = std::static_pointer_cast(message); + eth.preemptionFlags = ethmsg->preemptionFlags; + eth.status.incompleteFrame = ethmsg->frameTooShort; + // TODO Fill in extra status bits + //eth.status.xyz = ethmsg->preemptionEnabled; + //eth.status.xyz = ethmsg->fcsAvailable; + //eth.status.xyz = ethmsg->noPadding; + break; + } + default: + // TODO Implement others + break; } - case Network::Type::Ethernet: { - neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg; - auto ethmsg = std::static_pointer_cast(message); - eth.preemptionFlags = ethmsg->preemptionFlags; - eth.status.incompleteFrame = ethmsg->frameTooShort; - // TODO Fill in extra status bits - //eth.status.xyz = ethmsg->preemptionEnabled; - //eth.status.xyz = ethmsg->fcsAvailable; - //eth.status.xyz = ethmsg->noPadding; - break; - } - default: - // TODO Implement others - break; + break; + } + case Message::Type::CANErrorCount: { + neomessage_can_error_t& canerror = *(neomessage_can_error_t*)&neomsg; + auto canerrormsg = std::static_pointer_cast(message); + canerror.transmitErrorCount = canerrormsg->transmitErrorCount; + canerror.receiveErrorCount = canerrormsg->receiveErrorCount; + canerror.status.canBusOff = canerrormsg->busOff; + canerror.netid = (neonetid_t)canerrormsg->network.getNetID(); + canerror.type = (neonettype_t)canerrormsg->network.getType(); + break; + } + default: + break; } - return neomsg; } std::shared_ptr icsneo::CreateMessageFromNeoMessage(const neomessage_t* neomessage) { - const Network network = neomessage->netid; - switch(network.getType()) { - case Network::Type::CAN: - case Network::Type::SWCAN: - case Network::Type::LSFTCAN: { - neomessage_can_t& can = *(neomessage_can_t*)neomessage; - auto canmsg = std::make_shared(); - canmsg->network = network; - canmsg->description = can.description; - canmsg->data.insert(canmsg->data.end(), can.data, can.data + can.length); - canmsg->arbid = can.arbid; - canmsg->isExtended = can.status.extendedFrame; - canmsg->isRemote = can.status.remoteFrame | can.status.canfdRTR; - canmsg->isCANFD = can.status.canfdFDF; - canmsg->baudrateSwitch = can.status.canfdBRS; - canmsg->errorStateIndicator = can.status.canfdESI; - return canmsg; + switch((Message::Type)neomessage->messageType) { + case Message::Type::Frame: { + const Network network = ((neomessage_frame_t*)neomessage)->netid; + switch(network.getType()) { + case Network::Type::CAN: + case Network::Type::SWCAN: + case Network::Type::LSFTCAN: { + neomessage_can_t& can = *(neomessage_can_t*)neomessage; + auto canmsg = std::make_shared(); + canmsg->network = network; + canmsg->description = can.description; + canmsg->data.insert(canmsg->data.end(), can.data, can.data + can.length); + canmsg->arbid = can.arbid; + canmsg->dlcOnWire = can.dlcOnWire; + canmsg->isExtended = can.status.extendedFrame; + canmsg->isRemote = can.status.remoteFrame | can.status.canfdRTR; + canmsg->isCANFD = can.status.canfdFDF; + canmsg->baudrateSwitch = can.status.canfdBRS; + canmsg->errorStateIndicator = can.status.canfdESI; + return canmsg; + } + case Network::Type::Ethernet: { + neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage; + auto ethmsg = std::make_shared(); + ethmsg->network = network; + ethmsg->description = eth.description; + ethmsg->data.insert(ethmsg->data.end(), eth.data, eth.data + eth.length); + return ethmsg; + } + default: break; + } + break; } - case Network::Type::Ethernet: { - neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage; - auto ethmsg = std::make_shared(); - ethmsg->network = network; - ethmsg->description = eth.description; - ethmsg->data.insert(ethmsg->data.end(), eth.data, eth.data + eth.length); - return ethmsg; - } - default: - // TODO Implement others - return std::shared_ptr(); + default: break; } + return std::shared_ptr(); + } \ No newline at end of file diff --git a/communication/packet/canpacket.cpp b/communication/packet/canpacket.cpp index 4268a69..50190f7 100644 --- a/communication/packet/canpacket.cpp +++ b/communication/packet/canpacket.cpp @@ -1,4 +1,5 @@ #include "icsneo/communication/packet/canpacket.h" +#include "icsneo/communication/message/canerrorcountmessage.h" #include "icsneo/platform/optional.h" using namespace icsneo; @@ -6,7 +7,7 @@ using namespace icsneo; static optional CANFD_DLCToLength(uint8_t length) { if (length < 8) return length; - + switch(length) { case 0x9: return 12; @@ -26,61 +27,75 @@ static optional CANFD_DLCToLength(uint8_t length) { return nullopt; } -std::shared_ptr HardwareCANPacket::DecodeToMessage(const std::vector& bytestream) { +std::shared_ptr HardwareCANPacket::DecodeToMessage(const std::vector& bytestream) { const HardwareCANPacket* data = (const HardwareCANPacket*)bytestream.data(); - auto msg = std::make_shared(); + if(data->dlc.RB1) { // Change counts reporting - // Arb ID - if(data->header.IDE) { // Extended 29-bit ID - msg->arbid = (data->header.SID & 0x7ff) << 18; - msg->arbid |= (data->eid.EID & 0xfff) << 6; - msg->arbid |= (data->dlc.EID2 & 0x3f); - msg->isExtended = true; - } else { // Standard 11-bit ID - msg->arbid = data->header.SID; - } + const bool busOff = data->data[0] & 0b00100000; - // This timestamp is raw off the device (in timestampResolution increments) - // Decoder will fix as it has information about the timestampResolution increments - msg->timestamp = data->timestamp.TS; + auto msg = std::make_shared(data->data[2], data->data[1], busOff); - // DLC - uint8_t length = data->dlc.DLC; - msg->dlcOnWire = length; // This will hold the real DLC on wire 0x0 - 0xF - if(data->header.EDL && data->timestamp.IsExtended) { // CAN FD - msg->isCANFD = true; - msg->baudrateSwitch = data->header.BRS; // CAN FD Baudrate Switch - msg->errorStateIndicator = data->header.ESI; - const optional lenFromDLC = CANFD_DLCToLength(length); - if (lenFromDLC) - length = *lenFromDLC; - } else if(length > 8) { // This is a standard CAN frame with a length of more than 8 - // Yes, this is possible. On the wire, the length field is a nibble, and we do want to return an accurate value - // We don't want to overread our buffer, though, so make sure we cap the length - length = 8; - } - - // Data - // The first 8 bytes are always in the standard place - if((data->dlc.RTR && data->header.IDE) || (!data->header.IDE && data->header.SRR)) { // Remote Request Frame - msg->data.resize(length); // This data will be all zeros, but the length will be set - msg->isRemote = true; - } else { - msg->data.reserve(length); - msg->data.insert(msg->data.end(), data->data, data->data + (length > 8 ? 8 : length)); - if(length > 8) { // If there are more than 8 bytes, they come at the end of the message - // Messages with extra data are formatted as message, then uint16_t netid, then uint16_t length, then extra data - const auto extraDataStart = bytestream.begin() + sizeof(HardwareCANPacket) + 2 + 2; - msg->data.insert(msg->data.end(), extraDataStart, extraDataStart + (length - 8)); + // This timestamp is raw off the device (in timestampResolution increments) + // Decoder will fix as it has information about the timestampResolution increments + msg->timestamp = data->timestamp.TS; + + return msg; + + } else { // CAN Frame + auto msg = std::make_shared(); + + // Arb ID + if(data->header.IDE) { // Extended 29-bit ID + msg->arbid = (data->header.SID & 0x7ff) << 18; + msg->arbid |= (data->eid.EID & 0xfff) << 6; + msg->arbid |= (data->dlc.EID2 & 0x3f); + msg->isExtended = true; + } else { // Standard 11-bit ID + msg->arbid = data->header.SID; } + + // This timestamp is raw off the device (in timestampResolution increments) + // Decoder will fix as it has information about the timestampResolution increments + msg->timestamp = data->timestamp.TS; + + // DLC + uint8_t length = data->dlc.DLC; + msg->dlcOnWire = length; // This will hold the real DLC on wire 0x0 - 0xF + if(data->header.EDL && data->timestamp.IsExtended) { // CAN FD + msg->isCANFD = true; + msg->baudrateSwitch = data->header.BRS; // CAN FD Baudrate Switch + msg->errorStateIndicator = data->header.ESI; + const optional lenFromDLC = CANFD_DLCToLength(length); + if (lenFromDLC) + length = *lenFromDLC; + } else if(length > 8) { // This is a standard CAN frame with a length of more than 8 + // Yes, this is possible. On the wire, the length field is a nibble, and we do want to return an accurate value + // We don't want to overread our buffer, though, so make sure we cap the length + length = 8; + } + + // Data + // The first 8 bytes are always in the standard place + if((data->dlc.RTR && data->header.IDE) || (!data->header.IDE && data->header.SRR)) { // Remote Request Frame + msg->data.resize(length); // This data will be all zeros, but the length will be set + msg->isRemote = true; + } else { + msg->data.reserve(length); + msg->data.insert(msg->data.end(), data->data, data->data + (length > 8 ? 8 : length)); + if(length > 8) { // If there are more than 8 bytes, they come at the end of the message + // Messages with extra data are formatted as message, then uint16_t netid, then uint16_t length, then extra data + const auto extraDataStart = bytestream.begin() + sizeof(HardwareCANPacket) + 2 + 2; + msg->data.insert(msg->data.end(), extraDataStart, extraDataStart + (length - 8)); + } + } + + msg->transmitted = data->eid.TXMSG; + msg->error = data->eid.TXAborted || data->eid.TXError || data->eid.TXLostArb; + msg->description = data->stats; + + return msg; } - - msg->transmitted = data->eid.TXMSG; - msg->error = data->eid.TXAborted || data->eid.TXError || data->eid.TXLostArb; - msg->description = data->stats; - - return msg; } bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector& result, const device_eventhandler_t& report) { diff --git a/communication/packet/versionpacket.cpp b/communication/packet/versionpacket.cpp index 7725965..4176419 100644 --- a/communication/packet/versionpacket.cpp +++ b/communication/packet/versionpacket.cpp @@ -6,7 +6,7 @@ std::shared_ptr HardwareVersionPacket::DecodeMainToMessage(const if(bytestream.size() < 3) // Not enough bytes to decode return std::shared_ptr(); - auto msg = std::make_shared(true); + auto msg = std::make_shared(VersionMessage::MainChip); optional& version = msg->Versions.emplace_back(); version.emplace(); @@ -17,7 +17,7 @@ std::shared_ptr HardwareVersionPacket::DecodeMainToMessage(const } std::shared_ptr HardwareVersionPacket::DecodeSecondaryToMessage(const std::vector& bytestream) { - auto msg = std::make_shared(false); + auto msg = std::make_shared(VersionMessage::SecondaryChips); size_t bytesLeft = bytestream.size(); if(bytesLeft) diff --git a/device/device.cpp b/device/device.cpp index e4e4fd2..5d12ac3 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -117,19 +117,16 @@ std::pair>, bool> Device::getMessages() { } bool Device::getMessages(std::vector>& container, size_t limit, std::chrono::milliseconds timeout) { - // not open if(!isOpen()) { report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); return false; } - // not online if(!isOnline()) { report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error); return false; } - // not currently polling, throw error if(!isMessagePollingEnabled()) { report(APIEvent::Type::DeviceNotCurrentlyPolling, APIEvent::Severity::Error); return false; @@ -285,7 +282,7 @@ APIEvent::Type Device::attemptToBeginCommunication() { } if(!serial) // "Communication could not be established with the device. Perhaps it is not powered with 12 volts?" return getCommunicationNotEstablishedError(); - + std::string currentSerial = getNeoDevice().serial; if(currentSerial != serial->deviceSerial) return APIEvent::Type::IncorrectSerialNumber; @@ -309,7 +306,7 @@ bool Device::close() { if(isOnline()) goOffline(); - + if(internalHandlerCallbackID) com->removeMessageCallback(internalHandlerCallbackID); @@ -352,7 +349,7 @@ bool Device::goOnline() { if(failOut) return false; } - + online = true; forEachExtension([](const std::shared_ptr& ext) { ext->onGoOnline(); return true; }); @@ -373,9 +370,9 @@ bool Device::goOffline() { auto startTime = std::chrono::system_clock::now(); ledState = (latestResetStatus && latestResetStatus->cmRunning) ? LEDState::CoreMiniRunning : LEDState::Offline; - + updateLEDState(); - + MessageFilter filter(Network::NetID::Reset_Status); filter.includeInternalInAny = true; @@ -383,32 +380,30 @@ bool Device::goOffline() { while((std::chrono::system_clock::now() - startTime) < std::chrono::seconds(5)) { if(latestResetStatus && !latestResetStatus->comEnabled) break; - + if(!com->sendCommand(Command::RequestStatusUpdate)) return false; com->waitForMessageSync(filter, std::chrono::milliseconds(100)); } - + online = false; return true; } -bool Device::transmit(std::shared_ptr message) { - // not open +bool Device::transmit(std::shared_ptr frame) { if(!isOpen()) { report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); return false; } - // not online if(!isOnline()) { report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error); return false; } - if(!isSupportedTXNetwork(message->network)) { + if(!isSupportedTXNetwork(frame->network)) { report(APIEvent::Type::UnsupportedTXNetwork, APIEvent::Severity::Error); return false; } @@ -416,7 +411,7 @@ bool Device::transmit(std::shared_ptr message) { bool extensionHookedTransmit = false; bool transmitStatusFromExtension = false; forEachExtension([&](const std::shared_ptr& ext) { - if(!ext->transmitHook(message, transmitStatusFromExtension)) + if(!ext->transmitHook(frame, transmitStatusFromExtension)) extensionHookedTransmit = true; return !extensionHookedTransmit; // false breaks out of the loop early }); @@ -424,15 +419,15 @@ bool Device::transmit(std::shared_ptr message) { return transmitStatusFromExtension; std::vector packet; - if(!com->encoder->encode(*com->packetizer, packet, message)) + if(!com->encoder->encode(*com->packetizer, packet, frame)) return false; - + return com->sendPacket(packet); } -bool Device::transmit(std::vector> messages) { - for(auto& message : messages) { - if(!transmit(message)) +bool Device::transmit(std::vector> frames) { + for(auto& frame : frames) { + if(!transmit(frame)) return false; } return true; @@ -692,22 +687,32 @@ void Device::forEachExtension(std::function message) { - switch(message->network.getNetID()) { - case Network::NetID::Reset_Status: - latestResetStatus = std::dynamic_pointer_cast(message); + switch(message->type) { + case Message::Type::ResetStatus: + latestResetStatus = std::static_pointer_cast(message); break; - case Network::NetID::Device: { - auto canmsg = std::dynamic_pointer_cast(message); - if(canmsg) - handleNeoVIMessage(std::move(canmsg)); + case Message::Type::RawMessage: { + auto rawMessage = std::static_pointer_cast(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(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); + break; + default: + break; //std::cout << "HandleInternalMessage got a message from " << message->network << " and it was unhandled!" << std::endl; + } break; } - case Network::NetID::DeviceStatus: - // Device Status format is unique per device, so the devices need to decode it themselves - handleDeviceStatus(message); - break; - default: - break; //std::cout << "HandleInternalMessage got a message from " << message->network << " and it was unhandled!" << std::endl; + default: break; } forEachExtension([&](const std::shared_ptr& ext) { ext->handleMessage(message); diff --git a/device/extensions/flexray/extension.cpp b/device/extensions/flexray/extension.cpp index fb5d0e2..96e7d8d 100644 --- a/device/extensions/flexray/extension.cpp +++ b/device/extensions/flexray/extension.cpp @@ -26,18 +26,16 @@ void FlexRay::Extension::onGoOffline() { } void FlexRay::Extension::handleMessage(const std::shared_ptr& message) { - switch(message->network.getNetID()) { - case Network::NetID::FlexRayControl: { + switch(message->type) { + case Message::Type::FlexRayControl: { auto msg = std::dynamic_pointer_cast(message); if(!msg || !msg->decoded) return; switch(msg->opcode) { case FlexRay::Opcode::ReadCCStatus: - if(auto status = std::dynamic_pointer_cast(message)) { // TODO else report error? - if(status->controller >= controllers.size()) - return; // TODO error - controllers[status->controller]->_setStatus(status); - } + if(msg->controller >= controllers.size()) + return; // TODO error + controllers[msg->controller]->_setStatus(msg); break; } break; @@ -47,18 +45,18 @@ void FlexRay::Extension::handleMessage(const std::shared_ptr& message) } } -bool FlexRay::Extension::transmitHook(const std::shared_ptr& message, bool& success) { - if(!message || message->network.getType() != Network::Type::FlexRay) +bool FlexRay::Extension::transmitHook(const std::shared_ptr& frame, bool& success) { + if(!frame || frame->network.getType() != Network::Type::FlexRay) return true; // Don't hook non-FlexRay messages success = false; - std::shared_ptr frmsg = std::dynamic_pointer_cast(message); + std::shared_ptr frmsg = std::dynamic_pointer_cast(frame); if(!frmsg) return false; for(auto& controller : controllers) { - if(controller->getNetwork() != message->network) + if(controller->getNetwork() != frame->network) continue; success |= controller->transmit(frmsg); } diff --git a/device/idevicesettings.cpp b/device/idevicesettings.cpp index 8f27ce6..88c9417 100644 --- a/device/idevicesettings.cpp +++ b/device/idevicesettings.cpp @@ -17,7 +17,7 @@ optional IDeviceSettings::CalculateGSChecksum(const std::vector msg = com->waitForMessageSync([this, &bytestream]() { + + std::shared_ptr msg = std::dynamic_pointer_cast(com->waitForMessageSync([this, &bytestream]() { return com->sendCommand(Command::SetSettings, bytestream); - }, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000)); + }, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000))); if(!msg || msg->data[0] != 1) { // We did not receive a response // Attempt to get the settings from the device so we're up to date if possible @@ -254,9 +254,9 @@ bool IDeviceSettings::apply(bool temporary) { bytestream[6] = (uint8_t)(*gsChecksum >> 8); memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size()); - msg = com->waitForMessageSync([this, &bytestream]() { + msg = std::dynamic_pointer_cast(com->waitForMessageSync([this, &bytestream]() { return com->sendCommand(Command::SetSettings, bytestream); - }, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000)); + }, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000))); if(!msg || msg->data[0] != 1) { // Attempt to get the settings from the device so we're up to date if possible if(refresh()) { @@ -267,11 +267,11 @@ bool IDeviceSettings::apply(bool temporary) { } if(!temporary) { - msg = com->waitForMessageSync([this]() { + msg = std::dynamic_pointer_cast(com->waitForMessageSync([this]() { return com->sendCommand(Command::SaveSettings); - }, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000)); + }, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000))); } - + applyingSettings = false; refresh(); // Refresh our buffer with what the device has, whether we were successful or not @@ -296,9 +296,9 @@ bool IDeviceSettings::applyDefaults(bool temporary) { applyingSettings = true; - std::shared_ptr msg = com->waitForMessageSync([this]() { + std::shared_ptr msg = std::dynamic_pointer_cast(com->waitForMessageSync([this]() { return com->sendCommand(Command::SetDefaultSettings); - }, Main51MessageFilter(Command::SetDefaultSettings), std::chrono::milliseconds(1000)); + }, Main51MessageFilter(Command::SetDefaultSettings), std::chrono::milliseconds(1000))); if(!msg || msg->data[0] != 1) { // Attempt to get the settings from the device so we're up to date if possible if(refresh()) { @@ -331,9 +331,9 @@ bool IDeviceSettings::applyDefaults(bool temporary) { bytestream[6] = (uint8_t)(*gsChecksum >> 8); memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size()); - msg = com->waitForMessageSync([this, &bytestream]() { + msg = std::dynamic_pointer_cast(com->waitForMessageSync([this, &bytestream]() { return com->sendCommand(Command::SetSettings, bytestream); - }, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000)); + }, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000))); if(!msg || msg->data[0] != 1) { // Attempt to get the settings from the device so we're up to date if possible if(refresh()) { @@ -344,13 +344,13 @@ bool IDeviceSettings::applyDefaults(bool temporary) { } if(!temporary) { - msg = com->waitForMessageSync([this]() { + msg = std::dynamic_pointer_cast(com->waitForMessageSync([this]() { return com->sendCommand(Command::SaveSettings); - }, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000)); + }, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000))); } applyingSettings = false; - + refresh(); // Refresh our buffer with what the device has, whether we were successful or not bool ret = (msg && msg->data[0] == 1); // Device sends 0x01 for success @@ -420,7 +420,7 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) { report(APIEvent::Type::CANSettingsNotAvailable, APIEvent::Severity::Error); return false; } - + CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate); if(newBaud == (CANBaudrate)-1) { report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error); @@ -437,7 +437,7 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) { report(APIEvent::Type::LSFTCANSettingsNotAvailable, APIEvent::Severity::Error); return false; } - + CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate); if(newBaud == (CANBaudrate)-1) { report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error); @@ -454,7 +454,7 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) { report(APIEvent::Type::SWCANSettingsNotAvailable, APIEvent::Severity::Error); return false; } - + CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate); if(newBaud == (CANBaudrate)-1) { report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error); @@ -691,7 +691,7 @@ template bool IDeviceSettings::applyStructure(const T& newStructure) report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error); return false; } - + // This function is only called from C++ so the caller's structure size and ours should never differ if(sizeof(T) != structSize) { report(APIEvent::Type::SettingsStructureMismatch, APIEvent::Severity::Error); diff --git a/examples/c/interactive/src/main.c b/examples/c/interactive/src/main.c index 509d36a..0f2daaf 100644 --- a/examples/c/interactive/src/main.c +++ b/examples/c/interactive/src/main.c @@ -314,7 +314,7 @@ int main() { printLastError(); printf("\n"); } - + break; default: printf("Canceling!\n\n"); @@ -425,7 +425,7 @@ int main() { break; default: printf("Canceling!\n\n"); - } + } } break; // Get messages @@ -467,24 +467,34 @@ int main() { // Print out the received messages for(size_t i = 0; i < msgCount; i++) { - neomessage_t* msg = &msgs[i]; - switch(msg->type) { - case ICSNEO_NETWORK_TYPE_CAN: // CAN - { - neomessage_can_t* canMsg = (neomessage_can_t*) msg; - printf("\t0x%03x [%zu] ", canMsg->arbid, canMsg->length); - for(size_t i = 0; i < canMsg->length; i++) { - printf("%02x ", canMsg->data[i]); + const neomessage_t* msg = &msgs[i]; + switch(msg->messageType) { + case ICSNEO_MESSAGE_TYPE_FRAME: { + const neomessage_frame_t* frame = (neomessage_frame_t*)msg; + switch(frame->type) { + case ICSNEO_NETWORK_TYPE_CAN: { + neomessage_can_t* canMsg = (neomessage_can_t*)frame; + printf("\t0x%03x [%zu] ", canMsg->arbid, canMsg->length); + for(size_t i = 0; i < canMsg->length; i++) { + printf("%02x ", canMsg->data[i]); + } + if(canMsg->status.transmitMessage) + printf("TX%s %04x ", canMsg->status.globalError ? " ERR" : "", canMsg->description); + printf("(%"PRIu64")\n", canMsg->timestamp); + break; + } + default: + printf("\tMessage on netid %d with length %zu\n", frame->netid, frame->length); + break; + } + break; + } + case ICSNEO_MESSAGE_TYPE_CAN_ERROR_COUNT: { + const neomessage_can_error_t* cec = (neomessage_can_error_t*)msg; + printf("\tCAN error counts changed, TEC=%d, REC=%d%s", cec->transmitErrorCount, cec->receiveErrorCount, + cec->status.canBusOff ? " (Bus Off)" : ""); + break; } - if(canMsg->status.transmitMessage) - printf("TX%s %04x ", canMsg->status.globalError ? " ERR" : "", canMsg->description); - printf("(%"PRIu64")\n", canMsg->timestamp); - break; - } - default: - if(msg->netid != 0) - printf("\tMessage on netid %d with length %zu\n", msg->netid, msg->length); - break; } } printf("\n"); @@ -689,7 +699,7 @@ int main() { { case '1': type = ICSNEO_IO_ETH_ACTIVATION; break; case '2': type = ICSNEO_IO_USB_HOST_POWER; break; - case '3': type = ICSNEO_IO_BACKUP_POWER_EN; break; + case '3': type = ICSNEO_IO_BACKUP_POWER_EN; break; }; if(icsneo_setDigitalIO(selectedDevice, type, 1, set)) { printf("OK!\n\n"); diff --git a/examples/cpp/interactive/CMakeLists.txt b/examples/cpp/interactive/CMakeLists.txt index 63671d9..ea897b7 100644 --- a/examples/cpp/interactive/CMakeLists.txt +++ b/examples/cpp/interactive/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.2) project(libicsneocpp-interactive-example VERSION 0.2.0) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED 11) include(GNUInstallDirs) diff --git a/examples/cpp/interactive/src/InteractiveExample.cpp b/examples/cpp/interactive/src/InteractiveExample.cpp index add2a84..dea2fad 100644 --- a/examples/cpp/interactive/src/InteractiveExample.cpp +++ b/examples/cpp/interactive/src/InteractiveExample.cpp @@ -182,6 +182,102 @@ std::shared_ptr selectDevice(const std::vector& message) { + switch(message->type) { + case icsneo::Message::Type::Frame: { + // A message of type Frame is guaranteed to be a Frame, so we can static cast safely + auto frame = std::static_pointer_cast(message); + switch(frame->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(message); + + std::cout << "\t\t" << frame->network << ' '; + 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(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; + } + case icsneo::Network::Type::ISO9141: { + // Note that the default settings on some devices have ISO9141 disabled by default in favor of LIN + // and that this example loads the device defaults at the very end. + // A message of type ISO9414 is guaranteed to be an ISO9141Message, so we can static cast safely + auto isoMessage = std::static_pointer_cast(message); + + std::cout << "\t\t" << isoMessage->network << ' '; + + // Print the header bytes + std::cout << '(' << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[0] << ' '; + std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[1] << ' '; + std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[2] << ") "; + + // Print the data length + std::cout << std::dec << " [" << isoMessage->data.size() << "] "; + + // Print the data + for(auto& databyte : isoMessage->data) + std::cout << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)databyte << ' '; + + // Print the timestamp + std::cout << std::dec << '(' << isoMessage->timestamp << " ns since 1/1/2007)\n"; + break; + } + default: + // Ignoring non-network messages + break; + } + break; + } // end of icsneo::Message::Type::Frame + case icsneo::Message::Type::CANErrorCount: { + // A message of type CANErrorCount is guaranteed to be a CANErrorCount, so we can static cast safely + auto cec = std::static_pointer_cast(message); + std::cout << "\t\t" << cec->network << " error counts changed, REC=" << cec->receiveErrorCount + << " TEC=" << cec->transmitErrorCount << " (" << (cec->busOff ? "" : "Not ") << "Bus Off)" << std::endl; + break; + } + default: + // Ignoring other types of messages + break; + } +} + int main() { std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl << std::endl; @@ -237,7 +333,7 @@ int main() { std::cout << "[1] Open" << std::endl << "[2] Close" << std::endl << "[3] Cancel" << std::endl << std::endl; char selection = getCharInput(std::vector {'1', '2', '3'}); std::cout << std::endl; - + switch(selection) { case '1': if(selectedDevice->open()) { @@ -247,7 +343,7 @@ int main() { std::cout << icsneo::GetLastError() << std::endl; std::cout << std::endl; } - + break; case '2': // Attempt to close the device @@ -259,7 +355,7 @@ int main() { std::cout << icsneo::GetLastError() << std::endl;; std::cout << std::endl; } - + break; default: std::cout << "Canceling!" << std::endl << std::endl; @@ -360,7 +456,7 @@ int main() { default: std::cout << "Canceling!" << std::endl << std::endl; break; - } + } } break; // Get messages @@ -392,29 +488,9 @@ int main() { } // 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(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; - } + for(const auto& msg : msgs) + printMessage(msg); - 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; } @@ -445,7 +521,7 @@ int main() { 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(); @@ -538,28 +614,8 @@ int main() { switch(selection) { case '1': { - // Shameless copy-paste from get messages above, demonstrating a callback int callbackID = selectedDevice->addMessageCallback(icsneo::MessageCallback([](std::shared_ptr 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(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; - } + printMessage(msg); })); if(callbackID != -1) { @@ -578,7 +634,7 @@ int main() { break; } else { std::vector allowed; - + std::cout << "Which id would you like to remove?" << std::endl; for(int id : callbacks.find(selectedDevice)->second) { allowed.push_back(static_cast(id) + '0'); @@ -595,7 +651,7 @@ int main() { } else { std::cout << "Failed to remove message callback id " << removeID << " from " << selectedDevice->describe() << "!" << std::endl << std::endl; std::cout << icsneo::GetLastError() << std::endl;; - } + } } } break; diff --git a/examples/cpp/simple/CMakeLists.txt b/examples/cpp/simple/CMakeLists.txt index e89a63f..4a5f5ec 100644 --- a/examples/cpp/simple/CMakeLists.txt +++ b/examples/cpp/simple/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.2) project(libicsneocpp-simple-example VERSION 0.2.0) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED 11) include(GNUInstallDirs) diff --git a/examples/cpp/simple/src/SimpleExample.cpp b/examples/cpp/simple/src/SimpleExample.cpp index 4dcc7ed..e7c7738 100644 --- a/examples/cpp/simple/src/SimpleExample.cpp +++ b/examples/cpp/simple/src/SimpleExample.cpp @@ -8,7 +8,7 @@ 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.getGenericProductName() << std::endl; @@ -85,7 +85,7 @@ int main() { 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) @@ -126,82 +126,118 @@ int main() { 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 transmit messages + std::cout << "\tTransmitting an extended CAN FD frame... "; + auto txMessage5 = std::make_shared(); + txMessage5->network = icsneo::Network::NetID::HSCAN; + txMessage5->arbid = 0x1C5001C5; + txMessage5->data.insert(txMessage5->data.end(), {0xaa, 0xbb, 0xcc}); + // The DLC will come from the length of the data vector + txMessage5->isExtended = true; + txMessage5->isCANFD = true; + ret = device->transmit(txMessage5); // This will return false if the device does not support CAN FD, or does not have HSCAN + std::cout << (ret ? "OK" : "FAIL") << std::endl; + // 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 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(message); - - std::cout << "\t\tCAN "; - if(canMessage->isCANFD) { - std::cout << "FD "; - if(!canMessage->baudrateSwitch) - std::cout << "(No BRS) "; + switch(message->type) { + case icsneo::Message::Type::Frame: { + // A message of type Frame is guaranteed to be a Frame, so we can static cast safely + auto frame = std::static_pointer_cast(message); + switch(frame->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(message); + + std::cout << "\t\t" << frame->network << ' '; + 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(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; + } + case icsneo::Network::Type::ISO9141: { + // Note that the default settings on some devices have ISO9141 disabled by default in favor of LIN + // and that this example loads the device defaults at the very end. + // A message of type ISO9414 is guaranteed to be an ISO9141Message, so we can static cast safely + auto isoMessage = std::static_pointer_cast(message); + + std::cout << "\t\t" << isoMessage->network << ' '; + + // Print the header bytes + std::cout << '(' << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[0] << ' '; + std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[1] << ' '; + std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[2] << ") "; + + // Print the data length + std::cout << std::dec << " [" << isoMessage->data.size() << "] "; + + // Print the data + for(auto& databyte : isoMessage->data) + std::cout << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)databyte << ' '; + + // Print the timestamp + std::cout << std::dec << '(' << isoMessage->timestamp << " ns since 1/1/2007)\n"; + break; + } + default: + // Ignoring non-network messages + break; } - - // 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(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] << ' '; - } + } // end of icsneo::Message::Type::Frame + case icsneo::Message::Type::CANErrorCount: { + // A message of type CANErrorCount is guaranteed to be a CANErrorCount, so we can static cast safely + auto cec = std::static_pointer_cast(message); - std::cout << std::dec << std::endl; - break; - } - case icsneo::Network::Type::ISO9141: { - // Note that the default settings on some devices have ISO9141 disabled by default in favor of LIN - // and that this example loads the device defaults at the very end. - // A message of type ISO9414 is guaranteed to be an ISO9141Message, so we can static cast safely - auto isoMessage = std::static_pointer_cast(message); - - std::cout << "\t\t" << isoMessage->network << ' '; - - // Print the header bytes - std::cout << '(' << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[0] << ' '; - std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[1] << ' '; - std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[2] << ") "; - - // Print the data length - std::cout << std::dec << " [" << isoMessage->data.size() << "] "; - - // Print the data - for(auto& databyte : isoMessage->data) - std::cout << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)databyte << ' '; + // Print the error counts + std::cout << "\t\t" << cec->network << " error counts changed, REC=" << std::to_string(cec->receiveErrorCount) + << " TEC=" << std::to_string(cec->transmitErrorCount) << " (" << (cec->busOff ? "" : "Not ") << "Bus Off) "; // Print the timestamp - std::cout << std::dec << '(' << isoMessage->timestamp << " ns since 1/1/2007)\n"; + std::cout << std::dec << '(' << cec->timestamp << " ns since 1/1/2007)\n"; break; } default: - // Ignoring non-network messages + // Ignoring other types of messages break; } })); @@ -278,7 +314,7 @@ int main() { 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; diff --git a/include/icsneo/communication/message/canerrorcountmessage.h b/include/icsneo/communication/message/canerrorcountmessage.h new file mode 100644 index 0000000..b40f459 --- /dev/null +++ b/include/icsneo/communication/message/canerrorcountmessage.h @@ -0,0 +1,25 @@ +#ifndef __CANERRORCOUNTMESSAGE_H_ +#define __CANERRORCOUNTMESSAGE_H_ + +#ifdef __cplusplus + +#include "icsneo/communication/message/message.h" + +namespace icsneo { + +class CANErrorCountMessage : public Message { +public: + CANErrorCountMessage(uint8_t tec, uint8_t rec, bool busOffFlag) + : Message(Message::Type::CANErrorCount), transmitErrorCount(tec), receiveErrorCount(rec), busOff(busOffFlag){} + + Network network; + uint8_t transmitErrorCount; + uint8_t receiveErrorCount; + bool busOff; +}; + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/communication/message/canmessage.h b/include/icsneo/communication/message/canmessage.h index 158b532..c8703b0 100644 --- a/include/icsneo/communication/message/canmessage.h +++ b/include/icsneo/communication/message/canmessage.h @@ -7,7 +7,7 @@ namespace icsneo { -class CANMessage : public Message { +class CANMessage : public Frame { public: uint32_t arbid; uint8_t dlcOnWire; diff --git a/include/icsneo/communication/message/ethernetmessage.h b/include/icsneo/communication/message/ethernetmessage.h index bdd119f..3c54975 100644 --- a/include/icsneo/communication/message/ethernetmessage.h +++ b/include/icsneo/communication/message/ethernetmessage.h @@ -31,7 +31,7 @@ struct MACAddress { } }; -class EthernetMessage : public Message { +class EthernetMessage : public Frame { public: bool preemptionEnabled = false; uint8_t preemptionFlags = 0; diff --git a/include/icsneo/communication/message/filter/canmessagefilter.h b/include/icsneo/communication/message/filter/canmessagefilter.h index 8070b92..7bc5941 100644 --- a/include/icsneo/communication/message/filter/canmessagefilter.h +++ b/include/icsneo/communication/message/filter/canmessagefilter.h @@ -13,8 +13,8 @@ namespace icsneo { class CANMessageFilter : public MessageFilter { public: - CANMessageFilter() : MessageFilter(Network::Type::CAN), arbid(INVALID_ARBID) {} - CANMessageFilter(uint32_t arbid) : MessageFilter(Network::Type::CAN), arbid(arbid) {} + CANMessageFilter() : MessageFilter(Network::Type::CAN), arbid(INVALID_ARBID) { messageType = Message::Type::Frame; } + CANMessageFilter(uint32_t arbid) : MessageFilter(Network::Type::CAN), arbid(arbid) { messageType = Message::Type::Frame; } bool match(const std::shared_ptr& message) const { if(!MessageFilter::match(message)) diff --git a/include/icsneo/communication/message/filter/main51messagefilter.h b/include/icsneo/communication/message/filter/main51messagefilter.h index 977ae3d..2d3aa86 100644 --- a/include/icsneo/communication/message/filter/main51messagefilter.h +++ b/include/icsneo/communication/message/filter/main51messagefilter.h @@ -14,8 +14,10 @@ namespace icsneo { class Main51MessageFilter : public MessageFilter { public: - Main51MessageFilter() : MessageFilter(Network::NetID::Main51), command(INVALID_COMMAND) {} - Main51MessageFilter(Command command) : MessageFilter(Network::NetID::Main51), command(command) {} + Main51MessageFilter() : MessageFilter(Message::Type::Main51), command(INVALID_COMMAND) {} + // Don't filter on Type::Main51 for Command as some Commands have their own type + // We still guarantee it's a Main51Message if it matches because of the dynamic_pointer_cast below + Main51MessageFilter(Command command) : command(command) { includeInternalInAny = true; } bool match(const std::shared_ptr& message) const { if(!MessageFilter::match(message)) { diff --git a/include/icsneo/communication/message/filter/messagefilter.h b/include/icsneo/communication/message/filter/messagefilter.h index e076de1..0ba85b0 100644 --- a/include/icsneo/communication/message/filter/messagefilter.h +++ b/include/icsneo/communication/message/filter/messagefilter.h @@ -12,26 +12,44 @@ namespace icsneo { class MessageFilter { public: MessageFilter() {} - MessageFilter(Network::Type type) : type(type) {} - MessageFilter(Network::NetID netid) : type(Network::GetTypeOfNetID(netid)), netid(netid) {} - virtual ~MessageFilter() {} + MessageFilter(Message::Type type) : includeInternalInAny(neomessagetype_t(type) & 0x8000), messageType(type) {} + MessageFilter(Network::NetID netid) : MessageFilter(Network::GetTypeOfNetID(netid), netid) {} + MessageFilter(Network::Type type, Network::NetID net = Network::NetID::Any) : networkType(type), netid(net) { + // If a Network::Type::Internal is used, we want to also get internal Message::Types + // The NetID we want may be in there + includeInternalInAny = (networkType == Network::Type::Internal); + } + virtual ~MessageFilter() = default; // When getting "all" types of messages, include the ones marked as "internal only" bool includeInternalInAny = false; virtual bool match(const std::shared_ptr& message) const { - if(!matchType(message->network.getType())) - return false; - if(!matchNetID(message->network.getNetID())) + if(!matchMessageType(message->type)) return false; + + if(message->type == Message::Type::Frame) { + Frame& frame = *static_cast(message.get()); + if(!matchNetworkType(frame.network.getType())) + return false; + if(!matchNetID(frame.network.getNetID())) + return false; + } return true; } -private: - Network::Type type = Network::Type::Any; - bool matchType(Network::Type mtype) const { - if(type == Network::Type::Any && (mtype != Network::Type::Internal || includeInternalInAny)) +protected: + Message::Type messageType = Message::Type::Invalid; // Used here for "any" + bool matchMessageType(Message::Type mtype) const { + if(messageType == Message::Type::Invalid && ((neomessagetype_t(mtype) & 0x8000) == 0 || includeInternalInAny)) return true; - return type == mtype; + return messageType == mtype; + } + + Network::Type networkType = Network::Type::Any; + bool matchNetworkType(Network::Type mtype) const { + if(networkType == Network::Type::Any && (mtype != Network::Type::Internal || includeInternalInAny)) + return true; + return networkType == mtype; } Network::NetID netid = Network::NetID::Any; diff --git a/include/icsneo/communication/message/flexray/control/flexraycontrolmessage.h b/include/icsneo/communication/message/flexray/control/flexraycontrolmessage.h index c2d6180..63a4648 100644 --- a/include/icsneo/communication/message/flexray/control/flexraycontrolmessage.h +++ b/include/icsneo/communication/message/flexray/control/flexraycontrolmessage.h @@ -23,7 +23,7 @@ public: uint8_t controller, uint16_t bufferId, const std::vector& data, uint16_t desiredSize); FlexRayControlMessage(const Packet& packet); - virtual ~FlexRayControlMessage() = default; + bool decoded = false; uint8_t controller = 0xff; // Controller index, either 0 or 1 FlexRay::Opcode opcode = FlexRay::Opcode::Unknown; diff --git a/include/icsneo/communication/message/flexray/flexraymessage.h b/include/icsneo/communication/message/flexray/flexraymessage.h index fa5b7cf..16f5907 100644 --- a/include/icsneo/communication/message/flexray/flexraymessage.h +++ b/include/icsneo/communication/message/flexray/flexraymessage.h @@ -10,7 +10,7 @@ namespace icsneo { -class FlexRayMessage : public Message { +class FlexRayMessage : public Frame { public: uint16_t slotid = 0; double tsslen = 0; diff --git a/include/icsneo/communication/message/iso9141message.h b/include/icsneo/communication/message/iso9141message.h index e994f59..0e35554 100644 --- a/include/icsneo/communication/message/iso9141message.h +++ b/include/icsneo/communication/message/iso9141message.h @@ -8,7 +8,7 @@ namespace icsneo { -class ISO9141Message : public Message { +class ISO9141Message : public Frame { public: std::array header; bool isInit = false; diff --git a/include/icsneo/communication/message/main51message.h b/include/icsneo/communication/message/main51message.h index 168ae56..12f51ea 100644 --- a/include/icsneo/communication/message/main51message.h +++ b/include/icsneo/communication/message/main51message.h @@ -8,9 +8,9 @@ namespace icsneo { -class Main51Message : public Message { +class Main51Message : public RawMessage { public: - virtual ~Main51Message() = default; + Main51Message() : RawMessage(Message::Type::Main51, Network::NetID::Main51) {} Command command = Command(0); bool forceShortFormat = false; // Necessary for EnableNetworkCom and EnableNetworkComEx }; diff --git a/include/icsneo/communication/message/message.h b/include/icsneo/communication/message/message.h index b06d319..918f5ef 100644 --- a/include/icsneo/communication/message/message.h +++ b/include/icsneo/communication/message/message.h @@ -1,6 +1,9 @@ #ifndef __MESSAGE_H_ #define __MESSAGE_H_ +#include +typedef uint16_t neomessagetype_t; + #ifdef __cplusplus #include "icsneo/communication/network.h" @@ -10,10 +13,42 @@ namespace icsneo { class Message { public: + enum class Type : neomessagetype_t { + Frame = 0, + + CANErrorCount = 0x100, + + // Past 0x8000 are all for internal use only + Invalid = 0x8000, + RawMessage = 0x8001, + ReadSettings = 0x8002, + ResetStatus = 0x8003, + DeviceVersion = 0x8004, + Main51 = 0x8005, + FlexRayControl = 0x8006, + }; + + Message(Type t) : type(t) {} virtual ~Message() = default; + const Type type; + uint64_t timestamp = 0; +}; + +class RawMessage : public Message { +public: + RawMessage(Message::Type type = Message::Type::RawMessage) : Message(type) {} + RawMessage(Message::Type type, Network net) : Message(type), network(net) {} + RawMessage(Network net) : Message(Message::Type::RawMessage), network(net) {} + RawMessage(Network net, std::vector d) : Message(Message::Type::RawMessage), network(net), data(d) {} + Network network; std::vector data; - uint64_t timestamp = 0; +}; + +class Frame : public RawMessage { +public: + Frame() : RawMessage(Message::Type::Frame) {} + uint16_t description = 0; bool transmitted = false; bool error = false; @@ -23,4 +58,18 @@ public: #endif // __cplusplus +#ifdef __ICSNEOC_H_ + +#define ICSNEO_MESSAGE_TYPE_FRAME (0x0) +#define ICSNEO_MESSAGE_TYPE_CAN_ERROR_COUNT (0x100) +#define ICSNEO_MESSAGE_TYPE_INVALID (0x8000) +#define ICSNEO_MESSAGE_TYPE_RAW_MESSAGE (0x8001) +#define ICSNEO_MESSAGE_TYPE_READ_SETTINGS (0x8002) +#define ICSNEO_MESSAGE_TYPE_RESET_STATUS (0x8003) +#define ICSNEO_MESSAGE_TYPE_DEVICE_VERSION (0x8004) +#define ICSNEO_MESSAGE_TYPE_MAIN51 (0x8005) +#define ICSNEO_MESSAGE_TYPE_FLEXRAY_CONTROL (0x8006) + +#endif // __ICSNEOC_H_ + #endif \ No newline at end of file diff --git a/include/icsneo/communication/message/neomessage.h b/include/icsneo/communication/message/neomessage.h index 6ef975f..0de8ec1 100644 --- a/include/icsneo/communication/message/neomessage.h +++ b/include/icsneo/communication/message/neomessage.h @@ -4,6 +4,7 @@ #include #include #include "icsneo/communication/network.h" +#include "icsneo/communication/message/message.h" #pragma pack(push, 1) @@ -18,12 +19,12 @@ typedef union { uint32_t extendedFrame : 1; uint32_t remoteFrame : 1; uint32_t crcError : 1; - uint32_t canErrorPassive : 1; + uint32_t canErrorPassive : 1; // Occupies the same space as headerCRCError uint32_t incompleteFrame : 1; uint32_t lostArbitration : 1; uint32_t undefinedError : 1; uint32_t canBusOff : 1; - uint32_t canErrorWarning : 1; + uint32_t canBusRecovered : 1; uint32_t canBusShortedPlus : 1; uint32_t canBusShortedGround : 1; uint32_t checksumError : 1; @@ -101,24 +102,34 @@ typedef union { #endif typedef struct { - neomessage_statusbitfield_t status; + uint8_t _reserved1[16]; uint64_t timestamp; - uint64_t timestampReserved; - const uint8_t* data; - size_t length; - uint8_t header[4]; - neonetid_t netid; - neonettype_t type; - uint8_t reserved0; - uint16_t description; - uint8_t reserved1[14]; + uint64_t _reservedTimestamp; + uint8_t _reserved2[sizeof(size_t) * 2 + 7 + sizeof(neonetid_t) + sizeof(neonettype_t)]; + neomessagetype_t messageType; + uint8_t _reserved3[12]; } neomessage_t; // 72 bytes total // Any time you add another neomessage_*_t type, make sure to add it to the static_asserts below! typedef struct { neomessage_statusbitfield_t status; uint64_t timestamp; - uint64_t timestampReserved; + uint64_t _reservedTimestamp; + const uint8_t* data; + size_t length; + uint8_t header[4]; + neonetid_t netid; + neonettype_t type; + uint8_t _reserved0; + uint16_t description; + neomessagetype_t messageType; + uint8_t _reserved1[12]; +} neomessage_frame_t; + +typedef struct { + neomessage_statusbitfield_t status; + uint64_t timestamp; + uint64_t _reservedTimestamp; const uint8_t* data; size_t length; uint32_t arbid; @@ -126,22 +137,38 @@ typedef struct { neonettype_t type; uint8_t dlcOnWire; uint16_t description; - uint8_t reserved[14]; + neomessagetype_t messageType; + uint8_t _reserved1[12]; } neomessage_can_t; typedef struct { neomessage_statusbitfield_t status; uint64_t timestamp; - uint64_t timestampReserved; + uint64_t _reservedTimestamp; + size_t _reserved2[2]; + uint8_t transmitErrorCount; + uint8_t receiveErrorCount; + uint8_t _reserved3[5]; + neonetid_t netid; + neonettype_t type; + neomessagetype_t messageType; + uint8_t _reserved4[12]; +} neomessage_can_error_t; + +typedef struct { + neomessage_statusbitfield_t status; + uint64_t timestamp; + uint64_t _reservedTimestamp; const uint8_t* data; size_t length; uint8_t preemptionFlags; - uint8_t reservedHeader[3]; + uint8_t _reservedHeader[3]; neonetid_t netid; neonettype_t type; - uint8_t reserved0; + uint8_t _reserved0; uint16_t description; - uint8_t reserved1[14]; + neomessagetype_t messageType; + uint8_t _reserved1[12]; } neomessage_eth_t; #pragma pack(pop) @@ -151,7 +178,9 @@ typedef struct { #include static_assert(sizeof(neomessage_t) == (56 + sizeof(void*) + sizeof(size_t)), "neomessage_t size is incorrect! Changing size will break compatibility with existing C API programs."); +static_assert(sizeof(neomessage_frame_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (Base frame is not)"); static_assert(sizeof(neomessage_can_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (CAN is not)"); +static_assert(sizeof(neomessage_can_error_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (CAN error is not)"); static_assert(sizeof(neomessage_eth_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (Ethernet is not)"); namespace icsneo { diff --git a/include/icsneo/communication/message/readsettingsmessage.h b/include/icsneo/communication/message/readsettingsmessage.h index 64819e4..3be1054 100644 --- a/include/icsneo/communication/message/readsettingsmessage.h +++ b/include/icsneo/communication/message/readsettingsmessage.h @@ -8,9 +8,9 @@ namespace icsneo { -class ReadSettingsMessage : public Message { +class ReadSettingsMessage : public RawMessage { public: - virtual ~ReadSettingsMessage() = default; + ReadSettingsMessage() : RawMessage(Message::Type::ReadSettings, Network::NetID::ReadSettings) {} enum class Response : uint8_t { OK = 0, diff --git a/include/icsneo/communication/message/resetstatusmessage.h b/include/icsneo/communication/message/resetstatusmessage.h index 2784cba..695cc3d 100644 --- a/include/icsneo/communication/message/resetstatusmessage.h +++ b/include/icsneo/communication/message/resetstatusmessage.h @@ -11,8 +11,8 @@ namespace icsneo { class ResetStatusMessage : public Message { public: - ResetStatusMessage() : Message() {} - virtual ~ResetStatusMessage() = default; + ResetStatusMessage() : Message(Message::Type::ResetStatus) {} + uint16_t mainLoopTime; uint16_t maxMainLoopTime; bool justReset; diff --git a/include/icsneo/communication/message/versionmessage.h b/include/icsneo/communication/message/versionmessage.h index f6ca828..8775b93 100644 --- a/include/icsneo/communication/message/versionmessage.h +++ b/include/icsneo/communication/message/versionmessage.h @@ -11,13 +11,18 @@ namespace icsneo { class VersionMessage : public Message { public: - VersionMessage(bool main) : MainChip(main) { network = Network::NetID::Main51; } + enum Chip : uint8_t { + MainChip, + SecondaryChips + }; - // If true, the included version is for the main chip - const bool MainChip; + VersionMessage(Chip chip) : Message(Message::Type::DeviceVersion), ForChip(chip) {} // nullopt here indicates invalid std::vector< optional > Versions; + + // What chips the versions are for + const Chip ForChip; }; } diff --git a/include/icsneo/communication/packet/canpacket.h b/include/icsneo/communication/packet/canpacket.h index 6b59ea4..4e8597c 100644 --- a/include/icsneo/communication/packet/canpacket.h +++ b/include/icsneo/communication/packet/canpacket.h @@ -13,7 +13,7 @@ namespace icsneo { typedef uint16_t icscm_bitfield; struct HardwareCANPacket { - static std::shared_ptr DecodeToMessage(const std::vector& bytestream); + static std::shared_ptr DecodeToMessage(const std::vector& bytestream); static bool EncodeFromMessage(const CANMessage& message, std::vector& bytestream, const device_eventhandler_t& report); struct { diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 1aa72be..91b1a7d 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -121,8 +121,8 @@ public: int addMessageCallback(const MessageCallback& cb) { return com->addMessageCallback(cb); } bool removeMessageCallback(int id) { return com->removeMessageCallback(id); } - bool transmit(std::shared_ptr message); - bool transmit(std::vector> messages); + bool transmit(std::shared_ptr frame); + bool transmit(std::vector> frames); void setWriteBlocks(bool blocks); @@ -328,7 +328,7 @@ protected: void handleInternalMessage(std::shared_ptr message); - virtual void handleDeviceStatus(const std::shared_ptr&) {} + virtual void handleDeviceStatus(const std::shared_ptr&) {} neodevice_t& getWritableNeoDevice() { return data; } diff --git a/include/icsneo/device/extensions/deviceextension.h b/include/icsneo/device/extensions/deviceextension.h index e31bbe8..b45596f 100644 --- a/include/icsneo/device/extensions/deviceextension.h +++ b/include/icsneo/device/extensions/deviceextension.h @@ -33,7 +33,7 @@ public: virtual void handleMessage(const std::shared_ptr&) {} // Return true to continue transmitting, success should be written to if false is returned - virtual bool transmitHook(const std::shared_ptr& message, bool& success) { (void)message; (void)success; return true; } + virtual bool transmitHook(const std::shared_ptr& frame, bool& success) { (void)frame; (void)success; return true; } protected: Device& device; diff --git a/include/icsneo/device/extensions/flexray/extension.h b/include/icsneo/device/extensions/flexray/extension.h index 3f18679..0d70268 100644 --- a/include/icsneo/device/extensions/flexray/extension.h +++ b/include/icsneo/device/extensions/flexray/extension.h @@ -25,7 +25,7 @@ public: void onGoOffline() override; void handleMessage(const std::shared_ptr& message) override; - bool transmitHook(const std::shared_ptr& message, bool& success) override; + bool transmitHook(const std::shared_ptr& frame, bool& success) override; std::shared_ptr getController(uint8_t index) const { if(index >= controllers.size()) diff --git a/include/icsneo/device/tree/neovifire2/neovifire2.h b/include/icsneo/device/tree/neovifire2/neovifire2.h index b611a1f..ec9ae3c 100644 --- a/include/icsneo/device/tree/neovifire2/neovifire2.h +++ b/include/icsneo/device/tree/neovifire2/neovifire2.h @@ -104,11 +104,12 @@ protected: // The supported TX networks are the same as the supported RX networks for this device virtual void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } - void handleDeviceStatus(const std::shared_ptr& message) override { - if(!message || message->data.size() < sizeof(neovifire2_status_t)) + void handleDeviceStatus(const std::shared_ptr& message) override { + const auto& data = message->data; + if(data.size() < sizeof(neovifire2_status_t)) return; std::lock_guard lk(ioMutex); - const neovifire2_status_t* status = reinterpret_cast(message->data.data()); + const neovifire2_status_t* status = reinterpret_cast(data.data()); backupPowerEnabled = status->backupPowerEnabled; backupPowerGood = status->backupPowerGood; ethActivationStatus = status->ethernetActivationLineEnabled; diff --git a/include/icsneo/device/tree/neovifire2/neovifire2eth.h b/include/icsneo/device/tree/neovifire2/neovifire2eth.h index 7771c37..ba9596c 100644 --- a/include/icsneo/device/tree/neovifire2/neovifire2eth.h +++ b/include/icsneo/device/tree/neovifire2/neovifire2eth.h @@ -24,7 +24,7 @@ public: if (!fakedev->com->decoder->decode(msg, packet)) continue; // We failed to decode this packet - if(!msg || msg->network.getNetID() != Network::NetID::Main51) + if(!msg || msg->type != Message::Type::Main51) continue; // Not a message we care about auto sn = std::dynamic_pointer_cast(msg); if(!sn) diff --git a/include/icsneo/device/tree/plasion/plasion.h b/include/icsneo/device/tree/plasion/plasion.h index 3355a3e..6ed13c5 100644 --- a/include/icsneo/device/tree/plasion/plasion.h +++ b/include/icsneo/device/tree/plasion/plasion.h @@ -80,11 +80,12 @@ protected: return ret; } - void handleDeviceStatus(const std::shared_ptr& message) override { - if(!message || message->data.size() < sizeof(fire2vnet_status_t)) + void handleDeviceStatus(const std::shared_ptr& message) override { + const auto& data = message->data; + if(data.size() < sizeof(fire2vnet_status_t)) return; std::lock_guard lk(ioMutex); - const fire2vnet_status_t* status = reinterpret_cast(message->data.data()); + const fire2vnet_status_t* status = reinterpret_cast(data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } diff --git a/include/icsneo/device/tree/radgalaxy/radgalaxy.h b/include/icsneo/device/tree/radgalaxy/radgalaxy.h index dcf5b32..f2f2cdd 100644 --- a/include/icsneo/device/tree/radgalaxy/radgalaxy.h +++ b/include/icsneo/device/tree/radgalaxy/radgalaxy.h @@ -30,7 +30,7 @@ public: if(!fakedev->com->decoder->decode(msg, packet)) continue; // We failed to decode this packet - if(!msg || msg->network.getNetID() != Network::NetID::Main51) + if(!msg || msg->type != Message::Type::Main51) continue; // Not a message we care about auto sn = std::dynamic_pointer_cast(msg); if(!sn) @@ -118,11 +118,12 @@ protected: // The supported TX networks are the same as the supported RX networks for this device void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } - void handleDeviceStatus(const std::shared_ptr& message) override { - if(!message || message->data.size() < sizeof(radgalaxy_status_t)) + void handleDeviceStatus(const std::shared_ptr& message) override { + const auto& data = message->data; + if(data.size() < sizeof(radgalaxy_status_t)) return; std::lock_guard lk(ioMutex); - const radgalaxy_status_t* status = reinterpret_cast(message->data.data()); + const radgalaxy_status_t* status = reinterpret_cast(data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } }; diff --git a/include/icsneo/device/tree/radgigalog/radgigalog.h b/include/icsneo/device/tree/radgigalog/radgigalog.h index 6adc69d..2b155a0 100644 --- a/include/icsneo/device/tree/radgigalog/radgigalog.h +++ b/include/icsneo/device/tree/radgigalog/radgigalog.h @@ -77,11 +77,12 @@ protected: txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end()); } - void handleDeviceStatus(const std::shared_ptr& message) override { - if(!message || message->data.size() < sizeof(radgigalog_status_t)) + void handleDeviceStatus(const std::shared_ptr& message) override { + const auto& data = message->data; + if(data.size() < sizeof(radgigalog_status_t)) return; std::lock_guard lk(ioMutex); - const radgigalog_status_t* status = reinterpret_cast(message->data.data()); + const radgigalog_status_t* status = reinterpret_cast(data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } }; diff --git a/include/icsneo/device/tree/radgigalog/radgigalogeth.h b/include/icsneo/device/tree/radgigalog/radgigalogeth.h index ab0baeb..4c1f0b8 100644 --- a/include/icsneo/device/tree/radgigalog/radgigalogeth.h +++ b/include/icsneo/device/tree/radgigalog/radgigalogeth.h @@ -23,7 +23,7 @@ public: if (!fakedev->com->decoder->decode(msg, packet)) continue; // We failed to decode this packet - if(!msg || msg->network.getNetID() != Network::NetID::Main51) + if(!msg || msg->type != Message::Type::Main51) continue; // Not a message we care about auto sn = std::dynamic_pointer_cast(msg); if(!sn) diff --git a/include/icsneo/device/tree/radgigastar/radgigastar.h b/include/icsneo/device/tree/radgigastar/radgigastar.h index 3842a11..61b091b 100644 --- a/include/icsneo/device/tree/radgigastar/radgigastar.h +++ b/include/icsneo/device/tree/radgigastar/radgigastar.h @@ -81,11 +81,12 @@ protected: txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end()); } - void handleDeviceStatus(const std::shared_ptr& message) override { - if(!message || message->data.size() < sizeof(radgigastar_status_t)) + void handleDeviceStatus(const std::shared_ptr& message) override { + const auto& data = message->data; + if(data.size() < sizeof(radgigastar_status_t)) return; std::lock_guard lk(ioMutex); - const radgigastar_status_t* status = reinterpret_cast(message->data.data()); + const radgigastar_status_t* status = reinterpret_cast(data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } }; diff --git a/include/icsneo/device/tree/radgigastar/radgigastareth.h b/include/icsneo/device/tree/radgigastar/radgigastareth.h index 1a4a57e..95e95f7 100644 --- a/include/icsneo/device/tree/radgigastar/radgigastareth.h +++ b/include/icsneo/device/tree/radgigastar/radgigastareth.h @@ -23,7 +23,7 @@ public: if (!fakedev->com->decoder->decode(msg, packet)) continue; // We failed to decode this packet - if(!msg || msg->network.getNetID() != Network::NetID::Main51) + if(!msg || msg->type != Message::Type::Main51) continue; // Not a message we care about auto sn = std::dynamic_pointer_cast(msg); if(!sn) diff --git a/include/icsneo/device/tree/radstar2/radstar2eth.h b/include/icsneo/device/tree/radstar2/radstar2eth.h index dce6e12..5d9cae4 100644 --- a/include/icsneo/device/tree/radstar2/radstar2eth.h +++ b/include/icsneo/device/tree/radstar2/radstar2eth.h @@ -25,7 +25,7 @@ public: if(!fakedev->com->decoder->decode(msg, packet)) continue; // We failed to decode this packet - if(!msg || msg->network.getNetID() != Network::NetID::Main51) + if(!msg || msg->type != Message::Type::Main51) continue; // Not a message we care about auto sn = std::dynamic_pointer_cast(msg); if(!sn) diff --git a/include/icsneo/device/tree/valuecan4/valuecan4-2el.h b/include/icsneo/device/tree/valuecan4/valuecan4-2el.h index 962fe6c..cda4200 100644 --- a/include/icsneo/device/tree/valuecan4/valuecan4-2el.h +++ b/include/icsneo/device/tree/valuecan4/valuecan4-2el.h @@ -73,11 +73,12 @@ protected: size_t getEthernetActivationLineCount() const override { return 1; } - void handleDeviceStatus(const std::shared_ptr& message) override { - if(!message || message->data.size() < sizeof(valuecan4_2el_status_t)) + void handleDeviceStatus(const std::shared_ptr& message) override { + const auto& data = message->data; + if(data.size() < sizeof(valuecan4_2el_status_t)) return; std::lock_guard lk(ioMutex); - const valuecan4_2el_status_t* status = reinterpret_cast(message->data.data()); + const valuecan4_2el_status_t* status = reinterpret_cast(data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } }; diff --git a/include/icsneo/device/tree/valuecan4/valuecan4-2eleth.h b/include/icsneo/device/tree/valuecan4/valuecan4-2eleth.h index 9560fcf..f5f594c 100644 --- a/include/icsneo/device/tree/valuecan4/valuecan4-2eleth.h +++ b/include/icsneo/device/tree/valuecan4/valuecan4-2eleth.h @@ -25,7 +25,7 @@ public: if (!fakedev->com->decoder->decode(msg, packet)) continue; // We failed to decode this packet - if(!msg || msg->network.getNetID() != Network::NetID::Main51) + if(!msg || msg->type != Message::Type::Main51) continue; // Not a message we care about auto sn = std::dynamic_pointer_cast(msg); if(!sn) diff --git a/include/icsneo/device/tree/valuecan4/valuecan4industrialeth.h b/include/icsneo/device/tree/valuecan4/valuecan4industrialeth.h index bc7aa8c..d8b4eb6 100644 --- a/include/icsneo/device/tree/valuecan4/valuecan4industrialeth.h +++ b/include/icsneo/device/tree/valuecan4/valuecan4industrialeth.h @@ -25,7 +25,7 @@ public: if (!fakedev->com->decoder->decode(msg, packet)) continue; // We failed to decode this packet - if(!msg || msg->network.getNetID() != Network::NetID::Main51) + if(!msg || msg->type != Message::Type::Main51) continue; // Not a message we care about auto sn = std::dynamic_pointer_cast(msg); if(!sn) diff --git a/include/icsneo/icsneocpp.h b/include/icsneo/icsneocpp.h index f0847bc..ddd5391 100644 --- a/include/icsneo/icsneocpp.h +++ b/include/icsneo/icsneocpp.h @@ -14,6 +14,7 @@ #include "icsneo/communication/message/ethernetmessage.h" #include "icsneo/communication/message/flexray/flexraymessage.h" #include "icsneo/communication/message/iso9141message.h" +#include "icsneo/communication/message/canerrorcountmessage.h" namespace icsneo {