нужна помощ в доведении охраной сигнализации до ума

alexBCN
Offline
Зарегистрирован: 01.07.2019
Друзья доброго времени суток  нужна помощь и не бесплатная, если поможете 
с прoшивкой  и частично с подключением дополнительного датчика 
речь идет о системе прото-типе сигнализации на ардуино нано 3.0 
с модулем отправки смс m590 neoway,   управление системой тоже по смс 
с датчиком противопожарной сигнализации на термодатчике dallas ds18b20
с пирометрическим датчиком движения HC-SR501 
с датчиком газа на присутствие бутана MQ-2
 
возможно в систему понадобится добавить емкостной датчик  для baypass (защиты ) пирометрического  и нужна будет помощь в его подключении в плате
или просто все заменить на микроволновый датчик движения  ..(нужно где то 7 метров реагирования  плюс минус )
как это реализовано в этом проэкте  
проэкт мне этот передали  по наследству со всеми болячками от того кто этот концепт разрабатывал но по каким то мотивам  
отошел от проэкта и поддержи этого проэкта 
надеюсь с вашей помощью можно будет быстро его довести до ума   в С++ я ноль  а платформой Адрунино встречаюсь впервые хотя в принципе понимаю как там все 
но не в деталях 
контакт whatsup   +34 6О4.2I6.7I5    или пишите в личку или тут на форуме 
 
на данный момент нужно 
1 ограничить время гореня светодиодов 3 минутами (где то в прошивке пошукать)
2 установить смс  отстук   ..потому что система принимает входящие но не отстукивает обратно о статусе системы итд
3 прикрутить дополнительный емкостной датчик или/и микроволновый движения  (заказали несколько  разных выбирем какой подойдет лутче)
4 заставить таки работать газовый датчик на бутан и термодатчик dallas ds18b20 
 
прошивка  на систему  
 
#include <EEPROM.h> 
#include <OneWire.h>
#include<SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);
 
OneWire ds(4);             // датчик температуры подключен к 4 пину, подтяжка 4.7кОм на +.
#define DOOR 6             // концевик двери.
#define PIR 9              // датчик движения.
#define INPIR 7            // выход для подачи напряжения на свет
#define Led 5              // состояние системы. моргает - на охране.
#define GAS A0             // датчик дыма.
#define BUZ 12             // сирена.
 
// DOOR     - если сработал, на входе "+" HIGH.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// Led      - если "-" LOW, то горит.
 
int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
int8_t SendSMS = 0;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
int8_t DOORon = 0;         // 4. контроль концевиков дверей:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 0;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.
int8_t Sirena = 1;         // 7. сирена:                         1 - вкл, 0 - выкл. 
 
int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.   // датчик висит в воздухе программно. аппаратно на минус через 10k.
int8_t LedState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t Firststart;         // первый старт.
uint32_t msAT = 0;
 
char Bal[4] = "";          // для временного хранения номера баланса.   
char Phone[12];            // для временного хранения номера телефона. 
//(если размер номера более 12 цифр нужно поменять на нужное количество по факту определителя как его видно на дисплее +1 )   
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.
 
String val;                // переменная для хранения пришедших данных.   
String temp;               // переменная для хранения температуры.
String CSQ;                // переменная для хранения пришедших данных уровня сигнала.   
String LastEvent;          // полное состояние системы.
String RingPhone;          // номер звонившего.
String AlarmPhone[5];      // номера для постановки/снятии с охраны и отправки смс.
String Info1 = "Kommanda - deistvie:\nstatus - sostoyanie\nmoney - balance\n";  // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
String Info2 = "sirenaon/off\nsystemon/off\nringon/off\nsmson/off\n";           
String Info3 = "dooron/off\npiron/off\ngason/off";
 
int p = 0;
int GASThres = 400;           // предельная концентрация газа
int interval_alarm = 20;      // Секунд до отключения "тревожного" пина, max 300сек 
int previousMillis_alarm = 0;
int interval_led = 1000;      // для мигания Led
int previousMillis_led = 0;
int interval_door = 10;       // секунд не смотрим на датчик двери
int previousMillis_door = 0;
int interval_pir = 10;        // секунд не смотрим на датчик движения
int previousMillis_pir = 0;
int interval_gas = 60;        // секунд не смотрим на датчик газа
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 - PIRon = 1;       // датчик движения:    1 - вкл.
  6 - GASon = 1;       // датчик дыма:        1 - вкл.
  7 - Sirena = 1;      // сирена:             1 - вкл.
  10 - Firststars = 1;    // первый запуск       1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/
 
void setup() { /// === настройка программы === ///
  Serial.begin(9600); 
  Serial.println(F("GSMTruck4.7"));
  pinMode(DOOR, INPUT_PULLUP);        // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);                // вход датчика движения .  
  pinMode(INPIR, OUTPUT);             // определяем как выход      
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);
  pinMode(Led, OUTPUT);               // светодиод как выход.
    digitalWrite(BUZ, HIGH);          // сирена выкл.
    digitalWrite(PIR, LOW);           // отключаем внутренню подтяжку и вешаем сопротивлени 10k на GND для внешней подтяжки, чтобы не срабатывало на наводки
  InitModem();                        // запускаем инициализация модема.
  eepromconfig();
  eepromtext();
  eepromphone();
    digitalWrite(Led, HIGH);           // гасим светодиод состояния сигнализации. 
}                                   
void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    LED();          // моргаем светодиодом.
    Timeled();      // включаем свет и камеру при любом движении на заданное время.
  }
  if (mySerial.available()) {     // если GSM модем что-то послал.
    while (mySerial.available()) {  // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf(F("+CLIP")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      delay(2000);                             // дадим гудок
      mySerial.println(F("ATH"));              // сбрасываем вызов.
      if (CheckPhone() == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
      } else  Serial.println(F("No Master Ring!"));  
    } else if (val.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
  Serial.println(String(F("SMS->")) + val);    // что пришло в смс
        if (CheckPhone() == 1) {               // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  MasterSMS();
        } else  Serial.println(F("No Master SMS!"));
      } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
        int p1 = val.indexOf(F("\""));         // начало строки
        int p2 = val.lastIndexOf(F("\""));     // конец строки -  нужно поставить вместо "\""  значение "значение" которое приходит от оператора после суммы чтобы обрезать строку
        val = val.substring(p1+1,p2);
        Serial.println("");
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(val);
        String decodestr;
        Decode7bit(val, decodestr);
        Serial.println("");
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        Serial.println(decodestr);
sms(String("SIM " + decodestr), RingPhone);    // смс на последний звонивший
         } else if (val.indexOf(F("+CSQ:")) > -1) { // пришел уровень сигнала сети
          int x = val.indexOf("+CSQ:");
          CSQ = "Signal " + val.substring(x+5, x+7) + "%";
           } val = ""; 
  } if (Serial.available()) {           // если в мониторе порта что-то ввели
        while (Serial.available()) {         // сохраняем входную строку в переменную val.
        char ch = Serial.read();
        val += char(ch);                   // собираем принятые символы в строку
        delay(3);
        } 
  ConsolePrint();                        // запускаем консольную программу
        val = "";  
    }
}
 
int CheckPhone() { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (val.indexOf(AlarmPhone[i]) > -1) {    // && val.indexOf(AlarmPhone[i]) != 0) { // если есть вызов, и он наш
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 12);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      if (val.indexOf("+CLIP: \"7") > -1) {
      int ind = val.indexOf("+CLIP:") + 8;          // обрезаем номер 
      String num = val.substring(ind, ind + 11); 
      num.toCharArray(Phone, 12);
      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("Master0:")) + AlarmPhone[0]); 
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String("Master0:" + num + " Ok"), num);     // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
      }
    } return 1;                               
}
 
void eepromconfig() { /// === конфигурирование сигнализации === ///
   // pinMode(13, OUTPUT);
    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);   // PIRon       датчик движения вкл.
      EEPROM.update(6, 1);   // GASon       датчик газа вкл.
      EEPROM.update(7, 1);   // Sirena      сирена вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
    //  digitalWrite(13, HIGH);
  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);   // Датчик двери
      PIRon      = EEPROM.read(5);   // Датчик движения
      GASon      = EEPROM.read(6);   // Датчик газа/дыма
      Sirena     = EEPROM.read(7);   // сирена
      Firststart = EEPROM.read(10);  //
    }
}
 
void eepromtext() { /// === состояние системы === ///
   mySerial.println("AT+CSQ");
   TempC();
   delay(250);
   String SIGN = "";         // текущее состояние системы.
   String SIRENA = "";       // аварийная сирена.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
   if (Guard == 1) SIGN = String(F("System on\n")); else (SIGN = String(F("System off\n")));
   if (Sirena == 1) SIRENA = String(F("Sirena on\n")); else (SIRENA = String(F("Sirena off\n")));
   if (AlarmRING == 1) RING = String(F("Ring on\n")); else (RING = String(F("Ring off\n")));
   if (SendSMS == 1) SMS = String(F("SMS on\n")); else (SMS = String(F("SMS off\n")));
   if (PIRon == 1) Pir = String(F("Pir on\n")); else (Pir = String(F("Pir off\n")));
   if (DOORon == 1) Door = String(F("Door on\n")); else (Door = String(F("Door off\n")));
   if (GASon == 1) Gas = String(F("Gas on\n")); else (Gas = String(F("Gas off\n")));
    String System = SIGN + SIRENA + RING + SMS;     // состояние (вкл/выкл) системы.
    String Sensors = Pir + Door + Gas + temp;       // состояние (вкл/выкл) датчиков.
    LastEvent = System + Sensors + CSQ;             // полное состояние системы и датчиков.
  Serial.println(LastEvent);
}
 
void eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем мастер-номера 
      if (Phone != 0) AlarmPhone[i] = Phone;
  Serial.println(String(F("Phone[")) + i + String(F("]:")) + AlarmPhone[i]); 
    }
    EEPROM.get(100, Phone);                // считываем номер последнего звонившего
    RingPhone = Phone;
  Serial.println(String(F("Ring [ ]:")) + RingPhone);
    EEPROM.get(20, Bal);                   // считываем номер баланса
  Serial.println(String(F("Balance:")) + Bal);
    Firststart = EEPROM.read(10);          // cчитаем первый старт
  Serial.println(String(F("Firststart:")) + Firststart);
}
 
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();                                // 
    }
    if (DOORState == LOW && DOORFlag == 1) {
      int currentMillis_door = millis();
      if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
        DOORFlag = 0;
      }
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
  Serial.println(F("Dvizhenie u dveri!"));         // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
  Alarm();                                // 
    }
    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();                                // 
    }
    if ((Smoky < GASThres) && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) {
        GASFlag = 0; 
      }
    }
  }
}
 
void Timeled() { ///=== включаем свет и камеру === ///
  unsigned long curMil = millis();
   const long interal = 3600000;                // задаем время работы света и камеры желательно не менее цикла записи 3 минуты. >=200000 мс сейчас стоит 60 мин
  int8_t preMil = 0;
  if (Guard == 1 && PIRFlag == 1) {            //PIRFlag == 1 заменить на PIRState == HIGH  если будут проблемы со срабатыванием
   digitalWrite(INPIR, HIGH);
  }
  if ((curMil - preMil) >= interal) {
    preMil = curMil;
    digitalWrite(INPIR, LOW);
    }
    curMil = 0;
}
 
void Alarm() { /// === запускаем сирену и отправку смс === ///
  if (Guard == 1) {
    previousMillis_alarm = millis();
    if (Sirena == 1) digitalWrite(BUZ, HIGH);
    Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
      for (int i = 0; i < 5; i++) {           // if (AlarmPhone[i] != 0)  {
        if (DOORFlag == 1) {
sms(String("Dver' otkrita!"), AlarmPhone[i]); // смс на все номера     // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
        }
        if (PIRFlag == 1) {
sms(String("Dvizhenie y dveri!"), AlarmPhone[i]); // смс на все номера // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
        }
        if (GASFlag == 1) {
sms(String("Gas v dome!"), AlarmPhone[i]); // смс на все номера        // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
        }
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
  }
}
 
void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  int currentMillis_alarm = millis();
  if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) {
    digitalWrite(BUZ, LOW);
  } 
}
 
void MasterRing() { /// === мастер звонков === //
  if (Guard == 1) GuardOff();     // меняем состояние
  else if (Guard == 0) GuardOn(); // меняем состояние
}
 
void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->off. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                     // if (AlarmPhone[i] != 0)  {
sms(String("System->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
}
 
void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->on. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                    // if (AlarmPhone[i] != 0)  {
sms(String("System->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
}
 
void LED() { /// === состояние светодиода === ///
  if (Guard == 1) {                   // если на охране
  int currentMillis_led = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis_led - previousMillis_led > interval_led) {
      // сохраняем время последнего переключения
      previousMillis_led = currentMillis_led;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LedState == HIGH) LedState = LOW;
      else LedState = HIGH;
      digitalWrite(Led, LedState);
    }
  } else digitalWrite(Led, HIGH); // иначе гасим его
}
 
