I used the MQTT client to send log prints to a broker on the network. It works very well and can handle a ridiculous number of prints per second.
I used the mqtt_event_handler callback event MQTT_EVENT_CONNECTED to register a new log vprintf function.
Here's how I did it.
To get the log output, just subscribe to the log's topic on the MQTT broker.
Code: Select all
// A simple helper function to publish a string log message.
// The return code is passed through from the underlying call.
int mqttSendLog(char *msg, int length)
{
// Use whatever MQTT topic you like here.
// I usually use no QOS here to keep things fast. (Also it's a tcp connection to the broken on my local network).
return esp_mqtt_client_publish(mqttClient, "test/Nate/log", msg, length, MQTT_QOS_NONE, 0);
}
// This function can be registered with the ESP_LOG subsystem to replace it's default
// output function. This lets us get system print logs over MQTT.
// The function signature must be the same as vprintf.
int systemLogApiVprintf(const char* fmt, va_list args)
{
// This also sends the log print to the normal serial output.
vprintf(fmt, args); // If you don't want this behavior, just comment this out.
int status = 0;
// In my system, I keep my prints pretty short so:
#define LOG_BUFFER_SIZE (128)
// Allocate some memory.
char *logBuff = malloc(LOG_BUFFER_SIZE);
if(logBuff != NULL)
{
// Print the log entry into a buffer.
status = vsnprintf(logBuff, LOG_BUFFER_SIZE, fmt, args);
// Send it to the MQTT client.
int mqttStatus = mqttSendLog(logBuff, status);
if(mqttStatus < 0)
{
// This is a global in my system to keep track of printing errors.
droppedPrintCount++;
}
// Free the buffer.
free(logBuff);
}
return status;
}
// Save the original registered log handler function pointer so we can restore it if
// we need to.
vprintf_like_t originalLogPrinter = NULL;
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
// Register the new log handler.
originalLogPrinter = esp_log_set_vprintf(systemLogApiVprintf);
// Try printing on the new handler.
ESP_LOGI(TAG, "Switched to MQTT logging");
break;
// The rest of the mqtt event handler code, etc...
}
}