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
12 changes: 12 additions & 0 deletions components/influx/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
idf_component_register(
SRCS
"influx.c"
INCLUDE_DIRS
"include"
REQUIRES
"esp_http_client"
"json"
"esp_timer"
"nvs_flash"
"driver"
)
81 changes: 81 additions & 0 deletions components/influx/include/influx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#pragma once

#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
float asicTemp;
float vrTemp;
float hashingSpeed;
int invalidShares;
int validShares;
int difficulty;
float bestSessionDifficulty;
int poolErrors;
int accepted;
int notAccepted;
int totalUptime;
float totalBestDifficulty;
int uptime;
int blocksFound;
int totalBlocksFound;
int duplicateHashes;
float voltage;
float current;
float power;
} influx_stats_t;

typedef struct {
char *host;
int port;
char *token;
char *org;
char *bucket;
char *prefix;
char auth_header[128];
char *big_buffer;
pthread_mutex_t lock;
influx_stats_t stats;
} influx_client_t;

/**
* @brief Initialize the InfluxDB client
*
* @param client Pointer to the client structure to initialize
* @param host InfluxDB server hostname
* @param port InfluxDB server port
* @param token Authentication token
* @param bucket Bucket name
* @param org Organization name
* @param prefix Metric prefix
* @return true if initialization successful
* @return false if initialization failed
*/
bool influx_init(influx_client_t *client, const char *host, int port,
const char *token, const char *bucket, const char *org,
const char *prefix);

/**
* @brief Write current stats to InfluxDB
*
* @param client Pointer to the client structure
* @return true if write successful
* @return false if write failed
*/
bool influx_write(influx_client_t *client);

/**
* @brief Deinitialize and cleanup the InfluxDB client
*
* @param client Pointer to the client structure
*/
void influx_deinit(influx_client_t *client);

#ifdef __cplusplus
}
#endif
173 changes: 173 additions & 0 deletions components/influx/influx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include "esp_http_client.h"
#include "esp_timer.h"
#include "cJSON.h"
#include "influx.h"

static const char *TAG = "influx";

#define INFLUX_BUFFER_SIZE 2048
#define INFLUX_API_VERSION "2.0"
#define INFLUX_WRITE_PATH "/api/v2/write"
#define INFLUX_BUCKETS_PATH "/api/v2/buckets"

static esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
// Log the event ID for debugging
ESP_LOGD(TAG, "HTTP Event: %d", evt->event_id);

// Handle specific events
if (evt->event_id == HTTP_EVENT_ERROR) {
ESP_LOGE(TAG, "HTTP_EVENT_ERROR");
} else if (evt->event_id == HTTP_EVENT_ON_CONNECTED) {
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
} else if (evt->event_id == HTTP_EVENT_ON_HEADER) {
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
} else if (evt->event_id == HTTP_EVENT_ON_DATA) {
if (!esp_http_client_is_chunked_response(evt->client)) {
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
}
} else if (evt->event_id == HTTP_EVENT_ON_FINISH) {
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
} else if (evt->event_id == HTTP_EVENT_DISCONNECTED) {
ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
} else if (evt->event_id == HTTP_EVENT_REDIRECT) {
ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
}

return ESP_OK;
}

bool influx_init(influx_client_t *client, const char *host, int port,
const char *token, const char *bucket, const char *org,
const char *prefix)
{
if (!client || !host || !token || !bucket || !org || !prefix) {
ESP_LOGE(TAG, "Invalid parameters");
return false;
}

memset(client, 0, sizeof(influx_client_t));

// Allocate and copy strings
client->host = strdup(host);
client->token = strdup(token);
client->bucket = strdup(bucket);
client->org = strdup(org);
client->prefix = strdup(prefix);
client->port = port;

// Initialize mutex
if (pthread_mutex_init(&client->lock, NULL) != 0) {
ESP_LOGE(TAG, "Mutex initialization failed");
influx_deinit(client);
return false;
}

// Allocate buffer for HTTP requests
client->big_buffer = malloc(INFLUX_BUFFER_SIZE);
if (!client->big_buffer) {
ESP_LOGE(TAG, "Failed to allocate buffer");
influx_deinit(client);
return false;
}

// Create auth header
snprintf(client->auth_header, sizeof(client->auth_header), "Token %s", token);

return true;
}

void influx_deinit(influx_client_t *client)
{
if (!client) return;

pthread_mutex_destroy(&client->lock);
free(client->host);
free(client->token);
free(client->bucket);
free(client->org);
free(client->prefix);
free(client->big_buffer);
memset(client, 0, sizeof(influx_client_t));
}

