GSM сигнализация M590+Arduino

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

Umka пишет:

Не взлетит скорее всего. Скорость для MQTT не подходящая и задержки. Тут лучше на ESP8266 делать имхо.

Дело не в скорости. MQTT требует сетевых взаимодействий низкого уровня - сокетов, а через GPRS реализовать их весьма затруднительно.

Что касается ESP - имеется в виду переход на WiFi? - по-моему это не замена GSM. так как GSM обычно используется там, где WiFi и прочего инета нет. Если есть сеть в любом виде - GSM вообще не нужен

pasha413
Offline
Зарегистрирован: 27.11.2016

b707 пишет:
Что касается ESP - имеется в виду переход на WiFi? - по-моему это не замена GSM. так как GSM обычно используется там, где WiFi и прочего инета нет. Если есть сеть в любом виде - GSM вообще не нужен

согласен!

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

это я тоже понял, но мысль пришла управлять есп-хой по вайфай... не удалнно а локально. к примеру приехал на дачу и зашел в приложение и снял с охраны, точно так же поставить на охрану. Только этот плюс вижу, и не нужно не каких ключей для снятия с охраны городить. Вот только встает вопрос безопасности локальной сети вайфай и доступа к той же ESP

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Baks пишет:

Вот только встает вопрос безопасности локальной сети вайфай и доступа к той же ESP

А что не так с безопасностью там? wpa-psk/wpa2-psk - уже отменили?

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

WPA2 уже взломали. GSM может быть резервным каналом оповещения. А по вайфай пушить сообщения на смартфон считай даром. Ну или да, в режиме точки доступа запускать ESP и даже можно по регистрации мобилы в домашней сети снимать с охраны. У кого как с фантазией :) 

Хреново разве в Телеграм получать месседжи и рулить оттуда? ИМХО удобнее, чем смс строчить. А ботом и кнопочки можно сделать понятные. 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Umka пишет:

WPA2 уже взломали. 

Там, при этом "взломе", ключевое - слабые пароли, на мысли не наводит? Юзайте нормальные пароли, и все словари нервно курят в сторонке. Да и цена такого взлома - кому упёрлась какая-то ESP, которая занимается каким-то простым делом? Но нормальные пароли - ключевое, можно спокойно выдыхать и юзать WPA2, не рефлексируя.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Это шутка юмора была же!

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Umka пишет:

Это шутка юмора была же!

Ну тады сорь, не въехал :)

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

b707 пишет:

где WiFi и прочего инета нет. Если есть сеть в любом виде - GSM вообще не нужен

что вы говорите...?? 

а как быть с надежностью интернета через роутер-пров1-пров2-пров3  и т.д..?

и просто сравнить gsm  связь надежность работы которой в разы больше?

так что не мелите ерундой..

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Ну щас начнут комбайн с асфальтоукладчиком сравнивать.

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

Short Circuit пишет:

а как быть с надежностью интернета через роутер-пров1-пров2-пров3  и т.д..?

и просто сравнить gsm  связь надежность работы которой в разы больше?

так что не мелите ерундой..

Не надо быть таким категоричным. К примеру, мой домашний интернет в этом году за десять месяцев не выключался ни разу. На работе сеть похуже - иногда пропадает, но обычно не дольше, чем на 3-5 минут. А вот с глюками мобильной связи я сталкиваюсь постоянно.

Ну и не надо забывать еще один фактор. Кроме надежности сети есть еще надежность программного клиента. Библиотеки работы с TCP/IP написаны на порядок качественнее, чем либы для работы с модемом через AT команды. Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Ничего не мешает работать с модемом нёс помощью кривых либ а напрямую с модемом - я за GSM

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012
Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

а я за совместное использование))

в случае чего всегда есть резевный доступ или через GSM ИЛИ WIFI

 

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

b707 пишет:
Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi

кривые что ?:)  не смешите..  например я не использую библиотеки для GSM - просто не зачем.

это раз.

во вторых - куда такое в основном ставят? правильно - на дачу.. И будете утверждать, что там у прова и аккумы стоятна оборудовании, и все резервируется и т.д.??  ха-ха-ха...

а ваша квартира и интернет в ней - тут не причем..

для вайфая заводите отдельную ветку и делайте в ней свой проект, здесь тема о другом.

pasha413
Offline
Зарегистрирован: 27.11.2016

У меня на даче нет эл-ва, поэтому и остановился на варианте с gsm модемом. А wifi - это ещё и роутер вешать и опять же usb свисток... с GPRS пока не особо разобрался.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

  pasha413 Ваша разработка уже стоит на своем месте и работает? или пока на столе испытываете?

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

Не надо быть таким категоричным. К примеру, мой домашний интернет в этом году за десять месяцев не выключался ни разу. На работе сеть похуже - иногда пропадает, но обычно не дольше, чем на 3-5 минут. А вот с глюками мобильной связи я сталкиваюсь постоянно.

Ну и не надо забывать еще один фактор. Кроме надежности сети есть еще надежность программного клиента. Библиотеки работы с TCP/IP написаны на порядок качественнее, чем либы для работы с модемом через AT команды. Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi

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

b707 пишет:

А вот с глюками мобильной связи я сталкиваюсь постоянно.

Может быть стоит написать в техподдержку оператора для начала, или, в конце концов, сменить оператора?

 

pasha413
Offline
Зарегистрирован: 27.11.2016

Baks, все никак не довезут до дачи. 3 дня гонял на столе, не отключая. Но ещё есть в коде моменты которые нужно исправить, но на работу вроде не влияет

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

КороткоеЗамыкание и КВолк - мы оба обкурились что ли? :)

Я не продвигаю Вай-Фай (да и ГСМ) в этой теме,  и потом я сразу сказал, что в местах, где нет инета - ГСМ незаменим. 

Я среагировал на бредовое заявление, что инет через GPRS-модем "в разы надежнее" Вайфая.  Short Circuit - не имеет значения, работаете ли вы с модемом через библиотеку или напрямую - в любом случае GPRS через АТ-команды не предполагает сколько-нибудь серьезное использование нетекстовых сетевых протоколов и сравнивать его с Wi-Fi просто смешно.

pasha413
Offline
Зарегистрирован: 27.11.2016

подскажите, пожалуйста, как в этом коде положить трубку после 2 гудка (либо на 2 секунде). никак не могу добиться: 

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

int8_t ModemID = 0;
uint32_t msAT = 0;
char Master[] = "79111234567";
String _response = "";                      // Переменная для хранения ответа модуля

void setup() {
  Serial.begin(9600);                       // Скорость обмена данными с компьютером
  InitModem();                      // запускаем инициализация модема.
}

void InitModem() { /// === инициализация модема === ///
  Serial.println(F("Start GSM"));
  gsm.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  String val = sendATCommand(F("ATI"), true);
  if (val.indexOf(F("M590")) > -1) ModemID = 1; // Serial.println("Modem M590");
  else if (val.indexOf(F("SIM800")) > -1) ModemID = 2; // Serial.println("Modem SIM800"); 
  else if (val.indexOf("A6") > -1) ModemID = 3; // Serial.println("Modem A6");
  Serial.println(String(F("ModemID ")) + ModemID);
  sendATCommand(F("AT+CLIP=1"), true);         // включить АОН
  sendATCommand(F("AT+CMGF=1"), true);         // Включить TextMode для SMS
  sendATCommand(F("AT+CSCS=\"GSM\""), true);   // кодировка текста - GSM
  sendATCommand(F("AT+CNMI=2,2,0,0,0"), true);
  sendATCommand(F("AT+CREG?"), true);
  delay(1000); 
}

void loop() {
  if (gsm.available())   {                      // Если модем, что-то отправил...
    _response = waitResponse();                 // Получаем ответ от модема для анализа
    Serial.println(_response);                  // Если нужно выводим в монитор порта
    // ... здесь можно анализировать данные полученные от GSM-модуля
    if (_response.indexOf(F("+PBREADY")) > -1) InitModem();
    if (_response.indexOf(F("+CLIP: \"")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      if (CheckPhone(_response) == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
//  MasterRing();                                // меняем состояние охраны
      } else  Serial.println(F("No Master Ring!"));  
      delay(2000);                             // дадим гудок
      gsm.println(F("ATH"));              // сбрасываем вызов.
    } else if (_response.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
//  Serial.println("val " + val);                            
        if (CheckPhone(_response) == 1) {               // если СМС от хозяина
          parsesms(_response);
  Serial.println(F("Master SMS OK!"));
//  Serial.println("sms->" + val);
//  Komand();
        } else  Serial.println(F("No Master SMS!"));
      }  
  }
  if (Serial.available())  {                    // Ожидаем команды по Serial...
    gsm.write(Serial.read());                   // ...и отправляем полученную команду модему
  }
}

int CheckPhone(String num) {              // сверяем номер свой/чужой
   int ind = num.indexOf(F("+CLIP: \""));          // обрезаем номер 
   if (ind >= 0) {                     // Если информация была найдена
     ind += 8;                         // Парсим строку и
     num = num.substring(ind, num.indexOf("\"", ind));
   }
   if (num.length() >= 7 && num == Master) return 1;
   Serial.println("Tell: " + num);
   return 0;
}

void parsesms(String msg) {
  String msgheader  = "";
  String msgbody    = "";
  String msgphone   = "";

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

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

  int Index = msgheader.indexOf("+CMT:");
  msgphone = msgheader.substring(Index + 8, Index + 19);
  msgphone.trim();

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

String sendATCommand(String cmd, bool waiting) {
  String _resp = "";                            // Переменная для хранения результата
  Serial.println(cmd);                          // Дублируем команду в монитор порта
  gsm.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 = "";                            // Переменная для хранения результата
  uint32_t _timeout = millis() + 10000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!gsm.available() && (millis() < _timeout))  {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  if (gsm.available()) {                        // Если есть, что считывать...
    _resp = gsm.readString();                   // ... считываем и запоминаем
  } else {                                      // Если пришел таймаут, то...
    Serial.println(F("Timeout..."));               // ... оповещаем об этом и...
  }
  return _resp;                                 // ... возвращаем результат. Пусто, если проблема
}

void waitConnect() {  // запуск модема
  int countok = 0;
  uint32_t msAT = 0;
  String str; 
  while(countok < 5) {                      //ждём пять ОК  
    uint32_t ms = millis();
    if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс 
      msAT = ms;
      Serial.println(">>AT");
      gsm.println("AT");                    // посылаем команду
      str = "";
      delay(100);                           // ждём ответа
      while(gsm.available()) {
        char ch = gsm.read();
        str += ch;
      } 
      if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;}
      else countok = 0;
    }
  }  
}

 

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

после  if (CheckPhone(_response) == 1)  посчитайте два ответа RING  от модема...

pasha413
Offline
Зарегистрирован: 27.11.2016

В порт ring сыпятся после того как я сам положу трубку, здесь получается: пока от модема идут сообщения в порт не выводит, а выводит когда закончена передача

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

угу, скетч переделайте. подумайте почему так происходит, учитесь анализироввать.

AleksandrM
Offline
Зарегистрирован: 20.07.2017

pasha413

Подскажи твой скетч с сообщения 216 все в терминале работает а ни звонить ни смс слать не хочет

В чем проблема может быть? Вот пример команды money

Money

Master SMS OK!
Balance#101#

