Add EtsDeviceRuntime class for handling KNX device runtime operations

- Introduced EtsDeviceRuntime class to manage device runtime functionalities including handling tunnel frames and function property commands.
- Added support for individual address management and memory snapshot retrieval.
- Updated EtsMemorySnapshot structure to include individual address.
- Implemented identity application for DALI devices in the memory loader.
- Enhanced CMakeLists.txt to include new source files and compile definitions.
- Updated header files to include new dependencies and declarations.
- Refactored existing memory loading logic to accommodate new device runtime features.

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-12 05:19:14 +08:00
parent d231460612
commit 36d10702da
14 changed files with 1034 additions and 41 deletions
@@ -3,8 +3,11 @@
#include "openknx_idf/esp_idf_platform.h"
#include "knx/bau07B0.h"
#include "knx/property.h"
#include <algorithm>
#include <cstdint>
#include <memory>
namespace gateway::openknx {
namespace {
@@ -18,18 +21,45 @@ void CollectAssociation(uint16_t group_address, uint16_t group_object_number,
associations->push_back(EtsAssociation{group_address, group_object_number});
}
bool IsErasedMemory(const uint8_t* data, size_t size) {
if (data == nullptr) {
return false;
}
return std::all_of(data, data + size, [](uint8_t value) { return value == 0xff; });
}
constexpr uint16_t kReg1DaliManufacturerId = 0x00a4;
constexpr uint8_t kReg1DaliApplicationNumber = 0x01;
constexpr uint8_t kReg1DaliApplicationVersion = 0x05;
constexpr uint8_t kReg1DaliOrderNumber[10] = {'R', 'E', 'G', '1', '-', 'D', 'a', 'l', 'i', 0};
void ApplyReg1DaliIdentity(Bau07B0& device, EspIdfPlatform& platform) {
device.deviceObject().manufacturerId(kReg1DaliManufacturerId);
device.deviceObject().bauNumber(platform.uniqueSerialNumber());
device.deviceObject().orderNumber(kReg1DaliOrderNumber);
const uint8_t program_version[5] = {0x00, 0xa4, 0x00, kReg1DaliApplicationNumber,
kReg1DaliApplicationVersion};
device.parameters().property(PID_PROG_VERSION)->write(program_version);
}
} // namespace
EtsMemorySnapshot LoadEtsMemorySnapshot(const std::string& nvs_namespace) {
EspIdfPlatform platform(nullptr, nvs_namespace.c_str());
Bau07B0 device(platform);
device.deviceObject().manufacturerId(0xfa);
device.deviceObject().bauNumber(platform.uniqueSerialNumber());
device.readMemory();
EtsMemorySnapshot snapshot;
snapshot.configured = device.configured();
device.forEachEtsAssociation(CollectAssociation, &snapshot.associations);
const uint8_t* memory = platform.getNonVolatileMemoryStart();
const size_t memory_size = platform.getNonVolatileMemorySize();
if (memory == nullptr || memory_size == 0 || IsErasedMemory(memory, memory_size)) {
return snapshot;
}
auto device = std::make_unique<Bau07B0>(platform);
ApplyReg1DaliIdentity(*device, platform);
device->readMemory();
snapshot.configured = device->configured();
snapshot.individual_address = device->deviceObject().individualAddress();
device->forEachEtsAssociation(CollectAssociation, &snapshot.associations);
std::sort(snapshot.associations.begin(), snapshot.associations.end(),
[](const EtsAssociation& lhs, const EtsAssociation& rhs) {
if (lhs.group_address != rhs.group_address) {