main/config.c

Sat, 06 Jun 2020 13:28:46 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 06 Jun 2020 13:28:46 +0200
changeset 77
66c77497d86d
parent 57
6c5211c0120b
child 82
7d17e2cb31a8
permissions
-rw-r--r--

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.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));
    } else {
	ESP_LOGD(TAG, "/spiffs/etc/config.conf written %d bytes", bytes);
    }
}



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]);
	sprintf(config.ap_ssid, "brewboardAP-%02x%02x%02x", mac_addr[3], mac_addr[4], mac_addr[5]);
	sprintf(config.ap_pwd, "%s", "triplehop");
	config.ap_channel = 5;
	config.ap_ssid_hidden = 0;
	config.ap_bandwidth = WIFI_BW_HT20;
	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;
	size_t bytes = fread(dst, 1, sizeof(config), f);
	fclose(f);
	ESP_LOGD(TAG, "/spiffs/etc/config.conf read %d bytes", bytes);
	if (config.AskIodine && ! config.IodineTime) {
	    config.IodineTime = 30;
	    write_config();
	}
	if (strlen(config.uuid) !=36) {
	    esp_efuse_mac_get_default(mac_addr);
	    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();
	}
    }
}



void append_equipment() {
    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, sizeof(equipment), f);
    fclose(f);
    ESP_LOGI(TAG, "/spiffs/etc/equipments.conf appended %d bytes", bytes);
}



void read_equipment(int RecNo) {
    uint8_t *dst;
    FILE  *f = fopen("/spiffs/etc/equipments.conf", "r");
	      
    if (f == NULL) {
	// No configuration yet, create it.
	equipment.Version = 1;
	equipment.Record = 1;
	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 = 150.0;
	equipment.PID_kI = 1.5;
	equipment.PID_kD = 15000.0;
	equipment.PID_POn = PID_P_ON_E;
	equipment.SampleTime = 5000;
	append_equipment();
    } else {
	dst = (uint8_t*)&equipment;
	while (1) {
	    size_t bytes = fread(dst, 1, sizeof(equipment), f);
	    if (bytes && equipment.Record == RecNo) {
		fclose(f);
		ESP_LOGD(TAG, "/spiffs/etc/equipments.conf read %d bytes, record %d: %s", bytes, RecNo, equipment.Name);
		return;
	    }
	    if (bytes == 0)
		break;
	}
	fclose(f);
	ESP_LOGE(TAG, "/spiffs/etc/equipments.conf read error, record %d not found", RecNo);
    }
}



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) * sizeof(equipment), SEEK_SET);
    size_t bytes = fwrite(dst, 1, sizeof(equipment), f);
    fclose(f);
    ESP_LOGI(TAG, "/spiffs/etc/equipments.conf update record %d, %d bytes", RecNo, bytes);
}



void delete_equipment(int RecNo)
{
    int		RecNow = 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;
    while (true) {
	bytes = fread(dst, 1, sizeof(equipment), o);
	if (bytes == 0)
	    break;

	if (equipment.Record == RecNo) {
	    // Record to delete, don't copy
	    printf("Ditch %d\n", RecNo);
	} else {
	    if ((config.EquipmentRec == equipment.Record) && (config.EquipmentRec != RecNow)) {
		// We need to change the default record.
		config.EquipmentRec = RecNow;
		write_config();
	    }
	    printf("Copy %d to %d\n", equipment.Record, RecNow);
	    equipment.Record = RecNow;
	    fwrite(dst, 1, sizeof(equipment), n);
	    RecNow++;
	}
    }
    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");
}



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));
    } else {
	ESP_LOGD(TAG, "/spiffs/etc/runtime.conf written %d bytes", bytes);
    }
}



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;
	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.MashStep = 0;
	    runtime.MaltAdded = false;
	}
#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);
}

mercurial