implement knx-ip searchresponse

This commit is contained in:
Thomas Kunze 2019-12-28 00:29:17 +01:00
parent 02a24ea3b8
commit e2fd20ab9a
37 changed files with 447 additions and 188 deletions

View File

@ -49,9 +49,13 @@ add_executable(knx-linux
../../src/knx/ip_data_link_layer.h ../../src/knx/ip_data_link_layer.h
../../src/knx/ip_parameter_object.cpp ../../src/knx/ip_parameter_object.cpp
../../src/knx/ip_parameter_object.h ../../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_frame.cpp
../../src/knx/knx_ip_routing_indication.cpp ../../src/knx/knx_ip_routing_indication.cpp
../../src/knx/knx_ip_search_request.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/ip_host_protocol_address_information.cpp
../../src/knx/knx_value.cpp ../../src/knx/knx_value.cpp
../../src/knx/knx_value.h ../../src/knx/knx_value.h
@ -87,7 +91,7 @@ add_executable(knx-linux
main.cpp) main.cpp)
target_link_libraries(knx-linux "${LIBRARIES_FROM_REFERENCES}") target_link_libraries(knx-linux "${LIBRARIES_FROM_REFERENCES}")
include_directories(../../src) include_directories(../../src)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_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 -Wno-switch -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) set_property(TARGET knx-linux PROPERTY CXX_STANDARD 11)
add_definitions(-DMEDIUM_TYPE=5) add_definitions(-DMEDIUM_TYPE=5)

View File

@ -7,7 +7,7 @@
<PathStyle>RemoteUnix</PathStyle> <PathStyle>RemoteUnix</PathStyle>
</CustomSourceDirectories> </CustomSourceDirectories>
<BuildHost> <BuildHost>
<HostName>Suzail</HostName> <HostName>Immerlund</HostName>
<Transport>SSH</Transport> <Transport>SSH</Transport>
<UserName>tkunze</UserName> <UserName>tkunze</UserName>
</BuildHost> </BuildHost>
@ -36,6 +36,7 @@
</FileMasks> </FileMasks>
<TransferNewFilesOnly>false</TransferNewFilesOnly> <TransferNewFilesOnly>false</TransferNewFilesOnly>
<IncludeSubdirectories>true</IncludeSubdirectories> <IncludeSubdirectories>true</IncludeSubdirectories>
<SelectedDirectories />
<DeleteDisappearedFiles>true</DeleteDisappearedFiles> <DeleteDisappearedFiles>true</DeleteDisappearedFiles>
<ApplyGlobalExclusionList>true</ApplyGlobalExclusionList> <ApplyGlobalExclusionList>true</ApplyGlobalExclusionList>
<Extension> <Extension>

View File

