#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "driver/adc.h"
#include "driver/gpio.h"
#include "esp_http_server.h"
#include "cJSON.h"
// Pin definitions
#define DHT_PIN 4
#define MOISTURE_ADC ADC1_CHANNEL_0 // GPIO36
#define FERTILITY_ADC ADC1_CHANNEL_3 // GPIO39
#define WATER_SENSOR_PIN 34
#define RELAY_PIN 2
// WiFi credentials
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASS ""
// Global variables
float g_temperature = 0;
float g_humidity = 0;
int g_moisture = 0;
int g_fertility = 0;
float g_water_level = 0;
static const char *TAG = "main";
// DHT22 simulation function (for Wokwi)
static int read_dht22(float *temp, float *humid) {
*temp = 20.0 + (esp_random() % 100) / 10.0;
*humid = 50.0 + (esp_random() % 300) / 10.0;
return 0;
}
// WiFi event handler
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect();
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
}
}
// Initialize WiFi
static void wifi_init(void) {
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&wifi_event_handler,
NULL,
NULL));
wifi_config_t wifi_config = {
.sta = {
.ssid = WIFI_SSID,
.password = WIFI_PASS,
.threshold.authmode = WIFI_AUTH_OPEN,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
}
// HTTP GET handler for /api/data
static esp_err_t get_data_handler(httpd_req_t *req) {
char response[512];
cJSON *root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "temperature", g_temperature);
cJSON_AddNumberToObject(root, "humidity", g_humidity);
cJSON_AddNumberToObject(root, "moisture", g_moisture);
cJSON_AddNumberToObject(root, "fertility", g_fertility);
cJSON_AddNumberToObject(root, "water_level", g_water_level);
const char *json_string = cJSON_Print(root);
snprintf(response, sizeof(response), "%s", json_string);
httpd_resp_set_type(req, "application/json");
httpd_resp_send(req, response, strlen(response));
cJSON_Delete(root);
free((void*)json_string);
return ESP_OK;
}
// URI structure for the data endpoint
static const httpd_uri_t data_uri = {
.uri = "/api/data",
.method = HTTP_GET,
.handler = get_data_handler,
.user_ctx = NULL
};
// Start the web server
static httpd_handle_t start_webserver(void) {
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.lru_purge_enable = true;
if (httpd_start(&server, &config) == ESP_OK) {
httpd_register_uri_handler(server, &data_uri);
}
return server;
}
// Main application entry point
void app_main(void) {
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Configure ADC channels (Note: ADC_ATTEN_DB_11 is deprecated but works)
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(MOISTURE_ADC, ADC_ATTEN_DB_11);
adc1_config_channel_atten(FERTILITY_ADC, ADC_ATTEN_DB_11);
// Configure water sensor pin as input
gpio_set_direction(WATER_SENSOR_PIN, GPIO_MODE_INPUT);
// Configure relay pin as output
gpio_set_direction(RELAY_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(RELAY_PIN, 0);
// Connect to WiFi
wifi_init();
// Start web server
httpd_handle_t server = start_webserver();
// Main loop
while (1) {
// Read sensors
read_dht22(&g_temperature, &g_humidity);
g_moisture = adc1_get_raw(MOISTURE_ADC);
g_fertility = adc1_get_raw(FERTILITY_ADC);
g_water_level = gpio_get_level(WATER_SENSOR_PIN) ? 0 : 100;
// Simple relay control based on moisture
if (g_moisture < 2000) {
gpio_set_level(RELAY_PIN, 1); // Turn on pump
} else {
gpio_set_level(RELAY_PIN, 0); // Turn off pump
}
ESP_LOGI(TAG, "Temp: %.1f, Hum: %.1f, Moisture: %d, Fertility: %d, Water: %.1f",
g_temperature, g_humidity, g_moisture, g_fertility, g_water_level);
vTaskDelay(pdMS_TO_TICKS(5000));
}
}