133 lines
3.8 KiB
C++
133 lines
3.8 KiB
C++
#include <RCSwitch.h>
|
||
#include <DHT.h>
|
||
|
||
// پینها
|
||
#define DHTPIN 2
|
||
#define DHTTYPE DHT11
|
||
#define SOIL_MOISTURE_PIN A3
|
||
#define GAS_SENSOR_PIN A2
|
||
#define RF_TRANSMIT_PIN 9
|
||
|
||
// متن ثابت و کلیدها
|
||
const String PUBLIC_KEY = "as23f";
|
||
const String DEVICE_ID = "dr142";
|
||
|
||
// اشیاء
|
||
DHT dht(DHTPIN, DHTTYPE);
|
||
RCSwitch tx = RCSwitch();
|
||
|
||
// زمانبندی
|
||
unsigned long lastSendTime = 0;
|
||
const unsigned long sendInterval = 5000;
|
||
|
||
// تاخیر بین ارسال هر کاراکتر (ms)
|
||
const unsigned int INTER_CHAR_DELAY_MS = 15;
|
||
|
||
// شمارهٔ بسته (در صورت نیاز بعداً)
|
||
uint8_t seqNumber = 0;
|
||
|
||
// XOR ساده
|
||
String encryptData(const String &data, const String &key) {
|
||
String out;
|
||
out.reserve(data.length());
|
||
for (int i = 0; i < data.length(); i++) {
|
||
out += (char)(data[i] ^ key[i % key.length()]);
|
||
}
|
||
return out;
|
||
}
|
||
|
||
static inline void sendChar(uint8_t c) {
|
||
tx.send((unsigned long)c, 8);
|
||
delay(INTER_CHAR_DELAY_MS);
|
||
}
|
||
|
||
void setup() {
|
||
Serial.begin(9600);
|
||
dht.begin();
|
||
|
||
tx.enableTransmit(RF_TRANSMIT_PIN);
|
||
tx.setProtocol(1);
|
||
tx.setPulseLength(300);
|
||
tx.setRepeatTransmit(3); // کتابخانه هر بایت را 3 بار تکرار میکند
|
||
|
||
Serial.println(F("=== Transmitter Started (with 1-byte checksum) ==="));
|
||
Serial.print(F("Public Key: ")); Serial.println(PUBLIC_KEY);
|
||
Serial.print(F("Device ID : ")); Serial.println(DEVICE_ID);
|
||
|
||
randomSeed(analogRead(0)); // برای ایجاد تاخیر تصادفی احتمالی
|
||
}
|
||
|
||
void loop() {
|
||
// خواندن سنسورها
|
||
float temperature = dht.readTemperature();
|
||
float humidity = dht.readHumidity();
|
||
int soilMoisture = analogRead(SOIL_MOISTURE_PIN);
|
||
int gasValue = analogRead(GAS_SENSOR_PIN);
|
||
|
||
if (isnan(temperature) || isnan(humidity)) {
|
||
temperature = 0; humidity = 0;
|
||
}
|
||
|
||
soilMoisture = constrain(soilMoisture, 0, 1023);
|
||
gasValue = constrain(gasValue, 0, 1023);
|
||
int tempInt = constrain((int)(temperature * 10), 0, 9999); // چهار رقمی
|
||
int humidityInt = constrain((int)(humidity * 10), 0, 9999); // چهار رقمی
|
||
|
||
// قالب دقیقاً 25 کاراکتر تولید میکند: 5 + (S####) + (G####) + (T####) + (H####)
|
||
char dataString[26];
|
||
int n = snprintf(
|
||
dataString, sizeof(dataString),
|
||
"%sS%04dG%04dT%04dH%04d",
|
||
DEVICE_ID.c_str(), soilMoisture, gasValue, tempInt, humidityInt
|
||
);
|
||
|
||
if (n != 25) {
|
||
Serial.print(F("Format length unexpected: ")); Serial.println(n);
|
||
delay(500);
|
||
return;
|
||
}
|
||
|
||
String plain = String(dataString);
|
||
String enc = encryptData(plain, PUBLIC_KEY); // length 25, may contain non-printables
|
||
|
||
if (millis() - lastSendTime >= sendInterval) {
|
||
Serial.println(F("=== Data to Send ==="));
|
||
Serial.print(F("Plain : ")); Serial.println(plain);
|
||
Serial.print(F("Enc : "));
|
||
for (int i = 0; i < enc.length(); i++) {
|
||
uint8_t b = (uint8_t)enc[i];
|
||
if (b < 0x10) Serial.print('0');
|
||
Serial.print(b, HEX); Serial.print(' ');
|
||
}
|
||
Serial.println();
|
||
|
||
// ساخت packet: [PUBLIC_KEY(5)] + [ENC(25)] + [CHK(1)] => مجموع 31 بایت
|
||
const int PACKET_LEN = 31;
|
||
uint8_t packet[PACKET_LEN];
|
||
|
||
// PUBLIC_KEY (5 bytes)
|
||
for (int i = 0; i < 5; i++) packet[i] = (uint8_t)PUBLIC_KEY[i];
|
||
|
||
// ENC (25 bytes)
|
||
for (int i = 0; i < 25; i++) packet[5 + i] = (uint8_t)enc[i];
|
||
|
||
// محاسبه چکسام ساده (sum of bytes 0..29) & 0xFF
|
||
uint16_t sum = 0;
|
||
for (int i = 0; i < 30; i++) sum += packet[i];
|
||
packet[30] = (uint8_t)(sum & 0xFF);
|
||
|
||
// ارسال تمام بایتها متوالی (فقط یک بار، بدون حلقهٔ 3تایی دستی)
|
||
for (int i = 0; i < PACKET_LEN; i++) {
|
||
sendChar(packet[i]);
|
||
}
|
||
|
||
Serial.print(F("Checksum sent: 0x"));
|
||
if (packet[30] < 0x10) Serial.print('0');
|
||
Serial.println(packet[30], HEX);
|
||
|
||
lastSendTime = millis();
|
||
}
|
||
|
||
delay(100);
|
||
}
|