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

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

kot488 пишет:

С SIM800L нормально должен работать?

Я изначально пробовал залить hex для проводной только, подвис в памяти мой номер, и сейчас нормально не стартует, вот что в мониторе порта

MasterPhone:
[0] 
[1] 
[2] ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
[3] ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
[4] ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
Ring +38*******
Balance *#
 
AT+CSQ
Timeout...
 

 

если это мой код, то выполните команду reset

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

эта версия под А6,

в ближайшее время постараюсь, переписать под сим800.

где-то посеял свои нарабтки сигнализации с автоопределением модема...

Буду очень ждать)
Пока попробую поискать A6. По совету в проводной теме специально покупал sim800

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

[/quote] Буду очень ждать) Пока попробую поискать A6. По совету в проводной теме специально покупал sim800[/quote]

что за проводная тема?

kot488
Offline
Зарегистрирован: 22.03.2018

Насколько понял, то вот эта взята за прототип, или не прав?
https://mysku.ru/blog/ebay/43282.html

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

что-то не до конца допилил, сегодня уже некогда...

двойное приглашение на отправку, не победил....

// 0 (основной) мастер-номер добавляется при первом звонке либо смс на систему.
// при звонке на номер сигнализации - прослушка помещения.
// при сработке датчиков- вызов (если ring on) на 0 мастер-номер и смс (если sms on) всем.
// длинна сообщения 123 символов.
/* 
 *Команды управления для 0 мастер-номера:
    "reset"                 сброс настроек и номеров на заводские.
    "master1:79112345678"   добавить номер 79112345678 в ячейку памяти 1.
    "balance:100"           номер баланса *100#.
    "dell:1"                удалить номер из ячейки 1.
    "phone"                 вывести список номеров в системе.
 *Команды управления для всех мастер-номеров:
    "info" либо "?"         инфо о состояни системы и уровня сигнала сети.
    "datchiki on\off"       вкл/выкл все датчики.
    "system on\off"         вкл/выкл охрану.
    "ring on\off"           вкл/выкл вызов при аварии или сработке сигнализации.
    "sirena on\off"         вкл/выкл сирену при сработке.
    "sms on\off"            вкл/выкл смс при аварии или сработке сигнализации.
    "door on\off"           вкл/выкл контроль датчика двери.
    "sarai on\off"          вкл/выкл контроль датчика двери сарая.
    "pir on\off"            вкл/выкл контроль датчика движения.
    "gas on\off"            вкл/выкл контроль датчика газа.
*/

#include <EEPROM.h>
#include <OneWire.h>
#include <RCSwitch.h>
#include <SoftwareSerial.h>
#include <DallasTemperature.h>
#define Ver F("Alarm  v2.1.3\n")

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

#define DOOR   17           // концевик двери. если сработал, на входе "+" HIGH.
#define PIR    16           // датчик движения. если сработал, на входе "+" HIGH.
#define GAS    14           // датчик дыма. если сработал, на входе "+" HIGH.
#define LED    9            // состояние системы. если "-" LOW, то горит.
#define BUZ    10           // сирена. если "-" LOW, то горит.
#define sarai 3258553       // адрес 433 передатчика геркона двери. если сработал, на пин 2 сигнал.

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

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

boolean DOORFlag = false;       // флаг состояние датчика двери.
boolean SARAIFlag = false;      // флаг состояние датчика двери 2.
boolean PIRFlag = false;        // флаг состояние датчика движения.
boolean GASFlag = false;        // флаг состояние датчика газа.
int8_t LEDState = LOW;          // Состояние светодиода.
int8_t DOORState = LOW;         // Состояние концевика двери.
int8_t PIRState = LOW;          // Состояние датчика движения.
int8_t Smoky = LOW;             // Состояние датчика газа.

float Temp_ul = false;          // температура.                
float Temp_pom = false;         // температура.                
char CSQ[4];                    // для хранения уровня сигнала.
char Bal[4];                    // для временного хранения номера баланса.
char Phone[14];                 // для временного хранения номера телефона, номер до 14 цифр.

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

unsigned int p = 0;
#define GASThres 400        // предельная концентрация газа
#define time_alarm 20       // Секунд до отключения "тревожного" пина. 
unsigned long lasttime_alarm = 0;
#define interval_led 1000   // для мигания LED, 1 сек.
unsigned long previousMillis_led = 0;
#define time_door 10        // секунд не смотрим на датчик двери.
unsigned long lasttime_door = 0;
#define time_sarai 10       // секунд не смотрим на датчик двери 2.
unsigned long lasttime_sarai = 0;
#define time_pir 20         // секунд не смотрим на датчик движения.
unsigned long lasttime_pir = 0;
#define time_gas 600        // секунд не смотрим на датчик газа. 10 минут
unsigned long lasttime_gas = 0;
unsigned long timer = 300000;

