diff --git a/src/knx/device_object.cpp b/src/knx/device_object.cpp index 0bcb866..38f327b 100644 --- a/src/knx/device_object.cpp +++ b/src/knx/device_object.cpp @@ -284,7 +284,10 @@ void DeviceObject::rfDomainAddress(uint8_t* value) prop->write(value); } - - - - +uint8_t DeviceObject::defaultHopCount() +{ + Property* prop = property(PID_ROUTING_COUNT); + uint8_t value; + prop->read(value); + return (value >> 4) & 0x07; +} diff --git a/src/knx/device_object.h b/src/knx/device_object.h index 023d840..12e6c8a 100644 --- a/src/knx/device_object.h +++ b/src/knx/device_object.h @@ -36,7 +36,8 @@ public: void maxApduLength(uint16_t value); const uint8_t* rfDomainAddress(); void rfDomainAddress(uint8_t* value); + uint8_t defaultHopCount(); private: uint8_t _prgMode = 0; uint16_t _ownAddress = 0; -}; \ No newline at end of file +}; diff --git a/src/knx/network_layer.cpp b/src/knx/network_layer.cpp new file mode 100644 index 0000000..498c197 --- /dev/null +++ b/src/knx/network_layer.cpp @@ -0,0 +1,97 @@ +#include "network_layer.h" +#include "device_object.h" +#include "tpdu.h" +#include "cemi_frame.h" +#include "bits.h" + +NetworkLayer::NetworkLayer(DeviceObject &deviceObj, TransportLayer& layer) : + _deviceObj(deviceObj), + _transportLayer(layer) +{ + _hopCount = _deviceObj.defaultHopCount(); +} + +uint8_t NetworkLayer::hopCount() const +{ + return _hopCount; +} + +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; + _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 new file mode 100644 index 0000000..1a21caa --- /dev/null +++ b/src/knx/network_layer.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include "knx_types.h" +#include "npdu.h" +#include "transport_layer.h" +#include "network_layer_entity.h" + +class DeviceObject; + +class NetworkLayer +{ + friend class NetworkLayerEntity; + + public: + NetworkLayer(DeviceObject& deviceObj, TransportLayer& layer); + + virtual NetworkLayerEntity& getEntity(uint8_t interfaceIndex) = 0; + + uint8_t hopCount() const; + + // from transport layer + virtual void dataIndividualRequest(AckType ack, uint16_t destination, HopCountType hopType, Priority priority, TPDU& tpdu) = 0; + virtual void dataGroupRequest(AckType ack, uint16_t destination, HopCountType hopType, Priority priority, TPDU& tpdu) = 0; + virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) = 0; + virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) = 0; + + protected: + DeviceObject& _deviceObj; + + // from entities + virtual void dataIndication(AckType ack, AddressType addType, uint16_t destination, FrameFormat format, NPDU& npdu, + Priority priority, uint16_t source); + virtual void dataConfirm(AckType ack, AddressType addressType, uint16_t destination, FrameFormat format, Priority priority, + uint16_t source, NPDU& npdu, bool status); + 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); + 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); + + private: + TransportLayer& _transportLayer; + uint8_t _hopCount = 6; +}; diff --git a/src/knx/network_layer_coupler.cpp b/src/knx/network_layer_coupler.cpp new file mode 100644 index 0000000..2fa3d7e --- /dev/null +++ b/src/knx/network_layer_coupler.cpp @@ -0,0 +1,126 @@ +#include "network_layer_coupler.h" +#include "device_object.h" +#include "tpdu.h" +#include "cemi_frame.h" +#include "bits.h" + +NetworkLayerCoupler::NetworkLayerCoupler(DeviceObject &deviceObj, TransportLayer& layer) : + NetworkLayer(deviceObj, layer), + _netLayerEntities { {*this, 0}, {*this, 1} } +{ +} + +NetworkLayerEntity& NetworkLayerCoupler::getEntity(uint8_t interfaceIndex) +{ + return _netLayerEntities[interfaceIndex]; +} + +void NetworkLayerCoupler::dataIndication(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) +{ + // 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 + 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) +{ + // 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); + } + // Do not process the frame any further +} + +void NetworkLayerCoupler::broadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) +{ + NetworkLayer::broadcastIndication(ack, format, npdu, priority, source); + + // TODO: implement routing +} + +void NetworkLayerCoupler::broadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) +{ + // 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); + } + // 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); + + // TODO: implement routing +} + +void NetworkLayerCoupler::systemBroadcastConfirm(AckType ack, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status) +{ + // 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); + } + // Do not process the frame any further +} + +void NetworkLayerCoupler::dataIndividualRequest(AckType ack, uint16_t destination, HopCountType hopType, Priority priority, TPDU& tpdu) +{ + NPDU& npdu = tpdu.frame().npdu(); + + if (hopType == UnlimitedRouting) + npdu.hopCount(7); + else + npdu.hopCount(hopCount()); + + //if (tpdu.apdu().length() > 0) + //{ + // print.print("-> NL "); + // tpdu.apdu().printPDU(); + //} + _netLayerEntities[0].sendDataRequest(npdu, ack, destination, priority, InduvidualAddress, Broadcast); +} + +void NetworkLayerCoupler::dataGroupRequest(AckType ack, uint16_t destination, HopCountType hopType, Priority priority, TPDU& tpdu) +{ + NPDU& npdu = tpdu.frame().npdu(); + + if (hopType == UnlimitedRouting) + npdu.hopCount(7); + else + npdu.hopCount(hopCount()); + + _netLayerEntities[0].sendDataRequest(npdu, ack, destination, priority, GroupAddress, Broadcast); +} + +void NetworkLayerCoupler::dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) +{ + NPDU& npdu = tpdu.frame().npdu(); + + if (hopType == UnlimitedRouting) + npdu.hopCount(7); + else + npdu.hopCount(hopCount()); + + _netLayerEntities[0].sendDataRequest(npdu, ack, 0, priority, GroupAddress, Broadcast); +} + +void NetworkLayerCoupler::dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) +{ + NPDU& npdu = tpdu.frame().npdu(); + + if (hopType == UnlimitedRouting) + npdu.hopCount(7); + else + npdu.hopCount(hopCount()); + + _netLayerEntities[0].sendDataRequest(npdu, ack, 0, priority, GroupAddress, SysBroadcast); +} diff --git a/src/knx/network_layer_coupler.h b/src/knx/network_layer_coupler.h new file mode 100644 index 0000000..4efd9b7 --- /dev/null +++ b/src/knx/network_layer_coupler.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include "knx_types.h" +#include "npdu.h" +#include "transport_layer.h" +#include "network_layer_entity.h" +#include "network_layer.h" + +class DeviceObject; + +class NetworkLayerCoupler : public NetworkLayer +{ + friend class NetworkLayerEntity; + + public: + NetworkLayerCoupler(DeviceObject& deviceObj, TransportLayer& layer); + + virtual NetworkLayerEntity& getEntity(uint8_t interfaceIndex) override; + + // from transport layer + virtual void dataIndividualRequest(AckType ack, uint16_t destination, HopCountType hopType, Priority priority, TPDU& tpdu) override; + virtual void dataGroupRequest(AckType ack, uint16_t destination, HopCountType hopType, Priority priority, TPDU& tpdu) override; + virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) override; + virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) override; + + private: + // 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 a maximum of two physical interfaces for couplers + NetworkLayerEntity _netLayerEntities[2]; +}; diff --git a/src/knx/network_layer_device.cpp b/src/knx/network_layer_device.cpp index d6bb5c4..22b5d8b 100644 --- a/src/knx/network_layer_device.cpp +++ b/src/knx/network_layer_device.cpp @@ -15,86 +15,6 @@ NetworkLayerEntity& NetworkLayerDevice::getEntity(uint8_t interfaceIndex) return _netLayerEntities[interfaceIndex]; } -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; - - // 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 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; - } - // destination == 0 - _transportLayer.dataBroadcastConfirm(ack, hopType, priority, npdu.tpdu(), status); -} - -void NetworkLayerDevice::broadcastIndication(AckType ack, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source) -{ - HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter; - _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); -} - void NetworkLayerDevice::dataIndividualRequest(AckType ack, uint16_t destination, HopCountType hopType, Priority priority, TPDU& tpdu) { NPDU& npdu = tpdu.frame().npdu(); diff --git a/src/knx/network_layer_device.h b/src/knx/network_layer_device.h index 4521108..fe8f620 100644 --- a/src/knx/network_layer_device.h +++ b/src/knx/network_layer_device.h @@ -25,18 +25,6 @@ class NetworkLayerDevice : public NetworkLayer virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, TPDU& tpdu) override; private: - // 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 addressType, 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 physical interface for normal devices NetworkLayerEntity _netLayerEntities[1]; };