diff --git a/README.md b/README.md index 58f4d542..cab83a4b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ See the examples for basic usage options - the Device Management Connection is now handled independently from Tunnel Connections and do not consume a Tunnel PA anymore new compiler option KNX_TUNNELING_DEVMGMT (default = 1) to set the number of availible Device Management Connections - new Compiler Option KNX_ROUTING_BC_DC: Unicast packets from the device itself is sent to both interfaces (IP and TP in case of 0x091A) +- change default PID_MAX_APDU_LENGTH_ROUTER from 220 to 254 +- fix broken ConfigReq Responses +- fix programming application when FlashTablesInvalid for 0x091A ### v2.3.1 - 2026-03-04 diff --git a/src/knx/bau091A.cpp b/src/knx/bau091A.cpp index f0834f9e..c32bfef5 100644 --- a/src/knx/bau091A.cpp +++ b/src/knx/bau091A.cpp @@ -37,7 +37,7 @@ Bau091A::Bau091A(Platform& platform) { // Before accessing anything of the router object they have to be initialized according to the used medium // Coupler model 1.x - _routerObj.initialize1x(DptMedium::KNX_IP, 220); + _routerObj.initialize1x(DptMedium::KNX_IP, 254); // Mask 091A uses older coupler model 1.x which only uses one router object _netLayer.rtObj(_routerObj); diff --git a/src/knx/cemi_server.cpp b/src/knx/cemi_server.cpp index 3c00b60d..dae344c7 100644 --- a/src/knx/cemi_server.cpp +++ b/src/knx/cemi_server.cpp @@ -125,7 +125,7 @@ void CemiServer::dataIndicationToTunnel(CemiFrame& frame) #endif } -void CemiServer::frameReceived(CemiFrame& frame) +void CemiServer::frameReceived(CemiFrame& frame, uint8_t channelId) { switch(frame.messageCode()) { @@ -137,13 +137,13 @@ void CemiServer::frameReceived(CemiFrame& frame) case M_PropRead_req: { - handleMPropRead(frame); + handleMPropRead(frame, channelId); break; } case M_PropWrite_req: { - handleMPropWrite(frame); + handleMPropWrite(frame, channelId); break; } @@ -161,7 +161,7 @@ void CemiServer::frameReceived(CemiFrame& frame) case M_Reset_req: { - handleMReset(frame); + handleMReset(frame, channelId); break; } @@ -234,7 +234,7 @@ void CemiServer::handleLData(CemiFrame& frame) _dataLinkLayer->dataRequestFromTunnel(frame); } -void CemiServer::handleMPropRead(CemiFrame& frame) +void CemiServer::handleMPropRead(CemiFrame& frame, uint8_t channelId) { #ifdef KNX_LOG_TUNNELING print("M_PropRead_req: "); @@ -299,7 +299,7 @@ void CemiServer::handleMPropRead(CemiFrame& frame) #ifdef USE_USB _usbTunnelInterface.sendCemiFrame(responseFrame); #elif defined(KNX_TUNNELING) - _ipTunnelServer.dataRequestToTunnel(responseFrame); + _ipTunnelServer.dataRequestToChannelId(responseFrame, channelId); #endif delete[] data; } @@ -319,12 +319,12 @@ void CemiServer::handleMPropRead(CemiFrame& frame) #ifdef USE_USB _usbTunnelInterface.sendCemiFrame(responseFrame); #elif defined(KNX_TUNNELING) - _ipTunnelServer.dataRequestToTunnel(responseFrame); + _ipTunnelServer.dataRequestToChannelId(responseFrame, channelId); #endif } } -void CemiServer::handleMPropWrite(CemiFrame& frame) +void CemiServer::handleMPropWrite(CemiFrame& frame, uint8_t channelId) { print("M_PropWrite_req: "); @@ -389,7 +389,7 @@ void CemiServer::handleMPropWrite(CemiFrame& frame) #ifdef USE_USB _usbTunnelInterface.sendCemiFrame(responseFrame); #elif defined(KNX_TUNNELING) - _ipTunnelServer.dataRequestToTunnel(responseFrame); + _ipTunnelServer.dataRequestToChannelId(responseFrame, channelId); #endif } else @@ -408,12 +408,12 @@ void CemiServer::handleMPropWrite(CemiFrame& frame) #ifdef USE_USB _usbTunnelInterface.sendCemiFrame(responseFrame); #elif defined(KNX_TUNNELING) - _ipTunnelServer.dataRequestToTunnel(responseFrame); + _ipTunnelServer.dataRequestToChannelId(responseFrame, channelId); #endif } } -void CemiServer::handleMReset(CemiFrame& frame) +void CemiServer::handleMReset(CemiFrame& frame, uint8_t channelId) { println("M_Reset_req: sending M_Reset_ind"); // A real device reset does not work for USB or KNXNET/IP. @@ -427,7 +427,7 @@ void CemiServer::handleMReset(CemiFrame& frame) #ifdef USE_USB _usbTunnelInterface.sendCemiFrame(responseFrame); #elif defined(KNX_TUNNELING) - _ipTunnelServer.dataRequestToTunnel(responseFrame); + _ipTunnelServer.dataRequestToChannelId(responseFrame, channelId); #endif } diff --git a/src/knx/cemi_server.h b/src/knx/cemi_server.h index 64fb461b..f33375cd 100644 --- a/src/knx/cemi_server.h +++ b/src/knx/cemi_server.h @@ -44,7 +44,7 @@ class CemiServer void dataConfirmationToTunnel(CemiFrame& frame); // From tunnel interface - void frameReceived(CemiFrame& frame); + void frameReceived(CemiFrame& frame, uint8_t channelId); uint16_t clientAddress() const; void clientAddress(uint16_t value); @@ -56,9 +56,9 @@ class CemiServer uint8_t _frameNumber = 0; void handleLData(CemiFrame& frame); - void handleMPropRead(CemiFrame& frame); - void handleMPropWrite(CemiFrame& frame); - void handleMReset(CemiFrame& frame); + void handleMPropRead(CemiFrame& frame, uint8_t channelId); + void handleMPropWrite(CemiFrame& frame, uint8_t channelId); + void handleMReset(CemiFrame& frame, uint8_t channelId); DataLinkLayer* _dataLinkLayer = nullptr; #ifdef KNX_TUNNELING diff --git a/src/knx/ip_tunnel_server.cpp b/src/knx/ip_tunnel_server.cpp index e910d1b4..f6b8e4aa 100644 --- a/src/knx/ip_tunnel_server.cpp +++ b/src/knx/ip_tunnel_server.cpp @@ -50,6 +50,42 @@ void IpTunnelServer::loop() } } +void IpTunnelServer::dataRequestToChannelId(CemiFrame& frame, uint8_t channelId) +{ + KnxIpTunnelConnection* tun = nullptr; + for (int i = 0; i < KNX_TUNNELING + KNX_TUNNELING_DEVMGMT; i++) + { +#ifdef KNX_LOG_TUNNELING + print("Tunnel ChannelId: "); +#endif + if(tunnels[i].IsConfig) + { +#ifdef KNX_LOG_TUNNELING + print("Config "); +#endif + } +#ifdef KNX_LOG_TUNNELING + println(tunnels[i].ChannelId, 16); +#endif + if (tunnels[i].ChannelId == channelId) + { + tun = &tunnels[i]; + break; + } + } + + if (tun == nullptr) + { +#ifdef KNX_LOG_TUNNELING + print("Found no Tunnel for ChannelId: "); + println(channelId, 16); +#endif + return; + } + + sendFrameToTunnel(tun, frame); +} + void IpTunnelServer::dataRequestToTunnel(CemiFrame& frame) { if (frame.addressType() == AddressType::GroupAddress) @@ -750,7 +786,7 @@ void IpTunnelServer::HandleDeviceConfigurationRequest(uint8_t* buffer, uint16_t _platform.sendBytesUniCast(tun->IpAddress, tun->PortData, tunnAck.data(), tunnAck.totalLength()); tun->lastHeartbeat = millis(); - _cemiServer.frameReceived(confReq.frame()); + _cemiServer.frameReceived(confReq.frame(), tun->ChannelId); } void IpTunnelServer::HandleTunnelingRequest(uint8_t* buffer, uint16_t length) @@ -819,7 +855,7 @@ void IpTunnelServer::HandleTunnelingRequest(uint8_t* buffer, uint16_t length) if (tunnReq.frame().sourceAddress() == 0) tunnReq.frame().sourceAddress(tun->IndividualAddress); - _cemiServer.frameReceived(tunnReq.frame()); + _cemiServer.frameReceived(tunnReq.frame(), tun->ChannelId); } #endif \ No newline at end of file diff --git a/src/knx/ip_tunnel_server.h b/src/knx/ip_tunnel_server.h index 7e4d7e0f..4b25ee5b 100644 --- a/src/knx/ip_tunnel_server.h +++ b/src/knx/ip_tunnel_server.h @@ -24,6 +24,7 @@ class IpTunnelServer IpTunnelServer(DeviceObject& devObj, IpParameterObject& ipParam, Platform& platform, CemiServer& cemiServer); void loop(); + void dataRequestToChannelId(CemiFrame& frame, uint8_t channelId); void dataRequestToTunnel(CemiFrame& frame); void dataConfirmationToTunnel(CemiFrame& frame); void dataIndicationToTunnel(CemiFrame& frame); diff --git a/src/knx/memory.cpp b/src/knx/memory.cpp index c074b3df..4bb7dcc2 100644 --- a/src/knx/memory.cpp +++ b/src/knx/memory.cpp @@ -91,37 +91,56 @@ void Memory::readMemory() } println("restoring data from flash..."); - print("saverestores "); + print("Restore saveRestores: "); println(_saveCount); for (int i = 0; i < _saveCount; i++) { - println(flashStart - buffer); - println("."); buffer = _saveRestores[i]->restore(buffer); } - println("restored saveRestores"); + println("Restored saveRestores"); + +#if MASK_VERSION == 0x091A + if(versionCheck == FlashTablesInvalid) + { + println("TableObjects are referring to an older firmware version and are restored, unloaded and filled with 0xff"); + } +#else if (versionCheck == FlashTablesInvalid) { - println("TableObjects are referring to an older firmware version and are not loaded"); + println("TableObjects are referring to an older firmware version and are not restored"); return; } - print("tableObjs "); +#endif + print("Restore TableObjs: "); println(_tableObjCount); for (int i = 0; i < _tableObjCount; i++) { - println(flashStart - buffer); - println("."); buffer = _tableObjects[i]->restore(buffer); uint16_t memorySize = 0; buffer = popWord(memorySize, buffer); + print("Size: "); println(memorySize); if (memorySize == 0) continue; // this works because TableObject saves a relative addr and restores it itself addNewUsedBlock(_tableObjects[i]->_data, memorySize); + +#if MASK_VERSION == 0x091A + // load the tables but delete the data + if(versionCheck == FlashTablesInvalid) + { + println("unload and fill with 0xff"); + _tableObjects[i]->loadState(LS_UNLOADED); + uint32_t start = toRelative(_tableObjects[i]->_data); + uint8_t fillByte = 0xff; + uint32_t end = start + _tableObjects[i]->_size; + for(int i = start;i < end;i++) + writeMemory(i, 1, &fillByte); + } +#endif } - println("restored Tableobjects"); + println("restored TableObjects"); } void Memory::writeMemory()