Input string:
O7(⸮⸮⸮A⸮⸮⸮]w⸮A⸮⸮U⸮H⸮⸮⸮⸮f⸮⸮⸮&⸮⸮ow⸮L⸮⸮⸮⸮⸮r⸮⸮⸮d⸮⸮dP⸮MO⸮A0⸮+s⸮`1⸮4|⸮⸮⸮1$~⸮⸮⸮⸮d~⸮AǤ⸮:
⸮⸮e7T⸮ݠis
⸮⸮A8⸮⸮⸮⸮at

Decode string:
On Your account 19.01 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
Start SMS send

Вот так в терминале после старта

Mode GSM:
GSM connected
>>AT+CREG?
R>
AT+CLIP=1

OK
AT+CMGF=1

OK
AT+CSCS=GSM

OK
AT+CNMI=2,2,0,0,0

OK
AT+CREG?

+CREG: 1,1

OK

Phone[0]:380888888888
Ring [ ]:380888888888
Balance:101
Firststart:0
System->off
Ring->on
SMS->on
Pir->on
Door->on
Gas->on
Sirena: 10sec
Temp: 0*C.

 

pasha413
Offline
Зарегистрирован: 27.11.2016

AleksandrM, номер правильно пишет в епром?

AleksandrM
Offline
Зарегистрирован: 20.07.2017

выводит бнз последнего знака

 

AleksandrM
Offline
Зарегистрирован: 20.07.2017

извиняюсь без последнего знака

В терминале при старте отсуствует последняя цыфра в номере

Phone[0]:38066******_
Ring [ ]:380066******_

pasha413
Offline
Зарегистрирован: 27.11.2016

Да, с номерами Украины я не думал даже... Можно добавить

AleksandrM
Offline
Зарегистрирован: 20.07.2017

если не затруднит

pasha413
Offline
Зарегистрирован: 27.11.2016

Занимаюсь

pasha413
Offline
Зарегистрирован: 27.11.2016

Пробуйте, переделал, 12 значные номера не могу проверить, но должно работать!

 

// max длинна сообщения в данный момент 135 символов.
#include <EEPROM.h> 
#include <OneWire.h>
#include <RCSwitch.h>
#include <SoftwareSerial.h>
#define Ver F("Alarm  v4.3.4\n")

OneWire ds(6);                  // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +.
SoftwareSerial gsm(7, 8);       // модем подключен к 7 и 8 пинам.
RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2.

#define DOOR 4             // пин 4. концевик двери.
#define PIR 5              // пин 5. датчик движения.
#define LED 13             // пин 13. состояние системы.
#define GAS 14             // пин A0. датчик дыма.
#define BUZ 15             // пин A1. сирена.
#define sarai 3258553      // адрес 433 передатчика геркона двери

// DOOR     - если сработал, на входе "+" HIGH.
// SARAI    - если сработал, на пин 2 сигнал.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// LED      - если "-" LOW, то горит.

#define on "on"     // вкл
#define off "off"   // выкл

int8_t ModemID = 0;        //    тип модема
int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевика двери:       1 - вкл, 0 - выкл.    
int8_t SARAIon = 1;        // 4. контроль концевика двери 2:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.
int8_t Sirena = 1;         // 7. сирена:                         1 - вкл, 0 - выкл. 
int8_t Firststart = 1;     // первый старт.

int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t SARAIFlag = 0;      // флаг состояние датчика двери 2.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LEDState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t sendsmscaller = 1;  // разрешение отправки смс.

uint32_t msAT = 0;

char Bal[4];               // для временного хранения номера баланса.   
char Phone[14];            // для временного хранения номера телефона, номер до 14 цифр.      
String  AT[] = {"AT+CLIP=1", "AT+CMGF=1", "AT+CSCS=\"GSM\"", "AT+CNMI=2,2,0,0,0", "AT+CREG?"}; // общие АТ команды
#define  AT_M590  F("AT+CUSD=1")            // баланс для М590
#define  AT_SIM800_A6  F("AT+CUSD=1,#")     // баланс для А6 и СИМ800

String RingPhone = "";          // номер звонившего.
String AlarmPhone[5];           // номера для постановки/снятии с охраны и отправки смс.
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.

int p = 0;
#define GASThres 400           // предельная концентрация газа
#define interval_alarm 20      // Секунд до отключения "тревожного" пина. 
int previousMillis_alarm = 0;
#define interval_led 1000      // для мигания LED, 1 сек.
int previousMillis_led = 0;
#define interval_door 10       // секунд не смотрим на датчик двери.
int previousMillis_door = 0;
#define interval_sarai 10      // секунд не смотрим на датчик двери 2.
int previousMillis_sarai = 0;
#define interval_pir 20        // секунд не смотрим на датчик движения.
int previousMillis_pir = 0;
#define interval_gas 600       // секунд не смотрим на датчик газа. 10минут
int previousMillis_gas = 0;

/* EEPROM Data:
  № ячейки - значение:
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:                0 - выкл.
  2 - AlarmRING = 1;   // звонок:                1 - вкл. 
  3 - SendSMS = 1;     // отправка смс:          1 - вкл.
  4 - DOORon = 1;      // концевик двери:        1 - вкл.
  5 - SARAIon = 1;     // концевик двери сарая:  1 - вкл.
  6 - PIRon = 1;       // датчик движения:       1 - вкл.
  7 - GASon = 1;       // датчик дыма:           1 - вкл.
  8 - Sirena = 1;      // сирена:                1 - вкл.
  10 - Firststars = 1; // первый запуск          1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// === настройка программы === ///
  Serial.begin(9600); 
  Serial.println(Ver); 
  pinMode(DOOR, INPUT_PULLUP);      // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);           
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);
  pinMode(LED, OUTPUT);             // светодиод горит во время запуска.
    digitalWrite(BUZ, HIGH);        // сирена выкл.
    digitalWrite(PIR, HIGH);        // игнорируем при включении.
  mySwitch.enableReceive(0);        // 433 приемник на 2 пине
  InitModem();                      // запускаем инициализация модема.
  eepromconfig();
  Serial.println(eepromtext()); 
  Serial.println(eepromphone()); 
    digitalWrite(LED, HIGH);        // гасим светодиод состояния сигнализации. 
}  
                                 
void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  }
  if (gsm.available()) {                      // Если модем, что-то отправил...
      String val = "";                      // Переменная для хранения ответа модуля
      val = waitgsm();                 // Получаем ответ от модема для анализа
//  Serial.println(val);                  // Если нужно выводим в монитор порта
      if (val.indexOf(F("+PBREADY")) > -1) InitModem();
      else if (val.indexOf(F("+CLIP: ")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
//        delay(2000);                             // дадим гудок
        int ind = val.indexOf(F("+CLIP: \""));          // обрезаем номер 
//        if (ind >= 0) {                     // Если информация была найдена
        ind += 8;                         // Парсим строку и
        val = val.substring(ind, val.indexOf("\"", ind));
//        }
  Serial.println("ring: " + val);                            
        gsm.println(F("ATH"));              // сбрасываем вызов.
        if (CheckPhone(val) == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
        } else  Serial.println(F("No Master Ring!"));  
      } else if (val.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
        parsesms(val);
      } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
        String bal = "";
        if (ModemID == 3) {
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
          int p1 = val.indexOf("\"");         // начало строки
          int p2 = val.lastIndexOf("\"");     // конец строки
          val = val.substring(p1+1,p2);
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(val);
  Decode7bit(val, bal);
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        } else if (ModemID == 1 || 2) {
          bal = String(val.substring(val.indexOf(",\"") + 2,val.indexOf("\",")));  //
        }
        Serial.println(bal);
sms("SIM " + bal + "\n", 0);    // смс на последний звонивший
        gsm.println(F("AT+CUSD=0"));
         } 
  } else if (Serial.available()) {           // если в мониторе порта что-то ввели
      String serialval = "";
      while (Serial.available()) {         // сохраняем входную строку в переменную val.
        char ch = Serial.read();
        serialval += char(ch);                   // собираем принятые символы в строку
        delay(3);
        } 
        sendsmscaller = 0;
  Komand(serialval);                        // запускаем консольную программу
        sendsmscaller = 1;
    }
}

String waitgsm() {                         // Функция ожидания ответа и возврата полученного результата
  String gsmval = "";                            // Переменная для хранения результата
  uint32_t _timeout = millis() + 5000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!gsm.available() && (millis() < _timeout))  {}; // Ждем ответа5 секунд, если пришел ответ или наступил таймаут, то...
  if (gsm.available()) {     // если GSM модем что-то послал.
    while (gsm.available()) {  // сохраняем входную строку в переменную val.
      char ch = gsm.read();
      gsmval += char(ch);              // собираем принятые символы в строку
      delay(5);
    } 
  } else {                                      // Если пришел таймаут, то...
    Serial.println(F("Timeout..."));               // ... оповещаем об этом и...
  }
  return gsmval;                                 // ... возвращаем результат. Пусто, если проблема
}

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

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

  int Index = msgheader.indexOf("+CMT:");
  Index += 8;                         // Парсим строку и
  msgphone = msgheader.substring(Index, msgheader.indexOf("\"", Index));
 
  Serial.println("Phone: " + msgphone);    // Выводим номер телефона
  Serial.println("Message: " + msgsms);    // Выводим текст SMS
     if (CheckPhone(msgphone) == 1) {      // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  Komand(msgsms);
     } else  Serial.println(F("No Master SMS!"));
}

int CheckPhone(String phone) { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (phone == AlarmPhone[i] && phone != 0) { // если есть вызов, и он наш
        phone = AlarmPhone[i];              // запоминаем его.
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 14);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
        phone.toCharArray(Phone, 14);
        EEPROM.put(25, Phone);                    // пишем номер в EEPROM
        EEPROM.put(100, Phone);                   // записываем RingPhone в память. 
        AlarmPhone[0] = Phone;                    // запишем
        RingPhone = Phone;                        // запоминаем его.
        EEPROM.update(10, 0);                     // обновляем Firststart
        Firststart = 0;                           // пишем 0
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String(F("Master0:")) + phone + " Ok\n", 0);     // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
    } return 1;                               
}

void eepromconfig() { /// === конфигурирование сигнализации === ///
    if (EEPROM.read(0) != 1) {           // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // SARAIon     датчики дверей вкл.
      EEPROM.update(6, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(7, 1);   // GASon       датчик газа вкл.
      EEPROM.update(8, 1);   // Sirena      сирена вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
  Serial.println(F("EEPROM != 1/ RESET!")); 
    } if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   // Охрана
      AlarmRING  = EEPROM.read(2);   // Вызов
      SendSMS    = EEPROM.read(3);   // Отправка смс
      DOORon     = EEPROM.read(4);   // Датчик двери
      SARAIon    = EEPROM.read(5);   // Датчик двери
      PIRon      = EEPROM.read(6);   // Датчик движения
      GASon      = EEPROM.read(7);   // Датчик газа/дыма
      Sirena     = EEPROM.read(8);   // сирена
      Firststart = EEPROM.read(10);  //
    }
}

String eepromtext() { /// === состояние системы === ///
   String SIGN = "";         // текущее состояние системы.
   String SIRENA = "";       // аварийная сирена.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Sarai = "";        // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
   if (Guard == 1) SIGN = F("System on\n"); else SIGN = F("System off\n");
   if (Sirena == 1) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n");
   if (AlarmRING == 1) RING = F("Ring on\n"); else RING = F("Ring off\n");
   if (SendSMS == 1) SMS = F("SMS on\n"); else SMS = F("SMS off\n");
   if (DOORon == 1) Door = F("Door on\n"); else Door = F("Door off\n");
   if (SARAIon == 1) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n");
   if (PIRon == 1) Pir = F("Pir on\n"); else Pir = F("Pir off\n");
   if (GASon == 1) Gas = F("Gas on\n"); else Gas = F("Gas off\n");
    String LastEvent = SIGN + RING + SMS + SIRENA + Pir + Door + Sarai + Gas;             // полное состояние системы и датчиков.
    return LastEvent;
}

String eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем мастер-номера 
      AlarmPhone[i] = Phone;
    }
    String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n";
    EEPROM.get(100, Phone);                // считываем номер последнего звонившего
    RingPhone = Phone;
    String ring = String(F("Ring ")) + RingPhone + "\n";
    EEPROM.get(20, Bal);                   // считываем номер баланса
    String bal = String(F("Balance *")) + Bal + "#\n"; 
    String EEPhone = numbers + ring + bal;
    return EEPhone;
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  
  if (DOORon == 1) {
    if (DOORState == HIGH && DOORFlag == 0) {
      previousMillis_door = millis();
      DOORFlag = 1;
//  Serial.println(F("Dver' otkrita!"));
  Alarm();                                // 
    }
    else if (DOORState == LOW && DOORFlag == 1) {
      int currentMillis_door = millis();
      if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
        DOORFlag = 0;
      }
    }
  }
  if (SARAIon == 1) {
    if (mySwitch.available()) {
      unsigned long value = mySwitch.getReceivedValue();
      if (value == sarai && SARAIFlag == 0) {
        previousMillis_sarai = millis();
        SARAIFlag = 1;
//  Serial.println(F("Sarai otkrit!"));
  Alarm();                                // 
      }
      mySwitch.resetAvailable();
    }
    int currentMillis_sarai = millis();
    if (((currentMillis_sarai - previousMillis_sarai) / 1000 > interval_sarai)) {
      SARAIFlag = 0;
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
//  Serial.println(F("Dvizhenie u dveri!"));
  Alarm();                                // 
    }
    else if (PIRState == LOW && PIRFlag == 1) {
      int currentMillis_pir = millis();
      if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_pir)) {
        PIRFlag = 0; 
      }
    }
  }
  if (GASon == 1) {
    if ((Smoky > GASThres) && GASFlag == 0) {
      previousMillis_gas = millis();
      GASFlag = 1;
      delay(100);
//  Serial.println(F("Gas v dome!"));
  Alarm();                                // 
    }
    else if ((Smoky < GASThres) && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) {
        GASFlag = 0; 
      }
    }
  }
}

void Alarm() { /// === запускаем сирену и отправку смс === ///
    previousMillis_alarm = millis();
    if (Sirena == 1) digitalWrite(BUZ, LOW);
    Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
        if (DOORFlag == 1) {
sms(F("Dver' otkrita!\n"), 1); // смс на все номера
        }
        else if (SARAIFlag == 1) {
sms(F("Sarai otkrit!\n"), 1); // смс на все номера
        }
        else if (PIRFlag == 1) {
sms(F("Dvizhenie y dveri!\n"), 1); // смс на все номера
        }
        else if (GASFlag == 1) {
sms(F("Gas v dome!\n"), 1); // смс на все номера
        }
    }
    if (AlarmRING == 1) {
      gsm.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
}

void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  int currentMillis_alarm = millis();
  if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) {
    digitalWrite(BUZ, HIGH);
  } 
}

void MasterRing() { /// === мастер звонков === //
  if (Guard == 1) GuardOff();     // меняем состояние
  else if (Guard == 0) GuardOn(); // меняем состояние
}

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
sms(String(F("System->off\n")), 1); // смс на все номера
}

void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
sms(String(F("System->on\n")), 1); // смс на все номера
}

void Led() { /// === состояние светодиода === ///
//  if (Guard == 1) {                   // если на охране
  int currentMillis_led = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis_led - previousMillis_led > interval_led) {
      // сохраняем время последнего переключения
      previousMillis_led = currentMillis_led;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LEDState == HIGH) LEDState = LOW;
      else LEDState = HIGH;
      digitalWrite(LED, LEDState);
    }
//  } else digitalWrite(LED, HIGH); // иначе гасим его
}

void Komand(String kom) { /// === мастер смс === ///
  Serial.println("-> " + kom);
  kom.toLowerCase();
  if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) {        // команды выполняются только с 0 мастер номера
    if (kom.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
sms(F("System Reset!\n"), 0); // смс на последний номер
      EEPROM.write(0, 0);
  eepromconfig();
  Serial.println(eepromtext());
  Serial.println(eepromphone());
    } else if ((p = kom.indexOf(F("master"))) > -1)  { // добавление мастер-номера
      master(kom.substring(p + 6, p + 7).toInt(), kom.substring(p + 8, kom.indexOf("\n", p + 8)));
///// sms типа: " master1:79111234567 " - ячейка + номер
    } else if ((p = kom.indexOf(F("balance:"))) > -1) { // добавление номера баланса
      balnum(kom.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
    } else if ((p = kom.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки     
      dellphone(kom.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } else if (kom.indexOf(F("phone")) > -1)     { // инфо о номерах системы
sms(eepromphone(), 0); // смс на последний номер
    }
  }  
  if ((kom.indexOf(F("info")) > -1) || (kom.indexOf(F("?")) > -1)) {     // инфо о состоянии системы
  eepromconfig();
sms(eepromtext(), 0); // смс на последний номер
  } else if (kom.indexOf(F("temp")) > -1)  {    // вкл
sms(TempC(), 0); // смс на последний номер
  } else if (kom.indexOf(F("money")) > -1) {   // запрос баланса
  balance();
  } else if (kom.indexOf(F("datchiki")) > -1) {
    if (kom.indexOf(on) > -1) {       // вкл 
      DOORon = 1;
      SARAIon = 1;
      PIRon = 1;
      GASon = 1;
      EEPROM.update(4, DOORon);
      EEPROM.update(5, SARAIon);
      EEPROM.update(6, PIRon);
      EEPROM.update(7, GASon);
    } else if (kom.indexOf(off) > -1) {       // выкл 
      DOORon = 0;
      SARAIon = 0;
      PIRon = 0;
      GASon = 0;
      EEPROM.update(4, DOORon);
      EEPROM.update(5, SARAIon);
      EEPROM.update(6, PIRon);
      EEPROM.update(7, GASon);
    }
sms(eepromtext(), 1); // смс на последний номер
  } else if (kom.indexOf(F("system")) > -1)  {  // вкл/выкл сигнализацию
    if (kom.indexOf(on) > -1)  {    // вкл 
  GuardOn();
    } else if (kom.indexOf(off) > -1)  {    // вкл
  GuardOff();
    }
  } else if (kom.indexOf(F("sirena")) > -1) {     // вкл/выкл сирены
    if (kom.indexOf(on) > -1) {       // вкл 
      Sirena = 1;
      EEPROM.update(8, Sirena);                   
sms(String(F("Sirena->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {      // выкл
      Sirena = 0;
      EEPROM.update(8, Sirena);                   
sms(String(F("Sirena->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("ring")) > -1)   { // вкл/выкл вызов при сработке
    if (kom.indexOf(on) > -1)   { // вкл 
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)   { // выкл 
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("sms")) > -1)    { // вкл/выкл смс при сработке
    if (kom.indexOf(on) > -1)    { // вкл 
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)    { // выкл
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("door")) > -1) {  // вкл/выкл контроль датчика двери
    if (kom.indexOf(on) > -1) {  // выкл
      DOORon = 1;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл контроль датчика двери
      DOORon = 0;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("sarai")) > -1) {  // вкл/выкл контроль датчика двери 2
    if (kom.indexOf(on) > -1) {  // вкл
      SARAIon = 1;
      EEPROM.update(5, SARAIon);
sms(String(F("SARAI->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      SARAIon = 0;
      EEPROM.update(5, SARAIon);
sms(String(F("SARAI->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("pir")) > -1) {  // вкл/выкл контрол датчика движения
    if (kom.indexOf(on) > -1) {  // вкл
      PIRon = 1;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл
      PIRon = 0;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("gas")) > -1) {  // вкл/выкл контроль датчика газа
    if (kom.indexOf(on) > -1) {  // вкл 
      GASon = 1;
      EEPROM.update(7, GASon);
sms(String(F("GAS->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      GASon = 0;
      EEPROM.update(7, GASon);
sms(String(F("GAS->off\n")), 1); // смс на все номера
    }
  }
  gsm.println(F("AT+CMGD=1,4")); // стираем смс
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(100);
  if (ModemID == 1) {
    gsm.println(AT_M590);
    delay(100);
  gsm.println(String("ATD#") + Bal + String("#;"));
  } else if (ModemID == 2 || ModemID == 3) gsm.println(String(AT_SIM800_A6) + Bal + "#,15");
  Serial.println(String(F("Balance#")) + Bal + "#"); 
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
    if (i < 5 && i != 0) {
      num.toCharArray(Phone, 14); // конвертируем
      AlarmPhone[i] = num;        // пишем номер  
      EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
sms(String(F("Master")) + i + ":" + num + " add\n", 0); // смс на 0 номер.
    }// else Serial.println(F("MAX number 4!"));             // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
    return 1;                             
}                              

int dellphone (int i) { /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
sms(String(F("Master")) + i + ":" + AlarmPhone[i] + " dell\n", 0); // смс на 0 номер
       EEPROM.put(Adress[i], 0);
       AlarmPhone[i] = "";   // обнулим номер
  } return 1;                          
}

int balnum (String num) { /// === добавляем номер баланса === ///
    num.toCharArray(Bal, 4);   // конвертируем
    EEPROM.put(20, Bal);           // записываем массив в EEPROM 
sms(String(F("Balance:*")) + num + F("# Ok\n"), 0); // смс на 0 номер
    return 1;                             
}

String TempC() {      /// === измеряем температуру === ///
  String temp;
    byte data[2];
    ds.reset();
    ds.write(0xCC);
    ds.write(0x44);
    delay(750);
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    int Temp = (data[1] << 8) + data[0];
    Temp = Temp >> 4;
    temp = String(F("Temp ")) + Temp + "*C";
  return temp;
}

void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === ///
  byte reminder = 0;
  int bitstate = 7;
  for (unsigned int i = 0; i < instr.length(); i++) {
    byte b = instr[i];
    byte bb = b << (7 - bitstate);
    char c = (bb + reminder) & 0x7F;
    outstr += c;
    reminder = b >> bitstate;
    bitstate--;
    if (bitstate == 0) {
      char c = reminder;
      outstr += c;
      reminder = 0;
      bitstate = 7;
    }
  }
}

void InitModem() { /// === инициализация модема === ///
  gsm.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  String val = sendATCommand(F("ATI"), true);
    for (int i = 0; i < 5; i++) {
        sendATCommand(AT[i], true);         // включить АОН
    }
    if (val.indexOf(F("M590")) > -1) ModemID = 1;
    else if (val.indexOf(F("SIM800")) > -1) ModemID = 2;
    else if (val.indexOf("A6") > -1) ModemID = 3;
    Serial.println(String(F("ModemID ")) + ModemID + "\n");
}

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

void waitConnect() {  // запуск модема
  int countok = 0;
  uint32_t msAT = 0;
  String str; 
  while(countok < 5) {                      //ждём пять ОК  
    uint32_t ms = millis();
    if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс 
      msAT = ms;
      Serial.println(">>AT");
      gsm.println("AT");                    // посылаем команду
      str = "";
      delay(100);                           // ждём ответа
      while(gsm.available()) {
        char ch = gsm.read();
        str += ch;
      } 
      if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;}
      else countok = 0;
    }
  }  
}

void sms(String text, byte sendnum) { /// === отправка СМС === ///
    String phone = "";
    if (sendsmscaller == 1 && sendnum == 0) {                  // отправка смс на номер звонившего
      phone = RingPhone;
      Serial.println(String(F("SMS send=>")) + phone); 
      gsm.println(String(F("AT+CMGS=\"+")) + phone + "\"");
      delay(100);
      gsm.print(text + TempC());
      delay(100);
      gsm.print((char)26);
      delay(2000);
    } 
    else if (sendsmscaller == 1 && sendnum == 1) {                  // отправка смс на все номера
      for (int i = 0; i < 4 ; i++) {        
        phone = AlarmPhone[i];
        if (phone != 0) {
          Serial.println(String(F("SMS send=>")) + phone); 
          gsm.println(String(F("AT+CMGS=\"+")) + phone + "\"");
          delay(100);
          gsm.print(text + TempC());
          delay(100);
          gsm.print((char)26);
          delay(4000);
        }
      }
    }
    Serial.println(text + TempC() + "\n");
}

в этом коде реализован автовыбор модема, и соответственно АТ команды для него

AleksandrM
Offline
Зарегистрирован: 20.07.2017

Спасибо попробовал все ОК до запроса баланса.При отправке сигналкой смс о состоянии счета устройство виснет наглухо помогает только кнопка сброс.Вот кусок с терминала

-> Money
Balance#101#
Input string:
O7(⸮⸮⸮A⸮⸮⸮]w⸮A⸮⸮⸮U⸮H⸮⸮⸮⸮f⸮⸮⸮&⸮⸮ow⸮L⸮⸮⸮⸮⸮r⸮⸮⸮d⸮⸮dP⸮MO⸮A0⸮+s⸮`1⸮4|⸮⸮⸮1$~⸮⸮⸮⸮d~⸮AǤ⸮:
⸮⸮e7T⸮ݠis
⸮⸮A8⸮⸮⸮⸮at

