Отправка 6 переменных в одном СМС с помощью SIM800L

k60
Offline
Зарегистрирован: 30.03.2018

Всем привет! Прошу сильно не пинать, так как я новичок! Третий день ломаю голову и не могу решить проблему: имеется Arduino Uno с подключенными датчиками (температуры и влажности воздуха, освещения, влажности почвы, температуры почвы, открытой форточки) и модулем SIM800L. Необходимо сделать так, чтобы при получении модулем СМС с цифрой "1" включалось реле на несколько секунд для полива, а при получении СМС с цифрой "2" модуль отправлял в ответ СМС, в котором бы высылались 6 переменных с показаниями, снимаемыми с датчиков (температура, влажность и т.д.).

Чтобы не усложнять ситуацию, пока тренируюсь на датчике DHT22, пробуя отправить в СМС всего две переменных. Но, пока что максимум, чего смог добится - это отправки какого-то одного показателя, а вот как вывести сразу два (температура и влажность)?

#include <SoftwareSerial.h>               // Библиотека програмной реализации обмена по UART-протоколу
SoftwareSerial SIM800(8, 9);             // RX, TX

#include "DHT.h"                         //dht22
#define DHTPIN 2                       //dht22
#define DHTTYPE DHT22                    //dht22
DHT dht(DHTPIN, DHTTYPE);                //dht22


int pins = 5;                                                 // Пин с подключенным реле

String _response    = "";                                     // Переменная для хранения ответа модуля
long lastUpdate = millis();                                   // Время последнего обновления
long updatePeriod   = 60000;                                  // Проверять каждую минуту

String phones = "+7920269****";   // Белый список телефонов

void setup() {

  dht.begin(); //dht
  pinMode(pins, OUTPUT);                                      // Настраиваем пины в OUTPUT
  digitalWrite(pins, HIGH);                                   // Изначально реле выключено
  Serial.begin(9600);                                         // Скорость обмена данными с компьютером
  SIM800.begin(9600);                                         // Скорость обмена данными с модемом
  Serial.println("Start!");

  sendATCommand("AT", true);                                  // Отправили AT для настройки скорости обмена данными
  sendATCommand("AT+CMGDA=\"DEL ALL\"", true);               // Удаляем все SMS, чтобы не забивать память

  // Команды настройки модема при каждом запуске
  sendATCommand("AT+CMGF=1;&W", true);                        // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
  lastUpdate = millis();                                      // Обнуляем таймер
}

String sendATCommand(String cmd, bool waiting) {
  String _resp = "";                                              // Переменная для хранения результата
  Serial.println(cmd);                                            // Дублируем команду в монитор порта
  SIM800.println(cmd);                                            // Отправляем команду модулю
  if (waiting) {                                                  // Если необходимо дождаться ответа...
    _resp = waitResponse();                                       // ... ждем, когда будет передан ответ
    // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
    if (_resp.startsWith(cmd)) {                                  // Убираем из ответа дублирующуюся команду
      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
    }
    Serial.println(_resp);                                        // Дублируем ответ в монитор порта
  }
  return _resp;                                                   // Возвращаем результат. Пусто, если проблема
}

String waitResponse() {                                           // Функция ожидания ответа и возврата полученного результата
  String _resp = "";                                              // Переменная для хранения результата
  long _timeout = millis() + 10000;                               // Переменная для отслеживания таймаута (10 секунд)
  while (!SIM800.available() && millis() < _timeout)  {};         // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  if (SIM800.available()) {                                       // Если есть, что считывать...
    _resp = SIM800.readString();                                  // ... считываем и запоминаем
  }
  else {                                                          // Если пришел таймаут, то...
    Serial.println("Timeout...");                                 // ... оповещаем об этом и...
  }
  return _resp;                                                   // ... возвращаем результат. Пусто, если проблема
}

bool hasmsg = false;                                              // Флаг наличия сообщений к удалению



void loop() {

  float h = dht.readHumidity(); //DHT
  float t = dht.readTemperature(); //DHT

  Serial.print("Humidity: "); //DHT    // выводим данные температуры и влажности в Serial
  Serial.print(h);//DHT
  Serial.print(" %\t");//DHT
  Serial.print("Temperature: "); //DHT
  Serial.print(t);//DHT
  Serial.println(" *C");//DHT



  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: "))).toInt();
        char i = 0;                                               // Объявляем счетчик попыток
        do {
          i++;                                                    // Увеличиваем счетчик
          _response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);  // Пробуем получить текст SMS по индексу
          _response.trim();                                       // Убираем пробелы в начале/конце
          if (_response.endsWith("OK")) {                         // Если ответ заканчивается на "ОК"
            if (!hasmsg) hasmsg = true;                           // Ставим флаг наличия сообщений для удаления
            sendATCommand("AT+CMGR=" + (String)msgIndex, true);   // Делаем сообщение прочитанным
            sendATCommand("\n", true);                            // Перестраховка - вывод новой строки
            parseSMS(_response);                                  // Отправляем текст сообщения на обработку
            break;                                                // Выход из do{}
          }
          else {                                                  // Если сообщение не заканчивается на OK
            Serial.println ("Error answer");                      // Какая-то ошибка
            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();                                 // Убираем лишние пробелы в начале и конце
    Serial.println(_response);                        // Если нужно выводим в монитор порта
    if (_response.indexOf("+CMTI:") > -1) {           // Пришло сообщение об отправке SMS
      lastUpdate = millis() -  updatePeriod;          // Теперь нет необходимости обрабатываеть SMS здесь, достаточно просто
      // сбросить счетчик автопроверки и в следующем цикле все будет обработано
    }
  }
  if (Serial.available())  {                          // Ожидаем команды по Serial...
    SIM800.write(Serial.read());                      // ...и отправляем полученную команду модему
  };
}



