From 91da7dff4c363061c58315f098c52b4da9026237 Mon Sep 17 00:00:00 2001 From: "Morgan 'ARR\\!' Allen" Date: Thu, 25 May 2023 13:46:14 -0700 Subject: [PATCH] now listens to tasmota power state and disables sleep mode when POWER ON --- main/main.c | 275 +++++++++++++++++++++------------------------------- 1 file changed, 112 insertions(+), 163 deletions(-) diff --git a/main/main.c b/main/main.c index f70feca..acdb8a8 100644 --- a/main/main.c +++ b/main/main.c @@ -28,21 +28,20 @@ #include "argtable3/argtable3.h" #include "driver/gpio.h" #include "driver/spi_master.h" +#include "lwip/sockets.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" + +#include "mqtt_client.h" #include "esp32-wifi-manager.h" -#define TAG "CACO" +#define TAG "BTN" #define GPIO_INPUT_IO_0 33 #define GPIO_INPUT_PIN_SEL ((1ULL<user_data); - - switch(evt->event_id) { - case HTTP_EVENT_ERROR: - ESP_LOGI(TAG, "HTTP_EVENT_ERROR"); - break; - case HTTP_EVENT_ON_CONNECTED: - ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED"); - break; - case HTTP_EVENT_HEADER_SENT: - ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT"); - break; - case HTTP_EVENT_ON_HEADER: - ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER"); - printf("%.*s", evt->data_len, (char*)evt->data); - break; - case HTTP_EVENT_ON_DATA: - ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); - if (!esp_http_client_is_chunked_response(evt->client)) { - printf("%.*s", evt->data_len, (char*)evt->data); - } - - break; - case HTTP_EVENT_ON_FINISH: - ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH"); - break; - case HTTP_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED"); - break; - } - return ESP_OK; -} +esp_mqtt_client_handle_t client; void enter_sleep() { ESP_LOGI(TAG, "Enter sleep"); @@ -147,65 +110,43 @@ void reset_sleep_timer() { xTimerStart(sleep_timer, portMAX_DELAY); } -void ping() { - esp_http_client_config_t config = { - .url = "http://192.168.0.1/_gr", - .method = HTTP_METHOD_POST, - }; +uint8_t led_state_new[4]; +uint8_t led_state_cur[4]; - esp_http_client_handle_t client = esp_http_client_init(&config); - esp_http_client_set_post_field(client, CMD_BEEP, strlen(CMD_BEEP)); - esp_err_t err = esp_http_client_perform(client); +void led_display_loop() { + static spi_transaction_t trans[SPI_BUF]; - if (err == ESP_OK) { - ESP_LOGI(TAG, "Status = %d, content_length = %d", - esp_http_client_get_status_code(client), - esp_http_client_get_content_length(client)); + int i; + for (i = 0; i < SPI_BUF; i++) { + memset(&trans[i], 0, sizeof(spi_transaction_t)); + + trans[i].length=8*4; + trans[i].flags = SPI_TRANS_USE_TXDATA; + } + + trans[1].tx_data[0] = (0b11100000 | 1); + memset(&trans[SPI_BUF - 1].tx_data, 0xFF, 4); + + bool update = false; + + while(true) { + /// TODO check _new vs _cur, ramping the channel value per step until they match + /// only transmit spi data if a change was made + if(led_state_new[1] != led_state_cur[1]) { + trans[1].tx_data[1] = 0; + } + trans[1].tx_data[2] = 127; + trans[1].tx_data[3] = 0; + + for(i = 0; i < SPI_BUF; i++) { + spi_device_queue_trans(spi, &trans[i], portMAX_DELAY); + } + + vTaskDelay(1000 / portTICK_PERIOD_MS); } } -void shoot() { - ESP_LOGI(TAG, "shooting"); - - esp_http_client_config_t config = { - .url = "http://192.168.0.1/v1/camera/shoot", - .method = HTTP_METHOD_POST, - }; - - esp_http_client_handle_t client = esp_http_client_init(&config); - esp_http_client_set_post_field(client, CMD_BEEP, strlen(CMD_BEEP)); - esp_err_t err = esp_http_client_perform(client); - - if (err == ESP_OK) { - ESP_LOGI(TAG, "Status = %d, content_length = %d", - esp_http_client_get_status_code(client), - esp_http_client_get_content_length(client)); - } -} - -void request(char *path) { - char *url = malloc(strlen(BASE_URL) + strlen(path) + 1); - strcpy(url, BASE_URL); - strcat(url, path); - - ESP_LOGI(TAG, "Making request to %s", url); - - esp_http_client_config_t config = { - .url = url, - .event_handler = _http_event_handle - }; - - esp_http_client_handle_t client = esp_http_client_init(&config); - esp_err_t err = esp_http_client_perform(client); - - if (err == ESP_OK) { - ESP_LOGI(TAG, "Status = %d, content_length = %d", - esp_http_client_get_status_code(client), - esp_http_client_get_content_length(client)); - } -} - -void led_loop() { +void led_control_loop() { uint8_t v = 0; while(true) { @@ -213,6 +154,9 @@ void led_loop() { EventBits_t ev_bits = xEventGroupGetBits(wm_event_group); ESP_LOGI(TAG, "got event: %d", ev_bits); + // TODO XXX rewrite to only update led_state_new and let led_display_loop + // handle rendering + static spi_transaction_t trans[SPI_BUF]; int i; @@ -226,6 +170,8 @@ void led_loop() { trans[1].tx_data[0] = (0b11100000 | 1); if(ev_bits & WIFI_CONNECTED) { + esp_mqtt_client_start(client); + trans[1].tx_data[1] = 0; trans[1].tx_data[2] = 127; trans[1].tx_data[3] = 0; @@ -252,76 +198,74 @@ void led_loop() { } } -void pwm_init() { - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, 21); - - mcpwm_config_t pwm_config; - pwm_config.frequency = 50; //frequency = 50Hz, i.e. for every servo motor time period should be 20ms - pwm_config.cmpr_a = 0; //duty cycle of PWMxA = 0 - pwm_config.cmpr_b = 0; //duty cycle of PWMxb = 0 - pwm_config.counter_mode = MCPWM_UP_COUNTER; - pwm_config.duty_mode = MCPWM_DUTY_MODE_0; - mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //Configure PWM0A & PWM0B with above settings -} - -void servo() { - ESP_LOGI(TAG, "value: %d duration: %d", servo_args.value->ival[0], servo_args.duration->ival[0]); - - while(true) { - mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, servo_args.value->ival[0]); - vTaskDelay(servo_args.duration->ival[0] / portTICK_PERIOD_MS); - mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, 1500); - - vTaskDelay(5000 / portTICK_PERIOD_MS); - } -} - -bool running = false; - -static int servo_start(int argc, char **argv) { - int nerrors = arg_parse(argc, argv, (void**) &servo_args); - if (nerrors != 0) { - arg_print_errors(stderr, servo_args.end, argv[0]); - return 1; - } - - if(!running) { - running = true; - xTaskCreate(&servo, "servo", 4096, NULL, 6, NULL); - } - - return ESP_OK; -} - -void register_servo_cmd() { - servo_args.value = arg_int0("v", "value", "", "move value in us"); - servo_args.value->ival[0] = 1200; - - servo_args.duration = arg_int0("d", "duration", "", "duration in ms"); - - servo_args.end = arg_end(2); - - const esp_console_cmd_t start_cmd = { - .command = "start", - .help = "Starts the servo", - .hint = NULL, - .func = &servo_start, - .argtable = &servo_args - }; - - ESP_ERROR_CHECK( esp_console_cmd_register(&start_cmd) ); -} - 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 mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id); + esp_mqtt_event_handle_t event = event_data; + esp_mqtt_client_handle_t client = event->client; + int msg_id; + switch ((esp_mqtt_event_id_t)event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + esp_mqtt_client_subscribe(client, "espbutton/update", 0); + esp_mqtt_client_subscribe(client, TOPIC_POWER_STATUS, 0); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_DATA: + ESP_LOGI(TAG, "MQTT_EVENT_DATA [topic: %.*s]", event->topic_len, event->topic); + + if(strncmp(event->topic, (const char*)TOPIC_POWER_STATUS, event->data_len) == 0) { + ESP_LOGI(TAG, "data_len: %d", event->data_len); + if(strncmp(event->data, "ON", 2) == 0) { + xTimerStop(sleep_timer, portMAX_DELAY); + } else if(strncmp(event->data, "OFF", 3) == 0) { + reset_sleep_timer(); + } + } + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { + ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno)); + + } + break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; + } +} + void gpio_loop() { int8_t state = -1; uint32_t io_num; + esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtt://192.168.1.1", + }; + + client = esp_mqtt_client_init(&mqtt_cfg); + /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ + esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); + for(;;) { if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { uint8_t level = gpio_get_level(io_num); @@ -347,7 +291,7 @@ void gpio_loop() { reset_sleep_timer(); if(level == 0) { - xTimerChangePeriod(button_timer, CONFIG_TIMEOUT_SHOOT, portMAX_DELAY); + xTimerChangePeriod(button_timer, 100 / portTICK_PERIOD_MS, portMAX_DELAY); xTimerStart(button_timer, portMAX_DELAY); } else { xTimerStop(button_timer, portMAX_DELAY); @@ -357,7 +301,7 @@ void gpio_loop() { } void handle_button_timer() { - shoot(); + esp_mqtt_client_publish(client, "cmnd/tasmota_E74A79/POWER", "TOGGLE", 0, 1, 0); } void gpio_init() { @@ -462,7 +406,12 @@ void app_main() { gpio_init(); spi_init(); - xTaskCreate(&led_loop, "led_loop", 4096, NULL, 6, NULL); + xTaskCreate(&led_display_loop, "led_display_loop", 4096, NULL, 6, NULL); + xTaskCreate(&led_control_loop, "led_control_loop", 4096, NULL, 6, NULL); wifi_manager_scan(); + + while(true) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } };