From 322c3bbff82c5014fea7ad5238abf50a5fcf6a8b Mon Sep 17 00:00:00 2001 From: nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Wed, 4 Dec 2019 20:32:03 +0100 Subject: [PATCH] Working with Net'N'Node and ETS. --- src/knx/cemi_frame.cpp | 6 ++-- src/knx/cemi_frame.h | 2 +- src/knx/cemi_server.cpp | 62 ++++++++++++++-------------------- src/knx/cemi_server.h | 1 + src/knx/data_link_layer.cpp | 4 +++ src/knx/rf_data_link_layer.cpp | 2 +- src/knx/rf_medium_object.cpp | 3 ++ 7 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/knx/cemi_frame.cpp b/src/knx/cemi_frame.cpp index 2448afb..289e83a 100644 --- a/src/knx/cemi_frame.cpp +++ b/src/knx/cemi_frame.cpp @@ -69,9 +69,9 @@ Control Field 1 */ CemiFrame::CemiFrame(uint8_t* data, uint16_t length) - : _npdu(data + NPDU_LPDU_DIFF, *this), - _tpdu(data + TPDU_LPDU_DIFF, *this), - _apdu(data + APDU_LPDU_DIFF, *this) + : _npdu(data + data[1] + NPDU_LPDU_DIFF, *this), + _tpdu(data + data[1] + TPDU_LPDU_DIFF, *this), + _apdu(data + data[1] + APDU_LPDU_DIFF, *this) { _data = data; _ctrl1 = data + data[1] + CEMI_HEADER_SIZE; diff --git a/src/knx/cemi_frame.h b/src/knx/cemi_frame.h index 80052d2..d9db230 100644 --- a/src/knx/cemi_frame.h +++ b/src/knx/cemi_frame.h @@ -83,5 +83,5 @@ class CemiFrame // only for RF medium uint8_t* _rfSerialOrDoA = 0; uint8_t _rfInfo = 0; - uint8_t _rfLfn = 0; // RF Data Link layer frame number + uint8_t _rfLfn = 0xFF; // RF Data Link layer frame number }; \ No newline at end of file diff --git a/src/knx/cemi_server.cpp b/src/knx/cemi_server.cpp index f22d890..b36bccf 100644 --- a/src/knx/cemi_server.cpp +++ b/src/knx/cemi_server.cpp @@ -47,17 +47,21 @@ void CemiServer::dataConfirmationToTunnel(CemiFrame& frame) void CemiServer::dataIndicationToTunnel(CemiFrame& frame) { -#if MEDIUM_TYPE == 2 +#if MEDIUM_TYPE == 2 uint8_t data[frame.dataLength() + 10]; data[0] = L_data_ind; // Message Code - data[1] = 10; // Total additional info length + 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); + memcpy(&data[12], &((frame.data())[2]), frame.dataLength() - 2); +#else + uint8_t data[frame.dataLength()]; + memcpy(&data[0], frame.data(), frame.dataLength()); +#endif CemiFrame tmpFrame(data, sizeof(data)); @@ -67,21 +71,9 @@ void CemiServer::dataIndicationToTunnel(CemiFrame& frame) print(tmpFrame.destinationAddress(), HEX); printHex(" frame: ", tmpFrame.data(), tmpFrame.dataLength()); + tmpFrame.apdu().type(); _usbTunnelInterface.sendCemiFrame(tmpFrame); - -#else - - print("L_data_ind: src: "); - print(frame.sourceAddress(), HEX); - print(" dst: "); - print(frame.destinationAddress(), HEX); - - printHex(" frame: ", frame.data(), frame.dataLength()); - - _usbTunnelInterface.sendCemiFrame(frame); - -#endif } /* @@ -107,35 +99,33 @@ void CemiServer::frameReceived(CemiFrame& frame) frame.sourceAddress(_clientAddress); } -#if MEDIUM_TYPE == 2 +#if MEDIUM_TYPE == 2 // Check if we have additional info for RF - - uint8_t rfSerialOrDoA[6]; - uint8_t rfLfn; - 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.rfInfo((frame.data())[4]); // Use the values provided in the RF additonal info - memcpy(&rfSerialOrDoA, &((frame.data())[5]), 6); - rfLfn = (frame.data())[11]; - } - else - { - // Let the RF data link layer fill in its own values - memset(&rfSerialOrDoA, 0x00, 6); - rfLfn = 0xFF; + 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 ( (rfSerialOrDoA[0] == 0x00) && (rfSerialOrDoA[1] == 0x00) && (rfSerialOrDoA[2] == 0x00) && - (rfSerialOrDoA[3] == 0x00) && (rfSerialOrDoA[4] == 0x00) && (rfSerialOrDoA[5] == 0x00) ) + // 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) { - frame.rfSerialOrDoA(nullptr); - } - else - { - frame.rfSerialOrDoA(rfSerialOrDoA); + // Set Data Link Layer Frame Number + frame.rfLfn(_frameNumber); + // Link Layer frame number counts 0..7 + _frameNumber = (_frameNumber + 1) & 0x7; } #endif diff --git a/src/knx/cemi_server.h b/src/knx/cemi_server.h index e45c3a9..931a4a9 100644 --- a/src/knx/cemi_server.h +++ b/src/knx/cemi_server.h @@ -42,6 +42,7 @@ class CemiServer private: uint16_t _clientAddress; + uint8_t _frameNumber = 0; DataLinkLayer* _dataLinkLayer; BauSystemB& _bau; diff --git a/src/knx/data_link_layer.cpp b/src/knx/data_link_layer.cpp index 0bbb63f..298bdff 100644 --- a/src/knx/data_link_layer.cpp +++ b/src/knx/data_link_layer.cpp @@ -48,6 +48,7 @@ void DataLinkLayer::systemBroadcastRequest(AckType ack, FrameFormat format, Prio void DataLinkLayer::dataConReceived(CemiFrame& frame, bool success) { + MessageCode backupMsgCode = frame.messageCode(); frame.messageCode(L_data_con); frame.confirm(success ? ConfirmNoError : ConfirmError); AckType ack = frame.ack(); @@ -77,6 +78,8 @@ void DataLinkLayer::dataConReceived(CemiFrame& frame, bool success) _networkLayer.broadcastConfirm(ack, type, priority, source, npdu, success); else _networkLayer.dataConfirm(ack, addrType, destination, type, priority, source, npdu, success); + + frame.messageCode(backupMsgCode); } void DataLinkLayer::frameRecieved(CemiFrame& frame) @@ -172,6 +175,7 @@ bool DataLinkLayer::sendTelegram(NPDU & npdu, AckType ack, uint16_t destinationA tmpFrame.rfSerialOrDoA(frame.rfSerialOrDoA()); tmpFrame.rfInfo(frame.rfInfo()); tmpFrame.rfLfn(frame.rfLfn()); + tmpFrame.confirm(ConfirmNoError); _cemiServer->dataIndicationToTunnel(tmpFrame); } diff --git a/src/knx/rf_data_link_layer.cpp b/src/knx/rf_data_link_layer.cpp index fdbbc08..cbbe6c4 100644 --- a/src/knx/rf_data_link_layer.cpp +++ b/src/knx/rf_data_link_layer.cpp @@ -200,7 +200,7 @@ void RfDataLinkLayer::frameBytesReceived(uint8_t* rfPacketBuf, uint16_t length) // then we received the domain address and not the KNX serial number if (systemBroadcast == Broadcast) { - // Check if the received RF domain address matches the one stored in the RF medium object + // Check if the received RF domain address matches the one stored in the RF medium object // If it does not match then skip the remaining processing if (memcmp(_rfMediumObj.rfDomainAddress(), &rfPacketBuf[4], 6)) { diff --git a/src/knx/rf_medium_object.cpp b/src/knx/rf_medium_object.cpp index 0aaef2c..f6d10e7 100644 --- a/src/knx/rf_medium_object.cpp +++ b/src/knx/rf_medium_object.cpp @@ -41,6 +41,9 @@ void RfMediumObject::writeProperty(PropertyID id, uint32_t start, uint8_t* data, { 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];