Merge branch 'volkmann_dev' into develop

This commit is contained in:
Timo Volkmann 2020-07-02 21:51:08 +02:00
commit 8512deb0c3
7 changed files with 194 additions and 120 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"cquery.cacheDirectory": "${workspaceFolder}/.vscode/cquery_cached_index/"
}

View File

@ -19,6 +19,9 @@ lib_deps =
19 #DHT sensor library 19 #DHT sensor library
31 #Adafruit Unified Sensor 31 #Adafruit Unified Sensor
AutoConnect@^1.1.7 AutoConnect@^1.1.7
; ESPRandom@^1.3.3
AsyncMqttClient@^0.8.2 AsyncMqttClient@^0.8.2
; PubSubClient@^2.8 ArduinoJson@^6.15.2
; MQTT@^2.4.7
PubSubClient@^2.8
ArduinoNvs@^2.5
; ESPRandom@^1.3.3

View File

@ -1,15 +1,22 @@
#include <ArduinoJson.h>
// #include <MQTT.h>
#include <PubSubClient.h>
#include <header.h> #include <header.h>
extern "C" extern "C" {
{
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/timers.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 mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer; TimerHandle_t wifiReconnectTimer;
// TimerHandle_t mqttProcessingTimer;
TaskHandle_t mqttTask;
WebServer Server; WebServer Server;
AutoConnect Portal(Server); AutoConnect Portal(Server);
WiFiClient client; WiFiClient client;
@ -17,122 +24,127 @@ WiFiClient client;
AutoConnectConfig Config; AutoConnectConfig Config;
// Config.autoReconnect = true; // Config.autoReconnect = true;
// WiFi.config(Config); // WiFi.config(Config);
// MQTTClient mqttClient;
PubSubClient mqttClient(client);
void connectWiFi() void connectWiFi() {
{
Serial.println("Start WiFi..."); Serial.println("Start WiFi...");
if (Portal.begin()) if (Portal.begin()) {
{
digitalWrite(PIN_LED_G, HIGH); digitalWrite(PIN_LED_G, HIGH);
} }
} }
void connectMQTT() void mqttLoop(void *parameter) {
{ do {
Serial.println("Connecting to MQTT..."); mqttClient.loop();
mqttClient.setClientId(MQTT_DEVICE_ID); delay(50);
mqttClient.connect(); } while (mqttClient.connected());
} Serial.println("Disconnected from MQTT.");
if (!mqttClient.connected()) {
void WiFiEvent(WiFiEvent_t event) Serial.println("Checking WiFi Connection.");
{ if (WiFi.isConnected()) {
Serial.printf("[WiFi-event] event: %d\n", event); Serial.println("Starting reconnect timer for MQTT.");
switch (event) xTimerStart(mqttReconnectTimer, 0);
{ }
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;
} }
vTaskDelete(NULL);
} }
void onMqttConnect(bool sessionPresent) void connectMQTT() {
{ Serial.println("Connecting to MQTT...");
Serial.println("Connected to MQTT."); // mqttClient.begin(MQTT_HOST, MQTT_PORT, client);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
Serial.print("Session present: "); mqttClient.connect(MQTT_DEVICE_ID);
Serial.println(sessionPresent); if (mqttClient.connected()) {
Serial.println("Connected!");
uint16_t packetIdSub = mqttClient.subscribe(MQTT_PATH_SUB, 2); } else {
Serial.println("NOT Connected!");
}
mqttClient.subscribe(MQTT_PATH_SUB);
Serial.print("subscribed to: "); Serial.print("subscribed to: ");
Serial.println(MQTT_PATH_SUB); Serial.println(MQTT_PATH_SUB);
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);
} }
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) void WiFiEvent(WiFiEvent_t event) {
{ Serial.printf("[WiFi-event] event: %d\n", event);
Serial.println("Disconnected from MQTT."); switch (event) {
case SYSTEM_EVENT_STA_GOT_IP:
if (WiFi.isConnected()) Serial.println("WiFi connected");
{ Serial.println("IP address: ");
xTimerStart(mqttReconnectTimer, 0); 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) // void onMqttMessage(MQTTClient *client, char topic[], char payload[], int payload_length) {
{ void onMqttMessage(char *topic, byte *payload, unsigned int payload_length) {
Serial.print("Subscribe acknowledged:"); Serial.print("Message arrived [");
Serial.print(" packetId: "); Serial.print(topic);
Serial.print(packetId); Serial.print("] ");
Serial.print(" qos: "); for (int i = 0; i < payload_length; i++) {
Serial.println(qos); Serial.print((char)payload[i]);
} }
Serial.println();
void onMqttUnsubscribe(uint16_t packetId) if (strcmp(topic, MQTT_VALVE_COMMAND) == 0) {
{ Serial.println("toggling valve...");
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...");
Serial.println(topic); Serial.println(topic);
toggleValve(); toggleValve();
} }
if (strcmp(topic, MQTT_SOIL_PROPERTIES) == 0) {
Serial.println("receiving soil thresholds...");
Serial.println(topic);
//Serial.println(reinterpret_cast<const char *>(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());
}
}
} }
void onMqttPublish(uint16_t packetId) void setupConnections() {
{
Serial.print("Publish acknowledged: ");
Serial.print(" packetId: ");
Serial.println(packetId);
}
void setupConnections()
{
Serial.println(); Serial.println();
Serial.println(); Serial.println();
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectMQTT)); mqttReconnectTimer = xTimerCreate(
wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectWiFi)); "mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectMQTT));
wifiReconnectTimer = xTimerCreate(
"wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectWiFi));
// mqttProcessingTimer = xTimerCreate(
// "messageTimer", pdMS_TO_TICKS(50), pdTRUE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(mqttLoop));
WiFi.onEvent(WiFiEvent); WiFi.onEvent(WiFiEvent);
mqttClient.onConnect(onMqttConnect); // mqttClient.onMessageAdvanced(onMqttMessage);
mqttClient.onDisconnect(onMqttDisconnect); mqttClient.setCallback(onMqttMessage);
mqttClient.onSubscribe(onMqttSubscribe);
mqttClient.onUnsubscribe(onMqttUnsubscribe);
mqttClient.onMessage(onMqttMessage);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
connectWiFi(); connectWiFi();
} }
void publishMessage(const char *topic, const char *msg) { void publishMessage(const char *topic, const char *msg) {
mqttClient.publish(topic, 1, true, msg); mqttClient.publish(topic, msg);
// mqttClient.publish(topic, msg, true, 1);
} }

