arp_monitoring/components/ping/ping.c
2026-07-15 20:32:20 +03:00

138 lines
3.3 KiB
C

#include "ping.h"
#include "device_list.h"
#include <string.h>
#include <stdio.h>
#include "ping/ping_sock.h"
#include "esp_netif.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
static const char *TAG = "ping";
typedef struct
{
bool reply_received;
SemaphoreHandle_t finished;
} ping_context_t;
static bool parse_mac_address(const char *text, struct eth_addr * mac);
static void ping_device(device_info_t *device);
void ping_selected_devices(const char *query);
static void ping_success_callback(esp_ping_handle_t handle, void *arguments);
static void ping_end_callback(esp_ping_handle_t handle, void *arguments);
static bool parse_mac_address(const char *text, struct eth_addr *mac)
{
if ((text == NULL) || (mac == NULL))
return false;
return (sscanf(text,
"%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX",
&mac->addr[0],
&mac->addr[1],
&mac->addr[2],
&mac->addr[3],
&mac->addr[4],
&mac->addr[5]) == 6);
}
void ping_selected_devices(const char *query)
{
const char *current = query;
while ((current = strstr(current, "mac=")) != NULL)
{
struct eth_addr mac;
device_info_t *device;
char mac_string[18];
size_t length;
current += 4;
const char *end = strchr(current, '&');
if (end != NULL)
length = end - current;
else
length = strlen(current);
if (length >= sizeof(mac_string))
break;
memcpy(mac_string, current, length);
mac_string[length] = '\0';
if (parse_mac_address(mac_string, &mac))
{
device = device_list_find_by_mac(&mac);
if (device != NULL)
{
ping_device(device);
}
}
if (end == NULL)
break;
current = end + 1;
}
}
static void ping_device(device_info_t *device)
{
ping_context_t context = {
.reply_received = false,
.finished = xSemaphoreCreateBinary()
};
if (context.finished == NULL)
return;
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
config.target_addr.type = ESP_IPADDR_TYPE_V4;
config.target_addr.u_addr.ip4.addr = device->ip.addr;
config.count = 1;
config.interval_ms = 1000;
config.timeout_ms = 1000;
esp_ping_callbacks_t callbacks = {
.on_ping_success = ping_success_callback,
.on_ping_end = ping_end_callback,
.cb_args = &context
};
esp_ping_handle_t ping;
if (esp_ping_new_session(&config, &callbacks, &ping) != ESP_OK)
{
vSemaphoreDelete(context.finished);
return;
}
esp_ping_start(ping);
xSemaphoreTake(context.finished, portMAX_DELAY);
esp_ping_stop(ping);
esp_ping_delete_session(ping);
device->active = context.reply_received;
vSemaphoreDelete(context.finished);
}
static void ping_success_callback(esp_ping_handle_t handle, void *args)
{
ping_context_t *context = (ping_context_t *)args;
context->reply_received = true;
}
static void ping_end_callback(esp_ping_handle_t handle, void *args)
{
ping_context_t *context = (ping_context_t *)args;
xSemaphoreGive(context->finished);
}