mof1re

arduino_roof_sms

Oct 3rd, 2018
118
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <SoftwareSerial.h>                                   // Библиотека програмной реализации обмена по UART-протоколу
  2. SoftwareSerial SIM800(8, 9);                                  // RX, TX
  3.  
  4. // Назначаем переменные для управления мотором.
  5. const int stepPin = 5;
  6. const int dirPin = 4;
  7. const int enPin = 7;
  8.  
  9. int count = 0;
  10.  
  11. // Переменные для ручного управления
  12. const int m_forward = 13;
  13. const int m_backward = 12;
  14.  
  15. // Переменные для датчиков-кнопок.
  16. const int ifSensorOpen = 11;
  17. const int ifSensorClosed = 10;
  18.  
  19.  
  20. // LOCK HUIOK.
  21. String _mainstatus = "unlock";
  22.  
  23. //Датчик дождя
  24. const int rainsensor = 3;
  25.  
  26.  
  27. String sensorStop = "";  // Датчик сработал.
  28. String _status = "";
  29. String _phone = "";
  30.  
  31. String _response    = "";                                     // Переменная для хранения ответа модуля
  32. long lastUpdate = millis();                                   // Время последнего обновления
  33. long updatePeriod   = 120000;                                  // Проверять каждые 2 минуты
  34.  
  35. String phones = "+37369777175, +37360450504, +37369277497";   // Белый список телефонов
  36.  
  37. void setup() {
  38.  
  39.   // Датчики препятствия открытия
  40.   pinMode(ifSensorOpen, INPUT_PULLUP);
  41.   pinMode(ifSensorClosed, INPUT_PULLUP);
  42.  
  43.  
  44. //Датчик дождя
  45.   pinMode(rainsensor, INPUT);
  46.  
  47.   // Ручное управление
  48.  
  49.   // Переменные для ручного управления
  50.   pinMode(m_forward, INPUT_PULLUP); // Открываем крышу
  51.   pinMode(m_backward, INPUT_PULLUP);   // Закрываем крышу
  52.  
  53.  
  54.   //Назначаем порты для двигателя
  55.   pinMode(stepPin, OUTPUT);
  56.   pinMode(dirPin, OUTPUT);
  57.   pinMode(enPin, OUTPUT);
  58.   digitalWrite(enPin, LOW);
  59.  
  60.  
  61.  
  62.   Serial.begin(9600);                                         // Скорость обмена данными с компьютером
  63.   SIM800.begin(9600);                                         // Скорость обмена данными с модемом
  64.   Serial.println("Start!");
  65.  
  66.   sendATCommand("AT", true);                                  // Отправили AT для настройки скорости обмена данными
  67.   sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память
  68.  
  69.   // Команды настройки модема при каждом запуске
  70.   _response = sendATCommand("AT+CLIP=1", true);             // Включаем АОН
  71.   //_response = sendATCommand("AT+DDET=1", true);             // Включаем DTMF
  72.   sendATCommand("AT+CMGF=1;&W", true);                        // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
  73.   lastUpdate = millis();                                      // Обнуляем таймер
  74. }
  75.  
  76. String sendATCommand(String cmd, bool waiting) {
  77.   String _resp = "";                                              // Переменная для хранения результата
  78.   Serial.println(cmd);                                            // Дублируем команду в монитор порта
  79.   SIM800.println(cmd);                                            // Отправляем команду модулю
  80.   if (waiting) {                                                  // Если необходимо дождаться ответа...
  81.     _resp = waitResponse();                                       // ... ждем, когда будет передан ответ
  82.     // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
  83.     if (_resp.startsWith(cmd)) {                                  // Убираем из ответа дублирующуюся команду
  84.       _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
  85.     }
  86.    // Serial.println(_resp);                                        // Дублируем ответ в монитор порта
  87.   }
  88.   return _resp;                                                   // Возвращаем результат. Пусто, если проблема
  89. }
  90.  
  91.  
  92. String waitResponse() {                                           // Функция ожидания ответа и возврата полученного результата
  93.   String _resp = "";                                              // Переменная для хранения результата
  94.   long _timeout = millis() + 10000;                               // Переменная для отслеживания таймаута (10 секунд)
  95.   while (!SIM800.available() && millis() < _timeout)  {};         // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  96.   if (SIM800.available()) {                                       // Если есть, что считывать...
  97.     _resp = SIM800.readString();                                  // ... считываем и запоминаем
  98.   }
  99.   else {                                                          // Если пришел таймаут, то...
  100.   //  Serial.println("Timeout...");                                 // ... оповещаем об этом и...
  101.   }
  102.   return _resp;                                                   // ... возвращаем результат. Пусто, если проблема
  103. }
  104.  
  105. bool hasmsg = false;   // Флаг наличия сообщений к удалению
  106. // НАЧАЛО ЛУПА. НАЧАЛО ЛУПА. НАЧАЛО ЛУПА. НАЧАЛО ЛУПА. НАЧАЛО ЛУПА. НАЧАЛО ЛУПА. НАЧАЛО ЛУПА. НАЧАЛО ЛУПА.
  107.  
  108.  
  109. void loop() {
  110.  
  111.  
  112.  
  113.  
  114. if (!digitalRead(ifSensorOpen) == 0 && _mainstatus != "lock") {
  115.     if (!digitalRead(m_forward) == 1) {
  116.     digitalWrite(dirPin, LOW); // Enables the motor to move in a particular direction
  117.   Serial.println("Manual Forward");
  118.       for (int x = 0; x < 70; x++) {
  119.        
  120.         digitalWrite(stepPin, HIGH);
  121.         delayMicroseconds(210);
  122.         digitalWrite(stepPin, LOW);
  123.         delayMicroseconds(210);
  124.       if (!digitalRead(ifSensorOpen) == 1) {
  125.                     sendSMS("+37369777175","Roof is opened by Button!");
  126.               sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память
  127.                   break;
  128.               }
  129.          }
  130.     }
  131.   }
  132.  
  133.    if (!digitalRead(ifSensorClosed) == 0 && _mainstatus != "lock") {
  134.  
  135.          if (!digitalRead(m_backward) == 1) {
  136.         //     Serial.println("Manual Backward");
  137.         digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction
  138.         for (int x = 0; x < 70; x++) {
  139.  
  140.         digitalWrite(stepPin, HIGH);
  141.         delayMicroseconds(210);
  142.         digitalWrite(stepPin, LOW);
  143.         delayMicroseconds(210);
  144.       }
  145.   }
  146.  
  147. }
  148.    
  149.  
  150.   if ((_status == "openroof" || _status == "closeroof")  && _mainstatus != "lock") {
  151.  
  152.     if (sensorStop == "true") {
  153.       sensorStop = "false";
  154.  
  155.    //   if (_status == "closeroof")    digitalWrite(dirPin, LOW);
  156.    //  else digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction
  157.       // Makes 200 pulses for making one full cycle rotation
  158.      
  159.       _status = "";
  160.       _phone = "";
  161.     } else {
  162.       setLedState(_status, _phone);
  163.     }
  164.   } else if (lastUpdate + updatePeriod < millis() && (!digitalRead(m_forward) == 0 || !digitalRead(m_backward) == 0 )) {                   // Пора проверить наличие новых сообщений
  165.     do {
  166.       if (!digitalRead(rainsensor) == 1) {
  167.                sendSMS("+37369777175"," RAIN! Check the CAMERA or CLOSE the roof!");
  168.       }
  169.  
  170.      
  171.       _response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true);// Отправляем запрос чтения непрочитанных сообщений
  172.      
  173.       if (_response.indexOf("+CMGL: ") > -1) {                    // Если есть хоть одно, получаем его индекс
  174.         int msgIndex = _response.substring(_response.indexOf("+CMGL: ") + 7, _response.indexOf("\"REC UNREAD\"", _response.indexOf("+CMGL: ")) - 1).toInt();
  175.         int i = 0;                                               // Объявляем счетчик попыток
  176.         do {
  177.           i++;                                                    // Увеличиваем счетчик
  178.           _response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);  // Пробуем получить текст SMS по индексу
  179.           Serial.println("readsms");
  180.           _response.trim();                                       // Убираем пробелы в начале/конце
  181.           if (_response.endsWith("OK")) {                         // Если ответ заканчивается на "ОК"
  182.             if (!hasmsg) hasmsg = true;                           // Ставим флаг наличия сообщений для удаления
  183.             sendATCommand("AT+CMGR=" + (String)msgIndex, true);   // Делаем сообщение прочитанным
  184.             sendATCommand("\n", true);                            // Перестраховка - вывод новой строки
  185.             parseSMS(_response);                                  // Отправляем текст сообщения на обработку
  186.         //    Serial.println(_response);
  187.             break;                                                // Выход из do{}
  188.           }
  189.           else {                                                  // Если сообщение не заканчивается на OK
  190.         //    Serial.println ("Error answer");                      // Какая-то ошибка
  191.             sendATCommand("\n", true);                            // Отправляем новую строку и повторяем попытку
  192.           }
  193.         } while (i < 10);
  194.         break;
  195.       }
  196.       else {
  197.         lastUpdate = millis();                                    // Обнуляем таймер
  198.  
  199.         if (hasmsg) {
  200.           sendATCommand("AT+CMGDA=\"DEL ALL\"", true);           // Удаляем все сообщения
  201.           hasmsg = false;
  202.         }
  203.         break;
  204.       }
  205.     } while (1);
  206.   }
  207.  
  208.   if (SIM800.available())   {                         // Если модем, что-то отправил...
  209.     _response = waitResponse();                       // Получаем ответ от модема для анализа
  210.     _response.trim();                                 // Убираем лишние пробелы в начале и конце
  211.     Serial.println(_response);                        // Если нужно выводим в монитор порта
  212.     if (_response.indexOf("+CMTI:") > -1) {           // Пришло сообщение об отправке SMS
  213.       lastUpdate = millis() -  updatePeriod;          // Теперь нет необходимости обрабатываеть SMS здесь, достаточно просто
  214.       // сбросить счетчик автопроверки и в следующем цикле все будет обработано
  215.     }
  216.   }
  217.   if (Serial.available())  {                          // Ожидаем команды по Serial...
  218.     SIM800.write(Serial.read());                      // ...и отправляем полученную команду модему
  219.   };
  220. }
  221.  
  222. void parseSMS(String msg) {                                   // Парсим SMS
  223.   String msgheader  = "";
  224.   String msgbody    = "";
  225.   String msgphone   = "";
  226.  
  227.   msg = msg.substring(msg.indexOf("+CMGR: "));
  228.   msgheader = msg.substring(0, msg.indexOf("\r"));            // Выдергиваем телефон
  229.  
  230.   msgbody = msg.substring(msgheader.length() + 2);
  231.   msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));  // Выдергиваем текст SMS
  232.   msgbody.trim();
  233.  
  234.   int firstIndex = msgheader.indexOf("\",\"") + 3;
  235.   int secondIndex = msgheader.indexOf("\",\"", firstIndex);
  236.   msgphone = msgheader.substring(firstIndex, secondIndex);
  237.  
  238.  // Serial.println("Phone: " + msgphone);                       // Выводим номер телефона
  239.  // Serial.println("Message: " + msgbody);                      // Выводим текст SMS
  240.  
  241.   if (msgphone.length() > 6 && phones.indexOf(msgphone) > -1) { // Если телефон в белом списке, то...
  242.     _status = msgbody;
  243.     _phone = msgphone;
  244.     setLedState(msgbody, msgphone);                           // ...выполняем команду
  245.   }
  246.   else {
  247.     Serial.println("Unknown phonenumber");
  248.   }
  249. }
  250.  
  251.  
  252. void setLedState (String result, String phone) {
  253.   bool correct = false;                                       // Для оптимизации кода, переменная корректности команды
  254.   String msgToSend = "";
  255.   if (result == "openroof") {
  256.     if  ( _mainstatus == "lock") {
  257.            sendSMS("+37369777175","Roof is LOCKED! Send \"unlock\" to unlock");
  258.       } else {
  259.         Serial.println("roof is opening");
  260.           digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction
  261.           if (count >= 13){
  262.             sensorStop = "true";
  263.             count = 0;
  264.             sendSMS("+37369777175","Roof is opened by COUNTER!");
  265.               sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память
  266.             } else {
  267.             // Makes 200 pulses for making one full cycle rotation
  268.             for (int x = 0; x < 25400; x++) {
  269.        
  270.               digitalWrite(stepPin, HIGH);
  271.               delayMicroseconds(225);
  272.               digitalWrite(stepPin, LOW);
  273.               delayMicroseconds(225);
  274.  
  275.               if (!digitalRead(ifSensorClosed) == 1) {
  276.                 sensorStop = "true";
  277.                 Serial.println("Break Done");
  278.                 sendSMS("+37369777175","Roof is opened by BUTTON!");
  279.                   sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память
  280.                 count = 0;
  281.                 break;
  282.                
  283.               }
  284.  
  285.             }
  286.             int x = 0;
  287.             count++;
  288.             Serial.print("counter: ");    
  289.             Serial.println(count);    
  290.          }
  291.           correct = true;
  292.       }
  293.   } else if (result == "closeroof") {
  294.     if  ( _mainstatus == "lock") {
  295.            sendSMS("+37369777175","Roof is LOCKED! Send \"unlock\" to unlock");
  296.       } else {
  297.     digitalWrite(dirPin, LOW); // Enables the motor to move in a particular direction
  298.  
  299.     if (count >= 13){
  300.       sensorStop = "true";
  301.       count = 0;
  302.       sendSMS("+37369777175","Roof is closed by COUNTER!");
  303.         sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память
  304.       } else {
  305.         // Makes 200 pulses for making one full cycle rotation
  306.           for (int x = 0; x < 25400; x++) {
  307.      
  308.             digitalWrite(stepPin, HIGH);
  309.             delayMicroseconds(225);
  310.             digitalWrite(stepPin, LOW);
  311.             delayMicroseconds(225);
  312.      
  313.             if (!digitalRead(ifSensorOpen) == 1) {
  314.               sensorStop = "true";
  315.               Serial.println("Break Done");
  316.               sendSMS("+37369777175","Roof is closed by BUTTON!");
  317.                 sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память
  318.               count = 0;
  319.               break;
  320.              
  321.             }
  322.    
  323.           }
  324.             int x = 0;
  325.             count++;
  326.             Serial.print("counter: ");    
  327.             Serial.println(count);
  328.         }  
  329.     correct = true;                                         // Флаг корректности команды
  330.      }
  331.   }  
  332.  
  333.   else if (result == "unlock") {
  334.              _mainstatus = "unlock";
  335.              sendSMS("+37369777175","Roof is UNLOCKED");
  336.                sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память
  337.           }
  338.  
  339.   if (!correct) {
  340.     msgToSend = "Incorrect command: " + result;               // Статус исполнения
  341.   }
  342.   Serial.println(msgToSend);                                  // Выводим результат в терминал
  343.  
  344. }
  345.  
  346.  
  347. void sendSMS(String phone, String message)
  348. {
  349.   sendATCommand("AT+CMGS=\"" + phone + "\"", true);             // Переходим в режим ввода текстового сообщения
  350.   sendATCommand(message + "\r\n" + (String)((char)26), true);   // После текста отправляем перенос строки и Ctrl+Z
  351. }
RAW Paste Data