void ConsolePrint() { /// === консольная программа === ///
    val.toLowerCase();
  if (val.indexOf(F("reset")) > -1) {    // сброс ЕЕПРОМ
  Serial.println(F("Reset System!"));  
    EEPROM.write(0, 0);
  eepromconfig();
  }
  if (val.indexOf(F("master")) > -1) {   // добавление мастер-номера
    master(val.substring(6, 7).toInt(), val.substring(8, 19));
// sms типа: " master1:79111234567 " - номер в ячейку "1", куда записать номер
  }
  if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
    balnum(val.substring(8, 13));
// sms типа: " balance:100 " - номер баланса
  }
  if (val.indexOf(F("dell:")) > -1) {    // удаление номера из ячейки     
    dellphone(val.substring(5, 6).toInt());
// sms типа: " dell:1 " - удалить номер из ячейки 1
  }
  if (val.indexOf(F("phone")) > -1)     { // инфо о телефонах
  eepromphone();
  }
  if (val.indexOf(F("status")) > -1) {     // инфо о состоянии системы
  eepromconfig();
  eepromtext();
  }
  if (val.indexOf(F("info")) > -1)    {   // запрос системы
  Serial.println(Info1 + Info2 + Info3);  // 
  }
  if (val.indexOf(F("money")) > -1) {    // запрос баланса
  balance();
  }
  if (val.indexOf(F("sirenaon")) > -1) {
    EEPROM.update(7, 1);   // Sirena      сирена вкл.
  }
  if (val.indexOf(F("sirenaoff")) > -1) {
    EEPROM.update(7, 0);   // Sirena      сирена выкл.
  }
  if (val.indexOf(F("systemon")) > -1) {  // вкл сигнализации
  GuardOn();
  }
  if (val.indexOf(F("systemoff")) > -1) { // выкл сигнализации
  GuardOff();
  }
  if (val.indexOf(F("ringon")) > -1) {   // вкл вызов при сработке
    AlarmRING = 1;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring->on"));      
  }
  if (val.indexOf(F("ringoff")) > -1) {  // выкл вызов при сработке
    AlarmRING = 0;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring->off"));  
  }
  if (val.indexOf(F("smson")) > -1) {    // вкл смс при сработке
    SendSMS = 1;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS->on"));  
  }
  if (val.indexOf(F("smsoff")) > -1) {   // выкл смс при сработке
    SendSMS = 0;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS->off"));  
  }
  if (val.indexOf(F("dooron")) > -1) {  // выкл вызов при сработке
    DOORon = 1;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
  }
  if (val.indexOf(F("dooroff")) > -1) {  // выкл вызов при сработке
    DOORon = 0;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
  }
  if (val.indexOf(F("piron")) > -1) {  // выкл вызов при сработке
    PIRon = 1;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->on"));  
  }
  if (val.indexOf(F("piroff")) > -1) {  // выкл вызов при сработке
    PIRon = 0;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->off"));  
  }
  if (val.indexOf(F("gason")) > -1) {  // выкл вызов при сработке
    GASon = 1;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->on"));  
  }
  if (val.indexOf(F("gasoff")) > -1) {  // выкл вызов при сработке
    GASon = 0;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->off"));  
  }
}
 
void MasterSMS() { /// === мастер смс === ///
    val.toLowerCase();
  if (RingPhone == AlarmPhone[0]) {        // команды выполняются только с 0 мастер номера
    if (val.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
sms(String("All System Reset!!!"), RingPhone); // смс на последний номер
  Serial.println(F("Reset System!!!"));          
      EEPROM.write(0, 0);
  eepromconfig();
    }
    if ((p = val.indexOf(F("master"))) > -1)  { // добавление мастер-номера
      master(val.substring(p + 6, p + 7).toInt(), val.substring(p + 8, p + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
    }
    if ((p = val.indexOf(F("balance:"))) > -1) { // добавление номера баланса
      balnum(val.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
    } 
    if ((p = val.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки     
      dellphone(val.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } 
    if (val.indexOf(F("phone")) > -1)     { // инфо о состоянии системы
  eepromphone();
      for (int i = 0; i < 5 ; i++)  if (AlarmPhone[i] != 0) {
sms(String(String("Master") + i + String(":") + AlarmPhone[i]), RingPhone); // смс на последний номер
      }
    }
  }  
  if (val.indexOf(F("info")) > -1)    {   // запрос баланса
sms(Info1 + Info2 + Info3, RingPhone); // смс на последний номер
  }
  if (val.indexOf(F("status")) > -1) { // инфо о состоянии системы
  eepromconfig();
  eepromtext();
sms(String(LastEvent), RingPhone); // смс на последний номер
  }
  if (val.indexOf(F("money")) > -1)    {   // запрос баланса
  balance();
  }
  if (val.indexOf(F("sirenaon")) > -1) {
    EEPROM.update(7, 1);                   // сирена вкл.
  }
  if (val.indexOf(F("sirenaoff")) > -1) {
    EEPROM.update(7, 0);                   // сирена выкл.
  }
  if (val.indexOf(F("systemon")) > -1)  {  // вкл сигнализации
  GuardOn();
  }
  if (val.indexOf(F("systemoff")) > -1) {  // выкл сигнализации
  GuardOff();
  }
  for (int i = 0; i < 5 ; i++) if (AlarmPhone[i] != 0) { // смс на все номера          
    if (val.indexOf(F("ringon")) > -1)   { // вкл вызов при сработке
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->on"));      
sms(String("Ring->on " + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("ringoff")) > -1)  { // выкл вызов при сработке
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->off"));  
sms(String("Ring->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("smson")) > -1)    { // вкл смс при сработке
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->on"));  
sms(String("SMS->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("smsoff")) > -1)   { // выкл смс при сработке
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->off"));  
sms(String("SMS->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("dooron")) > -1) {  // выкл вызов при сработке
    DOORon = 1;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
sms(String("DOOR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("dooroff")) > -1) {  // выкл вызов при сработке
    DOORon = 0;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
sms(String("DOOR->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("piron")) > -1) {  // выкл вызов при сработке
    PIRon = 1;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->on"));  
sms(String("PIR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("piroff")) > -1) {  // выкл вызов при сработке
    PIRon = 0;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR -> off"));  
sms(String("PIR -> off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("gason")) > -1) {  // выкл вызов при сработке
    GASon = 1;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->on"));  
sms(String("GAS->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("gasoff")) > -1) {  // выкл вызов при сработке
    GASon = 0;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->off"));  
sms(String("GAS->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
  } 
}
 
void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(1000);
  mySerial.println(String(F("ATD#")) + Bal + String(F("#")));
  Serial.println(String("Balance#") + Bal + "#"); 
}
 
int master (int i, String num) { /// === добавление мастер-номеров === ///
    if (i < 5 && i != 0) {
      num.toCharArray(Phone, 12); // конвертируем
      AlarmPhone[i] = num;        // пишем номер  
  Serial.println(String(F("Master[")) + i + String(F("]:")) + num);
      EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
sms(String(String("Master") + i + ":" + num + " add"), RingPhone); // смс на 0 номер.
sms(String("Master: " + AlarmPhone[i]), AlarmPhone[i]); // смс на добавленный номер.
    } else Serial.println(F("MAX number 4!"));          // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
    return 1;                             
}                              
 
int dellphone (int i) { /// === удаление мастeр-номеров === ///
     if (i < 5 && i != 0) {
  Serial.println(String(F("Master")) + i + String(F(" dell")));
sms(String(String("Master") + i + ":" + AlarmPhone[i] + " dell"), RingPhone); // смс на 0 номер
sms(String("Dell: " + AlarmPhone[i]), AlarmPhone[i]); // смс на удаленный номер.
       EEPROM.put(Adress[i], 0);
       AlarmPhone[i] = "";   // обнулим номер
  } return 1;                          
}
 
int balnum (String num) { /// === добавляем номер баланса === ///
    num.toCharArray(Bal, 4);   // конвертируем
  Serial.println(String(F("Balance:")) + Bal);
    EEPROM.put(20, Bal);           // записываем массив в EEPROM 
sms(String("Balance:*" + num + "# Ok"), RingPhone); // смс на 0 номер
    return 1;                             
}
 
void TempC() {      /// === измеряем температуру === ///
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
  delay(750);
  ds.reset();
  ds.write(0xCC);
  ds.write(0xBE);
  data[0] = ds.read();
  data[1] = ds.read();
  int Temp = (data[1] << 8) + data[0];
  Temp = Temp >> 4;
  temp = String(F("Temp: ")) + Temp + String(F("*C\n"));
}
 
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() { /// === инициализация модема === ///
  Serial.println(F("Start GSM"));
  mySerial.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  waitRegistration();
  delay(1000); 
}
 
void waitConnect() { /// === запуск модема === ///
  int countok = 0;
  String str; 
  while(countok < 5) {                   //ждём пять ОК  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс 
      msAT = ms;
//      Serial.println(">>AT");
      mySerial.println(F("AT"));          // посылаем команду
      str = "";
      delay(100);                      // ждём ответа
      while(mySerial.available()) {
        char ch = mySerial.read();
        str += ch;
      } 
//      Serial.println("C>");
//      Serial.println(str);
      if(str.indexOf(F("OK")) > -1)
        countok++;
      else
        countok = 0;
    }
  }  
  Serial.println(F("Turn on AOH:"));
  mySerial.println(F("AT+CLIP=1"));  // включить АОН
  delay(200);
  Serial.println(F("GSM registration"));
  mySerial.println(F("AT+CMGF=1"));
  delay(200); 
  Serial.println(F("Mode GSM:"));
  mySerial.println(F("AT+CSCS=\"GSM\""));  // кодировка текста - GSM
  delay(300);
  mySerial.println(F("AT+CNMI=2,2,0,0,0"));
  delay(300); 
}
 
void waitRegistration() { /// === регистрация модема в сети === ///
  bool ok = 0;
  String str;
  while(!ok) {  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
      msAT = ms;
      Serial.println(F(">>AT+CREG?"));
      mySerial.println(F("AT+CREG?"));      //посылаем команду
      delay(100);                           //Ждём ответа
      str = "";
      while(mySerial.available()) {
           char ch = mySerial.read();
           str += ch;
      } 
      Serial.println(F("R>"));
      Serial.println(str);
      if(str.indexOf(F("+CREG:"))>-1)
        ok = 1;
    }
  }  
}
 
void sms(String text, String phone) { /// === отправка СМС === ///
  if (phone != 0) {
    phone = "+" + phone;
    Serial.println(F("Start SMS send")); 
    mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
    delay(300);
    mySerial.print(text);
    delay(300);
    mySerial.print((char)26);
    delay(300);
    Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
    delay(5000);
  }
}
renoshnik
Offline
Зарегистрирован: 11.04.2013

Два совета !

1 - вставьте правильно код !

2 - озвучьте размер бюджета "не бесплатной помощи" !

vvadim
Offline
Зарегистрирован: 23.05.2012

код большой.
ковыряться с ним вряд ли кто будет.

проще с нуля написать.

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

Ужасть.....купите готовое, это г....проще выкинуть, написать с нуля после полного описания что и когда должно делать устройство - от 8000 рублей + модем m590 и затраты на паяние макета для полноценного тестирования.

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

vvadim пишет:

код большой.
ковыряться с ним вряд ли кто будет.

проще с нуля написать.

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

И я сильно сомневаюсь. что все это влезет в Нано и после этого будет работать :)

ТС - не зря прошлые авторы забросили проект. Последуй хорошему примеру :)

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

и еще - мне всегда было интересн смысл этого СМС оповещения?

Вот лежишь ты дома в постели, а тебе в 4 часа ночи приходит СМС "Запах газа!"

Ваши действия? :))))

sadman41
Offline
Зарегистрирован: 19.10.2016

Надеваешь противогаз (за нормативное время) и ползёшь на выход.

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

sadman41 пишет:

Надеваешь противогаз (за нормативное время) и ползёшь на выход.

противогаз сразу одевать необязательно, СМС-ка с дачи пришла :)

Onkel
Offline
Зарегистрирован: 22.02.2016

У меня есть готовые системы, отдам по 10 тыр, уже в корпусе и с антенной.
http://ydom.ru/item.html?page=yGuardPro

alexBCN
Offline
Зарегистрирован: 01.07.2019

Джельтмены пишите на ватсап или в личку смету ориентировочную и свои контакты ..обсудим детали.. с Уважением.

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

Пишите подробное ТЗ, будем обсуждать

Andycat2013@yandex.ru

fridgetester
fridgetester аватар
Offline
Зарегистрирован: 09.02.2019

Могу доработать ваш скетч. Стоимость ориентировочно 6тр. fridgetester@mail.ru

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ТС, абьявляй конкурс. 

alexBCN
Offline
Зарегистрирован: 01.07.2019

а как проводят конкурсы ? какие правила и где? 

вставил прошивку ещо раз ..надеюсь теперь правильно  

цену  и  время исполнения  предлагайте свою, свяжусь с каждым и обсудим как мы это будем делать ?

и как вообще это делают ? так чтобы и заказчик и исполнитель остались довольны и не кто не кого не кинул ?

[code]


#include <EEPROM.h> 
#include <OneWire.h>
#include<SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);

OneWire ds(4);             // датчик температуры подключен к 4 пину, подтяжка 4.7кОм на +.
#define DOOR 6             // концевик двери.
#define PIR 9              // датчик движения.
#define INPIR 7            // выход для подачи напряжения на свет
#define Led 5              // состояние системы. моргает - на охране.
#define GAS A0             // датчик дыма.
#define BUZ 12             // сирена.

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

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

int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.   // датчик висит в воздухе программно. аппаратно на минус через 10k.
int8_t LedState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t Firststart;         // первый старт.
uint32_t msAT = 0;

char Bal[4] = "";          // для временного хранения номера баланса.   
char Phone[12];            // для временного хранения номера телефона. 
//(если размер номера более 12 цифр нужно поменять на нужное количество по факту определителя как его видно на дисплее +1 )   
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.

String val;                // переменная для хранения пришедших данных.   
String temp;               // переменная для хранения температуры.
String CSQ;                // переменная для хранения пришедших данных уровня сигнала.   
String LastEvent;          // полное состояние системы.
String RingPhone;          // номер звонившего.
String AlarmPhone[5];      // номера для постановки/снятии с охраны и отправки смс.
String Info1 = "Kommanda - deistvie:\nstatus - sostoyanie\nmoney - balance\n";  // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
String Info2 = "sirenaon/off\nsystemon/off\nringon/off\nsmson/off\n";           
String Info3 = "dooron/off\npiron/off\ngason/off";

int p = 0;
int GASThres = 400;           // предельная концентрация газа
int interval_alarm = 20;      // Секунд до отключения "тревожного" пина, max 300сек 
int previousMillis_alarm = 0;
int interval_led = 1000;      // для мигания Led
int previousMillis_led = 0;
int interval_door = 10;       // секунд не смотрим на датчик двери
int previousMillis_door = 0;
int interval_pir = 10;        // секунд не смотрим на датчик движения
int previousMillis_pir = 0;
int interval_gas = 60;        // секунд не смотрим на датчик газа
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 - PIRon = 1;       // датчик движения:    1 - вкл.
  6 - GASon = 1;       // датчик дыма:        1 - вкл.
  7 - Sirena = 1;      // сирена:             1 - вкл.
  10 - Firststars = 1;    // первый запуск       1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// === настройка программы === ///
  Serial.begin(9600); 
  Serial.println(F("GSMTruck4.7"));
  pinMode(DOOR, INPUT_PULLUP);        // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);                // вход датчика движения .  
  pinMode(INPIR, OUTPUT);             // определяем как выход      
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);
  pinMode(Led, OUTPUT);               // светодиод как выход.
    digitalWrite(BUZ, HIGH);          // сирена выкл.
    digitalWrite(PIR, LOW);           // отключаем внутренню подтяжку и вешаем сопротивлени 10k на GND для внешней подтяжки, чтобы не срабатывало на наводки
  InitModem();                        // запускаем инициализация модема.
  eepromconfig();
  eepromtext();
  eepromphone();
    digitalWrite(Led, HIGH);           // гасим светодиод состояния сигнализации. 
}                                   
void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    LED();          // моргаем светодиодом.
    Timeled();      // включаем свет и камеру при любом движении на заданное время.
  }
  if (mySerial.available()) {     // если GSM модем что-то послал.
    while (mySerial.available()) {  // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf(F("+CLIP")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      delay(2000);                             // дадим гудок
      mySerial.println(F("ATH"));              // сбрасываем вызов.
      if (CheckPhone() == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
      } else  Serial.println(F("No Master Ring!"));  
    } else if (val.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
  Serial.println(String(F("SMS->")) + val);    // что пришло в смс
        if (CheckPhone() == 1) {               // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  MasterSMS();
        } else  Serial.println(F("No Master SMS!"));
      } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
        int p1 = val.indexOf(F("\""));         // начало строки
        int p2 = val.lastIndexOf(F("\""));     // конец строки -  нужно поставить вместо "\""  значение "значение" которое приходит от оператора после суммы чтобы обрезать строку
        val = val.substring(p1+1,p2);
        Serial.println("");
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(val);
        String decodestr;
        Decode7bit(val, decodestr);
        Serial.println("");
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        Serial.println(decodestr);
sms(String("SIM " + decodestr), RingPhone);    // смс на последний звонивший
         } else if (val.indexOf(F("+CSQ:")) > -1) { // пришел уровень сигнала сети
          int x = val.indexOf("+CSQ:");
          CSQ = "Signal " + val.substring(x+5, x+7) + "%";
           } val = ""; 
  } if (Serial.available()) {           // если в мониторе порта что-то ввели
        while (Serial.available()) {         // сохраняем входную строку в переменную val.
        char ch = Serial.read();
        val += char(ch);                   // собираем принятые символы в строку
        delay(3);
        } 
  ConsolePrint();                        // запускаем консольную программу
        val = "";  
    }
}

int CheckPhone() { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (val.indexOf(AlarmPhone[i]) > -1) {    // && val.indexOf(AlarmPhone[i]) != 0) { // если есть вызов, и он наш
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 12);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      if (val.indexOf("+CLIP: \"7") > -1) {
      int ind = val.indexOf("+CLIP:") + 8;          // обрезаем номер 
      String num = val.substring(ind, ind + 11); 
      num.toCharArray(Phone, 12);
      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("Master0:")) + AlarmPhone[0]); 
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String("Master0:" + num + " Ok"), num);     // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
      }
    } return 1;                               
}

void eepromconfig() { /// === конфигурирование сигнализации === ///
   // pinMode(13, OUTPUT);
    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);   // PIRon       датчик движения вкл.
      EEPROM.update(6, 1);   // GASon       датчик газа вкл.
      EEPROM.update(7, 1);   // Sirena      сирена вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
    //  digitalWrite(13, HIGH);
  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);   // Датчик двери
      PIRon      = EEPROM.read(5);   // Датчик движения
      GASon      = EEPROM.read(6);   // Датчик газа/дыма
      Sirena     = EEPROM.read(7);   // сирена
      Firststart = EEPROM.read(10);  //
    }
}

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

void eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем мастер-номера 
      if (Phone != 0) AlarmPhone[i] = Phone;
  Serial.println(String(F("Phone[")) + i + String(F("]:")) + AlarmPhone[i]); 
    }
    EEPROM.get(100, Phone);                // считываем номер последнего звонившего
    RingPhone = Phone;
  Serial.println(String(F("Ring [ ]:")) + RingPhone);
    EEPROM.get(20, Bal);                   // считываем номер баланса
  Serial.println(String(F("Balance:")) + Bal);
    Firststart = EEPROM.read(10);          // cчитаем первый старт
  Serial.println(String(F("Firststart:")) + Firststart);
}

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();                                // 
    }
    if (DOORState == LOW && DOORFlag == 1) {
      int currentMillis_door = millis();
      if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
        DOORFlag = 0;
      }
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
  Serial.println(F("Dvizhenie u dveri!"));         // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
  Alarm();                                // 
    }
    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();                                // 
    }
    if ((Smoky < GASThres) && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) {
        GASFlag = 0; 
      }
    }
  }
}