bool influx_write(influx_client_t *client)
{
if (!client) return false;

pthread_mutex_lock(&client->lock);

char url[128];
snprintf(url, sizeof(url), "http://%s:%d%s?bucket=%s&org=%s&precision=s",
client->host, client->port, INFLUX_WRITE_PATH,
client->bucket, client->org);

int len = snprintf(client->big_buffer, INFLUX_BUFFER_SIZE,
"%s asic_temp=%f,vr_temp=%f,"
"hashing_speed=%f,invalid_shares=%d,valid_shares=%d,uptime=%d,"
"best_difficulty=%f,total_best_difficulty=%f,pool_errors=%d,"
"accepted=%d,not_accepted=%d,total_uptime=%d,blocks_found=%d,"
"voltage=%f,current=%f,power=%f,"
"total_blocks_found=%d,duplicate_hashes=%d",
client->prefix,
(double)client->stats.asicTemp,
(double)client->stats.vrTemp,
(double)client->stats.hashingSpeed,
client->stats.invalidShares,
client->stats.validShares,
client->stats.uptime,
(double)client->stats.bestSessionDifficulty,
(double)client->stats.totalBestDifficulty,
client->stats.poolErrors,
client->stats.accepted,
client->stats.notAccepted,
client->stats.totalUptime,
client->stats.blocksFound,
(double)client->stats.voltage,
(double)client->stats.current,
(double)client->stats.power,
client->stats.totalBlocksFound,
client->stats.duplicateHashes);

if (len >= INFLUX_BUFFER_SIZE) {
ESP_LOGE(TAG, "Buffer too small for data");
pthread_mutex_unlock(&client->lock);
return false;
}

ESP_LOGI(TAG, "URL: %s", url);
ESP_LOGI(TAG, "POST: %s", client->big_buffer);

esp_http_client_config_t config = {
.url = url,
.event_handler = http_event_handler,
.method = HTTP_METHOD_POST,
};

esp_http_client_handle_t http_client = esp_http_client_init(&config);
if (!http_client) {
ESP_LOGE(TAG, "Failed to initialize HTTP client");
pthread_mutex_unlock(&client->lock);
return false;
}

esp_http_client_set_header(http_client, "Authorization", client->auth_header);
esp_http_client_set_header(http_client, "Content-Type", "text/plain; charset=utf-8");
esp_http_client_set_post_field(http_client, client->big_buffer, len);

esp_err_t err = esp_http_client_perform(http_client);
esp_http_client_cleanup(http_client);

pthread_mutex_unlock(&client->lock);

if (err != ESP_OK) {
ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
return false;
}

return true;
}
5 changes: 5 additions & 0 deletions main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ SRCS
"./tasks/asic_task.c"
"./tasks/asic_result_task.c"
"./tasks/power_management_task.c"
"./tasks/influx_task.c"
"./thermal/EMC2101.c"
"./thermal/EMC2103.c"
"./thermal/TMP1075.c"
Expand All @@ -40,9 +41,13 @@ INCLUDE_DIRS
"../components/connect/include"
"../components/dns_server/include"
"../components/stratum/include"
"../components/influx/include"
"thermal"
"power"

REQUIRES
"influx"

PRIV_REQUIRES
"app_update"
"driver"
Expand Down
46 changes: 46 additions & 0 deletions main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,49 @@ menu "Stratum Configuration"
A starting difficulty to use with the pool.

endmenu

menu "InfluxDB Configuration"

config INFLUXDB_ENABLED
int "Enable InfluxDB Integration"
default 0
help
Enable or disable InfluxDB metrics collection.

config INFLUXDB_HOST
string "InfluxDB Host"
default "localhost"
help
The hostname or IP address of your InfluxDB server.

config INFLUXDB_PORT
int "InfluxDB Port"
default 8086
help
The port number of your InfluxDB server.

config INFLUXDB_TOKEN
string "InfluxDB Token"
default ""
help
The authentication token for your InfluxDB server.

config INFLUXDB_ORG
string "InfluxDB Organization"
default "bitaxe"
help
The organization name in InfluxDB.

config INFLUXDB_BUCKET
string "InfluxDB Bucket"
default "bitaxe"
help
The bucket name in InfluxDB where metrics will be stored.

config INFLUXDB_MEASUREMENT
string "InfluxDB Measurement"
default "mainnet_stats"
help
The measurement name for the metrics in InfluxDB.

endmenu
4 changes: 4 additions & 0 deletions main/global_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ typedef struct

bool ASIC_initalized;
bool psram_is_available;

// InfluxDB client pointer (actual type is influx_client_t* from influx.h)
// Using void* here to avoid circular dependencies
void *influx_client;
} GlobalState;

#endif /* GLOBAL_STATE_H_ */
5 changes: 5 additions & 0 deletions main/http_server/axe-os/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { NetworkComponent } from './components/network/network.component';
import { SwarmComponent } from './components/swarm/swarm.component';
import { DesignComponent } from './components/design/design.component';
import { PoolComponent } from './components/pool/pool.component';
import { InfluxdbComponent } from './components/influxdb/influxdb.component';
import { AppLayoutComponent } from './layout/app.layout.component';
import { ApModeGuard } from './guards/ap-mode.guard';

Expand Down Expand Up @@ -54,6 +55,10 @@ const routes: Routes = [
{
path: 'pool',
component: PoolComponent
},
{
path: 'influxdb',
component: InfluxdbComponent
}
]
},
Expand Down
4 changes: 3 additions & 1 deletion main/http_server/axe-os/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { SettingsComponent } from './components/settings/settings.component';
import { SwarmComponent } from './components/swarm/swarm.component';
import { ThemeConfigComponent } from './components/design/theme-config.component';
import { DesignComponent } from './components/design/design.component';
import { InfluxdbComponent } from './components/influxdb/influxdb.component';
import { AppLayoutModule } from './layout/app.layout.module';
import { ANSIPipe } from './pipes/ansi.pipe';
import { DateAgoPipe } from './pipes/date-ago.pipe';
Expand All @@ -41,7 +42,8 @@ const components = [
NetworkComponent,
SettingsComponent,
LogsComponent,
PoolComponent
PoolComponent,
InfluxdbComponent
];

@NgModule({
Expand Down
Loading