Decode string:
On Your account 15.51 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
SMS send=>380662424500
SIM On Your account 15.51 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
Temp 23*C

может это длина сообщения? как его обрезать до 30 символов?

pasha413
Offline
Зарегистрирован: 27.11.2016

Да, это из-за длинны смс, у вас ответ баланса приходит не в таком виде как у нас. Сейчас посмотрю

Gienekb
Offline
Зарегистрирован: 29.08.2017

AleksandrM, Если у вас есть модем M590, попробуйте его заменить. Я читал, что по причине самого модема появляются такие ошибки.

pasha413
Offline
Зарегистрирован: 27.11.2016

подскажите, пожалуйста. как отправить смс на несколько номеров, поочередно, дождавшись отправки предыдущего (должно прийти от модема "ОК").

вот набросал код, но не получается:

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

int8_t ModemID = 0;
uint32_t msAT = 0;
String Master[2] = {"79531112233", "79112234455"};

void setup() {
  Serial.begin(9600);                       // Скорость обмена данными с компьютером
  InitModem();                      // запускаем инициализация модема.
  Serial.println(F("+++++READY+++++"));                              
}

void loop() {
  if (gsm.available()) {                      // Если модем, что-то отправил...
      String val = "";                      // Переменная для хранения ответа модуля
      val = waitgsm();                 // Получаем ответ от модема для анализа
  Serial.println("gsmval->" + val);    // Если нужно выводим в монитор порта, что пришло:
      if (val.indexOf(F("+PBREADY")) > -1) InitModem();
      else if (val.indexOf(F("+CLIP: ")) > -1) {        // если обнаружен вызов.
        gsm.println(F("ATH"));              // сбрасываем вызов.
  Serial.println(F("Process RING"));                              
        int ind = val.indexOf(F("+CLIP: \""));          // обрезаем номер 
        ind += 8;                         // Парсим строку и
        val = val.substring(ind, val.indexOf("\"", ind));
  Serial.println("phone->" + val);                            
        delay(3000);
sendSMS("TESTOK!");
      }   
  } else if (Serial.available())  {                    // Ожидаем команды по Serial...
    gsm.write(Serial.read());                   // ...и отправляем полученную команду модему
  }
}

