#ifndef __DEVICE_H__ #define __DEVICE_H__ #include #include #include #include "icsneo/api/errormanager.h" #include "icsneo/device/neodevice.h" #include "icsneo/device/idevicesettings.h" #include "icsneo/device/nullsettings.h" #include "icsneo/device/devicetype.h" #include "icsneo/communication/communication.h" #include "icsneo/communication/packetizer.h" #include "icsneo/communication/encoder.h" #include "icsneo/communication/decoder.h" #include "icsneo/communication/message/resetstatusmessage.h" #include "icsneo/third-party/concurrentqueue/concurrentqueue.h" namespace icsneo { class Device { public: virtual ~Device() { destructing = true; disableMessagePolling(); close(); } static std::string SerialNumToString(uint32_t serial); static uint32_t SerialStringToNum(const std::string& serial); static bool SerialStringIsNumeric(const std::string& serial); uint16_t getTimestampResolution() const; DeviceType getType() const { return DeviceType(data.type); } uint16_t getProductId() const { return productId; } std::string getSerial() const { return data.serial; } uint32_t getSerialNumber() const { return Device::SerialStringToNum(getSerial()); } const neodevice_t& getNeoDevice() const { return data; } std::string describe() const; friend std::ostream& operator<<(std::ostream& os, const Device& device) { os << device.describe(); return os; } virtual bool open(); virtual bool close(); virtual bool isOnline() const { return online; } virtual bool isOpen() const { return com->isOpen(); } virtual bool goOnline(); virtual bool goOffline(); // Message polling related functions void enableMessagePolling(); bool disableMessagePolling(); bool isMessagePollingEnabled() { return messagePollingCallbackID != 0; }; std::vector> getMessages(); bool getMessages(std::vector>& container, size_t limit = 0, std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); size_t getCurrentMessageCount() { return pollingContainer.size_approx(); } size_t getPollingMessageLimit() { return pollingMessageLimit; } void setPollingMessageLimit(size_t newSize) { pollingMessageLimit = newSize; enforcePollingMessageLimit(); } int addMessageCallback(const MessageCallback& cb) { return com->addMessageCallback(cb); } bool removeMessageCallback(int id) { return com->removeMessageCallback(id); } bool transmit(std::shared_ptr message); bool transmit(std::vector> messages); const std::vector& getSupportedRXNetworks() const { return supportedRXNetworks; } const std::vector& getSupportedTXNetworks() const { return supportedTXNetworks; } virtual bool isSupportedRXNetwork(const Network& net) const { return std::find(supportedRXNetworks.begin(), supportedRXNetworks.end(), net) != supportedRXNetworks.end(); } virtual bool isSupportedTXNetwork(const Network& net) const { return std::find(supportedTXNetworks.begin(), supportedTXNetworks.end(), net) != supportedTXNetworks.end(); } virtual size_t getNetworkCountByType(Network::Type) const; virtual Network getNetworkByNumber(Network::Type, size_t) const; std::shared_ptr com; std::unique_ptr settings; protected: uint16_t productId = 0; bool online = false; int messagePollingCallbackID = 0; int internalHandlerCallbackID = 0; device_errorhandler_t err; // START Initialization Functions Device(neodevice_t neodevice = { 0 }) { data = neodevice; data.device = this; } template void initialize() { err = makeErrorHandler(); auto transport = makeTransport(); setupTransport(*transport); auto packetizer = makePacketizer(); setupPacketizer(*packetizer); auto encoder = makeEncoder(packetizer); setupEncoder(*encoder); auto decoder = makeDecoder(); setupDecoder(*decoder); com = makeCommunication(std::move(transport), packetizer, std::move(encoder), std::move(decoder)); setupCommunication(*com); settings = makeSettings(com); setupSettings(*settings); setupSupportedRXNetworks(supportedRXNetworks); setupSupportedTXNetworks(supportedTXNetworks); } virtual device_errorhandler_t makeErrorHandler() { return [this](APIError::ErrorType type) { if(!destructing) ErrorManager::GetInstance().add(type, this); }; } template std::unique_ptr makeTransport() { return std::unique_ptr(new Transport(err, getWritableNeoDevice())); } virtual void setupTransport(ICommunication&) {} virtual std::shared_ptr makePacketizer() { return std::make_shared(err); } virtual void setupPacketizer(Packetizer&) {} virtual std::unique_ptr makeEncoder(std::shared_ptr p) { return std::unique_ptr(new Encoder(err, p)); } virtual void setupEncoder(Encoder&) {} virtual std::unique_ptr makeDecoder() { return std::unique_ptr(new Decoder(err)); } virtual void setupDecoder(Decoder&) {} virtual std::shared_ptr makeCommunication( std::unique_ptr t, std::shared_ptr p, std::unique_ptr e, std::unique_ptr d) { return std::make_shared(err, std::move(t), p, std::move(e), std::move(d)); } virtual void setupCommunication(Communication&) {} template std::unique_ptr makeSettings(std::shared_ptr com) { return std::unique_ptr(new Settings(com)); } virtual void setupSettings(IDeviceSettings&) {} virtual void setupSupportedRXNetworks(std::vector&) {} virtual void setupSupportedTXNetworks(std::vector&) {} // END Initialization Functions void handleInternalMessage(std::shared_ptr message); neodevice_t& getWritableNeoDevice() { return data; } private: neodevice_t data; std::shared_ptr latestResetStatus; std::vector supportedTXNetworks; std::vector supportedRXNetworks; enum class LEDState : uint8_t { Offline = 0x04, CoreMiniRunning = 0x08, // This should override "offline" if the CoreMini is running Online = 0x10 }; LEDState ledState; void updateLEDState(); size_t pollingMessageLimit = 20000; moodycamel::BlockingConcurrentQueue> pollingContainer; void enforcePollingMessageLimit(); bool destructing = false; }; } #endif