SIM800L mini

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Общий вид контроллера со снятой крышкой.

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

В корпусе установлен модуль питания ~220v -> 5V 3A.
Мощности модуля питания достаточно для питания ARDUINO Nano и модема SIM800L.

Поскольку питание каждого из модулей осуществляется от одного источника +5В, а SIM800L требует 4В, то запитка последнего осуществляется через 2 последовательно включенных диода, рассчитанных на ток 2 А. 
Параллельно выводу питания SIM800L подключены 4 электролитических конденсатора 1000 мкФ х 6.3 В.
В этом случае обеспечивается стабильная связь SIM800L с базовой станцией.

 Все протестировано с помощью АТ команд. Модуль подтвердил исправность и стабильную работу.

Содержимое скетча для тестирования не привожу, поскольку подобное было рассмотрено на этом форуме.
 

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Для надежной связи с базовой станцией антенна модема SIM800L вынесена наружу и закреплена на боковой стенке. Отрицательный вывод модуля питания соединен с металлическим корпусом контроллера.

                                         

                              

 

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

-

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

   Вот тут начались танцы с бубном...

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

   Признаком отказа системы отопления является падение температуры трубы для вывода топочных газов.
   При штатном режиме работы отопления эта температура изменяется в диапазоне +45 - +65 °С.
   Температура измеряется с помощью DS 18b20. Проблем кодом не оказалось...
   По запросу текущую температуру получаю СМС -кой на мой телефон. 

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

 

001// Все работает !!!
002// С мобильного телефона можем отправлять SMS сообщения следующего вида 001 ....... 99999 итого 100000 комбинаций....
003// С мобильного телефона можем отправлять SMS сообщения следующего вида *100# и другие
004/*
005На базе этого скетча попытаемся написать код управления для мониторинга текущей температуры датчика,
006для отправки СМС на мой смартфон в случае потухания котла,
007для получения баланса СИМ карты  МТС Беларусь. СИМ-ка установлена в слоте SIM800L.
008*/
009  
010#include <SoftwareSerial.h>                                   // Библиотека програмной реализации обмена по UART-протоколу
011SoftwareSerial SIM800(8, 9);                                  // RX, TX
012  
013// int pins[3] = {5, 6, 7};                                      // Пины с подключенными светодиодами
014  
015String _response    = "";                                     // Переменная для хранения ответа модуля
016long lastUpdate = millis();                                   // Время последнего обновления
017long updatePeriod   = 60000;                                  // Проверять каждую минуту
018  
019String phones = "+37529-------";                              // Белый список телефонов - Это мой мобильник A1
020  
021void setup()
022{
023   
024  Serial.begin(9600);                                         // Скорость обмена данными с компьютером
025  SIM800.begin(9600);                                         // Скорость обмена данными с модемом
026  Serial.println("Start!");
027  
028  sendATCommand("AT", true);                                  // Отправили AT для настройки скорости обмена данными
029  sendATCommand("AT+CMGDA=\"DEL ALL\"", true);                // Удаляем все SMS, чтобы не забивать память
030  
031  // Команды настройки модема при каждом запуске
032  _response = sendATCommand("AT+CLIP=1", true);               // Включаем АОН
033  _response = sendATCommand("AT+DDET=1", true);               // Включаем DTMF
034  sendATCommand("AT+CMGF=1;&W", true);                        // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
035  lastUpdate = millis();                                      // Обнуляем таймер
036}
037  
038String sendATCommand(String cmd, bool waiting) {
039  String _resp = "";                                              // Переменная для хранения результата
040  Serial.println(cmd);                                            // Дублируем команду в монитор порта
041  SIM800.println(cmd);                                            // Отправляем команду модулю
042  if (waiting) {                                                  // Если необходимо дождаться ответа...
043  _resp = waitResponse();                                         // ... ждем, когда будет передан ответ
044                                                                  // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
045    if (_resp.startsWith(cmd)) {                                  // Убираем из ответа дублирующуюся команду
046      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
047    }
048    Serial.println(_resp);                                        // Дублируем ответ в монитор порта
049  }
050  return _resp;                                                   // Возвращаем результат. Пусто, если проблема
051}
052  
053String waitResponse() {                                           // Функция ожидания ответа и возврата полученного результата
054  String _resp = "";                                              // Переменная для хранения результата
055  long _timeout = millis() + 5000;                                // Переменная для отслеживания таймаута (5 секунд)
056  while (!SIM800.available() && millis() < _timeout)  {};         // Ждем ответа 5 секунд, если пришел ответ или наступил таймаут, то...
057  if (SIM800.available()) {                                       // Если есть, что считывать...
058    _resp = SIM800.readString();                                  // ... считываем и запоминаем
059  }
060  else {                                                          // Если пришел таймаут, то...
061    Serial.println("Timeout...");                                 // ... оповещаем об этом и...
062  }
063  return _resp;                                                   // ... возвращаем результат. Пусто, если проблема
064}
065  
066bool hasmsg = false;                                              // Флаг наличия сообщений к удалению
067void loop() {
068  if (lastUpdate + updatePeriod < millis() ) {                    // Пора проверить наличие новых сообщений
069    do {
070      _response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true);// Отправляем запрос чтения непрочитанных сообщений
071      if (_response.indexOf("+CMGL: ") > -1) {                    // Если есть хоть одно, получаем его индекс
072        int msgIndex = _response.substring(_response.indexOf("+CMGL: ") + 7, _response.indexOf("\"REC UNREAD\"", _response.indexOf("+CMGL: ")) - 1).toInt();
073        char i = 0;                                               // Объявляем счетчик попыток
074        do {
075          i++;                                                    // Увеличиваем счетчик
076          _response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);  // Пробуем получить текст SMS по индексу
077          _response.trim();                                       // Убираем пробелы в начале/конце
078          if (_response.endsWith("OK")) {                         // Если ответ заканчивается на "ОК"
079            if (!hasmsg) hasmsg = true;                           // Ставим флаг наличия сообщений для удаления
080            sendATCommand("AT+CMGR=" + (String)msgIndex, true);   // Делаем сообщение прочитанным
081            sendATCommand("\n", true);                            // Перестраховка - вывод новой строки
082            parseSMS(_response);                                  // Отправляем текст сообщения на обработку
083            break;                                                // Выход из do{}
084          }
085          else {                                                  // Если сообщение не заканчивается на OK
086            Serial.println ("Error answer");                      // Какая-то ошибка
087            sendATCommand("\n", true);                            // Отправляем новую строку и повторяем попытку
088          }
089        } while (i < 10);
090        break;
091      }
092      else {
093        lastUpdate = millis();                                    // Обнуляем таймер
094        if (hasmsg) {
095          sendATCommand("AT+CMGDA=\"DEL READ\"", true);           // Удаляем все прочитанные сообщения
096          hasmsg = false;
097        }
098        break;
099      }
100    } while (1);
101  }
102  
103  if (SIM800.available())   {                                     // Если модем, что-то отправил...
104    _response = waitResponse();                                   // Получаем ответ от модема для анализа
105    _response.trim();                                             // Убираем лишние пробелы в начале и конце
106    Serial.println(_response);                                    // Если нужно выводим в монитор порта
107    if (_response.indexOf("+CMTI:")>-1) {                         // Пришло сообщение об отправке SMS
108      lastUpdate = millis() -  updatePeriod;                      // Теперь нет необходимости обрабатывать SMS здесь, достаточно просто
109                                                                  // сбросить счетчик автопроверки и в следующем цикле все будет обработано
110    }
111  }
112  if (Serial.available())  {                                      // Ожидаем команды по Serial...
113    SIM800.write(Serial.read());                                  // ...и отправляем полученную команду модему
114  };
115}
116  
117void parseSMS(String msg) {                                       // Парсим SMS
118  String msgheader  = "";
119  String msgbody    = "";
120  String msgphone   = "";
121  
122  msg = msg.substring(msg.indexOf("+CMGR: "));
123  msgheader = msg.substring(0, msg.indexOf("\r"));                // Извлекаем номер телефона отправившего СМС запрос
124  
125  msgbody = msg.substring(msgheader.length() + 1);                // не менять
126  msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));      // Извлекаем текст SMS
127  msgbody.trim();
128  //Serial.println();
129  int firstIndex = msgheader.indexOf("\",\"") + 3;                // не менять
130  int secondIndex = msgheader.indexOf("\",\"", firstIndex);
131  msgphone = msgheader.substring(firstIndex, secondIndex);
132  
133  Serial.println("Phone: " + msgphone);                           // Выводим номер телефона
134  Serial.println("Message: " + msgbody);                          // Выводим текст SMS
135  
136  if (msgphone.length() > 6 && phones.indexOf(msgphone) > -1)     // Если телефон в белом списке, то...
137  {  
138    // =====================================================================================================================================
139       sendSMS(phones, "Полученная СМС - ка:"+msgbody );              //ОТПРАВКА НА БЕЛЫЕ ТЕЛЕФОНЫ РЕЗУЛЬТАТА ВЫПОЛНЕНИЯ КОМАНДЫ !!!!!!!
140  
141  // =====================================================================================================================================
142  }
143  else {
144    Serial.println("Unknown phonenumber");
145    }
146}      // ============================================   End void parseSMS(String msg)  ==================================================
147  
148  
149void sendSMS(String phone, String message)
150{
151  sendATCommand("AT+CMGF=1", true);                               // Включаем текстовый режима SMS (Text mode)
152  sendATCommand("AT+CMGS=\"" + phone + "\"", true);               // Переходим в режим ввода текстового сообщения
153  sendATCommand(message + "\r\n" + (String)((char)26), true);     // После текста отправляем перенос строки и Ctrl+Z
154}

 

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

   

