diff --git a/examples/knx-linux/CMakeLists.txt b/examples/knx-linux/CMakeLists.txt index 24cff37..470dfaa 100644 --- a/examples/knx-linux/CMakeLists.txt +++ b/examples/knx-linux/CMakeLists.txt @@ -50,6 +50,7 @@ add_executable(knx-linux ../../src/knx/ip_parameter_object.cpp ../../src/knx/ip_parameter_object.h ../../src/knx/knx_ip_frame.cpp + ../../src/knx/knx_ip_routing_indication.cpp ../../src/knx/knx_value.cpp ../../src/knx/knx_value.h ../../src/knx/memory.cpp diff --git a/examples/knx-linux/knx-linux.vcxproj b/examples/knx-linux/knx-linux.vcxproj index a968974..b74baa1 100644 --- a/examples/knx-linux/knx-linux.vcxproj +++ b/examples/knx-linux/knx-linux.vcxproj @@ -99,6 +99,7 @@ + @@ -152,6 +153,7 @@ + diff --git a/examples/knx-linux/knx-linux.vcxproj.filters b/examples/knx-linux/knx-linux.vcxproj.filters index e4f7cab..fa8dd01 100644 --- a/examples/knx-linux/knx-linux.vcxproj.filters +++ b/examples/knx-linux/knx-linux.vcxproj.filters @@ -173,6 +173,9 @@ Header files + + Header files\knx + @@ -304,5 +307,8 @@ Source files\knx + + Source files\knx + \ No newline at end of file diff --git a/src/knx/device_object.cpp b/src/knx/device_object.cpp index 4c310b4..3d8e6c4 100644 --- a/src/knx/device_object.cpp +++ b/src/knx/device_object.cpp @@ -11,6 +11,8 @@ DeviceObject::DeviceObject() { //Default to KNXA (0xFA) uint8_t serialNumber[] = {0x00, 0xFA, 0x00, 0x00, 0x00, 0x00}; + uint8_t hardwareType[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t version[] = {0x00, 0x00, 0x03}; Property* properties[] = { @@ -27,7 +29,7 @@ DeviceObject::DeviceObject() }), new DataProperty(PID_DEVICE_CONTROL, true, PDT_BITSET8, 1, ReadLv3 | WriteLv3, (uint8_t)0), new DataProperty(PID_ORDER_INFO, false, PDT_GENERIC_10, 1, ReadLv3 | WriteLv0), - new DataProperty(PID_VERSION, false, PDT_VERSION, 1, ReadLv3 | WriteLv0, (uint16_t)3), + new DataProperty(PID_VERSION, false, PDT_VERSION, 1, ReadLv3 | WriteLv0, version), new DataProperty(PID_ROUTING_COUNT, true, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv3, (uint8_t)0), new CallbackProperty(this, PID_PROG_MODE, true, PDT_BITSET8, 1, ReadLv3 | WriteLv3, [](DeviceObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t @@ -66,9 +68,9 @@ DeviceObject::DeviceObject() *data = (io->_ownAddress & 0xff); return 1; }), - new DataProperty(PID_IO_LIST, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint8_t)0), - new DataProperty(PID_HARDWARE_TYPE, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv3, (uint8_t)0), - new DataProperty(PID_DEVICE_DESCRIPTOR, false, PDT_GENERIC_02, 1, ReadLv3 | WriteLv0, (uint8_t)0), + new DataProperty(PID_IO_LIST, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0), + new DataProperty(PID_HARDWARE_TYPE, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv3, hardwareType), + new DataProperty(PID_DEVICE_DESCRIPTOR, false, PDT_GENERIC_02, 1, ReadLv3 | WriteLv0), #ifdef USE_RF new DataProperty(PID_RF_DOMAIN_ADDRESS_CEMI_SERVER, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv3), #endif diff --git a/src/knx/ip_data_link_layer.cpp b/src/knx/ip_data_link_layer.cpp index f83fd0a..2cb2ad2 100644 --- a/src/knx/ip_data_link_layer.cpp +++ b/src/knx/ip_data_link_layer.cpp @@ -6,7 +6,7 @@ #include "platform.h" #include "device_object.h" #include "address_table_object.h" -#include "cemi_frame.h" +#include "knx_ip_routing_indication.h" #include #include @@ -14,8 +14,6 @@ #define KNXIP_HEADER_LEN 0x6 #define KNXIP_PROTOCOL_VERSION 0x10 -#define ROUTING_INDICATION 0x0530 - #define KNXIP_MULTICAST_PORT 3671 #define MIN_LEN_CEMI 10 @@ -26,20 +24,12 @@ IpDataLinkLayer::IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrT bool IpDataLinkLayer::sendFrame(CemiFrame& frame) { - uint16_t length = frame.totalLenght() + KNXIP_HEADER_LEN; - uint8_t* buffer = new uint8_t[length]; - buffer[0] = KNXIP_HEADER_LEN; - buffer[1] = KNXIP_PROTOCOL_VERSION; - pushWord(ROUTING_INDICATION, buffer + 2); - pushWord(length, buffer + 4); - - memcpy(buffer + KNXIP_HEADER_LEN, frameData(frame), frame.totalLenght()); + KnxIpRoutingIndication packet(frame); - bool success = sendBytes(buffer, length); + bool success = sendBytes(packet.data(), packet.totalLength()); // only send 50 packet per second: see KNX 3.2.6 p.6 delay(20); dataConReceived(frame, success); - delete[] buffer; return success; } @@ -62,15 +52,13 @@ void IpDataLinkLayer::loop() uint16_t code; popWord(code, buffer + 2); - if (code != ROUTING_INDICATION) // only routing indication for now - return; - - if (len < MIN_LEN_CEMI) - return; - - //TODO: Check correct length (additions Info + apdu length) - CemiFrame frame(buffer + KNXIP_HEADER_LEN, len - KNXIP_HEADER_LEN); - frameRecieved(frame); + switch ((KnxIpServiceType)code) + { + case RoutingIndication: + KnxIpRoutingIndication routingIndication(buffer, len); + frameRecieved(routingIndication.frame()); + break; + } } void IpDataLinkLayer::enabled(bool value) diff --git a/src/knx/knx_ip_frame.cpp b/src/knx/knx_ip_frame.cpp index 7527dd2..038a817 100644 --- a/src/knx/knx_ip_frame.cpp +++ b/src/knx/knx_ip_frame.cpp @@ -34,20 +34,43 @@ void KnxIpFrame::protocolVersion(KnxIpVersion version) uint16_t KnxIpFrame::serviceTypeIdentifier() const { - return 0; + return getWord(_data + 2); } void KnxIpFrame::serviceTypeIdentifier(uint16_t identifier) { + pushWord(identifier, _data + 2); } uint16_t KnxIpFrame::totalLength() const { - return getWord(_data + 2); + return getWord(_data + 4); } void KnxIpFrame::totalLength(uint16_t length) { - pushWord(length, _data + 2); + pushWord(length, _data + 4); +} +#endif + +uint8_t* KnxIpFrame::data() +{ + return _data; +} + + +KnxIpFrame::~KnxIpFrame() +{ + if (_freeData) + delete _data; +} + + +KnxIpFrame::KnxIpFrame(uint16_t length) +{ + _data = new uint8_t[length]; + _freeData = true; + headerLength(KNXIP_HEADER_LEN); + protocolVersion(KnxIp1_0); + totalLength(length); } -#endif \ No newline at end of file diff --git a/src/knx/knx_ip_frame.h b/src/knx/knx_ip_frame.h index 728ef30..b5ab6c8 100644 --- a/src/knx/knx_ip_frame.h +++ b/src/knx/knx_ip_frame.h @@ -3,9 +3,12 @@ #include "cemi_frame.h" #include "config.h" #ifdef USE_IP + +#define KNXIP_HEADER_LEN 0x6 + enum KnxIpVersion { - KnxIp1_0 + KnxIp1_0 = 0x10 }; enum KnxIpServiceType @@ -35,6 +38,8 @@ class KnxIpFrame { public: KnxIpFrame(uint8_t* data, uint16_t length); + KnxIpFrame(uint16_t totalLength); + virtual ~KnxIpFrame(); uint8_t headerLength() const; void headerLength(uint8_t length); KnxIpVersion protocolVersion() const; @@ -43,8 +48,10 @@ class KnxIpFrame void serviceTypeIdentifier(uint16_t identifier); uint16_t totalLength() const; void totalLength(uint16_t length); + uint8_t* data(); - private: + protected: + bool _freeData = false; uint8_t* _data = 0; }; #endif \ No newline at end of file diff --git a/src/knx/knx_ip_routing_indication.cpp b/src/knx/knx_ip_routing_indication.cpp new file mode 100644 index 0000000..df51576 --- /dev/null +++ b/src/knx/knx_ip_routing_indication.cpp @@ -0,0 +1,22 @@ +#include "knx_ip_routing_indication.h" +#include + +#ifdef USE_IP +CemiFrame& KnxIpRoutingIndication::frame() +{ + return _frame; +} + + +KnxIpRoutingIndication::KnxIpRoutingIndication(uint8_t* data, + uint16_t length) : KnxIpFrame(data, length), _frame(data + headerLength(), length - headerLength()) +{ +} + +KnxIpRoutingIndication::KnxIpRoutingIndication(CemiFrame frame) + : KnxIpFrame(frame.totalLenght() + KNXIP_HEADER_LEN), _frame(_data + headerLength(), frame.totalLenght()) +{ + serviceTypeIdentifier(RoutingIndication); + memcpy(_data + KNXIP_HEADER_LEN, frame.data(), frame.totalLenght()); +} +#endif \ No newline at end of file diff --git a/src/knx/knx_ip_routing_indication.h b/src/knx/knx_ip_routing_indication.h new file mode 100644 index 0000000..3de7975 --- /dev/null +++ b/src/knx/knx_ip_routing_indication.h @@ -0,0 +1,16 @@ +#pragma once + +#include "knx_ip_frame.h" +#include "cemi_frame.h" +#ifdef USE_IP + +class KnxIpRoutingIndication : public KnxIpFrame +{ + public: + KnxIpRoutingIndication(uint8_t* data, uint16_t length); + KnxIpRoutingIndication(CemiFrame frame); + CemiFrame& frame(); + private: + CemiFrame _frame; +}; +#endif \ No newline at end of file