Автоматические ворота с управлением по звонку

mrgreen
Offline
Зарегистрирован: 13.11.2018

Здравствуйте! Ищу программиста который сможет написать программу для ардуино для открывания автоматических ворот при помощи звонка и/или смс.

Есть Ардуино НАНО, sim800L.

Основные функции:

1. Возможность удобного просмотра разрешенных номеров 

2. Добавление/удаление разрешенных номеров по смс 

3. Ведение логов открывания/закрывания с указанием даты\времени

4. Запрос баланса и получение смс на номер администратора.

5. Запрос количества циклов открывания\закрывания за 24 часа\ месяц.

 

Для опытных думаю дело 30 минут. Спасибо всем кто откликнется! 

 

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

От 8000 рублей
Andycat2013@yandex.ru

PS студент? С такими запросами не найдёте дёшево и качественно.

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

Для опытных думаю дело 30 минут. Спасибо всем кто откликнется! 

------------
 
Тут нет таких, кто за такое время напишет. Если только готовое есть у кого.
sadman41
Offline
Зарегистрирован: 19.10.2016

30? Много что-то. Не более десяти.

mrgreen
Offline
Зарегистрирован: 13.11.2018

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

 

Реально сделать дешевле? И оставить только самую важную функцию: добавление\удаление разрешенного номера по смс.

mrgreen
Offline
Зарегистрирован: 13.11.2018

И действительно, может быть у когото есть готовый вариант что бы только поправить? 

 

На ютубе есть несколько роликов по этой теме, но там не совсем то что нужно. 

Например есть такой код. Но там с использованием дисплея. Он нам не нужен. И отсутствует функция добавления новых номеров.

https://yadi.sk/d/f0el4pHEp2jMT

https://www.youtube.com/watch?v=78TJRGNDf-w

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

100 номеров....

mrgreen
Offline
Зарегистрирован: 13.11.2018

vvadim пишет:

100 номеров....

Эти 100 номеров будут сразу добавлены в коде. Потом только добавлять\удалять.

Или памяти может не хватить ? Пишут что надо использовать EEPROM

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

mrgreen пишет:

И действительно, может быть у когото есть готовый вариант что бы только поправить? 

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

Есть готовый такой вариант (4990 рублей):

- прием команд по СМС по разрешенному списку (в скетче задается)

- отправка подтверждений/команд по СМС

- прием команд/данных по UART от внешнего устройства, в реальном устройстве это роутер с измененной прошивкой, который принимает команды от сервера, и контролирует работоспособность устройств (видеокамера, GPS и еще там что-то) в служебном авто.

- отправка HTTP запроса/ссылка на сервер - ведение лога состояний внешних устройств

- выполнение команд по звонку (DTMF)

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

 

mrgreen
Offline
Зарегистрирован: 13.11.2018

andycat пишет:

mrgreen пишет:

И действительно, может быть у когото есть готовый вариант что бы только поправить? 

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

Есть готовый такой вариант (4990 рублей):

- прием команд по СМС по разрешенному списку (в скетче задается)

- отправка подтверждений/команд по СМС

- прием команд/данных по UART от внешнего устройства, в реальном устройстве это роутер с измененной прошивкой, который принимает команды от сервера, и контролирует работоспособность устройств (видеокамера, GPS и еще там что-то) в служебном авто.

- отправка HTTP запроса/ссылка на сервер - ведение лога состояний внешних устройств

- выполнение команд по звонку (DTMF)

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

 

 

Ок. Можно начать с самого простого.

1. Что бы просто при звонке из белого списка открывались ворота, при повторном закрывались. 

2. Добавление/удаление номеров по смс (с телефона администратора)

Логи и прочее пока не нужно. Хотел бы увидеть цену в районе 1000р, а последующие доработки обсудеть отдельно.

 

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

mrgreen - мой вам совет, не делайте по звонку. это дико неудобно. Купите вот таких вот брелков (на Али от 100 рублей) и раздайте членам СНТ.

На каждый брелок зашейте свой код - так вы сможете регулировать, кому открывать, кому нет. И код будет проще

phoenixoid
Offline
Зарегистрирован: 14.07.2015

Со ста номерами, воможностью их удобного просмотра, логами и прочим от 7999 рублей. Простите, но это не 30 минут. Это дня два придется убить на код и отладку...

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

mrgreen пишет:

 Хотел бы увидеть цену в районе 1000р, а последующие доработки обсудеть отдельно.

я пас...

1. Тут уже неоднократно обсуждали - по самому минимальному день работы - 2000 рублей и то не МСК, то что вы перечислили вместе с тестированием минимум пару дней.

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

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

mrgreen пишет:

Хотел бы увидеть цену в районе 1000р, а последующие доработки обсудеть отдельно.

нереально, в таком случае ищите готовое в инете и сами дорабатывайте, готовых скетчей "включение чего-либо по звонку/СМС" - в инете сотни

mrgreen
Offline
Зарегистрирован: 13.11.2018

b707 пишет:

mrgreen - мой вам совет, не делайте по звонку. это дико неудобно. Купите вот таких вот брелков (на Али от 100 рублей) и раздайте членам СНТ.

На каждый брелок зашейте свой код - так вы сможете регулировать, кому открывать, кому нет. И код будет проще

 

Изначально с этого и начинал. Но:

1. Представьте что хозяин участка с пультом далеко от ворот, а к нему приехали гости. Очень не удобно ехать к воротам - открывать дверь.

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

3. Да и пенсионеров много, они запутаются в кнопках на пульте. Куда проще позвонить на номер ворот и все)

mrgreen
Offline
Зарегистрирован: 13.11.2018

b707 пишет:

mrgreen пишет:

Хотел бы увидеть цену в районе 1000р, а последующие доработки обсудеть отдельно.

