diff --git a/examples/knx-linux/knx-linux.vcxproj b/examples/knx-linux/knx-linux.vcxproj index ed5230c..cdc925d 100644 --- a/examples/knx-linux/knx-linux.vcxproj +++ b/examples/knx-linux/knx-linux.vcxproj @@ -93,6 +93,7 @@ + diff --git a/examples/knx-linux/knx-linux.vcxproj.filters b/examples/knx-linux/knx-linux.vcxproj.filters index 3f4a28a..6b44be3 100644 --- a/examples/knx-linux/knx-linux.vcxproj.filters +++ b/examples/knx-linux/knx-linux.vcxproj.filters @@ -194,6 +194,9 @@ Header files\knx + + Header files\knx + diff --git a/src/knx/function_property.h b/src/knx/function_property.h index b43df9f..78e6464 100644 --- a/src/knx/function_property.h +++ b/src/knx/function_property.h @@ -7,11 +7,11 @@ class InterfaceObject; template class FunctionProperty : public Property { public: - FunctionProperty(T* io, PropertyID id, uint8_t access, + FunctionProperty(T* io, PropertyID id, void (*commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&), void (*stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&)) - : Property(id, false, PDT_FUNCTION, 1, access), _interfaceObject(io), _commandCallback(commandCallback), _stateCallback(stateCallback) - /* max_elements is set to 1, see 3.3.7 Application Layer p.68 */ + : Property(id, false, PDT_FUNCTION, 1, ReadLv0|WriteLv0), _interfaceObject(io), _commandCallback(commandCallback), _stateCallback(stateCallback) + /* max_elements is set to 1, read and write level any value so we use Lv0, see 3.3.7 Application Layer p.68 */ {} virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override diff --git a/src/knx/interface_object.cpp b/src/knx/interface_object.cpp index 19396ac..3949409 100644 --- a/src/knx/interface_object.cpp +++ b/src/knx/interface_object.cpp @@ -10,54 +10,6 @@ InterfaceObject::~InterfaceObject() } void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access) -{ - PropertyDescription* descriptions = propertyDescriptions(); - uint8_t count = propertyDescriptionCount(); - - numberOfElements = 0; - if (descriptions == nullptr || count == 0) - return readPropertyDescription2(propertyId, propertyIndex, writeEnable, type, numberOfElements, access); - - PropertyDescription* desc = nullptr; - - // from KNX spec. 03.03.07 Application Layer (page 56) - 3.4.3.3 A_PropertyDescription_Read-service - // Summary: either propertyId OR propertyIndex, but not both at the same time - if (propertyId != 0) - { - for (uint8_t i = 0; i < count; i++) - { - PropertyDescription d = descriptions[i]; - if (d.Id != propertyId) - continue; - - desc = &d; - propertyIndex = i; - break; - } - } - else - { - // If propertyId is zero, propertyIndex shall be used. - // Response: propertyIndex of received A_PropertyDescription_Read - if (propertyIndex < count) - { - desc = &descriptions[propertyIndex]; - } - } - - if (desc != nullptr) - { - propertyId = desc->Id; - writeEnable = desc->WriteEnable; - type = desc->Type; - numberOfElements = desc->MaxElements; - access = desc->Access; - } - else - return readPropertyDescription2(propertyId, propertyIndex, writeEnable, type, numberOfElements, access); -} - -void InterfaceObject::readPropertyDescription2(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access) { uint8_t count = _propertyCount; @@ -161,17 +113,6 @@ void InterfaceObject::state(PropertyID id, uint8_t* data, uint8_t length, uint8_ prop->state(data, length, resultData, resultLength); } -uint8_t InterfaceObject::propertyDescriptionCount() -{ - return 0; -} - -PropertyDescription* InterfaceObject::propertyDescriptions() -{ - return nullptr; -} - - void InterfaceObject::initializeProperties(size_t propertiesSize, Property** properties) { _propertyCount = propertiesSize / sizeof(Property*); diff --git a/src/knx/interface_object.h b/src/knx/interface_object.h index 0b92633..63e6797 100644 --- a/src/knx/interface_object.h +++ b/src/knx/interface_object.h @@ -144,9 +144,7 @@ class InterfaceObject : public SaveRestore * * @param[out] access the ::AccessLevel necessary to read/write the property. */ - // TODO: remove first version after complete property refactoring void readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access); - void readPropertyDescription2(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access); /** * Gets property with PropertyID id if it exists and nullptr otherwise. @@ -181,15 +179,6 @@ class InterfaceObject : public SaveRestore virtual uint16_t saveSize() override; protected: - /** - * Returns the number of properties the interface object has. - */ - virtual uint8_t propertyDescriptionCount(); - /** - * Returns a pointer to the first PropertyDescription of the interface object. - * This is used by readPropertyDescription() together with propertyCount(). - */ - virtual PropertyDescription* propertyDescriptions(); /** * Intializes the Property-array the the supplied values. diff --git a/src/knx/rf_medium_object.cpp b/src/knx/rf_medium_object.cpp index d731975..be4d511 100644 --- a/src/knx/rf_medium_object.cpp +++ b/src/knx/rf_medium_object.cpp @@ -1,141 +1,60 @@ #include #include "rf_medium_object.h" #include "bits.h" +#include "data_property.h" +#include "function_property.h" #include "config.h" #ifdef USE_RF -void RfMediumObject::readProperty(PropertyID propertyId, uint16_t start, uint8_t& count, uint8_t* data) +RfMediumObject::RfMediumObject() { - switch (propertyId) + uint8_t rfDomainAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // see KNX RF S-Mode AN160 p.11 + Property* properties[] = { - case PID_OBJECT_TYPE: - pushWord(OT_RF_MEDIUM, data); - break; - case PID_RF_MULTI_TYPE: - data[0] = 0x00; // KNX RF ready only - break; - case PID_RF_DOMAIN_ADDRESS: - pushByteArray((uint8_t*)_rfDomainAddress, 6, data); - break; - case PID_RF_RETRANSMITTER: - data[0] = 0x00; // No KNX RF retransmitter - break; - case PID_RF_BIDIR_TIMEOUT: // PDT_FUNCTION - data[0] = 0x00; // success - data[1] = 0xFF; // permanent bidirectional device - data[2] = 0xFF; // permanent bidirectional device - break; - case PID_RF_DIAG_SA_FILTER_TABLE: // PDT_GENERIC_03[] - pushByteArray((uint8_t*)_rfDiagSourceAddressFilterTable, 24, data); - break; - case PID_RF_DIAG_BUDGET_TABLE: - pushByteArray((uint8_t*)_rfDiagLinkBudgetTable, 24, data); - break; - case PID_RF_DIAG_PROBE: // PDT_FUNCTION - // Not supported yet - break; - default: - count = 0; - } + new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t)OT_RF_MEDIUM), + new DataProperty(PID_RF_MULTI_TYPE, true, PDT_GENERIC_01, 1, ReadLv3 | WriteLv2, (uint8_t)0x00), + new DataProperty(PID_RF_RETRANSMITTER, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint8_t)0x00), + new DataProperty(PID_RF_DOMAIN_ADDRESS, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv2, rfDomainAddress), + new FunctionProperty(this, PID_RF_BIDIR_TIMEOUT, + [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) + { + resultData[0] = 0x00; // success + resultData[1] = 0xFF; // permanent bidirectional device + resultData[2] = 0xFF; // permanent bidirectional device + resultLength = 3; + }, + [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) + { + resultData[0] = 0x00; // success + resultData[1] = 0xFF; // permanent bidirectional device + resultData[2] = 0xFF; // permanent bidirectional device + resultLength = 3; + }), +/* This properties are used in NMP_LinkBudget_Measure to diagnose the Link Budget of the communication. + This in not implemented yet. + new DataProperty(PID_RF_DIAG_SA_FILTER_TABLE, true, PDT_GENERIC_03, 8, ReadLv3 | WriteLv3), + new DataProperty(PID_RF_DIAG_BUDGET_TABLE, false, PDT_GENERIC_03, 8, ReadLv3 | WriteLv0), + new FunctionProperty(this, PID_RF_DIAG_PROBE, + [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) + { + }, + [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) + { + }), */ + }; + initializeProperties(sizeof(properties), properties); } -void RfMediumObject::writeProperty(PropertyID id, uint16_t start, uint8_t* data, uint8_t& count) +const uint8_t* RfMediumObject::rfDomainAddress() { - switch (id) - { - case PID_RF_MULTI_TYPE: - // We only support RF ready and not RF multi, ignore write request - break; - case PID_RF_DOMAIN_ADDRESS: - for (uint8_t i = start; i < start + count; i++) - _rfDomainAddress[i-1] = data[i - start]; - break; - case PID_RF_BIDIR_TIMEOUT: // PDT_FUNCTION - // Not supported yet (permanent bidir device) - break; - case PID_RF_DIAG_SA_FILTER_TABLE: - for (uint8_t i = start; i < start + count; i++) - _rfDiagSourceAddressFilterTable[i-1] = data[i - start]; - break; - case PID_RF_DIAG_BUDGET_TABLE: - for (uint8_t i = start; i < start + count; i++) - _rfDiagLinkBudgetTable[i-1] = data[i - start]; - break; - case PID_RF_DIAG_PROBE: - // Not supported yet - break; - default: - count = 0; - break; - } -} - -uint8_t RfMediumObject::propertySize(PropertyID id) -{ - switch (id) - { - case PID_RF_MULTI_TYPE: - case PID_RF_RETRANSMITTER: - return 1; - case PID_OBJECT_TYPE: - return 2; - case PID_RF_DOMAIN_ADDRESS: - return 6; - case PID_RF_DIAG_SA_FILTER_TABLE: - case PID_RF_DIAG_BUDGET_TABLE: - return 24; - // case PID_RF_BIDIR_TIMEOUT: ? - // case PID_RF_DIAG_PROBE: ? - default: - break; - } - return 0; -} - -uint8_t* RfMediumObject::save(uint8_t* buffer) -{ - buffer = pushByteArray((uint8_t*)_rfDomainAddress, 6, buffer); - return buffer; -} - -const uint8_t* RfMediumObject::restore(const uint8_t* buffer) -{ - buffer = popByteArray((uint8_t*)_rfDomainAddress, 6, buffer); - return buffer; -} - -uint16_t RfMediumObject::saveSize() -{ - return 6; -} - -uint8_t* RfMediumObject::rfDomainAddress() -{ - return _rfDomainAddress; + DataProperty* prop = (DataProperty*)property(PID_RF_DOMAIN_ADDRESS); + return prop->data(); } void RfMediumObject::rfDomainAddress(const uint8_t* value) { - pushByteArray(value, 6, _rfDomainAddress); -} - -static PropertyDescription _propertyDescriptions[] = -{ - { PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 }, - { PID_RF_MULTI_TYPE, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0 }, - { PID_RF_RETRANSMITTER, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0 }, - { PID_RF_DOMAIN_ADDRESS, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv0 } -}; -static uint8_t _propertyDescriptionCount = sizeof(_propertyDescriptions) / sizeof(PropertyDescription); - -uint8_t RfMediumObject::propertyDescriptionCount() -{ - return _propertyDescriptionCount; -} - -PropertyDescription* RfMediumObject::propertyDescriptions() -{ - return _propertyDescriptions; + Property* prop = property(PID_RF_DOMAIN_ADDRESS); + prop->write(value); } #endif \ No newline at end of file diff --git a/src/knx/rf_medium_object.h b/src/knx/rf_medium_object.h index 6742a85..a07e03b 100644 --- a/src/knx/rf_medium_object.h +++ b/src/knx/rf_medium_object.h @@ -7,21 +7,11 @@ class RfMediumObject: public InterfaceObject { public: - void readProperty(PropertyID id, uint16_t start, uint8_t& count, uint8_t* data) override; - void writeProperty(PropertyID id, uint16_t start, uint8_t* data, uint8_t& count) override; - uint8_t propertySize(PropertyID id) override; - uint8_t* save(uint8_t* buffer) override; - const uint8_t* restore(const uint8_t* buffer) override; - uint16_t saveSize() override; - - uint8_t* rfDomainAddress(); + RfMediumObject(); + const uint8_t* rfDomainAddress(); void rfDomainAddress(const uint8_t* value); -protected: - uint8_t propertyDescriptionCount() override; - PropertyDescription* propertyDescriptions() override; private: - uint8_t _rfDomainAddress[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // see KNX RF S-Mode AN160 p.11 uint8_t _rfDiagSourceAddressFilterTable[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; uint8_t _rfDiagLinkBudgetTable[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; };