001// ЭТО УЖЕ РАБОТАЕТ !!!
002  #include <SoftwareSerial.h>                             // Библиотека програмной реализации обмена по UART-протоколу
003  SoftwareSerial SIM800(8, 9);                            // RX, TX
004  String _response = "";                                  // Переменная для хранения ответа модуля
005  String _phone_to_SMS = "+375---------";                 // Сюда пишем свой номер телефона в международном формате
006  void setup() {
007  Serial.begin(9600);                                     // Скорость обмена данными с компьютером
008  SIM800.begin(9600);                                     // Скорость обмена данными с модемом
009  Serial.println("Start!");
010 
011  sendATCommand("AT", true);                              // Отправили AT для настройки скорости обмена данными
012 
013  // Команды настройки модема при каждом запуске
014  _response = sendATCommand("AT+CLIP=1", true);           // Включаем АОН
015  //_response = sendATCommand("AT+DDET=1", true);         // Включаем DTMF
016  _response = sendATCommand("AT+CMGF=1", true);           // Включаем текстовый режим SMS (Text mode)
017  _response = sendATCommand("AT+CUSD=1,\"*100#\"", true); // Здесь необходимо указать свой USSD-запрос
018}
019 
020String sendATCommand(String cmd, bool waiting) {
021  String _resp = "";                                      // Переменная для хранения результата
022  Serial.println(cmd);                                    // Дублируем команду в монитор порта
023  SIM800.println(cmd);                                    // Отправляем команду модулю
024  if (waiting) {                                          // Если необходимо дождаться ответа...
025    _resp = waitResponse();                               // ... ждем, когда будет передан ответ
026                                                          // Если Echo Mode выключен (ATE0), то эти 3 строки можно закоментировать
027    if (_resp.startsWith(cmd)) {                          // Убираем из ответа дублирующуюся команду
028      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
029    }
030    Serial.println(_resp);                                // Дублируем ответ в монитор порта
031  }
032  return _resp;                                           // Возвращаем результат. Пусто, если проблема
033}
034 
035String waitResponse() {                                   // Функция ожидания ответа и возврата полученного результата
036  String _resp = "";                                      // Переменная для хранения результата
037  long _timeout = millis() + 5000;                        // Переменная для отслеживания таймаута (5 секунд)
038  while (!SIM800.available() && millis() < _timeout)  {}; // Ждем ответа 5 секунд, если пришел ответ или наступил таймаут, то...
039  if (SIM800.available()) {                               // Если есть, что считывать...
040    _resp = SIM800.readString();                          // ... считываем и запоминаем
041  }
042  else {                                                  // Если пришел таймаут, то...
043    Serial.println("Timeout...");                         // ... оповещаем об этом и...
044  }
045  return _resp;                                           // ... возвращаем результат. Пусто, если проблема
046}
047                  // ==================  Цикл void loop ========================
048void loop() {                                                                                                                                          //=
049  if (SIM800.available())   {                             // Если модем, что-то отправил...                                                              =
050    _response = waitResponse();                           // Получаем ответ от модема для анализа                                                        =
051    _response.trim();                                     // Убираем лишние пробелы в начале и конце                                                     =
052    Serial.println(_response);                            // Если нужно выводим в монитор порта                                                          =
053    //....                                                                                                                                               =
054    if (_response.startsWith("+CUSD:")) {                  // Пришло уведомление о USSD-ответе                                                 =
055      if (_response.indexOf("\"") > -1) {          // Если ответ содержит кавычки, значит есть сообщение                               =
056                                                                     //(предохранитель от "пустых" USSD-ответов)                               =
057        String msgBalance = _response.substring(_response.indexOf("\"") + 2);  // Получаем непосредственно текст                          =
058        msgBalance = msgBalance.substring(0, msgBalance.indexOf("\""));                                                                 //=
059        Serial.println("USSD: " + msgBalance);            // Выводим полученный USSD-ответ                                                     =
060                                                                                                                                                       //=
061       float balance = getFloatFromString(msgBalance);    // Извлекаем информацию о балансе                                                              =
062                                                                                                                                                       //=
063    Serial.println("\r\nBalance: " + (String)balance );   // Выводим информацию о балансе                                                      =
064        sendSMS(_phone_to_SMS, "\r\nBalance: " + (String)balance);                                                                           //=
065      }                                                                                                                                                //=
066    }                                                                                                                                                  //=
067  }                                                                                                                                                    //=
068   if (Serial.available())  {                    // Ожидаем команды по Serial...                                                                       //=
069    SIM800.write(Serial.read());                // ...и отправляем полученную команду модему                                                           //=
070  };                                                                                                                                                   //=
071}      //========================================================================
072 
073void sendSMS(String phone, String message)
074{
075  String _result = "";
076  sendATCommand("AT+CMGF=1", true);                                         // Включаем текстовый режима SMS (Text mode)
077  sendATCommand("AT+CMGS=\"" + phone + "\"", true);                         // Переходим в режим ввода текстового сообщения
078  _result = sendATCommand(message + (String)((char)26), true);              // После текста отправляем перенос строки и Ctrl+Z
079}
080 
081float getFloatFromString(String str) {                                      // Функция извлечения цифр из сообщения - для парсинга баланса из USSD-запроса
082  bool   flag     = false;
083  String result   = "";
084  str.replace(",", ".");                                                    // Если в качестве разделителя десятичных используется запятая - меняем её на точку.
085  for (int i = 0; i < str.length(); i++) {
086    if (isDigit(str[i]) || (str[i] == (char)46 && flag)) {                  // Если начинается группа цифр (при этом, на точку без цифр не обращаем внимания),
087      if (result == "" && i > 0 && (String)str[i - 1] == "-") {             // Нельзя забывать, что баланс может быть отрицательным
088        result += "-";                                                      // Добавляем знак в начале
089      }
090      result += str[i];                                                     // начинаем собирать их вместе
091      if (!flag) flag = true;                                               // Выставляем флаг, который указывает на то, что сборка числа началась.
092    }
093    else  {                                                                 // Если цифры закончились и флаг говорит о том, что сборка уже была,
094      if (str[i] != (char)32) {                                             // Если порядок числа отделен пробелом - игнорируем его, иначе...
095        if (flag) break;                                                    // ...считаем, что все.
096      }
097    }
098  }
099  return result.toFloat();                                                  // Возвращаем полученное число.
100}
wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

    Поскольку домик находится в 150 км от Минска, то возникла необходимость проверка текущего баланса на счету. Приведенный выше скетч с этой задачей справляется.

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

   Должен сказать, что приведенные выше тексты написаны не мною. Эти тексты взяты на Codius.ru и мною адаптированы под решаемую задачу. Должен сказать о хорошем качестве выложенной информации на этом сайте. Все выложенные примеры работоспособны.

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

   Эти скетчи каждый  сам по себе работают.
Первый скетч возвращает посланное в контроллер сообщение на телефон. 
Второй скетч высылает баланс, актуальный в данный момент времени.
Попытки все объединить в один скетч к успеху не привели. 
К тому же нужно прописать реагирование на 2 ситуации - снижение температуры ниже 40 °С и  наступление момента отрицательного баланса. Белорусский МТС позволяет иметь небольшой отрицательный баланс.

Прошу сообщество оказать мне помощь в решении проблемы. Нужны советы и работающие примеры.
В принципе с этой задачей могу справиться сам. Но возраст почти 70 лет и не очень хорошее знание С++ не способствуют быстрому решению этой задачи... 