нереально, в таком случае ищите готовое в инете и сами дорабатывайте, готовых скетчей "включение чего-либо по звонку/СМС" - в инете сотни

Вот есть такой примерно. https://www.youtube.com/watch?v=qh7dqAzKq0Y

Но там нет функции добавление номеров по смс.

Может быть кто то доработает ?

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

mrgreen пишет:

3. Да и пенсионеров много, они запутаются в кнопках на пульте. Куда проще позвонить на номер ворот и все)

это вам так кажется. На самом деле пульт в разы проще телефона - делаете ВСЕ 4 кнопки на открытие ворот - запутаться невозможно.

mrgreen
Offline
Зарегистрирован: 13.11.2018

b707 пишет:

mrgreen пишет:

3. Да и пенсионеров много, они запутаются в кнопках на пульте. Куда проще позвонить на номер ворот и все)

это вам так кажется. На самом деле пульт в разы проще телефона - делаете ВСЕ 4 кнопки на открытие ворот - запутаться невозможно.

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

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

mrgreen пишет:

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

с брелками тоже придется код писать....

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

RTU5015
RTU5024
RTU5025

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

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

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

andycat пишет:

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

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

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

phoenixoid
Offline
Зарегистрирован: 14.07.2015

mrgreen пишет:

andycat пишет:

mrgreen пишет:

И действительно, может быть у когото есть готовый вариант что бы только поправить? 

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

Есть готовый такой вариант (4990 рублей):

- прием команд по СМС по разрешенному списку (в скетче задается)

- отправка подтверждений/команд по СМС

- прием команд/данных по UART от внешнего устройства, в реальном устройстве это роутер с измененной прошивкой, который принимает команды от сервера, и контролирует работоспособность устройств (видеокамера, GPS и еще там что-то) в служебном авто.

- отправка HTTP запроса/ссылка на сервер - ведение лога состояний внешних устройств

- выполнение команд по звонку (DTMF)

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

 

 

Ок. Можно начать с самого простого.

1. Что бы просто при звонке из белого списка открывались ворота, при повторном закрывались. 

2. Добавление/удаление номеров по смс (с телефона администратора)

Логи и прочее пока не нужно. Хотел бы увидеть цену в районе 1000р, а последующие доработки обсудеть отдельно.

 

За эти 2 хотелки 1500. 

mrgreen
Offline
Зарегистрирован: 13.11.2018

b707 пишет:

andycat пишет:

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

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

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

Да, часть нелательщиков есть, но их не много, 15% от общего числа.. "Вы сначала сделайте, потом мы деньги заплатим". А на что делать если денег нет?

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

mrgreen
Offline
Зарегистрирован: 13.11.2018

Скажите Ваши контакты, обсудим. 

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

mrgreen пишет:

А на машине только те кто не имеет долгов, есть решение общего собрания.

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

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

 

Вообще, конечно, если "отказников" всего 15% - непонятно. в чем проблема. Соберите деньги с оставшихся 85% и сделайте. Или они тоже согласны только на словах? :)

mrgreen
Offline
Зарегистрирован: 13.11.2018

b707 пишет:

mrgreen пишет:

А на машине только те кто не имеет долгов, есть решение общего собрания.

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

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

 

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

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

mrgreen пишет:

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

проезд отдельно, долги отдельно. Причем незаконное ограничение доступа куда более простое дело (не в вашу пользу), чем взыскание долгов, которые должник еще и оспорить может.

Ну да ладно, это уже оффтоп.

mrgreen
Offline
Зарегистрирован: 13.11.2018

trembo пишет:

RTU5015
RTU5024
RTU5025

 

Спасибо, подходящий вариант. 

phoenixoid
Offline
Зарегистрирован: 14.07.2015
karamzin01
Offline
Зарегистрирован: 08.03.2018

Плюсую!
0
Минусую!
0
р е а л и з у е м о - maslachenko767@mail.ru

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

mrgreen пишет:

Но все же уверен, с телефона удобнее, и нет дополнительных брелков на ключах. телефон у всех есть, и на брелки тратиться не нужно.

вы просто не представляете себе сложность и стоимость ведения учёта, запись и удаление номеров (100 штук) в белом списке с помощью смс.

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

vvadim пишет:

запись и удаление номеров 

что там сложного? кроме как уместить 100 номеров в eeprom просто невозможно :)

вот древний но рабочий код который прекрасно и читает и выводит и сохраняет номера по СМС

#include <avr/wdt.h>
#include <EEPROM.h>
// address 0 = count control users phone
// address 1.... control users phones, first char - A - active D - deleted, last char = 0
#include "a6modem.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RCSwitch.h>

#define max_time_read_sms 120000UL // 2min
#define max_time_read_command 10000UL // 10sec
#define startEEPROMmessages 128 // 0 position = byte - current save posifion from 0
#define endEEPROMmessages 383
#define max_count_users_phone 6
#define max_len_sms 252
#define keypad_pin A0
#define min_time_period_key_press 1000
#define alarm_pin A1
#define rc_reciv_pin 2
#define ds18b20_pin 3
#define period_get_internal_temp 317947 // ~ 5 min
#define pos_eeprom_relay1_mode 456 // 0 or FF - off 12 -on
#define pos_eeprom_relay2_mode 458 // 0 or FF - off 21 -on
#define pos_eeprom_count_reset_timeout 454

OneWire oneWire(ds18b20_pin);
DallasTemperature sensors(&oneWire);
RCSwitch mySwitch = RCSwitch();

