#include <avr/eeprom.h>
#include <SoftwareSerial.h>
const byte relay_pin = 2; // реле
const byte alert_pin = 3; // клеммы
const byte btn_pin = 4; // кнопка
const byte led_pin = 5; // светодиод
SoftwareSerial SIM800(8, 9); // RX и TX
// кнопка
bool bounce = 0;
bool btn = 1, oldBtn;
unsigned long past;
const uint32_t time = 1000;
bool flag = 0;
uint32_t past_flag = 0;
// клеммы
bool c_bounce = 0;
bool cmm = 1, oldCmm;
unsigned long c_past;
const uint32_t c_time = 1000;
bool c_flag = 0;
uint32_t c_past_flag = 0;
// сигнализация
bool mode = 0;
bool bttn_state = 0;
bool clemm_state = 0;
bool led_state = LOW;
bool signalizuha = 0;
bool mssg = 0;
bool mssg1 = 0;
bool remssg = 0;
long last_led_time = 0;
const uint32_t led_time = 1000;
// SMS texts
String mssg_ready = "Alarm state: Ready";
String mssg_on = "Alarm state: ON";
String mssg_off = "Alarm state: OFF";
String mssg_alarm = "ALERT!";
String mssg_dooropen = "Door state: Opened";
String mssg_already_done = "Already done!";
String mssg_incorrect = "I don't understand :(";
String report_mssg = "";
// codius
String _response = "";
long lastUpdate = millis();
long updatePeriod = 60000;
String my_phone = "+7XXXXXXXXXX;
//--------------------------------- S E T U P ---------------------------------//
void setup() {
SIM800.begin(9600);
sendATCommand("AT", true);
sendATCommand("AT+CMGDA=\"DEL ALL\"", true);
pinMode(relay_pin, OUTPUT);
pinMode(alert_pin, INPUT_PULLUP);
pinMode(btn_pin, INPUT_PULLUP);
pinMode(led_pin, OUTPUT);
lastUpdate = millis();
// проверяем последнее состояние
mode = eeprom_read_byte(0);
signalizuha = eeprom_read_byte(1);
mssg = eeprom_read_byte(2);
mssg1 = eeprom_read_byte(3);
bttn_state = eeprom_read_byte(5);
digitalWrite(relay_pin, signalizuha);
}
//---------------------------------- SIM800 -----------------------------------//
String sendATCommand(String cmd, bool waiting) {
String _resp = "";
SIM800.println(cmd);
if (waiting) {
_resp = waitResponse();
}
return _resp;
}
String waitResponse() {
String _resp = "";
long _timeout = millis() + 10000;
while (!SIM800.available() && millis() < _timeout) {};
if (SIM800.available()) {
_resp = SIM800.readString();
}
return _resp;
}
bool hasmsg = false;
//---------------------------------- L O O P ----------------------------------//
void loop() {
// режим ожидания (мигаем светодиодом)
if (mode == 0) {
if(millis() - last_led_time > led_time) {
last_led_time = millis();
if (led_state == LOW)
led_state = HIGH;
else
led_state = LOW;
digitalWrite(led_pin, led_state);
}
// режим готовности (светодиод не мигает)
} else if (mode == 1) {
digitalWrite(led_pin, HIGH);
}
// нажатие кнопки
bool newBtn = digitalRead(btn_pin);
if (!bounce && newBtn != btn) { bounce = 1; past = millis(); }
if (bounce && millis() - past >= 10) {
bounce = 0 ; oldBtn = btn; btn = newBtn;
if (!btn && oldBtn) { flag = 1; past_flag = millis(); }
// переходим в режим готовности (нажатие кнопки)
if (!oldBtn && btn && flag && millis() - past_flag < time) {
bttn_state = 1;
eeprom_write_byte(5, 1);
flag = 0;
activate();
}
}
// выключаем сигнализацию (удержание кнопки)
if (flag && millis() - past_flag >= time) {
flag = 0;
deactivate();
}
// замыкание клемм
bool newCmm = digitalRead(alert_pin);
if (!c_bounce && newCmm != cmm) { c_bounce = 1; c_past = millis(); }
if (c_bounce && millis() - c_past >= 1000) {
c_bounce = 0 ; oldCmm = cmm; cmm = newCmm;
if (!cmm && oldCmm) {
c_flag = 1; c_past_flag = millis();
// активируем сигнализацию
clemm_state = 1;
activate();
} else if (cmm && !oldCmm) {
clemm_state = 0;
alarm();
}
}
// Codius.ru
if (lastUpdate + updatePeriod < millis() ) {
do {
_response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true);
if (_response.indexOf("+CMGL: ") > -1) {
int msgIndex = _response.substring(_response.indexOf("+CMGL: ") + 7, _response.indexOf("\"REC UNREAD\"", _response.indexOf("+CMGL: ")) - 1).toInt();
char i = 0;
do {
i++;
_response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);
_response.trim();
if (_response.endsWith("OK")) {
if (!hasmsg) hasmsg = true;
sendATCommand("AT+CMGR=" + (String)msgIndex, true);
sendATCommand("\n", true);
parseSMS(_response);
break;
}
else {
sendATCommand("\n", true);
}
} while (i < 10);
break;
}
else {
lastUpdate = millis();
if (hasmsg) {
sendATCommand("AT+CMGDA=\"DEL READ\"", true);
hasmsg = false;
}
break;
}
} while (1);
}
if (SIM800.available()) {
_response = waitResponse();
_response.trim();
if (_response.indexOf("+CMTI:")>-1) {
lastUpdate = millis() - updatePeriod;
}
}
}
void parseSMS(String msg) {
String msgheader = "";
String msgbody = "";
String msgphone = "";
msg = msg.substring(msg.indexOf("+CMGR: "));
msgheader = msg.substring(0, msg.indexOf("\r"));
msgbody = msg.substring(msgheader.length() + 2);
msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));
msgbody.trim();
int firstIndex = msgheader.indexOf("\",\"") + 3;
int secondIndex = msgheader.indexOf("\",\"", firstIndex);
msgphone = msgheader.substring(firstIndex, secondIndex);
if (msgphone.length() > 6 && my_phone.indexOf(msgphone) > -1) {
setAlertState(msgbody);
}
}
void activate() {
if (clemm_state == 1 && bttn_state == 1) {
mode = 1;
eeprom_write_byte(0, 1);
if (mssg1 == 0) {
mssg1 = 1;
eeprom_write_byte(3, 1);
sendSMS(my_phone, mssg_on);
}
} else if (clemm_state == 0 && bttn_state == 1) {
mode = 1;
eeprom_write_byte(0, 1);
}
}
void deactivate() {
if (mode == 1) {
mode = 0;
mssg = 0;
mssg1 = 0;
signalizuha = 0;
bttn_state = 0;
digitalWrite(relay_pin, 0);
eeprom_write_byte(0, 0);
eeprom_write_byte(1, 0);
eeprom_write_byte(2, 0);
eeprom_write_byte(3, 0);
eeprom_write_byte(5, 0);
sendSMS(my_phone, mssg_off);
}
}
void alarm() {
// врубаем сирену!
if (mode == 1) {
digitalWrite(relay_pin, 1);
signalizuha = 1;
eeprom_write_byte(1, 1);
if (mssg == 0) {
mssg = 1;
eeprom_write_byte(2, 1);
sendSMS(my_phone, mssg_alarm);
}
}
}
void report() {
if (mode == 0 && clemm_state == 1) {
report_mssg = "Alarm OFF, Door Closed";
} else if (mode == 0 && clemm_state == 0) {
report_mssg = "Alarm OFF, Door Opened";
} else if (mode == 1 && clemm_state == 1) {
report_mssg = "Alarm ON, Door Closed";
} else if (mode == 1 && clemm_state == 0) {
report_mssg = "ALERT! Alarm ON, Door Opened";
}
sendSMS(my_phone, report_mssg);
}
void setAlertState (String result) {
bool correct = false;
if (result.length() == 1) {
int command = ((String)result).toInt();
if (command == 0 || command == 1 || command == 2) {
switch (command) {
case 0:
if (mode == 1) {
deactivate();
} else {
sendSMS(my_phone, mssg_already_done);
}
break;
case 1:
if (clemm_state == 1 && mode == 0) {
bttn_state = 1;
eeprom_write_byte(5, 1);
activate();
} else if (clemm_state == 0 && mode == 0) {
sendSMS(my_phone, mssg_dooropen);
} else if (mode == 1) {
sendSMS(my_phone, mssg_already_done);
}
break;
case 2:
report();
break;
default:
sendSMS(my_phone, mssg_incorrect);
}
correct = true;
}
}
if (!correct) {
sendSMS(my_phone, mssg_incorrect);
}
}
void sendSMS(String phone, String message)
{
sendATCommand("AT+CMGS=\"" + phone + "\"", true);
sendATCommand(message + "\r\n" + (String)((char)26), true);
}