send data to zabbix

tgk8888
Posts: 3
Joined: Mon Feb 14, 2022 4:43 am

send data to zabbix

Postby tgk8888 » Thu Jan 02, 2025 1:45 am

Hi! I'm trying to send a random number to the zabbix server, but nothing is working. At the same time, zabbix-sender and the Python example work fine. It looks like I have an incorrect POST request. I get the error "HTTP POST request failed: ESP_ERR_HTTP_FETCH_HEADER" What am I doing wrong? Here is my code:

Code: Select all

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_http_client.h"

// Define the Wi-Fi credentials
#define WIFI_SSID      "mywifi"
#define WIFI_PASS      "mypass"

// Define the Zabbix server details
#define ZABBIX_SERVER_IP "here-my-zabbix-server-ip"
#define ZABBIX_SERVER_PORT "10051"

static const char *TAG = "wifi_station";

esp_err_t _http_event_handler(esp_http_client_event_t *evt) {
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client)) {
                ESP_LOGI(TAG, "%.*s", evt->data_len, (char*)evt->data);
            }
            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            break;
        case HTTP_EVENT_REDIRECT:
            ESP_LOGI(TAG, "HTTP_EVENT_REDIRECT");
            break;
    }
    return ESP_OK;
}

void send_data_to_zabbix() {
    char url[256];
    snprintf(url, sizeof(url), "http://%s:%s/api_jsonrpc.php", ZABBIX_SERVER_IP, ZABBIX_SERVER_PORT);

    esp_http_client_config_t config = {
        .url = url,
        .event_handler = _http_event_handler,
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);
    
    const char *post_data_format = "{\"request\":\"sender data\",\"data\":[{\"host\":\"ESP32\",\"key\":\"my.item\",\"value\":\"%.2f\"}]}";
    
    char post_data[512];
    float random_value = ((float)rand() / (float)(RAND_MAX)) * 4.0 + 1.0; // Generate random float between 1.0 and 5.0

    snprintf(post_data, sizeof(post_data), post_data_format, random_value);

    esp_http_client_set_method(client, HTTP_METHOD_POST);
    esp_http_client_set_post_field(client, post_data, strlen(post_data));

    esp_http_client_set_header(client, "Content-Type", "application/json-rpc");

    esp_err_t err = esp_http_client_perform(client);

    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %lld",
        esp_http_client_get_status_code(client), 
        esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
    }

    esp_http_client_cleanup(client);
}

void zabbix_task(void *pvParameters) {
    while (1) {
        send_data_to_zabbix();
        vTaskDelay(pdMS_TO_TICKS(5000)); // 5 seconds delay
    }
}

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                    int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        ESP_LOGI(TAG, "retry to connect to the AP");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));

        // Create the Zabbix task
        xTaskCreate(&zabbix_task, "zabbix_task", 4096, NULL, 5, NULL);
    }
}

void wifi_init_sta(void)
{
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    esp_event_handler_instance_register(WIFI_EVENT,
                                        ESP_EVENT_ANY_ID,
                                        &wifi_event_handler,
                                        NULL,
                                        &instance_any_id);
    esp_event_handler_instance_register(IP_EVENT,
                                        IP_EVENT_STA_GOT_IP,
                                        &wifi_event_handler,
                                        NULL,
                                        &instance_got_ip);

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
    esp_wifi_start();

    ESP_LOGI(TAG, "wifi_init_sta finished.");
}

void app_main(void)
{
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    wifi_init_sta();
}

tgk8888
Posts: 3
Joined: Mon Feb 14, 2022 4:43 am

Re: send data to zabbix

Postby tgk8888 » Thu Jan 02, 2025 10:03 am

While my topic was being approved, I realized what the problem was. My items on the zabbix server were configured as Zabbix Trapped, and this is not an HTTP protocol at all. Here's some code that might be useful to someone to get started (sending two random float values):

Code: Select all

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include "stdlib.h"
#include "string.h"

// Define the Wi-Fi credentials
#define WIFI_SSID      "mywifissid"
#define WIFI_PASS      "mywifipass"

// Define the Zabbix server details
#define ZABBIX_SERVER_IP "myzabbix_ip"
#define ZABBIX_SERVER_PORT 10051

static const char *TAG = "tcp_client";

typedef struct {
    char host_ip[16];
    int port;
    int interval_ms;
} tcp_client_config_t;

void log_bytes(const char *label, const char *data, size_t len) {
    printf("%s: ", label);
    for (size_t i = 0; i < len; i++) {
        printf("%02x ", (unsigned char)data[i]);
    }
    printf("\n");
}