unsigned long time_read_sms;
unsigned long time_read_command;
unsigned long time_unpress_key;
byte gsmmode, submode;
char OPSname[] = "Russia00";
char OPSbalance[] = "*99999#";
char* UnitCommands[] = {"addphone", "delphone", "getuptime", "getbalance", "gettemp", "resetmodem", "relay1on", "relay1off", "relay2on", "relay2off", "getrelay", "resetdevice"};
char sender[24];
char smsmsg[max_len_sms];
char begstr[] = "~NEWsSMS~";
char endstr[] = "~SUCCSMS~";
boolean sw_lcd_light;
unsigned long time_sw_lcd_light;
boolean req_temp;
byte internal_temp;
byte external_temp;
unsigned long time_get_internal_temp;
unsigned long time_req_internal_temp;
word mas_str_temp[10];
byte med_str_pos = 0;
byte med_str_cnt = 0;
boolean minus_str_temp = false;

void setup() {
  // put your setup code here, to run once:
  firststart();
}

void loop() {
  // put your main code here, to run repeatedly:
  wdt_reset();
  unsigned long current_millis = millis();
  // lcd backlight control
  if (!sw_lcd_light) {
    word palm = analogRead(alarm_pin);
    if (palm < 500) {
      time_sw_lcd_light = current_millis;
      sw_lcd_light = true;
      digitalWrite(10, HIGH);
    }
  } else {
    if ((current_millis - time_sw_lcd_light) >= 30000) { // 30 sec - lcd light on
      sw_lcd_light = false;
      digitalWrite(10, LOW);
    }
  }
  // end lcd backlight control
  // get ext temp
  if (mySwitch.available()) {
    unsigned long receivedCode =  mySwitch.getReceivedValue();
    mySwitch.resetAvailable();
    if ((receivedCode >= 11500UL) && (receivedCode <= 14750UL)) {
      receivedCode -= 11500;
      if (((receivedCode >= 2000UL) && (receivedCode <= 2600UL)) || ((receivedCode >= 0UL) && (receivedCode <= 400UL))) {
        if ((receivedCode <= 400UL)) {
          receivedCode = 2000UL - receivedCode;
        }
        // correct temp
        if (receivedCode <= 1900UL) {
          receivedCode -= 12UL; // 1.2 degree
        } else {
          if (receivedCode <= 1950UL) {
            receivedCode -= 8UL; // 0.8 degree
          }
          else {
            if (receivedCode <= 1999UL) {
              receivedCode -= 5UL; // 0.5 degree
            }
          }
        }
        // --
        mas_str_temp[med_str_pos] = (word)(receivedCode);
        if ((++med_str_pos) >= 10) {
          med_str_pos = 0;
        }
        if ((++med_str_cnt) >= 10) {
          med_str_cnt = 10;
        }
        word sum_temp = 0;
        for (int i = 0; i < med_str_cnt; ++i) {
          sum_temp += mas_str_temp[i];
        }
        sum_temp /= med_str_cnt;
        if (sum_temp < 2000) {
          minus_str_temp = true;
          sum_temp = 2000 - sum_temp;
        } else {
          minus_str_temp = false;
          sum_temp -= 2000;
        }
        sum_temp /= 10;
        external_temp = (byte)(sum_temp);
      }
    }
  }
  // end get ext temp
  byte result = a6work();
  if ((result == 1) || (result == 2)) {
    if (result == 1) {
      domainmode();
    } else {
      //timeout
      byte br = EEPROM.read(pos_eeprom_count_reset_timeout);
      if (br == 0xFF) br = 0;
      ++br;
      EEPROM.write(pos_eeprom_count_reset_timeout, br);
      wdt_disable();
      a6resetmodem();
      unsigned long delp = millis(); while ((millis() - delp) <= 20000); // boot modem
      firststart();
    }
  } else {
    // other action
    // read sms mode
    if ((current_millis - time_read_sms) >= max_time_read_sms) {
      if (gsmmode == 1) {
        if (a6sendcmd("AT+CMGL=4", "OK", "", "", true) == 1) { // read SMS, =0 unread, =4 all
          gsmmode = 2; submode = 0; // mode read sms
          time_read_sms = current_millis; // after sucess send command read sms
        }
      }
    }
    // end read sms mode
    // read sms from eeprom for execute comand
    if ((current_millis - time_read_command) >= max_time_read_command) {
      if (gsmmode == 1) {
        time_read_command = current_millis;
        readSMSforCommand();
      }
    }
    // end read command
    // read key pad
    if (gsmmode == 1) {
      if ((current_millis - time_unpress_key) >= min_time_period_key_press) {
        word kp = analogRead(keypad_pin);
        byte key_mode;
        if ((kp > 600) && (kp < 700)) {
          key_mode = 0;
        } else {
          if ((kp > 370) && (kp < 450)) {
            key_mode = 1;
          } else {
            if ((kp > 80) && (kp < 120)) {
              key_mode = 2;
            } else {
              if ((kp > 216) && (kp < 296)) {
                key_mode = 3;
              } else {
                if (kp < 20) {
                  key_mode = 4;
                } else {
                  key_mode = 5; // not press
                }
              }
            }
          }
        }
        if (key_mode < 5) {
          time_unpress_key = current_millis;
          switch (key_mode) {
            case 0: {
                char strtemp[4];
                SendStrToLCD("Int=");
                strtemp[0] = '0' + internal_temp / 10;
                strtemp[1] = '0' + internal_temp % 10;
                strtemp[2] = 0;
                SendStrToLCD(strtemp);
                SendStrToLCD(" Ext=");
                if (minus_str_temp) strtemp[0] = '-'; else strtemp[0] = '+';
                strtemp[1] = '0' + external_temp / 10;
                strtemp[2] = '0' + external_temp % 10;
                strtemp[3] = 0;
                SendStrToLCD(strtemp);
                SendStrToLCD(" ");
                break;
              }
            case 1: {
                if (a6sendcmd("AT+CREG?", "OK", "", "", true) == 1) {
                  gsmmode = 3; submode = 1;
                }
                break;
              }
            case 2: {
                byte i = 0;
                while ((smsmsg[i] = OPSname[i]) != 0 ) ++i;
                smsmsg[i] = ' '; ++i;
                i = addTextUptime(i);
                smsmsg[i] = 0;
                SendStrToLCD(smsmsg);
                break;
              }
            case 3: {
                gsmmode = 100;
                // show phones from eeprom
                byte pc = EEPROM.read(0);
                if (pc == 0xFF) pc = 0;
                for (byte i = 0; ((i < pc) && (i < max_count_users_phone)); ++i) {
                  byte possend = 0; boolean fle = true;
                  word startpos = 1 + i * 14;
                  if (EEPROM.read(startpos) == 'A') sender[possend] = 'A'; else sender[possend] = 'D';
                  ++possend; sender[possend] = ' '; ++possend;
                  byte j = 0;
                  while (EEPROM.read(startpos + j + 1) != 0) {
                    sender[possend] = EEPROM.read(startpos + j + 1);
                    ++j; ++possend;
                  }
                  sender[possend] = ' '; ++possend; sender[possend] = 0;
                  SendStrToLCD(sender);
                  unsigned long delp = millis(); while ((millis() - delp) <= 2000);
                  wdt_reset();
                }
                // end show phones
                resetModeAndClearRespBuf();
                break;
              }
            case 4: {
                if (a6sendcmd("AT+CSQ", "OK", "", "", true) == 1) {
                  gsmmode = 3; submode = 1;
                }
                break;
              }
            default: {
              }
          }
        }
      }
    }
    // end key pad
    // req temp
    if ((current_millis - time_req_internal_temp) >= period_get_internal_temp) {
      if ((gsmmode == 1) && (!req_temp)) {
        time_req_internal_temp = current_millis;
        sensors.requestTemperatures();
        req_temp = true;
        time_get_internal_temp = current_millis;
      }
    }
    // end req temp -> get temp
    if ((current_millis - time_get_internal_temp) >= 1200) {
      if ((gsmmode == 1) && (req_temp)) {
        internal_temp = sensors.getTempCByIndex(0);
        req_temp = false;
      }
    }
    // end get internal temp
  }
}

