diff --git a/api/icsneocpp/event.cpp b/api/icsneocpp/event.cpp index 6f3c2b3..d4030c0 100644 --- a/api/icsneocpp/event.cpp +++ b/api/icsneocpp/event.cpp @@ -73,7 +73,10 @@ static constexpr const char* VALUE_NOT_YET_PRESENT = "The value is not yet prese // 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* NO_SERIAL_NUMBER_FW_12V = "Communication could not be established with the device. Perhaps it is not powered with 12 volts?"; +static constexpr const char* NO_SERIAL_NUMBER_FW = "Communication could not be established with the device. Perhaps it is not powered?"; +static constexpr const char* NO_SERIAL_NUMBER_12V = "Communication could not be established with the device. Perhaps it is not powered with 12 volts or requires a firmware update using Vehicle Spy."; +static constexpr const char* NO_SERIAL_NUMBER = "Communication could not be established with the device. Perhaps it is not powered or requires a firmware update using Vehicle Spy."; 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."; @@ -202,6 +205,12 @@ const char* APIEvent::DescriptionForType(Type type) { return TERMINATION_NOT_SUPPORTED_NETWORK; case Type::AnotherInTerminationGroupEnabled: return ANOTHER_IN_TERMINATION_GROUP_ENABLED; + case Type::NoSerialNumberFW: + return NO_SERIAL_NUMBER_FW; + case Type::NoSerialNumber12V: + return NO_SERIAL_NUMBER_12V; + case Type::NoSerialNumberFW12V: + return NO_SERIAL_NUMBER_FW_12V; // Transport Errors case Type::FailedToRead: diff --git a/device/device.cpp b/device/device.cpp index 9142ed7..3bb379d 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -270,7 +270,7 @@ APIEvent::Type Device::attemptToBeginCommunication() { // Very unlikely, at the time of writing this only fails if rawWrite does. // If you're looking for this error, you're probably looking for if(!serial) below. // "Communication could not be established with the device. Perhaps it is not powered with 12 volts?" - return APIEvent::Type::NoSerialNumber; + return getCommunicationNotEstablishedError(); } auto serial = com->getSerialNumberSync(); @@ -281,7 +281,7 @@ APIEvent::Type Device::attemptToBeginCommunication() { break; } if(!serial) // "Communication could not be established with the device. Perhaps it is not powered with 12 volts?" - return APIEvent::Type::NoSerialNumber; + return getCommunicationNotEstablishedError(); std::string currentSerial = getNeoDevice().serial; if(currentSerial != serial->deviceSerial) @@ -726,6 +726,32 @@ void Device::handleNeoVIMessage(std::shared_ptr message) { } } +bool Device::firmwareUpdateSupported() { + bool ret = false; + forEachExtension([&ret](const std::shared_ptr& ext) { + if(ext->providesFirmware()) { + ret = true; + return false; + } + return true; // false breaks out early + }); + return ret; +} + +APIEvent::Type Device::getCommunicationNotEstablishedError() { + if(firmwareUpdateSupported()) { + if(requiresVehiclePower()) + return APIEvent::Type::NoSerialNumberFW12V; + else + return APIEvent::Type::NoSerialNumberFW; + } else { + if(requiresVehiclePower()) + return APIEvent::Type::NoSerialNumber12V; + else + return APIEvent::Type::NoSerialNumber; + } +} + void Device::updateLEDState() { std::vector args {(uint8_t) ledState}; com->sendCommand(Command::UpdateLEDState, args); diff --git a/include/icsneo/api/event.h b/include/icsneo/api/event.h index 3be2404..2c23f6e 100644 --- a/include/icsneo/api/event.h +++ b/include/icsneo/api/event.h @@ -76,6 +76,9 @@ public: TerminationNotSupportedDevice = 0x2024, TerminationNotSupportedNetwork = 0x2025, AnotherInTerminationGroupEnabled = 0x2026, + NoSerialNumberFW = 0x2027, // A firmware update was already attempted + NoSerialNumber12V = 0x2028, // The device must be powered with 12V for communication to be established + NoSerialNumberFW12V = 0x2029, // The device must be powered with 12V for communication to be established, a firmware update was already attempted // Transport Events FailedToRead = 0x3000, diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 08be7ae..70bc615 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -254,6 +254,8 @@ protected: // Hook for devices such as FIRE which need to inject traffic before RequestSerialNumber // Return false to bail virtual bool afterCommunicationOpen() { return true; } + + virtual bool requiresVehiclePower() const { return true; } template std::shared_ptr getExtension() const { @@ -291,6 +293,10 @@ private: bool heartbeatSuppressed() const { return heartbeatSuppressedByUser > 0 || (settings && settings->applyingSettings); } void handleNeoVIMessage(std::shared_ptr message); + + bool firmwareUpdateSupported(); + + APIEvent::Type getCommunicationNotEstablishedError(); enum class LEDState : uint8_t { Offline = 0x04, diff --git a/include/icsneo/device/extensions/deviceextension.h b/include/icsneo/device/extensions/deviceextension.h index 0a4684e..27e55e0 100644 --- a/include/icsneo/device/extensions/deviceextension.h +++ b/include/icsneo/device/extensions/deviceextension.h @@ -27,6 +27,8 @@ public: virtual void onGoOffline() {} virtual void onDeviceClose() {} + virtual bool providesFirmware() const { return false; } + virtual void handleMessage(const std::shared_ptr&) {} // Return true to continue transmitting, success should be written to if false is returned diff --git a/include/icsneo/device/tree/etherbadge/etherbadge.h b/include/icsneo/device/tree/etherbadge/etherbadge.h index 7f8923e..8f5f415 100644 --- a/include/icsneo/device/tree/etherbadge/etherbadge.h +++ b/include/icsneo/device/tree/etherbadge/etherbadge.h @@ -58,6 +58,8 @@ protected: // The supported TX networks are the same as the supported RX networks for this device virtual void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h b/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h index 2463a90..e41b5aa 100644 --- a/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h +++ b/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h @@ -45,6 +45,8 @@ private: // The supported TX networks are the same as the supported RX networks for this device virtual void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h b/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h index dd8d69f..52cae00 100644 --- a/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h +++ b/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h @@ -45,6 +45,8 @@ private: // The supported TX networks are the same as the supported RX networks for this device virtual void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/radmoon2/radmoon2.h b/include/icsneo/device/tree/radmoon2/radmoon2.h index e8777ab..591f41e 100644 --- a/include/icsneo/device/tree/radmoon2/radmoon2.h +++ b/include/icsneo/device/tree/radmoon2/radmoon2.h @@ -84,6 +84,8 @@ protected: Device::setupDecoder(decoder); decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/radmoonduo/radmoonduo.h b/include/icsneo/device/tree/radmoonduo/radmoonduo.h index 75c2d05..77ed88c 100644 --- a/include/icsneo/device/tree/radmoonduo/radmoonduo.h +++ b/include/icsneo/device/tree/radmoonduo/radmoonduo.h @@ -47,6 +47,8 @@ protected: // The supported TX networks are the same as the supported RX networks for this device void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/radpluto/radpluto.h b/include/icsneo/device/tree/radpluto/radpluto.h index 3533ab7..dc0ab0a 100644 --- a/include/icsneo/device/tree/radpluto/radpluto.h +++ b/include/icsneo/device/tree/radpluto/radpluto.h @@ -53,6 +53,8 @@ protected: // The supported TX networks are the same as the supported RX networks for this device virtual void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/radsupermoon/radsupermoon.h b/include/icsneo/device/tree/radsupermoon/radsupermoon.h index 27c81f4..5d63429 100644 --- a/include/icsneo/device/tree/radsupermoon/radsupermoon.h +++ b/include/icsneo/device/tree/radsupermoon/radsupermoon.h @@ -82,6 +82,8 @@ protected: // The supported TX networks are the same as the supported RX networks for this device void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/valuecan3/valuecan3.h b/include/icsneo/device/tree/valuecan3/valuecan3.h index b60e2af..7b673cd 100644 --- a/include/icsneo/device/tree/valuecan3/valuecan3.h +++ b/include/icsneo/device/tree/valuecan3/valuecan3.h @@ -45,6 +45,8 @@ private: // The supported TX networks are the same as the supported RX networks for this device virtual void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/valuecan4/valuecan4.h b/include/icsneo/device/tree/valuecan4/valuecan4.h index d7abe10..f98cb8c 100644 --- a/include/icsneo/device/tree/valuecan4/valuecan4.h +++ b/include/icsneo/device/tree/valuecan4/valuecan4.h @@ -20,6 +20,8 @@ protected: } ValueCAN4(neodevice_t neodevice) : Device(neodevice) {} + + bool requiresVehiclePower() const override { return false; } }; } diff --git a/include/icsneo/device/tree/vividcan/vividcan.h b/include/icsneo/device/tree/vividcan/vividcan.h index 147c5eb..2d4a148 100644 --- a/include/icsneo/device/tree/vividcan/vividcan.h +++ b/include/icsneo/device/tree/vividcan/vividcan.h @@ -35,6 +35,9 @@ public: return false; } +protected: + bool requiresVehiclePower() const override { return false; } + private: VividCAN(neodevice_t neodevice) : Device(neodevice) { initialize();