Initial commit: FarmBox edge stack (ESP32 firmware + MQTT bridge + sync agent)
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* FarmBox LoRa Gateway
|
||||
* ESP32 или Raspberry Pi + LoRa HAT
|
||||
* Принимает пакеты от всех датчиков → публикует в MQTT
|
||||
*
|
||||
* Для ESP32: подключить к WiFi → слать в Mosquitto
|
||||
* Для RPi: запустить как Python скрипт
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include <LoRa.h>
|
||||
#include <WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// ─── WiFi (локальная сеть фермы) ──────────────────────
|
||||
const char* WIFI_SSID = "FARM_WIFI"; // ← изменить
|
||||
const char* WIFI_PASS = "farm_password"; // ← изменить
|
||||
|
||||
// ─── MQTT (Mosquitto на Raspberry Pi / Mini PC) ────────
|
||||
const char* MQTT_HOST = "192.168.1.100"; // ← IP FarmBox
|
||||
const int MQTT_PORT = 1883;
|
||||
|
||||
// ─── LoRa пины (TTGO LoRa32) ──────────────────────────
|
||||
#define LORA_SCK 5
|
||||
#define LORA_MISO 19
|
||||
#define LORA_MOSI 27
|
||||
#define LORA_SS 18
|
||||
#define LORA_RST 23
|
||||
#define LORA_DI0 26
|
||||
#define LORA_BAND 868E6
|
||||
|
||||
WiFiClient wifiClient;
|
||||
PubSubClient mqtt(wifiClient);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("FarmBox LoRa Gateway v1.0");
|
||||
|
||||
// WiFi
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||
Serial.print("WiFi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500); Serial.print(".");
|
||||
}
|
||||
Serial.printf("\nWiFi OK: %s\n", WiFi.localIP().toString().c_str());
|
||||
|
||||
// MQTT
|
||||
mqtt.setServer(MQTT_HOST, MQTT_PORT);
|
||||
connectMqtt();
|
||||
|
||||
// LoRa
|
||||
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_SS);
|
||||
LoRa.setPins(LORA_SS, LORA_RST, LORA_DI0);
|
||||
if (!LoRa.begin(LORA_BAND)) {
|
||||
Serial.println("LoRa ОШИБКА!");
|
||||
while (true);
|
||||
}
|
||||
LoRa.setSpreadingFactor(9);
|
||||
LoRa.setSignalBandwidth(125E3);
|
||||
LoRa.enableCrc();
|
||||
Serial.println("LoRa Gateway готов. Слушаю...");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (!mqtt.connected()) connectMqtt();
|
||||
mqtt.loop();
|
||||
|
||||
int packetSize = LoRa.parsePacket();
|
||||
if (packetSize) {
|
||||
String received = "";
|
||||
while (LoRa.available()) received += (char)LoRa.read();
|
||||
int rssi = LoRa.packetRssi();
|
||||
float snr = LoRa.packetSnr();
|
||||
|
||||
Serial.printf("[RX] RSSI:%d SNR:%.1f | %s\n", rssi, snr, received.c_str());
|
||||
|
||||
// Парсим JSON и добавляем метаданные шлюза
|
||||
StaticJsonDocument<512> doc;
|
||||
if (deserializeJson(doc, received) == DeserializationError::Ok) {
|
||||
doc["gw_rssi"] = rssi;
|
||||
doc["gw_snr"] = snr;
|
||||
|
||||
String enhanced;
|
||||
serializeJson(doc, enhanced);
|
||||
|
||||
// Публикуем в MQTT топик farm/lora/{device_id}
|
||||
const char* deviceId = doc["id"] | "unknown";
|
||||
String topic = "farm/lora/" + String(deviceId);
|
||||
mqtt.publish(topic.c_str(), enhanced.c_str());
|
||||
|
||||
Serial.printf("[MQTT] → %s\n", topic.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void connectMqtt() {
|
||||
while (!mqtt.connected()) {
|
||||
Serial.print("MQTT...");
|
||||
if (mqtt.connect("farmbox-gateway")) {
|
||||
Serial.println("OK");
|
||||
// Публикуем статус шлюза
|
||||
mqtt.publish("farm/status/gateway", "{\"status\":\"online\"}");
|
||||
} else {
|
||||
Serial.printf("FAIL rc=%d, retry 5s\n", mqtt.state());
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user