@ -99,11 +99,13 @@
<ClInclude Include="..\..\src\knx\ip_data_link_layer.h" /> <ClInclude Include="..\..\src\knx\ip_data_link_layer.h" />
<ClInclude Include="..\..\src\knx\ip_host_protocol_address_information.h" /> <ClInclude Include="..\..\src\knx\ip_host_protocol_address_information.h" />
<ClInclude Include="..\..\src\knx\ip_parameter_object.h" /> <ClInclude Include="..\..\src\knx\ip_parameter_object.h" />
<ClInclude Include="..\..\src\knx\knx_ip_device_information_dib.h" />
<ClInclude Include="..\..\src\knx\knx_ip_dib.h" /> <ClInclude Include="..\..\src\knx\knx_ip_dib.h" />
<ClInclude Include="..\..\src\knx\knx_ip_frame.h" /> <ClInclude Include="..\..\src\knx\knx_ip_frame.h" />
<ClInclude Include="..\..\src\knx\knx_ip_routing_indication.h" /> <ClInclude Include="..\..\src\knx\knx_ip_routing_indication.h" />
<ClInclude Include="..\..\src\knx\knx_ip_search_request.h" /> <ClInclude Include="..\..\src\knx\knx_ip_search_request.h" />
<ClInclude Include="..\..\src\knx\knx_ip_search_response.h" /> <ClInclude Include="..\..\src\knx\knx_ip_search_response.h" />
<ClInclude Include="..\..\src\knx\knx_ip_supported_service_dib.h" />
<ClInclude Include="..\..\src\knx\knx_types.h" /> <ClInclude Include="..\..\src\knx\knx_types.h" />
<ClInclude Include="..\..\src\knx\knx_value.h" /> <ClInclude Include="..\..\src\knx\knx_value.h" />
<ClInclude Include="..\..\src\knx\memory.h" /> <ClInclude Include="..\..\src\knx\memory.h" />
@ -157,11 +159,13 @@
<ClCompile Include="..\..\src\knx\ip_data_link_layer.cpp" /> <ClCompile Include="..\..\src\knx\ip_data_link_layer.cpp" />
<ClCompile Include="..\..\src\knx\ip_host_protocol_address_information.cpp" /> <ClCompile Include="..\..\src\knx\ip_host_protocol_address_information.cpp" />
<ClCompile Include="..\..\src\knx\ip_parameter_object.cpp" /> <ClCompile Include="..\..\src\knx\ip_parameter_object.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_device_information_dib.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_dib.cpp" /> <ClCompile Include="..\..\src\knx\knx_ip_dib.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_frame.cpp" /> <ClCompile Include="..\..\src\knx\knx_ip_frame.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_routing_indication.cpp" /> <ClCompile Include="..\..\src\knx\knx_ip_routing_indication.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_search_request.cpp" /> <ClCompile Include="..\..\src\knx\knx_ip_search_request.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_search_response.cpp" /> <ClCompile Include="..\..\src\knx\knx_ip_search_response.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_supported_service_dib.cpp" />
<ClCompile Include="..\..\src\knx\knx_value.cpp" /> <ClCompile Include="..\..\src\knx\knx_value.cpp" />
<ClCompile Include="..\..\src\knx\memory.cpp" /> <ClCompile Include="..\..\src\knx\memory.cpp" />
<ClCompile Include="..\..\src\knx\network_layer.cpp" /> <ClCompile Include="..\..\src\knx\network_layer.cpp" />

View File

@ -188,6 +188,12 @@
<ClInclude Include="..\..\src\knx\knx_ip_dib.h"> <ClInclude Include="..\..\src\knx\knx_ip_dib.h">
<Filter>Header files\knx</Filter> <Filter>Header files\knx</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\knx\knx_ip_device_information_dib.h">
<Filter>Header files\knx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\knx\knx_ip_supported_service_dib.h">
<Filter>Header files\knx</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
@ -334,5 +340,11 @@
<ClCompile Include="..\..\src\knx\knx_ip_dib.cpp"> <ClCompile Include="..\..\src\knx\knx_ip_dib.cpp">
<Filter>Source files\knx</Filter> <Filter>Source files\knx</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\knx\knx_ip_device_information_dib.cpp">
<Filter>Source files\knx</Filter>
</ClCompile>
<ClCompile Include="..\..\src\knx\knx_ip_supported_service_dib.cpp">
<Filter>Source files\knx</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -51,6 +51,9 @@ void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priori
break; break;
case GroupValueWrite: case GroupValueWrite:
_bau.groupValueWriteIndication(asap, priority, hopType, data, len); _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: case GroupValueWrite:
_bau.groupValueWriteLocalConfirm(ack, _savedAsapWriteRequest, priority, hopType, apdu.data(), apdu.length() - 1, status); _bau.groupValueWriteLocalConfirm(ack, _savedAsapWriteRequest, priority, hopType, apdu.data(), apdu.length() - 1, status);
break; 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); _bau.individualAddressSerialNumberWriteIndication(priority, hopType, newIndividualAddress, knxSerialNumber);
break; 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); _bau.individualAddressSerialNumberWriteLocalConfirm(ack, hopType, data + 1, newAddress, status);
break; break;
} }
default:
print("Broadcast-confirm: unhandled APDU-Type: ");
println(apdu.type());
} }
} }
@ -791,6 +803,9 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior
case KeyResponse: case KeyResponse:
_bau.keyWriteAppLayerConfirm(priority, hopType, tsap, data[1]); _bau.keyWriteAppLayerConfirm(priority, hopType, tsap, data[1]);
break; 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: case KeyResponse:
_bau.keyWriteResponseConfirm(ack, priority, hopType, tsap, data[1], status); _bau.keyWriteResponseConfirm(ack, priority, hopType, tsap, data[1], status);
break; break;
default:
print("Indiviual-confirm: unhandled APDU-Type: ");
println(apdu.type());
} }
} }

