#include <SoftwareSerial.h>
#include <avr/wdt.h>
#include <TinyGPS++.h>
#include <avr/pgmspace.h>
SoftwareSerial sim800(0, 1);
SoftwareSerial gpsSerial(2, 3);
TinyGPSPlus gps;
// تعریف ثابتها برای پینها
const int pumpRelayPin = 4;
const int lockPin = 5;
const int buzzerPin = 13;
const int openPin = 6;
const int rightWindowLifter = 7;
const int rightWindowEncoder = 8;
const int leftWindowLifter = 9;
const int leftWindowEncoder = 10;
const int voltageSensorPin = A4;
const int indicatorlight = 11;
const int alarmStarlight = 12;
// پینهای 74HC165
const int dataPin = A0;
const int clockPin = A1;
const int latchPin = A2;
const int loadPin = A3;
// ورودیهای 74HC165
const int shockSensorPin = 0;
const int doorPin = 1;
const int remotePin1 = 2;
const int remotePin2 = 3;
const int remotePin3 = 4;
const int remotePin4 = 5;
const int switchPowerPin = 6;
const int extraSensorPin = 7;
// شماره تلفن مقصد در PROGMEM
const char phoneNumber[] PROGMEM = "+0000000000000";
// رشتههای ثابت در PROGMEM
const char MSG_ALARM_ACTIVE[] PROGMEM = "دزدگیر فعال شد!";
const char MSG_ALARM_INACTIVE[] PROGMEM = "دزدگیر غیر فعال شد!";
const char MSG_ALARM_SILENT[] PROGMEM = "دزدگیر حالت سایلنت فعال شد!";
const char MSG_ALARM_OFF[] PROGMEM = "الارم غیرفعال شد!";
const char MSG_DOOR_ACTIVE[] PROGMEM = "سنسور درب فعال شد!";
const char MSG_SHOCK_ACTIVE[] PROGMEM = "سنسور لرزش فعال شد!";
const char MSG_ALARM_ON[] PROGMEM = "الارم فعال شد!";
const char MSG_DOOR_OPEN[] PROGMEM = "درب خودرو باز شد!";
const char MSG_DOOR_CLOSED[] PROGMEM = "درب خودرو بسته شد!";
const char MSG_SWITCH_ON[] PROGMEM = "سوئیچ خودرو باز شد!";
const char MSG_SWITCH_OFF[] PROGMEM = "سوئیچ خودرو بسته شد!";
const char MSG_VOLTAGE_LOW[] PROGMEM = "هشدار: ولتاژ پایین است!";
const char MSG_VOLTAGE_ALARM[] PROGMEM = "الارم ولتاژ پایین فعال شد!";
const char MSG_WINDOWS_ACTIVE[] PROGMEM = "شیشه بالابر سمت راست و چپ فعال شدند!";
const char MSG_LOCKS_CLOSED[] PROGMEM = "دربها قفل شدند!";
const char MSG_LOCKS_OPEN[] PROGMEM = "دربها باز شدند!";
const char MSG_RIGHT_WINDOW_OFF[] PROGMEM = "شیشه بالابر سمت راست غیر فعال شد!";
const char MSG_LEFT_WINDOW_OFF[] PROGMEM = "شیشه بالابر سمت چپ غیر فعال شد!";
const char MSG_SMS_START[] PROGMEM = "ارسال پیامک: شروع تنظیم فرمت پیامک";
const char MSG_SMS_PHONE[] PROGMEM = "ارسال پیامک: تنظیم شماره مقصد - ";
const char MSG_SMS_TEXT[] PROGMEM = "ارسال پیامک: ارسال متن پیام - ";
const char MSG_SMS_SENT[] PROGMEM = "ارسال پیامک: پیامک با موفقیت ارسال شد";
const char MSG_SMS_RECEIVED[] PROGMEM = "پیامک دریافتی: ";
const char MSG_CALL_ATTEMPT[] PROGMEM = "تماس: تلاش شماره ";
const char MSG_CALL_PHONE[] PROGMEM = " برای تماس با ";
const char MSG_CALL_RESPONSE[] PROGMEM = "تماس: پاسخ ماژول SIM800 - ";
const char MSG_CALL_CONNECTED[] PROGMEM = "تماس: تماس برقرار شد. فعالسازی میکروفون.";
const char MSG_CALL_NO_ANSWER[] PROGMEM = "تماس: تماس بدون پاسخ یا تایماوت. قطع تماس.";
const char MSG_CALL_RETRY[] PROGMEM = "تماس: تلاش مجدد برای تماس با ";
const char MSG_CALL_ENDED[] PROGMEM = "تماس: تماس قطع شد. بازگشت به حالت آمادهباش.";
const char MSG_CALL_INPUT_ANSWERED[] PROGMEM = "تماس: تماس ورودی پاسخ داده شد.";
const char MSG_CALL_DTMF[] PROGMEM = "تماس: ورودی DTMF - ";
const char MSG_CALL_INPUT_ENDED[] PROGMEM = "تماس: تماس ورودی قطع شد.";
const char MSG_SIM800_AT[] PROGMEM = "تنظیم SIM800: ارسال دستور AT";
const char MSG_SIM800_CLIP[] PROGMEM = "تنظیم SIM800: فعالسازی شناسایی تماسگیرنده";
const char MSG_SIM800_GSM[] PROGMEM = "تنظیم SIM800: تنظیم کدگذاری GSM";
const char MSG_SIM800_SMS[] PROGMEM = "تنظیم SIM800: تنظیم فرمت پیامک";
const char MSG_SIM800_COMPLETE[] PROGMEM = "تنظیم SIM800: تنظیمات کامل شد";
const char MSG_LOCATION_INVALID[] PROGMEM = "موقعیت مکانی نامعتبر";
const char MSG_STATUS[] PROGMEM = "وضعیت دزدگیر: ";
const char MSG_STATUS_ACTIVE[] PROGMEM = "فعال";
const char MSG_STATUS_INACTIVE[] PROGMEM = "غیرفعال";
const char MSG_STATUS_SILENT[] PROGMEM = "فعال (سایلنت)";
const char MSG_DOORS_LOCKED[] PROGMEM = "قفل";
const char MSG_DOORS_OPEN[] PROGMEM = "باز";
const char MSG_SWITCH_OPEN[] PROGMEM = "باز";
const char MSG_SWITCH_CLOSED[] PROGMEM = "بسته";
const char MSG_VOLTAGE[] PROGMEM = "ولتاژ باتری: ";
// تعریف وضعیتها با استفاده از enum
enum AlarmState { INACTIVE, ACTIVE, ACTIVE_SILENT };
// متغیرهای وضعیت
AlarmState alarmState = INACTIVE;
volatile unsigned long timerTicks = 0;
unsigned long alarmStartTime = 0;
unsigned long switchOffTime = 0;
unsigned long previousVoltageTime = 0;
unsigned long indicatorlightTime = 0;
unsigned long rightWindowLifterTime = 0;
unsigned long leftWindowLifterTime = 0;
unsigned long sim800SetupTime = 0;
unsigned long confirmActionTime = 0;
unsigned long callStartTime = 0;
bool sim800Initialized = false;
bool lockPinState = false;
bool switchPower2State = false;
bool ActiveBuzzer = false;
bool switchPower3State = false;
bool rightWindowEncoderState = false;
bool leftWindowEncoderState = false;
bool voltageBuzzerState = false;
bool doorPinState = false;
bool shockSensorPinState = false;
bool switchPower4State = false;
bool confirmInProgress = false;
bool inCall = false;
int confirmStep = 0;
int callAttempts = 0;
const float voltageThreshold = 11.0;
const unsigned long SIM800_INIT_INTERVAL = 1000;
const unsigned long DELAY_300_MS = 300;
const unsigned long DELAY_1000_MS = 1000;
const unsigned long BEEP_DURATION = 100;
const unsigned long BLINK_DURATION = 200;
const unsigned long CONFIRM_INTERVAL = 200;
const unsigned long CALL_TIMEOUT = 30000;
const unsigned long CALL_INTERVAL = 5000;
// پرچم دیباگ برای کنترل چاپ پیامها
#define DEBUG true
// تابع برای چاپ رشتههای PROGMEM
void printProgmem(const char* str) {
if (DEBUG) {
char buffer[100];
strncpy_P(buffer, str, sizeof(buffer));
Serial.println(buffer);
}
}
// تنظیمات اولیه
void setup() {
pinMode(pumpRelayPin, OUTPUT);
pinMode(lockPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(openPin, OUTPUT);
pinMode(leftWindowLifter, OUTPUT);
pinMode(leftWindowEncoder, INPUT);
pinMode(rightWindowLifter, OUTPUT);
pinMode(rightWindowEncoder, INPUT);
pinMode(indicatorlight, OUTPUT);
pinMode(alarmStarlight, OUTPUT);
pinMode(dataPin, INPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(loadPin, OUTPUT);
Serial.begin(9600);
sim800.begin(9600);
gpsSerial.begin(9600);
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15624;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS12) | (1 << CS10);
TIMSK1 |= (1 << OCIE1A);
interrupts();
wdt_enable(WDTO_8S);
sim800SetupTime = millis();
}
// ISR برای تایمر1
ISR(TIMER1_COMPA_vect) {
timerTicks++;
}
// تابع تأیید دستور
void confirmAction() {
if (!confirmInProgress) {
confirmInProgress = true;
confirmStep = 0;
confirmActionTime = millis();
}
unsigned long currentMillis = millis();
if (confirmStep == 0 && currentMillis - confirmActionTime >= CONFIRM_INTERVAL) {
digitalWrite(buzzerPin, HIGH);
digitalWrite(indicatorlight, HIGH);
confirmStep = 1;
confirmActionTime = currentMillis;
} else if (confirmStep == 1 && currentMillis - confirmActionTime >= BEEP_DURATION) {
digitalWrite(buzzerPin, LOW);
confirmStep = 2;
confirmActionTime = currentMillis;
} else if (confirmStep == 2 && currentMillis - confirmActionTime >= CONFIRM_INTERVAL) {
digitalWrite(indicatorlight, LOW);
confirmStep = 3;
confirmActionTime = currentMillis;
} else if (confirmStep == 3 && currentMillis - confirmActionTime >= CONFIRM_INTERVAL) {
digitalWrite(buzzerPin, HIGH);
digitalWrite(indicatorlight, HIGH);
confirmStep = 4;
confirmActionTime = currentMillis;
} else if (confirmStep == 4 && currentMillis - confirmActionTime >= BEEP_DURATION) {
digitalWrite(buzzerPin, LOW);
confirmStep = 5;
confirmActionTime = currentMillis;
} else if (confirmStep == 5 && currentMillis - confirmActionTime >= BLINK_DURATION) {
digitalWrite(indicatorlight, LOW);
confirmStep = 0;
confirmInProgress = false;
confirmActionTime = currentMillis;
}
}
// تابع خواندن ورودیها
void readInputs(bool &shockSensorState, bool &doorState, bool &remote1State, bool &remote2State,
bool &remote3State, bool &remote4State, bool &switchPowerState, int &sensorValue) {
uint8_t inputStates = read74HC165();
shockSensorState = bitRead(inputStates, shockSensorPin);
doorState = bitRead(inputStates, doorPin);
remote1State = bitRead(inputStates, remotePin1);
remote2State = bitRead(inputStates, remotePin2);
remote3State = bitRead(inputStates, remotePin3);
remote4State = bitRead(inputStates, remotePin4);
switchPowerState = bitRead(inputStates, switchPowerPin);
sensorValue = analogRead(voltageSensorPin);
}
// تابع خواندن ورودیها از 74HC165
uint8_t read74HC165() {
uint8_t value = 0;
digitalWrite(loadPin, LOW);
digitalWrite(loadPin, HIGH);
for (int i = 0; i < 8; i++) {
value |= digitalRead(dataPin) << i;
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
return value;
}
// تابع تنظیم وضعیت دزدگیر
void setAlarmState(AlarmState newState) {
alarmState = newState;
}
// تابع ارسال پیامک
void sendSMS(const char* message) {
static unsigned long smsStartTime = 0;
static int smsStep = 0;
unsigned long currentMillis = millis();
char buffer[50];
if (smsStep == 0 && currentMillis - smsStartTime >= SIM800_INIT_INTERVAL) {
sim800.println("AT+CMGF=1");
smsStep = 1;
smsStartTime = currentMillis;
printProgmem(MSG_SMS_START);
} else if (smsStep == 1 && currentMillis - smsStartTime >= SIM800_INIT_INTERVAL) {
sim800.print("AT+CMGS=\"");
strncpy_P(buffer, phoneNumber, sizeof(buffer));
sim800.print(buffer);
sim800.println("\"");
smsStep = 2;
smsStartTime = currentMillis;
if (DEBUG) {
Serial.print(MSG_SMS_PHONE);
Serial.println(buffer);
}
} else if (smsStep == 2 && currentMillis - smsStartTime >= SIM800_INIT_INTERVAL) {
strncpy_P(buffer, message, sizeof(buffer));
sim800.print(buffer);
smsStep = 3;
smsStartTime = currentMillis;
if (DEBUG) {
Serial.print(MSG_SMS_TEXT);
Serial.println(buffer);
}
} else if (smsStep == 3 && currentMillis - smsStartTime >= SIM800_INIT_INTERVAL) {
sim800.println((char)26);
smsStep = 0;
smsStartTime = currentMillis;
printProgmem(MSG_SMS_SENT);
}
}
// تابع بررسی دریافت پیامک
bool receiveSMS(const char* command) {
if (sim800.available()) {
char buffer[100];
int i = 0;
while (sim800.available() && i < sizeof(buffer) - 1) {
buffer[i++] = sim800.read();
}
buffer[i] = '\0';
if (DEBUG) {
Serial.print(MSG_SMS_RECEIVED);
Serial.println(buffer);
}
return (strstr(buffer, command) != nullptr);
}
return false;
}
// تابع بررسی پیامکها و ارسال وضعیت
void checkSMS() {
if (receiveSMS("وضعیت")) {
char buffer[100];
char temp[50];
strcpy_P(buffer, MSG_STATUS);
if (alarmState == ACTIVE) {
strcat_P(buffer, MSG_STATUS_ACTIVE);
} else if (alarmState == INACTIVE) {
strcat_P(buffer, MSG_STATUS_INACTIVE);
} else {
strcat_P(buffer, MSG_STATUS_SILENT);
}
strcat(buffer, "\n");
// وضعیت دربها
strcat_P(buffer, lockPinState ? MSG_DOORS_LOCKED : MSG_DOORS_OPEN);
strcat(buffer, "\n");
// وضعیت سوئیچ
bool switchPowerState;
int sensorValue;
bool remote1State, remote2State, remote3State, remote4State; // تعریف متغیرهای محلی
readInputs(shockSensorPinState, doorPinState, remote1State, remote2State, remote3State, remote4State, switchPowerState, sensorValue);
strcat_P(buffer, switchPowerState ? MSG_SWITCH_OPEN : MSG_SWITCH_CLOSED);
strcat(buffer, "\n");
// ولتاژ باتری
float voltage = sensorValue * (5.0 / 1023.0) * 2.4;
strcat_P(buffer, MSG_VOLTAGE);
snprintf(temp, sizeof(temp), "%.2f ولت", voltage);
strcat(buffer, temp);
if (DEBUG) {
Serial.print(MSG_SMS_TEXT);
Serial.println(buffer);
}
sendSMS(buffer);
}
}
// بررسی پیامکهای دریافتی
void checkReceiveSMS() {
if (receiveSMS("فعال")) {
checkActiveAlarmState();
sendSMS(MSG_ALARM_ACTIVE);
confirmAction();
} else if (receiveSMS("غیرفعال")) {
checkInactiveAlarmState();
sendSMS(MSG_ALARM_INACTIVE);
confirmAction();
} else if (receiveSMS("سایلنت")) {
checkActiveSilentAlarmState();
sendSMS(MSG_ALARM_SILENT);
confirmAction();
}
}
// تابع دریافت موقعیت مکانی از GPS
void getGPSLocation(char* location, size_t size) {
if (gps.location.isValid()) {
snprintf(location, size, "Lat: %.6f, Lon: %.6f", gps.location.lat(), gps.location.lng());
} else {
strncpy_P(location, MSG_LOCATION_INVALID, size);
}
}
// تابع بررسی وضعیت فعال دزدگیر خودرو
void checkActiveAlarmState() {
alarmState = ACTIVE;
switchPower2State = true;
switchPower3State = false;
ActiveBuzzer = false;
shockSensorPinState = false;
doorPinState = false;
voltageBuzzerState = false;
printProgmem(MSG_ALARM_ACTIVE);
}
// تابع بررسی وضعیت غیرفعال دزدگیر خودرو
void checkInactiveAlarmState() {
alarmState = INACTIVE;
switchOffTime = millis();
switchPower2State = false;
ActiveBuzzer = false;
switchPower3State = false;
digitalWrite(buzzerPin, LOW);
digitalWrite(rightWindowLifter, LOW);
digitalWrite(leftWindowLifter, LOW);
digitalWrite(indicatorlight, LOW);
printProgmem(MSG_ALARM_INACTIVE);
}
// تابع بررسی وضعیت فعال سایلنت دزدگیر خودرو
void checkActiveSilentAlarmState() {
alarmState = ACTIVE_SILENT;
switchPower2State = true;
switchPower3State = false;
ActiveBuzzer = false;
shockSensorPinState = false;
doorPinState = false;
voltageBuzzerState = false;
printProgmem(MSG_ALARM_SILENT);
}
// تابع بررسی و تغییر وضعیت دزدگیر
void checkRemoteStates(bool remote1State, bool remote2State, bool remote3State, bool remote4State) {
static unsigned long remoteActionTime = 0;
if (remote1State == HIGH && millis() - remoteActionTime >= DELAY_300_MS) {
checkActiveAlarmState();
confirmAction();
remoteActionTime = millis();
} else if (remote2State == HIGH && millis() - remoteActionTime >= DELAY_300_MS) {
checkInactiveAlarmState();
confirmAction();
remoteActionTime = millis();
} else if (remote3State == HIGH && ActiveBuzzer && millis() - remoteActionTime >= DELAY_300_MS) {
printProgmem(MSG_ALARM_OFF);
digitalWrite(buzzerPin, LOW);
digitalWrite(indicatorlight, LOW);
switchPower2State = true;
ActiveBuzzer = false;
doorPinState = false;
shockSensorPinState = false;
confirmAction();
remoteActionTime = millis();
} else if (remote4State == HIGH && millis() - remoteActionTime >= DELAY_300_MS) {
checkActiveSilentAlarmState();
confirmAction();
remoteActionTime = millis();
}
}
// تابع تماس هنگام آلارم
void makeAlarmCall() {
static int callStep = 0;
static unsigned long callActionTime = 0;
unsigned long currentMillis = millis();
char buffer[50];
if (callAttempts >= 3) {
if (DEBUG) {
Serial.println("تماس: تلاشهای تماس به اتمام رسید (3 بار). بازگشت به حالت آمادهباش.");
}
callAttempts = 0;
callStep = 0;
inCall = false;
return;
}
if (callStep == 0 && currentMillis - callActionTime >= CALL_INTERVAL) {
strncpy_P(buffer, phoneNumber, sizeof(buffer));
sim800.print("ATD");
sim800.print(buffer);
sim800.println(";");
callStep = 1;
callActionTime = currentMillis;
callStartTime = currentMillis;
callAttempts++;
if (DEBUG) {
Serial.print(MSG_CALL_ATTEMPT);
Serial.print(callAttempts);
Serial.print(MSG_CALL_PHONE);
Serial.println(buffer);
if (callAttempts > 1) {
Serial.print(MSG_CALL_RETRY);
Serial.println(buffer);
}
}
} else if (callStep == 1 && sim800.available()) {
char response[100];
int i = 0;
while (sim800.available() && i < sizeof(response) - 1) {
response[i++] = sim800.read();
}
response[i] = '\0';
if (DEBUG) {
Serial.print(MSG_CALL_RESPONSE);
Serial.println(response);
}
if (strstr(response, "CONNECT") != nullptr) {
printProgmem(MSG_CALL_CONNECTED);
sim800.println("AT+CMIC=0,15");
inCall = true;
callStep = 2;
} else if (strstr(response, "NO CARRIER") != nullptr || currentMillis - callStartTime >= CALL_TIMEOUT) {
printProgmem(MSG_CALL_NO_ANSWER);
sim800.println("ATH");
callStep = 0;
inCall = false;
callActionTime = currentMillis;
}
} else if (callStep == 2 && sim800.available()) {
char response[100];
int i = 0;
while (sim800.available() && i < sizeof(response) - 1) {
response[i++] = sim800.read();
}
response[i] = '\0';
if (DEBUG) {
Serial.print(MSG_CALL_RESPONSE);
Serial.println(response);
}
if (strstr(response, "NO CARRIER") != nullptr) {
printProgmem(MSG_CALL_ENDED);
sim800.println("ATH");
callStep = 0;
callAttempts = 0;
inCall = false;
callActionTime = currentMillis;
}
}
}
// تابع بررسی و مدیریت سنسور درب
void checkAlarmDoors(bool doorState) {
static unsigned long doorActionTime = 0;
if ((alarmState == ACTIVE || alarmState == ACTIVE_SILENT) && doorState == HIGH && !doorPinState &&
millis() - doorActionTime >= DELAY_300_MS) {
printProgmem(MSG_DOOR_ACTIVE);
alarmStartTime = millis();
sendSMS(MSG_DOOR_ACTIVE);
if (alarmState == ACTIVE) {
digitalWrite(buzzerPin, HIGH);
printProgmem(MSG_ALARM_ON);
}
ActiveBuzzer = true;
doorPinState = true;
makeAlarmCall();
doorActionTime = millis();
}
}
// کنترل دربهای خودرو در وضعیت دزدگیر غیرفعال
void checkDoorState(bool doorState) {
static unsigned long doorActionTime = 0;
if (doorState == HIGH && !doorPinState && millis() - doorActionTime >= DELAY_300_MS) {
printProgmem(MSG_DOOR_OPEN);
doorPinState = true;
doorActionTime = millis();
} else if (doorState == LOW && doorPinState && millis() - doorActionTime >= DELAY_300_MS) {
printProgmem(MSG_DOOR_CLOSED);
doorPinState = false;
doorActionTime = millis();
}
}
// تابع بررسی و مدیریت الارم سنسور لرزش
void checkAlarmShockSensor(bool shockSensorState) {
static unsigned long shockActionTime = 0;
if ((alarmState == ACTIVE || alarmState == ACTIVE_SILENT) && shockSensorState == HIGH &&
!shockSensorPinState && millis() - shockActionTime >= DELAY_300_MS) {
if (alarmState == ACTIVE_SILENT) {
printProgmem(MSG_SHOCK_ACTIVE);
alarmStartTime = millis();
sendSMS(MSG_SHOCK_ACTIVE);
shockSensorPinState = true;
ActiveBuzzer = true;
} else {
printProgmem(MSG_SHOCK_ACTIVE);
alarmStartTime = millis();
sendSMS(MSG_SHOCK_ACTIVE);
digitalWrite(buzzerPin, HIGH);
printProgmem(MSG_ALARM_ON);
shockSensorPinState = true;
ActiveBuzzer = true;
}
shockActionTime = millis();
}
}
// تابع بررسی وضعیت بوزر
void checkBuzzer() {
if (ActiveBuzzer && millis() - alarmStartTime >= 10000) {
printProgmem(MSG_ALARM_OFF);
sendSMS(MSG_ALARM_OFF);
digitalWrite(buzzerPin, LOW);
ActiveBuzzer = false;
switchPower2State = true;
switchPower3State = false;
shockSensorPinState = false;
doorPinState = false;
voltageBuzzerState = false;
}
}
// تابع بررسی وضعیت سوئیچ خودرو
void checkSwitchPower(bool switchPowerState) {
static unsigned long switchActionTime = 0;
if (switchPowerState == HIGH && !switchPower2State && !switchPower3State) {
switchOffTime = millis();
} else if (switchPowerState == LOW && !switchPower2State && !switchPower3State &&
millis() - switchOffTime >= 10000) {
setAlarmState(ACTIVE);
sendSMS(MSG_ALARM_ACTIVE);
printProgmem(MSG_ALARM_ACTIVE);
confirmAction();
switchPower2State = true;
} else if (switchPowerState == HIGH && (alarmState == ACTIVE_SILENT || alarmState == ACTIVE) &&
switchPower2State && millis() - switchActionTime >= DELAY_300_MS) {
digitalWrite(buzzerPin, HIGH);
Serial.println("الارم سویچ فعال شد!");
alarmStartTime = millis();
sendSMS("الارم سویچ فعال شد!");
switchPower2State = false;
switchPower3State = true;
ActiveBuzzer = true;
makeAlarmCall();
switchActionTime = millis();
}
if (switchPowerState == HIGH && !switchPower4State && alarmState == INACTIVE &&
millis() - switchActionTime >= DELAY_300_MS) {
printProgmem(MSG_SWITCH_ON);
switchPower4State = true;
switchActionTime = millis();
} else if (switchPowerState == LOW && switchPower4State && alarmState == INACTIVE &&
millis() - switchActionTime >= DELAY_300_MS) {
printProgmem(MSG_SWITCH_OFF);
switchPower4State = false;
switchActionTime = millis();
}
}
// تابع کنترل چشمکزن و راهنماها
void checkIndicators(bool doorState) {
if ((digitalRead(buzzerPin) == HIGH) || ActiveBuzzer || (doorState == HIGH)) {
unsigned long currentMillis = millis();
if (currentMillis - indicatorlightTime >= 500) {
indicatorlightTime = currentMillis;
if (!confirmInProgress) {
digitalWrite(indicatorlight, !digitalRead(indicatorlight));
}
}
} else {
if (!confirmInProgress) {
digitalWrite(indicatorlight, LOW);
ActiveBuzzer = false;
}
}
}
// تابع کنترل قفل دربها و شیشه بالابرها
void checkLocksAndWindows() {
static unsigned long lockActionTime = 0;
if ((alarmState == ACTIVE_SILENT || alarmState == ACTIVE) && !lockPinState &&
millis() - lockActionTime >= DELAY_1000_MS) {
digitalWrite(lockPin, HIGH);
digitalWrite(rightWindowLifter, HIGH);
digitalWrite(leftWindowLifter, HIGH);
rightWindowEncoderState = false;
leftWindowEncoderState = false;
printProgmem(MSG_WINDOWS_ACTIVE);
printProgmem(MSG_LOCKS_CLOSED);
rightWindowLifterTime = millis();
leftWindowLifterTime = millis();
digitalWrite(lockPin, LOW);
lockPinState = true;
lockActionTime = millis();
} else if (alarmState == INACTIVE && lockPinState && millis() - lockActionTime >= DELAY_1000_MS) {
lockPinState = false;
digitalWrite(openPin, HIGH);
printProgmem(MSG_LOCKS_OPEN);
digitalWrite(openPin, LOW);
lockActionTime = millis();
}
if (digitalRead(rightWindowLifter) == HIGH && digitalRead(rightWindowEncoder) == LOW &&
!rightWindowEncoderState && millis() - rightWindowLifterTime >= DELAY_300_MS) {
digitalWrite(rightWindowLifter, LOW);
printProgmem(MSG_RIGHT_WINDOW_OFF);
rightWindowEncoderState = true;
}
if (digitalRead(rightWindowLifter) == HIGH && millis() - rightWindowLifterTime >= 15000) {
digitalWrite(rightWindowLifter, LOW);
printProgmem(MSG_RIGHT_WINDOW_OFF);
rightWindowEncoderState = true;
}
if (digitalRead(leftWindowLifter) == HIGH && digitalRead(leftWindowEncoder) == LOW &&
!leftWindowEncoderState && millis() - leftWindowLifterTime >= DELAY_300_MS) {
digitalWrite(leftWindowLifter, LOW);
printProgmem(MSG_LEFT_WINDOW_OFF);
leftWindowEncoderState = true;
}
if (digitalRead(leftWindowLifter) == HIGH && millis() - leftWindowLifterTime >= 15000) {
digitalWrite(leftWindowLifter, LOW);
printProgmem(MSG_LEFT_WINDOW_OFF);
leftWindowEncoderState = true;
}
}
// تابع بررسی ولتاژ باتری
void checkBatteryVoltage(int sensorValue) {
float voltage = sensorValue * (5.0 / 1023.0) * 2.4;
if (voltage < voltageThreshold && (alarmState == ACTIVE_SILENT || alarmState == ACTIVE) &&
!voltageBuzzerState) {
printProgmem(MSG_VOLTAGE_ALARM);
alarmStartTime = millis();
digitalWrite(buzzerPin, HIGH);
ActiveBuzzer = true;
voltageBuzzerState = true;
makeAlarmCall();
}
if (voltage < voltageThreshold && millis() - previousVoltageTime >= 20000) {
printProgmem(MSG_VOLTAGE_LOW);
sendSMS(MSG_VOLTAGE_LOW);
previousVoltageTime = millis();
}
}
// کنترل چشمکزن دزدگیر
void checkAlarmStarlight() {
digitalWrite(alarmStarlight, (alarmState == ACTIVE_SILENT || alarmState == ACTIVE) ? HIGH : LOW);
}
// تنظیم وضعیت رله پمپ
void checkPumpRelayState() {
digitalWrite(pumpRelayPin, (alarmState == ACTIVE_SILENT || alarmState == ACTIVE) ? LOW : HIGH);
}
// بررسی تماس ورودی
void callSim() {
static unsigned long callActionTime = 0;
if (sim800.available()) {
char response[100];
int i = 0;
while (sim800.available() && i < sizeof(response) - 1) {
response[i++] = sim800.read();
}
response[i] = '\0';
if (DEBUG) {
Serial.print(MSG_CALL_RESPONSE);
Serial.println(response);
}
if (strstr(response, "RING") != nullptr && millis() - callActionTime >= DELAY_1000_MS) {
sim800.println("ATA");
inCall = true;
callActionTime = millis();
printProgmem(MSG_CALL_INPUT_ANSWERED);
}
if (inCall && sim800.available()) {
char c = sim800.read();
if (DEBUG) {
Serial.print(MSG_CALL_DTMF);
Serial.println(c);
}
if (c == '1') {
checkActiveAlarmState();
confirmAction();
} else if (c == '2') {
checkInactiveAlarmState();
confirmAction();
} else if (c == '3') {
checkActiveSilentAlarmState();
confirmAction();
}
char hangupResponse[100];
i = 0;
while (sim800.available() && i < sizeof(hangupResponse) - 1) {
hangupResponse[i++] = sim800.read();
}
hangupResponse[i] = '\0';
if (strstr(hangupResponse, "NO CARRIER") != nullptr) {
sim800.println("ATH");
inCall = false;
callActionTime = millis();
printProgmem(MSG_CALL_INPUT_ENDED);
}
}
}
}
// بررسی و ارسال موقعیت مکانی
void locationSMS() {
if (receiveSMS("موقعیت")) {
char location[50];
getGPSLocation(location, sizeof(location));
sendSMS(location);
}
}
// تنظیمات ماژول SIM800
void setupSIM800() {
static int setupStep = 0;
unsigned long currentMillis = millis();
if (setupStep == 0 && currentMillis - sim800SetupTime >= SIM800_INIT_INTERVAL) {
sim800.println("AT");
setupStep = 1;
sim800SetupTime = currentMillis;
printProgmem(MSG_SIM800_AT);
} else if (setupStep == 1 && currentMillis - sim800SetupTime >= SIM800_INIT_INTERVAL) {
sim800.println("AT+CLIP=1");
setupStep = 2;
sim800SetupTime = currentMillis;
printProgmem(MSG_SIM800_CLIP);
} else if (setupStep == 2 && currentMillis - sim800SetupTime >= SIM800_INIT_INTERVAL) {
sim800.println("AT+CSCS=\"GSM\"");
setupStep = 3;
sim800SetupTime = currentMillis;
printProgmem(MSG_SIM800_GSM);
} else if (setupStep == 3 && currentMillis - sim800SetupTime >= SIM800_INIT_INTERVAL) {
sim800.println("AT+CMGF=1");
setupStep = 4;
sim800SetupTime = currentMillis;
printProgmem(MSG_SIM800_SMS);
} else if (setupStep == 4 && currentMillis - sim800SetupTime >= SIM800_INIT_INTERVAL) {
sim800.println("AT+CLCC=1");
setupStep = 0;
sim800Initialized = true;
sim800SetupTime = currentMillis;
printProgmem(MSG_SIM800_COMPLETE);
}
}
// حلقه اصلی برنامه
void loop() {
if (!sim800Initialized) {
setupSIM800();
} else {
bool shockSensorState, doorState, remote1State, remote2State, remote3State, remote4State, switchPowerState;
int sensorValue;
readInputs(shockSensorState, doorState, remote1State, remote2State, remote3State, remote4State, switchPowerState, sensorValue);
checkRemoteStates(remote1State, remote2State, remote3State, remote4State);
checkAlarmDoors(doorState);
checkAlarmShockSensor(shockSensorState);
checkBuzzer();
checkSwitchPower(switchPowerState);
checkIndicators(doorState);
checkLocksAndWindows();
checkBatteryVoltage(sensorValue);
checkAlarmStarlight();
checkDoorState(doorState);
checkPumpRelayState();
checkReceiveSMS();
callSim();
locationSMS();
checkSMS();
if (confirmInProgress) {
confirmAction();
}
if (inCall || callAttempts > 0) {
makeAlarmCall();
}
}
while (gpsSerial.available() > 0) {
gps.encode(gpsSerial.read());
}
wdt_reset();
}