Sat, 06 Jun 2020 13:28:46 +0200
Changed the recipe database so that it is expandable, version 2. More mash fields and allow 16 steps. Allow 20 Additions. Removed separate mash steps from the state machine, the steps are moved to the runtime data. There is no fixed step number for mashout anymore. There is no fixed step for mash-in anymore, just use the first step and heat to the infusion temperature. After malt add, switch to the normal step temperature. Implemented decoction steps.
/** * @file config.h * @brief The BrewBoard configuration data. These are stored in the * spiffs filesystem in a flash partition. */ #ifndef _CONFIG_H #define _CONFIG_H // Global includes for the project #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <time.h> #include <errno.h> #include <sys/unistd.h> #include <sys/fcntl.h> #include <sys/time.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/event_groups.h" #include "freertos/queue.h" #include "driver/i2c.h" #include "esp_log.h" #include "esp_spiffs.h" #include "esp_event.h" #include "esp_wifi.h" #include "esp_wifi_types.h" #include "esp_system.h" #include "esp_ota_ops.h" #include "esp_http_client.h" #include "esp_https_ota.h" #include "esp_vfs.h" #include "esp_vfs_fat.h" #include "nvs.h" #include "nvs_flash.h" #include "esp32/rom/crc.h" #include "mdns.h" #include "lwip/sockets.h" #include "lwip/api.h" #include "lwip/err.h" #include "lwip/netdb.h" #include "lwip/dns.h" #include "lwip/opt.h" #include "lwip/memp.h" #include "lwip/ip.h" #include "lwip/raw.h" #include "lwip/udp.h" #include "sdkconfig.h" #include "lwip/apps/sntp.h" #include "expat.h" #include "tftspi.h" #include "tft.h" #include "PID_v1.h" #include "websocket_server.h" #include "buttons.h" #include "calibration.h" #include "automation.h" #include "manual.h" #include "setup.h" #include "recipes.h" #include "files.h" #include "updates.h" #include "task_tft.h" #include "task_ds18b20.h" #include "task_sdcard.h" #include "task_driver.h" #include "task_wifi.h" #include "task_sound.h" #include "task_http.h" /** * @brief Main mode different screens */ typedef enum { MAIN_MODE_UNKNOWN = -1, ///< During system startup MAIN_MODE_FREE = 0, ///< Main menu, do nothing MAIN_MODE_CALIBRATION, ///< TFT calibration MAIN_INFO, ///< Info/about screen MAIN_TOOLS, ///< Main tools screen MAIN_TOOLS_SETUP, ///< Main setup screen MAIN_TOOLS_SETUP_CONFIG, ///< Main setup configuration MAIN_TOOLS_SETUP_CO_EDIT, ///< Main setup confguration editor MAIN_TOOLS_SETUP_EQUIPMENT, ///< Main setup equipment MAIN_TOOLS_SETUP_EQ_EDIT, ///< Main setup edit equipment MAIN_TOOLS_SETUP_WIFI, ///< Main setup WiFi MAIN_TOOLS_SETUP_WIFI_CUR, ///< Main setup WiFi current connection. MAIN_TOOLS_SETUP_WIFI_CON, ///< Main setup WiFi connect. MAIN_TOOLS_SETUP_WIFI_NEW, ///< Main setup WiFi new connection. MAIN_TOOLS_SETUP_CALIBRATION, ///< Main setup TFT calibration MAIN_TOOLS_RECIPE, ///< Main recipes screen. MAIN_TOOLS_RECIPE_EDIT, ///< Main recipes editor. MAIN_TOOLS_FILES, ///< Main files. MAIN_TOOLS_FILES_DIR, ///< Main files directory listings. MAIN_TOOLS_FILES_RESTORE, ///< Main files restore. MAIN_TOOLS_FILES_BACKUP, ///< Main files backup. MAIN_TOOLS_UPDATES, ///< Main Updates. MAIN_AUTO_INIT1 = 96, ///< Automatic start part 1 MAIN_AUTO_INIT2, ///< Automatic start part 2 MAIN_AUTO_DELAYSTART, ///< Delayed start MAIN_AUTO_HEATUP, ///< Heatup the HLT MAIN_AUTO_MASH = 100, ///< Mash steps MAIN_AUTO_TOBOIL = 120, ///< Going to boil MAIN_AUTO_BOILING, ///< Boiling MAIN_AUTO_WHIRLPOOL9, ///< Whirlpool MAIN_AUTO_COOLING_H, ///< Cooling hot type MAIN_AUTO_WHIRLPOOL7, ///< Whirlpool MAIN_AUTO_COOLING_M, ///< Cooling medium type MAIN_AUTO_WHIRLPOOL6, ///< Whirlpool MAIN_AUTO_COOLING_C, ///< Cooling cold type MAIN_AUTO_WHIRLPOOL2, ///< Whirlpool MAIN_AUTO_DONE, ///< Finished MAIN_AUTO_ABORT, ///< Aborted MAIN_MANUAL_INIT = 200, ///< Manual control init MAIN_MANUAL_MAIN, ///< Manual control main menu } MAIN_MODE; /** * @brief The differents stages in the mash steps. */ typedef enum { MASH_NONE = 0, ///< Initial Mash state MASH_WAITTEMP, ///< Wait to reach temperature. MASH_REST, ///< Mash rest MASH_ADD, ///< Wait add mash MASH_IODINE, ///< Wait iodine test MASH_REMOVE, ///< Wait mash remove MASH_INFUSE, ///< Wait infusion prompt MASH_DECOCT, ///< Wait decoction prompt } MASH_TYPE; /** * @brief The working mode of the second heater SSR. */ typedef enum { SSR2_OFF = 0, ///< SSR2 not used. SSR2_HLT_SHARE, ///< SSR2 for HLT shared with MLT SSR2_HLT_IND, ///< SSR2 for HLT independend. SSR2_ON_IDLE, ///< SSR2 on when NLT is idle. } SSR2_TYPE; /** * @brief Global configuration. File /spiffs/config.conf */ struct strConfig { uint8_t Version; ///< Record version number for updates. uint8_t Unit; ///< Celsius or Farenheit (not used yet). float BoilTemperature; ///< The temperature when water boils. bool AskAdd; ///< Ask to add the mash. bool AskRemove; ///< Ask to remove the mash. bool AskIodine; ///< Ask to confirm the iodine test. uint8_t IodineTime; ///< Continue after this time if not confirmed. int EquipmentRec; ///< Equipment record number. char ntp_server[32]; ///< Preffered NTP server. char hostname[32]; ///< Our hostname. char ap_ssid[32]; ///< AP SSID. char ap_pwd[64]; ///< AP password. uint8_t ap_channel; ///< AP channel. uint8_t ap_ssid_hidden; ///< AP SSID hidden. wifi_bandwidth_t ap_bandwidth; ///< AP channel bandwidth. uint16_t ts_xleft; ///< TS calibration X left. uint16_t ts_xright; ///< TS calibration X right. uint16_t ts_ytop; ///< TS calibration Y top. uint16_t ts_ybottom; ///< TS calibration Y bottom. int RecipeRec; ///< Current recipe record. char uuid[37]; ///< Sort of uuid code. char lastSSID[32]; ///< Last connected station. } config; ///< Config record. /** * @brief Write configuration to disk. */ void write_config(void); /** @brief Read configuration file. If it doesn't exist create and * write a new configuration file with sane defaults. */ void read_config(void); /** * @brief Equipment configuration. File /spiffs/equipments.conf */ struct strEquipment { int Version; ///< Record version number for updates. int Record; ///< Record number. char Name[32]; ///< Equipment name. int BoilPower; ///< The power percentage needed to keep the wort boiling. int MashPower; ///< The power percentage needed to heat during mash. int PumpCycle; ///< Minutes to run the pump during mash rest. int PumpRest; ///< Minutes to pause the pump during mash rests. bool PumpPreMash; ///< Pump on before mash-in. bool PumpOnMash; ///< Pump on during mashing. bool PumpMashOut; ///< Pump on during mash remove. bool PumpOnBoil; ///< Pump on during the boil. int PumpMaxTemp; ///< Turn pump off above this temperature. bool PIDPipe; ///< Run PID during mash removal. int SSR2; ///< Use second SSR (HLT) or not. float TempHLT; ///< The temperature of the sparge water. double PID_kP; ///< PID P setting. double PID_kI; ///< PID I setting. double PID_kD; ///< PID D setting. bool PID_POn; ///< PID compute on Measurement or Errors. int SampleTime; ///< PID sample time in seconds. } equipment; ///< Equipment record. /** * @brief Append equipments record to disk. */ void append_equipment(void); /** * @brief Read equipments file. If it doesn't exist create and * write a new equipment file with sane defaults. * This is then the first and default brew equipment. * @param RecNo Read the record with Record is RecNo. Start at 1. */ void read_equipment(int RecNo); /** * @brief Write rquipment record. It should exist. * @param RecNo The equipment record in memory to write at record. Records start at 1. */ void write_equipment(int RecNo); /** * @brief Delete equipment record, renumber remaining records. * @param RecNo The record to remove. */ void delete_equipment(int RecNo); /** * @brief Records with WiFi stations we have succesfully connected. */ struct strStations { char SSID[32]; ///< Station SSID char Password[64]; ///< Station password bool hide; ///< Hide from AP scan. } wifiStation; ///< Station record. /** * @brief Add a new station record. * @param SSID The SSID * @param Password The password for this SSID * @return The record number, or -1 if error. */ int add_station(uint8_t *SSID, uint8_t *Password); /** * @brief Read station info record. * @param SSID Search for the SSID and load the record if found. * @return Return -1 if not found, else the record number and the wifiStation record is filled. */ int read_station(uint8_t *SSID); /** * @brief Remove station record. * @param SSID The SSID to remove. */ void remove_station(uint8_t *SSID); /** * @brief Blacklist station SSID * @param SSID The SSID to blacklist. * @return -1 if error, else the record number. */ int blacklist_station(uint8_t *SSID); /** * @brief Runtime configuration. File /spiffs/runtime.conf */ struct strRuntime { uint8_t Version; ///< Record version number for updates. bool AutoModeStarted; ///< Running automode. int StageResume; ///< Current Resume Stage. int StageTimeLeft; ///< Current Stage Time left. uint8_t HopAddition; ///< Current Hop Addition. float ManualMLT; ///< Last used MLT temperature. float ManualHLT; ///< Last used HLT temperature. time_t BrewStart; ///< Brew start time. char Logfile[64]; ///< Brew logfile. bool UseHLT; ///< Use HLT during brew. bool PumpCooling; ///< Pump during cooling. uint32_t TimeBrewing; ///< Time we are brewing. uint8_t MashStep; ///< Current mash step. bool MaltAdded; ///< If malt was added. } runtime; ///< Runtime record. /** * @brief Write runtime information to disk. */ void write_runtime(void); /** * @brief Read runtime information file. If it doesn't exist create and * write a new runtime file with sane defaults. */ void read_runtime(void); #define RECIPE_VERSION 2 ///< Recipe file version #define MASH_MAX 16 ///< Maximum 16 mash steps #define ADDITION_MAX 20 ///< Maximum 20 additions /** * @brief Mash step types */ typedef enum { MASHTYPE_INFUSION = 0, MASHTYPE_TEMPERATURE, MASHTYPE_DECOCTION, } MASHSTEP_TYPE; /** * @brief Addition types */ typedef enum { ADDITION_HOP = 0, ADDITION_FERMENTABLE = 1, ADDITION_SPICE = 2, ADDITION_FINING = 3, ADDITION_WATER_AGENT = 4, ADDITION_HERB = 5, ADDITION_FLAVOR = 6, ADDITION_OTHER = 7, } ADDITION_TYPE; /** * @brief Mash steps */ typedef struct strMashStep { char Name[32]; ///< Step name. uint8_t Type; ///< Step Type. float Step_temp; ///< Step start temperature. uint16_t Step_time; ///< Step rest time. uint16_t Ramp_time; ///< Step time to reach temp. float End_temp; ///< Step end temperature. float Infuse_amount; ///< Infuse/decoct amount in liters. float Infuse_temp; ///< Infuse temperature. } mashstep_t; /** * @brief Hop and other additions */ typedef struct strAddition { uint16_t Time; ///< Time for addition. uint8_t Type; ///< Addition type, Hop, Syrop ... char Name[64]; ///< Addition name. } addition_t; /** * @brief Recipes database. Starts with a header block for future upgrades, * followed by the actual recpie records. */ struct hdrRecipe { uint32_t version; ///< Structure version. uint32_t hdrsize; ///< Size of this header. uint32_t recsize; ///< Size of a record. uint8_t mashmax; ///< Maximum mash steps. uint8_t additionmax; ///< Maximum additions. } recipe_hdr; struct strRecipe { char Name[128]; ///< Recipe name. char Code[32]; ///< Recipe code. uint16_t BoilTime; ///< Boil time. uint8_t Mashsteps; ///< Number of mashsteps. uint8_t Additions; ///< Number of additions. float CoolTemp; ///< Cool temperature. uint16_t Whirlpool9; ///< Zero or the Hot Whirlpool time 88..100 ° uint16_t Whirlpool7; ///< Zero or the Sub Isomerization Whirlpool time 71..77 ° uint16_t Whirlpool6; ///< Zero or the "Tepid" Whirlpool time 60..66 ° uint16_t Whirlpool2; ///< Zero or the Cold Whirlpool time < 30 ° float SpargeTemp; ///< Sparge water temperature. mashstep_t MashStep[MASH_MAX]; ///< Mash steps. addition_t Addition[ADDITION_MAX]; ///< Additions. } recipe; ///< Recipe record. /** * @brief Append a recipe record. Create file if it doesn't exist. */ void append_recipe(void); /** * @brief Write current recipe * @param RecNo Record number starting at 1. */ void write_recipe(int RecNo); /** * @brief Read current recipe * @param RecNo The record to read, start at 1. */ void read_recipe(int RecNo); /** * @brief Delete recipe record, renumber remaining records. * @param RecNo The record to remove. */ void delete_recipe(int RecNo); #endif