Wed, 19 May 2021 17:21:33 +0200
Version 0.3.14. Log brewing essentials at brew start.
/** * @file config.c * @brief BrewBoard configuration files. */ #include "config.h" static const char *TAG = "config"; void write_config() { uint8_t *dst = (uint8_t *)&config; FILE *f = fopen("/spiffs/etc/config.conf", "w+"); if (f == NULL) { ESP_LOGE(TAG, "write /spiffs/etc/config.conf failed"); return; } size_t bytes = fwrite(dst, 1, sizeof(config), f); fclose(f); if (bytes != sizeof(config)) { ESP_LOGE(TAG, "/spiffs/etc/config.conf written %d/%d bytes", bytes, sizeof(config)); } } void read_config() { uint8_t *dst; uint8_t mac_addr[8] = {0}; FILE *f = fopen("/spiffs/etc/config.conf", "r"); if (f == NULL) { // No configuration yet, create it. esp_efuse_mac_get_default(mac_addr); config.Version = 1; config.Unit = 'C'; config.BoilTemperature = 99.0; config.AskAdd = true; config.AskRemove = true; config.AskIodine = true; config.IodineTime = 30; config.EquipmentRec = 1; sprintf(config.hostname, "brewboard-%02x%02x%02x", mac_addr[3], mac_addr[4], mac_addr[5]); config.xap_ssid[0] = '\0'; config.xap_pwd[0] = '\0'; config.xap_channel = 0; config.xap_ssid_hidden = 0; config.xap_bandwidth = 0; config.ts_xleft = 0; config.ts_xright = 3600; config.ts_ytop = 3600; config.ts_ybottom = 0; config.RecipeRec = 1; sprintf(config.uuid, "c0ffeeee-dead-beef-cafe-%02x%02x%02x%02x%02x%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); write_config(); } else { dst = (uint8_t*)&config; fread(dst, 1, sizeof(config), f); fclose(f); } } void append_equipment() { return; uint8_t *dst = (uint8_t *)&equipment; FILE *f = fopen("/spiffs/etc/equipments.conf", "a"); if (f == NULL) { ESP_LOGE(TAG, "append /spiffs/etc/equipments.conf failed"); return; } size_t bytes = fwrite(dst, 1, equipment_hdr.recsize, f); fclose(f); ESP_LOGI(TAG, "/spiffs/etc/equipments.conf appended %d bytes", bytes); } void read_equipment(int RecNo) { size_t bytes; uint8_t *dst; FILE *f = fopen("/spiffs/etc/equipments.conf", "r"); if (f == NULL) { // No configuration yet, create it. dst = (uint8_t*)&equipment_hdr; memset(dst, 0, sizeof(equipment_hdr)); equipment_hdr.version = EQUIPMENT_VERSION; equipment_hdr.hdrsize = sizeof(equipment_hdr); equipment_hdr.recsize = sizeof(equipment); f = fopen("/spiffs/etc/equipments.conf", "w"); bytes = fwrite(dst, 1, sizeof(equipment_hdr), f); if (bytes != sizeof(equipment_hdr)) { ESP_LOGE(TAG, "/spiffs/etc/equipment.conf write header, %d/%d bytes", bytes, sizeof(equipment_hdr)); } dst = (uint8_t*)&equipment; memset(dst, 0, sizeof(equipment)); equipment.MLT_watt = 2000; equipment.HLT_watt = 2000; sprintf(equipment.Name, "default"); equipment.BoilPower = 80; equipment.MashPower = 100; equipment.PumpCycle = 8; equipment.PumpRest = 2; equipment.PumpPreMash = true; equipment.PumpOnMash = true; equipment.PumpMashOut = true; equipment.PumpOnBoil = false; equipment.PumpMaxTemp = 80; equipment.PIDPipe = true; equipment.SSR2 = 0; equipment.TempHLT = 85.0; equipment.PID_kP = 200.0; equipment.PID_kI = 2.0; equipment.PID_kD = 1.5; equipment.SampleTime = 3000; bytes = fwrite(dst, 1, sizeof(equipment), f); fclose(f); } else { /* * Try to read the new header */ dst = (uint8_t*)&equipment_hdr; fseek(f, 0, SEEK_SET); bytes = fread(dst, 1, sizeof(equipment_hdr), f); if (bytes != sizeof(equipment_hdr)) { ESP_LOGE(TAG, "/spiffs/etc/equipments.conf read header, %d/%d bytes", bytes, sizeof(equipment_hdr)); fclose(f); return; } #if 0 if (equipment_hdr.version < EQUIPMENT_VERSION) { FILE *nf = fopen("/spiffs/etc/equipments.new", "w"); ESP_LOGW(TAG, "/spiffs/etc/equipments.conf version %d, new %d", equipment_hdr.version, EQUIPMENT_VERSION); dst = (uint8_t*)&equipment_hdr; memset(dst, 0, sizeof(equipment_hdr)); equipment_hdr.version = EQUIPMENT_VERSION; equipment_hdr.hdrsize = sizeof(equipment_hdr); equipment_hdr.recsize = sizeof(equipment); bytes = fwrite(dst, 1, sizeof(equipment_hdr), nf); fseek(f, 0, SEEK_SET); dst = (uint8_t*)&recipe; while ((bytes = fread(dst, 1, equipment_hdr.recsize, f))) { // Upgrade data here bytes = fwrite(dst, 1, sizeof(equipment), nf); if (bytes != sizeof(equipment)) { ESP_LOGE(TAG, "/spiffs/etc/equipments.new write data, %d/%d bytes", bytes, sizeof(equipment)); } } // Update the header with new sizes fclose(nf); fclose(f); rename("/spiffs/etc/equipments.conf", "/spiffs/etc/equipments.old"); rename("/spiffs/etc/equipments.new", "/spiffs/etc/equipments.conf"); unlink("/spiffs/etc/equipments.old"); f = fopen("/spiffs/etc/equipments.conf", "r"); } #endif dst = (uint8_t*)&equipment; fseek(f, (RecNo - 1) * equipment_hdr.recsize + equipment_hdr.hdrsize, SEEK_SET); bytes = fread(dst, 1, equipment_hdr.recsize, f); fclose(f); if (bytes != equipment_hdr.recsize) { ESP_LOGE(TAG, "/spiffs/etc/equipments.conf read record %d, %d/%d bytes", RecNo, bytes, equipment_hdr.recsize); } else { ESP_LOGD(TAG, "/spiffs/etc/equipments.conf read %d bytes, record %d: %s", bytes, RecNo, equipment.Name); } } } void write_equipment(int RecNo) { uint8_t *dst = (uint8_t *)&equipment; FILE *f; f = fopen("/spiffs/etc/equipments.conf", "r+"); if (f == NULL) { ESP_LOGE(TAG, "write /spiffs/etc/equipments.conf failed"); return; } fseek(f, (RecNo - 1) * equipment_hdr.recsize + equipment_hdr.hdrsize, SEEK_SET); size_t bytes = fwrite(dst, 1, equipment_hdr.recsize, f); fclose(f); if (bytes != equipment_hdr.recsize) ESP_LOGE(TAG, "/spiffs/etc/equipments.conf write record %d, %d/%d bytes", RecNo, bytes, equipment_hdr.recsize); else ESP_LOGI(TAG, "/spiffs/etc/equipments.conf update record %d, %d bytes", RecNo, bytes); } void delete_equipment(int RecNo) { return; int RecRead = 1, RecWrite = 1; FILE *n, *o; uint8_t *dst; size_t bytes; n = fopen("/spiffs/etc/equipments.new", "a"); if (n == NULL) { ESP_LOGE(TAG, "cannot create /spiffs/etc/equipments.new"); return; } o = fopen("/spiffs/etc/equipments.conf", "r"); if (o == NULL) { ESP_LOGE(TAG, "cannot open spiffs/etc/equipments.conf for reading"); fclose(n); return; } dst = (uint8_t*)&equipment_hdr; fread(dst, 1, equipment_hdr.hdrsize, o); fwrite(dst, 1, equipment_hdr.hdrsize, n); dst = (uint8_t*)&equipment; while (true) { bytes = fread(dst, 1, equipment_hdr.recsize, o); if (bytes == 0) break; if (RecRead != RecNo) { // Record to copy if ((config.EquipmentRec == RecRead) && (config.EquipmentRec != RecWrite)) { // We need to change the default record. config.EquipmentRec = RecWrite; write_config(); } fwrite(dst, 1, equipment_hdr.recsize, n); RecWrite++; } RecRead++; } fclose(o); fclose(n); rename("/spiffs/etc/equipments.conf", "/spiffs/etc/equipments.old"); rename("/spiffs/etc/equipments.new", "/spiffs/etc/equipments.conf"); unlink("/spiffs/etc/equipments.old"); ESP_LOGI(TAG, "Deleted equipment %d", RecNo); } int add_station(uint8_t *SSID, uint8_t *Password) { FILE *f; uint8_t *dst = (uint8_t *)&wifiStation; if (read_station(SSID) >= 0) { ESP_LOGE(TAG, "add_station %s already excists", SSID); return -1; } f = fopen("/spiffs/etc/stations.conf", "a+"); if (f == NULL) { ESP_LOGE(TAG, "write /spiffs/etc/stations.conf failed"); return -1; } memset(dst, 0, sizeof(wifiStation)); sprintf(wifiStation.SSID, "%s", (char *)SSID); sprintf(wifiStation.Password, "%s", (char *)Password); wifiStation.hide = false; fwrite(dst, 1, sizeof(wifiStation), f); fclose(f); ESP_LOGI(TAG, "add_station %s record: %d", (char *)SSID, read_station(SSID)); /* Return the record number */ return read_station(SSID); } int read_station(uint8_t *SSID) { uint8_t *dst = (uint8_t *)&wifiStation; static int rc; FILE *f; size_t bytes; if ((SSID == NULL) || (strlen((char *)SSID) == 0)) { ESP_LOGI(TAG, "read_station(NULL)"); return -1; } memset(dst, 0, sizeof(wifiStation)); f = fopen("/spiffs/etc/stations.conf", "r+"); if (f == NULL) { f = fopen("/spiffs/etc/stations.conf", "w+"); fclose(f); ESP_LOGI(TAG, "/spiffs/etc/stations.conf created, return -1"); return -1; } rc = 0; fseek(f, 0, SEEK_SET); while (1) { bytes = fread(dst, 1, sizeof(wifiStation), f); if (bytes < sizeof(wifiStation)) { fclose(f); memset(dst, 0, sizeof(wifiStation)); return -1; } if (strcmp(wifiStation.SSID, (char *)SSID) == 0) { // Fount it fclose(f); return rc; } rc++; } return -1; } void remove_station(uint8_t *SSID) { FILE *n, *o; uint8_t *dst; size_t bytes; n = fopen("/spiffs/etc/stations.new", "a"); if (n == NULL) { ESP_LOGE(TAG, "cannot create /spiffs/etc/stations.new"); return; } o = fopen("/spiffs/etc/stations.conf", "r"); if (o == NULL) { ESP_LOGE(TAG, "cannot open spiffs/etc/stations.conf for reading"); fclose(n); return; } dst = (uint8_t*)&wifiStation; while (true) { bytes = fread(dst, 1, sizeof(wifiStation), o); if (bytes == 0) break; if ((strcmp((char *)SSID, wifiStation.SSID) == 0) || (strlen(wifiStation.SSID) == 0)) { // Record to delete, don't copy } else { fwrite(dst, 1, sizeof(wifiStation), n); } } fclose(o); fclose(n); rename("/spiffs/etc/stations.conf", "/spiffs/etc/stations.old"); rename("/spiffs/etc/stations.new", "/spiffs/etc/stations.conf"); unlink("/spiffs/etc/stations.old"); } int blacklist_station(uint8_t *SSID) { return -1; } void write_runtime() { uint8_t *dst = (uint8_t *)&runtime; FILE *f = fopen("/spiffs/etc/runtime.conf", "w+"); if (f == NULL) { ESP_LOGE(TAG, "write /spiffs/etc/runtime.conf failed"); return; } size_t bytes = fwrite(dst, 1, sizeof(runtime), f); fclose(f); if (bytes != sizeof(runtime)) { ESP_LOGE(TAG, "/spiffs/etc/runtime.conf written %d/%d bytes", bytes, sizeof(runtime)); } } void read_runtime() { uint8_t *dst; FILE *f = fopen("/spiffs/etc/runtime.conf", "r"); if (f == NULL) { // No runtime yet, create it. runtime.Version = 1; runtime.AutoModeStarted = false; runtime.StageResume = 0; runtime.StageTimeLeft = 0; runtime.HopAddition = 0; runtime.ManualMLT = 45.0; runtime.ManualHLT = 45.0; runtime.BrewStart = (time_t)0; runtime.Logfile[0] = '\0'; runtime.PumpCooling = false; runtime.TimeBrewing = 0; runtime.MashStep = 0; runtime.MLT_usage = 0; runtime.HLT_usage = 0; write_runtime(); } else { dst = (uint8_t*)&runtime; size_t bytes = fread(dst, 1, sizeof(runtime), f); fclose(f); if (bytes != sizeof(runtime)) { ESP_LOGE(TAG, "/spiffs/etc/runtime.conf read %d/%d bytes", bytes, sizeof(runtime)); runtime.MLT_usage = 0; runtime.HLT_usage = 0; } #if 0 printf("Auto started %s\n", runtime.AutoModeStarted ? "yes":"no"); printf("Stage resume %d\n", runtime.StageResume); printf("Stage time left %d\n", runtime.StageTimeLeft); printf("Hop addition %d\n", runtime.HopAddition); printf("Brew start %d\n", (int)runtime.BrewStart); printf("Log file %s\n", runtime.Logfile); printf("Pump cooling %s\n", runtime.PumpCooling ? "yes":"no"); printf("Time brewing %d\n", runtime.TimeBrewing); #endif } } void append_recipe() { uint8_t *dst = (uint8_t *)&recipe; FILE *f = fopen("/spiffs/etc/recipe.conf", "a"); if (f == NULL) { ESP_LOGE(TAG, "append /spiffs/etc/recipe.conf failed"); return; } size_t bytes = fwrite(dst, 1, recipe_hdr.recsize, f); fclose(f); ESP_LOGI(TAG, "/spiffs/etc/recipe.conf appended %d bytes", bytes); } void write_recipe(int RecNo) { uint8_t *dst = (uint8_t *)&recipe; FILE *f = fopen("/spiffs/etc/recipe.conf", "r+"); if (f == NULL) { ESP_LOGE(TAG, "write /spiffs/etc/recipe.conf failed"); return; } fseek(f, (RecNo - 1) * recipe_hdr.recsize + recipe_hdr.hdrsize, SEEK_SET); size_t bytes = fwrite(dst, 1, recipe_hdr.recsize, f); fclose(f); if (bytes != recipe_hdr.recsize) { ESP_LOGE(TAG, "/spiffs/etc/recipe.conf write record %d, %d/%d bytes", RecNo, bytes, recipe_hdr.recsize); } } void read_recipe(int RecNo) { uint8_t *dst; size_t bytes; FILE *f = fopen("/spiffs/etc/recipe.conf", "r"); if (f == NULL) { // No recipe yet, create it. dst = (uint8_t*)&recipe_hdr; memset(dst, 0, sizeof(recipe_hdr)); recipe_hdr.version = RECIPE_VERSION; recipe_hdr.hdrsize = sizeof(recipe_hdr); recipe_hdr.recsize = sizeof(recipe); recipe_hdr.mashmax = MASH_MAX; recipe_hdr.additionmax = ADDITION_MAX; f = fopen("/spiffs/etc/recipe.conf", "w"); bytes = fwrite(dst, 1, sizeof(recipe_hdr), f); if (bytes != sizeof(recipe_hdr)) { ESP_LOGE(TAG, "/spiffs/etc/recipe.conf write header, %d/%d bytes", bytes, sizeof(recipe_hdr)); } dst = (uint8_t*)&recipe; memset(dst, 0, sizeof(recipe)); sprintf(recipe.Name, "Recipe 1"); sprintf(recipe.Code, "001"); sprintf(recipe.MashStep[0].Name, "Mash-in"); recipe.MashStep[0].Type = MASHTYPE_INFUSION; recipe.MashStep[0].Step_temp = recipe.MashStep[0].End_temp = recipe.MashStep[0].Infuse_temp = 67.5; recipe.MashStep[0].Infuse_amount = 15.0; recipe.MashStep[0].Step_time = 1; recipe.MashStep[0].Ramp_time = 1; for (int i = 1; i < MASH_MAX; i++) recipe.MashStep[i].Type = MASHTYPE_TEMPERATURE; sprintf(recipe.MashStep[1].Name, "Mash"); recipe.MashStep[1].Step_temp = recipe.MashStep[1].End_temp = 67.0; recipe.MashStep[1].Step_time = 75; recipe.MashStep[1].Ramp_time = 1; sprintf(recipe.MashStep[2].Name, "Mash-out"); recipe.MashStep[2].Step_temp = recipe.MashStep[2].End_temp = 78.0; recipe.MashStep[2].Step_time = 5; recipe.MashStep[2].Ramp_time = 11; recipe.Mashsteps = 3; recipe.BoilTime = 60; recipe.Additions = 2; sprintf(recipe.Addition[0].Name, "Hop"); recipe.Addition[0].Time = 60; recipe.Addition[0].Type = ADDITION_HOP; sprintf(recipe.Addition[1].Name, "Hop"); recipe.Addition[1].Time = 10; recipe.Addition[1].Type = ADDITION_HOP; recipe.CoolTemp = 20.0; recipe.Whirlpool9 = 0; recipe.Whirlpool7 = 0; recipe.Whirlpool6 = 0; recipe.Whirlpool2 = 0; recipe.SpargeTemp = 85.0; bytes = fwrite(dst, 1, sizeof(recipe), f); fclose(f); } else { /* * Try to read the new file header */ dst = (uint8_t*)&recipe_hdr; fseek(f, 0, SEEK_SET); bytes = fread(dst, 1, sizeof(recipe_hdr), f); if (bytes != sizeof(recipe_hdr)) { ESP_LOGE(TAG, "/spiffs/etc/recipe.conf read header, %d/%d bytes", bytes, sizeof(recipe_hdr)); fclose(f); return; } /* if (recipe_hdr.version < RECIPE_VERSION) { FILE *nf = fopen("/spiffs/etc/recipe.new", "w"); ESP_LOGI(TAG, "/spiffs/etc/recipe.conf version %d, new %d", recipe_hdr.version, RECIPE_VERSION); fseek(f, recipe_hdr.hdrsize, SEEK_SET); dst = (uint8_t*)&recipe; while ((bytes = fread(dst, 1, recipe_hdr.recsize, f))) { // Upgrade data here bytes = fwrite(dst, 1, sizeof(recipe), nf); if (bytes != sizeof(recipe)) { ESP_LOGE(TAG, "/spiffs/etc/recipe.new write data, %d/%d bytes", bytes, sizeof(recipe)); } } // Update the header with new sizes fclose(nf); fclose(f); rename("/spiffs/etc/recipe.conf", "/spiffs/etc/recipe.old"); rename("/spiffs/etc/recipe.new", "/spiffs/etc/recipe.conf"); unlink("/spiffs/etc/recipe.old"); f = fopen("/spiffs/etc/recipe.conf", "r"); } */ dst = (uint8_t*)&recipe; fseek(f, (RecNo - 1) * recipe_hdr.recsize + recipe_hdr.hdrsize, SEEK_SET); bytes = fread(dst, 1, sizeof(recipe), f); fclose(f); if (bytes != sizeof(recipe)) { ESP_LOGE(TAG, "/spiffs/etc/recipe.conf read record %d, %d/%d bytes", RecNo, bytes, sizeof(recipe)); } } } void delete_recipe(int RecNo) { int RecRead = 1, RecWrite = 1; FILE *n, *o; uint8_t *dst; size_t bytes; n = fopen("/spiffs/etc/recipe.new", "a"); if (n == NULL) { ESP_LOGE(TAG, "cannot create /spiffs/etc/recipe.new"); return; } o = fopen("/spiffs/etc/recipe.conf", "r"); if (o == NULL) { ESP_LOGE(TAG, "cannot open spiffs/etc/recipe.conf for reading"); fclose(n); return; } dst = (uint8_t*)&recipe_hdr; fread(dst, 1, recipe_hdr.hdrsize, o); fwrite(dst, 1, recipe_hdr.hdrsize, n); dst = (uint8_t*)&recipe; while (true) { bytes = fread(dst, 1, recipe_hdr.recsize, o); if (bytes == 0) break; if (RecRead != RecNo) { // Record to copy if ((config.RecipeRec == RecRead) && (config.RecipeRec != RecWrite)) { // We need to change the default record. config.RecipeRec = RecWrite; write_config(); } fwrite(dst, 1, recipe_hdr.recsize, n); RecWrite++; } RecRead++; } fclose(o); fclose(n); rename("/spiffs/etc/recipe.conf", "/spiffs/etc/recipe.old"); rename("/spiffs/etc/recipe.new", "/spiffs/etc/recipe.conf"); unlink("/spiffs/etc/recipe.old"); ESP_LOGI(TAG, "Deleted recipe %d", RecNo); }