diff --git a/examples/knx-linux/CMakeLists.txt b/examples/knx-linux/CMakeLists.txt
index 3389d64..9660b58 100644
--- a/examples/knx-linux/CMakeLists.txt
+++ b/examples/knx-linux/CMakeLists.txt
@@ -49,9 +49,13 @@ add_executable(knx-linux
../../src/knx/ip_data_link_layer.h
../../src/knx/ip_parameter_object.cpp
../../src/knx/ip_parameter_object.h
+ ../../src/knx/knx_ip_device_information_dib.cpp
+ ../../src/knx/knx_ip_dib.cpp
../../src/knx/knx_ip_frame.cpp
../../src/knx/knx_ip_routing_indication.cpp
../../src/knx/knx_ip_search_request.cpp
+ ../../src/knx/knx_ip_search_response.cpp
+ ../../src/knx/knx_ip_supported_service_dib.cpp
../../src/knx/ip_host_protocol_address_information.cpp
../../src/knx/knx_value.cpp
../../src/knx/knx_value.h
@@ -87,7 +91,7 @@ add_executable(knx-linux
main.cpp)
target_link_libraries(knx-linux "${LIBRARIES_FROM_REFERENCES}")
include_directories(../../src)
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wno-unknown-pragmas -Wno-switch -g -O0")
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wno-unknown-pragmas -Wno-switch -g -O0")
+set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wno-unknown-pragmas -g -O0")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wno-unknown-pragmas -g -O0")
set_property(TARGET knx-linux PROPERTY CXX_STANDARD 11)
add_definitions(-DMEDIUM_TYPE=5)
diff --git a/examples/knx-linux/knx-linux-Debug.vgdbsettings b/examples/knx-linux/knx-linux-Debug.vgdbsettings
index 2b12566..5c17819 100644
--- a/examples/knx-linux/knx-linux-Debug.vgdbsettings
+++ b/examples/knx-linux/knx-linux-Debug.vgdbsettings
@@ -7,7 +7,7 @@
RemoteUnix
- Suzail
+ Immerlund
SSH
tkunze
@@ -36,6 +36,7 @@
false
true
+
true
true
diff --git a/examples/knx-linux/knx-linux.vcxproj b/examples/knx-linux/knx-linux.vcxproj
index aeca3e7..ed5230c 100644
--- a/examples/knx-linux/knx-linux.vcxproj
+++ b/examples/knx-linux/knx-linux.vcxproj
@@ -99,11 +99,13 @@
+
+
@@ -157,11 +159,13 @@
+
+
diff --git a/examples/knx-linux/knx-linux.vcxproj.filters b/examples/knx-linux/knx-linux.vcxproj.filters
index be2aad8..3f4a28a 100644
--- a/examples/knx-linux/knx-linux.vcxproj.filters
+++ b/examples/knx-linux/knx-linux.vcxproj.filters
@@ -188,6 +188,12 @@
Header files\knx
+
+ Header files\knx
+
+
+ Header files\knx
+
@@ -334,5 +340,11 @@
Source files\knx
+
+ Source files\knx
+
+
+ Source files\knx
+
\ No newline at end of file
diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp
index 45ae21c..2e2403e 100644
--- a/src/knx/application_layer.cpp
+++ b/src/knx/application_layer.cpp
@@ -51,6 +51,9 @@ void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priori
break;
case GroupValueWrite:
_bau.groupValueWriteIndication(asap, priority, hopType, data, len);
+ default:
+ /* other apdutypes ar not valid here. If the appear do nothing */
+ break;
}
}
}
@@ -68,6 +71,9 @@ void ApplicationLayer::dataGroupConfirm(AckType ack, HopCountType hopType, Prior
case GroupValueWrite:
_bau.groupValueWriteLocalConfirm(ack, _savedAsapWriteRequest, priority, hopType, apdu.data(), apdu.length() - 1, status);
break;
+ default:
+ print("datagroup-confirm: unhandled APDU-Type: ");
+ println(apdu.type());
}
}
@@ -111,6 +117,9 @@ void ApplicationLayer::dataBroadcastIndication(HopCountType hopType, Priority pr
_bau.individualAddressSerialNumberWriteIndication(priority, hopType, newIndividualAddress, knxSerialNumber);
break;
}
+ default:
+ print("Broadcast-indication: unhandled APDU-Type: ");
+ println(apdu.type());
}
}
@@ -149,6 +158,9 @@ void ApplicationLayer::dataBroadcastConfirm(AckType ack, HopCountType hopType, P
_bau.individualAddressSerialNumberWriteLocalConfirm(ack, hopType, data + 1, newAddress, status);
break;
}
+ default:
+ print("Broadcast-confirm: unhandled APDU-Type: ");
+ println(apdu.type());
}
}
@@ -791,6 +803,9 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior
case KeyResponse:
_bau.keyWriteAppLayerConfirm(priority, hopType, tsap, data[1]);
break;
+ default:
+ print("Indiviual-indication: unhandled APDU-Type: ");
+ println(apdu.type());
}
}
@@ -887,6 +902,9 @@ void ApplicationLayer::individualConfirm(AckType ack, HopCountType hopType, Prio
case KeyResponse:
_bau.keyWriteResponseConfirm(ack, priority, hopType, tsap, data[1], status);
break;
+ default:
+ print("Indiviual-confirm: unhandled APDU-Type: ");
+ println(apdu.type());
}
}
diff --git a/src/knx/bau27B0.cpp b/src/knx/bau27B0.cpp
index 253798f..bbddef4 100644
--- a/src/knx/bau27B0.cpp
+++ b/src/knx/bau27B0.cpp
@@ -121,7 +121,7 @@ void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCou
{
// If the received serial number matches our serial number
// then store the received RF domain address in the RF medium object
- if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6))
+ if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_rfMediumObj.rfDomainAddress(rfDoA);
}
@@ -129,7 +129,7 @@ void Bau27B0::domainAddressSerialNumberReadIndication(Priority priority, HopCoun
{
// 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, _deviceObj.knxSerialNumber(), 6))
+ if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_appLayer.domainAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
}
@@ -138,7 +138,7 @@ void Bau27B0::individualAddressSerialNumberWriteIndication(Priority priority, Ho
{
// If the received serial number matches our serial number
// then store the received new individual address in the device object
- if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6))
+ if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_deviceObj.induvidualAddress(newIndividualAddress);
}
@@ -146,7 +146,7 @@ void Bau27B0::individualAddressSerialNumberReadIndication(Priority priority, Hop
{
// 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, _deviceObj.knxSerialNumber(), 6))
+ if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
}
diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp
index e6e842d..8f44ef1 100644
--- a/src/knx/bau_systemB.cpp
+++ b/src/knx/bau_systemB.cpp
@@ -378,7 +378,7 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun
{
// Send reply. testResult data is KNX serial number
_appLayer.systemNetworkParameterReadResponse(priority, hopType, objectType, propertyId,
- testInfo, testInfoLength, (uint8_t*) _deviceObj.knxSerialNumber(), 6);
+ testInfo, testInfoLength, (uint8_t*)_deviceObj.propertyData(PID_SERIAL_NUMBER), 6);
}
break;
diff --git a/src/knx/device_object.cpp b/src/knx/device_object.cpp
index b24636e..1f23b49 100644
--- a/src/knx/device_object.cpp
+++ b/src/knx/device_object.cpp
@@ -23,7 +23,7 @@ DeviceObject::DeviceObject()
if(start == 0)
return 1;
- pushByteArray(io->knxSerialNumber(), 2, data);
+ pushByteArray(io->propertyData(PID_SERIAL_NUMBER), 2, data);
return 1;
}),
new DataProperty(PID_DEVICE_CONTROL, true, PDT_BITSET8, 1, ReadLv3 | WriteLv3, (uint8_t)0),
@@ -161,43 +161,31 @@ void DeviceObject::progMode(bool value)
uint16_t DeviceObject::manufacturerId()
{
uint16_t manufacturerId;
- popWord(manufacturerId, knxSerialNumber());
+ popWord(manufacturerId, propertyData(PID_SERIAL_NUMBER));
return manufacturerId;
}
void DeviceObject::manufacturerId(uint16_t value)
{
uint8_t data[LEN_KNX_SERIAL];
- memcpy(data, knxSerialNumber(), LEN_KNX_SERIAL);
+ memcpy(data, propertyData(PID_SERIAL_NUMBER), LEN_KNX_SERIAL);
pushWord(value, data);
- knxSerialNumber(data);
+ propertyValue(PID_SERIAL_NUMBER, data);
}
uint32_t DeviceObject::bauNumber()
{
uint32_t bauNumber;
- popInt(bauNumber, knxSerialNumber() + 2);
+ popInt(bauNumber, propertyData(PID_SERIAL_NUMBER) + 2);
return bauNumber;
}
void DeviceObject::bauNumber(uint32_t value)
{
uint8_t data[LEN_KNX_SERIAL];
- memcpy(data, knxSerialNumber(), LEN_KNX_SERIAL);
+ memcpy(data, propertyData(PID_SERIAL_NUMBER), LEN_KNX_SERIAL);
pushInt(value, data + 2);
- knxSerialNumber(data);
-}
-
-const uint8_t* DeviceObject::knxSerialNumber()
-{
- DataProperty* prop = (DataProperty*)property(PID_SERIAL_NUMBER);
- return prop->data();
-}
-
-void DeviceObject::knxSerialNumber(const uint8_t* value)
-{
- Property* prop = property(PID_SERIAL_NUMBER);
- prop->write(value);
+ propertyValue(PID_SERIAL_NUMBER, data);
}
const uint8_t* DeviceObject::orderNumber()
diff --git a/src/knx/device_object.h b/src/knx/device_object.h
index 6a9a21c..023d840 100644
--- a/src/knx/device_object.h
+++ b/src/knx/device_object.h
@@ -24,8 +24,6 @@ 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 uint8_t* orderNumber();
void orderNumber(const uint8_t* value);
const uint8_t* hardwareType();
diff --git a/src/knx/interface_object.cpp b/src/knx/interface_object.cpp
index 51632cc..20276f6 100644
--- a/src/knx/interface_object.cpp
+++ b/src/knx/interface_object.cpp
@@ -1,6 +1,7 @@
#include
#include "interface_object.h"
+#include "data_property.h"
InterfaceObject::~InterfaceObject()
{
@@ -217,3 +218,10 @@ const Property* InterfaceObject::property(PropertyID id) const
return nullptr;
}
+
+
+const uint8_t* InterfaceObject::propertyData(PropertyID id)
+{
+ DataProperty* prop = (DataProperty*)property(id);
+ return prop->data();
+}
diff --git a/src/knx/interface_object.h b/src/knx/interface_object.h
index ad5f614..03f93e9 100644
--- a/src/knx/interface_object.h
+++ b/src/knx/interface_object.h
@@ -125,6 +125,24 @@ class InterfaceObject : public SaveRestore
*/
Property* property(PropertyID id);
+ template
+ T propertyValue(PropertyID id)
+ {
+ const Property* prop = property(id);
+
+ T value = 0;
+ prop->read(value);
+ return value;
+ }
+
+ template
+ void propertyValue(PropertyID id, T value)
+ {
+ Property* prop = property(id);
+ prop->write(value);
+ }
+
+ const uint8_t* propertyData(PropertyID id);
/**
* Gets const property with PropertyID id if it exists and nullptr otherwise.
*/
diff --git a/src/knx/ip_data_link_layer.cpp b/src/knx/ip_data_link_layer.cpp
index ccd3e33..7219508 100644
--- a/src/knx/ip_data_link_layer.cpp
+++ b/src/knx/ip_data_link_layer.cpp
@@ -8,6 +8,7 @@
#include "address_table_object.h"
#include "knx_ip_routing_indication.h"
#include "knx_ip_search_request.h"
+#include "knx_ip_search_response.h"
#include
#include
@@ -15,7 +16,6 @@
#define KNXIP_HEADER_LEN 0x6
#define KNXIP_PROTOCOL_VERSION 0x10
-#define KNXIP_MULTICAST_PORT 3671
#define MIN_LEN_CEMI 10
IpDataLinkLayer::IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam,
@@ -64,6 +64,10 @@ void IpDataLinkLayer::loop()
case SearchRequest:
{
KnxIpSearchRequest searchRequest(buffer, len);
+ KnxIpSearchResponse searchResponse(_ipParameters, _deviceObject);
+
+ auto hpai = searchRequest.hpai();
+ _platform.sendBytesUniCast(hpai.ipAddress(), hpai.ipPortNumber(), searchResponse.data(), searchResponse.totalLength());
break;
}
default:
@@ -78,7 +82,7 @@ void IpDataLinkLayer::enabled(bool value)
// _println(_deviceObject.induvidualAddress());
if (value && !_enabled)
{
- _platform.setupMultiCast(_ipParameters.multicastAddress(), KNXIP_MULTICAST_PORT);
+ _platform.setupMultiCast(_ipParameters.propertyValue(PID_ROUTING_MULTICAST_ADDRESS), KNXIP_MULTICAST_PORT);
_enabled = true;
return;
}
diff --git a/src/knx/ip_host_protocol_address_information.cpp b/src/knx/ip_host_protocol_address_information.cpp
index 79a86cd..ed52814 100644
--- a/src/knx/ip_host_protocol_address_information.cpp
+++ b/src/knx/ip_host_protocol_address_information.cpp
@@ -6,26 +6,43 @@ IpHostProtocolAddressInformation::IpHostProtocolAddressInformation(uint8_t* data
{}
-uint8_t IpHostProtocolAddressInformation::length()
+uint8_t IpHostProtocolAddressInformation::length() const
{
return *_data;
}
+void IpHostProtocolAddressInformation::length(uint8_t value)
+{
+ *_data = value;
+}
-HostProtocolCode IpHostProtocolAddressInformation::code()
+HostProtocolCode IpHostProtocolAddressInformation::code() const
{
return (HostProtocolCode)_data[1];
}
+void IpHostProtocolAddressInformation::code(HostProtocolCode value)
+{
+ _data[1] = value;
+}
-uint32_t IpHostProtocolAddressInformation::ipAddress()
+uint32_t IpHostProtocolAddressInformation::ipAddress() const
{
return getInt(_data + 2);
}
+void IpHostProtocolAddressInformation::ipAddress(uint32_t value)
+{
+ pushInt(value, _data + 2);
+}
-uint16_t IpHostProtocolAddressInformation::ipPortNumber()
+uint16_t IpHostProtocolAddressInformation::ipPortNumber() const
{
return getWord(_data + 6);
}
-#endif
\ No newline at end of file
+
+void IpHostProtocolAddressInformation::ipPortNumber(uint16_t value)
+{
+ pushWord(value, _data + 6);
+}
+#endif
diff --git a/src/knx/ip_host_protocol_address_information.h b/src/knx/ip_host_protocol_address_information.h
index 29df5b7..f2c9ae7 100644
--- a/src/knx/ip_host_protocol_address_information.h
+++ b/src/knx/ip_host_protocol_address_information.h
@@ -10,14 +10,22 @@ enum HostProtocolCode : uint8_t
};
#ifdef USE_IP
+
+#define LEN_IPHPAI 8
+
class IpHostProtocolAddressInformation
{
public:
IpHostProtocolAddressInformation(uint8_t* data);
- uint8_t length();
- HostProtocolCode code();
- uint32_t ipAddress();
- uint16_t ipPortNumber();
+ uint8_t length() const;
+ void length(uint8_t value);
+ HostProtocolCode code() const;
+ void code(HostProtocolCode value);
+ uint32_t ipAddress() const;
+ void ipAddress(uint32_t value);
+ uint16_t ipPortNumber() const;
+ void ipPortNumber(uint16_t value);
+
private:
uint8_t* _data;
};
diff --git a/src/knx/ip_parameter_object.cpp b/src/knx/ip_parameter_object.cpp
index 62fadc4..f1ab75e 100644
--- a/src/knx/ip_parameter_object.cpp
+++ b/src/knx/ip_parameter_object.cpp
@@ -96,22 +96,4 @@ IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platf
initializeProperties(sizeof(properties), properties);
}
-uint32_t IpParameterObject::multicastAddress() const
-{
- const Property* prop = property(PID_ROUTING_MULTICAST_ADDRESS);
-
- uint32_t value = DEFAULT_MULTICAST_ADDR;
- prop->read(value);
-
- return value;
-}
-
-uint8_t IpParameterObject::ttl() const
-{
- const Property* prop = property(PID_TTL);
-
- uint8_t value = 0;
- prop->read(value);
- return value;
-}
#endif
\ No newline at end of file
diff --git a/src/knx/ip_parameter_object.h b/src/knx/ip_parameter_object.h
index 17f527a..0115be6 100644
--- a/src/knx/ip_parameter_object.h
+++ b/src/knx/ip_parameter_object.h
@@ -6,12 +6,12 @@
#include "device_object.h"
#include "platform.h"
+#define KNXIP_MULTICAST_PORT 3671
+
class IpParameterObject : public InterfaceObject
{
public:
IpParameterObject(DeviceObject& deviceObject, Platform& platform);
- uint32_t multicastAddress() const;
- uint8_t ttl() const;
private:
DeviceObject& _deviceObject;
diff --git a/src/knx/knx_ip_device_information_dib.cpp b/src/knx/knx_ip_device_information_dib.cpp
new file mode 100644
index 0000000..8d5cf95
--- /dev/null
+++ b/src/knx/knx_ip_device_information_dib.cpp
@@ -0,0 +1,100 @@
+#include "knx_ip_device_information_dib.h"
+#include "bits.h"
+
+KnxIpDeviceInformationDIB::KnxIpDeviceInformationDIB(uint8_t* data) : KnxIpDIB(data)
+{}
+
+uint8_t KnxIpDeviceInformationDIB::medium() const
+{
+ return _data[2];
+}
+
+
+void KnxIpDeviceInformationDIB::medium(uint8_t value)
+{
+ _data[2] = value;
+}
+
+
+uint8_t KnxIpDeviceInformationDIB::status() const
+{
+ return _data[3];
+}
+
+
+void KnxIpDeviceInformationDIB::status(uint8_t value)
+{
+ _data[3] = value;
+}
+
+
+uint16_t KnxIpDeviceInformationDIB::individualAddress() const
+{
+ return getWord(_data + 4);
+}
+
+
+void KnxIpDeviceInformationDIB::indiviudalAddress(uint16_t value)
+{
+ pushWord(value, _data + 4);
+}
+
+
+uint16_t KnxIpDeviceInformationDIB::projectInstallationIdentifier() const
+{
+ return getWord(_data + 6);
+}
+
+
+void KnxIpDeviceInformationDIB::projectInstallationIdentifier(uint16_t value)
+{
+ pushWord(value, _data + 6);
+}
+
+
+const uint8_t* KnxIpDeviceInformationDIB::serialNumber() const
+{
+ return _data + 8;
+}
+
+
+void KnxIpDeviceInformationDIB::serialNumber(const uint8_t* value)
+{
+ pushByteArray(value, LEN_SERIAL_NUMBER, _data + 8);
+}
+
+
+uint32_t KnxIpDeviceInformationDIB::routingMulicastAddress() const
+{
+ return getInt(_data + 14);
+}
+
+
+void KnxIpDeviceInformationDIB::routingMulticastAddress(uint32_t value)
+{
+ pushInt(value, _data + 14);
+}
+
+
+const uint8_t* KnxIpDeviceInformationDIB::macAddress() const
+{
+ return _data + 18;
+}
+
+
+void KnxIpDeviceInformationDIB::macAddress(const uint8_t* value)
+{
+ pushByteArray(value, LEN_MAC_ADDRESS, _data + 18);
+}
+
+
+const uint8_t* KnxIpDeviceInformationDIB::friendlyName() const
+{
+ return _data + 24;
+}
+
+
+void KnxIpDeviceInformationDIB::friendlyName(const uint8_t* value)
+{
+ pushByteArray(value, LEN_FRIENDLY_NAME, _data + 24);
+}
diff --git a/src/knx/knx_ip_device_information_dib.h b/src/knx/knx_ip_device_information_dib.h
new file mode 100644
index 0000000..8acad60
--- /dev/null
+++ b/src/knx/knx_ip_device_information_dib.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "knx_ip_dib.h"
+
+#ifdef USE_IP
+#define LEN_DEVICE_INFORMATION_DIB 54
+#define LEN_SERIAL_NUMBER 6
+#define LEN_MAC_ADDRESS 6
+#define LEN_FRIENDLY_NAME 30
+
+class KnxIpDeviceInformationDIB : public KnxIpDIB
+{
+ public:
+ KnxIpDeviceInformationDIB(uint8_t* data);
+ uint8_t medium() const;
+ void medium(uint8_t value);
+ uint8_t status() const;
+ void status(uint8_t value);
+ uint16_t individualAddress() const;
+ void indiviudalAddress(uint16_t value);
+ uint16_t projectInstallationIdentifier() const;
+ void projectInstallationIdentifier(uint16_t value);
+ const uint8_t* serialNumber() const;
+ void serialNumber(const uint8_t* value);
+ uint32_t routingMulicastAddress() const;
+ void routingMulticastAddress(uint32_t value);
+ const uint8_t* macAddress() const;
+ void macAddress(const uint8_t* value);
+ const uint8_t* friendlyName() const;
+ void friendlyName(const uint8_t* value);
+};
+
+#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_dib.cpp b/src/knx/knx_ip_dib.cpp
index 8310bab..f2b4a2d 100644
--- a/src/knx/knx_ip_dib.cpp
+++ b/src/knx/knx_ip_dib.cpp
@@ -1,16 +1,28 @@
#include "knx_ip_dib.h"
#ifdef USE_IP
-DIB::DIB(uint8_t* data) : _data(data)
+KnxIpDIB::KnxIpDIB(uint8_t* data) : _data(data)
{}
-DescriptionTypeCode DIB::code()
+KnxIpDIB::~KnxIpDIB()
+{}
+
+uint8_t KnxIpDIB::length() const
+{
+ return *_data;
+}
+
+void KnxIpDIB::length(uint8_t value)
+{
+ *_data = value;
+}
+
+DescriptionTypeCode KnxIpDIB::code() const
{
return (DescriptionTypeCode)_data[1];
}
-
-uint8_t DIB::length()
+void KnxIpDIB::code(DescriptionTypeCode value)
{
- return *_data;
+ _data[1] = value;
}
#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_dib.h b/src/knx/knx_ip_dib.h
index bafe7e6..236d25c 100644
--- a/src/knx/knx_ip_dib.h
+++ b/src/knx/knx_ip_dib.h
@@ -15,13 +15,17 @@ enum DescriptionTypeCode : uint8_t
MFR_DATA = 0xFE
};
-class DIB
+class KnxIpDIB
{
public:
- DIB(uint8_t* data);
- DescriptionTypeCode code();
- uint8_t length();
- private:
+ KnxIpDIB(uint8_t* data);
+ virtual ~KnxIpDIB();
+ DescriptionTypeCode code() const;
+ void code(DescriptionTypeCode value);
+ uint8_t length() const;
+ void length(uint8_t value);
+
+ protected:
uint8_t* _data = 0;
};
#endif
diff --git a/src/knx/knx_ip_frame.cpp b/src/knx/knx_ip_frame.cpp
index df0aa29..fad20ac 100644
--- a/src/knx/knx_ip_frame.cpp
+++ b/src/knx/knx_ip_frame.cpp
@@ -1,6 +1,8 @@
#include "knx_ip_frame.h"
#ifdef USE_IP
+
+#include
#include "bits.h"
#define KNXIP_HEADER_LEN 0x6
@@ -72,7 +74,8 @@ KnxIpFrame::KnxIpFrame(uint16_t length)
_data = new uint8_t[length];
_dataLength = length;
_freeData = true;
- headerLength(KNXIP_HEADER_LEN);
+ memset(_data, 0, length);
+ headerLength(LEN_KNXIP_HEADER);
protocolVersion(KnxIp1_0);
totalLength(length);
}
diff --git a/src/knx/knx_ip_frame.h b/src/knx/knx_ip_frame.h
index 688b2b2..3f21a15 100644
--- a/src/knx/knx_ip_frame.h
+++ b/src/knx/knx_ip_frame.h
@@ -4,7 +4,7 @@
#include "config.h"
#ifdef USE_IP
-#define KNXIP_HEADER_LEN 0x6
+#define LEN_KNXIP_HEADER 0x6
enum KnxIpVersion
{
diff --git a/src/knx/knx_ip_routing_indication.cpp b/src/knx/knx_ip_routing_indication.cpp
index df51576..7486365 100644
--- a/src/knx/knx_ip_routing_indication.cpp
+++ b/src/knx/knx_ip_routing_indication.cpp
@@ -14,9 +14,9 @@ KnxIpRoutingIndication::KnxIpRoutingIndication(uint8_t* data,
}
KnxIpRoutingIndication::KnxIpRoutingIndication(CemiFrame frame)
- : KnxIpFrame(frame.totalLenght() + KNXIP_HEADER_LEN), _frame(_data + headerLength(), frame.totalLenght())
+ : KnxIpFrame(frame.totalLenght() + LEN_KNXIP_HEADER), _frame(_data + headerLength(), frame.totalLenght())
{
serviceTypeIdentifier(RoutingIndication);
- memcpy(_data + KNXIP_HEADER_LEN, frame.data(), frame.totalLenght());
+ memcpy(_data + LEN_KNXIP_HEADER, frame.data(), frame.totalLenght());
}
#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_search_request.cpp b/src/knx/knx_ip_search_request.cpp
index ef9cca1..40d236a 100644
--- a/src/knx/knx_ip_search_request.cpp
+++ b/src/knx/knx_ip_search_request.cpp
@@ -1,7 +1,7 @@
#include "knx_ip_search_request.h"
#ifdef USE_IP
KnxIpSearchRequest::KnxIpSearchRequest(uint8_t* data, uint16_t length)
- : KnxIpFrame(data, length), _hpai(data + KNXIP_HEADER_LEN)
+ : KnxIpFrame(data, length), _hpai(data + LEN_KNXIP_HEADER)
{
}
diff --git a/src/knx/knx_ip_search_response.cpp b/src/knx/knx_ip_search_response.cpp
index 54cc32e..8f436a4 100644
--- a/src/knx/knx_ip_search_response.cpp
+++ b/src/knx/knx_ip_search_response.cpp
@@ -1,4 +1,63 @@
#include "knx_ip_search_response.h"
#ifdef USE_IP
-#endif
\ No newline at end of file
+#endif
+
+#define SERVICE_FAMILIES 2
+
+KnxIpSearchResponse::KnxIpSearchResponse(IpParameterObject& parameters, DeviceObject& deviceObject)
+ : KnxIpFrame(LEN_KNXIP_HEADER + LEN_IPHPAI + LEN_DEVICE_INFORMATION_DIB + 2 + 2 * SERVICE_FAMILIES),
+ _controlEndpoint(_data + LEN_KNXIP_HEADER), _deviceInfo(_data + LEN_KNXIP_HEADER + LEN_IPHPAI),
+ _supportedServices(_data + LEN_KNXIP_HEADER + LEN_IPHPAI + LEN_DEVICE_INFORMATION_DIB)
+{
+ serviceTypeIdentifier(SearchResponse);
+
+ _controlEndpoint.length(LEN_IPHPAI);
+ _controlEndpoint.code(IPV4_UDP);
+ _controlEndpoint.ipAddress(parameters.propertyValue(PID_CURRENT_IP_ADDRESS));
+ _controlEndpoint.ipPortNumber(KNXIP_MULTICAST_PORT);
+
+ _deviceInfo.length(LEN_DEVICE_INFORMATION_DIB);
+ _deviceInfo.code(DEVICE_INFO);
+ _deviceInfo.medium(0x20); //KNX-IP FIXME get this value from somewhere else
+ _deviceInfo.status(deviceObject.progMode());
+ _deviceInfo.indiviudalAddress(parameters.propertyValue(PID_KNX_INDIVIDUAL_ADDRESS));
+ _deviceInfo.projectInstallationIdentifier(parameters.propertyValue(PID_PROJECT_INSTALLATION_ID));
+ _deviceInfo.serialNumber(deviceObject.propertyData(PID_SERIAL_NUMBER));
+ //_deviceInfo.routingMulticastAddress(parameters.propertyValue(PID_ROUTING_MULTICAST_ADDRESS));
+ _deviceInfo.routingMulticastAddress(0);
+
+ uint8_t mac_address[LEN_MAC_ADDRESS] = {0};
+ Property* prop = parameters.property(PID_MAC_ADDRESS);
+ prop->read(mac_address);
+ _deviceInfo.macAddress(mac_address);
+
+ uint8_t friendlyName[LEN_FRIENDLY_NAME] = {0};
+ prop = parameters.property(PID_FRIENDLY_NAME);
+ prop->read(1, LEN_FRIENDLY_NAME, friendlyName);
+ _deviceInfo.friendlyName(friendlyName);
+
+ _supportedServices.length(2 + 2 * SERVICE_FAMILIES);
+ _supportedServices.code(SUPP_SVC_FAMILIES);
+ _supportedServices.serviceVersion(Core, 1);
+ _supportedServices.serviceVersion(DeviceManagement, 1);
+// _supportedServices.serviceVersion(Routing, 1);
+}
+
+
+IpHostProtocolAddressInformation& KnxIpSearchResponse::controlEndpoint()
+{
+ return _controlEndpoint;
+}
+
+
+KnxIpDeviceInformationDIB& KnxIpSearchResponse::deviceInfo()
+{
+ return _deviceInfo;
+}
+
+
+KnxIpSupportedServiceDIB& KnxIpSearchResponse::supportedServices()
+{
+ return _supportedServices;
+}
diff --git a/src/knx/knx_ip_search_response.h b/src/knx/knx_ip_search_response.h
index 2bff759..5cc84cd 100644
--- a/src/knx/knx_ip_search_response.h
+++ b/src/knx/knx_ip_search_response.h
@@ -2,12 +2,22 @@
#include "knx_ip_frame.h"
#include "ip_host_protocol_address_information.h"
+#include "knx_ip_device_information_dib.h"
+#include "knx_ip_supported_service_dib.h"
+#include "ip_parameter_object.h"
#ifdef USE_IP
class KnxIpSearchResponse : public KnxIpFrame
{
+ public:
+ KnxIpSearchResponse(IpParameterObject& parameters, DeviceObject& deviceObj);
IpHostProtocolAddressInformation& controlEndpoint();
-
+ KnxIpDeviceInformationDIB& deviceInfo();
+ KnxIpSupportedServiceDIB& supportedServices();
+ private:
+ IpHostProtocolAddressInformation _controlEndpoint;
+ KnxIpDeviceInformationDIB _deviceInfo;
+ KnxIpSupportedServiceDIB _supportedServices;
};
#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_supported_service_dib.cpp b/src/knx/knx_ip_supported_service_dib.cpp
new file mode 100644
index 0000000..2e73d69
--- /dev/null
+++ b/src/knx/knx_ip_supported_service_dib.cpp
@@ -0,0 +1,41 @@
+#include "knx_ip_supported_service_dib.h"
+
+KnxIpSupportedServiceDIB::KnxIpSupportedServiceDIB(uint8_t* data) : KnxIpDIB(data)
+{}
+
+
+uint8_t KnxIpSupportedServiceDIB::serviceVersion(ServiceFamily family)
+{
+ uint8_t* start = _data + 2;
+ uint8_t* end = _data + length();
+
+ for (uint8_t* it = start; it < end; it += 2)
+ {
+ if (*it == family)
+ return it[1];
+ }
+ return 0;
+}
+
+
+void KnxIpSupportedServiceDIB::serviceVersion(ServiceFamily family, uint8_t version)
+{
+ uint8_t* start = _data + 2;
+ uint8_t* end = _data + length();
+
+ for (uint8_t* it = start; it < end; it += 2)
+ {
+ if (*it == family)
+ {
+ it[1] = version;
+ break;
+ }
+
+ if (*it == 0)
+ {
+ *it = family;
+ it[1] = version;
+ break;
+ }
+ }
+}
diff --git a/src/knx/knx_ip_supported_service_dib.h b/src/knx/knx_ip_supported_service_dib.h
new file mode 100644
index 0000000..97cd974
--- /dev/null
+++ b/src/knx/knx_ip_supported_service_dib.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "knx_ip_dib.h"
+
+#ifdef USE_IP
+enum ServiceFamily : uint8_t
+{
+ Core = 2,
+ DeviceManagement = 3,
+ Tunnelling = 4,
+ Routing = 5,
+ RemoteLogging = 6,
+ RemoteConfigDiag = 7,
+ ObjectServer = 8
+};
+
+class KnxIpSupportedServiceDIB : public KnxIpDIB
+{
+ public:
+ KnxIpSupportedServiceDIB(uint8_t* data);
+ uint8_t serviceVersion(ServiceFamily family);
+ void serviceVersion(ServiceFamily family, uint8_t version);
+};
+#endif
\ No newline at end of file
diff --git a/src/knx/platform.cpp b/src/knx/platform.cpp
index 7ed8cfc..2484ba1 100644
--- a/src/knx/platform.cpp
+++ b/src/knx/platform.cpp
@@ -83,25 +83,12 @@ bool Platform::sendBytesMultiCast(uint8_t *buffer, uint16_t len)
return false;
}
-int Platform::readBytesMultiCast(uint8_t *buffer, uint16_t maxLen)
-{
- return 0;
-}
-
-void Platform::setupUniCast(uint32_t addr, uint16_t port, uint8_t type)
-{}
-
-
-void Platform::closeUniCast()
-{}
-
-
-bool Platform::sendBytesUniCast(uint8_t* buffer, uint16_t len)
+bool Platform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
{
return false;
}
-int Platform::readBytesUniCast(uint8_t *buffer, uint16_t maxLen)
+int Platform::readBytesMultiCast(uint8_t *buffer, uint16_t maxLen)
{
return 0;
-}
\ No newline at end of file
+}
diff --git a/src/knx/platform.h b/src/knx/platform.h
index 347e825..8604484 100644
--- a/src/knx/platform.h
+++ b/src/knx/platform.h
@@ -31,10 +31,7 @@ class Platform
virtual int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen);
//unicast socket
- virtual void setupUniCast(uint32_t addr, uint16_t port, uint8_t type);
- virtual void closeUniCast();
- virtual bool sendBytesUniCast(uint8_t* buffer, uint16_t len);
- virtual int readBytesUniCast(uint8_t* buffer, uint16_t maxLen);
+ virtual bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len);
//UART
virtual void setupUart();
diff --git a/src/knx/property.cpp b/src/knx/property.cpp
index aa0fad2..a5077dd 100644
--- a/src/knx/property.cpp
+++ b/src/knx/property.cpp
@@ -100,8 +100,9 @@ uint8_t Property::ElementSize() const
return 19;
case PDT_GENERIC_20:
return 20;
+ default:
+ return 0;
}
- return 0;
}
Property::Property(PropertyID id, bool writeEnable, PropertyDataType type,
@@ -151,6 +152,10 @@ uint8_t Property::read(uint32_t& value) const
return count;
}
+uint8_t Property::read(uint8_t* value) const
+{
+ return read(1, 1, value);
+}
uint8_t Property::write(uint8_t value)
{
diff --git a/src/knx/property.h b/src/knx/property.h
index 2f2c8de..11ac4ef 100644
--- a/src/knx/property.h
+++ b/src/knx/property.h
@@ -241,6 +241,7 @@ class Property : public SaveRestore
uint8_t read(uint8_t& value) const;
uint8_t read(uint16_t& value) const;
uint8_t read(uint32_t& value) const;
+ uint8_t read(uint8_t* value) const;
uint8_t write(uint8_t value);
uint8_t write(uint16_t value);
uint8_t write(uint16_t position, uint16_t value);
diff --git a/src/knx/rf_data_link_layer.cpp b/src/knx/rf_data_link_layer.cpp
index aee0728..0c06de1 100644
--- a/src/knx/rf_data_link_layer.cpp
+++ b/src/knx/rf_data_link_layer.cpp
@@ -32,7 +32,7 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame)
// or the RF domain address that was programmed by ETS
if (frame.systemBroadcast() == SysBroadcast)
{
- frame.rfSerialOrDoA((uint8_t*)_deviceObject.knxSerialNumber());
+ frame.rfSerialOrDoA((uint8_t*)_deviceObject.propertyData(PID_SERIAL_NUMBER));
}
else
{
diff --git a/src/knx/transport_layer.cpp b/src/knx/transport_layer.cpp
index e63f624..91cafc9 100644
--- a/src/knx/transport_layer.cpp
+++ b/src/knx/transport_layer.cpp
@@ -210,6 +210,8 @@ void TransportLayer::dataIndividualIndication(uint16_t destination, HopCountType
case Connecting:
A10(source);
break;
+ default: /* do nothing */
+ break;
}
}
break;
@@ -351,6 +353,9 @@ void TransportLayer::dataIndividualConfirm(AckType ack, uint16_t destination, Ho
//E24
//A0: do nothing
break;
+ default:
+ break;
+ /* DataGroup and DataBroadcast should not appear here. If they do ignore them. */
}
}
diff --git a/src/knx_facade.h b/src/knx_facade.h
index 5b26981..2aef3a8 100644
--- a/src/knx_facade.h
+++ b/src/knx_facade.h
@@ -71,7 +71,7 @@ template class KnxFacade : private SaveRestore
void enabled(bool value)
{
- _bau.enabled(true);
+ _bau.enabled(value);
}
bool progMode()
diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp
index f4ff659..2dfd2e3 100644
--- a/src/linux_platform.cpp
+++ b/src/linux_platform.cpp
@@ -77,7 +77,7 @@ LinuxPlatform::LinuxPlatform()
memcpy(_macAddress, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
ioctl(socketMac, SIOCGIFADDR, &ifr);
-
+
struct sockaddr_in* ipaddr = (struct sockaddr_in*)&ifr.ifr_addr;
_ipAddress = ntohl(ipaddr->sin_addr.s_addr);
@@ -111,7 +111,6 @@ LinuxPlatform::LinuxPlatform()
{
char* pEnd;
_defaultGateway = ntohl(strtol(g, &pEnd, 16));
-
}
break;
}
@@ -992,72 +991,17 @@ void delayMicroseconds(unsigned int howLong)
}
}
-void LinuxPlatform::setupUniCast(uint32_t addr, uint16_t port, uint8_t type)
-{
- if (_unicastSocketFd >= 0)
- closeUniCast();
-
- _unicastAddr = addr;
- _unicastPort = port;
- _unicastType = type;
-
- uint32_t loop = 1;
-
- struct sockaddr_in sin;
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_port = htons(port);
-
- int socketType = 0;
- if (type == IPV4_UDP)
- socketType = SOCK_DGRAM;
- else
- socketType = SOCK_STREAM;
-
- _unicastSocketFd = socket(AF_INET, socketType, 0);
- if (_unicastSocketFd == -1)
- {
- perror("socket()");
- fatalError();
- }
-
- /* Mehr Prozessen erlauben, denselben Port zu nutzen */
- loop = 1;
- if (setsockopt(_unicastSocketFd, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0)
- {
- perror("setsockopt:SO_REUSEADDR");
- fatalError();
- }
-
- if (bind(_unicastSocketFd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
- {
- perror("bind");
- fatalError();
- }
-
- uint32_t flags = fcntl(_unicastSocketFd, F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(_unicastSocketFd, F_SETFL, flags);
-}
-
-void LinuxPlatform::closeUniCast()
-{
- close(_unicastSocketFd);
- _unicastSocketFd = -1;
-}
-
-bool LinuxPlatform::sendBytesUniCast(uint8_t* buffer, uint16_t len)
+bool LinuxPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
{
struct sockaddr_in address = {0};
address.sin_family = AF_INET;
- address.sin_addr.s_addr = htonl(_unicastAddr);
- address.sin_port = htons(_unicastPort);
+ address.sin_addr.s_addr = htonl(addr);
+ address.sin_port = htons(port);
ssize_t retVal = 0;
do
{
- retVal = sendto(_unicastSocketFd, buffer, len, 0, (struct sockaddr*)&address, sizeof(address));
+ retVal = sendto(_multicastSocketFd, buffer, len, 0, (struct sockaddr*)&address, sizeof(address));
if (retVal == -1)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
@@ -1068,38 +1012,21 @@ bool LinuxPlatform::sendBytesUniCast(uint8_t* buffer, uint16_t len)
return true;
}
-int LinuxPlatform::readBytesUniCast(uint8_t* buffer,
- uint16_t maxLen)
-{
- uint32_t sin_len;
- struct sockaddr_in sin;
-
- sin_len = sizeof(sin);
- ssize_t len = recvfrom(_unicastSocketFd, buffer, maxLen, 0, (struct sockaddr*)&sin, &sin_len);
- // if (len > 0)
- // printHex("->", buffer, len);
-
- return len;
-}
-
void LinuxPlatform::macAddress(uint8_t* mac_address)
{
memcpy(mac_address, _macAddress, IFHWADDRLEN);
}
-
uint32_t LinuxPlatform::currentIpAddress()
{
return _ipAddress;
}
-
uint32_t LinuxPlatform::currentSubnetMask()
{
return _netmask;
}
-
uint32_t LinuxPlatform::currentDefaultGateway()
{
return _defaultGateway;
diff --git a/src/linux_platform.h b/src/linux_platform.h
index 90250b1..b82d3f8 100644
--- a/src/linux_platform.h
+++ b/src/linux_platform.h
@@ -38,11 +38,7 @@ public:
void closeMultiCast() override;
bool sendBytesMultiCast(uint8_t* buffer, uint16_t len) override;
int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen) override;
-
- void setupUniCast(uint32_t addr, uint16_t port, uint8_t type);
- void closeUniCast();
- bool sendBytesUniCast(uint8_t* buffer, uint16_t len);
- int readBytesUniCast(uint8_t* buffer, uint16_t maxLen);
+ bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) override;
//spi
void setupSpi() override;
@@ -59,11 +55,6 @@ public:
uint16_t _multicastPort = -1;
int _multicastSocketFd = -1;
- uint32_t _unicastAddr = -1;
- uint16_t _unicastPort = -1;
- int _unicastSocketFd = -1;
- uint8_t _unicastType = -1;
-
void doMemoryMapping();
uint8_t* _mappedFile = 0;
int _fd = -1;