diff --git a/examples/knx-linux/main.cpp b/examples/knx-linux/main.cpp index 488fbb4..4d80bd0 100644 --- a/examples/knx-linux/main.cpp +++ b/examples/knx-linux/main.cpp @@ -16,6 +16,8 @@ #include "fdsk.h" +#define LOGGER Logger::logger("App") + volatile sig_atomic_t loopActive = 1; void signalHandler(int sig) { @@ -109,20 +111,20 @@ void setup() GO_MAX.valueNoSend(-273.0); GO_RESET.dataPointType(Dpt(1, 15)); GO_RESET.callback(resetCallback); - printf("Timeout: %d\n", knx.paramWord(0)); - printf("Zykl. senden: %d\n", knx.paramByte(2)); - printf("Min/Max senden: %d\n", knx.paramByte(3)); - printf("Aenderung senden: %d\n", knx.paramByte(4)); - printf("Abgleich %d\n", knx.paramByte(5)); + LOGGER.info("Timeout: %d", knx.paramWord(0)); + LOGGER.info("Zykl. senden: %d", knx.paramByte(2)); + LOGGER.info("Min/Max senden: %d", knx.paramByte(3)); + LOGGER.info("Aenderung senden: %d", knx.paramByte(4)); + LOGGER.info("Abgleich %d", knx.paramByte(5)); } else - println("not configured"); + LOGGER.info("not configured"); knx.start(); } int main(int argc, char **argv) { - printf("main() start.\n"); + LOGGER.info("main() start."); uint8_t serialNumber[] = { 0x00, 0xFA, 0x01, 0x02, 0x03, 0x04}; uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; @@ -130,7 +132,7 @@ int main(int argc, char **argv) FdskCalculator calc; char fdskString[42]; // 6 * 6 chars + 5 dashes + nullbyte = 42 calc.snprintFdsk(fdskString, sizeof(fdskString), serialNumber, key); - printf("FDSK: %s\n", fdskString); + LOGGER.info("FDSK: %s", fdskString); // Prevent swapping of this process struct sched_param sp; @@ -160,5 +162,5 @@ int main(int argc, char **argv) // opens the "value" sysfs file to read or write the GPIO pin value. // The following calls will close the "value" sysfs fiel for the pin // and unexport the GPIO pin. - printf("main() exit.\n"); + LOGGER.info("main() exit."); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca23e76..28ba235 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -124,6 +124,7 @@ knx/ip/knx_ip_tunnel_connection.cpp knx/ip/knx_ip_tunnel_connection.h knx/ip/service_families.h knx/knx_types.h +knx/knx_types.cpp knx/knx_value.cpp knx/knx_value.h knx/memory.cpp diff --git a/src/knx/apdu.cpp b/src/knx/apdu.cpp index 966de35..1800335 100644 --- a/src/knx/apdu.cpp +++ b/src/knx/apdu.cpp @@ -6,7 +6,7 @@ APDU::APDU(uint8_t* data, CemiFrame& frame): _data(data), _frame(frame) { } -ApduType APDU::type() +ApduType APDU::type() const { uint16_t apci; apci = getWord(_data); @@ -40,20 +40,18 @@ uint8_t APDU::length() const return _frame.npdu().octetCount(); } -void APDU::printPDU() +APDU::operator std::string() const { - print("APDU: "); - print(type(), HEX); - print(" "); - print(_data[0] & 0x3, HEX); + string value = "APDU: " + enum_name(type()) + " "; + value += hex(_data[0] & 0x3); for (uint8_t i = 1; i < length() + 1; ++i) { if (i) - print(" "); + value += " "; - print(_data[i], HEX); + value += hex(_data[i]); } - println(); + return value; } diff --git a/src/knx/apdu.h b/src/knx/apdu.h index 7eacd32..13723b8 100644 --- a/src/knx/apdu.h +++ b/src/knx/apdu.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "knx_types.h" class CemiFrame; @@ -16,7 +17,7 @@ class APDU /** * Get the type of the APDU. */ - ApduType type(); + ApduType type() const; /** * Set the type of the APDU. */ @@ -34,9 +35,9 @@ class APDU */ uint8_t length() const; /** - * Print the contents of the APDU to console. + * Convert APDU to string. */ - void printPDU(); + operator std::string() const; protected: /** diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp index c7a3928..980486a 100644 --- a/src/knx/application_layer.cpp +++ b/src/knx/application_layer.cpp @@ -7,6 +7,8 @@ #include "string.h" #include "bits.h" #include +#include "util/logger.h" +#define LOGGER Logger::logger("ApplicationLayer") const SecurityControl ApplicationLayer::noSecurity {.toolAccess = false, .dataSecurity = DataSecurity::None}; @@ -1360,8 +1362,7 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior } default: - print("Individual-indication: unhandled APDU-Type: "); - apdu.printPDU(); + LOGGER.warning("Individual-indication: unhandled APDU-Type: %s", ((std::string)apdu).c_str()); } } diff --git a/src/knx/bits.cpp b/src/knx/bits.cpp index 16c2d6b..3800141 100644 --- a/src/knx/bits.cpp +++ b/src/knx/bits.cpp @@ -9,6 +9,15 @@ const uint8_t* popByte(uint8_t& b, const uint8_t* data) } #ifndef KNX_NO_PRINT +std::string hex(uint8_t byte) +{ + const char* hex = "0123456789ABCDEF"; + char out[3] = {0}; + out[0] = hex[(byte >> 4) & 0xF]; + out[1] = hex[ byte & 0xF]; + return std::string(out); +} + void printHex(const char* suffix, const uint8_t* data, size_t length, bool newline) { print(suffix); diff --git a/src/knx/bits.h b/src/knx/bits.h index 28d31e9..d9ee59f 100644 --- a/src/knx/bits.h +++ b/src/knx/bits.h @@ -2,6 +2,7 @@ #include #include +#include #if defined(__linux__) #include @@ -70,6 +71,7 @@ #endif #ifndef KNX_NO_PRINT + std::string hex(uint8_t byte); void print(const char[]); void print(char); void print(unsigned char, int = DEC); diff --git a/src/knx/data_link_layer.cpp b/src/knx/data_link_layer.cpp index 3eb159d..41c6658 100644 --- a/src/knx/data_link_layer.cpp +++ b/src/knx/data_link_layer.cpp @@ -5,6 +5,9 @@ #include "device_object.h" #include "cemi_server.h" #include "cemi_frame.h" +#include "util/logger.h" + +#define LOGGER Logger::logger("DataLinkLayer") void DataLinkLayerCallbacks::activity(uint8_t info) @@ -36,22 +39,22 @@ void DataLinkLayer::cemiServer(CemiServer& cemiServer) #ifdef KNX_TUNNELING void DataLinkLayer::dataRequestToTunnel(CemiFrame& frame) { - println("default dataRequestToTunnel"); + LOGGER.info("default dataRequestToTunnel"); } void DataLinkLayer::dataConfirmationToTunnel(CemiFrame& frame) { - println("default dataConfirmationToTunnel"); + LOGGER.info("default dataConfirmationToTunnel"); } void DataLinkLayer::dataIndicationToTunnel(CemiFrame& frame) { - println("default dataIndicationToTunnel"); + LOGGER.info("default dataIndicationToTunnel"); } bool DataLinkLayer::isTunnelAddress(uint16_t addr) { - println("default IsTunnelAddress"); + LOGGER.info("default IsTunnelAddress"); return false; } #endif @@ -157,6 +160,11 @@ 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()); + } + #ifdef USE_CEMI_SERVER // Do not send our own message back to the tunnel #ifdef KNX_TUNNELING @@ -207,7 +215,7 @@ bool DataLinkLayer::sendTelegram(NPDU& npdu, AckType ack, uint16_t destinationAd frame.sourceAddress(sourceAddr); frame.addressType(addrType); frame.priority(priority); - frame.repetition(doNotRepeat ? NoRepitiion : RepetitionAllowed); + frame.repetition(doNotRepeat ? NoRepetiion : RepetitionAllowed); frame.systemBroadcast(systemBroadcast); if (npdu.octetCount() <= 15) @@ -218,15 +226,14 @@ bool DataLinkLayer::sendTelegram(NPDU& npdu, AckType ack, uint16_t destinationAd if (!frame.valid()) { - println("invalid frame"); + LOGGER.warning("invalid frame"); return false; } - // if (frame.npdu().octetCount() > 0) - // { - // _print("<- DLL "); - // frame.apdu().printPDU(); - // } + if (frame.npdu().octetCount() > 0) + { + LOGGER.info("<- %s", ((string)frame.apdu()).c_str()); + } bool sendTheFrame = true; bool success = true; diff --git a/src/knx/dpt.cpp b/src/knx/dpt.cpp index 9af00c2..af0d994 100644 --- a/src/knx/dpt.cpp +++ b/src/knx/dpt.cpp @@ -1,4 +1,6 @@ #include "dpt.h" +#include "util/logger.h" +#define LOGGER Logger::logger("Dpt") #include "bits.h" diff --git a/src/knx/knx_types.cpp b/src/knx/knx_types.cpp new file mode 100644 index 0000000..1f9d033 --- /dev/null +++ b/src/knx/knx_types.cpp @@ -0,0 +1,706 @@ +#include "knx_types.h" + +const string enum_name(const LCCONFIG enum_val) +{ + switch (enum_val) + { + case PHYS_FRAME: + return "PHYS_FRAME(ROUT)"; + + case PHYS_FRAME_UNLOCK: + return "PHYS_FRAME_UNLOCK"; + + case PHYS_FRAME_LOCK: + return "PHYS_FRAME_LOCK"; + + case PHYS_REPEAT: + return "PHYS_REPEAT"; + + case BROADCAST_LOCK: + return "BROADCAST_LOCK"; + + case BROADCAST_REPEAT: + return "BROADCAST_REPEAT"; + + case GROUP_IACK_ROUT: + return "GROUP_IACK_ROUT"; + + case PHYS_IACK: + return "PHYS_IACK/NACK"; + + case PHYS_IACK_NORMAL: + return "PHYS_IACK_NORMAL"; + + case PHYS_IACK_ALL: + return "PHYS_IACK_ALL"; + } + + return to_string(enum_val); +} + + +const string enum_name(const LCGRPCONFIG enum_val) +{ + switch (enum_val) + { + case GROUP_6FFF: + return "GROUP_6FFF(ROUTE)"; + + case GROUP_7000: + return "GROUP_7000(ROUTE)"; + + case GROUP_REPEAT: + return "GROUP_REPEAT"; + + case GROUP_6FFFUNLOCK: + return "GROUP_6FFFUNLOCK"; + + case GROUP_6FFFLOCK: + return "GROUP_6FFFLOCK"; + + case GROUP_7000UNLOCK: + return "GROUP_7000UNLOCK"; + + case GROUP_7000LOCK: + return "GROUP_7000LOCK"; + } + + return to_string(enum_val); +} + + +const string enum_name(const DptMedium enum_val) +{ + switch (enum_val) + { + case KNX_TP1: + return "KNX_TP1"; + + case KNX_PL110: + return "KNX_PL110"; + + case KNX_RF: + return "KNX_RF"; + + case KNX_IP: + return "KNX_IP"; + } + + return to_string(enum_val); +} + + +const string enum_name(const EraseCode enum_val) +{ + switch (enum_val) + { + case Void: + return "Void"; + + case ConfirmedRestart: + return "ConfirmedRestart"; + + case FactoryReset: + return "FactoryReset"; + + case ResetIA: + return "ResetIA"; + + case ResetAP: + return "ResetAP"; + + case ResetParam: + return "ResetParam"; + + case ResetLinks: + return "ResetLinks"; + + case FactoryResetWithoutIA: + return "FactoryResetWithoutIA"; + } + + return to_string(enum_val); +} + + +const string enum_name(const RestartType enum_val) +{ + switch (enum_val) + { + case BasicRestart: + return "BasicRestart"; + + case MasterReset: + return "MasterReset"; + } + + return to_string(enum_val); +} + + +const string enum_name(const DataSecurity enum_val) +{ + switch (enum_val) + { + case None: + return "None"; + + case Auth: + return "Auth"; + + case AuthConf: + return "AuthConf"; + } + + return to_string(enum_val); +} + + +const string enum_name(const ApduType enum_val) +{ + switch (enum_val) + { + case GroupValueRead: + return "GroupValueRead"; + + case GroupValueResponse: + return "GroupValueResponse"; + + case GroupValueWrite: + return "GroupValueWrite"; + + case IndividualAddressWrite: + return "IndividualAddressWrite"; + + case IndividualAddressRead: + return "IndividualAddressRead"; + + case IndividualAddressResponse: + return "IndividualAddressResponse"; + + case IndividualAddressSerialNumberRead: + return "IndividualAddressSerialNumberRead"; + + case IndividualAddressSerialNumberResponse: + return "IndividualAddressSerialNumberResponse"; + + case IndividualAddressSerialNumberWrite: + return "IndividualAddressSerialNumberWrite"; + + case SystemNetworkParameterRead: + return "SystemNetworkParameterRead"; + + case SystemNetworkParameterResponse: + return "SystemNetworkParameterResponse"; + + case SystemNetworkParameterWrite: + return "SystemNetworkParameterWrite"; + + case DomainAddressWrite: + return "DomainAddressWrite"; + + case DomainAddressRead: + return "DomainAddressRead"; + + case DomainAddressResponse: + return "DomainAddressResponse"; + + case DomainAddressSelectiveRead: + return "DomainAddressSelectiveRead"; + + case DomainAddressSerialNumberRead: + return "DomainAddressSerialNumberRead"; + + case DomainAddressSerialNumberResponse: + return "DomainAddressSerialNumberResponse"; + + case DomainAddressSerialNumberWrite: + return "DomainAddressSerialNumberWrite"; + + case ADCRead: + return "ADCRead"; + + case ADCResponse: + return "ADCResponse"; + + case PropertyValueExtRead: + return "PropertyValueExtRead"; + + case PropertyValueExtResponse: + return "PropertyValueExtResponse"; + + case PropertyValueExtWriteCon: + return "PropertyValueExtWriteCon"; + + case PropertyValueExtWriteConResponse: + return "PropertyValueExtWriteConResponse"; + + case PropertyValueExtWriteUnCon: + return "PropertyValueExtWriteUnCon"; + + case PropertyExtDescriptionRead: + return "PropertyExtDescriptionRead"; + + case PropertyExtDescriptionResponse: + return "PropertyExtDescriptionResponse"; + + case FunctionPropertyExtCommand: + return "FunctionPropertyExtCommand"; + + case FunctionPropertyExtState: + return "FunctionPropertyExtState"; + + case FunctionPropertyExtStateResponse: + return "FunctionPropertyExtStateResponse"; + + case MemoryExtWrite: + return "MemoryExtWrite"; + + case MemoryExtWriteResponse: + return "MemoryExtWriteResponse"; + + case MemoryExtRead: + return "MemoryExtRead"; + + case MemoryExtReadResponse: + return "MemoryExtReadResponse"; + + case MemoryRead: + return "MemoryRead"; + + case MemoryResponse: + return "MemoryResponse"; + + case MemoryWrite: + return "MemoryWrite"; + + case UserMemoryRead: + return "UserMemoryRead"; + + case UserMemoryResponse: + return "UserMemoryResponse"; + + case UserMemoryWrite: + return "UserMemoryWrite"; + + case UserManufacturerInfoRead: + return "UserManufacturerInfoRead"; + + case UserManufacturerInfoResponse: + return "UserManufacturerInfoResponse"; + + case FunctionPropertyCommand: + return "FunctionPropertyCommand"; + + case FunctionPropertyState: + return "FunctionPropertyState"; + + case FunctionPropertyStateResponse: + return "FunctionPropertyStateResponse"; + + case DeviceDescriptorRead: + return "DeviceDescriptorRead"; + + case DeviceDescriptorResponse: + return "DeviceDescriptorResponse"; + + case Restart: + return "Restart"; + + case RestartMasterReset: + return "RestartMasterReset"; + + case RoutingTableOpen: + return "RoutingTableOpen"; + + case RoutingTableRead: + return "RoutingTableRead"; + + case RoutingTableReadResponse: + return "RoutingTableReadResponse"; + + case RoutingTableWrite: + return "RoutingTableWrite"; + + case MemoryRouterWrite: + return "MemoryRouterWrite"; + + case MemoryRouterReadResponse: + return "MemoryRouterReadResponse"; + + case AuthorizeRequest: + return "AuthorizeRequest"; + + case AuthorizeResponse: + return "AuthorizeResponse"; + + case KeyWrite: + return "KeyWrite"; + + case KeyResponse: + return "KeyResponse"; + + case PropertyValueRead: + return "PropertyValueRead"; + + case PropertyValueResponse: + return "PropertyValueResponse"; + + case PropertyValueWrite: + return "PropertyValueWrite"; + + case PropertyDescriptionRead: + return "PropertyDescriptionRead"; + + case PropertyDescriptionResponse: + return "PropertyDescriptionResponse"; + + case SecureService: + return "SecureService"; + } + + return to_string(enum_val); +} + + +const string enum_name(const TpduType enum_val) +{ + switch (enum_val) + { + case DataBroadcast: + return "DataBroadcast"; + + case DataGroup: + return "DataGroup"; + + case DataInduvidual: + return "DataInduvidual"; + + case DataConnected: + return "DataConnected"; + + case Connect: + return "Connect"; + + case Disconnect: + return "Disconnect"; + + case Ack: + return "Ack"; + + case Nack: + return "Nack"; + } + + return to_string(enum_val); +} + + +const string enum_name(const HopCountType enum_val) +{ + switch (enum_val) + { + case UnlimitedRouting: + return "UnlimitedRouting"; + + case NetworkLayerParameter: + return "NetworkLayerParameter"; + } + + return to_string(enum_val); +} + + +const string enum_name(const Confirm enum_val) +{ + switch (enum_val) + { + case ConfirmNoError: + return "ConfirmNoError"; + + case ConfirmError: + return "ConfirmError"; + } + + return to_string(enum_val); +} + + +const string enum_name(const SystemBroadcast enum_val) +{ + switch (enum_val) + { + case SysBroadcast: + return "SysBroadcast"; + + case Broadcast: + return "Broadcast"; + } + + return to_string(enum_val); +} + + +const string enum_name_in(Repetition enum_val) +{ + switch (enum_val) + { + case WasRepeated: + return "WasRepeated"; + + 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 to_string(enum_val); +} + +const string enum_name(const ReturnCodes enum_val) +{ + switch (enum_val) + { + case Success: + return "Success"; + + case SuccessWithCrc: + return "SuccessWithCrc"; + + case MemoryError: + return "MemoryError"; + + case InvalidCommand: + return "InvalidCommand"; + + case ImpossibleCommand: + return "ImpossibleCommand"; + + case ExceedsMaxApduLength: + return "ExceedsMaxApduLength"; + + case DataOverflow: + return "DataOverflow"; + + case OutOfMinRange: + return "OutOfMinRange"; + + case OutOfMaxRange: + return "OutOfMaxRange"; + + case DataVoid: + return "DataVoid"; + + case TemporarilyNotAvailable: + return "TemporarilyNotAvailable"; + + case AccessWriteOnly: + return "AccessWriteOnly"; + + case AccessReadOnly: + return "AccessReadOnly"; + + case AccessDenied: + return "AccessDenied"; + + case AddressVoid: + return "AddressVoid"; + + case DataTypeConflict: + return "DataTypeConflict"; + + case GenericError: + return "GenericError"; + } + + return to_string(enum_val); +} + + +const string enum_name(const cEmiErrorCode enum_val) +{ + switch (enum_val) + { + case Unspecified_Error: + return "Unspecified_Error"; + + case Out_Of_Range: + return "Out_Of_Range"; + + case Out_Of_Max_Range: + return "Out_Of_Max_Range"; + + case Out_Of_Min_Range: + return "Out_Of_Min_Range"; + + case Memory_Error: + return "Memory_Error"; + + case Read_Only: + return "Read_Only"; + + case Illegal_Command: + return "Illegal_Command"; + + case Void_DP: + return "Void_DP"; + + case Type_Conflict: + return "Type_Conflict"; + + case Prop_Index_Range_Error: + return "Prop_Index_Range_Error"; + + case Value_temp_not_writeable: + return "Value_temp_not_writeable"; + } + + return to_string(enum_val); +} + + +const string enum_name(const MessageCode enum_val) +{ + switch (enum_val) + { + case L_data_req: + return "L_data_req"; + + case L_data_con: + return "L_data_con"; + + case L_data_ind: + return "L_data_ind"; + + case M_PropRead_req: + return "M_PropRead_req"; + + case M_PropRead_con: + return "M_PropRead_con"; + + case M_PropWrite_req: + return "M_PropWrite_req"; + + case M_PropWrite_con: + return "M_PropWrite_con"; + + case M_PropInfo_ind: + return "M_PropInfo_ind"; + + case M_FuncPropCommand_req: + return "M_FuncPropCommand_req"; + + case M_FuncPropCommand_con: + return "M_FuncPropCommand/StateRead_con"; + + case M_FuncPropStateRead_req: + return "M_FuncPropStateRead_req"; + + case M_Reset_req: + return "M_Reset_req"; + + case M_Reset_ind: + return "M_Reset_ind"; + } + + return to_string(enum_val); +} + + +const string enum_name(const AddressType enum_val) +{ + switch (enum_val) + { + case IndividualAddress: + return "IndividualAddress"; + + case GroupAddress: + return "GroupAddress"; + } + + return to_string(enum_val); +} + + +const string enum_name(const TPAckType enum_val) +{ + switch (enum_val) + { + case AckReqNack: + return "AckReqNack"; + + case AckReqBusy: + return "AckReqBusy"; + + case AckReqAck: + return "AckReqAck"; + + case AckReqNone: + return "AckReqNone"; + } + + return to_string(enum_val); +} + + +const string enum_name(const AckType enum_val) +{ + switch (enum_val) + { + case AckDontCare: + return "AckDontCare"; + + case AckRequested: + return "AckRequested"; + } + + return to_string(enum_val); +} + + +const string enum_name(const Priority enum_val) +{ + switch (enum_val) + { + case LowPriority: + return "LowPriority"; + + case NormalPriority: + return "NormalPriority"; + + case UrgentPriority: + return "UrgentPriority"; + + case SystemPriority: + return "SystemPriority"; + } + + return to_string(enum_val); +} + + +const string enum_name(const FrameFormat enum_val) +{ + switch (enum_val) + { + case ExtendedFrame: + return "ExtendedFrame"; + + case StandardFrame: + return "StandardFrame"; + } + + return to_string(enum_val); +} diff --git a/src/knx/knx_types.h b/src/knx/knx_types.h index 9e8afea..e95ff53 100644 --- a/src/knx/knx_types.h +++ b/src/knx/knx_types.h @@ -1,10 +1,13 @@ #pragma once +#include +using namespace std; enum FrameFormat { ExtendedFrame = 0, StandardFrame = 0x80 }; +const string enum_name(const FrameFormat enum_val); enum Priority { @@ -13,12 +16,14 @@ enum Priority UrgentPriority = 0x8, //!< Used for alarms. SystemPriority = 0x0 //!< Mainly used by ETS for device programming. }; +const string enum_name(const Priority enum_val); enum AckType { AckDontCare = 0, //!< We don't care about DataLinkLayer acknowledgement. AckRequested = 0x2, //!< We want a DataLinkLayer acknowledgement. }; +const string enum_name(const AckType enum_val); enum TPAckType { @@ -28,12 +33,14 @@ enum TPAckType AckReqAck = 0x01, AckReqNone = 0x0, }; +const string enum_name(const TPAckType enum_val); enum AddressType { IndividualAddress = 0, GroupAddress = 0x80, }; +const string enum_name(const AddressType enum_val); enum MessageCode { @@ -59,6 +66,7 @@ enum MessageCode M_Reset_req = 0xF1, M_Reset_ind = 0xF0, }; +const string enum_name(const MessageCode enum_val); enum cEmiErrorCode { @@ -74,6 +82,7 @@ enum cEmiErrorCode Prop_Index_Range_Error = 0x09, // read or write access to a non existing Property array index (R/W) Value_temp_not_writeable = 0x0A, // The Property exists but can at this moment not be written with a new value (W) }; +const string enum_name(const cEmiErrorCode enum_val); // Unified return codes for KNX services and functions // Note, that several older KNX services and functions do not use these return codes. @@ -99,32 +108,38 @@ enum ReturnCodes DataTypeConflict = 0xFE, // write access with wrong datatype (datapoint length) GenericError = 0xFF // service, function or command failed }; +const string enum_name(const ReturnCodes enum_val); enum Repetition { - NoRepitiion = 0, + NoRepetiion = 0, WasRepeated = 0, RepetitionAllowed = 0x20, WasNotRepeated = 0x20, }; +const string enum_name_in(Repetition enum_val); +const string enum_name_out(Repetition enum_val); enum SystemBroadcast { SysBroadcast = 0, Broadcast = 0x10, }; +const string enum_name(const SystemBroadcast enum_val); enum Confirm { ConfirmNoError = 0, ConfirmError = 1, }; +const string enum_name(const Confirm enum_val); enum HopCountType { UnlimitedRouting, //!< NPDU::hopCount is set to 7. This means that the frame never expires. This could be a problem if your bus contains a circle. NetworkLayerParameter //!< use NetworkLayer::hopCount as NPDU::hopCount }; +const string enum_name(const HopCountType enum_val); enum TpduType { @@ -137,6 +152,7 @@ enum TpduType Ack, Nack, }; +const string enum_name(const TpduType enum_val); enum ApduType { @@ -218,6 +234,7 @@ enum ApduType // Secure Service SecureService = 0x3F1 }; +const string enum_name(const ApduType enum_val); enum DataSecurity { @@ -225,6 +242,7 @@ enum DataSecurity Auth, AuthConf }; +const string enum_name(const DataSecurity enum_val); struct SecurityControl { @@ -237,6 +255,7 @@ enum RestartType BasicRestart = 0x0, MasterReset = 0x1 }; +const string enum_name(const RestartType enum_val); enum EraseCode { @@ -249,6 +268,7 @@ enum EraseCode ResetLinks = 0x06, FactoryResetWithoutIA = 0x07 }; +const string enum_name(const EraseCode enum_val); enum DptMedium { @@ -259,6 +279,7 @@ enum DptMedium KNX_RF = 0x02, KNX_IP = 0x05 }; +const string enum_name(const DptMedium enum_val); enum LCGRPCONFIG { @@ -272,6 +293,7 @@ enum LCGRPCONFIG GROUP_7000LOCK = 0b00001000, GROUP_7000ROUTE = 0b00001100 }; +const string enum_name(const LCGRPCONFIG enum_val); enum LCCONFIG { @@ -287,4 +309,5 @@ enum LCCONFIG PHYS_IACK_NORMAL = 0b01000000, PHYS_IACK_ALL = 0b10000000, PHYS_IACK_NACK = 0b11000000 -}; \ No newline at end of file +}; +const string enum_name(const LCCONFIG enum_val); \ No newline at end of file diff --git a/src/knx/platform/arduino_platform.h b/src/knx/platform/arduino_platform.h index 3b44101..124c884 100644 --- a/src/knx/platform/arduino_platform.h +++ b/src/knx/platform/arduino_platform.h @@ -1,4 +1,4 @@ -#include "knx/platform.h" +#include "../platform.h" #include "Arduino.h" diff --git a/src/knx/platform/cc1310_platform.h b/src/knx/platform/cc1310_platform.h index 4289077..020dafa 100644 --- a/src/knx/platform/cc1310_platform.h +++ b/src/knx/platform/cc1310_platform.h @@ -6,7 +6,7 @@ #include #include -#include "knx/platform.h" +#include "../platform.h" class CC1310Platform : public Platform { diff --git a/src/knx/secure_application_layer.cpp b/src/knx/secure_application_layer.cpp index 99388d1..7eab51c 100644 --- a/src/knx/secure_application_layer.cpp +++ b/src/knx/secure_application_layer.cpp @@ -12,6 +12,8 @@ #include "bau.h" #include "string.h" #include "bits.h" +#include "util/logger.h" +#define LOGGER Logger::logger("SecureApplicationLayer") // Select what cipher modes to include. We need AES128-CBC and AES128-CTR modes. #define CBC 1 @@ -658,8 +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)) { - println("SyncRequest: "); - request.apdu().printPDU(); + LOGGER.info("SyncRequest: %s", ((string)request.apdu()).c_str()); if (_syncReqBroadcastOutgoing) { @@ -722,8 +723,7 @@ void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGr { _lastSyncRes = millis(); - println("SyncResponse: "); - response.apdu().printPDU(); + LOGGER.info("SyncResponse: %s", ((string)response.apdu()).c_str()); if (_syncReqBroadcastIncoming) { @@ -1063,9 +1063,7 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLengt bool SecureApplicationLayer::decodeSecureApdu(APDU& secureApdu, APDU& plainApdu, SecurityControl& secCtrl) { // Decode secure APDU - - println("decodeSecureApdu: Secure APDU: "); - secureApdu.printPDU(); + LOGGER.info("decodeSecureApdu: Secure APDU: %s", ((string)secureApdu).c_str()); uint16_t srcAddress = secureApdu.frame().sourceAddress(); uint16_t dstAddress = secureApdu.frame().destinationAddress(); @@ -1087,9 +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)) { - println("decodeSecureApdu: Plain APDU: "); - plainApdu.frame().apdu().printPDU(); - + LOGGER.info("decodeSecureApdu: Plain APDU: %s", ((string)plainApdu.frame().apdu()).c_str()); return true; } @@ -1264,8 +1260,7 @@ bool SecureApplicationLayer::createSecureApdu(APDU& plainApdu, APDU& secureApdu, { // Create secure APDU - println("createSecureApdu: Plain APDU: "); - plainApdu.printPDU(); + LOGGER.info("createSecureApdu: Plain APDU: %s", ((string)plainApdu.frame().apdu()).c_str()); uint16_t srcAddress = plainApdu.frame().sourceAddress(); uint16_t dstAddress = plainApdu.frame().destinationAddress(); @@ -1301,8 +1296,7 @@ bool SecureApplicationLayer::createSecureApdu(APDU& plainApdu, APDU& secureApdu, println(nextSequenceNumber(secCtrl.toolAccess), HEX); updateSequenceNumber(secCtrl.toolAccess, nextSequenceNumber(secCtrl.toolAccess) + 1); - println("createSecureApdu: Secure APDU: "); - secureApdu.frame().apdu().printPDU(); + LOGGER.info("createSecureApdu: Secure APDU: %s", ((string)secureApdu.frame().apdu()).c_str()); return true; } diff --git a/src/knx/util/logger.h b/src/knx/util/logger.h new file mode 100644 index 0000000..6e585ad --- /dev/null +++ b/src/knx/util/logger.h @@ -0,0 +1,124 @@ +#include "../bits.h" +#include +#include +using namespace std; + +class Logger +{ + public: + static Logger logger(const string name) + { + return Logger(name); + } + inline void info(const string message, ...) + { +#ifndef KNX_NO_PRINT + va_list objects; + va_start( objects, message); + log(LogType::Info, message.c_str(), objects); + va_end(objects); +#endif + } + inline void warning(const string message, ...) + { +#ifndef KNX_NO_PRINT + va_list objects; + va_start( objects, message); + log(LogType::Warning, message.c_str(), objects); + va_end(objects); +#endif + } + inline void error(const string message, ...) + { +#ifndef KNX_NO_PRINT + va_list objects; + va_start( objects, message); + log(LogType::Error, message.c_str(), objects); + va_end(objects); +#endif + } + inline void critical(const string message, ...) + { +#ifndef KNX_NO_PRINT + va_list objects; + va_start( objects, message); + log(LogType::Critical, message.c_str(), objects); + va_end(objects); +#endif + } + inline void exception(const string message, ...) + { +#ifndef KNX_NO_PRINT + va_list objects; + va_start( objects, message); + log(LogType::Exception, message.c_str(), objects); + va_end(objects); +#endif + } + private: + enum LogType { Info, Warning, Error, Critical, Exception}; + const string enum_name(LogType type) + { + switch (type) + { + case LogType::Info: + return "INFO"; + + case LogType::Warning: + return "WARNING"; + + case LogType::Error: + return "ERROR"; + + case LogType::Critical: + return "CRITICAL"; + + case LogType::Exception: + return "EXCEPTION"; + } + return to_string(type); + } + const string _name; + Logger(const string name) : _name(name) {} + inline void log(LogType type, const char* format, va_list args) + { +#ifndef KNX_NO_PRINT + print(millis()); + print("\t"); + print(_name.c_str()); + print("\t"); + print(enum_name(type).c_str()); + print("\t"); + + while (*format) + { + if (*format == '%') + { + format++; + + if (*format == 'd') + { + print(va_arg(args, int)); + } + else if (*format == 's') + { + print(va_arg(args, char*)); + } + else if (*format == 'f') + { + print(va_arg(args, double)); + } + } + else + { + print(*format); + } + + format++; + } + + va_end(args); + println(); +#endif + } +}; \ No newline at end of file diff --git a/src/knx_facade.h b/src/knx_facade.h index 2fe0d0c..09fe25c 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -1,6 +1,7 @@ #pragma once #include "knx/bits.h" +#include "knx/util/logger.h" #include "knx/config.h" #include "knx/bau.h" #include "knx/bau07B0.h" @@ -201,12 +202,12 @@ template class KnxFacade : private SaveRestore if (_progLedState) { - println("progmode on"); + Logger::logger("KnxFacade").info("progmode on"); progLedOn(); } else { - println("progmode off"); + Logger::logger("KnxFacade").info("progmode off"); progLedOff(); } }