mirror of
https://github.com/thelsing/knx.git
synced 2024-12-18 19:08:18 +01:00
frame logging data link layer
This commit is contained in:
parent
2585deb52c
commit
59a76b7c3f
@ -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;
|
||||
|
@ -37,7 +37,7 @@ class APDU
|
||||
/**
|
||||
* Convert APDU to string.
|
||||
*/
|
||||
operator std::string() const;
|
||||
std::string to_string() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user