hydroponic-controller/include/wifi_functions.h
2025-06-29 19:25:17 +02:00

216 lines
No EOL
6.8 KiB
C

#ifndef _WIFI_FUNCTIONS_H_
#define _WIFI_FUNCTIONS_H_
#include <WiFi.h>
#include <MQTT.h>
#include "wifi_settings.h"
#include "helpfunctions.h"
#if defined(RELAISCOUNT) || defined(VALVECOUNT)
#include "pump.h"
#endif
bool force_ec_measurement=false;
struct mqttValueTiming{
float minchange;
float maxchange;
unsigned long mintime;
unsigned long maxtime;
float lastvalue=0;
unsigned long lasttime=0;
};
WiFiClient net;
MQTTClient client;
bool sendallnext_flag=false;
bool enableTiming=true;
bool publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis);
void publishValue(String topic,float value,uint8_t decimals);
void publishInfo(String topic,String text);
bool isInt(String str);
void connect() {
Serial.print("checking wifi...");
uint8_t timeout=0;
while (WiFi.status() != WL_CONNECTED && timeout<10) {
timeout++;
Serial.print(".");
delay(500);
}
if (WiFi.status() == WL_CONNECTED)
{
Serial.print("\nconnecting...");
timeout=0;
#define CONNECT_TIMEOUT 5
while (!client.connect(client_id, "public", "public") && timeout<CONNECT_TIMEOUT) {
Serial.print(".");
delay(1000);
timeout++;
}
if (timeout>=CONNECT_TIMEOUT) {
Serial.println("\nconnection failed!");
}else{
Serial.println("\nconnected!");
client.subscribe((String)client_id+"/sendall");
#ifdef EC_CALIBRATION_POLYNOM
client.subscribe((String)client_id+"/ec/trigger");
#endif
client.subscribe((String)client_id+"/errorack");
client.subscribe((String)client_id+"/reboot");
#ifdef RELAISCOUNT
client.subscribe((String)client_id+"/pump");
#endif
#ifdef VALVECOUNT
client.subscribe((String)client_id+"/pump1");
client.subscribe((String)client_id+"/pump2");
client.subscribe((String)client_id+"/pump3");
client.subscribe((String)client_id+"/pump4");
client.subscribe((String)client_id+"/pump5");
client.subscribe((String)client_id+"/pump6");
client.subscribe((String)client_id+"/pump7");
client.subscribe((String)client_id+"/pump8");
#endif
}
}
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
if (topic==((String)client_id+"/sendall") && payload=="true") {
sendallnext_flag=true;
Serial.println("Send all values next time");
}
#ifdef EC_CALIBRATION_POLYNOM
if (topic==((String)client_id+"/ec/trigger") && payload=="true") {
force_ec_measurement=true;
Serial.println("Forced EC Measurement");
}
#endif
if (topic==((String)client_id+"/errorack") && payload=="true") { //error acknowledge
valueError=false;
Serial.println("Reset value error flag");
}
if (topic==((String)client_id+"/reboot") && payload=="true") { //error acknowledge
Serial.println("Reboot by mqtt");
delay(100);
ESP.restart();
}
#if defined(VALVECOUNT) || defined(RELAISCOUNT)
if (topic.startsWith((String)client_id+"/pump")) {
if (isInt(payload)){
int duration=payload.toInt(); //duration in seconds
if (duration>0 && duration<=10*60) {
String valveidStr=topic.substring( ((String)client_id+"/pump").length() );
if (valveidStr.length()==0) { //topic is "/pump" without number
//Turn on just the pump for duration time
Serial.print("Turning on just the pump for "); Serial.println(duration);
enableRelais(1,duration*1000); //Only relais 1 for pump used at the moment
}else{
if (isInt(valveidStr)){
int valveid=valveidStr.toInt();
//Turn on pump and valve for duration time
Serial.print("Turning on pump and valve "); Serial.print(valveid); Serial.print("for "); Serial.println(duration);
bool res=enableValve(valveid,duration*1000+500);
enableRelais(1,duration*1000); //Only relais 1 for pump used at the moment
if (!res) {
publishInfo("error/pump","failed to set valve");
}
}else{
publishInfo("error/pump","topic id not int");
}
}
}else{
publishInfo("error/pump","duration too high or low");
}
}else{
publishInfo("error/pump","payload not int");
}
}
#endif
}
bool mqtt_loop(unsigned long loopmillis) {
static unsigned long last_client_loop=0;
#define CLIENT_LOOP_INTERVAL 10 //ms. fixes some wifi issues. from example https://registry.platformio.org/libraries/256dpi/MQTT/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino
if (loopmillis >= last_client_loop+CLIENT_LOOP_INTERVAL) {
last_client_loop=loopmillis;
client.loop();
static unsigned long last_connection_try=0;
#define RETRY_CONNECTION 60000
if (!client.connected()) {
if (loopmillis-last_connection_try>RETRY_CONNECTION) {
connect();
}
}else{
return true;
}
}
return false;
}
bool publishValueTimedOverride(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis) {
mqttvt.lasttime=loopmillis;
mqttvt.lastvalue=value;
publishValue(topic,value,decimals);
return true;
}
bool publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis) {
unsigned long timediff=loopmillis-mqttvt.lasttime;
float valuediff=abs(value-mqttvt.lastvalue);
valuediff=constrain(valuediff,mqttvt.minchange,mqttvt.maxchange);
unsigned long sendafter=mapf(valuediff,mqttvt.minchange,mqttvt.maxchange,mqttvt.maxtime,mqttvt.mintime); //map valuediff to time when to send
/*Serial.println();
Serial.print("timediff="); Serial.print(timediff);
Serial.print(" valuediff="); Serial.print(valuediff);
Serial.print(" sendafter="); Serial.println(sendafter);*/
if (timediff>=sendafter || !enableTiming) {
mqttvt.lasttime=loopmillis;
mqttvt.lastvalue=value;
publishValue(topic,value,decimals);
return true;
}
return false;
}
void publishValue(String topic,float value,uint8_t decimals) {
char buffer[16];
dtostrf(value,1,decimals,buffer);
client.publish((String)client_id+"/"+topic, buffer);
Serial.print("Publish Topic="); Serial.print((String)client_id+"/"+topic); Serial.print(" Message="); Serial.println(buffer);
}
void publishInfo(String topic,String text) {
client.publish((String)client_id+"/"+topic, text);
Serial.print("Publish Topic="); Serial.print((String)client_id+"/"+topic); Serial.print(" Message="); Serial.println(text);
}
bool isInt(String str){
bool isnumeric=true;
for (uint8_t i=0;i<str.length();i++) {
isnumeric&=isDigit(str.charAt(0));
}
return isnumeric;
}
#endif