diff --git a/api/icsneoc/icsneoc.cpp b/api/icsneoc/icsneoc.cpp index 7cf4ee5..124c2ae 100644 --- a/api/icsneoc/icsneoc.cpp +++ b/api/icsneoc/icsneoc.cpp @@ -212,24 +212,44 @@ bool icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLeng return true; } -bool icsneo_settingsSend(const neodevice_t* device) { +bool icsneo_settingsApply(const neodevice_t* device) { if(!icsneo_isValidNeoDevice(device)) return false; if(!device->device->settings) // Settings are not available for this device return false; - return device->device->settings->send(); + return device->device->settings->apply(); } -bool icsneo_settingsCommit(const neodevice_t* device) { +bool icsneo_settingsApplyTemporary(const neodevice_t* device) { if(!icsneo_isValidNeoDevice(device)) return false; if(!device->device->settings) // Settings are not available for this device return false; - return device->device->settings->commit(); + return device->device->settings->apply(true); +} + +bool icsneo_settingsApplyDefaults(const neodevice_t* device) { + if(!icsneo_isValidNeoDevice(device)) + return false; + + if(!device->device->settings) // Settings are not available for this device + return false; + + return device->device->settings->applyDefaults(); +} + +bool icsneo_settingsApplyDefaultsTemporary(const neodevice_t* device) { + if(!icsneo_isValidNeoDevice(device)) + return false; + + if(!device->device->settings) // Settings are not available for this device + return false; + + return device->device->settings->applyDefaults(true); } bool icsneo_setBaudrate(const neodevice_t* device, uint16_t netid, uint32_t newBaudrate) { diff --git a/api/icsneoc/include/icsneoc.h b/api/icsneoc/include/icsneoc.h index b93b387..7a38c6d 100644 --- a/api/icsneoc/include/icsneoc.h +++ b/api/icsneoc/include/icsneoc.h @@ -44,9 +44,13 @@ extern bool DLLExport icsneo_setPollingMessageLimit(const neodevice_t* device, s extern bool DLLExport icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLength); -extern bool DLLExport icsneo_settingsSend(const neodevice_t* device); +extern bool DLLExport icsneo_settingsApply(const neodevice_t* device); -extern bool DLLExport icsneo_settingsCommit(const neodevice_t* device); +extern bool DLLExport icsneo_settingsApplyTemporary(const neodevice_t* device); + +extern bool DLLExport icsneo_settingsApplyDefaults(const neodevice_t* device); + +extern bool DLLExport icsneo_settingsApplyDefaultsTemporary(const neodevice_t* device); extern bool DLLExport icsneo_setBaudrate(const neodevice_t* device, uint16_t netid, uint32_t newBaudrate); @@ -101,16 +105,22 @@ fn_icsneo_getPollingMessageLimit icsneo_getPollingMessageLimit; typedef bool(*fn_icsneo_setPollingMessageLimit)(const neodevice_t* device, size_t newLimit); fn_icsneo_setPollingMessageLimit icsneo_setPollingMessageLimit; -typedef size_t(*fn_icsneo_getProductName)(const neodevice_t* device, char* str, size_t* maxLength); +typedef bool(*fn_icsneo_getProductName)(const neodevice_t* device, char* str, size_t* maxLength); fn_icsneo_getProductName icsneo_getProductName; -typedef size_t(*fn_icsneo_settingsSend)(const neodevice_t* device); -fn_icsneo_settingsSend icsneo_settingsSend; +typedef bool(*fn_icsneo_settingsApply)(const neodevice_t* device); +fn_icsneo_settingsApply icsneo_settingsApply; -typedef size_t(*fn_icsneo_settingsCommit)(const neodevice_t* device); -fn_icsneo_settingsCommit icsneo_settingsCommit; +typedef bool(*fn_icsneo_settingsApplyTemporary)(const neodevice_t* device); +fn_icsneo_settingsApplyTemporary icsneo_settingsApplyTemporary; -typedef size_t(*fn_icsneo_setBaudrate)(const neodevice_t* device, uint16_t netid, uint32_t newBaudrate); +typedef bool(*fn_icsneo_settingsApplyDefaults)(const neodevice_t* device); +fn_icsneo_settingsApplyDefaults icsneo_settingsApplyDefaults; + +typedef bool(*fn_icsneo_settingsApplyDefaultsTemporary)(const neodevice_t* device); +fn_icsneo_settingsApplyDefaultsTemporary icsneo_settingsApplyDefaultsTemporary; + +typedef bool(*fn_icsneo_setBaudrate)(const neodevice_t* device, uint16_t netid, uint32_t newBaudrate); fn_icsneo_setBaudrate icsneo_setBaudrate; #define ICSNEO_IMPORT(func) func = (fn_##func)icsneo_dynamicLibraryGetFunction(icsneo_libraryHandle, #func) @@ -143,8 +153,10 @@ int icsneo_init() { ICSNEO_IMPORTASSERT(icsneo_getPollingMessageLimit); ICSNEO_IMPORTASSERT(icsneo_setPollingMessageLimit); ICSNEO_IMPORTASSERT(icsneo_getProductName); - ICSNEO_IMPORTASSERT(icsneo_settingsSend); - ICSNEO_IMPORTASSERT(icsneo_settingsCommit); + ICSNEO_IMPORTASSERT(icsneo_settingsApply); + ICSNEO_IMPORTASSERT(icsneo_settingsApplyTemporary); + ICSNEO_IMPORTASSERT(icsneo_settingsApplyDefaults); + ICSNEO_IMPORTASSERT(icsneo_settingsApplyDefaultsTemporary); ICSNEO_IMPORTASSERT(icsneo_setBaudrate); icsneo_initialized = true; diff --git a/communication/include/command.h b/communication/include/command.h index 37a42e4..6869be6 100644 --- a/communication/include/command.h +++ b/communication/include/command.h @@ -8,7 +8,8 @@ enum class Command : uint8_t { RequestSerialNumber = 0xA1, SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM GetSettings = 0xA5, // Previously known as RED_CMD_READ_BAUD_REQ - SaveSettings = 0xA6 + SaveSettings = 0xA6, + SetDefaultSettings = 0xA8 // Follow up with SaveSettings to write to EEPROM }; } diff --git a/device/idevicesettings.cpp b/device/idevicesettings.cpp index c1eb724..f0449fa 100644 --- a/device/idevicesettings.cpp +++ b/device/idevicesettings.cpp @@ -82,8 +82,7 @@ void IDeviceSettings::refresh(bool ignoreChecksum) { } } -bool IDeviceSettings::send() { - constexpr uint16_t GS_VERSION = 5; +bool IDeviceSettings::apply(bool temporary) { std::vector bytestream; bytestream.resize(7 + structSize); bytestream[0] = 0x00; @@ -114,21 +113,58 @@ bool IDeviceSettings::send() { com->sendCommand(Command::SetSettings, bytestream); msg = com->waitForMessageSync(std::make_shared(Command::SetSettings), std::chrono::milliseconds(1000)); + if(!msg || msg->data[0] != 1) { + refresh(); + return false; + } + if(!temporary) { + com->sendCommand(Command::SaveSettings); + msg = com->waitForMessageSync(std::make_shared(Command::SaveSettings), std::chrono::milliseconds(5000)); + } + refresh(); // Refresh our buffer with what the device has, whether we were successful or not return (msg && msg->data[0] == 1); // Device sends 0x01 for success } -bool IDeviceSettings::commit() { - if(!send()) +bool IDeviceSettings::applyDefaults(bool temporary) { + com->sendCommand(Command::SetDefaultSettings); + std::shared_ptr msg = com->waitForMessageSync(std::make_shared(Command::SetDefaultSettings), std::chrono::milliseconds(1000)); + if(!msg || msg->data[0] != 1) { + refresh(); return false; + } - com->sendCommand(Command::SaveSettings); - std::shared_ptr msg = com->waitForMessageSync(std::make_shared(Command::SaveSettings), std::chrono::milliseconds(5000)); + refresh(true); // Refresh ignoring checksum + // The device might modify the settings once they are applied, however in this case it does not update the checksum + // We refresh to get these updates, update the checksum, and send it back so it's all in sync + std::vector bytestream; + bytestream.resize(7 + structSize); + bytestream[0] = 0x00; + bytestream[1] = GS_VERSION; + bytestream[2] = GS_VERSION >> 8; + bytestream[3] = (uint8_t)structSize; + bytestream[4] = (uint8_t)(structSize >> 8); + uint16_t gs_checksum = CalculateGSChecksum(settings); + bytestream[5] = (uint8_t)gs_checksum; + bytestream[6] = (uint8_t)(gs_checksum >> 8); + memcpy(bytestream.data() + 7, getRawStructurePointer(), structSize); - refresh(); // Refresh our buffer with what the device has, whether we were successful or not + com->sendCommand(Command::SetSettings, bytestream); + msg = com->waitForMessageSync(std::make_shared(Command::SetSettings), std::chrono::milliseconds(1000)); + if(!msg || msg->data[0] != 1) { + refresh(); + return false; + } + + if(!temporary) { + com->sendCommand(Command::SaveSettings); + msg = com->waitForMessageSync(std::make_shared(Command::SaveSettings), std::chrono::milliseconds(5000)); + } + refresh(); // Refresh our buffer with what the device has, whether we were successful or not + return (msg && msg->data[0] == 1); // Device sends 0x01 for success } diff --git a/device/include/idevicesettings.h b/device/include/idevicesettings.h index c864abd..8c9f649 100644 --- a/device/include/idevicesettings.h +++ b/device/include/idevicesettings.h @@ -278,6 +278,7 @@ namespace icsneo { class IDeviceSettings { public: + static constexpr uint16_t GS_VERSION = 5; static uint16_t CalculateGSChecksum(const std::vector& settings); IDeviceSettings(std::shared_ptr com, size_t size) : com(com), structSize(size) {} @@ -285,8 +286,10 @@ public: bool ok() { return settingsLoaded; } void refresh(bool ignoreChecksum = false); // Get from device - bool send(); // Send to device, device keeps settings in volatile RAM until power cycle - bool commit(); // Send to device, device keeps settings in EEPROM until next commit + + // Send to device, if temporary device keeps settings in volatile RAM until power cycle, otherwise saved to EEPROM + bool apply(bool temporary = false); + bool applyDefaults(bool temporary = false); virtual bool setBaudrateFor(Network net, uint32_t baudrate);