Relay control by web call

parent 6e29f465
/*
* Copyright (c) 2018- Franco (nextime) Lanza <franco@nexlab.it>
* Nexboot [https://git.nexlab.net/esp/nexboot]
* This file is part of Nexboot.
* Nexboot is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "esp_ota_ops.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
//#include "https_server.h"
#include "mongoose.h"
#include "html.h"
#include "driver/gpio.h"
/* You can set Wifi configuration via
'make menuconfig'.
If you'd rather not, just change the below entries to strings with
the config you want - ie #define WIFI_SSID "mywifissid"
*/
#define ESP_WIFI_MODE_AP CONFIG_ESP_WIFI_MODE_AP //TRUE:AP FALSE:STA
#define ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define MAX_STA_CONN CONFIG_MAX_STA_CONN
#define MG_LISTEN_ADDR "80"
// outputs
#define GPIO_STEP 18
#define GPIO_STEPPER_ENA 16
#define GPIO_DIRECTION 17
#define GPIO_LED 16
// Relay outputs
#define GPIO_STOPFLOW 32
#define GPIO_PERPUMP 33
// inputs (microswitches)
#define GPIO_BOOTLOAD 26
#define GPIO_MOVE 27
// inputs (straight)
#define GPIO_ES_F 4
#define GPIO_ES_B 2
#define GPIO_ES_R 15
#define GPIO_FLOWSENS 25
// inputs (optocoupled)
#define GPIO_OVERFLOW 35
#define GPIO_FLOWRUN 34
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_STEP)|(1ULL<<GPIO_STEPPER_ENA)| \
(1ULL<<GPIO_DIRECTION))
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_BOOTLOAD)|(1ULL<<GPIO_MOVE)|(1ULL<<GPIO_ES_F)| \
(1ULL<<GPIO_ES_B)|(1ULL<<GPIO_ES_R)|(1ULL<<GPIO_OVERFLOW)| \
(1ULL<<GPIO_FLOWRUN)|(1ULL<<GPIO_FLOWSENS))
#define GPIO_INOUT_PIN_SEL ((1ULL<<GPIO_PERPUMP)|(1ULL<<GPIO_STOPFLOW)|(1ULL<<GPIO_LED))
#define ESP_INTR_FLAG_DEFAULT 0
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t wifi_event_group;
/* The event group allows multiple bits for each event,
but we only care about one event - are we connected
to the AP with an IP? */
const int WIFI_CONNECTED_BIT = BIT0;
static const char *TAG = "HTWBAckwash";
static xQueueHandle gpio_evt_queue = NULL;
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_task_bw(void* arg)
{
uint32_t io_num;
for(;;) {
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
ESP_LOGI(TAG, "GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
}
}
}
static void gpio_task_out(void* arg)
{
int cnt = 0;
for(;;) {
printf("cnt: %d\n", cnt++);
vTaskDelay(1000 / portTICK_RATE_MS);
gpio_set_level(GPIO_LED, cnt % 2);
}
}
static void gpio_htw_init(void)
{
gpio_config_t io_conf;
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);
io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
io_conf.pin_bit_mask = GPIO_INOUT_PIN_SEL;
gpio_config(&io_conf);
io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
//change gpio intrrupt type for one pin
gpio_set_intr_type(GPIO_FLOWRUN, GPIO_INTR_ANYEDGE);
gpio_set_intr_type(GPIO_OVERFLOW, GPIO_INTR_ANYEDGE);
}
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch(event->event_id) {
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
ESP_LOGI(TAG, "got ip:%s",
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
break;
case SYSTEM_EVENT_AP_STACONNECTED:
ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d",
MAC2STR(event->event_info.sta_connected.mac),
event->event_info.sta_connected.aid);
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d",
MAC2STR(event->event_info.sta_disconnected.mac),
event->event_info.sta_disconnected.aid);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT);
break;
default:
break;
}
return ESP_OK;
}
#if ESP_WIFI_MODE_AP
void wifi_init_softap()
{
wifi_event_group = xEventGroupCreate();
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_config_t wifi_config = {
.ap = {
.ssid = ESP_WIFI_SSID,
.ssid_len = strlen(ESP_WIFI_SSID),
.password = ESP_WIFI_PASS,
.max_connection = MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s",
ESP_WIFI_SSID, ESP_WIFI_PASS);
}
#else // if ESP_WIFI_MODE_AP
void wifi_init_sta()
{
wifi_event_group = xEventGroupCreate();
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_config_t wifi_config = {
.sta = {
.ssid = ESP_WIFI_SSID,
.password = ESP_WIFI_PASS
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(TAG, "wifi_init_sta finished.");
ESP_LOGI(TAG, "connect to ap SSID:%s password:%s",
ESP_WIFI_SSID, ESP_WIFI_PASS);
}
#endif // if ESP_WIFI_MODE_AP
// Convert a mongoose string to a string
char *mgStrToStr(struct mg_str mgStr) {
char *retStr = (char *) malloc(mgStr.len + 1);
memcpy(retStr, mgStr.p, mgStr.len);
retStr[mgStr.len] = 0;
return retStr;
}
struct fwriter_data {
const esp_partition_t *update_partition;
esp_ota_handle_t update_handle;
size_t bytes_written;
};
static void mg_ev_handler(struct mg_connection *nc, int ev, void *p) {
struct fwriter_data *data = (struct fwriter_data *) nc->user_data;
struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *) p;
switch (ev) {
case MG_EV_ACCEPT: {
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
ESP_LOGI(TAG, "Connection %p from %s\n", nc, addr);
break;
}
case MG_EV_HTTP_REQUEST: {
char addr[32];
struct http_message *hm = (struct http_message *) p;
char *uri = mgStrToStr(hm->uri);
char *method = mgStrToStr(hm->method);
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
ESP_LOGI(TAG, "HTTP request from %s: %.*s %.*s\n", addr, (int) hm->method.len,
hm->method.p, (int) hm->uri.len, hm->uri.p);
if(strcmp(uri, "/") == 0) {
if(!strcmp(method, "POST") == 0) {
mg_send_head(nc, 200, index_html_len, "Content-Type: text/html");
mg_send(nc, index_html, index_html_len);
}
} else if(strcmp(uri, "/reboot") == 0) {
mg_send_head(nc, 200, reboot_html_len, "Content-Type: text/html");
mg_send(nc, reboot_html, reboot_html_len);
ESP_LOGI(TAG,"Rebooting... ");
esp_restart();
} else if(strcmp(uri, "/stopflow") == 0) {
mg_send_head(nc, 200, index_html_len, "Content-Type: text/html");
mg_send(nc, index_html, index_html_len);
ESP_LOGI(TAG,"Activate Stop FLOW");
gpio_set_level(GPIO_STOPFLOW, gpio_get_level(GPIO_STOPFLOW) ^ 1);
} else if(strcmp(uri, "/perpump") == 0) {
mg_send_head(nc, 200, index_html_len, "Content-Type: text/html");
mg_send(nc, index_html, index_html_len);
ESP_LOGI(TAG,"Activate Peristaltic Pump");
gpio_set_level(GPIO_PERPUMP, gpio_get_level(GPIO_PERPUMP) ^ 1);
} else {
mg_send_head(nc, 404, 0, "Content-Type: text/plain");
}
nc->flags |= MG_F_SEND_AND_CLOSE;
free(uri);
break;
}
case MG_EV_CLOSE: {
ESP_LOGI(TAG, "Connection %p closed\n", nc);
break;
}
}
}
void mongooseTask(void *data) {
ESP_LOGI(TAG, "Mongoose task starting");
struct mg_mgr mgr;
struct mg_connection *nc;
ESP_LOGD(TAG, "Mongoose: Starting setup");
mg_mgr_init(&mgr, NULL);
ESP_LOGD(TAG, "Mongoose succesfully inited");
nc = mg_bind(&mgr, MG_LISTEN_ADDR, mg_ev_handler);
ESP_LOGI(TAG, "Webserver successfully bound on port %s\n", MG_LISTEN_ADDR);
if (nc == NULL) {
ESP_LOGE(TAG, "No connection from the mg_bind()");
vTaskDelete(NULL);
return;
}
mg_set_protocol_http_websocket(nc);
for(;;) {
mg_mgr_poll(&mgr, 1000);
}
}
void app_main()
{
//Initialize NVS
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);
#if ESP_WIFI_MODE_AP
ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
wifi_init_softap();
#else
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
wifi_init_sta();
#endif /*ESP_WIFI_MODE_AP*/
gpio_htw_init();
//create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
//start gpio task
xTaskCreate(gpio_task_bw, "gpio_task_bw", 2048, NULL, 10, NULL);
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_BOOTLOAD, gpio_isr_handler, (void*) GPIO_BOOTLOAD);
gpio_isr_handler_add(GPIO_MOVE, gpio_isr_handler, (void*) GPIO_MOVE);
gpio_isr_handler_add(GPIO_ES_F, gpio_isr_handler, (void*) GPIO_ES_F);
gpio_isr_handler_add(GPIO_ES_B, gpio_isr_handler, (void*) GPIO_ES_B);
gpio_isr_handler_add(GPIO_ES_R, gpio_isr_handler, (void*) GPIO_ES_R);
gpio_isr_handler_add(GPIO_OVERFLOW, gpio_isr_handler, (void*) GPIO_OVERFLOW);
gpio_isr_handler_add(GPIO_FLOWRUN, gpio_isr_handler, (void*) GPIO_FLOWRUN);
gpio_isr_handler_add(GPIO_FLOWSENS, gpio_isr_handler, (void*) GPIO_FLOWSENS);
xTaskCreate(gpio_task_out, "gpio_task_out", 2048, NULL, 7, NULL);
// Start Mongoose task
xTaskCreatePinnedToCore(&mongooseTask, "mongooseTask", 20000, NULL, 5, NULL,0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment