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_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)

View File

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

View File

@ -99,11 +99,13 @@
<ClInclude Include="..\..\src\knx\ip_data_link_layer.h" />
<ClInclude Include="..\..\src\knx\ip_host_protocol_address_information.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_frame.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_response.h" />
<ClInclude Include="..\..\src\knx\knx_ip_supported_service_dib.h" />
<ClInclude Include="..\..\src\knx\knx_types.h" />
<ClInclude Include="..\..\src\knx\knx_value.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_host_protocol_address_information.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_frame.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_response.cpp" />
<ClCompile Include="..\..\src\knx\knx_ip_supported_service_dib.cpp" />
<ClCompile Include="..\..\src\knx\knx_value.cpp" />
<ClCompile Include="..\..\src\knx\memory.cpp" />
<ClCompile Include="..\..\src\knx\network_layer.cpp" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
#include <cstring>
#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();
}

View File

@ -125,6 +125,24 @@ class InterfaceObject : public SaveRestore
*/
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.
*/

View File

@ -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 <stdio.h>
#include <string.h>
@ -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<uint32_t>(PID_ROUTING_MULTICAST_ADDRESS), KNXIP_MULTICAST_PORT);
_enabled = true;
return;
}

View File

@ -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);
}
void IpHostProtocolAddressInformation::ipPortNumber(uint16_t value)
{
pushWord(value, _data + 6);
}
#endif

View File

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

View File

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

View File

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

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"
#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

View File

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

View File

@ -1,6 +1,8 @@
#include "knx_ip_frame.h"
#ifdef USE_IP
#include <cstring>
#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);
}

View File

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

View File

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

View File

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

View File

@ -2,3 +2,62 @@
#ifdef USE_IP
#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 "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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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. */
}
}

View File

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

View File

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

View File

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