diff --git a/examples/knx-linux-coupler/CMakeLists.txt b/examples/knx-linux-coupler/CMakeLists.txt index e61549d..dce9641 100644 --- a/examples/knx-linux-coupler/CMakeLists.txt +++ b/examples/knx-linux-coupler/CMakeLists.txt @@ -23,7 +23,9 @@ add_executable(knx-linux ../../src/knx/bau091A.h ../../src/knx/bau27B0.cpp ../../src/knx/bau27B0.h - ../../src/knx/bau57B0.cpp + ../../src/knx/bau2920.cpp + ../../src/knx/bau2920.h + ../../src/knx/bau57B0.cpp ../../src/knx/bau57B0.h ../../src/knx/bau_systemB.cpp ../../src/knx/bau_systemB.h diff --git a/examples/knx-linux-coupler/main.cpp b/examples/knx-linux-coupler/main.cpp index 750ebef..e65c95f 100644 --- a/examples/knx-linux-coupler/main.cpp +++ b/examples/knx-linux-coupler/main.cpp @@ -1,6 +1,7 @@ #include "knx_facade.h" #include "knx/bau091A.h" +#include "knx/bau2920.h" #include "knx/bits.h" #include diff --git a/src/knx/bau07B0.cpp b/src/knx/bau07B0.cpp index d3cada7..5e64898 100644 --- a/src/knx/bau07B0.cpp +++ b/src/knx/bau07B0.cpp @@ -18,6 +18,7 @@ Bau07B0::Bau07B0(Platform& platform) _netLayer.getEntity(0).dataLinkLayer(_dlLayer); #ifdef USE_CEMI_SERVER + _cemiServerObject.setMediumTypeAsSupported(DptMedium::KNX_TP1); _cemiServer.dataLinkLayer(_dlLayer); _dlLayer.cemiServer(_cemiServer); _memory.addSaveRestore(&_cemiServerObject); diff --git a/src/knx/bau091A.cpp b/src/knx/bau091A.cpp index 8b5fcb9..36769c6 100644 --- a/src/knx/bau091A.cpp +++ b/src/knx/bau091A.cpp @@ -4,7 +4,7 @@ #include #include -#ifdef USE_IP +#if defined(USE_IP) && defined (USE_TP) using namespace std; @@ -26,8 +26,10 @@ Bau091A::Bau091A(Platform& platform) _netLayer.getEntity(1).dataLinkLayer(_dlLayerSecondary); #ifdef USE_CEMI_SERVER + _cemiServerObject.setMediumTypeAsSupported(DptMedium::KNX_IP); + _cemiServerObject.setMediumTypeAsSupported(DptMedium::KNX_TP1); _cemiServer.dataLinkLayer(_dlLayerSecondary); // Secondary I/F is the important one! - _dlLayer.cemiServer(_cemiServer); + _dlLayerSecondary.cemiServer(_cemiServer); _memory.addSaveRestore(&_cemiServerObject); #endif diff --git a/src/knx/bau091A.h b/src/knx/bau091A.h index 846f0a3..a79ac97 100644 --- a/src/knx/bau091A.h +++ b/src/knx/bau091A.h @@ -1,7 +1,7 @@ #pragma once #include "config.h" -#ifdef USE_IP +#if defined(USE_IP) && defined (USE_TP) #include "bau_systemB_coupler.h" #include "ip_parameter_object.h" #include "ip_data_link_layer.h" diff --git a/src/knx/bau27B0.cpp b/src/knx/bau27B0.cpp index 034437d..5fcb88c 100644 --- a/src/knx/bau27B0.cpp +++ b/src/knx/bau27B0.cpp @@ -16,6 +16,7 @@ Bau27B0::Bau27B0(Platform& platform) _netLayer.getEntity(0).dataLinkLayer(_dlLayer); _memory.addSaveRestore(&_rfMediumObj); #ifdef USE_CEMI_SERVER + _cemiServerObject.setMediumTypeAsSupported(DptMedium::KNX_RF); _cemiServer.dataLinkLayer(_dlLayer); _dlLayer.cemiServer(_cemiServer); _memory.addSaveRestore(&_cemiServerObject); diff --git a/src/knx/bau57B0.cpp b/src/knx/bau57B0.cpp index e12c5af..1316ecc 100644 --- a/src/knx/bau57B0.cpp +++ b/src/knx/bau57B0.cpp @@ -19,6 +19,7 @@ Bau57B0::Bau57B0(Platform& platform) { _netLayer.getEntity(0).dataLinkLayer(_dlLayer); #ifdef USE_CEMI_SERVER + _cemiServerObject.setMediumTypeAsSupported(DptMedium::KNX_IP); _cemiServer.dataLinkLayer(_dlLayer); _dlLayer.cemiServer(_cemiServer); _memory.addSaveRestore(&_cemiServerObject); diff --git a/src/knx/bau_systemB_device.cpp b/src/knx/bau_systemB_device.cpp index 018162f..4281636 100644 --- a/src/knx/bau_systemB_device.cpp +++ b/src/knx/bau_systemB_device.cpp @@ -16,7 +16,9 @@ BauSystemBDevice::BauSystemBDevice(Platform& platform) : { _appLayer.transportLayer(_transLayer); _appLayer.associationTableObject(_assocTable); +#ifdef USE_DATASECURE _appLayer.groupAddressTable(_addrTable); +#endif _transLayer.networkLayer(_netLayer); _transLayer.groupAddressTable(_addrTable); diff --git a/src/knx/cemi_server.cpp b/src/knx/cemi_server.cpp index 54baab5..2a9b557 100644 --- a/src/knx/cemi_server.cpp +++ b/src/knx/cemi_server.cpp @@ -56,21 +56,24 @@ void CemiServer::dataConfirmationToTunnel(CemiFrame& frame) void CemiServer::dataIndicationToTunnel(CemiFrame& frame) { -#if MEDIUM_TYPE == 2 + bool isRf = _dataLinkLayer->isOpenMedium(); + uint8_t data[frame.dataLength() + (isRf ? 10 : 0)]; - uint8_t data[frame.dataLength() + 10]; - data[0] = L_data_ind; // Message Code - data[1] = 0x0A; // Total additional info length - data[2] = 0x02; // RF add. info: type - data[3] = 0x08; // RF add. info: length - data[4] = frame.rfInfo(); // RF add. info: info field (batt ok, bidir) - pushByteArray(frame.rfSerialOrDoA(), 6, &data[5]); // RF add. info:Serial or Domain Address - data[11] = frame.rfLfn(); // RF add. info: link layer frame number - memcpy(&data[12], &((frame.data())[2]), frame.dataLength() - 2); -#else - uint8_t data[frame.dataLength()]; - memcpy(&data[0], frame.data(), frame.dataLength()); -#endif + if (_dataLinkLayer->isOpenMedium()) + { + data[0] = L_data_ind; // Message Code + data[1] = 0x0A; // Total additional info length + data[2] = 0x02; // RF add. info: type + data[3] = 0x08; // RF add. info: length + data[4] = frame.rfInfo(); // RF add. info: info field (batt ok, bidir) + pushByteArray(frame.rfSerialOrDoA(), 6, &data[5]); // RF add. info:Serial or Domain Address + data[11] = frame.rfLfn(); // RF add. info: link layer frame number + memcpy(&data[12], &((frame.data())[2]), frame.dataLength() - 2); + } + else + { + memcpy(&data[0], frame.data(), frame.dataLength()); + } CemiFrame tmpFrame(data, sizeof(data)); @@ -87,6 +90,8 @@ void CemiServer::dataIndicationToTunnel(CemiFrame& frame) void CemiServer::frameReceived(CemiFrame& frame) { + bool isRf = _dataLinkLayer->isOpenMedium(); + switch(frame.messageCode()) { case L_data_req: @@ -98,35 +103,36 @@ void CemiServer::frameReceived(CemiFrame& frame) frame.sourceAddress(_clientAddress); } -#if MEDIUM_TYPE == 2 - // Check if we have additional info for RF - if (((frame.data())[1] == 0x0A) && // Additional info total length: we only handle one additional info of type RF - ((frame.data())[2] == 0x02) && // Additional info type: RF - ((frame.data())[3] == 0x08) ) // Additional info length of type RF: 8 bytes (fixed) + if (isRf) { - frame.rfInfo((frame.data())[4]); - // Use the values provided in the RF additonal info - if ( ((frame.data())[5] != 0x00) || ((frame.data())[6] != 0x00) || ((frame.data())[7] != 0x00) || - ((frame.data())[8] != 0x00) || ((frame.data())[9] != 0x00) || ((frame.data())[10] != 0x00) ) + // Check if we have additional info for RF + if (((frame.data())[1] == 0x0A) && // Additional info total length: we only handle one additional info of type RF + ((frame.data())[2] == 0x02) && // Additional info type: RF + ((frame.data())[3] == 0x08) ) // Additional info length of type RF: 8 bytes (fixed) { - frame.rfSerialOrDoA(&((frame.data())[5])); - } // else leave the nullptr as it is - frame.rfLfn((frame.data())[11]); - } + frame.rfInfo((frame.data())[4]); + // Use the values provided in the RF additonal info + if ( ((frame.data())[5] != 0x00) || ((frame.data())[6] != 0x00) || ((frame.data())[7] != 0x00) || + ((frame.data())[8] != 0x00) || ((frame.data())[9] != 0x00) || ((frame.data())[10] != 0x00) ) + { + frame.rfSerialOrDoA(&((frame.data())[5])); + } // else leave the nullptr as it is + frame.rfLfn((frame.data())[11]); + } - // If the cEMI client does not provide a link layer frame number (LFN), - // we use our own counter. - // Note: There is another link layer frame number counter inside the RF data link layer class! - // That counter is solely for the local application! - // If we set a LFN here, the data link layer counter is NOT used! - if (frame.rfLfn() == 0xFF) - { - // Set Data Link Layer Frame Number - frame.rfLfn(_frameNumber); - // Link Layer frame number counts 0..7 - _frameNumber = (_frameNumber + 1) & 0x7; + // If the cEMI client does not provide a link layer frame number (LFN), + // we use our own counter. + // Note: There is another link layer frame number counter inside the RF data link layer class! + // That counter is solely for the local application! + // If we set a LFN here, the data link layer counter is NOT used! + if (frame.rfLfn() == 0xFF) + { + // Set Data Link Layer Frame Number + frame.rfLfn(_frameNumber); + // Link Layer frame number counts 0..7 + _frameNumber = (_frameNumber + 1) & 0x7; + } } -#endif print("L_data_req: src: "); print(frame.sourceAddress(), HEX); diff --git a/src/knx/cemi_server_object.cpp b/src/knx/cemi_server_object.cpp index 3b4bc1b..140c414 100644 --- a/src/knx/cemi_server_object.cpp +++ b/src/knx/cemi_server_object.cpp @@ -8,26 +8,51 @@ CemiServerObject::CemiServerObject() { - uint16_t mediumType = 0; -#if MEDIUM_TYPE == 0 - mediumType = 2; // TP1 supported -#elif MEDIUM_TYPE == 2 - mediumType = 16; // RF supported -#elif MEDIUM_TYPE == 5 - mediumType = 32; // IP supported -#endif - Property* properties[] = { new DataProperty( PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t)OT_CEMI_SERVER ), - new DataProperty( PID_MEDIUM_TYPE, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0, mediumType), + new DataProperty( PID_MEDIUM_TYPE, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0, (uint16_t)0), new DataProperty( PID_COMM_MODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint16_t)0), new DataProperty( PID_COMM_MODES_SUPPORTED, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0, (uint16_t)0x100), - new DataProperty( PID_MEDIUM_AVAILABILITY, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0, mediumType), + new DataProperty( PID_MEDIUM_AVAILABILITY, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0, (uint16_t)0), // cEMI additional info types supported by this cEMI server: only 0x02 (RF Control Octet and Serial Number or DoA) new DataProperty( PID_ADD_INFO_TYPES, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)0x02) }; initializeProperties(sizeof(properties), properties); } + +void CemiServerObject::setMediumTypeAsSupported(DptMedium dptMedium) +{ + uint16_t mediaTypesSupported; + property(PID_MEDIUM_TYPE)->read(mediaTypesSupported); + + switch(dptMedium) + { + case DptMedium::KNX_IP: + mediaTypesSupported |= 1 << 1; + break; + case DptMedium::KNX_RF: + mediaTypesSupported |= 1 << 4; + break; + case DptMedium::KNX_TP1: + mediaTypesSupported |= 1 << 5; + break; + case DptMedium::KNX_PL110: + mediaTypesSupported |= 1 << 2; + break; + } + + property(PID_MEDIUM_TYPE)->write(mediaTypesSupported); + // We also set the medium as available too + property(PID_MEDIUM_AVAILABILITY)->write(mediaTypesSupported); +} + +void CemiServerObject::clearSupportedMediaTypes() +{ + property(PID_MEDIUM_TYPE)->write((uint16_t) 0); + // We also set the medium as not available too + property(PID_MEDIUM_AVAILABILITY)->write((uint16_t) 0); +} + #endif diff --git a/src/knx/cemi_server_object.h b/src/knx/cemi_server_object.h index 9287c5d..726f82e 100644 --- a/src/knx/cemi_server_object.h +++ b/src/knx/cemi_server_object.h @@ -9,5 +9,9 @@ class CemiServerObject: public InterfaceObject { public: CemiServerObject(); + + void setMediumTypeAsSupported(DptMedium dptMedium); + void clearSupportedMediaTypes(); }; -#endif \ No newline at end of file + +#endif