void domainmode() {
  switch (gsmmode) {
    case 0: { // init modem
        switch (submode) {
          case 0: { // wait reponse first command AT
              if (a6sendcmd("ATE0", "OK", "", "", true) == 1) submode = 1; // no echo
              break;
            }
          case 1: { // wait reponse command ATE0
              if (a6sendcmd("ATV1", "OK", "", "", true) == 1) submode = 2; // get text for error
              break;
            }
          case 2: { // wait reponse command ATV1
              if (a6sendcmd("AT+CMEE=2", "OK", "", "", true) == 1) submode = 3; // get full text error
              break;
            }
          case 3: { // wait reponse command cmee
              if (a6sendcmd("AT+CLIP=1", "OK", "", "", true) == 1) submode = 4; // on aon
              break;
            }
          case 4: { // wait reponse command clip
              if (a6sendcmd("ATS0=3", "OK", "", "", true) == 1) submode = 5; // 3 ring
              break;
            }
          case 5: { // wait reponse command ats
              unsigned long delp = millis(); while ((millis() - delp) <= 30000); //delay for registration
              if (a6sendcmd("AT+CREG?", "+CREG: 1,1", "OK", "", true) == 1) submode = 6; // true registration
              //if (a6sendcmd("AT+CREG?", "OK", "", "", true) == 1) submode = 6; // registration
              break;
            }
          case 6: { // wait registration
              if (a6sendcmd("AT+CMGF=0", "OK", "", "", true) == 1) submode = 7; // mode SMS = PDU
              break;
            }
          case 7: { // wait mode sms
              if (a6sendcmd("AT+CMGD=1,4", "OK", "", "", true) == 1) submode = 8; // delete all sms
              break;
            }
          case 8: { // wait del sms
              if (a6sendcmd("AT+COPS?", "+COPS:", "OK", "", true) == 1) submode = 9; // load operator data
              break;
            }
          case 9: { // decode operator data
              a6getopsname(OPSname, OPSbalance);
              resetModeAndClearRespBuf(); // init ok
              digitalWrite(LED_BUILTIN, HIGH);
              SendByteToLCD(32, true);
              SendByteToLCD(223, false);
              SendByteToLCD(32, true);
              SendByteToLCD(226, false);
              SendByteToLCD(32, true);
              SendByteToLCD(241, false);
              SendByteToLCD(229, false);
              SendByteToLCD(242, false);
              SendByteToLCD(232, false);
              SendByteToLCD(32, true);
              SendByteToLCD('!', true);
              SendByteToLCD(32, true);
              wdt_enable(WDTO_8S);
              break;
            }
        }
        break;
      }
    case 1: { // main loop
        break;
      }
    case 2: { // mode read sms
        switch (submode) {
          case 0: {
              byte countsms = a6getcountsms();
              if (countsms > 0) {
                while (countsms > 0) { // loop by sms
                  a6readsms(countsms, sender, smsmsg);
                  if ((getAllowCommandPhone(sender) == 1) || (getAllowCommandPhone(sender) == 2)) {
                    // save sms to eeprom
                    saveSMStoEEPROM(sender, smsmsg);
                  }
                  // - end loop sms
                  --countsms;
                }
                // delete all sms
                if (a6sendcmd("AT+CMGD=1,4", "OK", "", "", true) == 1) submode = 1;
              } else {
                resetModeAndClearRespBuf(); // no sms
              }
              break;
            }
          default: {
              resetModeAndClearRespBuf();
            }
        }
        break;
      }
    case 3: { // mode send sms and mode test commands
        switch (submode) {
          case 0: {
              if (a6sendcmd(smsmsg, "+CMGS:", "OK", "", false) == 1) submode = 1;
              break;
            }
          default: {
              resetModeAndClearRespBuf();
            }
        }
        break;
      }
    case 4: { // mode get balance
        switch (submode) {
          case 0: {
              // decode USSD
              // send SMS text from USSD
              resetModeAndClearRespBuf(); // temp text, need submode = 1
              break;
            }
          default: {
              resetModeAndClearRespBuf();
            }
        }
        break;
      }
    default: {
        a6clearrespbuf();
      }
  }
}

