Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions stm32/Stm32 Blue Pill Testing.md

Large diffs are not rendered by default.

88 changes: 88 additions & 0 deletions stm32/spotflow/logging/spotflow_log_backend.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "spotflow_log_backend.h"
#include "spotflow_log_cbor.h"
#include <stdio.h>
#include <string.h>

/* =========================
Internal Types
========================= */

typedef struct
{
char buffer[SPOTFLOW_LOG_BUFFER_SIZE];
} spotflow_log_msg_t;

/* =========================
Helpers
========================= */

static const char *spotflow_level_to_string(spotflow_log_level_t level)
{
switch (level)
{
case SPOTFLOW_LOG_LEVEL_ERROR: return "E";
case SPOTFLOW_LOG_LEVEL_WARN: return "W";
case SPOTFLOW_LOG_LEVEL_INFO: return "I";
case SPOTFLOW_LOG_LEVEL_DEBUG: return "D";
default: return "?";
}
}

static uint32_t spotflow_get_timestamp(void)
{
#if (SPOTFLOW_LOG_USE_TIMESTAMP == 1)
uint32_t ticks = spotflow_port_get_tick_count();

#if (SPOTFLOW_LOG_TIMESTAMP_IN_MS == 1)
return spotflow_port_tick_to_ms(ticks);
#else
return ticks;
#endif

#else
return 0;
#endif
}

/* =========================
Logging Task
========================= */

static void spotflow_log_task(void *argument)
{

}

/* =========================
Public API
========================= */

void spotflow_log_init(void)
{

}

void spotflow_log_write(spotflow_log_level_t level,
const char *tag,
const char *format, ...)
{
static size_t sequence_counter = 0;

char temp[SPOTFLOW_LOG_BUFFER_SIZE];

va_list args;
va_start(args, format);
vsnprintf(temp, sizeof(temp), format, args);
va_end(args);


/* --- CBOR integration --- */
struct message_metadata metadata = {
.severity = spotflow_cbor_convert_log_level_to_severity(level),
.uptime_ms = spotflow_get_timestamp(),
.sequence_number = sequence_counter++,
.source = tag
};

spotflow_log_cbor_send(format, temp, &metadata); // use level-char mapping
}
62 changes: 62 additions & 0 deletions stm32/spotflow/logging/spotflow_log_backend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef SPOTFLOW_BACKEND_LOG_H
#define SPOTFLOW_BACKEND_LOG_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdarg.h>
#include <stdint.h>
#include "spotflow.h"

struct message_metadata {
uint8_t severity;
unsigned long uptime_ms;
size_t sequence_number;
const char* source;
};

void spotflow_log_init(void);

void spotflow_log_write(spotflow_log_level_t level,
const char *tag,
const char *format, ...);


/* =========================
Logging Macros
========================= */