//function for construct the message
size_t construct_zabbix_message(const char *json_payload, char *zabbix_message, size_t zabbix_message_size) {
    size_t json_length = strlen(json_payload);
    const char header[] = "ZBXD\x01";
    const char placeholder[] = "\x00\x00\x00\x00\x00\x00\x00\x00";

    if (zabbix_message_size < 13 + json_length) {
        ESP_LOGE(TAG, "Zabbix message buffer too small");
        return 0;
    }

    memcpy(zabbix_message, header, sizeof(header) - 1);
    zabbix_message[5] = (unsigned char)(json_length & 0xFF);
    zabbix_message[6] = (unsigned char)((json_length >> 8) & 0xFF);
    zabbix_message[7] = (unsigned char)((json_length >> 16) & 0xFF);
    zabbix_message[8] = (unsigned char)((json_length >> 24) & 0xFF);
    memcpy(zabbix_message + 9, placeholder, sizeof(placeholder) - 1);
    memcpy(zabbix_message + 13, json_payload, json_length);

    return 13 + json_length;
}

void send_data_to_server(int sock) {
    // Create the JSON message with random float values
    float random_value = ((float)rand() / (float)(RAND_MAX)) * 99.0 + 1.0;
    float random_value2 = ((float)rand() / (float)(RAND_MAX)) * 4.0 + 60.0;
    char json_payload[256];
    snprintf(json_payload, sizeof(json_payload), "{\"request\":\"sender data\",\"data\":[{\"host\":\"my_host\",\"key\":\"my.itemkey\",\"value\":\"%.2f\"}, {\"host\":\"ESP32\",\"key\":\"my.item2\",\"value\":\"%.2f\"}]}", random_value, random_value2);

    ESP_LOGI(TAG, "payload length: %d", strlen(json_payload));

    // Create the Zabbix Sender message
    char zabbix_message[512];
    size_t message_length = construct_zabbix_message(json_payload, zabbix_message, sizeof(zabbix_message));
    if (message_length == 0) {
        ESP_LOGE(TAG, "Failed to construct Zabbix message");
        return;
    }

    // Log the data to be sent
    ESP_LOGI(TAG, "Sending data to server: %s", zabbix_message);
    log_bytes("Zabbix Message Bytes", zabbix_message, message_length);

    // Send the Zabbix Sender message
    int err = send(sock, zabbix_message, message_length, 0);
    if (err < 0) {
        ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
        return;
    }
    ESP_LOGI(TAG, "Message sent: %s", json_payload);

    // Receive data
    char rx_buffer[128];
    int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
    if (len < 0) {
        ESP_LOGE(TAG, "recv failed: errno %d", errno);
    } else {
        rx_buffer[len] = 0; // Null-terminate whatever we received and treat it like a string
        ESP_LOGI(TAG, "Received %d bytes: %s", len, rx_buffer);
    }
}

void tcp_client_task(void *pvParameters) {
    tcp_client_config_t *config = (tcp_client_config_t *)pvParameters;
    char host_ip[16];
    strncpy(host_ip, config->host_ip, sizeof(host_ip));
    int port = config->port;
    int interval_ms = config->interval_ms;

    int addr_family = AF_INET;
    int ip_protocol = IPPROTO_IP;

    struct sockaddr_in dest_addr;
    dest_addr.sin_addr.s_addr = inet_addr(host_ip);
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(port);

    while (1) {
        int sock = socket(addr_family, SOCK_STREAM, ip_protocol);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, port);

        int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
        if (err != 0) {
            ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(interval_ms)); // Wait before retrying
            continue; //if socket error, continue task and try to reconnect
        }
        ESP_LOGI(TAG, "Successfully connected");

        send_data_to_server(sock);

        // Close the socket
        close(sock);
        ESP_LOGI(TAG, "Socket closed");

        vTaskDelay(pdMS_TO_TICKS(interval_ms)); // Wait for the specified interval before reconnecting
    }
    vTaskDelete(NULL);
}

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                    int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        ESP_LOGI(TAG, "retry to connect to the AP");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        // Create the TCP client task with parameters
        tcp_client_config_t config = {
            .interval_ms = 10000 // 10 seconds
        };
        strncpy(config.host_ip, ZABBIX_SERVER_IP, sizeof(config.host_ip));
        config.port = ZABBIX_SERVER_PORT;
        xTaskCreate(&tcp_client_task, "tcp_client_task", 4096, &config, 5, NULL);
    }
}

void wifi_init_sta(void)
{
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    esp_event_handler_instance_register(WIFI_EVENT,
                                        ESP_EVENT_ANY_ID,
                                        &wifi_event_handler,
                                        NULL,
                                        &instance_any_id);
    esp_event_handler_instance_register(IP_EVENT,
                                        IP_EVENT_STA_GOT_IP,
                                        &wifi_event_handler,
                                        NULL,
                                        &instance_got_ip);

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
    esp_wifi_start();

    ESP_LOGI(TAG, "wifi_init_sta finished.");
}

void app_main(void)
{
    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // Initialize Wi-Fi
    wifi_init_sta();
}

Who is online

Users browsing this forum: No registered users and 83 guests