void firststart() {
  pinMode(A0, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
  pinMode(10, OUTPUT);
  pinMode(rc_reciv_pin, INPUT);
  digitalWrite(10, LOW); // LCD backlight control
  sensors.begin();
  time_req_internal_temp = 0;
  req_temp = false;
  sw_lcd_light = false;
  gsmmode = 0; submode = 0; // start
  time_read_sms = 0UL; time_read_command = 0UL;
  mySwitch.enableReceive(0);
  pinMode(A2, OUTPUT); // relay 1
  pinMode(A3, OUTPUT); // relay 2
  // on off relay
  if (EEPROM.read(pos_eeprom_relay1_mode) == 12) digitalWrite(A2, LOW); else digitalWrite(A2, HIGH);
  if (EEPROM.read(pos_eeprom_relay2_mode) == 21) digitalWrite(A3, LOW); else digitalWrite(A3, HIGH);
  // end on off relay
  pinMode(A4, OUTPUT); digitalWrite(A4, LOW);
  pinMode(A5, OUTPUT); digitalWrite(A5, LOW);
  a6initmodem(9600); // work - hard uart
}

void SerialPrintWin1251(char* textsms) {
  byte i = 0;
  while (textsms[i] != 0) {
    byte wb = textsms[i];
    if (wb <= 128) {
      Serial.write(wb);
    } else {
      switch (wb) {
        case 168: {
            Serial.write(208); Serial.write(101);
            break;
          }
        case 184: {
            Serial.write(209); Serial.write(145);
            break;
          }
        default: {
            if (wb < 192) {
              Serial.write(wb);
            } else {
              if (wb < 240) {
                Serial.write(208); Serial.write(wb - 48);
              } else {
                Serial.write(209); Serial.write(wb - 112);
              }
            }
          }
      }
    }
    ++i;
  }
}

byte getAllowCommandPhone(char* sender) {
  if (strPos(sender, ADMIN_PHONE) >= 0) return 2;
  word rb = FindPhomeFromUsersList(sender);
  if ((rb > 1000) && (rb < 2000)) {
    return 1;
  } else {
    return 0;
  }
}

void saveSMStoEEPROM(char* sender, char* textsms) {
  byte l1 = strlen(sender); byte l2 = strlen(textsms);
  word lastpos = EEPROM.read(startEEPROMmessages);
  if ((lastpos == 0xFF) || ((lastpos + l1 + l2 + 12) >= (endEEPROMmessages - startEEPROMmessages))) lastpos = 0;
  lastpos += (startEEPROMmessages + 1); byte i = 0;
  while (begstr[i] != 0) {
    EEPROM.write(lastpos + i, begstr[i]); ++i;
  }
  EEPROM.write(lastpos + i, 0);
  lastpos += (i + 1); i = 0;
  while (sender[i] != 0) {
    EEPROM.write(lastpos + i, sender[i]); ++i;
  }
  EEPROM.write(lastpos + i, 0);
  lastpos += (i + 1); i = 0;
  while (textsms[i] != 0) {
    EEPROM.write(lastpos + i, textsms[i]); ++i;
  }
  EEPROM.write(lastpos + i, 0);
  lastpos += (i + 1);
  EEPROM.write(startEEPROMmessages, (lastpos - startEEPROMmessages - 1));
}

void readSMSforCommand() {
  word lastpos = startEEPROMmessages + 1;
  word i, j, k;
m3:  i = 0; j = 0; k = 0;
m1:  byte eb = EEPROM.read(lastpos + i);
  if ((eb == begstr[i]) || (eb == endstr[i])) {
    if (eb == begstr[i]) ++j; if (eb == endstr[i]) ++k;
    if ((++i) >= 9) goto m2;
    goto m1;
  } else {
    return;
  }
m2:  if (k == 9) {
    // skip -> new sms
    lastpos += (k + 1);
    // find 0 and 0
    i = 0; while (EEPROM.read(lastpos + i) != 0) ++i;
    lastpos += (i + 1);
    if (lastpos >= endEEPROMmessages) return;
    i = 0; while (EEPROM.read(lastpos + i) != 0) ++i;
    lastpos += (i + 1);
    if (lastpos >= endEEPROMmessages) return;
    goto m3;
  }
  if (j == 9) {
    // save to eeprom ~SUCCSMS~
    i = 0;
    while ((endstr[i]) != 0) {
      EEPROM.write((lastpos + i), endstr[i]);
      ++i;
    }
    // new command
    lastpos += (j + 1); i = 0;
    while ((sender[i] = EEPROM.read(lastpos + i)) != 0) ++i;
    sender[i] = 0;
    lastpos += (i + 1); i = 0;
    while ((smsmsg[i] = EEPROM.read(lastpos + i)) != 0) ++i;
    smsmsg[i] = 0;
    lastpos += (i + 1);
    // find command
    j = 0; // num found command
    for (i = 0; i < 12; ++i) { // 12 commands
      if (strPos(smsmsg, UnitCommands[i]) >= 0) {
        j = i + 1;
        break;
      }
    }
    switch (j) {
      case 1: {
          if (getAllowCommandPhone(sender) != 2) return; // command for admin only
          if (CutPhoneFromText(smsmsg) != 1) return;
          // save phone to eeprom
          AddPhoneToUsersList(smsmsg);
          break;
        }
      case 2: {
          if (getAllowCommandPhone(sender) != 2) return; // command for admin only
          if (CutPhoneFromText(smsmsg) != 1) return;
          // delete phone from eeprom
          DelPhoneToUsersList(smsmsg);
          break;
        }
      case 3: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          // prepare send text
          i = 0;
          while ((smsmsg[i] = OPSname[i]) != 0 ) ++i;
          smsmsg[i] = ' '; ++i;
          i = addTextUptime(i);
          smsmsg[i] = 0;
          sendSMS();
          break;
        }
      case 4: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          char strcmd[] = "AT+CUSD=1,";
          i = 0;
          while ((sender[i] = strcmd[i]) != 0) ++i;
          j = 0;
          while ((sender[i] = OPSbalance[j]) != 0) {
            ++i; ++j;
          }
          sender[i] = ','; ++i; sender[i] = '1'; ++i; sender[i] = '5'; ++i;
          sender[i] = 0;
          a6sendcmd(sender, "OK", "+CUSD: 2,", ",72", true);
          gsmmode = 4; submode = 0;
          break;
        }
      case 5: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          // prepare send text
          char strtemp[] = "Int=";
          i = 0;
          while ((smsmsg[i] = strtemp[i]) != 0 ) ++i;
          strtemp[0] = '0' + internal_temp / 10;
          strtemp[1] = '0' + internal_temp % 10;
          strtemp[2] = 0;
          j = 0;
          while ((smsmsg[i] = strtemp[j]) != 0 ) {
            ++i; ++j;
          }
          smsmsg[i] = ','; ++i;
          strtemp[0] = 'E'; strtemp[1] = 'x'; strtemp[2] = 't'; strtemp[3] = '='; strtemp[4] = 0;
          j = 0;
          while ((smsmsg[i] = strtemp[j]) != 0 ) {
            ++i; ++j;
          }
          if (minus_str_temp) strtemp[0] = '-'; else strtemp[0] = '+';
          strtemp[1] = '0' + external_temp / 10;
          strtemp[2] = '0' + external_temp % 10;
          strtemp[3] = 0;
          j = 0;
          while ((smsmsg[i] = strtemp[j]) != 0 ) {
            ++i; ++j;
          }
          smsmsg[i] = ','; ++i;
          i = addTextUptime(i);
          smsmsg[i] = 0;
          sendSMS();
          break;
        }
      case 6: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          byte br = EEPROM.read(pos_eeprom_count_reset_timeout);
          if (br == 0xFF) br = 0;
          ++br;
          EEPROM.write(pos_eeprom_count_reset_timeout, br);
          wdt_disable();
          a6resetmodem();
          unsigned long delp = millis(); while ((millis() - delp) <= 20000); // boot modem
          firststart();
          break;
        }
      case 7: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          // relay 1 ON
          EEPROM.write(pos_eeprom_relay1_mode, 12);
          digitalWrite(A2, LOW);
          unsigned long delp = millis(); while ((millis() - delp) <= 1000);
          // relay 2 ON
          EEPROM.write(pos_eeprom_relay2_mode, 21);
          digitalWrite(A3, LOW);
          break;
        }
      case 8: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          // relay 1 OFF
          EEPROM.write(pos_eeprom_relay1_mode, 00);
          digitalWrite(A2, HIGH);
          unsigned long delp = millis(); while ((millis() - delp) <= 1000);
          // relay 2 OFF
          EEPROM.write(pos_eeprom_relay2_mode, 00);
          digitalWrite(A3, HIGH);
          break;
        }
      case 9: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          // relay 2 ON
          EEPROM.write(pos_eeprom_relay2_mode, 21);
          digitalWrite(A3, LOW);
          unsigned long delp = millis(); while ((millis() - delp) <= 1000);
          // relay 1 ON
          EEPROM.write(pos_eeprom_relay1_mode, 12);
          digitalWrite(A2, LOW);
          break;
        }
      case 10: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          // relay 2 OFF
          EEPROM.write(pos_eeprom_relay2_mode, 00);
          digitalWrite(A3, HIGH);
          unsigned long delp = millis(); while ((millis() - delp) <= 1000);
          // relay 1 OFF
          EEPROM.write(pos_eeprom_relay1_mode, 00);
          digitalWrite(A2, HIGH);
          break;
        }
      case 11: {
          if (getAllowCommandPhone(sender) == 0) return; // command for any user
          // prepare send text
          char strtemp[] = "Rl1";
          i = 0;
          while ((smsmsg[i] = strtemp[i]) != 0 ) ++i;
          if (EEPROM.read(pos_eeprom_relay1_mode) == 12) {
            strtemp[0] = 'o'; strtemp[1] = 'n'; strtemp[2] = 0;
          } else {
            strtemp[0] = 'o'; strtemp[1] = 'f'; strtemp[2] = 'f'; strtemp[3] = 0;
          }
          j = 0;
          while ((smsmsg[i] = strtemp[j]) != 0 ) {
            ++i; ++j;
          }
          smsmsg[i] = ','; ++i;
          strtemp[0] = 'R'; strtemp[1] = 'l'; strtemp[2] = '2'; strtemp[3] = 0;
          j = 0;
          while ((smsmsg[i] = strtemp[j]) != 0 ) {
            ++i; ++j;
          }
          if (EEPROM.read(pos_eeprom_relay2_mode) == 21) {
            strtemp[0] = 'o'; strtemp[1] = 'n'; strtemp[2] = 0;
          } else {
            strtemp[0] = 'o'; strtemp[1] = 'f'; strtemp[2] = 'f'; strtemp[3] = 0;
          }
          j = 0;
          while ((smsmsg[i] = strtemp[j]) != 0 ) {
            ++i; ++j;
          }
          smsmsg[i] = ','; ++i;
          i = addTextUptime(i);
          smsmsg[i] = 0;
          sendSMS();
          break;
        }
      case 12: {
          if (getAllowCommandPhone(sender) != 2) return; // command for admin only
          // test WDT
          unsigned long delp = millis(); while ((millis() - delp) <= 20000); // reboot device after 8 sec
          break;
        }
      default: {
        }
    }
  } else {
    return;
  }
}

