#include <stdio.h>
#include <stdbool.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_err.h>
#include "freertos/semphr.h"
#include "ultrasonic.h"
#include "esp_system.h"
#include <string.h> //strlen
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
//PROTÓTIPO DE FUNÇÕES=====================================================================
void app_main(void);
void setup();
void task_ultrasonic_test(void *pvParameters);
void task_control_leds(void *pvParameters);
void tcp_client(void *pvParameters);
void task_i_am_alive(void *pvParameters);
void wifi_connect();
//DEFINIÇÕES E CONSTATNTES=================================================================
#define delay(value) vTaskDelay(value/portTICK_PERIOD_MS)
#define ECHO_GPIO 12
#define TRIGGER_GPIO 13
#define MAX_DISTANCE_CM 500 // Maximum of 5 meters
#define LED_VERD GPIO_NUM_23
#define LED_AMAR GPIO_NUM_19
#define LED_VERM GPIO_NUM_4
enum estados_led {VERM, AMAR, VERD, INIC};
#define SSID "Wokwi-GUEST"
#define PASSPHARSE ""
#define TCPServerIP "159.203.79.141"
#define PORT 50000
#define ALIVE "alive"
static const char *id = "201811250039";
static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
static const char *TAG="tcp_client";
//MÁSCARA PARA SAÍDAS====================================================================
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<LED_VERD) | (1ULL<<LED_AMAR) | (1ULL<<LED_VERM))
//VARIÁVEIS==============================================================================
static TaskHandle_t xtask_handle_leds = NULL;
static TaskHandle_t xtask_handle_ultrasonic = NULL;
static TaskHandle_t xtask_handle_tcp_client = NULL;
static TaskHandle_t xtask_handle_alive = NULL;
enum estados_led estado;
float distance;
uint8_t flag_task = 1;
SemaphoreHandle_t mutex;
//FUNÇÕES E TASKS=======================================================================
void wifi_connect() {
wifi_config_t cfg = {
.sta = {
.ssid = SSID,
.password = PASSPHARSE,
},
};
ESP_ERROR_CHECK(esp_wifi_disconnect());
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &cfg));
ESP_ERROR_CHECK(esp_wifi_connect());
}
static esp_err_t event_handler(void *ctx, system_event_t *event) {
switch(event->event_id) {
case SYSTEM_EVENT_STA_START:
wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
break;
default:
break;
}
return ESP_OK;
}
static void initialise_wifi(void) {
esp_log_level_set("wifi", ESP_LOG_NONE); // disable wifi driver logging
tcpip_adapter_init();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());
}
void task_control_leds(void *pvParameters) {
while(true){
if(estado == VERM) {
gpio_set_level(LED_AMAR, 0);
gpio_set_level(LED_VERD, 0);
gpio_set_level(LED_VERM, 1);
}
else if(estado == VERD) {
gpio_set_level(LED_VERM, 0);
gpio_set_level(LED_AMAR, 0);
gpio_set_level(LED_VERD, 1);
}
else if(estado == AMAR) {
gpio_set_level(LED_VERM, 0);
gpio_set_level(LED_VERD, 0);
gpio_set_level(LED_AMAR, 1);
}
else {
gpio_set_level(LED_VERM, 1);
gpio_set_level(LED_VERD, 1);
gpio_set_level(LED_AMAR, 1);
}
}
}
void task_ultrasonic_test(void *pvParameters) {
ultrasonic_sensor_t sensor = {
.trigger_pin = TRIGGER_GPIO,
.echo_pin = ECHO_GPIO
};
ultrasonic_init(&sensor);
while (true) {
esp_err_t res = ultrasonic_measure(&sensor, MAX_DISTANCE_CM, &distance);
if (res == ESP_OK) {
xSemaphoreTake(mutex, portMAX_DELAY);
flag_task = 1;
vTaskSuspend(xtask_handle_leds);
if(distance <= 1){
printf("Nível do Reservatório Crítico: %0.02f\n", distance);
estado = VERM;
}
else if (distance <= 2.5){
printf("Nível do Reservatório em Alerta: %0.02f\n", distance);
estado = AMAR;
}
else {
printf("Nível do Reservatório Satisfatório: %0.02f\n", distance);
estado = VERD;
}
vTaskResume(xtask_handle_leds);
vTaskResume(xtask_handle_tcp_client);
xSemaphoreGive(mutex);
} // Print error
else {
printf("Error %d: ", res);
switch (res) {
case ESP_ERR_ULTRASONIC_PING:
printf("Cannot ping (device is in invalid state)\n");
break;
case ESP_ERR_ULTRASONIC_PING_TIMEOUT:
printf("Ping timeout (no device found)\n");
break;
case ESP_ERR_ULTRASONIC_ECHO_TIMEOUT:
printf("Echo timeout (i.e. distance too big)\n");
break;
default:
printf("%s\n", esp_err_to_name(res));
}
}
delay(35000);
}
}
void tcp_client(void *pvParam){
char rx_buffer[128];
char rx2_buffer[128];
char tx_buffer[128];
char tx2_buffer[128];
char host_ip[] = TCPServerIP;
int addr_family = 0;
int ip_protocol = 0;
struct sockaddr_in tcpServerAddr;
tcpServerAddr.sin_addr.s_addr = inet_addr(TCPServerIP);
tcpServerAddr.sin_family = AF_INET;
tcpServerAddr.sin_port = htons(PORT);
int s, r;
while(true) {
printf("tcp_client task started \n");
xEventGroupWaitBits(wifi_event_group,CONNECTED_BIT,false,true,portMAX_DELAY);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return;
}
ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);
int err = connect(sock, (struct sockaddr *)&tcpServerAddr, sizeof(tcpServerAddr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
return;
}
ESP_LOGI(TAG, "Successfully connected");
err = send(sock, id, strlen(id), 0);
if (err < 0) {
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
}
else {
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
// Error occurred during receiving
if (len < 0) {
ESP_LOGE(TAG, "recv failed: errno %d", errno);
}
// Data received
else {
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
if(strcmp(rx_buffer,"ok") == 0){
printf("Login realizado com sucesso\n");
if(flag_task == 1) {
printf("Enviando %.2f\n", distance);
sprintf(tx2_buffer,"%.2f", distance);
int err = send(sock, tx2_buffer, strlen(tx2_buffer), 0);
flag_task = 0;
}
else {
printf("Enviando %s\n", ALIVE);
sprintf(tx_buffer,"%s", ALIVE);
int err = send(sock, tx_buffer, strlen(tx_buffer), 0);
int len2 = recv(sock, rx2_buffer, sizeof(rx2_buffer) - 1, 0);
rx2_buffer[len2] = 0;
printf("Recebendo %s\n ", rx2_buffer);
flag_task = 1;
}
if (err < 0) {
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
}
//delay(00);
}
else {
printf("Falha no login");
}
}
}
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket...");
shutdown(sock, 0);
close(sock);
}
vTaskSuspend(NULL);
}
}
void task_i_am_alive(void *pvParameters) {
while(true) {
delay(10000);
xSemaphoreTake(mutex, portMAX_DELAY);
flag_task = 0;
vTaskResume(xtask_handle_tcp_client);
xSemaphoreGive(mutex);
}
}
void setup() {
//CONFIGURANDO SAÍDAS===================================================
gpio_config_t output_config = {};//variável descritora
output_config.intr_type = GPIO_INTR_DISABLE;//desabilita interrupção externa
output_config.mode = GPIO_MODE_OUTPUT;//configura GPIO como saídas
output_config.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;//carrega GPIOs configuradas
output_config.pull_up_en = 0;//desativa pull_up
output_config.pull_down_en = 0;//desativa pull_down
gpio_config(&output_config);//configura GPIO conforme descritor
estado = INIC;
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
wifi_event_group = xEventGroupCreate();
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
initialise_wifi();
}
void app_main() {
setup();
mutex = xSemaphoreCreateMutex();
xTaskCreate(&task_control_leds, "LEDs", 2048, NULL, 3, &xtask_handle_leds);
xTaskCreate(&tcp_client,"tcp_client", 4096, NULL, 5, &xtask_handle_tcp_client);
xTaskCreate(&task_ultrasonic_test, "ultrasonic_test", configMINIMAL_STACK_SIZE * 3, NULL, 5, &xtask_handle_ultrasonic);
xTaskCreate(&task_i_am_alive, "device_alive", 4096, NULL, 5, &xtask_handle_alive);
}