View File

@ -15,7 +15,10 @@
#include <WiFi.h> #include <WiFi.h>
#include <WebServer.h> #include <WebServer.h>
#include <AutoConnect.h> #include <AutoConnect.h>
#include <AsyncMqttClient.h>
// fix for core panic during wifi initialization
// #define configMINIMAL_STACK_SIZE 2048
// #define CONFIG_TIMER_TASK_STACK_SIZE 8192
// DHT11 // DHT11
#define PIN_DHT11 14 #define PIN_DHT11 14
@ -70,4 +73,6 @@ extern void publishMessage(const char *topic, const char *msg);
// sensors // sensors
void readSensors(); void readSensors();
void toggleValve(); void toggleValve();
void setSoilProperties(int FC, int PWP, int SAT);
void setupStore();

View File

@ -3,13 +3,12 @@
BH1750 lightMeter; BH1750 lightMeter;
void setupLightSensor() { void setupLightSensor() {
Wire.begin(); Wire.begin();
lightMeter.begin(); lightMeter.begin();
Serial.println("Sensor started..."); Serial.println("Sensor started...");
} }
float readLightSensorValue() float readLightSensorValue() {
{ float intensity = lightMeter.readLightLevel();
float intensity = lightMeter.readLightLevel(); return intensity;
return intensity;
} }

View File

@ -3,13 +3,13 @@
*/ */
#include <header.h> #include <header.h>
#include <string> #include <string>
unsigned long sensorReadTimer = 0; unsigned long sensorReadTimer = 0;
bool valveOpen = false; bool valveOpen = false;
void setup() void setup() {
{
Serial.begin(115200); Serial.begin(115200);
sensorReadTimer = millis(); sensorReadTimer = millis();
@ -20,6 +20,7 @@ void setup()
digitalWrite(PIN_VALVE, LOW); digitalWrite(PIN_VALVE, LOW);
setupStore();
setupConnections(); setupConnections();
setupLightSensor(); setupLightSensor();
setupTemperatureSensor(); setupTemperatureSensor();
@ -29,17 +30,13 @@ void setup()
Serial.println(); Serial.println();
} }
void loop() void loop() {
{
// read sensors // read sensors
if (millis() - sensorReadTimer >= FREQUENCY) if (millis() - sensorReadTimer >= FREQUENCY) {
{
readSensors(); readSensors();
sensorReadTimer = millis(); sensorReadTimer = millis();
} }
// toggle valve // toggle valve
if (valveOpen) { if (valveOpen) {
} }
} }

View File

@ -1,8 +1,9 @@
#include <header.h> #include <header.h>
#include <ArduinoNvs.h>
#include <string> #include <string>
//using namespace std; //using namespace std;
extern "C" extern "C" {
{
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
} }
@ -14,8 +15,14 @@ extern "C"
char buffer[16]; 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(); float lxValue = readLightSensorValue();
Serial.print("Light intensity: "); Serial.print("Light intensity: ");
Serial.print(lxValue); Serial.print(lxValue);
@ -57,18 +64,15 @@ bool closeValve() {
return false; return false;
} }
void valveTask(void *parameter) void valveTask(void *parameter) {
{
unsigned long valveTimeoutTimer = millis(); unsigned long valveTimeoutTimer = millis();
bool valveOpen = openValve(); bool valveOpen = openValve();
while (valveOpen) while (valveOpen) {
{
delay(500); delay(500);
int mstValue = readCapacitiveSoilMoistureSensor(); int mstValue = readCapacitiveSoilMoistureSensor();
if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) {
{
valveOpen = closeValve(); valveOpen = closeValve();
} }
// if (mstValue > 80) { // if (mstValue > 80) {
@ -78,13 +82,64 @@ void valveTask(void *parameter)
vTaskDelete(NULL); vTaskDelete(NULL);
} }
void toggleValve() void toggleValve() {
{
xTaskCreate( xTaskCreate(
valveTask, /* Task function. */ valveTask, /* Task function. */
"valveTask", /* String with name of task. */ "valveTask", /* String with name of task. */
10000, /* Stack size in bytes. */ 512, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the task */ NULL, /* Parameter passed as input of the task */
1, /* Priority of the task. */ 1, /* Priority of the task. */
NULL); /* Task handle. */ 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);
}