byte CutPhoneFromText(char* smstxt) {
  int pp = strPos(smstxt, "+79");
  if (pp > 0) {
    byte cb = 0;
    for (byte i = 0; i < 12; ++i) { // +7 and 10 digit
      smstxt[cb] = smstxt[pp + cb]; ++cb;
    }
    smstxt[cb] = 0;
    if (cb == 12) return 1;
  }
  return 0;
}

void AddPhoneToUsersList(char* phoneNumber) {
  word rb = FindPhomeFromUsersList(phoneNumber);
  if (rb > 2000) {
    // set active number
    EEPROM.write((rb - 2000), 'A');
    return;
  }
  if (rb > 1000) {
    return;
  }
  // add new number
  byte pc = EEPROM.read(0);
  if (pc == 0xFF) pc = 0;
  if (pc >= max_count_users_phone) pc = 5; // last number;
  word startpos = 1 + (pc * 14);
  byte i = 0;
  EEPROM.write(startpos, 'A');
  while (phoneNumber[i] != 0) {
    EEPROM.write((startpos + 1 + i), phoneNumber[i]);
    ++i;
  }
  EEPROM.write((startpos + 1 + i), 0);
  ++pc;
  EEPROM.write(0, pc);
}

void DelPhoneToUsersList(char* phoneNumber) {
  word rb = FindPhomeFromUsersList(phoneNumber);
  if (rb > 1000) {
    // set delete number
    EEPROM.write((rb - 1000), 'D');
    return;
  }
}