View File

@ -121,7 +121,7 @@ void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCou
{ {
// If the received serial number matches our serial number // If the received serial number matches our serial number
// then store the received RF domain address in the RF medium object // 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); _rfMediumObj.rfDomainAddress(rfDoA);
} }
@ -129,7 +129,7 @@ void Bau27B0::domainAddressSerialNumberReadIndication(Priority priority, HopCoun
{ {
// If the received serial number matches our serial number // 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 // 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); _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 // If the received serial number matches our serial number
// then store the received new individual address in the device object // 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); _deviceObj.induvidualAddress(newIndividualAddress);
} }
@ -146,7 +146,7 @@ void Bau27B0::individualAddressSerialNumberReadIndication(Priority priority, Hop
{ {
// If the received serial number matches our serial number // 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 // 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); _appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
} }

View File

@ -378,7 +378,7 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun
{ {
// Send reply. testResult data is KNX serial number // Send reply. testResult data is KNX serial number
_appLayer.systemNetworkParameterReadResponse(priority, hopType, objectType, propertyId, _appLayer.systemNetworkParameterReadResponse(priority, hopType, objectType, propertyId,
testInfo, testInfoLength, (uint8_t*) _deviceObj.knxSerialNumber(), 6); testInfo, testInfoLength, (uint8_t*)_deviceObj.propertyData(PID_SERIAL_NUMBER), 6);
} }
break; break;

View File

@ -23,7 +23,7 @@ DeviceObject::DeviceObject()
if(start == 0) if(start == 0)
return 1; return 1;
pushByteArray(io->knxSerialNumber(), 2, data); pushByteArray(io->propertyData(PID_SERIAL_NUMBER), 2, data);
return 1; return 1;
}), }),
new DataProperty(PID_DEVICE_CONTROL, true, PDT_BITSET8, 1, ReadLv3 | WriteLv3, (uint8_t)0), 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 DeviceObject::manufacturerId()
{ {
uint16_t manufacturerId; uint16_t manufacturerId;
popWord(manufacturerId, knxSerialNumber()); popWord(manufacturerId, propertyData(PID_SERIAL_NUMBER));
return manufacturerId; return manufacturerId;
} }
void DeviceObject::manufacturerId(uint16_t value) void DeviceObject::manufacturerId(uint16_t value)
{ {
uint8_t data[LEN_KNX_SERIAL]; uint8_t data[LEN_KNX_SERIAL];
memcpy(data, knxSerialNumber(), LEN_KNX_SERIAL); memcpy(data, propertyData(PID_SERIAL_NUMBER), LEN_KNX_SERIAL);
pushWord(value, data); pushWord(value, data);
knxSerialNumber(data); propertyValue(PID_SERIAL_NUMBER, data);
} }
uint32_t DeviceObject::bauNumber() uint32_t DeviceObject::bauNumber()
{ {
uint32_t bauNumber; uint32_t bauNumber;
popInt(bauNumber, knxSerialNumber() + 2); popInt(bauNumber, propertyData(PID_SERIAL_NUMBER) + 2);
return bauNumber; return bauNumber;
} }
void DeviceObject::bauNumber(uint32_t value) void DeviceObject::bauNumber(uint32_t value)
{ {
uint8_t data[LEN_KNX_SERIAL]; 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); pushInt(value, data + 2);
knxSerialNumber(data); propertyValue(PID_SERIAL_NUMBER, 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);
} }
const uint8_t* DeviceObject::orderNumber() const uint8_t* DeviceObject::orderNumber()

View File

@ -24,8 +24,6 @@ public:
void manufacturerId(uint16_t value); void manufacturerId(uint16_t value);
uint32_t bauNumber(); uint32_t bauNumber();
void bauNumber(uint32_t value); void bauNumber(uint32_t value);
const uint8_t* knxSerialNumber();
void knxSerialNumber(const uint8_t* value);
const uint8_t* orderNumber(); const uint8_t* orderNumber();
void orderNumber(const uint8_t* value); void orderNumber(const uint8_t* value);
const uint8_t* hardwareType(); const uint8_t* hardwareType();