/* 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);
  ds.begin();                                    // Запуск библиотеки, по умолчанию 9 бит
  pinMode(DOOR, INPUT_PULLUP);                   // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);  digitalWrite(PIR, HIGH); //
  pinMode(GAS, INPUT);
  pinMode(BUZ, OUTPUT); digitalWrite(BUZ, LOW);  // сирена выкл.
  pinMode(LED, OUTPUT); 
  mySwitch.enableReceive(0);                     // RF433 приемник на 2 пине
  Restart();                                     // перезапускаем систему
}

void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (millis()/1000 > timer) {  // проверяем каждый час 
    TempC();
    Signal();
    timer += 360; 
  }
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  } else digitalWrite(LED, LOW);
  if (gsm.available()) {               // Если модем что-то отправил...
    serial = false;
    String gval = "";                  // Переменная для хранения ответа модуля
      while (gsm.available()) {        
        char ch = gsm.read();
        gval += char(ch);              // сохраняем входную строку в переменную gval
        delay(3);
      }
Serial.println("gval->" + gval);
   if (gval.indexOf(F("RING")) > -1) {        // если обнаружен вызов.
      sendATCommand(F("ATH"));                // снимаем трубку  
      for (int i = 0; i < 5; i++) {           // проверяем сохраненные номера
        if (gval.indexOf(AlarmPhone[i]) > -1 && AlarmPhone[i] != 0) {  // если он наш
          RingPhone = AlarmPhone[i];          // запоминаем номер звонящего
          RingPhone.toCharArray(Phone, 14);   
          EEPROM.put(100, Phone);             // записываем RingPhone в память. 
        } else if (Firststart) {              // если первый старт
          int ind = gval.indexOf(F("+CLIP: \""));   // обрезаем номер ... 
          ind += 8;
          String ring = gval.substring(ind, gval.indexOf("\"", ind));
          RingPhone = ring;                         // запоминаем номер звонящего 
          ring.toCharArray(Phone, 14);              // сохраняем в переменную Phone
          EEPROM.put(25, Phone);                    // пишем номер в EEPROM как основной мастер-номер
          EEPROM.put(100, Phone);                   // записываем RingPhone в память. 
          AlarmPhone[0] = Phone;                    // запишем
          Firststart = false;                       // пишем 0
          EEPROM.update(10, Firststart);            // обновляем Firststart
Serial.println(String(F("Firststart:")) + Firststart);
sms(String(F("Master0:")) + ring + " Ok", 0);       // смс на звонивший
//sms("Master0:" + ring + " Ok", 0);                  // смс на звонивший
        } 
      }
    } else if (gval.indexOf(F("+CMT")) > -1) {      // если обнаруженa СМС
      for (int i = 0; i < 5; i++) {                 // проверяем сохраненные номера
        if (gval.indexOf(AlarmPhone[i]) > -1 && AlarmPhone[i] != 0) { // если он наш 
          RingPhone = AlarmPhone[i];                // запоминаем его.
  parsesms(gval);                                   // запускаем подпрограмму парсинга сообщений
        }
      }     
    } else if (gval.indexOf(F("+CUSD:")) > -1) {  // если пришел баланс
      // анализируем строку
      int p1 = gval.indexOf("\"");         // начало строки
      int p2 = gval.lastIndexOf("\"");     // конец строки
      gval = gval.substring(p1 + 1, p2);   // обрезаем строку
//      Decode7bit(gval, bal);               // декодируем сообщение
      bal = gval;
Serial.println(bal);
      sendATCommand(F("AT+CUSD=0"));       
    } 
  } else if (Serial.available()) {         // если в мониторе порта что-то ввели
    String sval = "";                      // Переменная для хранения сообщения из монитора порта
    while (Serial.available()) {           
      char ch = Serial.read();
      sval += char(ch);                    // сохраняем входную строку в переменную sval.
      delay(3);
    }
    serial = true;
    Komand(sval);                          // запускаем подпрограмму распознавания команд
  }
}

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)); // Выдергиваем телефон
  msgphone.trim();                                         // удаляем пробелы вначале и в конце строки

//Serial.println(String(F("Phone: ")) + msgphone);           // Выводим номер телефона
//Serial.println(String(F("Message: ")) + msgsms);           // Выводим текст SMS
  RingPhone = msgphone;
  RingPhone.toCharArray(Phone, 14);         
  EEPROM.put(100, Phone);                   // записываем номер  
  Komand(msgsms);                           // запускаем подпрограмму распознавания команд
}

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

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

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

void Signal() { /// === проверка уровня сигнала сети === ///
  String csq = sendATCommand(F("AT+CSQ"));           
  csq = csq.substring(csq.indexOf(":") + 2, csq.indexOf(",")); // парсим ответ об уровне сигнала
  csq.trim();                                        // удаляем пробелы вначале и в конце строки
  csq.toCharArray(CSQ, 4);                           
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(2000);                // ждем секунду, т.к. вылетает с ошибкой
  sendATCommand(String(F("AT+CUSD=1,\"#")) + Bal + F("#\",15"));
//  gsm.println(String(F("AT+CUSD=1,#")) + Bal + "#,15");
//  Serial.println(String(F("AT+CUSD=1,#")) + Bal + "#,15");
}

void TempC() { /// === измеряем температуру === ///
  ds.requestTemperatures();             // Запрос на считывание температуры
  Temp_ul = ds.getTempCByIndex(0);      // считываем температуру с первого датчика
  Temp_pom = ds.getTempCByIndex(1);     // считываем температуру со второго датчика 
}

void Restart() { /// === рестарт системы === ///
  gsm.println(F("AT+CFUN=1,1"));
  delay(2000);
Serial.println(String(F("Modem restart!")));    
  InitModem();
  eepromconfig();                              // читаем конфигурацию из памяти
Serial.println(String(F("MasterPhone:\n")) + eepromphone());  // выводим список номеров из памяти в порт
  TempC();                                     // читаем температуру
  Signal();                                    // читаем сигнал сети GSM
Serial.println(String(F("Firststart:")) + Firststart);
  if (!Firststart) sms(String(F("Modem restart\n")) + eepromtext(), 0);  // если не первый старт смс на последний номер
  else Serial.println(String(F("\nSystem config:\n")) + eepromtext() + "\r\n");
  digitalWrite(LED, LOW);                      // гасим светодиод состояния сигнализации.
}

void InitModem() { /// === инициализация модема === ///
  gsm.begin(9600);                       //Скорость порта для связи Arduino с GSM модулем
  sendATCommand(F("AT"));              // выключить эхо
  sendATCommand(F("ATE0"));              // выключить эхо
  sendATCommand(F("AT+CLIP=1"));         // включить АОН
  sendATCommand(F("AT+CMGF=1"));         // включить текстовый формат смс
  sendATCommand(F("AT+CSCS=\"GSM\""));   // включить кодировку текста gsm
  sendATCommand(F("AT+CNMI=2,2,0,0,0")); // смс прямо в порт
  sendATCommand(F("AT+CREG?"));          // регистрация в сети
  sendATCommand(F("AT+CMGD=1,4"));       // стираем смс
}

String sendATCommand(String cmd) {
  String atval = "";                             // Переменная для хранения результата
  Serial.println(cmd);                           // Дублируем команду в монитор порта
  gsm.println(cmd);                              // Отправляем команду модулю
    long _timeout = millis() + 10000;            // Переменная для отслеживания таймаута (10 секунд)
    while (!gsm.available() && millis() < _timeout) {}; // Ждем ответа 10 секунд
    if (gsm.available()) {                       // если GSM модем что-то послал.
      while (gsm.available()) {                  // сохраняем входную строку в переменную val.
        char ch = gsm.read();
        atval += char(ch);                       // собираем принятые символы в строку
        delay(3);
      }
    } else {
      Serial.println(F("Timeout..."));           // ... оповещаем об этом и...
      Restart();                                 // перезапускаем модем
    }
    Serial.println(atval);                       // Дублируем ответ в монитор порта
  return atval;
}

void sms(String text, byte sendnum) { /// === отправка СМС === ///
  String phone = "";
  text += String(F("\nTemp_ul ")) + Temp_ul;           // добавляем к тексту температуру на улице
  text += String(F("*C\nTemp_pom ")) + Temp_pom;       // добавляем к тексту температуру на в помещении
  text += String(F("*C\n")) + bal;                     // добавляем к тексту баланс sim карты
  if (!serial) {                                       // если не команда из сериала
    if (!sendnum) {                                    // отправка смс на номер звонившего
      phone = RingPhone;
      sendATCommand(String(F("AT+CMGS=\"+")) + phone + "\""); // Переходим в режим ввода текстового сообщения
      sendATCommand(text + ((char)26));               // отправка текста 
    } else if (sendnum) {                              // отправка смс на все номера
      for (uint8_t i = 0; i < 4 ; i++) {
        phone = AlarmPhone[i];
        if (phone != 0) {                              // если ячейка пустая - не отправлять смс
          sendATCommand(String(F("AT+CMGS=\"+")) + phone + "\""); // Переходим в режим ввода текстового сообщения
          sendATCommand(text + ((char)26));               // отправка текста 
          delay(200);
        }
      }
    }
  } else Serial.println(text);                         // если команда из сериала пишем выводим результат
  if (Bal != 0) balance();                             // если есть номер баланса проверяем его
}

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

void master (int i, String num) { /// === добавление мастер-номеров === ///
  if (i < 5 && i != 0) {                             // если ячейка от 1 до 4
    num.trim();                       
    num.toCharArray(Phone, 14);                      // конвертируем номер
    AlarmPhone[i] = num;                             
    EEPROM.put(Adress[i], Phone);                    // записываем массив в EEPROM
sms(String(F("Master")) + i + "->" + num + " add", 0); // смс на 0 номер.
  } 
}

void dellphone (int i) { /// === удаление мастар-номеров === ///
  if (i < 5 && i != 0) {                             // если ячейка от 1 до 4
    AlarmPhone[i] = "";                              // стираем номер
    EEPROM.put(Adress[i], 0);                        // стираем номер
sms(String(F("Master")) + i + "->" + AlarmPhone[i] + " dell", 0); // смс на 0 номер
  }
// 0 номер можно удалить только через RESET!!!
}

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

void eepromconfig() { /// === конфигурирование сигнализации === ///
  if (EEPROM.read(0) != 1) {           // если по 0 адресу записана не 1, переписываем в память 000
    for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
      EEPROM.write(i, 0);
    }                              // и записываем:
    EEPROM.update(1, 0);           // Guard       охрана выкл.
    EEPROM.update(2, 0);           // AlarmRING   вызов при сработке вкл.
    EEPROM.update(3, 0);           // SendSMS     смс при сработке вкл.
    EEPROM.update(4, 0);           // DOORon      датчики дверей вкл.
    EEPROM.update(5, 0);           // SARAIon     датчики дверей вкл.
    EEPROM.update(6, 0);           // PIRon       датчик движения вкл.
    EEPROM.update(7, 0);           // GASon       датчик газа вкл.
    EEPROM.update(8, 0);           // Sirena      сирена при сработке вкл.
    EEPROM.update(10, 1);          // Firststart  первый старт!
    EEPROM.update(0, 1);           // пишем 1 в 0 адрес
Serial.println(F("EEPROM != 1/ RESET!"));
  } if (EEPROM.read(0) == 1) {     // если в 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 = "";        // датчика двери RF433.
  String Pir = "";          // датчик движения.
  String Gas = "";          // датчик газа.
  if (Guard) SIGN = F("System on\n"); else SIGN = F("System off\n");
  if (Sirena) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n");
  if (AlarmRING) RING = F("Ring on\n"); else RING = F("Ring off\n");
  if (SendSMS) SMS = F("SMS on\n"); else SMS = F("SMS off\n");
  if (DOORon) Door = F("Door on\n"); else Door = F("Door off\n");
  if (SARAIon) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n");
  if (PIRon) Pir = F("Pir on\n"); else Pir = F("Pir off\n");
  if (GASon) Gas = F("Gas on\n"); else Gas = F("Gas off");
  String LastEvent = SIGN + SIRENA + RING + SMS + Door + Sarai + Pir + 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 + "#";
  String EEPhone = numbers + ring + bal;
  return EEPhone;
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  if (DOORon) {                                            // если датчик двери включен
    if (DOORState == HIGH && !DOORFlag) {                  // если он сработал
      lasttime_door = millis();                            // запускаем таймер
      DOORFlag = true;                                     // ставим флаг
//Serial.println(F("Dver' otkrita!"));
      Alarm();                                             // запускаем подпрограмму Alarm        
    } else if (DOORState == LOW && DOORFlag) {                       
      if (((millis() - lasttime_door)/1000 > time_door)) { // и прошел интервал
        DOORFlag = false;                                  // возвращаем флаг к начальному состоянию
//Serial.println(F("Dver' zakrita!"));
      }
    }
  }
  if (SARAIon) {
    if (mySwitch.available()) {                            // если датчик сарая включен
      unsigned long value = mySwitch.getReceivedValue();   // считываем значение с RF433
      if (value == sarai && !SARAIFlag) {                  // если он сработал
        lasttime_sarai = millis();                         // запускаем таймер
        SARAIFlag = true;                                  // ставим флаг
//Serial.println(F("Sarai otkrit!"));       
        Alarm();                                           // запускаем подпрограмму Alarm
      }
      mySwitch.resetAvailable();                          
    } 
    if (((millis() - lasttime_sarai)/1000 > time_sarai)) { // если прошол интервал
      SARAIFlag = false;                                   // возвращаем флаг к начальному состоянию
    }
  }
  if (PIRon) {                                             // если включен PIR датчик движения
    if (PIRState == HIGH && !PIRFlag) {                    // если он сработал
      lasttime_pir = millis();                             // запускаем таймер  
      PIRFlag = true;                                      // ставим флаг
//Serial.println(F("Dvizhenie u dveri!"));
      Alarm();                                             // запускаем подпрограмму Alarm
    } else if (PIRState == LOW && PIRFlag) {               // иначе если движения нет
      if (((millis() - lasttime_pir)/1000 > time_pir)) {   // и прошел интервал
        PIRFlag = false;                                   // возвращаем флаг к начальному состоянию
      }
    }
  }
  if (GASon) {                                             // если включен датчик газа
    if ((Smoky > GASThres) && !GASFlag) {                  // если он сработал
      lasttime_gas = millis();                             // запускаем таймер 
      GASFlag = true;                                      // ставим флаг
//Serial.println(F("Gas v dome!"));
      Alarm();                                             // запускаем подпрограмму Alarm 
    } else if ((Smoky < GASThres) && GASFlag) {            // иначе если газа нет
      if (((millis() - lasttime_gas)/1000 > time_gas)) {   // и прошел интервал
        GASFlag = false;                                   // возвращаем флаг к начальному состоянию
      }
    }
  }
}

void Alarm() { /// === аварийные сигналы === ///
  if (Sirena) {                              // если включена сирена при сработке
    lasttime_alarm = millis();               // запускаем таймер сирены
    digitalWrite(BUZ, HIGH);                 // запускаем ее
  }
//Serial.println(F("Alarm!!!"));
  if (SendSMS) {                             // если включена отправка смс при сработке
    if (DOORFlag) {                          // если сработал датчик двери
sms(F("Dver' otkrita!"), 1);                 // смс на все номера
    } else if (SARAIFlag) {                  // если сработал датчик двери RF433
sms(F("Sarai otkrit!"), 1);                  // смс на все номера
    } else if (PIRFlag) {                    // если сработал датчик движения
sms(F("Dvizhenie y dveri!"), 1);             // смс на все номера
    } else if (GASFlag) {                    // если сработал датчик газа
sms(F("Gas v dome!"), 1);                    // смс на все номера
    }
  }
  if (AlarmRING) {                           // если включен вызов при сработке
sendATCommand("ATD+" + String(AlarmPhone[0]) + ";"); // делаем вызов основного мастер-номера
  }
}

void AlarmPinOff() { /// === отключаем сирену === ///
  if ((millis() - lasttime_alarm)/1000 > time_alarm) digitalWrite(BUZ, LOW); // если прошло время, отключаем сирену
}
Alarm  v2.1.3

Modem restart!
AT

OK

ATE0

OK

AT+CLIP=1

OK

AT+CMGF=1

OK

AT+CSCS="GSM"

OK

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

OK

AT+CREG?

+CREG: 0,2

OK

AT+CMGD=1,4

OK

MasterPhone:
[0] *************
[1] 
[2] 
[3] 
[4] 
Ring ***************
Balance *105#
AT+CSQ

+CSQ: 16,0

OK

Firststart:0
Modem restart
System off
Sirena off
Ring off
SMS off
Door off
Sarai off
Pir off
Gas off
Temp_ul 25.00*C
Temp_pom 25.06*C

AT+CUSD=1,"#105#",15

OK

gval->
+CUSD: 0, "OCTATOK 87.50 p.", 1

OCTATOK 87.50 p.
AT+CUSD=0

OK

gval->
+CMT: "+**********","","18/06/05,19:31:15+12"
Info

Kom->Info
AT+CSQ

+CSQ: 13,0

OK

AT+CMGS="+***************"

> 
System off
Sirena off
Ring off
SMS off
Door off
Sarai off
Pir off
Gas off
Temp_ul 25.00*C
Temp_pom 25.06*C
OCTATOK 87.50 p.

>                                                    здесь не должно быть приглашения, это окончание отправки
AT+CUSD=1,"#105#",15
Timeout...
Modem restart!
AT

 

kot488
Offline
Зарегистрирован: 22.03.2018

Подправленый код в том же посте?

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

да это подправленный код для сим800, пробуйте, может у меня какой параметр в модеме не так стоит

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

сейчас занялся доработкой кода под GPRS с управление по MQTT, за основу взял https://www.drive2.ru/c/499270089304965988/, спасибо martinhol за проделанную работу.

kot488
Offline
Зарегистрирован: 22.03.2018

Спасибо, завтра попробую, оставил все на работе .
Если никакие датчики не подключать, то тоже должна запустится?

За автозапуск прикольно, но как по мне только на автомате. Я например всегда сцепление выжимаю перед запуском, да и зимой так механике полезно. У друга хундай, так пока педальку не нажмешь не заведешь

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

без датчиков запустится, все датчики по умолчанию выключены, кроме температуры.

kot488 пишет:
У друга хундай, так пока педальку не нажмешь не заведешь

для этого и есть дополнительные каналы, чтоб имитировать присутствие)

 

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

без датчиков запустится, все датчики по умолчанию выключены, кроме температуры.

kot488 пишет:
У друга хундай, так пока педальку не нажмешь не заведешь

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

на 3 мондео был автозапуск так зимой самое то сел и поехал (греть мерзнуть не надо), а здесь еще и бонус в виде gsm/ 

 

Djoin
Offline
Зарегистрирован: 04.06.2018

smesharik пишет:

Djoin, а если info посылать 3 раза сподрят, теряется что то?

и у вас теряется только на on1 и off1?

Если 3 раза подряд отправить info придет 2 смс. 
1 и 3.
2 будет в ошибке.
Т.е. смс уходят через одну.

pasha413 пишет:

Djoin, видимо у вас длинное сообщение получилось, у меня тоже такое было...сколько у вас символов в сообщении, у меня на данный момент 137, по-моему, и норм отправляется

Смс короткие, можете сами убедиться - я выложил лог с порта монитора.
Rele->on
Rele->off

С обычного info текст длиннее.

Проблема в том, что команда отправки СМС передается раньше самого текста, и она через раз передается не полностью.
Тут длина смс сообщение не может никак влиять.

Может сделать проверку ответа от модема: если получили ERROR - повторно попытаться отправить смс... пытаться 3 раза например...

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

ну у меня таких проблем небыло с А6, с сим800 вот что-то заступорился. но завтра попробую разобраться

уже почти 2 месяца стоит на даче блочек, пока норм работает

Djoin
Offline
Зарегистрирован: 04.06.2018

pasha413 пишет:

ну у меня таких проблем небыло с А6, с сим800 вот что-то заступорился. но завтра попробую разобраться

уже почти 2 месяца стоит на даче блочек, пока норм работает

Если вы мне - у меня M590E

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

Djoin пишет:

pasha413 пишет:

ну у меня таких проблем небыло с А6, с сим800 вот что-то заступорился. но завтра попробую разобраться

уже почти 2 месяца стоит на даче блочек, пока норм работает

Если вы мне - у меня M590E

понятно, на 590 давно не проверял.

вот отрыл код с определением модема, вроде был рабочий, проверьте как это работать будет:

// 0 (основной) мастер-номер добавляется при первом звонке либо смс на систему.
/* Команды управления для 0 мастер-номера:
    "reset"                 сброс настроек и номеров на заводские.
    "master1:79112345678"   добавить номер 79112345678 в ячейку памяти 1.
    "balance:100"           номер баланса *100#.
    "dell:1"                удалить номер из ячейки 1.
    "phone"                 вывести список номеров в системе.
*/
/* Команды управления для всех мастер-номеров:
    "info" либо "?"         инфо о состояни системы и уровня сигнала сети.
    "money"                 проверка баланса.
    "datchiki on\off"       вкл/выкл все датчики.
    "system on\off"         вкл/выкл охрану.
    "ring on\off"           вкл/выкл вызов при аварии или сработке сигнализации.
    "sirena on\off"         вкл/выкл сирену при сработке.
    "sms on\off"            вкл/выкл смс при аварии или сработке сигнализации.
    "door on\off"           вкл/выкл контроль датчика двери.
    "sarai on\off"          вкл/выкл контроль датчика двери сарая.
    "pir on\off"            вкл/выкл контроль датчика движения.
    "gas on\off"            вкл/выкл контроль датчика газа.
*/
// при звонке на номер сигнализации - прослушка помещения.
// при сработке датчиков вызов (если ring on) на 0 мастер-номер и смс (если sms on) всем.
// длинна сообщения  символов.