word FindPhomeFromUsersList(char* phoneNumber) {
  byte pc = EEPROM.read(0);
  if (pc == 0xFF) pc = 0;
  if (pc == 0) {
    return 0;
  }
  byte i; boolean fla = false;
  for (i = 0; ((i < pc) && (i < max_count_users_phone)); ++i) {
    boolean fle = true;
    word startpos = 1 + i * 14;
    if (EEPROM.read(startpos) == 'A') fla = true; else fla = false;
    byte j = 0;
    while (phoneNumber[j] != 0) {
      if (phoneNumber[j] != EEPROM.read(startpos + j + 1)) {
        fle = false;
        break;
      }
      ++j;
    }
    if (fle) {
      if (fla) {
        return (1000 + startpos);
      } else {
        return (2000 + startpos);
      }
    }
  }
  return 0;
}

byte addTextUptime(byte firstpos) {
  unsigned long cml = millis() / 1000UL;
  byte days = cml / 86400;
  byte hours = (cml % 86400) / 3600;
  byte mins = ((cml % 86400) % 3600) / 60;
  if (days > 9) {
    smsmsg[firstpos] = (days / 10) + '0';
    ++firstpos;
  }
  smsmsg[firstpos] = (days % 10) + '0'; ++firstpos;
  smsmsg[firstpos] = 228; ++firstpos; smsmsg[firstpos] = 237; ++firstpos; smsmsg[firstpos] = '.'; ++firstpos;
  if (hours > 9) {
    smsmsg[firstpos] = (hours / 10) + '0';
    ++firstpos;
  }
  smsmsg[firstpos] = (hours % 10) + '0'; ++firstpos;
  smsmsg[firstpos] = 247; ++firstpos; smsmsg[firstpos] = 224; ++firstpos; smsmsg[firstpos] = 241; ++firstpos;
  smsmsg[firstpos] = '.'; ++firstpos;
  if (mins > 9) {
    smsmsg[firstpos] = (mins / 10) + '0';
    ++firstpos;
  }
  smsmsg[firstpos] = (mins % 10) + '0'; ++firstpos;
  smsmsg[firstpos] = 236; ++firstpos; smsmsg[firstpos] = 232; ++firstpos; smsmsg[firstpos] = 237; ++firstpos;
  smsmsg[firstpos] = '.'; ++firstpos;
  // add count timeout reset
  smsmsg[firstpos] = 'R'; ++firstpos;
  byte br = EEPROM.read(pos_eeprom_count_reset_timeout);
  smsmsg[firstpos] = '0' + (br / 100); ++firstpos;
  smsmsg[firstpos] = '0' + ((br % 100) / 10); ++firstpos;
  smsmsg[firstpos] = '0' + ((br % 100) % 10); ++firstpos;
  smsmsg[firstpos] = '.'; ++firstpos;
  return firstpos;
}

