fix ade7758
This commit is contained in:
@@ -10,7 +10,7 @@ LED_STOP_GPIO=12
|
||||
|
||||
#BUZZER
|
||||
BUZZER=y
|
||||
BUZZER_GPIO=21
|
||||
BUZZER_GPIO=27
|
||||
|
||||
#Button
|
||||
BUTTON_WIFI_GPIO=32
|
||||
|
||||
@@ -13,16 +13,21 @@
|
||||
#include "timeout_utils.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_limits.h"
|
||||
#include "evse_state.h"
|
||||
#include "evse_config.h"
|
||||
#include "ocpp.h"
|
||||
#include "board_config.h"
|
||||
#include "socket_lock.h"
|
||||
#include "proximity.h"
|
||||
//#include "modbus.h"
|
||||
//#include "modbus_tcp.h"
|
||||
#include "rest.h"
|
||||
//#include "rest.h"
|
||||
#include "temp_sensor.h"
|
||||
// #include "script.h"
|
||||
#include "date_time.h"
|
||||
#include "evse_meter.h"
|
||||
|
||||
|
||||
#define RETURN_ON_ERROR(x) \
|
||||
do \
|
||||
@@ -335,9 +340,9 @@ cJSON *json_get_state(void)
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddStringToObject(root, "state", evse_state_to_str(evse_get_state()));
|
||||
cJSON_AddBoolToObject(root, "available", evse_is_available());
|
||||
cJSON_AddBoolToObject(root, "enabled", evse_is_enabled());
|
||||
cJSON_AddBoolToObject(root, "pendingAuth", false);
|
||||
cJSON_AddBoolToObject(root, "available", evse_config_is_available());
|
||||
cJSON_AddBoolToObject(root, "enabled", evse_config_is_enabled());
|
||||
cJSON_AddBoolToObject(root, "pendingAuth", evse_is_require_auth());
|
||||
cJSON_AddBoolToObject(root, "limitReached", evse_is_limit_reached());
|
||||
|
||||
uint32_t error = evse_error_get_bits();
|
||||
@@ -383,17 +388,33 @@ cJSON *json_get_state(void)
|
||||
cJSON_AddItemToObject(root, "errors", errors);
|
||||
}
|
||||
|
||||
/*
|
||||
cJSON_AddNumberToObject(root, "sessionTime", energy_meter_get_session_time());
|
||||
cJSON_AddNumberToObject(root, "chargingTime", energy_meter_get_charging_time());
|
||||
cJSON_AddNumberToObject(root, "consumption", energy_meter_get_consumption());
|
||||
cJSON_AddNumberToObject(root, "power", energy_meter_get_power());
|
||||
float values[3];
|
||||
energy_meter_get_voltage(values);
|
||||
cJSON_AddItemToObject(root, "voltage", cJSON_CreateFloatArray(values, 3));
|
||||
energy_meter_get_current(values);
|
||||
cJSON_AddItemToObject(root, "current", cJSON_CreateFloatArray(values, 3));
|
||||
*/
|
||||
|
||||
cJSON_AddNumberToObject(root, "sessionTime", evse_get_session_start());
|
||||
cJSON_AddNumberToObject(root, "chargingTime", 0);
|
||||
cJSON_AddNumberToObject(root, "consumption", 0);
|
||||
|
||||
// 1) Arrays temporários para ler dados do medidor
|
||||
float voltage_f[EVSE_METER_PHASE_COUNT];
|
||||
float current_f[EVSE_METER_PHASE_COUNT];
|
||||
uint32_t power_w[ EVSE_METER_PHASE_COUNT];
|
||||
|
||||
// 2) Leitura dos valores via API pública
|
||||
evse_meter_get_voltage(voltage_f); // já em volts
|
||||
evse_meter_get_current(current_f); // já em amperes
|
||||
evse_meter_get_power(power_w); // em watts por fase
|
||||
|
||||
// 4) Energia acumulada em kWh
|
||||
//float consumption_kwh = evse_meter_get_total_energy() / 1000.0f; // Wh → kWh
|
||||
|
||||
// 6) Arrays de tensão e corrente
|
||||
cJSON_AddItemToObject(root, "power",
|
||||
cJSON_CreateFloatArray(power_w, EVSE_METER_PHASE_COUNT));
|
||||
cJSON_AddItemToObject(root, "voltage",
|
||||
cJSON_CreateFloatArray(voltage_f, EVSE_METER_PHASE_COUNT));
|
||||
cJSON_AddItemToObject(root, "current",
|
||||
cJSON_CreateFloatArray(current_f, EVSE_METER_PHASE_COUNT));
|
||||
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "timeout_utils.h"
|
||||
#include "wifi.h"
|
||||
#include "rest.h"
|
||||
//#include "rest.h"
|
||||
|
||||
static void restart_func(void* arg)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ set(srcs
|
||||
evse_manager.c
|
||||
evse_hardware.c
|
||||
evse_pilot.c
|
||||
evse_meter.c
|
||||
)
|
||||
|
||||
idf_component_register(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// evse_core.c - Função principal de controle do EVSE
|
||||
// evse_core.c - Main EVSE control logic
|
||||
|
||||
#include "evse_fsm.h"
|
||||
#include "evse_error.h"
|
||||
@@ -13,23 +13,30 @@
|
||||
static const char *TAG = "evse_core";
|
||||
|
||||
static SemaphoreHandle_t mutex;
|
||||
|
||||
static evse_state_t last_state = EVSE_STATE_A;
|
||||
|
||||
static void evse_core_task(void *arg);
|
||||
|
||||
// ================================
|
||||
// Initialization
|
||||
// ================================
|
||||
|
||||
void evse_init(void) {
|
||||
ESP_LOGI(TAG, "EVSE Init");
|
||||
|
||||
mutex = xSemaphoreCreateMutex();
|
||||
mutex = xSemaphoreCreateMutex(); // Optional: use static version for deterministic memory
|
||||
|
||||
evse_check_defaults();
|
||||
evse_fsm_reset();
|
||||
pilot_set_level(true); // Estado inicial do piloto
|
||||
pilot_set_level(true); // Enable pilot output
|
||||
|
||||
xTaskCreate(evse_core_task, "evse_core_task", 4096, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Main Processing Logic
|
||||
// ================================
|
||||
|
||||
void evse_process(void) {
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
|
||||
@@ -39,42 +46,36 @@ void evse_process(void) {
|
||||
pilot_measure(&pilot_voltage, &is_n12v);
|
||||
ESP_LOGD(TAG, "Pilot: %d, -12V: %s", pilot_voltage, is_n12v ? "yes" : "no");
|
||||
|
||||
if (evse_get_error() == 0 && !evse_is_error_cleared()) {
|
||||
evse_error_check(pilot_voltage, is_n12v);
|
||||
|
||||
evse_error_check(pilot_voltage, is_n12v);
|
||||
// Só chama FSM, que decide tudo
|
||||
evse_fsm_process(
|
||||
pilot_voltage,
|
||||
evse_state_get_authorized(),
|
||||
evse_config_is_available(),
|
||||
evse_config_is_enabled()
|
||||
);
|
||||
|
||||
evse_fsm_process(
|
||||
pilot_voltage,
|
||||
evse_state_get_authorized(),
|
||||
evse_config_is_available(),
|
||||
evse_config_is_enabled()
|
||||
);
|
||||
evse_limits_check();
|
||||
|
||||
evse_limits_check();
|
||||
|
||||
evse_state_t current = evse_get_state();
|
||||
if (current != last_state) {
|
||||
ESP_LOGI(TAG, "State changed: %s → %s",
|
||||
evse_state_to_str(last_state),
|
||||
evse_state_to_str(current));
|
||||
last_state = current;
|
||||
}
|
||||
|
||||
evse_mark_error_cleared();
|
||||
evse_state_t current = evse_get_state();
|
||||
if (current != last_state) {
|
||||
ESP_LOGI(TAG, "State changed: %s → %s",
|
||||
evse_state_to_str(last_state),
|
||||
evse_state_to_str(current));
|
||||
last_state = current;
|
||||
}
|
||||
|
||||
evse_mark_error_cleared();
|
||||
|
||||
xSemaphoreGive(mutex);
|
||||
}
|
||||
|
||||
|
||||
// ================================
|
||||
// Interface pública
|
||||
// Public Configuration Interface
|
||||
// ================================
|
||||
|
||||
bool evse_is_enabled(void) {
|
||||
return evse_config_is_enabled();
|
||||
}
|
||||
|
||||
void evse_set_enabled(bool value) {
|
||||
ESP_LOGI(TAG, "Set enabled %d", value);
|
||||
evse_config_set_enabled(value);
|
||||
@@ -90,21 +91,12 @@ void evse_set_available(bool value) {
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Tarefa principal
|
||||
// Background Task
|
||||
// ================================
|
||||
|
||||
static void evse_core_task(void *arg) {
|
||||
while (true) {
|
||||
evse_process();
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 10 Hz cycle
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t evse_get_total_energy(void) {
|
||||
return 0; // Stub de 1 kWh
|
||||
}
|
||||
|
||||
uint32_t evse_get_instant_power(void) {
|
||||
return 0; // Stub de 2 kW
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
// evse_fsm.c - Máquina de Estados EVSE com controle centralizado
|
||||
|
||||
#include "evse_fsm.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_pilot.h"
|
||||
@@ -11,6 +9,7 @@
|
||||
#include "proximity.h"
|
||||
#include "rcm.h"
|
||||
#include "evse_state.h"
|
||||
#include "evse_error.h"
|
||||
|
||||
static const char *TAG = "evse_fsm";
|
||||
|
||||
@@ -27,6 +26,8 @@ void evse_fsm_reset(void) {
|
||||
c1_d1_relay_to = 0;
|
||||
}
|
||||
|
||||
// ... includes e defines como já estão
|
||||
|
||||
static void update_outputs(evse_state_t state) {
|
||||
const uint16_t current = evse_get_runtime_charging_current();
|
||||
uint8_t cable_max_current = evse_get_max_charging_current();
|
||||
@@ -36,6 +37,21 @@ static void update_outputs(evse_state_t state) {
|
||||
cable_max_current = proximity_get_max_current();
|
||||
}
|
||||
|
||||
// Segurança: relé sempre off e outputs seguros em caso de erro
|
||||
if (evse_get_error() != 0) {
|
||||
if (ac_relay_get_state()) {
|
||||
ac_relay_set_state(false);
|
||||
ESP_LOGW(TAG, "ERRO ativo: relé estava ligado, agora desligado por segurança!");
|
||||
}
|
||||
ac_relay_set_state(false); // redundância tolerável
|
||||
pilot_set_level(true); // sinal pilot sempre 12V (A)
|
||||
if (board_config.socket_lock && socket_outlet) {
|
||||
socket_lock_set_locked(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fluxo normal
|
||||
switch (state) {
|
||||
case EVSE_STATE_A:
|
||||
case EVSE_STATE_E:
|
||||
@@ -53,7 +69,6 @@ static void update_outputs(evse_state_t state) {
|
||||
if (board_config.socket_lock && socket_outlet) {
|
||||
socket_lock_set_locked(true);
|
||||
}
|
||||
|
||||
if (rcm_test()) {
|
||||
ESP_LOGI(TAG, "RCM self test passed");
|
||||
} else {
|
||||
@@ -76,12 +91,28 @@ static void update_outputs(evse_state_t state) {
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
pilot_set_amps(MIN(current * 10, cable_max_current * 10));
|
||||
ac_relay_set_state(true);
|
||||
ac_relay_set_state(true); // Só chega aqui se não há erro!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool available, bool enabled) {
|
||||
// FSM principal - centraliza a lógica de erro e de todos os estados
|
||||
void evse_fsm_process(
|
||||
pilot_voltage_t pilot_voltage,
|
||||
bool authorized,
|
||||
bool available,
|
||||
bool enabled
|
||||
) {
|
||||
// Proteção total: erro força F sempre!
|
||||
if (evse_get_error() != 0) {
|
||||
if (evse_get_state() != EVSE_STATE_F) {
|
||||
ESP_LOGW(TAG, "Erro ativo detectado: forçando estado FAULT (F)");
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
}
|
||||
update_outputs(EVSE_STATE_F);
|
||||
return;
|
||||
}
|
||||
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
evse_state_t prev = evse_get_state();
|
||||
evse_state_t curr = prev;
|
||||
@@ -101,7 +132,6 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pilot_voltage) {
|
||||
case PILOT_VOLTAGE_12:
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
@@ -127,15 +157,15 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
|
||||
break;
|
||||
}
|
||||
}
|
||||
__attribute__((fallthrough)); // Evita warning de fallthrough implícito
|
||||
__attribute__((fallthrough));
|
||||
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
if (!enabled || !available) {
|
||||
evse_set_state((curr == EVSE_STATE_D2 || curr == EVSE_STATE_D1) ? EVSE_STATE_D1 : EVSE_STATE_C1);
|
||||
evse_set_state((curr == EVSE_STATE_D2 || curr == EVSE_STATE_D1)
|
||||
? EVSE_STATE_D1 : EVSE_STATE_C1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pilot_voltage) {
|
||||
case PILOT_VOLTAGE_6:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_C2 : EVSE_STATE_C1);
|
||||
@@ -155,18 +185,23 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
|
||||
break;
|
||||
|
||||
case EVSE_STATE_E:
|
||||
break; // Sem transições a partir de E
|
||||
// Estado elétrico grave: só reset manual
|
||||
break;
|
||||
|
||||
case EVSE_STATE_F:
|
||||
if (available) {
|
||||
// Fault: só sai se disponível e sem erro
|
||||
if (available && evse_get_error() == 0) {
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
evse_state_t next = evse_get_state();
|
||||
update_outputs(next);
|
||||
|
||||
if (next != prev) {
|
||||
ESP_LOGI(TAG, "State changed: %s -> %s", evse_state_to_str(prev), evse_state_to_str(next));
|
||||
update_outputs(next);
|
||||
ESP_LOGI(TAG, "State changed: %s -> %s",
|
||||
evse_state_to_str(prev),
|
||||
evse_state_to_str(next));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "evse_state.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_limits.h"
|
||||
#include "evse_meter.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -146,8 +147,8 @@ void evse_limits_check(void) {
|
||||
|
||||
bool reached = false;
|
||||
|
||||
uint32_t energy = evse_get_total_energy();
|
||||
uint32_t power = evse_get_instant_power();
|
||||
uint32_t energy = evse_meter_get_total_energy();
|
||||
uint32_t power = evse_meter_get_instant_power();
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
TickType_t start = evse_get_session_start();
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "evse_hardware.h"
|
||||
#include "evse_config.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_meter.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -87,6 +88,7 @@ void evse_manager_init(void) {
|
||||
evse_error_init();
|
||||
evse_hardware_init();
|
||||
evse_state_init();
|
||||
evse_meter_init();
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(AUTH_EVENTS, ESP_EVENT_ANY_ID, &on_auth_event, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(LOADBALANCER_EVENTS, ESP_EVENT_ANY_ID, &on_loadbalancer_event, NULL));
|
||||
@@ -120,29 +122,3 @@ void evse_manager_tick(void) {
|
||||
|
||||
xSemaphoreGive(evse_mutex);
|
||||
}
|
||||
|
||||
|
||||
// ===== API pública =====
|
||||
bool evse_manager_is_available(void) {
|
||||
return evse_config_is_available();
|
||||
}
|
||||
|
||||
void evse_manager_set_available(bool available) {
|
||||
evse_config_set_available(available);
|
||||
}
|
||||
|
||||
void evse_manager_set_authorized(bool authorized) {
|
||||
evse_state_set_authorized(authorized);
|
||||
}
|
||||
|
||||
bool evse_manager_is_charging(void) {
|
||||
return evse_state_is_charging(evse_get_state());
|
||||
}
|
||||
|
||||
void evse_manager_set_enabled(bool enabled) {
|
||||
evse_config_set_enabled(enabled);
|
||||
}
|
||||
|
||||
bool evse_manager_is_enabled(void) {
|
||||
return evse_config_is_enabled();
|
||||
}
|
||||
|
||||
105
components/evse/evse_meter.c
Normal file
105
components/evse/evse_meter.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "evse_meter.h"
|
||||
#include "meter_events.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static const char *TAG = "evse_meter";
|
||||
static SemaphoreHandle_t meter_mutex;
|
||||
|
||||
typedef struct {
|
||||
uint32_t power_watts[EVSE_METER_PHASE_COUNT];
|
||||
float voltage[EVSE_METER_PHASE_COUNT];
|
||||
float current[EVSE_METER_PHASE_COUNT];
|
||||
uint32_t energy_wh;
|
||||
} evse_meter_data_t;
|
||||
|
||||
static evse_meter_data_t meter_data;
|
||||
|
||||
static void on_meter_event_dispatcher(void* arg, esp_event_base_t base, int32_t id, void* data) {
|
||||
if (base == METER_EVENT && id == METER_EVENT_DATA_READY && data) {
|
||||
const meter_event_data_t *evt = (const meter_event_data_t *)data;
|
||||
if (strcmp(evt->source, "EVSE") == 0) {
|
||||
evse_meter_on_meter_event(arg, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void evse_meter_on_meter_event(void* arg, void* event_data) {
|
||||
const meter_event_data_t *evt = (const meter_event_data_t *)event_data;
|
||||
if (!evt) return;
|
||||
|
||||
xSemaphoreTake(meter_mutex, portMAX_DELAY);
|
||||
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
|
||||
meter_data.power_watts[i] = evt->watt[i];
|
||||
meter_data.voltage[i] = evt->vrms[i];
|
||||
meter_data.current[i] = evt->irms[i];
|
||||
}
|
||||
meter_data.energy_wh = (uint32_t)(evt->total_energy * 1000.0f);
|
||||
xSemaphoreGive(meter_mutex);
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Meter updated: power[W]={%" PRIu32 ",%" PRIu32 ",%" PRIu32 "}, "
|
||||
"voltage[V]={%.2f,%.2f,%.2f}, "
|
||||
"current[A]={%.2f,%.2f,%.2f}, "
|
||||
"total_energy=%" PRIu32 "Wh",
|
||||
meter_data.power_watts[0], meter_data.power_watts[1], meter_data.power_watts[2],
|
||||
meter_data.voltage[0], meter_data.voltage[1], meter_data.voltage[2],
|
||||
meter_data.current[0], meter_data.current[1], meter_data.current[2],
|
||||
meter_data.energy_wh
|
||||
);
|
||||
}
|
||||
|
||||
void evse_meter_init(void) {
|
||||
meter_mutex = xSemaphoreCreateMutex();
|
||||
ESP_ERROR_CHECK(meter_mutex ? ESP_OK : ESP_FAIL);
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(
|
||||
METER_EVENT, METER_EVENT_DATA_READY,
|
||||
on_meter_event_dispatcher, NULL));
|
||||
memset(&meter_data, 0, sizeof(meter_data));
|
||||
ESP_LOGI(TAG, "EVSE Meter listener registered.");
|
||||
}
|
||||
|
||||
uint32_t evse_meter_get_instant_power(void) {
|
||||
xSemaphoreTake(meter_mutex, portMAX_DELAY);
|
||||
uint32_t sum = 0;
|
||||
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
|
||||
sum += meter_data.power_watts[i];
|
||||
}
|
||||
xSemaphoreGive(meter_mutex);
|
||||
return sum;
|
||||
}
|
||||
|
||||
uint32_t evse_meter_get_total_energy(void) {
|
||||
xSemaphoreTake(meter_mutex, portMAX_DELAY);
|
||||
uint32_t val = meter_data.energy_wh;
|
||||
xSemaphoreGive(meter_mutex);
|
||||
return val;
|
||||
}
|
||||
|
||||
void evse_meter_get_power(uint32_t power[EVSE_METER_PHASE_COUNT]) {
|
||||
xSemaphoreTake(meter_mutex, portMAX_DELAY);
|
||||
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
|
||||
power[i] = meter_data.power_watts[i];
|
||||
}
|
||||
xSemaphoreGive(meter_mutex);
|
||||
}
|
||||
|
||||
void evse_meter_get_voltage(float voltage[EVSE_METER_PHASE_COUNT]) {
|
||||
xSemaphoreTake(meter_mutex, portMAX_DELAY);
|
||||
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
|
||||
voltage[i] = meter_data.voltage[i];
|
||||
}
|
||||
xSemaphoreGive(meter_mutex);
|
||||
}
|
||||
|
||||
void evse_meter_get_current(float current[EVSE_METER_PHASE_COUNT]) {
|
||||
xSemaphoreTake(meter_mutex, portMAX_DELAY);
|
||||
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
|
||||
current[i] = meter_data.current[i];
|
||||
}
|
||||
xSemaphoreGive(meter_mutex);
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#include "evse_pilot.h"
|
||||
#include "adc.h"
|
||||
#include "adc121s021_dma.h"
|
||||
#include "board_config.h"
|
||||
|
||||
#define PILOT_PWM_TIMER LEDC_TIMER_0
|
||||
@@ -23,10 +23,24 @@
|
||||
#define MAX_SAMPLE_ATTEMPTS 1000
|
||||
#define PILOT_EXTREME_PERCENT 10 // 10% superior e inferior
|
||||
|
||||
// ADC121S021 setup
|
||||
#define ADC121_VREF_MV 3300 // AJUSTE conforme Vref do seu hardware!
|
||||
#define ADC121_MAX 4095 // 12 bits
|
||||
|
||||
static const char *TAG = "evse_pilot";
|
||||
|
||||
// Memoização de estado para evitar comandos/logs desnecessários
|
||||
static int last_pilot_level = -1;
|
||||
static uint32_t last_pwm_duty = 0;
|
||||
|
||||
// Função para converter leitura bruta do ADC para mV
|
||||
static int adc_raw_to_mv(uint16_t raw) {
|
||||
return (raw * ADC121_VREF_MV) / ADC121_MAX;
|
||||
}
|
||||
|
||||
void pilot_init(void)
|
||||
{
|
||||
// PWM (LEDC) configuração
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = PILOT_PWM_SPEED_MODE,
|
||||
.timer_num = PILOT_PWM_TIMER,
|
||||
@@ -47,27 +61,24 @@ void pilot_init(void)
|
||||
};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
|
||||
ESP_ERROR_CHECK(ledc_stop(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL, 0));
|
||||
|
||||
ESP_ERROR_CHECK(ledc_fade_func_install(0));
|
||||
|
||||
adc_oneshot_chan_cfg_t config = {
|
||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||
.atten = ADC_ATTEN_DB_12,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle, board_config.pilot_adc_channel, &config));
|
||||
// Inicializa ADC121S021 externo
|
||||
adc121s021_dma_init();
|
||||
}
|
||||
|
||||
void pilot_set_level(bool level)
|
||||
{
|
||||
if (last_pilot_level == level) return; // só muda se necessário
|
||||
last_pilot_level = level;
|
||||
|
||||
ESP_LOGI(TAG, "Set level %d", level);
|
||||
ledc_stop(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL, level ? 1 : 0);
|
||||
last_pwm_duty = 0; // PWM parado
|
||||
}
|
||||
|
||||
void pilot_set_amps(uint16_t amps)
|
||||
{
|
||||
ESP_LOGI(TAG, "Set amps %d", amps);
|
||||
|
||||
if (amps < 60 || amps > 800) {
|
||||
ESP_LOGE(TAG, "Invalid ampere value: %d A*10", amps);
|
||||
return;
|
||||
@@ -79,14 +90,17 @@ void pilot_set_amps(uint16_t amps)
|
||||
} else {
|
||||
duty = ((PILOT_PWM_MAX_DUTY * amps) / 2500) + (64 * (PILOT_PWM_MAX_DUTY / 100));
|
||||
}
|
||||
if (duty > PILOT_PWM_MAX_DUTY) duty = PILOT_PWM_MAX_DUTY;
|
||||
|
||||
if (duty > PILOT_PWM_MAX_DUTY)
|
||||
duty = PILOT_PWM_MAX_DUTY;
|
||||
if (last_pilot_level == 0 && last_pwm_duty == duty) return;
|
||||
last_pilot_level = 0;
|
||||
last_pwm_duty = duty;
|
||||
|
||||
ESP_LOGI(TAG, "Set amp %dA*10 -> duty %lu/%d", amps, duty, PILOT_PWM_MAX_DUTY);
|
||||
ledc_set_duty(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL, duty);
|
||||
ledc_update_duty(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL);
|
||||
}
|
||||
|
||||
static int compare_int(const void *a, const void *b) {
|
||||
return (*(int *)a - *(int *)b);
|
||||
}
|
||||
@@ -94,10 +108,8 @@ static int compare_int(const void *a, const void *b) {
|
||||
static int select_low_median_qsort(int *src, int n, int percent) {
|
||||
int k = (n * percent) / 100;
|
||||
if (k == 0) k = 1;
|
||||
|
||||
int *copy = alloca(n * sizeof(int));
|
||||
memcpy(copy, src, n * sizeof(int));
|
||||
|
||||
qsort(copy, n, sizeof(int), compare_int);
|
||||
return copy[k / 2];
|
||||
}
|
||||
@@ -105,10 +117,8 @@ static int select_low_median_qsort(int *src, int n, int percent) {
|
||||
static int select_high_median_qsort(int *src, int n, int percent) {
|
||||
int k = (n * percent) / 100;
|
||||
if (k == 0) k = 1;
|
||||
|
||||
int *copy = alloca(n * sizeof(int));
|
||||
memcpy(copy, src, n * sizeof(int));
|
||||
|
||||
qsort(copy, n, sizeof(int), compare_int);
|
||||
return copy[n - k + (k / 2)];
|
||||
}
|
||||
@@ -119,11 +129,13 @@ void pilot_measure(pilot_voltage_t *up_voltage, bool *down_voltage_n12)
|
||||
|
||||
int samples[NUM_PILOT_SAMPLES];
|
||||
int collected = 0, attempts = 0;
|
||||
int sample;
|
||||
uint16_t adc_sample = 0;
|
||||
|
||||
// Lê samples usando ADC121S021 externo
|
||||
while (collected < NUM_PILOT_SAMPLES && attempts < MAX_SAMPLE_ATTEMPTS) {
|
||||
if (adc_oneshot_read(adc_handle, board_config.pilot_adc_channel, &sample) == ESP_OK) {
|
||||
samples[collected++] = sample;
|
||||
adc_sample = 0;
|
||||
if (adc121s021_dma_get_sample(&adc_sample)) {
|
||||
samples[collected++] = adc_sample;
|
||||
esp_rom_delay_us(10);
|
||||
} else {
|
||||
esp_rom_delay_us(100);
|
||||
@@ -141,20 +153,10 @@ void pilot_measure(pilot_voltage_t *up_voltage, bool *down_voltage_n12)
|
||||
int high_raw = select_high_median_qsort(samples, collected, PILOT_EXTREME_PERCENT);
|
||||
int low_raw = select_low_median_qsort(samples, collected, PILOT_EXTREME_PERCENT);
|
||||
|
||||
int high_mv = adc_raw_to_mv(high_raw);
|
||||
int low_mv = adc_raw_to_mv(low_raw);
|
||||
|
||||
ESP_LOGD(TAG, "Final: high_raw=%d, low_raw=%d", high_raw, low_raw);
|
||||
|
||||
int high_mv = 0;
|
||||
int low_mv = 0;
|
||||
|
||||
if (adc_cali_raw_to_voltage(adc_cali_handle, high_raw, &high_mv) != ESP_OK ||
|
||||
adc_cali_raw_to_voltage(adc_cali_handle, low_raw, &low_mv) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "ADC calibration failed");
|
||||
*up_voltage = PILOT_VOLTAGE_1;
|
||||
*down_voltage_n12 = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Aplica thresholds definidos em board_config (em mV)
|
||||
if (high_mv >= board_config.pilot_down_threshold_12)
|
||||
*up_voltage = PILOT_VOLTAGE_12;
|
||||
else if (high_mv >= board_config.pilot_down_threshold_9)
|
||||
|
||||
@@ -46,9 +46,14 @@ void evse_set_state(evse_state_t state) {
|
||||
current_state = state;
|
||||
changed = true;
|
||||
|
||||
// When entering a charging state, record the start tick
|
||||
if (evse_state_is_charging(state) && !evse_state_is_charging(previous_state)) {
|
||||
session_start_tick = xTaskGetTickCount();
|
||||
}
|
||||
// When exiting a charging state, reset the start tick
|
||||
else if (!evse_state_is_charging(state) && evse_state_is_charging(previous_state)) {
|
||||
session_start_tick = 0;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&state_mux);
|
||||
|
||||
@@ -60,7 +65,11 @@ void evse_set_state(evse_state_t state) {
|
||||
evse_state_event_data_t evt = {
|
||||
.state = map_state_to_event(state)
|
||||
};
|
||||
esp_event_post(EVSE_EVENTS, EVSE_EVENT_STATE_CHANGED, &evt, sizeof(evt), portMAX_DELAY);
|
||||
esp_event_post(EVSE_EVENTS,
|
||||
EVSE_EVENT_STATE_CHANGED,
|
||||
&evt,
|
||||
sizeof(evt),
|
||||
portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,73 +3,77 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "evse_state.h" // Define evse_state_t
|
||||
#include "evse_state.h" // Tipos e estados
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
// Inicialização
|
||||
void evse_init(void);
|
||||
void evse_process(void);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Estado
|
||||
// ===============================
|
||||
// Core EVSE State
|
||||
// ===============================
|
||||
|
||||
/**
|
||||
* @brief Get current EVSE state (e.g., A, B1, C2).
|
||||
*/
|
||||
evse_state_t evse_get_state(void);
|
||||
const char* evse_state_to_str(evse_state_t state);
|
||||
bool evse_is_connector_plugged(evse_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Set the EVSE state (e.g., called by FSM or hardware layer).
|
||||
*/
|
||||
void evse_set_state(evse_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Get timestamp when the current session started (for timing limits).
|
||||
*/
|
||||
TickType_t evse_get_session_start(void);
|
||||
|
||||
// ===============================
|
||||
// Charging Session Info
|
||||
// ===============================
|
||||
|
||||
/**
|
||||
* @brief Returns true if the EV is charging (C1 or C2).
|
||||
*/
|
||||
bool evse_state_is_charging(evse_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the EV is connected (plugged).
|
||||
*/
|
||||
bool evse_state_is_plugged(evse_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Returns true if a charging session is active (B2, C1, C2).
|
||||
*/
|
||||
bool evse_state_is_session(evse_state_t state);
|
||||
|
||||
// ===============================
|
||||
// Authorization
|
||||
// ===============================
|
||||
|
||||
/**
|
||||
* @brief Set whether the vehicle is authorized to charge.
|
||||
*/
|
||||
void evse_state_set_authorized(bool authorized);
|
||||
|
||||
/**
|
||||
* @brief Get current authorization status.
|
||||
*/
|
||||
bool evse_state_get_authorized(void);
|
||||
|
||||
|
||||
// ===============================
|
||||
// Limit Status
|
||||
// ===============================
|
||||
|
||||
/**
|
||||
* @brief Returns true if any runtime charging limit has been reached.
|
||||
*/
|
||||
bool evse_is_limit_reached(void);
|
||||
|
||||
// Autorização e disponibilidade
|
||||
bool evse_is_enabled(void);
|
||||
void evse_set_enabled(bool value);
|
||||
bool evse_is_available(void);
|
||||
void evse_set_available(bool value);
|
||||
bool evse_is_require_auth(void);
|
||||
void evse_set_require_auth(bool value);
|
||||
|
||||
// Corrente
|
||||
uint16_t evse_get_charging_current(void);
|
||||
esp_err_t evse_set_charging_current(uint16_t value);
|
||||
uint16_t evse_get_default_charging_current(void);
|
||||
esp_err_t evse_set_default_charging_current(uint16_t value);
|
||||
uint8_t evse_get_max_charging_current(void);
|
||||
esp_err_t evse_set_max_charging_current(uint8_t value);
|
||||
|
||||
// Temperatura
|
||||
uint8_t evse_get_temp_threshold(void);
|
||||
esp_err_t evse_set_temp_threshold(uint8_t value);
|
||||
|
||||
// RCM / Socket
|
||||
bool evse_get_socket_outlet(void);
|
||||
esp_err_t evse_set_socket_outlet(bool value);
|
||||
bool evse_is_rcm(void);
|
||||
esp_err_t evse_set_rcm(bool value);
|
||||
|
||||
// Limites
|
||||
uint32_t evse_get_consumption_limit(void);
|
||||
void evse_set_consumption_limit(uint32_t value);
|
||||
uint32_t evse_get_charging_time_limit(void);
|
||||
void evse_set_charging_time_limit(uint32_t value);
|
||||
uint16_t evse_get_under_power_limit(void);
|
||||
void evse_set_under_power_limit(uint16_t value);
|
||||
|
||||
void evse_set_limit_reached(bool value);
|
||||
|
||||
// Energia total acumulada da sessão (em Wh)
|
||||
uint32_t evse_get_total_energy(void);
|
||||
|
||||
// Potência instantânea medida (em W)
|
||||
uint32_t evse_get_instant_power(void);
|
||||
|
||||
// Limites default
|
||||
uint32_t evse_get_default_consumption_limit(void);
|
||||
void evse_set_default_consumption_limit(uint32_t value);
|
||||
uint32_t evse_get_default_charging_time_limit(void);
|
||||
void evse_set_default_charging_time_limit(uint32_t value);
|
||||
uint16_t evse_get_default_under_power_limit(void);
|
||||
void evse_set_default_under_power_limit(uint16_t value);
|
||||
|
||||
|
||||
uint32_t evse_get_total_energy(void);
|
||||
uint32_t evse_get_instant_power(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_API_H
|
||||
|
||||
17
components/evse/include/evse_core.h
Normal file
17
components/evse/include/evse_core.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef EVSE_CORE_H
|
||||
#define EVSE_CORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initializes the EVSE system and starts core task loop.
|
||||
*/
|
||||
void evse_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_CORE_H
|
||||
@@ -9,47 +9,58 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ========================
|
||||
// Limit state control
|
||||
// ========================
|
||||
// ============================
|
||||
// Limit Status & Evaluation
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Sets the 'limit reached' flag. Used internally when a session exceeds defined thresholds.
|
||||
* @brief Sets the internal 'limit reached' flag.
|
||||
* Called internally when a limit condition is triggered.
|
||||
*/
|
||||
void evse_set_limit_reached(bool value);
|
||||
|
||||
/**
|
||||
* @brief Returns whether any session limit has been reached (energy, time or power).
|
||||
* @brief Returns true if any runtime charging limit has been reached.
|
||||
*/
|
||||
bool evse_get_limit_reached(void);
|
||||
|
||||
// ========================
|
||||
// Limit checking
|
||||
// ========================
|
||||
|
||||
/**
|
||||
* @brief Evaluates if the session has exceeded any configured limits.
|
||||
* Should be called periodically while in charging state.
|
||||
* @brief Checks if any session limit has been exceeded (energy, time or power).
|
||||
* Should be called periodically during charging.
|
||||
*/
|
||||
void evse_limits_check(void);
|
||||
|
||||
// ========================
|
||||
// Runtime limit configuration
|
||||
// ========================
|
||||
// ============================
|
||||
// Runtime Limit Configuration
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Get/set energy consumption limit (in Wh).
|
||||
*/
|
||||
uint32_t evse_get_consumption_limit(void);
|
||||
void evse_set_consumption_limit(uint32_t value); // in Wh
|
||||
void evse_set_consumption_limit(uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Get/set maximum charging time (in seconds).
|
||||
*/
|
||||
uint32_t evse_get_charging_time_limit(void);
|
||||
void evse_set_charging_time_limit(uint32_t value); // in seconds
|
||||
void evse_set_charging_time_limit(uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Get/set minimum acceptable power level (in Watts).
|
||||
* If the power remains below this for a long time, the session may be interrupted.
|
||||
*/
|
||||
uint16_t evse_get_under_power_limit(void);
|
||||
void evse_set_under_power_limit(uint16_t value); // in Watts
|
||||
void evse_set_under_power_limit(uint16_t value);
|
||||
|
||||
// ========================
|
||||
// Default (persistent) limits
|
||||
// ========================
|
||||
// ============================
|
||||
// Default (Persistent) Limits
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Default values used after system boot or reset.
|
||||
* These can be restored from NVS or fallback values.
|
||||
*/
|
||||
uint32_t evse_get_default_consumption_limit(void);
|
||||
void evse_set_default_consumption_limit(uint32_t value);
|
||||
|
||||
|
||||
@@ -26,38 +26,6 @@ void evse_manager_init(void);
|
||||
*/
|
||||
void evse_manager_tick(void);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o EVSE está disponível para uso.
|
||||
*
|
||||
* Isso considera falhas críticas, disponibilidade configurada, etc.
|
||||
*/
|
||||
bool evse_manager_is_available(void);
|
||||
|
||||
/**
|
||||
* @brief Define se o EVSE deve estar disponível (ex: via controle remoto).
|
||||
*/
|
||||
void evse_manager_set_available(bool available);
|
||||
|
||||
/**
|
||||
* @brief Define se o EVSE está autorizado a carregar (ex: após autenticação).
|
||||
*/
|
||||
void evse_manager_set_authorized(bool authorized);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o EVSE está atualmente carregando.
|
||||
*/
|
||||
bool evse_manager_is_charging(void);
|
||||
|
||||
/**
|
||||
* @brief Ativa ou desativa logicamente o EVSE (controla habilitação geral).
|
||||
*/
|
||||
void evse_manager_set_enabled(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o EVSE está ativado logicamente.
|
||||
*/
|
||||
bool evse_manager_is_enabled(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
37
components/evse/include/evse_meter.h
Normal file
37
components/evse/include/evse_meter.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef EVSE_METER_H
|
||||
#define EVSE_METER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EVSE_METER_PHASE_COUNT 3
|
||||
|
||||
/// Inicializa o módulo EVSE Meter e registra os tratadores de eventos
|
||||
void evse_meter_init(void);
|
||||
|
||||
/// Retorna a potência instantânea (soma das 3 fases, em watts)
|
||||
uint32_t evse_meter_get_instant_power(void);
|
||||
|
||||
/// Retorna a energia total acumulada (em Wh)
|
||||
uint32_t evse_meter_get_total_energy(void);
|
||||
|
||||
/// Retorna as potências instantâneas nas fases L1, L2 e L3 (em watts)
|
||||
void evse_meter_get_power(uint32_t power[EVSE_METER_PHASE_COUNT]);
|
||||
|
||||
/// Retorna as tensões medidas nas fases L1, L2 e L3 (em volts)
|
||||
void evse_meter_get_voltage(float voltage[EVSE_METER_PHASE_COUNT]);
|
||||
|
||||
/// Retorna as correntes medidas nas fases L1, L2 e L3 (em amperes)
|
||||
void evse_meter_get_current(float current[EVSE_METER_PHASE_COUNT]);
|
||||
|
||||
/// Handler interno para eventos do medidor (não chamar externamente)
|
||||
void evse_meter_on_meter_event(void* arg, void* event_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_METER_H
|
||||
@@ -5,6 +5,10 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "evse_events.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ============================
|
||||
// EVSE Pilot Signal States
|
||||
// ============================
|
||||
@@ -22,21 +26,21 @@ typedef enum {
|
||||
} evse_state_t;
|
||||
|
||||
// ============================
|
||||
// Initialization & Core Control
|
||||
// Initialization
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Initializes the EVSE state machine.
|
||||
* @brief Initializes the EVSE state machine and default state.
|
||||
*/
|
||||
void evse_state_init(void);
|
||||
|
||||
/**
|
||||
* @brief Periodic tick function for the state machine.
|
||||
* @brief Periodic tick for state handling (optional hook).
|
||||
*/
|
||||
void evse_state_tick(void);
|
||||
|
||||
// ============================
|
||||
// State Access
|
||||
// State Access & Control
|
||||
// ============================
|
||||
|
||||
/**
|
||||
@@ -45,51 +49,55 @@ void evse_state_tick(void);
|
||||
evse_state_t evse_get_state(void);
|
||||
|
||||
/**
|
||||
* @brief Updates the current EVSE state and triggers events.
|
||||
* @brief Sets the current EVSE state and emits a change event if needed.
|
||||
*/
|
||||
void evse_set_state(evse_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Returns the tick count when charging session started.
|
||||
* @brief Returns the tick count when the current charging session began.
|
||||
*/
|
||||
TickType_t evse_get_session_start(void);
|
||||
|
||||
/**
|
||||
* @brief Converts the state enum to a human-readable string.
|
||||
* @brief Converts the state enum into a human-readable string.
|
||||
*/
|
||||
const char* evse_state_to_str(evse_state_t state);
|
||||
|
||||
// ============================
|
||||
// State Evaluators
|
||||
// State Evaluation Helpers
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Returns true if the state represents an active session (B2, C1, C2).
|
||||
* @brief True if EV is in an active session (B2, C1, C2).
|
||||
*/
|
||||
bool evse_state_is_session(evse_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the state represents active charging (C1, C2).
|
||||
* @brief True if EV is actively charging (C1, C2).
|
||||
*/
|
||||
bool evse_state_is_charging(evse_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the vehicle is plugged in.
|
||||
* @brief True if EV is physically plugged in (B1 and beyond).
|
||||
*/
|
||||
bool evse_state_is_plugged(evse_state_t state);
|
||||
|
||||
// ============================
|
||||
// Authorization
|
||||
// Authorization Control
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Sets the vehicle authorization state.
|
||||
* @brief Sets whether the EV is authorized to charge.
|
||||
*/
|
||||
void evse_state_set_authorized(bool authorized);
|
||||
|
||||
/**
|
||||
* @brief Returns the current vehicle authorization state.
|
||||
* @brief Gets whether the EV is currently authorized.
|
||||
*/
|
||||
bool evse_state_get_authorized(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_STATE_H
|
||||
|
||||
@@ -22,4 +22,4 @@ set(includes
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${includes}"
|
||||
PRIV_REQUIRES nvs_flash
|
||||
REQUIRES esp_event esp-modbus)
|
||||
REQUIRES esp_event esp-modbus spi_bus_manager)
|
||||
|
||||
@@ -1,186 +1,184 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "ade7758.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
spi_bus_config_t _spi_bus_cfg;
|
||||
// spi_device_interface_config_t _spi_interface_cfg;
|
||||
spi_device_handle_t _handle;
|
||||
spi_host_device_t _spi_peripheral;
|
||||
|
||||
spi_transaction_t _spi_transaction;
|
||||
|
||||
esp_err_t transferByte(const uint8_t reg_addr, const uint8_t data, const uint8_t command)
|
||||
{
|
||||
_spi_transaction.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
|
||||
_spi_transaction.length = 8;
|
||||
//_spi_transaction.rxlength = 8;
|
||||
_spi_transaction.cmd = command;
|
||||
_spi_transaction.addr = reg_addr;
|
||||
_spi_transaction.tx_data[0] = data;
|
||||
#define PIN_ADUM_EN 4 // ou o pino real conectado ao VE1 do ADUM1401
|
||||
|
||||
return spi_device_transmit(_handle, &_spi_transaction);
|
||||
|
||||
static const char *TAG = "ade7758";
|
||||
|
||||
// --- SPI internals ---
|
||||
static spi_device_handle_t ade7758_spi_handle = NULL;
|
||||
static spi_host_device_t spi_host = SPI2_HOST; // default
|
||||
|
||||
static spi_transaction_t spi_transaction;
|
||||
|
||||
// --- Configuração SPI do dispositivo ---
|
||||
static const uint8_t MODE = 2;
|
||||
static const uint8_t ADDR_BITS = 7;
|
||||
static const uint8_t CMD_BITS = 1;
|
||||
static const uint8_t SPI_WRITE = 1;
|
||||
static const uint8_t SPI_READ = 0;
|
||||
static const int BUS_SPEED_HZ = 1000000;
|
||||
|
||||
|
||||
static void adum1401_select(void) {
|
||||
gpio_set_level(PIN_ADUM_EN, 1);
|
||||
esp_rom_delay_us(2); // curto delay para estabilização
|
||||
}
|
||||
|
||||
esp_err_t transferMultiplesBytes(const uint8_t reg_addr, uint8_t *tx_buf, uint8_t *rx_buf, size_t data_length, const uint8_t command)
|
||||
{
|
||||
spi_transaction_t spi_transaction_multibyte; // spi_transaction_t to use the tx and rx buffers
|
||||
|
||||
if (data_length < 1)
|
||||
{
|
||||
data_length = 1;
|
||||
}
|
||||
|
||||
spi_transaction_multibyte.flags = 0; // SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
|
||||
spi_transaction_multibyte.length = (8 * data_length);
|
||||
spi_transaction_multibyte.rxlength = 0;
|
||||
spi_transaction_multibyte.cmd = command;
|
||||
spi_transaction_multibyte.addr = reg_addr;
|
||||
spi_transaction_multibyte.tx_buffer = tx_buf;
|
||||
spi_transaction_multibyte.rx_buffer = rx_buf;
|
||||
|
||||
return spi_device_transmit(_handle, &spi_transaction_multibyte);
|
||||
static void adum1401_deselect(void) {
|
||||
esp_rom_delay_us(2); // opcional: aguarde para evitar glitch
|
||||
gpio_set_level(PIN_ADUM_EN, 0);
|
||||
}
|
||||
|
||||
esp_err_t Init(const spi_host_device_t spi_peripheral, const int pin_miso, const int pin_mosi, const int pin_sclk)
|
||||
{
|
||||
esp_err_t status = ESP_OK;
|
||||
// === Transações básicas ===
|
||||
|
||||
_spi_peripheral = spi_peripheral;
|
||||
static esp_err_t transfer_byte(uint8_t reg_addr, uint8_t data, uint8_t command) {
|
||||
adum1401_select();
|
||||
|
||||
_spi_transaction.tx_buffer = NULL;
|
||||
_spi_transaction.rx_buffer = NULL;
|
||||
spi_transaction.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
|
||||
spi_transaction.length = 8;
|
||||
spi_transaction.cmd = command;
|
||||
spi_transaction.addr = reg_addr;
|
||||
spi_transaction.tx_data[0] = data;
|
||||
|
||||
_spi_bus_cfg.mosi_io_num = pin_mosi;
|
||||
_spi_bus_cfg.miso_io_num = pin_miso;
|
||||
_spi_bus_cfg.sclk_io_num = pin_sclk;
|
||||
_spi_bus_cfg.quadwp_io_num = -1;
|
||||
_spi_bus_cfg.quadhd_io_num = -1;
|
||||
esp_err_t err = spi_device_transmit(ade7758_spi_handle, &spi_transaction);
|
||||
|
||||
status |= spi_bus_initialize(spi_peripheral, &_spi_bus_cfg, SPI_DMA_CH_AUTO);
|
||||
|
||||
return status;
|
||||
adum1401_deselect();
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t RegisterDevice(const uint8_t mode, const int ss, const int addr_length, const int command_length, const int bus_speed)
|
||||
{
|
||||
esp_err_t status = ESP_OK;
|
||||
|
||||
spi_device_interface_config_t _spi_interface_cfg = {
|
||||
.command_bits = command_length,
|
||||
.address_bits = addr_length,
|
||||
.mode = mode,
|
||||
.clock_speed_hz = bus_speed,
|
||||
.spics_io_num = ss,
|
||||
static esp_err_t transfer_bytes(uint8_t reg_addr, uint8_t *tx_buf, uint8_t *rx_buf, size_t len, uint8_t command) {
|
||||
if (len < 1) len = 1;
|
||||
|
||||
spi_transaction_t t = {
|
||||
.flags = 0,
|
||||
.length = 8 * len,
|
||||
.cmd = command,
|
||||
.addr = reg_addr,
|
||||
.tx_buffer = tx_buf,
|
||||
.rx_buffer = rx_buf
|
||||
};
|
||||
|
||||
adum1401_select();
|
||||
esp_err_t err = spi_device_transmit(ade7758_spi_handle, &t);
|
||||
adum1401_deselect();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// === Interface pública ===
|
||||
|
||||
esp_err_t Init(spi_host_device_t host, int pin_miso, int pin_mosi, int pin_sclk) {
|
||||
// Essa função não inicializa o barramento SPI
|
||||
// Apenas armazena os parâmetros
|
||||
spi_host = host;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t InitSpi(int cs_gpio) {
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = CMD_BITS,
|
||||
.address_bits = ADDR_BITS,
|
||||
.mode = MODE,
|
||||
.clock_speed_hz = BUS_SPEED_HZ,
|
||||
.spics_io_num = cs_gpio,
|
||||
.queue_size = 5,
|
||||
};
|
||||
|
||||
status |= spi_bus_add_device(_spi_peripheral, &_spi_interface_cfg, &_handle);
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = BIT64(PIN_ADUM_EN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(PIN_ADUM_EN, 0); // inicialmente desativado
|
||||
|
||||
return status;
|
||||
|
||||
return spi_bus_add_device(spi_host, &devcfg, &ade7758_spi_handle);
|
||||
}
|
||||
|
||||
uint8_t ReadRegister(const uint8_t reg_addr, const uint8_t command)
|
||||
{
|
||||
transferByte(reg_addr, 0, command);
|
||||
|
||||
return _spi_transaction.rx_data[0];
|
||||
spi_device_handle_t GetHandle(void) {
|
||||
return ade7758_spi_handle;
|
||||
}
|
||||
|
||||
esp_err_t WriteRegister(const uint8_t reg_addr, const uint8_t reg_data, const uint8_t command)
|
||||
{
|
||||
esp_err_t status = ESP_OK;
|
||||
// === Registro de acesso ===
|
||||
|
||||
status |= transferByte(reg_addr, reg_data, command);
|
||||
|
||||
return status;
|
||||
uint8_t ReadRegister(uint8_t reg_addr, uint8_t command) {
|
||||
transfer_byte(reg_addr, 0, command);
|
||||
return spi_transaction.rx_data[0];
|
||||
}
|
||||
|
||||
esp_err_t WriteRegisterMultipleBytes(const uint8_t reg_addr, uint8_t *reg_data_buffer, const uint8_t byte_count, const uint8_t command)
|
||||
{
|
||||
return transferMultiplesBytes(reg_addr, reg_data_buffer, NULL, byte_count, command);
|
||||
esp_err_t WriteRegister(uint8_t reg_addr, uint8_t data, uint8_t command) {
|
||||
return transfer_byte(reg_addr, data, command);
|
||||
}
|
||||
|
||||
esp_err_t ReadRegisterMultipleBytes(const uint8_t reg_addr, uint8_t *reg_data_buffer, const uint8_t byte_count, const uint8_t command)
|
||||
{
|
||||
return transferMultiplesBytes(reg_addr, NULL, reg_data_buffer, byte_count, command);
|
||||
esp_err_t WriteRegisterMultipleBytes(uint8_t reg, uint8_t *data, uint8_t count, uint8_t command) {
|
||||
return transfer_bytes(reg, data, NULL, count, command);
|
||||
}
|
||||
|
||||
spi_device_handle_t GetHandle(void)
|
||||
{
|
||||
return _handle;
|
||||
esp_err_t ReadRegisterMultipleBytes(uint8_t reg, uint8_t *buf, uint8_t count, uint8_t command) {
|
||||
return transfer_bytes(reg, NULL, buf, count, command);
|
||||
}
|
||||
|
||||
static uint8_t MODE = 2;
|
||||
static uint8_t ADDR_BITS = 7;
|
||||
static uint8_t CMD_BITS = 1;
|
||||
// === Leitura e escrita de tamanho fixo ===
|
||||
|
||||
static uint8_t SPI_WRITE = 1;
|
||||
static uint8_t SPI_READ = 0;
|
||||
static int BUSSPEED = 1000000;
|
||||
|
||||
// static const char TAG[] = "ade7758";
|
||||
|
||||
esp_err_t write8(uint8_t reg, uint8_t value)
|
||||
{
|
||||
esp_err_t write8(uint8_t reg, uint8_t value) {
|
||||
return WriteRegister(reg, value, SPI_WRITE);
|
||||
}
|
||||
|
||||
esp_err_t write16(uint8_t reg, uint32_t value)
|
||||
{
|
||||
uint8_t buff[2];
|
||||
|
||||
buff[0] = (value >> 8) & 0xFF;
|
||||
buff[1] = (value >> 0) & 0xFF;
|
||||
|
||||
return WriteRegisterMultipleBytes(reg, buff, 3, SPI_WRITE);
|
||||
esp_err_t write16(uint8_t reg, uint32_t value) {
|
||||
uint8_t buf[2] = {
|
||||
(value >> 8) & 0xFF,
|
||||
(value >> 0) & 0xFF
|
||||
};
|
||||
return WriteRegisterMultipleBytes(reg, buf, 2, SPI_WRITE);
|
||||
}
|
||||
|
||||
esp_err_t write24(uint8_t reg, uint32_t value)
|
||||
{
|
||||
uint8_t buff[2];
|
||||
|
||||
buff[0] = (value >> 16) & 0xFF;
|
||||
buff[1] = (value >> 8) & 0xFF;
|
||||
buff[2] = (value >> 0) & 0xFF;
|
||||
|
||||
return WriteRegisterMultipleBytes(reg, buff, 4, SPI_WRITE);
|
||||
esp_err_t write24(uint8_t reg, uint32_t value) {
|
||||
uint8_t buf[3] = {
|
||||
(value >> 16) & 0xFF,
|
||||
(value >> 8) & 0xFF,
|
||||
(value >> 0) & 0xFF
|
||||
};
|
||||
return WriteRegisterMultipleBytes(reg, buf, 3, SPI_WRITE);
|
||||
}
|
||||
|
||||
uint8_t read8(const uint8_t reg)
|
||||
{
|
||||
uint8_t buff[1];
|
||||
ReadRegisterMultipleBytes(reg, buff, 2, SPI_READ);
|
||||
return buff[0];
|
||||
uint8_t read8(uint8_t reg) {
|
||||
uint8_t buf[1];
|
||||
ReadRegisterMultipleBytes(reg, buf, 1, SPI_READ);
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
uint32_t read16(const uint8_t reg)
|
||||
{
|
||||
uint8_t buff[2];
|
||||
ReadRegisterMultipleBytes(reg, buff, 3, SPI_READ);
|
||||
return buff[0] << 8 | buff[1];
|
||||
uint32_t read16(uint8_t reg) {
|
||||
uint8_t buf[2];
|
||||
ReadRegisterMultipleBytes(reg, buf, 2, SPI_READ);
|
||||
return (buf[0] << 8) | buf[1];
|
||||
}
|
||||
|
||||
uint32_t read24(const uint8_t reg)
|
||||
{
|
||||
uint8_t buff[3];
|
||||
ReadRegisterMultipleBytes(reg, buff, 4, SPI_READ);
|
||||
return buff[0] << 16 | buff[1] << 8 | buff[2];
|
||||
uint32_t read24(uint8_t reg) {
|
||||
uint8_t buf[3];
|
||||
ReadRegisterMultipleBytes(reg, buf, 3, SPI_READ);
|
||||
return (buf[0] << 16) | (buf[1] << 8) | buf[2];
|
||||
}
|
||||
|
||||
esp_err_t readBlockData(const uint8_t reg, uint8_t *buf, const int length)
|
||||
{
|
||||
return ReadRegisterMultipleBytes(reg, buf, length, SPI_READ);
|
||||
esp_err_t readBlockData(uint8_t reg, uint8_t *buf, int len) {
|
||||
return ReadRegisterMultipleBytes(reg, buf, len, SPI_READ);
|
||||
}
|
||||
|
||||
esp_err_t InitSpi(const int ss)
|
||||
{
|
||||
return RegisterDevice(MODE, ss, ADDR_BITS, CMD_BITS, BUSSPEED);
|
||||
}
|
||||
|
||||
/*****************************
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "meter_ade7758.h"
|
||||
#include "spi_bus_manager.h"
|
||||
#include "ade7758.h"
|
||||
#include "meter_events.h"
|
||||
|
||||
@@ -11,16 +12,13 @@
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#define TAG "meter_ade7758"
|
||||
|
||||
// === Configurações de hardware ===
|
||||
#define PIN_NUM_CLK 15
|
||||
#define PIN_NUM_MOSI 2
|
||||
#define PIN_NUM_MISO 4
|
||||
#define PIN_NUM_CS 23
|
||||
#define EEPROM_HOST HSPI_HOST
|
||||
// === Pinos ===
|
||||
#define PIN_NUM_CS 15
|
||||
#define PIN_ADUM_EN 4
|
||||
|
||||
// === Constantes de calibração ===
|
||||
#define VRMS_CAL 4732.78f
|
||||
@@ -28,13 +26,13 @@
|
||||
|
||||
#define METER_READ_INTERVAL_MS 5000
|
||||
|
||||
// === Dados internos ===
|
||||
// === Estrutura interna ===
|
||||
typedef struct {
|
||||
float vrms[3];
|
||||
float irms[3];
|
||||
int watt[3];
|
||||
int var[3]; // reservados
|
||||
int va[3]; // reservados
|
||||
int var[3]; // reservado
|
||||
int va[3]; // reservado
|
||||
} meter_ade7758_internal_data_t;
|
||||
|
||||
static meter_ade7758_internal_data_t meter_data;
|
||||
@@ -42,7 +40,8 @@ static TaskHandle_t meter_task = NULL;
|
||||
static SemaphoreHandle_t meter_mutex = NULL;
|
||||
static uint32_t meter_watchdog_counter = 0;
|
||||
|
||||
// === Utilitários internos ===
|
||||
|
||||
// === Post de evento ===
|
||||
static void meter_ade7758_post_event(const meter_ade7758_internal_data_t *data) {
|
||||
meter_event_data_t evt = {
|
||||
.frequency = 0,
|
||||
@@ -54,22 +53,23 @@ static void meter_ade7758_post_event(const meter_ade7758_internal_data_t *data)
|
||||
memcpy(evt.irms, data->irms, sizeof(evt.irms));
|
||||
memcpy(evt.watt, data->watt, sizeof(evt.watt));
|
||||
|
||||
esp_err_t err = esp_event_post(METER_EVENT, METER_EVENT_DATA_READY,
|
||||
&evt, sizeof(evt), pdMS_TO_TICKS(10));
|
||||
|
||||
esp_err_t err = esp_event_post(METER_EVENT, METER_EVENT_DATA_READY, &evt, sizeof(evt), pdMS_TO_TICKS(10));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Falha ao emitir evento: %s", esp_err_to_name(err));
|
||||
}
|
||||
}
|
||||
|
||||
// === Task de leitura ===
|
||||
static void meter_ade7758_task_func(void *param) {
|
||||
ESP_LOGI(TAG, "Meter task started");
|
||||
ESP_LOGI(TAG, "Tarefa de medição ADE7758 iniciada");
|
||||
|
||||
meter_ade7758_internal_data_t previous = {0};
|
||||
|
||||
while (true) {
|
||||
meter_ade7758_internal_data_t meterData = {0};
|
||||
|
||||
//ESP_LOGI(TAG, "Tarefa de medição ADE7758 iniciada %d",getVersion());
|
||||
|
||||
meterData.vrms[0] = avrms() / VRMS_CAL;
|
||||
meterData.vrms[1] = bvrms() / VRMS_CAL;
|
||||
meterData.vrms[2] = cvrms() / VRMS_CAL;
|
||||
@@ -97,10 +97,9 @@ static void meter_ade7758_task_func(void *param) {
|
||||
}
|
||||
}
|
||||
|
||||
// === Interface pública: controle ===
|
||||
|
||||
// === Inicialização ===
|
||||
esp_err_t meter_ade7758_init(void) {
|
||||
ESP_LOGI(TAG, "Inicializando medidor ADE7758...");
|
||||
ESP_LOGI(TAG, "Inicializando ADE7758...");
|
||||
|
||||
if (!meter_mutex) {
|
||||
meter_mutex = xSemaphoreCreateMutex();
|
||||
@@ -110,21 +109,38 @@ esp_err_t meter_ade7758_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = Init(EEPROM_HOST, PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK);
|
||||
if (!spi_bus_manager_is_initialized()) {
|
||||
esp_err_t err = spi_bus_manager_init(); // usa pinos padrão
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Erro ao inicializar SPI: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); // Delay de estabilização
|
||||
|
||||
esp_err_t err = Init(spi_bus_manager_get_host(), -1, -1, -1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Erro ao inicializar SPI (%d)", err);
|
||||
ESP_LOGE(TAG, "Erro Init SPI ADE7758: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
err = InitSpi(PIN_NUM_CS);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Erro ao registrar dispositivo SPI: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
InitSpi(PIN_NUM_CS);
|
||||
gainSetup(INTEGRATOR_OFF, FULLSCALESELECT_0_5V, GAIN_1, GAIN_1);
|
||||
setupDivs(1, 1, 1);
|
||||
setLcycMode(0x00);
|
||||
resetStatus();
|
||||
|
||||
ESP_LOGI(TAG, "ADE7758 inicializado com sucesso.");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// === Execução ===
|
||||
esp_err_t meter_ade7758_start(void) {
|
||||
if (meter_task) return ESP_ERR_INVALID_STATE;
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ void wifi_ini(void)
|
||||
char chargeid[6];
|
||||
uint8_t mac[6];
|
||||
esp_wifi_get_mac(ESP_IF_WIFI_AP, mac);
|
||||
sprintf((char *)chargeid, MDNS_SSID, mac[5]);
|
||||
sprintf((char *)chargeid, MDNS_SSID, 0);
|
||||
|
||||
ESP_ERROR_CHECK(mdns_init());
|
||||
ESP_ERROR_CHECK(mdns_hostname_set(chargeid));
|
||||
@@ -188,7 +188,9 @@ esp_netif_t *wifi_get_ap_netif(void)
|
||||
esp_err_t wifi_set_config(bool enabled, const char *ssid, const char *password)
|
||||
{
|
||||
|
||||
ESP_LOGI(TAG, "Wifi set config");
|
||||
|
||||
ESP_LOGI(TAG, "wifi_set_config(enabled=%d, ssid=\"%s\")", enabled, ssid?:"<nil>");
|
||||
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_mac.h"
|
||||
#include "nvs.h"
|
||||
#include "mdns.h"
|
||||
|
||||
#include "wifi.h"
|
||||
|
||||
|
||||
#include "nvs_flash.h"
|
||||
#include <string.h>
|
||||
|
||||
#define WIFI_STORAGE_NAMESPACE "wifi_config"
|
||||
|
||||
|
||||
|
||||
#define TAG "wifi"
|
||||
#define AP_SSID "plx-%02x%02x%02x"
|
||||
#define MDNS_HOSTNAME "plx%02x"
|
||||
|
||||
#define NVS_NAMESPACE "wifi"
|
||||
|
||||
static nvs_handle_t nvs;
|
||||
static esp_netif_t *ap_netif;
|
||||
EventGroupHandle_t wifi_event_group;
|
||||
|
||||
//
|
||||
// Event handler para modo AP
|
||||
//
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT) {
|
||||
switch (event_id) {
|
||||
case WIFI_EVENT_AP_STACONNECTED: {
|
||||
wifi_event_ap_staconnected_t *event = event_data;
|
||||
ESP_LOGI(TAG, "STA " MACSTR " conectou, AID=%d", MAC2STR(event->mac), event->aid);
|
||||
xEventGroupSetBits(wifi_event_group, WIFI_AP_CONNECTED_BIT);
|
||||
break;
|
||||
}
|
||||
case WIFI_EVENT_AP_STADISCONNECTED: {
|
||||
wifi_event_ap_stadisconnected_t *event = event_data;
|
||||
ESP_LOGI(TAG, "STA " MACSTR " desconectou, AID=%d", MAC2STR(event->mac), event->aid);
|
||||
xEventGroupClearBits(wifi_event_group, WIFI_AP_CONNECTED_BIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Iniciar o AP com SSID baseado no MAC
|
||||
//
|
||||
void wifi_ap_start(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Iniciando AP");
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_stop());
|
||||
|
||||
wifi_config_t ap_config = {
|
||||
.ap = {
|
||||
.ssid = "",
|
||||
.ssid_len = 0,
|
||||
.channel = 1,
|
||||
.password = "",
|
||||
.max_connection = 4,
|
||||
.authmode = WIFI_AUTH_OPEN
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t mac[6];
|
||||
ESP_ERROR_CHECK(esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP));
|
||||
snprintf((char *)ap_config.ap.ssid, sizeof(ap_config.ap.ssid), AP_SSID, mac[3], mac[4], mac[5]);
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
xEventGroupSetBits(wifi_event_group, WIFI_AP_MODE_BIT);
|
||||
}
|
||||
|
||||
//
|
||||
// Inicializar Wi-Fi em modo AP
|
||||
//
|
||||
void wifi_ini(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Inicializando Wi-Fi (modo AP)");
|
||||
|
||||
ESP_ERROR_CHECK(nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs));
|
||||
|
||||
wifi_event_group = xEventGroupCreate();
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
/*
|
||||
if (!esp_event_loop_is_running()) {
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
}*/
|
||||
|
||||
ap_netif = esp_netif_create_default_wifi_ap();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
||||
|
||||
uint8_t mac[6];
|
||||
ESP_ERROR_CHECK(esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP));
|
||||
char hostname[16];
|
||||
snprintf(hostname, sizeof(hostname), MDNS_HOSTNAME, mac[5]);
|
||||
|
||||
ESP_ERROR_CHECK(mdns_init());
|
||||
ESP_ERROR_CHECK(mdns_hostname_set(hostname));
|
||||
ESP_ERROR_CHECK(mdns_instance_name_set("EVSE Controller"));
|
||||
|
||||
wifi_ap_start();
|
||||
}
|
||||
|
||||
esp_netif_t *wifi_get_ap_netif(void)
|
||||
{
|
||||
return ap_netif;
|
||||
}
|
||||
|
||||
esp_err_t wifi_set_config(bool enabled, const char *ssid, const char *password) {
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void wifi_get_ssid(char *value) {
|
||||
// Your implementation here
|
||||
}
|
||||
|
||||
void wifi_get_password(char *value) {
|
||||
// Your implementation here
|
||||
}
|
||||
|
||||
bool wifi_get_enabled(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "evse_api.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_state.h"
|
||||
#include "evse_config.h"
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs.h"
|
||||
@@ -48,10 +49,10 @@ static void ocpp_task_func(void *param)
|
||||
mg_mgr_poll(&mgr, 10);
|
||||
ocpp_loop();
|
||||
|
||||
if (evse_is_enabled() != ocpp_isOperative())
|
||||
if (evse_config_is_enabled() != ocpp_isOperative())
|
||||
{
|
||||
printf("ocpp_isOperative()");
|
||||
evse_set_enabled(ocpp_isOperative());
|
||||
evse_config_set_enabled(ocpp_isOperative());
|
||||
}
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
@@ -129,7 +130,7 @@ void ocpp_set_rfid(char *value)
|
||||
bool setConnectorPluggedInput()
|
||||
{
|
||||
// ESP_LOGI(TAG, "setConnectorPluggedInput");
|
||||
return evse_is_connector_plugged(evse_get_state());
|
||||
return evse_state_is_plugged(evse_get_state());
|
||||
// return true;
|
||||
}
|
||||
|
||||
@@ -143,8 +144,8 @@ bool setEvReadyInput()
|
||||
bool setEvseReadyInput()
|
||||
{
|
||||
// ESP_LOGI(TAG, "EvseReadyInput");
|
||||
return evse_is_enabled();
|
||||
// return false;
|
||||
return evse_config_is_enabled();
|
||||
//return false;
|
||||
}
|
||||
|
||||
float setPowerMeterInput()
|
||||
|
||||
@@ -18,4 +18,4 @@ set(srcs
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES nvs_flash driver esp_adc esp_timer
|
||||
REQUIRES config evse api ntc_driver)
|
||||
REQUIRES config evse api ntc_driver spi_bus_manager)
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
|
||||
static const char* TAG = "ac_relay";
|
||||
|
||||
// Memoization do estado atual do relé (salvo em RAM)
|
||||
static int last_state = -1;
|
||||
|
||||
/**
|
||||
* @brief Initialize the AC relay GPIO.
|
||||
*
|
||||
@@ -16,7 +19,7 @@ void ac_relay_init(void)
|
||||
gpio_config_t conf = {
|
||||
.pin_bit_mask = BIT64(board_config.ac_relay_gpio),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE, ///< Disabled unless required
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
@@ -27,7 +30,8 @@ void ac_relay_init(void)
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_set_level(board_config.ac_relay_gpio, false); ///< Ensure relay starts OFF
|
||||
gpio_set_level(board_config.ac_relay_gpio, 0); ///< Ensure relay starts OFF
|
||||
last_state = 0;
|
||||
ESP_LOGI(TAG, "AC relay initialized. Pin: %d", board_config.ac_relay_gpio);
|
||||
}
|
||||
|
||||
@@ -38,9 +42,15 @@ void ac_relay_init(void)
|
||||
*/
|
||||
void ac_relay_set_state(bool state)
|
||||
{
|
||||
if (state == last_state) {
|
||||
// Estado não mudou; evita log e escrita desnecessária.
|
||||
return;
|
||||
}
|
||||
last_state = state;
|
||||
|
||||
ESP_LOGI(TAG, "Setting AC relay state: Pin: %d, State: %d", board_config.ac_relay_gpio, state);
|
||||
|
||||
esp_err_t ret = gpio_set_level(board_config.ac_relay_gpio, state);
|
||||
|
||||
esp_err_t ret = gpio_set_level(board_config.ac_relay_gpio, state ? 1 : 0);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set GPIO level (error: %s)", esp_err_to_name(ret));
|
||||
}
|
||||
@@ -55,5 +65,5 @@ bool ac_relay_get_state(void)
|
||||
{
|
||||
int level = gpio_get_level(board_config.ac_relay_gpio);
|
||||
ESP_LOGD(TAG, "Current AC relay state: Pin: %d, State: %d", board_config.ac_relay_gpio, level);
|
||||
return level;
|
||||
return (level != 0);
|
||||
}
|
||||
|
||||
@@ -1,53 +1,64 @@
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "adc121s021_dma.h"
|
||||
#include "spi_bus_manager.h"
|
||||
|
||||
#define TAG "adc_dma"
|
||||
|
||||
#define PIN_NUM_MOSI 23
|
||||
#define PIN_NUM_MISO 19
|
||||
#define PIN_NUM_CLK 18
|
||||
#define PIN_NUM_CS 5
|
||||
#define PIN_NUM_CS 5
|
||||
#define SAMPLE_SIZE_BYTES 2
|
||||
#define ADC_BITS 12
|
||||
#define SPI_CLOCK_HZ (6 * 1000 * 1000) // 6 MHz
|
||||
|
||||
#define SPI_HOST_USED SPI2_HOST
|
||||
#define SAMPLE_SIZE_BYTES 2
|
||||
#define ADC_BITS 12
|
||||
|
||||
static spi_device_handle_t adc_spi;
|
||||
static spi_device_handle_t adc_spi = NULL;
|
||||
|
||||
void adc121s021_dma_init(void)
|
||||
{
|
||||
spi_bus_config_t buscfg = {
|
||||
.mosi_io_num = PIN_NUM_MOSI,
|
||||
.miso_io_num = PIN_NUM_MISO,
|
||||
.sclk_io_num = PIN_NUM_CLK,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = SAMPLE_SIZE_BYTES,
|
||||
};
|
||||
if (adc_spi) {
|
||||
ESP_LOGW(TAG, "ADC121S021 já foi inicializado.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!spi_bus_manager_is_initialized()) {
|
||||
ESP_LOGI(TAG, "SPI bus não inicializado. Inicializando...");
|
||||
esp_err_t err = spi_bus_manager_init(); // 🔧 CORRIGIDO: sem argumentos
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Falha ao inicializar o SPI bus: %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.clock_speed_hz = 6000000, // 6 MHz
|
||||
.clock_speed_hz = SPI_CLOCK_HZ,
|
||||
.mode = 0,
|
||||
.spics_io_num = PIN_NUM_CS,
|
||||
.queue_size = 2,
|
||||
.flags = SPI_DEVICE_NO_DUMMY,
|
||||
.pre_cb = NULL,
|
||||
.post_cb = NULL,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI_HOST_USED, &buscfg, SPI_DMA_CH_AUTO));
|
||||
ESP_ERROR_CHECK(spi_bus_add_device(SPI_HOST_USED, &devcfg, &adc_spi));
|
||||
esp_err_t err = spi_bus_add_device(spi_bus_manager_get_host(), &devcfg, &adc_spi);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Falha ao registrar ADC121S021 no SPI: %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "ADC121S021 registrado no SPI com sucesso.");
|
||||
}
|
||||
|
||||
bool adc121s021_dma_get_sample(uint16_t *sample)
|
||||
{
|
||||
uint8_t tx_buffer[2] = {0x00, 0x00}; // Dummy TX
|
||||
if (!adc_spi) {
|
||||
ESP_LOGE(TAG, "ADC SPI não inicializado!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t tx_buffer[2] = {0x00, 0x00}; // Dummy
|
||||
uint8_t rx_buffer[2] = {0};
|
||||
|
||||
spi_transaction_t t = {
|
||||
.length = 16, // 16 bits
|
||||
.length = 16,
|
||||
.tx_buffer = tx_buffer,
|
||||
.rx_buffer = rx_buffer,
|
||||
.flags = 0
|
||||
@@ -55,12 +66,10 @@ bool adc121s021_dma_get_sample(uint16_t *sample)
|
||||
|
||||
esp_err_t err = spi_device_transmit(adc_spi, &t);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "SPI transmit error: %s", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "Erro na transmissão SPI: %s", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extrai os 12 bits significativos da resposta do ADC121S021
|
||||
*sample = ((rx_buffer[0] << 8) | rx_buffer[1]) & 0x0FFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ static void buzzer_worker_task(void *arg) {
|
||||
|
||||
while (true) {
|
||||
if (xQueueReceive(buzzer_queue, &pattern_id, portMAX_DELAY)) {
|
||||
//buzzer_execute_pattern(pattern_id);
|
||||
buzzer_execute_pattern(pattern_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
set(srcs
|
||||
"src/protocols.c"
|
||||
"src/rest.c"
|
||||
"src/mqtt.c"
|
||||
"src/date_time.c"
|
||||
)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef REST_H_
|
||||
#define REST_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize REST server
|
||||
*
|
||||
* @param base_path Path on the SPIFFS filesystem where static files reside
|
||||
* @return ESP_OK on success, ESP_FAIL otherwise
|
||||
*/
|
||||
esp_err_t rest_init(const char *base_path);
|
||||
|
||||
#endif /* REST_H_ */
|
||||
@@ -31,31 +31,31 @@ static esp_err_t open_mqtt_nvs(nvs_handle_t *handle) {
|
||||
|
||||
static void subcribe_topics(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "subcribe_topics");
|
||||
ESP_LOGI(TAG, "[MQTT] Subscribing to topics");
|
||||
|
||||
char base[32];
|
||||
mqtt_get_base_topic(base);
|
||||
|
||||
char topic[64];
|
||||
mqtt_get_base_topic(topic);
|
||||
|
||||
strcat(topic, "/request/#");
|
||||
snprintf(topic, sizeof(topic), "%s/request/#", base);
|
||||
esp_mqtt_client_subscribe(client, topic, 0);
|
||||
ESP_LOGI(TAG, "subscribed: %s", topic);
|
||||
ESP_LOGI(TAG, " subscribed: %s", topic);
|
||||
|
||||
mqtt_get_base_topic(topic);
|
||||
strcat(topic, "/set/config/#");
|
||||
snprintf(topic, sizeof(topic), "%s/set/config/#", base);
|
||||
esp_mqtt_client_subscribe(client, topic, 0);
|
||||
ESP_LOGI(TAG, "subscribed: %s", topic);
|
||||
ESP_LOGI(TAG, " subscribed: %s", topic);
|
||||
|
||||
mqtt_get_base_topic(topic);
|
||||
strcat(topic, "/enable");
|
||||
snprintf(topic, sizeof(topic), "%s/enable", base);
|
||||
esp_mqtt_client_subscribe(client, topic, 0);
|
||||
ESP_LOGI(TAG, "subscribed: %s", topic);
|
||||
ESP_LOGI(TAG, " subscribed: %s", topic);
|
||||
}
|
||||
|
||||
static void publish_message(const char* topic, cJSON* root)
|
||||
{
|
||||
char target_topic[64];
|
||||
mqtt_get_base_topic(target_topic);
|
||||
strcat(target_topic, topic);
|
||||
strncat(target_topic, topic, sizeof(target_topic) - strlen(target_topic) - 1);
|
||||
|
||||
const char* json = cJSON_PrintUnformatted(root);
|
||||
esp_mqtt_client_publish(client, target_topic, json, 0, 1, 0);
|
||||
@@ -67,34 +67,51 @@ static void handle_message(const char* topic, const char* data)
|
||||
char base_topic[32];
|
||||
mqtt_get_base_topic(base_topic);
|
||||
|
||||
ESP_LOGI(TAG, "[MQTT] Message received");
|
||||
ESP_LOGI(TAG, " > Topic: %s", topic);
|
||||
ESP_LOGI(TAG, " > Payload: %s", data);
|
||||
|
||||
if (strncmp(topic, base_topic, strlen(base_topic)) == 0) {
|
||||
const char* sub_topic = &topic[strlen(base_topic)];
|
||||
ESP_LOGI(TAG, " > Subtopic detected: %s", sub_topic);
|
||||
|
||||
if (strcmp(sub_topic, "/request/config/evse") == 0) {
|
||||
ESP_LOGI(TAG, " → Responding with EVSE configuration");
|
||||
cJSON* root = json_get_evse_config();
|
||||
publish_message("/response/config/evse", root);
|
||||
cJSON_Delete(root);
|
||||
} else {
|
||||
ESP_LOGW(TAG, " ! Unknown command: %s", sub_topic);
|
||||
}
|
||||
// [Outros comandos omitidos para brevidade...]
|
||||
} else {
|
||||
ESP_LOGW(TAG, " ! Topic does not match base: %s", topic);
|
||||
}
|
||||
}
|
||||
|
||||
static void 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;
|
||||
char topic[48], data[256];
|
||||
|
||||
switch (event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT conectado");
|
||||
ESP_LOGI(TAG, "[MQTT] Connected to broker");
|
||||
if (client_task) vTaskResume(client_task);
|
||||
subcribe_topics();
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
strncpy(topic, event->topic, MIN(event->topic_len, sizeof(topic)-1));
|
||||
strncpy(data, event->data, MIN(event->data_len, sizeof(data)-1));
|
||||
|
||||
case MQTT_EVENT_DATA: {
|
||||
char topic[64] = {0};
|
||||
char data[256] = {0};
|
||||
|
||||
int tlen = MIN(event->topic_len, sizeof(topic) - 1);
|
||||
int dlen = MIN(event->data_len, sizeof(data) - 1);
|
||||
|
||||
memcpy(topic, event->topic, tlen);
|
||||
memcpy(data, event->data, dlen);
|
||||
|
||||
handle_message(topic, data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -257,4 +274,4 @@ void mqtt_get_password(char* value)
|
||||
uint16_t mqtt_get_periodicity(void)
|
||||
{
|
||||
return periodicity;
|
||||
}
|
||||
}
|
||||
@@ -1,907 +0,0 @@
|
||||
/* HTTP Restful API Server
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_chip_info.h"
|
||||
#include "esp_random.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "cJSON.h"
|
||||
#include "rest.h"
|
||||
#include "evse_api.h"
|
||||
#include "cJSON.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_http_server.h"
|
||||
#include "auth.h"
|
||||
|
||||
static const char *REST_TAG = "esp-rest";
|
||||
#define REST_CHECK(a, str, goto_tag, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(REST_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
goto goto_tag; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128)
|
||||
#define SCRATCH_BUFSIZE (10240)
|
||||
|
||||
typedef struct rest_server_context {
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
} rest_server_context_t;
|
||||
|
||||
#define CHECK_FILE_EXTENSION(filename, ext) (strcasecmp(&filename[strlen(filename) - strlen(ext)], ext) == 0)
|
||||
|
||||
// Estruturas para armazenar as configurações
|
||||
static struct {
|
||||
bool enabled;
|
||||
char ssid[128];
|
||||
char password[128];
|
||||
} wifi_config = {false, "", ""};
|
||||
|
||||
static struct {
|
||||
bool enabled;
|
||||
char host[256];
|
||||
int port;
|
||||
char username[128];
|
||||
char password[128];
|
||||
char topic[128];
|
||||
} mqtt_config = {false, "", 1883, "", "", ""};
|
||||
|
||||
// Estrutura para armazenar as configurações OCPP em memória
|
||||
static struct {
|
||||
char url[256];
|
||||
char chargeBoxId[128];
|
||||
char certificate[256];
|
||||
char privateKey[256];
|
||||
} ocpp_config = {"", "", "", ""};
|
||||
|
||||
// Estrutura para armazenar as configurações de energia
|
||||
static struct {
|
||||
int currentLimit;
|
||||
int powerLimit;
|
||||
int energyLimit;
|
||||
int chargingTimeLimit;
|
||||
int temperatureLimit;
|
||||
} settings_config = {0, 0, 0, 0, 0};
|
||||
|
||||
static struct {
|
||||
char username[128];
|
||||
} users[10] = {{"admin"}, {"user1"}};
|
||||
static int num_users = 2; // Contador de usuários cadastrados
|
||||
|
||||
|
||||
// Set HTTP response content type according to file extension
|
||||
static esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filepath)
|
||||
{
|
||||
const char *type = "text/plain";
|
||||
if (CHECK_FILE_EXTENSION(filepath, ".html")) {
|
||||
type = "text/html";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".js")) {
|
||||
type = "application/javascript";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".css")) {
|
||||
type = "text/css";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".png")) {
|
||||
type = "image/png";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".ico")) {
|
||||
type = "image/x-icon";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".svg")) {
|
||||
type = "text/xml";
|
||||
}
|
||||
return httpd_resp_set_type(req, type);
|
||||
}
|
||||
|
||||
/* Send HTTP response with the contents of the requested file */
|
||||
static esp_err_t rest_common_get_handler(httpd_req_t *req)
|
||||
{
|
||||
char filepath[FILE_PATH_MAX];
|
||||
|
||||
rest_server_context_t *rest_context = (rest_server_context_t *)req->user_ctx;
|
||||
strlcpy(filepath, rest_context->base_path, sizeof(filepath));
|
||||
if (req->uri[strlen(req->uri) - 1] == '/') {
|
||||
strlcat(filepath, "/index.html", sizeof(filepath));
|
||||
} else {
|
||||
strlcat(filepath, req->uri, sizeof(filepath));
|
||||
}
|
||||
int fd = open(filepath, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
ESP_LOGW(REST_TAG, "Failed to open file : %s, redirecting to index", filepath);
|
||||
/* Try to serve index.html for SPA routing */
|
||||
strlcpy(filepath, rest_context->base_path, sizeof(filepath));
|
||||
strlcat(filepath, "/index.html", sizeof(filepath));
|
||||
fd = open(filepath, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
ESP_LOGE(REST_TAG, "Failed to open index file : %s", filepath);
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
set_content_type_from_file(req, filepath);
|
||||
|
||||
char *chunk = rest_context->scratch;
|
||||
ssize_t read_bytes;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
read_bytes = read(fd, chunk, SCRATCH_BUFSIZE);
|
||||
if (read_bytes == -1) {
|
||||
ESP_LOGE(REST_TAG, "Failed to read file : %s", filepath);
|
||||
} else if (read_bytes > 0) {
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, read_bytes) != ESP_OK) {
|
||||
close(fd);
|
||||
ESP_LOGE(REST_TAG, "File sending failed!");
|
||||
/* Abort sending file */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
} while (read_bytes > 0);
|
||||
/* Close file after sending complete */
|
||||
close(fd);
|
||||
ESP_LOGI(REST_TAG, "File sending complete");
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Manipulador para o endpoint GET /api/v1/config/electrical
|
||||
static esp_err_t electrical_config_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON com as configurações de rede elétrica
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
cJSON *monitor = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(monitor, "voltage", "230");
|
||||
cJSON_AddStringToObject(monitor, "current", "10");
|
||||
cJSON_AddStringToObject(monitor, "quality", "1");
|
||||
cJSON_AddItemToObject(config, "monitor", monitor);
|
||||
cJSON_AddBoolToObject(config, "alerts", true);
|
||||
|
||||
// Adicionar mais configurações (security, loadBalancing, solar) no objeto config
|
||||
// ...
|
||||
|
||||
// Enviar a resposta
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
// Liberar memória
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
// Manipulador para o endpoint POST /api/v1/config/electrical
|
||||
static esp_err_t electrical_config_post_handler(httpd_req_t *req)
|
||||
{
|
||||
char buf[512];
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Request body is empty");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0'; // Garantir que a string esteja terminada
|
||||
|
||||
// Parse JSON recebido
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (json == NULL) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Processar os dados recebidos e atualizar as configurações (monitor, alerts, etc.)
|
||||
// Exemplo de configuração:
|
||||
cJSON *monitor = cJSON_GetObjectItem(json, "monitor");
|
||||
if (monitor) {
|
||||
// Atualizar configurações do monitor
|
||||
// ...
|
||||
}
|
||||
|
||||
// Atualizar outras configurações...
|
||||
|
||||
// Responder com sucesso
|
||||
httpd_resp_sendstr(req, "Configuração gravada com sucesso!");
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
// Manipulador para o endpoint /api/v1/config/load-balancing
|
||||
static esp_err_t config_load_balancing_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON de configuração
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
|
||||
// Configuração de load balancing
|
||||
cJSON_AddBoolToObject(config, "enabled", true); // Exemplo: load balancing ativado
|
||||
cJSON_AddNumberToObject(config, "maxChargingCurrent", 32); // Exemplo: corrente máxima de 32A
|
||||
|
||||
// Lista de dispositivos disponíveis
|
||||
cJSON *devices = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(devices, cJSON_CreateString("Device 1")); // Exemplo de dispositivo
|
||||
cJSON_AddItemToArray(devices, cJSON_CreateString("Device 2")); // Outro exemplo de dispositivo
|
||||
cJSON_AddItemToObject(config, "devices", devices);
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
// Manipulador para o endpoint GET /api/v1/ocpp (Status do OCPP)
|
||||
static esp_err_t ocpp_status_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON de status
|
||||
cJSON *status = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(status, "status", "connected"); // Status de exemplo, você pode adaptar conforme sua lógica
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *status_str = cJSON_Print(status);
|
||||
httpd_resp_sendstr(req, status_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)status_str);
|
||||
cJSON_Delete(status);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Manipulador para o endpoint GET /api/v1/config/ocpp (Configuração OCPP)
|
||||
static esp_err_t config_ocpp_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON com as configurações do OCPP
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(config, "url", ocpp_config.url);
|
||||
cJSON_AddStringToObject(config, "chargeBoxId", ocpp_config.chargeBoxId);
|
||||
cJSON_AddStringToObject(config, "certificate", ocpp_config.certificate);
|
||||
cJSON_AddStringToObject(config, "privateKey", ocpp_config.privateKey);
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Manipulador para o endpoint POST /api/v1/config/ocpp (Salvar configuração OCPP)
|
||||
static esp_err_t config_ocpp_post_handler(httpd_req_t *req)
|
||||
{
|
||||
char buf[512]; // Buffer para armazenar a requisição
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0'; // Garantir que a string esteja terminada
|
||||
|
||||
// Parse JSON recebido
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (json == NULL) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Atualizando as configurações OCPP
|
||||
cJSON *url = cJSON_GetObjectItem(json, "url");
|
||||
if (url) strlcpy(ocpp_config.url, url->valuestring, sizeof(ocpp_config.url));
|
||||
|
||||
cJSON *chargeBoxId = cJSON_GetObjectItem(json, "chargeBoxId");
|
||||
if (chargeBoxId) strlcpy(ocpp_config.chargeBoxId, chargeBoxId->valuestring, sizeof(ocpp_config.chargeBoxId));
|
||||
|
||||
cJSON *certificate = cJSON_GetObjectItem(json, "certificate");
|
||||
if (certificate) strlcpy(ocpp_config.certificate, certificate->valuestring, sizeof(ocpp_config.certificate));
|
||||
|
||||
cJSON *privateKey = cJSON_GetObjectItem(json, "privateKey");
|
||||
if (privateKey) strlcpy(ocpp_config.privateKey, privateKey->valuestring, sizeof(ocpp_config.privateKey));
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
// Responder com uma mensagem de sucesso
|
||||
httpd_resp_sendstr(req, "Configuração OCPP atualizada com sucesso");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Manipulador para o endpoint POST /api/v1/config/settings
|
||||
static esp_err_t config_settings_post_handler(httpd_req_t *req)
|
||||
{
|
||||
char buf[512]; // Buffer para armazenar a requisição
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0'; // Garantir que a string esteja terminada
|
||||
|
||||
// Parse JSON recebido
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (json == NULL) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Atualizando as configurações
|
||||
cJSON *currentLimit = cJSON_GetObjectItem(json, "currentLimit");
|
||||
if (currentLimit)
|
||||
evse_set_max_charging_current(currentLimit->valueint);
|
||||
//settings_config.currentLimit = currentLimit->valueint;
|
||||
|
||||
cJSON *powerLimit = cJSON_GetObjectItem(json, "powerLimit");
|
||||
if (powerLimit) settings_config.powerLimit = powerLimit->valueint;
|
||||
|
||||
cJSON *energyLimit = cJSON_GetObjectItem(json, "energyLimit");
|
||||
if (energyLimit) settings_config.energyLimit = energyLimit->valueint;
|
||||
|
||||
cJSON *chargingTimeLimit = cJSON_GetObjectItem(json, "chargingTimeLimit");
|
||||
if (chargingTimeLimit) settings_config.chargingTimeLimit = chargingTimeLimit->valueint;
|
||||
|
||||
cJSON *temperatureLimit = cJSON_GetObjectItem(json, "temperatureLimit");
|
||||
if (temperatureLimit)
|
||||
evse_set_temp_threshold(temperatureLimit->valueint);
|
||||
|
||||
//settings_config.temperatureLimit = temperatureLimit->valueint;
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
// Responder com uma mensagem de sucesso
|
||||
httpd_resp_sendstr(req, "Configurações de energia atualizadas com sucesso");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
// Manipulador para o endpoint GET /api/v1/config/settings
|
||||
static esp_err_t config_settings_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON para enviar as configurações atuais
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
|
||||
|
||||
//cJSON_AddNumberToObject(config, "maxCurrentLimit", evse_get_max_charging_current());
|
||||
cJSON_AddNumberToObject(config, "currentLimit", evse_get_max_charging_current());
|
||||
cJSON_AddNumberToObject(config, "powerLimit", settings_config.powerLimit);
|
||||
cJSON_AddNumberToObject(config, "energyLimit", settings_config.energyLimit);
|
||||
cJSON_AddNumberToObject(config, "chargingTimeLimit", settings_config.chargingTimeLimit);
|
||||
cJSON_AddNumberToObject(config, "temperatureLimit", evse_get_temp_threshold());
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
// Manipulador para o endpoint GET /api/v1/dashboard
|
||||
static esp_err_t dashboard_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON com os dados do Dashboard
|
||||
cJSON *dashboard = cJSON_CreateObject();
|
||||
|
||||
// Status do sistema
|
||||
cJSON_AddStringToObject(dashboard, "status", "Ativo");
|
||||
|
||||
// Carregadores (exemplo)
|
||||
cJSON *chargers = cJSON_CreateArray();
|
||||
cJSON *charger1 = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(charger1, "id", 1);
|
||||
cJSON_AddStringToObject(charger1, "status", "Ativo");
|
||||
cJSON_AddNumberToObject(charger1, "current", 12);
|
||||
cJSON_AddNumberToObject(charger1, "power", 2200);
|
||||
cJSON_AddItemToArray(chargers, charger1);
|
||||
|
||||
cJSON_AddItemToObject(dashboard, "chargers", chargers);
|
||||
|
||||
// Consumo de energia
|
||||
cJSON_AddNumberToObject(dashboard, "energyConsumed", 50.3);
|
||||
|
||||
// Tempo de carregamento
|
||||
cJSON_AddNumberToObject(dashboard, "chargingTime", 120);
|
||||
|
||||
// Alertas
|
||||
cJSON *alerts = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(alerts, cJSON_CreateString("Aviso: Carregador 1 está com erro."));
|
||||
cJSON_AddItemToObject(dashboard, "alerts", alerts);
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *dashboard_str = cJSON_Print(dashboard);
|
||||
httpd_resp_sendstr(req, dashboard_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)dashboard_str);
|
||||
cJSON_Delete(dashboard);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t config_wifi_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON com as configurações de Wi-Fi
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(config, "enabled", wifi_config.enabled);
|
||||
cJSON_AddStringToObject(config, "ssid", wifi_config.ssid);
|
||||
cJSON_AddStringToObject(config, "password", wifi_config.password);
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Manipulador para o endpoint POST /api/v1/config/wifi */
|
||||
static esp_err_t config_wifi_post_handler(httpd_req_t *req)
|
||||
{
|
||||
char buf[512]; // Buffer para armazenar a requisição
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0'; // Garantir que a string esteja terminada
|
||||
|
||||
// Parse JSON recebido
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (json == NULL) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Atualizando as configurações Wi-Fi
|
||||
cJSON *enabled = cJSON_GetObjectItem(json, "enabled");
|
||||
if (enabled) wifi_config.enabled = enabled->valueint;
|
||||
|
||||
cJSON *ssid = cJSON_GetObjectItem(json, "ssid");
|
||||
if (ssid) strlcpy(wifi_config.ssid, ssid->valuestring, sizeof(wifi_config.ssid));
|
||||
|
||||
cJSON *password = cJSON_GetObjectItem(json, "password");
|
||||
if (password) strlcpy(wifi_config.password, password->valuestring, sizeof(wifi_config.password));
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
// Responder com uma mensagem de sucesso
|
||||
httpd_resp_sendstr(req, "Configuração Wi-Fi atualizada com sucesso");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Manipulador para o endpoint GET /api/v1/config/mqtt */
|
||||
static esp_err_t config_mqtt_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON com as configurações de MQTT
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(config, "enabled", mqtt_config.enabled);
|
||||
cJSON_AddStringToObject(config, "host", mqtt_config.host);
|
||||
cJSON_AddNumberToObject(config, "port", mqtt_config.port);
|
||||
cJSON_AddStringToObject(config, "username", mqtt_config.username);
|
||||
cJSON_AddStringToObject(config, "password", mqtt_config.password);
|
||||
cJSON_AddStringToObject(config, "topic", mqtt_config.topic);
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Manipulador para o endpoint POST /api/v1/config/mqtt */
|
||||
static esp_err_t config_mqtt_post_handler(httpd_req_t *req)
|
||||
{
|
||||
char buf[512]; // Buffer para armazenar a requisição
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0'; // Garantir que a string esteja terminada
|
||||
|
||||
// Parse JSON recebido
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (json == NULL) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Atualizando as configurações MQTT
|
||||
cJSON *enabled = cJSON_GetObjectItem(json, "enabled");
|
||||
if (enabled) mqtt_config.enabled = enabled->valueint;
|
||||
|
||||
cJSON *host = cJSON_GetObjectItem(json, "host");
|
||||
if (host) strlcpy(mqtt_config.host, host->valuestring, sizeof(mqtt_config.host));
|
||||
|
||||
cJSON *port = cJSON_GetObjectItem(json, "port");
|
||||
if (port) mqtt_config.port = port->valueint;
|
||||
|
||||
cJSON *username = cJSON_GetObjectItem(json, "username");
|
||||
if (username) strlcpy(mqtt_config.username, username->valuestring, sizeof(mqtt_config.username));
|
||||
|
||||
cJSON *password = cJSON_GetObjectItem(json, "password");
|
||||
if (password) strlcpy(mqtt_config.password, password->valuestring, sizeof(mqtt_config.password));
|
||||
|
||||
cJSON *topic = cJSON_GetObjectItem(json, "topic");
|
||||
if (topic) strlcpy(mqtt_config.topic, topic->valuestring, sizeof(mqtt_config.topic));
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
// Responder com uma mensagem de sucesso
|
||||
httpd_resp_sendstr(req, "Configuração MQTT atualizada com sucesso");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// GET /api/v1/config/auth-methods
|
||||
static esp_err_t config_auth_methods_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(config, "RFID", auth_is_enabled());
|
||||
cJSON_AddBoolToObject(config, "App", false);
|
||||
cJSON_AddBoolToObject(config, "Password", false);
|
||||
|
||||
char *config_str = cJSON_PrintUnformatted(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
free(config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// POST /api/v1/config/auth-methods
|
||||
static esp_err_t config_auth_methods_post_handler(httpd_req_t *req)
|
||||
{
|
||||
char buf[512];
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (!json) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
cJSON *RFID = cJSON_GetObjectItem(json, "RFID");
|
||||
if (cJSON_IsBool(RFID)) {
|
||||
auth_set_enabled(cJSON_IsTrue(RFID));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
cJSON *App = cJSON_GetObjectItem(json, "App");
|
||||
if (cJSON_IsBool(App)) {
|
||||
auth_methods.App = cJSON_IsTrue(App);
|
||||
}
|
||||
|
||||
cJSON *Password = cJSON_GetObjectItem(json, "Password");
|
||||
if (cJSON_IsBool(Password)) {
|
||||
auth_methods.Password = cJSON_IsTrue(Password);
|
||||
}*/
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
httpd_resp_sendstr(req, "Configurações de autenticação atualizadas com sucesso");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Manipulador para o endpoint GET /api/v1/config/users
|
||||
static esp_err_t config_users_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Criar objeto JSON com a lista de usuários
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
cJSON *users_list = cJSON_CreateArray();
|
||||
|
||||
for (int i = 0; i < num_users; i++) {
|
||||
cJSON *user = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(user, "username", users[i].username);
|
||||
cJSON_AddItemToArray(users_list, user);
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(config, "users", users_list);
|
||||
|
||||
// Convertendo para string e enviando a resposta
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
// Liberando a memória
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
// Manipulador para o endpoint POST /api/v1/config/users
|
||||
static esp_err_t config_users_post_handler(httpd_req_t *req)
|
||||
{
|
||||
char buf[128]; // Buffer para armazenar o nome do novo usuário
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0'; // Garantir que a string esteja terminada
|
||||
|
||||
// Adicionar o novo usuário
|
||||
if (num_users < 10) {
|
||||
strlcpy(users[num_users].username, buf, sizeof(users[num_users].username));
|
||||
num_users++;
|
||||
httpd_resp_sendstr(req, "Usuário adicionado com sucesso");
|
||||
} else {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Máximo de usuários atingido");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
// Manipulador para o endpoint DELETE /api/v1/config/users/{username}
|
||||
static esp_err_t config_users_delete_handler(httpd_req_t *req)
|
||||
{
|
||||
char username[128]; // Nome do usuário a ser removido
|
||||
if (httpd_req_get_url_query_str(req, username, sizeof(username)) == ESP_OK) {
|
||||
// Verificar e remover o usuário
|
||||
for (int i = 0; i < num_users; i++) {
|
||||
if (strcmp(users[i].username, username) == 0) {
|
||||
// Remover o usuário
|
||||
for (int j = i; j < num_users - 1; j++) {
|
||||
users[j] = users[j + 1];
|
||||
}
|
||||
num_users--;
|
||||
httpd_resp_sendstr(req, "Usuário removido com sucesso");
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Usuário não encontrado");
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t rest_init(const char *base_path)
|
||||
{
|
||||
|
||||
/*
|
||||
REST_CHECK(base_path, "wrong base path", err);
|
||||
rest_server_context_t *rest_context = calloc(1, sizeof(rest_server_context_t));
|
||||
REST_CHECK(rest_context, "No memory for rest context", err_start);
|
||||
strlcpy(rest_context->base_path, base_path, sizeof(rest_context->base_path));
|
||||
|
||||
httpd_handle_t server = NULL;
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.max_uri_handlers = 30; // Ajuste conforme necessário
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
|
||||
ESP_LOGI(REST_TAG, "Starting HTTP Server");
|
||||
REST_CHECK(httpd_start(&server, &config) == ESP_OK, "Start server failed", err_start);
|
||||
|
||||
// Registrar manipuladores de URI para as configurações
|
||||
httpd_uri_t config_load_balancing_get_uri = {
|
||||
.uri = "/api/v1/config/load-balancing",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_load_balancing_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_load_balancing_get_uri);
|
||||
|
||||
// URI handler for fetching OCPP status
|
||||
httpd_uri_t ocpp_status_get_uri = {
|
||||
.uri = "/api/v1/ocpp",
|
||||
.method = HTTP_GET,
|
||||
.handler = ocpp_status_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &ocpp_status_get_uri);
|
||||
|
||||
// URI handler for fetching OCPP config
|
||||
httpd_uri_t config_ocpp_get_uri = {
|
||||
.uri = "/api/v1/config/ocpp",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_ocpp_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_ocpp_get_uri);
|
||||
|
||||
// URI handler for posting OCPP config
|
||||
httpd_uri_t config_ocpp_post_uri = {
|
||||
.uri = "/api/v1/config/ocpp",
|
||||
.method = HTTP_POST,
|
||||
.handler = config_ocpp_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_ocpp_post_uri);
|
||||
|
||||
// Manipulador para o endpoint POST /api/v1/config/settings
|
||||
httpd_uri_t config_settings_post_uri = {
|
||||
.uri = "/api/v1/config/settings",
|
||||
.method = HTTP_POST,
|
||||
.handler = config_settings_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_settings_post_uri);
|
||||
|
||||
// Manipulador para o endpoint GET /api/v1/config/settings
|
||||
httpd_uri_t config_settings_get_uri = {
|
||||
.uri = "/api/v1/config/settings",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_settings_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_settings_get_uri);
|
||||
|
||||
// Manipulador para o endpoint GET /api/v1/dashboard
|
||||
httpd_uri_t dashboard_get_uri = {
|
||||
.uri = "/api/v1/dashboard",
|
||||
.method = HTTP_GET,
|
||||
.handler = dashboard_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &dashboard_get_uri);
|
||||
|
||||
// Register URI Handlers for electrical configuration
|
||||
httpd_uri_t electrical_config_get_uri = {
|
||||
.uri = "/api/v1/config/electrical",
|
||||
.method = HTTP_GET,
|
||||
.handler = electrical_config_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &electrical_config_get_uri);
|
||||
|
||||
httpd_uri_t electrical_config_post_uri = {
|
||||
.uri = "/api/v1/config/electrical",
|
||||
.method = HTTP_POST,
|
||||
.handler = electrical_config_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &electrical_config_post_uri);
|
||||
|
||||
// URI handler for getting Wi-Fi config
|
||||
httpd_uri_t config_wifi_get_uri = {
|
||||
.uri = "/api/v1/config/wifi",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_wifi_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_wifi_get_uri);
|
||||
|
||||
// URI handler for posting Wi-Fi config
|
||||
httpd_uri_t config_wifi_post_uri = {
|
||||
.uri = "/api/v1/config/wifi",
|
||||
.method = HTTP_POST,
|
||||
.handler = config_wifi_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_wifi_post_uri);
|
||||
|
||||
// URI handler for getting MQTT config
|
||||
httpd_uri_t config_mqtt_get_uri = {
|
||||
.uri = "/api/v1/config/mqtt",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_mqtt_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_mqtt_get_uri);
|
||||
|
||||
// URI handler for posting MQTT config
|
||||
httpd_uri_t config_mqtt_post_uri = {
|
||||
.uri = "/api/v1/config/mqtt",
|
||||
.method = HTTP_POST,
|
||||
.handler = config_mqtt_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_mqtt_post_uri);
|
||||
|
||||
// Registrar manipuladores para as configurações de autenticação
|
||||
httpd_uri_t config_auth_methods_get_uri = {
|
||||
.uri = "/api/v1/config/auth-methods",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_auth_methods_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_auth_methods_get_uri);
|
||||
|
||||
httpd_uri_t config_auth_methods_post_uri = {
|
||||
.uri = "/api/v1/config/auth-methods",
|
||||
.method = HTTP_POST,
|
||||
.handler = config_auth_methods_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_auth_methods_post_uri);
|
||||
|
||||
// Registrar manipuladores para as configurações de usuários
|
||||
httpd_uri_t config_users_get_uri = {
|
||||
.uri = "/api/v1/config/users",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_users_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_users_get_uri);
|
||||
|
||||
httpd_uri_t config_users_post_uri = {
|
||||
.uri = "/api/v1/config/users",
|
||||
.method = HTTP_POST,
|
||||
.handler = config_users_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_users_post_uri);
|
||||
|
||||
httpd_uri_t config_users_delete_uri = {
|
||||
.uri = "/api/v1/config/users",
|
||||
.method = HTTP_DELETE,
|
||||
.handler = config_users_delete_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_users_delete_uri);
|
||||
|
||||
// URI handler for getting web server files
|
||||
httpd_uri_t common_get_uri = {
|
||||
.uri = "/",
|
||||
.method = HTTP_GET,
|
||||
.handler = rest_common_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &common_get_uri);
|
||||
*/
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -3,6 +3,9 @@
|
||||
#include "cJSON.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_config.h"
|
||||
#include "evse_limits.h"
|
||||
|
||||
|
||||
static const char *TAG = "dashboard_api";
|
||||
|
||||
@@ -40,10 +43,10 @@ static esp_err_t dashboard_get_handler(httpd_req_t *req) {
|
||||
if (evse_is_limit_reached()) {
|
||||
cJSON_AddItemToArray(alerts, cJSON_CreateString("Limite de consumo atingido."));
|
||||
}
|
||||
if (!evse_is_available()) {
|
||||
if (!evse_config_is_available()) {
|
||||
cJSON_AddItemToArray(alerts, cJSON_CreateString("Estação indisponível."));
|
||||
}
|
||||
if (!evse_is_enabled()) {
|
||||
if (!evse_config_is_enabled()) {
|
||||
cJSON_AddItemToArray(alerts, cJSON_CreateString("EVSE desativado."));
|
||||
}
|
||||
cJSON_AddItemToObject(dashboard, "alerts", alerts);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// =========================
|
||||
#include "evse_settings_api.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_config.h"
|
||||
#include "esp_log.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ static esp_err_t meters_config_post_handler(httpd_req_t *req) {
|
||||
|
||||
// Registrando os manipuladores de URI para os contadores
|
||||
void register_meters_settings_handlers(httpd_handle_t server, void *ctx) {
|
||||
ESP_LOGI(TAG, "Registering URI handlers for meters settings");
|
||||
ESP_LOGD(TAG, "Registering URI handlers for meters settings");
|
||||
|
||||
// URI para o método GET
|
||||
httpd_uri_t meters_get_uri = {
|
||||
@@ -96,7 +96,7 @@ void register_meters_settings_handlers(httpd_handle_t server, void *ctx) {
|
||||
.handler = meters_config_get_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
ESP_LOGI(TAG, "Registering GET handler for /api/v1/config/meters");
|
||||
ESP_LOGD(TAG, "Registering GET handler for /api/v1/config/meters");
|
||||
httpd_register_uri_handler(server, &meters_get_uri);
|
||||
|
||||
// URI para o método POST
|
||||
@@ -106,6 +106,6 @@ void register_meters_settings_handlers(httpd_handle_t server, void *ctx) {
|
||||
.handler = meters_config_post_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
ESP_LOGI(TAG, "Registering POST handler for /api/v1/config/meters");
|
||||
ESP_LOGD(TAG, "Registering POST handler for /api/v1/config/meters");
|
||||
httpd_register_uri_handler(server, &meters_post_uri);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
// #include "inc/version_autogen.h"
|
||||
#include "sync_master.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_state.h"
|
||||
#include "evse_config.h"
|
||||
|
||||
#define VERSION_STRING "2.2"
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#include "sync_slave.h"
|
||||
#include "loadbalancer.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_state.h"
|
||||
#include "evse_config.h"
|
||||
|
||||
#define VERSION_STRING "2.2"
|
||||
|
||||
|
||||
10
components/spi_bus_manager/CMakeLists.txt
Executable file
10
components/spi_bus_manager/CMakeLists.txt
Executable file
@@ -0,0 +1,10 @@
|
||||
set(srcs
|
||||
"src/spi_bus_manager.c"
|
||||
)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${srcs}
|
||||
INCLUDE_DIRS include
|
||||
PRIV_REQUIRES driver esp_timer
|
||||
REQUIRES config
|
||||
)
|
||||
20
components/spi_bus_manager/include/spi_bus_manager.h
Executable file
20
components/spi_bus_manager/include/spi_bus_manager.h
Executable file
@@ -0,0 +1,20 @@
|
||||
#ifndef SPI_BUS_MANAGER_H_
|
||||
#define SPI_BUS_MANAGER_H_
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
#include "esp_err.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
esp_err_t spi_bus_manager_init(void);
|
||||
spi_host_device_t spi_bus_manager_get_host(void);
|
||||
bool spi_bus_manager_is_initialized(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SPI_BUS_MANAGER_H_
|
||||
48
components/spi_bus_manager/src/spi_bus_manager.c
Executable file
48
components/spi_bus_manager/src/spi_bus_manager.c
Executable file
@@ -0,0 +1,48 @@
|
||||
#include "spi_bus_manager.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#define TAG "spi_bus_mgr"
|
||||
|
||||
#define SHARED_SPI_HOST SPI2_HOST
|
||||
|
||||
// Pinos padrão (podem ser futuramente configuráveis)
|
||||
#define PIN_NUM_MOSI 23
|
||||
#define PIN_NUM_MISO 19
|
||||
#define PIN_NUM_CLK 18
|
||||
|
||||
static bool initialized = false;
|
||||
|
||||
esp_err_t spi_bus_manager_init(void) {
|
||||
if (initialized) {
|
||||
ESP_LOGW(TAG, "SPI bus already initialized on host %d", SHARED_SPI_HOST);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
spi_bus_config_t buscfg = {
|
||||
.mosi_io_num = PIN_NUM_MOSI,
|
||||
.miso_io_num = PIN_NUM_MISO,
|
||||
.sclk_io_num = PIN_NUM_CLK,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = 64, // Ajustável conforme necessidade
|
||||
};
|
||||
|
||||
esp_err_t ret = spi_bus_initialize(SHARED_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize SPI bus: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
ESP_LOGI(TAG, "SPI bus initialized on host %d", SHARED_SPI_HOST);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
spi_host_device_t spi_bus_manager_get_host(void) {
|
||||
return SHARED_SPI_HOST;
|
||||
}
|
||||
|
||||
bool spi_bus_manager_is_initialized(void) {
|
||||
return initialized;
|
||||
}
|
||||
10
main/main.c
10
main/main.c
@@ -23,7 +23,7 @@
|
||||
#include "peripherals.h"
|
||||
#include "protocols.h"
|
||||
#include "evse_manager.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_core.h"
|
||||
#include "auth.h"
|
||||
#include "loadbalancer.h"
|
||||
#include "meter_manager.h"
|
||||
@@ -118,12 +118,13 @@ static void user_input_task_func(void *param) {
|
||||
if (notification & PRESS_BIT) {
|
||||
press_tick = xTaskGetTickCount();
|
||||
pressed = true;
|
||||
ESP_LOGI(TAG, "Botão pressionado");
|
||||
ESP_LOGI(TAG, "Pressed Button");
|
||||
handle_button_press();
|
||||
}
|
||||
|
||||
if (notification & RELEASED_BIT && pressed) {
|
||||
pressed = false;
|
||||
ESP_LOGI(TAG, "Botão liberado");
|
||||
ESP_LOGI(TAG, "Reladead Buttton");
|
||||
handle_button_press();
|
||||
}
|
||||
}
|
||||
@@ -175,7 +176,8 @@ static void init_modules(void) {
|
||||
loadbalancer_init();
|
||||
meter_manager_grid_init();
|
||||
meter_manager_grid_start();
|
||||
//meter_manager_evse_init();
|
||||
meter_manager_evse_init();
|
||||
meter_manager_evse_start();
|
||||
|
||||
// Outros módulos (descomente conforme necessário)
|
||||
// meter_init();
|
||||
|
||||
3679
projeto_parte1.c
Executable file → Normal file
3679
projeto_parte1.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,46 +0,0 @@
|
||||
|
||||
|
||||
// === Início de: components/peripherals/include/temp_sensor.h ===
|
||||
#ifndef TEMP_SENSOR_H_
|
||||
#define TEMP_SENSOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize DS18S20 temperature sensor bus
|
||||
*
|
||||
*/
|
||||
void temp_sensor_init(void);
|
||||
|
||||
/**
|
||||
* @brief Get found sensor count
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t temp_sensor_get_count(void);
|
||||
|
||||
/**
|
||||
* @brief Return lowest temperature after temp_sensor_measure
|
||||
*
|
||||
* @return int16_t
|
||||
*/
|
||||
int16_t temp_sensor_get_low(void);
|
||||
|
||||
/**
|
||||
* @brief Return highest temperature after temp_sensor_measure
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int temp_sensor_get_high(void);
|
||||
|
||||
/**
|
||||
* @brief Return temperature sensor error
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool temp_sensor_is_error(void);
|
||||
|
||||
#endif /* TEMP_SENSOR_H_ */
|
||||
|
||||
// === Fim de: components/peripherals/include/temp_sensor.h ===
|
||||
3678
projeto_parte2.c
Executable file → Normal file
3678
projeto_parte2.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
1652
projeto_parte3.c
Executable file → Normal file
1652
projeto_parte3.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
896
projeto_parte4.c
896
projeto_parte4.c
@@ -1,896 +0,0 @@
|
||||
|
||||
|
||||
// === Início de: components/auth/include/auth.h ===
|
||||
#ifndef AUTH_H
|
||||
#define AUTH_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Tamanho máximo de uma tag RFID (incluindo '\0')
|
||||
#define AUTH_TAG_MAX_LEN 20
|
||||
|
||||
/// Estrutura de evento emitida após leitura de uma tag
|
||||
typedef struct {
|
||||
char tag[AUTH_TAG_MAX_LEN]; ///< Tag lida
|
||||
bool authorized; ///< true se a tag for reconhecida como válida
|
||||
} auth_event_t;
|
||||
|
||||
/**
|
||||
* @brief Inicializa o sistema de autenticação.
|
||||
*
|
||||
* - Carrega a configuração (enabled) da NVS
|
||||
* - Inicia o leitor Wiegand
|
||||
* - Emite evento AUTH_EVENT_INIT com estado atual
|
||||
*/
|
||||
void auth_init(void);
|
||||
|
||||
/**
|
||||
* @brief Ativa ou desativa o uso de autenticação via RFID.
|
||||
*
|
||||
* Esta configuração é persistida em NVS. Se desativado, o sistema
|
||||
* considerará todas as autorizações como aceitas.
|
||||
*
|
||||
* @param value true para ativar, false para desativar
|
||||
*/
|
||||
void auth_set_enabled(bool value);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o sistema de autenticação está habilitado.
|
||||
*/
|
||||
bool auth_is_enabled(void);
|
||||
|
||||
/**
|
||||
* @brief Adiciona uma nova tag RFID à lista de autorizadas.
|
||||
*
|
||||
* @param tag String da tag (máx AUTH_TAG_MAX_LEN-1)
|
||||
* @return true se a tag foi adicionada, false se já existia ou inválida
|
||||
*/
|
||||
bool auth_add_tag(const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Remove uma tag previamente cadastrada.
|
||||
*
|
||||
* @param tag String da tag
|
||||
* @return true se foi removida, false se não encontrada
|
||||
*/
|
||||
bool auth_remove_tag(const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Verifica se uma tag já está registrada como válida.
|
||||
*/
|
||||
bool auth_tag_exists(const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Lista todas as tags válidas atualmente registradas (via logs).
|
||||
*/
|
||||
void auth_list_tags(void);
|
||||
|
||||
/**
|
||||
* @brief Processa uma tag RFID lida (chamada normalmente pelo leitor).
|
||||
*
|
||||
* - Verifica validade
|
||||
* - Emite evento AUTH_EVENT_TAG_PROCESSED
|
||||
* - Inicia timer de expiração se autorizada
|
||||
*/
|
||||
void auth_process_tag(const char *tag);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AUTH_H
|
||||
|
||||
// === Fim de: components/auth/include/auth.h ===
|
||||
|
||||
|
||||
// === Início de: components/auth/include/auth_events.h ===
|
||||
#pragma once
|
||||
#include "esp_event.h"
|
||||
|
||||
#define AUTH_EVENT_TAG_MAX_LEN 32
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(AUTH_EVENTS);
|
||||
|
||||
typedef enum {
|
||||
AUTH_EVENT_TAG_PROCESSED,
|
||||
AUTH_EVENT_ENABLED_CHANGED,
|
||||
AUTH_EVENT_INIT,
|
||||
} auth_event_id_t;
|
||||
|
||||
typedef struct {
|
||||
char tag[AUTH_EVENT_TAG_MAX_LEN];
|
||||
bool authorized;
|
||||
} auth_tag_event_data_t;
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
} auth_enabled_event_data_t;
|
||||
|
||||
// === Fim de: components/auth/include/auth_events.h ===
|
||||
|
||||
|
||||
// === Início de: components/auth/include/wiegand.h ===
|
||||
/*
|
||||
* Copyright (c) 2021 Ruslan V. Uss <unclerus@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of itscontributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file wiegand.h
|
||||
* @defgroup wiegand wiegand
|
||||
* @{
|
||||
*
|
||||
* ESP-IDF Wiegand protocol receiver
|
||||
*
|
||||
* Copyright (c) 2021 Ruslan V. Uss <unclerus@gmail.com>
|
||||
*
|
||||
* BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
#ifndef __WIEGAND_H__
|
||||
#define __WIEGAND_H__
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_timer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct wiegand_reader wiegand_reader_t;
|
||||
|
||||
typedef void (*wiegand_callback_t)(wiegand_reader_t *reader);
|
||||
|
||||
/**
|
||||
* Bit and byte order of data
|
||||
*/
|
||||
typedef enum {
|
||||
WIEGAND_MSB_FIRST = 0,
|
||||
WIEGAND_LSB_FIRST
|
||||
} wiegand_order_t;
|
||||
|
||||
/**
|
||||
* Wiegand reader descriptor
|
||||
*/
|
||||
struct wiegand_reader
|
||||
{
|
||||
gpio_num_t gpio_d0, gpio_d1;
|
||||
wiegand_callback_t callback;
|
||||
wiegand_order_t bit_order;
|
||||
wiegand_order_t byte_order;
|
||||
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
size_t bits;
|
||||
esp_timer_handle_t timer;
|
||||
bool start_parity;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create and initialize reader instance.
|
||||
*
|
||||
* @param reader Reader descriptor
|
||||
* @param gpio_d0 GPIO pin for D0
|
||||
* @param gpio_d1 GPIO pin for D0
|
||||
* @param internal_pullups Enable internal pull-up resistors for D0 and D1 GPIO
|
||||
* @param buf_size Reader buffer size in bytes, must be large enough to
|
||||
* contain entire Wiegand key
|
||||
* @param callback Callback function for processing received codes
|
||||
* @param bit_order Bit order of data
|
||||
* @param byte_order Byte order of data
|
||||
* @return `ESP_OK` on success
|
||||
*/
|
||||
esp_err_t wiegand_reader_init(wiegand_reader_t *reader, gpio_num_t gpio_d0, gpio_num_t gpio_d1,
|
||||
bool internal_pullups, size_t buf_size, wiegand_callback_t callback, wiegand_order_t bit_order,
|
||||
wiegand_order_t byte_order);
|
||||
|
||||
/**
|
||||
* @brief Disable reader
|
||||
*
|
||||
* While reader is disabled, it will not receive new data
|
||||
*
|
||||
* @param reader Reader descriptor
|
||||
* @return `ESP_OK` on success
|
||||
*/
|
||||
esp_err_t wiegand_reader_disable(wiegand_reader_t *reader);
|
||||
|
||||
/**
|
||||
* @brief Enable reader
|
||||
*
|
||||
* @param reader Reader descriptor
|
||||
* @return `ESP_OK` on success
|
||||
*/
|
||||
esp_err_t wiegand_reader_enable(wiegand_reader_t *reader);
|
||||
|
||||
/**
|
||||
* @brief Delete reader instance.
|
||||
*
|
||||
* @param reader Reader descriptor
|
||||
* @return `ESP_OK` on success
|
||||
*/
|
||||
esp_err_t wiegand_reader_done(wiegand_reader_t *reader);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
||||
|
||||
#endif /* __WIEGAND_H__ */
|
||||
|
||||
// === Fim de: components/auth/include/wiegand.h ===
|
||||
|
||||
|
||||
// === Início de: components/auth/include/wiegand_reader.h ===
|
||||
#ifndef WIEGAND_READER_H
|
||||
#define WIEGAND_READER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void initWiegand(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // WIEGAND_READER_H
|
||||
|
||||
// === Fim de: components/auth/include/wiegand_reader.h ===
|
||||
|
||||
|
||||
// === Início de: components/rest_api/src/ocpp_api.c ===
|
||||
// =========================
|
||||
// ocpp_api.c
|
||||
// =========================
|
||||
#include "ocpp_api.h"
|
||||
#include "esp_log.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *TAG = "ocpp_api";
|
||||
|
||||
static struct {
|
||||
char url[256];
|
||||
char chargeBoxId[128];
|
||||
char certificate[256];
|
||||
char privateKey[256];
|
||||
} ocpp_config = {"", "", "", ""};
|
||||
|
||||
static esp_err_t ocpp_get_status_handler(httpd_req_t *req) {
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
cJSON *status = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(status, "status", "connected");
|
||||
char *str = cJSON_Print(status);
|
||||
httpd_resp_sendstr(req, str);
|
||||
free(str);
|
||||
cJSON_Delete(status);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t ocpp_get_config_handler(httpd_req_t *req) {
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
cJSON *json = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(json, "url", ocpp_config.url);
|
||||
cJSON_AddStringToObject(json, "chargeBoxId", ocpp_config.chargeBoxId);
|
||||
cJSON_AddStringToObject(json, "certificate", ocpp_config.certificate);
|
||||
cJSON_AddStringToObject(json, "privateKey", ocpp_config.privateKey);
|
||||
char *str = cJSON_Print(json);
|
||||
httpd_resp_sendstr(req, str);
|
||||
free(str);
|
||||
cJSON_Delete(json);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t ocpp_post_config_handler(httpd_req_t *req) {
|
||||
char buf[512];
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Empty body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (!json) {
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
cJSON *url = cJSON_GetObjectItem(json, "url");
|
||||
if (url) strlcpy(ocpp_config.url, url->valuestring, sizeof(ocpp_config.url));
|
||||
cJSON *id = cJSON_GetObjectItem(json, "chargeBoxId");
|
||||
if (id) strlcpy(ocpp_config.chargeBoxId, id->valuestring, sizeof(ocpp_config.chargeBoxId));
|
||||
cJSON *cert = cJSON_GetObjectItem(json, "certificate");
|
||||
if (cert) strlcpy(ocpp_config.certificate, cert->valuestring, sizeof(ocpp_config.certificate));
|
||||
cJSON *key = cJSON_GetObjectItem(json, "privateKey");
|
||||
if (key) strlcpy(ocpp_config.privateKey, key->valuestring, sizeof(ocpp_config.privateKey));
|
||||
cJSON_Delete(json);
|
||||
httpd_resp_sendstr(req, "OCPP config atualizada com sucesso");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void register_ocpp_handlers(httpd_handle_t server, void *ctx) {
|
||||
httpd_uri_t status_uri = {
|
||||
.uri = "/api/v1/ocpp",
|
||||
.method = HTTP_GET,
|
||||
.handler = ocpp_get_status_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &status_uri);
|
||||
|
||||
httpd_uri_t get_uri = {
|
||||
.uri = "/api/v1/config/ocpp",
|
||||
.method = HTTP_GET,
|
||||
.handler = ocpp_get_config_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &get_uri);
|
||||
|
||||
httpd_uri_t post_uri = {
|
||||
.uri = "/api/v1/config/ocpp",
|
||||
.method = HTTP_POST,
|
||||
.handler = ocpp_post_config_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &post_uri);
|
||||
}
|
||||
|
||||
// === Fim de: components/rest_api/src/ocpp_api.c ===
|
||||
|
||||
|
||||
// === Início de: components/rest_api/src/static_file_api.c ===
|
||||
#include "static_file_api.h"
|
||||
#include "esp_log.h"
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "esp_vfs.h"
|
||||
|
||||
static const char *TAG = "static_file_api";
|
||||
|
||||
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128)
|
||||
#define SCRATCH_BUFSIZE (10240)
|
||||
|
||||
typedef struct rest_server_context {
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
} rest_server_context_t;
|
||||
|
||||
#define CHECK_FILE_EXTENSION(filename, ext) \
|
||||
(strcasecmp(&filename[strlen(filename) - strlen(ext)], ext) == 0)
|
||||
|
||||
static esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filepath) {
|
||||
const char *type = "text/plain";
|
||||
if (CHECK_FILE_EXTENSION(filepath, ".html")) type = "text/html";
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".js")) type = "application/javascript";
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".css")) type = "text/css";
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".png")) type = "image/png";
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".ico")) type = "image/x-icon";
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".svg")) type = "image/svg+xml";
|
||||
return httpd_resp_set_type(req, type);
|
||||
}
|
||||
|
||||
static esp_err_t static_get_handler(httpd_req_t *req) {
|
||||
char filepath[FILE_PATH_MAX];
|
||||
rest_server_context_t *ctx = (rest_server_context_t *) req->user_ctx;
|
||||
|
||||
strlcpy(filepath, ctx->base_path, sizeof(filepath));
|
||||
if (req->uri[strlen(req->uri) - 1] == '/') {
|
||||
strlcat(filepath, "/index.html", sizeof(filepath));
|
||||
} else {
|
||||
strlcat(filepath, req->uri, sizeof(filepath));
|
||||
}
|
||||
|
||||
int fd = open(filepath, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
// fallback para /index.html (SPA)
|
||||
ESP_LOGW(TAG, "Arquivo não encontrado: %s. Tentando index.html", filepath);
|
||||
strlcpy(filepath, ctx->base_path, sizeof(filepath));
|
||||
strlcat(filepath, "/index.html", sizeof(filepath));
|
||||
fd = open(filepath, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Arquivo não encontrado");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
set_content_type_from_file(req, filepath);
|
||||
|
||||
char *chunk = ctx->scratch;
|
||||
ssize_t read_bytes;
|
||||
do {
|
||||
read_bytes = read(fd, chunk, SCRATCH_BUFSIZE);
|
||||
if (read_bytes == -1) {
|
||||
ESP_LOGE(TAG, "Erro lendo arquivo: %s", filepath);
|
||||
close(fd);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Erro ao ler arquivo");
|
||||
return ESP_FAIL;
|
||||
} else if (read_bytes > 0) {
|
||||
if (httpd_resp_send_chunk(req, chunk, read_bytes) != ESP_OK) {
|
||||
close(fd);
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Erro ao enviar arquivo");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
} while (read_bytes > 0);
|
||||
|
||||
close(fd);
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void register_static_file_handlers(httpd_handle_t server, void *ctx) {
|
||||
httpd_uri_t uri = {
|
||||
.uri = "/*",
|
||||
.method = HTTP_GET,
|
||||
.handler = static_get_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &uri);
|
||||
}
|
||||
|
||||
// === Fim de: components/rest_api/src/static_file_api.c ===
|
||||
|
||||
|
||||
// === Início de: components/rest_api/src/meters_settings_api.c ===
|
||||
#include "meters_settings_api.h"
|
||||
#include "meter_manager.h" // Atualizado para usar o novo manager
|
||||
#include "esp_log.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *TAG = "meters_settings_api";
|
||||
|
||||
// Função para recuperar as configurações dos contadores
|
||||
static esp_err_t meters_config_get_handler(httpd_req_t *req) {
|
||||
ESP_LOGI(TAG, "Received GET request for /api/v1/config/meters");
|
||||
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
|
||||
// Recuperando as configurações dos contadores
|
||||
meter_type_t gridmeterType = meter_manager_grid_get_model();
|
||||
meter_type_t evsemeterType = meter_manager_evse_get_model();
|
||||
|
||||
ESP_LOGI(TAG, "Grid meter type: %s", meter_type_to_str(gridmeterType));
|
||||
ESP_LOGI(TAG, "EVSE meter type: %s", meter_type_to_str(evsemeterType));
|
||||
|
||||
// Adicionando os tipos de contadores ao objeto JSON
|
||||
cJSON_AddStringToObject(config, "gridmeter", meter_type_to_str(gridmeterType));
|
||||
cJSON_AddStringToObject(config, "evsemeter", meter_type_to_str(evsemeterType));
|
||||
|
||||
// Convertendo o objeto JSON para uma string
|
||||
const char *json_str = cJSON_Print(config);
|
||||
ESP_LOGI(TAG, "Returning meters config: %s", json_str);
|
||||
|
||||
httpd_resp_sendstr(req, json_str);
|
||||
|
||||
// Liberação da memória
|
||||
free((void *)json_str);
|
||||
cJSON_Delete(config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Função para atualizar as configurações dos contadores
|
||||
static esp_err_t meters_config_post_handler(httpd_req_t *req) {
|
||||
ESP_LOGI(TAG, "Received POST request for /api/v1/config/meters");
|
||||
|
||||
char buf[512];
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
|
||||
if (len <= 0) {
|
||||
ESP_LOGE(TAG, "Received empty body in POST request");
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Empty body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
buf[len] = '\0'; // Garantir que a string está terminada
|
||||
|
||||
ESP_LOGI(TAG, "Received POST data: %s", buf);
|
||||
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (!json) {
|
||||
ESP_LOGE(TAG, "Failed to parse JSON data");
|
||||
// Resposta detalhada de erro
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON format");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Atualizando os contadores
|
||||
cJSON *gridmeter = cJSON_GetObjectItem(json, "gridmeter");
|
||||
if (gridmeter) {
|
||||
meter_type_t gridType = string_to_meter_type(gridmeter->valuestring); // Usando a função string_to_meter_type
|
||||
ESP_LOGI(TAG, "Updating grid meter type to: %s", gridmeter->valuestring);
|
||||
meter_manager_grid_set_model(gridType);
|
||||
}
|
||||
|
||||
cJSON *evsemeter = cJSON_GetObjectItem(json, "evsemeter");
|
||||
if (evsemeter) {
|
||||
meter_type_t evseType = string_to_meter_type(evsemeter->valuestring); // Usando a função string_to_meter_type
|
||||
ESP_LOGI(TAG, "Updating EVSE meter type to: %s", evsemeter->valuestring);
|
||||
meter_manager_evse_set_model(evseType);
|
||||
}
|
||||
|
||||
cJSON_Delete(json);
|
||||
httpd_resp_sendstr(req, "Meters updated successfully");
|
||||
|
||||
ESP_LOGI(TAG, "Meters configuration updated successfully");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Registrando os manipuladores de URI para os contadores
|
||||
void register_meters_settings_handlers(httpd_handle_t server, void *ctx) {
|
||||
ESP_LOGI(TAG, "Registering URI handlers for meters settings");
|
||||
|
||||
// URI para o método GET
|
||||
httpd_uri_t meters_get_uri = {
|
||||
.uri = "/api/v1/config/meters",
|
||||
.method = HTTP_GET,
|
||||
.handler = meters_config_get_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
ESP_LOGI(TAG, "Registering GET handler for /api/v1/config/meters");
|
||||
httpd_register_uri_handler(server, &meters_get_uri);
|
||||
|
||||
// URI para o método POST
|
||||
httpd_uri_t meters_post_uri = {
|
||||
.uri = "/api/v1/config/meters",
|
||||
.method = HTTP_POST,
|
||||
.handler = meters_config_post_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
ESP_LOGI(TAG, "Registering POST handler for /api/v1/config/meters");
|
||||
httpd_register_uri_handler(server, &meters_post_uri);
|
||||
}
|
||||
|
||||
// === Fim de: components/rest_api/src/meters_settings_api.c ===
|
||||
|
||||
|
||||
// === Início de: components/rest_api/src/rest_main.c ===
|
||||
#include "rest_main.h"
|
||||
#include "evse_settings_api.h"
|
||||
#include "meters_settings_api.h"
|
||||
#include "loadbalancing_settings_api.h"
|
||||
#include "network_api.h"
|
||||
#include "ocpp_api.h"
|
||||
#include "auth_api.h"
|
||||
#include "dashboard_api.h"
|
||||
#include "static_file_api.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
static const char *TAG = "rest_main";
|
||||
|
||||
esp_err_t rest_server_init(const char *base_path) {
|
||||
ESP_LOGI(TAG, "Initializing REST API with base path: %s", base_path);
|
||||
|
||||
rest_server_context_t *ctx = calloc(1, sizeof(rest_server_context_t));
|
||||
if (!ctx) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for REST context");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
strlcpy(ctx->base_path, base_path, sizeof(ctx->base_path));
|
||||
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
config.max_uri_handlers = 32;
|
||||
|
||||
httpd_handle_t server = NULL;
|
||||
esp_err_t err = httpd_start(&server, &config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start HTTP server: %s", esp_err_to_name(err));
|
||||
free(ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "HTTP server started successfully");
|
||||
|
||||
// Register endpoint groups
|
||||
register_evse_settings_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
register_network_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
register_ocpp_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
register_auth_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
register_dashboard_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
register_meters_settings_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
register_loadbalancing_settings_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
register_static_file_handlers(server, ctx); // Apenas chamando a função sem comparação
|
||||
|
||||
ESP_LOGI(TAG, "All REST API endpoint groups registered successfully");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// === Fim de: components/rest_api/src/rest_main.c ===
|
||||
|
||||
|
||||
// === Início de: components/rest_api/src/network_api.c ===
|
||||
// =========================
|
||||
// network_api.c
|
||||
// =========================
|
||||
|
||||
#include "network_api.h"
|
||||
#include "esp_log.h"
|
||||
#include "cJSON.h"
|
||||
#include "wifi.h"
|
||||
#include "mqtt.h"
|
||||
|
||||
static const char *TAG = "network_api";
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
char ssid[33];
|
||||
char password[65];
|
||||
} wifi_task_data_t;
|
||||
|
||||
|
||||
static void wifi_apply_config_task(void *param) {
|
||||
wifi_task_data_t *data = (wifi_task_data_t *)param;
|
||||
ESP_LOGI("wifi_task", "Applying Wi-Fi config in background task");
|
||||
wifi_set_config(data->enabled, data->ssid, data->password);
|
||||
free(data);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static esp_err_t wifi_get_handler(httpd_req_t *req) {
|
||||
ESP_LOGI(TAG, "Handling GET /api/v1/config/wifi");
|
||||
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Obter dados da NVS via wifi.c
|
||||
bool enabled = wifi_get_enabled();
|
||||
char ssid[33] = {0};
|
||||
char password[65] = {0};
|
||||
|
||||
wifi_get_ssid(ssid);
|
||||
wifi_get_password(password);
|
||||
|
||||
// Criar JSON
|
||||
cJSON *json = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(json, "enabled", enabled);
|
||||
cJSON_AddStringToObject(json, "ssid", ssid);
|
||||
cJSON_AddStringToObject(json, "password", password);
|
||||
|
||||
// Enviar resposta
|
||||
char *response = cJSON_Print(json);
|
||||
httpd_resp_sendstr(req, response);
|
||||
|
||||
// Limpeza
|
||||
free(response);
|
||||
cJSON_Delete(json);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t wifi_post_handler(httpd_req_t *req) {
|
||||
ESP_LOGI(TAG, "Handling POST /api/v1/config/wifi");
|
||||
|
||||
char buf[512];
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) return ESP_FAIL;
|
||||
buf[len] = '\0';
|
||||
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (!json) return ESP_FAIL;
|
||||
|
||||
// Valores padrão
|
||||
bool enabled = false;
|
||||
const char *ssid = NULL;
|
||||
const char *password = NULL;
|
||||
|
||||
cJSON *j_enabled = cJSON_GetObjectItem(json, "enabled");
|
||||
if (cJSON_IsBool(j_enabled)) enabled = j_enabled->valueint;
|
||||
|
||||
cJSON *j_ssid = cJSON_GetObjectItem(json, "ssid");
|
||||
if (cJSON_IsString(j_ssid)) ssid = j_ssid->valuestring;
|
||||
|
||||
cJSON *j_password = cJSON_GetObjectItem(json, "password");
|
||||
if (cJSON_IsString(j_password)) password = j_password->valuestring;
|
||||
|
||||
// Enviar resposta antes de alterar Wi-Fi
|
||||
httpd_resp_sendstr(req, "Wi-Fi config atualizada com sucesso");
|
||||
|
||||
// Alocar struct para passar para a task
|
||||
wifi_task_data_t *task_data = malloc(sizeof(wifi_task_data_t));
|
||||
if (!task_data) {
|
||||
cJSON_Delete(json);
|
||||
ESP_LOGE(TAG, "Memory allocation failed for Wi-Fi task");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
task_data->enabled = enabled;
|
||||
strncpy(task_data->ssid, ssid ? ssid : "", sizeof(task_data->ssid));
|
||||
strncpy(task_data->password, password ? password : "", sizeof(task_data->password));
|
||||
|
||||
// Criar task normal com função C
|
||||
xTaskCreate(
|
||||
wifi_apply_config_task,
|
||||
"wifi_config_task",
|
||||
4096,
|
||||
task_data,
|
||||
3,
|
||||
NULL
|
||||
);
|
||||
|
||||
cJSON_Delete(json);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t config_mqtt_get_handler(httpd_req_t *req)
|
||||
{
|
||||
ESP_LOGI(TAG, "Handling GET /api/v1/config/mqtt");
|
||||
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
bool enabled = mqtt_get_enabled();
|
||||
char server[64] = {0};
|
||||
char base_topic[32] = {0};
|
||||
char username[32] = {0};
|
||||
char password[64] = {0};
|
||||
uint16_t periodicity = mqtt_get_periodicity();
|
||||
|
||||
mqtt_get_server(server);
|
||||
mqtt_get_base_topic(base_topic);
|
||||
mqtt_get_user(username);
|
||||
mqtt_get_password(password);
|
||||
|
||||
ESP_LOGI(TAG, "MQTT Config:");
|
||||
ESP_LOGI(TAG, " Enabled: %s", enabled ? "true" : "false");
|
||||
ESP_LOGI(TAG, " Server: %s", server);
|
||||
ESP_LOGI(TAG, " Topic: %s", base_topic);
|
||||
ESP_LOGI(TAG, " Username: %s", username);
|
||||
ESP_LOGI(TAG, " Password: %s", password);
|
||||
ESP_LOGI(TAG, " Periodicity: %d", periodicity);
|
||||
|
||||
cJSON *config = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(config, "enabled", enabled);
|
||||
cJSON_AddStringToObject(config, "host", server);
|
||||
cJSON_AddNumberToObject(config, "port", 1883);
|
||||
cJSON_AddStringToObject(config, "username", username);
|
||||
cJSON_AddStringToObject(config, "password", password);
|
||||
cJSON_AddStringToObject(config, "topic", base_topic);
|
||||
cJSON_AddNumberToObject(config, "periodicity", periodicity);
|
||||
|
||||
const char *config_str = cJSON_Print(config);
|
||||
httpd_resp_sendstr(req, config_str);
|
||||
|
||||
free((void *)config_str);
|
||||
cJSON_Delete(config);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t config_mqtt_post_handler(httpd_req_t *req)
|
||||
{
|
||||
ESP_LOGI(TAG, "Handling POST /api/v1/config/mqtt");
|
||||
|
||||
char buf[512];
|
||||
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
ESP_LOGE(TAG, "Failed to read request body");
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
ESP_LOGI(TAG, "Received JSON: %s", buf);
|
||||
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (!json) {
|
||||
ESP_LOGE(TAG, "Invalid JSON format");
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
bool enabled = false;
|
||||
const char *host = NULL, *topic = NULL, *username = NULL, *password = NULL;
|
||||
int periodicity = 30;
|
||||
|
||||
if (cJSON_IsBool(cJSON_GetObjectItem(json, "enabled")))
|
||||
enabled = cJSON_GetObjectItem(json, "enabled")->valueint;
|
||||
|
||||
cJSON *j_host = cJSON_GetObjectItem(json, "host");
|
||||
if (cJSON_IsString(j_host)) host = j_host->valuestring;
|
||||
|
||||
cJSON *j_topic = cJSON_GetObjectItem(json, "topic");
|
||||
if (cJSON_IsString(j_topic)) topic = j_topic->valuestring;
|
||||
|
||||
cJSON *j_user = cJSON_GetObjectItem(json, "username");
|
||||
if (cJSON_IsString(j_user)) username = j_user->valuestring;
|
||||
|
||||
cJSON *j_pass = cJSON_GetObjectItem(json, "password");
|
||||
if (cJSON_IsString(j_pass)) password = j_pass->valuestring;
|
||||
|
||||
cJSON *j_periodicity = cJSON_GetObjectItem(json, "periodicity");
|
||||
if (cJSON_IsNumber(j_periodicity)) periodicity = j_periodicity->valueint;
|
||||
|
||||
ESP_LOGI(TAG, "Applying MQTT config:");
|
||||
ESP_LOGI(TAG, " Enabled: %s", enabled ? "true" : "false");
|
||||
ESP_LOGI(TAG, " Host: %s", host);
|
||||
ESP_LOGI(TAG, " Topic: %s", topic);
|
||||
ESP_LOGI(TAG, " Username: %s", username);
|
||||
ESP_LOGI(TAG, " Password: %s", password);
|
||||
ESP_LOGI(TAG, " Periodicity: %d", periodicity);
|
||||
|
||||
esp_err_t err = mqtt_set_config(enabled, host, topic, username, password, periodicity);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to apply MQTT config (code %d)", err);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to apply config");
|
||||
cJSON_Delete(json);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_resp_sendstr(req, "Configuração MQTT atualizada com sucesso");
|
||||
cJSON_Delete(json);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void register_network_handlers(httpd_handle_t server, void *ctx) {
|
||||
httpd_uri_t wifi_get = {
|
||||
.uri = "/api/v1/config/wifi",
|
||||
.method = HTTP_GET,
|
||||
.handler = wifi_get_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &wifi_get);
|
||||
|
||||
httpd_uri_t wifi_post = {
|
||||
.uri = "/api/v1/config/wifi",
|
||||
.method = HTTP_POST,
|
||||
.handler = wifi_post_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &wifi_post);
|
||||
|
||||
// URI handler for getting MQTT config
|
||||
httpd_uri_t config_mqtt_get_uri = {
|
||||
.uri = "/api/v1/config/mqtt",
|
||||
.method = HTTP_GET,
|
||||
.handler = config_mqtt_get_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_mqtt_get_uri);
|
||||
|
||||
// URI handler for posting MQTT config
|
||||
httpd_uri_t config_mqtt_post_uri = {
|
||||
.uri = "/api/v1/config/mqtt",
|
||||
.method = HTTP_POST,
|
||||
.handler = config_mqtt_post_handler,
|
||||
.user_ctx = ctx
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_mqtt_post_uri);
|
||||
}
|
||||
|
||||
// === Fim de: components/rest_api/src/network_api.c ===
|
||||
1066
projeto_parte5.c
1066
projeto_parte5.c
File diff suppressed because it is too large
Load Diff
735
projeto_parte6.c
735
projeto_parte6.c
@@ -1,735 +0,0 @@
|
||||
|
||||
|
||||
// === Início de: components/network/include/wifi.h ===
|
||||
#ifndef WIFI_H_
|
||||
#define WIFI_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
#define WIFI_SCAN_SCAN_LIST_SIZE 10
|
||||
|
||||
#define WIFI_AP_CONNECTED_BIT BIT0
|
||||
#define WIFI_AP_DISCONNECTED_BIT BIT1
|
||||
#define WIFI_STA_CONNECTED_BIT BIT2
|
||||
#define WIFI_STA_DISCONNECTED_BIT BIT3
|
||||
#define WIFI_AP_MODE_BIT BIT4
|
||||
#define WIFI_STA_MODE_BIT BIT5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char ssid[32];
|
||||
int rssi;
|
||||
bool auth;
|
||||
} wifi_scan_ap_t;
|
||||
|
||||
/**
|
||||
* @brief WiFi event group WIFI_AP_CONNECTED_BIT | WIFI_AP_DISCONNECTED_BIT | WIFI_STA_CONNECTED_BIT | WIFI_STA_DISCONNECTED_BIT | WIFI_AP_MODE_BIT | WIFI_STA_MODE_BIT
|
||||
*
|
||||
*/
|
||||
extern EventGroupHandle_t wifi_event_group;
|
||||
|
||||
/**
|
||||
* @brief Initialize WiFi
|
||||
*
|
||||
*/
|
||||
void wifi_ini(void);
|
||||
|
||||
/**
|
||||
* @brief Return WiFi STA network interface
|
||||
*
|
||||
* @return esp_netif_t*
|
||||
*/
|
||||
esp_netif_t* wifi_get_sta_netif(void);
|
||||
|
||||
/**
|
||||
* @brief Return WiFi AP network interface
|
||||
*
|
||||
* @return esp_netif_t*
|
||||
*/
|
||||
esp_netif_t* wifi_get_ap_netif(void);
|
||||
|
||||
/**
|
||||
* @brief Set WiFi config
|
||||
*
|
||||
* @param enabled
|
||||
* @param ssid NULL value will be skiped
|
||||
* @param password NULL value will be skiped
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t wifi_set_config(bool enabled, const char* ssid, const char* password);
|
||||
|
||||
/**
|
||||
* @brief Get WiFi STA enabled, stored in NVS
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool wifi_get_enabled(void);
|
||||
|
||||
/**
|
||||
* @brief Scan for AP
|
||||
*
|
||||
* @param scan_aps array with length WIFI_SCAN_SCAN_LIST_SIZE
|
||||
* @return uint16_t number of available AP
|
||||
*/
|
||||
uint16_t wifi_scan(wifi_scan_ap_t *scan_aps);
|
||||
|
||||
/**
|
||||
* @brief Get WiFi STA ssid, string length 32, stored in NVS
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void wifi_get_ssid(char* value);
|
||||
|
||||
/**
|
||||
* @brief Get WiFi STA password, string length 32, stored in NVS
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void wifi_get_password(char* value);
|
||||
|
||||
/**
|
||||
* @brief Start WiFi AP mode
|
||||
*
|
||||
*/
|
||||
void wifi_ap_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop WiFi AP mode
|
||||
*
|
||||
*/
|
||||
void wifi_ap_stop(void);
|
||||
|
||||
#endif /* WIFI_H_ */
|
||||
|
||||
// === Fim de: components/network/include/wifi.h ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/ac_relay.c ===
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ac_relay.h"
|
||||
#include "board_config.h"
|
||||
|
||||
static const char* TAG = "ac_relay";
|
||||
|
||||
/**
|
||||
* @brief Initialize the AC relay GPIO.
|
||||
*
|
||||
* Configures the specified GPIO pin as an output and sets its initial state to OFF (low).
|
||||
*/
|
||||
void ac_relay_init(void)
|
||||
{
|
||||
gpio_config_t conf = {
|
||||
.pin_bit_mask = BIT64(board_config.ac_relay_gpio),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE, ///< Disabled unless required
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
|
||||
esp_err_t ret = gpio_config(&conf);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to configure GPIO (error: %s)", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_set_level(board_config.ac_relay_gpio, false); ///< Ensure relay starts OFF
|
||||
ESP_LOGI(TAG, "AC relay initialized. Pin: %d", board_config.ac_relay_gpio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the state of the AC relay.
|
||||
*
|
||||
* @param state True to turn the relay ON, False to turn it OFF.
|
||||
*/
|
||||
void ac_relay_set_state(bool state)
|
||||
{
|
||||
ESP_LOGI(TAG, "Setting AC relay state: Pin: %d, State: %d", board_config.ac_relay_gpio, state);
|
||||
|
||||
esp_err_t ret = gpio_set_level(board_config.ac_relay_gpio, state);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set GPIO level (error: %s)", esp_err_to_name(ret));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current state of the AC relay.
|
||||
*
|
||||
* @return true if the relay is ON, false if OFF.
|
||||
*/
|
||||
bool ac_relay_get_state(void)
|
||||
{
|
||||
int level = gpio_get_level(board_config.ac_relay_gpio);
|
||||
ESP_LOGD(TAG, "Current AC relay state: Pin: %d, State: %d", board_config.ac_relay_gpio, level);
|
||||
return level;
|
||||
}
|
||||
|
||||
// === Fim de: components/peripherals/src/ac_relay.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/ntc_sensor.c ===
|
||||
#include <sys/param.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "ntc_sensor.h"
|
||||
#include "ntc_driver.h"
|
||||
|
||||
#include "adc.h"
|
||||
|
||||
static const char *TAG = "temp_sensor";
|
||||
|
||||
#define MEASURE_PERIOD 15000 // 10s
|
||||
|
||||
static float temp = 0.0;
|
||||
|
||||
static ntc_device_handle_t ntc = NULL;
|
||||
|
||||
static portMUX_TYPE temp_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static void ntc_sensor_task_func(void *param) {
|
||||
float t;
|
||||
while (true) {
|
||||
if (ntc_dev_get_temperature(ntc, &t) == ESP_OK) {
|
||||
portENTER_CRITICAL(&temp_mux);
|
||||
temp = t;
|
||||
portEXIT_CRITICAL(&temp_mux);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(MEASURE_PERIOD));
|
||||
}
|
||||
}
|
||||
|
||||
float ntc_temp_sensor(void) {
|
||||
float t;
|
||||
portENTER_CRITICAL(&temp_mux);
|
||||
t = temp;
|
||||
portEXIT_CRITICAL(&temp_mux);
|
||||
return t;
|
||||
}
|
||||
|
||||
void ntc_sensor_init(void)
|
||||
{
|
||||
|
||||
ESP_LOGI(TAG, "ntc_sensor_init");
|
||||
|
||||
// Select the NTC sensor and initialize the hardware parameters
|
||||
ntc_config_t ntc_config = {
|
||||
.b_value = 3950,
|
||||
.r25_ohm = 10000,
|
||||
.fixed_ohm = 4700,
|
||||
.vdd_mv = 3300,
|
||||
.circuit_mode = CIRCUIT_MODE_NTC_GND,
|
||||
.atten = ADC_ATTEN_DB_12,
|
||||
.channel = ADC_CHANNEL_0,
|
||||
.unit = ADC_UNIT_1};
|
||||
|
||||
// Create the NTC Driver and Init ADC
|
||||
// ntc_device_handle_t ntc = NULL;
|
||||
// adc_oneshot_unit_handle_t adc_handle = NULL;
|
||||
ESP_ERROR_CHECK(ntc_dev_create(&ntc_config, &ntc, &adc_handle));
|
||||
ESP_ERROR_CHECK(ntc_dev_get_adc_handle(ntc, &adc_handle));
|
||||
|
||||
xTaskCreate(ntc_sensor_task_func, "ntc_sensor_task", 5 * 1024, NULL, 3, NULL);
|
||||
}
|
||||
|
||||
// === Fim de: components/peripherals/src/ntc_sensor.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/proximity.c ===
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "proximity.h"
|
||||
#include "board_config.h"
|
||||
#include "adc.h"
|
||||
|
||||
static const char *TAG = "proximity";
|
||||
|
||||
void proximity_init(void)
|
||||
{
|
||||
if (board_config.proximity)
|
||||
{
|
||||
adc_oneshot_chan_cfg_t config = {
|
||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||
.atten = ADC_ATTEN_DB_12};
|
||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle, board_config.proximity_adc_channel, &config));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t proximity_get_max_current(void)
|
||||
{
|
||||
int voltage;
|
||||
adc_oneshot_read(adc_handle, board_config.proximity_adc_channel, &voltage);
|
||||
adc_cali_raw_to_voltage(adc_cali_handle, voltage, &voltage);
|
||||
|
||||
ESP_LOGI(TAG, "Measured: %dmV", voltage);
|
||||
|
||||
uint8_t current;
|
||||
|
||||
if (voltage >= board_config.proximity_down_threshold_8)
|
||||
{
|
||||
current = 8;
|
||||
}
|
||||
else if (voltage >= board_config.proximity_down_threshold_10)
|
||||
{
|
||||
current = 10;
|
||||
}
|
||||
|
||||
else if (voltage >= board_config.proximity_down_threshold_13)
|
||||
{
|
||||
current = 13;
|
||||
}
|
||||
else if (voltage >= board_config.proximity_down_threshold_20)
|
||||
{
|
||||
current = 20;
|
||||
}
|
||||
|
||||
else if (voltage >= board_config.proximity_down_threshold_25)
|
||||
{
|
||||
current = 25;
|
||||
}
|
||||
else if (voltage >= board_config.proximity_down_threshold_32)
|
||||
{
|
||||
current = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = 32;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Max current: %dA", current);
|
||||
|
||||
return current;
|
||||
}
|
||||
// === Fim de: components/peripherals/src/proximity.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/buzzer.c ===
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "board_config.h"
|
||||
#include "buzzer.h"
|
||||
#include "evse_api.h"
|
||||
|
||||
static gpio_num_t buzzer_gpio = GPIO_NUM_NC;
|
||||
static evse_state_t last_buzzer_state = -1;
|
||||
static QueueHandle_t buzzer_queue = NULL;
|
||||
|
||||
void buzzer_on(void) {
|
||||
if (buzzer_gpio != GPIO_NUM_NC)
|
||||
gpio_set_level(buzzer_gpio, 1);
|
||||
}
|
||||
|
||||
void buzzer_off(void) {
|
||||
if (buzzer_gpio != GPIO_NUM_NC)
|
||||
gpio_set_level(buzzer_gpio, 0);
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// Padrões de Buzzer
|
||||
// ----------------------
|
||||
|
||||
typedef struct {
|
||||
uint16_t on_ms;
|
||||
uint16_t off_ms;
|
||||
} buzzer_pattern_step_t;
|
||||
|
||||
typedef enum {
|
||||
BUZZER_PATTERN_NONE = 0,
|
||||
BUZZER_PATTERN_PLUGGED,
|
||||
BUZZER_PATTERN_UNPLUGGED,
|
||||
BUZZER_PATTERN_CHARGING,
|
||||
} buzzer_pattern_id_t;
|
||||
|
||||
static const buzzer_pattern_step_t pattern_plugged[] = {
|
||||
{100, 100}, {200, 0}
|
||||
};
|
||||
|
||||
static const buzzer_pattern_step_t pattern_unplugged[] = {
|
||||
{150, 150}, {150, 150}, {150, 0}
|
||||
};
|
||||
|
||||
static const buzzer_pattern_step_t pattern_charging[] = {
|
||||
{80, 150}, {100, 120}, {120, 100}, {140, 0}
|
||||
};
|
||||
|
||||
// ----------------------
|
||||
// Executor de padrões
|
||||
// ----------------------
|
||||
|
||||
static void buzzer_execute_pattern(buzzer_pattern_id_t pattern_id) {
|
||||
const buzzer_pattern_step_t *pattern = NULL;
|
||||
size_t length = 0;
|
||||
|
||||
switch (pattern_id) {
|
||||
case BUZZER_PATTERN_PLUGGED:
|
||||
pattern = pattern_plugged;
|
||||
length = sizeof(pattern_plugged) / sizeof(pattern_plugged[0]);
|
||||
break;
|
||||
case BUZZER_PATTERN_UNPLUGGED:
|
||||
pattern = pattern_unplugged;
|
||||
length = sizeof(pattern_unplugged) / sizeof(pattern_unplugged[0]);
|
||||
break;
|
||||
case BUZZER_PATTERN_CHARGING:
|
||||
pattern = pattern_charging;
|
||||
length = sizeof(pattern_charging) / sizeof(pattern_charging[0]);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
buzzer_on();
|
||||
vTaskDelay(pdMS_TO_TICKS(pattern[i].on_ms));
|
||||
buzzer_off();
|
||||
if (pattern[i].off_ms > 0)
|
||||
vTaskDelay(pdMS_TO_TICKS(pattern[i].off_ms));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// Task que toca o buzzer
|
||||
// ----------------------
|
||||
|
||||
static void buzzer_worker_task(void *arg) {
|
||||
buzzer_pattern_id_t pattern_id;
|
||||
|
||||
while (true) {
|
||||
if (xQueueReceive(buzzer_queue, &pattern_id, portMAX_DELAY)) {
|
||||
//buzzer_execute_pattern(pattern_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// Task de monitoramento
|
||||
// ----------------------
|
||||
|
||||
static void buzzer_monitor_task(void *arg) {
|
||||
while (true) {
|
||||
evse_state_t current = evse_get_state();
|
||||
|
||||
if (current != last_buzzer_state) {
|
||||
buzzer_pattern_id_t pattern_id = BUZZER_PATTERN_NONE;
|
||||
|
||||
switch (current) {
|
||||
case EVSE_STATE_A:
|
||||
if (last_buzzer_state != EVSE_STATE_A)
|
||||
pattern_id = BUZZER_PATTERN_UNPLUGGED;
|
||||
break;
|
||||
case EVSE_STATE_B1:
|
||||
case EVSE_STATE_B2:
|
||||
if (last_buzzer_state != EVSE_STATE_B1 && last_buzzer_state != EVSE_STATE_B2)
|
||||
pattern_id = BUZZER_PATTERN_PLUGGED;
|
||||
break;
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
if (last_buzzer_state != EVSE_STATE_C2 && last_buzzer_state != EVSE_STATE_D2)
|
||||
pattern_id = BUZZER_PATTERN_CHARGING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pattern_id != BUZZER_PATTERN_NONE) {
|
||||
xQueueSend(buzzer_queue, &pattern_id, 0); // Não bloqueia
|
||||
}
|
||||
|
||||
last_buzzer_state = current;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// Inicialização
|
||||
// ----------------------
|
||||
|
||||
void buzzer_init(void) {
|
||||
if (board_config.buzzer) {
|
||||
buzzer_gpio = board_config.buzzer_gpio;
|
||||
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = BIT64(buzzer_gpio),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(buzzer_gpio, 0);
|
||||
}
|
||||
|
||||
buzzer_queue = xQueueCreate(4, sizeof(buzzer_pattern_id_t));
|
||||
|
||||
xTaskCreate(buzzer_monitor_task, "buzzer_monitor", 2048, NULL, 3, NULL);
|
||||
xTaskCreate(buzzer_worker_task, "buzzer_worker", 2048, NULL, 3, NULL);
|
||||
}
|
||||
|
||||
// === Fim de: components/peripherals/src/buzzer.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/ds18x20.h ===
|
||||
/*
|
||||
* Copyright (c) 2016 Grzegorz Hetman <ghetman@gmail.com>
|
||||
* Copyright (c) 2016 Alex Stewart <foogod@gmail.com>
|
||||
* Copyright (c) 2018 Ruslan V. Uss <unclerus@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of itscontributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DS18X20_H
|
||||
#define _DS18X20_H
|
||||
|
||||
#include <esp_err.h>
|
||||
#include "onewire.h"
|
||||
|
||||
typedef onewire_addr_t ds18x20_addr_t;
|
||||
|
||||
/** An address value which can be used to indicate "any device on the bus" */
|
||||
#define DS18X20_ANY ONEWIRE_NONE
|
||||
|
||||
/** Family ID (lower address byte) of DS18B20 sensors */
|
||||
#define DS18B20_FAMILY_ID 0x28
|
||||
|
||||
/** Family ID (lower address byte) of DS18S20 sensors */
|
||||
#define DS18S20_FAMILY_ID 0x10
|
||||
|
||||
/**
|
||||
* @brief Find the addresses of all ds18x20 devices on the bus.
|
||||
*
|
||||
* Scans the bus for all devices and places their addresses in the supplied
|
||||
* array. If there are more than `addr_count` devices on the bus, only the
|
||||
* first `addr_count` are recorded.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 bus
|
||||
* @param addr_list A pointer to an array of ::ds18x20_addr_t values.
|
||||
* This will be populated with the addresses of the found
|
||||
* devices.
|
||||
* @param addr_count Number of slots in the `addr_list` array. At most this
|
||||
* many addresses will be returned.
|
||||
* @param found The number of devices found. Note that this may be less
|
||||
* than, equal to, or more than `addr_count`, depending on
|
||||
* how many ds18x20 devices are attached to the bus.
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18x20_scan_devices(gpio_num_t pin, ds18x20_addr_t *addr_list, size_t addr_count, size_t *found);
|
||||
|
||||
/**
|
||||
* @brief Tell one or more sensors to perform a temperature measurement and
|
||||
* conversion (CONVERT_T) operation.
|
||||
*
|
||||
* This operation can take up to 750ms to complete.
|
||||
*
|
||||
* If `wait=true`, this routine will automatically drive the pin high for the
|
||||
* necessary 750ms after issuing the command to ensure parasitically-powered
|
||||
* devices have enough power to perform the conversion operation (for
|
||||
* non-parasitically-powered devices, this is not necessary but does not
|
||||
* hurt). If `wait=false`, this routine will drive the pin high, but will
|
||||
* then return immediately. It is up to the caller to wait the requisite time
|
||||
* and then depower the bus using onewire_depower() or by issuing another
|
||||
* command once conversion is done.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device on the bus. This can be set
|
||||
* to ::DS18X20_ANY to send the command to all devices on the bus
|
||||
* at the same time.
|
||||
* @param wait Whether to wait for the necessary 750ms for the ds18x20 to
|
||||
* finish performing the conversion before returning to the
|
||||
* caller (You will normally want to do this).
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18x20_measure(gpio_num_t pin, ds18x20_addr_t addr, bool wait);
|
||||
|
||||
/**
|
||||
* @brief Read the value from the last CONVERT_T operation.
|
||||
*
|
||||
* This should be called after ds18x20_measure() to fetch the result of the
|
||||
* temperature measurement.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to read. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param temperature The temperature in degrees Celsius
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18x20_read_temperature(gpio_num_t pin, ds18x20_addr_t addr, int16_t *temperature);
|
||||
|
||||
/**
|
||||
* @brief Read the value from the last CONVERT_T operation (ds18b20 version).
|
||||
*
|
||||
* This should be called after ds18x20_measure() to fetch the result of the
|
||||
* temperature measurement.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to read. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param temperature The temperature in degrees Celsius
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18b20_read_temperature(gpio_num_t pin, ds18x20_addr_t addr, int16_t *temperature);
|
||||
|
||||
/**
|
||||
* @brief Read the value from the last CONVERT_T operation (ds18s20 version).
|
||||
*
|
||||
* This should be called after ds18x20_measure() to fetch the result of the
|
||||
* temperature measurement.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to read. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param temperature The temperature in degrees Celsius
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18s20_read_temperature(gpio_num_t pin, ds18x20_addr_t addr, int16_t *temperature);
|
||||
|
||||
/**
|
||||
* @brief Read the value from the last CONVERT_T operation for multiple devices.
|
||||
*
|
||||
* This should be called after ds18x20_measure() to fetch the result of the
|
||||
* temperature measurement.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 bus
|
||||
* @param addr_list A list of addresses for devices to read.
|
||||
* @param addr_count The number of entries in `addr_list`.
|
||||
* @param result_list An array of int16_ts to hold the returned temperature
|
||||
* values. It should have at least `addr_count` entries.
|
||||
*
|
||||
* @returns `ESP_OK` if all temperatures were fetched successfully
|
||||
*/
|
||||
esp_err_t ds18x20_read_temp_multi(gpio_num_t pin, ds18x20_addr_t *addr_list, size_t addr_count, int16_t *result_list);
|
||||
|
||||
/** Perform a ds18x20_measure() followed by ds18s20_read_temperature()
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18s20 device
|
||||
* @param addr The 64-bit address of the device to read. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param temperature The temperature in degrees Celsius
|
||||
*/
|
||||
esp_err_t ds18s20_measure_and_read(gpio_num_t pin, ds18x20_addr_t addr, int16_t *temperature);
|
||||
|
||||
/** Perform a ds18x20_measure() followed by ds18b20_read_temperature()
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to read. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param temperature The temperature in degrees Celsius
|
||||
*/
|
||||
esp_err_t ds18b20_measure_and_read(gpio_num_t pin, ds18x20_addr_t addr, int16_t *temperature);
|
||||
|
||||
/** Perform a ds18x20_measure() followed by ds18x20_read_temperature()
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to read. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param temperature The temperature in degrees Celsius
|
||||
*/
|
||||
esp_err_t ds18x20_measure_and_read(gpio_num_t pin, ds18x20_addr_t addr, int16_t *temperature);
|
||||
|
||||
/**
|
||||
* @brief Perform a ds18x20_measure() followed by ds18x20_read_temp_multi()
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 bus
|
||||
* @param addr_list A list of addresses for devices to read.
|
||||
* @param addr_count The number of entries in `addr_list`.
|
||||
* @param result_list An array of int16_ts to hold the returned temperature
|
||||
* values. It should have at least `addr_count` entries.
|
||||
*
|
||||
* @returns `ESP_OK` if all temperatures were fetched successfully
|
||||
*/
|
||||
esp_err_t ds18x20_measure_and_read_multi(gpio_num_t pin, ds18x20_addr_t *addr_list, size_t addr_count, int16_t *result_list);
|
||||
|
||||
/**
|
||||
* @brief Read the scratchpad data for a particular ds18x20 device.
|
||||
*
|
||||
* This is not generally necessary to do directly. It is done automatically
|
||||
* as part of ds18x20_read_temperature().
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to read. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param buffer An 8-byte buffer to hold the read data.
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18x20_read_scratchpad(gpio_num_t pin, ds18x20_addr_t addr, uint8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Write the scratchpad data for a particular ds18x20 device.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to write. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
* @param buffer An 3-byte buffer to hold the data to write
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18x20_write_scratchpad(gpio_num_t pin, ds18x20_addr_t addr, uint8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Issue the copy scratchpad command, copying current scratchpad to
|
||||
* EEPROM.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the ds18x20 device
|
||||
* @param addr The 64-bit address of the device to command. This can be set
|
||||
* to ::DS18X20_ANY to read any device on the bus (but note
|
||||
* that this will only work if there is exactly one device
|
||||
* connected, or they will corrupt each others' transmissions)
|
||||
*
|
||||
* @returns `ESP_OK` if the command was successfully issued
|
||||
*/
|
||||
esp_err_t ds18x20_copy_scratchpad(gpio_num_t pin, ds18x20_addr_t addr);
|
||||
|
||||
|
||||
#endif /* _DS18X20_H */
|
||||
// === Fim de: components/peripherals/src/ds18x20.h ===
|
||||
793
projeto_parte7.c
793
projeto_parte7.c
@@ -1,793 +0,0 @@
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/socket_lock.c ===
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "nvs.h"
|
||||
|
||||
#include "socket_lock.h"
|
||||
#include "board_config.h"
|
||||
|
||||
#define NVS_NAMESPACE "socket_lock"
|
||||
#define NVS_OPERATING_TIME "op_time"
|
||||
#define NVS_BREAK_TIME "break_time"
|
||||
#define NVS_RETRY_COUNT "retry_count"
|
||||
#define NVS_DETECTION_HIGH "detect_hi"
|
||||
|
||||
#define OPERATING_TIME_MIN 100
|
||||
#define OPERATING_TIME_MAX 1000
|
||||
#define LOCK_DELAY 500
|
||||
|
||||
#define LOCK_BIT BIT0
|
||||
#define UNLOCK_BIT BIT1
|
||||
#define REPEAT_LOCK_BIT BIT2
|
||||
#define REPEAT_UNLOCK_BIT BIT3
|
||||
|
||||
static const char* TAG = "socket_lock";
|
||||
|
||||
static nvs_handle_t nvs;
|
||||
|
||||
static uint16_t operating_time = 300;
|
||||
|
||||
static uint16_t break_time = 1000;
|
||||
|
||||
static bool detection_high;
|
||||
|
||||
static uint8_t retry_count = 5;
|
||||
|
||||
static socket_lock_status_t status;
|
||||
|
||||
static TaskHandle_t socket_lock_task;
|
||||
|
||||
static bool is_locked(void)
|
||||
{
|
||||
gpio_set_level(board_config.socket_lock_a_gpio, 1);
|
||||
gpio_set_level(board_config.socket_lock_b_gpio, 1);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(board_config.socket_lock_detection_delay));
|
||||
|
||||
return gpio_get_level(board_config.socket_lock_detection_gpio) == detection_high;
|
||||
}
|
||||
|
||||
bool socket_lock_is_locked_state(void)
|
||||
{
|
||||
return is_locked();
|
||||
}
|
||||
|
||||
static void socket_lock_task_func(void* param)
|
||||
{
|
||||
uint32_t notification;
|
||||
|
||||
TickType_t previous_tick = 0;
|
||||
uint8_t attempt = 0;
|
||||
|
||||
while (true) {
|
||||
if (xTaskNotifyWait(0x00, 0xff, ¬ification, portMAX_DELAY)) {
|
||||
if (notification & (LOCK_BIT | UNLOCK_BIT)) {
|
||||
attempt = retry_count;
|
||||
}
|
||||
|
||||
if (notification & (UNLOCK_BIT | REPEAT_UNLOCK_BIT)) {
|
||||
gpio_set_level(board_config.socket_lock_a_gpio, 0);
|
||||
gpio_set_level(board_config.socket_lock_b_gpio, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(operating_time));
|
||||
|
||||
if (!is_locked()) {
|
||||
ESP_LOGI(TAG, "Unlock OK");
|
||||
status = SOCKED_LOCK_STATUS_IDLE;
|
||||
} else {
|
||||
if (attempt > 1) {
|
||||
ESP_LOGW(TAG, "Not unlocked yet, repeating...");
|
||||
attempt--;
|
||||
xTaskNotify(socket_lock_task, REPEAT_UNLOCK_BIT, eSetBits);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Not unlocked");
|
||||
status = SOCKED_LOCK_STATUS_UNLOCKING_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
gpio_set_level(board_config.socket_lock_a_gpio, 0);
|
||||
gpio_set_level(board_config.socket_lock_b_gpio, 0);
|
||||
} else if (notification & (LOCK_BIT | REPEAT_LOCK_BIT)) {
|
||||
if (notification & LOCK_BIT) {
|
||||
vTaskDelay(pdMS_TO_TICKS(LOCK_DELAY)); //delay before first lock attempt
|
||||
}
|
||||
gpio_set_level(board_config.socket_lock_a_gpio, 1);
|
||||
gpio_set_level(board_config.socket_lock_b_gpio, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(operating_time));
|
||||
|
||||
if (is_locked()) {
|
||||
ESP_LOGI(TAG, "Lock OK");
|
||||
status = SOCKED_LOCK_STATUS_IDLE;
|
||||
} else {
|
||||
if (attempt > 1) {
|
||||
ESP_LOGW(TAG, "Not locked yet, repeating...");
|
||||
attempt--;
|
||||
xTaskNotify(socket_lock_task, REPEAT_LOCK_BIT, eSetBits);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Not locked");
|
||||
status = SOCKED_LOCK_STATUS_LOCKING_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
gpio_set_level(board_config.socket_lock_a_gpio, 0);
|
||||
gpio_set_level(board_config.socket_lock_b_gpio, 0);
|
||||
}
|
||||
|
||||
TickType_t delay_tick = xTaskGetTickCount() - previous_tick;
|
||||
if (delay_tick < pdMS_TO_TICKS(break_time)) {
|
||||
vTaskDelay(pdMS_TO_TICKS(break_time) - delay_tick);
|
||||
}
|
||||
previous_tick = xTaskGetTickCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void socket_lock_init(void)
|
||||
{
|
||||
if (board_config.socket_lock) {
|
||||
ESP_ERROR_CHECK(nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs));
|
||||
|
||||
nvs_get_u16(nvs, NVS_OPERATING_TIME, &operating_time);
|
||||
|
||||
nvs_get_u16(nvs, NVS_BREAK_TIME, &break_time);
|
||||
|
||||
nvs_get_u8(nvs, NVS_RETRY_COUNT, &retry_count);
|
||||
|
||||
uint8_t u8;
|
||||
if (nvs_get_u8(nvs, NVS_DETECTION_HIGH, &u8) == ESP_OK) {
|
||||
detection_high = u8;
|
||||
}
|
||||
|
||||
gpio_config_t io_conf = {};
|
||||
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = BIT64(board_config.socket_lock_a_gpio) | BIT64(board_config.socket_lock_b_gpio);
|
||||
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pin_bit_mask = BIT64(board_config.socket_lock_detection_gpio);
|
||||
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||
|
||||
xTaskCreate(socket_lock_task_func, "socket_lock_task", 2 * 1024, NULL, 10, &socket_lock_task);
|
||||
}
|
||||
}
|
||||
|
||||
bool socket_lock_is_detection_high(void)
|
||||
{
|
||||
return detection_high;
|
||||
}
|
||||
|
||||
void socket_lock_set_detection_high(bool _detection_high)
|
||||
{
|
||||
detection_high = _detection_high;
|
||||
|
||||
nvs_set_u8(nvs, NVS_DETECTION_HIGH, detection_high);
|
||||
nvs_commit(nvs);
|
||||
}
|
||||
|
||||
uint16_t socket_lock_get_operating_time(void)
|
||||
{
|
||||
return operating_time;
|
||||
}
|
||||
|
||||
esp_err_t socket_lock_set_operating_time(uint16_t _operating_time)
|
||||
{
|
||||
if (_operating_time < OPERATING_TIME_MIN || _operating_time > OPERATING_TIME_MAX) {
|
||||
ESP_LOGE(TAG, "Operating time out of range");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
operating_time = _operating_time;
|
||||
nvs_set_u16(nvs, NVS_OPERATING_TIME, operating_time);
|
||||
nvs_commit(nvs);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t socket_lock_get_retry_count(void)
|
||||
{
|
||||
return retry_count;
|
||||
}
|
||||
|
||||
void socket_lock_set_retry_count(uint8_t _retry_count)
|
||||
{
|
||||
retry_count = _retry_count;
|
||||
nvs_set_u8(nvs, NVS_RETRY_COUNT, retry_count);
|
||||
nvs_commit(nvs);
|
||||
}
|
||||
|
||||
uint16_t socket_lock_get_break_time(void)
|
||||
{
|
||||
return break_time;
|
||||
}
|
||||
|
||||
esp_err_t socket_lock_set_break_time(uint16_t _break_time)
|
||||
{
|
||||
if (_break_time < board_config.socket_lock_min_break_time) {
|
||||
ESP_LOGE(TAG, "Operating time out of range");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
break_time = _break_time;
|
||||
nvs_set_u16(nvs, NVS_BREAK_TIME, break_time);
|
||||
nvs_commit(nvs);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void socket_lock_set_locked(bool locked)
|
||||
{
|
||||
ESP_LOGI(TAG, "Set locked %d", locked);
|
||||
|
||||
xTaskNotify(socket_lock_task, locked ? LOCK_BIT : UNLOCK_BIT, eSetBits);
|
||||
status = SOCKED_LOCK_STATUS_OPERATING;
|
||||
}
|
||||
|
||||
socket_lock_status_t socket_lock_get_status(void)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
// === Fim de: components/peripherals/src/socket_lock.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/temp_sensor.c ===
|
||||
#include <sys/param.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "temp_sensor.h"
|
||||
#include "lm75a.h"
|
||||
|
||||
#define MAX_SENSORS 5
|
||||
#define MEASURE_PERIOD 10000 // 10s
|
||||
#define MEASURE_ERR_THRESHOLD 3
|
||||
|
||||
static const char *TAG = "temp_sensor";
|
||||
|
||||
static uint8_t sensor_count = 0;
|
||||
|
||||
static int16_t low_temp = 0;
|
||||
|
||||
static int high_temp = 0;
|
||||
|
||||
static uint8_t measure_err_count = 0;
|
||||
|
||||
static void temp_sensor_task_func(void *param)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
high_temp = lm75a_read_temperature(0);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(MEASURE_PERIOD));
|
||||
}
|
||||
}
|
||||
|
||||
void temp_sensor_init(void)
|
||||
{
|
||||
|
||||
ESP_LOGW(TAG, "temp_sensor_init");
|
||||
|
||||
lm75a_init();
|
||||
|
||||
xTaskCreate(temp_sensor_task_func, "temp_sensor_task", 5 * 1024, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
uint8_t temp_sensor_get_count(void)
|
||||
{
|
||||
return sensor_count;
|
||||
}
|
||||
|
||||
int16_t temp_sensor_get_low(void)
|
||||
{
|
||||
return low_temp;
|
||||
}
|
||||
|
||||
int temp_sensor_get_high(void)
|
||||
{
|
||||
return high_temp;
|
||||
}
|
||||
|
||||
bool temp_sensor_is_error(void)
|
||||
{
|
||||
return sensor_count == 0 || measure_err_count > MEASURE_ERR_THRESHOLD;
|
||||
}
|
||||
// === Fim de: components/peripherals/src/temp_sensor.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/aux_io.c ===
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "nvs.h"
|
||||
|
||||
#include "aux_io.h"
|
||||
#include "board_config.h"
|
||||
#include "adc.h"
|
||||
|
||||
#define MAX_AUX_IN 4
|
||||
#define MAX_AUX_OUT 4
|
||||
#define MAX_AUX_AIN 4
|
||||
|
||||
//static const char* TAG = "aux";
|
||||
|
||||
static int aux_in_count = 0;
|
||||
static int aux_out_count = 0;
|
||||
static int aux_ain_count = 0;
|
||||
|
||||
static struct aux_gpio_s
|
||||
{
|
||||
gpio_num_t gpio;
|
||||
const char* name;
|
||||
} aux_in[MAX_AUX_IN], aux_out[MAX_AUX_OUT];
|
||||
|
||||
static struct aux_adc_s
|
||||
{
|
||||
adc_channel_t adc;
|
||||
const char* name;
|
||||
} aux_ain[MAX_AUX_AIN];
|
||||
|
||||
|
||||
void aux_init(void)
|
||||
{
|
||||
// IN
|
||||
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLDOWN_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.pin_bit_mask = 0
|
||||
};
|
||||
|
||||
if (board_config.aux_in_1) {
|
||||
aux_in[aux_in_count].gpio = board_config.aux_in_1_gpio;
|
||||
aux_in[aux_in_count].name = board_config.aux_in_1_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_in_1_gpio);
|
||||
aux_in_count++;
|
||||
}
|
||||
|
||||
if (board_config.aux_in_2) {
|
||||
aux_in[aux_in_count].gpio = board_config.aux_in_2_gpio;
|
||||
aux_in[aux_in_count].name = board_config.aux_in_2_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_in_2_gpio);
|
||||
aux_in_count++;
|
||||
}
|
||||
|
||||
if (board_config.aux_in_3) {
|
||||
aux_in[aux_in_count].gpio = board_config.aux_in_3_gpio;
|
||||
aux_in[aux_in_count].name = board_config.aux_in_3_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_in_3_gpio);
|
||||
aux_in_count++;
|
||||
}
|
||||
|
||||
if (board_config.aux_in_4) {
|
||||
aux_in[aux_in_count].gpio = board_config.aux_in_4_gpio;
|
||||
aux_in[aux_in_count].name = board_config.aux_in_4_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_in_4_gpio);
|
||||
aux_in_count++;
|
||||
}
|
||||
|
||||
if (io_conf.pin_bit_mask > 0) {
|
||||
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||
}
|
||||
|
||||
// OUT
|
||||
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = 0;
|
||||
|
||||
if (board_config.aux_out_1) {
|
||||
aux_out[aux_out_count].gpio = board_config.aux_out_1_gpio;
|
||||
aux_out[aux_out_count].name = board_config.aux_out_1_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_out_1_gpio);
|
||||
aux_out_count++;
|
||||
}
|
||||
|
||||
if (board_config.aux_out_2) {
|
||||
aux_out[aux_out_count].gpio = board_config.aux_out_2_gpio;
|
||||
aux_out[aux_out_count].name = board_config.aux_out_2_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_out_2_gpio);
|
||||
aux_out_count++;
|
||||
}
|
||||
|
||||
if (board_config.aux_out_3) {
|
||||
aux_out[aux_out_count].gpio = board_config.aux_out_3_gpio;
|
||||
aux_out[aux_out_count].name = board_config.aux_out_3_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_out_3_gpio);
|
||||
aux_out_count++;
|
||||
}
|
||||
|
||||
if (board_config.aux_out_4) {
|
||||
aux_out[aux_out_count].gpio = board_config.aux_out_4_gpio;
|
||||
aux_out[aux_out_count].name = board_config.aux_out_4_name;
|
||||
io_conf.pin_bit_mask |= BIT64(board_config.aux_out_4_gpio);
|
||||
aux_out_count++;
|
||||
}
|
||||
|
||||
if (io_conf.pin_bit_mask > 0) {
|
||||
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||
}
|
||||
|
||||
// AIN
|
||||
|
||||
adc_oneshot_chan_cfg_t config = {
|
||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||
.atten = ADC_ATTEN_DB_12
|
||||
};
|
||||
|
||||
if (board_config.aux_ain_1) {
|
||||
aux_ain[aux_ain_count].adc = board_config.aux_ain_1_adc_channel;
|
||||
aux_ain[aux_ain_count].name = board_config.aux_out_1_name;
|
||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle, board_config.aux_ain_1_adc_channel, &config));
|
||||
aux_ain_count++;
|
||||
}
|
||||
|
||||
if (board_config.aux_ain_2) {
|
||||
aux_ain[aux_ain_count].adc = board_config.aux_ain_2_adc_channel;
|
||||
aux_ain[aux_ain_count].name = board_config.aux_out_2_name;
|
||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle, board_config.aux_ain_2_adc_channel, &config));
|
||||
aux_ain_count++;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t aux_read(const char* name, bool* value)
|
||||
{
|
||||
for (int i = 0; i < aux_in_count; i++) {
|
||||
if (strcmp(aux_in[i].name, name) == 0) {
|
||||
*value = gpio_get_level(aux_in[i].gpio) == 1;
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
esp_err_t aux_write(const char* name, bool value)
|
||||
{
|
||||
for (int i = 0; i < aux_out_count; i++) {
|
||||
if (strcmp(aux_out[i].name, name) == 0) {
|
||||
return gpio_set_level(aux_out[i].gpio, value);
|
||||
}
|
||||
}
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
esp_err_t aux_analog_read(const char* name, int* value)
|
||||
{
|
||||
for (int i = 0; i < aux_ain_count; i++) {
|
||||
if (strcmp(aux_ain[i].name, name) == 0) {
|
||||
int raw = 0;
|
||||
esp_err_t ret = adc_oneshot_read(adc_handle, aux_ain[i].adc, &raw);
|
||||
if (ret == ESP_OK) {
|
||||
return adc_cali_raw_to_voltage(adc_cali_handle, raw, value);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
// === Fim de: components/peripherals/src/aux_io.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/lm75a.c ===
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
|
||||
#define I2C_MASTER_NUM I2C_NUM_1
|
||||
#define I2C_MASTER_SCL_IO GPIO_NUM_22 // CONFIG_EXAMPLE_I2C_SCL /*!< gpio number for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO GPIO_NUM_21 // CONFIG_EXAMPLE_I2C_SDA /*!< gpio number for I2C master data */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // CONFIG_I2C_TRANS_SPEED /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||
#define LM75A_SLAVE_ADDR 0x48 // CONFIG_LM75A_SLAVE_ADDR /*!< LM75A slave address, you can set any 7bit value */
|
||||
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||
|
||||
/*
|
||||
#define GPIO_INPUT_IO_0 CONFIG_LM75A_OS_PIN
|
||||
#define GPIO_OUTPUT_IO_0 CONFIG_LM75A_VCC_PIN
|
||||
#define GPIO_OUTPUT_PIN_SEL (1ULL << GPIO_OUTPUT_IO_0)
|
||||
#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO_0)
|
||||
#define ESP_INTR_FLAG_DEFAULT 0
|
||||
*/
|
||||
|
||||
// static xQueueHandle gpio_evt_queue = NULL;
|
||||
// static int gpio_int_task_enable = 0;
|
||||
// static TaskHandle_t gpio_int_task_handle = NULL;
|
||||
|
||||
/**
|
||||
* @brief test code to read esp-i2c-slave
|
||||
* We need to fill the buffer of esp slave device, then master can read them out.
|
||||
*
|
||||
* _______________________________________________________________________________________
|
||||
* | start | slave_addr + rd_bit +ack | read n-1 bytes + ack | read 1 byte + nack | stop |
|
||||
* --------|--------------------------|----------------------|--------------------|------|
|
||||
*
|
||||
*/
|
||||
static esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t *data_rd, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (LM75A_SLAVE_ADDR << 1) | READ_BIT, ACK_CHECK_EN);
|
||||
if (size > 1)
|
||||
{
|
||||
i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
|
||||
}
|
||||
i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test code to write esp-i2c-slave
|
||||
* Master device write data to slave(both esp32),
|
||||
* the data will be stored in slave buffer.
|
||||
* We can read them out from slave buffer.
|
||||
*
|
||||
* ___________________________________________________________________
|
||||
* | start | slave_addr + wr_bit + ack | write n bytes + ack | stop |
|
||||
* --------|---------------------------|----------------------|------|
|
||||
*
|
||||
*/
|
||||
static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size)
|
||||
{
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (LM75A_SLAVE_ADDR << 1) | WRITE_BIT, ACK_CHECK_EN);
|
||||
i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief i2c master initialization
|
||||
*/
|
||||
static void i2c_master_init()
|
||||
{
|
||||
int i2c_master_port = I2C_MASTER_NUM;
|
||||
i2c_config_t conf;
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = I2C_MASTER_SDA_IO;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
|
||||
conf.scl_io_num = I2C_MASTER_SCL_IO;
|
||||
conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
|
||||
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
|
||||
conf.clk_flags = 0;
|
||||
|
||||
i2c_param_config(i2c_master_port, &conf);
|
||||
i2c_driver_install(i2c_master_port, conf.mode,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0);
|
||||
}
|
||||
|
||||
int lm75a_read_temperature(int show)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
float tmp;
|
||||
buf[0] = 0;
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, buf, 1);
|
||||
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2);
|
||||
tmp = buf[0];
|
||||
if (buf[1] & 128)
|
||||
tmp += 0.5;
|
||||
if (show)
|
||||
printf("lm75a_read_temperature=%.1f\n", tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
static void IRAM_ATTR gpio_isr_handler(void *arg)
|
||||
{
|
||||
uint32_t gpio_num = (uint32_t)arg;
|
||||
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
|
||||
}
|
||||
|
||||
static void gpio_int_task(void *arg)
|
||||
{
|
||||
uint32_t io_num;
|
||||
gpio_int_task_enable = 1;
|
||||
while (gpio_int_task_enable)
|
||||
{
|
||||
if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
|
||||
{
|
||||
|
||||
// read temperature to clean int;
|
||||
if (io_num == GPIO_INPUT_IO_0)
|
||||
{
|
||||
printf("GPIO[%d] intr, val: %d\n\n", io_num, gpio_get_level(io_num));
|
||||
lm75a_read_temperature(0); // read to clean interrupt.
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("quit gpio_int_task\n");
|
||||
if (gpio_evt_queue)
|
||||
{
|
||||
vQueueDelete(gpio_evt_queue);
|
||||
gpio_evt_queue = NULL;
|
||||
}
|
||||
gpio_int_task_handle = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void init_os_gpio()
|
||||
{
|
||||
printf("init_os_gpio!\n");
|
||||
|
||||
if (gpio_evt_queue == NULL)
|
||||
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
|
||||
|
||||
if (gpio_int_task_handle == NULL)
|
||||
{
|
||||
xTaskCreate(gpio_int_task, "gpio_int_task", 2048, NULL, 10, &gpio_int_task_handle);
|
||||
// install gpio isr service
|
||||
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
|
||||
// hook isr handler for specific gpio pin again
|
||||
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *)GPIO_INPUT_IO_0);
|
||||
}
|
||||
}
|
||||
|
||||
static void deinit_os_gpio()
|
||||
{
|
||||
printf("deinit_os_gpio!\n");
|
||||
|
||||
if (gpio_int_task_handle)
|
||||
{
|
||||
gpio_isr_handler_remove(GPIO_INPUT_IO_0);
|
||||
gpio_uninstall_isr_service();
|
||||
gpio_int_task_enable = 0;
|
||||
int io = 0;
|
||||
xQueueSend(gpio_evt_queue, &io, 0); // send a fake signal to quit task.
|
||||
}
|
||||
}
|
||||
|
||||
static void lm75a_vcc_enable()
|
||||
{
|
||||
gpio_config_t io_conf;
|
||||
// enable output for vcc
|
||||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
|
||||
io_conf.pull_down_en = 0;
|
||||
io_conf.pull_up_en = 0;
|
||||
gpio_config(&io_conf);
|
||||
|
||||
// enable input for interrupt
|
||||
io_conf.intr_type = GPIO_PIN_INTR_NEGEDGE; // GPIO_PIN_INTR_ANYEDGE;
|
||||
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_up_en = 1;
|
||||
gpio_set_pull_mode(GPIO_INPUT_IO_0, GPIO_FLOATING);
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(GPIO_OUTPUT_IO_0, 1);
|
||||
}
|
||||
|
||||
static void lm75a_vcc_disable()
|
||||
{
|
||||
gpio_set_level(GPIO_OUTPUT_IO_0, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
void lm75a_init()
|
||||
{
|
||||
// lm75a_vcc_enable();
|
||||
i2c_master_init();
|
||||
}
|
||||
|
||||
void lm75a_deinit()
|
||||
{
|
||||
// deinit_os_gpio();
|
||||
i2c_driver_delete(I2C_MASTER_NUM);
|
||||
// lm75a_vcc_disable();
|
||||
}
|
||||
|
||||
void lm75a_set_tos(int tos)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
printf("lm75a_set_tos: %d\n", tos);
|
||||
// set Tos:
|
||||
buf[0] = 0x3;
|
||||
buf[1] = (tos & 0xff);
|
||||
buf[2] = 0;
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, buf, 3);
|
||||
}
|
||||
|
||||
void lm75a_set_thys(int thys)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
printf("lm75a_set_thys: %d\n", thys);
|
||||
// set Thyst:
|
||||
buf[0] = 0x2;
|
||||
buf[1] = (thys & 0xff);
|
||||
buf[2] = 0;
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, buf, 3);
|
||||
}
|
||||
|
||||
void lm75a_get_tos()
|
||||
{
|
||||
uint8_t buf[4];
|
||||
float tmp;
|
||||
buf[0] = 0x3;
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, buf, 1);
|
||||
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2);
|
||||
tmp = buf[0];
|
||||
if (buf[1] & 128)
|
||||
tmp += 0.5;
|
||||
|
||||
printf("lm75a_get_tos: %.1f\n", tmp);
|
||||
}
|
||||
|
||||
void lm75a_get_thys()
|
||||
{
|
||||
uint8_t buf[4];
|
||||
float tmp;
|
||||
buf[0] = 0x2;
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, buf, 1);
|
||||
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2);
|
||||
tmp = buf[0];
|
||||
if (buf[1] & 128)
|
||||
tmp += 0.5;
|
||||
|
||||
printf("lm75a_get_thys: %.1f\n", tmp);
|
||||
}
|
||||
|
||||
void lm75a_set_int(int en)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
|
||||
en = !!en;
|
||||
if (en)
|
||||
{
|
||||
printf("lm75a_set_int: %d\n", en);
|
||||
buf[0] = 0x1;
|
||||
buf[1] = (1 << 1); // D1 set to 1;
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, buf, 2);
|
||||
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2); // do one time read to clean interrupt before enter interrupt mode.
|
||||
// gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_NEGEDGE);
|
||||
// init_os_gpio();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("lm75a_set_int: %d\n", en);
|
||||
// deinit_os_gpio();
|
||||
buf[0] = 0x1;
|
||||
buf[1] = 0;
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, buf, 2);
|
||||
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2); // do one time read to clean interrupt before enter interrupt mode.
|
||||
}
|
||||
}
|
||||
|
||||
void lm75a_get_osio()
|
||||
{
|
||||
// printf("os_io: %d\n", gpio_get_level(GPIO_INPUT_IO_0));
|
||||
}
|
||||
|
||||
// === Fim de: components/peripherals/src/lm75a.c ===
|
||||
783
projeto_parte8.c
783
projeto_parte8.c
@@ -1,783 +0,0 @@
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/onewire.c ===
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 zeroday nodemcu.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
* -------------------------------------------------------------------------------
|
||||
* Portions copyright (C) 2000 Dallas Semiconductor Corporation, under the
|
||||
* following additional terms:
|
||||
*
|
||||
* Except as contained in this notice, the name of Dallas Semiconductor
|
||||
* shall not be used except as stated in the Dallas Semiconductor
|
||||
* Branding Policy.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
#include "onewire.h"
|
||||
|
||||
#define ONEWIRE_SELECT_ROM 0x55
|
||||
#define ONEWIRE_SKIP_ROM 0xcc
|
||||
#define ONEWIRE_SEARCH 0xf0
|
||||
#define ONEWIRE_CRC8_TABLE
|
||||
|
||||
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
// Waits up to `max_wait` microseconds for the specified pin to go high.
|
||||
// Returns true if successful, false if the bus never comes high (likely
|
||||
// shorted).
|
||||
static inline bool _onewire_wait_for_bus(gpio_num_t pin, int max_wait)
|
||||
{
|
||||
bool state;
|
||||
for (int i = 0; i < ((max_wait + 4) / 5); i++) {
|
||||
if (gpio_get_level(pin))
|
||||
break;
|
||||
ets_delay_us(5);
|
||||
}
|
||||
state = gpio_get_level(pin);
|
||||
// Wait an extra 1us to make sure the devices have an adequate recovery
|
||||
// time before we drive things low again.
|
||||
ets_delay_us(1);
|
||||
return state;
|
||||
}
|
||||
|
||||
static void setup_pin(gpio_num_t pin, bool open_drain)
|
||||
{
|
||||
gpio_set_direction(pin, open_drain ? GPIO_MODE_INPUT_OUTPUT_OD : GPIO_MODE_OUTPUT);
|
||||
// gpio_set_pull_mode(pin, GPIO_PULLUP_ONLY);
|
||||
}
|
||||
|
||||
// Perform the onewire reset function. We will wait up to 250uS for
|
||||
// the bus to come high, if it doesn't then it is broken or shorted
|
||||
// and we return false;
|
||||
//
|
||||
// Returns true if a device asserted a presence pulse, false otherwise.
|
||||
//
|
||||
bool onewire_reset(gpio_num_t pin)
|
||||
{
|
||||
setup_pin(pin, true);
|
||||
|
||||
gpio_set_level(pin, 1);
|
||||
// wait until the wire is high... just in case
|
||||
if (!_onewire_wait_for_bus(pin, 250))
|
||||
return false;
|
||||
|
||||
gpio_set_level(pin, 0);
|
||||
ets_delay_us(480);
|
||||
|
||||
portENTER_CRITICAL(&mux);
|
||||
gpio_set_level(pin, 1); // allow it to float
|
||||
ets_delay_us(70);
|
||||
bool r = !gpio_get_level(pin);
|
||||
portEXIT_CRITICAL(&mux);
|
||||
|
||||
// Wait for all devices to finish pulling the bus low before returning
|
||||
if (!_onewire_wait_for_bus(pin, 410))
|
||||
return false;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool _onewire_write_bit(gpio_num_t pin, bool v)
|
||||
{
|
||||
if (!_onewire_wait_for_bus(pin, 10))
|
||||
return false;
|
||||
|
||||
portENTER_CRITICAL(&mux);
|
||||
if (v) {
|
||||
gpio_set_level(pin, 0); // drive output low
|
||||
ets_delay_us(10);
|
||||
gpio_set_level(pin, 1); // allow output high
|
||||
ets_delay_us(55);
|
||||
} else {
|
||||
gpio_set_level(pin, 0); // drive output low
|
||||
ets_delay_us(65);
|
||||
gpio_set_level(pin, 1); // allow output high
|
||||
}
|
||||
ets_delay_us(1);
|
||||
portEXIT_CRITICAL(&mux);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int _onewire_read_bit(gpio_num_t pin)
|
||||
{
|
||||
if (!_onewire_wait_for_bus(pin, 10))
|
||||
return -1;
|
||||
|
||||
portENTER_CRITICAL(&mux);
|
||||
gpio_set_level(pin, 0);
|
||||
ets_delay_us(2);
|
||||
gpio_set_level(pin, 1); // let pin float, pull up will raise
|
||||
ets_delay_us(11);
|
||||
int r = gpio_get_level(pin); // Must sample within 15us of start
|
||||
ets_delay_us(48);
|
||||
portEXIT_CRITICAL(&mux);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Write a byte. The writing code uses open-drain mode and expects the pullup
|
||||
// resistor to pull the line high when not driven low. If you need strong
|
||||
// power after the write (e.g. DS18B20 in parasite power mode) then call
|
||||
// onewire_power() after this is complete to actively drive the line high.
|
||||
//
|
||||
bool onewire_write(gpio_num_t pin, uint8_t v)
|
||||
{
|
||||
for (uint8_t bitMask = 0x01; bitMask; bitMask <<= 1)
|
||||
if (!_onewire_write_bit(pin, (bitMask & v)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onewire_write_bytes(gpio_num_t pin, const uint8_t* buf, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
if (!onewire_write(pin, buf[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read a byte
|
||||
//
|
||||
int onewire_read(gpio_num_t pin)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
for (uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) {
|
||||
int bit = _onewire_read_bit(pin);
|
||||
if (bit < 0)
|
||||
return -1;
|
||||
else if (bit)
|
||||
r |= bitMask;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool onewire_read_bytes(gpio_num_t pin, uint8_t* buf, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
int b;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
b = onewire_read(pin);
|
||||
if (b < 0)
|
||||
return false;
|
||||
buf[i] = b;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onewire_select(gpio_num_t pin, onewire_addr_t addr)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (!onewire_write(pin, ONEWIRE_SELECT_ROM))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (!onewire_write(pin, addr & 0xff))
|
||||
return false;
|
||||
addr >>= 8;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onewire_skip_rom(gpio_num_t pin)
|
||||
{
|
||||
return onewire_write(pin, ONEWIRE_SKIP_ROM);
|
||||
}
|
||||
|
||||
bool onewire_power(gpio_num_t pin)
|
||||
{
|
||||
// Make sure the bus is not being held low before driving it high, or we
|
||||
// may end up shorting ourselves out.
|
||||
if (!_onewire_wait_for_bus(pin, 10))
|
||||
return false;
|
||||
|
||||
setup_pin(pin, false);
|
||||
gpio_set_level(pin, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void onewire_depower(gpio_num_t pin)
|
||||
{
|
||||
setup_pin(pin, true);
|
||||
}
|
||||
|
||||
void onewire_search_start(onewire_search_t* search)
|
||||
{
|
||||
// reset the search state
|
||||
memset(search, 0, sizeof(*search));
|
||||
}
|
||||
|
||||
void onewire_search_prefix(onewire_search_t* search, uint8_t family_code)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
search->rom_no[0] = family_code;
|
||||
for (i = 1; i < 8; i++) {
|
||||
search->rom_no[i] = 0;
|
||||
}
|
||||
search->last_discrepancy = 64;
|
||||
search->last_device_found = false;
|
||||
}
|
||||
|
||||
// Perform a search. If the next device has been successfully enumerated, its
|
||||
// ROM address will be returned. If there are no devices, no further
|
||||
// devices, or something horrible happens in the middle of the
|
||||
// enumeration then ONEWIRE_NONE is returned. Use OneWire::reset_search() to
|
||||
// start over.
|
||||
//
|
||||
// --- Replaced by the one from the Dallas Semiconductor web site ---
|
||||
//--------------------------------------------------------------------------
|
||||
// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
|
||||
// search state.
|
||||
// Return 1 : device found, ROM number in ROM_NO buffer
|
||||
// 0 : device not found, end of search
|
||||
//
|
||||
onewire_addr_t onewire_search_next(onewire_search_t* search, gpio_num_t pin)
|
||||
{
|
||||
//TODO: add more checking for read/write errors
|
||||
uint8_t id_bit_number;
|
||||
uint8_t last_zero, search_result;
|
||||
int rom_byte_number;
|
||||
int8_t id_bit, cmp_id_bit;
|
||||
onewire_addr_t addr;
|
||||
unsigned char rom_byte_mask;
|
||||
bool search_direction;
|
||||
|
||||
// initialize for search
|
||||
id_bit_number = 1;
|
||||
last_zero = 0;
|
||||
rom_byte_number = 0;
|
||||
rom_byte_mask = 1;
|
||||
search_result = 0;
|
||||
|
||||
// if the last call was not the last one
|
||||
if (!search->last_device_found) {
|
||||
// 1-Wire reset
|
||||
if (!onewire_reset(pin)) {
|
||||
// reset the search
|
||||
search->last_discrepancy = 0;
|
||||
search->last_device_found = false;
|
||||
return ONEWIRE_NONE;
|
||||
}
|
||||
|
||||
// issue the search command
|
||||
onewire_write(pin, ONEWIRE_SEARCH);
|
||||
|
||||
// loop to do the search
|
||||
do {
|
||||
// read a bit and its complement
|
||||
id_bit = _onewire_read_bit(pin);
|
||||
cmp_id_bit = _onewire_read_bit(pin);
|
||||
|
||||
if ((id_bit == 1) && (cmp_id_bit == 1))
|
||||
break;
|
||||
else {
|
||||
// all devices coupled have 0 or 1
|
||||
if (id_bit != cmp_id_bit)
|
||||
search_direction = id_bit; // bit write value for search
|
||||
else {
|
||||
// if this discrepancy if before the Last Discrepancy
|
||||
// on a previous next then pick the same as last time
|
||||
if (id_bit_number < search->last_discrepancy)
|
||||
search_direction = ((search->rom_no[rom_byte_number] & rom_byte_mask) > 0);
|
||||
else
|
||||
// if equal to last pick 1, if not then pick 0
|
||||
search_direction = (id_bit_number == search->last_discrepancy);
|
||||
|
||||
// if 0 was picked then record its position in LastZero
|
||||
if (!search_direction)
|
||||
last_zero = id_bit_number;
|
||||
}
|
||||
|
||||
// set or clear the bit in the ROM byte rom_byte_number
|
||||
// with mask rom_byte_mask
|
||||
if (search_direction)
|
||||
search->rom_no[rom_byte_number] |= rom_byte_mask;
|
||||
else
|
||||
search->rom_no[rom_byte_number] &= ~rom_byte_mask;
|
||||
|
||||
// serial number search direction write bit
|
||||
_onewire_write_bit(pin, search_direction);
|
||||
|
||||
// increment the byte counter id_bit_number
|
||||
// and shift the mask rom_byte_mask
|
||||
id_bit_number++;
|
||||
rom_byte_mask <<= 1;
|
||||
|
||||
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
|
||||
if (rom_byte_mask == 0) {
|
||||
rom_byte_number++;
|
||||
rom_byte_mask = 1;
|
||||
}
|
||||
}
|
||||
} while (rom_byte_number < 8); // loop until through all ROM bytes 0-7
|
||||
|
||||
// if the search was successful then
|
||||
if (!(id_bit_number < 65)) {
|
||||
// search successful so set last_discrepancy,last_device_found,search_result
|
||||
search->last_discrepancy = last_zero;
|
||||
|
||||
// check for last device
|
||||
if (search->last_discrepancy == 0)
|
||||
search->last_device_found = true;
|
||||
|
||||
search_result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if no device found then reset counters so next 'search' will be like a first
|
||||
if (!search_result || !search->rom_no[0]) {
|
||||
search->last_discrepancy = 0;
|
||||
search->last_device_found = false;
|
||||
return ONEWIRE_NONE;
|
||||
} else {
|
||||
addr = 0;
|
||||
for (rom_byte_number = 7; rom_byte_number >= 0; rom_byte_number--) {
|
||||
addr = (addr << 8) | search->rom_no[rom_byte_number];
|
||||
}
|
||||
//printf("Ok I found something at %08x%08x...\n", (uint32_t)(addr >> 32), (uint32_t)addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
// The 1-Wire CRC scheme is described in Maxim Application Note 27:
|
||||
// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
|
||||
//
|
||||
|
||||
#ifdef ONEWIRE_CRC8_TABLE
|
||||
// This table comes from Dallas sample code where it is freely reusable,
|
||||
// though Copyright (c) 2000 Dallas Semiconductor Corporation
|
||||
static const uint8_t dscrc_table[] = {
|
||||
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
|
||||
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
|
||||
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
|
||||
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
|
||||
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
|
||||
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
|
||||
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
|
||||
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
|
||||
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
|
||||
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
|
||||
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
|
||||
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
|
||||
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
|
||||
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
|
||||
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
|
||||
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
|
||||
};
|
||||
|
||||
//
|
||||
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
|
||||
// and the registers. (note: this might better be done without to
|
||||
// table, it would probably be smaller and certainly fast enough
|
||||
// compared to all those delayMicrosecond() calls. But I got
|
||||
// confused, so I use this table from the examples.)
|
||||
//
|
||||
uint8_t onewire_crc8(const uint8_t* data, uint8_t len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
|
||||
while (len--)
|
||||
crc = dscrc_table[crc ^ *data++];
|
||||
|
||||
return crc;
|
||||
}
|
||||
#else
|
||||
//
|
||||
// Compute a Dallas Semiconductor 8 bit CRC directly.
|
||||
// this is much slower, but much smaller, than the lookup table.
|
||||
//
|
||||
uint8_t onewire_crc8(const uint8_t* data, uint8_t len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
uint8_t inbyte = *data++;
|
||||
for (int i = 8; i; i--)
|
||||
{
|
||||
uint8_t mix = (crc ^ inbyte) & 0x01;
|
||||
crc >>= 1;
|
||||
if (mix)
|
||||
crc ^= 0x8C;
|
||||
inbyte >>= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
#endif /* ONEWIRE_CRC8_TABLE */
|
||||
|
||||
// Compute the 1-Wire CRC16 and compare it against the received CRC.
|
||||
// Example usage (reading a DS2408):
|
||||
// // Put everything in a buffer so we can compute the CRC easily.
|
||||
// uint8_t buf[13];
|
||||
// buf[0] = 0xF0; // Read PIO Registers
|
||||
// buf[1] = 0x88; // LSB address
|
||||
// buf[2] = 0x00; // MSB address
|
||||
// WriteBytes(net, buf, 3); // Write 3 cmd bytes
|
||||
// ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16
|
||||
// if (!CheckCRC16(buf, 11, &buf[11])) {
|
||||
// // Handle error.
|
||||
// }
|
||||
//
|
||||
// @param input - Array of bytes to checksum.
|
||||
// @param len - How many bytes to use.
|
||||
// @param inverted_crc - The two CRC16 bytes in the received data.
|
||||
// This should just point into the received data,
|
||||
// *not* at a 16-bit integer.
|
||||
// @param crc - The crc starting value (optional)
|
||||
// @return 1, iff the CRC matches.
|
||||
bool onewire_check_crc16(const uint8_t* input, size_t len, const uint8_t* inverted_crc, uint16_t crc_iv)
|
||||
{
|
||||
uint16_t crc = ~onewire_crc16(input, len, crc_iv);
|
||||
return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
|
||||
}
|
||||
|
||||
// Compute a Dallas Semiconductor 16 bit CRC. This is required to check
|
||||
// the integrity of data received from many 1-Wire devices. Note that the
|
||||
// CRC computed here is *not* what you'll get from the 1-Wire network,
|
||||
// for two reasons:
|
||||
// 1) The CRC is transmitted bitwise inverted.
|
||||
// 2) Depending on the endian-ness of your processor, the binary
|
||||
// representation of the two-byte return value may have a different
|
||||
// byte order than the two bytes you get from 1-Wire.
|
||||
// @param input - Array of bytes to checksum.
|
||||
// @param len - How many bytes to use.
|
||||
// @param crc - The crc starting value (optional)
|
||||
// @return The CRC16, as defined by Dallas Semiconductor.
|
||||
uint16_t onewire_crc16(const uint8_t* input, size_t len, uint16_t crc_iv)
|
||||
{
|
||||
uint16_t crc = crc_iv;
|
||||
static const uint8_t oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
|
||||
|
||||
uint16_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
// Even though we're just copying a byte from the input,
|
||||
// we'll be doing 16-bit computation with it.
|
||||
uint16_t cdata = input[i];
|
||||
cdata = (cdata ^ crc) & 0xff;
|
||||
crc >>= 8;
|
||||
|
||||
if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
|
||||
crc ^= 0xC001;
|
||||
|
||||
cdata <<= 6;
|
||||
crc ^= cdata;
|
||||
cdata <<= 1;
|
||||
crc ^= cdata;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
// === Fim de: components/peripherals/src/onewire.c ===
|
||||
|
||||
|
||||
// === Início de: components/peripherals/src/onewire.h ===
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 zeroday nodemcu.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
* -------------------------------------------------------------------------------
|
||||
* Portions copyright (C) 2000 Dallas Semiconductor Corporation, under the
|
||||
* following additional terms:
|
||||
*
|
||||
* Except as contained in this notice, the name of Dallas Semiconductor
|
||||
* shall not be used except as stated in the Dallas Semiconductor
|
||||
* Branding Policy.
|
||||
*/
|
||||
|
||||
#ifndef ONEWIRE_H_
|
||||
#define ONEWIRE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "driver/gpio.h"
|
||||
|
||||
/**
|
||||
* Type used to hold all 1-Wire device ROM addresses (64-bit)
|
||||
*/
|
||||
typedef uint64_t onewire_addr_t;
|
||||
|
||||
/**
|
||||
* Structure to contain the current state for onewire_search_next(), etc
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t rom_no[8];
|
||||
uint8_t last_discrepancy;
|
||||
bool last_device_found;
|
||||
} onewire_search_t;
|
||||
|
||||
/**
|
||||
* ::ONEWIRE_NONE is an invalid ROM address that will never occur in a device
|
||||
* (CRC mismatch), and so can be useful as an indicator for "no-such-device",
|
||||
* etc.
|
||||
*/
|
||||
#define ONEWIRE_NONE ((onewire_addr_t)(0xffffffffffffffffLL))
|
||||
|
||||
/**
|
||||
* @brief Perform a 1-Wire reset cycle.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
*
|
||||
* @return `true` if at least one device responds with a presence pulse,
|
||||
* `false` if no devices were detected (or the bus is shorted, etc)
|
||||
*/
|
||||
bool onewire_reset(gpio_num_t pin);
|
||||
|
||||
/**
|
||||
* @brief Issue a 1-Wire "ROM select" command to select a particular device.
|
||||
*
|
||||
* It is necessary to call ::onewire_reset() before calling this function.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
* @param addr The ROM address of the device to select
|
||||
*
|
||||
* @return `true` if the "ROM select" command could be successfully issued,
|
||||
* `false` if there was an error.
|
||||
*/
|
||||
bool onewire_select(gpio_num_t pin, const onewire_addr_t addr);
|
||||
|
||||
/**
|
||||
* @brief Issue a 1-Wire "skip ROM" command to select *all* devices on the bus.
|
||||
*
|
||||
* It is necessary to call ::onewire_reset() before calling this function.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
*
|
||||
* @return `true` if the "skip ROM" command could be successfully issued,
|
||||
* `false` if there was an error.
|
||||
*/
|
||||
bool onewire_skip_rom(gpio_num_t pin);
|
||||
|
||||
/**
|
||||
* @brief Write a byte on the onewire bus.
|
||||
*
|
||||
* The writing code uses open-drain mode and expects the pullup resistor to
|
||||
* pull the line high when not driven low. If you need strong power after the
|
||||
* write (e.g. DS18B20 in parasite power mode) then call ::onewire_power()
|
||||
* after this is complete to actively drive the line high.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
* @param v The byte value to write
|
||||
*
|
||||
* @return `true` if successful, `false` on error.
|
||||
*/
|
||||
bool onewire_write(gpio_num_t pin, uint8_t v);
|
||||
|
||||
/**
|
||||
* @brief Write multiple bytes on the 1-Wire bus.
|
||||
*
|
||||
* See ::onewire_write() for more info.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
* @param buf A pointer to the buffer of bytes to be written
|
||||
* @param count Number of bytes to write
|
||||
*
|
||||
* @return `true` if all bytes written successfully, `false` on error.
|
||||
*/
|
||||
bool onewire_write_bytes(gpio_num_t pin, const uint8_t *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Read a byte from a 1-Wire device.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
*
|
||||
* @return the read byte on success, negative value on error.
|
||||
*/
|
||||
int onewire_read(gpio_num_t pin);
|
||||
|
||||
/**
|
||||
* @brief Read multiple bytes from a 1-Wire device.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
* @param[out] buf A pointer to the buffer to contain the read bytes
|
||||
* @param count Number of bytes to read
|
||||
*
|
||||
* @return `true` on success, `false` on error.
|
||||
*/
|
||||
bool onewire_read_bytes(gpio_num_t pin, uint8_t *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Actively drive the bus high to provide extra power for certain
|
||||
* operations of parasitically-powered devices.
|
||||
*
|
||||
* For parasitically-powered devices which need more power than can be
|
||||
* provided via the normal pull-up resistor, it may be necessary for some
|
||||
* operations to drive the bus actively high. This function can be used to
|
||||
* perform that operation.
|
||||
*
|
||||
* The bus can be depowered once it is no longer needed by calling
|
||||
* ::onewire_depower(), or it will be depowered automatically the next time
|
||||
* ::onewire_reset() is called to start another command.
|
||||
*
|
||||
* @note Make sure the device(s) you are powering will not pull more current
|
||||
* than the ESP32/ESP8266 is able to supply via its GPIO pins (this is
|
||||
* especially important when multiple devices are on the same bus and
|
||||
* they are all performing a power-intensive operation at the same time
|
||||
* (i.e. multiple DS18B20 sensors, which have all been given a
|
||||
* "convert T" operation by using ::onewire_skip_rom())).
|
||||
*
|
||||
* @note This routine will check to make sure that the bus is already high
|
||||
* before driving it, to make sure it doesn't attempt to drive it high
|
||||
* while something else is pulling it low (which could cause a reset or
|
||||
* damage the ESP32/ESP8266).
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
*
|
||||
* @return `true` on success, `false` on error.
|
||||
*/
|
||||
bool onewire_power(gpio_num_t pin);
|
||||
|
||||
/**
|
||||
* @brief Stop forcing power onto the bus.
|
||||
*
|
||||
* You only need to do this if you previously called ::onewire_power() to drive
|
||||
* the bus high and now want to allow it to float instead. Note that
|
||||
* onewire_reset() will also automatically depower the bus first, so you do
|
||||
* not need to call this first if you just want to start a new operation.
|
||||
*
|
||||
* @param pin The GPIO pin connected to the 1-Wire bus.
|
||||
*/
|
||||
void onewire_depower(gpio_num_t pin);
|
||||
|
||||
/**
|
||||
* @brief Clear the search state so that it will start from the beginning on
|
||||
* the next call to ::onewire_search_next().
|
||||
*
|
||||
* @param[out] search The onewire_search_t structure to reset.
|
||||
*/
|
||||
void onewire_search_start(onewire_search_t *search);
|
||||
|
||||
/**
|
||||
* @brief Setup the search to search for devices with the specified
|
||||
* "family code".
|
||||
*
|
||||
* @param[out] search The onewire_search_t structure to update.
|
||||
* @param family_code The "family code" to search for.
|
||||
*/
|
||||
void onewire_search_prefix(onewire_search_t *search, uint8_t family_code);
|
||||
|
||||
/**
|
||||
* @brief Search for the next device on the bus.
|
||||
*
|
||||
* The order of returned device addresses is deterministic. You will always
|
||||
* get the same devices in the same order.
|
||||
*
|
||||
* @note It might be a good idea to check the CRC to make sure you didn't get
|
||||
* garbage.
|
||||
*
|
||||
* @return the address of the next device on the bus, or ::ONEWIRE_NONE if
|
||||
* there is no next address. ::ONEWIRE_NONE might also mean that
|
||||
* the bus is shorted, there are no devices, or you have already
|
||||
* retrieved all of them.
|
||||
*/
|
||||
onewire_addr_t onewire_search_next(onewire_search_t *search, gpio_num_t pin);
|
||||
|
||||
/**
|
||||
* @brief Compute a Dallas Semiconductor 8 bit CRC.
|
||||
*
|
||||
* These are used in the ROM address and scratchpad registers to verify the
|
||||
* transmitted data is correct.
|
||||
*/
|
||||
uint8_t onewire_crc8(const uint8_t *data, uint8_t len);
|
||||
|
||||
/**
|
||||
* @brief Compute the 1-Wire CRC16 and compare it against the received CRC.
|
||||
*
|
||||
* Example usage (reading a DS2408):
|
||||
* @code{.c}
|
||||
* // Put everything in a buffer so we can compute the CRC easily.
|
||||
* uint8_t buf[13];
|
||||
* buf[0] = 0xF0; // Read PIO Registers
|
||||
* buf[1] = 0x88; // LSB address
|
||||
* buf[2] = 0x00; // MSB address
|
||||
* onewire_write_bytes(pin, buf, 3); // Write 3 cmd bytes
|
||||
* onewire_read_bytes(pin, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16
|
||||
* if (!onewire_check_crc16(buf, 11, &buf[11])) {
|
||||
* // TODO: Handle error.
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param input Array of bytes to checksum.
|
||||
* @param len Number of bytes in `input`
|
||||
* @param inverted_crc The two CRC16 bytes in the received data.
|
||||
* This should just point into the received data,
|
||||
* *not* at a 16-bit integer.
|
||||
* @param crc_iv The crc starting value (optional)
|
||||
*
|
||||
* @return `true` if the CRC matches, `false` otherwise.
|
||||
*/
|
||||
bool onewire_check_crc16(const uint8_t* input, size_t len, const uint8_t* inverted_crc, uint16_t crc_iv);
|
||||
|
||||
/**
|
||||
* @brief Compute a Dallas Semiconductor 16 bit CRC.
|
||||
*
|
||||
* This is required to check the integrity of data received from many 1-Wire
|
||||
* devices. Note that the CRC computed here is *not* what you'll get from the
|
||||
* 1-Wire network, for two reasons:
|
||||
*
|
||||
* 1. The CRC is transmitted bitwise inverted.
|
||||
* 2. Depending on the endian-ness of your processor, the binary
|
||||
* representation of the two-byte return value may have a different
|
||||
* byte order than the two bytes you get from 1-Wire.
|
||||
*
|
||||
* @param input Array of bytes to checksum.
|
||||
* @param len How many bytes are in `input`.
|
||||
* @param crc_iv The crc starting value (optional)
|
||||
*
|
||||
* @return the CRC16, as defined by Dallas Semiconductor.
|
||||
*/
|
||||
uint16_t onewire_crc16(const uint8_t* input, size_t len, uint16_t crc_iv);
|
||||
|
||||
|
||||
#endif /* ONEWIRE_H_ */
|
||||
// === Fim de: components/peripherals/src/onewire.h ===
|
||||
1232
projeto_parte9.c
1232
projeto_parte9.c
File diff suppressed because it is too large
Load Diff
8613
projeto_unificado.c
8613
projeto_unificado.c
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
|
||||
TAMANHO_MAX = 31000 # Limite por arquivo
|
||||
TAMANHO_MAX = 100000 # Limite por arquivo
|
||||
|
||||
def coletar_arquivos(diretorios, extensoes=(".c", ".h")):
|
||||
arquivos = []
|
||||
@@ -15,7 +15,7 @@ def coletar_arquivos(diretorios, extensoes=(".c", ".h")):
|
||||
|
||||
def unir_em_partes(arquivos, prefixo="projeto_parte", limite=TAMANHO_MAX):
|
||||
parte = 1
|
||||
conteudo_atual = ""
|
||||
conteudo_atual = "."
|
||||
total_arquivos = 0
|
||||
|
||||
for arquivo in arquivos:
|
||||
@@ -53,8 +53,7 @@ def unir_em_partes(arquivos, prefixo="projeto_parte", limite=TAMANHO_MAX):
|
||||
def main():
|
||||
diretorio_main = "main"
|
||||
componentes_escolhidos = [
|
||||
"evse", "loadbalancer", "auth", "manager_meter",
|
||||
"rest_api", "network", "peripherals"
|
||||
"peripherals" , "meter_manager"
|
||||
]
|
||||
|
||||
diretorios_componentes = [os.path.join("components", nome) for nome in componentes_escolhidos]
|
||||
|
||||
Reference in New Issue
Block a user