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.v0.3.0-dev
parent
21e93d1f73
commit
21bc4eeff2
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.2)
|
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_TESTS "Build all tests." OFF)
|
||||||
option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF)
|
option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ bool Communication::open() {
|
||||||
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!driver->open())
|
if(!driver->open())
|
||||||
return false;
|
return false;
|
||||||
spawnThreads();
|
spawnThreads();
|
||||||
|
|
@ -114,7 +114,7 @@ bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::mil
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = std::move(msg->data);
|
data = std::move(gsmsg->data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +128,7 @@ std::shared_ptr<SerialNumberMessage> Communication::getSerialNumberSync(std::chr
|
||||||
auto m51 = std::dynamic_pointer_cast<Main51Message>(msg);
|
auto m51 = std::dynamic_pointer_cast<Main51Message>(msg);
|
||||||
if(!m51) // Could not upcast for some reason
|
if(!m51) // Could not upcast for some reason
|
||||||
return std::shared_ptr<SerialNumberMessage>();
|
return std::shared_ptr<SerialNumberMessage>();
|
||||||
|
|
||||||
return std::dynamic_pointer_cast<SerialNumberMessage>(m51);
|
return std::dynamic_pointer_cast<SerialNumberMessage>(m51);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ optional< std::vector< optional<DeviceAppVersion> > > Communication::getVersions
|
||||||
if(!ver) // Could not upcast for some reason
|
if(!ver) // Could not upcast for some reason
|
||||||
return nullopt;
|
return nullopt;
|
||||||
|
|
||||||
if(!ver->MainChip || ver->Versions.size() != 1)
|
if(ver->ForChip != VersionMessage::MainChip || ver->Versions.size() != 1)
|
||||||
return nullopt;
|
return nullopt;
|
||||||
|
|
||||||
ret.push_back(ver->Versions.front());
|
ret.push_back(ver->Versions.front());
|
||||||
|
|
@ -155,9 +155,8 @@ optional< std::vector< optional<DeviceAppVersion> > > Communication::getVersions
|
||||||
}, Main51MessageFilter(Command::GetSecondaryVersions), timeout);
|
}, Main51MessageFilter(Command::GetSecondaryVersions), timeout);
|
||||||
if(msg) { // This one is allowed to fail
|
if(msg) { // This one is allowed to fail
|
||||||
ver = std::dynamic_pointer_cast<VersionMessage>(msg);
|
ver = std::dynamic_pointer_cast<VersionMessage>(msg);
|
||||||
if(ver && !ver->MainChip) {
|
if(ver && ver->ForChip != VersionMessage::MainChip)
|
||||||
ret.insert(ret.end(), ver->Versions.begin(), ver->Versions.end());
|
ret.insert(ret.end(), ver->Versions.begin(), ver->Versions.end());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -231,7 +230,7 @@ void Communication::readTask() {
|
||||||
std::vector<uint8_t> readBytes;
|
std::vector<uint8_t> readBytes;
|
||||||
|
|
||||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||||
|
|
||||||
while(!closing) {
|
while(!closing) {
|
||||||
readBytes.clear();
|
readBytes.clear();
|
||||||
if(driver->readWait(readBytes)) {
|
if(driver->readWait(readBytes)) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "icsneo/communication/message/serialnumbermessage.h"
|
#include "icsneo/communication/message/serialnumbermessage.h"
|
||||||
#include "icsneo/communication/message/resetstatusmessage.h"
|
#include "icsneo/communication/message/resetstatusmessage.h"
|
||||||
#include "icsneo/communication/message/readsettingsmessage.h"
|
#include "icsneo/communication/message/readsettingsmessage.h"
|
||||||
|
#include "icsneo/communication/message/canerrorcountmessage.h"
|
||||||
#include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h"
|
#include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h"
|
||||||
#include "icsneo/communication/command.h"
|
#include "icsneo/communication/command.h"
|
||||||
#include "icsneo/device/device.h"
|
#include "icsneo/device/device.h"
|
||||||
|
|
@ -24,7 +25,7 @@ uint64_t Decoder::GetUInt64FromLEBytes(const uint8_t* bytes) {
|
||||||
|
|
||||||
bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet) {
|
bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet) {
|
||||||
switch(packet->network.getType()) {
|
switch(packet->network.getType()) {
|
||||||
case Network::Type::Ethernet:
|
case Network::Type::Ethernet: {
|
||||||
result = HardwareEthernetPacket::DecodeToMessage(packet->data, report);
|
result = HardwareEthernetPacket::DecodeToMessage(packet->data, report);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
|
@ -33,9 +34,11 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
|
|
||||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||||
// The resolution depends on the device
|
// The resolution depends on the device
|
||||||
result->timestamp *= timestampResolution;
|
EthernetMessage& eth = *static_cast<EthernetMessage*>(result.get());
|
||||||
result->network = packet->network;
|
eth.timestamp *= timestampResolution;
|
||||||
|
eth.network = packet->network;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
case Network::Type::CAN:
|
case Network::Type::CAN:
|
||||||
case Network::Type::SWCAN:
|
case Network::Type::SWCAN:
|
||||||
case Network::Type::LSFTCAN: {
|
case Network::Type::LSFTCAN: {
|
||||||
|
|
@ -49,10 +52,28 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
return false; // A nullptr was returned, the packet was malformed
|
return false; // A nullptr was returned, the packet was malformed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||||
// The resolution depends on the device
|
// The resolution depends on the device
|
||||||
result->timestamp *= timestampResolution;
|
result->timestamp *= timestampResolution;
|
||||||
result->network = packet->network;
|
|
||||||
|
switch(result->type) {
|
||||||
|
case Message::Type::Frame: {
|
||||||
|
CANMessage& can = *static_cast<CANMessage*>(result.get());
|
||||||
|
can.network = packet->network;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Message::Type::CANErrorCount: {
|
||||||
|
CANErrorCountMessage& can = *static_cast<CANErrorCountMessage*>(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;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::Type::FlexRay: {
|
case Network::Type::FlexRay: {
|
||||||
|
|
@ -66,10 +87,12 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
return false; // A nullptr was returned, the packet was malformed
|
return false; // A nullptr was returned, the packet was malformed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||||
// The resolution depends on the device
|
// The resolution depends on the device
|
||||||
result->timestamp *= timestampResolution;
|
FlexRayMessage& fr = *static_cast<FlexRayMessage*>(result.get());
|
||||||
result->network = packet->network;
|
fr.timestamp *= timestampResolution;
|
||||||
|
fr.network = packet->network;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::Type::ISO9141: {
|
case Network::Type::ISO9141: {
|
||||||
|
|
@ -84,8 +107,9 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
|
|
||||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||||
// The resolution depends on the device
|
// The resolution depends on the device
|
||||||
result->timestamp *= timestampResolution;
|
ISO9141Message& iso = *static_cast<ISO9141Message*>(result.get());
|
||||||
result->network = packet->network;
|
iso.timestamp *= timestampResolution;
|
||||||
|
iso.network = packet->network;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::Type::Internal: {
|
case Network::Type::Internal: {
|
||||||
|
|
@ -98,7 +122,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
|
|
||||||
HardwareResetStatusPacket* data = (HardwareResetStatusPacket*)packet->data.data();
|
HardwareResetStatusPacket* data = (HardwareResetStatusPacket*)packet->data.data();
|
||||||
auto msg = std::make_shared<ResetStatusMessage>();
|
auto msg = std::make_shared<ResetStatusMessage>();
|
||||||
msg->network = packet->network;
|
|
||||||
msg->mainLoopTime = data->main_loop_time_25ns * 25;
|
msg->mainLoopTime = data->main_loop_time_25ns * 25;
|
||||||
msg->maxMainLoopTime = data->max_main_loop_time_25ns * 25;
|
msg->maxMainLoopTime = data->max_main_loop_time_25ns * 25;
|
||||||
msg->busVoltage = data->busVoltage;
|
msg->busVoltage = data->busVoltage;
|
||||||
|
|
@ -124,9 +147,9 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
// They come in as CAN but we will handle them in the device rather than
|
// They come in as CAN but we will handle them in the device rather than
|
||||||
// passing them onto the user.
|
// passing them onto the user.
|
||||||
if(packet->data.size() < 24) {
|
if(packet->data.size() < 24) {
|
||||||
result = std::make_shared<Message>();
|
auto rawmsg = std::make_shared<RawMessage>(Network::NetID::Device);
|
||||||
result->network = packet->network;
|
result = rawmsg;
|
||||||
result->data = packet->data;
|
rawmsg->data = packet->data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,17 +158,21 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
return false; // A nullptr was returned, the packet was malformed
|
return false; // A nullptr was returned, the packet was malformed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||||
// The resolution depends on the device
|
// The resolution depends on the device
|
||||||
result->timestamp *= timestampResolution;
|
auto* raw = dynamic_cast<RawMessage*>(result.get());
|
||||||
result->network = packet->network;
|
if(raw == nullptr) {
|
||||||
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
return false; // A nullptr was returned, the packet was malformed
|
||||||
|
}
|
||||||
|
raw->timestamp *= timestampResolution;
|
||||||
|
raw->network = packet->network;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::NetID::DeviceStatus: {
|
case Network::NetID::DeviceStatus: {
|
||||||
result = std::make_shared<Message>();
|
|
||||||
result->network = packet->network;
|
|
||||||
// Just pass along the data, the device needs to handle this itself
|
// Just pass along the data, the device needs to handle this itself
|
||||||
result->data = packet->data;
|
result = std::make_shared<RawMessage>(packet->network, packet->data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::NetID::FlexRayControl: {
|
case Network::NetID::FlexRayControl: {
|
||||||
|
|
@ -161,7 +188,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
switch((Command)packet->data[0]) {
|
switch((Command)packet->data[0]) {
|
||||||
case Command::RequestSerialNumber: {
|
case Command::RequestSerialNumber: {
|
||||||
auto msg = std::make_shared<SerialNumberMessage>();
|
auto msg = std::make_shared<SerialNumberMessage>();
|
||||||
msg->network = packet->network;
|
|
||||||
uint64_t serial = GetUInt64FromLEBytes(packet->data.data() + 1);
|
uint64_t serial = GetUInt64FromLEBytes(packet->data.data() + 1);
|
||||||
// The device sends 64-bits of serial number, but we never use more than 32-bits.
|
// The device sends 64-bits of serial number, but we never use more than 32-bits.
|
||||||
msg->deviceSerial = Device::SerialNumToString((uint32_t)serial);
|
msg->deviceSerial = Device::SerialNumToString((uint32_t)serial);
|
||||||
|
|
@ -194,7 +220,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
auto msg = std::make_shared<Main51Message>();
|
auto msg = std::make_shared<Main51Message>();
|
||||||
msg->network = packet->network;
|
|
||||||
msg->command = Command(packet->data[0]);
|
msg->command = Command(packet->data[0]);
|
||||||
msg->data.insert(msg->data.begin(), packet->data.begin() + 1, packet->data.end());
|
msg->data.insert(msg->data.begin(), packet->data.begin() + 1, packet->data.end());
|
||||||
result = msg;
|
result = msg;
|
||||||
|
|
@ -218,9 +243,8 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
}
|
}
|
||||||
case Network::NetID::ReadSettings: {
|
case Network::NetID::ReadSettings: {
|
||||||
auto msg = std::make_shared<ReadSettingsMessage>();
|
auto msg = std::make_shared<ReadSettingsMessage>();
|
||||||
msg->network = packet->network;
|
|
||||||
msg->response = ReadSettingsMessage::Response(packet->data[0]);
|
msg->response = ReadSettingsMessage::Response(packet->data[0]);
|
||||||
|
|
||||||
if(msg->response == ReadSettingsMessage::Response::OK) {
|
if(msg->response == ReadSettingsMessage::Response::OK) {
|
||||||
// The global settings structure is the payload of the message in this case
|
// 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());
|
msg->data.insert(msg->data.begin(), packet->data.begin() + 10, packet->data.end());
|
||||||
|
|
@ -243,9 +267,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the moment other types of messages will automatically be decoded as raw messages
|
// For the moment other types of messages will automatically be decoded as raw messages
|
||||||
auto msg = std::make_shared<Message>();
|
result = std::make_shared<RawMessage>(packet->network, packet->data);
|
||||||
msg->network = packet->network;
|
|
||||||
msg->data = packet->data;
|
|
||||||
result = msg;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -9,119 +9,144 @@ using namespace icsneo;
|
||||||
|
|
||||||
bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result, const std::shared_ptr<Message>& message) {
|
bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result, const std::shared_ptr<Message>& message) {
|
||||||
bool shortFormat = false;
|
bool shortFormat = false;
|
||||||
bool useResultAsBuffer = false; // Otherwise it's expected that we use message->data
|
std::vector<uint8_t>* buffer = &result;
|
||||||
|
uint16_t netid = 0;
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
||||||
switch(message->network.getType()) {
|
switch(message->type) {
|
||||||
case Network::Type::Ethernet: {
|
case Message::Type::Frame: {
|
||||||
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(message);
|
auto frame = std::dynamic_pointer_cast<Frame>(message);
|
||||||
if(!ethmsg) {
|
|
||||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
|
||||||
return false; // The message was not a properly formed EthernetMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
useResultAsBuffer = true;
|
// Frame uses frame->data as the buffer unless directed otherwise
|
||||||
if(!HardwareEthernetPacket::EncodeFromMessage(*ethmsg, result, report))
|
buffer = &frame->data;
|
||||||
return false;
|
netid = uint16_t(frame->network.getNetID());
|
||||||
|
|
||||||
|
switch(frame->network.getType()) {
|
||||||
|
case Network::Type::Ethernet: {
|
||||||
|
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(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<CANMessage>(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<ISO9141Message>(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;
|
break;
|
||||||
} // End of Network::Type::Ethernet
|
}
|
||||||
case Network::Type::CAN:
|
case Message::Type::RawMessage: {
|
||||||
case Network::Type::SWCAN:
|
auto raw = std::dynamic_pointer_cast<RawMessage>(message);
|
||||||
case Network::Type::LSFTCAN: {
|
|
||||||
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
|
||||||
if(!canmsg) {
|
|
||||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
|
||||||
return false; // The message was not a properly formed CANMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!supportCANFD && canmsg->isCANFD) {
|
// Raw message uses raw->data as the buffer unless directed otherwise
|
||||||
report(APIEvent::Type::CANFDNotSupported, APIEvent::Severity::Error);
|
buffer = &raw->data;
|
||||||
return false; // This device does not support CAN FD
|
netid = uint16_t(raw->network.getNetID());
|
||||||
}
|
|
||||||
|
|
||||||
useResultAsBuffer = true;
|
|
||||||
if(!HardwareCANPacket::EncodeFromMessage(*canmsg, result, report))
|
|
||||||
return false; // The CANMessage was malformed
|
|
||||||
|
|
||||||
break;
|
switch(raw->network.getNetID()) {
|
||||||
} // End of Network::Type::CAN
|
|
||||||
case Network::Type::ISO9141: {
|
|
||||||
auto isomsg = std::dynamic_pointer_cast<ISO9141Message>(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()) {
|
|
||||||
case Network::NetID::Device:
|
case Network::NetID::Device:
|
||||||
shortFormat = true;
|
shortFormat = true;
|
||||||
break;
|
break;
|
||||||
case Network::NetID::Main51: {
|
|
||||||
auto m51msg = std::dynamic_pointer_cast<Main51Message>(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: {
|
case Network::NetID::RED_OLDFORMAT: {
|
||||||
// See the decoder for an explanation
|
// See the decoder for an explanation
|
||||||
// We expect the network byte to be populated already in data, but not the length
|
// We expect the network byte to be populated already in data, but not the length
|
||||||
uint16_t length = uint16_t(message->data.size()) - 1;
|
uint16_t length = uint16_t(raw->data.size()) - 1;
|
||||||
message->data.insert(message->data.begin(), {(uint8_t)length, (uint8_t)(length >> 8)});
|
raw->data.insert(raw->data.begin(), {(uint8_t)length, (uint8_t)(length >> 8)});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Message::Type::Main51: {
|
||||||
|
auto m51msg = std::dynamic_pointer_cast<Main51Message>(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
|
// 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) {
|
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 {
|
} else {
|
||||||
// Size in long format is the size of the entire packet
|
// 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
|
// 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;
|
uint16_t size = uint16_t(buffer->size()) + 1 + 1 + 2 + 2;
|
||||||
buffer.insert(buffer.begin(), {
|
buffer->insert(buffer->begin(), {
|
||||||
(uint8_t)Network::NetID::RED, // 0x0C for long message
|
(uint8_t)Network::NetID::RED, // 0x0C for long message
|
||||||
(uint8_t)size, // Size, little endian 16-bit
|
(uint8_t)size, // Size, little endian 16-bit
|
||||||
(uint8_t)(size >> 8),
|
(uint8_t)(size >> 8),
|
||||||
(uint8_t)message->network.getNetID(), // NetID, little endian 16-bit
|
(uint8_t)netid, // NetID, little endian 16-bit
|
||||||
(uint8_t)(uint16_t(message->network.getNetID()) >> 8)
|
(uint8_t)(netid >> 8)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
result = packetizer.packetWrap(buffer, shortFormat);
|
result = packetizer.packetWrap(*buffer, shortFormat);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,20 +158,19 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||||
* In this case, command 0x06 is SetLEDState.
|
* In this case, command 0x06 is SetLEDState.
|
||||||
* This old command type is not really used anywhere else.
|
* This old command type is not really used anywhere else.
|
||||||
*/
|
*/
|
||||||
msg = std::make_shared<Message>();
|
auto canmsg = std::make_shared<RawMessage>(Network::NetID::Device);
|
||||||
|
msg = canmsg;
|
||||||
if(arguments.empty()) {
|
if(arguments.empty()) {
|
||||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
msg->network = Network::NetID::Device;
|
canmsg->data.reserve(3);
|
||||||
msg->data.reserve(3);
|
canmsg->data.push_back(0x00);
|
||||||
msg->data.push_back(0x00);
|
canmsg->data.push_back(0x06); // SetLEDState
|
||||||
msg->data.push_back(0x06); // SetLEDState
|
canmsg->data.push_back(arguments.at(0)); // See Device::LEDState
|
||||||
msg->data.push_back(arguments.at(0)); // See Device::LEDState
|
|
||||||
} else {
|
} else {
|
||||||
auto m51msg = std::make_shared<Main51Message>();
|
auto m51msg = std::make_shared<Main51Message>();
|
||||||
msg = m51msg;
|
msg = m51msg;
|
||||||
msg->network = Network::NetID::Main51;
|
|
||||||
m51msg->command = cmd;
|
m51msg->command = cmd;
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case Command::ReadSettings:
|
case Command::ReadSettings:
|
||||||
|
|
@ -161,8 +185,8 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||||
default:
|
default:
|
||||||
break;
|
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);
|
return encode(packetizer, result, msg);
|
||||||
}
|
}
|
||||||
|
|
@ -64,9 +64,7 @@ std::vector<uint8_t> FlexRayControlMessage::BuildWriteMessageBufferArgs(
|
||||||
return BuildBaseControlArgs(controller, FlexRay::Opcode::WriteMessageBuffer, args);
|
return BuildBaseControlArgs(controller, FlexRay::Opcode::WriteMessageBuffer, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message() {
|
FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message(Message::Type::FlexRayControl) {
|
||||||
network = Network::NetID::FlexRayControl;
|
|
||||||
|
|
||||||
if(packet.data.size() < 2)
|
if(packet.data.size() < 2)
|
||||||
return; // huh?
|
return; // huh?
|
||||||
controller = packet.data[0];
|
controller = packet.data[0];
|
||||||
|
|
@ -77,7 +75,7 @@ FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message() {
|
||||||
opcode = FlexRay::Opcode(packet.data[1]);
|
opcode = FlexRay::Opcode(packet.data[1]);
|
||||||
if(opcode != FlexRay::Opcode::ReadCCRegs && opcode != FlexRay::Opcode::ReadCCStatus)
|
if(opcode != FlexRay::Opcode::ReadCCRegs && opcode != FlexRay::Opcode::ReadCCStatus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Read out registers
|
// Read out registers
|
||||||
size_t bytes = packet.data.size() - 2;
|
size_t bytes = packet.data.size() - 2;
|
||||||
const size_t count = bytes / sizeof(uint32_t);
|
const size_t count = bytes / sizeof(uint32_t);
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,116 @@
|
||||||
#include "icsneo/communication/message/neomessage.h"
|
#include "icsneo/communication/message/neomessage.h"
|
||||||
#include "icsneo/communication/message/canmessage.h"
|
#include "icsneo/communication/message/canmessage.h"
|
||||||
#include "icsneo/communication/message/ethernetmessage.h"
|
#include "icsneo/communication/message/ethernetmessage.h"
|
||||||
|
#include "icsneo/communication/message/canerrorcountmessage.h"
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
|
neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
|
||||||
// This function is not responsible for storing the message!
|
// This function is not responsible for storing the message!
|
||||||
// Keep the shared_ptr around for the lifetime of the data access
|
// 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
|
neomessage_t neomsg = {}; // Clear out the memory
|
||||||
neomsg.netid = (uint32_t)message->network.getNetID();
|
neomsg.messageType = (neomessagetype_t)message->type;
|
||||||
neomsg.type = (uint8_t)type;
|
|
||||||
neomsg.description = message->description;
|
|
||||||
neomsg.length = message->data.size();
|
|
||||||
neomsg.data = message->data.data();
|
|
||||||
neomsg.timestamp = message->timestamp;
|
neomsg.timestamp = message->timestamp;
|
||||||
neomsg.status.globalError = message->error;
|
switch (message->type)
|
||||||
neomsg.status.transmitMessage = message->transmitted;
|
{
|
||||||
|
case Message::Type::Frame: {
|
||||||
|
neomessage_frame_t& frame = *(neomessage_frame_t*)&neomsg;
|
||||||
|
auto framemsg = std::static_pointer_cast<Frame>(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) {
|
switch(netType) {
|
||||||
case Network::Type::CAN:
|
case Network::Type::CAN:
|
||||||
case Network::Type::SWCAN:
|
case Network::Type::SWCAN:
|
||||||
case Network::Type::LSFTCAN: {
|
case Network::Type::LSFTCAN: {
|
||||||
neomessage_can_t& can = *(neomessage_can_t*)&neomsg;
|
neomessage_can_t& can = *(neomessage_can_t*)&neomsg;
|
||||||
auto canmsg = std::static_pointer_cast<CANMessage>(message);
|
auto canmsg = std::static_pointer_cast<CANMessage>(message);
|
||||||
can.arbid = canmsg->arbid;
|
can.arbid = canmsg->arbid;
|
||||||
can.dlcOnWire = canmsg->dlcOnWire;
|
can.dlcOnWire = canmsg->dlcOnWire;
|
||||||
can.status.extendedFrame = canmsg->isExtended;
|
can.status.extendedFrame = canmsg->isExtended;
|
||||||
can.status.remoteFrame = canmsg->isRemote;
|
can.status.remoteFrame = canmsg->isRemote;
|
||||||
can.status.canfdRTR = canmsg->isRemote;
|
can.status.canfdRTR = canmsg->isRemote;
|
||||||
can.status.canfdFDF = canmsg->isCANFD;
|
can.status.canfdFDF = canmsg->isCANFD;
|
||||||
can.status.canfdBRS = canmsg->baudrateSwitch;
|
can.status.canfdBRS = canmsg->baudrateSwitch;
|
||||||
can.status.canfdESI = canmsg->errorStateIndicator;
|
can.status.canfdESI = canmsg->errorStateIndicator;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case Network::Type::Ethernet: {
|
||||||
|
neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg;
|
||||||
|
auto ethmsg = std::static_pointer_cast<EthernetMessage>(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: {
|
break;
|
||||||
neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg;
|
}
|
||||||
auto ethmsg = std::static_pointer_cast<EthernetMessage>(message);
|
case Message::Type::CANErrorCount: {
|
||||||
eth.preemptionFlags = ethmsg->preemptionFlags;
|
neomessage_can_error_t& canerror = *(neomessage_can_error_t*)&neomsg;
|
||||||
eth.status.incompleteFrame = ethmsg->frameTooShort;
|
auto canerrormsg = std::static_pointer_cast<CANErrorCountMessage>(message);
|
||||||
// TODO Fill in extra status bits
|
canerror.transmitErrorCount = canerrormsg->transmitErrorCount;
|
||||||
//eth.status.xyz = ethmsg->preemptionEnabled;
|
canerror.receiveErrorCount = canerrormsg->receiveErrorCount;
|
||||||
//eth.status.xyz = ethmsg->fcsAvailable;
|
canerror.status.canBusOff = canerrormsg->busOff;
|
||||||
//eth.status.xyz = ethmsg->noPadding;
|
canerror.netid = (neonetid_t)canerrormsg->network.getNetID();
|
||||||
break;
|
canerror.type = (neonettype_t)canerrormsg->network.getType();
|
||||||
}
|
break;
|
||||||
default:
|
}
|
||||||
// TODO Implement others
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return neomsg;
|
return neomsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Message> icsneo::CreateMessageFromNeoMessage(const neomessage_t* neomessage) {
|
std::shared_ptr<Message> icsneo::CreateMessageFromNeoMessage(const neomessage_t* neomessage) {
|
||||||
const Network network = neomessage->netid;
|
switch((Message::Type)neomessage->messageType) {
|
||||||
switch(network.getType()) {
|
case Message::Type::Frame: {
|
||||||
case Network::Type::CAN:
|
const Network network = ((neomessage_frame_t*)neomessage)->netid;
|
||||||
case Network::Type::SWCAN:
|
switch(network.getType()) {
|
||||||
case Network::Type::LSFTCAN: {
|
case Network::Type::CAN:
|
||||||
neomessage_can_t& can = *(neomessage_can_t*)neomessage;
|
case Network::Type::SWCAN:
|
||||||
auto canmsg = std::make_shared<CANMessage>();
|
case Network::Type::LSFTCAN: {
|
||||||
canmsg->network = network;
|
neomessage_can_t& can = *(neomessage_can_t*)neomessage;
|
||||||
canmsg->description = can.description;
|
auto canmsg = std::make_shared<CANMessage>();
|
||||||
canmsg->data.insert(canmsg->data.end(), can.data, can.data + can.length);
|
canmsg->network = network;
|
||||||
canmsg->arbid = can.arbid;
|
canmsg->description = can.description;
|
||||||
canmsg->isExtended = can.status.extendedFrame;
|
canmsg->data.insert(canmsg->data.end(), can.data, can.data + can.length);
|
||||||
canmsg->isRemote = can.status.remoteFrame | can.status.canfdRTR;
|
canmsg->arbid = can.arbid;
|
||||||
canmsg->isCANFD = can.status.canfdFDF;
|
canmsg->dlcOnWire = can.dlcOnWire;
|
||||||
canmsg->baudrateSwitch = can.status.canfdBRS;
|
canmsg->isExtended = can.status.extendedFrame;
|
||||||
canmsg->errorStateIndicator = can.status.canfdESI;
|
canmsg->isRemote = can.status.remoteFrame | can.status.canfdRTR;
|
||||||
return canmsg;
|
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<EthernetMessage>();
|
||||||
|
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: {
|
default: break;
|
||||||
neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage;
|
|
||||||
auto ethmsg = std::make_shared<EthernetMessage>();
|
|
||||||
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<Message>();
|
|
||||||
}
|
}
|
||||||
|
return std::shared_ptr<Message>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "icsneo/communication/packet/canpacket.h"
|
#include "icsneo/communication/packet/canpacket.h"
|
||||||
|
#include "icsneo/communication/message/canerrorcountmessage.h"
|
||||||
#include "icsneo/platform/optional.h"
|
#include "icsneo/platform/optional.h"
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
@ -6,7 +7,7 @@ using namespace icsneo;
|
||||||
static optional<uint8_t> CANFD_DLCToLength(uint8_t length) {
|
static optional<uint8_t> CANFD_DLCToLength(uint8_t length) {
|
||||||
if (length < 8)
|
if (length < 8)
|
||||||
return length;
|
return length;
|
||||||
|
|
||||||
switch(length) {
|
switch(length) {
|
||||||
case 0x9:
|
case 0x9:
|
||||||
return 12;
|
return 12;
|
||||||
|
|
@ -26,61 +27,75 @@ static optional<uint8_t> CANFD_DLCToLength(uint8_t length) {
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CANMessage> HardwareCANPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
std::shared_ptr<Message> HardwareCANPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
const HardwareCANPacket* data = (const HardwareCANPacket*)bytestream.data();
|
const HardwareCANPacket* data = (const HardwareCANPacket*)bytestream.data();
|
||||||
|
|
||||||
auto msg = std::make_shared<CANMessage>();
|
if(data->dlc.RB1) { // Change counts reporting
|
||||||
|
|
||||||
// Arb ID
|
const bool busOff = data->data[0] & 0b00100000;
|
||||||
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)
|
auto msg = std::make_shared<CANErrorCountMessage>(data->data[2], data->data[1], busOff);
|
||||||
// Decoder will fix as it has information about the timestampResolution increments
|
|
||||||
msg->timestamp = data->timestamp.TS;
|
|
||||||
|
|
||||||
// DLC
|
// This timestamp is raw off the device (in timestampResolution increments)
|
||||||
uint8_t length = data->dlc.DLC;
|
// Decoder will fix as it has information about the timestampResolution increments
|
||||||
msg->dlcOnWire = length; // This will hold the real DLC on wire 0x0 - 0xF
|
msg->timestamp = data->timestamp.TS;
|
||||||
if(data->header.EDL && data->timestamp.IsExtended) { // CAN FD
|
|
||||||
msg->isCANFD = true;
|
return msg;
|
||||||
msg->baudrateSwitch = data->header.BRS; // CAN FD Baudrate Switch
|
|
||||||
msg->errorStateIndicator = data->header.ESI;
|
} else { // CAN Frame
|
||||||
const optional<uint8_t> lenFromDLC = CANFD_DLCToLength(length);
|
auto msg = std::make_shared<CANMessage>();
|
||||||
if (lenFromDLC)
|
|
||||||
length = *lenFromDLC;
|
// Arb ID
|
||||||
} else if(length > 8) { // This is a standard CAN frame with a length of more than 8
|
if(data->header.IDE) { // Extended 29-bit ID
|
||||||
// Yes, this is possible. On the wire, the length field is a nibble, and we do want to return an accurate value
|
msg->arbid = (data->header.SID & 0x7ff) << 18;
|
||||||
// We don't want to overread our buffer, though, so make sure we cap the length
|
msg->arbid |= (data->eid.EID & 0xfff) << 6;
|
||||||
length = 8;
|
msg->arbid |= (data->dlc.EID2 & 0x3f);
|
||||||
}
|
msg->isExtended = true;
|
||||||
|
} else { // Standard 11-bit ID
|
||||||
// Data
|
msg->arbid = data->header.SID;
|
||||||
// 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;
|
||||||
|
|
||||||
|
// 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<uint8_t> 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<uint8_t>& result, const device_eventhandler_t& report) {
|
bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& result, const device_eventhandler_t& report) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ std::shared_ptr<VersionMessage> HardwareVersionPacket::DecodeMainToMessage(const
|
||||||
if(bytestream.size() < 3) // Not enough bytes to decode
|
if(bytestream.size() < 3) // Not enough bytes to decode
|
||||||
return std::shared_ptr<VersionMessage>();
|
return std::shared_ptr<VersionMessage>();
|
||||||
|
|
||||||
auto msg = std::make_shared<VersionMessage>(true);
|
auto msg = std::make_shared<VersionMessage>(VersionMessage::MainChip);
|
||||||
|
|
||||||
optional<DeviceAppVersion>& version = msg->Versions.emplace_back();
|
optional<DeviceAppVersion>& version = msg->Versions.emplace_back();
|
||||||
version.emplace();
|
version.emplace();
|
||||||
|
|
@ -17,7 +17,7 @@ std::shared_ptr<VersionMessage> HardwareVersionPacket::DecodeMainToMessage(const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VersionMessage> HardwareVersionPacket::DecodeSecondaryToMessage(const std::vector<uint8_t>& bytestream) {
|
std::shared_ptr<VersionMessage> HardwareVersionPacket::DecodeSecondaryToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
auto msg = std::make_shared<VersionMessage>(false);
|
auto msg = std::make_shared<VersionMessage>(VersionMessage::SecondaryChips);
|
||||||
|
|
||||||
size_t bytesLeft = bytestream.size();
|
size_t bytesLeft = bytestream.size();
|
||||||
if(bytesLeft)
|
if(bytesLeft)
|
||||||
|
|
|
||||||
|
|
@ -117,19 +117,16 @@ std::pair<std::vector<std::shared_ptr<Message>>, bool> Device::getMessages() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit, std::chrono::milliseconds timeout) {
|
bool Device::getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit, std::chrono::milliseconds timeout) {
|
||||||
// not open
|
|
||||||
if(!isOpen()) {
|
if(!isOpen()) {
|
||||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not online
|
|
||||||
if(!isOnline()) {
|
if(!isOnline()) {
|
||||||
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not currently polling, throw error
|
|
||||||
if(!isMessagePollingEnabled()) {
|
if(!isMessagePollingEnabled()) {
|
||||||
report(APIEvent::Type::DeviceNotCurrentlyPolling, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceNotCurrentlyPolling, APIEvent::Severity::Error);
|
||||||
return false;
|
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?"
|
if(!serial) // "Communication could not be established with the device. Perhaps it is not powered with 12 volts?"
|
||||||
return getCommunicationNotEstablishedError();
|
return getCommunicationNotEstablishedError();
|
||||||
|
|
||||||
std::string currentSerial = getNeoDevice().serial;
|
std::string currentSerial = getNeoDevice().serial;
|
||||||
if(currentSerial != serial->deviceSerial)
|
if(currentSerial != serial->deviceSerial)
|
||||||
return APIEvent::Type::IncorrectSerialNumber;
|
return APIEvent::Type::IncorrectSerialNumber;
|
||||||
|
|
@ -309,7 +306,7 @@ bool Device::close() {
|
||||||
|
|
||||||
if(isOnline())
|
if(isOnline())
|
||||||
goOffline();
|
goOffline();
|
||||||
|
|
||||||
if(internalHandlerCallbackID)
|
if(internalHandlerCallbackID)
|
||||||
com->removeMessageCallback(internalHandlerCallbackID);
|
com->removeMessageCallback(internalHandlerCallbackID);
|
||||||
|
|
||||||
|
|
@ -352,7 +349,7 @@ bool Device::goOnline() {
|
||||||
if(failOut)
|
if(failOut)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
online = true;
|
online = true;
|
||||||
|
|
||||||
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
|
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
|
||||||
|
|
@ -373,9 +370,9 @@ bool Device::goOffline() {
|
||||||
auto startTime = std::chrono::system_clock::now();
|
auto startTime = std::chrono::system_clock::now();
|
||||||
|
|
||||||
ledState = (latestResetStatus && latestResetStatus->cmRunning) ? LEDState::CoreMiniRunning : LEDState::Offline;
|
ledState = (latestResetStatus && latestResetStatus->cmRunning) ? LEDState::CoreMiniRunning : LEDState::Offline;
|
||||||
|
|
||||||
updateLEDState();
|
updateLEDState();
|
||||||
|
|
||||||
MessageFilter filter(Network::NetID::Reset_Status);
|
MessageFilter filter(Network::NetID::Reset_Status);
|
||||||
filter.includeInternalInAny = true;
|
filter.includeInternalInAny = true;
|
||||||
|
|
||||||
|
|
@ -383,32 +380,30 @@ bool Device::goOffline() {
|
||||||
while((std::chrono::system_clock::now() - startTime) < std::chrono::seconds(5)) {
|
while((std::chrono::system_clock::now() - startTime) < std::chrono::seconds(5)) {
|
||||||
if(latestResetStatus && !latestResetStatus->comEnabled)
|
if(latestResetStatus && !latestResetStatus->comEnabled)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(!com->sendCommand(Command::RequestStatusUpdate))
|
if(!com->sendCommand(Command::RequestStatusUpdate))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
com->waitForMessageSync(filter, std::chrono::milliseconds(100));
|
com->waitForMessageSync(filter, std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
online = false;
|
online = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::transmit(std::shared_ptr<Message> message) {
|
bool Device::transmit(std::shared_ptr<Frame> frame) {
|
||||||
// not open
|
|
||||||
if(!isOpen()) {
|
if(!isOpen()) {
|
||||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not online
|
|
||||||
if(!isOnline()) {
|
if(!isOnline()) {
|
||||||
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isSupportedTXNetwork(message->network)) {
|
if(!isSupportedTXNetwork(frame->network)) {
|
||||||
report(APIEvent::Type::UnsupportedTXNetwork, APIEvent::Severity::Error);
|
report(APIEvent::Type::UnsupportedTXNetwork, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -416,7 +411,7 @@ bool Device::transmit(std::shared_ptr<Message> message) {
|
||||||
bool extensionHookedTransmit = false;
|
bool extensionHookedTransmit = false;
|
||||||
bool transmitStatusFromExtension = false;
|
bool transmitStatusFromExtension = false;
|
||||||
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
||||||
if(!ext->transmitHook(message, transmitStatusFromExtension))
|
if(!ext->transmitHook(frame, transmitStatusFromExtension))
|
||||||
extensionHookedTransmit = true;
|
extensionHookedTransmit = true;
|
||||||
return !extensionHookedTransmit; // false breaks out of the loop early
|
return !extensionHookedTransmit; // false breaks out of the loop early
|
||||||
});
|
});
|
||||||
|
|
@ -424,15 +419,15 @@ bool Device::transmit(std::shared_ptr<Message> message) {
|
||||||
return transmitStatusFromExtension;
|
return transmitStatusFromExtension;
|
||||||
|
|
||||||
std::vector<uint8_t> packet;
|
std::vector<uint8_t> packet;
|
||||||
if(!com->encoder->encode(*com->packetizer, packet, message))
|
if(!com->encoder->encode(*com->packetizer, packet, frame))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return com->sendPacket(packet);
|
return com->sendPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::transmit(std::vector<std::shared_ptr<Message>> messages) {
|
bool Device::transmit(std::vector<std::shared_ptr<Frame>> frames) {
|
||||||
for(auto& message : messages) {
|
for(auto& frame : frames) {
|
||||||
if(!transmit(message))
|
if(!transmit(frame))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -692,22 +687,32 @@ void Device::forEachExtension(std::function<bool(const std::shared_ptr<DeviceExt
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::handleInternalMessage(std::shared_ptr<Message> message) {
|
void Device::handleInternalMessage(std::shared_ptr<Message> message) {
|
||||||
switch(message->network.getNetID()) {
|
switch(message->type) {
|
||||||
case Network::NetID::Reset_Status:
|
case Message::Type::ResetStatus:
|
||||||
latestResetStatus = std::dynamic_pointer_cast<ResetStatusMessage>(message);
|
latestResetStatus = std::static_pointer_cast<ResetStatusMessage>(message);
|
||||||
break;
|
break;
|
||||||
case Network::NetID::Device: {
|
case Message::Type::RawMessage: {
|
||||||
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
|
||||||
if(canmsg)
|
switch(rawMessage->network.getNetID()) {
|
||||||
handleNeoVIMessage(std::move(canmsg));
|
case Network::NetID::Device: {
|
||||||
|
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
|
||||||
|
// if it couldn't be decoded to a CANMessage. We only care about the
|
||||||
|
// CANMessage decoding right now.
|
||||||
|
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
||||||
|
if(canmsg)
|
||||||
|
handleNeoVIMessage(std::move(canmsg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Network::NetID::DeviceStatus:
|
||||||
|
// Device Status format is unique per device, so the devices need to decode it themselves
|
||||||
|
handleDeviceStatus(rawMessage);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break; //std::cout << "HandleInternalMessage got a message from " << message->network << " and it was unhandled!" << std::endl;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Network::NetID::DeviceStatus:
|
default: break;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
||||||
ext->handleMessage(message);
|
ext->handleMessage(message);
|
||||||
|
|
|
||||||
|
|
@ -26,18 +26,16 @@ void FlexRay::Extension::onGoOffline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlexRay::Extension::handleMessage(const std::shared_ptr<Message>& message) {
|
void FlexRay::Extension::handleMessage(const std::shared_ptr<Message>& message) {
|
||||||
switch(message->network.getNetID()) {
|
switch(message->type) {
|
||||||
case Network::NetID::FlexRayControl: {
|
case Message::Type::FlexRayControl: {
|
||||||
auto msg = std::dynamic_pointer_cast<FlexRayControlMessage>(message);
|
auto msg = std::dynamic_pointer_cast<FlexRayControlMessage>(message);
|
||||||
if(!msg || !msg->decoded)
|
if(!msg || !msg->decoded)
|
||||||
return;
|
return;
|
||||||
switch(msg->opcode) {
|
switch(msg->opcode) {
|
||||||
case FlexRay::Opcode::ReadCCStatus:
|
case FlexRay::Opcode::ReadCCStatus:
|
||||||
if(auto status = std::dynamic_pointer_cast<FlexRayControlMessage>(message)) { // TODO else report error?
|
if(msg->controller >= controllers.size())
|
||||||
if(status->controller >= controllers.size())
|
return; // TODO error
|
||||||
return; // TODO error
|
controllers[msg->controller]->_setStatus(msg);
|
||||||
controllers[status->controller]->_setStatus(status);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -47,18 +45,18 @@ void FlexRay::Extension::handleMessage(const std::shared_ptr<Message>& message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlexRay::Extension::transmitHook(const std::shared_ptr<Message>& message, bool& success) {
|
bool FlexRay::Extension::transmitHook(const std::shared_ptr<Frame>& frame, bool& success) {
|
||||||
if(!message || message->network.getType() != Network::Type::FlexRay)
|
if(!frame || frame->network.getType() != Network::Type::FlexRay)
|
||||||
return true; // Don't hook non-FlexRay messages
|
return true; // Don't hook non-FlexRay messages
|
||||||
|
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
std::shared_ptr<FlexRayMessage> frmsg = std::dynamic_pointer_cast<FlexRayMessage>(message);
|
std::shared_ptr<FlexRayMessage> frmsg = std::dynamic_pointer_cast<FlexRayMessage>(frame);
|
||||||
if(!frmsg)
|
if(!frmsg)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for(auto& controller : controllers) {
|
for(auto& controller : controllers) {
|
||||||
if(controller->getNetwork() != message->network)
|
if(controller->getNetwork() != frame->network)
|
||||||
continue;
|
continue;
|
||||||
success |= controller->transmit(frmsg);
|
success |= controller->transmit(frmsg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
bool iBit = temp & 1;
|
bool iBit = temp & 1;
|
||||||
|
|
||||||
int iCrcNxt;
|
int iCrcNxt;
|
||||||
//CRCNXT = NXTBIT EXOR CRC_RG(15);
|
//CRCNXT = NXTBIT EXOR CRC_RG(15);
|
||||||
if (gsCrc & (1 << 15))
|
if (gsCrc & (1 << 15))
|
||||||
|
|
@ -187,7 +187,7 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
|
||||||
settingsLoaded = true;
|
settingsLoaded = true;
|
||||||
|
|
||||||
// TODO Warn user that their API version differs from the device firmware version
|
// TODO Warn user that their API version differs from the device firmware version
|
||||||
//if(settings.size() != structSize)
|
//if(settings.size() != structSize)
|
||||||
|
|
||||||
return settingsLoaded;
|
return settingsLoaded;
|
||||||
}
|
}
|
||||||
|
|
@ -227,10 +227,10 @@ bool IDeviceSettings::apply(bool temporary) {
|
||||||
|
|
||||||
// Pause I/O with the device while the settings are applied
|
// Pause I/O with the device while the settings are applied
|
||||||
applyingSettings = true;
|
applyingSettings = true;
|
||||||
|
|
||||||
std::shared_ptr<Message> msg = com->waitForMessageSync([this, &bytestream]() {
|
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
|
||||||
return com->sendCommand(Command::SetSettings, 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
|
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
|
// 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);
|
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
|
||||||
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
||||||
|
|
||||||
msg = com->waitForMessageSync([this, &bytestream]() {
|
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
|
||||||
return com->sendCommand(Command::SetSettings, 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) {
|
if(!msg || msg->data[0] != 1) {
|
||||||
// Attempt to get the settings from the device so we're up to date if possible
|
// Attempt to get the settings from the device so we're up to date if possible
|
||||||
if(refresh()) {
|
if(refresh()) {
|
||||||
|
|
@ -267,11 +267,11 @@ bool IDeviceSettings::apply(bool temporary) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!temporary) {
|
if(!temporary) {
|
||||||
msg = com->waitForMessageSync([this]() {
|
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||||
return com->sendCommand(Command::SaveSettings);
|
return com->sendCommand(Command::SaveSettings);
|
||||||
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000));
|
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
applyingSettings = false;
|
applyingSettings = false;
|
||||||
|
|
||||||
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
|
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;
|
applyingSettings = true;
|
||||||
|
|
||||||
std::shared_ptr<Message> msg = com->waitForMessageSync([this]() {
|
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||||
return com->sendCommand(Command::SetDefaultSettings);
|
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) {
|
if(!msg || msg->data[0] != 1) {
|
||||||
// Attempt to get the settings from the device so we're up to date if possible
|
// Attempt to get the settings from the device so we're up to date if possible
|
||||||
if(refresh()) {
|
if(refresh()) {
|
||||||
|
|
@ -331,9 +331,9 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||||
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
|
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
|
||||||
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
||||||
|
|
||||||
msg = com->waitForMessageSync([this, &bytestream]() {
|
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
|
||||||
return com->sendCommand(Command::SetSettings, 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) {
|
if(!msg || msg->data[0] != 1) {
|
||||||
// Attempt to get the settings from the device so we're up to date if possible
|
// Attempt to get the settings from the device so we're up to date if possible
|
||||||
if(refresh()) {
|
if(refresh()) {
|
||||||
|
|
@ -344,13 +344,13 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!temporary) {
|
if(!temporary) {
|
||||||
msg = com->waitForMessageSync([this]() {
|
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||||
return com->sendCommand(Command::SaveSettings);
|
return com->sendCommand(Command::SaveSettings);
|
||||||
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000));
|
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
applyingSettings = false;
|
applyingSettings = false;
|
||||||
|
|
||||||
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
|
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
|
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);
|
report(APIEvent::Type::CANSettingsNotAvailable, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
||||||
if(newBaud == (CANBaudrate)-1) {
|
if(newBaud == (CANBaudrate)-1) {
|
||||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
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);
|
report(APIEvent::Type::LSFTCANSettingsNotAvailable, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
||||||
if(newBaud == (CANBaudrate)-1) {
|
if(newBaud == (CANBaudrate)-1) {
|
||||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
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);
|
report(APIEvent::Type::SWCANSettingsNotAvailable, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
||||||
if(newBaud == (CANBaudrate)-1) {
|
if(newBaud == (CANBaudrate)-1) {
|
||||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
||||||
|
|
@ -691,7 +691,7 @@ template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure)
|
||||||
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
|
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is only called from C++ so the caller's structure size and ours should never differ
|
// This function is only called from C++ so the caller's structure size and ours should never differ
|
||||||
if(sizeof(T) != structSize) {
|
if(sizeof(T) != structSize) {
|
||||||
report(APIEvent::Type::SettingsStructureMismatch, APIEvent::Severity::Error);
|
report(APIEvent::Type::SettingsStructureMismatch, APIEvent::Severity::Error);
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ int main() {
|
||||||
printLastError();
|
printLastError();
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Canceling!\n\n");
|
printf("Canceling!\n\n");
|
||||||
|
|
@ -425,7 +425,7 @@ int main() {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Canceling!\n\n");
|
printf("Canceling!\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Get messages
|
// Get messages
|
||||||
|
|
@ -467,24 +467,34 @@ int main() {
|
||||||
|
|
||||||
// Print out the received messages
|
// Print out the received messages
|
||||||
for(size_t i = 0; i < msgCount; i++) {
|
for(size_t i = 0; i < msgCount; i++) {
|
||||||
neomessage_t* msg = &msgs[i];
|
const neomessage_t* msg = &msgs[i];
|
||||||
switch(msg->type) {
|
switch(msg->messageType) {
|
||||||
case ICSNEO_NETWORK_TYPE_CAN: // CAN
|
case ICSNEO_MESSAGE_TYPE_FRAME: {
|
||||||
{
|
const neomessage_frame_t* frame = (neomessage_frame_t*)msg;
|
||||||
neomessage_can_t* canMsg = (neomessage_can_t*) msg;
|
switch(frame->type) {
|
||||||
printf("\t0x%03x [%zu] ", canMsg->arbid, canMsg->length);
|
case ICSNEO_NETWORK_TYPE_CAN: {
|
||||||
for(size_t i = 0; i < canMsg->length; i++) {
|
neomessage_can_t* canMsg = (neomessage_can_t*)frame;
|
||||||
printf("%02x ", canMsg->data[i]);
|
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");
|
printf("\n");
|
||||||
|
|
@ -689,7 +699,7 @@ int main() {
|
||||||
{
|
{
|
||||||
case '1': type = ICSNEO_IO_ETH_ACTIVATION; break;
|
case '1': type = ICSNEO_IO_ETH_ACTIVATION; break;
|
||||||
case '2': type = ICSNEO_IO_USB_HOST_POWER; 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)) {
|
if(icsneo_setDigitalIO(selectedDevice, type, 1, set)) {
|
||||||
printf("OK!\n\n");
|
printf("OK!\n\n");
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
project(libicsneocpp-interactive-example VERSION 0.2.0)
|
project(libicsneocpp-interactive-example VERSION 0.2.0)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD_REQUIRED 11)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,102 @@ std::shared_ptr<icsneo::Device> selectDevice(const std::vector<std::shared_ptr<i
|
||||||
return from.at(selectedDeviceNum - 1);
|
return from.at(selectedDeviceNum - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printMessage(const std::shared_ptr<icsneo::Message>& 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<icsneo::Frame>(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<icsneo::CANMessage>(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<icsneo::EthernetMessage>(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<icsneo::ISO9141Message>(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<icsneo::CANErrorCountMessage>(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() {
|
int main() {
|
||||||
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl << std::endl;
|
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;
|
std::cout << "[1] Open" << std::endl << "[2] Close" << std::endl << "[3] Cancel" << std::endl << std::endl;
|
||||||
char selection = getCharInput(std::vector<char> {'1', '2', '3'});
|
char selection = getCharInput(std::vector<char> {'1', '2', '3'});
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
switch(selection) {
|
switch(selection) {
|
||||||
case '1':
|
case '1':
|
||||||
if(selectedDevice->open()) {
|
if(selectedDevice->open()) {
|
||||||
|
|
@ -247,7 +343,7 @@ int main() {
|
||||||
std::cout << icsneo::GetLastError() << std::endl;
|
std::cout << icsneo::GetLastError() << std::endl;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
// Attempt to close the device
|
// Attempt to close the device
|
||||||
|
|
@ -259,7 +355,7 @@ int main() {
|
||||||
std::cout << icsneo::GetLastError() << std::endl;;
|
std::cout << icsneo::GetLastError() << std::endl;;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << "Canceling!" << std::endl << std::endl;
|
std::cout << "Canceling!" << std::endl << std::endl;
|
||||||
|
|
@ -360,7 +456,7 @@ int main() {
|
||||||
default:
|
default:
|
||||||
std::cout << "Canceling!" << std::endl << std::endl;
|
std::cout << "Canceling!" << std::endl << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Get messages
|
// Get messages
|
||||||
|
|
@ -392,29 +488,9 @@ int main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print out the received messages
|
// Print out the received messages
|
||||||
for(auto msg : msgs) {
|
for(const auto& msg : msgs)
|
||||||
switch(msg->network.getType()) {
|
printMessage(msg);
|
||||||
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<icsneo::CANMessage>(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << std::endl;
|
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 << "Failed to transmit message to " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||||
std::cout << icsneo::GetLastError() << std::endl;;
|
std::cout << icsneo::GetLastError() << std::endl;;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Example of CAN FD
|
/** Example of CAN FD
|
||||||
std::cout << "Transmitting an extended CAN FD frame... " << std::endl;
|
std::cout << "Transmitting an extended CAN FD frame... " << std::endl;
|
||||||
auto txMessage = std::make_shared<icsneo::CANMessage>();
|
auto txMessage = std::make_shared<icsneo::CANMessage>();
|
||||||
|
|
@ -538,28 +614,8 @@ int main() {
|
||||||
switch(selection) {
|
switch(selection) {
|
||||||
case '1':
|
case '1':
|
||||||
{
|
{
|
||||||
// Shameless copy-paste from get messages above, demonstrating a callback
|
|
||||||
int callbackID = selectedDevice->addMessageCallback(icsneo::MessageCallback([](std::shared_ptr<icsneo::Message> msg){
|
int callbackID = selectedDevice->addMessageCallback(icsneo::MessageCallback([](std::shared_ptr<icsneo::Message> msg){
|
||||||
switch(msg->network.getType()) {
|
printMessage(msg);
|
||||||
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<icsneo::CANMessage>(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;
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if(callbackID != -1) {
|
if(callbackID != -1) {
|
||||||
|
|
@ -578,7 +634,7 @@ int main() {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
std::vector<char> allowed;
|
std::vector<char> allowed;
|
||||||
|
|
||||||
std::cout << "Which id would you like to remove?" << std::endl;
|
std::cout << "Which id would you like to remove?" << std::endl;
|
||||||
for(int id : callbacks.find(selectedDevice)->second) {
|
for(int id : callbacks.find(selectedDevice)->second) {
|
||||||
allowed.push_back(static_cast<char>(id) + '0');
|
allowed.push_back(static_cast<char>(id) + '0');
|
||||||
|
|
@ -595,7 +651,7 @@ int main() {
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Failed to remove message callback id " << removeID << " from " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
std::cout << "Failed to remove message callback id " << removeID << " from " << selectedDevice->describe() << "!" << std::endl << std::endl;
|
||||||
std::cout << icsneo::GetLastError() << std::endl;;
|
std::cout << icsneo::GetLastError() << std::endl;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
project(libicsneocpp-simple-example VERSION 0.2.0)
|
project(libicsneocpp-simple-example VERSION 0.2.0)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD_REQUIRED 11)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
int main() {
|
int main() {
|
||||||
// Print version
|
// Print version
|
||||||
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl;
|
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl;
|
||||||
|
|
||||||
std::cout<< "Supported devices:" << std::endl;
|
std::cout<< "Supported devices:" << std::endl;
|
||||||
for(auto& dev : icsneo::GetSupportedDevices())
|
for(auto& dev : icsneo::GetSupportedDevices())
|
||||||
std::cout << '\t' << dev.getGenericProductName() << std::endl;
|
std::cout << '\t' << dev.getGenericProductName() << std::endl;
|
||||||
|
|
@ -85,7 +85,7 @@ int main() {
|
||||||
std::cout << "FAIL" << std::endl;
|
std::cout << "FAIL" << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
std::cout << "OK, " << (baud/1000) << "kbit/s" << std::endl;
|
||||||
|
|
||||||
std::cout << "\tGetting HSCANFD Baudrate... ";
|
std::cout << "\tGetting HSCANFD Baudrate... ";
|
||||||
baud = device->settings->getFDBaudrateFor(icsneo::Network::NetID::HSCAN);
|
baud = device->settings->getFDBaudrateFor(icsneo::Network::NetID::HSCAN);
|
||||||
if(baud < 0)
|
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
|
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!
|
// 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<icsneo::CANMessage>();
|
||||||
|
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
|
// We can also register a handler
|
||||||
std::cout << "\tStreaming messages in for 3 seconds... " << std::endl;
|
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
|
// MessageCallbacks are powerful, and can filter on things like ArbID for you. See the documentation
|
||||||
auto handler = device->addMessageCallback(icsneo::MessageCallback([](std::shared_ptr<icsneo::Message> message) {
|
auto handler = device->addMessageCallback(icsneo::MessageCallback([](std::shared_ptr<icsneo::Message> message) {
|
||||||
switch(message->network.getType()) {
|
switch(message->type) {
|
||||||
case icsneo::Network::Type::CAN: {
|
case icsneo::Message::Type::Frame: {
|
||||||
// A message of type CAN is guaranteed to be a CANMessage, so we can static cast safely
|
// A message of type Frame is guaranteed to be a Frame, so we can static cast safely
|
||||||
auto canMessage = std::static_pointer_cast<icsneo::CANMessage>(message);
|
auto frame = std::static_pointer_cast<icsneo::Frame>(message);
|
||||||
|
switch(frame->network.getType()) {
|
||||||
std::cout << "\t\tCAN ";
|
case icsneo::Network::Type::CAN: {
|
||||||
if(canMessage->isCANFD) {
|
// A message of type CAN is guaranteed to be a CANMessage, so we can static cast safely
|
||||||
std::cout << "FD ";
|
auto canMessage = std::static_pointer_cast<icsneo::CANMessage>(message);
|
||||||
if(!canMessage->baudrateSwitch)
|
|
||||||
std::cout << "(No BRS) ";
|
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<icsneo::EthernetMessage>(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<icsneo::ISO9141Message>(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;
|
break;
|
||||||
}
|
} // end of icsneo::Message::Type::Frame
|
||||||
case icsneo::Network::Type::Ethernet: {
|
case icsneo::Message::Type::CANErrorCount: {
|
||||||
auto ethMessage = std::static_pointer_cast<icsneo::EthernetMessage>(message);
|
// A message of type CANErrorCount is guaranteed to be a CANErrorCount, so we can static cast safely
|
||||||
|
auto cec = std::static_pointer_cast<icsneo::CANErrorCountMessage>(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;
|
// Print the error counts
|
||||||
break;
|
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) ";
|
||||||
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<icsneo::ISO9141Message>(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
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// Ignoring non-network messages
|
// Ignoring other types of messages
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
@ -278,7 +314,7 @@ int main() {
|
||||||
ret = device->close();
|
ret = device->close();
|
||||||
std::cout << (ret ? "OK\n" : "FAIL\n") << std::endl;
|
std::cout << (ret ? "OK\n" : "FAIL\n") << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Press any key to continue..." << std::endl;
|
std::cout << "Press any key to continue..." << std::endl;
|
||||||
std::cin.get();
|
std::cin.get();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
class CANMessage : public Message {
|
class CANMessage : public Frame {
|
||||||
public:
|
public:
|
||||||
uint32_t arbid;
|
uint32_t arbid;
|
||||||
uint8_t dlcOnWire;
|
uint8_t dlcOnWire;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ struct MACAddress {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class EthernetMessage : public Message {
|
class EthernetMessage : public Frame {
|
||||||
public:
|
public:
|
||||||
bool preemptionEnabled = false;
|
bool preemptionEnabled = false;
|
||||||
uint8_t preemptionFlags = 0;
|
uint8_t preemptionFlags = 0;
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ namespace icsneo {
|
||||||
|
|
||||||
class CANMessageFilter : public MessageFilter {
|
class CANMessageFilter : public MessageFilter {
|
||||||
public:
|
public:
|
||||||
CANMessageFilter() : MessageFilter(Network::Type::CAN), arbid(INVALID_ARBID) {}
|
CANMessageFilter() : MessageFilter(Network::Type::CAN), arbid(INVALID_ARBID) { messageType = Message::Type::Frame; }
|
||||||
CANMessageFilter(uint32_t arbid) : MessageFilter(Network::Type::CAN), arbid(arbid) {}
|
CANMessageFilter(uint32_t arbid) : MessageFilter(Network::Type::CAN), arbid(arbid) { messageType = Message::Type::Frame; }
|
||||||
|
|
||||||
bool match(const std::shared_ptr<Message>& message) const {
|
bool match(const std::shared_ptr<Message>& message) const {
|
||||||
if(!MessageFilter::match(message))
|
if(!MessageFilter::match(message))
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,10 @@ namespace icsneo {
|
||||||
|
|
||||||
class Main51MessageFilter : public MessageFilter {
|
class Main51MessageFilter : public MessageFilter {
|
||||||
public:
|
public:
|
||||||
Main51MessageFilter() : MessageFilter(Network::NetID::Main51), command(INVALID_COMMAND) {}
|
Main51MessageFilter() : MessageFilter(Message::Type::Main51), command(INVALID_COMMAND) {}
|
||||||
Main51MessageFilter(Command command) : MessageFilter(Network::NetID::Main51), command(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>& message) const {
|
bool match(const std::shared_ptr<Message>& message) const {
|
||||||
if(!MessageFilter::match(message)) {
|
if(!MessageFilter::match(message)) {
|
||||||
|
|
|
||||||
|
|
@ -12,26 +12,44 @@ namespace icsneo {
|
||||||
class MessageFilter {
|
class MessageFilter {
|
||||||
public:
|
public:
|
||||||
MessageFilter() {}
|
MessageFilter() {}
|
||||||
MessageFilter(Network::Type type) : type(type) {}
|
MessageFilter(Message::Type type) : includeInternalInAny(neomessagetype_t(type) & 0x8000), messageType(type) {}
|
||||||
MessageFilter(Network::NetID netid) : type(Network::GetTypeOfNetID(netid)), netid(netid) {}
|
MessageFilter(Network::NetID netid) : MessageFilter(Network::GetTypeOfNetID(netid), netid) {}
|
||||||
virtual ~MessageFilter() {}
|
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"
|
// When getting "all" types of messages, include the ones marked as "internal only"
|
||||||
bool includeInternalInAny = false;
|
bool includeInternalInAny = false;
|
||||||
|
|
||||||
virtual bool match(const std::shared_ptr<Message>& message) const {
|
virtual bool match(const std::shared_ptr<Message>& message) const {
|
||||||
if(!matchType(message->network.getType()))
|
if(!matchMessageType(message->type))
|
||||||
return false;
|
|
||||||
if(!matchNetID(message->network.getNetID()))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(message->type == Message::Type::Frame) {
|
||||||
|
Frame& frame = *static_cast<Frame*>(message.get());
|
||||||
|
if(!matchNetworkType(frame.network.getType()))
|
||||||
|
return false;
|
||||||
|
if(!matchNetID(frame.network.getNetID()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
Network::Type type = Network::Type::Any;
|
Message::Type messageType = Message::Type::Invalid; // Used here for "any"
|
||||||
bool matchType(Network::Type mtype) const {
|
bool matchMessageType(Message::Type mtype) const {
|
||||||
if(type == Network::Type::Any && (mtype != Network::Type::Internal || includeInternalInAny))
|
if(messageType == Message::Type::Invalid && ((neomessagetype_t(mtype) & 0x8000) == 0 || includeInternalInAny))
|
||||||
return true;
|
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;
|
Network::NetID netid = Network::NetID::Any;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public:
|
||||||
uint8_t controller, uint16_t bufferId, const std::vector<uint8_t>& data, uint16_t desiredSize);
|
uint8_t controller, uint16_t bufferId, const std::vector<uint8_t>& data, uint16_t desiredSize);
|
||||||
|
|
||||||
FlexRayControlMessage(const Packet& packet);
|
FlexRayControlMessage(const Packet& packet);
|
||||||
virtual ~FlexRayControlMessage() = default;
|
|
||||||
bool decoded = false;
|
bool decoded = false;
|
||||||
uint8_t controller = 0xff; // Controller index, either 0 or 1
|
uint8_t controller = 0xff; // Controller index, either 0 or 1
|
||||||
FlexRay::Opcode opcode = FlexRay::Opcode::Unknown;
|
FlexRay::Opcode opcode = FlexRay::Opcode::Unknown;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
class FlexRayMessage : public Message {
|
class FlexRayMessage : public Frame {
|
||||||
public:
|
public:
|
||||||
uint16_t slotid = 0;
|
uint16_t slotid = 0;
|
||||||
double tsslen = 0;
|
double tsslen = 0;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
class ISO9141Message : public Message {
|
class ISO9141Message : public Frame {
|
||||||
public:
|
public:
|
||||||
std::array<uint8_t, 3> header;
|
std::array<uint8_t, 3> header;
|
||||||
bool isInit = false;
|
bool isInit = false;
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
class Main51Message : public Message {
|
class Main51Message : public RawMessage {
|
||||||
public:
|
public:
|
||||||
virtual ~Main51Message() = default;
|
Main51Message() : RawMessage(Message::Type::Main51, Network::NetID::Main51) {}
|
||||||
Command command = Command(0);
|
Command command = Command(0);
|
||||||
bool forceShortFormat = false; // Necessary for EnableNetworkCom and EnableNetworkComEx
|
bool forceShortFormat = false; // Necessary for EnableNetworkCom and EnableNetworkComEx
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
#ifndef __MESSAGE_H_
|
#ifndef __MESSAGE_H_
|
||||||
#define __MESSAGE_H_
|
#define __MESSAGE_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef uint16_t neomessagetype_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#include "icsneo/communication/network.h"
|
#include "icsneo/communication/network.h"
|
||||||
|
|
@ -10,10 +13,42 @@ namespace icsneo {
|
||||||
|
|
||||||
class Message {
|
class Message {
|
||||||
public:
|
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;
|
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<uint8_t> d) : Message(Message::Type::RawMessage), network(net), data(d) {}
|
||||||
|
|
||||||
Network network;
|
Network network;
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
uint64_t timestamp = 0;
|
};
|
||||||
|
|
||||||
|
class Frame : public RawMessage {
|
||||||
|
public:
|
||||||
|
Frame() : RawMessage(Message::Type::Frame) {}
|
||||||
|
|
||||||
uint16_t description = 0;
|
uint16_t description = 0;
|
||||||
bool transmitted = false;
|
bool transmitted = false;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
@ -23,4 +58,18 @@ public:
|
||||||
|
|
||||||
#endif // __cplusplus
|
#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
|
#endif
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "icsneo/communication/network.h"
|
#include "icsneo/communication/network.h"
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
|
@ -18,12 +19,12 @@ typedef union {
|
||||||
uint32_t extendedFrame : 1;
|
uint32_t extendedFrame : 1;
|
||||||
uint32_t remoteFrame : 1;
|
uint32_t remoteFrame : 1;
|
||||||
uint32_t crcError : 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 incompleteFrame : 1;
|
||||||
uint32_t lostArbitration : 1;
|
uint32_t lostArbitration : 1;
|
||||||
uint32_t undefinedError : 1;
|
uint32_t undefinedError : 1;
|
||||||
uint32_t canBusOff : 1;
|
uint32_t canBusOff : 1;
|
||||||
uint32_t canErrorWarning : 1;
|
uint32_t canBusRecovered : 1;
|
||||||
uint32_t canBusShortedPlus : 1;
|
uint32_t canBusShortedPlus : 1;
|
||||||
uint32_t canBusShortedGround : 1;
|
uint32_t canBusShortedGround : 1;
|
||||||
uint32_t checksumError : 1;
|
uint32_t checksumError : 1;
|
||||||
|
|
@ -101,24 +102,34 @@ typedef union {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
neomessage_statusbitfield_t status;
|
uint8_t _reserved1[16];
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
uint64_t timestampReserved;
|
uint64_t _reservedTimestamp;
|
||||||
const uint8_t* data;
|
uint8_t _reserved2[sizeof(size_t) * 2 + 7 + sizeof(neonetid_t) + sizeof(neonettype_t)];
|
||||||
size_t length;
|
neomessagetype_t messageType;
|
||||||
uint8_t header[4];
|
uint8_t _reserved3[12];
|
||||||
neonetid_t netid;
|
|
||||||
neonettype_t type;
|
|
||||||
uint8_t reserved0;
|
|
||||||
uint16_t description;
|
|
||||||
uint8_t reserved1[14];
|
|
||||||
} neomessage_t; // 72 bytes total
|
} neomessage_t; // 72 bytes total
|
||||||
// Any time you add another neomessage_*_t type, make sure to add it to the static_asserts below!
|
// Any time you add another neomessage_*_t type, make sure to add it to the static_asserts below!
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
neomessage_statusbitfield_t status;
|
neomessage_statusbitfield_t status;
|
||||||
uint64_t timestamp;
|
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;
|
const uint8_t* data;
|
||||||
size_t length;
|
size_t length;
|
||||||
uint32_t arbid;
|
uint32_t arbid;
|
||||||
|
|
@ -126,22 +137,38 @@ typedef struct {
|
||||||
neonettype_t type;
|
neonettype_t type;
|
||||||
uint8_t dlcOnWire;
|
uint8_t dlcOnWire;
|
||||||
uint16_t description;
|
uint16_t description;
|
||||||
uint8_t reserved[14];
|
neomessagetype_t messageType;
|
||||||
|
uint8_t _reserved1[12];
|
||||||
} neomessage_can_t;
|
} neomessage_can_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
neomessage_statusbitfield_t status;
|
neomessage_statusbitfield_t status;
|
||||||
uint64_t timestamp;
|
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;
|
const uint8_t* data;
|
||||||
size_t length;
|
size_t length;
|
||||||
uint8_t preemptionFlags;
|
uint8_t preemptionFlags;
|
||||||
uint8_t reservedHeader[3];
|
uint8_t _reservedHeader[3];
|
||||||
neonetid_t netid;
|
neonetid_t netid;
|
||||||
neonettype_t type;
|
neonettype_t type;
|
||||||
uint8_t reserved0;
|
uint8_t _reserved0;
|
||||||
uint16_t description;
|
uint16_t description;
|
||||||
uint8_t reserved1[14];
|
neomessagetype_t messageType;
|
||||||
|
uint8_t _reserved1[12];
|
||||||
} neomessage_eth_t;
|
} neomessage_eth_t;
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
@ -151,7 +178,9 @@ typedef struct {
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
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_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_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)");
|
static_assert(sizeof(neomessage_eth_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (Ethernet is not)");
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
class ReadSettingsMessage : public Message {
|
class ReadSettingsMessage : public RawMessage {
|
||||||
public:
|
public:
|
||||||
virtual ~ReadSettingsMessage() = default;
|
ReadSettingsMessage() : RawMessage(Message::Type::ReadSettings, Network::NetID::ReadSettings) {}
|
||||||
|
|
||||||
enum class Response : uint8_t {
|
enum class Response : uint8_t {
|
||||||
OK = 0,
|
OK = 0,
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ namespace icsneo {
|
||||||
|
|
||||||
class ResetStatusMessage : public Message {
|
class ResetStatusMessage : public Message {
|
||||||
public:
|
public:
|
||||||
ResetStatusMessage() : Message() {}
|
ResetStatusMessage() : Message(Message::Type::ResetStatus) {}
|
||||||
virtual ~ResetStatusMessage() = default;
|
|
||||||
uint16_t mainLoopTime;
|
uint16_t mainLoopTime;
|
||||||
uint16_t maxMainLoopTime;
|
uint16_t maxMainLoopTime;
|
||||||
bool justReset;
|
bool justReset;
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,18 @@ namespace icsneo {
|
||||||
|
|
||||||
class VersionMessage : public Message {
|
class VersionMessage : public Message {
|
||||||
public:
|
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
|
VersionMessage(Chip chip) : Message(Message::Type::DeviceVersion), ForChip(chip) {}
|
||||||
const bool MainChip;
|
|
||||||
|
|
||||||
// nullopt here indicates invalid
|
// nullopt here indicates invalid
|
||||||
std::vector< optional<DeviceAppVersion> > Versions;
|
std::vector< optional<DeviceAppVersion> > Versions;
|
||||||
|
|
||||||
|
// What chips the versions are for
|
||||||
|
const Chip ForChip;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace icsneo {
|
||||||
typedef uint16_t icscm_bitfield;
|
typedef uint16_t icscm_bitfield;
|
||||||
|
|
||||||
struct HardwareCANPacket {
|
struct HardwareCANPacket {
|
||||||
static std::shared_ptr<CANMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
static bool EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
static bool EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,8 @@ public:
|
||||||
int addMessageCallback(const MessageCallback& cb) { return com->addMessageCallback(cb); }
|
int addMessageCallback(const MessageCallback& cb) { return com->addMessageCallback(cb); }
|
||||||
bool removeMessageCallback(int id) { return com->removeMessageCallback(id); }
|
bool removeMessageCallback(int id) { return com->removeMessageCallback(id); }
|
||||||
|
|
||||||
bool transmit(std::shared_ptr<Message> message);
|
bool transmit(std::shared_ptr<Frame> frame);
|
||||||
bool transmit(std::vector<std::shared_ptr<Message>> messages);
|
bool transmit(std::vector<std::shared_ptr<Frame>> frames);
|
||||||
|
|
||||||
void setWriteBlocks(bool blocks);
|
void setWriteBlocks(bool blocks);
|
||||||
|
|
||||||
|
|
@ -328,7 +328,7 @@ protected:
|
||||||
|
|
||||||
void handleInternalMessage(std::shared_ptr<Message> message);
|
void handleInternalMessage(std::shared_ptr<Message> message);
|
||||||
|
|
||||||
virtual void handleDeviceStatus(const std::shared_ptr<Message>&) {}
|
virtual void handleDeviceStatus(const std::shared_ptr<RawMessage>&) {}
|
||||||
|
|
||||||
neodevice_t& getWritableNeoDevice() { return data; }
|
neodevice_t& getWritableNeoDevice() { return data; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ public:
|
||||||
virtual void handleMessage(const std::shared_ptr<Message>&) {}
|
virtual void handleMessage(const std::shared_ptr<Message>&) {}
|
||||||
|
|
||||||
// Return true to continue transmitting, success should be written to if false is returned
|
// Return true to continue transmitting, success should be written to if false is returned
|
||||||
virtual bool transmitHook(const std::shared_ptr<Message>& message, bool& success) { (void)message; (void)success; return true; }
|
virtual bool transmitHook(const std::shared_ptr<Frame>& frame, bool& success) { (void)frame; (void)success; return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Device& device;
|
Device& device;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ public:
|
||||||
void onGoOffline() override;
|
void onGoOffline() override;
|
||||||
|
|
||||||
void handleMessage(const std::shared_ptr<Message>& message) override;
|
void handleMessage(const std::shared_ptr<Message>& message) override;
|
||||||
bool transmitHook(const std::shared_ptr<Message>& message, bool& success) override;
|
bool transmitHook(const std::shared_ptr<Frame>& frame, bool& success) override;
|
||||||
|
|
||||||
std::shared_ptr<Controller> getController(uint8_t index) const {
|
std::shared_ptr<Controller> getController(uint8_t index) const {
|
||||||
if(index >= controllers.size())
|
if(index >= controllers.size())
|
||||||
|
|
|
||||||
|
|
@ -104,11 +104,12 @@ protected:
|
||||||
// The supported TX networks are the same as the supported RX networks for this device
|
// The supported TX networks are the same as the supported RX networks for this device
|
||||||
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
|
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
|
||||||
|
|
||||||
void handleDeviceStatus(const std::shared_ptr<Message>& message) override {
|
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
|
||||||
if(!message || message->data.size() < sizeof(neovifire2_status_t))
|
const auto& data = message->data;
|
||||||
|
if(data.size() < sizeof(neovifire2_status_t))
|
||||||
return;
|
return;
|
||||||
std::lock_guard<std::mutex> lk(ioMutex);
|
std::lock_guard<std::mutex> lk(ioMutex);
|
||||||
const neovifire2_status_t* status = reinterpret_cast<const neovifire2_status_t*>(message->data.data());
|
const neovifire2_status_t* status = reinterpret_cast<const neovifire2_status_t*>(data.data());
|
||||||
backupPowerEnabled = status->backupPowerEnabled;
|
backupPowerEnabled = status->backupPowerEnabled;
|
||||||
backupPowerGood = status->backupPowerGood;
|
backupPowerGood = status->backupPowerGood;
|
||||||
ethActivationStatus = status->ethernetActivationLineEnabled;
|
ethActivationStatus = status->ethernetActivationLineEnabled;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ public:
|
||||||
if (!fakedev->com->decoder->decode(msg, packet))
|
if (!fakedev->com->decoder->decode(msg, packet))
|
||||||
continue; // We failed to decode this 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
|
continue; // Not a message we care about
|
||||||
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
||||||
if(!sn)
|
if(!sn)
|
||||||
|
|
|
||||||
|
|
@ -80,11 +80,12 @@ protected:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeviceStatus(const std::shared_ptr<Message>& message) override {
|
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
|
||||||
if(!message || message->data.size() < sizeof(fire2vnet_status_t))
|
const auto& data = message->data;
|
||||||
|
if(data.size() < sizeof(fire2vnet_status_t))
|
||||||
return;
|
return;
|
||||||
std::lock_guard<std::mutex> lk(ioMutex);
|
std::lock_guard<std::mutex> lk(ioMutex);
|
||||||
const fire2vnet_status_t* status = reinterpret_cast<const fire2vnet_status_t*>(message->data.data());
|
const fire2vnet_status_t* status = reinterpret_cast<const fire2vnet_status_t*>(data.data());
|
||||||
ethActivationStatus = status->ethernetActivationLineEnabled;
|
ethActivationStatus = status->ethernetActivationLineEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public:
|
||||||
if(!fakedev->com->decoder->decode(msg, packet))
|
if(!fakedev->com->decoder->decode(msg, packet))
|
||||||
continue; // We failed to decode this 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
|
continue; // Not a message we care about
|
||||||
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
||||||
if(!sn)
|
if(!sn)
|
||||||
|
|
@ -118,11 +118,12 @@ protected:
|
||||||
// The supported TX networks are the same as the supported RX networks for this device
|
// The supported TX networks are the same as the supported RX networks for this device
|
||||||
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
|
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
|
||||||
|
|
||||||
void handleDeviceStatus(const std::shared_ptr<Message>& message) override {
|
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
|
||||||
if(!message || message->data.size() < sizeof(radgalaxy_status_t))
|
const auto& data = message->data;
|
||||||
|
if(data.size() < sizeof(radgalaxy_status_t))
|
||||||
return;
|
return;
|
||||||
std::lock_guard<std::mutex> lk(ioMutex);
|
std::lock_guard<std::mutex> lk(ioMutex);
|
||||||
const radgalaxy_status_t* status = reinterpret_cast<const radgalaxy_status_t*>(message->data.data());
|
const radgalaxy_status_t* status = reinterpret_cast<const radgalaxy_status_t*>(data.data());
|
||||||
ethActivationStatus = status->ethernetActivationLineEnabled;
|
ethActivationStatus = status->ethernetActivationLineEnabled;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -77,11 +77,12 @@ protected:
|
||||||
txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end());
|
txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeviceStatus(const std::shared_ptr<Message>& message) override {
|
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
|
||||||
if(!message || message->data.size() < sizeof(radgigalog_status_t))
|
const auto& data = message->data;
|
||||||
|
if(data.size() < sizeof(radgigalog_status_t))
|
||||||
return;
|
return;
|
||||||
std::lock_guard<std::mutex> lk(ioMutex);
|
std::lock_guard<std::mutex> lk(ioMutex);
|
||||||
const radgigalog_status_t* status = reinterpret_cast<const radgigalog_status_t*>(message->data.data());
|
const radgigalog_status_t* status = reinterpret_cast<const radgigalog_status_t*>(data.data());
|
||||||
ethActivationStatus = status->ethernetActivationLineEnabled;
|
ethActivationStatus = status->ethernetActivationLineEnabled;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public:
|
||||||
if (!fakedev->com->decoder->decode(msg, packet))
|
if (!fakedev->com->decoder->decode(msg, packet))
|
||||||
continue; // We failed to decode this 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
|
continue; // Not a message we care about
|
||||||
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
||||||
if(!sn)
|
if(!sn)
|
||||||
|
|
|
||||||
|
|
@ -81,11 +81,12 @@ protected:
|
||||||
txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end());
|
txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeviceStatus(const std::shared_ptr<Message>& message) override {
|
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
|
||||||
if(!message || message->data.size() < sizeof(radgigastar_status_t))
|
const auto& data = message->data;
|
||||||
|
if(data.size() < sizeof(radgigastar_status_t))
|
||||||
return;
|
return;
|
||||||
std::lock_guard<std::mutex> lk(ioMutex);
|
std::lock_guard<std::mutex> lk(ioMutex);
|
||||||
const radgigastar_status_t* status = reinterpret_cast<const radgigastar_status_t*>(message->data.data());
|
const radgigastar_status_t* status = reinterpret_cast<const radgigastar_status_t*>(data.data());
|
||||||
ethActivationStatus = status->ethernetActivationLineEnabled;
|
ethActivationStatus = status->ethernetActivationLineEnabled;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public:
|
||||||
if (!fakedev->com->decoder->decode(msg, packet))
|
if (!fakedev->com->decoder->decode(msg, packet))
|
||||||
continue; // We failed to decode this 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
|
continue; // Not a message we care about
|
||||||
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
||||||
if(!sn)
|
if(!sn)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ public:
|
||||||
if(!fakedev->com->decoder->decode(msg, packet))
|
if(!fakedev->com->decoder->decode(msg, packet))
|
||||||
continue; // We failed to decode this 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
|
continue; // Not a message we care about
|
||||||
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
||||||
if(!sn)
|
if(!sn)
|
||||||
|
|
|
||||||
|
|
@ -73,11 +73,12 @@ protected:
|
||||||
|
|
||||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||||
|
|
||||||
void handleDeviceStatus(const std::shared_ptr<Message>& message) override {
|
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
|
||||||
if(!message || message->data.size() < sizeof(valuecan4_2el_status_t))
|
const auto& data = message->data;
|
||||||
|
if(data.size() < sizeof(valuecan4_2el_status_t))
|
||||||
return;
|
return;
|
||||||
std::lock_guard<std::mutex> lk(ioMutex);
|
std::lock_guard<std::mutex> lk(ioMutex);
|
||||||
const valuecan4_2el_status_t* status = reinterpret_cast<const valuecan4_2el_status_t*>(message->data.data());
|
const valuecan4_2el_status_t* status = reinterpret_cast<const valuecan4_2el_status_t*>(data.data());
|
||||||
ethActivationStatus = status->ethernetActivationLineEnabled;
|
ethActivationStatus = status->ethernetActivationLineEnabled;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ public:
|
||||||
if (!fakedev->com->decoder->decode(msg, packet))
|
if (!fakedev->com->decoder->decode(msg, packet))
|
||||||
continue; // We failed to decode this 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
|
continue; // Not a message we care about
|
||||||
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
||||||
if(!sn)
|
if(!sn)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ public:
|
||||||
if (!fakedev->com->decoder->decode(msg, packet))
|
if (!fakedev->com->decoder->decode(msg, packet))
|
||||||
continue; // We failed to decode this 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
|
continue; // Not a message we care about
|
||||||
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
|
||||||
if(!sn)
|
if(!sn)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include "icsneo/communication/message/ethernetmessage.h"
|
#include "icsneo/communication/message/ethernetmessage.h"
|
||||||
#include "icsneo/communication/message/flexray/flexraymessage.h"
|
#include "icsneo/communication/message/flexray/flexraymessage.h"
|
||||||
#include "icsneo/communication/message/iso9141message.h"
|
#include "icsneo/communication/message/iso9141message.h"
|
||||||
|
#include "icsneo/communication/message/canerrorcountmessage.h"
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue