Event refactor builds on Windows
parent
878d9e6dde
commit
50dba62a89
|
|
@ -121,8 +121,8 @@ include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
|||
|
||||
add_library(icsneocpp
|
||||
api/icsneocpp/icsneocpp.cpp
|
||||
api/icsneocpp/error.cpp
|
||||
api/icsneocpp/errormanager.cpp
|
||||
api/icsneocpp/event.cpp
|
||||
api/icsneocpp/eventmanager.cpp
|
||||
api/icsneocpp/version.cpp
|
||||
${SRC_FILES}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ for(size_t i = 0; i < deviceCount; i++) {
|
|||
|
||||
neodevice_t* myDevice = &devices[0];
|
||||
if(!icsneo_openDevice(myDevice)) {
|
||||
neoerror_t error;
|
||||
neoevent_t error;
|
||||
if(icsneo_getLastError(&error))
|
||||
printf("Error! %s\n", error.description);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "icsneo/icsneoc.h"
|
||||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/platform/dynamiclib.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/device/devicefinder.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
@ -28,7 +28,7 @@ void icsneo_findAllDevices(neodevice_t* devices, size_t* count) {
|
|||
std::vector<std::shared_ptr<Device>> foundDevices = icsneo::FindAllDevices();
|
||||
|
||||
if(count == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ void icsneo_findAllDevices(neodevice_t* devices, size_t* count) {
|
|||
*count = foundDevices.size();
|
||||
size_t outputSize = *count;
|
||||
if(outputSize > inputSize) {
|
||||
ErrorManager::GetInstance().add(APIError::OutputTruncated);
|
||||
EventManager::GetInstance().add(APIEvent::Type::OutputTruncated, APIEvent::Severity::EventWarning);
|
||||
outputSize = inputSize;
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ void icsneo_freeUnconnectedDevices() {
|
|||
bool icsneo_serialNumToString(uint32_t num, char* str, size_t* count) {
|
||||
// TAG String copy function
|
||||
if(count == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ bool icsneo_serialNumToString(uint32_t num, char* str, size_t* count) {
|
|||
|
||||
if(*count < result.length()) {
|
||||
*count = result.length() + 1; // This is how big of a buffer we need
|
||||
ErrorManager::GetInstance().add(APIError::BufferInsufficient);
|
||||
EventManager::GetInstance().add(APIEvent::Type::BufferInsufficient, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ uint32_t icsneo_serialStringToNum(const char* str) {
|
|||
bool icsneo_isValidNeoDevice(const neodevice_t* device) {
|
||||
// return false on nullptr
|
||||
if(!device) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
// If this neodevice_t was returned by a previous search, it will no longer be valid (as the underlying icsneo::Device is freed)
|
||||
|
|
@ -102,7 +102,7 @@ bool icsneo_isValidNeoDevice(const neodevice_t* device) {
|
|||
return true;
|
||||
}
|
||||
|
||||
ErrorManager::GetInstance().add(APIError::InvalidNeoDevice);
|
||||
EventManager::GetInstance().add(APIEvent::Type::InvalidNeoDevice, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ bool icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_
|
|||
return false;
|
||||
|
||||
if(items == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ bool icsneo_setPollingMessageLimit(const neodevice_t* device, size_t newLimit) {
|
|||
bool icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLength) {
|
||||
// TAG String copy function
|
||||
if(maxLength == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ bool icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLeng
|
|||
str[*maxLength] = '\0';
|
||||
|
||||
if(output.length() > *maxLength)
|
||||
ErrorManager::GetInstance().add(APIError::OutputTruncated);
|
||||
EventManager::GetInstance().add(APIEvent::Type::OutputTruncated, APIEvent::Severity::EventWarning);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -271,7 +271,7 @@ bool icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLeng
|
|||
bool icsneo_getProductNameForType(devicetype_t type, char* str, size_t* maxLength) {
|
||||
// TAG String copy function
|
||||
if(maxLength == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ bool icsneo_getProductNameForType(devicetype_t type, char* str, size_t* maxLengt
|
|||
str[*maxLength] = '\0';
|
||||
|
||||
if(output.length() > *maxLength)
|
||||
ErrorManager::GetInstance().add(APIError::OutputTruncated);
|
||||
EventManager::GetInstance().add(APIEvent::Type::OutputTruncated, APIEvent::Severity::EventWarning);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -336,13 +336,13 @@ size_t icsneo_settingsReadStructure(const neodevice_t* device, void* structure,
|
|||
if(readSize > structureSize) {
|
||||
// Client application has a smaller structure than we do
|
||||
// It is probably built against an older version of the API
|
||||
ErrorManager::GetInstance().add(APIError::OutputTruncated);
|
||||
EventManager::GetInstance().add(APIEvent::Type::OutputTruncated, APIEvent::Severity::EventWarning);
|
||||
readSize = structureSize;
|
||||
}
|
||||
|
||||
const void* deviceStructure = device->device->settings->getRawStructurePointer();
|
||||
if(deviceStructure == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::SettingsNotAvailable);
|
||||
EventManager::GetInstance().add(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -360,19 +360,19 @@ static bool icsneo_settingsWriteStructure(const neodevice_t* device, const void*
|
|||
return false;
|
||||
|
||||
if(structure == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t writeSize = device->device->settings->getSize();
|
||||
if(writeSize < structureSize) {
|
||||
ErrorManager::GetInstance().add(APIError::OutputTruncated);
|
||||
EventManager::GetInstance().add(APIEvent::Type::OutputTruncated, APIEvent::Severity::EventWarning);
|
||||
structureSize = writeSize;
|
||||
}
|
||||
|
||||
void* deviceStructure = device->device->settings->getMutableRawStructurePointer();
|
||||
if(deviceStructure == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::SettingsNotAvailable);
|
||||
EventManager::GetInstance().add(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +440,7 @@ bool icsneo_transmitMessages(const neodevice_t* device, const neomessage_t* mess
|
|||
bool icsneo_describeDevice(const neodevice_t* device, char* str, size_t* maxLength) {
|
||||
// TAG String copy function
|
||||
if(maxLength == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -453,7 +453,7 @@ bool icsneo_describeDevice(const neodevice_t* device, char* str, size_t* maxLeng
|
|||
str[*maxLength] = '\0';
|
||||
|
||||
if(output.length() > *maxLength)
|
||||
ErrorManager::GetInstance().add(APIError::OutputTruncated);
|
||||
EventManager::GetInstance().add(APIEvent::Type::OutputTruncated, APIEvent::Severity::EventWarning);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -462,88 +462,88 @@ neoversion_t icsneo_getVersion(void) {
|
|||
return icsneo::GetVersion();
|
||||
}
|
||||
|
||||
bool icsneo_getErrors(neoerror_t* errors, size_t* size) {
|
||||
bool icsneo_getEvents(neoevent_t* events, size_t* size) {
|
||||
if(size == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(errors == nullptr) {
|
||||
*size = icsneo::ErrorCount();
|
||||
if(events == nullptr) {
|
||||
*size = icsneo::EventCount();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto cppErrors = icsneo::GetErrors(*size);
|
||||
auto cppErrors = icsneo::GetEvents(*size);
|
||||
for(size_t i = 0; i < cppErrors.size(); i++)
|
||||
memcpy(&errors[i], cppErrors[i].getNeoError(), sizeof(neoerror_t));
|
||||
memcpy(&events[i], cppErrors[i].getNeoEvent(), sizeof(neoevent_t));
|
||||
*size = cppErrors.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool icsneo_getDeviceErrors(const neodevice_t* device, neoerror_t* errors, size_t* size) {
|
||||
bool icsneo_getDeviceEvents(const neodevice_t* device, neoevent_t* events, size_t* size) {
|
||||
if(!icsneo_isValidNeoDevice(device))
|
||||
return false;
|
||||
|
||||
if(size == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Creating the filter will nullptr is okay! It will find any errors not associated with a device.
|
||||
ErrorFilter filter = (device != nullptr ? device->device : nullptr);
|
||||
// Creating the filter will nullptr is okay! It will find any events not associated with a device.
|
||||
EventFilter filter = (device != nullptr ? device->device : nullptr);
|
||||
|
||||
if(errors == nullptr) {
|
||||
*size = icsneo::ErrorCount(filter);
|
||||
if(events == nullptr) {
|
||||
*size = icsneo::EventCount(filter);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto cppErrors = icsneo::GetErrors(*size, filter);
|
||||
auto cppErrors = icsneo::GetEvents(*size, filter);
|
||||
for(size_t i = 0; i < cppErrors.size(); i++)
|
||||
memcpy(&errors[i], cppErrors[i].getNeoError(), sizeof(neoerror_t));
|
||||
memcpy(&events[i], cppErrors[i].getNeoEvent(), sizeof(neoevent_t));
|
||||
*size = cppErrors.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool icsneo_getLastError(neoerror_t* error) {
|
||||
bool icsneo_getLastError(neoevent_t* error) {
|
||||
if(error == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
APIError cppErr;
|
||||
if(!icsneo::GetLastError(cppErr))
|
||||
APIEvent cppErr = icsneo::GetLastError();
|
||||
if(cppErr.getType() == icsneo::APIEvent::Type::NoErrorFound)
|
||||
return false;
|
||||
memcpy(error, cppErr.getNeoError(), sizeof(neoerror_t));
|
||||
memcpy(error, cppErr.getNeoEvent(), sizeof(neoevent_t));
|
||||
return true;
|
||||
}
|
||||
|
||||
void icsneo_discardAllErrors(void) {
|
||||
icsneo::DiscardErrors();
|
||||
void icsneo_discardAllEvents(void) {
|
||||
icsneo::DiscardEvents();
|
||||
}
|
||||
|
||||
void icsneo_discardDeviceErrors(const neodevice_t* device) {
|
||||
void icsneo_discardDeviceEvents(const neodevice_t* device) {
|
||||
if(!icsneo_isValidNeoDevice(device))
|
||||
return;
|
||||
|
||||
if(device == nullptr)
|
||||
icsneo::DiscardErrors(nullptr); // Discard errors not associated with a device
|
||||
icsneo::DiscardEvents(nullptr); // Discard events not associated with a device
|
||||
else
|
||||
icsneo::DiscardErrors(device->device);
|
||||
icsneo::DiscardEvents(device->device);
|
||||
}
|
||||
|
||||
void icsneo_setErrorLimit(size_t newLimit) {
|
||||
icsneo::SetErrorLimit(newLimit);
|
||||
void icsneo_setEventLimit(size_t newLimit) {
|
||||
icsneo::SetEventLimit(newLimit);
|
||||
}
|
||||
|
||||
size_t icsneo_getErrorLimit(void) {
|
||||
return icsneo::GetErrorLimit();
|
||||
size_t icsneo_getEventLimit(void) {
|
||||
return icsneo::GetEventLimit();
|
||||
}
|
||||
|
||||
bool icsneo_getSupportedDevices(devicetype_t* devices, size_t* count) {
|
||||
if(count == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -557,7 +557,7 @@ bool icsneo_getSupportedDevices(devicetype_t* devices, size_t* count) {
|
|||
|
||||
if(*count < len) {
|
||||
len = *count;
|
||||
ErrorManager::GetInstance().add(APIError::OutputTruncated);
|
||||
EventManager::GetInstance().add(APIEvent::Type::OutputTruncated, APIEvent::Severity::EventWarning);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < len; i++)
|
||||
|
|
@ -572,7 +572,7 @@ extern bool DLLExport icsneo_getTimestampResolution(const neodevice_t* device, u
|
|||
return false;
|
||||
|
||||
if(resolution == nullptr) {
|
||||
ErrorManager::GetInstance().add(APIError::RequiredParameterNull);
|
||||
EventManager::GetInstance().add(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,294 +0,0 @@
|
|||
#include "icsneo/api/error.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
APIError::APIError(ErrorType error) : errorStruct({}) {
|
||||
init(error);
|
||||
}
|
||||
|
||||
APIError::APIError(ErrorType error, const Device* forDevice) : errorStruct({}) {
|
||||
device = forDevice;
|
||||
serial = device->getSerial();
|
||||
errorStruct.serial[serial.copy(errorStruct.serial, sizeof(errorStruct.serial))] = '\0';
|
||||
|
||||
init(error);
|
||||
}
|
||||
|
||||
void APIError::init(ErrorType error) {
|
||||
timepoint = ErrorClock::now();
|
||||
errorStruct.description = DescriptionForType(error);
|
||||
errorStruct.errorNumber = (uint32_t)error;
|
||||
errorStruct.severity = (uint8_t)SeverityForType(error);
|
||||
errorStruct.timestamp = ErrorClock::to_time_t(timepoint);
|
||||
}
|
||||
|
||||
std::string APIError::describe() const noexcept {
|
||||
std::stringstream ss;
|
||||
if(device)
|
||||
ss << *device; // Makes use of device.describe()
|
||||
else
|
||||
ss << "API";
|
||||
|
||||
Severity severity = getSeverity();
|
||||
if(severity == Severity::Info) {
|
||||
ss << " Info: ";
|
||||
} else if(severity == Severity::Warning) {
|
||||
ss << " Warning: ";
|
||||
} else if(severity == Severity::Error) {
|
||||
ss << " Error: ";
|
||||
} else {
|
||||
// Should never get here, since Severity::Any should only be used for filtering
|
||||
ss << " Any: ";
|
||||
}
|
||||
|
||||
ss << getDescription();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool APIError::isForDevice(std::string filterSerial) const noexcept {
|
||||
if(!device || filterSerial.length() == 0)
|
||||
return false;
|
||||
return device->getSerial() == filterSerial;
|
||||
}
|
||||
|
||||
// API Errors
|
||||
static constexpr const char* ERROR_INVALID_NEODEVICE = "The provided neodevice_t object was invalid.";
|
||||
static constexpr const char* ERROR_REQUIRED_PARAMETER_NULL = "A required parameter was NULL.";
|
||||
static constexpr const char* ERROR_BUFFER_INSUFFICIENT = "The provided buffer was insufficient. No data was written.";
|
||||
static constexpr const char* ERROR_OUTPUT_TRUNCATED = "The output was too large for the provided buffer and has been truncated.";
|
||||
static constexpr const char* ERROR_PARAMETER_OUT_OF_RANGE = "A parameter was out of range.";
|
||||
static constexpr const char* ERROR_DEVICE_CURRENTLY_OPEN = "The device is currently open. Perhaps a different device state is required.";
|
||||
static constexpr const char* ERROR_DEVICE_CURRENTLY_CLOSED = "The device is currently closed. Perhaps a different device state is required.";
|
||||
static constexpr const char* ERROR_DEVICE_CURRENTLY_ONLINE = "The device is currently online. Perhaps a different device state is required.";
|
||||
static constexpr const char* ERROR_DEVICE_CURRENTLY_OFFLINE = "The device is currently offline. Perhaps a different device state is required.";
|
||||
static constexpr const char* ERROR_DEVICE_CURRENTLY_POLLING = "The device is currently polling for messages. Perhaps a different device state is required.";
|
||||
static constexpr const char* ERROR_DEVICE_NOT_CURRENTLY_POLLING = "The device is not currently polling for messages. Perhaps a different device state is required.";
|
||||
static constexpr const char* ERROR_UNSUPPORTED_TX_NETWORK = "Message network is not a supported TX network.";
|
||||
static constexpr const char* ERROR_MESSAGE_MAX_LENGTH_EXCEEDED = "The message was too long.";
|
||||
|
||||
// Device Errors
|
||||
static constexpr const char* ERROR_POLLING_MESSAGE_OVERFLOW = "Too many messages have been recieved for the polling message buffer, some have been lost!";
|
||||
static constexpr const char* ERROR_NO_SERIAL_NUMBER = "Communication could not be established with the device. Perhaps it is not powered with 12 volts?";
|
||||
static constexpr const char* ERROR_INCORRECT_SERIAL_NUMBER = "The device did not return the expected serial number!";
|
||||
static constexpr const char* ERROR_SETTINGS_READ = "The device settings could not be read.";
|
||||
static constexpr const char* ERROR_SETTINGS_VERSION = "The settings version is incorrect, please update your firmware with neoVI Explorer.";
|
||||
static constexpr const char* ERROR_SETTINGS_LENGTH = "The settings length is incorrect, please update your firmware with neoVI Explorer.";
|
||||
static constexpr const char* ERROR_SETTINGS_CHECKSUM = "The settings checksum is incorrect, attempting to set defaults may remedy this issue.";
|
||||
static constexpr const char* ERROR_SETTINGS_NOT_AVAILABLE = "Settings are not available for this device.";
|
||||
static constexpr const char* ERROR_SETTINGS_READONLY = "Settings are read-only for this device.";
|
||||
static constexpr const char* ERROR_CAN_SETTINGS_NOT_AVAILABLE = "CAN settings are not available for this device.";
|
||||
static constexpr const char* ERROR_CANFD_SETTINGS_NOT_AVAILABLE = "CANFD settings are not available for this device.";
|
||||
static constexpr const char* ERROR_LSFTCAN_SETTINGS_NOT_AVAILABLE = "LSFTCAN settings are not available for this device.";
|
||||
static constexpr const char* ERROR_SWCAN_SETTINGS_NOT_AVAILABLE = "SWCAN settings are not available for this device.";
|
||||
static constexpr const char* ERROR_BAUDRATE_NOT_FOUND = "The baudrate was not found.";
|
||||
static constexpr const char* ERROR_UNEXPECTED_NETWORK_TYPE = "The network type was not found.";
|
||||
static constexpr const char* ERROR_DEVICE_FIRMWARE_OUT_OF_DATE = "The device firmware is out of date. New API functionality may not be supported.";
|
||||
static constexpr const char* ERROR_SETTINGS_STRUCTURE_MISMATCH = "Unexpected settings structure for this device.";
|
||||
static constexpr const char* ERROR_SETTINGS_STRUCTURE_TRUNCATED = "Settings structure is longer than the device supports and will be truncated.";
|
||||
static constexpr const char* ERROR_NO_DEVICE_RESPONSE = "Expected a response from the device but none were found.";
|
||||
static constexpr const char* ERROR_MESSAGE_FORMATTING = "The message was not properly formed.";
|
||||
static constexpr const char* ERROR_CANFD_NOT_SUPPORTED = "This device does not support CANFD.";
|
||||
static constexpr const char* ERROR_RTR_NOT_SUPPORTED = "RTR is not supported with CANFD.";
|
||||
|
||||
// Transport Errors
|
||||
static constexpr const char* ERROR_FAILED_TO_READ = "A read operation failed.";
|
||||
static constexpr const char* ERROR_FAILED_TO_WRITE = "A write operation failed.";
|
||||
static constexpr const char* ERROR_DRIVER_FAILED_TO_OPEN = "The device driver encountered a low-level error while opening the device.";
|
||||
static constexpr const char* ERROR_DRIVER_FAILED_TO_CLOSE = "The device driver encountered a low-level error while closing the device.";
|
||||
static constexpr const char* ERROR_PACKET_CHECKSUM_ERROR = "There was a checksum error while decoding a packet. The packet was dropped.";
|
||||
static constexpr const char* ERROR_TRANSMIT_BUFFER_FULL = "The transmit buffer is full and the device is set to non-blocking.";
|
||||
static constexpr const char* ERROR_PCAP_COULD_NOT_START = "The PCAP driver could not be started. Ethernet devices will not be found.";
|
||||
static constexpr const char* ERROR_PCAP_COULD_NOT_FIND_DEVICES = "The PCAP driver failed to find devices. Ethernet devices will not be found.";
|
||||
static constexpr const char* ERROR_PACKET_DECODING = "The packet could not be decoded.";
|
||||
|
||||
static constexpr const char* ERROR_TOO_MANY_ERRORS = "Too many errors have occurred. The list has been truncated.";
|
||||
static constexpr const char* ERROR_UNKNOWN = "An unknown internal error occurred.";
|
||||
static constexpr const char* ERROR_INVALID = "An invalid internal error occurred.";
|
||||
const char* APIError::DescriptionForType(ErrorType type) {
|
||||
switch(type) {
|
||||
// API Errors
|
||||
case InvalidNeoDevice:
|
||||
return ERROR_INVALID_NEODEVICE;
|
||||
case RequiredParameterNull:
|
||||
return ERROR_REQUIRED_PARAMETER_NULL;
|
||||
case BufferInsufficient:
|
||||
return ERROR_BUFFER_INSUFFICIENT;
|
||||
case OutputTruncated:
|
||||
return ERROR_OUTPUT_TRUNCATED;
|
||||
case ParameterOutOfRange:
|
||||
return ERROR_PARAMETER_OUT_OF_RANGE;
|
||||
case DeviceCurrentlyOpen:
|
||||
return ERROR_DEVICE_CURRENTLY_OPEN;
|
||||
case DeviceCurrentlyClosed:
|
||||
return ERROR_DEVICE_CURRENTLY_CLOSED;
|
||||
case DeviceCurrentlyOnline:
|
||||
return ERROR_DEVICE_CURRENTLY_ONLINE;
|
||||
case DeviceCurrentlyOffline:
|
||||
return ERROR_DEVICE_CURRENTLY_OFFLINE;
|
||||
case DeviceCurrentlyPolling:
|
||||
return ERROR_DEVICE_CURRENTLY_POLLING;
|
||||
case DeviceNotCurrentlyPolling:
|
||||
return ERROR_DEVICE_NOT_CURRENTLY_POLLING;
|
||||
case UnsupportedTXNetwork:
|
||||
return ERROR_UNSUPPORTED_TX_NETWORK;
|
||||
case MessageMaxLengthExceeded:
|
||||
return ERROR_MESSAGE_MAX_LENGTH_EXCEEDED;
|
||||
|
||||
// Device Errors
|
||||
case PollingMessageOverflow:
|
||||
return ERROR_POLLING_MESSAGE_OVERFLOW;
|
||||
case NoSerialNumber:
|
||||
return ERROR_NO_SERIAL_NUMBER;
|
||||
case IncorrectSerialNumber:
|
||||
return ERROR_INCORRECT_SERIAL_NUMBER;
|
||||
case SettingsReadError:
|
||||
return ERROR_SETTINGS_READ;
|
||||
case SettingsVersionError:
|
||||
return ERROR_SETTINGS_VERSION;
|
||||
case SettingsLengthError:
|
||||
return ERROR_SETTINGS_LENGTH;
|
||||
case SettingsChecksumError:
|
||||
return ERROR_SETTINGS_CHECKSUM;
|
||||
case SettingsNotAvailable:
|
||||
return ERROR_SETTINGS_NOT_AVAILABLE;
|
||||
case SettingsReadOnly:
|
||||
return ERROR_SETTINGS_READONLY;
|
||||
case CANSettingsNotAvailable:
|
||||
return ERROR_CAN_SETTINGS_NOT_AVAILABLE;
|
||||
case CANFDSettingsNotAvailable:
|
||||
return ERROR_CANFD_SETTINGS_NOT_AVAILABLE;
|
||||
case LSFTCANSettingsNotAvailable:
|
||||
return ERROR_LSFTCAN_SETTINGS_NOT_AVAILABLE;
|
||||
case SWCANSettingsNotAvailable:
|
||||
return ERROR_SWCAN_SETTINGS_NOT_AVAILABLE;
|
||||
case BaudrateNotFound:
|
||||
return ERROR_BAUDRATE_NOT_FOUND;
|
||||
case UnexpectedNetworkType:
|
||||
return ERROR_UNEXPECTED_NETWORK_TYPE;
|
||||
case DeviceFirmwareOutOfDate:
|
||||
return ERROR_DEVICE_FIRMWARE_OUT_OF_DATE;
|
||||
case SettingsStructureMismatch:
|
||||
return ERROR_SETTINGS_STRUCTURE_MISMATCH;
|
||||
case SettingsStructureTruncated:
|
||||
return ERROR_SETTINGS_STRUCTURE_TRUNCATED;
|
||||
case NoDeviceResponse:
|
||||
return ERROR_NO_DEVICE_RESPONSE;
|
||||
case MessageFormattingError:
|
||||
return ERROR_MESSAGE_FORMATTING;
|
||||
case CANFDNotSupported:
|
||||
return ERROR_CANFD_NOT_SUPPORTED;
|
||||
case RTRNotSupported:
|
||||
return ERROR_RTR_NOT_SUPPORTED;
|
||||
|
||||
// Transport Errors
|
||||
case FailedToRead:
|
||||
return ERROR_FAILED_TO_READ;
|
||||
case FailedToWrite:
|
||||
return ERROR_FAILED_TO_WRITE;
|
||||
case DriverFailedToOpen:
|
||||
return ERROR_DRIVER_FAILED_TO_OPEN;
|
||||
case DriverFailedToClose:
|
||||
return ERROR_DRIVER_FAILED_TO_CLOSE;
|
||||
case PacketChecksumError:
|
||||
return ERROR_PACKET_CHECKSUM_ERROR;
|
||||
case TransmitBufferFull:
|
||||
return ERROR_TRANSMIT_BUFFER_FULL;
|
||||
case PCAPCouldNotStart:
|
||||
return ERROR_PCAP_COULD_NOT_START;
|
||||
case PCAPCouldNotFindDevices:
|
||||
return ERROR_PCAP_COULD_NOT_FIND_DEVICES;
|
||||
case PacketDecodingError:
|
||||
return ERROR_PACKET_DECODING;
|
||||
|
||||
// Other Errors
|
||||
case TooManyErrors:
|
||||
return ERROR_TOO_MANY_ERRORS;
|
||||
case Unknown:
|
||||
return ERROR_UNKNOWN;
|
||||
default:
|
||||
return ERROR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
APIError::Severity APIError::SeverityForType(ErrorType type) {
|
||||
switch(type) {
|
||||
// API Warnings
|
||||
case OutputTruncated:
|
||||
|
||||
// Device Warnings
|
||||
case PollingMessageOverflow:
|
||||
case DeviceFirmwareOutOfDate:
|
||||
case SettingsStructureTruncated:
|
||||
// Transport Warnings
|
||||
case PCAPCouldNotStart:
|
||||
case PCAPCouldNotFindDevices:
|
||||
return Severity::Warning;
|
||||
|
||||
// API Errors
|
||||
case InvalidNeoDevice:
|
||||
case RequiredParameterNull:
|
||||
case BufferInsufficient:
|
||||
case ParameterOutOfRange:
|
||||
case UnsupportedTXNetwork:
|
||||
case MessageMaxLengthExceeded:
|
||||
|
||||
// Device Errors
|
||||
case DeviceCurrentlyOpen:
|
||||
case DeviceCurrentlyClosed:
|
||||
case DeviceCurrentlyOnline:
|
||||
case DeviceCurrentlyOffline:
|
||||
case DeviceCurrentlyPolling:
|
||||
case DeviceNotCurrentlyPolling:
|
||||
case NoSerialNumber:
|
||||
case IncorrectSerialNumber:
|
||||
case SettingsReadError:
|
||||
case SettingsVersionError:
|
||||
case SettingsLengthError:
|
||||
case SettingsChecksumError:
|
||||
case SettingsNotAvailable:
|
||||
case SettingsReadOnly:
|
||||
case CANSettingsNotAvailable:
|
||||
case CANFDSettingsNotAvailable:
|
||||
case LSFTCANSettingsNotAvailable:
|
||||
case SWCANSettingsNotAvailable:
|
||||
case BaudrateNotFound:
|
||||
case UnexpectedNetworkType:
|
||||
case SettingsStructureMismatch:
|
||||
case NoDeviceResponse:
|
||||
case MessageFormattingError:
|
||||
case CANFDNotSupported:
|
||||
case RTRNotSupported:
|
||||
|
||||
// Transport Errors
|
||||
case FailedToRead:
|
||||
case FailedToWrite:
|
||||
case DriverFailedToOpen:
|
||||
case DriverFailedToClose:
|
||||
case PacketChecksumError:
|
||||
case TransmitBufferFull:
|
||||
case PacketDecodingError:
|
||||
// Other Errors
|
||||
case TooManyErrors:
|
||||
case Unknown:
|
||||
default:
|
||||
return Severity::Error;
|
||||
}
|
||||
}
|
||||
|
||||
bool ErrorFilter::match(const APIError& error) const noexcept {
|
||||
if(type != APIError::Any && type != error.getType())
|
||||
return false;
|
||||
|
||||
if(matchOnDevicePtr && !error.isForDevice(device))
|
||||
return false;
|
||||
|
||||
if(severity != APIError::Severity::Any && severity != error.getSeverity())
|
||||
return false;
|
||||
|
||||
if(serial.length() != 0 && !error.isForDevice(serial))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
#include "icsneo/api/errormanager.h"
|
||||
#include <memory>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
static std::unique_ptr<ErrorManager> singleton;
|
||||
|
||||
ErrorManager& ErrorManager::GetInstance() {
|
||||
if(!singleton)
|
||||
singleton = std::unique_ptr<ErrorManager>(new ErrorManager());
|
||||
return *singleton.get();
|
||||
}
|
||||
|
||||
void ErrorManager::get(std::vector<APIError>& errorOutput, size_t max, ErrorFilter filter) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
|
||||
if(max == 0) // A limit of 0 indicates no limit
|
||||
max = (size_t)-1;
|
||||
|
||||
size_t count = 0;
|
||||
errorOutput.clear();
|
||||
auto it = errors.begin();
|
||||
while(it != errors.end()) {
|
||||
if(filter.match(*it)) {
|
||||
errorOutput.push_back(*it);
|
||||
errors.erase(it++);
|
||||
if(count++ >= max)
|
||||
break; // We now have as many written to output as we can
|
||||
} else {
|
||||
std::advance(it, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ErrorManager::getLastError(APIError& errorOutput, ErrorFilter filter) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
|
||||
auto it = errors.rbegin();
|
||||
while(it != errors.rend()) {
|
||||
if(filter.match(*it)) {
|
||||
errorOutput = *it;
|
||||
errors.erase(std::next(it).base());
|
||||
return true;
|
||||
}
|
||||
std::advance(it, 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ErrorManager::getLastError(APIError& errorOutput, std::thread::id id) {
|
||||
auto iter = lastUserErrors.find(id);
|
||||
if(iter == lastUserErrors.end()) {
|
||||
return false;
|
||||
} else {
|
||||
errorOutput = iter->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ErrorManager::discard(ErrorFilter filter) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
errors.remove_if([&filter](const APIError& error) {
|
||||
return filter.match(error);
|
||||
});
|
||||
}
|
||||
|
||||
size_t ErrorManager::count_internal(ErrorFilter filter) const {
|
||||
size_t ret = 0;
|
||||
for(auto& error : errors)
|
||||
if(filter.match(error))
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures errors is always at most errorLimit - 1 in size.
|
||||
* Returns true if any errors were removed in the process of doing so.
|
||||
*/
|
||||
bool ErrorManager::enforceLimit() {
|
||||
// Remove all TooManyErrors before checking
|
||||
errors.remove_if([](icsneo::APIError err){ return err.getType() == icsneo::APIError::TooManyErrors; });
|
||||
|
||||
// We are not overflowing
|
||||
if(errors.size() < errorLimit)
|
||||
return false;
|
||||
|
||||
size_t amountToRemove = errors.size() + 1 - errorLimit;
|
||||
|
||||
discardLeastSevere(amountToRemove);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
APIError::Severity ErrorManager::lowestCurrentSeverity() {
|
||||
if(errors.empty())
|
||||
return APIError::Severity(0);
|
||||
|
||||
APIError::Severity lowest = APIError::Severity::Error;
|
||||
auto it = errors.begin();
|
||||
while(it != errors.end()) {
|
||||
if((*it).getSeverity() < lowest)
|
||||
lowest = (*it).getSeverity();
|
||||
it++;
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
void ErrorManager::discardLeastSevere(size_t count) {
|
||||
if(count == 0)
|
||||
return;
|
||||
|
||||
// Erase needed Info level errors, starting from the beginning
|
||||
ErrorFilter infoFilter(APIError::Severity::Info);
|
||||
auto it = errors.begin();
|
||||
while(it != errors.end()) {
|
||||
if(infoFilter.match(*it)) {
|
||||
errors.erase(it++);
|
||||
if(--count == 0)
|
||||
break;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// Erase needed Warning level errors, starting from the beginning
|
||||
if(count != 0) {
|
||||
ErrorFilter warningFilter(APIError::Severity::Warning);
|
||||
it = errors.begin();
|
||||
while(it != errors.end()) {
|
||||
if(warningFilter.match(*it)) {
|
||||
errors.erase(it++);
|
||||
if(--count == 0)
|
||||
break;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Erase needed Error level errors, starting from the beginning
|
||||
if(count != 0) {
|
||||
ErrorFilter errorFilter(APIError::Severity::Error);
|
||||
it = errors.begin();
|
||||
while(it != errors.end()) {
|
||||
if(errorFilter.match(*it)) {
|
||||
errors.erase(it++);
|
||||
if(--count == 0)
|
||||
break;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
#include "icsneo/api/event.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
APIEvent::APIEvent(Type type, APIEvent::Severity severity, const Device* device) : eventStruct({}) {
|
||||
this->device = device;
|
||||
if(!device) {
|
||||
serial = device->getSerial();
|
||||
eventStruct.serial[serial.copy(eventStruct.serial, sizeof(eventStruct.serial))] = '\0';
|
||||
}
|
||||
|
||||
init(type, severity);
|
||||
}
|
||||
|
||||
void APIEvent::init(Type event, APIEvent::Severity severity) {
|
||||
timepoint = EventClock::now();
|
||||
eventStruct.description = DescriptionForType(event);
|
||||
eventStruct.eventNumber = (uint32_t)event;
|
||||
eventStruct.severity = (uint8_t) severity;
|
||||
eventStruct.timestamp = EventClock::to_time_t(timepoint);
|
||||
}
|
||||
|
||||
std::string APIEvent::describe() const noexcept {
|
||||
std::stringstream ss;
|
||||
if(device)
|
||||
ss << *device; // Makes use of device.describe()
|
||||
else
|
||||
ss << "API";
|
||||
|
||||
Severity severity = getSeverity();
|
||||
if(severity == Severity::EventInfo) {
|
||||
ss << " Info: ";
|
||||
} else if(severity == Severity::EventWarning) {
|
||||
ss << " Warning: ";
|
||||
} else if(severity == Severity::Error) {
|
||||
ss << " Error: ";
|
||||
} else {
|
||||
// Should never get here, since Severity::Any should only be used for filtering
|
||||
ss << " Any: ";
|
||||
}
|
||||
|
||||
ss << getDescription();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool APIEvent::isForDevice(std::string filterSerial) const noexcept {
|
||||
if(!device || filterSerial.length() == 0)
|
||||
return false;
|
||||
return device->getSerial() == filterSerial;
|
||||
}
|
||||
|
||||
// API Errors
|
||||
static constexpr const char* INVALID_NEODEVICE = "The provided neodevice_t object was invalid.";
|
||||
static constexpr const char* REQUIRED_PARAMETER_NULL = "A required parameter was NULL.";
|
||||
static constexpr const char* OUTPUT_TRUNCATED = "The output was too large for the provided buffer and has been truncated.";
|
||||
static constexpr const char* BUFFER_INSUFFICIENT = "The provided buffer was insufficient. No data was written.";
|
||||
static constexpr const char* PARAMETER_OUT_OF_RANGE = "A parameter was out of range.";
|
||||
static constexpr const char* DEVICE_CURRENTLY_OPEN = "The device is currently open.";
|
||||
static constexpr const char* DEVICE_CURRENTLY_CLOSED = "The device is currently closed.";
|
||||
static constexpr const char* DEVICE_CURRENTLY_ONLINE = "The device is currently online.";
|
||||
static constexpr const char* DEVICE_CURRENTLY_OFFLINE = "The device is currently offline.";
|
||||
static constexpr const char* DEVICE_CURRENTLY_POLLING = "The device is currently polling for messages.";
|
||||
static constexpr const char* DEVICE_NOT_CURRENTLY_POLLING = "The device is not currently polling for messages.";
|
||||
static constexpr const char* UNSUPPORTED_TX_NETWORK = "Message network is not a supported TX network.";
|
||||
static constexpr const char* MESSAGE_MAX_LENGTH_EXCEEDED = "The message was too long.";
|
||||
|
||||
// Device Errors
|
||||
static constexpr const char* POLLING_MESSAGE_OVERFLOW = "Too many messages have been recieved for the polling message buffer, some have been lost!";
|
||||
static constexpr const char* NO_SERIAL_NUMBER = "Communication could not be established with the device. Perhaps it is not powered with 12 volts?";
|
||||
static constexpr const char* INCORRECT_SERIAL_NUMBER = "The device did not return the expected serial number!";
|
||||
static constexpr const char* SETTINGS_READ = "The device settings could not be read.";
|
||||
static constexpr const char* SETTINGS_VERSION = "The settings version is incorrect, please update your firmware with neoVI Explorer.";
|
||||
static constexpr const char* SETTINGS_LENGTH = "The settings length is incorrect, please update your firmware with neoVI Explorer.";
|
||||
static constexpr const char* SETTINGS_CHECKSUM = "The settings checksum is incorrect, attempting to set defaults may remedy this issue.";
|
||||
static constexpr const char* SETTINGS_NOT_AVAILABLE = "Settings are not available for this device.";
|
||||
static constexpr const char* SETTINGS_READONLY = "Settings are read-only for this device.";
|
||||
static constexpr const char* CAN_SETTINGS_NOT_AVAILABLE = "CAN settings are not available for this device.";
|
||||
static constexpr const char* CANFD_SETTINGS_NOT_AVAILABLE = "CANFD settings are not available for this device.";
|
||||
static constexpr const char* LSFTCAN_SETTINGS_NOT_AVAILABLE = "LSFTCAN settings are not available for this device.";
|
||||
static constexpr const char* SWCAN_SETTINGS_NOT_AVAILABLE = "SWCAN settings are not available for this device.";
|
||||
static constexpr const char* BAUDRATE_NOT_FOUND = "The baudrate was not found.";
|
||||
static constexpr const char* UNEXPECTED_NETWORK_TYPE = "The network type was not found.";
|
||||
static constexpr const char* DEVICE_FIRMWARE_OUT_OF_DATE = "The device firmware is out of date. New API functionality may not be supported.";
|
||||
static constexpr const char* SETTINGS_STRUCTURE_MISMATCH = "Unexpected settings structure for this device.";
|
||||
static constexpr const char* SETTINGS_STRUCTURE_TRUNCATED = "Settings structure is longer than the device supports and will be truncated.";
|
||||
static constexpr const char* NO_DEVICE_RESPONSE = "Expected a response from the device but none were found.";
|
||||
static constexpr const char* MESSAGE_FORMATTING = "The message was not properly formed.";
|
||||
static constexpr const char* CANFD_NOT_SUPPORTED = "This device does not support CANFD.";
|
||||
static constexpr const char* RTR_NOT_SUPPORTED = "RTR is not supported with CANFD.";
|
||||
|
||||
// Transport Errors
|
||||
static constexpr const char* FAILED_TO_READ = "A read operation failed.";
|
||||
static constexpr const char* FAILED_TO_WRITE = "A write operation failed.";
|
||||
static constexpr const char* DRIVER_FAILED_TO_OPEN = "The device driver encountered a low-level error while opening the device.";
|
||||
static constexpr const char* DRIVER_FAILED_TO_CLOSE = "The device driver encountered a low-level error while closing the device.";
|
||||
static constexpr const char* PACKET_CHECKSUM_ERROR = "There was a checksum error while decoding a packet. The packet was dropped.";
|
||||
static constexpr const char* TRANSMIT_BUFFER_FULL = "The transmit buffer is full and the device is set to non-blocking.";
|
||||
static constexpr const char* PCAP_COULD_NOT_START = "The PCAP driver could not be started. Ethernet devices will not be found.";
|
||||
static constexpr const char* PCAP_COULD_NOT_FIND_DEVICES = "The PCAP driver failed to find devices. Ethernet devices will not be found.";
|
||||
static constexpr const char* PACKET_DECODING = "The packet could not be decoded.";
|
||||
|
||||
static constexpr const char* TOO_MANY_EVENTS = "Too many events have occurred. The list has been truncated.";
|
||||
static constexpr const char* UNKNOWN = "An unknown internal error occurred.";
|
||||
static constexpr const char* INVALID = "An invalid internal error occurred.";
|
||||
const char* APIEvent::DescriptionForType(Type type) {
|
||||
switch(type) {
|
||||
// API Errors
|
||||
case Type::InvalidNeoDevice:
|
||||
return INVALID_NEODEVICE;
|
||||
case Type::RequiredParameterNull:
|
||||
return REQUIRED_PARAMETER_NULL;
|
||||
case Type::BufferInsufficient:
|
||||
return BUFFER_INSUFFICIENT;
|
||||
case Type::OutputTruncated:
|
||||
return OUTPUT_TRUNCATED;
|
||||
case Type::ParameterOutOfRange:
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
case Type::DeviceCurrentlyOpen:
|
||||
return DEVICE_CURRENTLY_OPEN;
|
||||
case Type::DeviceCurrentlyClosed:
|
||||
return DEVICE_CURRENTLY_CLOSED;
|
||||
case Type::DeviceCurrentlyOnline:
|
||||
return DEVICE_CURRENTLY_ONLINE;
|
||||
case Type::DeviceCurrentlyOffline:
|
||||
return DEVICE_CURRENTLY_OFFLINE;
|
||||
case Type::DeviceCurrentlyPolling:
|
||||
return DEVICE_CURRENTLY_POLLING;
|
||||
case Type::DeviceNotCurrentlyPolling:
|
||||
return DEVICE_NOT_CURRENTLY_POLLING;
|
||||
case Type::UnsupportedTXNetwork:
|
||||
return UNSUPPORTED_TX_NETWORK;
|
||||
case Type::MessageMaxLengthExceeded:
|
||||
return MESSAGE_MAX_LENGTH_EXCEEDED;
|
||||
|
||||
// Device Errors
|
||||
case Type::PollingMessageOverflow:
|
||||
return POLLING_MESSAGE_OVERFLOW;
|
||||
case Type::NoSerialNumber:
|
||||
return NO_SERIAL_NUMBER;
|
||||
case Type::IncorrectSerialNumber:
|
||||
return INCORRECT_SERIAL_NUMBER;
|
||||
case Type::SettingsReadError:
|
||||
return SETTINGS_READ;
|
||||
case Type::SettingsVersionError:
|
||||
return SETTINGS_VERSION;
|
||||
case Type::SettingsLengthError:
|
||||
return SETTINGS_LENGTH;
|
||||
case Type::SettingsChecksumError:
|
||||
return SETTINGS_CHECKSUM;
|
||||
case Type::SettingsNotAvailable:
|
||||
return SETTINGS_NOT_AVAILABLE;
|
||||
case Type::SettingsReadOnly:
|
||||
return SETTINGS_READONLY;
|
||||
case Type::CANSettingsNotAvailable:
|
||||
return CAN_SETTINGS_NOT_AVAILABLE;
|
||||
case Type::CANFDSettingsNotAvailable:
|
||||
return CANFD_SETTINGS_NOT_AVAILABLE;
|
||||
case Type::LSFTCANSettingsNotAvailable:
|
||||
return LSFTCAN_SETTINGS_NOT_AVAILABLE;
|
||||
case Type::SWCANSettingsNotAvailable:
|
||||
return SWCAN_SETTINGS_NOT_AVAILABLE;
|
||||
case Type::BaudrateNotFound:
|
||||
return BAUDRATE_NOT_FOUND;
|
||||
case Type::UnexpectedNetworkType:
|
||||
return UNEXPECTED_NETWORK_TYPE;
|
||||
case Type::DeviceFirmwareOutOfDate:
|
||||
return DEVICE_FIRMWARE_OUT_OF_DATE;
|
||||
case Type::SettingsStructureMismatch:
|
||||
return SETTINGS_STRUCTURE_MISMATCH;
|
||||
case Type::SettingsStructureTruncated:
|
||||
return SETTINGS_STRUCTURE_TRUNCATED;
|
||||
case Type::NoDeviceResponse:
|
||||
return NO_DEVICE_RESPONSE;
|
||||
case Type::MessageFormattingError:
|
||||
return MESSAGE_FORMATTING;
|
||||
case Type::CANFDNotSupported:
|
||||
return CANFD_NOT_SUPPORTED;
|
||||
case Type::RTRNotSupported:
|
||||
return RTR_NOT_SUPPORTED;
|
||||
|
||||
// Transport Errors
|
||||
case Type::FailedToRead:
|
||||
return FAILED_TO_READ;
|
||||
case Type::FailedToWrite:
|
||||
return FAILED_TO_WRITE;
|
||||
case Type::DriverFailedToOpen:
|
||||
return DRIVER_FAILED_TO_OPEN;
|
||||
case Type::DriverFailedToClose:
|
||||
return DRIVER_FAILED_TO_CLOSE;
|
||||
case Type::PacketChecksumError:
|
||||
return PACKET_CHECKSUM_ERROR;
|
||||
case Type::TransmitBufferFull:
|
||||
return TRANSMIT_BUFFER_FULL;
|
||||
case Type::PCAPCouldNotStart:
|
||||
return PCAP_COULD_NOT_START;
|
||||
case Type::PCAPCouldNotFindDevices:
|
||||
return PCAP_COULD_NOT_FIND_DEVICES;
|
||||
case Type::PacketDecodingError:
|
||||
return PACKET_DECODING;
|
||||
|
||||
// Other Errors
|
||||
case Type::TooManyEvents:
|
||||
return TOO_MANY_EVENTS;
|
||||
case Type::Unknown:
|
||||
return UNKNOWN;
|
||||
default:
|
||||
return INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventFilter::match(const APIEvent& event) const noexcept {
|
||||
if(type != APIEvent::Type::Any && type != event.getType())
|
||||
return false;
|
||||
|
||||
if(matchOnDevicePtr && !event.isForDevice(device))
|
||||
return false;
|
||||
|
||||
if(severity != APIEvent::Severity::Any && severity != event.getSeverity())
|
||||
return false;
|
||||
|
||||
if(serial.length() != 0 && !event.isForDevice(serial))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
#include "icsneo/api/eventmanager.h"
|
||||
#include <memory>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
static std::unique_ptr<EventManager> singleton;
|
||||
|
||||
EventManager& EventManager::GetInstance() {
|
||||
if(!singleton)
|
||||
singleton = std::unique_ptr<EventManager>(new EventManager());
|
||||
return *singleton.get();
|
||||
}
|
||||
|
||||
void EventManager::get(std::vector<APIEvent>& eventOutput, size_t max, EventFilter filter) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
|
||||
if(max == 0) // A limit of 0 indicates no limit
|
||||
max = (size_t)-1;
|
||||
|
||||
size_t count = 0;
|
||||
eventOutput.clear();
|
||||
auto it = events.begin();
|
||||
while(it != events.end()) {
|
||||
if(filter.match(*it)) {
|
||||
eventOutput.push_back(*it);
|
||||
events.erase(it++);
|
||||
if(count++ >= max)
|
||||
break; // We now have as many written to output as we can
|
||||
} else {
|
||||
std::advance(it, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the returned error from the map
|
||||
* If no error was found, return a default-constructed event
|
||||
*/
|
||||
APIEvent EventManager::getLastError() {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
|
||||
auto it = lastUserErrors.find(std::this_thread::get_id());
|
||||
if(it == lastUserErrors.end()) {
|
||||
return APIEvent(APIEvent::Type::NoErrorFound, APIEvent::Severity::EventInfo);
|
||||
} else {
|
||||
APIEvent ret = it->second;
|
||||
lastUserErrors.erase(it);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::discard(EventFilter filter) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
events.remove_if([&filter](const APIEvent& event) {
|
||||
return filter.match(event);
|
||||
});
|
||||
}
|
||||
|
||||
size_t EventManager::count_internal(EventFilter filter) const {
|
||||
size_t ret = 0;
|
||||
for(auto& event : events)
|
||||
if(filter.match(event))
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures events is always at most eventLimit - 1 in size.
|
||||
* Returns true if any events were removed in the process of doing so.
|
||||
*/
|
||||
bool EventManager::enforceLimit() {
|
||||
// Remove all TooManyEvents before checking
|
||||
events.remove_if([](icsneo::APIEvent err){ return err.getType() == APIEvent::Type::TooManyEvents; });
|
||||
|
||||
// We are not overflowing
|
||||
if(events.size() < eventLimit)
|
||||
return false;
|
||||
|
||||
size_t amountToRemove = events.size() + 1 - eventLimit;
|
||||
|
||||
discardLeastSevere(amountToRemove);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
APIEvent::Severity EventManager::lowestCurrentSeverity() {
|
||||
if(events.empty())
|
||||
return APIEvent::Severity(0);
|
||||
|
||||
APIEvent::Severity lowest = APIEvent::Severity::Error;
|
||||
auto it = events.begin();
|
||||
while(it != events.end()) {
|
||||
if((*it).getSeverity() < lowest)
|
||||
lowest = (*it).getSeverity();
|
||||
it++;
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
void EventManager::discardLeastSevere(size_t count) {
|
||||
if(count == 0)
|
||||
return;
|
||||
|
||||
// Erase needed Info level events, starting from the beginning
|
||||
EventFilter infoFilter(APIEvent::Severity::EventInfo);
|
||||
auto it = events.begin();
|
||||
while(it != events.end()) {
|
||||
if(infoFilter.match(*it)) {
|
||||
events.erase(it++);
|
||||
if(--count == 0)
|
||||
break;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// Erase needed Warning level events, starting from the beginning
|
||||
if(count != 0) {
|
||||
EventFilter warningFilter(APIEvent::Severity::EventWarning);
|
||||
it = events.begin();
|
||||
while(it != events.end()) {
|
||||
if(warningFilter.match(*it)) {
|
||||
events.erase(it++);
|
||||
if(--count == 0)
|
||||
break;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No need to check for Error level events, as they are not stored in the list of events.
|
||||
}
|
||||
|
|
@ -11,38 +11,38 @@ std::vector<DeviceType> icsneo::GetSupportedDevices() {
|
|||
return DeviceFinder::GetSupportedDevices();
|
||||
}
|
||||
|
||||
size_t icsneo::ErrorCount(ErrorFilter filter) {
|
||||
return ErrorManager::GetInstance().count(filter);
|
||||
size_t icsneo::EventCount(EventFilter filter) {
|
||||
return EventManager::GetInstance().count(filter);
|
||||
}
|
||||
|
||||
std::vector<APIError> icsneo::GetErrors(ErrorFilter filter, size_t max) {
|
||||
return ErrorManager::GetInstance().get(filter, max);
|
||||
std::vector<APIEvent> icsneo::GetEvents(EventFilter filter, size_t max) {
|
||||
return EventManager::GetInstance().get(filter, max);
|
||||
}
|
||||
|
||||
std::vector<APIError> icsneo::GetErrors(size_t max, ErrorFilter filter) {
|
||||
return ErrorManager::GetInstance().get(max, filter);
|
||||
std::vector<APIEvent> icsneo::GetEvents(size_t max, EventFilter filter) {
|
||||
return EventManager::GetInstance().get(max, filter);
|
||||
}
|
||||
|
||||
void icsneo::GetErrors(std::vector<APIError>& errors, ErrorFilter filter, size_t max) {
|
||||
ErrorManager::GetInstance().get(errors, filter, max);
|
||||
void icsneo::GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max) {
|
||||
EventManager::GetInstance().get(events, filter, max);
|
||||
}
|
||||
|
||||
void icsneo::GetErrors(std::vector<APIError>& errors, size_t max, ErrorFilter filter) {
|
||||
ErrorManager::GetInstance().get(errors, max, filter);
|
||||
void icsneo::GetEvents(std::vector<APIEvent>& events, size_t max, EventFilter filter) {
|
||||
EventManager::GetInstance().get(events, max, filter);
|
||||
}
|
||||
|
||||
bool icsneo::GetLastError(APIError& error, ErrorFilter filter) {
|
||||
return ErrorManager::GetInstance().getLastError(error, filter);
|
||||
APIEvent icsneo::GetLastError() {
|
||||
return EventManager::GetInstance().getLastError();
|
||||
}
|
||||
|
||||
void icsneo::DiscardErrors(ErrorFilter filter) {
|
||||
ErrorManager::GetInstance().discard(filter);
|
||||
void icsneo::DiscardEvents(EventFilter filter) {
|
||||
EventManager::GetInstance().discard(filter);
|
||||
}
|
||||
|
||||
void icsneo::SetErrorLimit(size_t newLimit) {
|
||||
ErrorManager::GetInstance().setErrorLimit(newLimit);
|
||||
void icsneo::SetEventLimit(size_t newLimit) {
|
||||
EventManager::GetInstance().setEventLimit(newLimit);
|
||||
}
|
||||
|
||||
size_t icsneo::GetErrorLimit() {
|
||||
return ErrorManager::GetInstance().getErrorLimit();
|
||||
size_t icsneo::GetEventLimit() {
|
||||
return EventManager::GetInstance().getEventLimit();
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ int Communication::messageCallbackIDCounter = 1;
|
|||
|
||||
bool Communication::open() {
|
||||
if(isOpen()) {
|
||||
err(APIError::DeviceCurrentlyOpen);
|
||||
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ void Communication::joinThreads() {
|
|||
|
||||
bool Communication::close() {
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -74,12 +74,12 @@ bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::mil
|
|||
|
||||
std::shared_ptr<ReadSettingsMessage> gsmsg = std::dynamic_pointer_cast<ReadSettingsMessage>(msg);
|
||||
if(!gsmsg) {
|
||||
err(APIError::Unknown);
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(gsmsg->response != ReadSettingsMessage::Response::OK) {
|
||||
err(APIError::Unknown);
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ bool Communication::removeMessageCallback(int id) {
|
|||
messageCallbacks.erase(id);
|
||||
return true;
|
||||
} catch(...) {
|
||||
err(APIError::Unknown);
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||
case Network::Type::Ethernet:
|
||||
result = HardwareEthernetPacket::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
err(APIError::PacketDecodingError);
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was not long enough to decode
|
||||
}
|
||||
|
||||
|
|
@ -36,13 +36,13 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
if(packet->data.size() < 24) {
|
||||
err(APIError::PacketDecodingError);
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = HardwareCANPacket::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
err(APIError::PacketDecodingError);
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
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
|
||||
|
|
@ -55,7 +55,7 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||
switch(packet->network.getNetID()) {
|
||||
case Network::NetID::Reset_Status: {
|
||||
if(packet->data.size() < sizeof(HardwareResetStatusPacket)) {
|
||||
err(APIError::PacketDecodingError);
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ bool Encoder::encode(std::vector<uint8_t>& result, const std::shared_ptr<Message
|
|||
case Network::Type::Ethernet: {
|
||||
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(message);
|
||||
if(!ethmsg) {
|
||||
err(APIError::MessageFormattingError);
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed EthernetMessage
|
||||
}
|
||||
|
||||
useResultAsBuffer = true;
|
||||
if(!HardwareEthernetPacket::EncodeFromMessage(*ethmsg, result, err))
|
||||
if(!HardwareEthernetPacket::EncodeFromMessage(*ethmsg, result, report))
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
|
@ -29,17 +29,17 @@ bool Encoder::encode(std::vector<uint8_t>& result, const std::shared_ptr<Message
|
|||
case Network::Type::LSFTCAN: {
|
||||
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
||||
if(!canmsg) {
|
||||
err(APIError::MessageFormattingError);
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed CANMessage
|
||||
}
|
||||
|
||||
if(!supportCANFD && canmsg->isCANFD) {
|
||||
err(APIError::CANFDNotSupported);
|
||||
report(APIEvent::Type::CANFDNotSupported, APIEvent::Severity::Error);
|
||||
return false; // This device does not support CAN FD
|
||||
}
|
||||
|
||||
useResultAsBuffer = true;
|
||||
if(!HardwareCANPacket::EncodeFromMessage(*canmsg, result, err))
|
||||
if(!HardwareCANPacket::EncodeFromMessage(*canmsg, result, report))
|
||||
return false; // The CANMessage was malformed
|
||||
|
||||
break;
|
||||
|
|
@ -75,7 +75,7 @@ bool Encoder::encode(std::vector<uint8_t>& result, const std::shared_ptr<Message
|
|||
break;
|
||||
}
|
||||
default:
|
||||
err(APIError::UnexpectedNetworkType);
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ bool ICommunication::readWait(std::vector<uint8_t>& bytes, std::chrono::millisec
|
|||
|
||||
bool ICommunication::write(const std::vector<uint8_t>& bytes) {
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -50,14 +50,14 @@ bool ICommunication::write(const std::vector<uint8_t>& bytes) {
|
|||
writeCV.wait(lk);
|
||||
} else {
|
||||
if(writeQueue.size_approx() > writeQueueSize) {
|
||||
err(APIError::TransmitBufferFull);
|
||||
report(APIEvent::Type::TransmitBufferFull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = writeQueue.enqueue(WriteOperation(bytes));
|
||||
if(!ret)
|
||||
err(APIError::Unknown);
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ void MultiChannelCommunication::readTask() {
|
|||
for(auto& packet : packetizer->output()) {
|
||||
std::shared_ptr<Message> msg;
|
||||
if(!decoder->decode(msg, packet)) {
|
||||
err(APIError::Unknown); // TODO Use specific error
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error); // TODO Use specific error
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,15 +79,15 @@ std::shared_ptr<CANMessage> HardwareCANPacket::DecodeToMessage(const std::vector
|
|||
return msg;
|
||||
}
|
||||
|
||||
bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& result, const device_errorhandler_t& err) {
|
||||
bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& result, const device_eventhandler_t& report) {
|
||||
if(message.isCANFD && message.isRemote) {
|
||||
err(APIError::RTRNotSupported);
|
||||
report(APIEvent::Type::RTRNotSupported, APIEvent::Severity::Error);
|
||||
return false; // RTR frames can not be used with CAN FD
|
||||
}
|
||||
|
||||
const size_t dataSize = message.data.size();
|
||||
if(dataSize > 64 || (dataSize > 8 && !message.isCANFD)) {
|
||||
err(APIError::MessageMaxLengthExceeded);
|
||||
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
|
||||
return false; // Too much data for the protocol
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector
|
|||
lengthNibble = 0xF;
|
||||
break;
|
||||
default:
|
||||
err(APIError::MessageMaxLengthExceeded);
|
||||
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
|
||||
return false; // CAN FD frame may have had an incorrect byte count
|
||||
}
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector
|
|||
// Next 2-4 bytes are ArbID
|
||||
if(message.isExtended) {
|
||||
if(message.arbid >= 0x20000000) {// Extended messages use 29-bit arb IDs
|
||||
err(APIError::MessageFormattingError);
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -194,7 +194,7 @@ bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector
|
|||
});
|
||||
} else {
|
||||
if(message.arbid >= 0x800) {// Standard messages use 11-bit arb IDs
|
||||
err(APIError::MessageFormattingError);
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
|
|||
return messagePtr;
|
||||
}
|
||||
|
||||
bool HardwareEthernetPacket::EncodeFromMessage(const EthernetMessage& message, std::vector<uint8_t>& bytestream, const device_errorhandler_t&) {
|
||||
bool HardwareEthernetPacket::EncodeFromMessage(const EthernetMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t&) {
|
||||
const size_t unpaddedSize = message.data.size();
|
||||
size_t paddedSize = unpaddedSize;
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ bool Packetizer::input(const std::vector<uint8_t>& inputBytes) {
|
|||
bytes.pop_front();
|
||||
} else {
|
||||
if(gotGoodPackets) // Don't complain unless we've already gotten a good packet, in case we started in the middle of a stream
|
||||
err(APIError::PacketChecksumError);
|
||||
report(APIEvent::Type::PacketChecksumError, APIEvent::Severity::Error);
|
||||
bytes.pop_front(); // Drop the first byte so it doesn't get picked up again
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ std::string Device::describe() const {
|
|||
|
||||
bool Device::enableMessagePolling() {
|
||||
if(isMessagePollingEnabled()) {// We are already polling
|
||||
err(APIError::DeviceCurrentlyPolling);
|
||||
report(APIEvent::Type::DeviceCurrentlyPolling, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
messagePollingCallbackID = com->addMessageCallback(MessageCallback([this](std::shared_ptr<Message> message) {
|
||||
|
|
@ -91,7 +91,7 @@ bool Device::enableMessagePolling() {
|
|||
|
||||
bool Device::disableMessagePolling() {
|
||||
if(!isMessagePollingEnabled()) {
|
||||
err(APIError::DeviceNotCurrentlyPolling);
|
||||
report(APIEvent::Type::DeviceNotCurrentlyPolling, APIEvent::Severity::Error);
|
||||
return false; // Not currently polling
|
||||
}
|
||||
auto ret = com->removeMessageCallback(messagePollingCallbackID);
|
||||
|
|
@ -117,19 +117,19 @@ std::vector<std::shared_ptr<Message>> Device::getMessages() {
|
|||
bool Device::getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit, std::chrono::milliseconds timeout) {
|
||||
// not open
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// not online
|
||||
if(!isOnline()) {
|
||||
err(APIError::DeviceCurrentlyOffline);
|
||||
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// not currently polling, throw error
|
||||
if(!isMessagePollingEnabled()) {
|
||||
err(APIError::DeviceNotCurrentlyPolling);
|
||||
report(APIEvent::Type::DeviceNotCurrentlyPolling, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -159,13 +159,13 @@ void Device::enforcePollingMessageLimit() {
|
|||
while(pollingContainer.size_approx() > pollingMessageLimit) {
|
||||
std::shared_ptr<Message> throwAway;
|
||||
pollingContainer.try_dequeue(throwAway);
|
||||
err(APIError::PollingMessageOverflow);
|
||||
report(APIEvent::Type::PollingMessageOverflow, APIEvent::Severity::EventWarning);
|
||||
}
|
||||
}
|
||||
|
||||
bool Device::open() {
|
||||
if(!com) {
|
||||
err(APIError::Unknown);
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -181,14 +181,14 @@ bool Device::open() {
|
|||
break;
|
||||
}
|
||||
if(!serial) {
|
||||
err(APIError::NoSerialNumber); // Communication could not be established with the device. Perhaps it is not powered with 12 volts?
|
||||
report(APIEvent::Type::NoSerialNumber, APIEvent::Severity::Error); // Communication could not be established with the device. Perhaps it is not powered with 12 volts?
|
||||
com->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string currentSerial = getNeoDevice().serial;
|
||||
if(currentSerial != serial->deviceSerial) {
|
||||
err(APIError::IncorrectSerialNumber);
|
||||
report(APIEvent::Type::IncorrectSerialNumber, APIEvent::Severity::Error);
|
||||
com->close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ bool Device::open() {
|
|||
|
||||
bool Device::close() {
|
||||
if(!com) {
|
||||
err(APIError::Unknown);
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -247,18 +247,18 @@ bool Device::goOffline() {
|
|||
bool Device::transmit(std::shared_ptr<Message> message) {
|
||||
// not open
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// not online
|
||||
if(!isOnline()) {
|
||||
err(APIError::DeviceCurrentlyOffline);
|
||||
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isSupportedTXNetwork(message->network)) {
|
||||
err(APIError::UnsupportedTXNetwork);
|
||||
report(APIEvent::Type::UnsupportedTXNetwork, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ int64_t IDeviceSettings::GetBaudrateValueForEnum(CANBaudrate enumValue) {
|
|||
|
||||
bool IDeviceSettings::refresh(bool ignoreChecksum) {
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -140,12 +140,12 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
|
|||
std::vector<uint8_t> rxSettings;
|
||||
bool ret = com->getSettingsSync(rxSettings);
|
||||
if(!ret) {
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(rxSettings.size() < 6) { // We need to at least have the header of GLOBAL_SETTINGS
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -158,17 +158,17 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
|
|||
rxSettings.erase(rxSettings.begin(), rxSettings.begin() + gs_size);
|
||||
|
||||
if(gs_version != 5) {
|
||||
err(APIError::SettingsVersionError);
|
||||
report(APIEvent::Type::SettingsVersionError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(rxLen != gs_len) {
|
||||
err(APIError::SettingsLengthError);
|
||||
report(APIEvent::Type::SettingsLengthError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ignoreChecksum && gs_chksum != CalculateGSChecksum(rxSettings)) {
|
||||
err(APIError::SettingsChecksumError);
|
||||
report(APIEvent::Type::SettingsChecksumError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -184,17 +184,17 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
|
|||
|
||||
bool IDeviceSettings::apply(bool temporary) {
|
||||
if(readonly) {
|
||||
err(APIError::SettingsReadOnly);
|
||||
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!settingsLoaded) {
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ bool IDeviceSettings::apply(bool temporary) {
|
|||
// Attempt to get the settings from the device so we're up to date if possible
|
||||
if(refresh()) {
|
||||
// refresh succeeded but previously there was an error
|
||||
err(APIError::NoDeviceResponse);
|
||||
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -236,7 +236,7 @@ bool IDeviceSettings::apply(bool temporary) {
|
|||
// Attempt to get the settings from the device so we're up to date if possible
|
||||
if(refresh()) {
|
||||
// refresh succeeded but previously there was an error
|
||||
err(APIError::NoDeviceResponse);
|
||||
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -250,19 +250,19 @@ bool IDeviceSettings::apply(bool temporary) {
|
|||
|
||||
bool ret = (msg && msg->data[0] == 1); // Device sends 0x01 for success
|
||||
if(!ret) {
|
||||
err(APIError::FailedToWrite);
|
||||
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(readonly) {
|
||||
err(APIError::SettingsReadOnly);
|
||||
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +272,7 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
|||
// Attempt to get the settings from the device so we're up to date if possible
|
||||
if(refresh()) {
|
||||
// refresh succeeded but previously there was an error
|
||||
err(APIError::NoDeviceResponse);
|
||||
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -301,7 +301,7 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
|||
// Attempt to get the settings from the device so we're up to date if possible
|
||||
if(refresh()) {
|
||||
// refresh succeeded but previously there was an error
|
||||
err(APIError::NoDeviceResponse);
|
||||
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -315,19 +315,19 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
|||
|
||||
bool ret = (msg && msg->data[0] == 1); // Device sends 0x01 for success
|
||||
if(!ret) {
|
||||
err(APIError::FailedToWrite);
|
||||
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t IDeviceSettings::getBaudrateFor(Network net) const {
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!settingsLoaded) {
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -335,55 +335,55 @@ int64_t IDeviceSettings::getBaudrateFor(Network net) const {
|
|||
case Network::Type::CAN: {
|
||||
const CAN_SETTINGS* cfg = getCANSettingsFor(net);
|
||||
if(cfg == nullptr) {
|
||||
err(APIError::CANFDSettingsNotAvailable);
|
||||
report(APIEvent::Type::CANFDSettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t baudrate = GetBaudrateValueForEnum((CANBaudrate)cfg->Baudrate);
|
||||
if(baudrate == -1) {
|
||||
err(APIError::BaudrateNotFound);
|
||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
return baudrate;
|
||||
}
|
||||
default:
|
||||
err(APIError::UnexpectedNetworkType);
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!settingsLoaded) {
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(readonly) {
|
||||
err(APIError::SettingsReadOnly);
|
||||
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(net.getType()) {
|
||||
case Network::Type::CAN: {
|
||||
if(baudrate > 1000000) { // This is an FD baudrate. Use setFDBaudrateFor instead.
|
||||
err(APIError::CANFDSettingsNotAvailable);
|
||||
report(APIEvent::Type::CANFDSettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
CAN_SETTINGS* cfg = getMutableCANSettingsFor(net);
|
||||
if(cfg == nullptr) {
|
||||
err(APIError::CANSettingsNotAvailable);
|
||||
report(APIEvent::Type::CANSettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
||||
if(newBaud == (CANBaudrate)-1) {
|
||||
err(APIError::BaudrateNotFound);
|
||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
cfg->Baudrate = (uint8_t)newBaud;
|
||||
|
|
@ -394,13 +394,13 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
|
|||
case Network::Type::LSFTCAN: {
|
||||
CAN_SETTINGS* cfg = getMutableLSFTCANSettingsFor(net);
|
||||
if(cfg == nullptr) {
|
||||
err(APIError::LSFTCANSettingsNotAvailable);
|
||||
report(APIEvent::Type::LSFTCANSettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
||||
if(newBaud == (CANBaudrate)-1) {
|
||||
err(APIError::BaudrateNotFound);
|
||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
cfg->Baudrate = (uint8_t)newBaud;
|
||||
|
|
@ -411,13 +411,13 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
|
|||
case Network::Type::SWCAN: {
|
||||
SWCAN_SETTINGS* cfg = getMutableSWCANSettingsFor(net);
|
||||
if(cfg == nullptr) {
|
||||
err(APIError::SWCANSettingsNotAvailable);
|
||||
report(APIEvent::Type::SWCANSettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
||||
if(newBaud == (CANBaudrate)-1) {
|
||||
err(APIError::BaudrateNotFound);
|
||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
cfg->Baudrate = (uint8_t)newBaud;
|
||||
|
|
@ -426,18 +426,18 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
|
|||
return true;
|
||||
}
|
||||
default:
|
||||
err(APIError::UnexpectedNetworkType);
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t IDeviceSettings::getFDBaudrateFor(Network net) const {
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
}
|
||||
|
||||
if(!settingsLoaded) {
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -445,37 +445,37 @@ int64_t IDeviceSettings::getFDBaudrateFor(Network net) const {
|
|||
case Network::Type::CAN: {
|
||||
const CANFD_SETTINGS* cfg = getCANFDSettingsFor(net);
|
||||
if(cfg == nullptr) {
|
||||
err(APIError::CANFDSettingsNotAvailable);
|
||||
report(APIEvent::Type::CANFDSettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t baudrate = GetBaudrateValueForEnum((CANBaudrate)cfg->FDBaudrate);
|
||||
if(baudrate == -1) {
|
||||
err(APIError::BaudrateNotFound);
|
||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return baudrate;
|
||||
}
|
||||
default:
|
||||
err(APIError::UnexpectedNetworkType);
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool IDeviceSettings::setFDBaudrateFor(Network net, int64_t baudrate) {
|
||||
if(!settingsLoaded) {
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(readonly) {
|
||||
err(APIError::SettingsReadOnly);
|
||||
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -483,53 +483,53 @@ bool IDeviceSettings::setFDBaudrateFor(Network net, int64_t baudrate) {
|
|||
case Network::Type::CAN: {
|
||||
CANFD_SETTINGS* cfg = getMutableCANFDSettingsFor(net);
|
||||
if(cfg == nullptr) {
|
||||
err(APIError::CANFDSettingsNotAvailable);
|
||||
report(APIEvent::Type::CANFDSettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
|
||||
if(newBaud == (CANBaudrate)-1) {
|
||||
err(APIError::BaudrateNotFound);
|
||||
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
cfg->FDBaudrate = (uint8_t)newBaud;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
err(APIError::UnexpectedNetworkType);
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure) {
|
||||
if(!settingsLoaded) {
|
||||
err(APIError::SettingsReadError);
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(disabled) {
|
||||
err(APIError::SettingsNotAvailable);
|
||||
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(readonly) {
|
||||
err(APIError::SettingsReadOnly);
|
||||
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) {
|
||||
err(APIError::SettingsStructureMismatch);
|
||||
report(APIEvent::Type::SettingsStructureMismatch, APIEvent::Severity::Error);
|
||||
return false; // The wrong structure was passed in for the current device
|
||||
}
|
||||
size_t copySize = sizeof(T);
|
||||
if(copySize > settings.size()) {
|
||||
err(APIError::SettingsStructureTruncated);
|
||||
report(APIEvent::Type::SettingsStructureTruncated, APIEvent::Severity::EventWarning);
|
||||
copySize = settings.size(); // TODO Warn user that their structure is truncated
|
||||
}
|
||||
// Warn user that the device firmware doesn't support all the settings in the current API
|
||||
if(copySize < settings.size())
|
||||
err(APIError::DeviceFirmwareOutOfDate);
|
||||
report(APIEvent::Type::DeviceFirmwareOutOfDate, APIEvent::Severity::EventWarning);
|
||||
|
||||
memcpy(settings.data(), &newStructure, structSize);
|
||||
return apply();
|
||||
|
|
|
|||
|
|
@ -1,145 +0,0 @@
|
|||
#ifndef __ICSNEO_API_ERRORMANAGER_H_
|
||||
#define __ICSNEO_API_ERRORMANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include "icsneo/api/error.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
typedef std::function<void (APIError::ErrorType)> device_errorhandler_t;
|
||||
|
||||
class ErrorManager {
|
||||
public:
|
||||
static ErrorManager& GetInstance();
|
||||
|
||||
size_t count(ErrorFilter filter = ErrorFilter()) const {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
return count_internal(filter);
|
||||
};
|
||||
|
||||
std::vector<APIError> get(ErrorFilter filter, size_t max = 0) { return get(max, filter); }
|
||||
std::vector<APIError> get(size_t max = 0, ErrorFilter filter = ErrorFilter()) {
|
||||
std::vector<APIError> ret;
|
||||
get(ret, filter, max);
|
||||
return ret;
|
||||
}
|
||||
void get(std::vector<APIError>& outErrors, ErrorFilter filter, size_t max = 0) { get(outErrors, max, filter); }
|
||||
void get(std::vector<APIError>& outErrors, size_t max = 0, ErrorFilter filter = ErrorFilter());
|
||||
bool getLastError(APIError& outErrors, ErrorFilter filter = ErrorFilter());
|
||||
bool getLastError(APIError& errorOutput, std::thread::id id);
|
||||
|
||||
void add(APIError error) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
add_internal(error);
|
||||
}
|
||||
void add(APIError error, std::thread::id id) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
if(id == std::thread::id())
|
||||
add_internal(error);
|
||||
else
|
||||
add_internal_threaded(error, id);
|
||||
}
|
||||
void add(APIError::ErrorType type) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
add_internal(APIError::APIError(type));
|
||||
}
|
||||
void add(APIError::ErrorType type, std::thread::id id) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
if(id == std::thread::id())
|
||||
add_internal(APIError::APIError(type));
|
||||
else
|
||||
add_internal_threaded(APIError::APIError(type), id);
|
||||
|
||||
}
|
||||
void add(APIError::ErrorType type, const Device* forDevice) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
add_internal(APIError::APIError(type, forDevice));
|
||||
}
|
||||
void add(APIError::ErrorType type, const Device* forDevice, std::thread::id id) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
if(id == std::thread::id())
|
||||
add_internal(APIError::APIError(type, forDevice));
|
||||
else
|
||||
add_internal_threaded(APIError::APIError(type, forDevice), id);
|
||||
}
|
||||
|
||||
void discard(ErrorFilter filter = ErrorFilter());
|
||||
|
||||
void setErrorLimit(size_t newLimit) {
|
||||
if(newLimit == errorLimit)
|
||||
return;
|
||||
|
||||
if(newLimit < 10) {
|
||||
add(APIError::ParameterOutOfRange);
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
errorLimit = newLimit;
|
||||
if(enforceLimit())
|
||||
add(APIError::TooManyErrors);
|
||||
}
|
||||
|
||||
size_t getErrorLimit() const { return errorLimit; }
|
||||
|
||||
private:
|
||||
ErrorManager() {}
|
||||
// Used by functions for threadsafety
|
||||
mutable std::mutex mutex;
|
||||
|
||||
// Stores all errors
|
||||
std::list<APIError> errors;
|
||||
std::unordered_map<std::thread::id, APIError> lastUserErrors;
|
||||
size_t errorLimit = 10000;
|
||||
|
||||
size_t count_internal(ErrorFilter filter = ErrorFilter()) const;
|
||||
|
||||
/**
|
||||
* Places a {id, error} pair into the lastUserErrors
|
||||
* If the key id already exists in the map, replace the error of that pair with the new one
|
||||
*/
|
||||
void add_internal_threaded(APIError error, std::thread::id id) {
|
||||
auto iter = lastUserErrors.find(id);
|
||||
if(iter == lastUserErrors.end()) {
|
||||
lastUserErrors.insert(std::make_pair(id, error));
|
||||
} else {
|
||||
iter->second = error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If errors is not full, add the error at the end
|
||||
* Otherwise, remove the least significant errors, push the error to the back and push a APIError::TooManyErrors to the back (in that order)
|
||||
*/
|
||||
void add_internal(APIError error) {
|
||||
// Ensure the error list is at most exactly full (size of errorLimit - 1, leaving room for a potential APIError::TooManyErrors)
|
||||
enforceLimit();
|
||||
|
||||
// We are exactly full, either because the list was truncated or because we were simply full before
|
||||
if(errors.size() == errorLimit - 1) {
|
||||
// If the error is worth adding
|
||||
if(APIError::SeverityForType(error.getType()) >= lowestCurrentSeverity()) {
|
||||
discardLeastSevere(1);
|
||||
errors.push_back(error);
|
||||
}
|
||||
|
||||
errors.push_back(APIError(APIError::TooManyErrors));
|
||||
} else {
|
||||
errors.push_back(error);
|
||||
}
|
||||
}
|
||||
|
||||
bool enforceLimit(); // Returns whether the limit enforcement resulted in an overflow
|
||||
|
||||
APIError::Severity lowestCurrentSeverity();
|
||||
void discardLeastSevere(size_t count = 1);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef __ICSNEO_API_ERROR_H_
|
||||
#define __ICSNEO_API_ERROR_H_
|
||||
#ifndef __ICSNEO_API_EVENT_H_
|
||||
#define __ICSNEO_API_EVENT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
|
@ -7,11 +7,11 @@
|
|||
typedef struct {
|
||||
const char* description;
|
||||
time_t timestamp;
|
||||
uint32_t errorNumber;
|
||||
uint32_t eventNumber;
|
||||
uint8_t severity;
|
||||
char serial[7];
|
||||
uint8_t reserved[16];
|
||||
} neoerror_t;
|
||||
} neoevent_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
|
|
@ -24,19 +24,19 @@ namespace icsneo {
|
|||
|
||||
class Device;
|
||||
|
||||
class APIError {
|
||||
class APIEvent {
|
||||
public:
|
||||
typedef std::chrono::system_clock ErrorClock;
|
||||
typedef std::chrono::time_point<ErrorClock> ErrorTimePoint;
|
||||
typedef std::chrono::system_clock EventClock;
|
||||
typedef std::chrono::time_point<EventClock> EventTimePoint;
|
||||
|
||||
enum ErrorType : uint32_t {
|
||||
enum class Type : uint32_t {
|
||||
Any = 0, // Used for filtering, should not appear in data
|
||||
|
||||
// API Errors
|
||||
InvalidNeoDevice = 0x1000,
|
||||
// API Events
|
||||
InvalidNeoDevice = 0x1000, // api
|
||||
RequiredParameterNull = 0x1001,
|
||||
BufferInsufficient = 0x1002,
|
||||
OutputTruncated = 0x1003,
|
||||
OutputTruncated = 0x1003, // just a warning
|
||||
ParameterOutOfRange = 0x1004,
|
||||
DeviceCurrentlyOpen = 0x1005,
|
||||
DeviceCurrentlyClosed = 0x1006,
|
||||
|
|
@ -47,10 +47,10 @@ public:
|
|||
UnsupportedTXNetwork = 0x1011,
|
||||
MessageMaxLengthExceeded = 0x1012,
|
||||
|
||||
// Device Errors
|
||||
// Device Events
|
||||
PollingMessageOverflow = 0x2000,
|
||||
NoSerialNumber = 0x2001,
|
||||
IncorrectSerialNumber = 0x2002,
|
||||
NoSerialNumber = 0x2001, // api
|
||||
IncorrectSerialNumber = 0x2002, // api
|
||||
SettingsReadError = 0x2003,
|
||||
SettingsVersionError = 0x2004,
|
||||
SettingsLengthError = 0x2005,
|
||||
|
|
@ -71,7 +71,7 @@ public:
|
|||
CANFDNotSupported = 0x2020,
|
||||
RTRNotSupported = 0x2021,
|
||||
|
||||
// Transport Errors
|
||||
// Transport Events
|
||||
FailedToRead = 0x3000,
|
||||
FailedToWrite = 0x3001,
|
||||
DriverFailedToOpen = 0x3002,
|
||||
|
|
@ -81,66 +81,65 @@ public:
|
|||
PCAPCouldNotStart = 0x3102,
|
||||
PCAPCouldNotFindDevices = 0x3103,
|
||||
PacketDecodingError = 0x3104,
|
||||
|
||||
TooManyErrors = 0xFFFFFFFE,
|
||||
|
||||
NoErrorFound = 0xFFFFFFFD,
|
||||
TooManyEvents = 0xFFFFFFFE,
|
||||
Unknown = 0xFFFFFFFF
|
||||
};
|
||||
enum class Severity : uint8_t {
|
||||
Any = 0, // Used for filtering, should not appear in data
|
||||
Info = 0x10,
|
||||
Warning = 0x20,
|
||||
EventInfo = 0x10,
|
||||
EventWarning = 0x20,
|
||||
Error = 0x30
|
||||
};
|
||||
|
||||
APIError() : errorStruct({}), device(nullptr) {}
|
||||
APIError(ErrorType error);
|
||||
APIError(ErrorType error, const Device* device);
|
||||
|
||||
const neoerror_t* getNeoError() const noexcept { return &errorStruct; }
|
||||
ErrorType getType() const noexcept { return ErrorType(errorStruct.errorNumber); }
|
||||
Severity getSeverity() const noexcept { return Severity(errorStruct.severity); }
|
||||
std::string getDescription() const noexcept { return std::string(errorStruct.description); }
|
||||
const Device* getDevice() const noexcept { return device; } // Will return nullptr if this is an API-wide error
|
||||
ErrorTimePoint getTimestamp() const noexcept { return timepoint; }
|
||||
APIEvent() : eventStruct({}), device(nullptr), serial(), timepoint() {}
|
||||
APIEvent(APIEvent::Type event, APIEvent::Severity severity, const Device* device = nullptr);
|
||||
|
||||
const neoevent_t* getNeoEvent() const noexcept { return &eventStruct; }
|
||||
Type getType() const noexcept { return Type(eventStruct.eventNumber); }
|
||||
Severity getSeverity() const noexcept { return Severity(eventStruct.severity); }
|
||||
std::string getDescription() const noexcept { return std::string(eventStruct.description); }
|
||||
const Device* getDevice() const noexcept { return device; } // Will return nullptr if this is an API-wide event
|
||||
EventTimePoint getTimestamp() const noexcept { return timepoint; }
|
||||
|
||||
bool isForDevice(const Device* forDevice) const noexcept { return forDevice == device; }
|
||||
bool isForDevice(std::string serial) const noexcept;
|
||||
|
||||
// As opposed to getDescription, this will also add text such as "neoVI FIRE 2 CY2468 Error: " to fully describe the problem
|
||||
std::string describe() const noexcept;
|
||||
friend std::ostream& operator<<(std::ostream& os, const APIError& error) {
|
||||
os << error.describe();
|
||||
friend std::ostream& operator<<(std::ostream& os, const APIEvent& event) {
|
||||
os << event.describe();
|
||||
return os;
|
||||
}
|
||||
|
||||
static const char* DescriptionForType(ErrorType type);
|
||||
static Severity SeverityForType(ErrorType type);
|
||||
static const char* DescriptionForType(Type type);
|
||||
|
||||
private:
|
||||
neoerror_t errorStruct;
|
||||
neoevent_t eventStruct;
|
||||
std::string serial;
|
||||
ErrorTimePoint timepoint;
|
||||
EventTimePoint timepoint;
|
||||
const Device* device;
|
||||
|
||||
void init(ErrorType error);
|
||||
void init(Type event, APIEvent::Severity);
|
||||
};
|
||||
|
||||
class ErrorFilter {
|
||||
class EventFilter {
|
||||
public:
|
||||
ErrorFilter() {} // Empty filter matches anything
|
||||
ErrorFilter(APIError::ErrorType error) : type(error) {}
|
||||
ErrorFilter(APIError::Severity severity) : severity(severity) {}
|
||||
ErrorFilter(const Device* device, APIError::ErrorType error = APIError::Any) : type(error), matchOnDevicePtr(true), device(device) {}
|
||||
ErrorFilter(const Device* device, APIError::Severity severity) : severity(severity), matchOnDevicePtr(true), device(device) {}
|
||||
ErrorFilter(std::string serial, APIError::ErrorType error = APIError::Any) : type(error), serial(serial) {}
|
||||
ErrorFilter(std::string serial, APIError::Severity severity) : severity(severity), serial(serial) {}
|
||||
EventFilter() {} // Empty filter matches anything
|
||||
EventFilter(APIEvent::Type type) : type(type) {}
|
||||
EventFilter(APIEvent::Severity severity) : severity(severity) {}
|
||||
EventFilter(const Device* device, APIEvent::Type type = APIEvent::Type::Any) : type(type), matchOnDevicePtr(true), device(device) {}
|
||||
EventFilter(const Device* device, APIEvent::Severity severity) : severity(severity), matchOnDevicePtr(true), device(device) {}
|
||||
EventFilter(std::string serial, APIEvent::Type type = APIEvent::Type::Any) : type(type), serial(serial) {}
|
||||
EventFilter(std::string serial, APIEvent::Severity severity) : severity(severity), serial(serial) {}
|
||||
|
||||
bool match(const APIError& error) const noexcept;
|
||||
bool match(const APIEvent& event) const noexcept;
|
||||
|
||||
APIError::Severity severity = APIError::Severity::Any;
|
||||
APIError::ErrorType type = APIError::Any;
|
||||
APIEvent::Type type = APIEvent::Type::Any;
|
||||
APIEvent::Severity severity = APIEvent::Severity::Any;
|
||||
bool matchOnDevicePtr = false;
|
||||
const Device* device = nullptr; // nullptr will match on "no device, generic API error"
|
||||
const Device* device = nullptr; // nullptr will match on "no device, generic API event"
|
||||
std::string serial; // Empty serial will match any, including no device. Not affected by matchOnDevicePtr
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
#ifndef __ICSNEO_API_EVENTMANAGER_H_
|
||||
#define __ICSNEO_API_EVENTMANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include "icsneo/api/event.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
typedef std::function<void (APIEvent::Type, APIEvent::Severity)> device_eventhandler_t;
|
||||
|
||||
class EventManager {
|
||||
public:
|
||||
static EventManager& GetInstance();
|
||||
|
||||
size_t count(EventFilter filter = EventFilter()) const {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
return count_internal(filter);
|
||||
};
|
||||
|
||||
std::vector<APIEvent> get(EventFilter filter, size_t max = 0) { return get(max, filter); }
|
||||
std::vector<APIEvent> get(size_t max = 0, EventFilter filter = EventFilter()) {
|
||||
std::vector<APIEvent> ret;
|
||||
get(ret, filter, max);
|
||||
return ret;
|
||||
}
|
||||
void get(std::vector<APIEvent>& outEvents, EventFilter filter, size_t max = 0) { get(outEvents, max, filter); }
|
||||
void get(std::vector<APIEvent>& outEvents, size_t max = 0, EventFilter filter = EventFilter());
|
||||
|
||||
APIEvent getLastError();
|
||||
|
||||
void add(APIEvent event) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
add_internal(event);
|
||||
}
|
||||
void add(APIEvent::Type type, APIEvent::Severity severity, const Device* forDevice = nullptr) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
add_internal(APIEvent::APIEvent(type, severity, forDevice));
|
||||
}
|
||||
|
||||
void discard(EventFilter filter = EventFilter());
|
||||
|
||||
void setEventLimit(size_t newLimit) {
|
||||
if(newLimit == eventLimit)
|
||||
return;
|
||||
|
||||
if(newLimit < 10) {
|
||||
add(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::EventWarning);
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
eventLimit = newLimit;
|
||||
if(enforceLimit())
|
||||
add(APIEvent::Type::TooManyEvents, APIEvent::Severity::EventWarning);
|
||||
}
|
||||
|
||||
size_t getEventLimit() const { return eventLimit; }
|
||||
|
||||
private:
|
||||
EventManager() {}
|
||||
// Used by functions for threadsafety
|
||||
mutable std::mutex mutex;
|
||||
|
||||
// Stores all events
|
||||
std::list<APIEvent> events;
|
||||
std::unordered_map<std::thread::id, APIEvent> lastUserErrors;
|
||||
size_t eventLimit = 10000;
|
||||
|
||||
size_t count_internal(EventFilter filter = EventFilter()) const;
|
||||
|
||||
void add_internal(APIEvent event) {
|
||||
if(event.getSeverity() == APIEvent::Severity::Error)
|
||||
add_internal_error(event);
|
||||
else
|
||||
add_internal_event(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places a {id, event} pair into the lastUserErrors
|
||||
* If the key id already exists in the map, replace the event of that pair with the new one
|
||||
*/
|
||||
void add_internal_error(APIEvent event) {
|
||||
auto iter = lastUserErrors.find(std::this_thread::get_id());
|
||||
if(iter == lastUserErrors.end())
|
||||
lastUserErrors.insert(std::make_pair(std::this_thread::get_id(), event));
|
||||
else
|
||||
iter->second = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* If events is not full, add the event at the end
|
||||
* Otherwise, remove the least significant events, push the event to the back and push a APIEvent::TooManyEvents to the back (in that order)
|
||||
*/
|
||||
void add_internal_event(APIEvent event) {
|
||||
// Ensure the event list is at most exactly full (size of eventLimit - 1, leaving room for a potential APIEvent::TooManyEvents)
|
||||
enforceLimit();
|
||||
|
||||
// We are exactly full, either because the list was truncated or because we were simply full before
|
||||
if(events.size() == eventLimit - 1) {
|
||||
// If the event is worth adding
|
||||
if(event.getSeverity() >= lowestCurrentSeverity()) {
|
||||
discardLeastSevere(1);
|
||||
events.push_back(event);
|
||||
}
|
||||
|
||||
events.push_back(APIEvent(APIEvent::Type::TooManyEvents, APIEvent::Severity::EventWarning));
|
||||
} else {
|
||||
events.push_back(event);
|
||||
}
|
||||
}
|
||||
|
||||
bool enforceLimit(); // Returns whether the limit enforcement resulted in an overflow
|
||||
|
||||
APIEvent::Severity lowestCurrentSeverity();
|
||||
void discardLeastSevere(size_t count = 1);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
#include "icsneo/communication/packet.h"
|
||||
#include "icsneo/communication/message/callback/messagecallback.h"
|
||||
#include "icsneo/communication/message/serialnumbermessage.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/communication/packetizer.h"
|
||||
#include "icsneo/communication/encoder.h"
|
||||
#include "icsneo/communication/decoder.h"
|
||||
|
|
@ -23,11 +23,11 @@ namespace icsneo {
|
|||
class Communication {
|
||||
public:
|
||||
Communication(
|
||||
device_errorhandler_t err,
|
||||
device_eventhandler_t report,
|
||||
std::unique_ptr<ICommunication> com,
|
||||
std::shared_ptr<Packetizer> p,
|
||||
std::unique_ptr<Encoder> e,
|
||||
std::unique_ptr<Decoder> md) : packetizer(p), encoder(std::move(e)), decoder(std::move(md)), err(err), impl(std::move(com)) {}
|
||||
std::unique_ptr<Decoder> md) : packetizer(p), encoder(std::move(e)), decoder(std::move(md)), report(report), impl(std::move(com)) {}
|
||||
virtual ~Communication() { close(); }
|
||||
|
||||
bool open();
|
||||
|
|
@ -53,7 +53,7 @@ public:
|
|||
std::shared_ptr<Packetizer> packetizer; // Ownership is shared with the encoder
|
||||
std::unique_ptr<Encoder> encoder;
|
||||
std::unique_ptr<Decoder> decoder;
|
||||
device_errorhandler_t err;
|
||||
device_eventhandler_t report;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ICommunication> impl;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include "icsneo/communication/message/canmessage.h"
|
||||
#include "icsneo/communication/packet.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
|
@ -16,13 +16,13 @@ class Decoder {
|
|||
public:
|
||||
static uint64_t GetUInt64FromLEBytes(uint8_t* bytes);
|
||||
|
||||
Decoder(device_errorhandler_t err) : err(err) {}
|
||||
Decoder(device_eventhandler_t report) : report(report) {}
|
||||
bool decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet);
|
||||
|
||||
uint16_t timestampResolution = 25;
|
||||
|
||||
private:
|
||||
device_errorhandler_t err;
|
||||
device_eventhandler_t report;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace icsneo {
|
|||
|
||||
class Encoder {
|
||||
public:
|
||||
Encoder(device_errorhandler_t err, std::shared_ptr<Packetizer> p) : packetizer(p), err(err) {}
|
||||
Encoder(device_eventhandler_t report, std::shared_ptr<Packetizer> p) : packetizer(p), report(report) {}
|
||||
bool encode(std::vector<uint8_t>& result, const std::shared_ptr<Message>& message);
|
||||
bool encode(std::vector<uint8_t>& result, Command cmd, bool boolean) { return encode(result, cmd, std::vector<uint8_t>({ (uint8_t)boolean })); }
|
||||
bool encode(std::vector<uint8_t>& result, Command cmd, std::vector<uint8_t> arguments = {});
|
||||
|
|
@ -23,7 +23,7 @@ public:
|
|||
bool supportCANFD = false;
|
||||
private:
|
||||
std::shared_ptr<Packetizer> packetizer;
|
||||
device_errorhandler_t err;
|
||||
device_eventhandler_t report;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class ICommunication {
|
||||
public:
|
||||
ICommunication(const device_errorhandler_t& handler) : err(handler) {}
|
||||
ICommunication(const device_eventhandler_t& handler) : report(handler) {}
|
||||
virtual ~ICommunication() {}
|
||||
virtual bool open() = 0;
|
||||
virtual bool isOpen() = 0;
|
||||
|
|
@ -27,7 +27,7 @@ public:
|
|||
writeCV.notify_one();
|
||||
}
|
||||
|
||||
device_errorhandler_t err;
|
||||
device_eventhandler_t report;
|
||||
|
||||
size_t writeQueueSize = 50;
|
||||
bool writeBlocks = true; // Otherwise it just fails when the queue is full
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace icsneo {
|
|||
class MultiChannelCommunication : public Communication {
|
||||
public:
|
||||
MultiChannelCommunication(
|
||||
device_errorhandler_t err,
|
||||
device_eventhandler_t err,
|
||||
std::unique_ptr<ICommunication> com,
|
||||
std::shared_ptr<Packetizer> p,
|
||||
std::unique_ptr<Encoder> e,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define __CANPACKET_H__
|
||||
|
||||
#include "icsneo/communication/message/canmessage.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ typedef uint16_t icscm_bitfield;
|
|||
|
||||
struct HardwareCANPacket {
|
||||
static std::shared_ptr<CANMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||
static bool EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& bytestream, const device_errorhandler_t& err);
|
||||
static bool EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
||||
|
||||
struct {
|
||||
icscm_bitfield IDE : 1;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define __ETHERNETPACKET_H__
|
||||
|
||||
#include "icsneo/communication/message/ethernetmessage.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ typedef uint16_t icscm_bitfield;
|
|||
|
||||
struct HardwareEthernetPacket {
|
||||
static std::shared_ptr<EthernetMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||
static bool EncodeFromMessage(const EthernetMessage& message, std::vector<uint8_t>& bytestream, const device_errorhandler_t& err);
|
||||
static bool EncodeFromMessage(const EthernetMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& err);
|
||||
|
||||
struct {
|
||||
icscm_bitfield FCS_AVAIL : 1;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define __PACKETIZER_H_
|
||||
|
||||
#include "icsneo/communication/packet.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
|
@ -13,7 +13,7 @@ class Packetizer {
|
|||
public:
|
||||
static uint8_t ICSChecksum(const std::vector<uint8_t>& data);
|
||||
|
||||
Packetizer(device_errorhandler_t err) : err(err) {}
|
||||
Packetizer(device_eventhandler_t report) : report(report) {}
|
||||
|
||||
std::vector<uint8_t>& packetWrap(std::vector<uint8_t>& data, bool shortFormat);
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ private:
|
|||
|
||||
std::vector<std::shared_ptr<Packet>> processedPackets;
|
||||
|
||||
device_errorhandler_t err;
|
||||
device_eventhandler_t report;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/device/neodevice.h"
|
||||
#include "icsneo/device/idevicesettings.h"
|
||||
#include "icsneo/device/nullsettings.h"
|
||||
|
|
@ -88,7 +88,7 @@ protected:
|
|||
bool online = false;
|
||||
int messagePollingCallbackID = 0;
|
||||
int internalHandlerCallbackID = 0;
|
||||
device_errorhandler_t err;
|
||||
device_eventhandler_t report;
|
||||
|
||||
// START Initialization Functions
|
||||
Device(neodevice_t neodevice = { 0 }) {
|
||||
|
|
@ -98,7 +98,7 @@ protected:
|
|||
|
||||
template<typename Transport, typename Settings = NullSettings>
|
||||
void initialize() {
|
||||
err = makeErrorHandler();
|
||||
report = makeEventHandler();
|
||||
auto transport = makeTransport<Transport>();
|
||||
setupTransport(*transport);
|
||||
auto packetizer = makePacketizer();
|
||||
|
|
@ -115,31 +115,31 @@ protected:
|
|||
setupSupportedTXNetworks(supportedTXNetworks);
|
||||
}
|
||||
|
||||
virtual device_errorhandler_t makeErrorHandler() {
|
||||
return [this](APIError::ErrorType type) {
|
||||
virtual device_eventhandler_t makeEventHandler() {
|
||||
return [this](APIEvent::Type type, APIEvent::Severity severity) {
|
||||
if(!destructing)
|
||||
ErrorManager::GetInstance().add(type, this);
|
||||
EventManager::GetInstance().add(type, severity, this);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Transport>
|
||||
std::unique_ptr<ICommunication> makeTransport() { return std::unique_ptr<ICommunication>(new Transport(err, getWritableNeoDevice())); }
|
||||
std::unique_ptr<ICommunication> makeTransport() { return std::unique_ptr<ICommunication>(new Transport(report, getWritableNeoDevice())); }
|
||||
virtual void setupTransport(ICommunication&) {}
|
||||
|
||||
virtual std::shared_ptr<Packetizer> makePacketizer() { return std::make_shared<Packetizer>(err); }
|
||||
virtual std::shared_ptr<Packetizer> makePacketizer() { return std::make_shared<Packetizer>(report); }
|
||||
virtual void setupPacketizer(Packetizer&) {}
|
||||
|
||||
virtual std::unique_ptr<Encoder> makeEncoder(std::shared_ptr<Packetizer> p) { return std::unique_ptr<Encoder>(new Encoder(err, p)); }
|
||||
virtual std::unique_ptr<Encoder> makeEncoder(std::shared_ptr<Packetizer> p) { return std::unique_ptr<Encoder>(new Encoder(report, p)); }
|
||||
virtual void setupEncoder(Encoder&) {}
|
||||
|
||||
virtual std::unique_ptr<Decoder> makeDecoder() { return std::unique_ptr<Decoder>(new Decoder(err)); }
|
||||
virtual std::unique_ptr<Decoder> makeDecoder() { return std::unique_ptr<Decoder>(new Decoder(report)); }
|
||||
virtual void setupDecoder(Decoder&) {}
|
||||
|
||||
virtual std::shared_ptr<Communication> makeCommunication(
|
||||
std::unique_ptr<ICommunication> t,
|
||||
std::shared_ptr<Packetizer> p,
|
||||
std::unique_ptr<Encoder> e,
|
||||
std::unique_ptr<Decoder> d) { return std::make_shared<Communication>(err, std::move(t), p, std::move(e), std::move(d)); }
|
||||
std::unique_ptr<Decoder> d) { return std::make_shared<Communication>(report, std::move(t), p, std::move(e), std::move(d)); }
|
||||
virtual void setupCommunication(Communication&) {}
|
||||
|
||||
template<typename Settings>
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ public:
|
|||
static CANBaudrate GetEnumValueForBaudrate(int64_t baudrate);
|
||||
static int64_t GetBaudrateValueForEnum(CANBaudrate enumValue);
|
||||
|
||||
IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), err(com->err), structSize(size) {}
|
||||
IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), report(com->report), structSize(size) {}
|
||||
virtual ~IDeviceSettings() {}
|
||||
bool ok() { return !disabled && settingsLoaded; }
|
||||
|
||||
|
|
@ -406,7 +406,7 @@ public:
|
|||
bool disableGSChecksumming = false;
|
||||
protected:
|
||||
std::shared_ptr<Communication> com;
|
||||
device_errorhandler_t err;
|
||||
device_eventhandler_t report;
|
||||
size_t structSize;
|
||||
|
||||
// if we hold any local copies of the device settings
|
||||
|
|
@ -418,7 +418,7 @@ protected:
|
|||
// Parameter createInoperableSettings exists because it is serving as a warning that you probably don't want to do this
|
||||
typedef void* warn_t;
|
||||
IDeviceSettings(warn_t createInoperableSettings, std::shared_ptr<Communication> com)
|
||||
: disabled(true), readonly(true), err(com->err), structSize(0) { (void)createInoperableSettings; }
|
||||
: disabled(true), readonly(true), report(com->report), structSize(0) { (void)createInoperableSettings; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ protected:
|
|||
std::shared_ptr<Packetizer> packetizer,
|
||||
std::unique_ptr<Encoder> encoder,
|
||||
std::unique_ptr<Decoder> decoder
|
||||
) override { return std::make_shared<MultiChannelCommunication>(err, std::move(transport), packetizer, std::move(encoder), std::move(decoder)); }
|
||||
) override { return std::make_shared<MultiChannelCommunication>(report, std::move(transport), packetizer, std::move(encoder), std::move(decoder)); }
|
||||
|
||||
// TODO: This is done so that Plasion can still transmit it's basic networks, awaiting VLAN support
|
||||
virtual bool isSupportedRXNetwork(const Network&) const override { return true; }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "icsneo/platform/dynamiclib.h" // Dynamic library loading and exporting
|
||||
#include "icsneo/communication/network.h" // Network type and netID defines
|
||||
#include "icsneo/api/version.h" // For version info
|
||||
#include "icsneo/api/error.h" // For error info
|
||||
#include "icsneo/api/event.h" // For error info
|
||||
|
||||
#ifndef ICSNEOC_DYNAMICLOAD
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ extern "C" {
|
|||
* To invoke this behavior without finding devices again, call icsneo_freeUnconnectedDevices().
|
||||
*
|
||||
* If the size provided is not large enough, the output will be truncated.
|
||||
* An icsneo::APIError::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* An icsneo::APIEvent::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
*/
|
||||
extern void DLLExport icsneo_findAllDevices(neodevice_t* devices, size_t* count);
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ extern void DLLExport icsneo_freeUnconnectedDevices();
|
|||
*
|
||||
* If the size provided is not large enough, the output will be **NOT** be truncated.
|
||||
* Nothing will be written to the output.
|
||||
* Instead, an icsneo::APIError::BufferInsufficient will be available in icsneo_getLastError().
|
||||
* Instead, an icsneo::APIEvent::BufferInsufficient will be available in icsneo_getLastError().
|
||||
* False will be returned, and `count` will now contain the number of *bytes* necessary to store the full string.
|
||||
*/
|
||||
extern bool DLLExport icsneo_serialNumToString(uint32_t num, char* str, size_t* count);
|
||||
|
|
@ -86,7 +86,7 @@ extern uint32_t DLLExport icsneo_serialStringToNum(const char* str);
|
|||
* \returns True if the neodevice_t is valid.
|
||||
*
|
||||
* This check is automatically performed at the beginning of any API function that operates on a device.
|
||||
* If there is a failure, an icsneo::APIError::InvalidNeoDevice will be available in icsneo_getLastError().
|
||||
* If there is a failure, an icsneo::APIEvent::InvalidNeoDevice will be available in icsneo_getLastError().
|
||||
*
|
||||
* See icsneo_findAllDevices() for information regarding the neodevice_t validity contract.
|
||||
*/
|
||||
|
|
@ -103,7 +103,7 @@ extern bool DLLExport icsneo_isValidNeoDevice(const neodevice_t* device);
|
|||
*
|
||||
* If the open did not succeed, icsneo_getLastError() should provide more information about why.
|
||||
*
|
||||
* If the device was already open, an icsneo::APIError::DeviceCurrentlyOpen will be available in icsneo_getLastError().
|
||||
* If the device was already open, an icsneo::APIEvent::DeviceCurrentlyOpen will be available in icsneo_getLastError().
|
||||
*/
|
||||
extern bool DLLExport icsneo_openDevice(const neodevice_t* device);
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ extern bool DLLExport icsneo_isOnline(const neodevice_t* device);
|
|||
* The client application will have to call icsneo_getMessages() very often to avoid losing messages, or change the limit.
|
||||
*
|
||||
* If the message limit is exceeded before a call to icsneo_getMessages() takes ownership of the messages,
|
||||
* the oldest message will be dropped (**LOST**) and an icsneo::APIError::PollingMessageOverflow will be flagged for the device.
|
||||
* the oldest message will be dropped (**LOST**) and an icsneo::APIEvent::PollingMessageOverflow will be flagged for the device.
|
||||
*
|
||||
* This function will succeed even if the device is not open.
|
||||
*/
|
||||
|
|
@ -280,7 +280,7 @@ extern size_t DLLExport icsneo_getPollingMessageLimit(const neodevice_t* device)
|
|||
* See icsneo_enableMessagePolling() for more information about the message polling system.
|
||||
*
|
||||
* Setting the maximum lower than the current number of stored messages will cause the oldest messages
|
||||
* to be dropped (**LOST**) and an icsneo::APIError::PollingMessageOverflow to be flagged for the device.
|
||||
* to be dropped (**LOST**) and an icsneo::APIEvent::PollingMessageOverflow to be flagged for the device.
|
||||
*/
|
||||
extern bool DLLExport icsneo_setPollingMessageLimit(const neodevice_t* device, size_t newLimit);
|
||||
|
||||
|
|
@ -303,7 +303,7 @@ extern bool DLLExport icsneo_setPollingMessageLimit(const neodevice_t* device, s
|
|||
* icsneo_getLastError() should be checked to verify that the neodevice_t provided was valid.
|
||||
*
|
||||
* If the size provided is not large enough, the output will be truncated.
|
||||
* An icsneo::APIError::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* An icsneo::APIEvent::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* True will still be returned.
|
||||
*/
|
||||
extern bool DLLExport icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLength);
|
||||
|
|
@ -327,7 +327,7 @@ extern bool DLLExport icsneo_getProductName(const neodevice_t* device, char* str
|
|||
* icsneo_getLastError() should be checked to verify that the neodevice_t provided was valid.
|
||||
*
|
||||
* If the size provided is not large enough, the output will be truncated.
|
||||
* An icsneo::APIError::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* An icsneo::APIEvent::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* True will still be returned.
|
||||
*/
|
||||
extern bool DLLExport icsneo_getProductNameForType(devicetype_t type, char* str, size_t* maxLength);
|
||||
|
|
@ -551,7 +551,7 @@ extern bool DLLExport icsneo_transmitMessages(const neodevice_t* device, const n
|
|||
* icsneo_getLastError() should be checked to verify that the neodevice_t provided was valid.
|
||||
*
|
||||
* If the size provided is not large enough, the output will be truncated.
|
||||
* An icsneo::APIError::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* An icsneo::APIEvent::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* True will still be returned.
|
||||
*/
|
||||
extern bool DLLExport icsneo_describeDevice(const neodevice_t* device, char* str, size_t* maxLength);
|
||||
|
|
@ -563,75 +563,82 @@ extern bool DLLExport icsneo_describeDevice(const neodevice_t* device, char* str
|
|||
extern neoversion_t DLLExport icsneo_getVersion(void);
|
||||
|
||||
/**
|
||||
* \brief Read out errors which have occurred in API operation
|
||||
* \param[out] errors A pointer to a buffer which neoerror_t structures will be written to. NULL can be passed, which will write the current error count to size.
|
||||
* \brief Read out events which have occurred in API operation
|
||||
* \param[out] events A pointer to a buffer which neoevent_t structures will be written to. NULL can be passed, which will write the current event count to size.
|
||||
* \param[inout] size A pointer to a size_t which, prior to the call,
|
||||
* holds the maximum number of errors to be written, and after the call holds the number of errors written.
|
||||
* \returns True if the errors were read out successfully (even if there were no errors to report).
|
||||
* holds the maximum number of events to be written, and after the call holds the number of events written.
|
||||
* \returns True if the events were read out successfully (even if there were no events to report).
|
||||
*
|
||||
* Errors can be caused by API usage, such as bad input or operating on a closed neodevice_t.
|
||||
* Events contain INFO and WARNINGS, and may potentially contain one TooManyEvents ERROR at the end. No other ERRORS are found in Events, see icsneo_getLastError() instead.
|
||||
*
|
||||
* Errors can also occur asynchronously to the client application threads, in the case of a device communication error or similar.
|
||||
* Events can be caused by API usage, such as providing too small of a buffer or disconnecting from a device.
|
||||
*
|
||||
* Errors are read out of the API managed buffer in order of oldest to newest.
|
||||
* Events can also occur asynchronously to the client application threads, in the case of a device communication event or similar.
|
||||
*
|
||||
* Events are read out of the API managed buffer in order of oldest to newest.
|
||||
* As they are read out, they are removed from the API managed buffer.
|
||||
*
|
||||
* If size is too small to contain all errors, as many errors as will fit will be read out.
|
||||
* Subsequent calls to icsneo_getErrors() can retrieve any errors which were not read out.
|
||||
* If size is too small to contain all events, as many events as will fit will be read out.
|
||||
* Subsequent calls to icsneo_getErrors() can retrieve any events which were not read out.
|
||||
*/
|
||||
extern bool DLLExport icsneo_getErrors(neoerror_t* errors, size_t* size);
|
||||
extern bool DLLExport icsneo_getEvents(neoevent_t* events, size_t* size);
|
||||
|
||||
/**
|
||||
* \brief Read out errors which have occurred in API operation for a specific device
|
||||
* \param[in] device A pointer to the neodevice_t structure specifying the device to read out errors for. NULL can be passed, which indicates that **ONLY** errors *not* associated with a device are desired (API errors).
|
||||
* \param[out] errors A pointer to a buffer which neoerror_t structures will be written to. NULL can be passed, which will write the current error count to size.
|
||||
* \brief Read out events which have occurred in API operation for a specific device
|
||||
* \param[in] device A pointer to the neodevice_t structure specifying the device to read out events for. NULL can be passed, which indicates that **ONLY** events *not* associated with a device are desired (API events).
|
||||
* \param[out] events A pointer to a buffer which neoevent_t structures will be written to. NULL can be passed, which will write the current event count to size.
|
||||
* \param[inout] size A pointer to a size_t which, prior to the call,
|
||||
* holds the maximum number of errors to be written, and after the call holds the number of errors written.
|
||||
* \returns True if the errors were read out successfully (even if there were no errors to report).
|
||||
* holds the maximum number of events to be written, and after the call holds the number of events written.
|
||||
* \returns True if the events were read out successfully (even if there were no events to report).
|
||||
*
|
||||
* See icsneo_getErrors() for more information about the error system.
|
||||
* See icsneo_getEvents() for more information about the event system.
|
||||
*/
|
||||
extern bool DLLExport icsneo_getDeviceErrors(const neodevice_t* device, neoerror_t* errors, size_t* size);
|
||||
extern bool DLLExport icsneo_getDeviceEvents(const neodevice_t* device, neoevent_t* events, size_t* size);
|
||||
|
||||
/**
|
||||
* \brief Read out the last error which occurred in API operation.
|
||||
* \param[out] error A pointer to a buffer which a neoerror_t structure will be written to.
|
||||
* \brief Read out the last error which occurred in API operation on this thread.
|
||||
* \param[out] error A pointer to a buffer which a neoevent_t structure will be written to.
|
||||
* \returns True if an error was read out.
|
||||
*
|
||||
* See icsneo_getErrors() for more information about the error system.
|
||||
* All errors are stored on a per-thread basis, meaning that calling icsneo_getLastError() will return the last error that occured on the calling thread.
|
||||
* Any errors can only be retrieved through this function, and NOT ics_neo_getEvents() or similar! Only INFO and WARNING level events are accessible through those, with the exception of the
|
||||
* Only the last error is stored, so call this function often!
|
||||
* Calling icsneo_getLastError() will remove the returned error, meaning that subsequent calls to icsneo_getLastError() on the same thread will return false (barring any additional errors)
|
||||
*
|
||||
* See icsneo_getEvents() for more information about the event system.
|
||||
*
|
||||
* This operation removes the returned error from the buffer, so subsequent calls to error functions will not include the error.
|
||||
*/
|
||||
extern bool DLLExport icsneo_getLastError(neoerror_t* error);
|
||||
extern bool DLLExport icsneo_getLastError(neoevent_t* error);
|
||||
|
||||
/**
|
||||
* \brief Discard all errors which have occurred in API operation.
|
||||
*/
|
||||
extern void DLLExport icsneo_discardAllErrors(void);
|
||||
extern void DLLExport icsneo_discardAllEvents(void);
|
||||
|
||||
/**
|
||||
* \brief Discard all errors which have occurred in API operation.
|
||||
* \param[in] device A pointer to the neodevice_t structure specifying the device to discard errors for. NULL can be passed, which indicates that **ONLY** errors *not* associated with a device are desired (API errors).
|
||||
*/
|
||||
extern void DLLExport icsneo_discardDeviceErrors(const neodevice_t* device);
|
||||
extern void DLLExport icsneo_discardDeviceEvents(const neodevice_t* device);
|
||||
|
||||
/**
|
||||
* \brief Set the number of errors which will be held in the API managed buffer before icsneo::APIError::TooManyErrors
|
||||
* \param[in] newLimit The new limit. Must be >10. 1 error slot is always reserved for a potential icsneo::APIError::TooManyErrors, so (newLimit - 1) other errors can be stored.
|
||||
* \brief Set the number of errors which will be held in the API managed buffer before icsneo::APIEvent::TooManyEvents
|
||||
* \param[in] newLimit The new limit. Must be >10. 1 error slot is always reserved for a potential icsneo::APIEvent::TooManyEvents, so (newLimit - 1) other errors can be stored.
|
||||
*
|
||||
* If the error limit is reached, an icsneo::APIError::TooManyErrors will be flagged.
|
||||
* If the error limit is reached, an icsneo::APIEvent::TooManyEvents will be flagged.
|
||||
*
|
||||
* If the `newLimit` is smaller than the current error count,
|
||||
* errors will be removed in order of increasing severity and decreasing age.
|
||||
* This will also flag an icsneo::APIError::TooManyErrors.
|
||||
* This will also flag an icsneo::APIEvent::TooManyEvents.
|
||||
*/
|
||||
extern void DLLExport icsneo_setErrorLimit(size_t newLimit);
|
||||
extern void DLLExport icsneo_setEventLimit(size_t newLimit);
|
||||
|
||||
/**
|
||||
* \brief Get the number of errors which can be held in the API managed buffer
|
||||
* \returns The current limit.
|
||||
*/
|
||||
extern size_t DLLExport icsneo_getErrorLimit(void);
|
||||
extern size_t DLLExport icsneo_getEventLimit(void);
|
||||
|
||||
/**
|
||||
* \brief Get the devices supported by the current version of the API
|
||||
|
|
@ -647,7 +654,7 @@ extern size_t DLLExport icsneo_getErrorLimit(void);
|
|||
* A query for length (`devices == NULL`) will return false.
|
||||
*
|
||||
* If the count provided is not large enough, the output will be truncated.
|
||||
* An icsneo::APIError::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* An icsneo::APIEvent::OutputTruncatedError will be available in icsneo_getLastError() in this case.
|
||||
* True will still be returned.
|
||||
*/
|
||||
extern bool DLLExport icsneo_getSupportedDevices(devicetype_t* devices, size_t* count);
|
||||
|
|
@ -772,13 +779,13 @@ fn_icsneo_describeDevice icsneo_describeDevice;
|
|||
typedef neoversion_t(*fn_icsneo_getVersion)(void);
|
||||
fn_icsneo_getVersion icsneo_getVersion;
|
||||
|
||||
typedef bool(*fn_icsneo_getErrors)(neoerror_t* errors, size_t* size);
|
||||
typedef bool(*fn_icsneo_getErrors)(neoevent_t* errors, size_t* size);
|
||||
fn_icsneo_getErrors icsneo_getErrors;
|
||||
|
||||
typedef bool(*fn_icsneo_getDeviceErrors)(const neodevice_t* device, neoerror_t* errors, size_t* size);
|
||||
typedef bool(*fn_icsneo_getDeviceErrors)(const neodevice_t* device, neoevent_t* errors, size_t* size);
|
||||
fn_icsneo_getDeviceErrors icsneo_getDeviceErrors;
|
||||
|
||||
typedef bool(*fn_icsneo_getLastError)(neoerror_t* error);
|
||||
typedef bool(*fn_icsneo_getLastError)(neoevent_t* error);
|
||||
fn_icsneo_getLastError icsneo_getLastError;
|
||||
|
||||
typedef void(*fn_icsneo_discardAllErrors)(void);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/api/version.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
|
||||
#include "icsneo/communication/message/canmessage.h"
|
||||
#include "icsneo/communication/message/ethernetmessage.h"
|
||||
|
|
@ -16,15 +16,15 @@ namespace icsneo {
|
|||
std::vector<std::shared_ptr<Device>> FindAllDevices();
|
||||
std::vector<DeviceType> GetSupportedDevices();
|
||||
|
||||
size_t ErrorCount(ErrorFilter filter = ErrorFilter());
|
||||
std::vector<APIError> GetErrors(ErrorFilter filter, size_t max = 0);
|
||||
std::vector<APIError> GetErrors(size_t max = 0, ErrorFilter filter = ErrorFilter());
|
||||
void GetErrors(std::vector<APIError>& errors, ErrorFilter filter, size_t max = 0);
|
||||
void GetErrors(std::vector<APIError>& errors, size_t max = 0, ErrorFilter filter = ErrorFilter());
|
||||
bool GetLastError(APIError& error, ErrorFilter filter = ErrorFilter());
|
||||
void DiscardErrors(ErrorFilter filter = ErrorFilter());
|
||||
void SetErrorLimit(size_t newLimit);
|
||||
size_t GetErrorLimit();
|
||||
size_t EventCount(EventFilter filter = EventFilter());
|
||||
std::vector<APIEvent> GetEvents(EventFilter filter, size_t max = 0);
|
||||
std::vector<APIEvent> GetEvents(size_t max = 0, EventFilter filter = EventFilter());
|
||||
void GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max = 0);
|
||||
void GetEvents(std::vector<APIEvent>& events, size_t max = 0, EventFilter filter = EventFilter());
|
||||
APIEvent GetLastError();
|
||||
void DiscardEvents(EventFilter filter = EventFilter());
|
||||
void SetEventLimit(size_t newLimit);
|
||||
size_t GetEventLimit();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ extern int DLLExport icsneoGetDeviceParameters(void* hObject, char* pParameter,
|
|||
extern int DLLExport icsneoSetDeviceParameters(void* hObject, char* pParmValue, int* pErrorIndex, int bSaveToEEPROM);
|
||||
|
||||
//Error Functions
|
||||
extern int DLLExport icsneoGetLastAPIError(void* hObject, unsigned long* pErrorNumber);
|
||||
extern int DLLExport icsneoGetLastAPIEvent(void* hObject, unsigned long* peventNumber);
|
||||
extern int DLLExport icsneoGetErrorMessages(void* hObject, int* pErrorMsgs, int* pNumberOfErrors);
|
||||
extern int DLLExport icsneoGetErrorInfo(int lErrorNumber, TCHAR*szErrorDescriptionShort, TCHAR*szErrorDescriptionLong, int* lMaxLengthShort, int* lMaxLengthLong,int* lErrorSeverity,int* lRestartNeeded);
|
||||
extern int DLLExport icsneoGetErrorInfo(int leventNumber, TCHAR*szErrorDescriptionShort, TCHAR*szErrorDescriptionLong, int* lMaxLengthShort, int* lMaxLengthLong,int* lErrorSeverity,int* lRestartNeeded);
|
||||
|
||||
//ISO15765-2 Functions
|
||||
extern int DLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "icsneo/device/neodevice.h"
|
||||
#include "icsneo/communication/icommunication.h"
|
||||
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ class FTDI : public ICommunication {
|
|||
public:
|
||||
static std::vector<neodevice_t> FindByProduct(int product);
|
||||
|
||||
FTDI(const device_errorhandler_t& err, neodevice_t& forDevice);
|
||||
FTDI(const device_eventhandler_t& err, neodevice_t& forDevice);
|
||||
~FTDI() { close(); }
|
||||
bool open();
|
||||
bool close();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "icsneo/device/neodevice.h"
|
||||
#include "icsneo/communication/icommunication.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <string>
|
||||
#include <pcap.h>
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ public:
|
|||
static std::string GetEthDevSerialFromMacAddress(uint8_t product, uint16_t macSerial);
|
||||
static bool IsHandleValid(neodevice_handle_t handle);
|
||||
|
||||
PCAP(device_errorhandler_t err, neodevice_t& forDevice);
|
||||
PCAP(device_eventhandler_t err, neodevice_t& forDevice);
|
||||
bool open();
|
||||
bool isOpen();
|
||||
bool close();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "icsneo/communication/icommunication.h"
|
||||
#include "icsneo/device/neodevice.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <chrono>
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ namespace icsneo {
|
|||
|
||||
class STM32 : public ICommunication {
|
||||
public:
|
||||
STM32(const device_errorhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {}
|
||||
STM32(const device_eventhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {}
|
||||
static std::vector<neodevice_t> FindByProduct(int product);
|
||||
|
||||
bool open();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace icsneo {
|
|||
|
||||
class FTDI : public VCP {
|
||||
public:
|
||||
FTDI(const device_errorhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
|
||||
FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
|
||||
static std::vector<neodevice_t> FindByProduct(int product) { return VCP::FindByProduct(product, { L"serenum" /*, L"ftdibus" */ }); }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "icsneo/platform/windows/internal/pcapdll.h"
|
||||
#include "icsneo/device/neodevice.h"
|
||||
#include "icsneo/communication/icommunication.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <string>
|
||||
|
||||
namespace icsneo {
|
||||
|
|
@ -21,7 +21,7 @@ public:
|
|||
static std::string GetEthDevSerialFromMacAddress(uint8_t product, uint16_t macSerial);
|
||||
static bool IsHandleValid(neodevice_handle_t handle);
|
||||
|
||||
PCAP(const device_errorhandler_t& err, neodevice_t& forDevice);
|
||||
PCAP(const device_eventhandler_t& err, neodevice_t& forDevice);
|
||||
bool open();
|
||||
bool isOpen();
|
||||
bool close();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace icsneo {
|
|||
|
||||
class STM32 : public VCP {
|
||||
public:
|
||||
STM32(const device_errorhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
|
||||
STM32(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
|
||||
static std::vector<neodevice_t> FindByProduct(int product) { return VCP::FindByProduct(product, { L"usbser" }); }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <Windows.h>
|
||||
#include "icsneo/device/neodevice.h"
|
||||
#include "icsneo/communication/icommunication.h"
|
||||
#include "icsneo/api/errormanager.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ public:
|
|||
static bool IsHandleValid(neodevice_handle_t handle);
|
||||
typedef void(*fn_boolCallback)(bool success);
|
||||
|
||||
VCP(const device_errorhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
overlappedRead.hEvent = INVALID_HANDLE_VALUE;
|
||||
overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
|
||||
overlappedWait.hEvent = INVALID_HANDLE_VALUE;
|
||||
|
|
|
|||
|
|
@ -39,25 +39,25 @@ std::vector<neodevice_t> FTDI::FindByProduct(int product) {
|
|||
return found;
|
||||
}
|
||||
|
||||
FTDI::FTDI(const device_errorhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
FTDI::FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
openable = strlen(forDevice.serial) > 0 && device.handle >= 0 && device.handle < (neodevice_handle_t)handles.size();
|
||||
}
|
||||
|
||||
bool FTDI::open() {
|
||||
if(isOpen()) {
|
||||
err(APIError::DeviceCurrentlyOpen);
|
||||
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!openable) {
|
||||
err(APIError::InvalidNeoDevice);
|
||||
report(APIEvent::Type::InvalidNeoDevice, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// At this point the handle has been checked to be within the bounds of the handles array
|
||||
std::tuple<int, std::string>& handle = handles[device.handle];
|
||||
if(ftdi.openDevice(std::get<0>(handle), std::get<1>(handle).c_str()) != 0) {
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ bool FTDI::open() {
|
|||
|
||||
bool FTDI::close() {
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ bool FTDI::close() {
|
|||
|
||||
bool ret = ftdi.closeDevice();
|
||||
if(ret != 0)
|
||||
err(APIError::DriverFailedToClose);
|
||||
report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error);
|
||||
|
||||
uint8_t flush;
|
||||
WriteOperation flushop;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
|
|||
}
|
||||
|
||||
if(!success) {
|
||||
ErrorManager::GetInstance().add(APIError::PCAPCouldNotFindDevices);
|
||||
EventManager::GetInstance().add(APIEvent::PCAPCouldNotFindDevices);
|
||||
return std::vector<PCAPFoundDevice>();
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) {
|
|||
return (netifIndex < knownInterfaces.size());
|
||||
}
|
||||
|
||||
PCAP::PCAP(device_errorhandler_t err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
PCAP::PCAP(device_eventhandler_t err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
if(IsHandleValid(device.handle)) {
|
||||
interface = knownInterfaces[(device.handle >> 24) & 0xFF];
|
||||
interface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case.
|
||||
|
|
@ -193,7 +193,7 @@ bool PCAP::open() {
|
|||
// Open the interface
|
||||
interface.fp = pcap_open_live(interface.nameFromWinPCAP.c_str(), INT16_MAX, 1, 0, errbuf);
|
||||
if(interface.fp == nullptr) {
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ void PCAP::readTask() {
|
|||
while(!closing) {
|
||||
auto readBytes = pcap_next_ex(interface.fp, &header, &data);
|
||||
if(readBytes < 0) {
|
||||
err(APIError::FailedToRead);
|
||||
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
break;
|
||||
}
|
||||
if(readBytes == 0)
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ std::vector<neodevice_t> STM32::FindByProduct(int product) {
|
|||
|
||||
bool STM32::open() {
|
||||
if(isOpen()) {
|
||||
err(APIError::DeviceCurrentlyOpen);
|
||||
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
std::stringstream ss;
|
||||
|
|
@ -200,7 +200,7 @@ bool STM32::open() {
|
|||
fd = ::open(ss.str().c_str(), O_RDWR | O_NOCTTY | O_SYNC);
|
||||
if(!isOpen()) {
|
||||
//std::cout << "Open of " << ss.str().c_str() << " failed with " << strerror(errno) << ' ';
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ bool STM32::open() {
|
|||
|
||||
if(tcgetattr(fd, &tty) != 0) {
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +232,7 @@ bool STM32::open() {
|
|||
|
||||
if(tcsetattr(fd, TCSAFLUSH, &tty) != 0) { // Flushes input and output buffers as well as setting settings
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ bool STM32::isOpen() {
|
|||
|
||||
bool STM32::close() {
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -279,7 +279,7 @@ bool STM32::close() {
|
|||
if(ret == 0) {
|
||||
return true;
|
||||
} else {
|
||||
err(APIError::DriverFailedToClose);
|
||||
report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -303,7 +303,7 @@ void STM32::writeTask() {
|
|||
const ssize_t writeSize = (ssize_t)writeOp.bytes.size();
|
||||
ssize_t actualWritten = ::write(fd, writeOp.bytes.data(), writeSize);
|
||||
if(actualWritten != writeSize)
|
||||
err(APIError::FailedToWrite);
|
||||
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
||||
onWrite();
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
|
|||
std::vector<PCAPFoundDevice> foundDevices;
|
||||
PCAPDLL pcap;
|
||||
if(!pcap.ok()) {
|
||||
ErrorManager::GetInstance().add(APIError::PCAPCouldNotStart);
|
||||
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotStart, APIEvent::Severity::Error);
|
||||
return std::vector<PCAPFoundDevice>();
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
|
|||
}
|
||||
|
||||
if(!success) {
|
||||
ErrorManager::GetInstance().add(APIError::PCAPCouldNotFindDevices);
|
||||
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
|
||||
return std::vector<PCAPFoundDevice>();
|
||||
}
|
||||
|
||||
|
|
@ -55,13 +55,13 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
|
|||
// Now we're going to ask Win32 for the information as well
|
||||
ULONG size = 0;
|
||||
if(GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &size) != ERROR_BUFFER_OVERFLOW) {
|
||||
ErrorManager::GetInstance().add(APIError::PCAPCouldNotFindDevices);
|
||||
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
|
||||
return std::vector<PCAPFoundDevice>();
|
||||
}
|
||||
std::vector<uint8_t> adapterAddressBuffer;
|
||||
adapterAddressBuffer.resize(size);
|
||||
if(GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, (IP_ADAPTER_ADDRESSES*)adapterAddressBuffer.data(), &size) != ERROR_SUCCESS) {
|
||||
ErrorManager::GetInstance().add(APIError::PCAPCouldNotFindDevices);
|
||||
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
|
||||
return std::vector<PCAPFoundDevice>();
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) {
|
|||
return (netifIndex < knownInterfaces.size());
|
||||
}
|
||||
|
||||
PCAP::PCAP(const device_errorhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
PCAP::PCAP(const device_eventhandler_t& err, neodevice_t& forDevice) : ICommunication(err), device(forDevice) {
|
||||
if(IsHandleValid(device.handle)) {
|
||||
interface = knownInterfaces[(device.handle >> 24) & 0xFF];
|
||||
interface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case.
|
||||
|
|
@ -195,24 +195,24 @@ PCAP::PCAP(const device_errorhandler_t& err, neodevice_t& forDevice) : ICommunic
|
|||
|
||||
bool PCAP::open() {
|
||||
if(!openable) {
|
||||
err(APIError::InvalidNeoDevice);
|
||||
report(APIEvent::Type::InvalidNeoDevice, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!pcap.ok()) {
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isOpen()) {
|
||||
err(APIError::DeviceCurrentlyOpen);
|
||||
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open the interface
|
||||
interface.fp = pcap.open(interface.nameFromWinPCAP.c_str(), 100, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 1, nullptr, errbuf);
|
||||
if(interface.fp == nullptr) {
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ bool PCAP::isOpen() {
|
|||
|
||||
bool PCAP::close() {
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ void PCAP::readTask() {
|
|||
while(!closing) {
|
||||
auto readBytes = pcap.next_ex(interface.fp, &header, &data);
|
||||
if(readBytes < 0) {
|
||||
err(APIError::FailedToRead);
|
||||
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
break;
|
||||
}
|
||||
if(readBytes == 0)
|
||||
|
|
|
|||
|
|
@ -184,12 +184,12 @@ bool VCP::IsHandleValid(neodevice_handle_t handle) {
|
|||
|
||||
bool VCP::open(bool fromAsync) {
|
||||
if(isOpen() || (!fromAsync && opening)) {
|
||||
err(APIError::DeviceCurrentlyOpen);
|
||||
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!IsHandleValid(device.handle)) {
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ bool VCP::open(bool fromAsync) {
|
|||
opening = false;
|
||||
|
||||
if(!isOpen()) {
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ bool VCP::open(bool fromAsync) {
|
|||
COMMTIMEOUTS timeouts;
|
||||
if(!GetCommTimeouts(handle, &timeouts)) {
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ bool VCP::open(bool fromAsync) {
|
|||
|
||||
if(!SetCommTimeouts(handle, &timeouts)) {
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ bool VCP::open(bool fromAsync) {
|
|||
DCB comstate;
|
||||
if(!GetCommState(handle, &comstate)) {
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -252,7 +252,7 @@ bool VCP::open(bool fromAsync) {
|
|||
|
||||
if(!SetCommState(handle, &comstate)) {
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -264,14 +264,14 @@ bool VCP::open(bool fromAsync) {
|
|||
overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
||||
if (overlappedRead.hEvent == nullptr || overlappedWrite.hEvent == nullptr || overlappedWait.hEvent == nullptr) {
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up event so that we will satisfy overlappedWait when a character comes in
|
||||
if(!SetCommMask(handle, EV_RXCHAR)) {
|
||||
close();
|
||||
err(APIError::DriverFailedToOpen);
|
||||
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ void VCP::openAsync(fn_boolCallback callback) {
|
|||
|
||||
bool VCP::close() {
|
||||
if(!isOpen()) {
|
||||
err(APIError::DeviceCurrentlyClosed);
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -304,7 +304,7 @@ bool VCP::close() {
|
|||
closing = false;
|
||||
|
||||
if(!CloseHandle(handle)) {
|
||||
err(APIError::DriverFailedToClose);
|
||||
report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ bool VCP::close() {
|
|||
while(writeQueue.try_dequeue(flushop)) {}
|
||||
|
||||
if(!ret)
|
||||
err(APIError::DriverFailedToClose);
|
||||
report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error);
|
||||
|
||||
// TODO Set up some sort of shared memory, free which COM port we had open so we can try to open it again
|
||||
|
||||
|
|
@ -365,7 +365,7 @@ void VCP::readTask() {
|
|||
if(lastError == ERROR_IO_PENDING)
|
||||
state = WAIT;
|
||||
else if(lastError != ERROR_SUCCESS)
|
||||
err(APIError::FailedToRead);
|
||||
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
}
|
||||
break;
|
||||
case WAIT: {
|
||||
|
|
@ -375,11 +375,11 @@ void VCP::readTask() {
|
|||
readQueue.enqueue_bulk(readbuf, bytesRead);
|
||||
state = LAUNCH;
|
||||
} else
|
||||
err(APIError::FailedToRead);
|
||||
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
}
|
||||
if(ret == WAIT_ABANDONED) {
|
||||
state = LAUNCH;
|
||||
err(APIError::FailedToRead);
|
||||
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -407,19 +407,19 @@ void VCP::writeTask() {
|
|||
state = WAIT;
|
||||
}
|
||||
else
|
||||
err(APIError::FailedToWrite);
|
||||
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
||||
}
|
||||
break;
|
||||
case WAIT: {
|
||||
auto ret = WaitForSingleObject(overlappedWrite.hEvent, 50);
|
||||
if(ret == WAIT_OBJECT_0) {
|
||||
if(!GetOverlappedResult(handle, &overlappedWrite, &bytesWritten, FALSE))
|
||||
err(APIError::FailedToWrite);
|
||||
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
||||
state = LAUNCH;
|
||||
}
|
||||
|
||||
if(ret == WAIT_ABANDONED) {
|
||||
err(APIError::FailedToWrite);
|
||||
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
||||
state = LAUNCH;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue