From 586855f3a83594d9478d20cea3faa41ce52d9b8d Mon Sep 17 00:00:00 2001 From: Timm Bogner <64260873+timmbogner@users.noreply.github.com> Date: Sat, 29 Jan 2022 21:19:29 -0600 Subject: [PATCH] Add files via upload --- .../FDRS_Gateway2000/DataReading.h | 7 + .../FDRS_Gateway2000/FDRS_Gateway2000.ino | 123 +++++++ .../FDRS_Gateway2000/fdrs_config.h | 73 +++++ .../FDRS_Gateway2000/fdrs_functions.h | 309 ++++++++++++++++++ 4 files changed, 512 insertions(+) create mode 100644 FDRS_Gateway2000/FDRS_Gateway2000/DataReading.h create mode 100644 FDRS_Gateway2000/FDRS_Gateway2000/FDRS_Gateway2000.ino create mode 100644 FDRS_Gateway2000/FDRS_Gateway2000/fdrs_config.h create mode 100644 FDRS_Gateway2000/FDRS_Gateway2000/fdrs_functions.h diff --git a/FDRS_Gateway2000/FDRS_Gateway2000/DataReading.h b/FDRS_Gateway2000/FDRS_Gateway2000/DataReading.h new file mode 100644 index 0000000..78c817e --- /dev/null +++ b/FDRS_Gateway2000/FDRS_Gateway2000/DataReading.h @@ -0,0 +1,7 @@ + +typedef struct DataReading { + float d; + uint16_t id; + uint8_t t; + +} DataReading; diff --git a/FDRS_Gateway2000/FDRS_Gateway2000/FDRS_Gateway2000.ino b/FDRS_Gateway2000/FDRS_Gateway2000/FDRS_Gateway2000.ino new file mode 100644 index 0000000..58e7ac5 --- /dev/null +++ b/FDRS_Gateway2000/FDRS_Gateway2000/FDRS_Gateway2000.ino @@ -0,0 +1,123 @@ +// FARM DATA RELAY SYSTEM +// +// GATEWAY 2.000 +// +// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA. +// + +#if defined(ESP8266) +#include +#include +#elif defined(ESP32) +#include +#include +#include +#endif +#include "fdrs_config.h" +#include +#include "DataReading.h" +#include +#include "fdrs_functions.h" +#include + +#ifdef USE_WIFI +const char* ssid = WIFI_NET; +const char* password = WIFI_PASS; +const char* mqtt_server = MQTT_ADDR; +#endif + + +void setup() { +#if defined(ESP8266) + Serial.begin(115200); +#elif defined(ESP32) + Serial.begin(115200, SERIAL_8N1, RXD2, TXD2); +#endif + begin_espnow(); +#ifdef USE_WIFI + delay(10); + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + } + client.setServer(mqtt_server, 1883); + client.setCallback(mqtt_callback); +#endif +#ifdef USE_LORA + SPI.begin(SCK, MISO, MOSI, SS); + LoRa.setPins(SS, RST, DIO0); + if (!LoRa.begin(BAND)) { + while (1); + } +#endif +} + +void loop() { + if (millis() > timeESPNOWG) { + timeESPNOWG += ESPNOWG_DELAY; + if (lenESPNOWG > 0) releaseESPNOW(0); + } + if (millis() > timeESPNOW1) { + timeESPNOW1 += ESPNOW1_DELAY; + if (lenESPNOW1 > 0) releaseESPNOW(1); + } + if (millis() > timeESPNOW2) { + timeESPNOW2 += ESPNOW2_DELAY; + if (lenESPNOW2 > 0) releaseESPNOW(2); + } + if (millis() > timeSERIAL) { + //Serial.println("timeSERIAL tripped: " + String(lenSERIAL)); + timeSERIAL += SERIAL_DELAY; + if (lenSERIAL > 0) releaseSerial(); + } + if (millis() > timeMQTT) { + timeMQTT += MQTT_DELAY; + if (lenMQTT > 0) releaseMQTT(); + } + if (millis() > timeLORA) { + timeLORA += LORA_DELAY; + if (lenLORA > 0) releaseLoRa(); + } + + while (Serial.available()) { + getSerial(); + } +#ifdef USE_LORA + int packetSize = LoRa.parsePacket(); + if (packetSize) + { + LoRa.readBytes((uint8_t *)&theData, packetSize); + ln = packetSize; + newData = 6; + } +#endif +#ifdef USE_WIFI + if (!client.connected()) { + reconnect(); + } + client.loop(); +#endif + if (newData) { + switch (newData) { + case 1: //ESP-NOW #1 + ESPNOW1_ACT + break; + case 2: //ESP-NOW #2 + ESPNOW2_ACT + break; + case 3: //ESP-NOW General + ESPNOWG_ACT + break; + case 4: //Serial + SERIAL_ACT + break; + case 5: //MQTT + MQTT_ACT + break; + case 6: //LoRa + LORA_ACT + break; + } + newData = 0; + } +} diff --git a/FDRS_Gateway2000/FDRS_Gateway2000/fdrs_config.h b/FDRS_Gateway2000/FDRS_Gateway2000/fdrs_config.h new file mode 100644 index 0000000..66e275f --- /dev/null +++ b/FDRS_Gateway2000/FDRS_Gateway2000/fdrs_config.h @@ -0,0 +1,73 @@ +// FARM DATA RELAY SYSTEM +// +// GATEWAY 2.000 Configuration + +#define UNIT_MAC 0x00 // THIS UNIT +#define ESPNOW1_MAC 0x01 // ESPNOW1 Address +#define ESPNOW2_MAC 0x01 // ESPNOW2 Address + +//Actions -- Define what happens when a packet arrives at each interface: +//Current function options are: sendESPNOW(interface), sendSerial(), sendMQTT(), and sendLoRa(). + +#define ESPNOW1_ACT sendSerial(); +#define ESPNOW2_ACT sendSerial(); +#define ESPNOWG_ACT sendSerial(); +#define SERIAL_ACT sendESPNOW(0); +#define MQTT_ACT sendSerial(); +#define LORA_ACT sendSerial(); + +//ESP32 Only +#define RXD2 21 +#define TXD2 22 + +//#define USE_WIFI //You should not use ESP-NOW while WiFi is in use +#define WIFI_NET "Your SSID" +#define WIFI_PASS "Password" +#define MQTT_ADDR "192.168.0.8" + +//#define USE_LORA +#define SCK 5 +#define MISO 19 +#define MOSI 27 +#define SS 18 +#define RST 14 +#define DIO0 26 +//433E6 for Asia +//866E6 for Europe +//915E6 for North America +#define BAND 915E6 + +#define ESPNOW1_DELAY 0 +#define ESPNOW2_DELAY 0 +#define ESPNOWG_DELAY 0 +#define SERIAL_DELAY 0 +#define MQTT_DELAY 0 +#define LORA_DELAY 0 + +//Use these settings for a gateway that recieves ESP-NOW data and sends serial (UART). +//#define ESPNOW1_ACT sendSerial(); +//#define ESPNOW2_ACT sendSerial(); +//#define ESPNOWG_ACT sendSerial(); +//#define SERIAL_ACT sendESPNOW(0); +//#define MQTT_ACT sendSerial(); +//#define LORA_ACT sendSerial(); + +//Use these settings for a gateway that recieves serial (UART) data and sends MQTT. +//#define USE_WIFI +//#define ESPNOW1_ACT +//#define ESPNOW2_ACT +//#define ESPNOWG_ACT +//#define SERIAL_ACT sendMQTT(); +//#define MQTT_ACT sendSerial(); +//#define LORA_ACT sendSerial(); + +//Use these settings for a basic repeater addressed to the final gateway. +//#define UNIT_MAC 0x01 // THIS UNIT +//#define ESPNOW1_MAC 0x00 // ESPNOW1 Address +//#define ESPNOW2_MAC 0x02 // ESPNOW2 Address +//#define ESPNOW1_ACT sendESPNOW(2); +//#define ESPNOW2_ACT sendESPNOW(1); +//#define ESPNOWG_ACT sendESPNOW(1); +//#define SERIAL_ACT +//#define MQTT_ACT +//#define LORA_ACT diff --git a/FDRS_Gateway2000/FDRS_Gateway2000/fdrs_functions.h b/FDRS_Gateway2000/FDRS_Gateway2000/fdrs_functions.h new file mode 100644 index 0000000..d0a8bcd --- /dev/null +++ b/FDRS_Gateway2000/FDRS_Gateway2000/fdrs_functions.h @@ -0,0 +1,309 @@ +const uint8_t espnow_size = 250 / sizeof(DataReading); +const uint8_t lora_size = 256 / sizeof(DataReading); + +uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t ESPNOW1[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, ESPNOW1_MAC}; +uint8_t selfAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, UNIT_MAC}; +uint8_t ESPNOW2[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, ESPNOW2_MAC}; +uint8_t incMAC[6]; + +DataReading theData[256]; +uint8_t ln; +uint8_t newData = 0; + +DataReading bufferESPNOW1[256]; +uint8_t lenESPNOW1 = 0; +uint32_t timeESPNOW1 = 0; +DataReading bufferESPNOW2[256]; +uint8_t lenESPNOW2 = 0; +uint32_t timeESPNOW2 = 0; +DataReading bufferESPNOWG[256]; +uint8_t lenESPNOWG = 0; +uint32_t timeESPNOWG = 0; +DataReading bufferSERIAL[256]; +uint8_t lenSERIAL = 0; +uint32_t timeSERIAL = 0; +DataReading bufferMQTT[256]; +uint8_t lenMQTT = 0; +uint32_t timeMQTT = 0; +DataReading bufferLORA[256]; +uint8_t lenLORA = 0; +uint32_t timeLORA = 0; + + +WiFiClient espClient; +PubSubClient client(espClient); + +// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32 +#if defined(ESP8266) +void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) { +} +void OnDataRecv(uint8_t* mac, uint8_t *incomingData, uint8_t len) { +#elif defined(ESP32) +void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { +} +void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { +#endif + memcpy(&theData, incomingData, sizeof(theData)); + memcpy(&incMAC, mac, sizeof(incMAC)); + if (memcmp(&incMAC, &ESPNOW1, 6) == 0) newData = 1; + else if (memcmp(&incMAC, &ESPNOW2, 6) == 0) newData = 2; + else newData = 3; + ln = len / sizeof(DataReading); + Serial.println("RCV:" + String(ln)); +} +void getSerial() { + String incomingString = Serial.readStringUntil('\n'); + DynamicJsonDocument doc(24576); + DeserializationError error = deserializeJson(doc, incomingString); + if (error) { // Test if parsing succeeds. + Serial.println("parse err"); + return; + } else { + int s = doc.size(); + //Serial.println(s); + for (int i = 0; i < s; i++) { + theData[i].id = doc[i]["id"]; + theData[i].t = doc[i]["type"]; + theData[i].d = doc[i]["data"]; + } + ln = s; + newData = 4; + } +} +void mqtt_callback(char* topic, byte * message, unsigned int length) { + String incomingString; + for (int i = 0; i < length; i++) { + incomingString += (char)message[i]; + } + StaticJsonDocument<2048> doc; + DeserializationError error = deserializeJson(doc, incomingString); + if (error) { // Test if parsing succeeds. + //Serial.println("parse err"); + return; + } else { + int s = doc.size(); + //Serial.println(s); + for (int i = 0; i < s; i++) { + theData[i].id = doc[i]["id"]; + theData[i].t = doc[i]["type"]; + theData[i].d = doc[i]["data"]; + } + ln = s; + newData = 5; + } +} +#ifdef USE_LORA +void getLoRa() { + int packetSize = LoRa.parsePacket(); + if (packetSize) + { + LoRa.readBytes((uint8_t *)&theData, packetSize); + ln = packetSize / sizeof(DataReading); + newData = 6; + } +} +#endif + + +void sendESPNOW(uint8_t interface) { + switch (interface) { + case 0: + for (int i = 0; i < ln; i++) { + bufferESPNOWG[lenESPNOWG + i] = theData[i]; + } + lenESPNOWG += ln; + break; + case 1: + for (int i = 0; i < ln; i++) { + bufferESPNOW1[lenESPNOW1 + i] = theData[i]; + } + lenESPNOW1 += ln; + break; + case 2: + for (int i = 0; i < ln; i++) { + bufferESPNOW2[lenESPNOW2 + i] = theData[i]; + } + lenESPNOW2 += ln; + break; + } +} +void sendSerial() { + for (int i = 0; i < ln; i++) { + bufferSERIAL[lenSERIAL + i] = theData[i]; + } + lenSERIAL += ln; + Serial.println("SENDSERIAL:" + String(lenSERIAL)+" "); + +} +void sendMQTT() { + for (int i = 0; i < ln; i++) { + bufferMQTT[lenMQTT + i] = theData[i]; + } + lenMQTT += ln; +} +void sendLoRa() { + for (int i = 0; i < ln; i++) { + bufferLORA[lenLORA + i] = theData[i]; + } + lenLORA += ln; +} + +void releaseESPNOW(uint8_t interface) { + switch (interface) { + case 0: + { + DataReading thePacket[espnow_size]; + int j = 0; + for (int i = 0; i < lenESPNOWG; i++) { + if ( j > 250 / sizeof(DataReading)) { + j = 0; + esp_now_send(broadcast_mac, (uint8_t *) &thePacket, sizeof(thePacket)); + } + thePacket[j] = bufferESPNOWG[i]; + j++; + } + esp_now_send(broadcast_mac, (uint8_t *) &thePacket, j * sizeof(DataReading)); + lenESPNOWG = 0; + break; + } + case 1: + { + DataReading thePacket[espnow_size]; + int j = 0; + for (int i = 0; i < lenESPNOW1; i++) { + if ( j > 250 / sizeof(DataReading)) { + j = 0; + esp_now_send(ESPNOW1, (uint8_t *) &thePacket, sizeof(thePacket)); + } + thePacket[j] = bufferESPNOW1[i]; + j++; + } + esp_now_send(ESPNOW1, (uint8_t *) &thePacket, j * sizeof(DataReading)); + lenESPNOW1 = 0; + break; + } + case 2: + { + DataReading thePacket[espnow_size]; + int j = 0; + for (int i = 0; i < lenESPNOW2; i++) { + if ( j > 250 / sizeof(DataReading)) { + j = 0; + esp_now_send(ESPNOW2, (uint8_t *) &thePacket, sizeof(thePacket)); + } + thePacket[j] = bufferESPNOW2[i]; + j++; + } + esp_now_send(ESPNOW2, (uint8_t *) &thePacket, j * sizeof(DataReading)); + lenESPNOW2 = 0; + break; + } + } +} +void releaseSerial() { + //DynamicJsonDocument doc(24576); + StaticJsonDocument<2048> doc; + + for (int i = 0; i < lenSERIAL; i++) { + doc[i]["id"] = bufferSERIAL[i].id; + doc[i]["type"] = bufferSERIAL[i].t; + doc[i]["data"] = bufferSERIAL[i].d; + } + serializeJson(doc, Serial); + Serial.println(); + lenSERIAL = 0; +} +void releaseMQTT() { +#ifdef USE_WIFI + DynamicJsonDocument doc(24576); + for (int i = 0; i < lenMQTT; i++) { + doc[i]["id"] = bufferMQTT[i].id; + doc[i]["type"] = bufferMQTT[i].t; + doc[i]["data"] = bufferMQTT[i].d; + } + String outgoingString; + serializeJson(doc, outgoingString); + client.publish("esp/fdrs", (char*) outgoingString.c_str()); + lenMQTT = 0; +#endif +} +void releaseLoRa() { +#ifdef USE_LORA + DataReading thePacket[lora_size]; + int j = 0; + for (int i = 0; i < lenLORA); i++) { + if ( j > lora_size)) { + j = 0; + LoRa.beginPacket(); + LoRa.write((uint8_t*)&thePacket, j * sizeof(DataReading)); + LoRa.endPacket(); + } + thePacket[j] = bufferLORA[i]; + j++; + } + LoRa.beginPacket(); + LoRa.write((uint8_t*)&thePacket, j * sizeof(DataReading)); + LoRa.endPacket(); + lenLORA = 0; + +#endif +} + +void reconnect() { + // Loop until reconnected + while (!client.connected()) { + // Attempt to connect + if (client.connect("FDRS_GATEWAY")) { + // Subscribe + client.subscribe("esp/fdrs"); + } else { + // Wait 5 seconds before retrying + delay(5000); + } + } +} +void begin_espnow() { + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + // Init ESP-NOW for either ESP8266 or ESP32 and set MAC address +#if defined(ESP8266) + wifi_set_macaddr(STATION_IF, selfAddress); + if (esp_now_init() != 0) { + return; + } + esp_now_set_self_role(ESP_NOW_ROLE_COMBO); + esp_now_register_send_cb(OnDataSent); + esp_now_register_recv_cb(OnDataRecv); + // Register peers + esp_now_add_peer(ESPNOW1, ESP_NOW_ROLE_COMBO, 0, NULL, 0); + esp_now_add_peer(ESPNOW2, ESP_NOW_ROLE_COMBO, 0, NULL, 0); +#elif defined(ESP32) + esp_wifi_set_mac(WIFI_IF_STA, &selfAddress[0]); + if (esp_now_init() != ESP_OK) { + Serial.println("Error initializing ESP-NOW"); + return; + } + esp_now_register_send_cb(OnDataSent); + esp_now_register_recv_cb(OnDataRecv); + esp_now_peer_info_t peerInfo; + peerInfo.channel = 0; + peerInfo.encrypt = false; + // Register first peer + memcpy(peerInfo.peer_addr, ESPNOW1, 6); + if (esp_now_add_peer(&peerInfo) != ESP_OK) { + Serial.println("Failed to add peer"); + return; + } + memcpy(peerInfo.peer_addr, ESPNOW2, 6); + if (esp_now_add_peer(&peerInfo) != ESP_OK) { + Serial.println("Failed to add peer"); + return; + } + memcpy(peerInfo.peer_addr, broadcast_mac, 6); + if (esp_now_add_peer(&peerInfo) != ESP_OK) { + Serial.println("Failed to add peer"); + return; + } +#endif +}