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;