void sendSMS() {
  // convert msg to pdu format
  byte lenTextByChar = strlen(smsmsg);
  // move text to end buf
  byte i, j;
  for (i = 0; i < lenTextByChar; ++i) {
    smsmsg[max_len_sms - lenTextByChar + i] = smsmsg[i];
  }
  byte curr_pos_pdu = 0;
  smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; // SCA field
  smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '1'; ++curr_pos_pdu; // PDU type
  smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; // MR
  byte lenSenderPhone = strlen(sender);
  if (lenSenderPhone != 12) return;
  smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = 'B'; ++curr_pos_pdu; // DA-PL
  smsmsg[curr_pos_pdu] = '9'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '1'; ++curr_pos_pdu; // DA-PT
  // convert sender number
  for (i = 0; i < lenSenderPhone; ++i) {
    sender[i] = sender[i + 1];
  }
  sender[lenSenderPhone - 1] = 'F'; sender[lenSenderPhone] = 0;
  for (i = 0; i < lenSenderPhone; i += 2) {
    j = sender[i + 1];
    sender[i + 1] = sender[i];
    sender[i] = j;
  }
  for (i = 0; i < lenSenderPhone; ++i) { // DA-RP
    smsmsg[curr_pos_pdu] = sender[i];
    ++curr_pos_pdu;
  }
  smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; // PID field
  smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '8'; ++curr_pos_pdu; // DCS field
  lenTextByChar *= 2; // UDL
  byte bb = lenTextByChar / 16;
  if (bb < 10) {
    smsmsg[curr_pos_pdu] = (bb + '0'); ++curr_pos_pdu;
  } else {
    smsmsg[curr_pos_pdu] = (bb + '0' + 7); ++curr_pos_pdu;
  }
  bb = lenTextByChar % 16;
  if (bb < 10) {
    smsmsg[curr_pos_pdu] = (bb + '0'); ++curr_pos_pdu;
  } else {
    smsmsg[curr_pos_pdu] = (bb + '0' + 7); ++curr_pos_pdu;
  }
  // UD - text by UCS2
  for (i = 0; i < (lenTextByChar / 2); ++i) {
    bb = smsmsg[max_len_sms - (lenTextByChar / 2) + i];
    if (bb < 0x7F) {
      smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu;
      // convert to hex
      j = bb / 16;
      if (j < 10) {
        smsmsg[curr_pos_pdu] = (j + '0'); ++curr_pos_pdu;
      } else {
        smsmsg[curr_pos_pdu] = (j + '0' + 7); ++curr_pos_pdu;
      }
      j = bb % 16;
      if (j < 10) {
        smsmsg[curr_pos_pdu] = (j + '0'); ++curr_pos_pdu;
      } else {
        smsmsg[curr_pos_pdu] = (j + '0' + 7); ++curr_pos_pdu;
      }
    } else {
      switch (bb) {
        case 168: {
            smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '4'; ++curr_pos_pdu;
            smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '1'; ++curr_pos_pdu;
            break;
          }
        case 184: {
            smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '4'; ++curr_pos_pdu;
            smsmsg[curr_pos_pdu] = '5'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '1'; ++curr_pos_pdu;
            break;
          }
        default: {
            if (bb < 192) {
              smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu;
              // convert to hex
              j = bb / 16;
              if (j < 10) {
                smsmsg[curr_pos_pdu] = (j + '0'); ++curr_pos_pdu;
              } else {
                smsmsg[curr_pos_pdu] = (j + '0' + 7); ++curr_pos_pdu;
              }
              j = bb % 16;
              if (j < 10) {
                smsmsg[curr_pos_pdu] = (j + '0'); ++curr_pos_pdu;
              } else {
                smsmsg[curr_pos_pdu] = (j + '0' + 7); ++curr_pos_pdu;
              }
            } else {
              smsmsg[curr_pos_pdu] = '0'; ++curr_pos_pdu; smsmsg[curr_pos_pdu] = '4'; ++curr_pos_pdu;
              // convert to hex
              j = (bb - 176) / 16;
              if (j < 10) {
                smsmsg[curr_pos_pdu] = (j + '0'); ++curr_pos_pdu;
              } else {
                smsmsg[curr_pos_pdu] = (j + '0' + 7); ++curr_pos_pdu;
              }
              j = (bb - 176) % 16;
              if (j < 10) {
                smsmsg[curr_pos_pdu] = (j + '0'); ++curr_pos_pdu;
              } else {
                smsmsg[curr_pos_pdu] = (j + '0' + 7); ++curr_pos_pdu;
              }
            }
          }
      }
    }
  }
  // -
  smsmsg[curr_pos_pdu] = 26;
  smsmsg[curr_pos_pdu + 1] = 0;
  char strcmd[] = "AT+CMGS=";
  i = 0;
  while ((sender[i] = strcmd[i]) != 0) ++i;
  sender[i] = ((curr_pos_pdu / 2 - 1) / 10) + '0'; ++i;
  sender[i] = ((curr_pos_pdu / 2 - 1) % 10) + '0'; ++i;
  sender[i] = 0;
  a6sendcmd(sender, ">", "", "", false);
  gsmmode = 3; submode = 0;
}

void resetMode() {
  gsmmode = 1; submode = 0; // main loop
}

void resetModeAndClearRespBuf() {
  resetMode();
  a6clearrespbuf();
}

 

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

это вы к чему ?
что программа простецкая или  дешёвая))))

vk007
Offline
Зарегистрирован: 16.06.2015

andycat пишет:
уместить 100 номеров в eeprom просто невозможно :)

Возможно я что-то упускаю, но коды мобильных операторов начинаются на 9, т.е. +79 можно не хранить. Тогда максимально возможное число (для номера +7(999)999-99-99) будет 999999999 или 3B 9A C9 FF - это 4 байта. Итого 4 х 100 = 400 байт. Я нигде не ошибся?

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

vk007 пишет:

andycat пишет:
уместить 100 номеров в eeprom просто невозможно :)

Возможно я что-то упускаю, но коды мобильных операторов начинаются на 9, т.е. +79 можно не хранить. Тогда максимально возможное число (для номера +7(999)999-99-99) будет 999999999 или 3B 9A C9 FF - это 4 байта. Итого 4 х 100 = 400 байт. Я нигде не ошибся?

ну да, усложнив логику обработки, согласен - возможно.

беда в другом - что делать когда их будет например 300 :)

Update: да вы расслабьтесь :)  с ТС я уже общался, он реально понял что проще готовое устройство купить чем заказывать.

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

Приклеить еще одну обдурину сверху.

vk007
Offline
Зарегистрирован: 16.06.2015

andycat пишет:
беда в другом - что делать когда их будет например 300 :)

Взять ардуину с мегой 2560, там больше тыщи номеров влезет :) или прицепить внешнюю EEPROM.

andycat пишет:
Update: да вы расслабьтесь :)  с ТС я уже общался, он реально понял что проще готовое устройство купить чем заказывать.

А потрындеть :) Нам же это тоже интересно :)