@ -1,178 +1,178 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// "fdrs_sensor.h"
|
||||
//
|
||||
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
//
|
||||
#include "sensor_setup.h"
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
|
||||
#ifdef GLOBALS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) (Serial.println(a))
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
#define STATUS_T 0 // Status
|
||||
#define TEMP_T 1 // Temperature
|
||||
#define TEMP2_T 2 // Temperature #2
|
||||
#define HUMIDITY_T 3 // Relative Humidity
|
||||
#define PRESSURE_T 4 // Atmospheric Pressure
|
||||
#define LIGHT_T 5 // Light (lux)
|
||||
#define SOIL_T 6 // Soil Moisture
|
||||
#define SOIL2_T 7 // Soil Moisture #2
|
||||
#define SOILR_T 8 // Soil Resistance
|
||||
#define SOILR2_T 9 // Soil Resistance #2
|
||||
#define OXYGEN_T 10 // Oxygen
|
||||
#define CO2_T 11 // Carbon Dioxide
|
||||
#define WINDSPD_T 12 // Wind Speed
|
||||
#define WINDHDG_T 13 // Wind Direction
|
||||
#define RAINFALL_T 14 // Rainfall
|
||||
#define MOTION_T 15 // Motion
|
||||
#define VOLTAGE_T 16 // Voltage
|
||||
#define VOLTAGE2_T 17 // Voltage #2
|
||||
#define CURRENT_T 18 // Current
|
||||
#define CURRENT2_T 19 // Current #2
|
||||
#define IT_T 20 // Iterations
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
||||
|
||||
const uint16_t espnow_size = 250 / sizeof(DataReading);
|
||||
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
|
||||
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
|
||||
uint8_t LoRaAddress[] = {0x42, 0x00};
|
||||
|
||||
uint32_t wait_time = 0;
|
||||
DataReading fdrsData[espnow_size];
|
||||
uint8_t data_count = 0;
|
||||
|
||||
void beginFDRS() {
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
|
||||
DBG(" Gateway: " + String (GTWY_MAC, HEX));
|
||||
#ifdef POWER_CTRL
|
||||
DBG("Powering up the sensor array!");
|
||||
pinMode(POWER_CTRL, OUTPUT);
|
||||
digitalWrite(POWER_CTRL, 1);
|
||||
#endif
|
||||
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
|
||||
#ifdef USE_ESPNOW
|
||||
DBG("Initializing ESP-NOW!");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#if defined(ESP8266)
|
||||
if (esp_now_init() != 0) {
|
||||
return;
|
||||
}
|
||||
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||
// Register peers
|
||||
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
#elif defined(ESP32)
|
||||
if (esp_now_init() != ESP_OK) {
|
||||
DBG("Error initializing ESP-NOW");
|
||||
return;
|
||||
}
|
||||
esp_now_peer_info_t peerInfo;
|
||||
peerInfo.ifidx = WIFI_IF_STA;
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
// Register first peer
|
||||
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG(" ESP-NOW Initialized.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
DBG("Initializing LoRa!");
|
||||
DBG(BAND);
|
||||
DBG(SF);
|
||||
#ifndef __AVR__
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
#endif
|
||||
LoRa.setPins(SS, RST, DIO0);
|
||||
if (!LoRa.begin(FDRS_BAND)) {
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(FDRS_SF);
|
||||
DBG(" LoRa Initialized.");
|
||||
#endif
|
||||
}
|
||||
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
|
||||
#ifdef USE_LORA
|
||||
uint8_t pkt[5 + (len * sizeof(DataReading))];
|
||||
memcpy(&pkt, mac, 3); //
|
||||
memcpy(&pkt[3], &LoRaAddress, 2);
|
||||
memcpy(&pkt[5], packet, len * sizeof(DataReading));
|
||||
LoRa.beginPacket();
|
||||
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
|
||||
LoRa.endPacket();
|
||||
#endif
|
||||
}
|
||||
void sendFDRS() {
|
||||
DBG("Sending FDRS Packet!");
|
||||
#ifdef USE_ESPNOW
|
||||
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
|
||||
delay(5);
|
||||
DBG(" ESP-NOW sent.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
transmitLoRa(gtwyAddress, fdrsData, data_count);
|
||||
DBG(" LoRa sent.");
|
||||
#endif
|
||||
data_count = 0;
|
||||
}
|
||||
void loadFDRS(float d, uint8_t t) {
|
||||
DBG("Data loaded. Type: " + String(t));
|
||||
if (data_count > espnow_size) sendFDRS();
|
||||
DataReading dr;
|
||||
dr.id = READING_ID;
|
||||
dr.t = t;
|
||||
dr.d = d;
|
||||
fdrsData[data_count] = dr;
|
||||
data_count++;
|
||||
}
|
||||
void sleepFDRS(int sleep_time) {
|
||||
DBG("Sleepytime!");
|
||||
#ifdef DEEP_SLEEP
|
||||
DBG(" Deep sleeping.");
|
||||
#ifdef ESP32
|
||||
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
ESP.deepSleep(sleep_time * 1000000);
|
||||
#endif
|
||||
#endif
|
||||
DBG(" Delaying.");
|
||||
delay(sleep_time * 1000);
|
||||
}
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// "fdrs_sensor.h"
|
||||
//
|
||||
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
//
|
||||
#include "sensor_setup.h"
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
|
||||
#ifdef GLOBALS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) (Serial.println(a))
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
#define STATUS_T 0 // Status
|
||||
#define TEMP_T 1 // Temperature
|
||||
#define TEMP2_T 2 // Temperature #2
|
||||
#define HUMIDITY_T 3 // Relative Humidity
|
||||
#define PRESSURE_T 4 // Atmospheric Pressure
|
||||
#define LIGHT_T 5 // Light (lux)
|
||||
#define SOIL_T 6 // Soil Moisture
|
||||
#define SOIL2_T 7 // Soil Moisture #2
|
||||
#define SOILR_T 8 // Soil Resistance
|
||||
#define SOILR2_T 9 // Soil Resistance #2
|
||||
#define OXYGEN_T 10 // Oxygen
|
||||
#define CO2_T 11 // Carbon Dioxide
|
||||
#define WINDSPD_T 12 // Wind Speed
|
||||
#define WINDHDG_T 13 // Wind Direction
|
||||
#define RAINFALL_T 14 // Rainfall
|
||||
#define MOTION_T 15 // Motion
|
||||
#define VOLTAGE_T 16 // Voltage
|
||||
#define VOLTAGE2_T 17 // Voltage #2
|
||||
#define CURRENT_T 18 // Current
|
||||
#define CURRENT2_T 19 // Current #2
|
||||
#define IT_T 20 // Iterations
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
||||
|
||||
const uint16_t espnow_size = 250 / sizeof(DataReading);
|
||||
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
|
||||
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
|
||||
uint8_t LoRaAddress[] = {0x42, 0x00};
|
||||
|
||||
uint32_t wait_time = 0;
|
||||
DataReading fdrsData[espnow_size];
|
||||
uint8_t data_count = 0;
|
||||
|
||||
void beginFDRS() {
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
|
||||
DBG(" Gateway: " + String (GTWY_MAC, HEX));
|
||||
#ifdef POWER_CTRL
|
||||
DBG("Powering up the sensor array!");
|
||||
pinMode(POWER_CTRL, OUTPUT);
|
||||
digitalWrite(POWER_CTRL, 1);
|
||||
#endif
|
||||
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
|
||||
#ifdef USE_ESPNOW
|
||||
DBG("Initializing ESP-NOW!");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#if defined(ESP8266)
|
||||
if (esp_now_init() != 0) {
|
||||
return;
|
||||
}
|
||||
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||
// Register peers
|
||||
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
#elif defined(ESP32)
|
||||
if (esp_now_init() != ESP_OK) {
|
||||
DBG("Error initializing ESP-NOW");
|
||||
return;
|
||||
}
|
||||
esp_now_peer_info_t peerInfo;
|
||||
peerInfo.ifidx = WIFI_IF_STA;
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
// Register first peer
|
||||
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG(" ESP-NOW Initialized.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
DBG("Initializing LoRa!");
|
||||
DBG(BAND);
|
||||
DBG(SF);
|
||||
#ifdef ESP32
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
#endif
|
||||
LoRa.setPins(SS, RST, DIO0);
|
||||
if (!LoRa.begin(FDRS_BAND)) {
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(FDRS_SF);
|
||||
DBG(" LoRa Initialized.");
|
||||
#endif
|
||||
}
|
||||
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
|
||||
#ifdef USE_LORA
|
||||
uint8_t pkt[5 + (len * sizeof(DataReading))];
|
||||
memcpy(&pkt, mac, 3); //
|
||||
memcpy(&pkt[3], &LoRaAddress, 2);
|
||||
memcpy(&pkt[5], packet, len * sizeof(DataReading));
|
||||
LoRa.beginPacket();
|
||||
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
|
||||
LoRa.endPacket();
|
||||
#endif
|
||||
}
|
||||
void sendFDRS() {
|
||||
DBG("Sending FDRS Packet!");
|
||||
#ifdef USE_ESPNOW
|
||||
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
|
||||
delay(5);
|
||||
DBG(" ESP-NOW sent.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
transmitLoRa(gtwyAddress, fdrsData, data_count);
|
||||
DBG(" LoRa sent.");
|
||||
#endif
|
||||
data_count = 0;
|
||||
}
|
||||
void loadFDRS(float d, uint8_t t) {
|
||||
DBG("Data loaded. Type: " + String(t));
|
||||
if (data_count > espnow_size) sendFDRS();
|
||||
DataReading dr;
|
||||
dr.id = READING_ID;
|
||||
dr.t = t;
|
||||
dr.d = d;
|
||||
fdrsData[data_count] = dr;
|
||||
data_count++;
|
||||
}
|
||||
void sleepFDRS(int sleep_time) {
|
||||
DBG("Sleepytime!");
|
||||
#ifdef DEEP_SLEEP
|
||||
DBG(" Deep sleeping.");
|
||||
#ifdef ESP32
|
||||
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
ESP.deepSleep(sleep_time * 1000000);
|
||||
#endif
|
||||
#endif
|
||||
DBG(" Delaying.");
|
||||
delay(sleep_time * 1000);
|
||||
}
|
||||
|
@ -1,178 +1,178 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// "fdrs_sensor.h"
|
||||
//
|
||||
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
//
|
||||
#include "sensor_setup.h"
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
|
||||
#ifdef GLOBALS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) (Serial.println(a))
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
#define STATUS_T 0 // Status
|
||||
#define TEMP_T 1 // Temperature
|
||||
#define TEMP2_T 2 // Temperature #2
|
||||
#define HUMIDITY_T 3 // Relative Humidity
|
||||
#define PRESSURE_T 4 // Atmospheric Pressure
|
||||
#define LIGHT_T 5 // Light (lux)
|
||||
#define SOIL_T 6 // Soil Moisture
|
||||
#define SOIL2_T 7 // Soil Moisture #2
|
||||
#define SOILR_T 8 // Soil Resistance
|
||||
#define SOILR2_T 9 // Soil Resistance #2
|
||||
#define OXYGEN_T 10 // Oxygen
|
||||
#define CO2_T 11 // Carbon Dioxide
|
||||
#define WINDSPD_T 12 // Wind Speed
|
||||
#define WINDHDG_T 13 // Wind Direction
|
||||
#define RAINFALL_T 14 // Rainfall
|
||||
#define MOTION_T 15 // Motion
|
||||
#define VOLTAGE_T 16 // Voltage
|
||||
#define VOLTAGE2_T 17 // Voltage #2
|
||||
#define CURRENT_T 18 // Current
|
||||
#define CURRENT2_T 19 // Current #2
|
||||
#define IT_T 20 // Iterations
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
||||
|
||||
const uint16_t espnow_size = 250 / sizeof(DataReading);
|
||||
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
|
||||
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
|
||||
uint8_t LoRaAddress[] = {0x42, 0x00};
|
||||
|
||||
uint32_t wait_time = 0;
|
||||
DataReading fdrsData[espnow_size];
|
||||
uint8_t data_count = 0;
|
||||
|
||||
void beginFDRS() {
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
|
||||
DBG(" Gateway: " + String (GTWY_MAC, HEX));
|
||||
#ifdef POWER_CTRL
|
||||
DBG("Powering up the sensor array!");
|
||||
pinMode(POWER_CTRL, OUTPUT);
|
||||
digitalWrite(POWER_CTRL, 1);
|
||||
#endif
|
||||
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
|
||||
#ifdef USE_ESPNOW
|
||||
DBG("Initializing ESP-NOW!");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#if defined(ESP8266)
|
||||
if (esp_now_init() != 0) {
|
||||
return;
|
||||
}
|
||||
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||
// Register peers
|
||||
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
#elif defined(ESP32)
|
||||
if (esp_now_init() != ESP_OK) {
|
||||
DBG("Error initializing ESP-NOW");
|
||||
return;
|
||||
}
|
||||
esp_now_peer_info_t peerInfo;
|
||||
peerInfo.ifidx = WIFI_IF_STA;
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
// Register first peer
|
||||
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG(" ESP-NOW Initialized.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
DBG("Initializing LoRa!");
|
||||
DBG(BAND);
|
||||
DBG(SF);
|
||||
#ifndef __AVR__
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
#endif
|
||||
LoRa.setPins(SS, RST, DIO0);
|
||||
if (!LoRa.begin(FDRS_BAND)) {
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(FDRS_SF);
|
||||
DBG(" LoRa Initialized.");
|
||||
#endif
|
||||
}
|
||||
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
|
||||
#ifdef USE_LORA
|
||||
uint8_t pkt[5 + (len * sizeof(DataReading))];
|
||||
memcpy(&pkt, mac, 3); //
|
||||
memcpy(&pkt[3], &LoRaAddress, 2);
|
||||
memcpy(&pkt[5], packet, len * sizeof(DataReading));
|
||||
LoRa.beginPacket();
|
||||
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
|
||||
LoRa.endPacket();
|
||||
#endif
|
||||
}
|
||||
void sendFDRS() {
|
||||
DBG("Sending FDRS Packet!");
|
||||
#ifdef USE_ESPNOW
|
||||
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
|
||||
delay(5);
|
||||
DBG(" ESP-NOW sent.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
transmitLoRa(gtwyAddress, fdrsData, data_count);
|
||||
DBG(" LoRa sent.");
|
||||
#endif
|
||||
data_count = 0;
|
||||
}
|
||||
void loadFDRS(float d, uint8_t t) {
|
||||
DBG("Data loaded. Type: " + String(t));
|
||||
if (data_count > espnow_size) sendFDRS();
|
||||
DataReading dr;
|
||||
dr.id = READING_ID;
|
||||
dr.t = t;
|
||||
dr.d = d;
|
||||
fdrsData[data_count] = dr;
|
||||
data_count++;
|
||||
}
|
||||
void sleepFDRS(int sleep_time) {
|
||||
DBG("Sleepytime!");
|
||||
#ifdef DEEP_SLEEP
|
||||
DBG(" Deep sleeping.");
|
||||
#ifdef ESP32
|
||||
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
ESP.deepSleep(sleep_time * 1000000);
|
||||
#endif
|
||||
#endif
|
||||
DBG(" Delaying.");
|
||||
delay(sleep_time * 1000);
|
||||
}
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// "fdrs_sensor.h"
|
||||
//
|
||||
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
//
|
||||
#include "sensor_setup.h"
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
|
||||
#ifdef GLOBALS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) (Serial.println(a))
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
#define STATUS_T 0 // Status
|
||||
#define TEMP_T 1 // Temperature
|
||||
#define TEMP2_T 2 // Temperature #2
|
||||
#define HUMIDITY_T 3 // Relative Humidity
|
||||
#define PRESSURE_T 4 // Atmospheric Pressure
|
||||
#define LIGHT_T 5 // Light (lux)
|
||||
#define SOIL_T 6 // Soil Moisture
|
||||
#define SOIL2_T 7 // Soil Moisture #2
|
||||
#define SOILR_T 8 // Soil Resistance
|
||||
#define SOILR2_T 9 // Soil Resistance #2
|
||||
#define OXYGEN_T 10 // Oxygen
|
||||
#define CO2_T 11 // Carbon Dioxide
|
||||
#define WINDSPD_T 12 // Wind Speed
|
||||
#define WINDHDG_T 13 // Wind Direction
|
||||
#define RAINFALL_T 14 // Rainfall
|
||||
#define MOTION_T 15 // Motion
|
||||
#define VOLTAGE_T 16 // Voltage
|
||||
#define VOLTAGE2_T 17 // Voltage #2
|
||||
#define CURRENT_T 18 // Current
|
||||
#define CURRENT2_T 19 // Current #2
|
||||
#define IT_T 20 // Iterations
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
||||
|
||||
const uint16_t espnow_size = 250 / sizeof(DataReading);
|
||||
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
|
||||
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
|
||||
uint8_t LoRaAddress[] = {0x42, 0x00};
|
||||
|
||||
uint32_t wait_time = 0;
|
||||
DataReading fdrsData[espnow_size];
|
||||
uint8_t data_count = 0;
|
||||
|
||||
void beginFDRS() {
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
|
||||
DBG(" Gateway: " + String (GTWY_MAC, HEX));
|
||||
#ifdef POWER_CTRL
|
||||
DBG("Powering up the sensor array!");
|
||||
pinMode(POWER_CTRL, OUTPUT);
|
||||
digitalWrite(POWER_CTRL, 1);
|
||||
#endif
|
||||
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
|
||||
#ifdef USE_ESPNOW
|
||||
DBG("Initializing ESP-NOW!");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#if defined(ESP8266)
|
||||
if (esp_now_init() != 0) {
|
||||
return;
|
||||
}
|
||||
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||
// Register peers
|
||||
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
#elif defined(ESP32)
|
||||
if (esp_now_init() != ESP_OK) {
|
||||
DBG("Error initializing ESP-NOW");
|
||||
return;
|
||||
}
|
||||
esp_now_peer_info_t peerInfo;
|
||||
peerInfo.ifidx = WIFI_IF_STA;
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
// Register first peer
|
||||
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG(" ESP-NOW Initialized.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
DBG("Initializing LoRa!");
|
||||
DBG(BAND);
|
||||
DBG(SF);
|
||||
#ifdef ESP32
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
#endif
|
||||
LoRa.setPins(SS, RST, DIO0);
|
||||
if (!LoRa.begin(FDRS_BAND)) {
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(FDRS_SF);
|
||||
DBG(" LoRa Initialized.");
|
||||
#endif
|
||||
}
|
||||
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
|
||||
#ifdef USE_LORA
|
||||
uint8_t pkt[5 + (len * sizeof(DataReading))];
|
||||
memcpy(&pkt, mac, 3); //
|
||||
memcpy(&pkt[3], &LoRaAddress, 2);
|
||||
memcpy(&pkt[5], packet, len * sizeof(DataReading));
|
||||
LoRa.beginPacket();
|
||||
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
|
||||
LoRa.endPacket();
|
||||
#endif
|
||||
}
|
||||
void sendFDRS() {
|
||||
DBG("Sending FDRS Packet!");
|
||||
#ifdef USE_ESPNOW
|
||||
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
|
||||
delay(5);
|
||||
DBG(" ESP-NOW sent.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
transmitLoRa(gtwyAddress, fdrsData, data_count);
|
||||
DBG(" LoRa sent.");
|
||||
#endif
|
||||
data_count = 0;
|
||||
}
|
||||
void loadFDRS(float d, uint8_t t) {
|
||||
DBG("Data loaded. Type: " + String(t));
|
||||
if (data_count > espnow_size) sendFDRS();
|
||||
DataReading dr;
|
||||
dr.id = READING_ID;
|
||||
dr.t = t;
|
||||
dr.d = d;
|
||||
fdrsData[data_count] = dr;
|
||||
data_count++;
|
||||
}
|
||||
void sleepFDRS(int sleep_time) {
|
||||
DBG("Sleepytime!");
|
||||
#ifdef DEEP_SLEEP
|
||||
DBG(" Deep sleeping.");
|
||||
#ifdef ESP32
|
||||
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
ESP.deepSleep(sleep_time * 1000000);
|
||||
#endif
|
||||
#endif
|
||||
DBG(" Delaying.");
|
||||
delay(sleep_time * 1000);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ void setup() {
|
||||
delay(500);
|
||||
}
|
||||
DBG("WiFi Connected");
|
||||
client.setServer(mqtt_server, 1883);
|
||||
client.setServer(mqtt_server, mqtt_port);
|
||||
if (!client.connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
reconnect();
|
||||
|
@ -34,6 +34,13 @@
|
||||
#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
|
||||
|
||||
//MQTT Credentials -- Needed only if MQTT broker requires authentication
|
||||
//#define MQTT_AUTH //uncomment to enable MQTT authentication
|
||||
#define MQTT_USER "Your MQTT Username"
|
||||
#define MQTT_PASS "Your MQTT Password"
|
||||
|
||||
// MQTT Topics
|
||||
#define TOPIC_DATA "fdrs/data"
|
||||
#define TOPIC_STATUS "fdrs/status"
|
||||
|
@ -49,7 +49,7 @@ void setup() {
|
||||
delay(500);
|
||||
}
|
||||
DBG("WiFi Connected");
|
||||
client.setServer(mqtt_server, 1883);
|
||||
client.setServer(mqtt_server, mqtt_port);
|
||||
if (!client.connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
reconnect();
|
||||
|
@ -34,6 +34,13 @@
|
||||
#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
|
||||
|
||||
//MQTT Credentials -- Needed only if MQTT broker requires authentication
|
||||
//#define MQTT_AUTH //uncomment to enable MQTT authentication
|
||||
#define MQTT_USER "Your MQTT Username"
|
||||
#define MQTT_PASS "Your MQTT Password"
|
||||
|
||||
// MQTT Topics
|
||||
#define TOPIC_DATA "fdrs/data"
|
||||
#define TOPIC_STATUS "fdrs/status"
|
||||
|
@ -14,16 +14,26 @@
|
||||
#define FDRS_WIFI_SSID GLOBAL_SSID
|
||||
#define FDRS_WIFI_PASS GLOBAL_PASS
|
||||
#define FDRS_MQTT_ADDR GLOBAL_MQTT_ADDR
|
||||
#define FDRS_MQTT_PORT GLOBAL_MQTT_PORT
|
||||
#define FDRS_MQTT_USER GLOBAL_MQTT_USER
|
||||
#define FDRS_MQTT_PASS GLOBAL_MQTT_PASS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_WIFI_SSID WIFI_SSID
|
||||
#define FDRS_WIFI_PASS WIFI_PASS
|
||||
#define FDRS_MQTT_ADDR MQTT_ADDR
|
||||
#define FDRS_MQTT_PORT MQTT_PORT
|
||||
#define FDRS_MQTT_USER MQTT_USER
|
||||
#define FDRS_MQTT_PASS MQTT_PASS
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#if defined (MQTT_AUTH) || defined (GLOBAL_MQTT_AUTH)
|
||||
#define FDRS_MQTT_AUTH
|
||||
#endif
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading {
|
||||
@ -100,8 +110,15 @@ PubSubClient client(espClient);
|
||||
const char* ssid = FDRS_WIFI_SSID;
|
||||
const char* password = FDRS_WIFI_PASS;
|
||||
const char* mqtt_server = FDRS_MQTT_ADDR;
|
||||
const int mqtt_port = FDRS_MQTT_PORT;
|
||||
#endif
|
||||
#ifdef FDRS_MQTT_AUTH
|
||||
const char* mqtt_user = FDRS_MQTT_USER;
|
||||
const char* mqtt_pass = FDRS_MQTT_PASS;
|
||||
#else
|
||||
const char* mqtt_user = NULL;
|
||||
const char* mqtt_pass = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32
|
||||
#if defined(ESP8266)
|
||||
@ -482,7 +499,7 @@ void reconnect() {
|
||||
// Loop until reconnected
|
||||
while (!client.connected()) {
|
||||
// Attempt to connect
|
||||
if (client.connect("FDRS_GATEWAY")) {
|
||||
if (client.connect("FDRS_GATEWAY", mqtt_user, mqtt_pass)) {
|
||||
// Subscribe
|
||||
client.subscribe(TOPIC_COMMAND);
|
||||
} else {
|
||||
|
@ -49,7 +49,7 @@ void setup() {
|
||||
delay(500);
|
||||
}
|
||||
DBG("WiFi Connected");
|
||||
client.setServer(mqtt_server, 1883);
|
||||
client.setServer(mqtt_server, mqtt_port);
|
||||
if (!client.connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
reconnect();
|
||||
|
@ -67,6 +67,13 @@
|
||||
#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
|
||||
|
||||
//MQTT Credentials -- Needed only if MQTT broker requires authentication
|
||||
//#define MQTT_AUTH //uncomment to enable MQTT authentication
|
||||
#define MQTT_USER "Your MQTT Username"
|
||||
#define MQTT_PASS "Your MQTT Password"
|
||||
|
||||
// MQTT Topics
|
||||
#define TOPIC_DATA "fdrs/data"
|
||||
#define TOPIC_STATUS "fdrs/status"
|
||||
|
@ -14,16 +14,26 @@
|
||||
#define FDRS_WIFI_SSID GLOBAL_SSID
|
||||
#define FDRS_WIFI_PASS GLOBAL_PASS
|
||||
#define FDRS_MQTT_ADDR GLOBAL_MQTT_ADDR
|
||||
#define FDRS_MQTT_PORT GLOBAL_MQTT_PORT
|
||||
#define FDRS_MQTT_USER GLOBAL_MQTT_USER
|
||||
#define FDRS_MQTT_PASS GLOBAL_MQTT_PASS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_WIFI_SSID WIFI_SSID
|
||||
#define FDRS_WIFI_PASS WIFI_PASS
|
||||
#define FDRS_MQTT_ADDR MQTT_ADDR
|
||||
#define FDRS_MQTT_PORT MQTT_PORT
|
||||
#define FDRS_MQTT_USER MQTT_USER
|
||||
#define FDRS_MQTT_PASS MQTT_PASS
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#if defined (MQTT_AUTH) || defined (GLOBAL_MQTT_AUTH)
|
||||
#define FDRS_MQTT_AUTH
|
||||
#endif
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading {
|
||||
@ -100,8 +110,15 @@ PubSubClient client(espClient);
|
||||
const char* ssid = FDRS_WIFI_SSID;
|
||||
const char* password = FDRS_WIFI_PASS;
|
||||
const char* mqtt_server = FDRS_MQTT_ADDR;
|
||||
const int mqtt_port = FDRS_MQTT_PORT;
|
||||
#endif
|
||||
#ifdef FDRS_MQTT_AUTH
|
||||
const char* mqtt_user = FDRS_MQTT_USER;
|
||||
const char* mqtt_pass = FDRS_MQTT_PASS;
|
||||
#else
|
||||
const char* mqtt_user = NULL;
|
||||
const char* mqtt_pass = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32
|
||||
#if defined(ESP8266)
|
||||
@ -482,7 +499,7 @@ void reconnect() {
|
||||
// Loop until reconnected
|
||||
while (!client.connected()) {
|
||||
// Attempt to connect
|
||||
if (client.connect("FDRS_GATEWAY")) {
|
||||
if (client.connect("FDRS_GATEWAY", mqtt_user, mqtt_pass)) {
|
||||
// Subscribe
|
||||
client.subscribe(TOPIC_COMMAND);
|
||||
} else {
|
||||
|
@ -1,3 +0,0 @@
|
||||
Please copy this directory into your Arduino "libraries" directory.
|
||||
Edit the files in your libraries folder according to your needs with your WiFi info, LoRa band, etc.
|
||||
Never edit them here!!!
|
@ -1,8 +0,0 @@
|
||||
#define GLOBAL_SSID "Your SSID"
|
||||
#define GLOBAL_PASS "Password"
|
||||
#define GLOBAL_MQTT_ADDR "192.168.0.8"
|
||||
|
||||
#define GLOBAL_BAND 915E6 //LoRa Frequency Band
|
||||
#define GLOBAL_SF 7 //LoRa Spreading Factor
|
||||
|
||||
#define GLOBALS
|
234
Examples/Universal_Gateway/Universal_Gateway.ino
Normal file
@ -0,0 +1,234 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// Experimental Universal Gateway
|
||||
//
|
||||
// Under construction, feedback is appreciated!
|
||||
//
|
||||
|
||||
#include "fdrs_config.h"
|
||||
|
||||
#ifdef USE_LED
|
||||
#include <FastLED.h>
|
||||
#endif
|
||||
#include "fdrs_gateway.h"
|
||||
#include "fdrs_config.h"
|
||||
|
||||
#ifdef USE_LED
|
||||
CRGB leds[NUM_LEDS];
|
||||
#endif
|
||||
|
||||
uint8_t selfAddress[6] = {MAC_PREFIX, UNIT_MAC};
|
||||
|
||||
#if defined(ESP_GET) || defined(ESP_SEND)
|
||||
|
||||
#ifdef ESPNOW_ALL
|
||||
std::vector<DataReading_t> espnow_peer_unknown_data;
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_1
|
||||
uint8_t ESPNOW1[] = {MAC_PREFIX, ESPNOW_PEER_1};
|
||||
std::vector<DataReading_t> espnow_peer_1_data;
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_2
|
||||
uint8_t ESPNOW2[] = {MAC_PREFIX, ESPNOW_PEER_2};
|
||||
std::vector<DataReading_t> espnow_peer_2_data;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LORA_GET) || defined(LORA_SEND)
|
||||
|
||||
#ifdef LORA_PEER_1
|
||||
uint8_t LoRa1[6] = {MAC_PREFIX, LORA_PEER_1};
|
||||
std::vector<DataReading_t> lora_peer_1_data;
|
||||
#endif
|
||||
|
||||
#ifdef LORA_PEER_2
|
||||
uint8_t LoRa2[6] = {MAC_PREFIX, LORA_PEER_2};
|
||||
std::vector<DataReading_t> lora_peer_2_data;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MQTT_GET) || defined(MQTT_SEND)
|
||||
MQTT_FDRSGateWay MQTT(WIFI_SSID,WIFI_PASS,MQTT_ADDR,MQTT_PORT);
|
||||
std::vector<DataReading_t> mqtt_data;
|
||||
#endif
|
||||
|
||||
#if defined(ESP_GET) || defined(ESP_SEND)
|
||||
ESP_FDRSGateWay ESPNow;
|
||||
#endif
|
||||
|
||||
#if defined(SER_GET) || defined(SER_SEND)
|
||||
|
||||
#ifdef ESP32
|
||||
Serial_FDRSGateWay SerialGW(&Serial1,115200);
|
||||
#else
|
||||
Serial_FDRSGateWay SerialGW(&Serial,115200);
|
||||
#endif
|
||||
|
||||
std::vector<DataReading_t> serial_data;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LORA_GET) || defined(LORA_SEND)
|
||||
|
||||
LoRa_FDRSGateWay LoRaGW(MISO,MOSI,SCK,SS,RST,DIO0,BAND,SF);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
#ifdef USE_LED
|
||||
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
|
||||
leds[0] = CRGB::Blue;
|
||||
FastLED.show();
|
||||
#endif
|
||||
|
||||
#if defined(MQTT_GET) || defined(MQTT_SEND)
|
||||
MQTT.init();
|
||||
#endif
|
||||
|
||||
#if defined(ESP_GET) || defined(ESP_SEND)
|
||||
ESPNow.init(selfAddress);
|
||||
|
||||
#ifdef ESPNOW_PEER_1
|
||||
ESPNow.add_peer(ESPNOW1);
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_2
|
||||
ESPNow.add_peer(ESPNOW2);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(SER_GET) || defined(SER_SEND)
|
||||
|
||||
#ifdef ESP32
|
||||
SerialGW.init(SERIAL_8N1,RXD2,TXD2);
|
||||
#else
|
||||
SerialGW.init();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LORA_GET) || defined(LORA_SEND)
|
||||
LoRaGW.init(selfAddress);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
//collect data
|
||||
#ifdef LORA_GET
|
||||
LoRaGW.get();
|
||||
#endif
|
||||
|
||||
#ifdef SER_GET
|
||||
SerialGW.get();
|
||||
#endif
|
||||
|
||||
//get the collected data
|
||||
#ifdef ESP_GET
|
||||
#ifdef ESPNOW_ALL
|
||||
espnow_peer_unknown_data = ESPNow.get_unkown_peer_data();
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_1
|
||||
espnow_peer_1_data = ESPNow.get_peer_data(ESPNOW1);
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_2
|
||||
espnow_peer_2_data = ESPNow.get_peer_data(ESPNOW2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MQTT_GET
|
||||
mqtt_data = MQTT.get_data();
|
||||
#endif
|
||||
|
||||
#ifdef SER_GET
|
||||
serial_data = SerialGW.get_data();
|
||||
#endif
|
||||
|
||||
#ifdef LORA_GET
|
||||
#ifdef LORA_PEER_1
|
||||
lora_peer_1_data = LoRaGW.get_peer_data(LoRa1);
|
||||
#endif
|
||||
#ifdef LORA_PEER_1
|
||||
lora_peer_2_data = LoRaGW.get_peer_data(LoRa2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//send the collected data to where you want it
|
||||
#ifdef ESP_SEND
|
||||
#ifdef ESPNOW_ALL
|
||||
// send ESPNOW_UNKNOWN_PEER data to ESPNOW_UNKNOWN_PEER
|
||||
ESPNow.release(espnow_peer_unknown_data);
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_1
|
||||
// send ESPNOW_PEER_2 data to ESPNOW_PEER_1
|
||||
ESPNow.release(espnow_peer_2_data,ESPNOW1);
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_2
|
||||
// send ESPNOW_PEER_1 data to ESPNOW_PEER_2
|
||||
ESPNow.release(espnow_peer_1_data,ESPNOW2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MQTT_SEND
|
||||
// send ESPNOW_PEER_1 data to MQTT
|
||||
MQTT.release(espnow_peer_1_data);
|
||||
#endif
|
||||
|
||||
#ifdef SER_SEND
|
||||
// send ESPNOW_PEER_2 data to SERIAL
|
||||
SerialGW.release(espnow_peer_2_data);
|
||||
#endif
|
||||
|
||||
#ifdef LORA_SEND
|
||||
// send SERIAL data to LoRa
|
||||
LoRaGW.release(serial_data);
|
||||
#endif
|
||||
|
||||
//clear out the buffers
|
||||
#ifdef ESP_GET
|
||||
#ifdef ESPNOW_ALL
|
||||
ESPNow.flush();
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_1
|
||||
ESPNow.flush(ESPNOW1);
|
||||
#endif
|
||||
|
||||
#ifdef ESPNOW_PEER_2
|
||||
ESPNow.flush(ESPNOW2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MQTT_GET
|
||||
MQTT.flush();
|
||||
#endif
|
||||
|
||||
#ifdef SER_GET
|
||||
SerialGW.flush();
|
||||
#endif
|
||||
|
||||
#ifdef LORA_GET
|
||||
#ifdef LORA_PEER_1
|
||||
LoRaGW.flush(LoRa1);
|
||||
#endif
|
||||
#ifdef LORA_PEER_1
|
||||
LoRaGW.flush(LoRa2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
delay(1000);
|
||||
|
||||
}
|
61
Examples/Universal_Gateway/fdrs_config.h
Normal file
@ -0,0 +1,61 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// GATEWAY 2.000 Configuration
|
||||
|
||||
//#include <fdrs_globals.h> //Uncomment if you install the globals file
|
||||
#define DEBUG
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
#define UNIT_MAC 0x03 // The address of this gateway
|
||||
|
||||
//Where we get the data from
|
||||
#define LORA_GET
|
||||
#define MQTT_GET
|
||||
#define ESP_GET
|
||||
#define SER_GET
|
||||
|
||||
//Where we send the data to
|
||||
#define LORA_SEND
|
||||
#define MQTT_SEND
|
||||
#define ESP_SEND
|
||||
#define SER_SEND
|
||||
|
||||
//#define USE_LORA
|
||||
//#define USE_WIFI //Used only for MQTT gateway
|
||||
|
||||
// Peer addresses
|
||||
|
||||
#define LORA_PEER_1 0x0E // LoRa1 Address
|
||||
#define LORA_PEER_2 0x0F // LoRa2 Address
|
||||
|
||||
#define ESPNOW_ALL //send to all know and unknow peers
|
||||
#define ESPNOW_PEER_1 0x0C // ESPNOW1 Address
|
||||
#define ESPNOW_PEER_2 0x0D // ESPNOW2 Address
|
||||
|
||||
//WiFi and MQTT Credentials -- Needed only for MQTT gateway
|
||||
#define WIFI_SSID "Your SSID"
|
||||
#define WIFI_PASS "Your Password"
|
||||
#define MQTT_ADDR "192.168.0.8"
|
||||
#define MQTT_PORT 1883
|
||||
|
||||
//Pins for UART data interface (ESP32 only)
|
||||
#define RXD2 14
|
||||
#define TXD2 15
|
||||
|
||||
//LoRa Configuration -- Needed only if using 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 SF 7
|
||||
|
||||
//#define USE_LED //Not yet fully implemented
|
||||
#define LED_PIN 32
|
||||
#define NUM_LEDS 4
|
685
Examples/Universal_Gateway/fdrs_gateway.cpp
Normal file
@ -0,0 +1,685 @@
|
||||
#include "fdrs_gateway.h"
|
||||
|
||||
// #define ESP8266
|
||||
// #define ESP32
|
||||
|
||||
// #define USE_WIFI
|
||||
|
||||
bool ESP_FDRSGateWay::is_init = false;
|
||||
std::vector<Peer_t> ESP_FDRSGateWay::_peer_list;
|
||||
std::vector<Peer_t> ESP_FDRSGateWay::_unknow_peer;
|
||||
|
||||
std::vector<DataReading_t> MQTT_FDRSGateWay::_buffer;
|
||||
std::vector<DataReading_t> Serial_FDRSGateWay::_buffer;
|
||||
|
||||
// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32
|
||||
void ESP_FDRSGateWay::OnDataRecv(uint8_t * mac, const uint8_t *incomingData, int len){
|
||||
|
||||
DataReading_t data;
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
|
||||
uint8_t d = len / sizeof(DataReading_t);
|
||||
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(_peer_list[i]._get_peer(),mac,6) == 0){
|
||||
for(j = 0; j < d; j++){
|
||||
memcpy(&data,&incomingData[j*sizeof(DataReading_t)],sizeof(DataReading_t));
|
||||
_peer_list[i].buffer.push_back(data);
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < _unknow_peer.size();i++){
|
||||
if(memcmp(_unknow_peer[i]._get_peer(),mac,6) == 0){
|
||||
for(j = 0; j < d; j++){
|
||||
memcpy(&data,&incomingData[j*sizeof(DataReading_t)],sizeof(DataReading_t));
|
||||
_unknow_peer[i].buffer.push_back(data);
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Peer_t peer;
|
||||
peer._set_peer(mac);
|
||||
_unknow_peer.push_back(peer);
|
||||
|
||||
for(j = 0; j < d; j++){
|
||||
memcpy(&data,&incomingData[j*sizeof(DataReading_t)],sizeof(DataReading_t));
|
||||
_unknow_peer.back().buffer.push_back(data);
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(ESP8266)
|
||||
void ESP8266OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
|
||||
|
||||
}
|
||||
|
||||
void ESP8266OnDataRecv(uint8_t* mac, uint8_t *incomingData, uint8_t len) {
|
||||
ESP_FDRSGateWay::OnDataRecv((uint8_t*)mac,*(const uint8_t *)incomingData,len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
void ESP32OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
|
||||
|
||||
}
|
||||
|
||||
void ESP32OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
|
||||
ESP_FDRSGateWay::OnDataRecv((uint8_t*)mac,incomingData,len);
|
||||
}
|
||||
#endif
|
||||
|
||||
FDRSGateWayBase::FDRSGateWayBase(){
|
||||
|
||||
}
|
||||
|
||||
FDRSGateWayBase::~FDRSGateWayBase(){
|
||||
}
|
||||
|
||||
void FDRSGateWayBase::release(std::vector<DataReading_t> data,uint8_t *peer_mac){
|
||||
if(peer_mac == NULL){
|
||||
send(data);
|
||||
}
|
||||
forward(peer_mac ,data);
|
||||
|
||||
}
|
||||
|
||||
ESP_FDRSGateWay::ESP_FDRSGateWay(void)
|
||||
{
|
||||
|
||||
memset(_broadcast_mac,0xFF,6);
|
||||
memset(_inturnal_mac,0,6);
|
||||
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::init(uint8_t inturnal_mac[5]){
|
||||
|
||||
memcpy(_inturnal_mac,inturnal_mac,6);
|
||||
|
||||
#if defined(ESP8266)
|
||||
wifi_set_macaddr(STATION_IF, _inturnal_mac);
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
esp_wifi_set_mac(WIFI_IF_STA, &_inturnal_mac[0]);
|
||||
#endif
|
||||
|
||||
ESP_FDRSGateWay::setup();
|
||||
|
||||
#if defined(ESP32)
|
||||
esp_now_peer_info_t peerInfo;
|
||||
memset(&peerInfo, 0, sizeof(peerInfo));
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
// Register first peer
|
||||
memcpy(peerInfo.peer_addr, _broadcast_mac, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer bcast");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::setup(void){
|
||||
if(is_init){
|
||||
return;
|
||||
}
|
||||
is_init = true;
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
|
||||
#if defined(ESP8266)
|
||||
|
||||
if (esp_now_init() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||
esp_now_register_send_cb(ESP8266OnDataSent);
|
||||
esp_now_register_recv_cb(ESP8266OnDataRecv);
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
|
||||
|
||||
if(esp_now_init() != ESP_OK) {
|
||||
DBG("Error initializing ESP-NOW");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_now_register_send_cb(ESP32OnDataSent);
|
||||
esp_now_register_recv_cb(ESP32OnDataRecv);
|
||||
|
||||
#endif
|
||||
|
||||
DBG("ESP-NOW Initialized.");
|
||||
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::add_peer(uint8_t peer_mac[6]){
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(_peer_list[i]._get_peer(),peer_mac,6) == 0){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
list_peer(peer_mac);
|
||||
|
||||
Peer_t peer;
|
||||
peer._set_peer(peer_mac);
|
||||
//esp_now_del_peer(NEWPEER);
|
||||
|
||||
_peer_list.push_back(peer);
|
||||
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::remove_peer(uint8_t peer_mac[6]){
|
||||
|
||||
unlist_peer(peer_mac);
|
||||
|
||||
if(_peer_list.size() == 0){
|
||||
return;
|
||||
}
|
||||
Peer_t peer;
|
||||
peer._set_peer(peer_mac);
|
||||
_peer_list.erase(std::find(_peer_list.begin(),_peer_list.end(),peer));
|
||||
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::list_peer(uint8_t peer_mac[6]){
|
||||
|
||||
#if defined(ESP8266)
|
||||
esp_now_add_peer(peer_mac, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
esp_now_peer_info_t peerInfo;
|
||||
memset(&peerInfo, 0, sizeof(peerInfo));
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
memcpy(peerInfo.peer_addr, peer_mac, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer 1");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::unlist_peer(uint8_t peer_mac[6]){
|
||||
|
||||
esp_now_del_peer(peer_mac);
|
||||
|
||||
}
|
||||
|
||||
std::vector<DataReading_t> ESP_FDRSGateWay::get_peer_data(uint8_t *peer_mac){
|
||||
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(_peer_list[i]._get_peer(),peer_mac,6) == 0){
|
||||
return _peer_list[i].buffer;
|
||||
}
|
||||
}
|
||||
return std::vector<DataReading_t>();
|
||||
}
|
||||
|
||||
std::vector<DataReading_t> ESP_FDRSGateWay::get_unkown_peer_data(void){
|
||||
|
||||
std::vector<DataReading_t> data;
|
||||
for(uint32_t i = 0; i < _unknow_peer.size(); i++){
|
||||
data.insert(data.end(),_unknow_peer[i].buffer.begin(),_unknow_peer[i].buffer.end());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::flush(uint8_t *peer_mac){
|
||||
|
||||
if(peer_mac == NULL){
|
||||
for(uint32_t i = 0; i < _unknow_peer.size(); i++){
|
||||
_unknow_peer[i].buffer.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(_peer_list[i]._get_peer(),peer_mac,6) == 0){
|
||||
_peer_list[i].buffer.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ESP_FDRSGateWay::send(std::vector<DataReading_t> data){
|
||||
|
||||
const uint8_t espnow_size = 250 / sizeof(DataReading_t);
|
||||
|
||||
uint32_t i = 0;
|
||||
for(i = 0; i < _unknow_peer.size(); i++){
|
||||
list_peer(_unknow_peer[i]._get_peer());
|
||||
}
|
||||
|
||||
uint8_t d = data.size() / espnow_size;
|
||||
|
||||
DataReading_t buffer1[d * sizeof(DataReading_t)];
|
||||
memset(buffer1,0,d * sizeof(DataReading_t));
|
||||
uint32_t j = 0;
|
||||
for(i = 0; i < data.size(); i++){
|
||||
|
||||
buffer1[j++] = data[i];
|
||||
if(j >= d){
|
||||
esp_now_send(NULL, (uint8_t *) buffer1, d * sizeof(DataReading_t));
|
||||
|
||||
memset(buffer1,0,d * sizeof(DataReading_t));
|
||||
j = 0;
|
||||
delay(10);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(j != 0){
|
||||
esp_now_send(NULL, (uint8_t *) buffer1, j * sizeof(DataReading_t));
|
||||
}
|
||||
|
||||
for(i = 0; i < _unknow_peer.size(); i++){
|
||||
unlist_peer(_unknow_peer[i]._get_peer());
|
||||
}
|
||||
|
||||
_unknow_peer.clear();
|
||||
|
||||
}
|
||||
|
||||
void ESP_FDRSGateWay::forward(uint8_t *peer_mac ,std::vector<DataReading_t> data){
|
||||
|
||||
const uint8_t espnow_size = 250 / sizeof(DataReading_t);
|
||||
|
||||
uint8_t d = data.size() / espnow_size;
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
DataReading_t buffer1[d * sizeof(DataReading_t)];
|
||||
memset(buffer1,0,d * sizeof(DataReading_t));
|
||||
uint32_t j = 0;
|
||||
for(i = 0; i < data.size(); i++){
|
||||
|
||||
buffer1[j++] = data[i];
|
||||
if(j >= d){
|
||||
esp_now_send(NULL, (uint8_t *) buffer1, d * sizeof(DataReading_t));
|
||||
|
||||
memset(buffer1,0,d * sizeof(DataReading_t));
|
||||
j = 0;
|
||||
delay(10);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(j != 0){
|
||||
esp_now_send(NULL, (uint8_t *) buffer1, j * sizeof(DataReading_t));
|
||||
}
|
||||
|
||||
esp_now_send(peer_mac, (uint8_t *) buffer1, d * sizeof(DataReading_t));
|
||||
|
||||
}
|
||||
|
||||
MQTT_FDRSGateWay::MQTT_FDRSGateWay(const char *ssid, const char *password, const char *server,int port):
|
||||
_ssid(ssid),
|
||||
_password(password),
|
||||
_server(server),
|
||||
_port(port)
|
||||
{
|
||||
|
||||
_client = new PubSubClient(espClient);
|
||||
|
||||
}
|
||||
|
||||
MQTT_FDRSGateWay::~MQTT_FDRSGateWay(void){
|
||||
delete _client;
|
||||
}
|
||||
|
||||
void MQTT_FDRSGateWay::mqtt_callback(char* topic, byte * message, unsigned int length){
|
||||
|
||||
//No point in reading topics that are not data.
|
||||
if(strcmp(TOPIC_DATA,topic) != 0){
|
||||
return;
|
||||
}
|
||||
|
||||
String incomingString;
|
||||
DBG(topic);
|
||||
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.
|
||||
DBG("json parse err");
|
||||
DBG(incomingString);
|
||||
return;
|
||||
}
|
||||
int s = doc.size();
|
||||
//UART_IF.println(s);
|
||||
DataReading_t data;
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
for (int i = 0; i < s; i++) {
|
||||
data.id = doc[i]["id"];
|
||||
data.type = doc[i]["type"];
|
||||
data.data = doc[i]["data"];
|
||||
_buffer.push_back(data);
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
}
|
||||
DBG("Incoming MQTT.");
|
||||
|
||||
}
|
||||
|
||||
void MQTT_FDRSGateWay::init(void){
|
||||
delay(10);
|
||||
WiFi.begin(_ssid, _password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
DBG("Connecting to WiFi... ");
|
||||
DBG(_ssid);
|
||||
|
||||
delay(500);
|
||||
}
|
||||
DBG("WiFi Connected");
|
||||
_client->setServer(_server, _port);
|
||||
if (!_client->connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
reconnect();
|
||||
}
|
||||
DBG("MQTT Connected");
|
||||
_client->setCallback(MQTT_FDRSGateWay::mqtt_callback);
|
||||
|
||||
_client->publish(TOPIC_STATUS, "FDRS initialized");
|
||||
}
|
||||
|
||||
void MQTT_FDRSGateWay::reconnect() {
|
||||
// Loop until reconnected
|
||||
while (!_client->connected()) {
|
||||
// Attempt to connect
|
||||
if (_client->connect("FDRS_GATEWAY")) {
|
||||
// Subscribe
|
||||
_client->subscribe(TOPIC_COMMAND);
|
||||
break;
|
||||
}
|
||||
DBG("Connecting MQTT.");
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTT_FDRSGateWay::send(std::vector<DataReading_t> data) {
|
||||
|
||||
DBG("Releasing MQTT.");
|
||||
DynamicJsonDocument doc(24576);
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
doc[i]["id"] = data[i].id;
|
||||
doc[i]["type"] = data[i].type;
|
||||
doc[i]["data"] = data[i].data;
|
||||
}
|
||||
String outgoingString;
|
||||
serializeJson(doc, outgoingString);
|
||||
_client->publish(TOPIC_DATA, (char*) outgoingString.c_str());
|
||||
|
||||
reconnect();
|
||||
_client->loop();
|
||||
|
||||
}
|
||||
|
||||
void MQTT_FDRSGateWay::forward(uint8_t *peer_mac ,std::vector<DataReading_t> data){
|
||||
//does nothing. just here implement the pure virtule from the base class.
|
||||
send(data);
|
||||
}
|
||||
|
||||
std::vector<DataReading_t> MQTT_FDRSGateWay::get_data(void){
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
void MQTT_FDRSGateWay::flush(uint8_t *peer_mac){
|
||||
_buffer.clear();
|
||||
}
|
||||
|
||||
Serial_FDRSGateWay::Serial_FDRSGateWay(HardwareSerial *serial, uint32_t baud):
|
||||
_serial(serial),
|
||||
_baud(baud)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Serial_FDRSGateWay::init(void){
|
||||
_serial->begin(_baud);
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
void Serial_FDRSGateWay::init(int mode, int rx_pin, int tx_pin){
|
||||
_serial->begin(_baud,mode,rx_pin,tx_pin);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Serial_FDRSGateWay::pull(void){
|
||||
//TDDO: This is blocking. Some method of escaping is required.
|
||||
// At the momment we are just hoping we get a \n
|
||||
String incomingString = _serial->readStringUntil('\n');
|
||||
DynamicJsonDocument doc(24576);
|
||||
DeserializationError error = deserializeJson(doc, incomingString);
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
// DBG("json parse err");
|
||||
// DBG(incomingString);
|
||||
return;
|
||||
}
|
||||
|
||||
int s = doc.size();
|
||||
//UART_IF.println(s);
|
||||
DataReading_t data;
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
for (int i = 0; i < s; i++) {
|
||||
data.id = doc[i]["id"];
|
||||
data.type = doc[i]["type"];
|
||||
data.data = doc[i]["data"];
|
||||
_buffer.push_back(data);
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
}
|
||||
DBG("Incoming Serial.");
|
||||
|
||||
}
|
||||
|
||||
std::vector<DataReading_t> Serial_FDRSGateWay::get_data(void){
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
void Serial_FDRSGateWay::get(void){
|
||||
while(_serial->available()){
|
||||
pull();
|
||||
}
|
||||
}
|
||||
|
||||
void Serial_FDRSGateWay::send(std::vector<DataReading_t> data){
|
||||
|
||||
DBG("Releasing Serial.");
|
||||
DynamicJsonDocument doc(24576);
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
doc[i]["id"] = data[i].id;
|
||||
doc[i]["type"] = data[i].type;
|
||||
doc[i]["data"] = data[i].data;
|
||||
}
|
||||
serializeJson(doc, *_serial);
|
||||
_serial->println();
|
||||
}
|
||||
|
||||
void Serial_FDRSGateWay::forward(uint8_t *peer_mac ,std::vector<DataReading_t> data){
|
||||
//does nothing. just here implement the pure virtule from the base class.
|
||||
}
|
||||
|
||||
void Serial_FDRSGateWay::flush(uint8_t *peer_mac){
|
||||
_buffer.clear();
|
||||
}
|
||||
|
||||
LoRa_FDRSGateWay::LoRa_FDRSGateWay(uint8_t miso,uint8_t mosi,uint8_t sck, uint8_t ss,uint8_t rst,uint8_t dio0,double band,uint8_t sf):
|
||||
_miso(miso),
|
||||
_mosi(mosi),
|
||||
_sck(sck),
|
||||
_ss(ss),
|
||||
_rst(rst),
|
||||
_dio0(dio0),
|
||||
_band(band),
|
||||
_sf(sf)
|
||||
{
|
||||
memset(_mac,0,6);
|
||||
_peer_list.clear();
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::init(uint8_t mac[6]){
|
||||
|
||||
memcpy(_mac,mac,6);
|
||||
|
||||
DBG("Initializing LoRa!");
|
||||
SPI.begin(_sck, _miso, _mosi, _ss);
|
||||
LoRa.setPins(_ss, _rst, _dio0);
|
||||
if (!LoRa.begin(_band)) {
|
||||
DBG(" LoRa initialize failed");
|
||||
return;
|
||||
}
|
||||
LoRa.setSpreadingFactor(_sf);
|
||||
DBG(" LoRa initialized.");
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::add_peer(uint8_t peer_mac[6]){
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(_peer_list[i]._get_peer(),peer_mac,6) == 0){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Peer_t peer;
|
||||
peer._set_peer(peer_mac);
|
||||
_peer_list.push_back(peer);
|
||||
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::remove_peer(uint8_t peer_mac[6]){
|
||||
|
||||
if(_peer_list.size() == 0){
|
||||
return;
|
||||
}
|
||||
Peer_t peer;
|
||||
peer._set_peer(peer_mac);
|
||||
_peer_list.erase(std::find(_peer_list.begin(),_peer_list.end(),peer));
|
||||
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::get(void){
|
||||
|
||||
int packetSize = LoRa.parsePacket();
|
||||
if (packetSize== 0) {
|
||||
return;
|
||||
}
|
||||
uint8_t packet[packetSize];
|
||||
uint8_t incLORAMAC[2];
|
||||
LoRa.readBytes((uint8_t *)&packet, packetSize);
|
||||
// for (int i = 0; i < packetSize; i++) {
|
||||
// UART_IF.println(packet[i], HEX);
|
||||
// }
|
||||
|
||||
//Check if addressed to this device
|
||||
if (memcmp(&packet, &_mac[3], 3) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t theData[packetSize - 5];
|
||||
|
||||
memcpy(&incLORAMAC, &packet[3], 2); //Split off address portion of packet
|
||||
memcpy(&theData, &packet[5], packetSize - 5); //Split off data portion of packet
|
||||
|
||||
//Check if it is from a registered sender
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(&_peer_list[i].peer[3],incLORAMAC,2) == 0){
|
||||
DataReading_t data;
|
||||
uint32_t i = 0;
|
||||
uint8_t d = packetSize / sizeof(DataReading_t);
|
||||
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
|
||||
for(uint32_t j = 0; j < d; j++){
|
||||
memcpy(&data,&theData[j*sizeof(DataReading_t)],sizeof(DataReading_t));
|
||||
_peer_list[i].buffer.push_back(data);
|
||||
memset(&data,0,sizeof(DataReading_t));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("Incoming LoRa.");
|
||||
|
||||
}
|
||||
|
||||
std::vector<DataReading_t> LoRa_FDRSGateWay::get_peer_data(uint8_t *peer_mac){
|
||||
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(_peer_list[i]._get_peer(),peer_mac,6) == 0){
|
||||
return _peer_list[i].buffer;
|
||||
}
|
||||
}
|
||||
return std::vector<DataReading_t>();
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::send(std::vector<DataReading_t> data){
|
||||
|
||||
const uint8_t espnow_size = 250 / sizeof(DataReading_t);
|
||||
|
||||
uint32_t i = 0;
|
||||
uint8_t d = data.size() / espnow_size;
|
||||
|
||||
DataReading_t buffer1[d];
|
||||
for(i = 0; i < d; i++){
|
||||
buffer1[i] = data[i];
|
||||
}
|
||||
|
||||
transmit(buffer1, d * sizeof(DataReading_t));
|
||||
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::forward(uint8_t *peer_mac ,std::vector<DataReading_t> data){
|
||||
//TODO: add peer forwading.
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::transmit(DataReading_t *packet, uint8_t len) {
|
||||
DBG("Transmitting LoRa.");
|
||||
uint8_t pkt[5 + (len * sizeof(DataReading_t))];
|
||||
memcpy(&pkt, _mac, 3);
|
||||
memcpy(&pkt[3], &_mac[4], 2);
|
||||
memcpy(&pkt[5], packet, len * sizeof(DataReading_t));
|
||||
LoRa.beginPacket();
|
||||
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
|
||||
LoRa.endPacket();
|
||||
}
|
||||
|
||||
void LoRa_FDRSGateWay::flush(uint8_t *peer_mac){
|
||||
|
||||
if(peer_mac == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < _peer_list.size();i++){
|
||||
if(memcmp(_peer_list[i]._get_peer(),peer_mac,6) == 0){
|
||||
_peer_list[i].buffer.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
186
Examples/Universal_Gateway/fdrs_gateway.h
Normal file
@ -0,0 +1,186 @@
|
||||
/* FARM DATA RELAY SYSTEM
|
||||
*
|
||||
* "fdrs_sensor.h"
|
||||
*
|
||||
* Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
* Condensed and refactored to a single file pair by Binder Tronics (info@bindertronics.com).
|
||||
*/
|
||||
|
||||
#ifndef __FDRS_GATEWAY_H__
|
||||
#define __FDRS_GATEWAY_H__
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
#include "fdrs_types.h"
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#include "ArduinoJson.h"
|
||||
#include "PubSubClient.h"
|
||||
#include "LoRa.h"
|
||||
|
||||
|
||||
#define USE_LORA
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) (Serial.println(a))
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
class FDRSGateWayBase{
|
||||
public:
|
||||
|
||||
FDRSGateWayBase();
|
||||
~FDRSGateWayBase();
|
||||
|
||||
void release(std::vector<DataReading_t> data, uint8_t *peer_mac = NULL);
|
||||
virtual void flush(uint8_t *peer_mac = NULL) = 0;
|
||||
|
||||
private:
|
||||
static uint32_t peer_id;
|
||||
virtual void send(std::vector<DataReading_t> data) = 0;
|
||||
virtual void forward(uint8_t *peer_mac ,std::vector<DataReading_t> data) = 0;
|
||||
};
|
||||
|
||||
class ESP_FDRSGateWay: public FDRSGateWayBase{
|
||||
public:
|
||||
ESP_FDRSGateWay(void);
|
||||
|
||||
static void OnDataRecv(uint8_t * mac, const uint8_t *incomingData, int len);
|
||||
|
||||
void init(uint8_t inturnal_mac[5]);
|
||||
|
||||
void add_peer(uint8_t peer_mac[6]);
|
||||
void remove_peer(uint8_t peer_mac[6]);
|
||||
std::vector<DataReading_t> get_peer_data(uint8_t peer_mac[6]);
|
||||
std::vector<DataReading_t> get_unkown_peer_data(void);
|
||||
|
||||
void flush(uint8_t *peer_mac = NULL) override;
|
||||
|
||||
private:
|
||||
|
||||
static bool is_init;
|
||||
uint8_t _broadcast_mac[6];
|
||||
uint8_t _inturnal_mac[6];
|
||||
static std::vector<Peer_t> _peer_list;
|
||||
static std::vector<Peer_t> _unknow_peer;
|
||||
|
||||
static void setup(void);
|
||||
|
||||
void send(std::vector<DataReading_t> data) override;
|
||||
void forward(uint8_t *peer_mac ,std::vector<DataReading_t> data) override;
|
||||
|
||||
void list_peer(uint8_t peer_mac[6]);
|
||||
void unlist_peer(uint8_t peer_mac[6]);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class MQTT_FDRSGateWay: public FDRSGateWayBase{
|
||||
|
||||
public:
|
||||
|
||||
MQTT_FDRSGateWay(const char *ssid, const char *password, const char *server,int port = 1883);
|
||||
~MQTT_FDRSGateWay(void);
|
||||
|
||||
void init(void);
|
||||
|
||||
std::vector<DataReading_t> get_data(void);
|
||||
|
||||
void flush(uint8_t *peer_mac = NULL) override;
|
||||
|
||||
private:
|
||||
#define TOPIC_DATA "fdrs/data"
|
||||
#define TOPIC_STATUS "fdrs/status"
|
||||
#define TOPIC_COMMAND "fdrs/command"
|
||||
|
||||
static void mqtt_callback(char* topic, byte * message, unsigned int length);
|
||||
|
||||
const char *_ssid;
|
||||
const char *_password;
|
||||
const char *_server;
|
||||
int _port;
|
||||
WiFiClient espClient;
|
||||
PubSubClient *_client;
|
||||
|
||||
static std::vector<DataReading_t> _buffer;
|
||||
|
||||
void reconnect();
|
||||
void send(std::vector<DataReading_t> data) override;
|
||||
void forward(uint8_t *peer_mac ,std::vector<DataReading_t> data) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Serial_FDRSGateWay: public FDRSGateWayBase{
|
||||
|
||||
public:
|
||||
Serial_FDRSGateWay(HardwareSerial *serial, uint32_t baud);
|
||||
|
||||
void init(void);
|
||||
#if defined(ESP32)
|
||||
void init(int mode, int rx_pin, int tx_pin);
|
||||
#endif
|
||||
void get(void);
|
||||
|
||||
std::vector<DataReading_t> get_data(void);
|
||||
|
||||
void flush(uint8_t *peer_mac = NULL) override;
|
||||
|
||||
private:
|
||||
|
||||
HardwareSerial *_serial;
|
||||
uint32_t _baud;
|
||||
static std::vector<DataReading_t> _buffer;
|
||||
|
||||
static void setup(void);
|
||||
void pull(void);
|
||||
void send(std::vector<DataReading_t> data) override;
|
||||
void forward(uint8_t *peer_mac ,std::vector<DataReading_t> data) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class LoRa_FDRSGateWay: public FDRSGateWayBase{
|
||||
|
||||
public:
|
||||
LoRa_FDRSGateWay(uint8_t miso,uint8_t mosi,uint8_t sck, uint8_t ss,uint8_t rst,uint8_t dio0,double band,uint8_t sf);
|
||||
|
||||
void init(uint8_t mac[6]);
|
||||
void get(void);
|
||||
void add_peer(uint8_t peer_mac[6]);
|
||||
void remove_peer(uint8_t peer_mac[6]);
|
||||
std::vector<DataReading_t> get_peer_data(uint8_t *peer_mac);
|
||||
|
||||
void flush(uint8_t *peer_mac = NULL) override;
|
||||
|
||||
private:
|
||||
|
||||
uint8_t _mac[6];
|
||||
uint8_t _miso;
|
||||
uint8_t _mosi;
|
||||
uint8_t _sck;
|
||||
uint8_t _ss;
|
||||
uint8_t _rst;
|
||||
uint8_t _dio0;
|
||||
uint32_t _band;
|
||||
uint8_t _sf;
|
||||
|
||||
std::vector<Peer_t> _peer_list;
|
||||
|
||||
void transmit(DataReading_t *packet, uint8_t len);
|
||||
|
||||
void send(std::vector<DataReading_t> data) override;
|
||||
void forward(uint8_t *peer_mac ,std::vector<DataReading_t> data) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
39
Examples/Universal_Gateway/fdrs_types.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef __FDRS_TYPES_H__
|
||||
#define __FDRS_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading_t {
|
||||
float data;
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
DataReading_t(): data(0.0),id(0),type(0){
|
||||
}
|
||||
} DataReading_t;
|
||||
|
||||
typedef struct Peer_t{
|
||||
|
||||
uint8_t peer[6];
|
||||
std::vector<DataReading_t> buffer;
|
||||
Peer_t(){
|
||||
memset(peer,0,6);
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
void _set_peer(uint8_t p[6]){
|
||||
memcpy(peer,p,6);
|
||||
}
|
||||
uint8_t *_get_peer(void){
|
||||
return peer;
|
||||
}
|
||||
|
||||
bool operator==(Peer_t c){
|
||||
return (memcmp(this->peer,c.peer,6) == 0);
|
||||
}
|
||||
|
||||
}Peer_t;
|
||||
|
||||
|
||||
#endif
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 228 KiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 238 KiB |
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 241 KiB |
Before Width: | Height: | Size: 221 KiB After Width: | Height: | Size: 221 KiB |
@ -1,169 +1,169 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// GATEWAY 2.000
|
||||
//
|
||||
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
//
|
||||
|
||||
#include "fdrs_config.h"
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#include <ArduinoJson.h>
|
||||
#ifdef USE_WIFI
|
||||
#include <PubSubClient.h>
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
#ifdef USE_LED
|
||||
#include <FastLED.h>
|
||||
#endif
|
||||
#include "fdrs_functions.h"
|
||||
|
||||
void setup() {
|
||||
#if defined(ESP8266)
|
||||
Serial.begin(115200);
|
||||
#elif defined(ESP32)
|
||||
Serial.begin(115200);
|
||||
UART_IF.begin(115200, SERIAL_8N1, RXD2, TXD2);
|
||||
#endif
|
||||
DBG("Address:" + String (UNIT_MAC, HEX));
|
||||
#ifdef USE_LED
|
||||
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
|
||||
leds[0] = CRGB::Blue;
|
||||
FastLED.show();
|
||||
#endif
|
||||
#ifdef USE_WIFI
|
||||
delay(10);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
DBG("Connecting to WiFi...");
|
||||
DBG(FDRS_WIFI_SSID);
|
||||
|
||||
delay(500);
|
||||
}
|
||||
DBG("WiFi Connected");
|
||||
client.setServer(mqtt_server, 1883);
|
||||
if (!client.connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
reconnect();
|
||||
}
|
||||
DBG("MQTT Connected");
|
||||
client.setCallback(mqtt_callback);
|
||||
#else
|
||||
begin_espnow();
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
DBG("Initializing LoRa!");
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
LoRa.setPins(SS, RST, DIO0);
|
||||
if (!LoRa.begin(FDRS_BAND)) {
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(FDRS_SF);
|
||||
DBG(" LoRa initialized.");
|
||||
#endif
|
||||
|
||||
//DBG(sizeof(DataReading));
|
||||
#ifdef USE_WIFI
|
||||
client.publish(TOPIC_STATUS, "FDRS initialized");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef ESPNOWG_DELAY
|
||||
if (millis() > timeESPNOWG) {
|
||||
timeESPNOWG += ESPNOWG_DELAY;
|
||||
if (lenESPNOWG > 0) releaseESPNOW(0);
|
||||
}
|
||||
#endif
|
||||
#ifdef ESPNOW1_DELAY
|
||||
if (millis() > timeESPNOW1) {
|
||||
timeESPNOW1 += ESPNOW1_DELAY;
|
||||
if (lenESPNOW1 > 0) releaseESPNOW(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef ESPNOW2_DELAY
|
||||
if (millis() > timeESPNOW2) {
|
||||
timeESPNOW2 += ESPNOW2_DELAY;
|
||||
if (lenESPNOW2 > 0) releaseESPNOW(2);
|
||||
}
|
||||
#endif
|
||||
#ifdef SERIAL_DELAY
|
||||
if (millis() > timeSERIAL) {
|
||||
timeSERIAL += SERIAL_DELAY;
|
||||
if (lenSERIAL > 0) releaseSerial();
|
||||
}
|
||||
#endif
|
||||
#ifdef MQTT_DELAY
|
||||
if (millis() > timeMQTT) {
|
||||
timeMQTT += MQTT_DELAY;
|
||||
if (lenMQTT > 0) releaseMQTT();
|
||||
}
|
||||
#endif
|
||||
#ifdef LORAG_DELAY
|
||||
if (millis() > timeLORAG) {
|
||||
timeLORAG += LORAG_DELAY;
|
||||
if (lenLORAG > 0) releaseLoRa(0);
|
||||
}
|
||||
#endif
|
||||
#ifdef LORA1_DELAY
|
||||
if (millis() > timeLORA1) {
|
||||
timeLORA1 += LORA1_DELAY;
|
||||
if (lenLORA1 > 0) releaseLoRa(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef LORA2_DELAY
|
||||
if (millis() > timeLORA2) {
|
||||
timeLORA2 += LORA2_DELAY;
|
||||
if (lenLORA2 > 0) releaseLoRa(2);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (UART_IF.available()) {
|
||||
getSerial();
|
||||
}
|
||||
getLoRa();
|
||||
#ifdef USE_WIFI
|
||||
if (!client.connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
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 General
|
||||
LORAG_ACT
|
||||
break;
|
||||
case 7: //LoRa #1
|
||||
LORA1_ACT
|
||||
break;
|
||||
case 8: //LoRa #2
|
||||
LORA2_ACT
|
||||
break;
|
||||
}
|
||||
newData = 0;
|
||||
}
|
||||
}
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// GATEWAY 2.000
|
||||
//
|
||||
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
//
|
||||
|
||||
#include "fdrs_config.h"
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#include <ArduinoJson.h>
|
||||
#ifdef USE_WIFI
|
||||
#include <PubSubClient.h>
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
#ifdef USE_LED
|
||||
#include <FastLED.h>
|
||||
#endif
|
||||
#include "fdrs_functions.h"
|
||||
|
||||
void setup() {
|
||||
#if defined(ESP8266)
|
||||
Serial.begin(115200);
|
||||
#elif defined(ESP32)
|
||||
Serial.begin(115200);
|
||||
UART_IF.begin(115200, SERIAL_8N1, RXD2, TXD2);
|
||||
#endif
|
||||
DBG("Address:" + String (UNIT_MAC, HEX));
|
||||
#ifdef USE_LED
|
||||
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
|
||||
leds[0] = CRGB::Blue;
|
||||
FastLED.show();
|
||||
#endif
|
||||
#ifdef USE_WIFI
|
||||
delay(10);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
DBG("Connecting to WiFi...");
|
||||
DBG(FDRS_WIFI_SSID);
|
||||
|
||||
delay(500);
|
||||
}
|
||||
DBG("WiFi Connected");
|
||||
client.setServer(mqtt_server, mqtt_port);
|
||||
if (!client.connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
reconnect();
|
||||
}
|
||||
DBG("MQTT Connected");
|
||||
client.setCallback(mqtt_callback);
|
||||
#else
|
||||
begin_espnow();
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
DBG("Initializing LoRa!");
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
LoRa.setPins(SS, RST, DIO0);
|
||||
if (!LoRa.begin(FDRS_BAND)) {
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(FDRS_SF);
|
||||
DBG(" LoRa initialized.");
|
||||
#endif
|
||||
|
||||
//DBG(sizeof(DataReading));
|
||||
#ifdef USE_WIFI
|
||||
client.publish(TOPIC_STATUS, "FDRS initialized");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef ESPNOWG_DELAY
|
||||
if (millis() > timeESPNOWG) {
|
||||
timeESPNOWG += ESPNOWG_DELAY;
|
||||
if (lenESPNOWG > 0) releaseESPNOW(0);
|
||||
}
|
||||
#endif
|
||||
#ifdef ESPNOW1_DELAY
|
||||
if (millis() > timeESPNOW1) {
|
||||
timeESPNOW1 += ESPNOW1_DELAY;
|
||||
if (lenESPNOW1 > 0) releaseESPNOW(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef ESPNOW2_DELAY
|
||||
if (millis() > timeESPNOW2) {
|
||||
timeESPNOW2 += ESPNOW2_DELAY;
|
||||
if (lenESPNOW2 > 0) releaseESPNOW(2);
|
||||
}
|
||||
#endif
|
||||
#ifdef SERIAL_DELAY
|
||||
if (millis() > timeSERIAL) {
|
||||
timeSERIAL += SERIAL_DELAY;
|
||||
if (lenSERIAL > 0) releaseSerial();
|
||||
}
|
||||
#endif
|
||||
#ifdef MQTT_DELAY
|
||||
if (millis() > timeMQTT) {
|
||||
timeMQTT += MQTT_DELAY;
|
||||
if (lenMQTT > 0) releaseMQTT();
|
||||
}
|
||||
#endif
|
||||
#ifdef LORAG_DELAY
|
||||
if (millis() > timeLORAG) {
|
||||
timeLORAG += LORAG_DELAY;
|
||||
if (lenLORAG > 0) releaseLoRa(0);
|
||||
}
|
||||
#endif
|
||||
#ifdef LORA1_DELAY
|
||||
if (millis() > timeLORA1) {
|
||||
timeLORA1 += LORA1_DELAY;
|
||||
if (lenLORA1 > 0) releaseLoRa(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef LORA2_DELAY
|
||||
if (millis() > timeLORA2) {
|
||||
timeLORA2 += LORA2_DELAY;
|
||||
if (lenLORA2 > 0) releaseLoRa(2);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (UART_IF.available()) {
|
||||
getSerial();
|
||||
}
|
||||
getLoRa();
|
||||
#ifdef USE_WIFI
|
||||
if (!client.connected()) {
|
||||
DBG("Connecting MQTT...");
|
||||
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 General
|
||||
LORAG_ACT
|
||||
break;
|
||||
case 7: //LoRa #1
|
||||
LORA1_ACT
|
||||
break;
|
||||
case 8: //LoRa #2
|
||||
LORA2_ACT
|
||||
break;
|
||||
}
|
||||
newData = 0;
|
||||
}
|
||||
}
|
@ -45,10 +45,10 @@ Buffers can hold a maximum of 256 DataReadings.
|
||||
|
||||
|
||||
|
||||
![Basic](/FDRS_Gateway2000/Basic_Setup.png)
|
||||
![Basic](/FDRS_Gateway/Basic_Setup.png)
|
||||
|
||||
![Advanced](/FDRS_Gateway2000/Advanced_Setup.png)
|
||||
![Advanced](/FDRS_Gateway/Advanced_Setup.png)
|
||||
|
||||
![Basic LoRa](/FDRS_Gateway2000/Basic_LoRa_Setup.png)
|
||||
![Basic LoRa](/FDRS_Gateway/Basic_LoRa_Setup.png)
|
||||
|
||||
![Advanced LoRa](/FDRS_Gateway2000/Advanced_Setup_LoRa.png)
|
||||
![Advanced LoRa](/FDRS_Gateway/Advanced_Setup_LoRa.png)
|
@ -1,73 +1,80 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// GATEWAY 2.000 Configuration
|
||||
|
||||
//#include <fdrs_globals.h> //Uncomment if you install the globals file
|
||||
#define DEBUG //Enable USB-Serial debugging
|
||||
|
||||
#define UNIT_MAC 0x01 // The address of this gateway
|
||||
|
||||
//Actions -- Define what happens when a packet arrives at each interface:
|
||||
// Current function options are: sendESPNOW(MAC), sendSerial(), sendMQTT(),
|
||||
// bufferLoRa(interface), bufferESPNOW(interface), bufferSerial(), and bufferMQTT().
|
||||
|
||||
#define ESPNOWG_ACT sendSerial();
|
||||
#define SERIAL_ACT
|
||||
#define MQTT_ACT
|
||||
#define LORAG_ACT sendSerial();
|
||||
|
||||
//#define USE_LORA
|
||||
//#define USE_WIFI //Used only for MQTT gateway
|
||||
|
||||
// Peer addresses
|
||||
#define ESPNOW1_PEER 0x0E // ESPNOW1 Address
|
||||
#define ESPNOW2_PEER 0x0F // ESPNOW2 Address
|
||||
#define LORA1_PEER 0x0E // LoRa1 Address
|
||||
#define LORA2_PEER 0x0F // LoRa2 Address
|
||||
|
||||
// Peer Actions
|
||||
#define ESPNOW1_ACT
|
||||
#define ESPNOW2_ACT
|
||||
#define LORA1_ACT
|
||||
#define LORA2_ACT
|
||||
|
||||
//Pins for UART data interface (ESP32 only)
|
||||
#define RXD2 14
|
||||
#define TXD2 15
|
||||
|
||||
//LoRa Configuration -- Needed only if using 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 SF 7
|
||||
|
||||
// Buffer Delays - in milliseconds - Uncomment to enable any buffer
|
||||
|
||||
//#define ESPNOW1_DELAY 0
|
||||
//#define ESPNOW2_DELAY 0
|
||||
//#define ESPNOWG_DELAY 0
|
||||
//#define SERIAL_DELAY 0
|
||||
//#define MQTT_DELAY 0
|
||||
//#define LORAG_DELAY 1000
|
||||
//#define LORA1_DELAY 1000
|
||||
//#define LORA2_DELAY 1000
|
||||
|
||||
//#define USE_LED //Not yet fully implemented
|
||||
#define LED_PIN 32
|
||||
#define NUM_LEDS 4
|
||||
|
||||
//WiFi and MQTT Credentials -- Needed only for MQTT gateway
|
||||
#define WIFI_SSID "Your SSID"
|
||||
#define WIFI_PASS "Your Password"
|
||||
#define MQTT_ADDR "192.168.0.8"
|
||||
// MQTT Topics
|
||||
#define TOPIC_DATA "fdrs/data"
|
||||
#define TOPIC_STATUS "fdrs/status"
|
||||
#define TOPIC_COMMAND "fdrs/command"
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// GATEWAY 2.000 Configuration
|
||||
|
||||
//#include <fdrs_globals.h> //Uncomment if you install the globals file
|
||||
#define DEBUG //Enable USB-Serial debugging
|
||||
|
||||
#define UNIT_MAC 0x01 // The address of this gateway
|
||||
|
||||
//Actions -- Define what happens when a packet arrives at each interface:
|
||||
// Current function options are: sendESPNOW(MAC), sendSerial(), sendMQTT(),
|
||||
// bufferLoRa(interface), bufferESPNOW(interface), bufferSerial(), and bufferMQTT().
|
||||
|
||||
#define ESPNOWG_ACT sendSerial();
|
||||
#define SERIAL_ACT
|
||||
#define MQTT_ACT
|
||||
#define LORAG_ACT sendSerial();
|
||||
|
||||
//#define USE_LORA
|
||||
//#define USE_WIFI //Used only for MQTT gateway
|
||||
|
||||
// Peer addresses
|
||||
#define ESPNOW1_PEER 0x0E // ESPNOW1 Address
|
||||
#define ESPNOW2_PEER 0x0F // ESPNOW2 Address
|
||||
#define LORA1_PEER 0x0E // LoRa1 Address
|
||||
#define LORA2_PEER 0x0F // LoRa2 Address
|
||||
|
||||
// Peer Actions
|
||||
#define ESPNOW1_ACT
|
||||
#define ESPNOW2_ACT
|
||||
#define LORA1_ACT
|
||||
#define LORA2_ACT
|
||||
|
||||
//Pins for UART data interface (ESP32 only)
|
||||
#define RXD2 14
|
||||
#define TXD2 15
|
||||
|
||||
//LoRa Configuration -- Needed only if using 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 SF 7
|
||||
|
||||
// Buffer Delays - in milliseconds - Uncomment to enable any buffer
|
||||
|
||||
//#define ESPNOW1_DELAY 0
|
||||
//#define ESPNOW2_DELAY 0
|
||||
//#define ESPNOWG_DELAY 0
|
||||
//#define SERIAL_DELAY 0
|
||||
//#define MQTT_DELAY 0
|
||||
//#define LORAG_DELAY 1000
|
||||
//#define LORA1_DELAY 1000
|
||||
//#define LORA2_DELAY 1000
|
||||
|
||||
//#define USE_LED //Not yet fully implemented
|
||||
#define LED_PIN 32
|
||||
#define NUM_LEDS 4
|
||||
|
||||
//WiFi and MQTT Credentials -- Needed only for MQTT gateway
|
||||
#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
|
||||
|
||||
//MQTT Credentials -- Needed only if MQTT broker requires authentication
|
||||
//#define MQTT_AUTH //uncomment to enable MQTT authentication
|
||||
#define MQTT_USER "Your MQTT Username"
|
||||
#define MQTT_PASS "Your MQTT Password"
|
||||
|
||||
// MQTT Topics
|
||||
#define TOPIC_DATA "fdrs/data"
|
||||
#define TOPIC_STATUS "fdrs/status"
|
||||
#define TOPIC_COMMAND "fdrs/command"
|
@ -1,3 +1,3 @@
|
||||
Please copy this directory into your Arduino "libraries" directory.
|
||||
Edit the files in your libraries folder according to your needs with your WiFi info, LoRa band, etc.
|
||||
Edit 'fdrs_globals.h' in your libraries folder according to your needs with your WiFi info, LoRa band, etc.
|
||||
Never edit them here!!!
|
@ -2,6 +2,10 @@
|
||||
#define GLOBAL_PASS "Password"
|
||||
#define GLOBAL_MQTT_ADDR "192.168.0.8"
|
||||
|
||||
//#define GLOBAL_MQTT_AUTH //uncomment to enable MQTT authentication
|
||||
#define GLOBAL_MQTT_USER "Your MQTT Username"
|
||||
#define GLOBAL_MQTT_PASS "Your MQTT Password"
|
||||
|
||||
#define GLOBAL_BAND 915E6 //LoRa Frequency Band
|
||||
#define GLOBAL_SF 7 //LoRa Spreading Factor
|
||||
|
||||
|
@ -1,33 +1,33 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// Basic Sensor Example
|
||||
//
|
||||
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
// An example of how to send data using "fdrs_sensor.h".
|
||||
//
|
||||
|
||||
|
||||
#include "fdrs_sensor.h"
|
||||
|
||||
float data1;
|
||||
float data2;
|
||||
|
||||
void setup() {
|
||||
beginFDRS();
|
||||
}
|
||||
void loop() {
|
||||
data1 = readHum();
|
||||
loadFDRS(data1, HUMIDITY_T);
|
||||
data2 = readTemp();
|
||||
loadFDRS(data2, TEMP_T);
|
||||
sendFDRS();
|
||||
sleepFDRS(10); //Sleep time in seconds
|
||||
}
|
||||
|
||||
float readTemp() {
|
||||
return 42.069;
|
||||
}
|
||||
|
||||
float readHum() {
|
||||
return 21.0345;
|
||||
}
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// Basic Sensor Example
|
||||
//
|
||||
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
// An example of how to send data using "fdrs_sensor.h".
|
||||
//
|
||||
|
||||
|
||||
#include "fdrs_sensor.h"
|
||||
|
||||
float data1;
|
||||
float data2;
|
||||
|
||||
void setup() {
|
||||
beginFDRS();
|
||||
}
|
||||
void loop() {
|
||||
data1 = readHum();
|
||||
loadFDRS(data1, HUMIDITY_T);
|
||||
data2 = readTemp();
|
||||
loadFDRS(data2, TEMP_T);
|
||||
sendFDRS();
|
||||
sleepFDRS(10); //Sleep time in seconds
|
||||
}
|
||||
|
||||
float readTemp() {
|
||||
return 42.069;
|
||||
}
|
||||
|
||||
float readHum() {
|
||||
return 21.0345;
|
||||
}
|
@ -116,7 +116,7 @@ void beginFDRS() {
|
||||
DBG("Initializing LoRa!");
|
||||
DBG(BAND);
|
||||
DBG(SF);
|
||||
#ifndef __AVR__
|
||||
#ifdef ESP32
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
#endif
|
||||
LoRa.setPins(SS, RST, DIO0);
|
@ -1,178 +0,0 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// "fdrs_sensor.h"
|
||||
//
|
||||
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
//
|
||||
#include "sensor_setup.h"
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
|
||||
#ifdef GLOBALS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) (Serial.println(a))
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
#define STATUS_T 0 // Status
|
||||
#define TEMP_T 1 // Temperature
|
||||
#define TEMP2_T 2 // Temperature #2
|
||||
#define HUMIDITY_T 3 // Relative Humidity
|
||||
#define PRESSURE_T 4 // Atmospheric Pressure
|
||||
#define LIGHT_T 5 // Light (lux)
|
||||
#define SOIL_T 6 // Soil Moisture
|
||||
#define SOIL2_T 7 // Soil Moisture #2
|
||||
#define SOILR_T 8 // Soil Resistance
|
||||
#define SOILR2_T 9 // Soil Resistance #2
|
||||
#define OXYGEN_T 10 // Oxygen
|
||||
#define CO2_T 11 // Carbon Dioxide
|
||||
#define WINDSPD_T 12 // Wind Speed
|
||||
#define WINDHDG_T 13 // Wind Direction
|
||||
#define RAINFALL_T 14 // Rainfall
|
||||
#define MOTION_T 15 // Motion
|
||||
#define VOLTAGE_T 16 // Voltage
|
||||
#define VOLTAGE2_T 17 // Voltage #2
|
||||
#define CURRENT_T 18 // Current
|
||||
#define CURRENT2_T 19 // Current #2
|
||||
#define IT_T 20 // Iterations
|
||||
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
||||
|
||||
const uint16_t espnow_size = 250 / sizeof(DataReading);
|
||||
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
|
||||
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
|
||||
uint8_t LoRaAddress[] = {0x42, 0x00};
|
||||
|
||||
uint32_t wait_time = 0;
|
||||
DataReading fdrsData[espnow_size];
|
||||
uint8_t data_count = 0;
|
||||
|
||||
void beginFDRS() {
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
|
||||
DBG(" Gateway: " + String (GTWY_MAC, HEX));
|
||||
#ifdef POWER_CTRL
|
||||
DBG("Powering up the sensor array!");
|
||||
pinMode(POWER_CTRL, OUTPUT);
|
||||
digitalWrite(POWER_CTRL, 1);
|
||||
#endif
|
||||
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
|
||||
#ifdef USE_ESPNOW
|
||||
DBG("Initializing ESP-NOW!");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#if defined(ESP8266)
|
||||
if (esp_now_init() != 0) {
|
||||
return;
|
||||
}
|
||||
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||
// Register peers
|
||||
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
#elif defined(ESP32)
|
||||
if (esp_now_init() != ESP_OK) {
|
||||
DBG("Error initializing ESP-NOW");
|
||||
return;
|
||||
}
|
||||
esp_now_peer_info_t peerInfo;
|
||||
peerInfo.ifidx = WIFI_IF_STA;
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
// Register first peer
|
||||
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG(" ESP-NOW Initialized.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
DBG("Initializing LoRa!");
|
||||
DBG(BAND);
|
||||
DBG(SF);
|
||||
#ifndef __AVR__
|
||||
SPI.begin(SCK, MISO, MOSI, SS);
|
||||
#endif
|
||||
LoRa.setPins(SS, RST, DIO0);
|
||||
if (!LoRa.begin(FDRS_BAND)) {
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(FDRS_SF);
|
||||
DBG(" LoRa Initialized.");
|
||||
#endif
|
||||
}
|
||||
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
|
||||
#ifdef USE_LORA
|
||||
uint8_t pkt[5 + (len * sizeof(DataReading))];
|
||||
memcpy(&pkt, mac, 3); //
|
||||
memcpy(&pkt[3], &LoRaAddress, 2);
|
||||
memcpy(&pkt[5], packet, len * sizeof(DataReading));
|
||||
LoRa.beginPacket();
|
||||
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
|
||||
LoRa.endPacket();
|
||||
#endif
|
||||
}
|
||||
void sendFDRS() {
|
||||
DBG("Sending FDRS Packet!");
|
||||
#ifdef USE_ESPNOW
|
||||
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
|
||||
delay(5);
|
||||
DBG(" ESP-NOW sent.");
|
||||
#endif
|
||||
#ifdef USE_LORA
|
||||
transmitLoRa(gtwyAddress, fdrsData, data_count);
|
||||
DBG(" LoRa sent.");
|
||||
#endif
|
||||
data_count = 0;
|
||||
}
|
||||
void loadFDRS(float d, uint8_t t) {
|
||||
DBG("Data loaded. Type: " + String(t));
|
||||
if (data_count > espnow_size) sendFDRS();
|
||||
DataReading dr;
|
||||
dr.id = READING_ID;
|
||||
dr.t = t;
|
||||
dr.d = d;
|
||||
fdrsData[data_count] = dr;
|
||||
data_count++;
|
||||
}
|
||||
void sleepFDRS(int sleep_time) {
|
||||
DBG("Sleepytime!");
|
||||
#ifdef DEEP_SLEEP
|
||||
DBG(" Deep sleeping.");
|
||||
#ifdef ESP32
|
||||
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
ESP.deepSleep(sleep_time * 1000000);
|
||||
#endif
|
||||
#endif
|
||||
DBG(" Delaying.");
|
||||
delay(sleep_time * 1000);
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
|
||||
typedef struct DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
@ -1,135 +0,0 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// GATEWAY MODULE
|
||||
//
|
||||
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
// Setup instructions located in the "fdrs_config.h" file.
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#define RXD2 21
|
||||
#define TXD2 22
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#include "fdrs_config.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include "DataReading.h"
|
||||
|
||||
uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t prevAddress[] = {MAC_PREFIX, PREV_MAC};
|
||||
uint8_t selfAddress[] = {MAC_PREFIX, UNIT_MAC};
|
||||
DataReading incData[31];
|
||||
bool newData = false;
|
||||
int pkt_readings;
|
||||
uint8_t incMAC[6];
|
||||
|
||||
#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(&incData, incomingData, len);
|
||||
memcpy(&incMAC, mac, 6);
|
||||
pkt_readings = len / sizeof(DataReading);
|
||||
newData = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
|
||||
#if defined(ESP8266)
|
||||
Serial.begin(115200);
|
||||
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 peer
|
||||
esp_now_add_peer(prevAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
esp_now_add_peer(broadcast_mac, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
|
||||
#elif defined(ESP32)
|
||||
Serial.begin(115200, SERIAL_8N1, RXD2, TXD2);
|
||||
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;
|
||||
memcpy(peerInfo.peer_addr, prevAddress, 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
|
||||
}
|
||||
|
||||
//CMD example {"id":72,"type":201,"data":166}
|
||||
|
||||
void getSerial() {
|
||||
DataReading theCommands[31];
|
||||
String incomingString = Serial.readStringUntil('\n');
|
||||
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++) {
|
||||
if (i > 31) break;
|
||||
theCommands[i].id = doc[i]["id"];
|
||||
theCommands[i].t = doc[i]["type"];
|
||||
theCommands[i].d = doc[i]["data"];
|
||||
}
|
||||
esp_now_send(broadcast_mac, (uint8_t *) &theCommands, s * sizeof(DataReading));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void encodeJSON() {
|
||||
StaticJsonDocument<2048> doc;
|
||||
for (int i = 0; i < pkt_readings; i++) {
|
||||
doc[i]["id"] = incData[i].id;
|
||||
doc[i]["type"] = incData[i].t;
|
||||
doc[i]["data"] = incData[i].d;
|
||||
incData[i].id = 0;
|
||||
incData[i].t = 0;
|
||||
incData[i].d = 0;
|
||||
}
|
||||
serializeJson(doc, Serial);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (Serial.available()) {
|
||||
getSerial();
|
||||
}
|
||||
if (newData) {
|
||||
newData = false;
|
||||
encodeJSON();
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
// To configure your FDRS Gateway:
|
||||
|
||||
// Each device in the system has a unique, one-byte address which
|
||||
// is assigned to the last digit of its MAC address at startup.
|
||||
|
||||
// Each device is configured to know what the previous and/or next
|
||||
// device in the line of communication is.
|
||||
|
||||
// The gateway should usually be assigned the address 0x00.
|
||||
// The PREV_MAC is currently not used, as the gateway responds
|
||||
// to all packets in the same manner.
|
||||
|
||||
|
||||
|
||||
// THIS UNIT
|
||||
#define UNIT_MAC 0x00
|
||||
#define PREV_MAC 0x01
|
||||
|
||||
//MAC prefix:
|
||||
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE
|
@ -1,141 +0,0 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// RELAY MODULE
|
||||
//
|
||||
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
// Setup instructions located in the "fdrs_config.h" file.
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#include "fdrs_config.h"
|
||||
|
||||
uint8_t prevAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, PREV_MAC};
|
||||
uint8_t selfAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, UNIT_MAC};
|
||||
uint8_t nextAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, NEXT_MAC};
|
||||
uint8_t outMAC[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, DEFT_MAC};
|
||||
uint8_t incMAC[6];
|
||||
|
||||
uint8_t theData[250];
|
||||
uint8_t ln;
|
||||
bool newData = false;
|
||||
bool isLocal = false;
|
||||
void passOn() {
|
||||
switch (incMAC[5]) {
|
||||
case PREV_MAC:
|
||||
outMAC[5] = NEXT_MAC;
|
||||
break;
|
||||
case NEXT_MAC:
|
||||
outMAC[5] = PREV_MAC;
|
||||
break;
|
||||
default:
|
||||
outMAC[5] = DEFT_MAC;
|
||||
break;
|
||||
}
|
||||
if (!isLocal) outMAC[5] = DEFT_MAC;
|
||||
Serial.print("Packet Received from device: ");
|
||||
Serial.println(incMAC[5]);
|
||||
Serial.print("and sending to: ");
|
||||
Serial.println(outMAC[5]);
|
||||
esp_now_send(outMAC, (uint8_t *) &theData, ln);
|
||||
}
|
||||
|
||||
// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32
|
||||
#if defined(ESP8266)
|
||||
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
|
||||
Serial.print("Last Packet Send Status: ");
|
||||
if (sendStatus == 0) {
|
||||
Serial.println("Delivery success");
|
||||
}
|
||||
else {
|
||||
|
||||
Serial.println("Delivery fail");
|
||||
}
|
||||
}
|
||||
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) {
|
||||
Serial.print("Last Packet Send Status:");
|
||||
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
|
||||
}
|
||||
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, &selfAddress, 5) != 0) {
|
||||
isLocal = false;
|
||||
} else {
|
||||
isLocal = true;
|
||||
}
|
||||
Serial.print("Data received: ");
|
||||
Serial.println(len);
|
||||
ln = len;
|
||||
newData = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Init Serial Monitor
|
||||
Serial.begin(115200);
|
||||
// Init WiFi
|
||||
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(prevAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
esp_now_add_peer(nextAddress, 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, prevAddress, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
Serial.println("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
// Register second peer
|
||||
memcpy(peerInfo.peer_addr, nextAddress, 6);
|
||||
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
Serial.println("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Serial.println();
|
||||
Serial.println("FARM DATA RELAY SYSTEM :: Relay Module");
|
||||
Serial.println("MAC:" + WiFi.macAddress());
|
||||
Serial.print("Previous device: ");
|
||||
Serial.println(PREV_MAC);
|
||||
Serial.print("Next device: ");
|
||||
Serial.println(NEXT_MAC);
|
||||
Serial.print("Default device: ");
|
||||
Serial.println(DEFT_MAC);
|
||||
Serial.println(" ");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (newData) {
|
||||
newData = false;
|
||||
passOn();
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
// To configure FDRS:
|
||||
|
||||
// Each device in the system has a unique, one-byte address which
|
||||
// is assigned to the last digit of its MAC address at startup.
|
||||
|
||||
// Each relay receives data from its pre-programmed "PREV_MAC" device and
|
||||
// sends the packet verbatim to the address corresponding to "NEXT_MAC".
|
||||
|
||||
// The gateway receives the data and outputs it as a json string over the serial port.
|
||||
|
||||
|
||||
// THIS UNIT
|
||||
#define UNIT_MAC 0x01
|
||||
|
||||
// NEXT UNIT
|
||||
#define NEXT_MAC 0x00
|
||||
|
||||
// PREVIOUS UNIT
|
||||
#define PREV_MAC 0x02
|
||||
|
||||
//Packets from unknown MACs are sent here.
|
||||
#define DEFT_MAC NEXT_MAC
|
@ -1,7 +0,0 @@
|
||||
|
||||
typedef struct DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
@ -1,151 +0,0 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// TERMINAL MODULE
|
||||
//
|
||||
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
// Setup instructions located in the "fdrs_config.h" file.
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#include "fdrs_config.h"
|
||||
#include "DataReading.h"
|
||||
|
||||
|
||||
uint8_t selfAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, UNIT_MAC};
|
||||
uint8_t nextAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, NEXT_MAC};
|
||||
uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
DataReading incData[31];
|
||||
DataReading theData[31];
|
||||
DataReading theCommands[31];
|
||||
bool newCMD = false;
|
||||
int wait_time = 0;
|
||||
int tot_readings = 0;
|
||||
int tot_commands = 0;
|
||||
|
||||
|
||||
#if defined(ESP8266)
|
||||
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
|
||||
Serial.print("Last Packet Send Status: ");
|
||||
if (sendStatus == 0) {
|
||||
Serial.println("Delivery success");
|
||||
}
|
||||
else {
|
||||
Serial.println("Delivery fail");
|
||||
}
|
||||
}
|
||||
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) {
|
||||
Serial.print("Last Packet Send Status:");
|
||||
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
|
||||
}
|
||||
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
|
||||
#endif
|
||||
uint8_t incMAC[6];
|
||||
memcpy(&incData, incomingData, len);
|
||||
memcpy(&mac, incMAC, 6);
|
||||
//if (memcmp(&incMAC, &nextAddress, 6) == 0)
|
||||
int pkt_readings = len / sizeof(DataReading);
|
||||
Serial.println(":Packet:");
|
||||
for (byte i = 0; i < pkt_readings; i++) {
|
||||
Serial.println("SENSOR ID: " + String(incData[i].id) + " TYPE " + String(incData[i].t) + " DATA " + String(incData[i].d));
|
||||
|
||||
if (incData[i].t < 200) {
|
||||
|
||||
if (tot_readings >= 250 / sizeof(DataReading)) {
|
||||
Serial.println("ERROR::Too many sensor readings sent within delay period.");
|
||||
break;
|
||||
}
|
||||
theData[tot_readings] = incData[i]; //Save the current incoming reading to the next open packet slot
|
||||
++tot_readings;
|
||||
} else {
|
||||
theCommands[tot_commands] = incData[i]; //Save the current incoming reading to the next open packet slot
|
||||
++tot_commands;
|
||||
newCMD = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Init Serial
|
||||
Serial.begin(115200);
|
||||
// Init WiFi
|
||||
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 peer
|
||||
esp_now_add_peer(nextAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
esp_now_add_peer(broadcast_mac, 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 peer
|
||||
memcpy(peerInfo.peer_addr, nextAddress, 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
|
||||
Serial.println();
|
||||
Serial.println("FARM DATA RELAY SYSTEM :: Terminal Module");
|
||||
Serial.println("MAC:" + WiFi.macAddress());
|
||||
Serial.print("Next device: ");
|
||||
Serial.println(NEXT_MAC);
|
||||
// Serial.println(250 / sizeof(DataReading), DEC);
|
||||
// Serial.println(sizeof(DataReading), DEC);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (newCMD) sendCmd();
|
||||
if (millis() > wait_time) {
|
||||
wait_time = wait_time + DELAY;
|
||||
if (tot_readings != 0) passForward();
|
||||
}
|
||||
}
|
||||
|
||||
void passForward() {
|
||||
Serial.println("Passing Forward");
|
||||
esp_now_send(nextAddress, (uint8_t *) &theData, sizeof(DataReading)*tot_readings);
|
||||
tot_readings = 0;
|
||||
for (int i = 0; i < 250 / sizeof(DataReading); i++) {
|
||||
theData[i].d = 0;
|
||||
theData[i].id = 0;
|
||||
theData[i].t = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void sendCmd() {
|
||||
newCMD = false;
|
||||
esp_now_send(broadcast_mac, (uint8_t *) &theCommands, tot_commands* sizeof(DataReading));
|
||||
tot_commands = 0;
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// To configure FDRS:
|
||||
|
||||
// Uncomment the code corresponding to the unit you are configuring,
|
||||
// then uncomment the code corresponding to the unit you would like
|
||||
// to be previous and/or next in the line of communication.
|
||||
|
||||
// Each device in the system has a unique, one-byte address which
|
||||
// is assigned to the last digit of its MAC address at startup.
|
||||
|
||||
// Each device is configured to know what the previous and/or next
|
||||
// device in the line of communication is.
|
||||
|
||||
// The terminal is considered the "first" device, which can be addressed
|
||||
// to a relay or the gateway.
|
||||
|
||||
// Each relay receives data from its pre-programmed "PREV_MAC" device and
|
||||
// sends the packet verbatim to the address corresponding to "NEXT_MAC".
|
||||
|
||||
// The gateway receives the data and outputs it as a json string over the serial port.
|
||||
|
||||
#define DELAY 15000
|
||||
|
||||
// THIS UNIT
|
||||
#define UNIT_MAC 0x01
|
||||
|
||||
// NEXT UNIT
|
||||
#define NEXT_MAC 0x00
|
@ -1,7 +0,0 @@
|
||||
|
||||
typedef struct DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
|
||||
} DataReading;
|
@ -1,151 +0,0 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// BLYNK FRONT-END MODULE
|
||||
// Uses JSON data from the serial port to set Blynk variables.
|
||||
//
|
||||
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
// This code was written for the now-outdated version of Blynk, and is mostly here for reference.
|
||||
//
|
||||
|
||||
#define STASSID "" //Your SSID
|
||||
#define STAPSK "" //Your Password
|
||||
#define BLKAUTH "" //Your Blynk auth code
|
||||
|
||||
#define DELAY 30000
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <BlynkSimpleEsp8266.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#elif defined(ESP32)
|
||||
#include <BlynkSimpleEsp32.h>
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
#include <ArduinoJson.h>
|
||||
#include "DataReading.h"
|
||||
|
||||
BlynkTimer timer;
|
||||
WidgetTerminal terminal(V69);
|
||||
|
||||
DataReading allData[256];
|
||||
int wait_time = DELAY;
|
||||
char auth[] = BLKAUTH;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
bool is_new[255];
|
||||
int new_readings;
|
||||
bool term_flag;
|
||||
String the_command;
|
||||
|
||||
BLYNK_WRITE(V69)
|
||||
{
|
||||
Serial.println("blynkwrite");
|
||||
the_command = param.asStr();
|
||||
term_flag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.mode(WIFI_STA);
|
||||
Serial.println();
|
||||
Serial.println("FDRS Blynk Module");
|
||||
Serial.println("Connect to WiFi please?");
|
||||
Blynk.begin(auth, ssid, password);
|
||||
// Blynk.config(auth);
|
||||
// Blynk.connectWiFi(ssid, password);
|
||||
Serial.println("Thanks!");
|
||||
//terminal.clear();
|
||||
timer.setInterval(30000L, updateBlynk);
|
||||
Blynk.run();
|
||||
terminal.println("Hello, world!");
|
||||
terminal.flush();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
while (Serial.available()) {
|
||||
Serial.println("waiting for tilda");
|
||||
if (Serial.read() == '~') { //Waits for '~', then parses following data
|
||||
getSerial();
|
||||
Serial.println("getSerial done");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (millis() > wait_time) {
|
||||
// wait_time = wait_time + DELAY;
|
||||
// if (Blynk.connected()) {
|
||||
// updateBlynk();
|
||||
// Serial.println("blynk updated");
|
||||
// }
|
||||
// }
|
||||
if (term_flag) {
|
||||
parseBlynkTerm(the_command);
|
||||
term_flag = false;
|
||||
}
|
||||
Blynk.run();
|
||||
timer.run();
|
||||
}
|
||||
|
||||
void getSerial() {
|
||||
String incomingString = Serial.readString();
|
||||
StaticJsonDocument<3072> doc;
|
||||
Serial.println("Received: " + incomingString);
|
||||
DeserializationError error = deserializeJson(doc, incomingString);
|
||||
if (error) { // Test if parsing succeeds.
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return;
|
||||
} else {
|
||||
for (int i = 0; i < doc.size(); i++) {
|
||||
Serial.println(doc.size());
|
||||
DataReading newData;
|
||||
newData.id = doc[i]["id"];
|
||||
newData.t = doc[i]["type"];
|
||||
newData.d = doc[i]["data"];
|
||||
allData[newData.id] = newData;
|
||||
is_new[newData.id] = true;
|
||||
Serial.println("SENSOR ID: " + String(newData.id) + " TYPE " + String(newData.t) + " DATA " + String(newData.d));
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateBlynk() {
|
||||
Serial.println("Updateblynk");
|
||||
for (int i = 0; i < 127; i++) {
|
||||
if (is_new[i] == true) {
|
||||
Serial.println("abt to write");
|
||||
Blynk.virtualWrite(i, allData[i].d);
|
||||
is_new[i] = false;
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
void parseBlynkTerm(String command) {
|
||||
int ind1 = command.indexOf(" ");
|
||||
String arg1 = command.substring(0, ind1);
|
||||
if (arg1.equalsIgnoreCase(String("SET"))) {
|
||||
int ind2 = command.indexOf(" ", ind1 + 1);
|
||||
String arg2 = command.substring(ind1 + 1, ind2);
|
||||
String arg3 = command.substring(ind2 + 1, command.length());
|
||||
terminal.println("ARG1:" + arg1);
|
||||
terminal.println("ARG2:" + arg2);
|
||||
terminal.println("ARG3:" + arg3);
|
||||
terminal.flush();
|
||||
DataReading newCMD;
|
||||
newCMD.id = arg2.toInt();
|
||||
newCMD.t = 201;
|
||||
newCMD.d = arg3.toFloat();
|
||||
allData[newCMD.id] = newCMD;
|
||||
StaticJsonDocument<2048> doc;
|
||||
doc[0]["id"] = newCMD.id;
|
||||
doc[0]["type"] = newCMD.t;
|
||||
doc[0]["data"] = newCMD.d;
|
||||
Serial.write('~');
|
||||
serializeJson(doc, Serial);
|
||||
Serial.println();
|
||||
} else if (arg1.equalsIgnoreCase(String("GET"))) {
|
||||
String arg2 = command.substring(ind1 + 1, command.length());
|
||||
terminal.println("DataReading " + arg2 + " :: " + String(allData[arg2.toInt()].d));
|
||||
terminal.flush();
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
# <p align="center">Ye Olde Farm Data Relay System
|
||||
##### <p align="center">[***In loving memory of Gay Holman, an extraordinary woman.***](https://www.facebook.com/CFECI/posts/2967989419953119) #####
|
||||
|
||||
### This is the first version of my project, and is left here only for reference.
|
||||
|
||||
The Farm Data Relay System is an easy way to link remote sensors to the internet without the need for WiFi. It uses the ESP-NOW protocol on widely availabe ESP32 and ESP8266 microcontroller boards, and can be used to collect and transmit sensor data in situations where it would be too difficult or energy-consuming to provide full WiFi coverage.
|
||||
|
||||
A major consideration has been to make the system straight-forward and easy to set up, since the primary user may not be very familiar with Arduino. Using an assigned MAC address scheme allows for the whole system to be configured by setting just a handful of values in code.
|
||||
|
||||
Other than the nodes, each device in the system has a one-byte address. At boot, each device changes its MAC address to "AA:BB:CC:DD:EE:xx" where xx is the device's address identifier. Nodes can send their data to a terminal, a relay, or directly to a gateway. Each of these devices can be connected as needed in a chain that leads to a gateway, where the data is handed off to another system.
|
||||
|
||||
## Getting Started
|
||||
To get started using FDRS with Node-Red, you'll first need to flash an ESP32 or 8266 device with the FDRS_Gateway sketch. Next, connect the device via serial port to a computer running Node-Red. You can then use the serialport node connected to a JSON node, and finally a split node to get your data ready to use. You can find the basic flow examples in the 'NodeRed-Basic.json' file. If you are using a usb-serial port, keep in mind that you may have to change the selected port after plugging in your device, or de-select the port when trying to flash the device from another program.
|
||||
|
||||
As you flash each sensor, you'll need to change the UNIT_ID to a unique integer (0-65535). For some sensors, you'll also need to adjust pin assignments and install libraries.
|
||||
By default, all sensors have GTWY_MAC set to 0x00. You'll only need to change this if you are going to use a relay to extend the system's range.
|
||||
|
||||
If you need to get data from sensors that are out of reach of the gateway, place an FDRS_Relay device near the edge of the gateway's range. Flash this device with the default parameters, and then flash the sensors with GTWY_MAC set to 0x01. They will now send their data to the relay, which in turn sends it to the gateway.
|
||||
|
||||
## Sensors
|
||||
```
|
||||
typedef struct DataReading {
|
||||
float d;
|
||||
uint16_t id;
|
||||
uint8_t t;
|
||||
} DataReading;
|
||||
```
|
||||
Each sensor in the system sends its data over ESP-NOW as a float 'd' inside of a structure called a DataReading. Its global sensor address is represented by an integer 'id', and each type is represented by a single byte 't'. If sensors need to send multiple types of readings (ex: temp and humidity), then they are sent in an array of DataReadings. In this case each reading will share an id, but be differentiated by its type.
|
||||
|
||||
## Terminal
|
||||
A terminal is a device that recieves data from the nodes and aggregates it into a larger array. The larger array is then periodically sent forward through the system to the gateway. The time between sends must be short enough so as not to exceed the maximum legnth of an ESP-NOW packet with DataReadings, which is 31.
|
||||
|
||||
|
||||
## Relays
|
||||
Relays are absolute ESP-NOW repeaters. They are programmed with the address of the previous and next device, and when data is received from one, it delivers it to the other. The "DEFT_MAC" setting defines where a relay will send an incoming packet with an unknown address. This can be used to direct sensor packets either to the terminal or the gateway.
|
||||
|
||||
In the FDRS, one can place as many relays as needed to span the distance to the gateway, which is the final device in the system.
|
||||
|
||||
## Gateway
|
||||
The gateway takes the packet of DataReadings and interprets it into json format, then outputs it over the serial port. From here it can be collected by another microcontroller or a Raspberry Pi front-end to be sent to the cloud for further processing and storage.
|
||||
|
||||
|
||||
|
||||
|
12
README.md
@ -7,10 +7,10 @@ Using an assigned MAC address scheme allows for the whole system to be configure
|
||||
|
||||
## Getting Started
|
||||
|
||||
### [Sensors](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Sensor2000)
|
||||
### [Sensors](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Sensor)
|
||||
Sensors gather data and send it to a gateway via ESP-NOW or LoRa.
|
||||
|
||||
### [Gateways](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Gateway2000)
|
||||
### [Gateways](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Gateway)
|
||||
Gateways listen for packets over ESP-NOW, LoRa, UART, and/or MQTT, then re-transmit the packets using one or more of the same interfaces.
|
||||
|
||||
### Front-end
|
||||
@ -19,7 +19,9 @@ The Node-RED front-end can be set up with these nodes to format and send the dat
|
||||
[{"id":"66d36c0f.cedf94","type":"influxdb out","z":"d7346a99.716ef8","influxdb":"905dd357.34717","name":"","measurement":"DataReading","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"the_organization","bucket":"bkt","x":760,"y":240,"wires":[]},{"id":"93e9822a.3ad59","type":"mqtt in","z":"d7346a99.716ef8","name":"","topic":"esp/fdrs","qos":"2","datatype":"auto","broker":"c513f7e9.760658","nl":false,"rap":true,"rh":0,"x":170,"y":220,"wires":[["d377f9e0.faef98"]]},{"id":"d377f9e0.faef98","type":"json","z":"d7346a99.716ef8","name":"","property":"payload","action":"obj","pretty":false,"x":290,"y":220,"wires":[["ca383562.4014e8"]]},{"id":"ca383562.4014e8","type":"split","z":"d7346a99.716ef8","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":410,"y":220,"wires":[["6eaba8dd.429e38"]]},{"id":"6eaba8dd.429e38","type":"function","z":"d7346a99.716ef8","name":"Fields","func":"msg.payload = [{\n data: msg.payload.data\n},{\n id: msg.payload.id,\n type: msg.payload.type\n}]\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":220,"wires":[["296d0f4b.37a46","66d36c0f.cedf94"]]},{"id":"296d0f4b.37a46","type":"debug","z":"d7346a99.716ef8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":200,"wires":[]},{"id":"905dd357.34717","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"","usetls":false,"tls":"d50d0c9f.31e858","influxdbVersion":"2.0","url":"http://localhost:8086","rejectUnauthorized":true},{"id":"c513f7e9.760658","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"d50d0c9f.31e858","type":"tls-config","name":"","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","servername":"","verifyservercert":false}]
|
||||
```
|
||||
|
||||
|
||||
## Dependencies
|
||||
[LoRa library](https://github.com/sandeepmistry/arduino-LoRa)
|
||||
[ArduinoJson](https://arduinojson.org/)
|
||||
|
||||
## Future Plans
|
||||
A few things that I intend to add are:
|
||||
@ -41,5 +43,5 @@ Development of this project would not have been possible without the support of
|
||||
|
||||
|
||||
|
||||
![Basic](/FDRS_Gateway2000/Basic_Setup.png)
|
||||
![Advanced](/FDRS_Gateway2000/Advanced_Setup.png)
|
||||
![Basic](/FDRS_Gateway/Basic_Setup.png)
|
||||
![Advanced](/FDRS_Gateway/Advanced_Setup.png)
|
||||
|
37
Universal_Sensor_beta/Universal_Sensor_beta.ino
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// Basic Sensor Example
|
||||
//
|
||||
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
// An example of how to send data using "fdrs_sensor.h".
|
||||
//
|
||||
|
||||
|
||||
#include "fdrs_sensor.h"
|
||||
#include "sensor_setup.h"
|
||||
|
||||
FDRSLoRa FDRS(GTWY_MAC,READING_ID,MISO,MOSI,SCK,SS,RST,DIO0,BAND,SF);
|
||||
|
||||
float data1;
|
||||
float data2;
|
||||
|
||||
void setup() {
|
||||
FDRS.begin();
|
||||
}
|
||||
void loop() {
|
||||
data1 = readHum();
|
||||
FDRS.load(data1, HUMIDITY_T);
|
||||
data2 = readTemp();
|
||||
FDRS.load(data2, TEMP_T);
|
||||
FDRS.send();
|
||||
FDRS.sleep(10); //Sleep time in seconds
|
||||
}
|
||||
|
||||
float readTemp() {
|
||||
return 42.069;
|
||||
}
|
||||
|
||||
float readHum() {
|
||||
return 21.0345;
|
||||
}
|
181
Universal_Sensor_beta/fdrs_sensor.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
#include "fdrs_sensor.h"
|
||||
|
||||
|
||||
const uint8_t prefix[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE}; // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
uint8_t LoRaAddress[] = {0x42, 0x00};
|
||||
|
||||
uint32_t wait_time = 0;
|
||||
|
||||
|
||||
FDRSBase::FDRSBase(uint8_t gtwy_mac,uint8_t reading_id):
|
||||
_gtwy_mac(gtwy_mac),
|
||||
_espnow_size(250 / sizeof(DataReading_t)),
|
||||
_reading_id(reading_id),
|
||||
_data_count(0)
|
||||
{
|
||||
fdrsData = new DataReading_t[_espnow_size];
|
||||
}
|
||||
|
||||
FDRSBase::~FDRSBase(){
|
||||
delete[] fdrsData;
|
||||
}
|
||||
|
||||
void FDRSBase::begin() {
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
DBG("FDRS Sensor ID " + String(_reading_id) + " initializing...");
|
||||
DBG(" Gateway: " + String (_gtwy_mac, HEX));
|
||||
#ifdef POWER_CTRL
|
||||
DBG("Powering up the sensor array!");
|
||||
pinMode(POWER_CTRL, OUTPUT);
|
||||
digitalWrite(POWER_CTRL, 1);
|
||||
#endif
|
||||
|
||||
init();
|
||||
|
||||
}
|
||||
|
||||
void FDRSBase::send(void) {
|
||||
DBG("Sending FDRS Packet!");
|
||||
|
||||
if(_data_count == 0){
|
||||
return;
|
||||
}
|
||||
transmit(fdrsData,_data_count);
|
||||
_data_count = 0;
|
||||
}
|
||||
|
||||
void FDRSBase::load(float data, uint8_t type) {
|
||||
DBG("Data loaded. Type: " + String(type));
|
||||
if (_data_count > _espnow_size){
|
||||
send();
|
||||
}
|
||||
DataReading_t dr;
|
||||
dr.id = _reading_id;
|
||||
dr.type = type;
|
||||
dr.data = data;
|
||||
fdrsData[_data_count] = dr;
|
||||
_data_count++;
|
||||
}
|
||||
|
||||
void FDRSBase::sleep(int seconds){
|
||||
DBG("Sleepytime!");
|
||||
#ifdef DEEP_SLEEP
|
||||
DBG(" Deep sleeping.");
|
||||
#ifdef ESP32
|
||||
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
ESP.deepSleep(sleep_time * 1000000);
|
||||
#endif
|
||||
#endif
|
||||
DBG(" Delaying.");
|
||||
delay(seconds * 1000);
|
||||
}
|
||||
|
||||
|
||||
FDRS_EspNow::FDRS_EspNow(uint8_t gtwy_mac,uint8_t reading_id):
|
||||
FDRSBase(gtwy_mac,reading_id)
|
||||
{
|
||||
|
||||
memcpy(_gatewayAddress,MAC_PREFIX,5);
|
||||
_gatewayAddress[5] = gtwy_mac;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FDRS_EspNow::init(void){
|
||||
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
|
||||
|
||||
DBG("Initializing ESP-NOW!");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#if defined(ESP8266)
|
||||
if (esp_now_init() != 0) {
|
||||
return;
|
||||
}
|
||||
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||
// Register peers
|
||||
esp_now_add_peer(_gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
|
||||
#elif defined(ESP32)
|
||||
if(esp_now_init() != ESP_OK){
|
||||
DBG("Error initializing ESP-NOW");
|
||||
return;
|
||||
|
||||
}
|
||||
esp_now_peer_info_t peerInfo;
|
||||
peerInfo.ifidx = WIFI_IF_STA;
|
||||
peerInfo.channel = 0;
|
||||
peerInfo.encrypt = false;
|
||||
// Register first peer
|
||||
memcpy(peerInfo.peer_addr, _gatewayAddress, 6);
|
||||
if(esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||
DBG("Failed to add peer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG(" ESP-NOW Initialized.");
|
||||
}
|
||||
|
||||
void FDRS_EspNow::transmit(DataReading_t *fdrsData, uint8_t _data_count){
|
||||
esp_now_send(_gatewayAddress, (uint8_t *) fdrsData, _data_count * sizeof(DataReading_t));
|
||||
delay(5);
|
||||
DBG(" ESP-NOW sent.");
|
||||
}
|
||||
|
||||
#ifdef USE_LORA
|
||||
|
||||
FDRSLoRa::FDRSLoRa(uint8_t gtwy_mac,
|
||||
uint8_t reading_id,uint8_t miso,uint8_t mosi,uint8_t sck,
|
||||
uint8_t ss,uint8_t rst,uint8_t dio0,uint32_t band,uint8_t sf):
|
||||
FDRSBase(gtwy_mac,reading_id),
|
||||
_miso(miso),
|
||||
_mosi(mosi),
|
||||
_sck(sck),
|
||||
_ss(ss),
|
||||
_rst(rst),
|
||||
_dio0(dio0),
|
||||
_band(band),
|
||||
_sf(sf)
|
||||
{
|
||||
_gatewayAddress[0] = prefix[3];
|
||||
_gatewayAddress[1] = prefix[4];
|
||||
_gatewayAddress[2] = gtwy_mac;
|
||||
}
|
||||
|
||||
void FDRSLoRa::init(void){
|
||||
|
||||
DBG("Initializing LoRa!");
|
||||
DBG(_band);
|
||||
DBG(_sf);
|
||||
#ifdef ESP32
|
||||
SPI.begin(_sck, _miso, _mosi, _ss);
|
||||
#endif
|
||||
LoRa.setPins(_ss, _rst, _dio0);
|
||||
if (!LoRa.begin(_band)) {
|
||||
DBG("LoRa Initialize Failed.");
|
||||
while (1);
|
||||
}
|
||||
LoRa.setSpreadingFactor(_sf);
|
||||
DBG("LoRa Initialized.");
|
||||
}
|
||||
|
||||
void FDRSLoRa::buildPacket(uint8_t* mac, DataReading_t * packet, uint8_t len) {
|
||||
uint8_t pkt[5 + (len * sizeof(DataReading_t))];
|
||||
memcpy(&pkt, mac, 3); //
|
||||
memcpy(&pkt[3], &LoRaAddress, 2);
|
||||
memcpy(&pkt[5], packet, len * sizeof(DataReading_t));
|
||||
LoRa.beginPacket();
|
||||
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
|
||||
LoRa.endPacket();
|
||||
}
|
||||
|
||||
void FDRSLoRa::transmit(DataReading_t *fdrsData, uint8_t _data_count){
|
||||
buildPacket(_gatewayAddress, fdrsData, _data_count);
|
||||
DBG(" LoRa sent.");
|
||||
}
|
||||
|
||||
#endif
|
141
Universal_Sensor_beta/fdrs_sensor.h
Normal file
@ -0,0 +1,141 @@
|
||||
/* FARM DATA RELAY SYSTEM
|
||||
*
|
||||
* "fdrs_sensor.h"
|
||||
*
|
||||
* Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
|
||||
* Condensed and refactored to a single file pair by Binder Tronics (info@bindertronics.com).
|
||||
*/
|
||||
|
||||
#ifndef __FDRS_SENSOR__H__
|
||||
#define __FDRS_SENSOR__H__
|
||||
|
||||
#include "fdrs_types.h"
|
||||
|
||||
//1 to enable debugging prints. 0 disables the debugging prints
|
||||
#define ENABLE_DEBUG 1
|
||||
|
||||
#if ENABLE_DEBUG == 1
|
||||
#ifndef DEBUG
|
||||
#define DEBUG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USE_LORA
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <espnow.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_now.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_LORA
|
||||
#include "LoRa.h"
|
||||
#endif
|
||||
|
||||
#ifdef GLOBALS
|
||||
#define FDRS_BAND GLOBAL_BAND
|
||||
#define FDRS_SF GLOBAL_SF
|
||||
#else
|
||||
#define FDRS_BAND BAND
|
||||
#define FDRS_SF SF
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) (Serial.println(a))
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
#define STATUS_T 0 // Status
|
||||
#define TEMP_T 1 // Temperature
|
||||
#define TEMP2_T 2 // Temperature #2
|
||||
#define HUMIDITY_T 3 // Relative Humidity
|
||||
#define PRESSURE_T 4 // Atmospheric Pressure
|
||||
#define LIGHT_T 5 // Light (lux)
|
||||
#define SOIL_T 6 // Soil Moisture
|
||||
#define SOIL2_T 7 // Soil Moisture #2
|
||||
#define SOILR_T 8 // Soil Resistance
|
||||
#define SOILR2_T 9 // Soil Resistance #2
|
||||
#define OXYGEN_T 10 // Oxygen
|
||||
#define CO2_T 11 // Carbon Dioxide
|
||||
#define WINDSPD_T 12 // Wind Speed
|
||||
#define WINDHDG_T 13 // Wind Direction
|
||||
#define RAINFALL_T 14 // Rainfall
|
||||
#define MOTION_T 15 // Motion
|
||||
#define VOLTAGE_T 16 // Voltage
|
||||
#define VOLTAGE2_T 17 // Voltage #2
|
||||
#define CURRENT_T 18 // Current
|
||||
#define CURRENT2_T 19 // Current #2
|
||||
#define IT_T 20 // Iterations
|
||||
|
||||
extern const uint8_t prefix[5];
|
||||
|
||||
#define MAC_PREFIX prefix // Should only be changed if implementing multiple FDRS systems.
|
||||
|
||||
#define ESP_GATEWAY_ADDRESS_SIZE 6
|
||||
#define LORA_GATEWAY_ADDRESS_SIZE 3
|
||||
|
||||
class FDRSBase{
|
||||
public:
|
||||
|
||||
FDRSBase(uint8_t gtwy_mac,uint8_t reading_id);
|
||||
~FDRSBase();
|
||||
|
||||
void begin(void);
|
||||
void load(float data, uint8_t type);
|
||||
void sleep(int seconds);
|
||||
void send();
|
||||
|
||||
private:
|
||||
|
||||
uint8_t _gtwy_mac;
|
||||
const uint16_t _espnow_size;
|
||||
uint8_t _reading_id;
|
||||
uint8_t _data_count;
|
||||
DataReading_t *fdrsData;
|
||||
|
||||
virtual void init(void) = 0;
|
||||
virtual void transmit(DataReading_t *fdrsData, uint8_t _data_count) = 0;
|
||||
};
|
||||
|
||||
|
||||
class FDRS_EspNow: public FDRSBase{
|
||||
public:
|
||||
|
||||
FDRS_EspNow(uint8_t gtwy_mac, uint8_t reading_id);
|
||||
|
||||
private:
|
||||
|
||||
uint8_t _gatewayAddress[ESP_GATEWAY_ADDRESS_SIZE];
|
||||
void transmit(DataReading_t *fdrsData, uint8_t _data_count) override;
|
||||
void init(void) override;
|
||||
|
||||
};
|
||||
|
||||
class FDRSLoRa: public FDRSBase{
|
||||
public:
|
||||
|
||||
FDRSLoRa(uint8_t gtwy_mac, uint8_t reading_id,uint8_t miso,uint8_t mosi,uint8_t sck, uint8_t ss,uint8_t rst,uint8_t dio0,uint32_t band,uint8_t sf);
|
||||
|
||||
private:
|
||||
|
||||
uint8_t _gatewayAddress[LORA_GATEWAY_ADDRESS_SIZE];
|
||||
uint8_t _miso;
|
||||
uint8_t _mosi;
|
||||
uint8_t _sck;
|
||||
uint8_t _ss;
|
||||
uint8_t _rst;
|
||||
uint8_t _dio0;
|
||||
uint32_t _band;
|
||||
uint8_t _sf;
|
||||
|
||||
void buildPacket(uint8_t* mac, DataReading_t * packet, uint8_t len);
|
||||
void transmit(DataReading_t *fdrsData, uint8_t _data_count) override;
|
||||
void init(void) override;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
39
Universal_Sensor_beta/fdrs_types.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef __FDRS_TYPES_H__
|
||||
#define __FDRS_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
typedef struct __attribute__((packed)) DataReading_t {
|
||||
float data;
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
DataReading_t(): data(0.0),id(0),type(0){
|
||||
}
|
||||
} DataReading_t;
|
||||
|
||||
typedef struct Peer_t{
|
||||
|
||||
uint8_t peer[6];
|
||||
std::vector<DataReading_t> buffer;
|
||||
Peer_t(){
|
||||
memset(peer,0,6);
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
void _set_peer(uint8_t p[6]){
|
||||
memcpy(peer,p,6);
|
||||
}
|
||||
uint8_t *_get_peer(void){
|
||||
return peer;
|
||||
}
|
||||
|
||||
bool operator==(Peer_t c){
|
||||
return (memcmp(this->peer,c.peer,6) == 0);
|
||||
}
|
||||
|
||||
}Peer_t;
|
||||
|
||||
|
||||
#endif
|
27
Universal_Sensor_beta/sensor_setup.h
Normal file
@ -0,0 +1,27 @@
|
||||
// FARM DATA RELAY SYSTEM
|
||||
//
|
||||
// Sensor Configuration
|
||||
// (This file will soon be known as 'sensor_config.h')
|
||||
//
|
||||
|
||||
//#include <fdrs_globals.h> //Uncomment when you install the globals file
|
||||
|
||||
#define READING_ID 1 //Unique ID for this sensor
|
||||
#define GTWY_MAC 0x04 //Address of the nearest gateway
|
||||
|
||||
#define DEEP_SLEEP
|
||||
//#define POWER_CTRL 14
|
||||
#define DEBUG
|
||||
|
||||
//LoRa Configuration
|
||||
#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 SF 7
|