View File

@ -1,6 +1,7 @@
#include <cstring> #include <cstring>
#include "interface_object.h" #include "interface_object.h"
#include "data_property.h"
InterfaceObject::~InterfaceObject() InterfaceObject::~InterfaceObject()
{ {
@ -217,3 +218,10 @@ const Property* InterfaceObject::property(PropertyID id) const
return nullptr; return nullptr;
} }
const uint8_t* InterfaceObject::propertyData(PropertyID id)
{
DataProperty* prop = (DataProperty*)property(id);
return prop->data();
}

View File

@ -125,6 +125,24 @@ class InterfaceObject : public SaveRestore
*/ */
Property* property(PropertyID id); Property* property(PropertyID id);
template <typename T>
T propertyValue(PropertyID id)
{
const Property* prop = property(id);
T value = 0;
prop->read(value);
return value;
}
template <typename T>
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. * Gets const property with PropertyID id if it exists and nullptr otherwise.
*/ */

View File

@ -8,6 +8,7 @@
#include "address_table_object.h" #include "address_table_object.h"
#include "knx_ip_routing_indication.h" #include "knx_ip_routing_indication.h"
#include "knx_ip_search_request.h" #include "knx_ip_search_request.h"
#include "knx_ip_search_response.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -15,7 +16,6 @@
#define KNXIP_HEADER_LEN 0x6 #define KNXIP_HEADER_LEN 0x6
#define KNXIP_PROTOCOL_VERSION 0x10 #define KNXIP_PROTOCOL_VERSION 0x10
#define KNXIP_MULTICAST_PORT 3671
#define MIN_LEN_CEMI 10 #define MIN_LEN_CEMI 10
IpDataLinkLayer::IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam, IpDataLinkLayer::IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam,
@ -64,6 +64,10 @@ void IpDataLinkLayer::loop()
case SearchRequest: case SearchRequest:
{ {
KnxIpSearchRequest searchRequest(buffer, len); KnxIpSearchRequest searchRequest(buffer, len);
KnxIpSearchResponse searchResponse(_ipParameters, _deviceObject);
auto hpai = searchRequest.hpai();
_platform.sendBytesUniCast(hpai.ipAddress(), hpai.ipPortNumber(), searchResponse.data(), searchResponse.totalLength());
break; break;
} }
default: default:
@ -78,7 +82,7 @@ void IpDataLinkLayer::enabled(bool value)
// _println(_deviceObject.induvidualAddress()); // _println(_deviceObject.induvidualAddress());
if (value && !_enabled) if (value && !_enabled)
{ {
_platform.setupMultiCast(_ipParameters.multicastAddress(), KNXIP_MULTICAST_PORT); _platform.setupMultiCast(_ipParameters.propertyValue<uint32_t>(PID_ROUTING_MULTICAST_ADDRESS), KNXIP_MULTICAST_PORT);
_enabled = true; _enabled = true;
return; return;
} }

View File

@ -6,26 +6,43 @@ IpHostProtocolAddressInformation::IpHostProtocolAddressInformation(uint8_t* data
{} {}
uint8_t IpHostProtocolAddressInformation::length() uint8_t IpHostProtocolAddressInformation::length() const
{ {
return *_data; return *_data;
} }
void IpHostProtocolAddressInformation::length(uint8_t value)
{
*_data = value;
}
HostProtocolCode IpHostProtocolAddressInformation::code() HostProtocolCode IpHostProtocolAddressInformation::code() const
{ {
return (HostProtocolCode)_data[1]; 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); 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); return getWord(_data + 6);
} }
void IpHostProtocolAddressInformation::ipPortNumber(uint16_t value)
{
pushWord(value, _data + 6);
}
#endif #endif

View File

