diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..379e402 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cquery.cacheDirectory": "${workspaceFolder}/.vscode/cquery_cached_index/" +} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index fe810f5..346cfd9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,6 +19,9 @@ lib_deps = 19 #DHT sensor library 31 #Adafruit Unified Sensor AutoConnect@^1.1.7 - ; ESPRandom@^1.3.3 AsyncMqttClient@^0.8.2 - ; PubSubClient@^2.8 \ No newline at end of file + ArduinoJson@^6.15.2 + ; MQTT@^2.4.7 + PubSubClient@^2.8 + ArduinoNvs@^2.5 + ; ESPRandom@^1.3.3 \ No newline at end of file diff --git a/src/capacitiveSoilMoistureSensor.cpp b/src/capacitiveSoilMoistureSensor.cpp index ff6ff1d..3b67af6 100644 --- a/src/capacitiveSoilMoistureSensor.cpp +++ b/src/capacitiveSoilMoistureSensor.cpp @@ -24,5 +24,10 @@ int readCapacitiveSoilMoistureSensor() Serial.println(measurement); // add the reading to the total: //int measurement = analogRead(PIN_MS); - return map(measurement, VALUE_AIR, VALUE_WATER, 0, 100); + + if (map(measurement, VALUE_AIR, VALUE_WATER, 0, 100) < 0) { + return 0; + } else if (map(measurement, VALUE_AIR, VALUE_WATER, 0, 100) > 100) { + return 100; + } else {return map(measurement, VALUE_AIR, VALUE_WATER, 0, 100);} } \ No newline at end of file diff --git a/src/connections.cpp b/src/connections.cpp index 0977360..9b7e9fe 100644 --- a/src/connections.cpp +++ b/src/connections.cpp @@ -1,15 +1,22 @@ +#include +// #include +#include #include -extern "C" -{ +extern "C" { #include "freertos/FreeRTOS.h" #include "freertos/timers.h" } -AsyncMqttClient mqttClient; +#define MQTT_VALVE_COMMAND MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/valve" +#define MQTT_SOIL_PROPERTIES MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/soil" + TimerHandle_t mqttReconnectTimer; TimerHandle_t wifiReconnectTimer; +// TimerHandle_t mqttProcessingTimer; +TaskHandle_t mqttTask; + WebServer Server; AutoConnect Portal(Server); WiFiClient client; @@ -17,97 +24,97 @@ WiFiClient client; AutoConnectConfig Config; // Config.autoReconnect = true; // WiFi.config(Config); +// MQTTClient mqttClient; +PubSubClient mqttClient(client); -void connectWiFi() -{ +void connectWiFi() { Serial.println("Start WiFi..."); - if (Portal.begin()) - { + if (Portal.begin()) { digitalWrite(PIN_LED_G, HIGH); } } -void connectMQTT() -{ - Serial.println("Connecting to MQTT..."); - mqttClient.setClientId(MQTT_DEVICE_ID); - mqttClient.connect(); -} - -void WiFiEvent(WiFiEvent_t event) -{ - Serial.printf("[WiFi-event] event: %d\n", event); - switch (event) - { - case SYSTEM_EVENT_STA_GOT_IP: - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); - connectMQTT(); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - digitalWrite(PIN_LED_G, LOW); - Serial.println("WiFi lost connection"); - xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi - xTimerStart(wifiReconnectTimer, 0); - break; +void mqttLoop(void *parameter) { + do { + mqttClient.loop(); + delay(50); + } while (mqttClient.connected()); + Serial.println("Disconnected from MQTT."); + if (!mqttClient.connected()) { + Serial.println("Checking WiFi Connection."); + if (WiFi.isConnected()) { + Serial.println("Starting reconnect timer for MQTT."); + xTimerStart(mqttReconnectTimer, 0); + } } + vTaskDelete(NULL); } -void onMqttConnect(bool sessionPresent) -{ - Serial.println("Connected to MQTT."); - - Serial.print("Session present: "); - Serial.println(sessionPresent); - - uint16_t packetIdSub = mqttClient.subscribe(MQTT_PATH_SUB, 2); +void connectMQTT() { + Serial.println("Connecting to MQTT..."); + // mqttClient.begin(MQTT_HOST, MQTT_PORT, client); + mqttClient.setServer(MQTT_HOST, MQTT_PORT); + mqttClient.connect(MQTT_DEVICE_ID); + if (mqttClient.connected()) { + Serial.println("Connected!"); + } else { + Serial.println("NOT Connected!"); + } + mqttClient.subscribe(MQTT_PATH_SUB); Serial.print("subscribed to: "); Serial.println(MQTT_PATH_SUB); +<<<<<<< HEAD //Testing read uint16_t packetIdSub2 = mqttClient.subscribe("smartgarden/updates/esp-sebastian/brightness", 2); Serial.print("also subscribed to: "); Serial.println("smartgarden/updates/esp-sebastian/brightness"); +======= + xTaskCreate( + mqttLoop, /* Task function. */ + "mqttLoop", /* String with name of task. */ + 8192, /* Stack size in bytes. */ + NULL, /* Parameter passed as input of the task */ + 1, /* Priority of the task. */ + &mqttTask); /* Task handle. */ + //xTimerStart(mqttProcessingTimer, 0); +>>>>>>> develop } -void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) -{ - Serial.println("Disconnected from MQTT."); - - if (WiFi.isConnected()) - { - xTimerStart(mqttReconnectTimer, 0); +void WiFiEvent(WiFiEvent_t event) { + Serial.printf("[WiFi-event] event: %d\n", event); + switch (event) { + case SYSTEM_EVENT_STA_GOT_IP: + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + connectMQTT(); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + digitalWrite(PIN_LED_G, LOW); + xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi + // xTimerStop(mqttProcessingTimer, 0); + xTimerStart(wifiReconnectTimer, 0); + break; } } -void onMqttSubscribe(uint16_t packetId, uint8_t qos) -{ - Serial.print("Subscribe acknowledged:"); - Serial.print(" packetId: "); - Serial.print(packetId); - Serial.print(" qos: "); - Serial.println(qos); -} +// void onMqttMessage(MQTTClient *client, char topic[], char payload[], int payload_length) { +void onMqttMessage(char *topic, byte *payload, unsigned int payload_length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (int i = 0; i < payload_length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); -void onMqttUnsubscribe(uint16_t packetId) -{ - Serial.println("Unsubscribe acknowledged."); - Serial.print(" packetId: "); - Serial.println(packetId); -} - -void onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) -{ - Serial.print("Publish received: "); - Serial.print(" topic: "); - Serial.println(topic); - - if (strcmp(topic, "smartgarden/commands") == 0 ) { - Serial.println("executing command..."); + if (strcmp(topic, MQTT_VALVE_COMMAND) == 0) { + Serial.println("toggling valve..."); Serial.println(topic); toggleValve(); } +<<<<<<< HEAD //Testing reading String messageTemp; @@ -120,36 +127,52 @@ void onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties Serial.println(messageTemp); } +======= + if (strcmp(topic, MQTT_SOIL_PROPERTIES) == 0) { + Serial.println("receiving soil thresholds..."); + Serial.println(topic); + //Serial.println(reinterpret_cast(payload)); + // Serial.println(payload); + // const int capacity = JSON_OBJECT_SIZE(3) + 2 * JSON_OBJECT_SIZE(1); + StaticJsonDocument<1024> doc; + DeserializationError err = deserializeJson(doc, payload); + if (err == DeserializationError::Ok) { + int fc = doc["fc"]; + int pwp = doc["pwp"]; + int sat = doc["sat"]; + setSoilProperties(fc, pwp, sat); + } else { + Serial.println(err.c_str()); + } + } +>>>>>>> develop } -void onMqttPublish(uint16_t packetId) -{ - Serial.print("Publish acknowledged: "); - Serial.print(" packetId: "); - Serial.println(packetId); -} - -void setupConnections() -{ +void setupConnections() { Serial.println(); Serial.println(); - mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast(connectMQTT)); - wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast(connectWiFi)); + mqttReconnectTimer = xTimerCreate( + "mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast(connectMQTT)); + wifiReconnectTimer = xTimerCreate( + "wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast(connectWiFi)); + // mqttProcessingTimer = xTimerCreate( + // "messageTimer", pdMS_TO_TICKS(50), pdTRUE, (void *)0, reinterpret_cast(mqttLoop)); WiFi.onEvent(WiFiEvent); - mqttClient.onConnect(onMqttConnect); - mqttClient.onDisconnect(onMqttDisconnect); - mqttClient.onSubscribe(onMqttSubscribe); - mqttClient.onUnsubscribe(onMqttUnsubscribe); - mqttClient.onMessage(onMqttMessage); - mqttClient.onPublish(onMqttPublish); - mqttClient.setServer(MQTT_HOST, MQTT_PORT); + // mqttClient.onMessageAdvanced(onMqttMessage); + mqttClient.setCallback(onMqttMessage); connectWiFi(); } void publishMessage(const char *topic, const char *msg) { +<<<<<<< HEAD mqttClient.publish(topic, 1, true, msg); -} \ No newline at end of file +} +======= + mqttClient.publish(topic, msg); + // mqttClient.publish(topic, msg, true, 1); +} +>>>>>>> develop diff --git a/src/header.h b/src/header.h index 5820402..53d67c9 100644 --- a/src/header.h +++ b/src/header.h @@ -15,7 +15,10 @@ #include #include #include -#include + +// fix for core panic during wifi initialization +// #define configMINIMAL_STACK_SIZE 2048 +// #define CONFIG_TIMER_TASK_STACK_SIZE 8192 // BH1750 lightsensor #define MIN_LIGHT 0 @@ -78,4 +81,6 @@ extern void activateLight(); // sensors void readSensors(); -void toggleValve(); \ No newline at end of file +void toggleValve(); +void setSoilProperties(int FC, int PWP, int SAT); +void setupStore(); \ No newline at end of file diff --git a/src/lightSensor.cpp b/src/lightSensor.cpp index 80c4f32..992b5dd 100644 --- a/src/lightSensor.cpp +++ b/src/lightSensor.cpp @@ -3,13 +3,18 @@ BH1750 lightMeter; void setupLightSensor() { +<<<<<<< HEAD Wire.begin(); lightMeter.begin(); Serial.println("Light-Sensor started..."); +======= + Wire.begin(); + lightMeter.begin(); + Serial.println("Sensor started..."); +>>>>>>> develop } -float readLightSensorValue() -{ - float intensity = lightMeter.readLightLevel(); - return intensity; +float readLightSensorValue() { + float intensity = lightMeter.readLightLevel(); + return intensity; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 98cccc5..2515dd1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,13 +3,13 @@ */ #include + #include unsigned long sensorReadTimer = 0; bool valveOpen = false; -void setup() -{ +void setup() { Serial.begin(115200); sensorReadTimer = millis(); @@ -20,6 +20,7 @@ void setup() digitalWrite(PIN_VALVE, LOW); + setupStore(); setupConnections(); setupLightSensor(); setupPWM(); @@ -30,17 +31,13 @@ void setup() Serial.println(); } -void loop() -{ +void loop() { // read sensors - if (millis() - sensorReadTimer >= FREQUENCY) - { + if (millis() - sensorReadTimer >= FREQUENCY) { readSensors(); sensorReadTimer = millis(); } // toggle valve if (valveOpen) { - } } - diff --git a/src/peripherals.cpp b/src/peripherals.cpp index f7d68d2..db4aa27 100644 --- a/src/peripherals.cpp +++ b/src/peripherals.cpp @@ -1,8 +1,9 @@ #include +#include + #include //using namespace std; -extern "C" -{ +extern "C" { #include "freertos/FreeRTOS.h" #include "freertos/task.h" } @@ -14,8 +15,14 @@ extern "C" char buffer[16]; -void readSensors() -{ +// Feldkapazität des Bodens in Prozent: Standard ist Humus +int fieldCapacity = 44; +// PWP des Bodens in Prozent: Standard ist Humus +int permanentWiltingPoint = 25; +// Boden vollständig gesättigt bei (Prozent): Standard ist Humus +int soilSaturation = 69; + +void readSensors() { float lxValue = readLightSensorValue(); Serial.print("Light intensity: "); Serial.print(lxValue); @@ -57,18 +64,15 @@ bool closeValve() { return false; } -void valveTask(void *parameter) -{ +void valveTask(void *parameter) { unsigned long valveTimeoutTimer = millis(); bool valveOpen = openValve(); - while (valveOpen) - { + while (valveOpen) { delay(500); int mstValue = readCapacitiveSoilMoistureSensor(); - if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) - { + if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) { valveOpen = closeValve(); } // if (mstValue > 80) { @@ -78,13 +82,64 @@ void valveTask(void *parameter) vTaskDelete(NULL); } -void toggleValve() -{ +void toggleValve() { xTaskCreate( valveTask, /* Task function. */ "valveTask", /* String with name of task. */ - 10000, /* Stack size in bytes. */ + 2048, /* Stack size in bytes. */ NULL, /* Parameter passed as input of the task */ 1, /* Priority of the task. */ NULL); /* Task handle. */ } + +void persistSoilProps(int FC, int PWP, int SAT) { + Serial.println("persistSoilProps"); + bool f = NVS.setInt("fieldCapacity", FC); + bool p = NVS.setInt("permanentWilt", PWP); + bool s = NVS.setInt("soilSaturation", SAT); + if (f && p && s) { + Serial.println("Soil properties sucessfully stored."); + NVS.commit(); + } + else { + Serial.println("error occured while trying to persist soil properties"); + } +} + +void restoreSoilProps() { + Serial.println("restoreSoilProps"); + int fc = NVS.getInt("fieldCapacity"); + int pwp = NVS.getInt("permanentWilt"); + int sat = NVS.getInt("soilSaturation"); + if (fc != 0) { + fieldCapacity = fc; + } + if (pwp != 0) { + permanentWiltingPoint = pwp; + } + if (sat != 0) { + soilSaturation = sat; + } + Serial.print(fieldCapacity); + Serial.print(permanentWiltingPoint); + Serial.print(soilSaturation); +} + +void setupStore() { + NVS.begin("store"); + restoreSoilProps(); +} + +void setSoilProperties(int FC, int PWP, int SAT) { + fieldCapacity = FC; + permanentWiltingPoint = PWP; + soilSaturation = SAT; + persistSoilProps(FC, PWP, SAT); + Serial.print("new fieldCapacity: "); + Serial.println(fieldCapacity); + Serial.print("new permanentWiltingPoint: "); + Serial.println(permanentWiltingPoint); + Serial.print("new soilSaturation: "); + Serial.println(soilSaturation); +} +