#include <EEPROM.h> 
#include <OneWire.h>
#include <RCSwitch.h>
#include <SoftwareSerial.h>
#define Ver F("Alarm  v2.1.0\n")

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

#define DOOR 3             // пин 4. концевик двери.
#define PIR 4              // пин 5. датчик движения.
#define LED 8             // пин 13. состояние системы.
#define GAS 9             // пин A0. датчик дыма.
#define BUZ 10            // пин 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;         //    тип модема
boolean Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
boolean AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
boolean SendSMS = 1;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
boolean DOORon = 1;         // 4. контроль концевика двери:       1 - вкл, 0 - выкл.    
boolean SARAIon = 1;        // 4. контроль концевика двери 2:     1 - вкл, 0 - выкл.    
boolean PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
boolean GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.
boolean Sirena = 1;         // 7. сирена:                         1 - вкл, 0 - выкл. 
boolean Firststart = 1;     // первый старт.

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

int Temp = 0;
char CSQ[4];                    // для хранения уровня сигнала
char Bal[4];                    // для временного хранения номера баланса.
char Phone[14];                 // для временного хранения номера телефона, номер до 14 цифр.

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(eepromphone());
  TempC();
  Signal();
  Serial.println(eepromtext() + F("\nSignal seti: ") + CSQ + F("%\nTemp ") + Temp + "*C"); // закомментировать если смс