@ -10,14 +10,22 @@ enum HostProtocolCode : uint8_t
}; };
#ifdef USE_IP #ifdef USE_IP
#define LEN_IPHPAI 8
class IpHostProtocolAddressInformation class IpHostProtocolAddressInformation
{ {
public: public:
IpHostProtocolAddressInformation(uint8_t* data); IpHostProtocolAddressInformation(uint8_t* data);
uint8_t length(); uint8_t length() const;
HostProtocolCode code(); void length(uint8_t value);
uint32_t ipAddress(); HostProtocolCode code() const;
uint16_t ipPortNumber(); void code(HostProtocolCode value);
uint32_t ipAddress() const;
void ipAddress(uint32_t value);
uint16_t ipPortNumber() const;
void ipPortNumber(uint16_t value);
private: private:
uint8_t* _data; uint8_t* _data;
}; };

View File

@ -96,22 +96,4 @@ IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platf
initializeProperties(sizeof(properties), properties); 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 #endif

View File

@ -6,12 +6,12 @@
#include "device_object.h" #include "device_object.h"
#include "platform.h" #include "platform.h"
#define KNXIP_MULTICAST_PORT 3671
class IpParameterObject : public InterfaceObject class IpParameterObject : public InterfaceObject
{ {
public: public:
IpParameterObject(DeviceObject& deviceObject, Platform& platform); IpParameterObject(DeviceObject& deviceObject, Platform& platform);
uint32_t multicastAddress() const;
uint8_t ttl() const;
private: private:
DeviceObject& _deviceObject; DeviceObject& _deviceObject;

View File

@ -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);
}

View File

@ -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

View File

@ -1,16 +1,28 @@
#include "knx_ip_dib.h" #include "knx_ip_dib.h"
#ifdef USE_IP #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]; return (DescriptionTypeCode)_data[1];
} }
void KnxIpDIB::code(DescriptionTypeCode value)
uint8_t DIB::length()
{ {
return *_data; _data[1] = value;
} }
#endif #endif

View File

@ -15,13 +15,17 @@ enum DescriptionTypeCode : uint8_t
MFR_DATA = 0xFE MFR_DATA = 0xFE
}; };
class DIB class KnxIpDIB
{ {
public: public:
DIB(uint8_t* data); KnxIpDIB(uint8_t* data);
DescriptionTypeCode code(); virtual ~KnxIpDIB();
uint8_t length(); DescriptionTypeCode code() const;
private: void code(DescriptionTypeCode value);
uint8_t length() const;
void length(uint8_t value);
protected:
uint8_t* _data = 0; uint8_t* _data = 0;
}; };
#endif #endif

View File

@ -1,6 +1,8 @@
#include "knx_ip_frame.h" #include "knx_ip_frame.h"
#ifdef USE_IP #ifdef USE_IP
#include <cstring>
#include "bits.h" #include "bits.h"
#define KNXIP_HEADER_LEN 0x6 #define KNXIP_HEADER_LEN 0x6
@ -72,7 +74,8 @@ KnxIpFrame::KnxIpFrame(uint16_t length)
_data = new uint8_t[length]; _data = new uint8_t[length];
_dataLength = length; _dataLength = length;
_freeData = true; _freeData = true;
headerLength(KNXIP_HEADER_LEN); memset(_data, 0, length);
headerLength(LEN_KNXIP_HEADER);
protocolVersion(KnxIp1_0); protocolVersion(KnxIp1_0);
totalLength(length); totalLength(length);
} }

View File

@ -4,7 +4,7 @@
#include "config.h" #include "config.h"
#ifdef USE_IP #ifdef USE_IP
#define KNXIP_HEADER_LEN 0x6 #define LEN_KNXIP_HEADER 0x6
enum KnxIpVersion enum KnxIpVersion
{ {

View File

@ -14,9 +14,9 @@ KnxIpRoutingIndication::KnxIpRoutingIndication(uint8_t* data,
} }
KnxIpRoutingIndication::KnxIpRoutingIndication(CemiFrame frame) 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); serviceTypeIdentifier(RoutingIndication);
memcpy(_data + KNXIP_HEADER_LEN, frame.data(), frame.totalLenght()); memcpy(_data + LEN_KNXIP_HEADER, frame.data(), frame.totalLenght());
} }
#endif #endif

View File

