diff --git a/examples/knx-linux/main.cpp b/examples/knx-linux/main.cpp index d94a2bb..8c8f5fa 100644 --- a/examples/knx-linux/main.cpp +++ b/examples/knx-linux/main.cpp @@ -66,7 +66,7 @@ void measureTemp() currentValue -= 50; // currentValue *= (670433.28 + 273); // currentValue -= 273; - println(currentValue); + LOGGER.info("current value: %f",currentValue); GO_CURR.value(currentValue); double max = GO_MAX.value(); @@ -97,6 +97,9 @@ void appLoop() void setup() { srand((unsigned int)time(NULL)); + + Logger::logLevel("App", Logger::Info); + Logger::logLevel("ApplicationLayer", Logger::Info); knx.readMemory(); if (knx.individualAddress() == 0xFFFF) diff --git a/src/knx/bits.cpp b/src/knx/bits.cpp index f291f81..33a9180 100644 --- a/src/knx/bits.cpp +++ b/src/knx/bits.cpp @@ -9,7 +9,7 @@ const uint8_t* popByte(uint8_t& b, const uint8_t* data) } -std::string byte2hex(uint8_t byte) +std::string byte2hex(const uint8_t byte) { const char* hex = "0123456789ABCDEF"; char out[3] = {0}; @@ -18,11 +18,21 @@ std::string byte2hex(uint8_t byte) return std::string(out); } -std::string word2hex(uint16_t value) +std::string word2hex(const uint16_t value) { return byte2hex((uint8_t) (value & 0xFF00) >> 8) + byte2hex((uint8_t) (value & 0xFF)); } +std::string array2hex(const uint8_t* value, size_t length) +{ + std::string result(""); + + for (size_t i = 0; i < length; i++) + result += byte2hex(value[i]) + " "; + + return result; +} + #ifndef KNX_NO_PRINT void printHex(const char* suffix, const uint8_t* data, size_t length, bool newline) { diff --git a/src/knx/bits.h b/src/knx/bits.h index 772bf0a..6bec014 100644 --- a/src/knx/bits.h +++ b/src/knx/bits.h @@ -70,8 +70,9 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); #endif - std::string byte2hex(uint8_t byte); - std::string word2hex(uint16_t value); + std::string byte2hex(const uint8_t byte); + std::string word2hex(const uint16_t value); + std::string array2hex(const uint8_t* value, size_t length); #ifndef KNX_NO_PRINT void print(const char[]); diff --git a/src/knx/memory.cpp b/src/knx/memory.cpp index a09eb55..5183976 100644 --- a/src/knx/memory.cpp +++ b/src/knx/memory.cpp @@ -1,4 +1,7 @@ #include "memory.h" +#include "util/logger.h" + +#define LOGGER Logger::logger("Memory") #include @@ -13,18 +16,18 @@ Memory::~Memory() void Memory::readMemory() { - println("readMemory"); + LOGGER.info("restoring persistant Memory"); uint8_t* flashStart = _platform.getNonVolatileMemoryStart(); size_t flashSize = _platform.getNonVolatileMemorySize(); if (flashStart == nullptr) { - println("no user flash available;"); + LOGGER.error("no user flash available;"); return; } - printHex("RESTORED ", flashStart, _metadataSize); + LOGGER.info("content %S", array2hex(flashStart, _metadataSize)); uint16_t metadataBlockSize = alignToPageSize(_metadataSize); @@ -66,64 +69,51 @@ void Memory::readMemory() } else { - println("manufacturerId or hardwareType are different"); - print("expexted manufacturerId: "); - print(_deviceObject.manufacturerId(), HEX); - print(", stored manufacturerId: "); - println(manufacturerId, HEX); - print("expexted hardwareType: "); - printHex("", _deviceObject.hardwareType(), LEN_HARDWARE_TYPE); - print(", stored hardwareType: "); - printHex("", hardwareType, LEN_HARDWARE_TYPE); - println(""); + LOGGER.warning("manufacturerId or hardwareType are different"); + LOGGER.warning("expexted manufacturerId: %S , stored manufacturerId: %S", + word2hex(_deviceObject.manufacturerId()), manufacturerId); + LOGGER.warning("expexted hardwareType: %S, stored hardwareType: %S", + array2hex(_deviceObject.hardwareType(), LEN_HARDWARE_TYPE), + array2hex(hardwareType, LEN_HARDWARE_TYPE)); } } else { - println("DataObject api changed, any data stored in flash is invalid."); - print("expexted DataObject api version: "); - print(_deviceObject.apiVersion, HEX); - print(", stored api version: "); - println(apiVersion, HEX); + LOGGER.warning("DataObject api changed, any data stored in flash is invalid."); + LOGGER.warning("expexted DataObject api version: %S, stored api version: %S", word2hex(_deviceObject.apiVersion), word2hex(apiVersion)); } if (versionCheck == FlashAllInvalid) { - println("ETS has to reprogram PA and application!"); + LOGGER.warning("You need to reprogram PA and application with ETS!"); return; } - println("restoring data from flash..."); - print("saverestores "); - println(_saveCount); + LOGGER.info("saverestores %d", _saveCount); for (int i = 0; i < _saveCount; i++) { - println(flashStart - buffer); - println("."); + LOGGER.info("Offset %d", buffer - flashStart); buffer = _saveRestores[i]->restore(buffer); } - println("restored saveRestores"); + LOGGER.info("restored saveRestores"); if (versionCheck == FlashTablesInvalid) { - println("TableObjects are referring to an older firmware version and are not loaded"); + LOGGER.warning("TableObjects are referring to an older firmware version and are not loaded"); return; } - print("tableObjs "); - println(_tableObjCount); + LOGGER.info("tableObjs %d", _tableObjCount); for (int i = 0; i < _tableObjCount; i++) { - println(flashStart - buffer); - println("."); + ptrdiff_t offset = (buffer - flashStart); buffer = _tableObjects[i]->restore(buffer); uint16_t memorySize = 0; buffer = popWord(memorySize, buffer); - println(memorySize); - + LOGGER.info("Offset %d, Size %d", offset, memorySize); if (memorySize == 0) continue; @@ -131,11 +121,12 @@ void Memory::readMemory() addNewUsedBlock(_tableObjects[i]->_data, memorySize); } - println("restored Tableobjects"); + LOGGER.info("restored Tableobjects"); } void Memory::writeMemory() { + LOGGER.info("writing persistang memory"); // first get the necessary size of the writeBuffer uint16_t writeBufferSize = _metadataSize; @@ -156,8 +147,7 @@ void Memory::writeMemory() flashPos = _platform.writeNonVolatileMemory(flashPos, buffer, bufferPos - buffer); - print("save saveRestores "); - println(_saveCount); + LOGGER.info("write saveRestores %d", _saveCount); for (int i = 0; i < _saveCount; i++) { @@ -165,8 +155,7 @@ void Memory::writeMemory() flashPos = _platform.writeNonVolatileMemory(flashPos, buffer, bufferPos - buffer); } - print("save tableobjs "); - println(_tableObjCount); + LOGGER.info("save tableobjs %d", _tableObjCount); for (int i = 0; i < _tableObjCount; i++) { @@ -179,7 +168,7 @@ void Memory::writeMemory() if (block == nullptr) { - println("_data of TableObject not in _usedList"); + LOGGER.error("_data of TableObject not in _usedList"); _platform.fatalError(); } @@ -244,7 +233,7 @@ uint8_t* Memory::allocMemory(size_t size) if (!blockToUse) { - println("No available non volatile memory!"); + LOGGER.error("No available non volatile memory!"); _platform.fatalError(); } @@ -287,7 +276,7 @@ void Memory::freeMemory(uint8_t* ptr) if (!found) { - println("freeMemory for not used pointer called"); + LOGGER.error("freeMemory for not used pointer called"); _platform.fatalError(); } @@ -328,7 +317,7 @@ MemoryBlock* Memory::removeFromList(MemoryBlock* head, MemoryBlock* item) if (!head || !item) { - println("invalid parameters of Memory::removeFromList"); + LOGGER.critical("invalid parameters of Memory::removeFromList"); _platform.fatalError(); } @@ -349,7 +338,7 @@ MemoryBlock* Memory::removeFromList(MemoryBlock* head, MemoryBlock* item) if (!found) { - println("tried to remove block from list not in it"); + LOGGER.critical("tried to remove block from list not in it"); _platform.fatalError(); } @@ -475,13 +464,13 @@ void Memory::addNewUsedBlock(uint8_t* address, size_t size) if (smallerFreeBlock == nullptr) { - println("addNewUsedBlock: no smallerBlock found"); + LOGGER.critical("addNewUsedBlock: no smallerBlock found"); _platform.fatalError(); } if ((smallerFreeBlock->address + smallerFreeBlock->size) < (address + size)) { - println("addNewUsedBlock: found block can't contain new block"); + LOGGER.critical("addNewUsedBlock: found block can't contain new block"); _platform.fatalError(); } diff --git a/src/knx/platform/linux_platform.cpp b/src/knx/platform/linux_platform.cpp index 2ba4866..394ea12 100644 --- a/src/knx/platform/linux_platform.cpp +++ b/src/knx/platform/linux_platform.cpp @@ -37,6 +37,9 @@ #include "../ip/ip_parameter_object.h" #include "../bits.h" #include "../ip/ip_host_protocol_address_information.h" +#include "../util/logger.h" + +#define LOGGER Logger::logger("LinuxPlatform") #define MAX_MEM 4096 @@ -46,7 +49,7 @@ LinuxPlatform::LinuxPlatform() if (socketMac < 0) { - printf("Lookup socket creation failed"); + LOGGER.critical("Lookup socket creation failed"); return; } @@ -158,7 +161,7 @@ void LinuxPlatform::restart() void LinuxPlatform::fatalError() { - printf("A fatal error occured. Stopping.\n"); + LOGGER.critical("A fatal error occured. Stopping.\n"); while (true) sleep(1); @@ -185,7 +188,7 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port) if (_multicastSocketFd == -1) { - perror("socket()"); + LOGGER.critical("socket() %s", strerror(errno)); fatalError(); } @@ -194,13 +197,13 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port) if (setsockopt(_multicastSocketFd, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0) { - perror("setsockopt:SO_REUSEADDR"); + LOGGER.critical("setsockopt:SO_REUSEADDR %s", strerror(errno)); fatalError(); } if (bind(_multicastSocketFd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { - perror("bind"); + LOGGER.critical("bind %s", strerror(errno)); fatalError(); } @@ -209,7 +212,7 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port) if (setsockopt(_multicastSocketFd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { - perror("setsockopt:IP_MULTICAST_LOOP"); + LOGGER.critical("setsockopt:IP_MULTICAST_LOOP %s", strerror(errno)); fatalError(); } @@ -219,7 +222,7 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port) if (setsockopt(_multicastSocketFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof(command)) < 0) { - perror("setsockopt:IP_ADD_MEMBERSHIP"); + LOGGER.critical("setsockopt:IP_ADD_MEMBERSHIP %s", strerror(errno)); fatalError(); } @@ -239,7 +242,7 @@ void LinuxPlatform::closeMultiCast() IP_DROP_MEMBERSHIP, &command, sizeof(command)) < 0) { - perror("setsockopt:IP_DROP_MEMBERSHIP"); + LOGGER.error("setsockopt:IP_DROP_MEMBERSHIP %s", strerror(errno)); } close(_multicastSocketFd); @@ -306,7 +309,7 @@ void LinuxPlatform::doMemoryMapping() if (_fd < 0) { - puts("Error in file opening"); + LOGGER.critical("Error in file opening"); //exit(-1); } @@ -316,7 +319,7 @@ void LinuxPlatform::doMemoryMapping() if (ret < 0) { - puts("Error in fstat"); + LOGGER.critical("Error in fstat"); //exit(-1); } @@ -326,7 +329,7 @@ void LinuxPlatform::doMemoryMapping() { if (ftruncate(_fd, FLASHSIZE) != 0) { - puts("Error extending file"); + LOGGER.critical("Error extending file"); //exit(-1); } @@ -344,7 +347,7 @@ void LinuxPlatform::doMemoryMapping() if (addr == MAP_FAILED) { - puts("Error in mmap"); + LOGGER.critical("Error in mmap"); //exit(-1); } @@ -354,7 +357,7 @@ void LinuxPlatform::doMemoryMapping() void LinuxPlatform::closeSpi() { close(_spiFd); - printf("SPI device closed.\r\n"); + LOGGER.info("SPI device closed."); } int LinuxPlatform::readWriteSpi(uint8_t* data, size_t len) @@ -384,7 +387,7 @@ void LinuxPlatform::setupSpi() { if ((_spiFd = open("/dev/spidev0.0", O_RDWR)) < 0) { - printf("ERROR: SPI setup failed! Could not open SPI device!\r\n"); + LOGGER.error("ERROR: SPI setup failed! Could not open SPI device!"); return; } @@ -395,26 +398,26 @@ void LinuxPlatform::setupSpi() if (ioctl(_spiFd, SPI_IOC_WR_MODE, &mode) < 0) { - printf("ERROR: SPI Mode Change failure: %s\n", strerror(errno)); + LOGGER.error("ERROR: SPI Mode Change failure: %s", strerror(errno)); close(_spiFd); return; } if (ioctl(_spiFd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0) { - printf("ERROR: SPI BPW Change failure: %s\n", strerror(errno)); + LOGGER.error("ERROR: SPI BPW Change failure: %s", strerror(errno)); close(_spiFd); return; } if (ioctl(_spiFd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) { - printf("ERROR: SPI Speed Change failure: %s\n", strerror(errno)); + LOGGER.error("ERROR: SPI Speed Change failure: %s", strerror(errno)); close(_spiFd); return; } - printf("SPI device setup ok.\r\n"); + LOGGER.info("SPI device setup ok."); } void LinuxPlatform::flashFilePath(const std::string path) @@ -856,13 +859,13 @@ int gpio_export(int pin) int fd; /* Filedescriptor */ int res; /* Result from write() */ - fprintf(stderr, "Export GPIO pin %d\n", pin); + LOGGER.info("Export GPIO pin %d", pin); fd = open("/sys/class/gpio/export", O_WRONLY); if (fd < 0) { - perror("Could not export GPIO pin(open)!\n"); + LOGGER.error("Could not export GPIO pin(open)! %s", strerror(errno)); return (-1); } @@ -871,7 +874,7 @@ int gpio_export(int pin) if (res < 0) { - perror("Could not export GPIO pin(write)!\n"); + LOGGER.error("Could not export GPIO pin(write)! %s", strerror(errno)); return (-1); } @@ -892,7 +895,7 @@ int gpio_unexport(int pin) int fd; /* Filedescriptor */ int res; /* Result from write() */ - fprintf(stderr, "Unexport GPIO pin %d\n", pin); + LOGGER.info("Unexport GPIO pin %d", pin); close(gpioFds[pin]); @@ -900,7 +903,7 @@ int gpio_unexport(int pin) if (fd < 0) { - perror("Could not unexport GPIO pin(open)!\n"); + LOGGER.error("Could not unexport GPIO pin(open)! %s", strerror(errno)); return (-1); } @@ -909,7 +912,7 @@ int gpio_unexport(int pin) if (res < 0) { - perror("Could not unexport GPIO pin(write)!\n"); + LOGGER.error("Could not unexport GPIO pin(write)! %s", strerror(errno)); return (-1); } @@ -928,14 +931,14 @@ int gpio_direction(int pin, int dir) int fd; /* Filedescriptor */ int res; /* Result from write() */ - fprintf(stderr, "Set GPIO direction for pin %d to %s\n", pin, (dir == INPUT) ? "INPUT" : "OUTPUT"); + LOGGER.info("Set GPIO direction for pin %d to %s", pin, (dir == INPUT) ? "INPUT" : "OUTPUT"); snprintf(path, MAX_STRBUF_SIZE, "/sys/class/gpio/gpio%d/direction", pin); fd = open(path, O_WRONLY); if (fd < 0) { - perror("Could not set mode for GPIO pin(open)!\n"); + LOGGER.error("Could not set mode for GPIO pin(open)! %s", strerror(errno)); return (-1); } @@ -956,7 +959,7 @@ int gpio_direction(int pin, int dir) if (res < 0) { - perror("Could not set mode for GPIO pin(write)!\n"); + LOGGER.error("Could not set mode for GPIO pin(write)! %s", strerror(errno)); return (-1); } @@ -979,7 +982,7 @@ int gpio_read(int pin) if (gpioFds[pin] < 0) { - perror("Could not read from GPIO(open)!\n"); + LOGGER.error("Could not read from GPIO(open)! %s", strerror(errno)); return (-1); } @@ -987,7 +990,7 @@ int gpio_read(int pin) if (read(gpioFds[pin], &c, 1) < 0) { - perror("Could not read from GPIO(read)!\n"); + LOGGER.error("Could not read from GPIO(read)! %s", strerror(errno)); return (-1); } @@ -999,6 +1002,9 @@ int gpio_read(int pin) */ int gpio_write(int pin, int value) { + if (pin < 0) + return -1; + char path[MAX_STRBUF_SIZE]; /* Buffer for path */ int res; /* Result from write()*/ @@ -1009,7 +1015,7 @@ int gpio_write(int pin, int value) if (gpioFds[pin] < 0) { - perror("Could not write to GPIO(open)!\n"); + LOGGER.error("Could not write to GPIO(open)! %s", strerror(errno)); return (-1); } @@ -1030,7 +1036,7 @@ int gpio_write(int pin, int value) if (res < 0) { - perror("Could not write to GPIO(write)!\n"); + LOGGER.error("Could not write to GPIO(write)! %s", strerror(errno)); return (-1); } @@ -1053,7 +1059,7 @@ int gpio_edge(unsigned int pin, char edge) if (fd < 0) { - perror("Could not set GPIO edge detection(open)!\n"); + LOGGER.error("Could not set GPIO edge detection(open)! %s", strerror(errno)); return (-1); } @@ -1106,7 +1112,7 @@ int gpio_wait(unsigned int pin, int timeout) if (fd < 0) { - perror("Could not wait for GPIO edge(open)!\n"); + LOGGER.error("Could not wait for GPIO edge(open)! %s", strerror(errno)); return (-1); } @@ -1125,7 +1131,7 @@ int gpio_wait(unsigned int pin, int timeout) if (rc < 0) { /* poll() failed! */ - perror("Could not wait for GPIO edge(poll)!\n"); + LOGGER.error("Could not wait for GPIO edge(poll)! %s", strerror(errno)); close(fd); return (-1); } @@ -1142,7 +1148,7 @@ int gpio_wait(unsigned int pin, int timeout) if (rc < 0) { /* read() failed! */ - perror("Could not wait for GPIO edge(read)!\n"); + LOGGER.error("Could not wait for GPIO edge(read)! %s", strerror(errno)); close(fd); return (-2); } diff --git a/src/knx/util/logger.cpp b/src/knx/util/logger.cpp index 13117b3..59ef1fd 100644 --- a/src/knx/util/logger.cpp +++ b/src/knx/util/logger.cpp @@ -1,8 +1,17 @@ #include "logger.h" -Logger Logger::logger(const std::string name) +Map Logger::_loggers; +Logger Logger::_logger; + +Logger& Logger::logger(const std::string name) { - return Logger(name); + _logger.name(name); + return _logger; +} + +void Logger::logLevel(const std::string name, LogType level) +{ + _loggers.insertOrAssign(name, level); } void Logger::info(const std::string message, ...) @@ -58,6 +67,20 @@ void Logger::exception(const std::string message, ...) void Logger::log(LogType type, const char* format, va_list args) { #ifndef KNX_NO_PRINT + LogType* level = _loggers.get(_name); + if(level == nullptr) { + print("Logger "); + print(_name.c_str()); + print(" is disabled. Use Logger::logLevel(\""); + print(_name.c_str()); + println("\", Logger::Info) to enable."); + _loggers.insertOrAssign(_name, Disabled); + return; + } + + if(*level > type) + return; + print(millis()); print(" "); print(_name.c_str()); @@ -119,6 +142,9 @@ const std::string Logger::enum_name(LogType type) case LogType::Exception: return "EXCE"; + + case LogType::Disabled: + return "DISA"; } return std::to_string(type); diff --git a/src/knx/util/logger.h b/src/knx/util/logger.h index 73eb40d..6fabb31 100644 --- a/src/knx/util/logger.h +++ b/src/knx/util/logger.h @@ -1,20 +1,27 @@ #include "../bits.h" #include #include +#include "simple_map.h" +class NoOpLogger; class Logger { public: - static Logger logger(const std::string name); + enum LogType { Info, Warning, Error, Critical, Exception, Disabled}; + static Logger& logger(const std::string name); + static void logLevel(const std::string name, LogType level); void info(const std::string message, ...); void warning(const std::string message, ...); void error(const std::string message, ...); void critical(const std::string message, ...); void exception(const std::string message, ...); + protected: + Logger() {} + virtual void log(LogType type, const char* format, va_list args); + void name(std::string value) { _name = value; } private: - enum LogType { Info, Warning, Error, Critical, Exception}; const std::string enum_name(LogType type); - const std::string _name; - Logger(const std::string name) : _name(name) {} - inline void log(LogType type, const char* format, va_list args); + std::string _name = ""; + static Map _loggers; + static Logger _logger; }; \ No newline at end of file