void Timeled() { ///=== включаем свет и камеру === ///
  unsigned long curMil = millis();
   const long interal = 3600000;                // задаем время работы света и камеры желательно не менее цикла записи 3 минуты. >=200000 мс сейчас стоит 60 мин
  int8_t preMil = 0;
  if (Guard == 1 && PIRFlag == 1) {            //PIRFlag == 1 заменить на PIRState == HIGH  если будут проблемы со срабатыванием
   digitalWrite(INPIR, HIGH);
  }
  if ((curMil - preMil) >= interal) {
    preMil = curMil;
    digitalWrite(INPIR, LOW);
    }
    curMil = 0;
}

void Alarm() { /// === запускаем сирену и отправку смс === ///
  if (Guard == 1) {
    previousMillis_alarm = millis();
    if (Sirena == 1) digitalWrite(BUZ, HIGH);
    Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
      for (int i = 0; i < 5; i++) {           // if (AlarmPhone[i] != 0)  {
        if (DOORFlag == 1) {
sms(String("Dver' otkrita!"), AlarmPhone[i]); // смс на все номера     // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
        }
        if (PIRFlag == 1) {
sms(String("Dvizhenie y dveri!"), AlarmPhone[i]); // смс на все номера // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
        }
        if (GASFlag == 1) {
sms(String("Gas v dome!"), AlarmPhone[i]); // смс на все номера        // поменять на ИСПАНСКИЙ ЛАТИНИЦЕЙ
        }
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
  }
}

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

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

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->off. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                     // if (AlarmPhone[i] != 0)  {
sms(String("System->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
}

void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->on. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                    // if (AlarmPhone[i] != 0)  {
sms(String("System->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
}

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

void ConsolePrint() { /// === консольная программа === ///
    val.toLowerCase();
  if (val.indexOf(F("reset")) > -1) {    // сброс ЕЕПРОМ
  Serial.println(F("Reset System!"));  
    EEPROM.write(0, 0);
  eepromconfig();
  }
  if (val.indexOf(F("master")) > -1) {   // добавление мастер-номера
    master(val.substring(6, 7).toInt(), val.substring(8, 19));
// sms типа: " master1:79111234567 " - номер в ячейку "1", куда записать номер
  }
  if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
    balnum(val.substring(8, 13));
// sms типа: " balance:100 " - номер баланса
  }
  if (val.indexOf(F("dell:")) > -1) {    // удаление номера из ячейки     
    dellphone(val.substring(5, 6).toInt());
// sms типа: " dell:1 " - удалить номер из ячейки 1
  }
  if (val.indexOf(F("phone")) > -1)     { // инфо о телефонах
  eepromphone();
  }
  if (val.indexOf(F("status")) > -1) {     // инфо о состоянии системы
  eepromconfig();
  eepromtext();
  }
  if (val.indexOf(F("info")) > -1)    {   // запрос системы
  Serial.println(Info1 + Info2 + Info3);  // 
  }
  if (val.indexOf(F("money")) > -1) {    // запрос баланса
  balance();
  }
  if (val.indexOf(F("sirenaon")) > -1) {
    EEPROM.update(7, 1);   // Sirena      сирена вкл.
  }
  if (val.indexOf(F("sirenaoff")) > -1) {
    EEPROM.update(7, 0);   // Sirena      сирена выкл.
  }
  if (val.indexOf(F("systemon")) > -1) {  // вкл сигнализации
  GuardOn();
  }
  if (val.indexOf(F("systemoff")) > -1) { // выкл сигнализации
  GuardOff();
  }
  if (val.indexOf(F("ringon")) > -1) {   // вкл вызов при сработке
    AlarmRING = 1;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring->on"));      
  }
  if (val.indexOf(F("ringoff")) > -1) {  // выкл вызов при сработке
    AlarmRING = 0;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring->off"));  
  }
  if (val.indexOf(F("smson")) > -1) {    // вкл смс при сработке
    SendSMS = 1;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS->on"));  
  }
  if (val.indexOf(F("smsoff")) > -1) {   // выкл смс при сработке
    SendSMS = 0;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS->off"));  
  }
  if (val.indexOf(F("dooron")) > -1) {  // выкл вызов при сработке
    DOORon = 1;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
  }
  if (val.indexOf(F("dooroff")) > -1) {  // выкл вызов при сработке
    DOORon = 0;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
  }
  if (val.indexOf(F("piron")) > -1) {  // выкл вызов при сработке
    PIRon = 1;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->on"));  
  }
  if (val.indexOf(F("piroff")) > -1) {  // выкл вызов при сработке
    PIRon = 0;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->off"));  
  }
  if (val.indexOf(F("gason")) > -1) {  // выкл вызов при сработке
    GASon = 1;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->on"));  
  }
  if (val.indexOf(F("gasoff")) > -1) {  // выкл вызов при сработке
    GASon = 0;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->off"));  
  }
}

void MasterSMS() { /// === мастер смс === ///
    val.toLowerCase();
  if (RingPhone == AlarmPhone[0]) {        // команды выполняются только с 0 мастер номера
    if (val.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
sms(String("All System Reset!!!"), RingPhone); // смс на последний номер
  Serial.println(F("Reset System!!!"));          
      EEPROM.write(0, 0);
  eepromconfig();
    }
    if ((p = val.indexOf(F("master"))) > -1)  { // добавление мастер-номера
      master(val.substring(p + 6, p + 7).toInt(), val.substring(p + 8, p + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
    }
    if ((p = val.indexOf(F("balance:"))) > -1) { // добавление номера баланса
      balnum(val.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
    } 
    if ((p = val.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки     
      dellphone(val.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } 
    if (val.indexOf(F("phone")) > -1)     { // инфо о состоянии системы
  eepromphone();
      for (int i = 0; i < 5 ; i++)  if (AlarmPhone[i] != 0) {
sms(String(String("Master") + i + String(":") + AlarmPhone[i]), RingPhone); // смс на последний номер
      }
    }
  }  
  if (val.indexOf(F("info")) > -1)    {   // запрос баланса
sms(Info1 + Info2 + Info3, RingPhone); // смс на последний номер
  }
  if (val.indexOf(F("status")) > -1) { // инфо о состоянии системы
  eepromconfig();
  eepromtext();
sms(String(LastEvent), RingPhone); // смс на последний номер
  }
  if (val.indexOf(F("money")) > -1)    {   // запрос баланса
  balance();
  }
  if (val.indexOf(F("sirenaon")) > -1) {
    EEPROM.update(7, 1);                   // сирена вкл.
  }
  if (val.indexOf(F("sirenaoff")) > -1) {
    EEPROM.update(7, 0);                   // сирена выкл.
  }
  if (val.indexOf(F("systemon")) > -1)  {  // вкл сигнализации
  GuardOn();
  }
  if (val.indexOf(F("systemoff")) > -1) {  // выкл сигнализации
  GuardOff();
  }
  for (int i = 0; i < 5 ; i++) if (AlarmPhone[i] != 0) { // смс на все номера          
    if (val.indexOf(F("ringon")) > -1)   { // вкл вызов при сработке
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->on"));      
sms(String("Ring->on " + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("ringoff")) > -1)  { // выкл вызов при сработке
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->off"));  
sms(String("Ring->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("smson")) > -1)    { // вкл смс при сработке
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->on"));  
sms(String("SMS->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("smsoff")) > -1)   { // выкл смс при сработке
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->off"));  
sms(String("SMS->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("dooron")) > -1) {  // выкл вызов при сработке
    DOORon = 1;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
sms(String("DOOR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("dooroff")) > -1) {  // выкл вызов при сработке
    DOORon = 0;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
sms(String("DOOR->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("piron")) > -1) {  // выкл вызов при сработке
    PIRon = 1;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->on"));  
sms(String("PIR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("piroff")) > -1) {  // выкл вызов при сработке
    PIRon = 0;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR -> off"));  
sms(String("PIR -> off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("gason")) > -1) {  // выкл вызов при сработке
    GASon = 1;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->on"));  
sms(String("GAS->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("gasoff")) > -1) {  // выкл вызов при сработке
    GASon = 0;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->off"));  
sms(String("GAS->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
  } 
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(1000);
  mySerial.println(String(F("ATD#")) + Bal + String(F("#")));
  Serial.println(String("Balance#") + Bal + "#"); 
}

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

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

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

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

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() { /// === инициализация модема === ///
  Serial.println(F("Start GSM"));
  mySerial.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  waitRegistration();
  delay(1000); 
}

void waitConnect() { /// === запуск модема === ///
  int countok = 0;
  String str; 
  while(countok < 5) {                   //ждём пять ОК  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс 
      msAT = ms;
//      Serial.println(">>AT");
      mySerial.println(F("AT"));          // посылаем команду
      str = "";
      delay(100);                      // ждём ответа
      while(mySerial.available()) {
        char ch = mySerial.read();
        str += ch;
      } 
//      Serial.println("C>");
//      Serial.println(str);
      if(str.indexOf(F("OK")) > -1)
        countok++;
      else
        countok = 0;
    }
  }  
  Serial.println(F("Turn on AOH:"));
  mySerial.println(F("AT+CLIP=1"));  // включить АОН
  delay(200);
  Serial.println(F("GSM registration"));
  mySerial.println(F("AT+CMGF=1"));
  delay(200); 
  Serial.println(F("Mode GSM:"));
  mySerial.println(F("AT+CSCS=\"GSM\""));  // кодировка текста - GSM
  delay(300);
  mySerial.println(F("AT+CNMI=2,2,0,0,0"));
  delay(300); 
}

void waitRegistration() { /// === регистрация модема в сети === ///
  bool ok = 0;
  String str;
  while(!ok) {  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
      msAT = ms;
      Serial.println(F(">>AT+CREG?"));
      mySerial.println(F("AT+CREG?"));      //посылаем команду
      delay(100);                           //Ждём ответа
      str = "";
      while(mySerial.available()) {
           char ch = mySerial.read();
           str += ch;
      } 
      Serial.println(F("R>"));
      Serial.println(str);
      if(str.indexOf(F("+CREG:"))>-1)
        ok = 1;
    }
  }  
}

void sms(String text, String phone) { /// === отправка СМС === ///
  if (phone != 0) {
    phone = "+" + phone;
    Serial.println(F("Start SMS send")); 
    mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
    delay(300);
    mySerial.print(text);
    delay(300);
    mySerial.print((char)26);
    delay(300);
    Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
    delay(5000);
  }
}
[/code]

 

alexBCN
Offline
Зарегистрирован: 01.07.2019

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

info - меню помощи с командами в виде смс

Kommanda - deistvie:
status - sostoyanie
money - запрос баланса
 
status -информация о состоянии системы.
 
так же есть  косяк  .. 
после включения питания сирена пиликает секунд 5-6 
после systemon (или звонка на номер) сирена пиликает 25 секунд и выходит на режим охраны 
 
но  попозадумке сирена при актитивации  или подачи питания орать не   не должна 
 
я игрался с прошивкой менял скорости для м590  но  так на отстук по смс и не получилось настроить 

 

 

SMS команды управления:
 
reset - сброс на заводские (стираются все телл номера, номер баланса и сброс настроек).
 
master - добавление мастер номеров, имеет право добавить только мастер номер 0.
 
           мастер номер 0 - первый позвонивший на сигнализацию.
 
           пример:    master1:79111234567    сохранить мастер номер 79111234567 в ячейку 1.
 
balance - номер баланса симкарты, имеет право добавить только мастер номер 0.
 
          пример:    balance:100    номер баланса *100#.
 
dell - удаление мастер номеров, кроме 0, имеет право добавить только мастер номер 0.
 
         пример: dell:2   удалить номер в ячейке 2.
 
info - меню помощи с командами в виде смс
Kommanda - deistvie:
status - sostoyanie
money - запрос баланса
 
status -информация о состоянии системы.
приходит смс такого вида:
System->off
Ring->on
SMS->on
Pir->on
Door->on
Gas->on
Sirena->10sec
Temp: 25*C.
 
phone - информация о прописанных мастер номерах.
Master0:79111112345
Master1:79112645327
 
sirena - время сирены при сработке 
 
         пример:   sirena:60    время звучания сирены 1мин
 
money - проверка баланса SIM
 
SIM Balance 100
 
systemon / systemoff - вкл/выкл сигнализации.
 
ringon / ringoff - вкл/выкл вызова при сработке сигнализации.
 
smson / smsoff - вкл/выкл смс информирования при сработке сигнализации, инфо смс доступны.
 
dooron / dooroff - вкл/выкл контроля датчика двери.
 
piron / piroff - вкл/выкл контроля датчика движения.
 
gason / gasoff - вкл/выкл контроля датчика дыма/газа.
alexBCN
Offline
Зарегистрирован: 01.07.2019

ТЗ  наверно такое  

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

на телефоный номер или группу номеров приходило сообщение о взломе или пожаре плюс включалась сирена и  светодиоды типа фар 

так же по смс запросу система отстукивала о своем статусе  включена она или не включена и состояние датчиков 

постановка на охрану и снятие по звонку и по смс 

тоесть все примерно как уже реализовано 

НО ещо  не мешало бы дописать если это возможно примерно такую функцию при не долгом срабатывании  датчика  или датчиков движения 

скажем менее 10 секунд

сирена орала не долго  скажем секунд 5  но без отсылки смс о тревоге

а если датчик движения постоянно  регистрирует двжижение скажем более 10 секунд  (или многократно и часто )

смысл чтобы не было лишних фальш срабатываний  от того что кто то рядом прошел  

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

статусе  с текстом типа alarm on  / alarm off 

можете написать свою прошивку можете доработать имеющуюся ..это без разницы 

имеющяся прошивка залазит в ардуино нано 3.0  (где то около 87% занимая память)

 

 

+  

1 версия прошивки  это под работу датчиков движения   пирометрического датчика + емкосного + газового и температурного

2 версия это  под работу датчика движения   микроволнового  датчика  точно такого как по ссылке в первом посте + газового и температурного)

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

и подсказать куда и как подпаять версию на микроволновом датчике

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

электронную схемы системы буду скидывать уже в привате 

и ещо говорят м590 глючный и его уже сняли с производства . может быть имеет смысл поменять на другой чип если это целесообразно ?

ну вот вроде бы ничего не забыл в ТЗ надеюсь что составил его понятно, если будут вопросы задавайте  уточним

жаль что на форуме нет лички   поэтому  скину мой емайл  rap1db0xer@gmail.com  

alexBCN
Offline
Зарегистрирован: 01.07.2019

заказчик предлогает  оплату заказа оформить все через платформу типа  freelance.ru  или подобное   когда деньги за заказ переводятся  платформе посреднику  и до выполения заказа замораживаются  на счету этой платформы посредника

вы можете предложить другую платформу но он настаивает на оплате после того как работа была выполнена 

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

alexBCN пишет:

вы можете предложить другую платформу но он настаивает на оплате после того как работа была выполнена 

 это +50% к цене

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

дак и надо искать исполнителя тогда на freelance.ru

sadman41
Offline
Зарегистрирован: 19.10.2016

Тут одних переговоров тыщи на три ))

fridgetester
fridgetester аватар
Offline
Зарегистрирован: 09.02.2019

ТС получается посредник, фриланс тож посредник и комсу берет насколько мне известно. Цепочка достойная госзакупок выходит. Удачи.

alexBCN
Offline
Зарегистрирован: 01.07.2019

TC скажем так  будет все это на месте собирать спаивать и отлаживать по сути 

а  платит за все   заказчик    который и есть конечный бенефециар системы если ее довести до ума 

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

alexBCN пишет:

TC скажем так  будет все это на месте собирать спаивать и отлаживать по сути 

а  платит за все   заказчик    который и есть конечный бенефециар системы если ее довести до ума 

вы бы ему дали почитать эту ветку :)

Пишу специально для него - сама идея бредовая, платить за нее смешно. Купите готовое .

alexBCN
Offline
Зарегистрирован: 01.07.2019

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

чем лишние 50%  

называйте сумму ,примерные сроки, уточняйте ТЗ или предлогайте внести в ТЗ  коррективы 

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

прошивки 

на данный момент собраны две платы одна мной другая самим разработчиком  обе ведут себя на этой прошивке одинаково  

кроме того что добавить емкосной датчик в схему ИЛИ заменить пирометрический  микроволновым + рабочая прошивка 

более по сути проблем  которые мы не сможем решить на месте не наблюдаю 

alexBCN
Offline
Зарегистрирован: 01.07.2019

так заказчик и  почитывает ветку  )  

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

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

sadman41
Offline
Зарегистрирован: 19.10.2016

МКВ-датчик будет обнаруживать всех котов в округе - хоть в мешке, хоть без.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

видима, разрабоччиком был карамзин.  

rst
Offline
Зарегистрирован: 25.06.2018

DetSimen пишет:
видима, разрабоччиком был карамзин.

Тут есть и другие умельцы слиться втихую  ;)

alexBCN
Offline
Зарегистрирован: 01.07.2019

я тоже о котах думал в радиусе ..    но заказчик говорил что котов и собак с голубями  там нет, в чем я лично сомневаюсь 

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

и просто на микроволновом и проверит в реальных условиях что лутче ... 

хотя  я все равно  не верю что там не залетит какой нибуть воробей или не пробежит ящерица или крыса  не на делает ложных срабатываний 

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

микроволновый так не надуеш насколько я понимаю ..          думаю все же   надо сразу делать проэкт  на одном  микроволновом    

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

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

Тупой платит трижды. 

alexBCN
Offline
Зарегистрирован: 01.07.2019

есть такое дело  ..  сыр  только в мышеловке  дешовый  .

вношу коррективы в ТЗ 

вообщем да таки надо собирать только 1 версию на микроволновом    

пиродатчик слишком легко надуть  и не возможно в той зоне прикрыть ничем 

от ложных срабатываний  микроволновый прикрыть алгоритмом 

 

1 если кот   проходит рядом  пищим и светим 3 секунды   без отсыла смс 

2 если кот или жулик почему то задержался в охраняемой зоне более 20 секунд   то идет смс  оповещение  

орем сиреной и светим лампочками пока обьект не уйдет и продолжаем светить и орать ещо минуты 2 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

делать по такому ТЗ сигналку - проще и дешевле купить у китайцев муляж имперского штурмового лазера, перемещающегося на движение.  И по утрам собирать навоз по периметру. 

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

alexBCN  , одно только уточнение по Вашему "ТЗ" займет несколько дней, посчитайте для примера свою рабочую неделю в рублях  - Вы готовы оплачивать все это?

ЗЫ. Скучный / не интересный проект.

P.P.S. Вот вам свеженький пример (сигнализацией язык не поворачивается назвать) СМС информера о произошедшем событии, без задержек delay в основном цикле и без Software Serial, добавьте туда побольше датчиков и будет вам счастье.

#include <avr/wdt.h>
#include <avr\pgmspace.h>
#include <EEPROM.h>

char phoneMain[] = "7920*******"; // admin phone
const char at21cmd[] PROGMEM = "AT+CUSD=1,*100#,15\r\n"; // USSD string get balance

#define DOOR_CONTROL
#define EXT_POW_CONTROL
#define USE_DS18B20

#ifdef EXT_POW_CONTROL
#define ext_pow_pin (byte)5 // 2 <--> 5 test
#define READEXTPOW digitalRead(ext_pow_pin)
#define delaySMSpowerOFF 120000UL // задержка 2 минут отправки СМС при отключении питания
#define delaySMSpowerON 120000UL // задержка 2 минут отправки СМС при включении питания
unsigned long timer_power_on_off;
byte startPowerTimer;
byte lastPower220;
#endif

#ifdef DOOR_CONTROL
#define key_pin (byte)2 // 5 <--> 2 test
#define READKEY !digitalRead(key_pin)
#define delay_alarm_door 600000UL
unsigned long timer_alarm_door = 0;
byte flsend_alarm_door;
#endif

#ifdef USE_DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>
#define TEMPERATURE_PRECISION 9 // точность получения значения темературы
#define ds18_pin A0 // pin DS18B20
OneWire oneWire(ds18_pin); // объект 1Ware
DallasTemperature sensors(&oneWire); // объект  датчика температуты
byte dsCount; // количество датчиков температуры
#define max_ds_count 5 // максимальное количество датчиков
DeviceAddress massTherm[max_ds_count]; // массив адресов датчиков ds18b20
#define period_get_temp 780137UL // получение температуры каждые 13 min
unsigned long timer_get_temp; // таймер получения температуры
word massTemper[max_ds_count]; //массив температур
byte requestTemp = 1; // запрос температуры
#endif

#define bLedOn HIGH
#define led1_pin (byte)9 // status led
#define LED1ON digitalWrite(led1_pin,bLedOn)
#define LED1OFF digitalWrite(led1_pin,!bLedOn)
#define led2_pin  (byte)4 // error led
#define LED2ON digitalWrite(led2_pin,bLedOn)
#define LED2OFF digitalWrite(led2_pin,!bLedOn)
#define reset_A6_pin (byte)7
#define power_A6_pin (byte)8

#define count_ext_commands 4 // count external commands from incoming sms

byte deviceMode = 1; // 1 = сигнализация включена

byte flGetBalance;

byte FirstStart;

#define period_wait_phone 30000UL // ждем 30 секунд после инициализации модема звонка чтоб записать админский номер
unsigned long timer_wait_phone;
byte flag_wait_phone;
#define pos_eeprom_flag_saved_admin_phone 67 // value 139 - exist phone
#define pos_eeprom_admin_phone 76

unsigned long timer_reg_modem; // timer registration modem in net
#define max_size_pgm_buf 128
char pgm_buf[max_size_pgm_buf];
#define period_read_sms 29971UL // read sms every ~30 sec
unsigned long timer_read_sms = 0; // timer read sms
#define period_send_sms 8937UL // send sms every ~9 sec
unsigned long timer_send_sms = 0; // timer read sms

#define max_size_fixed_resp 16 // in work save 3 response from buf commands
char resp1[max_size_fixed_resp]; char resp2[max_size_fixed_resp]; char resp3[max_size_fixed_resp]; // 3 parts response
byte flresp1, flresp2, flresp3; // found parts of response
#define max_size_sms_buf 110 // max size sms with stop byte and text uptime
char sms_buf[max_size_sms_buf]; // sms buf
char sender[13]; // phone number for send sms. +7 and 10 digits + stop byte = always 13 digits!!!
#define max_size_resp_buf 254 // max size response buf from modem, then more than goodest
char resp_buf[max_size_resp_buf]; // response buf from modem
byte pos_buf; // current pos response buf

byte ledStatus, ledError, flLedSt, flLedEr;
// ledError
// 0 - normal work, modem status 101, 1 flash per 3 sec
// 1 - init modem status 100, 1 flash per 1 sec
// 2 - problem modem, no response, flash everu 20 milli sec,reset modem and new start
// ledStatus
// number flash per 3 sec = number modem step < 100
unsigned long timer_led_status, timer_led_error;


byte modem_step; // current work mode mode in table of command
// static steps:
// 100 - delay for registration modem in net
// 101 - not wait response, wait incomming call or other commands

byte wait_response; // 0-no wait response, wait ring or other command
// 1-wait fixed response, if time more - reset modem
#define period_fixed_wait 15000UL // max time for type 1 wait response
// 2-wait response data or wait action user, if time more - clear command
#define period_data_wait 15000UL // max time for type 2 wait response

unsigned long current_millis;

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((used)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}

void setup() {
  MCUSR = 0; wdt_disable();
  Serial.begin(9600); // modem speed
  // read mainPhone from EEPROM
  if ((EEPROM.read(pos_eeprom_flag_saved_admin_phone) == 139)) {
    for (byte i = 0; i < 11; ++i) phoneMain[i] = EEPROM.read(pos_eeprom_admin_phone + i);
    phoneMain[11] = 0;
  }
#ifdef USE_DS18B20
  sensors.begin(); // инициировать датчики температуры
  dsCount = sensors.getDeviceCount(); // получить количество датчиков
  if (dsCount > max_ds_count) dsCount = max_ds_count; // если датчиков больше чем максимальное - уменьшаем
  oneWire.reset_search(); // сброс шины поиска датчиков
  byte i = 0; while (i < dsCount) { // цикл по всем датчикам
    if (sensors.getAddress(massTherm[i], i)) sensors.setResolution(massTherm[i], TEMPERATURE_PRECISION); ++i;
  }
#endif
  // put your setup code here, to run once:
  initAll();
  wdt_enable(WDTO_8S);
}

void loop() {
  wdt_reset(); //delay(9000); // test WDT
  current_millis = millis();
  // put your main code here, to run repeatedly:
  flashLed();
  // read sms
  if (((current_millis - timer_read_sms) >= period_read_sms) && (wait_response == 0) && (modem_step == 101)) {
    timer_read_sms = current_millis; // reset timer read sms
    // set mode read sms
    modem_step = 9;
  }
  // send sms
  if (((current_millis - timer_send_sms) >= period_send_sms) && (wait_response == 0) && (modem_step == 101) && (sender[0] > 0) && (sms_buf[0] > 0)) {
    timer_send_sms = current_millis; // reset timer send sms
    // send sms
    modem_step = 11;
  }
  // door control
#ifdef DOOR_CONTROL
  if ((READKEY) && (deviceMode)) {
    if ((!flsend_alarm_door) && (modem_step != 100)) {
      flsend_alarm_door = 1; sendSMS(phoneMain, (char*) "Alarm! Door opened! ");
      timer_alarm_door = current_millis;
    }
  }
  if (flsend_alarm_door) if ((current_millis - timer_alarm_door) >= delay_alarm_door) flsend_alarm_door = 0;
#endif
  // external power control
#ifdef EXT_POW_CONTROL
  // power 220V control
  if (startPowerTimer) {
    byte currentPower = READEXTPOW;
    if (lastPower220) {
      if (!currentPower) {
        startPowerTimer = 0; lastPower220 = currentPower;
      } else {
        if ((current_millis - timer_power_on_off) >= delaySMSpowerON) {
          startPowerTimer = 0; sendSMS(phoneMain, (char *) "Power AC220 ON ");
        }
      }
    } else {
      if (currentPower) {
        startPowerTimer = 0; lastPower220 = currentPower;
      } else {
        if ((current_millis - timer_power_on_off) >= delaySMSpowerOFF) {
          startPowerTimer = 0; sendSMS(phoneMain, (char *) "Alarm! Power AC220 OFF ");
        }
      }
    }
  } else {
    if (READEXTPOW != lastPower220) {
      startPowerTimer = 1; timer_power_on_off = current_millis; lastPower220 = READEXTPOW;
    }
  }
#endif
  // get balance
  if ((wait_response == 0) && (modem_step == 101) && (flGetBalance)) {
    flGetBalance = 0; modem_step = 21;
  }
#ifdef USE_DS18B20
  if (((current_millis - timer_get_temp) >= period_get_temp) && (wait_response == 0) && (modem_step == 101)) {
    if (requestTemp) {
      sensors.requestTemperatures(); requestTemp = 0;
    } else if ((current_millis - timer_get_temp) >= (period_get_temp + 200UL)) { // for 9 bit PRECISION
      timer_get_temp = current_millis; requestTemp = 1;
      byte i = 0; while (i < dsCount) {
        float tct = sensors.getTempC(massTherm[i]);
        if (tct < 0) massTemper[i] = ((-tct) * 10) + 2000; else massTemper[i] = (tct * 10);
        ++i;
      }
    }
  }
#endif
  // modem work
  loadDataFromModem(); // load data
  mainLoopModem(); // main actions on modem
}

void initAll() {
#ifdef DOOR_CONTROL
  pinMode(key_pin, INPUT_PULLUP);
  flsend_alarm_door = 0;
#endif
#ifdef EXT_POW_CONTROL
  pinMode(ext_pow_pin, INPUT_PULLUP);
  lastPower220 = READEXTPOW; startPowerTimer = 0;
#endif
  pinMode(led1_pin, OUTPUT); LED1OFF;
  pinMode(led2_pin, OUTPUT); LED2OFF;
  pinMode(reset_A6_pin, OUTPUT); pinMode(power_A6_pin, OUTPUT);
  initModem();
  ledError = 1; // 1 = modem status 100
  deviceMode = 1;
}

void initModem() {
  digitalWrite(reset_A6_pin, LOW);
  digitalWrite(power_A6_pin, HIGH);
  while ((millis() - current_millis) <= 3200UL) {
    Serial.print("AT\r\n"); delay(100);
  }
  modem_step = 100; // first step = wait modem for registration on net
  wait_response = 0; // no wait response
  sms_buf[0] = 0; // clear sms
  sender[0] = 0; // clear sender
  timer_reg_modem = millis(); pos_buf = 0;
  resp_buf[pos_buf] = 0; ledStatus = 0;
  flGetBalance = 0; flag_wait_phone = 0; FirstStart = 1;
}

void resetModem() {
  ledError = 2;
  digitalWrite(reset_A6_pin, HIGH); delay(500);
  initModem();
}

void flashLed() {
  // led1 - led status
  if ((ledStatus > 0) && (ledStatus <= 15)) {
    if ((current_millis - timer_led_status) >= (3000UL + (250UL * flLedSt))) {
      if (flLedSt >= (ledStatus * 2)) {
        LED1OFF; flLedSt = 0; timer_led_status = current_millis;
      } else {
        if (bitRead(flLedSt, 0)) LED1OFF; else LED1ON; ++flLedSt;
      }
    }
  } else {
    LED1OFF;
  }
  // led2 - led error
  switch (ledError) {
    case 1: {
        if ((current_millis - timer_led_error) >= 1000UL) {
          if (flLedEr) {
            if ((current_millis - timer_led_error) >= 1050UL) {
              timer_led_error = current_millis; LED2OFF; flLedEr = 0;
            }
          } else {
            LED2ON; flLedEr = 1;
          }
        }
        break;
      }
    case 2: {
        if ((current_millis - timer_led_error) >= 50UL) {
          if (flLedEr) {
            if ((current_millis - timer_led_error) >= 100UL) {
              timer_led_error = current_millis; LED2OFF; flLedEr = 0;
            }
          } else {
            LED2ON; flLedEr = 1;
          }
        }
        break;
      }
    default: {
        if ((current_millis - timer_led_error) >= 3000UL) {
          if (flLedEr) {
            if ((current_millis - timer_led_error) >= 3050UL) {
              timer_led_error = current_millis; LED2OFF; flLedEr = 0;
            }
          } else {
            LED2ON; flLedEr = 1;
          }
        }
      }
  }
}

const char at0cmd[] PROGMEM = "AT\r\n"; //          0
const char at1cmd[] PROGMEM = "AT+DDET=1\r\n";
const char at2cmd[] PROGMEM = "ATE0\r\n"; //        1
const char at3cmd[] PROGMEM = "AT+CLIP=1\r\n"; //   3
const char at4cmd[] PROGMEM = "ATS0=5\r\n"; //      4
const char at5cmd[] PROGMEM = "ATV1\r\n"; //        2
const char at6cmd[] PROGMEM = "AT+CMEE=2\r\n";
const char at7cmd[] PROGMEM = "AT+CMGF=1\r\n"; //   6
const char at8cmd[] PROGMEM = "AT+CREG?\r\n"; const char at8resp1[] PROGMEM = "+CREG:"; const char at8resp2[] PROGMEM = ",1"; //   5
const char at9cmd[] PROGMEM = "AT+CMGL=\"ALL\"\r\n";
const char at10cmd[] PROGMEM = "AT+CMGD=1,4\r\n"; //   7
const char at11cmd[] PROGMEM = "AT+CMGS=\"";
const char at12cmd[] PROGMEM = "~sender~";
const char at13cmd[] PROGMEM = "\r\n"; const char at13resp1[] PROGMEM = ">";
const char at14cmd[] PROGMEM = "~textsms~";
const char at15cmd[] PROGMEM = "~ctrlz~"; const char at15resp1[] PROGMEM = "+CMGS:";
const char at16cmd[] PROGMEM = "ATA\r\n"; const char at16resp2[] PROGMEM = "NO CARRIER";
const char at17cmd[] PROGMEM = "ATH\r\n";
const char at18cmd[] PROGMEM = "\"";
const char at19cmd[] PROGMEM = "AT+CSQ\r\n"; const char at19resp1[] PROGMEM = "+CSQ:"; const char at19resp2[] PROGMEM = ",";
const char at20cmd[] PROGMEM = "AT+GSN\r\n"; // get imei
const char atOKcmd[] PROGMEM = "OK";
const char atOKRNcmd[] PROGMEM = "OK\r\n";
const char atNULLcmd[] PROGMEM = "";
const char at1status[] PROGMEM = "1";
const char at2status[] PROGMEM = "2";
const char at1step[] PROGMEM = "1"; const char at2step[] PROGMEM = "2"; const char at3step[] PROGMEM = "3"; const char at4step[] PROGMEM = "4";
const char at5step[] PROGMEM = "5"; const char at6step[] PROGMEM = "6"; const char at7step[] PROGMEM = "7"; const char at8step[] PROGMEM = "8";
const char at9step[] PROGMEM = "9"; const char at10step[] PROGMEM = "10"; const char at11step[] PROGMEM = "11"; const char at12step[] PROGMEM = "12";
const char at13step[] PROGMEM = "13"; const char at14step[] PROGMEM = "14"; const char at15step[] PROGMEM = "15"; const char at16step[] PROGMEM = "16";
const char at17step[] PROGMEM = "17"; const char at18step[] PROGMEM = "18"; const char at19step[] PROGMEM = "19"; const char at101step[] PROGMEM = "101";
const char at20step[] PROGMEM = "20";
const char at21resp1[] PROGMEM = "+CUSD: 2,"; const char at21resp2[] PROGMEM = ",72\r\n";

const char * const str_at[] PROGMEM = { // record of AT commands
  at0cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at2step,
  at1cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at2step,
  at2cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at3step,
  at3cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at4step,
  at4cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at5step,
  at5cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at7step,
  at6cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at7step,
  at7cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at8step,
  at8cmd, at8resp1, at8resp2, atOKcmd, at1status, at20step,
  at9cmd, atOKRNcmd, atNULLcmd, atNULLcmd, at1status, at101step,
  at10cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at101step,
  at11cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at12step,
  at12cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at18step,
  at13cmd, at13resp1, atNULLcmd, atNULLcmd, at1status, at14step,
  at14cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at15step,
  at15cmd, at15resp1, atOKcmd, atNULLcmd, at1status, at101step,
  at16cmd, atOKRNcmd, at16resp2, atNULLcmd, at2status, at101step,
  at17cmd, atOKRNcmd, atNULLcmd, atNULLcmd, at1status, at101step,
  at18cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at13step,
  at19cmd, at19resp1, at19resp2, atOKcmd, at1status, at101step,
  at20cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at10step, // get imei and go to 10 cmd - last cmd for init - delete sms
  at21cmd, atOKRNcmd, at21resp1, at21resp2, at1status, at101step
};

void getPgmBuf(byte idxPgmBuf) {
  const char * addrStroki = pgm_read_word_near((int)(str_at + idxPgmBuf));
  strcpy_P(pgm_buf, addrStroki);
}

void loadDataFromModem() { // load data from modem to buf - only one line (string)
  if (Serial.available()) {
    byte br;
    while (Serial.available()) {
      br = Serial.read();
      if (br) {
        if (pos_buf >= (max_size_resp_buf - 1)) pos_buf = 0;
        resp_buf[pos_buf] = br; ++pos_buf;
        if (br == '\n') if ((pos_buf > 1) && (resp_buf[pos_buf - 2] == '\r')) break; // new string*/
      }
    }
    resp_buf[pos_buf] = 0; // stop byte of string
  }
}

void mainLoopModem() { // main action modem
  switch (modem_step) {
    case 100: {
        if ((current_millis - timer_reg_modem) >= 20000UL) { // wait 20sec registration modem
          wait_response = 0; // do not response
          modem_step = 0; // go to init modem mode - first command
        }
        break;
      }
    case 101: {
        ledError = 0; ledStatus = 0;
        if (FirstStart) {
          FirstStart = 0;
          flag_wait_phone = 1;
          timer_wait_phone = current_millis;
        }
        if (pos_buf == 0) break; // no response
        // find ring and other commands and execute
        if (flag_wait_phone) {
          if ((current_millis - timer_wait_phone) < period_wait_phone) {
            byte pb1 = posSubStrFromPos(resp_buf, pos_buf, (char *) "+CLIP: \"79", 0);
            char testPhone[12];
            if ((pb1) && (pos_buf > (pb1 + 20))) {
              // save to EEPROM
              EEPROM.write(pos_eeprom_flag_saved_admin_phone, 139);
              for (byte i = 0; i < 11; ++i) {
                byte bc = resp_buf[i + pb1 + 7];
                phoneMain[i] = bc; EEPROM.write(pos_eeprom_admin_phone + i, bc);
              }
              phoneMain[11] = 0; EEPROM.write(pos_eeprom_admin_phone + 11, 0);
              flag_wait_phone = 0;
              wait_response = 0;
              modem_step = 17; // answer on ring 16 or break ring 17
              break;
            }
          } else {
            flag_wait_phone = 0;
          }
        }
        // other find
        break;
      }
    default: {
        switch (wait_response) {
          case 0: {
              sendAtCommand(modem_step); // send command to modem
              break;
            }
          case 1: {
              if ((current_millis - timer_reg_modem) >= period_fixed_wait) { // if end timer wait response
                resetModem(); // we have problem - no correct response from modem
              } else {
                if (pos_buf == 0) break; // no response
                // action before find response, example long ussd
                if (findRespParts() == 1) { // need fixed response
                  // good response from modem
                  // other action on one item command
                  switch (modem_step) {
                    case 15: { // end send sms
                        sender[0] = 0; sms_buf[0] = 0; // clear sms buf
                        // go to next step
                        wait_response = 0; // do not wait response
                        getPgmBuf(6 * modem_step + 5);
                        modem_step = strToByte(pgm_buf); // to next at command or mode
                        break;
                      }
                    case 9: { // read all sms
                        // find command from sms
                        if (posSubStrFromPos(resp_buf, pos_buf, (char*) "+CMGL: ", 0) > 0) { // we have sms
                          int sbeg = 0;
                          int spos;
lsms1: if (sbeg < pos_buf) {
                            spos = posSubStrFromPos(resp_buf, pos_buf, (char*) "+CMGL: ", sbeg);
                            if (spos > 0) {
                              spos += 7;
                              if (spos < pos_buf) {
                                spos = posSubStrFromPos(resp_buf, pos_buf, phoneMain, spos);
                                if (spos > 0) {
                                  spos += 7;
                                  spos = posSubStrFromPos(resp_buf, pos_buf, (char*) "\r\n", spos);
                                  if (spos > 0) {
                                    ++spos; // begin text sms
                                    byte ends = posSubStrFromPos(resp_buf, pos_buf, (char*) "\r\n", spos); // end text sms
                                    if (ends > 0) {
                                      for (byte i = 0; i < count_ext_commands; ++i) {
                                        getExtBuf(i);
                                        if (posSubStrFromPos(resp_buf, ends, pgm_buf, spos) > 0) {
                                          execExtCmd(i);
                                          break;
                                        }
                                      }
                                      sbeg = ends;
                                      goto lsms1;
                                    }
                                  }
                                }
                              }
                            }
                          }
                          // go to step delete SMS
                          wait_response = 0; // do not wait response
                          modem_step = 10; // step 10
                        } else {
                          // go to next step
                          wait_response = 0; // do not wait response
                          getPgmBuf(6 * modem_step + 5);
                          modem_step = strToByte(pgm_buf); // to next at command or mode
                        }
                        break;
                      }
                    default: {
                        // go to next step
                        wait_response = 0; // do not wait response
                        getPgmBuf(6 * modem_step + 5);
                        modem_step = strToByte(pgm_buf); // to next at command or mode
                      }
                  }
                }
              }
              break;
            }
          case 2: {
              if ((current_millis - timer_reg_modem) >= period_data_wait) { // if end timer wait response
                // no data or no user action
                // exit from command
                // go to next step
                wait_response = 0; // do not wait response
                getPgmBuf(6 * modem_step + 5);
                modem_step = strToByte(pgm_buf); // to next at command or mode
              } else {
                if (pos_buf == 0) break; // no response
                // read parts of sms or other commands or DTMF
                // go to next step after actions
                wait_response = 0; // do not wait response
                getPgmBuf(6 * modem_step + 5);
                modem_step = strToByte(pgm_buf); // to next at command or mode
              }
              break;
            }
          default: {
              // go to next step after actions
              wait_response = 0; // do not wait response
              getPgmBuf(6 * modem_step + 5);
              modem_step = strToByte(pgm_buf); // to next at command or mode
            }
        }
      }
  }
}

int strPos(char *str11, char *str22) { // find position substring in string
  char*p = LastPos(str11, str22);
  int n = p - str11;
  return n;
}

char* LastPos(char *str1, char *str2) { // find substring in string
  int L1 = strlen(str1);
  int L2 = strlen(str2);
  for (int i = L1 - L2; i >= 0; i--)
  {
    int j = 0;
    for (; j < L2; j++)
      if ((str1[i + j] != str2[j]))
        break;
    if (j == L2)
      return str1 + i;
  }
  return 0;
}

void sendAtCommand(byte numcmd) { // send at command if modem not busy
  // find key worlds
  getPgmBuf(6 * numcmd);
  if (posSubStrFromPos(pgm_buf, strlen(pgm_buf), (char *) "~sender~", 0) > 0) {
    Serial.print(sender);
  } else if (posSubStrFromPos(pgm_buf, strlen(pgm_buf), (char *) "~textsms~", 0) > 0) {
    Serial.print(sms_buf);
  } else if (posSubStrFromPos(pgm_buf, strlen(pgm_buf), (char *) "~ctrlz~", 0) > 0) {
    Serial.print(char(26));
  } else {
    Serial.print(pgm_buf); // send cmd from cmd buf by number cmd
  }
  timer_reg_modem = current_millis; // reset wait response timer
  // load response from command to buf
  getPgmBuf(6 * numcmd + 1);
  if (pgm_buf[0] == 0) { // no response
    resp1[0] = 0; resp2[0] = 0; resp3[0] = 0; // no response
    wait_response = 0;
    getPgmBuf(6 * numcmd + 5);
    modem_step = strToByte(pgm_buf); // go to next step or mode
    pos_buf = 0; // clear response buf
    return; // next loop
  } else {
    getPgmBuf(6 * numcmd + 1);
    byte i = 0; while ((resp1[i] = pgm_buf[i]) > 0) ++i; resp1[i] = 0; // save first response from buf at cmd
    getPgmBuf(6 * numcmd + 2);
    if (pgm_buf[0] == 0) { // no second response
      resp2[0] = 0; resp3[0] = 0; // no response 2 and 3
    } else {
      byte i = 0; while ((resp2[i] = pgm_buf[i]) > 0) ++i; resp2[i] = 0; // save secont response from buf at cmd
      getPgmBuf(6 * numcmd + 3);
      if (pgm_buf[0] == 0) { // no thr response
        resp3[0] = 0; // no response 3
      } else {
        byte i = 0; while ((resp3[i] = pgm_buf[i]) > 0) ++i; resp3[i] = 0; // save thr response from buf at cmd
      }
    }
  }
  getPgmBuf(6 * numcmd + 4);
  wait_response = strToByte(pgm_buf); // set wait resp from command buf
  flresp1 = 0; flresp2 = 0; flresp3 = 0; // clear result response
  pos_buf = 0; resp_buf[pos_buf] = 0; // clear response buf
  ledStatus = numcmd + 1; ledError = 0;
}


byte strToByte(char *instr) {
  byte sl = strlen(instr);
  if (sl < 1) return 0;
  byte res = 0, i = 0;
  while (instr[i] > 0) {
    res += ((instr[i] - '0') * pow(10, (sl - i - 1)));
    ++i;
  }
  if (sl > 2) ++res;
  return res;
}

byte posSubStrFromPos(char *inBuf, byte maxPosBuf, char *subStr, byte resPos) {
  if (resPos >= maxPosBuf) return 0;
  while ((resPos < maxPosBuf) && (inBuf[resPos] > 0)) {
    byte isub = 0;
    if (inBuf[resPos] == subStr[isub]) {
      byte sslen = strlen(subStr);
      while (((resPos + isub) < maxPosBuf) && (inBuf[resPos + isub] > 0) && (isub < sslen)) {
        if (subStr[isub] != inBuf[resPos + isub]) break;
        ++isub;
      }
      if (isub >= sslen)   {
        ++resPos;
        return resPos;
      }
    }
    ++resPos;
  }
  return 0;
}

byte findRespParts() { // find response parts in response buf
  byte countresp = 0, countgood = 0;
  if (resp1[0] > 0) { // exist response 1
    ++countresp;
    if (strPos(resp_buf, resp1) >= 0) {
      flresp1 = 1; // found response 1
    }
    if (resp2[0] > 0) { // exist response 2
      ++countresp;
      if (strPos(resp_buf, resp2 ) >= 0) {
        flresp2 = 1; // found response 2
      }
      if (resp3[0] > 0) { // exist response 3
        ++countresp;
        if (strPos(resp_buf, resp3) >= 0) {
          flresp3 = 1; // found response 3
        }
      }
    }
  }
  if (flresp1 == 1) {
    ++countgood;
  }
  if (flresp2 == 1) {
    ++countgood;
  }
  if (flresp3 == 1) {
    ++countgood; // calculate good response
  }
  if ((countresp > 0) && (countresp == countgood)) return 1; else return 0;
}

const char ex0cmd[] PROGMEM = "getstatus"; const char ex1cmd[] PROGMEM = "poweroff"; const char ex2cmd[] PROGMEM = "poweron";
const char ex3cmd[] PROGMEM = "getbalance";

const char * const ext_pgm_cmd[] PROGMEM = {
  ex0cmd, ex1cmd, ex2cmd, ex3cmd
};

void getExtBuf(byte idxPgmBuf) {
  const char * addrStroki = pgm_read_word_near((int)(ext_pgm_cmd + idxPgmBuf));
  strcpy_P(pgm_buf, addrStroki);
}

void execExtCmd(byte numCmd) {
  switch (numCmd) {
    case 0: {
        if (deviceMode) sendSMS(phoneMain, (char*) "Power ON "); sendSMS(phoneMain, (char*) "Power OFF "); break;
      }
    case 1: {
        deviceMode = 0; break;
      }
    case 2: {
        deviceMode = 1; break;
      }
    case 3: {
        flGetBalance = 1;
        break;
      }
    default: {}
  }
}

void sendSMS(char *phnum, char *txtsms) { // prepare sender phone number and text for sms
  sender[0] = 0;
  sms_buf[0] = 0;
  strcpy(sender, "+"); strcat(sender, phnum);
  strcpy(sms_buf, txtsms);
  byte i = strlen(sms_buf);
  i = addTextUptime(sms_buf, i , max_size_sms_buf); // add uptime text to sms buf
  sms_buf[i] = 0;
#ifdef USE_DS18B20
  if (dsCount) {
    i = addTextTemp0(sms_buf, i , max_size_sms_buf); // add DS18B20 temp idx 0 to sms buf
    sms_buf[i] = 0;
  }
#endif
  timer_send_sms = current_millis; // reset timer send sms
  timer_read_sms = current_millis; // reset timer read sms
}

byte addTextUptime(char *text, byte firstpos, byte maxsize) { // add uptime text to input text
  byte days = current_millis / 86400000UL;
  byte hours = (current_millis % 86400000UL) / 3600000UL;
  byte mins = ((current_millis % 86400000UL) % 3600000UL) / 60000UL;
  if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = 'u'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  if (days > 9) {
    text[firstpos] = (days / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  }
  text[firstpos] = (days % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = 'd'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  if (hours > 9) {
    text[firstpos] = (hours / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  }
  text[firstpos] = (hours % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = 'h'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  if (mins > 9) {
    text[firstpos] = (mins / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  }
  text[firstpos] = (mins % 10) + '0'; ++firstpos;  if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = 'm'; ++firstpos;
  return firstpos;
}

byte addTextTemp0(char *text, byte firstpos, byte maxsize) { // add uptime text to input text
  if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = ' '; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  word ttt = massTemper[0];
  if (ttt >= 2000) {
    text[firstpos] = '-'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
    ttt -= 2000;
  }
  word bbb = ttt / 10;
  if (bbb > 9) {
    text[firstpos] = (bbb / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  }
  text[firstpos] = (bbb % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = '.'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = (ttt % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = ' '; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos;
  text[firstpos] = 'C'; ++firstpos;
  return firstpos;
}

 

fridgetester
fridgetester аватар
Offline
Зарегистрирован: 09.02.2019

индусы в шоке

sadman41
Offline
Зарегистрирован: 19.10.2016

Все мои знакомые коты лижут яйца там, где им приперло и более 20сек. Или спят. Или втыкают на стену.

alexBCN
Offline
Зарегистрирован: 01.07.2019

абажаю людей с юмором   и ценю ...   но всеже    ..

http://psenyukov.ru/%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BC%D1%81-%D1%81-neoway-m590-%D0%BF%D1%80%D0%B8-%D0%BE%D0%B1%D0%BD%D0%B0%D1%80%D1%83%D0%B6%D0%B5%D0%BD%D0%B8%D0%B8-%D0%B4%D0%B2%D0%B8%D0%B6/

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

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

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

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

ок  можно ли этот проэкт что по ссылке собрать на ардуино нано 3.0 ?   

и может быть просто ТЗ  оформить как  то что чутка подправить под наши задачи эту готовую прошивку ? 

в этом случае проэкт этого  1 разработчика просто идет на свалку   

а делаем вот этот простейший проэкт ЕСЛИ ОН РАБОЧИЙ и без косяков ? и ТЗ  просто превращяется в некой модификаций уже имеющейся прошивки ? 

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

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

Вот такая, описанная система, это хуже, чем купить китайский GSM модуль сигналки, прошитый "на отъе..сь".

ОС - Охранные Сигнализации - это комплекс технических и психологических мероприятий и средств. Начинают с определения круга угроз и их классификации. Затем воздействия и оповещения.

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

Компонетны ОС:

1. скрытые датчики - пояснять не надо;

2. наглядные элементы - от муляжа камеры и мигающего диодика до реальных камер, лазеров и емкостных кабелей - цель повысить контрмотивацию у злодея: "Тут всё серьёзно! Да-ну-нах, пойду другой ларёк бомбану!";

3. средства ЗиВО Звукового и Визуального Оповещения - сирена, прожектор, проблесковый маяк и т.п. Нужны лишь в том случае, если предполагается, что кто-то среагирует, или хоть злодей испугается ;).

4. Коммуникационный блок - для приема команд, отправки извещений и телеметрии;

5. Центральное управляющее устройство.

---------------------------------------

Общие правила построения ОС, если не на "отъе..ись" и не детская поделка.

1. скрытые датчики должны быть соединены с ЦУУ так, чтобы определялось разрушении линии.

2. Желательно и наглядные средства тоже соединять таким образом.

3. средства ЗиВО должны быть нормально включены, иметь автономное питание (на время оповещения) и соединяться с ЦУУ гальванически развязанно. Нормально включены - чтобы сработать при разрушении ЦУУ, гальванически развязаны - защита от "шокера", разрушаюшего ЦУУ и линии.

4. Коммуникационный блок - как и ЗиВО, развязка и автономное питание на время, достаточное для отправки аларма.

5. ЦУУ - вот тут нужно помнить, что "в одну телегу впрячь неможно коня и трепетную лань". Не нужно грузить ЦУУ несвойственными функциями: предсказания погоды, заказ пиццы и деффок в баню и пр. Простой защищенный от сбоев алгоритм, просто конечный автомат. Если есть желание приделать "свистоперделки" - они оформляются в отдельный блок, который активизируется событиями определенного уровня ("цвета") опасности.

Вот про уровни опасности, на что реагировать немедленным самоуничтожением ;)))), а на что нежным посвистыванием - это тема отдельной лекции... и мне уже явно лень будет ее читать.

=====================================

В связи с изложенным - описанное решение  (пока трезвый - без мата) ..ну детский сад, штоле?!

alexBCN
Offline
Зарегистрирован: 01.07.2019
я прекрасно понимаю что все время разработчика должно быть оплачено  даже если он в это время сидит на форуме и переписывается или пошел на речку покупатся от летней жары чтобы мозги не сварились ...
 
а  не сидит с 8 утра до 5 вечера и  наворачивает оловом килограммы смд деталей  на платах  на заводе СЛАВА КПСС   ..
 
вопрос лишь   в том сколько время нужно  ? сколько это будет стоить ? и потянет ли заказчик  эти  неизбежные и необходимые расходы ? и потянуть ли заказ  сами взявшиеся за заказ ?
 
я тоже сторонник идеи  что сигналку должен разрабатывать спецы а не любители    а спецы себе в убыток  не работает ... 
 
называйте цены сроки предлогайте свои варианты   .. только одно  заказчик настаивает на работе через любую из площядок типа freelance.ru 
 
пс
абсолютно согласен с каждым словом  оратора wdrakula   
 
я был вообще удивлен что сигналку собрали на любительской платформе ардуино,   лично я привык в дубовым и простым  решениям    которые исповедовала совецкая школа сигнализации 
ну я устарел уже и много упустил  да и требуется на СМС оповещение ..
упустил все  что было за последние лет 10...15 .а то и забыл . может и ардуино тоже не плохо ? хотя то что все это с китая  лично у меня не вызывет уверенности что это будет работать долго и надежно 
там среди деталей что мне доставили  лежит  пачка м590 которая обозначена как бракованные,   и аж целый кастомный прибор для проверки бракованных .. да и везде пишут что м590 глючный 
ну и как делать серьозно промавтоматику  на этом китае ?  
там лежало олово китайское в комплекте деталей ,  я  был в шоке потому что думал что у меня подсгорел паяльник марки JBC который я  уже 10 лет не вынимал из ножен 
мне и в голову не могло прийти что кто то купит у китайцев олово которое голимый свинец  ...   потом допер но далеко не сразу ..   посмотрел да действительно иероглифы на бобине 
 
 и изобрели и собрали систему   так что любой водила, или жулик  или страховой агент ,  или конкурентная фирма максимум через неделю ..  а минимум после прочтения даташитана пиродатчик   тоесть через 5.. 10 минут  поймет что такую сигналку можно трякой отключить   или куском фанеры  
 
внешние уличные датчики которые должны быть пыле влаго  и вандало защитных корпусах.. но  были сделаны на 3д принтере  в черном цвете
 а внутри все уличные блоки плат  смонтрированы на термоклее,   
 и  а там же там стоит мощный светодиод  который по идее должен распугивать жуликов ночью на пустынном месте   
 и резистор на 5ватт  там же который греется как яйца у кота с планеты венера 
 
лично я бы предпочел все датчики на проникновение за периметр  таки сделать как можно более малозаментыми а не подсвечивать их местонахождение ещо и иллюминацией 
alexBCN
Offline
Зарегистрирован: 01.07.2019

По поводу того что коты лижут яйца как минимум 20 секунд абсолютно согласен.. сам котовод в прошлом.ок тогда выставим 40..50? секунд. Я ещё не видел чтобы коты занимались онанизмом. а на гигиену им хватит и 30 секунд? Логично? А глючный м590 заменим на более дорогой и не глючный?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

alexBCN пишет:

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

..там среди деталей что мне доставили  лежит  пачка м590 которая обозначена как бракованные

..ну и как делать серьозно промавтоматику  на этом китае ?  

Да нормально всё делать на Китае. Китай выпускает что угодно любого качества. Даже Ардуино модули можно использовать готовые. Если есть сомнения в пайке - прогреть феном, закрыть лаком...

М590 - говно, sim800 нужно использовать. Просто sim800 в три раза дороже.

А про твой заказ - бред это. С такими требованиями нужно просто купить хреновину на Али готовую.

Или делать по-человечески. Ты, как я понял, и сам знаешь как.

alexBCN
Offline
Зарегистрирован: 01.07.2019

вообщем пообрщявшись в вашим коллективным разумом  И с заказчиком и его запросами,  я понял что вы ребята правы ...  и генеральная линия сдесь только 1

или ты нанимаеш специалиста или команаду специалистов по сигналкам  например таких как wdrakula  и платиш им хорошие деньги  за каждый день их работы + матерьялы и прочие расходы включая аренду помещения 

 

либо вариант 2 ты просто покупаеш уже готовое и прособачиваеш под себя   я уверен что заказчик 1 линию просто не тянет 

а 3 варианта тут нет  ..3 эконом вариант  это то что он уже получил  свистелку недоделанную от некого  кулибина 

и платит за 3 вариант будет даже не дважды а как правильно сказали выше ТРИЖДЫ   а подделка в конечном итоге будет достойна только чтобы ее с размаха выкинуть в помойное ведро.

потеря время и денег 

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

 

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

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

куда можно подключить 2 датчика движения  и 1 датчик температуры и может быть ещо 1 или 2 каких то датчика скорее всего емкосных

 

 

 

 

alexBCN
Offline
Зарегистрирован: 01.07.2019

кстати по поводу китая ... я так померял  радномно несколько смд конденсаторов и резисторов  и везде отклонение от номинала около 10..15% 

чето многовато   

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

alexBCN пишет:

кстати по поводу китая ... я так померял  радномно несколько смд конденсаторов и резисторов  и везде отклонение от номинала около 10..15% 

чето многовато   

С чего это вы взяли ? Что касается резисторов то есть серии где допустимое отклонение +-10%, а некоторые серии конденсаторов +-50% !

https://www.proline-rus.ru/catalog/komplekty-besprovodnoj-gsm-signalizacii-bastion-2070/bastion-x1-55874/?utm_source=gm&utm_medium=gm&utm_campaign=gm&utm_content=komplekty_besprovodnoj_gsm_signalizacii_bastion&utm_term=55874&gclid=CjwKCAjwx_boBRA9EiwA4kIELo7Ag2DkonxJR_H2cYdY_U31otJg8qCJWDUxpjmyyDun80TZaFuX_RoCEaUQAvD_BwE

qbit
Offline
Зарегистрирован: 18.03.2019

alexBCN пишет:

...я так померял  радномно несколько смд конденсаторов и резисторов  и везде отклонение от номинала около 10..15%...

Во первых, чем меряли? Во вторых, условия измерения? В третьих, погрешность укладывается в разброс для X7R.

alexBCN
Offline
Зарегистрирован: 01.07.2019

multi meter Welleman  + capacitance meter TES 1500

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

я понимаю что адруино цифровая логическая схемотехника и там такой разброс  наверное  не  важен .. 

но все же  ... китаец он вседаки китаец 

я помню,  взял в китае на gearbest  исключительно потому что дизайн понравился ботинки, писали что кожа, оказалось бумага пропитанная чем то 

а подошва на 3 день насквозь  ибо толщина ее 1,5мм и сырой резины 

я в магазин выслал им фото ботинка с пальцем из подошвы деньги вернули ... а сколько тысячь или милионов пар этого  поделия  они людям впаривают ?  до сих пор реклама линейки этой CHINA SHOES моды  в браузер залазит 

вот где милионы денег надо делать 

я 1/4  добавил к цене тех  CHINA говнодавов  и купил в реальном магазине классные кожанные шузы на подошве из полиуретана 

3 года проходят и не развалятся 

alexBCN
Offline
Зарегистрирован: 01.07.2019

ой спасибо  ...  да добротная система 

БАСТИОН X1   

 а не кривое поделие на 3д принтере с лампочками   и свистком 

 

а система стоит вообще копейки,  блок и датчики да ещо и беспроводные 

пс

вы ребята были абсолютно правы что надо брать в китае готовое  ...     а не маяца фигней и фольклорной самодеятельностью 

alexBCN
Offline
Зарегистрирован: 01.07.2019

да и ещо вопрос  .. а то от многостраничных даташитов   уже  коты волосатые  летают перед глазами  

можно ли на плате которая разработана под M590   воткнуть  SIM800 или SIM 900 ?

или потребуются серьзеные доработки по обвеске  и плате ? 

а это новую плату делать ... просто из спортивного любопытства вопрос 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

alexBCN
Offline
Зарегистрирован: 01.07.2019
Итак ..после дополнительных переговоров с заказчиком  ..появилось новое ТЗ...  постараюсь быть лаконичным
 
заказчик   таки решил идти по  генеральному варианту 1 тоесть наем специалистов на свой собственный кастомный  проэкт...
 
хотя лично я настаивал на бюджетном  варианте 2  кастомный перепиленный и присобаченный под задачу  китай,  так как вы и советовали ..
 
но хозяин барин 
 
итак  новое ТЗ  которое я сформулирую просто как рубль,  в лучших традициях ТРИЗ 
 
ЗАДАЧА 
защитить больше-грузный автомобиль  типа SCANIA, IVECO  и прочие марки.  с прицепом
 
1 защитить сигнализацией что бы не скомуниздили АККАМУЛЯТОР
2 защитить сигнализацией что бы не скомуниздили ТОПЛИВО,  *чтобы не просверлили или открыли крышку топливного бака 
3 защитить сигнализацией кабину водителя от проникновения 
4 защитить сигнализацией все входящие в кабину источники воздуха АКА печки кондиционеры и даже открытые окна от того что туда НЕ вдули усыпляющий газ 
тип которого не известен, а скорее всего закись азота или хлороформ а может что то другое 
*я даю подсказку надо ставить не датчики газа, а датчики на  приближение любых обьектов к зоне откуда забирается воздух в кабину
5 защитить сигнализацией саму фуру (прицеп) и ее содержимое сигналкой  но учитывайте что прицеп фуры часто меняют  дальнобои при перегонах
на прицеп не оборудованный не какой сигналкой от совершенно другой компании ..  
*тоесть модуль что будет защищять прицеп наверное должен быть сьемным и беспроводным ..но это вы сами решайте 
6 пожарная сигналка на кабину ..  *хотя лично я не вижу в этом смысла ..ибо кабина сгорит за 1 минуту в угли 
7 нужна отдельная система типа видео регистратора по обе стороны автомобиля тоесть на две видеокамеры  чтобы регистрировать дорожные происшествия  
типичный CAR DVR  *который проще купить в китае  с типичными функциями записью на событие и цикличной записью 
флешка на которую будет запись внутри кабины 
*даю подсказку почти значительную часть  системы  охраны  можно реализовать на фиксации движения через видеокамеры  и триггер  что в поле камеры было движение 
естественно с алгоритмом отбраковки ложных сигналов и прочими мерами  ...но  решать  вам как надо делать
 
камеры смотрят от кабины и назад вдоль корпуса автофургона  ..тоесть банально из китая выбрать самое дешовое но и не глючное подходящее под задачу.
А) версии с монитором показывающим картинку с обеих камер и записью на флешку. тут цель проста не только запись ДТП но и визуальная охрана периметра из спального места в кабине
 
Б) без монитора  просто с записью на флешку 
 
8 нельзя вносить какие либо существеные изменения в сам автомобиль и его внешний облик ибо каждое такое изменения требует дорогово лиценцирования на предмет безопасности
 
9 цена электронных компонентов  желательно не должна превышать 60евро   со всеми датчиками .. это не учитывает систему  CAR DVR пункт 7  и корпуса для системы  кабелей и подобного
смысл один, система должна быть по карману  большинству потенциальных клиентов
10 бюджет и сроки НИОКР  вседаки в разумных рамках, но таки делать реальную сигналку а не свистелку
 
КОНЕЦ ЗАДАЧИ.
 
 
УСЛОВИЯ В КОТОРЫХ ПРИДЕТСЯ РАБОТАТЬ СИСТЕМЕ ОХРАНЫ.. И ПРОЧЕЕ
водила во время атаки может спать внутри так и быть за несколько километров во время посещения борделя, мотеля, лабаза, шавермы итд..
 .. он может ехать в команде  грузовиков   из одной компании а значит нужно учитывать что о том что кого то из команады атакуют должна быть оповещена вся комманда для кооперации в физической защите обьекта
водила так же может быть и одиночкой 
может парковатся ночью один в не охраняемой зоне так и среди таких же одиночек по несчясьтью ..
 
атака происходит на стоянках  дальнобойщиков  как правило тех что  не охраняемы 
 
я бы превратил весь грузовик с прицепом просто в емкостной датчик  если бы это было возможно??? 
( мое виденье решения всех перечисленных задач НО которое я не навязываю)
чтобы не кто не подошел не ближе 20-40 сантиметров в машине со всех сторон,но с учетом того что внутри спят водилы и могут сами быть источником ложного срабатывания
нужно максимально снизить вероятность ложных срабатываний, учитывать что автомобиль ездит в разных климатических зонах и в разную погоду 
учитывать  что рядом могут шататся другие водители, животные, насекомые,летучие мыши, и даже рептилии ака ящерицы  и саламандры
учтите что бортовя сеть у грузовиков как правило  на 24 вольта и бывают скачки напряжения от чего бывает горит электроника 
*и ещо! проэкт должен быть закончен с полной сопроводительной документацией  
типа исходников прошивки, перечня используемых деталей и матерьялов и где они куплены,полное описание технологических процессов 
для того чтобы потом другой человек или компания мог продолжить и внедрить это в производство  легко 
заказчик предпочитает систему охраны на СМС информировании и управлении через мобильный  телефон ..
но я бы посоветовал добавить к СМС информеру ещо и просто брелок  с двумя кнопками 
поставка на охрану и снятие, + индикация что постановка и снятие охраны прошла успешно, но это не условие вы вольны делать как вам виднее  
система управления сигнализацией должна быть проста и удобна ..водила умеет водить, ему уставшему не зачем парить себе мозги с заковыристым управлением
*по условиям ТЗ  которое дал заказчик это не противоугонная система а выходит охранная система .. но если вы прикрутите к ней противоугонный функционал  я думаю это будет не лишним 
 
УСЛОВИЯ ЗАКАЗЧИКА 
*заказчик ждет предложений о цене и сроках НИОКР и создания первого протопипа , и  по прежнему настаивает  на платформе посреднике типа freelance.ru  но готов через эту же платформу 
оплачивать детали матерьялы и прочие траты типа аванса .. 
 
*разработка и создание хотя бы пары работающих прототипов  этого  охранного комплекса 
*заказчик  ждет ваших предложений о цене и сроках, допустима корректировка или дополнения в ТЗ  итд 
*а я как был адвайзером и аудитором  в этом проэкте,  так и остаюсь на этих правах и на бюджете энтузиаста 
*на каких физических принципах, на какой стратегии  охраны обьекта  и на какой элементарной базе это сделать у вас полная свобода 
*заказчик считает что при нарушения периметра его сначало должен отпугивать свет мощных светодиодов..что в принципе довольно разумное решение применяемое в охране домов в латинской америке
и после превышения негого лимита времени нахождения посторонего обьекта в охраняемом периметре  уже врубается вся система со звуком и смс 
я не внес это в 10 пунктов ТЗ   потому что это уже вне правил формулирования задачи по  ТРИЗ  
НА ЭТОМ ВСЕ 
извините за грамматику и слэнг
критикуйте на форуме и трольте ... а по делу с предложениями предпроэктами и проэктами и вопросами  пишите сюда rap1db0xer@gmail.com  
 
sadman41
Offline
Зарегистрирован: 19.10.2016

Жесть. Тут объем работ на небольшое КБ. Особенно понравилось требование к обнаружению неизвестного газа.

gfx125
Offline
Зарегистрирован: 27.05.2017

может попробуете еще раз посоветовать заказчику сразу поменять свой

Цитата:
больше-грузный автомобиль  типа SCANIA, IVECO
на нечто подобное ?