Event refactor builds on Windows

This commit is contained in:
EricLiu2000
2019-06-24 17:59:45 -04:00
parent 878d9e6dde
commit 50dba62a89
47 changed files with 848 additions and 951 deletions
-145
View File
@@ -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
};
+125
View File
@@ -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
+4 -4
View File
@@ -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;
+3 -3
View File
@@ -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)
+2 -2
View File
@@ -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;
+3 -3
View File
@@ -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;
};
}
+11 -11
View File
@@ -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>
+3 -3
View File
@@ -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; }
};
}
+1 -1
View File
@@ -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; }
+50 -43
View File
@@ -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);
+10 -10
View File
@@ -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();
}
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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();
+2 -2
View File
@@ -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();
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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" */ }); }
};
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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" }); }
};
+2 -2
View File
@@ -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;