Другое дело помочь сделать 3D модель корпуса для электронных поделок, которые можно распечатать на 3D принтере... Или сделать рабочие чертежи, используя разработанную 3D модель...
Этим владею на уровне эксперта и обучаю этому студентов БГУ.

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Вот работающее решение. Вывод DQ датчика DS18b20 подключен к выводу D12 Arduino nano

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021
001#include <SoftwareSerial.h>
002#include <OneWire.h>
003#include <DallasTemperature.h>
004#define ONE_WIRE_BUS 12
005 
006 
007SoftwareSerial SIM800(8, 9);
008OneWire oneWire(ONE_WIRE_BUS);
009DallasTemperature sensors(&oneWire);
010 
011 
012const String MAIN_PHONE = "+************";       // напишите сюда свой номер в международном формате
013const String PDU_USSD_BALANCE_QUERY = "AT+CUSD=1,\"*100#\""; // пишем код для своего оператора
014const String TEXT_USSD_BALANCE_QUERY = "AT+CUSD=1,\"#100#\""; // пишем код для своего оператора
015const String BALANCE_TEXT_QUERY = "Balance";                    // содержание СМС для получения текстового ответа на запрос о балансе            
016const String BALANCE_PDU_QUERY = "Balance ussd";                // содержание СМС для получения PDU ответа на запрос о балансе
017const String TEMPERATURE_QUERY = "Temperature";                 // содержание СМС для получения ответа на запрос о температуре
018const String CURRENCY = " BYN";                                 // текстовое представление валюты
019const float  BALANCE_TRESHOLD = 5.0;                            // нижнее пороговое значение баланса
020const float  TEMPERATURE_TRESHOLD = 35.0;                       // нижнее пороговое значение температуры
021bool         hasmsg = false;
022 
023 
024String sendATCommand(const String& cmd, bool waiting) {
025  String response = "";                                      // Переменная для хранения результата
026  Serial.println(cmd);                                    // Дублируем команду в монитор порта
027  SIM800.println(cmd);                                    // Отправляем команду модулю
028  if (waiting) {                                          // Если необходимо дождаться ответа...
029    response = waitResponse();                               // ... ждем, когда будет передан ответ
030    if (response.startsWith(cmd)) {                          // Убираем из ответа дублирующуюся команду
031      response = response.substring(response.indexOf("\r", cmd.length()) + 2);
032    }
033    Serial.println(response );                               // Дублируем ответ в монитор порта
034  }
035  return response;                                           // Возвращаем результат. Пусто, если проблема
036}
037 
038String waitResponse() {                                   // Функция ожидания ответа и возврата полученного результата
039  String response = "";                                      // Переменная для хранения результата
040  int64_t timeout = millis() + 10000;                        // Переменная для отслеживания таймаута (5 секунд)
041  while (!SIM800.available() && millis() < timeout) {}; // Ждем ответа 5 секунд, если пришел ответ или наступил таймаут, то...
042  if (SIM800.available()) {                               // Если есть, что считывать...
043    response = SIM800.readString();                          // ... считываем и запоминаем
044  }
045  else {                                                  // Если пришел таймаут, то...
046    Serial.println("Timeout...");                         // ... оповещаем об этом и...
047  }
048  return response;                                           // ... возвращаем результат. Пусто, если проблема
049}
050 
051void sendSMS(const String& phone, const String& message) {
052  sendATCommand("AT+CMGS=\"" + phone + "\"", true);                         // Переходим в режим ввода текстового сообщения
053  sendATCommand(message + (String)((char)26), true);                        // После текста отправляем перенос строки и Ctrl+Z
054}
055 
056void getBalance() {
057  sendATCommand(PDU_USSD_BALANCE_QUERY, true);
058  String answer = waitResponse();
059  answer.trim();
060  String msgBalance = answer.substring(answer.indexOf("\"") + 1);  // Получаем непосредственно текст
061  msgBalance = msgBalance.substring(0, msgBalance.indexOf("\""));
062  float balance = getFloatFromString(UCS2ToString(msgBalance));    // Извлекаем информацию о балансе
063  sendSMS(MAIN_PHONE, "\r\nBalans SIM karty: " + (String)balance + CURRENCY + ".");
064}
065 
066void alternativeGetBalance() {
067  sendATCommand(TEXT_USSD_BALANCE_QUERY, true);
068  String answer = waitResponse();
069  answer.trim();
070  if (answer.indexOf("\"") > -1) {
071    String msgBalance = answer.substring(answer.indexOf("\"") + 2);
072    msgBalance = msgBalance.substring(0, msgBalance.indexOf("\""));
073    float balance = getFloatFromString(msgBalance);
074    Serial.println("\r\nBalans SIM karty: " + (String)balance);
075    sendSMS(MAIN_PHONE, "\r\nBalans SIM karty: " + (String)balance + CURRENCY + ".");
076  }
077}
078 
079float getFloatFromString(String str) {                                      // Функция извлечения цифр из сообщения - для парсинга баланса из USSD-запроса
080  bool flag = false;
081  String result = "";
082  str.replace(",", ".");                                                    // Если в качестве разделителя десятичных используется запятая - меняем её на точку.
083  for (size_t i = 0; i < str.length(); ++i) {
084    if (isDigit(str[i]) || (str[i] == (char)46 && flag)) {                  // Если начинается группа цифр (при этом на точку без цифр не обращаем внимания),
085      if (i != 0 && result == "" && (String)str[i - 1] == "-") {            // Нельзя забывать, что баланс может быть отрицательным
086        result += "-";                                                      // Добавляем знак в начале
087      }
088      result += str[i];                                                     // начинаем собирать их вместе
089      if (!flag) {
090        flag = true;                                                        // Выставляем флаг, который указывает на то, что сборка числа началась.
091      }
092    }
093    else {                                                                 // Если цифры закончились и флаг говорит о том, что сборка уже была,
094      if (str[i] != (char)32) {
095        if (flag) {
096          break;
097        }
098      }
099    }
100  }
101  return result.toFloat();                                                 // Возвращаем полученное число.
102}
103 
104void parseSMS(String msg) {                                   // Парсим SMS
105  String msgheader  = "";                                     // Переменная под звонивший телефона для анализа
106  String msgbody    = "";                                     // Переменная под SMS
107  String msgphone   = "";                                     // Переменная под номер телефона
108 
109  msg = msg.substring(msg.indexOf("+CMGR: "));
110  msgheader = msg.substring(0, msg.indexOf("\r"));            // Получаем звонивший телефон
111 
112  msgbody = msg.substring(msgheader.length() + 2);
113  msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));  // Получаем текст полученной SMS
114  msgbody.trim();                                             //Обрезаем начальные или концевые символы
115 
116  int firstIndex = msgheader.indexOf("\",\"") + 3;
117  int secondIndex = msgheader.indexOf("\",\"", firstIndex);
118  msgphone = msgheader.substring(firstIndex, secondIndex);
119 
120  if (msgphone.length() && MAIN_PHONE.indexOf(msgphone) != -1) { // Если телефон в белом списке, то...
121    if (msgbody == BALANCE_PDU_QUERY) {
122      getBalance();
123    }
124    else if (msgbody == BALANCE_TEXT_QUERY) {
125      alternativeGetBalance();
126    }
127    else if (msgbody == TEMPERATURE_QUERY) {
128      sendSMS(MAIN_PHONE, "SENSOR TEMPERATURE = " + String(obtainTemperature()) + " C.");
129    }
130 
131    Serial.println("Phone: " + msgphone);                          // Выводим номер телефона
132    Serial.println("Message: " + msgbody);                         // Выводим текст SMS
133  }
134  else if (msgphone.length()) {
135    Serial.println("Unknown phone number: " + msgphone);
136    Serial.println("Message: " + msgbody);
137  }
138}
139 
140unsigned char HexSymbolToChar(char c) {
141  if      ((c >= 0x30) && (c <= 0x39)) return (c - 0x30);
142  else if ((c >= 'A') && (c <= 'F'))   return (c - 'A' + 10);
143  else                                 return (0);
144}
145 
146String UCS2ToString(String s) {
147  String result = "";
148  unsigned char c[5] = "";
149  for (size_t i = 0; i < s.length() - 3; i += 4) {
150    unsigned long code = (((unsigned int)HexSymbolToChar(s[i])) << 12)    +
151                         (((unsigned int)HexSymbolToChar(s[i + 1])) << 8) +
152                         (((unsigned int)HexSymbolToChar(s[i + 2])) << 4) +
153                         ((unsigned int)HexSymbolToChar(s[i + 3]));
154    if (code <= 0x7F) {
155      c[0] = (char)code;
156      c[1] = 0;
157    } else if (code <= 0x7FF) {
158      c[0] = (char)(0xC0 | (code >> 6));
159      c[1] = (char)(0x80 | (code & 0x3F));
160      c[2] = 0;
161    } else if (code <= 0xFFFF) {
162      c[0] = (char)(0xE0 | (code >> 12));
163      c[1] = (char)(0x80 | ((code >> 6) & 0x3F));
164      c[2] = (char)(0x80 | (code & 0x3F));
165      c[3] = 0;
166    } else if (code <= 0x1FFFFF) {
167      c[0] = (char)(0xE0 | (code >> 18));
168      c[1] = (char)(0xE0 | ((code >> 12) & 0x3F));
169      c[2] = (char)(0x80 | ((code >> 6) & 0x3F));
170      c[3] = (char)(0x80 | (code & 0x3F));
171      c[4] = 0;
172    }
173    result += String((char*)c);
174  }
175  return (result);
176}
177 
178void checkNewMessages() {
179  String response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true);// Отправляем запрос чтения непрочитанных сообщений
180  if (response.indexOf("+CMGL: ") >= 0) {                    // Если есть хоть одно, получаем его индекс
181    int msgIndex = response.substring(response.indexOf("+CMGL: ") + 7, response.indexOf("\"REC UNREAD\"", response.indexOf("+CMGL: ")) - 1).toInt();
182    response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);  // Пробуем получить текст SMS по индексу
183    response.trim();                                       // Убираем пробелы в начале/конце
184    if (response.endsWith("OK")) {                         // Если ответ заканчивается на "ОК"
185      if (!hasmsg) {
186        hasmsg = true;                           // Ставим флаг наличия сообщений для удаления
187      }
188      sendATCommand("AT+CMGR=" + (String)msgIndex, true);   // Делаем сообщение прочитанным
189      sendATCommand("\n", true);                            // Перестраховка - вывод новой строки
190      parseSMS(response);                                  // Отправляем текст сообщения на обработку
191    }
192  }
193  else {
194    if (hasmsg == true) {
195      sendATCommand("AT+CMGDA=\"DEL READ\"", true);           // Удаляем все прочитанные сообщения
196      hasmsg = false;
197    }
198  }
199}
200 
201void modemQueryAndResponse() {
202  if (SIM800.available())   {                             // Если модем что-то получил...
203    String data = waitResponse();                           // Получаем ответ для модема для анализа
204    data.trim();                                     // Убираем лишние пробелы в начале и конце
205    parseSMS(data);
206    Serial.println(data);                            // Если нужно, выводим в монитор порта
207    if (data.startsWith("+CUSD:")) {                 // Пришло уведомление об USSD-ответе
208      if (data.indexOf("\"") > -1) {                 // Если ответ содержит кавычки, значит есть сообщение (предохранитель от "пустых" USSD-ответов)
209        String msgBalance = data.substring(data.indexOf("\"") + 2);
210        msgBalance = msgBalance.substring(0, msgBalance.indexOf("\""));
211        float balance = getFloatFromString(msgBalance);
212        Serial.println("\r\nBalans SIM karty: " + (String)balance + CURRENCY + ".");
213      }
214    }
215  }
216  else if (Serial.available())  {                    // Ожидаем команды по Serial...
217    SIM800.write(Serial.read());                // ... и отправляем полученную команду модему
218  }
219}
220 
221void sendTemperatureSMS(const String& current_temperature) {
222  sendSMS(MAIN_PHONE, "SENSOR TEMPERATURE = " + current_temperature + " degree " + "C" + ".");
223}
224 
225float obtainTemperature() {
226  sensors.requestTemperatures();
227  return sensors.getTempCByIndex(0);
228}
229 
230void tresholdTemperature(float current_temperature) {
231  static bool flag = 1;
232  if (current_temperature < TEMPERATURE_TRESHOLD && flag) {
233    sendSMS(MAIN_PHONE, "Temperature is less than " + String(TEMPERATURE_TRESHOLD)+ " deg C"+ " and equal to " + String(current_temperature) + " deg C.");
234    flag = 0;
235  }
236  else if (current_temperature >= TEMPERATURE_TRESHOLD && !flag) {
237    flag = 1;
238  }
239}
240 
241void balanceChecking() {
242  static bool flag = 1;
243  sendATCommand(TEXT_USSD_BALANCE_QUERY, true);
244  String answer = waitResponse();
245  answer.trim();
246  String msgBalance = answer.substring(answer.indexOf("\"") + 2);
247  msgBalance = msgBalance.substring(0, msgBalance.indexOf("\""));
248  float balance = getFloatFromString(msgBalance);
249  Serial.println("Balance is " + String(balance));
250  if (balance < BALANCE_TRESHOLD && flag) {
251    sendSMS(MAIN_PHONE, "Balance is less than " + String(BALANCE_TRESHOLD) + CURRENCY + " and equal to " + String(balance) + CURRENCY + ".");
252    flag = 0;
253  }
254  else if (balance >= BALANCE_TRESHOLD && !flag) {
255    flag = 1;
256  }
257}
258 
259void setup() {
260  Serial.begin(9600);
261  SIM800.begin(9600);
262 
263  sensors.begin();
264  sensors.requestTemperatures();
265 
266  Serial.println("Start!");
267 
268  sendATCommand("AT", true);
269  sendATCommand("AT+CMGDA=\"DEL ALL\"", true);
270  sendATCommand("AT+CLIP=1", true);
271  sendATCommand("AT+CMGF=1;&W", true);
272 
273}
274 
275void loop() {
276  static int64_t balance_check_timer = 0;
277  static int64_t temperature_check_timer = 0;
278  static int64_t new_message_check_timer = 0;
279 
280  modemQueryAndResponse();
281  if (abs(millis() - new_message_check_timer) >= 10000) { // раз в десять секунд проверка входящих СМС
282    checkNewMessages();
283    new_message_check_timer = millis();
284  }
285  if (abs(millis() - temperature_check_timer) >= 60000) { // раз в минуту проверка температуры; если она меньше установленного порога, то 1 раз отправляется СМС с текущей температурой на основной номер, прописанный в скетче
286    tresholdTemperature(obtainTemperature());
287    temperature_check_timer = millis();
288  }
289  if (abs(millis() - balance_check_timer) >= 40000) {  // раз в час проверка баланса; если он меньше установленного порога, то 1 раз отправляется СМС с текущим балансом на основной номер, прописанный в скетче
290    balanceChecking();                                 // уменьшил время срабатывания для того, чтобы не ждать час, значение по умолчанию - 3600000
291    balance_check_timer = millis();
292  }
293}

 

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Нужно изменить строку номер +100500 !

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Что Вы имеете в виду?

 