sms(eepromtext() + F("\nSignal seti: ") + CSQ + "%", 0); // смс на последний номер
  digitalWrite(LED, HIGH);        // гасим светодиод состояния сигнализации.
}  
                                 
void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  }
  if (gsm.available()) {                      // Если модем, что-то отправил...
      sendsmscaller = 1;
      String gval = "";                      // Переменная для хранения ответа модуля
      if (gsm.available()) {     // если GSM модем что-то послал.
        while (gsm.available()) {  // сохраняем входную строку в переменную val.
          char ch = gsm.read();
           gval += char(ch);              // собираем принятые символы в строку
           delay(3);
        } 
      } 
      if (gval.indexOf(F("+PBREADY")) > -1) InitModem();
      else if (gval.indexOf(F("+CLIP")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));
        int ind = gval.indexOf(F("+CLIP: \""));          // обрезаем номер
        ind += 8;                         // Парсим строку и
        String ring = gval.substring(ind, gval.indexOf("\"", ind));
  Serial.println(String(F("RingPhone->")) + ring);
        if (CheckPhone(ring) == 1) sendATCommand("ATA", true);               // снимаем трубку
        else sendATCommand("ATH", true);
      } else if (gval.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
        parsesms(gval);
      } else if(gval.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
  Serial.println(F("Process USD"));
  Serial.println("gval1 " + gval);
        String bal = "";
        if (ModemID == 3) {
          int p1 = gval.indexOf("\"");         // начало строки
          int p2 = gval.lastIndexOf("\"");     // конец строки
          gval = gval.substring(p1 + 1, p2);
  Decode7bit(gval, bal);
      sendATCommand(F("AT+CUSD=0"), true);
        } else if (ModemID == 1 || 2) {
          bal = String(gval.substring(gval.indexOf("\"") + 1,gval.indexOf("\",")));  //
        }
      sendATCommand(F("AT+CUSD=0"), true);
sms(String(F("Sim ")) + bal, 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;
  }
}

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));
  msgphone.trim();
 
  Serial.println(String(F("Phone: ")) + msgphone);    // Выводим номер телефона
  Serial.println(String(F("Message: ")) + msgsms);    // Выводим текст SMS
     if (CheckPhone(msgphone) == 1) Komand(msgsms);
}

int CheckPhone(String phone) { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (uint8_t 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 в память. 
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
    sendATCommand("ATH", true);               // кладем трубку
        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 + " Add", 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");
   String LastEvent = SIGN + RING + SMS + Door + Sarai + SIRENA + Pir + 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 + "#"; 
    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!"), 1); // смс на все номера
        }
        else if (SARAIFlag == 1) {
sms(F("Sarai otkrit!"), 1); // смс на все номера
        }
        else if (PIRFlag == 1) {
sms(F("Dvizhenie y dveri!"), 1); // смс на все номера
        }
        else if (GASFlag == 1) {
sms(F("Gas v dome!"), 1); // смс на все номера
        }
    }
    if (AlarmRING == 1) {
sendATCommand("ATD+" + String(AlarmPhone[0]) + ";", true);              // вывключить эхо
    }
}

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

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

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

void Led() { /// === состояние светодиода === ///
  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);
    }
}

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!"), 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)) {     // инфо о состоянии системы
    Signal();
