From 589aec4585ebc38975cd6278ab4be44347fd6880 Mon Sep 17 00:00:00 2001 From: nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Tue, 3 Dec 2019 15:25:53 +0100 Subject: [PATCH] save work --- src/knx/bau27B0.cpp | 24 ++++-------------------- src/knx/bau_systemB.cpp | 5 +---- src/knx/cemi_server.cpp | 31 ++++++++++++++++++++++--------- src/knx/data_link_layer.cpp | 16 ++++++++++++++-- src/knx/device_object.cpp | 27 ++++++++++++++++++++------- src/knx/device_object.h | 5 +++-- src/knx/rf_data_link_layer.cpp | 17 +++++++---------- 7 files changed, 71 insertions(+), 54 deletions(-) diff --git a/src/knx/bau27B0.cpp b/src/knx/bau27B0.cpp index 6fc9228..4f2d753 100644 --- a/src/knx/bau27B0.cpp +++ b/src/knx/bau27B0.cpp @@ -118,50 +118,34 @@ void Bau27B0::loop() void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint8_t* rfDoA, uint8_t* knxSerialNumber) { - uint8_t curSerialNumber[6]; - pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]); - pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]); - // If the received serial number matches our serial number // then store the received RF domain address in the RF medium object - if (!memcmp(knxSerialNumber, curSerialNumber, 6)) + if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6)) _rfMediumObj.rfDomainAddress(rfDoA); } void Bau27B0::domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber) { - uint8_t curSerialNumber[6]; - pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]); - pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]); - // If the received serial number matches our serial number // then send a response with the current RF domain address stored in the RF medium object - if (!memcmp(knxSerialNumber, curSerialNumber, 6)) + if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6)) _appLayer.domainAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber); } void Bau27B0::individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint16_t newIndividualAddress, uint8_t* knxSerialNumber) { - uint8_t curSerialNumber[6]; - pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]); - pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]); - // If the received serial number matches our serial number // then store the received new individual address in the device object - if (!memcmp(knxSerialNumber, curSerialNumber, 6)) + if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6)) _deviceObj.induvidualAddress(newIndividualAddress); } void Bau27B0::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber) { - uint8_t curSerialNumber[6]; - pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]); - pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]); - // If the received serial number matches our serial number // then send a response with the current RF domain address stored in the RF medium object and the serial number - if (!memcmp(knxSerialNumber, curSerialNumber, 6)) + if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6)) _appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber); } diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index 16955c6..c508bb1 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -362,7 +362,6 @@ void BauSystemB::nextRestartState() void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType, uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength) { - uint8_t knxSerialNumber[6]; uint8_t operand; popByte(operand, testInfo + 1); // First byte (+ 0) contains only 4 reserved bits (0) @@ -375,10 +374,8 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun if (_deviceObj.progMode() && (objectType == OT_DEVICE) && (propertyId == PID_SERIAL_NUMBER)) { // Send reply. testResult data is KNX serial number - pushWord(_deviceObj.manufacturerId(), &knxSerialNumber[0]); - pushInt(_deviceObj.bauNumber(), &knxSerialNumber[2]); _appLayer.systemNetworkParameterReadResponse(priority, hopType, objectType, propertyId, - testInfo, testInfoLength, knxSerialNumber, sizeof(knxSerialNumber)); + testInfo, testInfoLength, (uint8_t*) _deviceObj.knxSerialNumber(), 6); } break; diff --git a/src/knx/cemi_server.cpp b/src/knx/cemi_server.cpp index 27e175a..f22d890 100644 --- a/src/knx/cemi_server.cpp +++ b/src/knx/cemi_server.cpp @@ -47,16 +47,16 @@ void CemiServer::dataConfirmationToTunnel(CemiFrame& frame) void CemiServer::dataIndicationToTunnel(CemiFrame& frame) { - static uint8_t lfn = 0; +#if MEDIUM_TYPE == 2 + uint8_t data[frame.dataLength() + 10]; - data[0] = L_data_ind; - data[1] = 10; - data[2] = 0x02; // RF Info add. info - data[3] = 0x08; // RF info length - data[4] = 0x02; // RF info field (batt ok) - pushByteArray(_bau.deviceObject().rfDomainAddress(), 6, &data[5]); - data[11] = lfn; - lfn = (lfn + 1) & 0x7; + data[0] = L_data_ind; // Message Code + data[1] = 10; // 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); CemiFrame tmpFrame(data, sizeof(data)); @@ -69,6 +69,19 @@ void CemiServer::dataIndicationToTunnel(CemiFrame& frame) printHex(" frame: ", tmpFrame.data(), tmpFrame.dataLength()); _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 } /* diff --git a/src/knx/data_link_layer.cpp b/src/knx/data_link_layer.cpp index bc8b21f..0bbb63f 100644 --- a/src/knx/data_link_layer.cpp +++ b/src/knx/data_link_layer.cpp @@ -157,13 +157,25 @@ bool DataLinkLayer::sendTelegram(NPDU & npdu, AckType ack, uint16_t destinationA // frame.apdu().printPDU(); // } + // The data link layer might be an open media link layer + // and will setup rfSerialOrDoA, rfInfo and rfLfn that we also + // have to send through the cEMI server tunnel + // Thus, reuse the modified cEMI frame as "frame" is only passed by reference here! + bool success = sendFrame(frame); + if (_cemiServer) { CemiFrame tmpFrame(frame.data(), frame.totalLenght()); + // We can just copy the pointer for rfSerialOrDoA as sendFrame() sets + // a pointer to const uint8_t data in either device object (serial) or + // RF medium object (domain address) + tmpFrame.rfSerialOrDoA(frame.rfSerialOrDoA()); + tmpFrame.rfInfo(frame.rfInfo()); + tmpFrame.rfLfn(frame.rfLfn()); _cemiServer->dataIndicationToTunnel(tmpFrame); } - - return sendFrame(frame); + + return success; } uint8_t* DataLinkLayer::frameData(CemiFrame& frame) diff --git a/src/knx/device_object.cpp b/src/knx/device_object.cpp index 1cace46..92b94e1 100644 --- a/src/knx/device_object.cpp +++ b/src/knx/device_object.cpp @@ -10,11 +10,10 @@ void DeviceObject::readProperty(PropertyID propertyId, uint32_t start, uint32_t& pushWord(OT_DEVICE, data); break; case PID_SERIAL_NUMBER: - pushWord(_manufacturerId, data); - pushInt(_bauNumber, data + 2); + pushByteArray((uint8_t*)_knxSerialNumber, 6, data); break; case PID_MANUFACTURER_ID: - pushWord(_manufacturerId, data); + pushByteArray(&_knxSerialNumber[0], 2, data); break; case PID_DEVICE_CONTROL: *data = _deviceControl; @@ -220,22 +219,36 @@ void DeviceObject::progMode(bool value) uint16_t DeviceObject::manufacturerId() { - return _manufacturerId; + uint16_t manufacturerId; + popWord(manufacturerId, &_knxSerialNumber[0]); + return manufacturerId; } void DeviceObject::manufacturerId(uint16_t value) { - _manufacturerId = value; + pushWord(value, &_knxSerialNumber[0]); } uint32_t DeviceObject::bauNumber() { - return _bauNumber; + uint32_t bauNumber; + popInt(bauNumber, &_knxSerialNumber[2]); + return bauNumber; } void DeviceObject::bauNumber(uint32_t value) { - _bauNumber = value; + pushInt(value, &_knxSerialNumber[2]); +} + +const uint8_t* DeviceObject::knxSerialNumber() +{ + return _knxSerialNumber; +} + +void DeviceObject::knxSerialNumber(const uint8_t* value) +{ + pushByteArray(value, 6, _knxSerialNumber); } const char* DeviceObject::orderNumber() diff --git a/src/knx/device_object.h b/src/knx/device_object.h index fa66cf8..3ecda36 100644 --- a/src/knx/device_object.h +++ b/src/knx/device_object.h @@ -29,6 +29,8 @@ public: void manufacturerId(uint16_t value); uint32_t bauNumber(); void bauNumber(uint32_t value); + const uint8_t* knxSerialNumber(); + void knxSerialNumber(const uint8_t* value); const char* orderNumber(); void orderNumber(const char* value); const uint8_t* hardwareType(); @@ -51,8 +53,7 @@ private: uint8_t _routingCount = 0; uint8_t _prgMode = 0; uint16_t _ownAddress = 0; - uint16_t _manufacturerId = 0xfa; //Default to KNXA - uint32_t _bauNumber = 0; + uint8_t _knxSerialNumber[6] = { 0x00, 0xFA, 0x00, 0x00, 0x00, 0x00 }; //Default to KNXA (0xFA) char _orderNumber[10] = ""; uint8_t _hardwareType[6] = { 0, 0, 0, 0, 0, 0}; uint16_t _version = 0; diff --git a/src/knx/rf_data_link_layer.cpp b/src/knx/rf_data_link_layer.cpp index 749fdfa..fdbbc08 100644 --- a/src/knx/rf_data_link_layer.cpp +++ b/src/knx/rf_data_link_layer.cpp @@ -23,12 +23,6 @@ void RfDataLinkLayer::loop() bool RfDataLinkLayer::sendFrame(CemiFrame& frame) { - if (!_enabled) - { - dataConReceived(frame, false); - return false; - } - // If no serial number of domain address was set, // use our own SN/DoA if (frame.rfSerialOrDoA() == nullptr) @@ -37,10 +31,7 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame) // or the RF domain address that was programmed by ETS if (frame.systemBroadcast() == SysBroadcast) { - uint8_t knxSerialNumber[6]; - pushWord(_deviceObject.manufacturerId(), &knxSerialNumber[0]); - pushInt(_deviceObject.bauNumber(), &knxSerialNumber[2]); - frame.rfSerialOrDoA(&knxSerialNumber[0]); + frame.rfSerialOrDoA((uint8_t*)_deviceObject.knxSerialNumber()); } else { @@ -61,6 +52,12 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame) // bidirectional device, battery is ok, signal strength indication is void (no measurement) frame.rfInfo(0x02); + if (!_enabled) + { + dataConReceived(frame, false); + return false; + } + // TODO: Is queueing really required? // According to the spec. the upper layer may only send a new L_Data.req if it received // the L_Data.con for the previous L_Data.req.