136 lines
4.4 KiB
C++
136 lines
4.4 KiB
C++
#include <SPI.h>
|
|
#include <LoRa.h>
|
|
|
|
// ==========================================
|
|
// PIN DEFINITIONS (Sama dengan Node 2 - ESP8266)
|
|
// ==========================================
|
|
#define LORA_SS D8 // NSS/CS
|
|
#define LORA_RST D0 // Reset LoRa
|
|
#define LORA_DIO0 D1 // DIO0 / Interrupt
|
|
#define BUZZER_PIN D2 // Buzzer
|
|
#define LED_PIN D3 // LED Status
|
|
|
|
// ==========================================
|
|
// PACKET STRUCTURE (MUTLAK SAMA dengan Node 1 & Node 2)
|
|
// ==========================================
|
|
typedef struct struct_message {
|
|
char text[220]; // Kapasitas dikurangi untuk 4 variabel sinyal
|
|
int msgType; // 0=Request, 1=Response, 2=Ping, 3=Pong
|
|
int packetId;
|
|
int totalPackets;
|
|
int senderId; // 1=Node1, 2=Node2, 3=Repeater
|
|
int rssi_gw; // RSSI yang diterima Gateway
|
|
float snr_gw; // SNR yang diterima Gateway
|
|
int rssi_b; // RSSI yang diterima Node B
|
|
float snr_b; // SNR yang diterima Node B
|
|
} struct_message;
|
|
|
|
struct_message recvData;
|
|
|
|
// ==========================================
|
|
// SETUP
|
|
// ==========================================
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
delay(1000); // Jeda extra agar Serial siap
|
|
Serial.println("\n--- LoRa Gateway Starting ---");
|
|
|
|
pinMode(BUZZER_PIN, OUTPUT);
|
|
pinMode(LED_PIN, OUTPUT);
|
|
digitalWrite(BUZZER_PIN, LOW);
|
|
digitalWrite(LED_PIN, LOW);
|
|
|
|
// Inisialisasi SPI secara tegas
|
|
SPI.begin();
|
|
LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);
|
|
|
|
if (!LoRa.begin(433E6)) {
|
|
Serial.println("Gagal Inisialisasi LoRa Gateway");
|
|
// Indikator Error: Beep 2x cepat setiap 20 detik
|
|
while (1) {
|
|
for (int i = 0; i < 2; i++) {
|
|
digitalWrite(LED_PIN, HIGH);
|
|
digitalWrite(BUZZER_PIN, HIGH);
|
|
delay(100);
|
|
digitalWrite(LED_PIN, LOW);
|
|
digitalWrite(BUZZER_PIN, LOW);
|
|
delay(100);
|
|
}
|
|
delay(19600); // Jeda hingga mencapai 20 detik total (20000ms - 400ms)
|
|
}
|
|
}
|
|
|
|
// LED Nyala terus menandakan alat SIAP/READY
|
|
digitalWrite(LED_PIN, HIGH);
|
|
Serial.println("Repeater LoRa (Gateway Perantara) Standby (V2 Piggybacking)");
|
|
}
|
|
|
|
// ==========================================
|
|
// LOOP (TANGKAP & PANTULKAN)
|
|
// ==========================================
|
|
void loop() {
|
|
int packetSize = LoRa.parsePacket();
|
|
|
|
if (packetSize == sizeof(struct_message)) {
|
|
LoRa.readBytes((uint8_t*)&recvData, sizeof(recvData));
|
|
|
|
// 1. CEK IDENTITAS PENGIRIM (Proteksi Broadcast Storm)
|
|
if (recvData.senderId != 3) {
|
|
|
|
Serial.print("Menerima paket dari Node ");
|
|
Serial.print(recvData.senderId);
|
|
Serial.println(". Memantulkan...");
|
|
|
|
// JIKA PAKET DARI NODE 2 (B) - Berarti jalur Balasan (Downlink)
|
|
// Kita suntikkan kualitas sinyal Hop 1 (jalur pulang) ke sini
|
|
if (recvData.senderId == 2) {
|
|
recvData.rssi_gw = LoRa.packetRssi();
|
|
recvData.snr_gw = LoRa.packetSnr();
|
|
Serial.println("Downlink: Menyuntikkan Sinyal dari Node B ke Paket");
|
|
}
|
|
|
|
// 2. INDIKATOR SUARA & CAHAYA
|
|
digitalWrite(LED_PIN, LOW); // Matikan LED sebentar
|
|
digitalWrite(BUZZER_PIN, HIGH); // Bunyikan Buzzer
|
|
delay(50);
|
|
digitalWrite(BUZZER_PIN, LOW);
|
|
digitalWrite(LED_PIN, HIGH); // Nyalakan kembali LED (Ready state)
|
|
|
|
if (recvData.senderId == 1 && recvData.msgType == 2) {
|
|
struct_message repPong;
|
|
memset(&repPong, 0, sizeof(repPong));
|
|
repPong.msgType = 3; // PONG
|
|
repPong.packetId = 0;
|
|
repPong.totalPackets = 1;
|
|
repPong.senderId = 3; // Identitas Repeater
|
|
strcpy(repPong.text, "REPEATER_READY");
|
|
|
|
delay(600); // Beri waktu Node A bersiap & Web App merender state awal
|
|
LoRa.beginPacket();
|
|
LoRa.write((uint8_t*)&repPong, sizeof(repPong));
|
|
LoRa.endPacket();
|
|
Serial.println("Mengirim status REPEATER_READY ke Node 1");
|
|
}
|
|
|
|
// 3. UBAH IDENTITAS PAKET
|
|
recvData.senderId = 3;
|
|
|
|
// 4. JEDA AMAN UDARA
|
|
// Gunakan delay cepat (50ms) untuk pengiriman data (chunking) agar tidak memakan waktu lama
|
|
// Gunakan delay lama (500ms) untuk PING/PONG agar Web App sempat me-render state UI
|
|
if (recvData.msgType == 0 || recvData.msgType == 1) {
|
|
delay(50);
|
|
} else {
|
|
delay(500);
|
|
}
|
|
|
|
// 5. PANTULKAN (RE-BROADCAST)
|
|
LoRa.beginPacket();
|
|
LoRa.write((uint8_t*)&recvData, sizeof(recvData));
|
|
LoRa.endPacket();
|
|
|
|
Serial.println("Paket sukses dipantulkan ke udara!");
|
|
}
|
|
}
|
|
}
|