@ -1,7 +1,7 @@
#include "knx_ip_search_request.h" #include "knx_ip_search_request.h"
#ifdef USE_IP #ifdef USE_IP
KnxIpSearchRequest::KnxIpSearchRequest(uint8_t* data, uint16_t length) KnxIpSearchRequest::KnxIpSearchRequest(uint8_t* data, uint16_t length)
: KnxIpFrame(data, length), _hpai(data + KNXIP_HEADER_LEN) : KnxIpFrame(data, length), _hpai(data + LEN_KNXIP_HEADER)
{ {
} }

View File

@ -2,3 +2,62 @@
#ifdef USE_IP #ifdef USE_IP
#endif #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<uint32_t>(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<uint16_t>(PID_KNX_INDIVIDUAL_ADDRESS));
_deviceInfo.projectInstallationIdentifier(parameters.propertyValue<uint16_t>(PID_PROJECT_INSTALLATION_ID));
_deviceInfo.serialNumber(deviceObject.propertyData(PID_SERIAL_NUMBER));
//_deviceInfo.routingMulticastAddress(parameters.propertyValue<uint32_t>(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;
}

View File

@ -2,12 +2,22 @@
#include "knx_ip_frame.h" #include "knx_ip_frame.h"
#include "ip_host_protocol_address_information.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 #ifdef USE_IP
class KnxIpSearchResponse : public KnxIpFrame class KnxIpSearchResponse : public KnxIpFrame
{ {
public:
KnxIpSearchResponse(IpParameterObject& parameters, DeviceObject& deviceObj);
IpHostProtocolAddressInformation& controlEndpoint(); IpHostProtocolAddressInformation& controlEndpoint();
KnxIpDeviceInformationDIB& deviceInfo();
KnxIpSupportedServiceDIB& supportedServices();
private:
IpHostProtocolAddressInformation _controlEndpoint;
KnxIpDeviceInformationDIB _deviceInfo;
KnxIpSupportedServiceDIB _supportedServices;
}; };
#endif #endif

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -83,25 +83,12 @@ bool Platform::sendBytesMultiCast(uint8_t *buffer, uint16_t len)
return false; return false;
} }
int Platform::readBytesMultiCast(uint8_t *buffer, uint16_t maxLen) bool Platform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
{
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)
{ {
return false; return false;
} }
int Platform::readBytesUniCast(uint8_t *buffer, uint16_t maxLen) int Platform::readBytesMultiCast(uint8_t *buffer, uint16_t maxLen)
{ {
return 0; return 0;
} }

View File

@ -31,10 +31,7 @@ class Platform
virtual int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen); virtual int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen);
//unicast socket //unicast socket
virtual void setupUniCast(uint32_t addr, uint16_t port, uint8_t type); virtual bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len);
virtual void closeUniCast();
virtual bool sendBytesUniCast(uint8_t* buffer, uint16_t len);
virtual int readBytesUniCast(uint8_t* buffer, uint16_t maxLen);
//UART //UART
virtual void setupUart(); virtual void setupUart();

View File

@ -100,9 +100,10 @@ uint8_t Property::ElementSize() const
return 19; return 19;
case PDT_GENERIC_20: case PDT_GENERIC_20:
return 20; return 20;
} default:
return 0; return 0;
} }
}
Property::Property(PropertyID id, bool writeEnable, PropertyDataType type, Property::Property(PropertyID id, bool writeEnable, PropertyDataType type,
uint16_t maxElements, uint8_t access) uint16_t maxElements, uint8_t access)
@ -151,6 +152,10 @@ uint8_t Property::read(uint32_t& value) const
return count; return count;
} }
uint8_t Property::read(uint8_t* value) const
{
return read(1, 1, value);
}
uint8_t Property::write(uint8_t value) uint8_t Property::write(uint8_t value)
{ {

View File

@ -241,6 +241,7 @@ class Property : public SaveRestore
uint8_t read(uint8_t& value) const; uint8_t read(uint8_t& value) const;
uint8_t read(uint16_t& value) const; uint8_t read(uint16_t& value) const;
uint8_t read(uint32_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(uint8_t value);
uint8_t write(uint16_t value); uint8_t write(uint16_t value);
uint8_t write(uint16_t position, uint16_t value); uint8_t write(uint16_t position, uint16_t value);

View File

@ -32,7 +32,7 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame)
// or the RF domain address that was programmed by ETS // or the RF domain address that was programmed by ETS
if (frame.systemBroadcast() == SysBroadcast) if (frame.systemBroadcast() == SysBroadcast)
{ {
frame.rfSerialOrDoA((uint8_t*)_deviceObject.knxSerialNumber()); frame.rfSerialOrDoA((uint8_t*)_deviceObject.propertyData(PID_SERIAL_NUMBER));
} }
else else
{ {

View File

@ -210,6 +210,8 @@ void TransportLayer::dataIndividualIndication(uint16_t destination, HopCountType
case Connecting: case Connecting:
A10(source); A10(source);
break; break;
default: /* do nothing */
break;
} }
} }
break; break;
@ -351,6 +353,9 @@ void TransportLayer::dataIndividualConfirm(AckType ack, uint16_t destination, Ho
//E24 //E24
//A0: do nothing //A0: do nothing
break; break;
default:
break;
/* DataGroup and DataBroadcast should not appear here. If they do ignore them. */
} }
} }

