Как распознать два и более разрешённых номеров

Тема в разделе "Arduino & Shields", создана пользователем geniv82, 21 фев 2019.

  1. geniv82

    geniv82 Нерд

    Здравствуйте форумчане, который день бьюсь с GSM розеткой. Проблема в том, что не могу записать более одного разрешённого номера. Вот рабочий скетч.
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(10, 11); // RX, TX
    unsigned long timing; // Переменная для хранения точки отсчета
    ////////////--------------//////////////
    #define  TEL1  "79038599995"    //// 1 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL2  "79201234567"    //// 2 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL3  "79021234567"    //// 3 НАШ НОМЕР УПРАВЛЕНИЯ
    ////////////--------------//////////////
    void setup()
    { Serial.begin(9600);
      mySerial.begin(9600);
      pinMode(2, OUTPUT); // ЭТО РЕЛЕ
      digitalWrite(2, LOW); //  ПОДТЯЖКА ПОРТА HIGH
      mySerial.println("ATE0");  //ОТКЛ ЭХО
      delay(300);
      mySerial.println("AT+IPR=9600;");
      delay(300);
    }

    void loop()
    { digitalWrite(13, HIGH);// ИНДИКАЦИЯ СВЯЗИ СИМ800 И МИКРОК.
      mySerial.println("AT"); // РЕГИСТРАЦИЯ  СЕТИ
      if (millis() - timing > 500) { // Вместо 10000 подставьте нужное вам значение паузы
        if ( mySerial.find("OK")) // ОТВЕТ  ОК
        { Serial.println("SOEDINENIE OK");
          digitalWrite(13, LOW);
        }//  МИГАЕМ ВСЕ ОК
        else {
          Serial.println("SOEDINENIE NO");
          digitalWrite(13, HIGH); // ЕСЛИ НЕ НАШЛИ ГОРИМ
        }
        timing = millis();

      }

      /////////////ИЩЕМ ЗВОНОК/////////////

      if (mySerial.find("CLIP:")) // если нашли RING
      {
        Serial.println("RING!");
        delay(200);
        mySerial.println("AT+CLIP=1"); // ВКЛ ОПРЕДЕЛИТЕЛЬ НОМЕРА
        delay(300);
        while (1) // в цикле
        {
          if (mySerial.find(TEL1)) { // ищем номер телефона, если нашли
          { digitalWrite(2, !digitalRead(2)); // инвертируем A1
              delay(500);
              Serial.println("INVERSIA RELE");
              ////////////////////////////////////////
              delay(500);
              if ( digitalRead(2) == HIGH) //ЕСЛИ РЕЛЕ ВКЛ LOW
              { mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(400);
                Serial.println("VKL RELE");
              }
              else
              {
                Serial.println("OTKL  RELE");
                delay(6000);
                mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(500);

              }
              if (mySerial.find("CLIP:"))
                break;
            }

          }

          else { // иначе
            mySerial.println("AT"); // спрашиваем состояние модема
            delay(200);
            if (mySerial.find("OK"))
              break;   // и если он в "готовности", выходим из цикла
          }            // если звонок в процессе, возвращает +CPAS: 3
        }              // и крутимся дальше

        mySerial.println("AT+CHUP;"); // сбрасываем вызов
        delay(200);

      }
    }
    А вот этот работать не хочет, из-за изменений в строке: if (mySerial.find(TEL1)||(TEL2)||(TEL3)) { // ищем номер телефона, если нашли
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(10, 11); // RX, TX
    unsigned long timing; // Переменная для хранения точки отсчета
    ////////////--------------//////////////
    #define  TEL1  "79038599995"    //// 1 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL2  "79201234567"    //// 2 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL3  "79021234567"    //// 3 НАШ НОМЕР УПРАВЛЕНИЯ
    ////////////--------------//////////////
    void setup()
    { Serial.begin(9600);
      mySerial.begin(9600);
      pinMode(2, OUTPUT); // ЭТО РЕЛЕ
      digitalWrite(2, LOW); //  ПОДТЯЖКА ПОРТА HIGH
      mySerial.println("ATE0");  //ОТКЛ ЭХО
      delay(300);
      mySerial.println("AT+IPR=9600;");
      delay(300);
    }

    void loop()
    { digitalWrite(13, HIGH);// ИНДИКАЦИЯ СВЯЗИ СИМ800 И МИКРОК.
      mySerial.println("AT"); // РЕГИСТАЦИЯ  СЕТИ
      if (millis() - timing > 500) { // Вместо 10000 подставьте нужное вам значение паузы
        if ( mySerial.find("OK")) // ОТВЕТ  ОК
        { Serial.println("SOEDINENIE OK");
          digitalWrite(13, LOW);
        }//  МИГАЕМ ВСЕ ОК
        else {
          Serial.println("SOEDINENIE NO");
          digitalWrite(13, HIGH); // ЕСЛИ НЕ НАШЛИ ГОРИМ
        }
        timing = millis();

      }

      /////////////ИЩЕМ ЗВОНОК/////////////

      if (mySerial.find("CLIP:")) // если нашли RING
      {
        Serial.println("RING!");
        delay(200);
        mySerial.println("AT+CLIP=1"); // ВКЛ ОПРЕДЕЛИТЕЛЬ НОМЕРА
        delay(300);
        while (1) // в цикле
        {
         if (mySerial.find(TEL1)||(TEL2)||(TEL3)) { // ищим номер телефона, если нашли
          { digitalWrite(2, !digitalRead(2)); // инвертируем A1
              delay(500);
              Serial.println("INVERSIA RELE");
              ////////////////////////////////////////
              delay(500);
              if ( digitalRead(2) == HIGH) //ЕСЛИ РЕЛЕ ВКЛ LOW
              { mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(400);
                Serial.println("VKL RELE");
              }
              else
              {
                Serial.println("OTKL  RELE");
                delay(6000);
                mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(500);

              }
              if (mySerial.find("CLIP:"))
                break;
            }

          }

          else { // иначе
            mySerial.println("AT"); // спрашиваем состояние модема
            delay(200);
            if (mySerial.find("OK"))
              break;   // и если он в "готовности", выходим из цикла
          }            // если звонок в процессе, возвращает +CPAS: 3
        }              // и крутимся дальше

        mySerial.println("AT+CHUP;"); // сбрасываем вызов
        delay(200);

      }
    }
    Хотел получить то, что при звонке определяется номер телефона, и, если он совпадает с одним из номеров TEL1 или TEL2 или TEL3:
    #define TEL1 "79038599995" //// 1 НАШ НОМЕР УПРАВЛЕНИЯ
    #define TEL2 "79201234567" //// 2 НАШ НОМЕР УПРАВЛЕНИЯ
    #define TEL3 "79021234567" //// 3 НАШ НОМЕР УПРАВЛЕНИЯ
    то далее программа включает или выключает реле (в зависимости от первоначального состояния), а если номер не знакомый, то просто сбрасывает вызов.
    В первом скетче это условие выполняется, но если там прописан только один телефон. А с двумя и более номерами - не работает.
    Конечный результат следующий: на данный момент имеется розетка, которая управляется DTMF. Но не удобно включать, т.е. набрать номер, дождаться ответа, нажать соотв. цифру на клавиатуре, сбросить номер.
    Хочется, чтобы по звонку с двух, трёх номеров срабатывала розетка.
    Подскажите пожалуйста что сделать.
     
  2. DetSimen

    DetSimen Guest

    А так?
    if (mySerial.find(TEL1) || mySerial.find(TEL2) || mySerial.find(TEL3))
     
    Andrey12 и b707 нравится это.
  3. geniv82

    geniv82 Нерд

    Спасибо. Нет, работает только первый номер. Если переставить if (mySerial.find(TEL2) || mySerial.find(TEL1) || mySerial.find(TEL3)), то срабатывает только второй номер.
     
  4. find для разбора таких вещей совсем не подходит, потому что в случае неправильного ввода вообще всё пойдет наперекосяк. Изучайте стандартную библиотеку C по работе со строками.
     
  5. Tomasina

    Tomasina Сушитель лампочек Модератор

    А номер точно определяется именно как 79038599995?
    Или все же +79038599995, или 89038599995?
     
  6. Airbus

    Airbus Радиохулиган Модератор

    Там если включить АОН в порт пойдет имя.А определяется да +7
    А если так if(my Serial find(TEL)) ?
     
  7. geniv82

    geniv82 Нерд

    Ставлю +7 или 7 без разницы, всё равно определяет только первый номер.
    Изначально было до меня
    Код (C++):
    if (mySerial.find("+79038599995")) // ищим номер телефона, если нашли
    , но хочется больше номеров привязать (жена, дочь)
     
  8. Airbus

    Airbus Радиохулиган Модератор

    А так даже еще лучше.Если первый символ==Т то это наш клиент и инвертируем реле.
     
  9. Airbus

    Airbus Радиохулиган Модератор

    Запиши все номера под одним именем TEL Или как я делаю Admin
     
  10. geniv82

    geniv82 Нерд

    Записал - теперь любой номер сбрасывает, хоть записанный, хоть нет. Я так понял, что
    мне не подходит.
     
  11. Airbus

    Airbus Радиохулиган Модератор

    Ок немного не то имел ввиду но ладно.В ПЕРВОМ скетче в дефайнах проставь все номера как TEL1 (TEL2 и TEL3 замени на TEL1)
     
  12. geniv82

    geniv82 Нерд

    Так и сделал, в дефайнах все номера TEL , а if (mySerial.find(TEL)) и прописанные сбрасывает и не прописанные. Реле не переключается. В мониторе "SOEDINENIE OK" потом "RING!" и опять "SOEDINENIE OK".
     
  13. Andrey12

    Andrey12 Гик

    У вас первый вызов mySerial.find(TEL1); считывает буфер и когда читаете второй раз в буфере нет нифига.
    Вот внизу попробуйте код, идея такова считать буфер а переменную и потом в ней искать ваши телефоны.
    Я добавил чтение из Serial - String lTmpStr = mySerial.readString();
    И сравнение номеров уже уже с lTmpStr - if ((lTmpStr.indexOf(TEL1) !=-1) ||(lTmpStr.indexOf(TEL2) !=-1)||(lTmpStr.indexOf(TEL3) !=-1))
    Може синтаксис кривой на работе компилить негде. Но идея я думаю понятна.
    Конечно костыли еще те. Руки не отрывайте пожалуйста.

    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(10, 11); // RX, TX
    unsigned long timing; // Переменная для хранения точки отсчета
    ////////////--------------//////////////
    #define  TEL1  "79038599995"    //// 1 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL2  "79201234567"    //// 2 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL3  "79021234567"    //// 3 НАШ НОМЕР УПРАВЛЕНИЯ
    ////////////--------------//////////////
    void setup()
    { Serial.begin(9600);
      mySerial.begin(9600);
      pinMode(2, OUTPUT); // ЭТО РЕЛЕ
      digitalWrite(2, LOW); //  ПОДТЯЖКА ПОРТА HIGH
      mySerial.println("ATE0");  //ОТКЛ ЭХО
      delay(300);
      mySerial.println("AT+IPR=9600;");
      delay(300);
    }

    void loop()
    { digitalWrite(13, HIGH);// ИНДИКАЦИЯ СВЯЗИ СИМ800 И МИКРОК.
      mySerial.println("AT"); // РЕГИСТАЦИЯ  СЕТИ
      if (millis() - timing > 500) { // Вместо 10000 подставьте нужное вам значение паузы
        if ( mySerial.find("OK")) // ОТВЕТ  ОК
        { Serial.println("SOEDINENIE OK");
          digitalWrite(13, LOW);
        }//  МИГАЕМ ВСЕ ОК
        else {
          Serial.println("SOEDINENIE NO");
          digitalWrite(13, HIGH); // ЕСЛИ НЕ НАШЛИ ГОРИМ
        }
        timing = millis();

      }

      /////////////ИЩЕМ ЗВОНОК/////////////

      if (mySerial.find("CLIP:")) // если нашли RING
      {
        Serial.println("RING!");
        delay(200);
        mySerial.println("AT+CLIP=1"); // ВКЛ ОПРЕДЕЛИТЕЛЬ НОМЕРА
        delay(300);
    String lTmpStr = mySerial.readString();
        while (1) // в цикле
        {
         if ((lTmpStr.indexOf(TEL1) !=-1) ||(lTmpStr.indexOf(TEL2) !=-1)||(lTmpStr.indexOf(TEL3) !=-1)) { // ищим номер телефона, если нашли
          { digitalWrite(2, !digitalRead(2)); // инвертируем A1
              delay(500);
              Serial.println("INVERSIA RELE");
              ////////////////////////////////////////
              delay(500);
              if ( digitalRead(2) == HIGH) //ЕСЛИ РЕЛЕ ВКЛ LOW
              { mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(400);
                Serial.println("VKL RELE");
              }
              else
              {
                Serial.println("OTKL  RELE");
                delay(6000);
                mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(500);

              }
              if (mySerial.find("CLIP:"))
                break;
            }

          }

          else { // иначе
            mySerial.println("AT"); // спрашиваем состояние модема
            delay(200);
            if (mySerial.find("OK"))
              break;   // и если он в "готовности", выходим из цикла
          }            // если звонок в процессе, возвращает +CPAS: 3
        }              // и крутимся дальше

        mySerial.println("AT+CHUP;"); // сбрасываем вызов
        delay(200);

      }
    }
     
    Последнее редактирование: 22 фев 2019
  14. Daniil

    Daniil Гуру

    Если я правильно понял, то вы хотите проверить в одном условии принадлежность звонка одному из 2ух номеров. При этом у вас получается определить только 1 номер.
    Что если сделать натой быдлокод:
    Код (C++):
    Num=номер телефона
    flagTel1=false
    if (Num==тел1) {flagTel1=true}
    flagTel2=false
    if (Num==тел2) {flagTel2=true}
    if (flagTel1 || flagTel2)
    {ваш код}
     
  15. geniv82

    geniv82 Нерд

    Спасибо, почти всё работает, но... При звонке с незнакомого номера в мониторе порта RING!, далее сброс. При звонке с разрешённого номера, включается и выключается реле в цикле. Пока этот цикл идёт в это время набираю с незнакомого номера, цикл прекращается и в мониторе SOEDINENIE OK. Как убрать это зацикливание?
    [​IMG]
    P.S. Извините, раньше не мог ответить. С прошедшим праздником!
     
  16. parovoZZ

    parovoZZ Гуру

    Через флаги.
     
  17. geniv82

    geniv82 Нерд

    Вы меня, конечно, извините, но с программированием у меня очень туго. И когда Вы говорите про флаги то я :confused:. Максимум что получилось - воткнуть кнопку. Так вот, если я включаю реле кнопкой, то с разрешённого номера я её отключаю без всякого зацикливания. Когда включается и выключается реле в цикле, то кнопкой переключить ничего не могу. Уж сильно не пинайте - помогите.
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(10, 11); // RX, TX
    unsigned long timing; // Переменная для хранения точки отсчета
    boolean buttonWasUp = true;
    ////////////--------------//////////////
    #define  TEL1  "+79038599995"    //// 1 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL2  "+71111111111"    //// 2 НАШ НОМЕР УПРАВЛЕНИЯ+79202242392
    #define  TEL3  "+79021234567"    //// 3 НАШ НОМЕР УПРАВЛЕНИЯ
    ////////////--------------//////////////
    void setup()
    { Serial.begin(9600);
      mySerial.begin(9600);
      pinMode(2, OUTPUT); // ЭТО РЕЛЕ
      digitalWrite(2, LOW); //  ПОДТЯЖКА ПОРТА HIGH
      mySerial.println("ATE0");  //ОТКЛ ЭХО
      delay(300);
      mySerial.println("AT+IPR=9600;");
      delay(300);
      pinMode(3, INPUT_PULLUP);
    }
    /////////кнопка////////
    void button()
    {
      boolean buttonIsUp = digitalRead(3);
      if (buttonWasUp && !buttonIsUp){
        delay(10);
        buttonIsUp = digitalRead(3);
        if(!buttonIsUp) {
          digitalWrite(2, !digitalRead(2));
        }
      }
        buttonWasUp = buttonIsUp;
    }
    /////////кнопка////////
    void loop()
    {
      button();
      digitalWrite(13, HIGH);// ИНДИКАЦИЯ СВЯЗИ СИМ800 И МИКРОК.
      mySerial.println("AT"); // РЕГИСТАЦИЯ  СЕТИ
      if (millis() - timing > 500) { // Вместо 10000 подставьте нужное вам значение паузы
        if ( mySerial.find("OK")) // ОТВЕТ  ОК
        { Serial.println("SOEDINENIE OK");
          digitalWrite(13, LOW);
        }//  МИГАЕМ ВСЕ ОК
        else {
          Serial.println("SOEDINENIE NO");
          digitalWrite(13, HIGH); // ЕСЛИ НЕ НАШЛИ ГОРИМ
        }
        timing = millis();

      }

      /////////////ИЩЕМ ЗВОНОК/////////////

      if (mySerial.find("CLIP:")) // если нашли RING
      {
        Serial.println("RING!");
        delay(200);
        mySerial.println("AT+CLIP=1"); // ВКЛ ОПРЕДЕЛИТЕЛЬ НОМЕРА
        delay(300);
    String lTmpStr = mySerial.readString();
        while (1) // в цикле
        {
         if ((lTmpStr.indexOf(TEL1) !=-1)||(lTmpStr.indexOf(TEL2) !=-1)||(lTmpStr.indexOf(TEL3) !=-1)) { // ищим номер телефона, если нашли
          { digitalWrite(2, !digitalRead(2)); // инвертируем A1
              delay(500);
              Serial.println("INVERSIA RELE");
              ////////////////////////////////////////
              delay(500);
              if ( digitalRead(2) == HIGH) //ЕСЛИ РЕЛЕ ВКЛ LOW
              { mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(400);
                Serial.println("VKL RELE");
              }
              else
              {
                Serial.println("OTKL  RELE");
                delay(6000);
                mySerial.println("AT+CHUP;"); // сбрасываем вызов
                delay(500);

              }
              if (mySerial.find("CLIP:"))
                break;
            }

          }

          else { // иначе
            mySerial.println("AT"); // спрашиваем состояние модема
            delay(200);
            if (mySerial.find("OK"))
              break;   // и если он в "готовности", выходим из цикла
          }            // если звонок в процессе, возвращает +CPAS: 3
        }              // и крутимся дальше

        mySerial.println("AT+CHUP;"); // сбрасываем вызов
        delay(200);

      }
    }
     
  18. Andrey12

    Andrey12 Гик

    Если я правильно понял то работать должно примерно так:
    1. Включаем агрегат, реле в выключенном состоянии, ожидаем звонка.
    2.1 Поступил звонок, если номер неизвестен кладем трубку, состояние реле не меняем, ждем следующего звонка.
    2.2 Поступил звонок, номер известен состояние реле инвертируем, кладем трубку, ждем следующего звонка.

    Если так то зачем while(1)? loop() по сути и есть while(1). Зачем кнопка не понял вообще, включать выключать розетку вручную? Если да то тогда parovoZZ прав нужны флаги.

    Вот внизу код, попробуйте, он без кнопки.
    mySerial.println("AT+CLIP=1"); вынес в setup потому как не надо его каждый раз дергать как я понимаю.
    Попробуйте, не компилировал так как негде на работе, возможны ошибки.

    Если нужна критика по существу то код жуткий. От модема всегда надо ждать ответ на команду которую вы передали, причем не с delay(ххх) а по таймауту из даташита, и до ответа ничего не делать далее. С delay будет тормозить работу программы, с кнопкой не получится полноценно работать.

    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(10, 11); // RX, TX
    unsigned long timing; // Переменная для хранения точки отсчета
    ////////////--------------//////////////
    #define  TEL1  "+79038599995"    //// 1 НАШ НОМЕР УПРАВЛЕНИЯ
    #define  TEL2  "+71111111111"    //// 2 НАШ НОМЕР УПРАВЛЕНИЯ+79202242392
    #define  TEL3  "+79021234567"    //// 3 НАШ НОМЕР УПРАВЛЕНИЯ
    ////////////--------------//////////////
    void setup()
    { Serial.begin(9600);
      mySerial.begin(9600);
      pinMode(2, OUTPUT);                 // ЭТО РЕЛЕ
      digitalWrite(2, LOW);             // Низкий уровень на реле
      mySerial.println("ATE0");          //ОТКЛ ЭХО
      delay(300);
      mySerial.println("AT+CLIP=1");     // ВКЛ ОПРЕДЕЛИТЕЛЬ НОМЕРА
      delay(300);
      mySerial.println("AT+IPR=9600;");
      delay(300);
    }

    void loop()
    {
      button();
      digitalWrite(13, HIGH);// ИНДИКАЦИЯ СВЯЗИ СИМ800 И МИКРОК.
      mySerial.println("AT"); // РЕГИСТАЦИЯ  СЕТИ
      if (millis() - timing > 500) { // Вместо 10000 подставьте нужное вам значение паузы
        if ( mySerial.find("OK")) // ОТВЕТ  ОК
        { Serial.println("SOEDINENIE OK");
          digitalWrite(13, LOW);
        }//  МИГАЕМ ВСЕ ОК
        else {
          Serial.println("SOEDINENIE NO");
          digitalWrite(13, HIGH); // ЕСЛИ НЕ НАШЛИ ГОРИМ
        }
        timing = millis();
      }

      /////////////ИЩЕМ ЗВОНОК/////////////

      if (mySerial.find("CLIP:")) // если нашли RING
      {
        Serial.println("RING!");
        delay(200);
        // читаем строку
        String lTmpStr = mySerial.readString();
        // ищем номер из списка
        if ((lTmpStr.indexOf(TEL1) !=-1)||(lTmpStr.indexOf(TEL2) !=-1)||(lTmpStr.indexOf(TEL3) !=-1)) {
            // если нашли инвертируем состояние реле
            if ( digitalRead(2)){
                digitalWrite(2, LOW);
                Serial.println("OTKL  RELE");
            }
            else {
                digitalWrite(2, HIGH);
                Serial.println("VKL RELE");          
              }

            mySerial.println("AT+CHUP;"); // сбрасываем вызов
            delay(400);
        }
        else{
            // незнакомый номер
            mySerial.println("AT+CHUP;"); // сбрасываем вызов
            delay(400);
        }
      }
    }
     
    Airbus нравится это.
  19. trimmer2007

    trimmer2007 Нерд

    Может и не по теме, но у вас какая-то беда со скобками. Зачем у вас открываются две фигурные скобки после if (там где он проверяет номер)?
     
  20. trimmer2007

    trimmer2007 Нерд

    Если у вас первый код рабочий, и вас удовлетворяет, нельзя ли каждый номер проверить через if else ? То бишь не логическим ИЛИ (||) перебрать в одном if, а для каждого номера отдельно?! Всего-то по пару строчек на каждый номер добавить.
    PS не ругайте меня сильно, я не программист и не ардуинщик.
     
    Airbus нравится это.