String waitgsm() {                         // Функция ожидания ответа и возврата полученного результата
  String gsmval = "";                            // Переменная для хранения результата
  uint32_t _timeout = millis() + 10000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!gsm.available() && (millis() < _timeout))  {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  if (gsm.available()) {     // если GSM модем что-то послал.
    while (gsm.available()) {  // сохраняем входную строку в переменную val.
      char ch = gsm.read();
      gsmval += char(ch);              // собираем принятые символы в строку
      delay(5);
    } 
  } else {                                      // Если пришел таймаут, то...
    Serial.println(F("Timeout..."));               // ... оповещаем об этом и...
  }
  return gsmval;                                 // ... возвращаем результат. Пусто, если проблема
}

void InitModem() { /// === инициализация модема === ///
  Serial.println(F("Start GSM"));
  gsm.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  String val = sendATCommand(F("ATI"), true);
  if (val.indexOf(F("M590")) > -1) ModemID = 1; // Serial.println("Modem M590");
  else if (val.indexOf(F("SIM800")) > -1) ModemID = 2; // Serial.println("Modem SIM800"); 
  else if (val.indexOf("A6") > -1) ModemID = 3; // Serial.println("Modem A6");
  Serial.println(String(F("ModemID ")) + ModemID);
  sendATCommand(F("AT+CLIP=1"), true);         // включить АОН
  sendATCommand(F("AT+CMGF=1"), true);         // Включить TextMode для SMS
  sendATCommand(F("AT+CSCS=\"GSM\""), true);   // кодировка текста - GSM
  sendATCommand(F("AT+CNMI=2,2,0,0,0"), true);
  sendATCommand(F("AT+CREG?"), true);
//  delay(1000); 
}

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

void waitConnect() {  // запуск модема
  int countok = 0;
  uint32_t msAT = 0;
  String str; 
  while(countok < 5) {                      //ждём пять ОК  
    uint32_t ms = millis();
    if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс 
      msAT = ms;
      Serial.println(">>AT");
      gsm.println("AT");                    // посылаем команду
      str = "";
      delay(100);                           // ждём ответа
      str = waitgsm();
      if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;}
      else countok = 0;
    }
  }  
}

int sendSMS(String message) {
  for (int i = 0; i < 2; i++) {
    sendATCommand("AT+CMGS=\"+" + Master[i] + "\"", true);             // Переходим в режим ввода текстового сообщения
    sendATCommand(message + "\r\n" + (String)((char)26), true);   // После текста отправляем перенос строки и Ctrl+Z+
    
    String x = waitgsm();
    x.toLowerCase();
    if (x.indexOf("+CMGS:") > -1) { Serial.println("OK!!"); return 1; }
    else  Serial.println(F("Timeout!!!")); 
  } return 0;
}

 

AleksandrM
Offline
Зарегистрирован: 20.07.2017

pasha413

По поводу укоротить сообщение о балансе не поможешь?

pasha413
Offline
Зарегистрирован: 27.11.2016

AleksandrM, попробуйте.

// max длинна сообщения в данный момент 135 символов.
#include <EEPROM.h> 
#include <OneWire.h>
#include <RCSwitch.h>
#include <SoftwareSerial.h>
#define Ver F("Alarm  v4.3.3_UK_Phone[12]\n")

OneWire ds(6);                  // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +.
SoftwareSerial gsm(7, 8);  // модем подключен к 7 и 8 пинам.
RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2.

#define DOOR 4             // пин 4. концевик двери.
#define PIR 5              // пин 5. датчик движения.
#define LED 13             // пин 13. состояние системы.
#define GAS 14             // пин A0. датчик дыма.
#define BUZ 15             // пин A1. сирена.
#define sarai 3258553      // адрес 433 передатчика геркона двери

// DOOR     - если сработал, на входе "+" HIGH.
// SARAI    - если сработал, на пин 2 сигнал.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// LED      - если "-" LOW, то горит.

#define on "on"     // вкл
#define off "off"   // выкл

int8_t ModemID = 0;        //    тип модема
int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевика двери:       1 - вкл, 0 - выкл.    
int8_t SARAIon = 1;        // 4. контроль концевика двери 2:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.
int8_t Sirena = 1;         // 7. сирена:                         1 - вкл, 0 - выкл. 
int8_t Firststart = 1;     // первый старт.

int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t SARAIFlag = 0;      // флаг состояние датчика двери 2.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LEDState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t sendsmscaller = 1;  // разрешение отправки смс.

uint32_t msAT = 0;

char Bal[4];               // для временного хранения номера баланса.   
char Phone[13];            // для временного хранения номера телефона.      
String  AT[] = {"AT+CLIP=1", "AT+CMGF=1", "AT+CSCS=\"GSM\"", "AT+CNMI=2,2,0,0,0", "AT+CREG?"}; // общие АТ команды
#define  AT_M590  F("AT+CUSD=1")            // баланс для М590
#define  AT_SIM800_A6  F("AT+CUSD=1,#")     // баланс для А6 и СИМ800
 
String RingPhone = "";          // номер звонившего.
String AlarmPhone[5];           // номера для постановки/снятии с охраны и отправки смс.
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.

int p = 0;
#define GASThres 400           // предельная концентрация газа
#define interval_alarm 20      // Секунд до отключения "тревожного" пина. 
int previousMillis_alarm = 0;
#define interval_led 1000      // для мигания LED, 1 сек.
int previousMillis_led = 0;
#define interval_door 10       // секунд не смотрим на датчик двери.
int previousMillis_door = 0;
#define interval_sarai 10      // секунд не смотрим на датчик двери 2.
int previousMillis_sarai = 0;
#define interval_pir 20        // секунд не смотрим на датчик движения.
int previousMillis_pir = 0;
#define interval_gas 600       // секунд не смотрим на датчик газа. 10минут
int previousMillis_gas = 0;