View File

@ -71,7 +71,7 @@ template <class P, class B> class KnxFacade : private SaveRestore
void enabled(bool value) void enabled(bool value)
{ {
_bau.enabled(true); _bau.enabled(value);
} }
bool progMode() bool progMode()

View File

@ -111,7 +111,6 @@ LinuxPlatform::LinuxPlatform()
{ {
char* pEnd; char* pEnd;
_defaultGateway = ntohl(strtol(g, &pEnd, 16)); _defaultGateway = ntohl(strtol(g, &pEnd, 16));
} }
break; break;
} }
@ -992,72 +991,17 @@ void delayMicroseconds(unsigned int howLong)
} }
} }
void LinuxPlatform::setupUniCast(uint32_t addr, uint16_t port, uint8_t type) bool LinuxPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
{
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)
{ {
struct sockaddr_in address = {0}; struct sockaddr_in address = {0};
address.sin_family = AF_INET; address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(_unicastAddr); address.sin_addr.s_addr = htonl(addr);
address.sin_port = htons(_unicastPort); address.sin_port = htons(port);
ssize_t retVal = 0; ssize_t retVal = 0;
do 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 (retVal == -1)
{ {
if (errno != EAGAIN && errno != EWOULDBLOCK) if (errno != EAGAIN && errno != EWOULDBLOCK)
@ -1068,38 +1012,21 @@ bool LinuxPlatform::sendBytesUniCast(uint8_t* buffer, uint16_t len)
return true; 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) void LinuxPlatform::macAddress(uint8_t* mac_address)
{ {
memcpy(mac_address, _macAddress, IFHWADDRLEN); memcpy(mac_address, _macAddress, IFHWADDRLEN);
} }
uint32_t LinuxPlatform::currentIpAddress() uint32_t LinuxPlatform::currentIpAddress()
{ {
return _ipAddress; return _ipAddress;
} }
uint32_t LinuxPlatform::currentSubnetMask() uint32_t LinuxPlatform::currentSubnetMask()
{ {
return _netmask; return _netmask;
} }
uint32_t LinuxPlatform::currentDefaultGateway() uint32_t LinuxPlatform::currentDefaultGateway()
{ {
return _defaultGateway; return _defaultGateway;

View File

@ -38,11 +38,7 @@ public:
void closeMultiCast() override; void closeMultiCast() override;
bool sendBytesMultiCast(uint8_t* buffer, uint16_t len) override; bool sendBytesMultiCast(uint8_t* buffer, uint16_t len) override;
int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen) override; int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen) override;
bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) 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);
//spi //spi
void setupSpi() override; void setupSpi() override;
@ -59,11 +55,6 @@ public:
uint16_t _multicastPort = -1; uint16_t _multicastPort = -1;
int _multicastSocketFd = -1; int _multicastSocketFd = -1;
uint32_t _unicastAddr = -1;
uint16_t _unicastPort = -1;
int _unicastSocketFd = -1;
uint8_t _unicastType = -1;
void doMemoryMapping(); void doMemoryMapping();
uint8_t* _mappedFile = 0; uint8_t* _mappedFile = 0;
int _fd = -1; int _fd = -1;