added logger

This commit is contained in:
Dennis Gunia
2025-10-19 17:59:59 +02:00
parent dbb3f1c868
commit 9a5f18979a
10 changed files with 176 additions and 85 deletions

View File

@@ -87,7 +87,10 @@
"functional": "c",
"variant": "c",
"*.def": "c",
"unistd.h": "c"
"unistd.h": "c",
"string.h": "c",
"ftdi485.h": "c",
"logger.h": "c"
},
"C_Cpp.errorSquiggles": "enabled"
}

View File

@@ -60,8 +60,6 @@ void cmd_dm_register(json_object *req, json_object *res)
x = json_object_get_int(jx);
y = json_object_get_int(jy);
printf("[INFO][console] register new device wit addr %i at (%i,%i)", address, x, y);
int newId = devicemgr_register(fd, address, x, y, -1);
json_object_object_add(res, "id", json_object_new_int(newId));
}

View File

@@ -10,6 +10,7 @@
*/
#include "devicemgr.h"
#include "logging/logger.h"
#include <json-c/json_object.h>
#include <string.h>
#include <sys/types.h>
@@ -127,7 +128,7 @@ int devicemgr_readCalib(int device_id)
}
else
{
printf("Error reading eeprom from %i\n", device_id);
log_message(LOG_ERROR, "Error reading eeprom from %i", device_id);
free(buffer_r);
return -1;
}
@@ -246,12 +247,12 @@ void setSingle(int id, char flap)
{
// first convert char to flap id
char test_char = toupper(flap);
printf("find char %c\n", test_char);
// printf("find char %c\n", test_char);
for (int ix = 0; ix < 45; ix++)
{
if (*symbols[ix] == test_char)
{
printf("match char %i %i %i\n", test_char, *symbols[ix], ix);
// printf("match char %i %i %i\n", test_char, *symbols[ix], ix);
sfbus_display_full(devices[id].rs485_descriptor, devices[id].address, ix);
devices[id].current_flap = ix;
break;
@@ -272,7 +273,7 @@ void devicemgr_printText(const char *text, int x, int y)
int this_id = deviceMap[x + i][y];
if (this_id >= 0)
{
printf("print char %c to %i\n", *(text + i), devices[this_id].address);
log_message(LOG_DEBUG, "print char '%c' to id:%i", *(text + i), devices[this_id].address);
setSingle(this_id, *(text + i));
}
@@ -310,6 +311,7 @@ int devicemgr_register(int rs485_descriptor, u_int16_t address, int x, int y, in
nextFreeSlot++;
nid = nextFreeSlot;
}
log_message(LOG_INFO, "Register new device with addr %i at (%i,%i) with id %i", address, x, y, nid);
devices[nid].pos_x = x;
devices[nid].pos_y = y;
@@ -380,7 +382,7 @@ int devicemgr_save(char *file)
json_object_object_add(root, "devices", device_array);
const char *data = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY);
printf("[INFO][console] store data to %s\n", file);
log_message(LOG_INFO, "store config data to %s\n", file);
FILE *fptr;
fptr = fopen(file, "w");
@@ -392,6 +394,9 @@ int devicemgr_load(char *file)
{
FILE *fptr;
char *line_in_file = malloc(JSON_MAX_LINE_LEN); // maximum of 256 bytes per line;
log_message(LOG_INFO, "load config data from %s\n", file);
fptr = fopen(file, "r");
json_tokener *tok = json_tokener_new();
json_object *jobj = NULL;
@@ -412,7 +417,7 @@ int devicemgr_load(char *file)
if (jerr != json_tokener_success)
{
free(fptr); //free file pointer
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
log_message(LOG_ERROR, "%s", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
return -1;
}
@@ -429,7 +434,7 @@ int devicemgr_load(char *file)
json_object *next_free;
if (!json_object_object_get_ex(jobj, "nextFreeSlot", &next_free))
{
fprintf(stderr, "Error: %s\n", "Key 'nextFreeSlot' not found.");
log_message(LOG_ERROR, "%s", "Key 'nextFreeSlot' not found.");
return -1;
}
else
@@ -445,7 +450,7 @@ int devicemgr_load(char *file)
json_object *devices;
if (!json_object_object_get_ex(jobj, "devices", &devices))
{
fprintf(stderr, "Error: %s\n", "Key 'devices' not found.");
log_message(LOG_ERROR, "%s", "Key 'devices' not found.");
return -1;
}
else
@@ -470,22 +475,22 @@ int devicemgr_load_single(json_object *device_obj)
// verify values are present
if (jid == NULL)
{
fprintf(stderr, "Error: Key 'device.%s' not found\n", "id");
log_message(LOG_ERROR, "Key 'device.%s' not found", "id");
return -1;
}
if (jaddr == NULL)
{
fprintf(stderr, "Error: Key 'address.%s' not found\n", "id");
log_message(LOG_ERROR, "Error: Key 'address.%s' not found", "id");
return -1;
}
if (jposx == NULL)
{
fprintf(stderr, "Error: Key 'device.%s' not found\n", "position.x");
log_message(LOG_ERROR, "Error: Key 'device.%s' not found", "position.x");
return -1;
}
if (jposy == NULL)
{
fprintf(stderr, "Error: Key 'device.%s' not found\n", "position.y");
log_message(LOG_ERROR, "Error: Key 'device.%s' not found", "position.y");
return -1;
}

View File

@@ -8,50 +8,56 @@
*/
#include "ftdi485.h"
#include "logging/logger.h"
/*
* Open RS485 Interface (FT232RL)
*/
int rs485_init(char *device, int baud) {
int rs485_fd = open(device, O_RDWR);
if (rs485_fd < 0) {
printf("Error %i from open: %s\n", errno, strerror(errno));
return -1;
}
// Flush all data
int result = tcflush(rs485_fd, TCIOFLUSH);
if (result) {
perror("tcflush failed"); // just a warning, not a fatal error
return -1;
}
// Set port config and baud
struct termios options;
result = tcgetattr(rs485_fd, &options);
if (result) {
perror("tcgetattr failed");
close(rs485_fd);
return -1;
}
int rs485_init(char *device, int baud)
{
int rs485_fd = open(device, O_RDWR);
if (rs485_fd < 0)
{
log_message(LOG_CRITICAL, "Error %i from open: %s", errno, strerror(errno));
return -1;
}
// Flush all data
int result = tcflush(rs485_fd, TCIOFLUSH);
if (result)
{
log_message(LOG_WARNING, "RS485 tcflush failed"); // just a warning, not a fatal error
return -1;
}
// Set port config and baud
struct termios options;
result = tcgetattr(rs485_fd, &options);
if (result)
{
log_message(LOG_CRITICAL, "tcgetattr failed");
close(rs485_fd);
return -1;
}
// Turn off any options that might interfere with our ability to send and
// receive raw binary bytes.
options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
options.c_oflag &= ~(ONLCR | OCRNL);
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
// Turn off any options that might interfere with our ability to send and
// receive raw binary bytes.
options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
options.c_oflag &= ~(ONLCR | OCRNL);
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
// Set up timeouts: Calls to read() will return as soon as there is
// at least one byte available or when 100 ms has passed.
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 0;
// Set up timeouts: Calls to read() will return as soon as there is
// at least one byte available or when 100 ms has passed.
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 0;
cfsetospeed(&options, baud);
cfsetispeed(&options, baud);
result = tcsetattr(rs485_fd, TCSANOW, &options);
if (result) {
perror("tcsetattr failed");
close(rs485_fd);
return -1;
}
cfsetospeed(&options, baud);
cfsetispeed(&options, baud);
result = tcsetattr(rs485_fd, TCSANOW, &options);
if (result)
{
log_message(LOG_CRITICAL, "tcsetattr failed");
close(rs485_fd);
return -1;
}
return rs485_fd;
return rs485_fd;
}

View File

@@ -0,0 +1,43 @@
#include "logger.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int log_level_global = 4;
const char *loglevel[] = {"TRACE","DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"};
void init_logger(int log_level)
{
log_level_global = log_level;
}
void log_message(int level, const char *message, ...)
{
if (level >= log_level_global)
{
va_list args; // get arguments
va_start(args, message);
time_t now; // prepare time
time(&now);
char *ctime_no_newline = strtok(ctime(&now), "\n");
printf("%s [%s]: ", ctime_no_newline, loglevel[level]); // print message
vprintf(message, args);
printf("\n");
}
}
int log_message_header(int level)
{
if (level >= log_level_global)
{
time_t now; // prepare time
time(&now);
char *ctime_no_newline = strtok(ctime(&now), "\n");
printf("%s [%s]: ", ctime_no_newline, loglevel[level]); // print message
return 1;
}
return 0;
}

View File

@@ -0,0 +1,17 @@
#ifndef LOGGER_H
#define LOGGER_H
void log_message(int level, const char *message, ...);
int log_message_header(int level);
void init_logger(int log_level);
enum logLevelEnum
{
LOG_TRACE,
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR,
LOG_CRITICAL
};
#endif /* LOG_H */

View File

@@ -19,6 +19,7 @@
#include "console.h"
#include "devicemgr.h"
#include "ftdi485.h"
#include "logging/logger.h"
#include "sfbus.h"
extern char *optarg;
@@ -31,6 +32,9 @@ void printUsage(char *argv[])
int main(int argc, char *argv[])
{
init_logger(LOG_TRACE);
log_message(LOG_INFO, "Starting split-flap pc client %s", "v1.0.0");
log_message(LOG_INFO, "(c) 2024-2025 GuniaLabs (www.dennisgunia.de)");
int opt = ' ';
u_int16_t addr_int = 0;
char *port = malloc(256);
@@ -62,13 +66,13 @@ int main(int argc, char *argv[])
}
if (access(port, F_OK) != 0)
{
fprintf(stderr, "Filedescriptor: %s does not exist or cannot be opened\n", port);
log_message(LOG_CRITICAL, "Filedescriptor: %s does not exist or cannot be opened\n", port);
printUsage(argv);
}
// parse address
if (strlen(addr) == 0)
{
fprintf(stderr, "Please specify address\n");
log_message(LOG_CRITICAL, "Please specify address\n");
printUsage(argv);
}
else
@@ -79,7 +83,7 @@ int main(int argc, char *argv[])
// start program
setvbuf(stdout, NULL, _IONBF, 0); // do not buffer stdout!!!!
printf("Open device at %s\n", port);
log_message(LOG_INFO,"Open device at %s @ 57600 Baud", port);
int fd = rs485_init(port, B57600); // setup rs485
if (strcmp(command, "ping") == 0)

View File

@@ -8,11 +8,14 @@
*/
#include "sfbus-util.h"
#include "logging/logger.h"
int sfbusu_write_address(int fd, u_int16_t current, u_int16_t new)
{
log_message(LOG_INFO, "Writing new address 0x%04X to device with current address 0x%04X", new, current);
if (new < 1)
{
printf("Please specify new address > 0 with -d\n");
log_message(LOG_ERROR, "Cannot write address: Please specify new address > 0 with -d");
return -1;
}
// read current eeprom status
@@ -20,7 +23,7 @@ int sfbusu_write_address(int fd, u_int16_t current, u_int16_t new)
char *buffer_r = malloc(64);
if (sfbus_read_eeprom(fd, current, buffer_w) < 0)
{
fprintf(stderr, "Error reading eeprom\n");
log_message(LOG_ERROR, "Cannot write address: Error reading eeprom");
return 1;
}
// modify current addr
@@ -28,28 +31,28 @@ int sfbusu_write_address(int fd, u_int16_t current, u_int16_t new)
memcpy(buffer_w, &n_addr_16, 2);
if (sfbus_write_eeprom(fd, current, buffer_w, buffer_r) < 0)
{
fprintf(stderr, "Error writing eeprom\n");
log_message(LOG_ERROR, "Cannot write address: Error writing eeprom");
return 1;
}
return 0;
}
int sfbusu_write_calibration(int fd, u_int16_t address, u_int16_t data)
{
log_message(LOG_INFO, "Writing new calibration 0x%04X to device at address 0x%04X", data, address);
// read current eeprom status
char *buffer_w = malloc(64);
char *buffer_r = malloc(64);
if (sfbus_read_eeprom(fd, address, buffer_w) < 0)
{
fprintf(stderr, "Error reading eeprom\n");
log_message(LOG_ERROR, "Cannot write calibration: Error reading eeprom");
return 1;
}
// modify current calibration
memcpy(buffer_w + 2, &data, 2);
if (sfbus_write_eeprom(fd, address, buffer_w, buffer_r) < 0)
{
fprintf(stderr, "Error writing eeprom\n");
log_message(LOG_ERROR, "Cannot write address: Error writing eeprom");
return 1;
}

View File

@@ -8,10 +8,12 @@
*/
#include "sfbus.h"
#include "logging/logger.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
void print_charHex(char *buffer, int length)
{
int _tlength = length;
@@ -25,16 +27,22 @@ void print_charHex(char *buffer, int length)
void print_bufferHexRx(char *buffer, int length, u_int16_t address)
{
printf("Rx (0x%04X): ", address);
print_charHex(buffer, length);
printf("| %i bytes received\n", length);
if (log_message_header(LOG_TRACE) > 0)
{
printf("Rx (0x%04X): ", address);
print_charHex(buffer, length);
printf("| %i bytes received\n", length);
}
}
void print_bufferHexTx(char *buffer, int length, u_int16_t address)
{
printf("Tx (0x%04X): ", address);
print_charHex(buffer, length);
printf("| %i bytes sent\n", length);
if (log_message_header(LOG_TRACE) > 0)
{
printf("Tx (0x%04X): ", address);
print_charHex(buffer, length);
printf("| %i bytes sent\n", length);
}
}
ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
@@ -47,7 +55,7 @@ ssize_t sfbus_recv_frame_wait(int fd, u_int16_t address, char *buffer)
retryCount--;
if (retryCount == 0)
{
fprintf(stderr, "Rx timeout\n");
log_message(LOG_WARNING, "RX timeout waiting for data at 0x%04X", address);
return -1;
}
} while (len <= 0);
@@ -99,13 +107,16 @@ ssize_t sfbus_recv_frame_v2(int fd, u_int16_t address, char *buffer)
if (frm_crc == calc_crc)
{
printf("crc check okay! expected: %04X received: %04X\n", calc_crc, frm_crc);
log_message(LOG_DEBUG, "crc check okay! expected: %04X received: %04X", calc_crc, frm_crc);
return frm_length;
}
else
{
print_bufferHexRx(buffer, frm_length - 4, address);
printf("crc check failed! expected: %04X received: %04X\n", calc_crc, frm_crc);
if (log_message_header(LOG_TRACE) > 0)
{
print_bufferHexRx(buffer, frm_length - 4, address);
}
log_message(LOG_DEBUG,"crc check failed! expected: %04X received: %04X", calc_crc, frm_crc);
return -1;
}
@@ -150,13 +161,13 @@ int sfbus_ping(int fd, u_int16_t address)
int len = sfbus_recv_frame_wait(fd, 0xFFFF, buffer);
if (len == 5 && *buffer == (char)0xFF) // expect 0xFF on successful ping
{
printf("Ping okay!\n");
log_message(LOG_DEBUG, "Ping to 0x%04X okay!", address);
free(buffer);
return 0;
}
else
{
printf("Ping invalid response!\n");
log_message(LOG_WARNING, "Ping to 0x%04X failed! Invalid or no response.", address);
free(buffer);
return 1;
}
@@ -170,12 +181,12 @@ int sfbus_read_eeprom(int fd, u_int16_t address, char *buffer)
int len = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
if (len != 10)
{
printf("Invalid data!\n");
log_message(LOG_WARNING, "Invalid data received from 0x%04X! Unexpected package length.", address);
return -1;
}
if (*(_buffer + 5) != (char)0xAA || *(_buffer) != (char)0xAA)
{
printf("Invalid data!\n");
log_message(LOG_WARNING, "Invalid data received from 0x%04X! No ACK byte received.", address);
return -1;
}
memcpy(buffer, _buffer + 1, len - 4);
@@ -196,12 +207,12 @@ int sfbus_write_eeprom(int fd, u_int16_t address, char *wbuffer, char *rbuffer)
int len = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
if (len != 10)
{
printf("Invalid data!\n");
log_message(LOG_WARNING, "Invalid data received from 0x%04X! Unexpected package length.", address);
return -1;
}
if (*(_buffer + 5) != (char)0xAA || *(_buffer) != (char)0xAA)
{
printf("Invalid data!\n");
log_message(LOG_WARNING, "Invalid data received from 0x%04X! No ACK byte received.", address);
return -1;
}
memcpy(rbuffer, _buffer + 1, len - 4);
@@ -236,7 +247,7 @@ u_int8_t sfbus_read_status(int fd, u_int16_t address, double *voltage, u_int32_t
char *_buffer = malloc(256);
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
int res = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
int res = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
if (res < 0)
{
return 0xFF;

View File

@@ -8,7 +8,7 @@
*/
#include "wsserver.h"
#include "logging/logger.h"
/*
* This section provides a web server to controll the
* device manager through web sockets
@@ -22,7 +22,7 @@ void ws_opencon(ws_cli_conn_t client)
{
char *cli;
cli = ws_getaddress(client);
printf("Connection opened, addr: %s\n", cli);
log_message(LOG_DEBUG, "WebSocket connection opened, addr: %s", cli);
}
// called on closing websocket client
@@ -30,14 +30,14 @@ void ws_closecon(ws_cli_conn_t client)
{
char *cli;
cli = ws_getaddress(client);
printf("Connection closed, addr: %s\n", cli);
log_message(LOG_DEBUG, "WebSocket connection closed, addr: %s", cli);
}
// called on receiving websocket message
void ws_messagehandler(ws_cli_conn_t client, const unsigned char *msg, uint64_t size, int type)
{
char *cli = ws_getaddress(client);
printf("received message: %s (%zu), from: %s\n", msg, size, cli);
log_message(LOG_DEBUG, "WebSocket received message: %s (%zu), from: %s", msg, size, cli);
json_tokener *tok = json_tokener_new();
json_object *req = json_tokener_parse_ex(tok, msg, size);
@@ -46,13 +46,12 @@ void ws_messagehandler(ws_cli_conn_t client, const unsigned char *msg, uint64_t
if (jerr != json_tokener_success)
{
// check if request can be parsed, if not retrun error
send_json_error(client, "parsing error", json_tokener_error_desc(jerr));
send_json_error(client, "WebSocket JSON parsing error", json_tokener_error_desc(jerr));
}
else
{
// if it can be parsed, get command.
json_object *commandObj = json_object_object_get(req, "command");
printf("test");
if (commandObj != NULL)
{
const char *command = json_object_to_json_string(commandObj);
@@ -95,6 +94,8 @@ void send_json_error(ws_cli_conn_t client, char *error, const char *detail)
int start_webserver(json_object *(*commandparser_func_ptr)(json_object *))
{
commandparser_func = commandparser_func_ptr;
log_message(LOG_INFO, "Websocket server started at ws://%s:%d", WS_SERVER_ADDR, WS_SERVER_PORT);
ws_socket(&(struct ws_server){/*
* Bind host, such as:
* localhost -> localhost/127.0.0.1