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.
This commit is contained in:
Paul Hollinsky
2021-05-22 01:58:36 -04:00
parent 21e93d1f73
commit 21bc4eeff2
48 changed files with 853 additions and 527 deletions
+38 -33
View File
@@ -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) {
// not open
if(!isOpen()) {
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
return false;
}
// not online
if(!isOnline()) {
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
return false;
}
// not currently polling, throw error
if(!isMessagePollingEnabled()) {
report(APIEvent::Type::DeviceNotCurrentlyPolling, APIEvent::Severity::Error);
return false;
@@ -285,7 +282,7 @@ APIEvent::Type Device::attemptToBeginCommunication() {
}
if(!serial) // "Communication could not be established with the device. Perhaps it is not powered with 12 volts?"
return getCommunicationNotEstablishedError();
std::string currentSerial = getNeoDevice().serial;
if(currentSerial != serial->deviceSerial)
return APIEvent::Type::IncorrectSerialNumber;
@@ -309,7 +306,7 @@ bool Device::close() {
if(isOnline())
goOffline();
if(internalHandlerCallbackID)
com->removeMessageCallback(internalHandlerCallbackID);
@@ -352,7 +349,7 @@ bool Device::goOnline() {
if(failOut)
return false;
}
online = true;
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
@@ -373,9 +370,9 @@ bool Device::goOffline() {
auto startTime = std::chrono::system_clock::now();
ledState = (latestResetStatus && latestResetStatus->cmRunning) ? LEDState::CoreMiniRunning : LEDState::Offline;
updateLEDState();
MessageFilter filter(Network::NetID::Reset_Status);
filter.includeInternalInAny = true;
@@ -383,32 +380,30 @@ bool Device::goOffline() {
while((std::chrono::system_clock::now() - startTime) < std::chrono::seconds(5)) {
if(latestResetStatus && !latestResetStatus->comEnabled)
break;
if(!com->sendCommand(Command::RequestStatusUpdate))
return false;
com->waitForMessageSync(filter, std::chrono::milliseconds(100));
}
online = false;
return true;
}
bool Device::transmit(std::shared_ptr<Message> message) {
// not open
bool Device::transmit(std::shared_ptr<Frame> frame) {
if(!isOpen()) {
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
return false;
}
// not online
if(!isOnline()) {
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
return false;
}
if(!isSupportedTXNetwork(message->network)) {
if(!isSupportedTXNetwork(frame->network)) {
report(APIEvent::Type::UnsupportedTXNetwork, APIEvent::Severity::Error);
return false;
}
@@ -416,7 +411,7 @@ bool Device::transmit(std::shared_ptr<Message> message) {
bool extensionHookedTransmit = false;
bool transmitStatusFromExtension = false;
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
if(!ext->transmitHook(message, transmitStatusFromExtension))
if(!ext->transmitHook(frame, transmitStatusFromExtension))
extensionHookedTransmit = true;
return !extensionHookedTransmit; // false breaks out of the loop early
});
@@ -424,15 +419,15 @@ bool Device::transmit(std::shared_ptr<Message> message) {
return transmitStatusFromExtension;
std::vector<uint8_t> packet;
if(!com->encoder->encode(*com->packetizer, packet, message))
if(!com->encoder->encode(*com->packetizer, packet, frame))
return false;
return com->sendPacket(packet);
}
bool Device::transmit(std::vector<std::shared_ptr<Message>> messages) {
for(auto& message : messages) {
if(!transmit(message))
bool Device::transmit(std::vector<std::shared_ptr<Frame>> frames) {
for(auto& frame : frames) {
if(!transmit(frame))
return false;
}
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) {
switch(message->network.getNetID()) {
case Network::NetID::Reset_Status:
latestResetStatus = std::dynamic_pointer_cast<ResetStatusMessage>(message);
switch(message->type) {
case Message::Type::ResetStatus:
latestResetStatus = std::static_pointer_cast<ResetStatusMessage>(message);
break;
case Network::NetID::Device: {
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
if(canmsg)
handleNeoVIMessage(std::move(canmsg));
case Message::Type::RawMessage: {
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
switch(rawMessage->network.getNetID()) {
case Network::NetID::Device: {
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
// if it couldn't be decoded to a CANMessage. We only care about the
// CANMessage decoding right now.
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
if(canmsg)
handleNeoVIMessage(std::move(canmsg));
break;
}
case Network::NetID::DeviceStatus:
// Device Status format is unique per device, so the devices need to decode it themselves
handleDeviceStatus(rawMessage);
break;
default:
break; //std::cout << "HandleInternalMessage got a message from " << message->network << " and it was unhandled!" << std::endl;
}
break;
}
case Network::NetID::DeviceStatus:
// Device Status format is unique per device, so the devices need to decode it themselves
handleDeviceStatus(message);
break;
default:
break; //std::cout << "HandleInternalMessage got a message from " << message->network << " and it was unhandled!" << std::endl;
default: break;
}
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
ext->handleMessage(message);
+9 -11
View File
@@ -26,18 +26,16 @@ void FlexRay::Extension::onGoOffline() {
}
void FlexRay::Extension::handleMessage(const std::shared_ptr<Message>& message) {
switch(message->network.getNetID()) {
case Network::NetID::FlexRayControl: {
switch(message->type) {
case Message::Type::FlexRayControl: {
auto msg = std::dynamic_pointer_cast<FlexRayControlMessage>(message);
if(!msg || !msg->decoded)
return;
switch(msg->opcode) {
case FlexRay::Opcode::ReadCCStatus:
if(auto status = std::dynamic_pointer_cast<FlexRayControlMessage>(message)) { // TODO else report error?
if(status->controller >= controllers.size())
return; // TODO error
controllers[status->controller]->_setStatus(status);
}
if(msg->controller >= controllers.size())
return; // TODO error
controllers[msg->controller]->_setStatus(msg);
break;
}
break;
@@ -47,18 +45,18 @@ void FlexRay::Extension::handleMessage(const std::shared_ptr<Message>& message)
}
}
bool FlexRay::Extension::transmitHook(const std::shared_ptr<Message>& message, bool& success) {
if(!message || message->network.getType() != Network::Type::FlexRay)
bool FlexRay::Extension::transmitHook(const std::shared_ptr<Frame>& frame, bool& success) {
if(!frame || frame->network.getType() != Network::Type::FlexRay)
return true; // Don't hook non-FlexRay messages
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)
return false;
for(auto& controller : controllers) {
if(controller->getNetwork() != message->network)
if(controller->getNetwork() != frame->network)
continue;
success |= controller->transmit(frmsg);
}
+21 -21
View File
@@ -17,7 +17,7 @@ optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_
for (int i = 0; i < 16; i++) {
bool iBit = temp & 1;
int iCrcNxt;
//CRCNXT = NXTBIT EXOR CRC_RG(15);
if (gsCrc & (1 << 15))
@@ -187,7 +187,7 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
settingsLoaded = true;
// TODO Warn user that their API version differs from the device firmware version
//if(settings.size() != structSize)
//if(settings.size() != structSize)
return settingsLoaded;
}
@@ -227,10 +227,10 @@ bool IDeviceSettings::apply(bool temporary) {
// Pause I/O with the device while the settings are applied
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);
}, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000));
}, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000)));
if(!msg || msg->data[0] != 1) { // We did not receive a response
// Attempt to get the settings from the device so we're up to date if possible
@@ -254,9 +254,9 @@ bool IDeviceSettings::apply(bool temporary) {
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
msg = com->waitForMessageSync([this, &bytestream]() {
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream);
}, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000));
}, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000)));
if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible
if(refresh()) {
@@ -267,11 +267,11 @@ bool IDeviceSettings::apply(bool temporary) {
}
if(!temporary) {
msg = com->waitForMessageSync([this]() {
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return com->sendCommand(Command::SaveSettings);
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000));
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000)));
}
applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
@@ -296,9 +296,9 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
applyingSettings = true;
std::shared_ptr<Message> msg = com->waitForMessageSync([this]() {
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return com->sendCommand(Command::SetDefaultSettings);
}, Main51MessageFilter(Command::SetDefaultSettings), std::chrono::milliseconds(1000));
}, Main51MessageFilter(Command::SetDefaultSettings), std::chrono::milliseconds(1000)));
if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible
if(refresh()) {
@@ -331,9 +331,9 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
msg = com->waitForMessageSync([this, &bytestream]() {
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream);
}, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000));
}, Main51MessageFilter(Command::SetSettings), std::chrono::milliseconds(1000)));
if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible
if(refresh()) {
@@ -344,13 +344,13 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
}
if(!temporary) {
msg = com->waitForMessageSync([this]() {
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return com->sendCommand(Command::SaveSettings);
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000));
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000)));
}
applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
bool ret = (msg && msg->data[0] == 1); // Device sends 0x01 for success
@@ -420,7 +420,7 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
report(APIEvent::Type::CANSettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
if(newBaud == (CANBaudrate)-1) {
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
@@ -437,7 +437,7 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
report(APIEvent::Type::LSFTCANSettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
if(newBaud == (CANBaudrate)-1) {
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
@@ -454,7 +454,7 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
report(APIEvent::Type::SWCANSettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
if(newBaud == (CANBaudrate)-1) {
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
@@ -691,7 +691,7 @@ template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure)
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
return false;
}
// This function is only called from C++ so the caller's structure size and ours should never differ
if(sizeof(T) != structSize) {
report(APIEvent::Type::SettingsStructureMismatch, APIEvent::Severity::Error);