CanGrow/include/CanGrow.h

411 lines
9.6 KiB
C

/*
*
* include/CanGrow.h - main header file
*
*
*
*/
/* If you need detailed debug output, uncomment the following lines.
* DEBUG is less noisy messages
* DEBUG2 are noisy messages
* DEBUG3 are super noisy messages */
//#define DEBUG
//#define DEBUG2
//#define DEBUG3
/* ensure the code will also compile when CANGROW_VER and CANGROW_BUILD
* are not defined by the compiler arguments
* like -DCANGROW_VER="0.x-dev" or -DCANGROW_BUILD="commitid-core-timestamp"
*/
/*
*
*
* Constants
*
*
*/
#ifndef CANGROW_VER
#define CANGROW_VER "0.2-dev2"
#endif
#ifndef CANGROW_BUILD
#define CANGROW_BUILD "0420"
#endif
#ifndef CANGROW_BUILDTIME
#define CANGROW_BUILDTIME "1711922400" // 1.4.2024
#endif
#define CANGROW_DEFAULT_WIFI_SSID "CanGrow-unconfigured"
#define CANGROW_DEFAULT_WIFI_PASSWORD "letitgrow!"
#define CANGROW_CFG "/config.json"
#define TIME2FS "/time"
/* define Max limits for outputs and sensors */
const byte Max_Outputs = 16;
const byte Max_Sensors = 16;
/* How much values can a sensor contain at max */
const byte Max_Sensors_Read = 6;
/* how much GPIOs a Sensor can use */
const byte Max_Sensors_GPIO = 2;
/* actual structure initialization for GPIO_Index is done within the header files
* for ESP32 and ESP8266
*
* GPIO_Index.note explenation:
* 1 - BOOTFAILS_LOW: BootFails when LOW
* 2 - BOOTFAILS_HIGH: BootFails when HIGH
* 3 - FLASHMODE_LOW: FlashMode needs LOW to enter
* 4 - INPUT_ONLY: Input Only
* 5 - NO_PWM: No PWM output
* 6 - PWM_BOOT: PWM at boot time
* 7 - INT_ADC Pin for internal ADC (only ESP32, ESP8266 only has one Pin, A0)
*/
const byte BOOTFAILS_LOW = 1;
const byte BOOTFAILS_HIGH = 2;
const byte FLASHMODE_LOW = 3;
const byte INPUT_ONLY = 4;
const byte NO_PWM = 5;
const byte HIGH_BOOT = 6;
const byte INT_ADC = 7;
const byte INT_DAC = 8;
//const char signMessage[] PROGMEM = {"I AM PREDATOR, UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART"};
const char BOOTFAILS_LOW_descr[] PROGMEM = {"BF_LOW"};
const char BOOTFAILS_HIGH_descr[] PROGMEM = {"BF_HIGH"};
const char FLASMODE_LOW_descr[] PROGMEM = {"FM_LOW"};
const char INPUT_ONLY_descr[] PROGMEM = {"IN_ONLY"};
const char NO_PWM_descr[] PROGMEM = {"NO_PWM"};
const char HIGH_BOOT_descr[] PROGMEM = {"B_HIGH"};
const char INT_ADC_descr[] PROGMEM = {"INT_ADC"};
const char INT_DAC_descr[] PROGMEM = {"INT_DAC"};
const char * GPIO_Index_note_descr[] = {
NULL, // 0 - no note
BOOTFAILS_LOW_descr, // 1
BOOTFAILS_HIGH_descr, // 2
FLASMODE_LOW_descr, // 3
INPUT_ONLY_descr, // 4
NO_PWM_descr, // 5
HIGH_BOOT_descr, // 6
INT_ADC_descr, // 7
INT_DAC_descr, // 8
};
/*
* RTCs available
*/
// 0 is unconfigured
const byte RTCs_total = 4;
const byte RTCs_DS1307 = 1;
const byte RTCs_DS3231 = 2;
const byte RTCs_PCF8523 = 3;
const byte RTCs_PCF8563 = 4;
const char RTCs_DS1307_descr[] PROGMEM = {"DS1307"};
const char RTCs_DS3231_descr[] PROGMEM = {"DS3231"};
const char RTCs_PCF8523_descr[] PROGMEM = {"PCF8523"};
const char RTCs_PCF8563_descr[] PROGMEM = {"PCF8563"};
const char * RTCs_descr[] = {
NULL, // unconfigured
RTCs_DS1307_descr,
RTCs_DS3231_descr,
RTCs_PCF8523_descr,
RTCs_PCF8563_descr,
};
/*
* Time scales
*/
// 0 is unconfigured
const byte TIMESCALE_total = 7;
const byte TIMESCALE_SECOND = 0;
const byte TIMESCALE_MINUTE = 1;
const byte TIMESCALE_HOUR = 2;
const byte TIMESCALE_DAY = 3;
const byte TIMESCALE_WEEK = 4;
const byte TIMESCALE_MONTH = 5;
const byte TIMESCALE_YEAR = 6;
const char TIMESCALE_SECOND_descr[] PROGMEM = {"Second"};
const char TIMESCALE_MINUTE_descr[] PROGMEM = {"Minute"};
const char TIMESCALE_HOUR_descr[] PROGMEM = {"Hour"};
const char TIMESCALE_DAY_descr[] PROGMEM = {"Day"};
const char TIMESCALE_WEEK_descr[] PROGMEM = {"Week"};
const char TIMESCALE_MONTH_descr[] PROGMEM = {"Month"};
const char TIMESCALE_YEAR_descr[] PROGMEM = {"Year"};
const char * Timescale_descr[] = {
TIMESCALE_SECOND_descr,
TIMESCALE_MINUTE_descr,
TIMESCALE_HOUR_descr,
TIMESCALE_DAY_descr,
TIMESCALE_WEEK_descr,
TIMESCALE_MONTH_descr,
TIMESCALE_YEAR_descr,
};
/* GPIO Index struct
* filled with CanGrow_ESP8266.h and CanGrow_ESP32.h
*/
struct GPIO_Index {
const byte gpio;
const byte note;
};
/*
*
* Config
*
* Note: when adding/removing/changing a saved Config variable
* you have to touch the config struct, LoadConfig() and SaveConfig() at least too!
*/
/*
* Config WiFi
*/
struct Config_WiFi {
char ssid[32];
char password[64];
bool dhcp;
byte ip[4] = {192,168,4,20};
byte netmask[4] = {255,255,255,0};
byte gateway[4] = {0,0,0,0};
byte dns[4] = {0,0,0,0};
};
/*
* Config System
*/
struct Config_System_Output {
/*
* Config System Output
*
* - type: output type like GPIO, I2C, URL
* 1 - GPIO
* 2 - I2C
* 3 - Web
* - device: what this output is connected to
* 1 - Light
* 2 - Fan
* 3 - Pump
* 4 - Humudifier
* 5 - Dehumidifier
* 6 - Heating
* - name: name of output
* - enabled: enable output
* - gpio: which gpio is used
* - invert: invert output
* - gpio_pwm: enable pwm for output
* - i2c:
* - webcall_host: ip to smart plug (tasmota e.g.)
* - webcall_path_on: GET request path to turn ON
* - webcall_path_off: GET request path to turn OFF
*
*/
byte type[Max_Outputs];
byte device[Max_Outputs];
char name[Max_Outputs][32];
bool enabled[Max_Outputs];
byte gpio[Max_Outputs];
bool gpio_pwm[Max_Outputs];
bool invert[Max_Outputs];
byte i2c_type[Max_Outputs];
byte i2c_addr[Max_Outputs];
byte i2c_port[Max_Outputs];
char webcall_host[Max_Outputs][32];
char webcall_path_on[Max_Outputs][32];
char webcall_path_off[Max_Outputs][32];
char webcall_user[Max_Outputs][32];
char webcall_password[Max_Outputs][32];
};
struct Config_System_Sensor {
/*
* Config System Sensor
* - type: Index ID of SensorIndex, which Sensor to use (ADC, BME280, Chirp, ...)
* - name: nice name
* - gpio[]: gpio to use for RPM reading, builtin ADC, OneWire, TwoWire
*/
byte type[Max_Sensors];
char name[Max_Sensors][32];
byte i2c_addr[Max_Sensors];
byte gpio[Max_Sensors][Max_Sensors_GPIO];
float offset[Max_Sensors][Max_Sensors_Read];
unsigned int low[Max_Sensors][Max_Sensors_Read];
unsigned int high[Max_Sensors][Max_Sensors_Read];
byte rawConvert[Max_Sensors][Max_Sensors_Read];
};
/* main System struct */
struct Config_System {
bool ntp = true;
byte rtc;
bool time2fs;
short ntpOffset;
unsigned short maintenanceDuration;
char esp32cam[16];
char httpUser[32];
char httpPass[32];
bool httpLogSerial;
unsigned short schedulerInterval = 1000;
unsigned short pwmFreq = 13370;
Config_System_Output output;
Config_System_Sensor sensor;
};
/*
* Config Grow
*/
struct Config_Grow_Light {
bool configured[Max_Outputs];
byte output[Max_Outputs];
byte sunriseHourVeg[Max_Outputs];
byte sunriseMinuteVeg[Max_Outputs];
byte sunsetHourVeg[Max_Outputs];
byte sunsetMinuteVeg[Max_Outputs];
byte sunriseHourBloom[Max_Outputs];
byte sunriseMinuteBloom[Max_Outputs];
byte sunsetHourBloom[Max_Outputs];
byte sunsetMinuteBloom[Max_Outputs];
byte power[Max_Outputs];
bool fade[Max_Outputs];
byte fadeDuration[Max_Outputs];
};
struct Config_Grow_Air {
bool configured[Max_Outputs];
byte output[Max_Outputs];
byte power[Max_Sensors];
byte controlSensor[Max_Outputs];
byte controlRead[Max_Outputs];
byte controlMode[Max_Outputs];
float min[Max_Outputs];
float max[Max_Outputs];
};
struct Config_Grow_Water {
bool configured[Max_Outputs];
byte output[Max_Outputs];
byte controlSensor[Max_Outputs];
byte controlRead[Max_Outputs];
byte controlMode[Max_Outputs];
byte onTime[Max_Sensors];
byte min[Max_Sensors];
byte max[Max_Sensors];
byte interval[Max_Sensors];
byte intervalUnit[Max_Sensors];
};
struct Config_Grow_Dashboard {
bool configured[Max_Sensors][Max_Sensors_Read];
byte sensor[Max_Sensors][Max_Sensors_Read];
};
struct Config_Grow {
char name[64] = "CanGrow";
unsigned long start;
byte daysVeg = 42;
byte daysBloom = 69;
Config_Grow_Light light;
Config_Grow_Air air;
Config_Grow_Water water;
Config_Grow_Dashboard dashboard;
//unsigned short dayOfGrow;
//byte daysSeed;
//byte lightHoursVeg;
//byte lightHoursBloom;
//byte sunriseHour;
//byte sunriseMinute;
//bool sunFade;
//byte sunFadeDuration;
};
/*
* main Config struct
*/
struct Config {
char test[16] = "123";
Config_WiFi wifi;
Config_System system;
Config_Grow grow;
};
Config config;
/*
*
*
* Global Runtime variables
*
*
*/
// do we need a restart? (e.g. after wifi settings change)
bool needRestart = false;
// this triggers Restart() from the main loop
bool doRestart = false;
// previous value of millis within the scheduler loop
unsigned long schedulerPrevMillis = 0;
/* in which time status is the system
* 0 - OK
* 1 - RTC fallback is used
* 2 - Time2FS fallback is used
*/
byte timeSrcStatus;
/* rtcError - false no Error, true had error while init */
bool rtcError = false;
// did ntp offset got changed?
bool updateNtpOffset = false;
/* sensorStatus[] to keep track if sensor init succeeded or not, true is OK */
bool sensorStatus[Max_Sensors];
/* outputStatus[] to keep track if output init succeeded or not, true is OK */
bool outputStatus[Max_Outputs];
/* outputState[] gets read by Output_Update() */
byte outputState[Max_Outputs];
/* keep track how often a http call failed */
byte outputWebcallFailed[Max_Outputs];
/* remember timestamp when pump was turned on to turn it off after config.grow.water.onTime */
unsigned long controlWaterLastStarted[Max_Outputs];
/* remember timestamp when last water cycle was done.*/
unsigned long controlWaterLast[Max_Outputs];