From 5fce1ea32d42e3cd4e3366c4ff3f183d7f7abd9b Mon Sep 17 00:00:00 2001 From: Jeff Lehman Date: Tue, 7 May 2024 22:02:34 -0500 Subject: [PATCH 1/4] Update irrigation example to support time limited activation, small change in scheduler code --- .../Irrigation/Irrigation.ino | 263 ++++++++++-------- src/fdrs_gateway_scheduler.h | 8 +- 2 files changed, 157 insertions(+), 114 deletions(-) diff --git a/examples/Controller_examples/Irrigation/Irrigation.ino b/examples/Controller_examples/Irrigation/Irrigation.ino index ddc9649..25eb1b7 100644 --- a/examples/Controller_examples/Irrigation/Irrigation.ino +++ b/examples/Controller_examples/Irrigation/Irrigation.ino @@ -5,108 +5,126 @@ // Developed by Timm Bogner (timmbogner@gmail.com) in Urbana, Illinois, USA. // // + #include "fdrs_node_config.h" #include +#define CMD_GET 1 +#define CMD_SET 0 + +typedef struct irrigController +{ + uint address; + int coilPin; + bool updatePending; + unsigned long status; +} irrigController; + +/* + +Format of loadFDRS.... +loadFDRS(data, type, address); + +Get Coil status of address 102 (data value is ignored) +loadFDRS(1, 1, 102); + +Turn off (set) Coil at address 102 for an indefinite amount of time +loadFDRS(0, 0, 102); + +Turn on Coil (set) at address 102 for an indefinite amount of time +loadFDRS(1, 0, 102); + +Turn on (set) Coil at address 102 for 300 seconds +loadFDRS(300, 0, 102); + +When turning on coil for certain amount of time the data value +must be 10 or greater and is in units of seconds. + +*/ + #define CONTROL_1 101 //Address for controller 1 #define CONTROL_2 102 //Address for controller 2 #define CONTROL_3 103 //Address for controller 3 #define CONTROL_4 104 //Address for controller 4 -#define COIL_1 4 //Coil Pin 1 -#define COIL_2 5 //Coil Pin 2 -#define COIL_3 13 //Coil Pin 3 -#define COIL_4 14 //Coil Pin 4 +#define COIL_1 GPIO_NUM_16 //Coil Pin 1 +#define COIL_2 GPIO_NUM_17 //Coil Pin 2 +#define COIL_3 GPIO_NUM_18 //Coil Pin 3 +#define COIL_4 GPIO_NUM_19 //Coil Pin 4 + +// These are set up for relay module which are active-LOW. +// Swap 'HIGH'and 'LOW' to use the inverse. +#define ON LOW +#define OFF HIGH -int status_1 = 0; -int status_2 = 0; -int status_3 = 0; -int status_4 = 0; +irrigController cont[] = { + [0] = { .address = CONTROL_1, .coilPin = COIL_1, .updatePending = false, .status = 0 }, + [1] = { .address = CONTROL_2, .coilPin = COIL_2, .updatePending = false, .status = 0 }, + [2] = { .address = CONTROL_3, .coilPin = COIL_3, .updatePending = false, .status = 0 }, + [3] = { .address = CONTROL_4, .coilPin = COIL_4, .updatePending = false, .status = 0 }, + // [4] = { .address = CONTROL_5, .coilPin = COIL_5, .updatePending = false, .status = 0 }, + // [5] = { .address = CONTROL_6, .coilPin = COIL_6, .updatePending = false, .status = 0 }, + // [6] = { .address = CONTROL_7, .coilPin = COIL_7, .updatePending = false, .status = 0 }, + // [7] = { .address = CONTROL_8, .coilPin = COIL_8, .updatePending = false, .status = 0 }, + // [8] = { .address = CONTROL_9, .coilPin = COIL_9, .updatePending = false, .status = 0 }, + // [9] = { .address = CONTROL_10, .coilPin = COIL_10, .updatePending = false, .status = 0 }, + // [10] = { .address = CONTROL_11, .coilPin = COIL_11, .updatePending = false, .status = 0 }, + // [11] = { .address = CONTROL_12, .coilPin = COIL_12, .updatePending = false, .status = 0 }, + // [12] = { .address = CONTROL_13, .coilPin = COIL_13, .updatePending = false, .status = 0 }, +}; + +unsigned long statusCheck = 0; +unsigned long checkGatewayStatus = 0; bool isData = false; bool newStatus = false; +bool connectedToGateway = false; +uint numcontrollers; +// Callback function in the controller that receives data to get or set coils void fdrs_recv_cb(DataReading theData) { - DBG(String(theData.id)); - switch (theData.t) { - case 0: // Incoming command is to SET a value - switch (theData.id) { - case CONTROL_1: - status_1 = (int)theData.d; - isData = true; - break; - case CONTROL_2: - status_2 = (int)theData.d; - isData = true; - break; - case CONTROL_3: - status_3 = (int)theData.d; - isData = true; - break; - case CONTROL_4: - status_4 = (int)theData.d; + switch (theData.t) { + case CMD_SET: // Incoming command is to SET a value + for(int i = 0; i < numcontrollers; i++) { + if(cont[i].address == (uint) theData.id) { + cont[i].status = (unsigned long) theData.d; + cont[i].updatePending = true; isData = true; + DBG1("Received SET cmd. Address: " + String(theData.id) + " value: " + String(theData.d)); break; + } } break; - case 1: // Incoming command is to GET a value - switch (theData.id) { - case CONTROL_1: - if (digitalRead(COIL_1) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_1); - } else { - loadFDRS(0, STATUS_T, CONTROL_1); - } - break; - case CONTROL_2: - if (digitalRead(COIL_2) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_2); - } else { - loadFDRS(0, STATUS_T, CONTROL_2); - } - break; - case CONTROL_3: - if (digitalRead(COIL_3) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_3); + case CMD_GET: // Incoming command is to GET a value + for(int i = 0; i < numcontrollers; i++) { + if(cont[i].address == theData.id) { + if (digitalRead(cont[i].coilPin) == HIGH) { + loadFDRS(1, STATUS_T, cont[i].address); } else { - loadFDRS(0, STATUS_T, CONTROL_3); + loadFDRS(0, STATUS_T, cont[i].address); } - break; - case CONTROL_4: - if (digitalRead(COIL_4) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_4); - } else { - loadFDRS(0, STATUS_T, CONTROL_4); - } - break; + DBG1("Received GET cmd for address: " + String(theData.id)); + newStatus = true; + } } - newStatus = true; break; + + default: + DBG1("Unknown command: " + String(theData.t) + " address: " + String(theData.id) + " value: " + String(theData.d)); + break; + } } void checkCoils() { // Sends back a status report for each coil pin. - if (digitalRead(COIL_1) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_1); - } else { - loadFDRS(0, STATUS_T, CONTROL_1); - } - if (digitalRead(COIL_2) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_2); - } else { - loadFDRS(0, STATUS_T, CONTROL_2); - } - if (digitalRead(COIL_3) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_3); - } else { - loadFDRS(0, STATUS_T, CONTROL_3); - } - if (digitalRead(COIL_4) == HIGH) { - loadFDRS(1, STATUS_T, CONTROL_4); - } else { - loadFDRS(0, STATUS_T, CONTROL_4); + for(int i = 0; i < numcontrollers; i++) { + if (digitalRead(cont[i].coilPin == HIGH)) { + loadFDRS(1, STATUS_T, cont[i].address); + } else { + loadFDRS(0, STATUS_T, cont[i].address); + } } if (sendFDRS()) { DBG("Packet received by gateway"); @@ -115,50 +133,55 @@ void checkCoils() { // Sends back a status report for each coil pin. } } -void updateCoils() { //These are set up for relay module which are active-LOW. Swap 'HIGH'and 'LOW' in this function to use the inverse. - if (status_1) { - digitalWrite(COIL_1, LOW); - } else { - digitalWrite(COIL_1, HIGH); - } - if (status_2) { - digitalWrite(COIL_2, LOW); - } else { - digitalWrite(COIL_2, HIGH); - } - if (status_3) { - digitalWrite(COIL_3, LOW); - } else { - digitalWrite(COIL_3, HIGH); - } - if (status_4) { - digitalWrite(COIL_4, LOW); - } else { - digitalWrite(COIL_4, HIGH); + +// Sets coil value according to data received in callback function +void updateCoils() { + for(int i = 0; i < numcontrollers; i++) { + if(cont[i].updatePending == true) { + if(cont[i].status == 0) { + digitalWrite(cont[i].coilPin, OFF); + DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " off."); + } + else { + digitalWrite(cont[i].coilPin, ON); + DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " on."); + } + if(cont[i].status >= 10) { + DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " on for " + String(cont[i].status) + " seconds."); + cont[i].status = millis() + (cont[i].status * 1000); // this is the time when the coil will be commanded off + } + cont[i].updatePending = false; + } } } -void setup() { - beginFDRS(); - pingFDRS(1000); +// Attempts to inform gateway that we are alive and waiting to receive data +// Returns true if we have successfully registered with gateway otherwise return false +bool registerWithGateway() { if (addFDRS(1000, fdrs_recv_cb)) { - subscribeFDRS(CONTROL_1); - subscribeFDRS(CONTROL_2); - subscribeFDRS(CONTROL_3); - subscribeFDRS(CONTROL_4); + for(int i = 0; i < numcontrollers; i++) { + subscribeFDRS(cont[i].address); + } + return true; } else { DBG("Not Connected"); + // If we can't connect to gateway then we won't receive data should we delay and retry or delay and reboot? } - pinMode(COIL_1, OUTPUT); - digitalWrite(COIL_1, HIGH); - pinMode(COIL_2, OUTPUT); - digitalWrite(COIL_2, HIGH); - pinMode(COIL_3, OUTPUT); - digitalWrite(COIL_3, HIGH); - pinMode(COIL_4, OUTPUT); - digitalWrite(COIL_4, HIGH); + return false; +} +void setup() { + beginFDRS(); DBG("FARM DATA RELAY SYSTEM :: Irrigation Module"); + pingFDRS(1000); + + numcontrollers = (uint) sizeof(cont)/sizeof(irrigController); + // set up the physical outputs + for(int i = 0; i < numcontrollers; i++) { + pinMode(cont[i].coilPin, OUTPUT); + digitalWrite(cont[i].coilPin, OFF); + } + connectedToGateway = registerWithGateway(); } void loop() { @@ -176,4 +199,24 @@ void loop() { DBG("Unable to communicate with gateway!"); } } -} + // periodically check for timer expiration on coils + if(millis() - statusCheck > 500) { + for(int i = 0; i < numcontrollers; i++) { + if(cont[i].status >= 10 && (millis() > cont[i].status)) { + cont[i].status = 0; + digitalWrite(cont[i].coilPin, OFF); + loadFDRS(OFF, STATUS_T, cont[i].address); + DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " turned off."); + newStatus = true; + } + } + statusCheck = millis(); + } + // Periodically test and try to reestablish gateway connection if not connected + if(millis() - checkGatewayStatus > 20000) { + if(connectedToGateway == false){ + connectedToGateway = registerWithGateway(); + } + checkGatewayStatus = millis(); + } +} \ No newline at end of file diff --git a/src/fdrs_gateway_scheduler.h b/src/fdrs_gateway_scheduler.h index 687ef47..8f374d6 100644 --- a/src/fdrs_gateway_scheduler.h +++ b/src/fdrs_gateway_scheduler.h @@ -1,4 +1,4 @@ - +#define NUMSCHEDULES 16 typedef struct ScheduleItem { @@ -8,12 +8,12 @@ typedef struct ScheduleItem bool active; } ScheduleItem; -ScheduleItem theSchedule[16]; +ScheduleItem theSchedule[NUMSCHEDULES]; bool scheduleFDRS(void (*added_func)(), uint32_t added_interval) { ScheduleItem arg = {.interval = added_interval, .start = millis(), .functionName = added_func, .active = true}; - for (int i = 0; i < 16; i++) + for (int i = 0; i < NUMSCHEDULES; i++) { if (!theSchedule[i].active) { @@ -26,7 +26,7 @@ bool scheduleFDRS(void (*added_func)(), uint32_t added_interval) } void handle_schedule() { - for (int i = 0; i < 16; i++) + for (int i = 0; i < NUMSCHEDULES; i++) { if (theSchedule[i].active && (millis() - theSchedule[i].start > theSchedule[i].interval)) { From 1c5e9be91a01ccc085ae7249a617ea3135201e35 Mon Sep 17 00:00:00 2001 From: Jeff Lehman Date: Wed, 12 Jun 2024 21:37:15 -0500 Subject: [PATCH 2/4] Add 4 MQTT Global defines --- examples/0_MQTT_Gateway/fdrs_gateway_config.h | 15 ++++++---- examples/1_UART_Gateway/fdrs_gateway_config.h | 15 ++++++---- .../2_ESPNOW_Repeater/fdrs_gateway_config.h | 15 ++++++---- .../3_LoRa_Repeater/fdrs_gateway_config.h | 15 ++++++---- .../fdrs_gateway_config.h | 15 ++++++---- .../Repeater_Voltage/fdrs_gateway_config.h | 15 ++++++---- src/fdrs_checkConfig.h | 12 ++++++-- src/fdrs_gateway.h | 2 +- src/fdrs_gateway_mqtt.h | 28 +++++++++++++++++-- src/fdrs_globals.h | 8 +++--- 10 files changed, 100 insertions(+), 40 deletions(-) diff --git a/examples/0_MQTT_Gateway/fdrs_gateway_config.h b/examples/0_MQTT_Gateway/fdrs_gateway_config.h index 948b097..abf0c18 100644 --- a/examples/0_MQTT_Gateway/fdrs_gateway_config.h +++ b/examples/0_MQTT_Gateway/fdrs_gateway_config.h @@ -80,11 +80,16 @@ // #define DNS1_IPADDRESS "192.168.0.1" // #define DNS2_IPADDRESS "192.168.0.2" -//#define MQTT_ADDR "192.168.0.8" -//#define MQTT_PORT 1883 // Default MQTT port is 1883 -//#define MQTT_AUTH //Enable MQTT authentication -//#define MQTT_USER "Your MQTT Username" -//#define MQTT_PASS "Your MQTT Password" +// MQTT Settings +// #define MQTT_ADDR "192.168.0.8" +// #define MQTT_PORT 1883 // Default MQTT port is 1883 +// #define MQTT_AUTH //Enable MQTT authentication +// #define MQTT_USER "Your MQTT Username" +// #define MQTT_PASS "Your MQTT Password" +// #define TOPIC_DATA "fdrs/data" +// #define TOPIC_STATUS "fdrs/status" +// #define TOPIC_COMMAND "fdrs/command" +// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/1_UART_Gateway/fdrs_gateway_config.h b/examples/1_UART_Gateway/fdrs_gateway_config.h index 01075e6..aee9717 100644 --- a/examples/1_UART_Gateway/fdrs_gateway_config.h +++ b/examples/1_UART_Gateway/fdrs_gateway_config.h @@ -80,11 +80,16 @@ // #define DNS1_IPADDRESS "192.168.0.1" // #define DNS2_IPADDRESS "192.168.0.2" -//#define MQTT_ADDR "192.168.0.8" -//#define MQTT_PORT 1883 // Default MQTT port is 1883 -//#define MQTT_AUTH //Enable MQTT authentication -//#define MQTT_USER "Your MQTT Username" -//#define MQTT_PASS "Your MQTT Password" +// MQTT Settings +// #define MQTT_ADDR "192.168.0.8" +// #define MQTT_PORT 1883 // Default MQTT port is 1883 +// #define MQTT_AUTH //Enable MQTT authentication +// #define MQTT_USER "Your MQTT Username" +// #define MQTT_PASS "Your MQTT Password" +// #define TOPIC_DATA "fdrs/data" +// #define TOPIC_STATUS "fdrs/status" +// #define TOPIC_COMMAND "fdrs/command" +// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h b/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h index 755ebf4..b8a9cad 100644 --- a/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h +++ b/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h @@ -80,11 +80,16 @@ // #define DNS1_IPADDRESS "192.168.0.1" // #define DNS2_IPADDRESS "192.168.0.2" -//#define MQTT_ADDR "192.168.0.8" -//#define MQTT_PORT 1883 // Default MQTT port is 1883 -//#define MQTT_AUTH //Enable MQTT authentication -//#define MQTT_USER "Your MQTT Username" -//#define MQTT_PASS "Your MQTT Password" +// MQTT Settings +// #define MQTT_ADDR "192.168.0.8" +// #define MQTT_PORT 1883 // Default MQTT port is 1883 +// #define MQTT_AUTH //Enable MQTT authentication +// #define MQTT_USER "Your MQTT Username" +// #define MQTT_PASS "Your MQTT Password" +// #define TOPIC_DATA "fdrs/data" +// #define TOPIC_STATUS "fdrs/status" +// #define TOPIC_COMMAND "fdrs/command" +// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/3_LoRa_Repeater/fdrs_gateway_config.h b/examples/3_LoRa_Repeater/fdrs_gateway_config.h index 40659ef..3988098 100644 --- a/examples/3_LoRa_Repeater/fdrs_gateway_config.h +++ b/examples/3_LoRa_Repeater/fdrs_gateway_config.h @@ -80,11 +80,16 @@ // #define DNS1_IPADDRESS "192.168.0.1" // #define DNS2_IPADDRESS "192.168.0.2" -//#define MQTT_ADDR "192.168.0.8" -//#define MQTT_PORT 1883 // Default MQTT port is 1883 -//#define MQTT_AUTH //Enable MQTT authentication -//#define MQTT_USER "Your MQTT Username" -//#define MQTT_PASS "Your MQTT Password" +// MQTT Settings +// #define MQTT_ADDR "192.168.0.8" +// #define MQTT_PORT 1883 // Default MQTT port is 1883 +// #define MQTT_AUTH //Enable MQTT authentication +// #define MQTT_USER "Your MQTT Username" +// #define MQTT_PASS "Your MQTT Password" +// #define TOPIC_DATA "fdrs/data" +// #define TOPIC_STATUS "fdrs/status" +// #define TOPIC_COMMAND "fdrs/command" +// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h b/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h index dc57954..a9b4ef3 100644 --- a/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h +++ b/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h @@ -81,11 +81,16 @@ // #define DNS1_IPADDRESS "192.168.0.1" // #define DNS2_IPADDRESS "192.168.0.2" -#define MQTT_ADDR "192.168.2.3" -//#define MQTT_PORT 1883 // Default MQTT port is 1883 -//#define MQTT_AUTH //Enable MQTT authentication -//#define MQTT_USER "Your MQTT Username" -//#define MQTT_PASS "Your MQTT Password" +// MQTT Settings +// #define MQTT_ADDR "192.168.0.8" +// #define MQTT_PORT 1883 // Default MQTT port is 1883 +// #define MQTT_AUTH //Enable MQTT authentication +// #define MQTT_USER "Your MQTT Username" +// #define MQTT_PASS "Your MQTT Password" +// #define TOPIC_DATA "fdrs/data" +// #define TOPIC_STATUS "fdrs/status" +// #define TOPIC_COMMAND "fdrs/command" +// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h b/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h index 9423cce..a3c23f4 100644 --- a/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h +++ b/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h @@ -72,11 +72,16 @@ //#define WIFI_SSID "Your SSID" //#define WIFI_PASS "Your Password" -//#define MQTT_ADDR "192.168.0.8" -//#define MQTT_PORT 1883 // Default MQTT port is 1883 -//#define MQTT_AUTH //Enable MQTT authentication -//#define MQTT_USER "Your MQTT Username" -//#define MQTT_PASS "Your MQTT Password" +// MQTT Settings +// #define MQTT_ADDR "192.168.0.8" +// #define MQTT_PORT 1883 // Default MQTT port is 1883 +// #define MQTT_AUTH //Enable MQTT authentication +// #define MQTT_USER "Your MQTT Username" +// #define MQTT_PASS "Your MQTT Password" +// #define TOPIC_DATA "fdrs/data" +// #define TOPIC_STATUS "fdrs/status" +// #define TOPIC_COMMAND "fdrs/command" +// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/src/fdrs_checkConfig.h b/src/fdrs_checkConfig.h index 3ed0467..e2700b9 100644 --- a/src/fdrs_checkConfig.h +++ b/src/fdrs_checkConfig.h @@ -249,21 +249,27 @@ void printWifiDetails() { #endif //FDRS_MQTT_AUTH #if defined(TOPIC_DATA) - DBG("MQTT topic (TOPIC_DATA) : " + String(TOPIC_DATA)); + DBG("MQTT topic (TOPIC_DATA) : " + String(FDRS_TOPIC_DATA)); +#elif defined (GLOBAL_TOPIC_DATA) + DBG("MQTT topic used from GLOBAL_TOPIC_DATA : " + String(FDRS_TOPIC_DATA)); #else DBG("NO MQTT topic defined! Please define TOPIC_DATA in fdrs_globals.h (recommended) or in fdrs_node_config.h / fdrs_gateway_config.h"); //exit(0); #endif //TOPIC_DATA #if defined(TOPIC_STATUS) - DBG("MQTT topic (TOPIC_STATUS) : " + String(TOPIC_STATUS)); + DBG("MQTT topic (TOPIC_STATUS) : " + String(FDRS_TOPIC_STATUS)); +#elif defined (GLOBAL_TOPIC_STATUS) + DBG("MQTT topic used from GLOBAL_TOPIC_STATUS : " + String(FDRS_TOPIC_STATUS)); #else DBG("NO MQTT topic defined! Please define TOPIC_STATUS in fdrs_globals.h (recommended) or in fdrs_node_config.h / fdrs_gateway_config.h"); //exit(0); #endif //TOPIC_STATUS #if defined(TOPIC_COMMAND) - DBG("MQTT topic (TOPIC_COMMAND) : " + String(TOPIC_COMMAND)); + DBG("MQTT topic (TOPIC_COMMAND) : " + String(FDRS_TOPIC_COMMAND)); + #elif defined (GLOBAL_TOPIC_COMMAND) + DBG("MQTT topic used from GLOBAL_TOPIC_COMMAND : " + String(FDRS_TOPIC_COMMAND)); #else DBG("NO MQTT topic defined! Please define TOPIC_COMMAND in fdrs_globals.h (recommended) or in fdrs_node_config.h / fdrs_gateway_config.h"); //exit(0); diff --git a/src/fdrs_gateway.h b/src/fdrs_gateway.h index 65a2423..96df64b 100644 --- a/src/fdrs_gateway.h +++ b/src/fdrs_gateway.h @@ -189,7 +189,7 @@ void beginFDRS() #ifdef USE_WIFI - client.publish(TOPIC_STATUS, "FDRS initialized"); + client.publish(FDRS_TOPIC_STATUS, "FDRS initialized"); scheduleFDRS(fetchNtpTime,1000*60*FDRS_TIME_FETCHNTP); #endif scheduleFDRS(printTime,1000*60*FDRS_TIME_PRINTTIME); diff --git a/src/fdrs_gateway_mqtt.h b/src/fdrs_gateway_mqtt.h index 26465b9..1f4997e 100644 --- a/src/fdrs_gateway_mqtt.h +++ b/src/fdrs_gateway_mqtt.h @@ -40,6 +40,30 @@ #define FDRS_MQTT_AUTH #endif // MQTT_AUTH +#if defined(TOPIC_DATA) +#define FDRS_TOPIC_DATA TOPIC_DATA +#else +#define FDRS_TOPIC_DATA GLOBAL_TOPIC_DATA +#endif // TOPIC_DATA + +#if defined(TOPIC_STATUS) +#define FDRS_TOPIC_STATUS TOPIC_STATUS +#else +#define FDRS_TOPIC_STATUS GLOBAL_TOPIC_STATUS +#endif // TOPIC_STATUS + +#if defined(TOPIC_COMMAND) +#define FDRS_TOPIC_COMMAND TOPIC_COMMAND +#else +#define FDRS_TOPIC_COMMAND GLOBAL_TOPIC_COMMAND +#endif // TOPIC_COMMAND + +#if defined(TOPIC_DATA_BACKLOG) +#define FDRS_TOPIC_DATA_BACKLOG TOPIC_DATA_BACKLOG +#else +#define FDRS_TOPIC_DATA_BACKLOG GLOBAL_TOPIC_DATA_BACKLOG +#endif // TOPIC_DATA_BACKLOG + #define MQTT_MAX_BUFF_SIZE 1024 WiFiClient espClient; @@ -69,7 +93,7 @@ void reconnect_mqtt(short int attempts, bool silent) if (client.connect("FDRS_GATEWAY", mqtt_user, mqtt_pass)) { // Subscribe - client.subscribe(TOPIC_COMMAND); + client.subscribe(FDRS_TOPIC_COMMAND); if (!silent) DBG(" MQTT Connected"); return; @@ -157,7 +181,7 @@ void begin_mqtt() void mqtt_publish(const char *payload) { - if (!client.publish(TOPIC_DATA, payload)) + if (!client.publish(FDRS_TOPIC_DATA, payload)) { DBG(" Error on sending MQTT"); diff --git a/src/fdrs_globals.h b/src/fdrs_globals.h index 0916678..19665a1 100644 --- a/src/fdrs_globals.h +++ b/src/fdrs_globals.h @@ -22,10 +22,10 @@ #define GLOBAL_MQTT_USER "Your MQTT Username" #define GLOBAL_MQTT_PASS "Your MQTT Password" // MQTT Topics -#define TOPIC_DATA "fdrs/data" -#define TOPIC_STATUS "fdrs/status" -#define TOPIC_COMMAND "fdrs/command" -#define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module +#define GLOBAL_TOPIC_DATA "fdrs/data" +#define GLOBAL_TOPIC_STATUS "fdrs/status" +#define GLOBAL_TOPIC_COMMAND "fdrs/command" +#define GLOBAL_TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time Server #define GLOBAL_TIME_SERVER "0.us.pool.ntp.org" From d9f7d688215a448d7a6d363e35ca4ec9f1795de3 Mon Sep 17 00:00:00 2001 From: Jeff Lehman Date: Thu, 13 Jun 2024 11:03:15 -0500 Subject: [PATCH 3/4] Back out changes to irrigation sketch --- .../Irrigation/Irrigation.ino | 261 ++++++++---------- 1 file changed, 109 insertions(+), 152 deletions(-) diff --git a/examples/Controller_examples/Irrigation/Irrigation.ino b/examples/Controller_examples/Irrigation/Irrigation.ino index 25eb1b7..988f860 100644 --- a/examples/Controller_examples/Irrigation/Irrigation.ino +++ b/examples/Controller_examples/Irrigation/Irrigation.ino @@ -5,126 +5,108 @@ // Developed by Timm Bogner (timmbogner@gmail.com) in Urbana, Illinois, USA. // // - #include "fdrs_node_config.h" #include -#define CMD_GET 1 -#define CMD_SET 0 - -typedef struct irrigController -{ - uint address; - int coilPin; - bool updatePending; - unsigned long status; -} irrigController; - -/* - -Format of loadFDRS.... -loadFDRS(data, type, address); - -Get Coil status of address 102 (data value is ignored) -loadFDRS(1, 1, 102); - -Turn off (set) Coil at address 102 for an indefinite amount of time -loadFDRS(0, 0, 102); - -Turn on Coil (set) at address 102 for an indefinite amount of time -loadFDRS(1, 0, 102); - -Turn on (set) Coil at address 102 for 300 seconds -loadFDRS(300, 0, 102); - -When turning on coil for certain amount of time the data value -must be 10 or greater and is in units of seconds. - -*/ - #define CONTROL_1 101 //Address for controller 1 #define CONTROL_2 102 //Address for controller 2 #define CONTROL_3 103 //Address for controller 3 #define CONTROL_4 104 //Address for controller 4 -#define COIL_1 GPIO_NUM_16 //Coil Pin 1 -#define COIL_2 GPIO_NUM_17 //Coil Pin 2 -#define COIL_3 GPIO_NUM_18 //Coil Pin 3 -#define COIL_4 GPIO_NUM_19 //Coil Pin 4 - -// These are set up for relay module which are active-LOW. -// Swap 'HIGH'and 'LOW' to use the inverse. -#define ON LOW -#define OFF HIGH +#define COIL_1 4 //Coil Pin 1 +#define COIL_2 5 //Coil Pin 2 +#define COIL_3 13 //Coil Pin 3 +#define COIL_4 14 //Coil Pin 4 -irrigController cont[] = { - [0] = { .address = CONTROL_1, .coilPin = COIL_1, .updatePending = false, .status = 0 }, - [1] = { .address = CONTROL_2, .coilPin = COIL_2, .updatePending = false, .status = 0 }, - [2] = { .address = CONTROL_3, .coilPin = COIL_3, .updatePending = false, .status = 0 }, - [3] = { .address = CONTROL_4, .coilPin = COIL_4, .updatePending = false, .status = 0 }, - // [4] = { .address = CONTROL_5, .coilPin = COIL_5, .updatePending = false, .status = 0 }, - // [5] = { .address = CONTROL_6, .coilPin = COIL_6, .updatePending = false, .status = 0 }, - // [6] = { .address = CONTROL_7, .coilPin = COIL_7, .updatePending = false, .status = 0 }, - // [7] = { .address = CONTROL_8, .coilPin = COIL_8, .updatePending = false, .status = 0 }, - // [8] = { .address = CONTROL_9, .coilPin = COIL_9, .updatePending = false, .status = 0 }, - // [9] = { .address = CONTROL_10, .coilPin = COIL_10, .updatePending = false, .status = 0 }, - // [10] = { .address = CONTROL_11, .coilPin = COIL_11, .updatePending = false, .status = 0 }, - // [11] = { .address = CONTROL_12, .coilPin = COIL_12, .updatePending = false, .status = 0 }, - // [12] = { .address = CONTROL_13, .coilPin = COIL_13, .updatePending = false, .status = 0 }, -}; - -unsigned long statusCheck = 0; -unsigned long checkGatewayStatus = 0; +int status_1 = 0; +int status_2 = 0; +int status_3 = 0; +int status_4 = 0; bool isData = false; bool newStatus = false; -bool connectedToGateway = false; -uint numcontrollers; -// Callback function in the controller that receives data to get or set coils void fdrs_recv_cb(DataReading theData) { - + DBG(String(theData.id)); switch (theData.t) { - case CMD_SET: // Incoming command is to SET a value - for(int i = 0; i < numcontrollers; i++) { - if(cont[i].address == (uint) theData.id) { - cont[i].status = (unsigned long) theData.d; - cont[i].updatePending = true; + case 0: // Incoming command is to SET a value + + switch (theData.id) { + case CONTROL_1: + status_1 = (int)theData.d; + isData = true; + break; + case CONTROL_2: + status_2 = (int)theData.d; + isData = true; + break; + case CONTROL_3: + status_3 = (int)theData.d; + isData = true; + break; + case CONTROL_4: + status_4 = (int)theData.d; isData = true; - DBG1("Received SET cmd. Address: " + String(theData.id) + " value: " + String(theData.d)); break; - } } break; - case CMD_GET: // Incoming command is to GET a value - for(int i = 0; i < numcontrollers; i++) { - if(cont[i].address == theData.id) { - if (digitalRead(cont[i].coilPin) == HIGH) { - loadFDRS(1, STATUS_T, cont[i].address); + case 1: // Incoming command is to GET a value + switch (theData.id) { + case CONTROL_1: + if (digitalRead(COIL_1) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_1); + } else { + loadFDRS(0, STATUS_T, CONTROL_1); + } + break; + case CONTROL_2: + if (digitalRead(COIL_2) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_2); + } else { + loadFDRS(0, STATUS_T, CONTROL_2); + } + break; + case CONTROL_3: + if (digitalRead(COIL_3) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_3); } else { - loadFDRS(0, STATUS_T, cont[i].address); + loadFDRS(0, STATUS_T, CONTROL_3); } - DBG1("Received GET cmd for address: " + String(theData.id)); - newStatus = true; - } + break; + case CONTROL_4: + if (digitalRead(COIL_4) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_4); + } else { + loadFDRS(0, STATUS_T, CONTROL_4); + } + break; } + newStatus = true; break; - - default: - DBG1("Unknown command: " + String(theData.t) + " address: " + String(theData.id) + " value: " + String(theData.d)); - break; - } } void checkCoils() { // Sends back a status report for each coil pin. - for(int i = 0; i < numcontrollers; i++) { - if (digitalRead(cont[i].coilPin == HIGH)) { - loadFDRS(1, STATUS_T, cont[i].address); - } else { - loadFDRS(0, STATUS_T, cont[i].address); - } + if (digitalRead(COIL_1) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_1); + } else { + loadFDRS(0, STATUS_T, CONTROL_1); + } + if (digitalRead(COIL_2) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_2); + } else { + loadFDRS(0, STATUS_T, CONTROL_2); + } + if (digitalRead(COIL_3) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_3); + } else { + loadFDRS(0, STATUS_T, CONTROL_3); + } + if (digitalRead(COIL_4) == HIGH) { + loadFDRS(1, STATUS_T, CONTROL_4); + } else { + loadFDRS(0, STATUS_T, CONTROL_4); } if (sendFDRS()) { DBG("Packet received by gateway"); @@ -133,55 +115,50 @@ void checkCoils() { // Sends back a status report for each coil pin. } } - -// Sets coil value according to data received in callback function -void updateCoils() { - for(int i = 0; i < numcontrollers; i++) { - if(cont[i].updatePending == true) { - if(cont[i].status == 0) { - digitalWrite(cont[i].coilPin, OFF); - DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " off."); - } - else { - digitalWrite(cont[i].coilPin, ON); - DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " on."); - } - if(cont[i].status >= 10) { - DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " on for " + String(cont[i].status) + " seconds."); - cont[i].status = millis() + (cont[i].status * 1000); // this is the time when the coil will be commanded off - } - cont[i].updatePending = false; - } +void updateCoils() { //These are set up for relay module which are active-LOW. Swap 'HIGH'and 'LOW' in this function to use the inverse. + if (status_1) { + digitalWrite(COIL_1, LOW); + } else { + digitalWrite(COIL_1, HIGH); } -} - -// Attempts to inform gateway that we are alive and waiting to receive data -// Returns true if we have successfully registered with gateway otherwise return false -bool registerWithGateway() { - if (addFDRS(1000, fdrs_recv_cb)) { - for(int i = 0; i < numcontrollers; i++) { - subscribeFDRS(cont[i].address); - } - return true; + if (status_2) { + digitalWrite(COIL_2, LOW); } else { - DBG("Not Connected"); - // If we can't connect to gateway then we won't receive data should we delay and retry or delay and reboot? + digitalWrite(COIL_2, HIGH); + } + if (status_3) { + digitalWrite(COIL_3, LOW); + } else { + digitalWrite(COIL_3, HIGH); + } + if (status_4) { + digitalWrite(COIL_4, LOW); + } else { + digitalWrite(COIL_4, HIGH); } - return false; } void setup() { beginFDRS(); - DBG("FARM DATA RELAY SYSTEM :: Irrigation Module"); pingFDRS(1000); - - numcontrollers = (uint) sizeof(cont)/sizeof(irrigController); - // set up the physical outputs - for(int i = 0; i < numcontrollers; i++) { - pinMode(cont[i].coilPin, OUTPUT); - digitalWrite(cont[i].coilPin, OFF); + if (addFDRS(1000, fdrs_recv_cb)) { + subscribeFDRS(CONTROL_1); + subscribeFDRS(CONTROL_2); + subscribeFDRS(CONTROL_3); + subscribeFDRS(CONTROL_4); + } else { + DBG("Not Connected"); } - connectedToGateway = registerWithGateway(); + pinMode(COIL_1, OUTPUT); + digitalWrite(COIL_1, HIGH); + pinMode(COIL_2, OUTPUT); + digitalWrite(COIL_2, HIGH); + pinMode(COIL_3, OUTPUT); + digitalWrite(COIL_3, HIGH); + pinMode(COIL_4, OUTPUT); + digitalWrite(COIL_4, HIGH); + + DBG("FARM DATA RELAY SYSTEM :: Irrigation Module"); } void loop() { @@ -199,24 +176,4 @@ void loop() { DBG("Unable to communicate with gateway!"); } } - // periodically check for timer expiration on coils - if(millis() - statusCheck > 500) { - for(int i = 0; i < numcontrollers; i++) { - if(cont[i].status >= 10 && (millis() > cont[i].status)) { - cont[i].status = 0; - digitalWrite(cont[i].coilPin, OFF); - loadFDRS(OFF, STATUS_T, cont[i].address); - DBG1("Address " + String(cont[i].address) + " coil pin " + String(cont[i].coilPin) + " turned off."); - newStatus = true; - } - } - statusCheck = millis(); - } - // Periodically test and try to reestablish gateway connection if not connected - if(millis() - checkGatewayStatus > 20000) { - if(connectedToGateway == false){ - connectedToGateway = registerWithGateway(); - } - checkGatewayStatus = millis(); - } } \ No newline at end of file From 97c83f47d90dd34e8ae0570f184bb7133cbe309d Mon Sep 17 00:00:00 2001 From: Jeff Lehman Date: Sat, 15 Jun 2024 15:53:33 -0500 Subject: [PATCH 4/4] back out scheduler changes, remove MQTT backlog topic --- examples/0_MQTT_Gateway/fdrs_gateway_config.h | 1 - examples/1_UART_Gateway/fdrs_gateway_config.h | 1 - examples/2_ESPNOW_Repeater/fdrs_gateway_config.h | 1 - examples/3_LoRa_Repeater/fdrs_gateway_config.h | 1 - .../1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h | 1 - .../Repeater_Voltage/fdrs_gateway_config.h | 1 - src/fdrs_gateway_mqtt.h | 6 ------ src/fdrs_gateway_scheduler.h | 8 ++++---- src/fdrs_globals.h | 1 - 9 files changed, 4 insertions(+), 17 deletions(-) diff --git a/examples/0_MQTT_Gateway/fdrs_gateway_config.h b/examples/0_MQTT_Gateway/fdrs_gateway_config.h index abf0c18..51ab306 100644 --- a/examples/0_MQTT_Gateway/fdrs_gateway_config.h +++ b/examples/0_MQTT_Gateway/fdrs_gateway_config.h @@ -89,7 +89,6 @@ // #define TOPIC_DATA "fdrs/data" // #define TOPIC_STATUS "fdrs/status" // #define TOPIC_COMMAND "fdrs/command" -// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/1_UART_Gateway/fdrs_gateway_config.h b/examples/1_UART_Gateway/fdrs_gateway_config.h index aee9717..0b9ba6a 100644 --- a/examples/1_UART_Gateway/fdrs_gateway_config.h +++ b/examples/1_UART_Gateway/fdrs_gateway_config.h @@ -89,7 +89,6 @@ // #define TOPIC_DATA "fdrs/data" // #define TOPIC_STATUS "fdrs/status" // #define TOPIC_COMMAND "fdrs/command" -// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h b/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h index b8a9cad..2784cd6 100644 --- a/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h +++ b/examples/2_ESPNOW_Repeater/fdrs_gateway_config.h @@ -89,7 +89,6 @@ // #define TOPIC_DATA "fdrs/data" // #define TOPIC_STATUS "fdrs/status" // #define TOPIC_COMMAND "fdrs/command" -// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/3_LoRa_Repeater/fdrs_gateway_config.h b/examples/3_LoRa_Repeater/fdrs_gateway_config.h index 3988098..ddafc6e 100644 --- a/examples/3_LoRa_Repeater/fdrs_gateway_config.h +++ b/examples/3_LoRa_Repeater/fdrs_gateway_config.h @@ -89,7 +89,6 @@ // #define TOPIC_DATA "fdrs/data" // #define TOPIC_STATUS "fdrs/status" // #define TOPIC_COMMAND "fdrs/command" -// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h b/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h index a9b4ef3..9e261cd 100644 --- a/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h +++ b/examples/Gateway_Examples/1_MQTT_Gateway_Ethernet/fdrs_gateway_config.h @@ -90,7 +90,6 @@ // #define TOPIC_DATA "fdrs/data" // #define TOPIC_STATUS "fdrs/status" // #define TOPIC_COMMAND "fdrs/command" -// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h b/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h index a3c23f4..429cca1 100644 --- a/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h +++ b/examples/Gateway_Examples/Repeater_Voltage/fdrs_gateway_config.h @@ -81,7 +81,6 @@ // #define TOPIC_DATA "fdrs/data" // #define TOPIC_STATUS "fdrs/status" // #define TOPIC_COMMAND "fdrs/command" -// #define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time settings #define USDST diff --git a/src/fdrs_gateway_mqtt.h b/src/fdrs_gateway_mqtt.h index 1f4997e..b2eeda4 100644 --- a/src/fdrs_gateway_mqtt.h +++ b/src/fdrs_gateway_mqtt.h @@ -58,12 +58,6 @@ #define FDRS_TOPIC_COMMAND GLOBAL_TOPIC_COMMAND #endif // TOPIC_COMMAND -#if defined(TOPIC_DATA_BACKLOG) -#define FDRS_TOPIC_DATA_BACKLOG TOPIC_DATA_BACKLOG -#else -#define FDRS_TOPIC_DATA_BACKLOG GLOBAL_TOPIC_DATA_BACKLOG -#endif // TOPIC_DATA_BACKLOG - #define MQTT_MAX_BUFF_SIZE 1024 WiFiClient espClient; diff --git a/src/fdrs_gateway_scheduler.h b/src/fdrs_gateway_scheduler.h index 8f374d6..687ef47 100644 --- a/src/fdrs_gateway_scheduler.h +++ b/src/fdrs_gateway_scheduler.h @@ -1,4 +1,4 @@ -#define NUMSCHEDULES 16 + typedef struct ScheduleItem { @@ -8,12 +8,12 @@ typedef struct ScheduleItem bool active; } ScheduleItem; -ScheduleItem theSchedule[NUMSCHEDULES]; +ScheduleItem theSchedule[16]; bool scheduleFDRS(void (*added_func)(), uint32_t added_interval) { ScheduleItem arg = {.interval = added_interval, .start = millis(), .functionName = added_func, .active = true}; - for (int i = 0; i < NUMSCHEDULES; i++) + for (int i = 0; i < 16; i++) { if (!theSchedule[i].active) { @@ -26,7 +26,7 @@ bool scheduleFDRS(void (*added_func)(), uint32_t added_interval) } void handle_schedule() { - for (int i = 0; i < NUMSCHEDULES; i++) + for (int i = 0; i < 16; i++) { if (theSchedule[i].active && (millis() - theSchedule[i].start > theSchedule[i].interval)) { diff --git a/src/fdrs_globals.h b/src/fdrs_globals.h index 19665a1..f5f6a08 100644 --- a/src/fdrs_globals.h +++ b/src/fdrs_globals.h @@ -25,7 +25,6 @@ #define GLOBAL_TOPIC_DATA "fdrs/data" #define GLOBAL_TOPIC_STATUS "fdrs/status" #define GLOBAL_TOPIC_COMMAND "fdrs/command" -#define GLOBAL_TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module // NTP Time Server #define GLOBAL_TIME_SERVER "0.us.pool.ntp.org"