Tue, 26 Nov 2019 11:55:46 +0100
Version 0.2.1. When wakeup by user push, select the active unit screen if only one unit is active.
/** * @file co2meter.c * @brief co2meter project. */ #include "config.h" static const char *TAG = "co2meter"; const esp_app_desc_t *app_desc = NULL; ///< Application description int Main_Loop1 = ML1_INIT; ///< Loop 1 init int num_sensors = 0; ///< Detected DS18B20 sensors static TaskHandle_t xTaskDS18B20 = NULL; static TaskHandle_t xTaskADC = NULL; static TaskHandle_t xTaskWifi = NULL; static TaskHandle_t xTaskMQTT = NULL; static TaskHandle_t xTaskUser = NULL; extern unit_t units[3]; ///< Pressure test units extern SemaphoreHandle_t xSemaphoreUnits; ///< Units lock semaphore extern DS18B20_State *ds18b20_state; ///< DS18B20 state extern SemaphoreHandle_t xSemaphoreDS18B20; ///< DS18B20 lock semaphore extern ADC_State *adc_state; ///< ADC state extern SemaphoreHandle_t xSemaphoreADC; ///< ADC lock semaphore extern WIFI_State *wifi_state; ///< WiFi state extern EventGroupHandle_t xEventGroupUser; extern int count_pub; ///< Published MQTT messages in transit void app_main() { esp_err_t ret; Main_Loop1 = ML1_INIT; app_desc = esp_ota_get_app_description(); /* * event handler and event group for the user interface */ xEventGroupUser = xEventGroupCreate(); user_cold(); /* * Initialize NVS */ 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); /* * Setup SPIFFS filesystem */ ESP_LOGI(TAG, "Initializing SPIFFS"); esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", .partition_label = NULL, .max_files = 5, .format_if_mount_failed = true }; /* * Use settings defined above to initialize and mount SPIFFS filesystem. * Note: esp_vfs_spiffs_register is an all-in-one convenience function. */ ret = esp_vfs_spiffs_register(&conf); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount or format filesystem"); } else if (ret == ESP_ERR_NOT_FOUND) { ESP_LOGE(TAG, "Failed to find SPIFFS partition"); } else { ESP_LOGE(TAG, "Failed to initialize SPIFFS (%d)", ret); } return; // Stop application. } size_t total = 0, used = 0; ret = esp_spiffs_info(NULL, &total, &used); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to get SPIFFS partition information"); return; // Stop application. } else { ESP_LOGI(TAG, "Partition size: %d, used: %d - %d%%", total, used, (used * 100) / total); } // Just to debug, list the /spiffs filesystem. #if 0 DIR *dir = opendir("/spiffs"); struct dirent* de = readdir(dir); while (de) { if (de->d_type == DT_REG) { printf("F "); } if (de->d_type == DT_DIR) { printf("D "); } printf("%s\n", de->d_name); de = readdir(dir); } closedir(dir); #endif /* * Read or create configuration */ read_config(); read_units(); /* * Create FreeRTOS tasks */ xSemaphoreDS18B20 = xSemaphoreCreateMutex(); xSemaphoreADC = xSemaphoreCreateMutex(); xSemaphoreUnits = xSemaphoreCreateMutex(); xTaskCreate(&task_user, "task_user", 4096, NULL,10, &xTaskUser); xTaskCreate(&task_ds18b20, "task_ds18b20", 2560, NULL, 8, &xTaskDS18B20); xTaskCreate(&task_adc, "task_adc", 2560, NULL, 8, &xTaskADC); esp_log_level_set("wifi", ESP_LOG_ERROR); xTaskCreate(&task_wifi, "task_wifi", 4096, NULL, 3, &xTaskWifi); vTaskDelay(10 / portTICK_PERIOD_MS); esp_log_level_set("MQTT_CLIENT", ESP_LOG_ERROR); xTaskCreate(&task_mqtt, "task_mqtt", 4096, NULL, 5, &xTaskMQTT); /* * Main application loop. */ while (1) { ESP_LOGI(TAG, "Entered Main loop"); /* Measure process */ while (1) { switch (Main_Loop1) { case ML1_INIT: Main_Loop1 = ML1_CONNECT; requestWiFi_system(true); request_ds18b20(); request_adc(); break; case ML1_CONNECT: if (ready_WiFi()) { Main_Loop1 = ML1_MQTT_CONNECT; user_refresh(); } break; case ML1_MQTT_CONNECT: if (ready_ds18b20() && ready_adc()) { connect_mqtt(true); Main_Loop1 = ML1_WAITCON; uint32_t temp[DS18B20_MAX]; int state[DS18B20_MAX], i; char rom_code[DS18B20_MAX][17]; for (i = 0; i < DS18B20_MAX; i++) { temp[i] = 0; state[i] = 0; rom_code[i][0] = '\0'; } /* Copy results from all connected DS18B20 sensors */ num_sensors = 0; if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) { num_sensors = ds18b20_state->num_sensors; for (i = 0; i < num_sensors; i++) { temp[i] = (ds18b20_state->sensor[i].temperature * 1000); state[i] = (ds18b20_state->sensor[i].error == 0) ? 0:1; strncpy(rom_code[i], ds18b20_state->sensor[i].rom_code, 17); rom_code[i][16] = '\0'; } xSemaphoreGive(xSemaphoreDS18B20); } else { ESP_LOGE(TAG, "ML1_MQTT_CONNECT DS18B20 lock error"); } /* Copy measured data and calculate results */ for (i = 0; i < 3; i++) { if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { /* Search configured temperature sensor for this unit */ for (int j = 0; j < num_sensors; j++) { if (strcmp(rom_code[j], units[i].temperature_rom_code) == 0) { units[i].temperature = temp[j]; units[i].temperature_state = state[j]; units[i].alarm = 0; if (state[j]) units[i].alarm |= ALARM_SYS_TEMPERATURE & ALARM_UNIT_TEMPERATURE; break; } } /* Get the ADC results */ if (xSemaphoreTake(xSemaphoreADC, 10) == pdTRUE) { units[i].pressure_state = adc_state->Pressure[i].error; units[i].pressure_channel = adc_state->Pressure[i].channel; units[i].pressure_voltage = adc_state->Pressure[i].voltage; if (units[i].pressure_state || units[i].pressure_voltage < 80) units[i].alarm |= ALARM_UNIT_PRESSURE; int P = (units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero) * 14; // in bar if (P < 0) P = 0; units[i].pressure = P; ESP_LOGI(TAG, "%d vb:%.3f vp:%.3f zero:%d scale:%3d mbar:%4d alm: %d t:%6.3f %s", i, adc_state->Batt_voltage / 1000.0, units[i].pressure_voltage / 1000.0, units[i].pressure_zero, units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero, P, units[i].alarm, units[i].temperature / 1000.0, units[i].temperature_rom_code); xSemaphoreGive(xSemaphoreADC); } else { ESP_LOGE(TAG, "ML1_MQTT_CONNECT ADC[%d] lock error", i); } xSemaphoreGive(xSemaphoreUnits); } else { ESP_LOGE(TAG, "ML1_MQTT_CONNECT units[%d] lock error", i); } } if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { write_units(); xSemaphoreGive(xSemaphoreUnits); } else { ESP_LOGE(TAG, "ML1_MQTT_CONNECT write_units lock error"); } user_refresh(); } break; case ML1_WAITCON: if (ready_mqtt()) Main_Loop1 = ML1_SEND; break; case ML1_SEND: publishNode(); publishUnits(); publishLogs(); Main_Loop1 = ML1_WAITACK; break; case ML1_WAITACK: if (count_pub == 0) // Wait until all published messages are sent. Main_Loop1 = ML1_MQTT_DISCONNECT; break; case ML1_MQTT_DISCONNECT: connect_mqtt(false); // Doesn't really disconnect. Main_Loop1 = ML1_DISCONNECT; break; case ML1_DISCONNECT: if (! ready_mqtt()) { requestWiFi_system(false); Main_Loop1 = ML1_WIFI_OFF; } break; case ML1_WIFI_OFF: if (! ready_WiFi()) { ESP_LOGI(TAG, "Main loop: Done, user busy: %s", user_busy() ? "true":"false"); Main_Loop1 = ML1_DONE; user_refresh(); } break; case ML1_DONE: /* Wait here until the timer resets the loop */ break; } vTaskDelay(10 / portTICK_PERIOD_MS); } Main_Loop1 = ML1_INIT; } }