diff --git a/src/knx/bau091A.cpp b/src/knx/bau091A.cpp index 5c1bf64..f1ee291 100644 --- a/src/knx/bau091A.cpp +++ b/src/knx/bau091A.cpp @@ -18,9 +18,6 @@ Bau091A::Bau091A(Platform& platform) _cemiServer(*this) #endif { - // TODO: setup callback for address check on TP1 medium which supports ACK - //_dlLayerSecondary.setAckRequiredCallback(); - // Before accessing anything of the two router objects they have to be initialized according to the used media combination _rtObjPrimary.initialize(1, DptMedium::KNX_IP, true, false, 201); _rtObjSecondary.initialize(2, DptMedium::KNX_TP1, false, true, 201); diff --git a/src/knx/bau2920.cpp b/src/knx/bau2920.cpp new file mode 100644 index 0000000..3fda0ba --- /dev/null +++ b/src/knx/bau2920.cpp @@ -0,0 +1,149 @@ +#include "config.h" +#include "bau2920.h" +#include "bits.h" +#include +#include + +#if defined(USE_TP) && defined (USE_RF) + +using namespace std; + +Bau2920::Bau2920(Platform& platform) + : BauSystemBCoupler(platform), + _rfMediumObject(), + _dlLayerPrimary(_deviceObj, _netLayer.getEntity(0), _platform, (ITpUartCallBacks&) *this), + _dlLayerSecondary(_deviceObj, _rfMediumObject, _netLayer.getEntity(1), platform) +#ifdef USE_CEMI_SERVER + , + _cemiServer(*this) +#endif +{ + // Before accessing anything of the two router objects they have to be initialized according to the used media combination + _rtObjPrimary.initialize(1, DptMedium::KNX_TP1, true, false, 201); + _rtObjSecondary.initialize(2, DptMedium::KNX_RF, false, true, 201); + + _netLayer.getEntity(0).dataLinkLayer(_dlLayerPrimary); + _netLayer.getEntity(1).dataLinkLayer(_dlLayerSecondary); + +#ifdef USE_CEMI_SERVER + _cemiServerObject.setMediumTypeAsSupported(DptMedium::KNX_TP1); + _cemiServerObject.setMediumTypeAsSupported(DptMedium::KNX_RF); + _cemiServer.dataLinkLayer(_dlLayerSecondary); // Secondary I/F is the important one! + _dlLayerSecondary.cemiServer(_cemiServer); + _memory.addSaveRestore(&_cemiServerObject); +#endif + + _memory.addSaveRestore(&_rtObjPrimary); + _memory.addSaveRestore(&_rtObjSecondary); + + _memory.addSaveRestore(&_rfMediumObject); + + // Set Mask Version in Device Object depending on the BAU + _deviceObj.maskVersion(0x2920); + + // Set which interface objects are available in the device object + // This differs from BAU to BAU with different medium types. + // See PID_IO_LIST + Property* prop = _deviceObj.property(PID_IO_LIST); + prop->write(1, (uint16_t) OT_DEVICE); + prop->write(2, (uint16_t) OT_ROUTER); + prop->write(3, (uint16_t) OT_ROUTER); + prop->write(3, (uint16_t) OT_APPLICATION_PROG); + prop->write(4, (uint16_t) OT_RF_MEDIUM); +#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER) + prop->write(5, (uint16_t) OT_SECURITY); + prop->write(6, (uint16_t) OT_CEMI_SERVER); +#elif defined(USE_DATASECURE) + prop->write(5, (uint16_t) OT_SECURITY); +#elif defined(USE_CEMI_SERVER) + prop->write(5, (uint16_t) OT_CEMI_SERVER); +#endif +} + +InterfaceObject* Bau2920::getInterfaceObject(uint8_t idx) +{ + switch (idx) + { + case 0: + return &_deviceObj; + case 1: + return &_rtObjPrimary; + case 2: + return &_rtObjSecondary; + case 3: + return &_appProgram; + case 4: + return &_rfMediumObject; +#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER) + case 5: + return &_secIfObj; + case 6: + return &_cemiServerObject; +#elif defined(USE_CEMI_SERVER) + case 5: + return &_cemiServerObject; +#elif defined(USE_DATASECURE) + case 5: + return &_secIfObj; +#endif + default: + return nullptr; + } +} + +InterfaceObject* Bau2920::getInterfaceObject(ObjectType objectType, uint8_t objectInstance) +{ + // We do not use it right now. + // Required for coupler mode as there are multiple router objects for example + (void) objectInstance; + + switch (objectType) + { + case OT_DEVICE: + return &_deviceObj; + case OT_ROUTER: + return objectInstance == 0 ? &_rtObjPrimary : &_rtObjSecondary; + case OT_APPLICATION_PROG: + return &_appProgram; + case OT_RF_MEDIUM: + return &_rfMediumObject; +#ifdef USE_DATASECURE + case OT_SECURITY: + return &_secIfObj; +#endif +#ifdef USE_CEMI_SERVER + case OT_CEMI_SERVER: + return &_cemiServerObject; +#endif + default: + return nullptr; + } +} + +void Bau2920::doMasterReset(EraseCode eraseCode, uint8_t channel) +{ + // Common SystemB objects + BauSystemBCoupler::doMasterReset(eraseCode, channel); + + _rfMediumObject.masterReset(eraseCode, channel); +} + +bool Bau2920::enabled() +{ + return _dlLayerPrimary.enabled() && _dlLayerSecondary.enabled(); +} + +void Bau2920::enabled(bool value) +{ + _dlLayerPrimary.enabled(value); + _dlLayerSecondary.enabled(value); +} + +void Bau2920::loop() +{ + _dlLayerPrimary.loop(); + _dlLayerSecondary.loop(); + BauSystemBCoupler::loop(); +} + +#endif diff --git a/src/knx/bau2920.h b/src/knx/bau2920.h new file mode 100644 index 0000000..9b8a029 --- /dev/null +++ b/src/knx/bau2920.h @@ -0,0 +1,34 @@ +#pragma once + +#include "config.h" +#if defined(USE_TP) && defined (USE_RF) +#include "bau_systemB_coupler.h" +#include "tpuart_data_link_layer.h" +#include "rf_physical_layer.h" +#include "rf_data_link_layer.h" +#include "rf_medium_object.h" +#include "cemi_server_object.h" + +class Bau2920 : public BauSystemBCoupler +{ + public: + Bau2920(Platform& platform); + virtual void loop() override; + virtual bool enabled() override; + virtual void enabled(bool value) override; + + protected: + InterfaceObject* getInterfaceObject(uint8_t idx); + InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance); + + virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override; + private: + RfMediumObject _rfMediumObject; + TpUartDataLinkLayer _dlLayerPrimary; + RfDataLinkLayer _dlLayerSecondary; +#ifdef USE_CEMI_SERVER + CemiServer _cemiServer; + CemiServerObject _cemiServerObject; +#endif +}; +#endif diff --git a/src/knx/bau_systemB_coupler.cpp b/src/knx/bau_systemB_coupler.cpp index 618ae02..092bfef 100644 --- a/src/knx/bau_systemB_coupler.cpp +++ b/src/knx/bau_systemB_coupler.cpp @@ -14,7 +14,7 @@ BauSystemBCoupler::BauSystemBCoupler(Platform& platform) : _appLayer(*this), #endif _transLayer(_appLayer), - _netLayer(_deviceObj, _transLayer) + _netLayer(_deviceObj, _rtObjPrimary, _rtObjSecondary, _transLayer) { _appLayer.transportLayer(_transLayer); _transLayer.networkLayer(_netLayer); diff --git a/src/knx/data_link_layer.h b/src/knx/data_link_layer.h index abcd5d8..479c3d8 100644 --- a/src/knx/data_link_layer.h +++ b/src/knx/data_link_layer.h @@ -29,7 +29,7 @@ class DataLinkLayer virtual void loop() = 0; virtual void enabled(bool value) = 0; virtual bool enabled() const = 0; - virtual bool isOpenMedium() const = 0; + virtual DptMedium mediumType() const = 0; protected: void frameRecieved(CemiFrame& frame); diff --git a/src/knx/ip_data_link_layer.cpp b/src/knx/ip_data_link_layer.cpp index 06f0b6d..d2df559 100644 --- a/src/knx/ip_data_link_layer.cpp +++ b/src/knx/ip_data_link_layer.cpp @@ -99,9 +99,9 @@ bool IpDataLinkLayer::enabled() const return _enabled; } -bool IpDataLinkLayer::isOpenMedium() const +DptMedium IpDataLinkLayer::mediumType() const { - return false; + return DptMedium::KNX_IP; } bool IpDataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length) diff --git a/src/knx/ip_data_link_layer.h b/src/knx/ip_data_link_layer.h index 46fee6d..a4a7e68 100644 --- a/src/knx/ip_data_link_layer.h +++ b/src/knx/ip_data_link_layer.h @@ -17,7 +17,7 @@ class IpDataLinkLayer : public DataLinkLayer void loop(); void enabled(bool value); bool enabled() const; - virtual bool isOpenMedium() const override; + virtual DptMedium mediumType() const override; private: bool _enabled = false; diff --git a/src/knx/network_layer.cpp b/src/knx/network_layer.cpp index a09c3b2..8da6f6c 100644 --- a/src/knx/network_layer.cpp +++ b/src/knx/network_layer.cpp @@ -11,18 +11,6 @@ NetworkLayer::NetworkLayer(DeviceObject &deviceObj, TransportLayer& layer) : _transportLayer(layer) { _hopCount = _deviceObj.defaultHopCount(); - - if ((_deviceObj.induvidualAddress() & 0x00FF) == 0x00) - { - if ((_deviceObj.induvidualAddress() & 0x0F00) == 0x0) - { - // Device is a backbone coupler -> individual address: x.0.0 - } - else - { - // Device is a line coupler -> individual address: x.y.0 - } - } } uint8_t NetworkLayer::hopCount() const @@ -49,93 +37,3 @@ bool NetworkLayer::isApciSystemBroadcast(APDU& apdu) return false; } -void NetworkLayer::dataIndication(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) -{ - HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; - - // Only for devices which are not a coupler - if (addrType == InduvidualAddress && destination != _deviceObj.induvidualAddress()) - return; - - // TODO: remove. getTSAP() will return 0 later anyway. Get rid of dependency to GAT - //if (addrType == GroupAddress && !_groupAddressTable.contains(destination)) - // return; - -// if (frame.npdu().octetCount() > 0) -// { -// _print("-> DLL "); -// frame.apdu().printPDU(); -// } - - if (addrType == InduvidualAddress) - { - //if (npdu.octetCount() > 0) - //{ - // print.print("<- NL "); - // npdu.frame().apdu().printPDU(); - //} - _transportLayer.dataIndividualIndication(destination, hopType, priority, source, npdu.tpdu()); - return; - } - // group-address type - if (destination != 0) - { - _transportLayer.dataGroupIndication(destination, hopType, priority, source, npdu.tpdu()); - return; - } - // destination == 0 - _transportLayer.dataBroadcastIndication(hopType, priority, source, npdu.tpdu()); -} - -void NetworkLayer::dataConfirm(AckType ack, AddressType addressType, uint16_t destination, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) -{ - HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; - if (addressType == InduvidualAddress) - { - _transportLayer.dataIndividualConfirm(ack, destination, hopType, priority, npdu.tpdu(), status); - return; - } - // group-address type - if (destination != 0) - { - _transportLayer.dataGroupConfirm(ack, source, destination, hopType, priority, npdu.tpdu(), status); - return; - } - // destination == 0 - _transportLayer.dataBroadcastConfirm(ack, hopType, priority, npdu.tpdu(), status); -} - -void NetworkLayer::broadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) -{ - HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; - - DataLinkLayer& dlLayer = getEntity(npdu.frame().sourceInterface()).dataLinkLayer(); - - // for closed media like TP1 and IP - if (!dlLayer.isOpenMedium() && isApciSystemBroadcast(npdu.tpdu().apdu())) - { - npdu.frame().systemBroadcast(SysBroadcast); - _transportLayer.dataSystemBroadcastIndication(hopType, priority, source, npdu.tpdu()); - return; - } - - _transportLayer.dataBroadcastIndication(hopType, priority, source, npdu.tpdu()); -} - -void NetworkLayer::broadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) -{ - HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; - _transportLayer.dataBroadcastConfirm(ack, hopType, priority, npdu.tpdu(), status); -} - -void NetworkLayer::systemBroadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) -{ - HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; - _transportLayer.dataSystemBroadcastIndication(hopType, priority, source, npdu.tpdu()); -} - -void NetworkLayer::systemBroadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) -{ - HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; - _transportLayer.dataSystemBroadcastConfirm(ack, hopType, npdu.tpdu(), priority, status); -} diff --git a/src/knx/network_layer.h b/src/knx/network_layer.h index 2e570fd..0467d84 100644 --- a/src/knx/network_layer.h +++ b/src/knx/network_layer.h @@ -29,20 +29,20 @@ class NetworkLayer protected: DeviceObject& _deviceObj; + TransportLayer& _transportLayer; // from entities virtual void dataIndication(AckType ack, AddressType addType, uint16_t destination, FrameFormat format, NPDU& npdu, - Priority priority, uint16_t source); + Priority priority, uint16_t source) = 0; virtual void dataConfirm(AckType ack, AddressType addressType, uint16_t destination, FrameFormat format, Priority priority, - uint16_t source, NPDU& npdu, bool status); + uint16_t source, NPDU& npdu, bool status) = 0; virtual void broadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, - Priority priority, uint16_t source); - virtual void broadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status); + Priority priority, uint16_t source) = 0; + virtual void broadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) = 0; virtual void systemBroadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, - Priority priority, uint16_t source); - virtual void systemBroadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status); + Priority priority, uint16_t source) = 0; + virtual void systemBroadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) = 0; private: - TransportLayer& _transportLayer; uint8_t _hopCount; // Network Layer Parameter hop_count for the device's own outgoing frames (default value from PID_ROUTING_COUNT) }; diff --git a/src/knx/network_layer_coupler.cpp b/src/knx/network_layer_coupler.cpp index 2fa3d7e..6d4e0e2 100644 --- a/src/knx/network_layer_coupler.cpp +++ b/src/knx/network_layer_coupler.cpp @@ -1,13 +1,30 @@ #include "network_layer_coupler.h" #include "device_object.h" +#include "router_object.h" #include "tpdu.h" #include "cemi_frame.h" #include "bits.h" -NetworkLayerCoupler::NetworkLayerCoupler(DeviceObject &deviceObj, TransportLayer& layer) : +NetworkLayerCoupler::NetworkLayerCoupler(DeviceObject &deviceObj, + RouterObject& rtObjPrimary, + RouterObject& rtObjSecondary, + TransportLayer& layer) : NetworkLayer(deviceObj, layer), - _netLayerEntities { {*this, 0}, {*this, 1} } + _netLayerEntities { {*this, 0}, {*this, 1} }, + _rtObjPrimary(rtObjPrimary), + _rtObjSecondary(rtObjSecondary) { + if ((_deviceObj.induvidualAddress() & 0x00FF) == 0x00) + { + if ((_deviceObj.induvidualAddress() & 0x0F00) == 0x0) + { + // Device is a backbone coupler -> individual address: x.0.0 + } + else + { + // Device is a line coupler -> individual address: x.y.0 + } + } } NetworkLayerEntity& NetworkLayerCoupler::getEntity(uint8_t interfaceIndex) @@ -17,47 +34,86 @@ NetworkLayerEntity& NetworkLayerCoupler::getEntity(uint8_t interfaceIndex) void NetworkLayerCoupler::dataIndication(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) { + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + + // TODO: implement routing + // Check if received frame is for us, we are a normal device in this case if (addrType == InduvidualAddress && destination == _deviceObj.induvidualAddress()) { - NetworkLayer::dataIndication(ack, addrType, destination, format, npdu, priority, source); - // Do not process the frame any further + _transportLayer.dataIndividualIndication(destination, hopType, priority, source, npdu.tpdu()); + return; + } + + // group-address type + if (destination != 0) + { + _transportLayer.dataGroupIndication(destination, hopType, priority, source, npdu.tpdu()); return; } - // TODO: implement routing } void NetworkLayerCoupler::dataConfirm(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) { + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + // Check if received frame is an echo from our sent frame, we are a normal device in this case if (source == _deviceObj.induvidualAddress()) { - NetworkLayer::dataConfirm(ack, addrType, destination, format, priority, source, npdu, status); + if (addrType == InduvidualAddress) + { + _transportLayer.dataIndividualConfirm(ack, destination, hopType, priority, npdu.tpdu(), status); + return; + } + // group-address type + if (destination != 0) + { + _transportLayer.dataGroupConfirm(ack, source, destination, hopType, priority, npdu.tpdu(), status); + return; + } } - // Do not process the frame any further + + // Do not process the frame any further if it was a routed frame sent from network layer } void NetworkLayerCoupler::broadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) { - NetworkLayer::broadcastIndication(ack, format, npdu, priority, source); + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + + uint8_t sourceInterfaceIndex = npdu.frame().sourceInterface(); + DptMedium mediumType = getEntity(sourceInterfaceIndex).mediumType(); + + // for closed media like TP1 and IP + if ( ((mediumType == DptMedium::KNX_TP1) || (mediumType == DptMedium::KNX_IP)) && + isApciSystemBroadcast(npdu.tpdu().apdu())) + { + npdu.frame().systemBroadcast(SysBroadcast); + _transportLayer.dataSystemBroadcastIndication(hopType, priority, source, npdu.tpdu()); + return; + } + + _transportLayer.dataBroadcastIndication(hopType, priority, source, npdu.tpdu()); // TODO: implement routing } void NetworkLayerCoupler::broadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) { + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + // Check if received frame is an echo from our sent frame, we are a normal device in this case if (source == _deviceObj.induvidualAddress()) { - NetworkLayer::broadcastConfirm(ack, format, priority, source, npdu, status); + _transportLayer.dataBroadcastConfirm(ack, hopType, priority, npdu.tpdu(), status); } // Do not process the frame any further } void NetworkLayerCoupler::systemBroadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) { - NetworkLayer::systemBroadcastIndication(ack, format, npdu, priority, source); + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + _transportLayer.dataSystemBroadcastIndication(hopType, priority, source, npdu.tpdu()); // TODO: implement routing } @@ -67,7 +123,8 @@ void NetworkLayerCoupler::systemBroadcastConfirm(AckType ack, FrameFormat format // Check if received frame is an echo from our sent frame, we are a normal device in this case if (source == _deviceObj.induvidualAddress()) { - NetworkLayer::systemBroadcastConfirm(ack, format, priority, source, npdu, status); + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + _transportLayer.dataSystemBroadcastConfirm(ack, hopType, npdu.tpdu(), priority, status); } // Do not process the frame any further } diff --git a/src/knx/network_layer_coupler.h b/src/knx/network_layer_coupler.h index 4efd9b7..eca37c3 100644 --- a/src/knx/network_layer_coupler.h +++ b/src/knx/network_layer_coupler.h @@ -8,13 +8,15 @@ #include "network_layer.h" class DeviceObject; +class RouterObject; class NetworkLayerCoupler : public NetworkLayer { friend class NetworkLayerEntity; public: - NetworkLayerCoupler(DeviceObject& deviceObj, TransportLayer& layer); + NetworkLayerCoupler(DeviceObject& deviceObj, RouterObject& rtObjPrimary, + RouterObject& rtObjSecondary, TransportLayer& layer); virtual NetworkLayerEntity& getEntity(uint8_t interfaceIndex) override; @@ -39,4 +41,7 @@ class NetworkLayerCoupler : public NetworkLayer // Support a maximum of two physical interfaces for couplers NetworkLayerEntity _netLayerEntities[2]; + + RouterObject& _rtObjPrimary; + RouterObject& _rtObjSecondary; }; diff --git a/src/knx/network_layer_device.cpp b/src/knx/network_layer_device.cpp index 22b5d8b..e20c475 100644 --- a/src/knx/network_layer_device.cpp +++ b/src/knx/network_layer_device.cpp @@ -58,6 +58,10 @@ void NetworkLayerDevice::dataBroadcastRequest(AckType ack, HopCountType hopType, void NetworkLayerDevice::dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) { + // for closed media like TP1 and IP + bool isClosedMedium = (getEntity(0).mediumType() == DptMedium::KNX_TP1) || (getEntity(0).mediumType() == DptMedium::KNX_IP); + SystemBroadcast broadcastType = (isClosedMedium && isApciSystemBroadcast(tpdu.apdu()) ? Broadcast : SysBroadcast); + NPDU& npdu = tpdu.frame().npdu(); if (hopType == UnlimitedRouting) @@ -65,5 +69,79 @@ void NetworkLayerDevice::dataSystemBroadcastRequest(AckType ack, HopCountType ho else npdu.hopCount(hopCount()); - _netLayerEntities[0].sendDataRequest(npdu, ack, 0, priority, GroupAddress, SysBroadcast); + _netLayerEntities[0].sendDataRequest(npdu, ack, 0, priority, GroupAddress, broadcastType); +} + +void NetworkLayerDevice::dataIndication(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) +{ + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + + if (addrType == InduvidualAddress) + { + if (destination != _deviceObj.induvidualAddress()) + return; + + _transportLayer.dataIndividualIndication(destination, hopType, priority, source, npdu.tpdu()); + return; + } + + // group-address type + if (destination != 0) + { + _transportLayer.dataGroupIndication(destination, hopType, priority, source, npdu.tpdu()); + return; + } +} + +void NetworkLayerDevice::dataConfirm(AckType ack, AddressType addressType, uint16_t destination, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) +{ + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + if (addressType == InduvidualAddress) + { + _transportLayer.dataIndividualConfirm(ack, destination, hopType, priority, npdu.tpdu(), status); + return; + } + // group-address type + if (destination != 0) + { + _transportLayer.dataGroupConfirm(ack, source, destination, hopType, priority, npdu.tpdu(), status); + return; + } +} + +void NetworkLayerDevice::broadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) +{ + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + + uint8_t sourceInterfaceIndex = npdu.frame().sourceInterface(); + DptMedium mediumType = getEntity(sourceInterfaceIndex).mediumType(); + + // for closed media like TP1 and IP + if ( ((mediumType == DptMedium::KNX_TP1) || (mediumType == DptMedium::KNX_IP)) && + isApciSystemBroadcast(npdu.tpdu().apdu())) + { + npdu.frame().systemBroadcast(SysBroadcast); + _transportLayer.dataSystemBroadcastIndication(hopType, priority, source, npdu.tpdu()); + return; + } + + _transportLayer.dataBroadcastIndication(hopType, priority, source, npdu.tpdu()); +} + +void NetworkLayerDevice::broadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) +{ + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + _transportLayer.dataBroadcastConfirm(ack, hopType, priority, npdu.tpdu(), status); +} + +void NetworkLayerDevice::systemBroadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) +{ + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + _transportLayer.dataSystemBroadcastIndication(hopType, priority, source, npdu.tpdu()); +} + +void NetworkLayerDevice::systemBroadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) +{ + HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; + _transportLayer.dataSystemBroadcastConfirm(ack, hopType, npdu.tpdu(), priority, status); } diff --git a/src/knx/network_layer_device.h b/src/knx/network_layer_device.h index fe8f620..9d8143e 100644 --- a/src/knx/network_layer_device.h +++ b/src/knx/network_layer_device.h @@ -25,6 +25,18 @@ class NetworkLayerDevice : public NetworkLayer virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) override; private: - // Support only physical interface for normal devices + // from entities + virtual void dataIndication(AckType ack, AddressType addType, uint16_t destination, FrameFormat format, NPDU& npdu, + Priority priority, uint16_t source) override; + virtual void dataConfirm(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, Priority priority, + uint16_t source, NPDU& npdu, bool status) override; + virtual void broadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, + Priority priority, uint16_t source) override; + virtual void broadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) override; + virtual void systemBroadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, + Priority priority, uint16_t source) override; + virtual void systemBroadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) override; + + // Support only a single physical interface for normal devices NetworkLayerEntity _netLayerEntities[1]; }; diff --git a/src/knx/network_layer_entity.cpp b/src/knx/network_layer_entity.cpp index 0fca763..2367753 100644 --- a/src/knx/network_layer_entity.cpp +++ b/src/knx/network_layer_entity.cpp @@ -19,6 +19,11 @@ DataLinkLayer& NetworkLayerEntity::dataLinkLayer() return *_dataLinkLayer; } +DptMedium NetworkLayerEntity::mediumType() const +{ + return _dataLinkLayer->mediumType(); +} + void NetworkLayerEntity::dataIndication(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) { npdu.frame().sourceInterface(_entityIndex); diff --git a/src/knx/network_layer_entity.h b/src/knx/network_layer_entity.h index 4071612..f386173 100644 --- a/src/knx/network_layer_entity.h +++ b/src/knx/network_layer_entity.h @@ -18,6 +18,8 @@ class NetworkLayerEntity void dataLinkLayer(DataLinkLayer& layer); DataLinkLayer& dataLinkLayer(); + DptMedium mediumType() const; + // from data link layer void dataIndication(AckType ack, AddressType addType, uint16_t destination, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source); diff --git a/src/knx/rf_data_link_layer.cpp b/src/knx/rf_data_link_layer.cpp index b8f4930..fb3b3be 100644 --- a/src/knx/rf_data_link_layer.cpp +++ b/src/knx/rf_data_link_layer.cpp @@ -269,9 +269,9 @@ bool RfDataLinkLayer::enabled() const return _enabled; } -bool RfDataLinkLayer::isOpenMedium() const +DptMedium RfDataLinkLayer::mediumType() const { - return true; + return DptMedium::KNX_RF; } void RfDataLinkLayer::fillRfFrame(CemiFrame& frame, uint8_t* data) diff --git a/src/knx/rf_data_link_layer.h b/src/knx/rf_data_link_layer.h index 71902e7..849d12a 100644 --- a/src/knx/rf_data_link_layer.h +++ b/src/knx/rf_data_link_layer.h @@ -25,7 +25,7 @@ class RfDataLinkLayer : public DataLinkLayer void loop(); void enabled(bool value); bool enabled() const; - virtual bool isOpenMedium() const override; + virtual DptMedium mediumType() const override; private: bool _enabled = false; diff --git a/src/knx/tpuart_data_link_layer.cpp b/src/knx/tpuart_data_link_layer.cpp index 2ce4418..c55ab62 100644 --- a/src/knx/tpuart_data_link_layer.cpp +++ b/src/knx/tpuart_data_link_layer.cpp @@ -466,9 +466,9 @@ bool TpUartDataLinkLayer::enabled() const return _enabled; } -bool TpUartDataLinkLayer::isOpenMedium() const +DptMedium TpUartDataLinkLayer::mediumType() const { - return false; + return DptMedium::KNX_TP1; } bool TpUartDataLinkLayer::sendSingleFrameByte() diff --git a/src/knx/tpuart_data_link_layer.h b/src/knx/tpuart_data_link_layer.h index bc2de7b..74a1d78 100644 --- a/src/knx/tpuart_data_link_layer.h +++ b/src/knx/tpuart_data_link_layer.h @@ -27,7 +27,7 @@ class TpUartDataLinkLayer : public DataLinkLayer void loop(); void enabled(bool value); bool enabled() const; - virtual bool isOpenMedium() const override; + virtual DptMedium mediumType() const override; private: bool _enabled = false;