frame logging data link layer

This commit is contained in:
Thomas Kunze 2024-08-17 21:30:44 +02:00
parent 2585deb52c
commit 59a76b7c3f
15 changed files with 215 additions and 94 deletions

View File

@ -40,17 +40,17 @@ uint8_t APDU::length() const
return _frame.npdu().octetCount();
}
APDU::operator std::string() const
string APDU::to_string() const
{
string value = "APDU: " + enum_name(type()) + " ";
value += hex(_data[0] & 0x3);
value += byte2hex(_data[0] & 0x3);
for (uint8_t i = 1; i < length() + 1; ++i)
{
if (i)
value += " ";
value += hex(_data[i]);
value += byte2hex(_data[i]);
}
return value;

View File

@ -37,7 +37,7 @@ class APDU
/**
* Convert APDU to string.
*/
operator std::string() const;
std::string to_string() const;
protected:
/**

View File

@ -1362,7 +1362,7 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior
}
default:
LOGGER.warning("Individual-indication: unhandled APDU-Type: %s", ((std::string)apdu).c_str());
LOGGER.warning("Individual-indication: unhandled APDU-Type: %s", apdu.to_string().c_str());
}
}

View File

@ -8,8 +8,8 @@ const uint8_t* popByte(uint8_t& b, const uint8_t* data)
return data;
}
#ifndef KNX_NO_PRINT
std::string hex(uint8_t byte)
std::string byte2hex(uint8_t byte)
{
const char* hex = "0123456789ABCDEF";
char out[3] = {0};
@ -18,6 +18,12 @@ std::string hex(uint8_t byte)
return std::string(out);
}
std::string word2hex(uint16_t value)
{
return byte2hex((uint8_t) (value & 0xFF00) >> 8) + byte2hex((uint8_t) (value & 0xFF));
}
#ifndef KNX_NO_PRINT
void printHex(const char* suffix, const uint8_t* data, size_t length, bool newline)
{
print(suffix);

View File

@ -70,8 +70,10 @@
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
#endif
std::string byte2hex(uint8_t byte);
std::string word2hex(uint16_t value);
#ifndef KNX_NO_PRINT
std::string hex(uint8_t byte);
void print(const char[]);
void print(char);
void print(unsigned char, int = DEC);

View File

@ -399,3 +399,21 @@ bool CemiFrame::valid() const
return true;
}
std::string CemiFrame::to_string() const
{
std::string value = enum_name(frameType()) + " ";
value += enum_name(systemBroadcast()) + " ";
value += enum_name(ack()) + " ";
value += enum_name(repetition()) + " ";
value += enum_name(priority()) + " from ";
value += format_ia(sourceAddress()) + " to ";
value += enum_name(addressType()) + " ";
if (addressType() == AddressType::IndividualAddress)
value += format_ia(destinationAddress());
else
value += format_ga(destinationAddress());
return value;
}

View File

@ -72,6 +72,8 @@ class CemiFrame
uint8_t calcCrcTP(uint8_t* buffer, uint16_t len);
bool valid() const;
std::string to_string() const;
private:
uint8_t buffer[0xff + NPDU_LPDU_DIFF] = {0}; //only valid of add info is zero
uint8_t* _data = 0;

View File

@ -160,10 +160,9 @@ void DataLinkLayer::frameReceived(CemiFrame& frame)
uint16_t ownAddr = _deviceObject.individualAddress();
SystemBroadcast systemBroadcast = frame.systemBroadcast();
if (frame.npdu().octetCount() > 0)
{
LOGGER.info("-> %s", ((string)frame.apdu()).c_str());
}
LOGGER.info("frameReceived %s", frame.to_string().c_str());
#ifdef USE_CEMI_SERVER
// Do not send our own message back to the tunnel
@ -189,7 +188,7 @@ void DataLinkLayer::frameReceived(CemiFrame& frame)
// println();
// print("frameReceived: frame valid? :");
// println(npdu.frame().valid() ? "true" : "false");
if (source == ownAddr)
if (source == ownAddr)
_deviceObject.individualAddressDuplication(true);
if (addrType == GroupAddress && destination == 0)
@ -223,6 +222,7 @@ bool DataLinkLayer::sendTelegram(NPDU& npdu, AckType ack, uint16_t destinationAd
else
frame.frameType(format);
LOGGER.info("sendTelegram %s", frame.to_string().c_str());
if (!frame.valid())
{
@ -230,14 +230,10 @@ bool DataLinkLayer::sendTelegram(NPDU& npdu, AckType ack, uint16_t destinationAd
return false;
}
if (frame.npdu().octetCount() > 0)
{
LOGGER.info("<- %s", ((string)frame.apdu()).c_str());
}
bool sendTheFrame = true;
bool success = true;
#ifdef KNX_TUNNELING
// TunnelOpti
// Optimize performance when sending unicast data over tunnel wich is not meant to be used on the physical TP line
@ -253,6 +249,7 @@ bool DataLinkLayer::sendTelegram(NPDU& npdu, AckType ack, uint16_t destinationAd
#endif
// The data link layer might be an open media link layer
// and will setup rfSerialOrDoA, rfInfo and rfLfn that we also
// have to send through the cEMI server tunnel

View File

@ -8,8 +8,16 @@
#include "knx_ip_search_response.h"
#include "knx_ip_search_request_extended.h"
#include "knx_ip_search_response_extended.h"
#include "../util/logger.h"
const std::string ipaddr2str(const uint32_t addr)
{
return to_string(addr & 0xFF000000 >> 24) + "." + to_string(addr & 0xFF0000 >> 16) + "." + to_string(addr & 0xFF00 >> 8) + "." + to_string(addr & 0xFF);
}
#define LOGGER Logger::logger("IpDataLinkLayer")
#ifdef KNX_TUNNELING
#include "knx_ip_connect_request.h"
#include "knx_ip_connect_response.h"
#include "knx_ip_state_request.h"
@ -21,7 +29,7 @@
#include "knx_ip_description_request.h"
#include "knx_ip_description_response.h"
#include "knx_ip_config_request.h"
#endif
#include <stdio.h>
#include <string.h>
@ -44,7 +52,7 @@ bool IpDataLinkLayer::sendFrame(CemiFrame& frame)
if (isSendLimitReached())
return false;
bool success = sendBytes(packet.data(), packet.totalLength());
bool success = sendMulicast(packet);
#ifdef KNX_ACTIVITYCALLBACK
if (_dllcb)
@ -55,7 +63,6 @@ bool IpDataLinkLayer::sendFrame(CemiFrame& frame)
return success;
}
#ifdef KNX_TUNNELING
void IpDataLinkLayer::dataRequestToTunnel(CemiFrame& frame)
{
if (frame.addressType() == AddressType::GroupAddress)
@ -228,7 +235,8 @@ void IpDataLinkLayer::sendFrameToTunnel(KnxIpTunnelConnection* tunnel, CemiFrame
if (frame.messageCode() != L_data_req && frame.messageCode() != L_data_con && frame.messageCode() != L_data_ind)
req.serviceTypeIdentifier(DeviceConfigurationRequest);
_platform.sendBytesUniCast(tunnel->IpAddress, tunnel->PortData, req.data(), req.totalLength());
sendUnicast(tunnel->IpAddress, tunnel->PortData, req);
}
bool IpDataLinkLayer::isTunnelAddress(uint16_t addr)
@ -262,14 +270,14 @@ bool IpDataLinkLayer::isSentToTunnel(uint16_t address, bool isGrpAddr)
return false;
}
}
#endif
void IpDataLinkLayer::loop()
{
if (!_enabled)
return;
#ifdef KNX_TUNNELING
for (int i = 0; i < KNX_TUNNELING; i++)
{
@ -288,7 +296,7 @@ void IpDataLinkLayer::loop()
discReq.hpaiCtrl().code(IPV4_UDP);
discReq.hpaiCtrl().ipAddress(tunnels[i].IpAddress);
discReq.hpaiCtrl().ipPortNumber(tunnels[i].PortCtrl);
_platform.sendBytesUniCast(tunnels[i].IpAddress, tunnels[i].PortCtrl, discReq.data(), discReq.totalLength());
sendUnicast(tunnels[i].IpAddress, tunnels[i].PortCtrl, discReq);
tunnels[i].Reset();
}
@ -296,9 +304,6 @@ void IpDataLinkLayer::loop()
}
}
#endif
uint8_t buffer[512];
uint16_t remotePort = 0;
uint32_t remoteAddr = 0;
@ -324,6 +329,8 @@ void IpDataLinkLayer::loop()
uint16_t code;
popWord(code, buffer + 2);
LOGGER.info("loop: %s", enum_name((KnxIpServiceType)code).c_str());
switch ((KnxIpServiceType)code)
{
case RoutingIndication:
@ -345,7 +352,7 @@ void IpDataLinkLayer::loop()
_dllcb->activity((_netIndex << KNX_ACTIVITYCALLBACK_NET) | (KNX_ACTIVITYCALLBACK_DIR_SEND << KNX_ACTIVITYCALLBACK_DIR) | (KNX_ACTIVITYCALLBACK_IPUNICAST));
#endif
_platform.sendBytesUniCast(hpai.ipAddress(), hpai.ipPortNumber(), searchResponse.data(), searchResponse.totalLength());
sendUnicast(hpai.ipAddress(), hpai.ipPortNumber(), searchResponse);
break;
}
@ -355,7 +362,7 @@ void IpDataLinkLayer::loop()
break;
}
#ifdef KNX_TUNNELING
case ConnectRequest:
{
@ -407,11 +414,8 @@ void IpDataLinkLayer::loop()
break;
}
#endif
default:
print("Unhandled service identifier: ");
println(code, HEX);
LOGGER.warning("Unhandled service identifier: %s", word2hex(code).c_str());
break;
}
}
@ -545,9 +549,12 @@ void IpDataLinkLayer::loopHandleSearchRequestExtended(uint8_t* buffer, uint16_t
{
//println("requested MANUFACTURER_DATA but not implemented");
}
#ifdef KNX_TUNNELING
if (searchRequest.requestedDIB(TUNNELING_INFO))
searchResponse.setTunnelingInfo(_ipParameters, _deviceObject, tunnels);
#endif
}
@ -557,11 +564,11 @@ void IpDataLinkLayer::loopHandleSearchRequestExtended(uint8_t* buffer, uint16_t
return;
}
_platform.sendBytesUniCast(searchRequest.hpai().ipAddress(), searchRequest.hpai().ipPortNumber(), searchResponse.data(), searchResponse.totalLength());
sendUnicast(searchRequest.hpai().ipAddress(), searchRequest.hpai().ipPortNumber(), searchResponse);
}
#ifdef KNX_TUNNELING
void IpDataLinkLayer::loopHandleConnectRequest(uint8_t* buffer, uint16_t length, uint32_t& src_addr, uint16_t& src_port)
{
KnxIpConnectRequest connRequest(buffer, length);
@ -622,7 +629,7 @@ void IpDataLinkLayer::loopHandleConnectRequest(uint8_t* buffer, uint16_t length,
println("Only Tunnel/DeviceMgmt Connection ist supported!");
#endif
KnxIpConnectResponse connRes(0x00, E_CONNECTION_TYPE);
_platform.sendBytesUniCast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes.data(), connRes.totalLength());
sendUnicast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes);
return;
}
@ -633,7 +640,7 @@ void IpDataLinkLayer::loopHandleConnectRequest(uint8_t* buffer, uint16_t length,
println("Only LinkLayer ist supported!");
#endif
KnxIpConnectResponse connRes(0x00, E_TUNNELING_LAYER);
_platform.sendBytesUniCast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes.data(), connRes.totalLength());
sendUnicast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes);
return;
}
@ -777,7 +784,7 @@ void IpDataLinkLayer::loopHandleConnectRequest(uint8_t* buffer, uint16_t length,
discReq.hpaiCtrl().code(IPV4_UDP);
discReq.hpaiCtrl().ipAddress(tunnels[firstResAndOccTunnel].IpAddress);
discReq.hpaiCtrl().ipPortNumber(tunnels[firstResAndOccTunnel].PortCtrl);
_platform.sendBytesUniCast(tunnels[firstResAndOccTunnel].IpAddress, tunnels[firstResAndOccTunnel].PortCtrl, discReq.data(), discReq.totalLength());
sendUnicast(tunnels[firstResAndOccTunnel].IpAddress, tunnels[firstResAndOccTunnel].PortCtrl, discReq);
tunnels[firstResAndOccTunnel].Reset();
@ -837,7 +844,7 @@ void IpDataLinkLayer::loopHandleConnectRequest(uint8_t* buffer, uint16_t length,
{
println("no free tunnel availible");
KnxIpConnectResponse connRes(0x00, E_NO_MORE_CONNECTIONS);
_platform.sendBytesUniCast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes.data(), connRes.totalLength());
sendUnicast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes);
return;
}
@ -905,7 +912,7 @@ void IpDataLinkLayer::loopHandleConnectRequest(uint8_t* buffer, uint16_t length,
KnxIpConnectResponse connRes(_ipParameters, tun->IndividualAddress, 3671, tun->ChannelId, connRequest.cri().type());
_platform.sendBytesUniCast(tun->IpAddress, tun->PortCtrl, connRes.data(), connRes.totalLength());
sendUnicast(tun->IpAddress, tun->PortCtrl, connRes);
}
void IpDataLinkLayer::loopHandleConnectionStateRequest(uint8_t* buffer, uint16_t length)
@ -930,7 +937,7 @@ void IpDataLinkLayer::loopHandleConnectionStateRequest(uint8_t* buffer, uint16_t
println(stateRequest.channelId());
#endif
KnxIpStateResponse stateRes(0x00, E_CONNECTION_ID);
_platform.sendBytesUniCast(stateRequest.hpaiCtrl().ipAddress(), stateRequest.hpaiCtrl().ipPortNumber(), stateRes.data(), stateRes.totalLength());
sendUnicast(stateRequest.hpaiCtrl().ipAddress(), stateRequest.hpaiCtrl().ipPortNumber(), stateRes);
return;
}
@ -941,7 +948,7 @@ void IpDataLinkLayer::loopHandleConnectionStateRequest(uint8_t* buffer, uint16_t
tun->lastHeartbeat = millis();
KnxIpStateResponse stateRes(tun->ChannelId, E_NO_ERROR);
_platform.sendBytesUniCast(stateRequest.hpaiCtrl().ipAddress(), stateRequest.hpaiCtrl().ipPortNumber(), stateRes.data(), stateRes.totalLength());
sendUnicast(stateRequest.hpaiCtrl().ipAddress(), stateRequest.hpaiCtrl().ipPortNumber(), stateRes);
}
void IpDataLinkLayer::loopHandleDisconnectRequest(uint8_t* buffer, uint16_t length)
@ -971,13 +978,13 @@ void IpDataLinkLayer::loopHandleDisconnectRequest(uint8_t* buffer, uint16_t leng
println(discReq.channelId());
#endif
KnxIpDisconnectResponse discRes(0x00, E_CONNECTION_ID);
_platform.sendBytesUniCast(discReq.hpaiCtrl().ipAddress(), discReq.hpaiCtrl().ipPortNumber(), discRes.data(), discRes.totalLength());
sendUnicast(discReq.hpaiCtrl().ipAddress(), discReq.hpaiCtrl().ipPortNumber(), discRes);
return;
}
KnxIpDisconnectResponse discRes(tun->ChannelId, E_NO_ERROR);
_platform.sendBytesUniCast(discReq.hpaiCtrl().ipAddress(), discReq.hpaiCtrl().ipPortNumber(), discRes.data(), discRes.totalLength());
sendUnicast(discReq.hpaiCtrl().ipAddress(), discReq.hpaiCtrl().ipPortNumber(), discRes);
tun->Reset();
}
@ -985,7 +992,7 @@ void IpDataLinkLayer::loopHandleDescriptionRequest(uint8_t* buffer, uint16_t len
{
KnxIpDescriptionRequest descReq(buffer, length);
KnxIpDescriptionResponse descRes(_ipParameters, _deviceObject);
_platform.sendBytesUniCast(descReq.hpaiCtrl().ipAddress(), descReq.hpaiCtrl().ipPortNumber(), descRes.data(), descRes.totalLength());
sendUnicast(descReq.hpaiCtrl().ipAddress(), descReq.hpaiCtrl().ipPortNumber(), descRes);
}
void IpDataLinkLayer::loopHandleDeviceConfigurationRequest(uint8_t* buffer, uint16_t length)
@ -1008,7 +1015,7 @@ void IpDataLinkLayer::loopHandleDeviceConfigurationRequest(uint8_t* buffer, uint
print("Channel ID nicht gefunden: ");
println(confReq.connectionHeader().channelId());
KnxIpStateResponse stateRes(0x00, E_CONNECTION_ID);
_platform.sendBytesUniCast(0, 0, stateRes.data(), stateRes.totalLength());
sendUnicast(0, 0, stateRes);
return;
}
@ -1018,7 +1025,7 @@ void IpDataLinkLayer::loopHandleDeviceConfigurationRequest(uint8_t* buffer, uint
tunnAck.connectionHeader().channelId(tun->ChannelId);
tunnAck.connectionHeader().sequenceCounter(confReq.connectionHeader().sequenceCounter());
tunnAck.connectionHeader().status(E_NO_ERROR);
_platform.sendBytesUniCast(tun->IpAddress, tun->PortData, tunnAck.data(), tunnAck.totalLength());
sendUnicast(tun->IpAddress, tun->PortData, tunnAck);
tun->lastHeartbeat = millis();
_cemiServer->frameReceived(confReq.frame());
@ -1046,7 +1053,7 @@ void IpDataLinkLayer::loopHandleTunnelingRequest(uint8_t* buffer, uint16_t lengt
println(tunnReq.connectionHeader().channelId());
#endif
KnxIpStateResponse stateRes(0x00, E_CONNECTION_ID);
_platform.sendBytesUniCast(0, 0, stateRes.data(), stateRes.totalLength());
sendUnicast(0, 0, stateRes);
return;
}
@ -1065,7 +1072,7 @@ void IpDataLinkLayer::loopHandleTunnelingRequest(uint8_t* buffer, uint16_t lengt
tunnAck.connectionHeader().channelId(tun->ChannelId);
tunnAck.connectionHeader().sequenceCounter(tunnReq.connectionHeader().sequenceCounter());
tunnAck.connectionHeader().status(E_NO_ERROR);
_platform.sendBytesUniCast(tun->IpAddress, tun->PortData, tunnAck.data(), tunnAck.totalLength());
sendUnicast(tun->IpAddress, tun->PortData, tunnAck);
return;
}
else if ((uint8_t)(sequence - 1) != tun->SequenceCounter_R)
@ -1085,7 +1092,7 @@ void IpDataLinkLayer::loopHandleTunnelingRequest(uint8_t* buffer, uint16_t lengt
tunnAck.connectionHeader().channelId(tun->ChannelId);
tunnAck.connectionHeader().sequenceCounter(tunnReq.connectionHeader().sequenceCounter());
tunnAck.connectionHeader().status(E_NO_ERROR);
_platform.sendBytesUniCast(tun->IpAddress, tun->PortData, tunnAck.data(), tunnAck.totalLength());
sendUnicast(tun->IpAddress, tun->PortData, tunnAck);
tun->SequenceCounter_R = tunnReq.connectionHeader().sequenceCounter();
@ -1094,7 +1101,7 @@ void IpDataLinkLayer::loopHandleTunnelingRequest(uint8_t* buffer, uint16_t lengt
_cemiServer->frameReceived(tunnReq.frame());
}
#endif
void IpDataLinkLayer::enabled(bool value)
{
@ -1125,12 +1132,24 @@ DptMedium IpDataLinkLayer::mediumType() const
return DptMedium::KNX_IP;
}
bool IpDataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length)
bool IpDataLinkLayer::sendMulicast(KnxIpFrame& ipFrame)
{
if (!_enabled)
return false;
return _platform.sendBytesMultiCast(bytes, length);
LOGGER.info("sendMulicast %s", ipFrame.to_string().c_str());
return _platform.sendBytesMultiCast(ipFrame.data(), ipFrame.totalLength());
}
bool IpDataLinkLayer::sendUnicast(uint32_t addr, uint16_t port, KnxIpFrame& ipFrame)
{
if (!_enabled)
return false;
LOGGER.info("sendUnicast to %s:%d %s", ipaddr2str(addr).c_str(), port, ipFrame.to_string().c_str());
return _platform.sendBytesMultiCast(ipFrame.data(), ipFrame.totalLength());
}
bool IpDataLinkLayer::isSendLimitReached()
@ -1171,7 +1190,7 @@ bool IpDataLinkLayer::isSendLimitReached()
if (sum > 50)
{
println("Dropping packet due to 50p/s limit");
LOGGER.warning("Dropping packet due to 50p/s limit");
return true; // drop packet
}
else

View File

@ -5,6 +5,7 @@
#include "ip_parameter_object.h"
#include "knx_ip_tunnel_connection.h"
#include "service_families.h"
#include "knx_ip_frame.h"
class IpDataLinkLayer : public DataLinkLayer
{
@ -18,13 +19,11 @@ class IpDataLinkLayer : public DataLinkLayer
void enabled(bool value);
bool enabled() const;
DptMedium mediumType() const override;
#ifdef KNX_TUNNELING
void dataRequestToTunnel(CemiFrame& frame) override;
void dataConfirmationToTunnel(CemiFrame& frame) override;
void dataIndicationToTunnel(CemiFrame& frame) override;
bool isTunnelAddress(uint16_t addr) override;
bool isSentToTunnel(uint16_t address, bool isGrpAddr);
#endif
private:
bool _enabled = false;
@ -32,7 +31,6 @@ class IpDataLinkLayer : public DataLinkLayer
uint8_t _frameCountBase = 0;
uint32_t _frameCountTimeBase = 0;
bool sendFrame(CemiFrame& frame);
#ifdef KNX_TUNNELING
void sendFrameToTunnel(KnxIpTunnelConnection* tunnel, CemiFrame& frame);
void loopHandleConnectRequest(uint8_t* buffer, uint16_t length, uint32_t& src_addr, uint16_t& src_port);
void loopHandleConnectionStateRequest(uint8_t* buffer, uint16_t length);
@ -40,9 +38,9 @@ class IpDataLinkLayer : public DataLinkLayer
void loopHandleDescriptionRequest(uint8_t* buffer, uint16_t length);
void loopHandleDeviceConfigurationRequest(uint8_t* buffer, uint16_t length);
void loopHandleTunnelingRequest(uint8_t* buffer, uint16_t length);
#endif
void loopHandleSearchRequestExtended(uint8_t* buffer, uint16_t length);
bool sendBytes(uint8_t* buffer, uint16_t length);
bool sendMulicast(KnxIpFrame& ipFrame);
bool sendUnicast(uint32_t addr, uint16_t port, KnxIpFrame& ipFrame);
bool isSendLimitReached();
IpParameterObject& _ipParameters;
DataLinkLayerCallbacks* _dllcb;

View File

@ -33,14 +33,14 @@ void KnxIpFrame::protocolVersion(KnxIpVersion version)
_data[1] = (uint8_t)version;
}
uint16_t KnxIpFrame::serviceTypeIdentifier() const
KnxIpServiceType KnxIpFrame::serviceTypeIdentifier() const
{
return getWord(_data + 2);
return (KnxIpServiceType)getWord(_data + 2);
}
void KnxIpFrame::serviceTypeIdentifier(uint16_t identifier)
void KnxIpFrame::serviceTypeIdentifier(KnxIpServiceType identifier)
{
pushWord(identifier, _data + 2);
pushWord((uint16_t) identifier, _data + 2);
}
uint16_t KnxIpFrame::totalLength() const
@ -76,3 +76,81 @@ KnxIpFrame::KnxIpFrame(uint16_t length)
protocolVersion(KnxIp1_0);
totalLength(length);
}
const std::string KnxIpFrame::to_string() const
{
return enum_name(protocolVersion()) + " " + enum_name(serviceTypeIdentifier());
}
const string enum_name(const KnxIpVersion enum_val)
{
switch (enum_val)
{
case KnxIp1_0:
return "KnxIp1_0";
}
return to_string(enum_val);
}
const string enum_name(const KnxIpServiceType enum_val)
{
switch (enum_val)
{
case SearchRequest:
return "SearchRequest";
case SearchResponse:
return "SearchResponse";
case DescriptionRequest:
return "DescriptionRequest";
case DescriptionResponse:
return "DescriptionResponse";
case ConnectRequest:
return "ConnectRequest";
case ConnectResponse:
return "ConnectResponse";
case ConnectionStateRequest:
return "ConnectionStateRequest";
case ConnectionStateResponse:
return "ConnectionStateResponse";
case DisconnectRequest:
return "DisconnectRequest";
case DisconnectResponse:
return "DisconnectResponse";
case SearchRequestExt:
return "SearchRequestExt";
case SearchResponseExt:
return "SearchResponseExt";
case DeviceConfigurationRequest:
return "DeviceConfigurationRequest";
case DeviceConfigurationAck:
return "DeviceConfigurationAck";
case TunnelingRequest:
return "TunnelingRequest";
case TunnelingAck:
return "TunnelingAck";
case RoutingIndication:
return "RoutingIndication";
case RoutingLostMessage:
return "RoutingLostMessage";
}
return to_string(enum_val);
}

View File

@ -8,6 +8,7 @@ enum KnxIpVersion
{
KnxIp1_0 = 0x10
};
const string enum_name(const KnxIpVersion enum_val);
enum KnxIpServiceType
{
@ -30,6 +31,7 @@ enum KnxIpServiceType
RoutingIndication = 0x530,
RoutingLostMessage = 0x531,
};
const string enum_name(const KnxIpServiceType enum_val);
class KnxIpFrame
{
@ -41,12 +43,12 @@ class KnxIpFrame
void headerLength(uint8_t length);
KnxIpVersion protocolVersion() const;
void protocolVersion(KnxIpVersion version);
uint16_t serviceTypeIdentifier() const;
void serviceTypeIdentifier(uint16_t identifier);
KnxIpServiceType serviceTypeIdentifier() const;
void serviceTypeIdentifier(KnxIpServiceType identifier);
uint16_t totalLength() const;
void totalLength(uint16_t length);
uint8_t* data();
const std::string to_string() const;
protected:
bool _freeData = false;
uint8_t* _data = 0;

View File

@ -441,29 +441,15 @@ const string enum_name(const SystemBroadcast enum_val)
}
const string enum_name_in(Repetition enum_val)
const string enum_name(Repetition enum_val)
{
switch (enum_val)
{
case WasRepeated:
return "WasRepeated";
return "WasRepeated/NoRepetiion";
case WasNotRepeated:
return "WasNotRepeated";
}
return to_string(enum_val);
}
const string enum_name_out(Repetition enum_val)
{
switch (enum_val)
{
case NoRepetiion:
return "NoRepetiion";
case RepetitionAllowed:
return "RepetitionAllowed";
return "WasNotRepeated/RepetitionAllowed";
}
return to_string(enum_val);
@ -704,3 +690,13 @@ const string enum_name(const FrameFormat enum_val)
return to_string(enum_val);
}
const string format_ia(uint16_t ia)
{
return to_string(ia & 0xF000 >> 24) + "/" + to_string(ia & 0x0F00 >> 16) + "/" + to_string(ia & 0x00FF);
}
const string format_ga(uint16_t ga)
{
return to_string(ga & 0xF800 >> 23) + "/" + to_string(ga & 0x70 >> 16) + "/" + to_string(ga & 0x00FF);
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <string>
#include <stdint.h>
using namespace std;
enum FrameFormat
@ -117,8 +118,7 @@ enum Repetition
RepetitionAllowed = 0x20,
WasNotRepeated = 0x20,
};
const string enum_name_in(Repetition enum_val);
const string enum_name_out(Repetition enum_val);
const string enum_name(Repetition enum_val);
enum SystemBroadcast
{
@ -310,4 +310,7 @@ enum LCCONFIG
PHYS_IACK_ALL = 0b10000000,
PHYS_IACK_NACK = 0b11000000
};
const string enum_name(const LCCONFIG enum_val);
const string enum_name(const LCCONFIG enum_val);
const string format_ia(uint16_t ia);
const string format_ga(uint16_t ga);

View File

@ -660,7 +660,7 @@ void SecureApplicationLayer::sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGro
if (secure(request.data() + APDU_LPDU_DIFF, kSecureSyncRequest, _deviceObj.individualAddress(), dstAddr, dstAddrIsGroupAddr, tpci, asdu, sizeof(asdu), secCtrl, systemBcast))
{
LOGGER.info("SyncRequest: %s", ((string)request.apdu()).c_str());
LOGGER.info("SyncRequest: %s", request.apdu().to_string().c_str());
if (_syncReqBroadcastOutgoing)
{
@ -723,7 +723,7 @@ void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGr
{
_lastSyncRes = millis();
LOGGER.info("SyncResponse: %s", ((string)response.apdu()).c_str());
LOGGER.info("SyncResponse: %s", response.apdu().to_string().c_str());
if (_syncReqBroadcastIncoming)
{
@ -1063,7 +1063,7 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLengt
bool SecureApplicationLayer::decodeSecureApdu(APDU& secureApdu, APDU& plainApdu, SecurityControl& secCtrl)
{
// Decode secure APDU
LOGGER.info("decodeSecureApdu: Secure APDU: %s", ((string)secureApdu).c_str());
LOGGER.info("decodeSecureApdu: Secure APDU: %s", secureApdu.to_string().c_str());
uint16_t srcAddress = secureApdu.frame().sourceAddress();
uint16_t dstAddress = secureApdu.frame().destinationAddress();
@ -1085,7 +1085,7 @@ bool SecureApplicationLayer::decodeSecureApdu(APDU& secureApdu, APDU& plainApdu,
// We are starting from TPCI octet (including): plainApdu.frame().data()+APDU_LPDU_DIFF
if (decrypt(plainApdu.frame().data() + APDU_LPDU_DIFF, plainApdu.length() + 1, srcAddress, dstAddress, isDstAddrGroupAddr, tpci, secureApdu.data() + 1, secCtrl, isSystemBroadcast))
{
LOGGER.info("decodeSecureApdu: Plain APDU: %s", ((string)plainApdu.frame().apdu()).c_str());
LOGGER.info("decodeSecureApdu: Plain APDU: %s", plainApdu.frame().apdu().to_string().c_str());
return true;
}
@ -1260,7 +1260,7 @@ bool SecureApplicationLayer::createSecureApdu(APDU& plainApdu, APDU& secureApdu,
{
// Create secure APDU
LOGGER.info("createSecureApdu: Plain APDU: %s", ((string)plainApdu.frame().apdu()).c_str());
LOGGER.info("createSecureApdu: Plain APDU: %s", plainApdu.frame().apdu().to_string().c_str());
uint16_t srcAddress = plainApdu.frame().sourceAddress();
uint16_t dstAddress = plainApdu.frame().destinationAddress();
@ -1296,7 +1296,7 @@ bool SecureApplicationLayer::createSecureApdu(APDU& plainApdu, APDU& secureApdu,
println(nextSequenceNumber(secCtrl.toolAccess), HEX);
updateSequenceNumber(secCtrl.toolAccess, nextSequenceNumber(secCtrl.toolAccess) + 1);
LOGGER.info("createSecureApdu: Secure APDU: %s", ((string)secureApdu.frame().apdu()).c_str());
LOGGER.info("createSecureApdu: Secure APDU: %s", secureApdu.frame().apdu().to_string().c_str());
return true;
}