void parseSMS(String msg) {                                   // Парсим SMS
  String msgheader  = "";
  String msgbody    = "";
  String msgphone   = "";

  msg = msg.substring(msg.indexOf("+CMGR: "));
  msgheader = msg.substring(0, msg.indexOf("\r"));            // Выдергиваем телефон

  msgbody = msg.substring(msgheader.length() + 1);        // правил + 1. Было ( msgbody = msg.substring(msgheader.length() + 2);)
  msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));  // Выдергиваем текст SMS
  msgbody.trim();

  int firstIndex = msgheader.indexOf("\",\"") + 3;
  int secondIndex = msgheader.indexOf("\",\"", firstIndex);
  msgphone = msgheader.substring(firstIndex, secondIndex);

  Serial.println("Phone: " + msgphone);                       // Выводим номер телефона
  Serial.println("Message: " + msgbody);                      // Выводим текст SMS

  if (msgphone.length() > 6 && phones.indexOf(msgphone) > -1) { // Если телефон в белом списке, то...
    setLedState(msgbody, msgphone);                           // ...выполняем команду
  }
  else {
    Serial.println("Unknown phonenumber");
  }
}


void setLedState (String result, String phone) {
  bool correct = false;                                       // Для оптимизации кода, переменная корректности команды
  String msgToSend = "";

  if (result.length() == 1) {
    int ledIndex = ((String)result[0]).toInt();               // Получаем первую цифру команды

    if (ledIndex == 1 ) // Если все нормально, исполняем команду
    {
      float t = dht.readTemperature(); //DHT
      int SMSTEMP = t; //DHT
      //digitalWrite(pins, LOW);             // Включаем реле
      Serial.println("Otpravka SMS Temp");
      delay(3000);                           // Ждем 3 секунды
      sendSMS("+7920269****", String (SMSTEMP));
      correct = true;                                         // Флаг корректности команды
    }


    if (ledIndex == 2 ) // Если все нормально, исполняем команду
    {
      digitalWrite(pins, LOW);             // Включаем реле
      Serial.println("POLIV 2!");
      delay(3000);                           // Ждем 3 секунды
      digitalWrite(pins, HIGH);           // Выключаем реле
      Serial.println("POLIV 2 OKONCHEN");
      sendSMS("+7920269****", "POLIV 2 OKONCHEN");
      delay(5000);
      correct = true;                                         // Флаг корректности команды
    }


  }
  if (!correct) {
    msgToSend = "Incorrect command: " + result;               // Статус исполнения
  }
  Serial.println(msgToSend);                                  // Выводим результат в терминал
}


void sendSMS(String phone, String message)
{
  sendATCommand("AT+CMGS=\"" + phone + "\"", true);             // Переходим в режим ввода текстового сообщения
  sendATCommand(message + "\r\n" + (String)((char)26), true);   // После текста отправляем перенос строки и Ctrl+Z
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

k60 пишет:

Прошу сильно не пинать, так как я новичок!

Объясните мне, с какого перепугу Вас нельзя пинать? Потому, что Вы новичок? А кого прикажете пинать? Заслуженных ветеранов? У Вас с логикой всё нормально? Как раз новичков и надо пороть, чтобы ума набирались.

k60 пишет:

Третий день ломаю голову

А сюда чего пришли? Поломайте месяца три, проблема и решится, так хоть Вам польза будет.

k60 пишет:

Чтобы не усложнять ситуацию .... пока что максимум, чего смог добится - это отправки какого-то одного показателя

Чтобы не усложнять ситуацию, объясню Вам, что человек, который не может отправить две переменные в сообщении, в принципе, ни за какие коврижки, не способен написать код, который Вы привели. Код это не Ваш. А потому, всё, "чего Вы смогли добиться" - это стырить готовый код (вот здесь, возможно) и ни хрена в нём не понять.

Поэтому, давайте поступим так. Берите книжку. Хоть вот эту - она написана проще некуда - для совсем уж альтернативно одарённых. Изучайте, разбирайтесь. Потом напишите свой код отправки Ваших переменных и, если с ним будут проблемы, приходите, Вам помогут (я сам с удовольствием помогу).

А изменять для Вас чужой код, который Вы не только не писали, но даже и не понимаете - увольте. Сильно нужно - топайте в раздел "Ищу исполнителя" и заказывайте за деньги.

k60
Offline
Зарегистрирован: 30.03.2018

А я разве говорил, что код мой? Именно там, где Вы сказали я его и взял, теперь пытаюсь упростить под свои нужды, пока безуспешно. За книжку спасибо, почитаем!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

k60 пишет:

А я разве говорил, что код мой? 

Конечно. "чего смог добится" по мне это означает, что Вы добились, а не автор кода, которого Вы даже не поняли.