fixes that made it work
This commit is contained in:
175
components/ws_client/ws_client.c
Normal file
175
components/ws_client/ws_client.c
Normal file
@@ -0,0 +1,175 @@
|
||||
#include "ws_client.h"
|
||||
#include "esp_websocket_client.h"
|
||||
#include "esp_log.h"
|
||||
#include "cJSON.h"
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
static const char *TAG = "ws_client";
|
||||
|
||||
static esp_websocket_client_handle_t s_client = NULL;
|
||||
static pi_stats_t s_stats = {};
|
||||
static SemaphoreHandle_t s_stats_mutex = NULL;
|
||||
static ws_state_t s_state = WS_STATE_DISCONNECTED;
|
||||
static ws_data_callback_t s_data_cb = NULL;
|
||||
static ws_state_callback_t s_state_cb = NULL;
|
||||
|
||||
static void set_state(ws_state_t state)
|
||||
{
|
||||
s_state = state;
|
||||
if (s_state_cb) {
|
||||
s_state_cb(state);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_stats_json(const char *data, int len)
|
||||
{
|
||||
cJSON *root = cJSON_ParseWithLength(data, len);
|
||||
if (!root) {
|
||||
ESP_LOGW(TAG, "JSON parse failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xSemaphoreTake(s_stats_mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
cJSON *item;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "cpu_pct");
|
||||
if (item) s_stats.cpu_pct = (float)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "mem_pct");
|
||||
if (item) s_stats.mem_pct = (float)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "mem_used_mb");
|
||||
if (item) s_stats.mem_used_mb = (uint32_t)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "disk_pct");
|
||||
if (item) s_stats.disk_pct = (float)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "cpu_temp");
|
||||
if (item) s_stats.cpu_temp = (float)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "uptime_hrs");
|
||||
if (item) s_stats.uptime_hrs = (float)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "net_rx_kbps");
|
||||
if (item) s_stats.net_rx_kbps = (float)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "net_tx_kbps");
|
||||
if (item) s_stats.net_tx_kbps = (float)item->valuedouble;
|
||||
|
||||
item = cJSON_GetObjectItem(root, "timestamp");
|
||||
if (item) s_stats.last_update = (uint32_t)item->valuedouble;
|
||||
|
||||
cJSON *services = cJSON_GetObjectItem(root, "services");
|
||||
if (cJSON_IsArray(services)) {
|
||||
int count = cJSON_GetArraySize(services);
|
||||
if (count > WS_MAX_SERVICES) count = WS_MAX_SERVICES;
|
||||
s_stats.service_count = count;
|
||||
for (int i = 0; i < count; i++) {
|
||||
cJSON *svc = cJSON_GetArrayItem(services, i);
|
||||
cJSON *name = cJSON_GetObjectItem(svc, "name");
|
||||
cJSON *status = cJSON_GetObjectItem(svc, "status");
|
||||
if (name && name->valuestring) {
|
||||
strncpy(s_stats.services[i].name, name->valuestring, WS_SERVICE_NAME_LEN - 1);
|
||||
s_stats.services[i].name[WS_SERVICE_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
if (status && status->valuestring) {
|
||||
s_stats.services[i].running = (strcmp(status->valuestring, "running") == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_stats.valid = true;
|
||||
xSemaphoreGive(s_stats_mutex);
|
||||
|
||||
if (s_data_cb) {
|
||||
s_data_cb(&s_stats);
|
||||
}
|
||||
}
|
||||
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
static void ws_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||
|
||||
switch (event_id) {
|
||||
case WEBSOCKET_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "WebSocket connected");
|
||||
set_state(WS_STATE_CONNECTED);
|
||||
break;
|
||||
case WEBSOCKET_EVENT_DISCONNECTED:
|
||||
ESP_LOGW(TAG, "WebSocket disconnected");
|
||||
set_state(WS_STATE_DISCONNECTED);
|
||||
break;
|
||||
case WEBSOCKET_EVENT_DATA:
|
||||
if (data->op_code == 0x01 && data->data_len > 0) { // text frame
|
||||
ESP_LOGD(TAG, "Received %d bytes", data->data_len);
|
||||
parse_stats_json(data->data_ptr, data->data_len);
|
||||
}
|
||||
break;
|
||||
case WEBSOCKET_EVENT_ERROR:
|
||||
ESP_LOGE(TAG, "WebSocket error");
|
||||
set_state(WS_STATE_ERROR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ws_client_init(const char *uri)
|
||||
{
|
||||
s_stats_mutex = xSemaphoreCreateMutex();
|
||||
|
||||
esp_websocket_client_config_t config = {};
|
||||
config.uri = uri;
|
||||
config.reconnect_timeout_ms = 5000;
|
||||
config.buffer_size = 2048;
|
||||
|
||||
s_client = esp_websocket_client_init(&config);
|
||||
esp_websocket_register_events(s_client, WEBSOCKET_EVENT_ANY, ws_event_handler, NULL);
|
||||
|
||||
ESP_LOGI(TAG, "WS client initialized: %s", uri);
|
||||
}
|
||||
|
||||
void ws_client_start(void)
|
||||
{
|
||||
if (s_client) {
|
||||
set_state(WS_STATE_CONNECTING);
|
||||
esp_websocket_client_start(s_client);
|
||||
}
|
||||
}
|
||||
|
||||
void ws_client_stop(void)
|
||||
{
|
||||
if (s_client) {
|
||||
esp_websocket_client_stop(s_client);
|
||||
set_state(WS_STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
ws_state_t ws_client_get_state(void)
|
||||
{
|
||||
return s_state;
|
||||
}
|
||||
|
||||
void ws_client_get_stats(pi_stats_t *out)
|
||||
{
|
||||
if (xSemaphoreTake(s_stats_mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
memcpy(out, &s_stats, sizeof(pi_stats_t));
|
||||
xSemaphoreGive(s_stats_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void ws_client_set_data_callback(ws_data_callback_t cb)
|
||||
{
|
||||
s_data_cb = cb;
|
||||
}
|
||||
|
||||
void ws_client_set_state_callback(ws_state_callback_t cb)
|
||||
{
|
||||
s_state_cb = cb;
|
||||
}
|
||||
Reference in New Issue
Block a user