implement checks if gpio is free when adding new output
This commit is contained in:
parent
22c316edbb
commit
c8247268cc
6 changed files with 140 additions and 75 deletions
|
@ -149,43 +149,7 @@ void loop() {
|
||||||
|
|
||||||
|
|
||||||
if((digitalRead(PinWIPE) != PinWIPE_default) && (alrdySaved == false)) {
|
if((digitalRead(PinWIPE) != PinWIPE_default) && (alrdySaved == false)) {
|
||||||
Serial.println(":: [LOOP] PinWIPE is triggered, saving config.json and set config.system.httpLogSerial to true");
|
Serial.println(":: [LOOP] PinWIPE is triggered");
|
||||||
config.system.httpLogSerial = true;
|
|
||||||
|
|
||||||
// testing output save stuff
|
|
||||||
|
|
||||||
Serial.println(":: [LOOP] save output 0");
|
|
||||||
byte i = 0;
|
|
||||||
config.system.output.type[i] = 1;
|
|
||||||
config.system.output.device[i] = 1;
|
|
||||||
strlcpy(config.system.output.name[i], "bla", sizeof("bla"));
|
|
||||||
config.system.output.gpio[i] = 3;
|
|
||||||
config.system.output.gpio_invert[i] = false;
|
|
||||||
config.system.output.gpio_pwm[i] = false;
|
|
||||||
strlcpy(config.system.output.i2c[i], "0x3", sizeof("0x3"));
|
|
||||||
|
|
||||||
for(byte j=0; j < 4 ; j++) {
|
|
||||||
config.system.output.ip[i][j] = j + 3;
|
|
||||||
}
|
|
||||||
strlcpy(config.system.output.ip_path[i], "/asd?foo=lol", sizeof("/asd?foo=lol"));
|
|
||||||
config.system.output.enabled[i] = true;
|
|
||||||
|
|
||||||
Serial.println(":: [LOOP] save output 1");
|
|
||||||
i = 1;
|
|
||||||
config.system.output.type[i] = 2;
|
|
||||||
config.system.output.device[i] = 3;
|
|
||||||
strlcpy(config.system.output.name[i], "lol", sizeof("lol"));
|
|
||||||
config.system.output.gpio[i] = 5;
|
|
||||||
config.system.output.gpio_invert[i] = true;
|
|
||||||
config.system.output.gpio_pwm[i] = true;
|
|
||||||
strlcpy(config.system.output.i2c[i], "0x69", sizeof("0x69"));
|
|
||||||
|
|
||||||
for(byte j=0; j < 4 ; j++) {
|
|
||||||
config.system.output.ip[i][j] = j + 23;
|
|
||||||
}
|
|
||||||
strlcpy(config.system.output.ip_path[i], "/toggle_switch?on=true", sizeof("/toggle_switch?on=true"));
|
|
||||||
config.system.output.enabled[i] = true;
|
|
||||||
|
|
||||||
// save config to littlefs as json
|
// save config to littlefs as json
|
||||||
SaveConfig();
|
SaveConfig();
|
||||||
// only print json to serial
|
// only print json to serial
|
||||||
|
|
|
@ -70,6 +70,10 @@ const byte INPUT_ONLY = 4;
|
||||||
const byte NO_PWM = 5;
|
const byte NO_PWM = 5;
|
||||||
const byte HIGH_BOOT = 6;
|
const byte HIGH_BOOT = 6;
|
||||||
|
|
||||||
|
const byte OUTPUT_TYPE_GPIO = 1;
|
||||||
|
const byte OUTPUT_TYPE_I2C = 2;
|
||||||
|
const byte OUTPUT_TYPE_WEB = 3;
|
||||||
|
|
||||||
struct GPIO_Index {
|
struct GPIO_Index {
|
||||||
const byte gpio;
|
const byte gpio;
|
||||||
const byte note;
|
const byte note;
|
||||||
|
@ -110,7 +114,7 @@ struct Config_System_Output {
|
||||||
* - output_type: output type like GPIO, I2C, URL
|
* - output_type: output type like GPIO, I2C, URL
|
||||||
* 1 - GPIO
|
* 1 - GPIO
|
||||||
* 2 - I2C
|
* 2 - I2C
|
||||||
* 3 - URL
|
* 3 - Web
|
||||||
* - device: what this output is connected to
|
* - device: what this output is connected to
|
||||||
* 1 - Light
|
* 1 - Light
|
||||||
* 2 - Fan
|
* 2 - Fan
|
||||||
|
@ -118,25 +122,29 @@ struct Config_System_Output {
|
||||||
* 4 - Humudifier
|
* 4 - Humudifier
|
||||||
* 5 - Dehumidifier
|
* 5 - Dehumidifier
|
||||||
* 6 - Heating
|
* 6 - Heating
|
||||||
|
* - name: name of output
|
||||||
|
* - enabled: enable output
|
||||||
* - gpio: which gpio is used
|
* - gpio: which gpio is used
|
||||||
* - gpio_invert: invert gpio output
|
* - gpio_invert: invert gpio output
|
||||||
* - gpio_pwm: enable pwm for output
|
* - gpio_pwm: enable pwm for output
|
||||||
* - i2c:
|
* - i2c:
|
||||||
* - ip: ip to smart plug (tasmota e.g.)
|
* - web_host: ip to smart plug (tasmota e.g.)
|
||||||
* - ip_path: uri path
|
* - web_req_on: GET request path to turn ON
|
||||||
* - enabled: enable output
|
* - web_req_off: GET request path to turn ON
|
||||||
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
byte type[Max_Outputs];
|
byte type[Max_Outputs];
|
||||||
byte device[Max_Outputs];
|
byte device[Max_Outputs];
|
||||||
char name[Max_Outputs][32];
|
char name[Max_Outputs][32];
|
||||||
|
bool enabled[Max_Outputs];
|
||||||
byte gpio[Max_Outputs];
|
byte gpio[Max_Outputs];
|
||||||
bool gpio_invert[Max_Outputs];
|
bool gpio_invert[Max_Outputs];
|
||||||
bool gpio_pwm[Max_Outputs];
|
bool gpio_pwm[Max_Outputs];
|
||||||
char i2c[Max_Outputs][8];
|
char i2c[Max_Outputs][8];
|
||||||
byte ip[Max_Outputs][4];
|
char web_host[Max_Outputs][32];
|
||||||
char ip_path[Max_Outputs][32];
|
char web_req_on[Max_Outputs][32];
|
||||||
bool enabled[Max_Outputs];
|
char web_req_off[Max_Outputs][32];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* main System struct */
|
/* main System struct */
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
// blink fast with the built in LED in an infinite loop
|
// blink fast with the built in LED in an infinite loop
|
||||||
void Restart() {
|
void Restart() {
|
||||||
Serial.println(":: [Restart] got triggered, restarting in 2 seconds");
|
Serial.println(":: [Core:Restart] got triggered, restarting in 2 seconds");
|
||||||
byte i = 0;
|
byte i = 0;
|
||||||
while(i <= 16) {
|
while(i <= 16) {
|
||||||
if(i % 2) {
|
if(i % 2) {
|
||||||
|
@ -55,3 +55,60 @@ char* IP2Char(IPAddress ipaddr){
|
||||||
sprintf(buffer, "%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3] );
|
sprintf(buffer, "%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3] );
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte Give_Free_OutputId() {
|
||||||
|
byte outputId_free;
|
||||||
|
for(byte i=0; i < Max_Outputs; i++) {
|
||||||
|
if(config.system.output.type[i] > 0) {
|
||||||
|
// here i define that 255 stands for "no more free outputs"
|
||||||
|
outputId_free = 255;
|
||||||
|
} else {
|
||||||
|
outputId_free = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef DEBUG
|
||||||
|
Serial.printf("DB [Core:Give_Free_OutputId] next free output id: %d\n", outputId_free);
|
||||||
|
#endif
|
||||||
|
return outputId_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
//bool Check_OutputId_Used(byte outputId) {
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
// checks if GPIO is already in use by output or sensor
|
||||||
|
bool Check_GPIOindex_Used(byte gpio) {
|
||||||
|
bool used;
|
||||||
|
#ifndef DEBUG
|
||||||
|
Serial.printf("DB [Core:Check_GPIOindex_Used] check GPIO: %d\n", gpio);
|
||||||
|
#endif
|
||||||
|
// go through each outputid
|
||||||
|
for(byte i=0; i < Max_Outputs; i++) {
|
||||||
|
#ifndef DEBUG
|
||||||
|
//Serial.printf("DB [Core:Check_GPIOindex_Used] OutputId: %d , type: %d\n", i, config.system.output.type[i]);
|
||||||
|
#endif
|
||||||
|
// check if output type is gpio
|
||||||
|
if(config.system.output.type[i] == OUTPUT_TYPE_GPIO) {
|
||||||
|
#ifndef DEBUG
|
||||||
|
Serial.printf("DB [Core:Check_GPIOindex_Used] OutputId: %d is GPIO (type %d)\n", i, config.system.output.type[i]);
|
||||||
|
#endif
|
||||||
|
// check if gpio id is already in use
|
||||||
|
if(config.system.output.gpio[i] == gpio) {
|
||||||
|
#ifndef DEBUG
|
||||||
|
Serial.printf("DB [Core:Check_GPIOindex_Used] output.gpio[%d](%d) == GPIO %d\n", i, config.system.output.gpio[i], gpio);
|
||||||
|
#endif
|
||||||
|
used = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
used = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef DEBUG
|
||||||
|
Serial.printf("DB [Core:Check_GPIOindex_Used] GPIO: %d, used: %d\n", gpio, used);
|
||||||
|
#endif
|
||||||
|
// check sensors
|
||||||
|
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
|
@ -213,15 +213,17 @@ bool LoadConfig() {
|
||||||
config.system.output.type[i] = objSystemOutput["type"][i];
|
config.system.output.type[i] = objSystemOutput["type"][i];
|
||||||
config.system.output.device[i] = objSystemOutput["device"][i];
|
config.system.output.device[i] = objSystemOutput["device"][i];
|
||||||
strlcpy(config.system.output.name[i], objSystemOutput["name"][i], sizeof(config.system.output.name[i]));
|
strlcpy(config.system.output.name[i], objSystemOutput["name"][i], sizeof(config.system.output.name[i]));
|
||||||
|
config.system.output.enabled[i] = objSystemOutput["enabled"][i];
|
||||||
|
// gpio
|
||||||
config.system.output.gpio[i] = objSystemOutput["gpio"][i];
|
config.system.output.gpio[i] = objSystemOutput["gpio"][i];
|
||||||
config.system.output.gpio_invert[i] = objSystemOutput["gpio_invert"][i];
|
config.system.output.gpio_invert[i] = objSystemOutput["gpio_invert"][i];
|
||||||
config.system.output.gpio_pwm[i] = objSystemOutput["gpio_pwm"][i];
|
config.system.output.gpio_pwm[i] = objSystemOutput["gpio_pwm"][i];
|
||||||
|
// i2c
|
||||||
strlcpy(config.system.output.i2c[i], objSystemOutput["i2c"][i], sizeof(config.system.output.i2c[i]));
|
strlcpy(config.system.output.i2c[i], objSystemOutput["i2c"][i], sizeof(config.system.output.i2c[i]));
|
||||||
for(byte j=0; j < 4 ; j++) {
|
// web
|
||||||
config.system.output.ip[i][j] = objSystemOutput["ip"][i][j];
|
strlcpy(config.system.output.web_host[i], objSystemOutput["web_host"][i], sizeof(config.system.output.web_host[i]));
|
||||||
}
|
strlcpy(config.system.output.web_req_on[i], objSystemOutput["web_req_on"][i], sizeof(config.system.output.web_req_on[i]));
|
||||||
strlcpy(config.system.output.ip_path[i], objSystemOutput["ip_path"][i], sizeof(config.system.output.ip_path[i]));
|
strlcpy(config.system.output.web_req_off[i], objSystemOutput["web_req_off"][i], sizeof(config.system.output.web_req_off[i]));
|
||||||
config.system.output.enabled[i] = objSystemOutput["enabled"][i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,16 +293,18 @@ bool SaveConfig(bool writeToSerial = false) {
|
||||||
objSystemOutput["type"][i] = config.system.output.type[i];
|
objSystemOutput["type"][i] = config.system.output.type[i];
|
||||||
objSystemOutput["device"][i] = config.system.output.device[i];
|
objSystemOutput["device"][i] = config.system.output.device[i];
|
||||||
objSystemOutput["name"][i] = config.system.output.name[i];
|
objSystemOutput["name"][i] = config.system.output.name[i];
|
||||||
|
objSystemOutput["enabled"][i] = config.system.output.enabled[i];
|
||||||
|
// gpio
|
||||||
objSystemOutput["gpio"][i] = config.system.output.gpio[i];
|
objSystemOutput["gpio"][i] = config.system.output.gpio[i];
|
||||||
objSystemOutput["gpio_invert"][i] = config.system.output.gpio_invert[i];
|
objSystemOutput["gpio_invert"][i] = config.system.output.gpio_invert[i];
|
||||||
objSystemOutput["gpio_pwm"][i] = config.system.output.gpio_pwm[i];
|
objSystemOutput["gpio_pwm"][i] = config.system.output.gpio_pwm[i];
|
||||||
|
// i2c
|
||||||
objSystemOutput["i2c"][i] = config.system.output.i2c[i];
|
objSystemOutput["i2c"][i] = config.system.output.i2c[i];
|
||||||
|
// web
|
||||||
|
objSystemOutput["web_host"][i] = config.system.output.web_host[i];
|
||||||
|
objSystemOutput["web_req_on"][i] = config.system.output.web_req_on[i];
|
||||||
|
objSystemOutput["web_req_off"][i] = config.system.output.web_req_off[i];
|
||||||
|
|
||||||
for(byte j=0; j < 4 ; j++) {
|
|
||||||
objSystemOutput["ip"][i][j] = config.system.output.ip[i][j];
|
|
||||||
}
|
|
||||||
objSystemOutput["ip_path"][i] = config.system.output.ip_path[i];
|
|
||||||
objSystemOutput["enabled"][i] = config.system.output.enabled[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -365,26 +365,20 @@ String Proc_WebPage_system_output_add(const String& var) {
|
||||||
return Proc_WebPage_system_SUBNAV(var, 1);
|
return Proc_WebPage_system_SUBNAV(var, 1);
|
||||||
} else if(var == "OUTPUT_ID") {
|
} else if(var == "OUTPUT_ID") {
|
||||||
// we check which id is free. A free ID as type == 0
|
// we check which id is free. A free ID as type == 0
|
||||||
byte freeOutputId;
|
return String(Give_Free_OutputId());
|
||||||
|
|
||||||
for(byte i=0; i < Max_Outputs; i++) {
|
|
||||||
if(config.system.output.type[i] > 0) {
|
|
||||||
// here i define that 255 stands for "not available"
|
|
||||||
freeOutputId = 255;
|
|
||||||
} else {
|
|
||||||
freeOutputId = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Serial.printf("DB [Webserver:system:output:add(Proc)] next free output id: %d\n", freeOutputId);
|
|
||||||
return String(freeOutputId);
|
|
||||||
|
|
||||||
} else if(var == "GPIO_INDEX") {
|
} else if(var == "GPIO_INDEX") {
|
||||||
String gpioIndex_html;
|
String gpioIndex_html;
|
||||||
for(byte i = 0; i < GPIOindex_length; i++) {
|
for(byte i = 0; i < GPIOindex_length; i++) {
|
||||||
gpioIndex_html += "<option value='";
|
gpioIndex_html += "<option value='";
|
||||||
gpioIndex_html += i;
|
gpioIndex_html += i;
|
||||||
gpioIndex_html += "'>GPIO ";
|
gpioIndex_html += "'";
|
||||||
|
// set disabled option of gpio is already in use
|
||||||
|
if(Check_GPIOindex_Used(i) == true) {
|
||||||
|
gpioIndex_html += " disabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
gpioIndex_html += ">GPIO ";
|
||||||
gpioIndex_html += GPIOindex[i].gpio;
|
gpioIndex_html += GPIOindex[i].gpio;
|
||||||
//add gpio note if there is some
|
//add gpio note if there is some
|
||||||
if(GPIOindex[i].note > 0) {
|
if(GPIOindex[i].note > 0) {
|
||||||
|
@ -398,6 +392,10 @@ String Proc_WebPage_system_output_add(const String& var) {
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add USED if gpio is already in use
|
||||||
|
if(Check_GPIOindex_Used(i) == true) {
|
||||||
|
gpioIndex_html += " USED";
|
||||||
|
}
|
||||||
gpioIndex_html += "</option>";
|
gpioIndex_html += "</option>";
|
||||||
|
|
||||||
|
|
||||||
|
@ -444,6 +442,7 @@ void WebPage_system_output_add(AsyncWebServerRequest *request) {
|
||||||
if(request->method() == HTTP_POST) {
|
if(request->method() == HTTP_POST) {
|
||||||
Serial.println(":: [Webserver:system:output:add] [POST] hello");
|
Serial.println(":: [Webserver:system:output:add] [POST] hello");
|
||||||
byte outputId;
|
byte outputId;
|
||||||
|
byte outputType;
|
||||||
if(request->hasParam("outputId", true)) {
|
if(request->hasParam("outputId", true)) {
|
||||||
const AsyncWebParameter* p_outputId = request->getParam("outputId", true);
|
const AsyncWebParameter* p_outputId = request->getParam("outputId", true);
|
||||||
Serial.printf(":: [Webserver:system] POST[%s]: %s\n", p_outputId->name().c_str(), p_outputId->value().c_str());
|
Serial.printf(":: [Webserver:system] POST[%s]: %s\n", p_outputId->name().c_str(), p_outputId->value().c_str());
|
||||||
|
@ -453,7 +452,11 @@ void WebPage_system_output_add(AsyncWebServerRequest *request) {
|
||||||
if(request->hasParam("type", true)) {
|
if(request->hasParam("type", true)) {
|
||||||
const AsyncWebParameter* p_type = request->getParam("type", true);
|
const AsyncWebParameter* p_type = request->getParam("type", true);
|
||||||
Serial.printf(":: [Webserver:system] POST[%s]: %s\n", p_type->name().c_str(), p_type->value().c_str());
|
Serial.printf(":: [Webserver:system] POST[%s]: %s\n", p_type->name().c_str(), p_type->value().c_str());
|
||||||
|
// put info config struct
|
||||||
config.system.output.type[outputId] = p_type->value().toInt();
|
config.system.output.type[outputId] = p_type->value().toInt();
|
||||||
|
|
||||||
|
// remember the value in own var to work later with here
|
||||||
|
outputType = p_type->value().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(request->hasParam("device", true)) {
|
if(request->hasParam("device", true)) {
|
||||||
|
@ -474,6 +477,28 @@ void WebPage_system_output_add(AsyncWebServerRequest *request) {
|
||||||
config.system.output.enabled[outputId] = p_enabled->value().toInt();
|
config.system.output.enabled[outputId] = p_enabled->value().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only fill gpio values if type is GPIO
|
||||||
|
if(outputType == 1) {
|
||||||
|
if(request->hasParam("gpio", true)) {
|
||||||
|
const AsyncWebParameter* p_gpio = request->getParam("gpio", true);
|
||||||
|
Serial.printf(":: [Webserver:system] POST[%s]: %s\n", p_gpio->name().c_str(), p_gpio->value().c_str());
|
||||||
|
config.system.output.gpio[outputId] = p_gpio->value().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(request->hasParam("gpio_pwm", true)) {
|
||||||
|
const AsyncWebParameter* p_gpio_pwm = request->getParam("gpio_pwm", true);
|
||||||
|
Serial.printf(":: [Webserver:system] POST[%s]: %s\n", p_gpio_pwm->name().c_str(), p_gpio_pwm->value().c_str());
|
||||||
|
config.system.output.gpio_pwm[outputId] = p_gpio_pwm->value().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(request->hasParam("gpio_invert", true)) {
|
||||||
|
const AsyncWebParameter* p_gpio_invert = request->getParam("gpio_invert", true);
|
||||||
|
Serial.printf(":: [Webserver:system] POST[%s]: %s\n", p_gpio_invert->name().c_str(), p_gpio_invert->value().c_str());
|
||||||
|
config.system.output.gpio_invert[outputId] = p_gpio_invert->value().toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SaveConfig();
|
SaveConfig();
|
||||||
|
|
||||||
AsyncWebServerResponse *response = request->beginChunkedResponse("text/html", Chunk_system_output_add_HTML, Proc_WebPage_system_output_add_POST);
|
AsyncWebServerResponse *response = request->beginChunkedResponse("text/html", Chunk_system_output_add_HTML, Proc_WebPage_system_output_add_POST);
|
||||||
|
|
|
@ -202,7 +202,14 @@ const char* Page_system_output_add_HTML PROGMEM = R"(%HEADER%
|
||||||
<select name='gpio_pwm' >
|
<select name='gpio_pwm' >
|
||||||
<option disabled value='' selected hidden>---</option>
|
<option disabled value='' selected hidden>---</option>
|
||||||
<option value='1'>Enable</option>
|
<option value='1'>Enable</option>
|
||||||
<option value='2'>Disable</option>
|
<option value='0'>Disable</option>
|
||||||
|
</select><br>
|
||||||
|
|
||||||
|
<u>GPIO invert</u>:<br>
|
||||||
|
<select name='gpio_invert' >
|
||||||
|
<option disabled value='' selected hidden>---</option>
|
||||||
|
<option value='1'>Yes</option>
|
||||||
|
<option value='0'>No</option>
|
||||||
</select><br>
|
</select><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -213,14 +220,14 @@ const char* Page_system_output_add_HTML PROGMEM = R"(%HEADER%
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='hidden' id='type_3'>
|
<div class='hidden' id='type_3'>
|
||||||
<u>Host</u>:<br>
|
<u>Web</u>:<br>
|
||||||
<input type='text' name='host' maxlength='16' value='' ><br>
|
<input type='text' name='web_host' maxlength='32' value='' ><br>
|
||||||
|
|
||||||
<u>URI on</u>:<br>
|
<u>URI on</u>:<br>
|
||||||
<input type='text' name='req_on' maxlength='16' value='' ><br>
|
<input type='text' name='web_req_on' maxlength='32' value='' ><br>
|
||||||
|
|
||||||
<u>URI off</u>:<br>
|
<u>URI off</u>:<br>
|
||||||
<input type='text' name='req_off' maxlength='16' value='' ><br>
|
<input type='text' name='web_req_off' maxlength='32' value='' ><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
Loading…
Reference in a new issue