sms(eepromtext() + F("\nSignal seti: ") + CSQ + "%", 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")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {      // выкл
      Sirena = 0;
      EEPROM.update(8, Sirena);                   
sms(String(F("Sirena->off")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("ring")) > -1)   { // вкл/выкл вызов при сработке
    if (kom.indexOf(on) > -1)   { // вкл 
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->on")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)   { // выкл 
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
sms(String(F("Ring->off")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("sms")) > -1)    { // вкл/выкл смс при сработке
    if (kom.indexOf(on) > -1)    { // вкл 
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->on")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1)    { // выкл
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
sms(String(F("SMS->off")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("door")) > -1) {  // вкл/выкл контроль датчика двери
    if (kom.indexOf(on) > -1) {  // выкл
      DOORon = 1;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->on")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл контроль датчика двери
      DOORon = 0;
      EEPROM.update(4, DOORon);
sms(String(F("DOOR->off")), 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")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      SARAIon = 0;
      EEPROM.update(5, SARAIon);
sms(String(F("SARAI->off")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("pir")) > -1) {  // вкл/выкл контрол датчика движения
    if (kom.indexOf(on) > -1) {  // вкл
      PIRon = 1;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->on")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл
      PIRon = 0;
      EEPROM.update(6, PIRon);
sms(String(F("PIR->off")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("gas")) > -1) {  // вкл/выкл контроль датчика газа
    if (kom.indexOf(on) > -1) {  // вкл 
      GASon = 1;
      EEPROM.update(7, GASon);
sms(String(F("GAS->on")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл 
      GASon = 0;
      EEPROM.update(7, GASon);
sms(String(F("GAS->off")), 1); // смс на все номера
    }
  }
  gsm.println(F("AT+CMGD=1,4")); // стираем смс
}

void Signal() {
  String csq = sendATCommand(F("AT+CSQ"), true);           //
  csq = csq.substring(csq.indexOf(":") + 2, csq.indexOf(","));
  csq.trim();
  csq.toCharArray(CSQ, 4);
}

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

void 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", 0); // смс на 0 номер.
    }// else Serial.println(F("MAX number 4!"));             // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
}                              

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

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

void 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();
    Temp = (data[1] << 8) + data[0];
    Temp = Temp >> 4;
}

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("A6C") > -1) ModemID = 3;
    Serial.println(String(F("ModemID ")) + ModemID + "\n");
       sendATCommand(F("ATE0"), true);              // вывключить эхо
       sendATCommand(F("AT+CLIP=1"), true);         // включить АОН
       sendATCommand(F("AT+CMGF=1"), true);         // включить текстовый формат смс
       sendATCommand(F("AT+CSCS=\"GSM\""), true);   // включить кодировка текста gsm
       sendATCommand(F("AT+CNMI=2,2,0,0,0"), true); // смс прямо в порт
       sendATCommand(F("AT+CREG?"), true);          // регистрация в сети
}

String sendATCommand(String cmd, bool waiting) {
  String atval = "";                            // Переменная для хранения результата
  Serial.println(cmd);                          // Дублируем команду в монитор порта
  gsm.println(cmd);                             // Отправляем команду модулю
  if (waiting) {                              // Если необходимо дождаться ответа...
  long _timeout = millis() + 10000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!gsm.available() && (millis() < _timeout))  {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  if (gsm.available()) {     // если GSM модем что-то послал.
    while (gsm.available()) {  // сохраняем входную строку в переменную val.
      char ch = gsm.read();
      atval += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
  } else Serial.println(F("Timeout..."));               // ... оповещаем об этом и...
    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()) {  // сохраняем входную строку в переменную val.
      char ch = gsm.read();
      str += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
      if (str.indexOf("OK") > -1) {
        Serial.println("OK"); 
        countok++;
      } else countok = 0;
    }
  }  
}

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

 

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

без датчиков запустится, все датчики по умолчанию выключены, кроме температуры.

 

Взял подправленый код с 667 поста, в мониторе порта нечего не поменялось(

Alarm  v2.1.3

MasterPhone:
[0] 
[1] 
[2] ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮!
[3] ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮!
[4] ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮!
Ring +38******
Balance *#

AT+CSQ
Timeout...

 

 
А с этого поста 715 с автоопределением модема вот что кидает в монитор
Alarm  v2.1.0

>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT
>>AT

 

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

kot488, гляну через часик

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:
kot488, гляну через часик

 

Нашел сегодня А6, тот же результат.

 

 

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:
kot488, гляну через часик

 

Может в этом проблема? Подключил модем на прямую через usb-uart, на первой же команде ошибка. Потом ее повторяю все нормально. Через монитор порта не реагирует.

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

kot488, попробуйте команду настройки скорости AT+IPR=0, затем АТ.
Сегодня в ночь на работе, буду проверять коды

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

kot488 пишет:

pasha413 пишет:
kot488, гляну через часик

 

Может в этом проблема? Подключил модем на прямую через usb-uart, на первой же команде ошибка. Потом ее повторяю все нормально. Через монитор порта не реагирует.

Скорми модему команду

AT+CMEE=2

И будут тебе описания ошибок, вместо непонятных кодов.

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

kot488 пишет:

pasha413 пишет:
kot488, гляну через часик

 

Может в этом проблема? Подключил модем на прямую через usb-uart, на первой же команде ошибка. Потом ее повторяю все нормально. Через монитор порта не реагирует.

модем А6 ? у него проблемы с USSD в зависимости от прошивки, может не заработать. Мне например на SIM 800 пришлось переходить

 

 

kot488
Offline
Зарегистрирован: 22.03.2018

Да, А6. Не подскажешь какие изменения нужно внести для перехода на SIM800?
Сейчас на руках sim800l, a590 и A6

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

данную сигнализацию не делал, пробовал на совсем других проектах, поэтому конкретно подсказать не смогу.

при переходе взял готовый проект с модемом A6, запустил его на sim800 и после каждой команды смотрел будет ошибка или нет,

в основном отличия в применении кавычек, и USSD баланс на A6 я так и не смог запустить.

 

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

Извиняюсь, ничего не успел на работе...пишу с телефона...
Для применения кода из #667 на сим800 замените:
093 unsigned long timer = 3600; // каждый час
131 timer += timer;
155 ind += 9;
176 if (gval.indexOf(F("+CUSD:")) > -1) { // если пришел баланс
177 int p1 = gval.indexOf("\""); // начало строки
180 int p2 = gval.lastIndexOf("\""); // конец строки
181 gval = gval.substring(p1 + 1, p2); // обрезаем строку
182 bal = gval;
183 Serial.println(bal);
184 sendATCommand(F("AT+CUSD=0"));
185 }
Далее внимательнее номера строк не будут совпадать, пишу как могу)))
211 Index += 9;
560 sendATCommand(String(F("AT+CUSD=1,#\"")) + Bal + F("\"#,15")); //на сим 800 нужны кавычки, на А6 нет...
571 void Decode7bit(){} удаляем функцию
591 digitalWrite(rst, LOW); // перезапускаем модем
592 delay(200);
593 digitalWrite(rst, HIGH);

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

А6 у меня дефектных не попадалось, 2шт А6 и один А6С (с камерой был).
М590 3шт и все разные по АТ командам и току потребления.
SIM800l 2шт с разными прошивками отличия пока что увидел: gprs не завелся на одном, и голосовые команды на нём же не завелись

kot488
Offline
Зарегистрирован: 22.03.2018

Изменил, ситуация та ж line

вот такой код вышел

 

// 0 (основной) мастер-номер добавляется при первом звонке либо смс на систему.
// при звонке на номер сигнализации - прослушка помещения.
// при сработке датчиков- вызов (если ring on) на 0 мастер-номер и смс (если sms on) всем.
// длинна сообщения 123 символов.
/* 
 *Команды управления для 0 мастер-номера:
    "reset"                 сброс настроек и номеров на заводские.
    "master1:79112345678"   добавить номер 79112345678 в ячейку памяти 1.
    "balance:100"           номер баланса *100#.
    "dell:1"                удалить номер из ячейки 1.
    "phone"                 вывести список номеров в системе.
 *Команды управления для всех мастер-номеров:
    "info" либо "?"         инфо о состояни системы и уровня сигнала сети.
    "datchiki on\off"       вкл/выкл все датчики.
    "system on\off"         вкл/выкл охрану.
    "ring on\off"           вкл/выкл вызов при аварии или сработке сигнализации.
    "sirena on\off"         вкл/выкл сирену при сработке.
    "sms on\off"            вкл/выкл смс при аварии или сработке сигнализации.
    "door on\off"           вкл/выкл контроль датчика двери.
    "sarai on\off"          вкл/выкл контроль датчика двери сарая.
    "pir on\off"            вкл/выкл контроль датчика движения.
    "gas on\off"            вкл/выкл контроль датчика газа.
*/

#include <EEPROM.h>
#include <OneWire.h>
#include <RCSwitch.h>
#include <SoftwareSerial.h>
#include <DallasTemperature.h>
#define Ver F("Alarm  v2.1.3\n")

OneWire DS18B20(15);             // датчик температуры, подтяжка 4.7кОм на +.
DallasTemperature ds(&DS18B20);
SoftwareSerial gsm(4, 5);        // модем.
RCSwitch mySwitch = RCSwitch();  // беспроводной датчик двери, пин 2.

#define DOOR   17           // концевик двери. если сработал, на входе "+" HIGH.
#define PIR    16           // датчик движения. если сработал, на входе "+" HIGH.
#define GAS    14           // датчик дыма. если сработал, на входе "+" HIGH.
#define LED    9            // состояние системы. если "-" LOW, то горит.
#define BUZ    10           // сирена. если "-" LOW, то горит.
#define sarai 3258553       // адрес 433 передатчика геркона двери. если сработал, на пин 2 сигнал.
#define dvizhenie 3258553       // адрес 433 передатчика геркона двери. если сработал, на пин 2 сигнал.
#define rst    3            // reset модема.

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

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

boolean DOORFlag = false;       // флаг состояние датчика двери.
boolean SARAIFlag = false;      // флаг состояние датчика двери 2.
boolean DVIZHENIEFlag = false;      // флаг состояние датчика двери 2.
boolean PIRFlag = false;        // флаг состояние датчика движения.
boolean GASFlag = false;        // флаг состояние датчика газа.
int8_t LEDState = LOW;          // Состояние светодиода.
int8_t DOORState = LOW;         // Состояние концевика двери.
int8_t PIRState = LOW;          // Состояние датчика движения.
int8_t Smoky = LOW;             // Состояние датчика газа.

float Temp_ul = false;          // температура.                
float Temp_pom = false;         // температура.                
char CSQ[4];                    // для хранения уровня сигнала.
char Bal[4];                    // для временного хранения номера баланса.
char Phone[14];                 // для временного хранения номера телефона, номер до 14 цифр.

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

unsigned int p = 0;
#define GASThres 400        // предельная концентрация газа
#define time_alarm 20       // Секунд до отключения "тревожного" пина. 
unsigned long lasttime_alarm = 0;
#define interval_led 1000   // для мигания LED, 1 сек.
unsigned long previousMillis_led = 0;
#define time_door 10        // секунд не смотрим на датчик двери.
unsigned long lasttime_door = 0;
#define time_sarai 10       // секунд не смотрим на датчик двери 2.
unsigned long lasttime_sarai = 0;
#define time_dvizhenie 10       // секунд не смотрим на датчик двери 2.
unsigned long lasttime_dvizhenie = 0;
#define time_pir 20         // секунд не смотрим на датчик движения.
unsigned long lasttime_pir = 0;
#define time_gas 600        // секунд не смотрим на датчик газа. 10 минут
unsigned long lasttime_gas = 0;
unsigned long timer = 3600;

/* 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);
  ds.begin();                                    // Запуск библиотеки, по умолчанию 9 бит
  pinMode(DOOR, INPUT_PULLUP);                   // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);  digitalWrite(PIR, HIGH); //
  pinMode(GAS, INPUT);
  pinMode(BUZ, OUTPUT); digitalWrite(BUZ, LOW);  // сирена выкл.
  pinMode(LED, OUTPUT); 
  pinMode(rst, OUTPUT); digitalWrite(rst, LOW);  // 
  mySwitch.enableReceive(0);                     // RF433 приемник на 2 пине
  Restart();                                     // перезапускаем систему
}

void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (millis()/1000 > timer) {  // проверяем каждый час 
    TempC();
    Signal();
    timer += timer; 
  }
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  } else digitalWrite(LED, LOW);
  if (gsm.available()) {               // Если модем что-то отправил...
    serial = false;
    String gval = "";                  // Переменная для хранения ответа модуля
      while (gsm.available()) {        
        char ch = gsm.read();
        gval += char(ch);              // сохраняем входную строку в переменную gval
        delay(3);
      }
//Serial.println("gval->" + gval);
   if (gval.indexOf(F("RING")) > -1) {        // если обнаружен вызов.
      sendATCommand(F("ATH"));                // снимаем трубку  
      for (int i = 0; i < 5; i++) {           // проверяем сохраненные номера
        if (gval.indexOf(AlarmPhone[i]) > -1 && AlarmPhone[i] != 0) {  // если он наш
          RingPhone = AlarmPhone[i];          // запоминаем номер звонящего
          RingPhone.toCharArray(Phone, 14);   
          EEPROM.put(100, Phone);             // записываем RingPhone в память. 
        } else if (Firststart) {              // если первый старт
          int ind = gval.indexOf(F("+CLIP: \""));   // обрезаем номер ... 
          ind += 9;
          String ring = gval.substring(ind, gval.indexOf("\"", ind));
          RingPhone = ring;                         // запоминаем номер звонящего 
          ring.toCharArray(Phone, 14);              // сохраняем в переменную Phone
          EEPROM.put(25, Phone);                    // пишем номер в EEPROM как основной мастер-номер
          EEPROM.put(100, Phone);                   // записываем RingPhone в память. 
          AlarmPhone[0] = Phone;                    // запишем
          Firststart = false;                       // пишем 0
          EEPROM.update(10, Firststart);            // обновляем Firststart
Serial.println(String(F("Firststart:")) + Firststart);
sms(String(F("Master0:")) + ring + " Ok", 0);       // смс на звонивший
//sms("Master0:" + ring + " Ok", 0);                  // смс на звонивший
        } 
      }
    } else if (gval.indexOf(F("+CMT")) > -1) {      // если обнаруженa СМС
      for (int i = 0; i < 5; i++) {                 // проверяем сохраненные номера
        if (gval.indexOf(AlarmPhone[i]) > -1 && AlarmPhone[i] != 0) { // если он наш 
          RingPhone = AlarmPhone[i];                // запоминаем его.
  parsesms(gval);                                   // запускаем подпрограмму парсинга сообщений
        }
      }     
    } else if (gval.indexOf(F("+CUSD:")) > -1) {  // если пришел баланс
           int p1 = gval.indexOf("\"");         // начало строки
      int p2 = gval.lastIndexOf("\"");     // конец строки
      gval = gval.substring(p1 + 1, p2);    // обрезаем строку
      bal = gval;
      
Serial.println(bal);
      sendATCommand(F("AT+CUSD=0"));      
    } 
  } else if (Serial.available()) {         // если в мониторе порта что-то ввели
    String sval = "";                      // Переменная для хранения сообщения из монитора порта
    while (Serial.available()) {           
      char ch = Serial.read();
      sval += char(ch);                    // сохраняем входную строку в переменную sval.
      delay(3);
    }
    serial = true;
    Komand(sval);                          // запускаем подпрограмму распознавания команд
  }
}

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 += 9;                                             // Парсим строку и
  msgphone = msgheader.substring(Index, msgheader.indexOf("\"", Index)); // Выдергиваем телефон
  msgphone.trim();                                         // удаляем пробелы вначале и в конце строки

//Serial.println(String(F("Phone: ")) + msgphone);           // Выводим номер телефона
//Serial.println(String(F("Message: ")) + msgsms);           // Выводим текст SMS
  RingPhone = msgphone;
  RingPhone.toCharArray(Phone, 14);         
  EEPROM.put(100, Phone);                   // записываем номер  
  Komand(msgsms);                           // запускаем подпрограмму распознавания команд
}

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

void master (int i, String num) { /// === добавление мастер-номеров === ///
  if (i < 5 && i != 0) {                             // если ячейка от 1 до 4
    num.trim();                       
    num.toCharArray(Phone, 14);                      // конвертируем номер
    AlarmPhone[i] = num;                             
    EEPROM.put(Adress[i], Phone);                    // записываем массив в EEPROM
sms(String(F("Master")) + i + "->" + num + " add", 0); // смс на 0 номер.
  } 
}

void dellphone (int i) { /// === удаление мастар-номеров === ///
  if (i < 5 && i != 0) {                             // если ячейка от 1 до 4
    AlarmPhone[i] = "";                              // стираем номер
    EEPROM.put(Adress[i], 0);                        // стираем номер
sms(String(F("Master")) + i + "->" + AlarmPhone[i] + " dell", 0); // смс на 0 номер
  }
// 0 номер можно удалить только через RESET!!!
}

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

void eepromconfig() { /// === конфигурирование сигнализации === ///
  if (EEPROM.read(0) != 1) {           // если по 0 адресу записана не 1, переписываем в память 000
    for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
      EEPROM.write(i, 0);
    }                              // и записываем:
    EEPROM.update(1, 0);           // Guard       охрана выкл.
    EEPROM.update(2, 0);           // AlarmRING   вызов при сработке вкл.
    EEPROM.update(3, 0);           // SendSMS     смс при сработке вкл.
    EEPROM.update(4, 0);           // DOORon      датчики дверей вкл.
    EEPROM.update(5, 0);           // SARAIon     датчики дверей вкл.
    EEPROM.update(6, 0);           // PIRon       датчик движения вкл.
    EEPROM.update(7, 0);           // GASon       датчик газа вкл.
    EEPROM.update(8, 0);           // Sirena      сирена при сработке вкл.
    EEPROM.update(10, 1);          // Firststart  первый старт!
    EEPROM.update(0, 1);           // пишем 1 в 0 адрес
Serial.println(F("EEPROM != 1/ RESET!"));
  } if (EEPROM.read(0) == 1) {     // если в 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 = "";        // датчика двери RF433.
  String Pir = "";          // датчик движения.
  String Gas = "";          // датчик газа.
  if (Guard) SIGN = F("System on\n"); else SIGN = F("System off\n");
  if (Sirena) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n");
  if (AlarmRING) RING = F("Ring on\n"); else RING = F("Ring off\n");
  if (SendSMS) SMS = F("SMS on\n"); else SMS = F("SMS off\n");
  if (DOORon) Door = F("Door on\n"); else Door = F("Door off\n");
  if (SARAIon) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n");
  if (PIRon) Pir = F("Pir on\n"); else Pir = F("Pir off\n");
  if (GASon) Gas = F("Gas on\n"); else Gas = F("Gas off");
  String LastEvent = SIGN + SIRENA + RING + SMS + Door + Sarai + Pir + 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 + "#";
  String EEPhone = numbers + ring + bal;
  return EEPhone;
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  if (DOORon) {                                            // если датчик двери включен
    if (DOORState == HIGH && !DOORFlag) {                  // если он сработал
      lasttime_door = millis();                            // запускаем таймер
      DOORFlag = true;                                     // ставим флаг
//Serial.println(F("Dver' otkrita!"));
      Alarm();                                             // запускаем подпрограмму Alarm        
    } else if (DOORState == LOW && DOORFlag) {                       
      if (((millis() - lasttime_door)/1000 > time_door)) { // и прошел интервал
        DOORFlag = false;                                  // возвращаем флаг к начальному состоянию
//Serial.println(F("Dver' zakrita!"));
      }
    }
  }
  if (SARAIon) {
    if (mySwitch.available()) {                            // если датчик сарая включен
      unsigned long value = mySwitch.getReceivedValue();   // считываем значение с RF433
      if (value == sarai && !SARAIFlag) {                  // если он сработал
        lasttime_sarai = millis();                         // запускаем таймер
        SARAIFlag = true;                                  // ставим флаг
//Serial.println(F("Sarai otkrit!"));       
        Alarm();                                           // запускаем подпрограмму Alarm
      }
      mySwitch.resetAvailable();                          
    } 
    if (((millis() - lasttime_sarai)/1000 > time_sarai)) { // если прошол интервал
      SARAIFlag = false;                                   // возвращаем флаг к начальному состоянию
    }
  }
  if (PIRon) {                                             // если включен PIR датчик движения
    if (PIRState == HIGH && !PIRFlag) {                    // если он сработал
      lasttime_pir = millis();                             // запускаем таймер  
      PIRFlag = true;                                      // ставим флаг
//Serial.println(F("Dvizhenie u dveri!"));
      Alarm();                                             // запускаем подпрограмму Alarm
    } else if (PIRState == LOW && PIRFlag) {               // иначе если движения нет
      if (((millis() - lasttime_pir)/1000 > time_pir)) {   // и прошел интервал
        PIRFlag = false;                                   // возвращаем флаг к начальному состоянию
      }
    }
  }
  if (GASon) {                                             // если включен датчик газа
    if ((Smoky > GASThres) && !GASFlag) {                  // если он сработал
      lasttime_gas = millis();                             // запускаем таймер 
      GASFlag = true;                                      // ставим флаг
//Serial.println(F("Gas v dome!"));
      Alarm();                                             // запускаем подпрограмму Alarm 
    } else if ((Smoky < GASThres) && GASFlag) {            // иначе если газа нет
      if (((millis() - lasttime_gas)/1000 > time_gas)) {   // и прошел интервал
        GASFlag = false;                                   // возвращаем флаг к начальному состоянию
      }
    }
  }
}

void Alarm() { /// === аварийные сигналы === ///
  if (Sirena) {                              // если включена сирена при сработке
    lasttime_alarm = millis();               // запускаем таймер сирены
    digitalWrite(BUZ, HIGH);                 // запускаем ее
  }
//Serial.println(F("Alarm!!!"));
  if (SendSMS) {                             // если включена отправка смс при сработке
    if (DOORFlag) {                          // если сработал датчик двери
sms(F("Dver' otkrita!"), 1);                 // смс на все номера
    } else if (SARAIFlag) {                  // если сработал датчик двери RF433
sms(F("Sarai otkrit!"), 1);                  // смс на все номера
    } else if (PIRFlag) {                    // если сработал датчик движения
sms(F("Dvizhenie y dveri!"), 1);             // смс на все номера
    } else if (GASFlag) {                    // если сработал датчик газа
sms(F("Gas v dome!"), 1);                    // смс на все номера
    }
  }
  if (AlarmRING) {                           // если включен вызов при сработке
sendATCommand("ATD+" + String(AlarmPhone[0]) + ";"); // делаем вызов основного мастер-номера
  }
}

void AlarmPinOff() { /// === отключаем сирену === ///
  if ((millis() - lasttime_alarm)/1000 > time_alarm) digitalWrite(BUZ, LOW); // если прошло время, отключаем сирену
}

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

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

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

void Signal() { /// === проверка уровня сигнала сети === ///
  String csq = sendATCommand(F("AT+CSQ"));           
  csq = csq.substring(csq.indexOf(":") + 2, csq.indexOf(",")); // парсим ответ об уровне сигнала
  csq.trim();                                        // удаляем пробелы вначале и в конце строки
  csq.toCharArray(CSQ, 4);                           
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(1000);                // ждем секунду, т.к. вылетает с ошибкой
  sendATCommand(String(F("AT+CUSD=1,#\"")) + Bal + F("\"#,15"));
//  gsm.println(String(F("AT+CUSD=1,#")) + Bal + "#,15");
//  Serial.println(String(F("AT+CUSD=1,#")) + Bal + "#,15");
}

void TempC() { /// === измеряем температуру === ///
  ds.requestTemperatures();             // Запрос на считывание температуры
  Temp_ul = ds.getTempCByIndex(0);      // считываем температуру с первого датчика
  Temp_pom = ds.getTempCByIndex(1);     // считываем температуру со второго датчика 
}



void Restart() { /// === рестарт системы === ///
  digitalWrite(rst, LOW);                     // перезапускаем модем
  delay(200);
  digitalWrite(rst, HIGH);         
  digitalWrite(LED, HIGH);                     // светодиод горит во время запуска
  eepromconfig();                              // читаем конфигурацию из памяти
Serial.println(String(F("MasterPhone:\n")) + eepromphone() + "\r\n");  // выводим список номеров из памяти в порт
//Serial.println(String(F("AlarmConfig:\n")) + eepromtext());            // закомментировать если смс
  TempC();                                     // читаем температуру
  Signal();                                    // читаем сигнал сети GSM
Serial.println(String(F("Firststart:")) + Firststart);
if (!Firststart) sms(String(F("Modem restart\n")) + eepromtext(), 0);  // если не первый старт смс на последний номер
  digitalWrite(LED, LOW);                      // гасим светодиод состояния сигнализации.
}

void InitModem() { /// === инициализация модема === ///
  gsm.begin(9600);                       //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  sendATCommand(F("ATE0"));              // выключить эхо
  sendATCommand(F("AT+CLIP=1"));         // включить АОН
  sendATCommand(F("AT+CMGF=1"));         // включить текстовый формат смс
  sendATCommand(F("AT+CSCS=\"GSM\""));   // включить кодировку текста gsm
  sendATCommand(F("AT+CNMI=2,2,0,0,0")); // смс прямо в порт
  sendATCommand(F("AT+CREG?"));          // регистрация в сети
  sendATCommand(F("AT+CMGD=1,4"));       // стираем смс
}

String sendATCommand(String cmd) {
  String atval = "";                             // Переменная для хранения результата
  Serial.println(cmd);                           // Дублируем команду в монитор порта
  gsm.println(cmd);                              // Отправляем команду модулю
    long _timeout = millis() + 10000;            // Переменная для отслеживания таймаута (10 секунд)
    while (!gsm.available() && millis() < _timeout) {}; // Ждем ответа 10 секунд
    if (gsm.available()) {                       // если GSM модем что-то послал.
      while (gsm.available()) {                  // сохраняем входную строку в переменную val.
        char ch = gsm.read();
        atval += char(ch);                       // собираем принятые символы в строку
        delay(3);
      }
    } else {
      Serial.println(F("Timeout..."));           // ... оповещаем об этом и...
      Restart();                                 // перезапускаем модем
    }
    Serial.println(atval);                       // Дублируем ответ в монитор порта
  return atval;
}

void waitConnect() {  // запуск модема
  uint16_t 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()) {              // сохраняем входную строку в переменную val.
        char ch = gsm.read();
        str += char(ch);                     // собираем принятые символы в строку
        delay(3);
      }
      if (str.indexOf("OK") > -1) {
        Serial.println("OK");
        countok++;
      } else countok = 0;
    }
  }
}

void sms(String text, byte sendnum) { /// === отправка СМС === ///
  String phone = "";
  text += String(F("\nTemp_ul ")) + Temp_ul;           // добавляем к тексту температуру на улице
  text += String(F("*C\nTemp_pom ")) + Temp_pom;       // добавляем к тексту температуру на в помещении
  text += String(F("*C\n")) + bal;                     // добавляем к тексту баланс sim карты
  if (!serial) {                                       // если не команда из сериала
    if (!sendnum) {                                    // отправка смс на номер звонившего
      phone = RingPhone;
      sendATCommand(String(F("AT+CMGS=\"+")) + phone + "\""); // Переходим в режим ввода текстового сообщения
      sendATCommand(text + (String)((char)26));        // отправка текста 
    } else if (sendnum) {                              // отправка смс на все номера
      for (uint8_t i = 0; i < 4 ; i++) {
        phone = AlarmPhone[i];
        if (phone != 0) {                              // если ячейка пустая - не отправлять смс
          sendATCommand(String(F("AT+CMGS=\"+")) + phone + "\""); // Переходим в режим ввода текстового сообщения
          sendATCommand(text + (String)((char)26));    // отправка текста 
        }
      }
    }
  } else Serial.println(text);                         // если команда из сериала пишем выводим результат
  if (Bal != 0) balance();                             // если есть номер баланса проверяем его
}

по коду есть ребут модема, на sim800 не нашел контакта rst

 

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

RST после Vcc перед Rx

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:
RST после Vcc перед Rx

Извините пожалуйста не досмотрел.

Вообщем я походу баран и нашел проблему, симка которая стоит в модуле проверяет баланс через *111#, в этом судя по всему и вся проблема. Можно на програмной уровне заменить номер? Ведь через терминал не реагирует на команды, пока не загрузится нормально(

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

Так загрузится должна и так потом выполните команду reset
и добавьте номер баланса.

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:
Так загрузится должна и так потом выполните команду reset и добавьте номер баланса.

 

Там же в коде читал, пока 5 Ок не получит то не запустится. По коду на команду баланс нет ответа, вроде изза этого повторяется попытка

Alarm  v2.1.3

 
MasterPhone:
[0] 
[1] 
[2] 
[3] 
[4] 
Ring 
Balance *101#
 
AT+CSQ
Timeout...
MasterPhone:
[0] 
[1] 
[2] 
[3] 
[4] 
Ring 
Balance *101#
 
pasha413
Offline
Зарегистрирован: 27.11.2016

загрузите такой код:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 6);  // модем подключен к 7 и 8 пинам.


void setup(){  
  Serial.begin(9600);
  mySerial.begin(9600);   
}

void loop() {
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
    mySerial.write(Serial.read());
}

и вводите в сериал поочередно команды, ответ сюда:

AT

ATE1

ATI

AT+CSQ

AT+CREG?

 

посмотрим что отвечает модем

kot488
Offline
Зарегистрирован: 22.03.2018

Бывает ошибка на первой команде и на последней, если повторить то все ок

AT
OK
ATE1
OK
ATI
SIM800 R14.18
 
OK
AT+CSQ
+CSQ: 22,0
 
OK
AT+CREG?
ERROR
AT+CREG?
+CREG: 0,1
 
pasha413
Offline
Зарегистрирован: 27.11.2016

сделайте сброс до заводских AT&F

настройка модема, необходимы команды: AT+IPR=9600;E1+DDET=1;+CMGF=1;+CSCS=\"gsm\";+CNMI=2,1,0,0,0;+VTD=1;+CMEE=1;&W

да, если AT+CMEE=2   то выдаст описание ошибки

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

сделайте сброс до заводских AT&F

настройка модема, необходимы команды: AT+IPR=9600;E1+DDET=1;+CMGF=1;+CSCS=\"gsm\";+CNMI=2,1,0,0,0;+VTD=1;+CMEE=1;&W

да, если AT+CMEE=2   то выдаст описание ошибки

 

A6 нормально отработал команды.

AT
OK
ATE1
OK
ATI
Ai Thinker Co.LTD
A6
 
V03.05.20170090814H38
 
OK
AT+CSQ
+CSQ: 22,99
 
OK
AT+CREG?
+CREG: 1,1
 
OK
 
 
pasha413
Offline
Зарегистрирован: 27.11.2016

кстати что у вас с питанием SIM800 4V?

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

кстати что у вас с питанием SIM800 4V?

 

Arduino UNO, в контакт 5V подключен. Так же и А6 подключал

Сейчас по такой же схеме подключен, на команды ответ дает

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

питание sim800 от 3.7В до 4.2В! если только у вас не v2. ну и тока на uno не хватит. я подключаю через dc\dc преобразователь в отдельный USB.

kot488
Offline
Зарегистрирован: 22.03.2018

Я uno запитал от доп БП питания 5V.

На ногах 5V

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

sim800 нестабильно работает от 5V, если вообще работает...питание sim800 от 3.7В до 4.2В!

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

sim800 нестабильно работает от 5V, если вообще работает...питание sim800 от 3.7В до 4.2В!

 

Подал 4.1В, все по прежнему, Но команды как и раньше через putty вводятся только

Alarm  v2.1.3

MasterPhone:
[0] 
[1] 
[2] 
[3] 
[4] 
Ring 
Balance *101#

AT+CSQ
Timeout...
MasterPhone:
[0] 
[1] 
[2] 
[3] 
[4] 
Ring 
Balance *101#

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

AT&F делали?

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

AT&F делали?

 

Да

AT
OK
AT&F
OK
AT+IPR=9600;E1+DDET=1;+CMGF=1;+CSCS=\"gsm\";+CNMI=2,1,0,0,0;+VTD=1;+CMEE=1;&W
ERROR
AT+IPR=9600;E1+DDET=1;+CMGF=1;+CSCS=\"gsm\";+CNMI=2,1,0,0,0;+VTD=1;+CMEE=1;&W
ERROR

Вот так запустил строку

AT+IPR=9600;E1+DDET=1;+CMGF=1;+CSCS="gsm";+CNMI=2,1,0,0,0;+VTD=1;+CMEE=1;&W

 

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

хм, я с таким не сталкивался, даже не знаю чем помочь... симка стоит? после AT&F снимите и подайте питание на модем. земля модема и uno соединены?

 

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

хм, я с таким не сталкивался, даже не знаю чем помочь... симка стоит? после AT&F снимите и подайте питание на модем. земля модема и uno соединены?

 

 

GND Uno идет на GND SIM800, через понижалку.

После сброса модем мусор постоянно начал кидать

AT
OK
AT&F
OK

RDY

+CFUN: 1

+CPIN: READY

Call Ready

SMS Ready

RDY

+CFUN: 1

 

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

это не мусор!

если постоянно

12 Call Ready
13  
14 SMS Ready
 

значит модем постоянно перезагружается, что-то нето с питанием!!!

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

это не мусор!

если постоянно

12 Call Ready
13  
14 SMS Ready
 

значит модем постоянно перезагружается, что-то нето с питанием!!!

 

Ходит на на ногах модем от 4.0 до 4.25

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

это не мусор!

если постоянно

12 Call Ready
13  
14 SMS Ready
 

значит модем постоянно перезагружается, что-то нето с питанием!!!

 

Ходит на на ногах модем от 4.0 до 4.25

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

это не мусор!

если постоянно

12 Call Ready
13  
14 SMS Ready
 

значит модем постоянно перезагружается, что-то нето с питанием!!!

 

Ходит на на ногах модем от 4.0 до 4.25

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

это не мусор!

если постоянно

12 Call Ready
13  
14 SMS Ready
 

значит модем постоянно перезагружается, что-то нето с питанием!!!

 

Ходит на на ногах модем от 4.0 до 4.25

kot488
Offline
Зарегистрирован: 22.03.2018

pasha413 пишет:

это не мусор!

если постоянно

12 Call Ready
13  
14 SMS Ready
 

значит модем постоянно перезагружается, что-то нето с питанием!!!

 

Ходит на на ногах модем от 4.0 до 4.25