|
|
@ -1,43 +1,64 @@ |
|
|
#include <Arduino.h> |
|
|
#include <Arduino.h> |
|
|
#include <ESP8266WiFi.h> |
|
|
|
|
|
#include <ESP8266WebServer.h> |
|
|
|
|
|
#include <PubSubClient.h> |
|
|
|
|
|
|
|
|
|
|
|
#define WLAN_SSID "TP-LINK-RPT0" |
|
|
#include <WiFi.h> |
|
|
#define WLAN_PASS "6JM54UG4EY" |
|
|
#include <ArduinoOTA.h> |
|
|
|
|
|
#include <WebServer.h> |
|
|
|
|
|
#include <PubSubClient.h> |
|
|
|
|
|
#include "credentials.h" |
|
|
|
|
|
#include "webpage.h" |
|
|
|
|
|
|
|
|
#define MQTT_CLID "ValveControl" |
|
|
#define MQTT_CLID "ValveControl" |
|
|
#define MQTT_HOST "192.168.1.133" |
|
|
#define MQTT_HOST "192.168.1.146" |
|
|
#define MQTT_PORT 1883 |
|
|
#define MQTT_PORT 1883 |
|
|
#define MQTT_USER "admin" |
|
|
|
|
|
#define MQTT_PASS "22pa0799" |
|
|
// Actuator state enum
|
|
|
|
|
|
enum ActuatorState { |
|
|
|
|
|
IDLE, |
|
|
|
|
|
OPENING, |
|
|
|
|
|
CLOSING |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
void openValve(); |
|
|
void openValve(); |
|
|
void closeValve(); |
|
|
void closeValve(); |
|
|
void stopValve(); |
|
|
void stopValve(); |
|
|
|
|
|
void updateActuator(); |
|
|
|
|
|
|
|
|
void OnConnect(); |
|
|
void OnConnect(); |
|
|
void OnOpen(); |
|
|
void OnOpen(); |
|
|
void OnClose(); |
|
|
void OnClose(); |
|
|
|
|
|
void OnStatus(); |
|
|
void OnRestart(); |
|
|
void OnRestart(); |
|
|
|
|
|
void OnStyle(); |
|
|
|
|
|
void OnScript(); |
|
|
void OnNotFound(); |
|
|
void OnNotFound(); |
|
|
|
|
|
|
|
|
String SendHTML(uint8_t ValveOpen); |
|
|
String GetStatusJSON(); |
|
|
|
|
|
|
|
|
bool ValveOpen = false; |
|
|
// Actuator control variables
|
|
|
|
|
|
ActuatorState currentState = IDLE; |
|
|
|
|
|
ActuatorState desiredState = IDLE; |
|
|
|
|
|
|
|
|
int ButtonOpen = 14; |
|
|
unsigned long operationStartTime = 0; |
|
|
int ButtonClose = 12; |
|
|
const unsigned long OPERATION_DURATION = 45000; // 45 seconds
|
|
|
|
|
|
|
|
|
int MotorPin1 = 0; |
|
|
bool ValveState = LOW; |
|
|
int MotorPin2 = 2; |
|
|
|
|
|
int duration = 10000; |
|
|
|
|
|
|
|
|
|
|
|
ESP8266WebServer server(80); |
|
|
int ButtonOpen = 16; |
|
|
|
|
|
int ButtonClose = 19; |
|
|
|
|
|
|
|
|
|
|
|
int MotorPin1 = 25; // ritrae il braccio -> valvola aperta
|
|
|
|
|
|
int MotorPin2 = 26; // estende il braccio -> valvola chiusa
|
|
|
|
|
|
|
|
|
|
|
|
WebServer server(80); |
|
|
|
|
|
|
|
|
WiFiClient espClient; |
|
|
WiFiClient espClient; |
|
|
PubSubClient client(espClient); |
|
|
PubSubClient client(espClient); |
|
|
|
|
|
|
|
|
|
|
|
void setup_ota() { |
|
|
|
|
|
ArduinoOTA.setPassword(OTA_PASS); |
|
|
|
|
|
ArduinoOTA.begin(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void setup_wifi() { |
|
|
void setup_wifi() { |
|
|
Serial.println(); |
|
|
Serial.println(); |
|
|
Serial.print("Connecting to "); |
|
|
Serial.print("Connecting to "); |
|
|
@ -49,8 +70,10 @@ void setup_wifi() { |
|
|
} |
|
|
} |
|
|
Serial.println(); |
|
|
Serial.println(); |
|
|
Serial.println("WiFi connected"); |
|
|
Serial.println("WiFi connected"); |
|
|
Serial.println("IP address: "); |
|
|
Serial.print("IP address: "); |
|
|
Serial.println(WiFi.localIP()); |
|
|
Serial.println(WiFi.localIP()); |
|
|
|
|
|
Serial.print("Starting OTA..."); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void onMessage(char* topic, byte* payload, unsigned int length) { |
|
|
void onMessage(char* topic, byte* payload, unsigned int length) { |
|
|
@ -94,8 +117,11 @@ void setup_mqtt() { |
|
|
void setup_http() { |
|
|
void setup_http() { |
|
|
Serial.println("Starting HTTP server..."); |
|
|
Serial.println("Starting HTTP server..."); |
|
|
server.on("/", OnConnect); |
|
|
server.on("/", OnConnect); |
|
|
|
|
|
server.on("/style.css", OnStyle); |
|
|
|
|
|
server.on("/app.js", OnScript); |
|
|
server.on("/open", OnOpen); |
|
|
server.on("/open", OnOpen); |
|
|
server.on("/close", OnClose); |
|
|
server.on("/close", OnClose); |
|
|
|
|
|
server.on("/status", OnStatus); |
|
|
server.on("/restart", OnRestart); |
|
|
server.on("/restart", OnRestart); |
|
|
server.onNotFound(OnNotFound); |
|
|
server.onNotFound(OnNotFound); |
|
|
server.begin(); |
|
|
server.begin(); |
|
|
@ -104,67 +130,70 @@ void setup_http() { |
|
|
|
|
|
|
|
|
void setup() { |
|
|
void setup() { |
|
|
|
|
|
|
|
|
Serial.begin(115200); |
|
|
Serial.begin(9600); |
|
|
while(!Serial) { |
|
|
while(!Serial) { |
|
|
delay(100); |
|
|
delay(100); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pinMode(ButtonOpen, INPUT); |
|
|
pinMode(ButtonOpen, INPUT_PULLUP); |
|
|
pinMode(ButtonClose, INPUT); |
|
|
pinMode(ButtonClose, INPUT_PULLUP); |
|
|
|
|
|
|
|
|
pinMode(MotorPin1, OUTPUT); |
|
|
pinMode(MotorPin1, OUTPUT); |
|
|
pinMode(MotorPin2, OUTPUT); |
|
|
pinMode(MotorPin2, OUTPUT); |
|
|
|
|
|
|
|
|
setup_wifi(); |
|
|
setup_wifi(); |
|
|
|
|
|
setup_ota(); |
|
|
setup_mqtt(); |
|
|
setup_mqtt(); |
|
|
setup_http(); |
|
|
setup_http(); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void loop() { |
|
|
void loop() { |
|
|
|
|
|
ArduinoOTA.handle(); |
|
|
|
|
|
|
|
|
if (!client.connected()) { |
|
|
if (!client.connected()) { |
|
|
reconnect(); |
|
|
reconnect(); |
|
|
} |
|
|
} |
|
|
client.loop(); |
|
|
client.loop(); |
|
|
|
|
|
|
|
|
server.handleClient(); |
|
|
// Handle physical buttons
|
|
|
|
|
|
|
|
|
int buttonOpenState = digitalRead(ButtonOpen); |
|
|
int buttonOpenState = digitalRead(ButtonOpen); |
|
|
int buttonCloseState = digitalRead(ButtonClose); |
|
|
int buttonCloseState = digitalRead(ButtonClose); |
|
|
|
|
|
|
|
|
if(buttonOpenState == LOW) { |
|
|
if(buttonOpenState == LOW) { |
|
|
buttonCloseState = !buttonOpenState; |
|
|
openValve(); |
|
|
digitalWrite(MotorPin1, LOW); |
|
|
|
|
|
digitalWrite(MotorPin2, HIGH); |
|
|
|
|
|
ValveOpen = true; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if(buttonCloseState == LOW) { |
|
|
if(buttonCloseState == LOW) { |
|
|
buttonOpenState = !buttonCloseState; |
|
|
closeValve(); |
|
|
digitalWrite(MotorPin1, HIGH); |
|
|
|
|
|
digitalWrite(MotorPin2, LOW); |
|
|
|
|
|
ValveOpen = false; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if(buttonOpenState == HIGH && buttonCloseState == HIGH) { |
|
|
// Update actuator state machine (non-blocking)
|
|
|
stopValve(); |
|
|
updateActuator(); |
|
|
} |
|
|
|
|
|
|
|
|
server.handleClient(); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void OnConnect() { |
|
|
void OnConnect() { |
|
|
server.send(200, "text/html", SendHTML(ValveOpen)); |
|
|
server.send_P(200, "text/html", webpage_html); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void OnOpen() { |
|
|
void OnOpen() { |
|
|
|
|
|
if(currentState == IDLE) { |
|
|
openValve(); |
|
|
openValve(); |
|
|
server.send(200, "text/html", SendHTML(ValveOpen)); |
|
|
} |
|
|
|
|
|
server.send(200, "application/json", GetStatusJSON()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void OnClose() { |
|
|
void OnClose() { |
|
|
|
|
|
if(currentState == IDLE) { |
|
|
closeValve(); |
|
|
closeValve(); |
|
|
server.send(200, "text/html", SendHTML(ValveOpen)); |
|
|
} |
|
|
|
|
|
server.send(200, "application/json", GetStatusJSON()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void OnStatus() { |
|
|
|
|
|
server.send(200, "application/json", GetStatusJSON()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void OnRestart() { |
|
|
void OnRestart() { |
|
|
@ -173,26 +202,36 @@ void OnRestart() { |
|
|
ESP.restart(); |
|
|
ESP.restart(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void OnStyle() { |
|
|
|
|
|
server.send_P(200, "text/css", webpage_css); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void OnScript() { |
|
|
|
|
|
server.send_P(200, "application/javascript", webpage_js); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void OnNotFound(){ |
|
|
void OnNotFound(){ |
|
|
server.send(404, "text/plain", "Not found"); |
|
|
server.send(404, "text/plain", "Not found"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void openValve() { |
|
|
void openValve() { |
|
|
|
|
|
if(currentState == IDLE) { |
|
|
Serial.println("Opening valve..."); |
|
|
Serial.println("Opening valve..."); |
|
|
digitalWrite(MotorPin1, LOW); |
|
|
digitalWrite(MotorPin1, LOW); |
|
|
digitalWrite(MotorPin2, HIGH); |
|
|
digitalWrite(MotorPin2, HIGH); |
|
|
delay(duration); |
|
|
currentState = OPENING; |
|
|
stopValve(); |
|
|
operationStartTime = millis(); |
|
|
ValveOpen = HIGH; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void closeValve() { |
|
|
void closeValve() { |
|
|
|
|
|
if(currentState == IDLE) { |
|
|
Serial.println("Closing valve..."); |
|
|
Serial.println("Closing valve..."); |
|
|
digitalWrite(MotorPin1, HIGH); |
|
|
digitalWrite(MotorPin1, HIGH); |
|
|
digitalWrite(MotorPin2, LOW); |
|
|
digitalWrite(MotorPin2, LOW); |
|
|
delay(duration); |
|
|
currentState = CLOSING; |
|
|
stopValve(); |
|
|
operationStartTime = millis(); |
|
|
ValveOpen = false; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void stopValve() { |
|
|
void stopValve() { |
|
|
@ -200,28 +239,45 @@ void stopValve() { |
|
|
digitalWrite(MotorPin2, LOW); |
|
|
digitalWrite(MotorPin2, LOW); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
String SendHTML(uint8_t ValveOpen) { |
|
|
void updateActuator() { |
|
|
String ptr = "<!DOCTYPE html> <html>\n"; |
|
|
// Check if operation is complete
|
|
|
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; |
|
|
if(currentState != IDLE) { |
|
|
ptr +="<title>Linear Actuator</title>\n"; |
|
|
unsigned long elapsedTime = millis() - operationStartTime; |
|
|
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; |
|
|
|
|
|
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; |
|
|
if(elapsedTime >= OPERATION_DURATION) { |
|
|
ptr +=".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"; |
|
|
// Operation complete
|
|
|
ptr +=".button-open {background-color: #1abc9c;}\n"; |
|
|
stopValve(); |
|
|
ptr +=".button-open:active {background-color: #16a085;}\n"; |
|
|
|
|
|
ptr +=".button-close {background-color: #34495e;}\n"; |
|
|
if(currentState == OPENING) { |
|
|
ptr +=".button-close:active {background-color: #2c3e50;}\n"; |
|
|
ValveState = HIGH; |
|
|
ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n"; |
|
|
Serial.println("Valve fully open"); |
|
|
ptr +="</style>\n"; |
|
|
} else if(currentState == CLOSING) { |
|
|
ptr +="</head>\n"; |
|
|
ValveState = LOW; |
|
|
ptr +="<body>\n"; |
|
|
Serial.println("Valve fully closed"); |
|
|
ptr +="<h1>Linear Actuator</h1>\n"; |
|
|
} |
|
|
if(ValveOpen) { |
|
|
|
|
|
ptr +="<p>Valve is OPEN</p><a class=\"button button-close\" href=\"/close\">CLOSE</a>\n"; |
|
|
currentState = IDLE; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String GetStatusJSON() { |
|
|
|
|
|
String json = "{" |
|
|
|
|
|
"\"state\":\""; |
|
|
|
|
|
|
|
|
|
|
|
if(currentState == OPENING) { |
|
|
|
|
|
json += "OPENING"; |
|
|
|
|
|
} else if(currentState == CLOSING) { |
|
|
|
|
|
json += "CLOSING"; |
|
|
} else { |
|
|
} else { |
|
|
ptr +="<p>Valve is CLOSED</p><a class=\"button button-open\" href=\"/open\">OPEN</a>\n"; |
|
|
json += "IDLE"; |
|
|
} |
|
|
} |
|
|
ptr +="</body>\n"; |
|
|
|
|
|
ptr +="</html>\n"; |
|
|
json += "\","; |
|
|
return ptr; |
|
|
json += "\"valveState\":" + String(ValveState ? 1 : 0) + ","; |
|
|
|
|
|
json += "\"elapsedTime\":" + String(millis() - operationStartTime) + ","; |
|
|
|
|
|
json += "\"totalTime\":" + String(OPERATION_DURATION); |
|
|
|
|
|
json += "}"; |
|
|
|
|
|
|
|
|
|
|
|
return json; |
|
|
} |
|
|
} |
|
|
|