#if (SPOTFLOW_LOG_LEVEL >= SPOTFLOW_LOG_LEVEL_ERROR)
#define SPOTFLOW_LOGE(tag, fmt, ...) \
spotflow_log_write(SPOTFLOW_LOG_LEVEL_ERROR, tag, fmt, ##__VA_ARGS__)
#else
#define SPOTFLOW_LOGE(tag, fmt, ...)
#endif

#if (SPOTFLOW_LOG_LEVEL >= SPOTFLOW_LOG_LEVEL_WARN)
#define SPOTFLOW_LOGW(tag, fmt, ...) \
spotflow_log_write(SPOTFLOW_LOG_LEVEL_WARN, tag, fmt, ##__VA_ARGS__)
#else
#define SPOTFLOW_LOGW(tag, fmt, ...)
#endif

#if (SPOTFLOW_LOG_LEVEL >= SPOTFLOW_LOG_LEVEL_INFO)
#define SPOTFLOW_LOGI(tag, fmt, ...) \
spotflow_log_write(SPOTFLOW_LOG_LEVEL_INFO, tag, fmt, ##__VA_ARGS__)
#else
#define SPOTFLOW_LOGI(tag, fmt, ...)
#endif

#if (SPOTFLOW_LOG_LEVEL >= SPOTFLOW_LOG_LEVEL_DEBUG)
#define SPOTFLOW_LOGD(tag, fmt, ...) \
spotflow_log_write(SPOTFLOW_LOG_LEVEL_DEBUG, tag, fmt, ##__VA_ARGS__)
#else
#define SPOTFLOW_LOGD(tag, fmt, ...)
#endif

#ifdef __cplusplus
}
#endif

#endif // SPOTFLOW_BACKEND_LOG_H
131 changes: 131 additions & 0 deletions stm32/spotflow/logging/spotflow_log_cbor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include "spotflow_log_cbor.h"
#include "tinycbor/src/cbor.h"
#include <string.h>
#include <stdlib.h>
#include "spotflow.h" // For SPOTFLOW_LOG, queue, mqtt

/* CBOR property keys */
#define KEY_MESSAGE_TYPE 0x00
#define LOGS_MESSAGE_TYPE 0x00
#define KEY_BODY 0x01
#define KEY_BODY_TEMPLATE 0x02
#define KEY_BODY_TEMPLATE_VALUES 0x03
#define KEY_SEVERITY 0x04
#define KEY_LABELS 0x05
#define KEY_DEVICE_UPTIME_MS 0x06
#define KEY_SEQUENCE_NUMBER 0x0D

typedef enum {
LOG_SEVERITY_ERROR = 0x3C,
LOG_SEVERITY_WARN = 0x32,
LOG_SEVERITY_INFO = 0x28,
LOG_SEVERITY_DEBUG = 0x1E,
} LogSeverity;

/* Convert character log level to internal severity */
static uint8_t spotflow_log_cbor_convert_char_log_lvl(const char lvl)
{
switch(lvl) {
case 'E': return LOG_SEVERITY_ERROR;
case 'W': return LOG_SEVERITY_WARN;
case 'I': return LOG_SEVERITY_INFO;
case 'D': return LOG_SEVERITY_DEBUG;
case 'V': return LOG_SEVERITY_DEBUG;
default: return 0;
}
}

uint8_t* spotflow_log_cbor(const char* log_template,
char* body,
size_t* out_len,
const struct message_metadata* metadata)
{
CborEncoder array_encoder, map_encoder, labels_encoder;
uint8_t* buf = malloc(SPOTFLOW_CBOR_LOG_MAX_LEN);
if(!buf) {
// SPOTFLOW_LOG("Failed to allocate CBOR buffer");
return NULL;
}

size_t body_len = strlen(body);
if(body_len > 0 && body[body_len - 1] == '\n')
body[body_len - 1] = '\0';

cbor_encoder_init(&array_encoder, buf, SPOTFLOW_CBOR_LOG_MAX_LEN, 0);
cbor_encoder_create_map(&array_encoder, &map_encoder, 7);

/* messageType */
cbor_encode_uint(&map_encoder, KEY_MESSAGE_TYPE);
cbor_encode_uint(&map_encoder, LOGS_MESSAGE_TYPE);

/* body */
cbor_encode_uint(&map_encoder, KEY_BODY);
cbor_encode_text_stringz(&map_encoder, body);

/* severity */
cbor_encode_uint(&map_encoder, KEY_SEVERITY);
cbor_encode_uint(&map_encoder, metadata->severity);

/* body template */
cbor_encode_uint(&map_encoder, KEY_BODY_TEMPLATE);
cbor_encode_text_stringz(&map_encoder, log_template);

/* sequence number */
cbor_encode_uint(&map_encoder, KEY_SEQUENCE_NUMBER);
cbor_encode_uint(&map_encoder, metadata->sequence_number);

/* device uptime */
cbor_encode_uint(&map_encoder, KEY_DEVICE_UPTIME_MS);
cbor_encode_uint(&map_encoder, metadata->uptime_ms);

/* labels map */
cbor_encode_uint(&map_encoder, KEY_LABELS);
cbor_encoder_create_map(&map_encoder, &labels_encoder, 1);
cbor_encode_text_stringz(&labels_encoder, "source");
cbor_encode_text_stringz(&labels_encoder, metadata->source ? metadata->source : "");
cbor_encoder_close_container(&map_encoder, &labels_encoder);

cbor_encoder_close_container(&array_encoder, &map_encoder);

*out_len = cbor_encoder_get_buffer_size(&array_encoder, buf);
return buf;
}

void spotflow_log_cbor_send(const char* fmt,
char* buffer,
const struct message_metadata* metadata)
{
size_t len = strlen(buffer);
uint8_t severity = metadata->severity;

if(len > 0 && len < SPOTFLOW_LOG_BUFFER_SIZE) {
uint8_t* clog_cbor = spotflow_log_cbor(fmt, buffer, &len, metadata);
if(clog_cbor) {
spotflow_queue_push(clog_cbor, len);
// spotflow_mqtt_notify_action(SPOTFLOW_MQTT_NOTIFY_LOGS);
free(clog_cbor);
}
}
}

/**
* @brief Convert log level to Cloud severity values
*
* @param lvl
* @return uint32_t
*/
uint32_t spotflow_cbor_convert_log_level_to_severity(uint8_t lvl)
{
switch (lvl) {
case 'E':
return LOG_SEVERITY_ERROR;
case 'W':
return LOG_SEVERITY_WARN;
case 'I':
return LOG_SEVERITY_INFO;
case 'D':
return LOG_SEVERITY_DEBUG;
default:
return 0; /* unknown level */
}
}
29 changes: 29 additions & 0 deletions stm32/spotflow/logging/spotflow_log_cbor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef SPOTFLOW_LOG_CBOR_H
#define SPOTFLOW_LOG_CBOR_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>
#include <stdint.h>
#include "spotflow_log_backend.h"
/* CBOR encoding functions */
uint8_t* spotflow_log_cbor(const char* log_template,
char* body,
size_t* out_len,
const struct message_metadata* metadata);

void spotflow_log_cbor_send(const char* log_template,
char* buffer,
const struct message_metadata* metadata);

/* Level conversion helpers */
uint32_t spotflow_cbor_convert_log_level_to_severity(uint8_t lvl);
uint8_t spotflow_cbor_convert_severity_to_log_level(uint32_t severity);

#ifdef __cplusplus
}
#endif

#endif /* SPOTFLOW_LOG_CBOR_H */
Loading
Loading