stambylov
stambylov аватар
Offline
Зарегистрирован: 10.05.2012

ПРивет, почитал сверху, решил тоже выложить рабочий обрезанный код для получения и отправки смс

Arduino Mega используется, если что

Да, еще на русском смс шлет))

Есть голая ардуина, на нее заливаете скетч, при первом запуске, она сама чистит EPPROM, т.к. не добавлен номер главного телефона(хранится он в EPPROM), далее отсылаете на номер, который вставлен в модуль SIM, "Register", в ответ получаете ответ на русском, далее разберетесь по счетчу сами, если прилепить часики реального времени, можно в определенное время проверять баланс(он и так проверяется, только по вашему запросу) и т.п.

001//Библиотеки
002#include <SoftwareSerial.h>
003#include <EEPROM.h>
004#include <Wire.h> // Wire.h
005#include <OneWire.h>// библиотека для работы с протоколом 1-Wire
006#include <DallasTemperature.h>// библиотека для работы с датчиком DS18B20
007 
008#define SIM800_TX_PIN 53
009#define SIM800_RX_PIN 52
010SoftwareSerial gsm(SIM800_TX_PIN,SIM800_RX_PIN);
011#define ONE_WIRE_BUS 2      //Датчики по шине 1-wire
012 
013 
014// создаём объект для работы с библиотекой OneWire
015OneWire oneWire(ONE_WIRE_BUS);
016// создадим объект для работы с библиотекой DallasTemperature
017DallasTemperature sensors(&oneWire);
018// создаём указатель массив для хранения адресов датчиков
019DeviceAddress *sensorsUnique;
020// количество датчиков на шине
021int countSensors;
022 
023unsigned long currentMillis = 0;
024//переменные для датчиков ТЕ по шине 1-WIRE
025long lastUpdateTime1WIRE = 0; // Переменная для хранения времени последнего считывания с датчика
026const int TEMP_UPDATE_TIME1WIRE = 5000; // Определяем периодичность проверок датчиков
027String STemperature1 = "";
028String STemperature2 = "";
029String STemperature3 = "";
030int StartGSM = 0;
031String NBoss = "";
032String NBoss1 = "";
033String NBoss2 = "";
034String NBoss3 = "";
035String NBoss4 = "";
036String NBoss5 = "";
037String NBossNumber = "";
038String Temp = "";
039int tempZaprosBalansa = 0; // переменная, хранящая метку о запросе каждый день баланса
040int tempForWaitSendSmsTE = 0;
041long counter = 0;
042long timerForSignalGSM = 1000000;
043 
044// Переменные для обработки смс +CSQ
045int intNumberLevelFirst = 0;
046int intNumberLevelSecond = 0;
047int IntSignalLevel = 0;
048int FlagSignal = 0;
049// Переменные для чтения смс
050String currStr = "";
051String dataSmsN = "";
052int flag1 = 0;
053int flag2 = 0;
054String currStrN = "";
055char currSymb = 0;
056String dataSms = "";
057String dataBalance = "";
058//String dataBalanceNumber = "";
059String dataBalanceTemp = "";
060String val = "";
061int ch = 0;
062char data = 0;
063// Переменные для циклов
064int i = 0;
065int k = 0;
066byte  s1;                          //
067byte  s2;                          //
068byte  s3;                          //
069byte  s4;                          //
070byte  s5;                          //
071byte  s6;                          //
072byte  s7;                          //
073byte  s8;                          //
074byte  s9;                          //
075byte  s10;                         //
076byte  s11;
077 
078String msgBalance = "";
079float balance = 0;
080 
081int tempBalans = 0; // переменная, хранящая метку о запросе баланса
082String textToSend = "";
083int Boss = 0;
084int BossTemp = 0;
085 
086String BalansSim = "Баланс: ";
087String HelloNumberIsBoss = "Ваш номер главный: ";
088String temp = "";
089String _response = ""// Переменная для хранения ответа модуля
090int IntSignalLevelTemp = 0;
091byte Temp2;// чтение телефона хозяина
092int intUstavkaTE = 0;
093int counterClearAddrDataEEprom = 0;
094 
095void setup() {
096  Serial.begin(9600);  // Сериал для PC
097  Serial.println("Start");
098   
099  gsm.begin(9600);  // Сериал для GSM
100  delay(1000);
101  sendATCommand("AT+CMGF=1\r", true);// устанавливает текстовый режим смс-сообщенияОК
102  sendATCommand("AT+IFC=1, 1\r", true);//устанавливает программный контроль потоком передачи данных
103  sendATCommand("AT+CPBS=\"SM\"\r", true);//открывает доступ к данным телефонной книги SIM-карты
104  sendATCommand("AT+CNMI=1,2,2,1,0\r", true);// включает оповещение о новых сообщениях, новые сообщения
105  sendATCommand("AT+GSMBUSY=1\r\n", true);// запрет всех входящих звонков.
106  sendATCommand("AT+CMGDA=DEL ALL\r\n", true);// команда удалит все сообщения
107  sendATCommand("AT+CSQ", true); // Проверяем уровень сигнала
108 
109  // начинаем работу с датчиком DS по шине
110    sensors.begin();
111    // выполняем поиск устройств на шине
112    countSensors = sensors.getDeviceCount();
113//    Serial.print("Found sensors: ");
114//    Serial.println(countSensors);
115    // выделяем память в динамическом массиве под количество обнаруженных сенсоров
116    sensorsUnique = new DeviceAddress[countSensors];
117 
118    // делаем запрос на получение адресов датчиков
119    for (int i = 0; i < countSensors; i++) {
120      sensors.getAddress(sensorsUnique[i], i);
121    }
122    // выводим полученные адреса
123    for (int i = 0; i < countSensors; i++) {
124      Serial.print("Device ");
125      Serial.print(i);
126      Serial.print(" Address: ");
127      printAddress(sensorsUnique[i]);
128      Serial.println();
129    }
130 
131    // устанавливаем разрешение всех датчиков в 12 бит
132    for (int i = 0; i < countSensors; i++) {
133      sensors.setResolution(sensorsUnique[i], 12);
134    }
135  //Конец поиска по шине DS
136}
137 
138void loop() {
139  //######### Начало. Если Главного номера нет в EEPROM и запустили систему в первый раз #################
140  // Удаляем из EEPROM все данные, записываем, что нет номеров и система не стоит на охране, выключаем сирену и маяк
141  if (EEPROM.read(20) == 0 && counterClearAddrDataEEprom == 0){
142    RAll();
143  }
144  //######### Конец. Если Главного номера нет в EEPROM и запустили систему в первый раз #################
145 
146  currentMillis = millis();
147   
148  // Запускаем GSM
149  if (StartGSM == 0){
150    gsm.write("AT+CMGF=1\r"); // устанавливает текстовый режим смс-сообщения
151    delay(300);
152  }
153  if (StartGSM == 1){
154    gsm.write("AT+IFC=1, 1\r"); //устанавливает программный контроль потоком передачи данных
155    delay(300);
156  }
157  if (StartGSM == 2){
158    gsm.write("AT+CPBS=\"SM\"\r");//открывает доступ к данным телефонной книги SIM-карты
159    delay(300);
160  }
161  if (StartGSM == 3){
162    gsm.write("AT+CNMI=1,2,2,1,0\r");// включает оповещение о новых сообщениях, новые сообщения
163    delay(500);
164  }
165  if (StartGSM == 4){
166    gsm.write("AT+GSMBUSY=1\r\n"); // запрет всех входящих звонков.
167    delay(300);
168  }
169  if (StartGSM == 5){
170    gsm.write("AT+CMGDA=DEL ALL\r\n"); // команда удалит все сообщения
171    delay(500);
172  }
173  if (FlagSignal == 0 && StartGSM == 6){
174    gsm.println("AT+CSQ");// Проверяем уровень сигнала
175    delay(800);
176  }
177 
178  if (gsm.available()) {          //есть данные от GSM модуля
179    currStr = "";                      //выждем, чтобы строка успела попасть в порт целиком раньше чем будет считана
180    currStrN = "";
181    dataBalanceTemp = "";
182    dataSms = "";
183    val = "";
184    flag1 = 0;
185    flag2 = 0;
186    while (gsm.available()) {      //сохраняем входную строку в переменную val
187      c:
188      ch = gsm.read();  //int
189//      Serial.println(ch);
190      val += char(ch);      // String
191      data = ch;      // char = int
192      if ('\r' == data) {
193        currStr = "";
194      } else if ('\n' != data) {
195          currStr += String(data);
196          dataSms = currStr;
197        }
198        //+CMT: "+79819998877","","16/04/18,20:25:08+12"
199      if (data == '+' && flag1 == 0){flag1 = 1;}
200      if (data == 'C' && flag1 == 1){flag1 = 2;}
201      if (data == 'M' && flag1 == 2){flag1 = 3;}
202      if (data == 'T' && flag1 == 3){flag1 = 4;}
203      if (data == '+' && flag1 == 4){currStrN = "";flag1 = 5;}
204      if (data != '"' && flag1 == 5){currStrN += String(data); dataSmsN = currStrN;}
205      if (data == '"' && flag1 == 5){flag1 = 6;}
206      //+CUSD: 0, "Balance:117,27r ", 15
207      if (data == 'U' && flag1 == 2){flag2 = 3;}
208      if (data == 'S' && flag2 == 3){flag2 = 4;}
209      if (data == 'D' && flag2 == 4){flag2 = 5;}
210      if (data == ':' && flag2 == 5){flag2 = 6;}
211      if (data == '"' && flag2 == 6){dataBalanceTemp = ""; flag2 = 7; goto c;}
212      if (data != '"' && flag2 == 7){dataBalanceTemp += String(data); dataBalance = dataBalanceTemp;}
213      if (data == '"' && flag2 == 7){flag2 = 8;}
214       
215    }
216// Смотрим данные полученные //режим кодировки СМС - обычный (для англ.)
217    if (val.indexOf("+CMGF") > -1){
218      if (dataSms.indexOf("OK") > -1) {
219        StartGSM = 1;
220      }
221    }
222// Смотрим данные полученные //устанавливает программный контроль потоком передачи данных
223    if (val.indexOf("+IFC") > -1){
224      if (dataSms.indexOf("OK") > -1) {
225        StartGSM = 2;
226      }
227    }
228// Смотрим данные полученные //открывает доступ к данным телефонной книги SIM-карты
229    if (val.indexOf("+CPBS") > -1){
230      if (dataSms.indexOf("OK") > -1) {
231        StartGSM = 3;
232      }
233    }
234// Смотрим данные полученные //включает оповещение о новых сообщениях, новые сообщения
235    if (val.indexOf("+CNMI") > -1){
236      if (dataSms.indexOf("OK") > -1) {
237        StartGSM = 4;
238      }
239    }
240// Смотрим данные полученные //запрет всех входящих звонков.
241    if (val.indexOf("+GSMBUSY") > -1){
242      if (dataSms.indexOf("OK") > -1) {
243        StartGSM = 5;
244      }
245    }
246// Смотрим данные полученные //команда удалит все сообщения
247    if (val.indexOf("+CMGDA") > -1){
248      if (dataSms.indexOf("OK") > -1) {
249        StartGSM = 6;
250      }
251    }
252// Смотрим данные полученные от модуля +CSQ: 22,0
253    if (val.indexOf("+CSQ") > -1) {
254      for (i=0; i<=20; i++){
255        if (val[i] == 58) {
256          intNumberLevelFirst = val[i+2]-48;
257          if (val[i+3] == 44){ intNumberLevelSecond = 0;}
258          if (val[i+3] != 44){ intNumberLevelSecond = val[i+3]-48;}
259          if (val[i+3] == 44){IntSignalLevel = intNumberLevelFirst;}
260          if (val[i+3] != 44){IntSignalLevel = (intNumberLevelFirst*10) + intNumberLevelSecond;}
261        }
262         
263      }
264      if (IntSignalLevel == 99 || IntSignalLevel == 0){
265        FlagSignal = 0; StartGSM = 0;
266//        digitalWrite(ledRed, HIGH);
267      }
268      if (IntSignalLevel <=32 && IntSignalLevel !=0){
269        FlagSignal = 1;
270      }
271    }
272     
273// Смотрим данные полученные от модуля пришло смс
274    if (val.indexOf("+CMTI:") > -1) { // +CMTI: "SM",
275      StartGSM = 0;
276    }
277     
278// Смотрим данные полученные от модуля, Получили смс с балансом, теперь отсылаем
279    if (val.indexOf("+CUSD:") > -1) {       // Пришло уведомление о USSD-ответе
280      if (val.indexOf("\"") > -1) {       // Если ответ содержит кавычки, значит есть сообщение (предохранитель от "пустых" USSD-ответов)
281        msgBalance = val.substring(val.indexOf("\"") + 2);  // Получаем непосредственно текст
282        msgBalance = msgBalance.substring(0, msgBalance.indexOf("\""));
283        balance = getFloatFromString(msgBalance);       // Извлекаем информацию о балансе
284         
285        if (tempBalans == 1) {
286          Boss = BossTemp;
287          textToSend = BalansSim;
288          textToSend += (String)balance;
289          textToSend += "руб";
290          smsSendAlarm(textToSend);
291          tempBalans = 0;
292          BossTemp = 0;
293        }
294         
295        if ((int)balance > 400){
296          tempForWaitSendSmsTE = 0;
297          // ничего не делаем
298        }else if (tempZaprosBalansa == 1){
299          if ((int)balance == 0){
300            tempZaprosBalansa = 2;
301            GoBalans();
302          }else {
303            Boss = 75;
304            textToSend = BalansSim;
305            textToSend += "меньше 400руб, ваш баланс: ";
306            textToSend += (String)balance;
307            smsSendAlarm(textToSend);
308            tempZaprosBalansa = 0;
309            tempForWaitSendSmsTE = 1;
310          }
311           
312        }
313       
314      }
315    }
316 
317//----------------------- определение факта приема СМС и сравнение номера(ов) с заданным(и)
318    if (val.indexOf("+CMT") > -1) {
319       
320// Регистрация хозяина
321      if (dataSms.indexOf("Register") > -1 && EEPROM.read(0) == 3) {
322        if (EEPROM.read(20) == 0){
323          k=1;
324          Temp = "";
325          for (i=20; i<=30; i++){            // записываем с 20 по 30 ячейку номер телефона главного
326            EEPROM.write(i,dataSmsN[k]-48);
327            Temp += dataSmsN[k]-48; // записываем в Temp номер телефона из прешедшей смс
328            k++;
329          }
330          EEPROM.write(0,0);
331          textToSend = "";
332          Serial1.print("Register"); Serial1.print(Temp);Serial1.println();
333          Boss = 1;
334          textToSend = HelloNumberIsBoss;
335          textToSend += Temp;
336          smsSendAlarm(textToSend);
337          goto Exit;
338        }
339        Exit:
340        ClearDataIn();
341        delay(1);
342         
343      }
344 
345       
346// Проверяем номер телефона хозяина
347      if (dataSmsN !=""){
348        Boss = 0;
349        for (i=1; i<=11; i++){
350          Temp += dataSmsN[i]-48; // записываем в Temp номер телефона из прешедшей смс
351        }
352        ReadNumber(1);// читаем номер хозяина из EEPROM
353         
354        if (Temp == NBoss){// Сравниваем номер прешедшей смс с номером из памяти
355          Boss = 1;
356          NBoss = "";
357          goto exitWriteNumber;
358        }
359        ReadNumber(2);// читаем номер хозяина из EEPROM
360        if (Temp == NBoss1){// Сравниваем номер прешедшей смс с номером из памяти
361          Boss = 2;
362          NBoss1 = "";
363          goto exitWriteNumber;
364        }
365        ReadNumber(3);// читаем номер хозяина из EEPROM
366        if (Temp == NBoss2){// Сравниваем номер прешедшей смс с номером из памяти
367          Boss = 3;
368          NBoss2 = "";
369          goto exitWriteNumber;
370        }
371        ReadNumber(4);// читаем номер хозяина из EEPROM
372        if (Temp == NBoss3){// Сравниваем номер прешедшей смс с номером из памяти
373          Boss = 4;
374          NBoss3 = "";
375          goto exitWriteNumber;
376        }
377        ReadNumber(5);// читаем номер хозяина из EEPROM
378        if (Temp == NBoss4){// Сравниваем номер прешедшей смс с номером из памяти
379          Boss = 5;
380          NBoss4 = "";
381          goto exitWriteNumber;
382        }
383        ReadNumber(6);// читаем номер хозяина из EEPROM
384        if (Temp == NBoss5){// Сравниваем номер прешедшей смс с номером из памяти
385          Boss = 6;
386          NBoss5 = "";
387          goto exitWriteNumber;
388        }
389        exitWriteNumber:
390        delay(1);
391      }
392 
393// Помощь, вывод меню в смс
394        if (dataSms.indexOf("Help") > -1){
395          if (Boss == 1 || Boss == 2 || Boss == 3 || Boss == 4 || Boss == 5 || Boss == 6){
396            temp = "Hi";//25
397            temp += "\r\n";//29
398            temp += "Balans";
399            smsSendAlarm(temp);
400            temp = "";                   // очищаем переменную
401          }
402        }
403// Информация
404        if (dataSms.indexOf("Info") > -1){
405          if (Boss == 1 || Boss == 2 || Boss == 3 || Boss == 4 || Boss == 5 || Boss == 6){
406             
407            Boss = 77;
408            textToSend = "Инфа";
409            textToSend += "\r\n";
410            textToSend += "Сигнал:";
411            IntSignalLevelTemp = map(IntSignalLevel, 0, 32, 0, 100);
412            textToSend += String(IntSignalLevelTemp);
413            textToSend += "%";
414            textToSend += "\r\n";
415            textToSend += "Темп:";
416            textToSend += STemperature1;
417            textToSend += "'С";
418            smsSendAlarm(textToSend);textToSend = "";
419          }
420        }
421// Запрос баланса, после получения ответа - отправка обратно на номер
422        if (dataSms.indexOf("Balans") > -1) {    // Запрос баланса
423          if (Boss == 1 || Boss == 2 || Boss == 3 || Boss == 6){
424            BossTemp = Boss;
425            tempBalans = 1;
426            GoBalans();
427          }
428        }
429 
430         
431    }//+cmt
432    ClearDataIn();
433     
434  }
435 
436  //Начало чтения для датчиков по шине 1-Wire
437  if (currentMillis - lastUpdateTime1WIRE > TEMP_UPDATE_TIME1WIRE)
438  {
439//    goto ENDWire;
440    lastUpdateTime1WIRE = currentMillis;
441    if (countSensors >= 1) {
442      // переменная для хранения температуры
443      float temperature[10];
444      // отправляем запрос на измерение температуры всех сенсоров
445      sensors.requestTemperatures();
446      // считываем данные из регистра каждого датчика по очереди
447      for (i = 0; i < countSensors; i++) {
448        temperature[i] = sensors.getTempCByIndex(i);
449        if (i == 0) {
450                      Serial.print("TE 1: ");
451                      Serial.println(temperature[0]);
452                      STemperature1 = temperature[0];
453        }
454//        if (i == 1) {
455//                      Serial.print("TE 2: ");
456//                      Serial.println(temperature[1]);
457//                      STemperature2 = temperature[1];
458//        }
459//        if (i == 2) {
460//                      Serial.print("TE 3: ");
461//                      Serial.println(temperature[2]);
462//                      STemperature3 = temperature[2];
463//        }
464      }
465    }
466  }//Конец для датчиков 1-Wire
467}
468 
469String sendATCommand(String cmd, bool waiting) {
470  String _resp = "";                            // Переменная для хранения результата
471//  Serial.print("CMD: ");                          // Дублируем команду в монитор порта
472//  Serial.println(cmd);                          // Дублируем команду в монитор порта
473  gsm.println(cmd);                          // Отправляем команду модулю
474  if (waiting) {                                // Если необходимо дождаться ответа...
475    _resp = waitResponse();                     // ... ждем, когда будет передан ответ
476    // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
477    if (_resp.startsWith(cmd)) {  // Убираем из ответа дублирующуюся команду
478      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
479    }
480//    Serial.println(_resp);                      // Дублируем ответ в монитор порта
481  }
482  return _resp;                                 // Возвращаем результат. Пусто, если проблема
483}
484 
485// Функция ожидания ответа и возврата полученного результата
486String waitResponse() {                         // Функция ожидания ответа и возврата полученного результата
487  String _resp = "";                            // Переменная для хранения результата
488  long _timeout = millis() + 10000;             // Переменная для отслеживания таймаута (10 секунд)
489  while (!gsm.available() && millis() < _timeout)  {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
490  if (gsm.available()) {                     // Если есть, что считывать...
491    _resp = gsm.readString();                // ... считываем и запоминаем
492  }
493  else {                                        // Если пришел таймаут, то...
494//    Serial.println("Timeout...");               // ... оповещаем об этом и...
495  }
496  return _resp;                                 // ... возвращаем результат. Пусто, если проблема
497}
498 
499// Обработка смс цифр из сообщения - для парсинга баланса из USSD-запроса
500float getFloatFromString(String str) {            // Функция извлечения цифр из сообщения - для парсинга баланса из USSD-запроса
501  bool flag = false;
502  String result = "";
503  str.replace(",", ".");                          // Если в качестве разделителя десятичных используется запятая - меняем её на точку.
504  for (int i = 0; i < str.length(); i++) {
505    if (isDigit(str[i]) || (str[i] == (char)46 && flag)) {        // Если начинается группа цифр (при этом, на точку без цифр не обращаем внимания),
506      if (result == "" && i > 0 && (String)str[i - 1] == "-") {   // Нельзя забывать, что баланс может быть отрицательным
507        result += "-";                            // Добавляем знак в начале
508      }
509      result += str[i];                           // начинаем собирать их вместе
510      if (!flag) flag = true;                     // Выставляем флаг, который указывает на то, что сборка числа началась.
511    }
512    else  {                                       // Если цифры закончились и флаг говорит о том, что сборка уже была,
513      if (str[i] != (char)32) {                   // Если порядок числа отделен пробелом - игнорируем его, иначе...
514        if (flag) break;                          // ...считаем, что все.
515      }
516    }
517  }
518  return result.toFloat();                        // Возвращаем полученное число.
519}
520 
521 
522//процедура отправки СМС
523void smsSendAlarm(String text) {
524  textToSend = "";
525  //Главный номер
526  if (EEPROM.read(20) == 7 && Boss == 1 || EEPROM.read(20) == 7 && Boss == 75 || EEPROM.read(20) == 7 && Boss == 74 || EEPROM.read(20) == 7 && Boss == 77 || EEPROM.read(20) == 7 && Boss == 80 || EEPROM.read(20) == 7 && Boss == 82 || EEPROM.read(20) == 7 && Boss == 83){
527    ReadNumber(1);
528    sendSms(text, NBoss);
529  }
530  //User1 31-41,
531  if (EEPROM.read(31) == 7 && Boss == 2 || EEPROM.read(31) == 7 && Boss == 75 || EEPROM.read(31) == 7 && Boss == 83 || EEPROM.read(31) == 7 && Boss == 74){
532    ReadNumber(2);
533    sendSms(text, NBoss1);
534  }
535  //User2 42-52,
536  if (EEPROM.read(42) == 7 && Boss == 3 || EEPROM.read(42) == 7 && Boss == 75 || EEPROM.read(42) == 7 && Boss == 83 || EEPROM.read(42) == 7 && Boss == 74){
537    ReadNumber(3);
538    sendSms(text, NBoss2);
539  }
540  //User3 53-63
541  if (EEPROM.read(53) == 7 && Boss == 4 || EEPROM.read(53) == 7 && Boss == 82 || EEPROM.read(53) == 7 && Boss == 83){
542    ReadNumber(4);
543    sendSms(text, NBoss3);
544  }
545  //User4 64-74
546  if (EEPROM.read(64) == 7 && Boss == 5 || EEPROM.read(64) == 7 && Boss == 82 || EEPROM.read(64) == 7 && Boss == 83){
547    ReadNumber(5);
548    sendSms(text, NBoss4);
549  }
550  //User5 75-85
551  if (EEPROM.read(75) == 7 && Boss == 6 || EEPROM.read(75) == 7 && Boss == 75  || EEPROM.read(75) == 7 && Boss == 77 || EEPROM.read(75) == 7 && Boss == 80 || EEPROM.read(75) == 7 && Boss == 82 || EEPROM.read(75) == 7 && Boss == 83){
552    ReadNumber(6);
553    sendSms(text, NBoss5);
554  }
555  text = "";
556  NBoss = "";
557  NBoss1 = "";
558  NBoss2 = "";
559  NBoss3 = "";
560  NBoss4 = "";
561  NBoss5 = "";
562  sendATCommand("AT+CMGDA=DEL ALL\r\n", true);
563  sendATCommand("AT+CMGD=4", true);
564  sendATCommand("AT+CMGF=1", true); // устанавливает текстовый режим смс-сообщения
565  Boss = 0;
566}
567 
568//Отправка смс о балансе
569void GoBalans(){
570  sendATCommand("AT+CUSD=1,\"#100#\"", true);
571}
572 
573//Начинаем поиск номера
574void ReadNumber(int numberN){
575  if (numberN == 1){
576    NBoss = "";
577    SearchN(20, 30);
578    NBoss = NBoss;
579    return NBoss;
580  }
581  if (numberN == 2){
582    NBoss = "";
583    SearchN(31, 41);
584    NBoss1 = NBoss;
585    NBoss = "";
586    return NBoss1;
587  }
588  if (numberN == 3){
589    NBoss = "";
590    SearchN(42, 52);
591    NBoss2 = NBoss;
592    NBoss = "";
593    return NBoss2;
594  }
595  if (numberN == 4){
596    NBoss = "";
597    SearchN(53, 63);
598    NBoss3 = NBoss;
599    NBoss = "";
600    return NBoss3;
601  }
602  if (numberN == 5){
603    NBoss = "";
604    SearchN(64, 74);
605    NBoss4 = NBoss;
606    NBoss = "";
607    return NBoss4;
608  }
609  if (numberN == 6){
610    NBoss = "";
611    SearchN(75, 85);
612    NBoss5 = NBoss;
613    NBoss = "";
614    return NBoss5;
615  }
616}
617 
618//ищем номер в EEPROM
619void SearchN(int firstI, int secondI){
620  for (i=firstI;i<=secondI;i++){
621    Temp2 = EEPROM.read(i);
622    if (Temp2 == 0){NBoss += "0";}
623    if (Temp2 == 1){NBoss += "1";}
624    if (Temp2 == 2){NBoss += "2";}
625    if (Temp2 == 3){NBoss += "3";}
626    if (Temp2 == 4){NBoss += "4";}
627    if (Temp2 == 5){NBoss += "5";}
628    if (Temp2 == 6){NBoss += "6";}
629    if (Temp2 == 7){NBoss += "7";}
630    if (Temp2 == 8){NBoss += "8";}
631    if (Temp2 == 9){NBoss += "9";}
632  }
633  return NBoss;
634  Temp2 = 0;
635}
636 
637// Удаление всех настроек и номера из памяти EEPROM
638void RAll(){
639  ClearAddresDataEEPROM();
640  WriteEEPROM(); // Записываем значения по умолчанию
641  Info(); // Вывод в Serial Инфу
642  counterClearAddrDataEEprom = 1;
643   
644}
645 
646// Очистка EEPROM
647void ClearAddresDataEEPROM(){
648  for (i=0; i<=100; i++){
649    EEPROM.write(i,0);
650  }
651}
652 
653void WriteEEPROM(){
654  //0=48-48
655  //1=49-48
656  //2=50-48
657  //3=51-48
658  //4=52-48
659  //5=53-48
660  //6=54-48
661  //7=55-48
662  //8=56-48
663  //9=57-48
664  EEPROM.write(0,3);   //состоянии системы = 3(в режиме регистации)
665//  EEPROM.write(75,3);//Уставка температуры, первая цифра
666//  EEPROM.write(76,0);//Уставка температуры, вторая цифра
667//  intUstavkaTE = EEPROM.read(75) * 10;
668//  intUstavkaTE = intUstavkaTE + EEPROM.read(76);
669}
670 
671void Info(){
672    Serial.println("Info");
673    delay(1);
674    // Состояние регистрации системы
675    Serial.print("State system register or not: ");
676    Serial.println(EEPROM.read(0));
677     
678//   20-30 - Храним номер №1 Хозяина
679    Serial.print("Number phone 1: ");
680    for (i=20; i<=30; i++){
681      Serial.print(EEPROM.read(i));
682    }
683    Serial.println("");
684   
685  // 31-41 - Храним номер №2
686    Serial.print("Number phone 2: ");
687    for (i=31; i<=41; i++){
688      Serial.print(EEPROM.read(i));
689    }
690    Serial.println("");
691     
692  // 42-52 - Храним номер №3
693    Serial.print("Number phone 3: ");
694    for (i=42; i<=52; i++){
695      Serial.print(EEPROM.read(i));
696    }
697    Serial.println("");
698     
699  // 53-63 - Храним номер №4
700    Serial.print("Number phone 4: ");
701    for (i=53; i<=63; i++){
702      Serial.print(EEPROM.read(i));
703    }
704    Serial.println("");
705     
706  // 64-74 - Храним номер №5
707    Serial.print("Number phone 5: ");
708    for (i=64; i<=74; i++){
709      Serial.print(EEPROM.read(i));
710    }
711    Serial.println("");
712     
713  // 75-85 - Храним номер №6
714    Serial.print("Number phone 6: ");
715    for (i=75; i<=85; i++){
716      Serial.print(EEPROM.read(i));
717    }
718    Serial.println("");
719}
720 
721// Очистка временных переменных
722void ClearDataIn(){
723  Temp = "";
724//  Boss = 0;
725  currStr = "";
726  currStrN = "";
727  dataBalanceTemp = "";
728  dataSms = "";
729  dataSmsN = "";
730//  dataBalance = "";
731  val = "";
732  flag1 = 0;
733  flag2 = 0;
734}
735 
736// Отправка смс
737void sendSms(String textForSend, String Number){
738  sendSMSinPDU(Number, textForSend);
739  do {
740    _response = sendATCommand("AT+CLIP=1", true);  // Включаем АОН
741    _response.trim();                       // Убираем пробельные символы в начале и конце
742  } while (_response != "OK");              // Не пускать дальше, пока модем не вернет ОК
743   
744   
745}
746 
747void sendSMSinPDU(String phone, String message)
748{
749//  Serial.println("Отправляем сообщение: " + message);
750 
751  // ============ Подготовка PDU-пакета =============================================================================================
752  // В целях экономии памяти будем использовать указатели и ссылки
753  String *ptrphone = &phone;                                    // Указатель на переменную с телефонным номером
754  String *ptrmessage = &message;                                // Указатель на переменную с сообщением
755 
756  String PDUPack;                                               // Переменная для хранения PDU-пакета
757  String *ptrPDUPack = &PDUPack;                                // Создаем указатель на переменную с PDU-пакетом
758 
759  int PDUlen = 0;                                               // Переменная для хранения длины PDU-пакета без SCA
760  int *ptrPDUlen = &PDUlen;                                     // Указатель на переменную для хранения длины PDU-пакета без SCA
761 
762  getPDUPack(ptrphone, ptrmessage, ptrPDUPack, ptrPDUlen);      // Функция формирующая PDU-пакет, и вычисляющая длину пакета без SCA
763 
764//  Serial.println("PDU-pack: " + PDUPack);
765//  Serial.println("PDU length without SCA:" + (String)PDUlen);
766 
767  // ============ Отправка PDU-сообщения ============================================================================================
768  sendATCommand("AT+CMGF=0", true);                             // Включаем PDU-режим
769  sendATCommand("AT+CMGS=" + (String)PDUlen, true);             // Отправляем длину PDU-пакета
770  sendATCommand(PDUPack + (String)((char)26), true);            // После PDU-пакета отправляем Ctrl+Z
771  PDUPack = "";
772  message = "";
773  *ptrphone = "";
774  *ptrmessage = "";
775  *ptrPDUlen = "";
776}
777 
778void getPDUPack(String *phone, String *message, String *result, int *PDUlen)
779{
780  // Поле SCA добавим в самом конце, после расчета длины PDU-пакета
781  *result += "01";                                // Поле PDU-type - байт 00000001b
782  *result += "00";                                // Поле MR (Message Reference)
783  *result += getDAfield(phone, true);             // Поле DA
784  *result += "00";                                // Поле PID (Protocol Identifier)
785  *result += "08";                                // Поле DCS (Data Coding Scheme)
786  //*result += "";                                // Поле VP (Validity Period) - не используется
787 
788  String msg = StringToUCS2(*message);            // Конвертируем строку в UCS2-формат
789 
790  *result += byteToHexString(msg.length() / 2);   // Поле UDL (User Data Length). Делим на 2, так как в UCS2-строке каждый закодированный символ представлен 2 байтами.
791  *result += msg;
792 
793  *PDUlen = (*result).length() / 2;               // Получаем длину PDU-пакета без поля SCA
794  *result = "00" + *result;                       // Добавляем поле SCA
795}
796 
797String getDAfield(String *phone, bool fullnum) {
798  String result = "";
799  for (int i = 0; i <= (*phone).length(); i++) {  // Оставляем только цифры
800    if (isDigit((*phone)[i])) {
801      result += (*phone)[i];
802    }
803  }
804  int phonelen = result.length();                 // Количество цифр в телефоне
805  if (phonelen % 2 != 0) result += "F";           // Если количество цифр нечетное, добавляем F
806 
807  for (int i = 0; i < result.length(); i += 2) {  // Попарно переставляем символы в номере
808    char symbol = result[i + 1];
809    result = result.substring(0, i + 1) + result.substring(i + 2);
810    result = result.substring(0, i) + (String)symbol + result.substring(i);
811  }
812 
813  result = fullnum ? "91" + result : "81" + result; // Добавляем формат номера получателя, поле PR
814  result = byteToHexString(phonelen) + result;    // Добавляем длину номера, поле PL
815 
816  return result;
817}
818 
819// =================================== Блок кодирования строки в представление UCS2 =================================
820String StringToUCS2(String s)
821{
822  String output = "";                                               // Переменная для хранения результата
823 
824  for (int k = 0; k < s.length(); k++) {                            // Начинаем перебирать все байты во входной строке
825    byte actualChar = (byte)s[k];                                   // Получаем первый байт
826    unsigned int charSize = getCharSize(actualChar);                // Получаем длину символа - кличество байт.
827 
828    // Максимальная длина символа в UTF-8 - 6 байт плюс завершающий ноль, итого 7
829    char symbolBytes[charSize + 1];                                 // Объявляем массив в соответствии с полученным размером
830    for (int i = 0; i < charSize; i++)  symbolBytes[i] = s[k + i];  // Записываем в массив все байты, которыми кодируется символ
831    symbolBytes[charSize] = '\0';                                   // Добавляем завершающий 0
832 
833    unsigned int charCode = symbolToUInt(symbolBytes);              // Получаем DEC-представление символа из набора байтов
834    if (charCode > 0)  {                                            // Если все корректно преобразовываем его в HEX-строку
835      // Остается каждый из 2 байт перевести в HEX формат, преобразовать в строку и собрать в кучу
836      output += byteToHexString((charCode & 0xFF00) >> 8) +
837                byteToHexString(charCode & 0xFF);
838    }
839    k += charSize - 1;                                              // Передвигаем указатель на начало нового символа
840    if (output.length() >= 280) break;                              // Строка превышает 70 (4 знака на символ * 70 = 280) символов, выходим
841  }
842  return output;                                                    // Возвращаем результат
843}
844 
845String byteToHexString(byte i) { // Функция преобразования числового значения байта в шестнадцатиричное (HEX)
846  String hex = String(i, HEX);
847  if (hex.length() == 1) hex = "0" + hex;
848  hex.toUpperCase();
849  return hex;
850}
851 
852unsigned int getCharSize(unsigned char b) { // Функция получения количества байт, которыми кодируется символ
853  // По правилам кодирования UTF-8, по старшим битам первого октета вычисляется общий размер символа
854  // 1  0xxxxxxx - старший бит ноль (ASCII код совпадает с UTF-8) - символ из системы ASCII, кодируется одним байтом
855  // 2  110xxxxx - два старших бита единицы - символ кодируется двумя байтами
856  // 3  1110xxxx - 3 байта и т.д.
857  // 4  11110xxx
858  // 5  111110xx
859  // 6  1111110x
860 
861  if (b < 128) return 1;             // Если первый байт из системы ASCII, то он кодируется одним байтом
862 
863  // Дальше нужно посчитать сколько единиц в старших битах до первого нуля - таково будет количество байтов на символ.
864  // При помощи маски, поочереди исключаем старшие биты, до тех пор пока не дойдет до нуля.
865  for (int i = 1; i <= 7; i++) {
866    if (((b << i) & 0xFF) >> 7 == 0) {
867      return i;
868    }
869  }
870  return 1;
871}
872 
873unsigned int symbolToUInt(const String& bytes) {  // Функция для получения DEC-представления символа
874  unsigned int charSize = bytes.length();         // Количество байт, которыми закодирован символ
875  unsigned int result = 0;
876  if (charSize == 1) {
877    return bytes[0]; // Если символ кодируется одним байтом, сразу отправляем его
878  }
879  else  {
880    unsigned char actualByte = bytes[0];
881    // У первого байта оставляем только значимую часть 1110XXXX - убираем в начале 1110, оставляем XXXX
882    // Количество единиц в начале совпадает с количеством байт, которыми кодируется символ - убираем их
883    // Например (для размера 2 байта), берем маску 0xFF (11111111) - сдвигаем её (>>) на количество ненужных бит (3 - 110) - 00011111
884    result = actualByte & (0xFF >> (charSize + 1)); // Было 11010001, далее 11010001&(11111111>>(2+1))=10001
885    // Каждый следующий байт начинается с 10XXXXXX - нам нужны только по 6 бит с каждого последующего байта
886    // А поскольку остался только 1 байт, резервируем под него место:
887    result = result << (6 * (charSize - 1)); // Было 10001, далее 10001<<(6*(2-1))=10001000000
888 
889    // Теперь у каждого следующего бита, убираем ненужные биты 10XXXXXX, а оставшиеся добавляем к result в соответствии с расположением
890    for (int i = 1; i < charSize; i++) {
891      actualByte = bytes[i];
892      if ((actualByte >> 6) != 2) return 0; // Если байт не начинается с 10, значит ошибка - выходим
893      // В продолжение примера, берется существенная часть следующего байта
894      // Например, у 10011111 убираем маской 10 (биты в начале), остается - 11111
895      // Теперь сдвигаем их на 2-1-1=0 сдвигать не нужно, просто добавляем на свое место
896      result |= ((actualByte & 0x3F) << (6 * (charSize - 1 - i)));
897      // Было result=10001000000, actualByte=10011111. Маской actualByte & 0x3F (10011111&111111=11111), сдвигать не нужно
898      // Теперь "пристыковываем" к result: result|11111 (10001000000|11111=10001011111)
899    }
900    return result;
901  }
902}
903 
904// функция вывода адреса датчика
905void printAddress(DeviceAddress deviceAddress){
906  for (uint8_t i = 0; i < 8; i++){
907    if (deviceAddress[i] < 16) Serial.print("0");
908    Serial.print(deviceAddress[i], HEX);
909  }
910}

 

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Приветствую.
А схему устройства увидеть можно?

b707
Offline
Зарегистрирован: 26.05.2017

Пипец, 900 строк чтоб отправить температуру по Смс?

b707
Offline
Зарегистрирован: 26.05.2017

Строка 618 и далее - это еще повезло, что цифр в арифметике всего 10. Страшно представить, сколько понадобилось бы условий, чтобы отыскать в тексте каждую букву кириллицы и латиницы обоих регистров.
Стамбулов, вы про массивы и циклы не слыхали?

Павел74
Offline
Зарегистрирован: 27.03.2019

ГРАНДИОЗНО!!!!!!!!! Я только в руки взял SIM800L  - пробую разобраться, ранее так же с нуля освоил NRF24 (делал на нем радиоуправление строительного крана - самоделка в помощь на моей стройке) 

По SIM800L  - пока тренируюсь с терминала, чтоб в дальнейшем проект отработат в Atmel Studio 7

 

возник вопрос по передаче смс - в начале настройка:

AT+CMGF=1\r\n - установка текстового режима.
AT+CSMP=17,167,0,0\r\n - установка параметров текстового режима.
AT+CMGS="+7XXXXXXXXXX"\r\n - номер получателя SMS.
>\r\n - ответ модуля (модуль готов принять текст SMS). -----------А ВОТ ТУТ Я ЗАВИС - отправляю текст ( латиница) - результат - ноль, 
к примеру нужно послать "HELLO" - как это должно выглядель ? почти все варианты уже испробовал - не могу верно понять рекомендацию :
 
 {     TEXT - ввод и отправка текста в модуль. Как только в тексте встретится символ <0x1A>, сообщение будет отправлено. Если в тексте встретится символ <0x1B>, сообщение не будет отправлено.
Примечание:
- В текстовом режиме можно добавлять в текст SMS сообщения символы переноса строки \r\n., в т.ч. перед символом подтверждающим/запрещающим отправку SMS.}  - это 

 

Павел74
Offline
Зарегистрирован: 27.03.2019

/

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Если Вы впервые держите в руках  SIM800L - то советую сюда - http://codius.ru/articles?page=1

 

andyparker
Offline
Зарегистрирован: 20.12.2020
001#include <SoftwareSerial.h>
002#include <OneWire.h>
003#include <DallasTemperature.h>
004#define ONE_WIRE_BUS 12
005 
006 
007SoftwareSerial SIM800(8, 9);
008OneWire oneWire(ONE_WIRE_BUS);
009DallasTemperature sensors(&oneWire);
010 
011 
012const String MAIN_PHONE = "+71234567890";                              // Основной номер
013const String WHITE_LIST = "+71234567890; +79999999999; +79888888888"// Включить основной и дополнительный/е телефоны в белый список
014const String TEXT_USSD_BALANCE_QUERY = "AT+CUSD=1,\"*100#\"";          // Отправляет ТЕКСТОВЫЙ ответ, а не PDU-пакет, альтернативный запрос - "#100#"
015const String BALANCE_TEXT_QUERY = "Balance";                           // Содержание СМС для получения текстового ответа на запрос о балансе
016const String TEMPERATURE_QUERY = "Temperature";                        // Содержание СМС для получения ответа на запрос о температуре
017const String CURRENCY = " BYN";                                        // Текстовое представление валюты
018const float  BALANCE_TRESHOLD = 15.0;                                  // Нижнее пороговое значение температуры
019const float  TEMPERATURE_TRESHOLD = 24.0;                              // Нижнее пороговое значение баланса
020 
021 
022String sendATCommand(const String& cmd, bool waiting) {
023  String response = "";
024  Serial.println(cmd);
025  SIM800.println(cmd);
026  if (waiting) {
027    response = waitAndReturnResponse();
028    if (response.startsWith(cmd)) {
029      response = response.substring(response.indexOf("\r", cmd.length()) + 2);
030    }
031    Serial.println(response);
032  }
033  return response;
034}
035 
036String waitAndReturnResponse() {
037  String response = "";
038  int64_t timeout = millis() + 10000;
039  while (!SIM800.available() && millis() < timeout) {};
040  if (SIM800.available()) {
041    response = SIM800.readString();
042  }
043  else {
044    Serial.println("Timeout...");
045  }
046  return response;
047}
048 
049void sendSMS(const String& phone, const String& message) {
050  sendATCommand("AT+CMGS=\"" + phone + "\"", true);
051  sendATCommand(message + (String)((char)26), true);
052}
053 
054void checkBalance(const String& number) {
055  sendATCommand(TEXT_USSD_BALANCE_QUERY, true);
056  String answer = waitAndReturnResponse();
057  answer.trim();
058  Serial.println("\r\nBalans SIM karty: " + (String)extractBalanceFromString(answer));
059  sendSMS(number, "\r\nBalans SIM karty: " + (String)extractBalanceFromString(answer) + CURRENCY + ".");
060}
061 
062float getFloatFromString(String str) {                                      // Функция извлечения цифр из сообщения - для парсинга баланса из USSD-запроса
063  bool flag = false;
064  String result = "";
065  str.replace(",", ".");                                                    // Если в качестве разделителя десятичных используется запятая - меняем её на точку.
066  for (size_t i = 0; i < str.length(); ++i) {
067    if (isDigit(str[i]) || (str[i] == (char)46 && flag)) {                  // Если начинается группа цифр (при этом на точку без цифр не обращаем внимания),
068      if (i != 0 && result == "" && (String)str[i - 1] == "-") {            // Нельзя забывать, что баланс может быть отрицательным
069        result += "-";                                                      // Добавляем знак в начале
070      }
071      result += str[i];                                                     // Начинаем собирать их вместе
072      if (!flag) {
073        flag = true;                                                        // Выставляем флаг, который указывает на то, что сборка числа началась.
074      }
075    }
076    else if (str[i] != (char)32 && flag) {
077      break;
078    }
079  }
080  return result.toFloat();                                                  // Возвращаем полученное число
081}
082 
083void parseSMS(String msg) {                                   // Парсим SMS
084  String msgheader  = "";                                     // Переменная под звонивший телефона для анализа
085  String msgbody    = "";                                     // Переменная под SMS
086  String msgphone   = "";                                     // Переменная под номер телефона
087 
088  msg = msg.substring(msg.indexOf("+CMGR: "));
089  msgheader = msg.substring(0, msg.indexOf("\r"));            // Получаем звонивший телефон
090 
091  msgbody = msg.substring(msgheader.length() + 2);
092  msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));  // Получаем текст полученной SMS
093  msgbody.trim();                                             // Обрезаем начальные или концевые символы
094 
095  int firstIndex = msgheader.indexOf("\",\"") + 3;
096  int secondIndex = msgheader.indexOf("\",\"", firstIndex);
097  msgphone = msgheader.substring(firstIndex, secondIndex);
098  if (WHITE_LIST.indexOf(msgphone) != -1) {                   // Если телефон в белом списке, то...
099    if (msgbody == BALANCE_TEXT_QUERY) {
100      checkBalance(msgphone);
101    }
102    else if (msgbody == TEMPERATURE_QUERY) {
103      sendSMS(msgphone, "Sensor temperature: " +
104              String(obtainTemperature()) + " C.");
105    }
106    Serial.println("Phone: " + msgphone);                      // Выводим номер телефона
107    Serial.println("Message: " + msgbody);                     // Выводим текст SMS
108  }
109  else if (msgphone.length()) {
110    Serial.println("Unknown phone number: " + msgphone);
111    Serial.println("Message: " + msgbody);
112  }
113}
114 
115void checkNewMessages() {
116  static bool hasmsg = false;
117  String response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true);                     // Отправляем запрос чтения непрочитанных сообщений
118  if (response.indexOf("+CMGL: ") >= 0) {                                                // Если есть хоть одно, получаем его индекс
119    int msgIndex = response.substring(response.indexOf("+CMGL: ") + 7,
120                                      response.indexOf("\"REC UNREAD\"",
121                                          response.indexOf("+CMGL: ")) - 1).toInt();
122    response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);                // Пробуем получить текст SMS по индексу
123    response.trim();                                                                     // Убираем пробелы в начале/конце
124    if (response.endsWith("OK")) {                                                       // Если ответ заканчивается на "ОК"
125      if (!hasmsg) {
126        hasmsg = true;                                                                   // Ставим флаг наличия сообщений для удаления
127      }
128      sendATCommand("AT+CMGR=" + (String)msgIndex, true);                                // Делаем сообщение прочитанным
129      sendATCommand("\n", true);                                                         // Перестраховка - вывод новой строки
130      parseSMS(response);                                                                // Отправляем текст сообщения на обработку
131    }
132  }
133  else {
134    if (hasmsg == true) {
135      sendATCommand("AT+CMGDA=\"DEL READ\"", true);                                      // Удаляем все прочитанные сообщения
136      hasmsg = false;
137    }
138  }
139}
140 
141void modemQueryAndResponse() {
142  if (SIM800.available())   {                                                             // Если модем что-то получил...
143    String data = waitAndReturnResponse();                                                // Получаем ответ для модема для анализа
144    data.trim();                                                                          // Убираем лишние пробелы в начале и конце
145    parseSMS(data);
146    Serial.println(data);                                                                 // Если нужно, выводим в монитор порта
147    if (data.startsWith("+CUSD:")) {                                                      // Пришло уведомление об USSD-ответе
148      if (data.indexOf("\"") > -1) {                                                      // Если ответ содержит кавычки, значит есть сообщение (предохранитель от "пустых" USSD-ответов)
149        float balance = extractBalanceFromString(data);
150        Serial.println("\r\nBalans SIM karty: " + (String)balance + CURRENCY + ".");
151      }
152    }
153  }
154  else if (Serial.available())  {                                                         // Ожидаем команды по Serial...
155    SIM800.write(Serial.read());                                                          // ... и отправляем полученную команду модему
156  }
157}
158 
159float obtainTemperature() {
160  sensors.requestTemperatures();
161  return sensors.getTempCByIndex(0);
162}
163 
164void tresholdTemperature(float current_temperature) {
165  static bool flag = 1;
166  if (current_temperature < TEMPERATURE_TRESHOLD && flag) {
167    sendSMS(MAIN_PHONE, "Temperature is currently below " + String(TEMPERATURE_TRESHOLD) +
168            " C and equal to " + String(current_temperature) + " C.");
169    flag = 0;
170  }
171  else if (current_temperature >= TEMPERATURE_TRESHOLD && !flag) {
172    flag = 1;
173  }
174}
175 
176float extractBalanceFromString(const String& response) {
177  String msgBalance = response.substring(response.indexOf("\"") + 2);
178  msgBalance = msgBalance.substring(0, msgBalance.indexOf("\""));
179  return getFloatFromString(msgBalance);
180}
181 
182void balanceChecking() {
183  static bool flag = 1;
184  sendATCommand(TEXT_USSD_BALANCE_QUERY, true);
185  String answer = waitAndReturnResponse();
186  answer.trim();
187  float balance = extractBalanceFromString(answer);
188  Serial.println("Balance is " + String(balance));
189  if (balance < BALANCE_TRESHOLD && flag) {
190    sendSMS(MAIN_PHONE, "Balance is below " + String(BALANCE_TRESHOLD) +
191            CURRENCY + " and equal to " + String(balance) + CURRENCY + ".");
192    flag = 0;
193  }
194  else if (balance >= BALANCE_TRESHOLD && !flag) {
195    flag = 1;
196  }
197}
198 
199void setup() {
200  Serial.begin(9600);
201  SIM800.begin(9600);
202 
203  sensors.begin();
204  sensors.requestTemperatures();
205 
206  Serial.println("Start!");
207 
208  sendATCommand("AT", true);
209  sendATCommand("AT+CMGDA=\"DEL ALL\"", true);
210  sendATCommand("AT+CLIP=1", true);
211  sendATCommand("AT+CMGF=1;&W", true);
212}
213 
214void loop() {
215  static int64_t balance_check_timer = 0;
216  static int64_t temperature_check_timer = 0;
217  static int64_t new_message_check_timer = 0;
218 
219  modemQueryAndResponse();
220  if (abs(millis() - new_message_check_timer) >= 5000) {
221    checkNewMessages();
222    new_message_check_timer = millis();
223  }
224  if (abs(millis() - temperature_check_timer) >= 10000) {
225    tresholdTemperature(obtainTemperature());
226    temperature_check_timer = millis();
227  }
228  if (abs(millis() - balance_check_timer) >= 300000) {
229    balanceChecking();
230    balance_check_timer = millis();
231  }
232}

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

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

andyparker с каких пор вы постите чужое?

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Приношу свои извинения andyparker!
Это и его код тоже.
Он вложил в него очень большой труд.
Его полезные советы помогли оживить устройство.
Теперь оно стабильно работает!!!

b707
Offline
Зарегистрирован: 26.05.2017

wiksoft.arduino пишет:

andyparker с каких пор вы постите чужое?

wiksoft.arduino пишет:

Приношу свои извинения andyparker!

что это было?

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

В понедельник узнаем)))

wiksoft.arduino
Offline
Зарегистрирован: 18.01.2021

Уже разобрались.
Все в порядке!