/* EEPROM Data:
  № ячейки - значение:
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:                0 - выкл.
  2 - AlarmRING = 1;   // звонок:                1 - вкл. 
  3 - SendSMS = 1;     // отправка смс:          1 - вкл.
  4 - DOORon = 1;      // концевик двери:        1 - вкл.
  5 - SARAIon = 1;     // концевик двери сарая:  1 - вкл.
  6 - PIRon = 1;       // датчик движения:       1 - вкл.
  7 - GASon = 1;       // датчик дыма:           1 - вкл.
  8 - Sirena = 1;      // сирена:                1 - вкл.
  10 - Firststars = 1; // первый запуск          1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// === настройка программы === ///
  Serial.begin(9600); 
  Serial.println(Ver); 
  pinMode(DOOR, INPUT_PULLUP);      // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);           
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);
  pinMode(LED, OUTPUT);             // светодиод горит во время запуска.
    digitalWrite(BUZ, HIGH);        // сирена выкл.
    digitalWrite(PIR, HIGH);        // игнорируем при включении.
  mySwitch.enableReceive(0);        // 433 приемник на 2 пине
  InitModem();                      // запускаем инициализация модема.
  eepromconfig();
  Serial.println(eepromtext()); 
  Serial.println(eepromphone()); 
    digitalWrite(LED, HIGH);        // гасим светодиод состояния сигнализации. 
}  
                                 
void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  }
  if (gsm.available()) {                      // Если модем, что-то отправил...
      String val = "";                      // Переменная для хранения ответа модуля
      val = waitgsm();                 // Получаем ответ от модема для анализа
//  Serial.println(val);                  // Если нужно выводим в монитор порта
      if (val.indexOf(F("+PBREADY")) > -1) InitModem();
      else if (val.indexOf(F("+CLIP: ")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
        int ind = val.indexOf(F("+CLIP: \""));          // обрезаем номер 
        if (ind >= 0) {                     // Если информация была найдена
          ind += 8;                         // Парсим строку и
          val = val.substring(ind, val.indexOf("\"", ind));
        }
        delay(3000);                             // дадим гудок
        gsm.println(F("ATH"));              // сбрасываем вызов.
  Serial.println("val: " + val);                            
        if (CheckPhone(val) == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
        } else  Serial.println(F("No Master Ring!"));  
      } else if (val.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
        parsesms(val);
      } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
        String bal = "";
        if (ModemID == 3) {
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
          int p1 = val.indexOf("");         // начало строки
          int p2 = val.lastIndexOf("UAH");     // конец строки
          val = val.substring(p1+1, p2);
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(val);
  Decode7bit(val, bal);
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        } else if (ModemID == 1 || 2) {
          bal = String(val.substring(val.indexOf(",\"") + 2,val.indexOf("\",")));  //
        }
        Serial.println(bal);
sms("SIM " + bal + "\n", 0);    // смс на последний звонивший
        gsm.println(F("AT+CUSD=0"));
         } 
  } else if (Serial.available()) {           // если в мониторе порта что-то ввели
      String serialval = "";
      while (Serial.available()) {         // сохраняем входную строку в переменную val.
        char ch = Serial.read();
        serialval += char(ch);                   // собираем принятые символы в строку
        delay(3);
        } 
        sendsmscaller = 0;
  Komand(serialval);                        // запускаем консольную программу
        sendsmscaller = 1;
    }
}

String waitgsm() {                         // Функция ожидания ответа и возврата полученного результата
  String gsmval = "";                            // Переменная для хранения результата
  uint32_t _timeout = millis() + 5000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!gsm.available() && (millis() < _timeout))  {}; // Ждем ответа5 секунд, если пришел ответ или наступил таймаут, то...
  if (gsm.available()) {     // если GSM модем что-то послал.
    while (gsm.available()) {  // сохраняем входную строку в переменную val.
      char ch = gsm.read();
      gsmval += char(ch);              // собираем принятые символы в строку
      delay(5);
    } 
  } else {                                      // Если пришел таймаут, то...
    Serial.println(F("Timeout..."));               // ... оповещаем об этом и...
  }
  return gsmval;                                 // ... возвращаем результат. Пусто, если проблема
}

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

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

  int Index = msgheader.indexOf("+CMT:");
  msgphone = msgheader.substring(Index + 8, Index + 20);
  msgphone.trim();
 
  Serial.println("Phone: " + msgphone);    // Выводим номер телефона
  Serial.println("Message: " + msgsms);    // Выводим текст SMS
     if (CheckPhone(msgphone) == 1) {      // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  Komand(msgsms);
     } else  Serial.println(F("No Master SMS!"));
}

int CheckPhone(String phone) { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (phone == AlarmPhone[i] && phone != 0) { // если есть вызов, и он наш
        phone = AlarmPhone[i];              // запоминаем его.
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 13);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
        phone.toCharArray(Phone, 13);
        EEPROM.put(25, Phone);                    // пишем номер в EEPROM
        EEPROM.put(100, Phone);                   // записываем RingPhone в память. 
        AlarmPhone[0] = Phone;                    // запишем
        RingPhone = Phone;                        // запоминаем его.
        EEPROM.update(10, 0);                     // обновляем Firststart
        Firststart = 0;                           // пишем 0
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String(F("Master0:")) + phone + " Ok\n", 0);     // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
    } return 1;                               
}

void eepromconfig() { /// === конфигурирование сигнализации === ///
    if (EEPROM.read(0) != 1) {           // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // SARAIon     датчики дверей вкл.
      EEPROM.update(6, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(7, 1);   // GASon       датчик газа вкл.
      EEPROM.update(8, 1);   // Sirena      сирена вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
  Serial.println(F("EEPROM != 1/ RESET!")); 
    } if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   // Охрана
      AlarmRING  = EEPROM.read(2);   // Вызов
      SendSMS    = EEPROM.read(3);   // Отправка смс
      DOORon     = EEPROM.read(4);   // Датчик двери
      SARAIon    = EEPROM.read(5);   // Датчик двери
      PIRon      = EEPROM.read(6);   // Датчик движения
      GASon      = EEPROM.read(7);   // Датчик газа/дыма
      Sirena     = EEPROM.read(8);   // сирена
      Firststart = EEPROM.read(10);  //
    }
}

String eepromtext() { /// === состояние системы === ///
   String SIGN = "";         // текущее состояние системы.
   String SIRENA = "";       // аварийная сирена.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Sarai = "";        // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
   if (Guard == 1) SIGN = F("System on\n"); else SIGN = F("System off\n");
   if (Sirena == 1) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n");
   if (AlarmRING == 1) RING = F("Ring on\n"); else RING = F("Ring off\n");
   if (SendSMS == 1) SMS = F("SMS on\n"); else SMS = F("SMS off\n");
   if (DOORon == 1) Door = F("Door on\n"); else Door = F("Door off\n");
   if (SARAIon == 1) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n");
   if (PIRon == 1) Pir = F("Pir on\n"); else Pir = F("Pir off\n");
   if (GASon == 1) Gas = F("Gas on\n"); else Gas = F("Gas off\n");
    String LastEvent = SIGN + RING + SMS + SIRENA + Pir + Door + Sarai + Gas;             // полное состояние системы и датчиков.
    return LastEvent;
}

String eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем мастер-номера 
      AlarmPhone[i] = Phone;
    }
    String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n";
    EEPROM.get(100, Phone);                // считываем номер последнего звонившего
    RingPhone = Phone;
    String ring = String(F("Ring ")) + RingPhone + "\n";
    EEPROM.get(20, Bal);                   // считываем номер баланса
    String bal = String(F("Balance *")) + Bal + "#\n"; 
    String EEPhone = numbers + ring + bal;
    return EEPhone;
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  
  if (DOORon == 1) {
    if (DOORState == HIGH && DOORFlag == 0) {
      previousMillis_door = millis();
      DOORFlag = 1;
//  Serial.println(F("Dver' otkrita!"));
  Alarm();                                // 
    }
    else if (DOORState == LOW && DOORFlag == 1) {
      int currentMillis_door = millis();
      if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
        DOORFlag = 0;
      }
    }
  }
  if (SARAIon == 1) {
    if (mySwitch.available()) {
      unsigned long value = mySwitch.getReceivedValue();
      if (value == sarai && SARAIFlag == 0) {
        previousMillis_sarai = millis();
        SARAIFlag = 1;
//  Serial.println(F("Sarai otkrit!"));
  Alarm();                                // 
      }
      mySwitch.resetAvailable();
    }
    int currentMillis_sarai = millis();
    if (((currentMillis_sarai - previousMillis_sarai) / 1000 > interval_sarai)) {
      SARAIFlag = 0;
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
//  Serial.println(F("Dvizhenie u dveri!"));
  Alarm();                                // 
    }
    else if (PIRState == LOW && PIRFlag == 1) {
      int currentMillis_pir = millis();
      if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_pir)) {
        PIRFlag = 0; 
      }
    }
  }
  if (GASon == 1) {
    if ((Smoky > GASThres) && GASFlag == 0) {
      previousMillis_gas = millis();
      GASFlag = 1;
      delay(100);
//  Serial.println(F("Gas v dome!"));
  Alarm();                                // 
    }
    else if ((Smoky < GASThres) && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) {
        GASFlag = 0; 
      }
    }
  }
}

void Alarm() { /// === запускаем сирену и отправку смс === ///
    previousMillis_alarm = millis();
    if (Sirena == 1) digitalWrite(BUZ, LOW);
    Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
        if (DOORFlag == 1) {
sms(F("Dver' otkrita!\n"), 1); // смс на все номера
        }
        else if (SARAIFlag == 1) {
sms(F("Sarai otkrit!\n"), 1); // смс на все номера
        }
        else if (PIRFlag == 1) {
sms(F("Dvizhenie y dveri!\n"), 1); // смс на все номера
        }
        else if (GASFlag == 1) {
sms(F("Gas v dome!\n"), 1); // смс на все номера
        }
    }
    if (AlarmRING == 1) {
      gsm.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
}

void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  int currentMillis_alarm = millis();
  if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) {
    digitalWrite(BUZ, HIGH);
  } 
}

void MasterRing() { /// === мастер звонков === //
  if (Guard == 1) GuardOff();     // меняем состояние
  else if (Guard == 0) GuardOn(); // меняем состояние
}

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
sms(String(F("System->off\n")), 1); // смс на все номера
}

void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
sms(String(F("System->on\n")), 1); // смс на все номера
}

void Led() { /// === состояние светодиода === ///
//  if (Guard == 1) {                   // если на охране
  int currentMillis_led = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis_led - previousMillis_led > interval_led) {
      // сохраняем время последнего переключения
      previousMillis_led = currentMillis_led;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LEDState == HIGH) LEDState = LOW;
      else LEDState = HIGH;
      digitalWrite(LED, LEDState);
    }
//  } else digitalWrite(LED, HIGH); // иначе гасим его
}

void Komand(String kom) { /// === мастер смс === ///
  Serial.println("-> " + kom);
  kom.toLowerCase();
  if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) {        // команды выполняются только с 0 мастер номера
    if (kom.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
sms(F("System Reset!\n"), 0); // смс на последний номер
      EEPROM.write(0, 0);
  eepromconfig();
  Serial.println(eepromtext());
  Serial.println(eepromphone());
    } else if ((p = kom.indexOf(F("master"))) > -1)  { // добавление мастер-номера
      master(kom.substring(p + 6, p + 7).toInt(), kom.substring(p + 8, p + 23));
///// sms типа: " master1:79111234567 " - ячейка + номер
    } else if ((p = kom.indexOf(F("balance:"))) > -1) { // добавление номера баланса
      balnum(kom.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
    } else if ((p = kom.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки     
      dellphone(kom.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } else if (kom.indexOf(F("phone")) > -1)     { // инфо о номерах системы
sms(eepromphone(), 0); // смс на последний номер
    }
  }  
  if ((kom.indexOf(F("info")) > -1) || (kom.indexOf(F("?")) > -1)) {     // инфо о состоянии системы
  eepromconfig();
sms(eepromtext(), 0); // смс на последний номер
  } else if (kom.indexOf(F("temp")) > -1)  {    // вкл
sms(TempC(), 0); // смс на последний номер
  } else if (kom.indexOf(F("money")) > -1) {   // запрос баланса
  balance();
  } else if (kom.indexOf(F("datchiki")) > -1) {
    if (kom.indexOf(on) > -1) {       // вкл 
      DOORon = 1;
      SARAIon = 1;
      PIRon = 1;
      GASon = 1;
      EEPROM.update(4, DOORon);
      EEPROM.update(5, SARAIon);
      EEPROM.update(6, PIRon);
      EEPROM.update(7, GASon);
    } else if (kom.indexOf(off) > -1) {       // выкл 
      DOORon = 0;
      SARAIon = 0;
      PIRon = 0;
      GASon = 0;
      EEPROM.update(4, DOORon);
      EEPROM.update(5, SARAIon);
      EEPROM.update(6, PIRon);
      EEPROM.update(7, GASon);
    }
sms(eepromtext(), 1); // смс на последний номер
  } else if (kom.indexOf(F("system")) > -1)  {  // вкл/выкл сигнализацию
    if (kom.indexOf(on) > -1)  {    // вкл 
  GuardOn();
    } else if (kom.indexOf(off) > -1)  {    // вкл
  GuardOff();
    }
  } else if (kom.indexOf(F("sirena")) > -1) {     // вкл/выкл сирены
    if (kom.indexOf(on) > -1) {       // вкл 
      Sirena = 1;
      EEPROM.update(8, Sirena);                   
sms(String(F("Sirena->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {      // выкл
      Sirena = 0;
      EEPROM.update(8, Sirena);                   
sms(String(F("Sirena->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("ring")) > -1)   { // вкл/выкл вызов при сработке
    if (kom.indexOf(on) > -1)   { // вкл 
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)   { // выкл 
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("sms")) > -1)    { // вкл/выкл смс при сработке
    if (kom.indexOf(on) > -1)    { // вкл 
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)    { // выкл
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("door")) > -1) {  // вкл/выкл контроль датчика двери
    if (kom.indexOf(on) > -1) {  // выкл
      DOORon = 1;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл контроль датчика двери
      DOORon = 0;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("sarai")) > -1) {  // вкл/выкл контроль датчика двери 2
    if (kom.indexOf(on) > -1) {  // вкл
      SARAIon = 1;
      EEPROM.update(5, SARAIon);
sms(String(F("SARAI->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      SARAIon = 0;
      EEPROM.update(5, SARAIon);
sms(String(F("SARAI->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("pir")) > -1) {  // вкл/выкл контрол датчика движения
    if (kom.indexOf(on) > -1) {  // вкл
      PIRon = 1;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл
      PIRon = 0;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("gas")) > -1) {  // вкл/выкл контроль датчика газа
    if (kom.indexOf(on) > -1) {  // вкл 
      GASon = 1;
      EEPROM.update(7, GASon);
sms(String(F("GAS->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      GASon = 0;
      EEPROM.update(7, GASon);
sms(String(F("GAS->off\n")), 1); // смс на все номера
    }
  }
  gsm.println(F("AT+CMGD=1,4")); // стираем смс
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(100);
  if (ModemID == 1) {
    gsm.println(AT_M590);
    delay(100);
  gsm.println(String("ATD#") + Bal + String("#;"));
  } else if (ModemID == 2 || ModemID == 3) gsm.println(String(AT_SIM800_A6) + Bal + "#,15");
  Serial.println(String(F("Balance#")) + Bal + "#"); 
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
    if (i < 5 && i != 0) {
      num.toCharArray(Phone, 13); // конвертируем
      AlarmPhone[i] = num;        // пишем номер  
      EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
sms(String(F("Master")) + i + ":" + num + " add\n", 0); // смс на 0 номер.
    }// else Serial.println(F("MAX number 4!"));             // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
    return 1;                             
}                              

int dellphone (int i) { /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
sms(String(F("Master")) + i + ":" + AlarmPhone[i] + " dell\n", 0); // смс на 0 номер
       EEPROM.put(Adress[i], 0);
       AlarmPhone[i] = "";   // обнулим номер
  } return 1;                          
}

int balnum (String num) { /// === добавляем номер баланса === ///
    num.toCharArray(Bal, 4);   // конвертируем
    EEPROM.put(20, Bal);           // записываем массив в EEPROM 
sms(String(F("Balance:*")) + num + F("# Ok\n"), 0); // смс на 0 номер
    return 1;                             
}

String TempC() {      /// === измеряем температуру === ///
  String temp;
    byte data[2];
    ds.reset();
    ds.write(0xCC);
    ds.write(0x44);
    delay(750);
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    int Temp = (data[1] << 8) + data[0];
    Temp = Temp >> 4;
    temp = String(F("Temp ")) + Temp + "*C";
  return temp;
}

void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === ///
  byte reminder = 0;
  int bitstate = 7;
  for (unsigned int i = 0; i < instr.length(); i++) {
    byte b = instr[i];
    byte bb = b << (7 - bitstate);
    char c = (bb + reminder) & 0x7F;
    outstr += c;
    reminder = b >> bitstate;
    bitstate--;
    if (bitstate == 0) {
      char c = reminder;
      outstr += c;
      reminder = 0;
      bitstate = 7;
    }
  }
}

void InitModem() { /// === инициализация модема === ///
  gsm.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  String val = sendATCommand(F("ATI"), true);
    for (int i = 0; i < 5; i++) {
        sendATCommand(AT[i], true);         // включить АОН
    }
    if (val.indexOf(F("M590")) > -1) ModemID = 1;
    else if (val.indexOf(F("SIM800")) > -1) ModemID = 2;
    else if (val.indexOf("A6") > -1) ModemID = 3;
    Serial.println(String(F("ModemID ")) + ModemID + "\n");
}

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

void waitConnect() {  // запуск модема
  int countok = 0;
  uint32_t msAT = 0;
  String str; 
  while(countok < 5) {                      //ждём пять ОК  
    uint32_t ms = millis();
    if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс 
      msAT = ms;
      Serial.println(">>AT");
      gsm.println("AT");                    // посылаем команду
      str = "";
      delay(100);                           // ждём ответа
      while(gsm.available()) {
        char ch = gsm.read();
        str += ch;
      } 
      if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;}
      else countok = 0;
    }
  }  
}

void sms(String text, byte sendnum) { /// === отправка СМС === ///
    String phone = "";
    if (sendsmscaller == 1 && sendnum == 0) {                  // отправка смс на номер звонившего
      phone = RingPhone;
      Serial.println(String(F("SMS send=>")) + phone); 
      gsm.println(String(F("AT+CMGS=\"+")) + phone + "\"");
      delay(100);
      gsm.print(text + TempC());
      delay(100);
      gsm.print((char)26);
      delay(2000);
    } 
    else if (sendsmscaller == 1 && sendnum == 1) {                  // отправка смс на все номера
      for (int i = 0; i < 4 ; i++) {        
        phone = AlarmPhone[i];
        if (phone != 0) {
          Serial.println(String(F("SMS send=>")) + phone); 
          gsm.println(String(F("AT+CMGS=\"+")) + phone + "\"");
          delay(100);
          gsm.print(text + TempC());
          delay(100);
          gsm.print((char)26);
          delay(4000);
        }
      }
    }
    Serial.println(text + TempC() + "\n");
}

 

AleksandrM
Offline
Зарегистрирован: 20.07.2017

Спасибо. Завтра с утра попробую, оставил железку в конторе.Я так понял Вы ограничили длину строки символом "UAH"?

            int p1 = val.indexOf("");         // начало строки

146           int p2 = val.lastIndexOf("UAH");     // конец строки
147           val = val.substring(p1+1, p2);

 

pasha413
Offline
Зарегистрирован: 27.11.2016

Да, других вариантов пока не вижу

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

pasha413 пишет:
Да, других вариантов пока не вижу

Другой вариант я вам, Паша, давно озвучивал - принимайте из модема только то, что нужно, остальное отбрасывайте. Буфером в 32 символа можно принять ответ от GPRS в 500 байт, а уж СМС-ку и подавно.

А вообще - работу с балансом, думаю, вам вообще для пользователей настраивать не надо. Пусть делают сами. Все возможные варианты строк от всех возможных операторов вы все равно в скетч не добавите - да и не нужно это. У нас тут программисткий форум, пусть попотеют хоть немного настроить скетч под себя - а то иначе это получается чистое нахлебничество.

pasha413
Offline
Зарегистрирован: 27.11.2016

b707, спасибо. Кто-то хочет учиться, самихоть что-то сделать, а кто-то только заливать и все)
Ну а помочь, чем могу тем и помогу. С балансом согласен, очень много разных вариантов получается.

Как вы говорите, для считывания с модема такая процедура годится, или надо что-то иное?:
while (gsm.available()) {
char ch = gsm.read();
gsmval += char(ch);
delay(5);
}

AleksandrM
Offline
Зарегистрирован: 20.07.2017

Спасиба за прмощь. Направили в нужную сторону. Вашим способом не получилось, сделал по другому:

Обрезал строку после перекодировки- результат:

SIM  Your account 12.01 UAH.
Temp 24*C

pasha413
Offline
Зарегистрирован: 27.11.2016

AleksandrM, пожалуйста. Я так и хотел, видимо поспешил с работы уйти и не там изменил. Обращайтесь.

pasha413
Offline
Зарегистрирован: 27.11.2016

вообщем доработал, т.к. не проверялся баланс при входящей смс money и не отправлялись смс на несколько номеров. сейчас это работает. проверяйте.

 

// max длинна сообщения в данный момент 135 символов.
#include <EEPROM.h> 
#include <OneWire.h>
#include <RCSwitch.h>
#include <SoftwareSerial.h>
#define Ver F("Alarm  v4.3.4\n")

OneWire ds(6);                  // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +.
SoftwareSerial gsm(7, 8);       // модем подключен к 7 и 8 пинам.
RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2.

#define DOOR 4             // пин 4. концевик двери.
#define PIR 5              // пин 5. датчик движения.
#define LED 13             // пин 13. состояние системы.
#define GAS 14             // пин A0. датчик дыма.
#define BUZ 15             // пин A1. сирена.
#define sarai 3258553      // адрес 433 передатчика геркона двери

// DOOR     - если сработал, на входе "+" HIGH.
// SARAI    - если сработал, на пин 2 сигнал.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// LED      - если "-" LOW, то горит.

#define on "on"     // вкл
#define off "off"   // выкл

int8_t ModemID = 0;        //    тип модема
int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевика двери:       1 - вкл, 0 - выкл.    
int8_t SARAIon = 1;        // 4. контроль концевика двери 2:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.
int8_t Sirena = 1;         // 7. сирена:                         1 - вкл, 0 - выкл. 
int8_t Firststart = 1;     // первый старт.

int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t SARAIFlag = 0;      // флаг состояние датчика двери 2.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LEDState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t sendsmscaller = 1;  // разрешение отправки смс.

uint32_t msAT = 0;

char Bal[4];               // для временного хранения номера баланса.   
char Phone[14];            // для временного хранения номера телефона, номер до 14 цифр.      
String  AT[] = {"ATE0", "AT+CLIP=1", "AT+CMGF=1", "AT+CSCS=\"GSM\"", "AT+CNMI=2,2,0,0,0", "AT+CREG?"}; // общие АТ команды
#define  AT_M590  F("AT+CUSD=1")            // баланс для М590
#define  AT_SIM800_A6  F("AT+CUSD=1,#")     // баланс для А6 и СИМ800

String RingPhone = "";          // номер звонившего.
String AlarmPhone[5];           // номера для постановки/снятии с охраны и отправки смс.
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.

int p = 0;
#define GASThres 400           // предельная концентрация газа
#define interval_alarm 20      // Секунд до отключения "тревожного" пина. 
int previousMillis_alarm = 0;
#define interval_led 1000      // для мигания LED, 1 сек.
int previousMillis_led = 0;
#define interval_door 10       // секунд не смотрим на датчик двери.
int previousMillis_door = 0;
#define interval_sarai 10      // секунд не смотрим на датчик двери 2.
int previousMillis_sarai = 0;
#define interval_pir 20        // секунд не смотрим на датчик движения.
int previousMillis_pir = 0;
#define interval_gas 600       // секунд не смотрим на датчик газа. 10минут
int previousMillis_gas = 0;

/* EEPROM Data:
  № ячейки - значение:
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:                0 - выкл.
  2 - AlarmRING = 1;   // звонок:                1 - вкл. 
  3 - SendSMS = 1;     // отправка смс:          1 - вкл.
  4 - DOORon = 1;      // концевик двери:        1 - вкл.
  5 - SARAIon = 1;     // концевик двери сарая:  1 - вкл.
  6 - PIRon = 1;       // датчик движения:       1 - вкл.
  7 - GASon = 1;       // датчик дыма:           1 - вкл.
  8 - Sirena = 1;      // сирена:                1 - вкл.
  10 - Firststars = 1; // первый запуск          1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// === настройка программы === ///
  Serial.begin(9600); 
  Serial.println(Ver); 
  pinMode(DOOR, INPUT_PULLUP);      // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);           
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);
  pinMode(LED, OUTPUT);             // светодиод горит во время запуска.
    digitalWrite(BUZ, HIGH);        // сирена выкл.
    digitalWrite(PIR, HIGH);        // игнорируем при включении.
  mySwitch.enableReceive(0);        // 433 приемник на 2 пине
  InitModem();                      // запускаем инициализация модема.
  eepromconfig();
  Serial.println(eepromtext()); 
  Serial.println(eepromphone()); 
    digitalWrite(LED, HIGH);        // гасим светодиод состояния сигнализации. 
}  
                                 
void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  }
  if (gsm.available()) {                      // Если модем, что-то отправил...
      sendsmscaller = 1;
      String gval = "";                      // Переменная для хранения ответа модуля
      gval = waitgsm();                 // Получаем ответ от модема для анализа
//  Serial.println("gval:" + gval);                  // Если нужно выводим в монитор порта
      if (gval.indexOf(F("+PBREADY")) > -1) InitModem();
      else if (gval.indexOf(F("+CLIP")) > -1) {        // если обнаружен вызов.
        gsm.println(F("ATH"));                 // сбрасываем вызов.
  Serial.println(F("Process RING"));                              
        int ind = gval.indexOf(F("+CLIP: \""));          // обрезаем номер 
//        if (ind >= 0) {                     // Если информация была найдена
        ind += 8;                         // Парсим строку и
        String ring = gval.substring(ind, gval.indexOf("\"", ind));
//        }
  Serial.println(String(F("RingPhone->")) + ring);                            
        if (CheckPhone(ring) == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
        } else  Serial.println(F("No Master Ring!"));  
      } else if (gval.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
        parsesms(gval);
      } else if(gval.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
        String bal = "";
        if (ModemID == 3) {
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
          int p1 = gval.indexOf("\"");         // начало строки
          int p2 = gval.lastIndexOf("\"");     // конец строки
          gval = gval.substring(p1+1,p2);
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(gval);
  Decode7bit(gval, bal);
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        } else if (ModemID == 1 || 2) {
          bal = String(gval.substring(gval.indexOf(",\"") + 2,gval.indexOf("\",")));  //
        }
        Serial.println(bal);
sms("SIM " + bal + "\n", 0);    // смс на последний звонивший
        gsm.println(F("AT+CUSD=0"));
         } 
  } else if (Serial.available()) {           // если в мониторе порта что-то ввели
      String sval = "";
      while (Serial.available()) {         // сохраняем входную строку в переменную val.
        char ch = Serial.read();
        sval += char(ch);                   // собираем принятые символы в строку
        delay(3);
        } 
        sendsmscaller = 0;
  Komand(sval);                        // запускаем консольную программу
        sendsmscaller = 1;
    }
}

String waitgsm() {                         // Функция ожидания ответа и возврата полученного результата
  String gsmval = "";                            // Переменная для хранения результата
  uint32_t _timeout = millis() + 10000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!gsm.available() && (millis() < _timeout))  {}; // Ждем ответа5 секунд, если пришел ответ или наступил таймаут, то...
  if (gsm.available()) {     // если GSM модем что-то послал.
    while (gsm.available()) {  // сохраняем входную строку в переменную val.
      char ch = gsm.read();
      gsmval += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
  } else {                                      // Если пришел таймаут, то...
    Serial.println(F("Timeout..."));               // ... оповещаем об этом и...
  }
  return gsmval;                                 // ... возвращаем результат. Пусто, если проблема
}

void parsesms(String msg) {
  String msgheader = "";
  String msgsms    = "";
  String msgphone  = "";
  
  msg = msg.substring(msg.indexOf(F("+CMT: ")));
  msgheader = msg.substring(0,msg.indexOf("\r"));            // Выдергиваем телефон

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

  int Index = msgheader.indexOf(F("+CMT:"));
  Index += 8;                         // Парсим строку и
  msgphone = msgheader.substring(Index, msgheader.indexOf("\"", Index));
 
  Serial.println(String(F("Phone: ")) + msgphone);    // Выводим номер телефона
  Serial.println(String(F("Message: ")) + msgsms);    // Выводим текст SMS
     if (CheckPhone(msgphone) == 1) {      // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  Komand(msgsms);
     } else  Serial.println(F("No Master SMS!"));
}

int CheckPhone(String phone) { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (phone == AlarmPhone[i] && phone != 0) { // если есть вызов, и он наш
        phone = AlarmPhone[i];              // запоминаем его.
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 14);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
//  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
        phone.toCharArray(Phone, 14);
        EEPROM.put(25, Phone);                    // пишем номер в EEPROM
        EEPROM.put(100, Phone);                   // записываем RingPhone в память. 
        AlarmPhone[0] = Phone;                    // запишем
        RingPhone = Phone;                        // запоминаем его.
        EEPROM.update(10, 0);                     // обновляем Firststart
        Firststart = 0;                           // пишем 0
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String(F("Master0:")) + phone + " Ok\n", 0);     // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
    } return 0;                               
}

void eepromconfig() { /// === конфигурирование сигнализации === ///
    if (EEPROM.read(0) != 1) {           // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // SARAIon     датчики дверей вкл.
      EEPROM.update(6, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(7, 1);   // GASon       датчик газа вкл.
      EEPROM.update(8, 1);   // Sirena      сирена вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
  Serial.println(F("EEPROM != 1/ RESET!")); 
    } if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   // Охрана
      AlarmRING  = EEPROM.read(2);   // Вызов
      SendSMS    = EEPROM.read(3);   // Отправка смс
      DOORon     = EEPROM.read(4);   // Датчик двери
      SARAIon    = EEPROM.read(5);   // Датчик двери
      PIRon      = EEPROM.read(6);   // Датчик движения
      GASon      = EEPROM.read(7);   // Датчик газа/дыма
      Sirena     = EEPROM.read(8);   // сирена
      Firststart = EEPROM.read(10);  //
    }
}

String eepromtext() { /// === состояние системы === ///
   String SIGN = "";         // текущее состояние системы.
   String SIRENA = "";       // аварийная сирена.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Sarai = "";        // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
   if (Guard == 1) SIGN = F("System on\n"); else SIGN = F("System off\n");
   if (Sirena == 1) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n");
   if (AlarmRING == 1) RING = F("Ring on\n"); else RING = F("Ring off\n");
   if (SendSMS == 1) SMS = F("SMS on\n"); else SMS = F("SMS off\n");
   if (DOORon == 1) Door = F("Door on\n"); else Door = F("Door off\n");
   if (SARAIon == 1) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n");
   if (PIRon == 1) Pir = F("Pir on\n"); else Pir = F("Pir off\n");
   if (GASon == 1) Gas = F("Gas on\n"); else Gas = F("Gas off\n");
    String LastEvent = SIGN + RING + SMS + SIRENA + Pir + Door + Sarai + Gas;             // полное состояние системы и датчиков.
    return LastEvent;
}

String eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем мастер-номера 
      AlarmPhone[i] = Phone;
    }
    String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n";
    EEPROM.get(100, Phone);                // считываем номер последнего звонившего
    RingPhone = Phone;
    String ring = String(F("Ring ")) + RingPhone + "\n";
    EEPROM.get(20, Bal);                   // считываем номер баланса
    String bal = String(F("Balance *")) + Bal + "#\n"; 
    String EEPhone = numbers + ring + bal;
    return EEPhone;
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  
  if (DOORon == 1) {
    if (DOORState == HIGH && DOORFlag == 0) {
      previousMillis_door = millis();
      DOORFlag = 1;
//  Serial.println(F("Dver' otkrita!"));
  Alarm();                                // 
    }
    else if (DOORState == LOW && DOORFlag == 1) {
      int currentMillis_door = millis();
      if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
        DOORFlag = 0;
      }
    }
  }
  if (SARAIon == 1) {
    if (mySwitch.available()) {
      unsigned long value = mySwitch.getReceivedValue();
      if (value == sarai && SARAIFlag == 0) {
        previousMillis_sarai = millis();
        SARAIFlag = 1;
//  Serial.println(F("Sarai otkrit!"));
  Alarm();                                // 
      }
      mySwitch.resetAvailable();
    }
    int currentMillis_sarai = millis();
    if (((currentMillis_sarai - previousMillis_sarai) / 1000 > interval_sarai)) {
      SARAIFlag = 0;
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
//  Serial.println(F("Dvizhenie u dveri!"));
  Alarm();                                // 
    }
    else if (PIRState == LOW && PIRFlag == 1) {
      int currentMillis_pir = millis();
      if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_pir)) {
        PIRFlag = 0; 
      }
    }
  }
  if (GASon == 1) {
    if ((Smoky > GASThres) && GASFlag == 0) {
      previousMillis_gas = millis();
      GASFlag = 1;
      delay(100);
//  Serial.println(F("Gas v dome!"));
  Alarm();                                // 
    }
    else if ((Smoky < GASThres) && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) {
        GASFlag = 0; 
      }
    }
  }
}

void Alarm() { /// === запускаем сирену и отправку смс === ///
    previousMillis_alarm = millis();
    if (Sirena == 1) digitalWrite(BUZ, LOW);
    Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
        if (DOORFlag == 1) {
sms(F("Dver' otkrita!\n"), 1); // смс на все номера
        }
        else if (SARAIFlag == 1) {
sms(F("Sarai otkrit!\n"), 1); // смс на все номера
        }
        else if (PIRFlag == 1) {
sms(F("Dvizhenie y dveri!\n"), 1); // смс на все номера
        }
        else if (GASFlag == 1) {
sms(F("Gas v dome!\n"), 1); // смс на все номера
        }
    }
    if (AlarmRING == 1) {
      gsm.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
}

void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  int currentMillis_alarm = millis();
  if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) {
    digitalWrite(BUZ, HIGH);
  } 
}

void MasterRing() { /// === мастер звонков === //
  if (Guard == 1) GuardOff();     // меняем состояние
  else if (Guard == 0) GuardOn(); // меняем состояние
}

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
sms(String(F("System->off\n")), 1); // смс на все номера
}

void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
sms(String(F("System->on\n")), 1); // смс на все номера
}

void Led() { /// === состояние светодиода === ///
//  if (Guard == 1) {                   // если на охране
  int currentMillis_led = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis_led - previousMillis_led > interval_led) {
      // сохраняем время последнего переключения
      previousMillis_led = currentMillis_led;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LEDState == HIGH) LEDState = LOW;
      else LEDState = HIGH;
      digitalWrite(LED, LEDState);
    }
//  } else digitalWrite(LED, HIGH); // иначе гасим его
}

void Komand(String kom) { /// === мастер смс === ///
  Serial.println("Kom->" + kom);
  kom.toLowerCase();
  if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) {        // команды выполняются только с 0 мастер номера
    if (kom.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
sms(F("System Reset!\n"), 0); // смс на последний номер
      EEPROM.write(0, 0);
  eepromconfig();
  Serial.println(eepromtext());
  Serial.println(eepromphone());
    } else if ((p = kom.indexOf(F("master"))) > -1)  { // добавление мастер-номера
      master(kom.substring(p + 6, p + 7).toInt(), kom.substring(p + 8, kom.indexOf("\n", p + 8)));
///// sms типа: " master1:79111234567 " - ячейка + номер
    } else if ((p = kom.indexOf(F("balance:"))) > -1) { // добавление номера баланса
      balnum(kom.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
    } else if ((p = kom.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки     
      dellphone(kom.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } else if (kom.indexOf(F("phone")) > -1)     { // инфо о номерах системы
sms(eepromphone(), 0); // смс на последний номер
    }
  }  
  if ((kom.indexOf(F("info")) > -1) || (kom.indexOf(F("?")) > -1)) {     // инфо о состоянии системы
  eepromconfig();
sms(eepromtext(), 0); // смс на последний номер
  } else if (kom.indexOf(F("money")) > -1) {   // запрос баланса
  balance();
  } else if (kom.indexOf(F("datchiki")) > -1) {
    if (kom.indexOf(on) > -1) {       // вкл 
      DOORon = 1;
      SARAIon = 1;
      PIRon = 1;
      GASon = 1;
      EEPROM.update(4, DOORon);
      EEPROM.update(5, SARAIon);
      EEPROM.update(6, PIRon);
      EEPROM.update(7, GASon);
    } else if (kom.indexOf(off) > -1) {       // выкл 
      DOORon = 0;
      SARAIon = 0;
      PIRon = 0;
      GASon = 0;
      EEPROM.update(4, DOORon);
      EEPROM.update(5, SARAIon);
      EEPROM.update(6, PIRon);
      EEPROM.update(7, GASon);
    }
sms(eepromtext(), 1); // смс на последний номер
  } else if (kom.indexOf(F("system")) > -1)  {  // вкл/выкл сигнализацию
    if (kom.indexOf(on) > -1)  {    // вкл 
  GuardOn();
    } else if (kom.indexOf(off) > -1)  {    // вкл
  GuardOff();
    }
  } else if (kom.indexOf(F("sirena")) > -1) {     // вкл/выкл сирены
    if (kom.indexOf(on) > -1) {       // вкл 
      Sirena = 1;
      EEPROM.update(8, Sirena);                   
sms(String(F("Sirena->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {      // выкл
      Sirena = 0;
      EEPROM.update(8, Sirena);                   
sms(String(F("Sirena->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("ring")) > -1)   { // вкл/выкл вызов при сработке
    if (kom.indexOf(on) > -1)   { // вкл 
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)   { // выкл 
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("sms")) > -1)    { // вкл/выкл смс при сработке
    if (kom.indexOf(on) > -1)    { // вкл 
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)    { // выкл
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("door")) > -1) {  // вкл/выкл контроль датчика двери
    if (kom.indexOf(on) > -1) {  // выкл
      DOORon = 1;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл контроль датчика двери
      DOORon = 0;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("sarai")) > -1) {  // вкл/выкл контроль датчика двери 2
    if (kom.indexOf(on) > -1) {  // вкл
      SARAIon = 1;
      EEPROM.update(5, SARAIon);
sms(String(F("SARAI->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      SARAIon = 0;
      EEPROM.update(5, SARAIon);
sms(String(F("SARAI->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("pir")) > -1) {  // вкл/выкл контрол датчика движения
    if (kom.indexOf(on) > -1) {  // вкл
      PIRon = 1;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл
      PIRon = 0;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("gas")) > -1) {  // вкл/выкл контроль датчика газа
    if (kom.indexOf(on) > -1) {  // вкл 
      GASon = 1;
      EEPROM.update(7, GASon);
sms(String(F("GAS->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      GASon = 0;
      EEPROM.update(7, GASon);
sms(String(F("GAS->off\n")), 1); // смс на все номера
    }
  }
  gsm.println(F("AT+CMGD=1,4")); // стираем смс
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  Serial.println(String("Modem ") + ModemID);
  delay(1000);                // ждем секунду, т.к. вылетает с ошибкой
  if (ModemID == 1) {
    gsm.println(AT_M590);
    delay(100);
  gsm.println(String(F("ATD#")) + Bal + "#;");
  } else if (ModemID == 2 || ModemID == 3) gsm.println(String(AT_SIM800_A6) + Bal + "#,15");
  Serial.println(String(F("Balance#")) + Bal + "#"); 
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
    if (i < 5 && i != 0) {
      num.toCharArray(Phone, 14); // конвертируем
      AlarmPhone[i] = num;        // пишем номер  
      EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
sms(String(F("Master")) + i + ":" + num + " add\n", 0); // смс на 0 номер.
    }// else Serial.println(F("MAX number 4!"));             // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
    return 1;                             
}                              

int dellphone (int i) { /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
sms(String(F("Master")) + i + ":" + AlarmPhone[i] + " dell\n", 0); // смс на 0 номер
       EEPROM.put(Adress[i], 0);
       AlarmPhone[i] = "";   // обнулим номер
  } 
  return 1;                          
}

int balnum (String num) { /// === добавляем номер баланса === ///
    num.toCharArray(Bal, 4);   // конвертируем
    EEPROM.put(20, Bal);           // записываем массив в EEPROM 
sms(String(F("Balance:*")) + num + F("# Ok\n"), 0); // смс на 0 номер
    return 1;                             
}

String TempC() {      /// === измеряем температуру === ///
  String temp;
    byte data[2];
    ds.reset();
    ds.write(0xCC);
    ds.write(0x44);
    delay(750);
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    int Temp = (data[1] << 8) + data[0];
    Temp = Temp >> 4;
    temp = String(F("Temp ")) + Temp + "*C";
  return temp;
}

void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === ///
  byte reminder = 0;
  int bitstate = 7;
  for (unsigned int i = 0; i < instr.length(); i++) {
    byte b = instr[i];
    byte bb = b << (7 - bitstate);
    char c = (bb + reminder) & 0x7F;
    outstr += c;
    reminder = b >> bitstate;
    bitstate--;
    if (bitstate == 0) {
      char c = reminder;
      outstr += c;
      reminder = 0;
      bitstate = 7;
    }
  }
}

void InitModem() { /// === инициализация модема === ///
  gsm.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  String val = sendATCommand(F("ATI"), true);
    if (val.indexOf(F("M590")) > -1) ModemID = 1;
    else if (val.indexOf(F("SIM800")) > -1) ModemID = 2;
    else if (val.indexOf("A6") > -1) ModemID = 3;
    Serial.println(String(F("ModemID ")) + ModemID + "\n");
    for (int i = 0; i < 6; i++) {
       sendATCommand(AT[i], true);         // включить АОН
    }
}

String sendATCommand(String cmd, bool waiting) {
  String atval = "";                            // Переменная для хранения результата
  Serial.println(cmd);                          // Дублируем команду в монитор порта
  gsm.println(cmd);                             // Отправляем команду модулю
//  if (waiting) {                                // Если необходимо дождаться ответа...
    atval = waitgsm();                          // ... ждем, когда будет передан ответ
    Serial.println(atval);                      // Дублируем ответ в монитор порта
//  }
  return atval;                                 // Возвращаем результат. Пусто, если проблема
}

void waitConnect() {  // запуск модема
  int countok = 0;
  uint32_t msAT = 0;
  String str; 
  while(countok < 5) {                      //ждём пять ОК  
    uint32_t ms = millis();
    if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс 
      msAT = ms;
      Serial.println(">>AT");
      gsm.println("AT");                    // посылаем команду
      str = "";
      delay(100);                           // ждём ответа
      str = waitgsm();
      if (str.indexOf("OK") > -1) {
        Serial.println("OK"); 
        countok++;
      } else countok = 0;
    }
  }  
}

void sms(String text, byte sendnum) { /// === отправка СМС === ///
    String phone = "";
    text = text + TempC();
    if (sendsmscaller == 1 && sendnum == 0) {                  // отправка смс на номер звонившего
      phone = RingPhone;
//      delay(500);
  sendATCommand("AT+CMGS=\"" + phone + "\"", true);             // Переходим в режим ввода текстового сообщения
  sendATCommand(text + (String)((char)26), true);   // После текста отправляем перенос строки и Ctrl+Z      Serial.println(String(F("SMS send=>")) + phone); 
  Serial.println(String(F("SMS sended=>")) + phone + "\n" + text + "\n"); 
    } else if (sendsmscaller == 1 && sendnum == 1) {                  // отправка смс на все номера
      for (int i = 0; i < 4 ; i++) {        
        phone = AlarmPhone[i];
        if (phone != 0) {
//      delay(500);
  sendATCommand("AT+CMGS=\"" + phone + "\"", true);             // Переходим в режим ввода текстового сообщения
  sendATCommand(text + (String)((char)26), true);   // После текста отправляем перенос строки и Ctrl+Z      Serial.println(String(F("SMS send=>")) + phone); 
  Serial.println(String(F("SMS sended=>")) + phone + "\n" + text + "\n"); 
//      delay(2000);
        }
      }
    } else if (sendsmscaller == 0) Serial.println("text:\n" + text + "\n");
}

 

kvolk
Offline
Зарегистрирован: 12.06.2017
pasha413
Offline
Зарегистрирован: 27.11.2016

kvolk, спасибо. Будем изучать

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Там кода нет.

pasha413
Offline
Зарегистрирован: 27.11.2016

А я скачал :)

pasha413
Offline
Зарегистрирован: 27.11.2016

kvolk, навскидку, можно оптимизировать ваш код процентов на 5, если заменить условия:

if {
}
if {
}
if {
}

на:

if {
}
else if {
}
else if {
}