Не взлетит скорее всего. Скорость для MQTT не подходящая и задержки. Тут лучше на ESP8266 делать имхо.
Дело не в скорости. MQTT требует сетевых взаимодействий низкого уровня - сокетов, а через GPRS реализовать их весьма затруднительно.
Что касается ESP - имеется в виду переход на WiFi? - по-моему это не замена GSM. так как GSM обычно используется там, где WiFi и прочего инета нет. Если есть сеть в любом виде - GSM вообще не нужен
Что касается ESP - имеется в виду переход на WiFi? - по-моему это не замена GSM. так как GSM обычно используется там, где WiFi и прочего инета нет. Если есть сеть в любом виде - GSM вообще не нужен
это я тоже понял, но мысль пришла управлять есп-хой по вайфай... не удалнно а локально. к примеру приехал на дачу и зашел в приложение и снял с охраны, точно так же поставить на охрану. Только этот плюс вижу, и не нужно не каких ключей для снятия с охраны городить. Вот только встает вопрос безопасности локальной сети вайфай и доступа к той же ESP
WPA2 уже взломали. GSM может быть резервным каналом оповещения. А по вайфай пушить сообщения на смартфон считай даром. Ну или да, в режиме точки доступа запускать ESP и даже можно по регистрации мобилы в домашней сети снимать с охраны. У кого как с фантазией :)
Хреново разве в Телеграм получать месседжи и рулить оттуда? ИМХО удобнее, чем смс строчить. А ботом и кнопочки можно сделать понятные.
Там, при этом "взломе", ключевое - слабые пароли, на мысли не наводит? Юзайте нормальные пароли, и все словари нервно курят в сторонке. Да и цена такого взлома - кому упёрлась какая-то ESP, которая занимается каким-то простым делом? Но нормальные пароли - ключевое, можно спокойно выдыхать и юзать WPA2, не рефлексируя.
а как быть с надежностью интернета через роутер-пров1-пров2-пров3 и т.д..?
и просто сравнить gsm связь надежность работы которой в разы больше?
так что не мелите ерундой..
Не надо быть таким категоричным. К примеру, мой домашний интернет в этом году за десять месяцев не выключался ни разу. На работе сеть похуже - иногда пропадает, но обычно не дольше, чем на 3-5 минут. А вот с глюками мобильной связи я сталкиваюсь постоянно.
Ну и не надо забывать еще один фактор. Кроме надежности сети есть еще надежность программного клиента. Библиотеки работы с TCP/IP написаны на порядок качественнее, чем либы для работы с модемом через AT команды. Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi
Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi
кривые что ?:) не смешите.. например я не использую библиотеки для GSM - просто не зачем.
это раз.
во вторых - куда такое в основном ставят? правильно - на дачу.. И будете утверждать, что там у прова и аккумы стоятна оборудовании, и все резервируется и т.д.?? ха-ха-ха...
а ваша квартира и интернет в ней - тут не причем..
для вайфая заводите отдельную ветку и делайте в ней свой проект, здесь тема о другом.
У меня на даче нет эл-ва, поэтому и остановился на варианте с gsm модемом. А wifi - это ещё и роутер вешать и опять же usb свисток... с GPRS пока не особо разобрался.
Не надо быть таким категоричным. К примеру, мой домашний интернет в этом году за десять месяцев не выключался ни разу. На работе сеть похуже - иногда пропадает, но обычно не дольше, чем на 3-5 минут. А вот с глюками мобильной связи я сталкиваюсь постоянно.
Ну и не надо забывать еще один фактор. Кроме надежности сети есть еще надежность программного клиента. Библиотеки работы с TCP/IP написаны на порядок качественнее, чем либы для работы с модемом через AT команды. Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi
В случае покушения на ваше имущество с огромной вероятностью и электроснабжение, и ваш безотказный домашний интернет будет отключен в считанные секунды щелчком автомата на лестничной площадке. И не важно оптика к вам заходит или витая пара, бокорезы никто не отменял.
b707 пишет:
А вот с глюками мобильной связи я сталкиваюсь постоянно.
Может быть стоит написать в техподдержку оператора для начала, или, в конце концов, сменить оператора?
Baks, все никак не довезут до дачи. 3 дня гонял на столе, не отключая. Но ещё есть в коде моменты которые нужно исправить, но на работу вроде не влияет
КороткоеЗамыкание и КВолк - мы оба обкурились что ли? :)
Я не продвигаю Вай-Фай (да и ГСМ) в этой теме, и потом я сразу сказал, что в местах, где нет инета - ГСМ незаменим.
Я среагировал на бредовое заявление, что инет через GPRS-модем "в разы надежнее" Вайфая. Short Circuit - не имеет значения, работаете ли вы с модемом через библиотеку или напрямую - в любом случае GPRS через АТ-команды не предполагает сколько-нибудь серьезное использование нетекстовых сетевых протоколов и сравнивать его с Wi-Fi просто смешно.
В порт ring сыпятся после того как я сам положу трубку, здесь получается: пока от модема идут сообщения в порт не выводит, а выводит когда закончена передача
Decode string:
On Your account 19.01 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
Start SMS send
Спасибо попробовал все ОК до запроса баланса.При отправке сигналкой смс о состоянии счета устройство виснет наглухо помогает только кнопка сброс.Вот кусок с терминала
Decode string:
On Your account 15.51 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
SMS send=>380662424500
SIM On Your account 15.51 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
Temp 23*C
может это длина сообщения? как его обрезать до 30 символов?
Другой вариант я вам, Паша, давно озвучивал - принимайте из модема только то, что нужно, остальное отбрасывайте. Буфером в 32 символа можно принять ответ от GPRS в 500 байт, а уж СМС-ку и подавно.
А вообще - работу с балансом, думаю, вам вообще для пользователей настраивать не надо. Пусть делают сами. Все возможные варианты строк от всех возможных операторов вы все равно в скетч не добавите - да и не нужно это. У нас тут программисткий форум, пусть попотеют хоть немного настроить скетч под себя - а то иначе это получается чистое нахлебничество.
b707, спасибо. Кто-то хочет учиться, самихоть что-то сделать, а кто-то только заливать и все)
Ну а помочь, чем могу тем и помогу. С балансом согласен, очень много разных вариантов получается.
Как вы говорите, для считывания с модема такая процедура годится, или надо что-то иное?:
while (gsm.available()) {
char ch = gsm.read();
gsmval += char(ch);
delay(5);
}
Не взлетит скорее всего. Скорость для MQTT не подходящая и задержки. Тут лучше на ESP8266 делать имхо.
Дело не в скорости. MQTT требует сетевых взаимодействий низкого уровня - сокетов, а через GPRS реализовать их весьма затруднительно.
Что касается ESP - имеется в виду переход на WiFi? - по-моему это не замена GSM. так как GSM обычно используется там, где WiFi и прочего инета нет. Если есть сеть в любом виде - GSM вообще не нужен
согласен!
это я тоже понял, но мысль пришла управлять есп-хой по вайфай... не удалнно а локально. к примеру приехал на дачу и зашел в приложение и снял с охраны, точно так же поставить на охрану. Только этот плюс вижу, и не нужно не каких ключей для снятия с охраны городить. Вот только встает вопрос безопасности локальной сети вайфай и доступа к той же ESP
Вот только встает вопрос безопасности локальной сети вайфай и доступа к той же ESP
А что не так с безопасностью там? wpa-psk/wpa2-psk - уже отменили?
WPA2 уже взломали. GSM может быть резервным каналом оповещения. А по вайфай пушить сообщения на смартфон считай даром. Ну или да, в режиме точки доступа запускать ESP и даже можно по регистрации мобилы в домашней сети снимать с охраны. У кого как с фантазией :)
Хреново разве в Телеграм получать месседжи и рулить оттуда? ИМХО удобнее, чем смс строчить. А ботом и кнопочки можно сделать понятные.
WPA2 уже взломали.
Там, при этом "взломе", ключевое - слабые пароли, на мысли не наводит? Юзайте нормальные пароли, и все словари нервно курят в сторонке. Да и цена такого взлома - кому упёрлась какая-то ESP, которая занимается каким-то простым делом? Но нормальные пароли - ключевое, можно спокойно выдыхать и юзать WPA2, не рефлексируя.
Это шутка юмора была же!
Это шутка юмора была же!
Ну тады сорь, не въехал :)
где WiFi и прочего инета нет. Если есть сеть в любом виде - GSM вообще не нужен
что вы говорите...??
а как быть с надежностью интернета через роутер-пров1-пров2-пров3 и т.д..?
и просто сравнить gsm связь надежность работы которой в разы больше?
так что не мелите ерундой..
Ну щас начнут комбайн с асфальтоукладчиком сравнивать.
а как быть с надежностью интернета через роутер-пров1-пров2-пров3 и т.д..?
и просто сравнить gsm связь надежность работы которой в разы больше?
так что не мелите ерундой..
Не надо быть таким категоричным. К примеру, мой домашний интернет в этом году за десять месяцев не выключался ни разу. На работе сеть похуже - иногда пропадает, но обычно не дольше, чем на 3-5 минут. А вот с глюками мобильной связи я сталкиваюсь постоянно.
Ну и не надо забывать еще один фактор. Кроме надежности сети есть еще надежность программного клиента. Библиотеки работы с TCP/IP написаны на порядок качественнее, чем либы для работы с модемом через AT команды. Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi
Ничего не мешает работать с модемом нёс помощью кривых либ а напрямую с модемом - я за GSM
http://food-side.com/image/data/eda5d51655e4.gif
а я за совместное использование))
в случае чего всегда есть резевный доступ или через GSM ИЛИ WIFI
кривые что ?:) не смешите.. например я не использую библиотеки для GSM - просто не зачем.
это раз.
во вторых - куда такое в основном ставят? правильно - на дачу.. И будете утверждать, что там у прова и аккумы стоятна оборудовании, и все резервируется и т.д.?? ха-ха-ха...
а ваша квартира и интернет в ней - тут не причем..
для вайфая заводите отдельную ветку и делайте в ней свой проект, здесь тема о другом.
У меня на даче нет эл-ва, поэтому и остановился на варианте с gsm модемом. А wifi - это ещё и роутер вешать и опять же usb свисток... с GPRS пока не особо разобрался.
pasha413 Ваша разработка уже стоит на своем месте и работает? или пока на столе испытываете?
Не надо быть таким категоричным. К примеру, мой домашний интернет в этом году за десять месяцев не выключался ни разу. На работе сеть похуже - иногда пропадает, но обычно не дольше, чем на 3-5 минут. А вот с глюками мобильной связи я сталкиваюсь постоянно.
Ну и не надо забывать еще один фактор. Кроме надежности сети есть еще надежность программного клиента. Библиотеки работы с TCP/IP написаны на порядок качественнее, чем либы для работы с модемом через AT команды. Так что совершенно не факт, что будет работать надежнее в конечном итоге, если рассмотреть на уровне скетча для ардуины. Я бы лично поставил на WiFi
В случае покушения на ваше имущество с огромной вероятностью и электроснабжение, и ваш безотказный домашний интернет будет отключен в считанные секунды щелчком автомата на лестничной площадке. И не важно оптика к вам заходит или витая пара, бокорезы никто не отменял.
А вот с глюками мобильной связи я сталкиваюсь постоянно.
Может быть стоит написать в техподдержку оператора для начала, или, в конце концов, сменить оператора?
Baks, все никак не довезут до дачи. 3 дня гонял на столе, не отключая. Но ещё есть в коде моменты которые нужно исправить, но на работу вроде не влияет
КороткоеЗамыкание и КВолк - мы оба обкурились что ли? :)
Я не продвигаю Вай-Фай (да и ГСМ) в этой теме, и потом я сразу сказал, что в местах, где нет инета - ГСМ незаменим.
Я среагировал на бредовое заявление, что инет через GPRS-модем "в разы надежнее" Вайфая. Short Circuit - не имеет значения, работаете ли вы с модемом через библиотеку или напрямую - в любом случае GPRS через АТ-команды не предполагает сколько-нибудь серьезное использование нетекстовых сетевых протоколов и сравнивать его с Wi-Fi просто смешно.
подскажите, пожалуйста, как в этом коде положить трубку после 2 гудка (либо на 2 секунде). никак не могу добиться:
#include <SoftwareSerial.h> // Библиотека програмной реализации обмена по UART-протоколу SoftwareSerial gsm(7, 8); // RX, TX int8_t ModemID = 0; uint32_t msAT = 0; char Master[] = "79111234567"; String _response = ""; // Переменная для хранения ответа модуля void setup() { Serial.begin(9600); // Скорость обмена данными с компьютером InitModem(); // запускаем инициализация модема. } void InitModem() { /// === инициализация модема === /// Serial.println(F("Start GSM")); gsm.begin(9600); //Скорость порта для связи Arduino с GSM модулем waitConnect(); Serial.println(F("GSM connected")); String val = sendATCommand(F("ATI"), true); if (val.indexOf(F("M590")) > -1) ModemID = 1; // Serial.println("Modem M590"); else if (val.indexOf(F("SIM800")) > -1) ModemID = 2; // Serial.println("Modem SIM800"); else if (val.indexOf("A6") > -1) ModemID = 3; // Serial.println("Modem A6"); Serial.println(String(F("ModemID ")) + ModemID); sendATCommand(F("AT+CLIP=1"), true); // включить АОН sendATCommand(F("AT+CMGF=1"), true); // Включить TextMode для SMS sendATCommand(F("AT+CSCS=\"GSM\""), true); // кодировка текста - GSM sendATCommand(F("AT+CNMI=2,2,0,0,0"), true); sendATCommand(F("AT+CREG?"), true); delay(1000); } void loop() { if (gsm.available()) { // Если модем, что-то отправил... _response = waitResponse(); // Получаем ответ от модема для анализа Serial.println(_response); // Если нужно выводим в монитор порта // ... здесь можно анализировать данные полученные от GSM-модуля if (_response.indexOf(F("+PBREADY")) > -1) InitModem(); if (_response.indexOf(F("+CLIP: \"")) > -1) { // если обнаружен вызов. Serial.println(F("Process RING")); if (CheckPhone(_response) == 1) { // проверяем номер, если наш. Serial.println(F("Master Ring OK!")); // MasterRing(); // меняем состояние охраны } else Serial.println(F("No Master Ring!")); delay(2000); // дадим гудок gsm.println(F("ATH")); // сбрасываем вызов. } else if (_response.indexOf(F("+CMT")) > -1) { // если обнаруженa СМС Serial.println(F("Process CMT")); // Serial.println("val " + val); if (CheckPhone(_response) == 1) { // если СМС от хозяина parsesms(_response); Serial.println(F("Master SMS OK!")); // Serial.println("sms->" + val); // Komand(); } else Serial.println(F("No Master SMS!")); } } if (Serial.available()) { // Ожидаем команды по Serial... gsm.write(Serial.read()); // ...и отправляем полученную команду модему } } int CheckPhone(String num) { // сверяем номер свой/чужой int ind = num.indexOf(F("+CLIP: \"")); // обрезаем номер if (ind >= 0) { // Если информация была найдена ind += 8; // Парсим строку и num = num.substring(ind, num.indexOf("\"", ind)); } if (num.length() >= 7 && num == Master) return 1; Serial.println("Tell: " + num); return 0; } void parsesms(String msg) { String msgheader = ""; String msgbody = ""; String msgphone = ""; msg = msg.substring(msg.indexOf("+CMT: ")); msgheader = msg.substring(0,msg.indexOf("\r")); // Выдергиваем телефон msgbody = msg.substring(msgheader.length() + 2); msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK")); // Выдергиваем текст SMS msgbody.trim(); int Index = msgheader.indexOf("+CMT:"); msgphone = msgheader.substring(Index + 8, Index + 19); msgphone.trim(); Serial.println("Phone: " + msgphone); // Выводим номер телефона Serial.println("Message: " + msgbody); // Выводим текст SMS } String sendATCommand(String cmd, bool waiting) { String _resp = ""; // Переменная для хранения результата Serial.println(cmd); // Дублируем команду в монитор порта gsm.println(cmd); // Отправляем команду модулю if (waiting) { // Если необходимо дождаться ответа... _resp = waitResponse(); // ... ждем, когда будет передан ответ // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать if (_resp.startsWith(cmd)) { // Убираем из ответа дублирующуюся команду _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2); } Serial.println(_resp); // Дублируем ответ в монитор порта } return _resp; // Возвращаем результат. Пусто, если проблема } String waitResponse() { // Функция ожидания ответа и возврата полученного результата String _resp = ""; // Переменная для хранения результата uint32_t _timeout = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд) while (!gsm.available() && (millis() < _timeout)) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то... if (gsm.available()) { // Если есть, что считывать... _resp = gsm.readString(); // ... считываем и запоминаем } else { // Если пришел таймаут, то... Serial.println(F("Timeout...")); // ... оповещаем об этом и... } return _resp; // ... возвращаем результат. Пусто, если проблема } void waitConnect() { // запуск модема int countok = 0; uint32_t msAT = 0; String str; while(countok < 5) { //ждём пять ОК uint32_t ms = millis(); if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс msAT = ms; Serial.println(">>AT"); gsm.println("AT"); // посылаем команду str = ""; delay(100); // ждём ответа while(gsm.available()) { char ch = gsm.read(); str += ch; } if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;} else countok = 0; } } }после
if(CheckPhone(_response) == 1) посчитайте два ответа RING от модема...В порт ring сыпятся после того как я сам положу трубку, здесь получается: пока от модема идут сообщения в порт не выводит, а выводит когда закончена передача
угу, скетч переделайте. подумайте почему так происходит, учитесь анализироввать.
pasha413
Подскажи твой скетч с сообщения 216 все в терминале работает а ни звонить ни смс слать не хочет
В чем проблема может быть? Вот пример команды money
Money
Master SMS OK!
Balance#101#
Input string:
O7(⸮⸮⸮A⸮⸮⸮]w⸮A⸮⸮U⸮H⸮⸮⸮⸮f⸮⸮⸮&⸮⸮ow⸮L⸮⸮⸮⸮⸮r⸮⸮⸮d⸮⸮dP⸮MO⸮A0⸮+s⸮`1⸮4|⸮⸮⸮1$~⸮⸮⸮⸮d~⸮AǤ⸮:
⸮⸮e7T⸮ݠis
⸮⸮A8⸮⸮⸮⸮at
Decode string:
On Your account 19.01 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
Start SMS send
Вот так в терминале после старта
Mode GSM:
GSM connected
>>AT+CREG?
R>
AT+CLIP=1
OK
AT+CMGF=1
OK
AT+CSCS=GSM
OK
AT+CNMI=2,2,0,0,0
OK
AT+CREG?
+CREG: 1,1
OK
Phone[0]:380888888888
Ring [ ]:380888888888
Balance:101
Firststart:0
System->off
Ring->on
SMS->on
Pir->on
Door->on
Gas->on
Sirena: 10sec
Temp: 0*C.
AleksandrM, номер правильно пишет в епром?
выводит бнз последнего знака
извиняюсь без последнего знака
В терминале при старте отсуствует последняя цыфра в номере
Phone[0]:38066******_
Ring [ ]:380066******_
Да, с номерами Украины я не думал даже... Можно добавить
если не затруднит
Занимаюсь
Пробуйте, переделал, 12 значные номера не могу проверить, но должно работать!
// max длинна сообщения в данный момент 135 символов. #include <EEPROM.h> #include <OneWire.h> #include <RCSwitch.h> #include <SoftwareSerial.h> #define Ver F("Alarm v4.3.4\n") OneWire ds(6); // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +. SoftwareSerial gsm(7, 8); // модем подключен к 7 и 8 пинам. RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2. #define DOOR 4 // пин 4. концевик двери. #define PIR 5 // пин 5. датчик движения. #define LED 13 // пин 13. состояние системы. #define GAS 14 // пин A0. датчик дыма. #define BUZ 15 // пин A1. сирена. #define sarai 3258553 // адрес 433 передатчика геркона двери // DOOR - если сработал, на входе "+" HIGH. // SARAI - если сработал, на пин 2 сигнал. // PIR - если сработал, на входе "+" HIGH. // GAS - если сработал, на входе "+" HIGH. // BUZ - если "-" LOW, то горит. // LED - если "-" LOW, то горит. #define on "on" // вкл #define off "off" // выкл int8_t ModemID = 0; // тип модема int8_t Guard = 0; // 1. охрана: 1 - вкл, 0 - выкл. int8_t AlarmRING = 1; // 2. вызов при сработке: 1 - вкл, 0 - выкл. int8_t SendSMS = 1; // 3. отправка смс при сработке: 1 - вкл, 0 - выкл. int8_t DOORon = 1; // 4. контроль концевика двери: 1 - вкл, 0 - выкл. int8_t SARAIon = 1; // 4. контроль концевика двери 2: 1 - вкл, 0 - выкл. int8_t PIRon = 1; // 5. контроль датчика движения: 1 - вкл, 0 - выкл. int8_t GASon = 1; // 6. контроль датчика дыма: 1 - вкл, 0 - выкл. int8_t Sirena = 1; // 7. сирена: 1 - вкл, 0 - выкл. int8_t Firststart = 1; // первый старт. int8_t DOORFlag = 0; // флаг состояние датчика двери. int8_t SARAIFlag = 0; // флаг состояние датчика двери 2. int8_t PIRFlag = 0; // флаг состояние датчика движения. int8_t GASFlag = 0; // флаг состояние датчика газа. int8_t DOORState = LOW; // Состояние концевика двери. int8_t PIRState = LOW; // Состояние датчика движения. int8_t LEDState = HIGH; // Состояние светодиода. int8_t Smoky = LOW; // Состояние датчика газа. int8_t sendsmscaller = 1; // разрешение отправки смс. uint32_t msAT = 0; char Bal[4]; // для временного хранения номера баланса. char Phone[14]; // для временного хранения номера телефона, номер до 14 цифр. String AT[] = {"AT+CLIP=1", "AT+CMGF=1", "AT+CSCS=\"GSM\"", "AT+CNMI=2,2,0,0,0", "AT+CREG?"}; // общие АТ команды #define AT_M590 F("AT+CUSD=1") // баланс для М590 #define AT_SIM800_A6 F("AT+CUSD=1,#") // баланс для А6 и СИМ800 String RingPhone = ""; // номер звонившего. String AlarmPhone[5]; // номера для постановки/снятии с охраны и отправки смс. byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ. int p = 0; #define GASThres 400 // предельная концентрация газа #define interval_alarm 20 // Секунд до отключения "тревожного" пина. int previousMillis_alarm = 0; #define interval_led 1000 // для мигания LED, 1 сек. int previousMillis_led = 0; #define interval_door 10 // секунд не смотрим на датчик двери. int previousMillis_door = 0; #define interval_sarai 10 // секунд не смотрим на датчик двери 2. int previousMillis_sarai = 0; #define interval_pir 20 // секунд не смотрим на датчик движения. int previousMillis_pir = 0; #define interval_gas 600 // секунд не смотрим на датчик газа. 10минут int previousMillis_gas = 0; /* EEPROM Data: № ячейки - значение: 0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию. 1 - Guard = 0; // охрана: 0 - выкл. 2 - AlarmRING = 1; // звонок: 1 - вкл. 3 - SendSMS = 1; // отправка смс: 1 - вкл. 4 - DOORon = 1; // концевик двери: 1 - вкл. 5 - SARAIon = 1; // концевик двери сарая: 1 - вкл. 6 - PIRon = 1; // датчик движения: 1 - вкл. 7 - GASon = 1; // датчик дыма: 1 - вкл. 8 - Sirena = 1; // сирена: 1 - вкл. 10 - Firststars = 1; // первый запуск 1. 20 - ячейка памяти баланса, 25, 40, 55, 70, 85 - ячейки памяти телефонов. 100 - ячейка памяти номера последнего звонившего RingPhone. */ void setup() { /// === настройка программы === /// Serial.begin(9600); Serial.println(Ver); pinMode(DOOR, INPUT_PULLUP); // вход датчика двери с подтяжкой на +. pinMode(PIR, INPUT); pinMode(GAS, INPUT); pinMode(BUZ, OUTPUT); pinMode(LED, OUTPUT); // светодиод горит во время запуска. digitalWrite(BUZ, HIGH); // сирена выкл. digitalWrite(PIR, HIGH); // игнорируем при включении. mySwitch.enableReceive(0); // 433 приемник на 2 пине InitModem(); // запускаем инициализация модема. eepromconfig(); Serial.println(eepromtext()); Serial.println(eepromphone()); digitalWrite(LED, HIGH); // гасим светодиод состояния сигнализации. } void loop() { /// === основной цикл программы === /// AlarmPinOff(); // выключаем сирену, если прошло время. if (Guard == 1) { // если на охране Detect(); // проверяем датчики. Led(); // моргаем светодиодом. } if (gsm.available()) { // Если модем, что-то отправил... String val = ""; // Переменная для хранения ответа модуля val = waitgsm(); // Получаем ответ от модема для анализа // Serial.println(val); // Если нужно выводим в монитор порта if (val.indexOf(F("+PBREADY")) > -1) InitModem(); else if (val.indexOf(F("+CLIP: ")) > -1) { // если обнаружен вызов. Serial.println(F("Process RING")); // delay(2000); // дадим гудок int ind = val.indexOf(F("+CLIP: \"")); // обрезаем номер // if (ind >= 0) { // Если информация была найдена ind += 8; // Парсим строку и val = val.substring(ind, val.indexOf("\"", ind)); // } Serial.println("ring: " + val); gsm.println(F("ATH")); // сбрасываем вызов. if (CheckPhone(val) == 1) { // проверяем номер, если наш. Serial.println(F("Master Ring OK!")); MasterRing(); // меняем состояние охраны } else Serial.println(F("No Master Ring!")); } else if (val.indexOf(F("+CMT")) > -1) { // если обнаруженa СМС Serial.println(F("Process CMT")); parsesms(val); } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс String bal = ""; if (ModemID == 3) { // команда проверки баланса AT+CUSD=1,#105#,15 // анализируем строку int p1 = val.indexOf("\""); // начало строки int p2 = val.lastIndexOf("\""); // конец строки val = val.substring(p1+1,p2); Serial.println(F("Input string:")); // пишем в порт пришедшую строку Serial.println(val); Decode7bit(val, bal); Serial.println(F("Decode string:")); // пишем в порт конвертированную строку } else if (ModemID == 1 || 2) { bal = String(val.substring(val.indexOf(",\"") + 2,val.indexOf("\","))); // } Serial.println(bal); sms("SIM " + bal + "\n", 0); // смс на последний звонивший gsm.println(F("AT+CUSD=0")); } } else if (Serial.available()) { // если в мониторе порта что-то ввели String serialval = ""; while (Serial.available()) { // сохраняем входную строку в переменную val. char ch = Serial.read(); serialval += char(ch); // собираем принятые символы в строку delay(3); } sendsmscaller = 0; Komand(serialval); // запускаем консольную программу sendsmscaller = 1; } } String waitgsm() { // Функция ожидания ответа и возврата полученного результата String gsmval = ""; // Переменная для хранения результата uint32_t _timeout = millis() + 5000; // Переменная для отслеживания таймаута (10 секунд) while (!gsm.available() && (millis() < _timeout)) {}; // Ждем ответа5 секунд, если пришел ответ или наступил таймаут, то... if (gsm.available()) { // если GSM модем что-то послал. while (gsm.available()) { // сохраняем входную строку в переменную val. char ch = gsm.read(); gsmval += char(ch); // собираем принятые символы в строку delay(5); } } else { // Если пришел таймаут, то... Serial.println(F("Timeout...")); // ... оповещаем об этом и... } return gsmval; // ... возвращаем результат. Пусто, если проблема } void parsesms(String msg) { String msgheader = ""; String msgsms = ""; String msgphone = ""; msg = msg.substring(msg.indexOf("+CMT: ")); msgheader = msg.substring(0,msg.indexOf("\r")); // Выдергиваем телефон msgsms = msg.substring(msgheader.length() + 2); msgsms = msgsms.substring(0, msgsms.lastIndexOf("OK")); // Выдергиваем текст SMS msgsms.trim(); int Index = msgheader.indexOf("+CMT:"); Index += 8; // Парсим строку и msgphone = msgheader.substring(Index, msgheader.indexOf("\"", Index)); Serial.println("Phone: " + msgphone); // Выводим номер телефона Serial.println("Message: " + msgsms); // Выводим текст SMS if (CheckPhone(msgphone) == 1) { // если СМС от хозяина Serial.println(F("Master SMS OK!")); Komand(msgsms); } else Serial.println(F("No Master SMS!")); } int CheckPhone(String phone) { /// === проверка телефона === /// if (Firststart == 0) { // если не первый старт for (int i = 0; i < 5; i++) { if (phone == AlarmPhone[i] && phone != 0) { // если есть вызов, и он наш phone = AlarmPhone[i]; // запоминаем его. RingPhone = AlarmPhone[i]; // запоминаем его. RingPhone.toCharArray(Phone, 14); EEPROM.put(100, Phone); // записываем RingPhone в память. Serial.println(String(F("RingPhone ")) + RingPhone); return 1; // возвращаем 1 - номер наш! } } return 0; // возвращаем 0 - номер не наш! } else if (Firststart == 1) { // иначе (если первый старт) // первый звонивший добавляется как основной мастер номер для управления сигнализацией phone.toCharArray(Phone, 14); EEPROM.put(25, Phone); // пишем номер в EEPROM EEPROM.put(100, Phone); // записываем RingPhone в память. AlarmPhone[0] = Phone; // запишем RingPhone = Phone; // запоминаем его. EEPROM.update(10, 0); // обновляем Firststart Firststart = 0; // пишем 0 Serial.println(String(F("Firststart:")) + Firststart); sms(String(F("Master0:")) + phone + " Ok\n", 0); // смс на звонивший // приходит смс в виде: " Master0:79111234567 Ok " } return 1; } void eepromconfig() { /// === конфигурирование сигнализации === /// if (EEPROM.read(0) != 1) { // если записана не 1 for (int i = 0 ; i < 512 ; i++) { // переписываем все ячейки EEPROM.write(i, 0); } // и записываем: EEPROM.update(1, 0); // Guard охрана выкл. EEPROM.update(2, 1); // AlarmRING вызов вкл. EEPROM.update(3, 1); // SendSMS смс вкл. EEPROM.update(4, 1); // DOORon датчики дверей вкл. EEPROM.update(5, 1); // SARAIon датчики дверей вкл. EEPROM.update(6, 1); // PIRon датчик движения вкл. EEPROM.update(7, 1); // GASon датчик газа вкл. EEPROM.update(8, 1); // Sirena сирена вкл. EEPROM.update(10, 1); // Firststart первый старт!. EEPROM.update(20, 0); // баланс, записываем массив в EEPROM EEPROM.update(0, 1); // Serial.println(F("EEPROM != 1/ RESET!")); } if (EEPROM.read(0) == 1) { Guard = EEPROM.read(1); // Охрана AlarmRING = EEPROM.read(2); // Вызов SendSMS = EEPROM.read(3); // Отправка смс DOORon = EEPROM.read(4); // Датчик двери SARAIon = EEPROM.read(5); // Датчик двери PIRon = EEPROM.read(6); // Датчик движения GASon = EEPROM.read(7); // Датчик газа/дыма Sirena = EEPROM.read(8); // сирена Firststart = EEPROM.read(10); // } } String eepromtext() { /// === состояние системы === /// String SIGN = ""; // текущее состояние системы. String SIRENA = ""; // аварийная сирена. String RING = ""; // текущее состояние вызов. String SMS = ""; // текущее состояние смс. String Door = ""; // текущее состояние датчика двери. String Sarai = ""; // текущее состояние датчика двери. String Pir = ""; // текущее состояние датчика движения. String Gas = ""; // текущее состояние датчика газа. if (Guard == 1) SIGN = F("System on\n"); else SIGN = F("System off\n"); if (Sirena == 1) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n"); if (AlarmRING == 1) RING = F("Ring on\n"); else RING = F("Ring off\n"); if (SendSMS == 1) SMS = F("SMS on\n"); else SMS = F("SMS off\n"); if (DOORon == 1) Door = F("Door on\n"); else Door = F("Door off\n"); if (SARAIon == 1) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n"); if (PIRon == 1) Pir = F("Pir on\n"); else Pir = F("Pir off\n"); if (GASon == 1) Gas = F("Gas on\n"); else Gas = F("Gas off\n"); String LastEvent = SIGN + RING + SMS + SIRENA + Pir + Door + Sarai + Gas; // полное состояние системы и датчиков. return LastEvent; } String eepromphone() { /// === чтение мастер-номеров из EEPROM === /// for (int i = 0; i < 5 ; i++) { EEPROM.get(Adress[i], Phone); // считываем мастер-номера AlarmPhone[i] = Phone; } String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n"; EEPROM.get(100, Phone); // считываем номер последнего звонившего RingPhone = Phone; String ring = String(F("Ring ")) + RingPhone + "\n"; EEPROM.get(20, Bal); // считываем номер баланса String bal = String(F("Balance *")) + Bal + "#\n"; String EEPhone = numbers + ring + bal; return EEPhone; } void Detect() { /// === чтение датчиков === /// DOORState = digitalRead(DOOR); PIRState = digitalRead(PIR); Smoky = analogRead(GAS); if (DOORon == 1) { if (DOORState == HIGH && DOORFlag == 0) { previousMillis_door = millis(); DOORFlag = 1; // Serial.println(F("Dver' otkrita!")); Alarm(); // } else if (DOORState == LOW && DOORFlag == 1) { int currentMillis_door = millis(); if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) { DOORFlag = 0; } } } if (SARAIon == 1) { if (mySwitch.available()) { unsigned long value = mySwitch.getReceivedValue(); if (value == sarai && SARAIFlag == 0) { previousMillis_sarai = millis(); SARAIFlag = 1; // Serial.println(F("Sarai otkrit!")); Alarm(); // } mySwitch.resetAvailable(); } int currentMillis_sarai = millis(); if (((currentMillis_sarai - previousMillis_sarai) / 1000 > interval_sarai)) { SARAIFlag = 0; } } if (PIRon == 1) { if (PIRState == HIGH && PIRFlag == 0) { previousMillis_pir = millis(); PIRFlag = 1; // Serial.println(F("Dvizhenie u dveri!")); Alarm(); // } else if (PIRState == LOW && PIRFlag == 1) { int currentMillis_pir = millis(); if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_pir)) { PIRFlag = 0; } } } if (GASon == 1) { if ((Smoky > GASThres) && GASFlag == 0) { previousMillis_gas = millis(); GASFlag = 1; delay(100); // Serial.println(F("Gas v dome!")); Alarm(); // } else if ((Smoky < GASThres) && GASFlag == 1) { int currentMillis_gas = millis(); if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) { GASFlag = 0; } } } } void Alarm() { /// === запускаем сирену и отправку смс === /// previousMillis_alarm = millis(); if (Sirena == 1) digitalWrite(BUZ, LOW); Serial.println(F("Alarm!!!")); if (SendSMS == 1) { if (DOORFlag == 1) { sms(F("Dver' otkrita!\n"), 1); // смс на все номера } else if (SARAIFlag == 1) { sms(F("Sarai otkrit!\n"), 1); // смс на все номера } else if (PIRFlag == 1) { sms(F("Dvizhenie y dveri!\n"), 1); // смс на все номера } else if (GASFlag == 1) { sms(F("Gas v dome!\n"), 1); // смс на все номера } } if (AlarmRING == 1) { gsm.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру } } void AlarmPinOff() { /// === если прошло время, отключаем сирену === /// int currentMillis_alarm = millis(); if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) { digitalWrite(BUZ, HIGH); } } void MasterRing() { /// === мастер звонков === // if (Guard == 1) GuardOff(); // меняем состояние else if (Guard == 0) GuardOn(); // меняем состояние } void GuardOff() { /// === выключение сигнализации === /// Guard = 0; EEPROM.update(1, Guard); sms(String(F("System->off\n")), 1); // смс на все номера } void GuardOn() { /// === включение сигнализации === /// Guard = 1; EEPROM.update(1, Guard); sms(String(F("System->on\n")), 1); // смс на все номера } void Led() { /// === состояние светодиода === /// // if (Guard == 1) { // если на охране int currentMillis_led = millis(); // светодиод моргает //проверяем не прошел ли нужный интервал, если прошел то if (currentMillis_led - previousMillis_led > interval_led) { // сохраняем время последнего переключения previousMillis_led = currentMillis_led; // если светодиод не горит, то зажигаем, и наоборот if (LEDState == HIGH) LEDState = LOW; else LEDState = HIGH; digitalWrite(LED, LEDState); } // } else digitalWrite(LED, HIGH); // иначе гасим его } void Komand(String kom) { /// === мастер смс === /// Serial.println("-> " + kom); kom.toLowerCase(); if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) { // команды выполняются только с 0 мастер номера if (kom.indexOf(F("reset")) > -1) { // полный сброс ЕЕПРОМ sms(F("System Reset!\n"), 0); // смс на последний номер EEPROM.write(0, 0); eepromconfig(); Serial.println(eepromtext()); Serial.println(eepromphone()); } else if ((p = kom.indexOf(F("master"))) > -1) { // добавление мастер-номера master(kom.substring(p + 6, p + 7).toInt(), kom.substring(p + 8, kom.indexOf("\n", p + 8))); ///// sms типа: " master1:79111234567 " - ячейка + номер } else if ((p = kom.indexOf(F("balance:"))) > -1) { // добавление номера баланса balnum(kom.substring(p + 8, p + 11)); ///// sms типа: " balance:100 " - номер баланса } else if ((p = kom.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки dellphone(kom.substring(p + 5, p + 6).toInt()); ///// sms типа: " dell:1 " - удалить номер из ячейки 1 } else if (kom.indexOf(F("phone")) > -1) { // инфо о номерах системы sms(eepromphone(), 0); // смс на последний номер } } if ((kom.indexOf(F("info")) > -1) || (kom.indexOf(F("?")) > -1)) { // инфо о состоянии системы eepromconfig(); sms(eepromtext(), 0); // смс на последний номер } else if (kom.indexOf(F("temp")) > -1) { // вкл sms(TempC(), 0); // смс на последний номер } else if (kom.indexOf(F("money")) > -1) { // запрос баланса balance(); } else if (kom.indexOf(F("datchiki")) > -1) { if (kom.indexOf(on) > -1) { // вкл DOORon = 1; SARAIon = 1; PIRon = 1; GASon = 1; EEPROM.update(4, DOORon); EEPROM.update(5, SARAIon); EEPROM.update(6, PIRon); EEPROM.update(7, GASon); } else if (kom.indexOf(off) > -1) { // выкл DOORon = 0; SARAIon = 0; PIRon = 0; GASon = 0; EEPROM.update(4, DOORon); EEPROM.update(5, SARAIon); EEPROM.update(6, PIRon); EEPROM.update(7, GASon); } sms(eepromtext(), 1); // смс на последний номер } else if (kom.indexOf(F("system")) > -1) { // вкл/выкл сигнализацию if (kom.indexOf(on) > -1) { // вкл GuardOn(); } else if (kom.indexOf(off) > -1) { // вкл GuardOff(); } } else if (kom.indexOf(F("sirena")) > -1) { // вкл/выкл сирены if (kom.indexOf(on) > -1) { // вкл Sirena = 1; EEPROM.update(8, Sirena); sms(String(F("Sirena->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл Sirena = 0; EEPROM.update(8, Sirena); sms(String(F("Sirena->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("ring")) > -1) { // вкл/выкл вызов при сработке if (kom.indexOf(on) > -1) { // вкл AlarmRING = 1; EEPROM.update(2, AlarmRING); sms(String(F("Ring->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл AlarmRING = 0; EEPROM.update(2, AlarmRING); sms(String(F("Ring->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("sms")) > -1) { // вкл/выкл смс при сработке if (kom.indexOf(on) > -1) { // вкл SendSMS = 1; EEPROM.update(3, SendSMS); sms(String(F("SMS->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл SendSMS = 0; EEPROM.update(3, SendSMS); sms(String(F("SMS->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("door")) > -1) { // вкл/выкл контроль датчика двери if (kom.indexOf(on) > -1) { // выкл DOORon = 1; EEPROM.update(4, DOORon); sms(String(F("DOOR->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл контроль датчика двери DOORon = 0; EEPROM.update(4, DOORon); sms(String(F("DOOR->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("sarai")) > -1) { // вкл/выкл контроль датчика двери 2 if (kom.indexOf(on) > -1) { // вкл SARAIon = 1; EEPROM.update(5, SARAIon); sms(String(F("SARAI->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл SARAIon = 0; EEPROM.update(5, SARAIon); sms(String(F("SARAI->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("pir")) > -1) { // вкл/выкл контрол датчика движения if (kom.indexOf(on) > -1) { // вкл PIRon = 1; EEPROM.update(6, PIRon); sms(String(F("PIR->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл PIRon = 0; EEPROM.update(6, PIRon); sms(String(F("PIR->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("gas")) > -1) { // вкл/выкл контроль датчика газа if (kom.indexOf(on) > -1) { // вкл GASon = 1; EEPROM.update(7, GASon); sms(String(F("GAS->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл GASon = 0; EEPROM.update(7, GASon); sms(String(F("GAS->off\n")), 1); // смс на все номера } } gsm.println(F("AT+CMGD=1,4")); // стираем смс } void balance() { /// === проверка баланса сим-карты === /// EEPROM.get(20, Bal); // считываем массив символов delay(100); if (ModemID == 1) { gsm.println(AT_M590); delay(100); gsm.println(String("ATD#") + Bal + String("#;")); } else if (ModemID == 2 || ModemID == 3) gsm.println(String(AT_SIM800_A6) + Bal + "#,15"); Serial.println(String(F("Balance#")) + Bal + "#"); } int master (int i, String num) { /// === добавление мастер-номеров === /// if (i < 5 && i != 0) { num.toCharArray(Phone, 14); // конвертируем AlarmPhone[i] = num; // пишем номер EEPROM.put(Adress[i], Phone); // записываем массив в EEPROM sms(String(F("Master")) + i + ":" + num + " add\n", 0); // смс на 0 номер. }// else Serial.println(F("MAX number 4!")); // 4 номера максимум! // 0 номер можно удалить только через RESET!!! return 1; } int dellphone (int i) { /// === удаление мастар-номеров === /// if (i < 5 && i != 0) { sms(String(F("Master")) + i + ":" + AlarmPhone[i] + " dell\n", 0); // смс на 0 номер EEPROM.put(Adress[i], 0); AlarmPhone[i] = ""; // обнулим номер } return 1; } int balnum (String num) { /// === добавляем номер баланса === /// num.toCharArray(Bal, 4); // конвертируем EEPROM.put(20, Bal); // записываем массив в EEPROM sms(String(F("Balance:*")) + num + F("# Ok\n"), 0); // смс на 0 номер return 1; } String TempC() { /// === измеряем температуру === /// String temp; byte data[2]; ds.reset(); ds.write(0xCC); ds.write(0x44); delay(750); ds.reset(); ds.write(0xCC); ds.write(0xBE); data[0] = ds.read(); data[1] = ds.read(); int Temp = (data[1] << 8) + data[0]; Temp = Temp >> 4; temp = String(F("Temp ")) + Temp + "*C"; return temp; } void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === /// byte reminder = 0; int bitstate = 7; for (unsigned int i = 0; i < instr.length(); i++) { byte b = instr[i]; byte bb = b << (7 - bitstate); char c = (bb + reminder) & 0x7F; outstr += c; reminder = b >> bitstate; bitstate--; if (bitstate == 0) { char c = reminder; outstr += c; reminder = 0; bitstate = 7; } } } void InitModem() { /// === инициализация модема === /// gsm.begin(9600); //Скорость порта для связи Arduino с GSM модулем waitConnect(); String val = sendATCommand(F("ATI"), true); for (int i = 0; i < 5; i++) { sendATCommand(AT[i], true); // включить АОН } if (val.indexOf(F("M590")) > -1) ModemID = 1; else if (val.indexOf(F("SIM800")) > -1) ModemID = 2; else if (val.indexOf("A6") > -1) ModemID = 3; Serial.println(String(F("ModemID ")) + ModemID + "\n"); } String sendATCommand(String cmd, bool waiting) { String atval = ""; // Переменная для хранения результата Serial.println(cmd); // Дублируем команду в монитор порта gsm.println(cmd); // Отправляем команду модулю if (waiting) { // Если необходимо дождаться ответа... atval = waitgsm(); // ... ждем, когда будет передан ответ // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать if (atval.startsWith(cmd)) { // Убираем из ответа дублирующуюся команду atval = atval.substring(atval.indexOf("\r", cmd.length()) + 2); } Serial.println(atval); // Дублируем ответ в монитор порта } return atval; // Возвращаем результат. Пусто, если проблема } void waitConnect() { // запуск модема int countok = 0; uint32_t msAT = 0; String str; while(countok < 5) { //ждём пять ОК uint32_t ms = millis(); if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс msAT = ms; Serial.println(">>AT"); gsm.println("AT"); // посылаем команду str = ""; delay(100); // ждём ответа while(gsm.available()) { char ch = gsm.read(); str += ch; } if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;} else countok = 0; } } } void sms(String text, byte sendnum) { /// === отправка СМС === /// String phone = ""; if (sendsmscaller == 1 && sendnum == 0) { // отправка смс на номер звонившего phone = RingPhone; Serial.println(String(F("SMS send=>")) + phone); gsm.println(String(F("AT+CMGS=\"+")) + phone + "\""); delay(100); gsm.print(text + TempC()); delay(100); gsm.print((char)26); delay(2000); } else if (sendsmscaller == 1 && sendnum == 1) { // отправка смс на все номера for (int i = 0; i < 4 ; i++) { phone = AlarmPhone[i]; if (phone != 0) { Serial.println(String(F("SMS send=>")) + phone); gsm.println(String(F("AT+CMGS=\"+")) + phone + "\""); delay(100); gsm.print(text + TempC()); delay(100); gsm.print((char)26); delay(4000); } } } Serial.println(text + TempC() + "\n"); }в этом коде реализован автовыбор модема, и соответственно АТ команды для него
Спасибо попробовал все ОК до запроса баланса.При отправке сигналкой смс о состоянии счета устройство виснет наглухо помогает только кнопка сброс.Вот кусок с терминала
-> Money
Balance#101#
Input string:
O7(⸮⸮⸮A⸮⸮⸮]w⸮A⸮⸮⸮U⸮H⸮⸮⸮⸮f⸮⸮⸮&⸮⸮ow⸮L⸮⸮⸮⸮⸮r⸮⸮⸮d⸮⸮dP⸮MO⸮A0⸮+s⸮`1⸮4|⸮⸮⸮1$~⸮⸮⸮⸮d~⸮AǤ⸮:
⸮⸮e7T⸮ݠis
⸮⸮A8⸮⸮⸮⸮at
Decode string:
On Your account 15.51 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
SMS send=>380662424500
SIM On Your account 15.51 UAH. Tariff 'Vodafone Light+'. Number valid until 06.11.2018. Collect bonuses for GIFTS! Send 5 in SMS to 820 (0 uah)
Temp 23*C
может это длина сообщения? как его обрезать до 30 символов?
Да, это из-за длинны смс, у вас ответ баланса приходит не в таком виде как у нас. Сейчас посмотрю
AleksandrM, Если у вас есть модем M590, попробуйте его заменить. Я читал, что по причине самого модема появляются такие ошибки.
подскажите, пожалуйста. как отправить смс на несколько номеров, поочередно, дождавшись отправки предыдущего (должно прийти от модема "ОК").
вот набросал код, но не получается:
#include <SoftwareSerial.h> // Библиотека програмной реализации обмена по UART-протоколу SoftwareSerial gsm(7, 8); // RX, TX int8_t ModemID = 0; uint32_t msAT = 0; String Master[2] = {"79531112233", "79112234455"}; void setup() { Serial.begin(9600); // Скорость обмена данными с компьютером InitModem(); // запускаем инициализация модема. Serial.println(F("+++++READY+++++")); } void loop() { if (gsm.available()) { // Если модем, что-то отправил... String val = ""; // Переменная для хранения ответа модуля val = waitgsm(); // Получаем ответ от модема для анализа Serial.println("gsmval->" + val); // Если нужно выводим в монитор порта, что пришло: if (val.indexOf(F("+PBREADY")) > -1) InitModem(); else if (val.indexOf(F("+CLIP: ")) > -1) { // если обнаружен вызов. gsm.println(F("ATH")); // сбрасываем вызов. Serial.println(F("Process RING")); int ind = val.indexOf(F("+CLIP: \"")); // обрезаем номер ind += 8; // Парсим строку и val = val.substring(ind, val.indexOf("\"", ind)); Serial.println("phone->" + val); delay(3000); sendSMS("TESTOK!"); } } else if (Serial.available()) { // Ожидаем команды по Serial... gsm.write(Serial.read()); // ...и отправляем полученную команду модему } } String waitgsm() { // Функция ожидания ответа и возврата полученного результата String gsmval = ""; // Переменная для хранения результата uint32_t _timeout = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд) while (!gsm.available() && (millis() < _timeout)) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то... if (gsm.available()) { // если GSM модем что-то послал. while (gsm.available()) { // сохраняем входную строку в переменную val. char ch = gsm.read(); gsmval += char(ch); // собираем принятые символы в строку delay(5); } } else { // Если пришел таймаут, то... Serial.println(F("Timeout...")); // ... оповещаем об этом и... } return gsmval; // ... возвращаем результат. Пусто, если проблема } void InitModem() { /// === инициализация модема === /// Serial.println(F("Start GSM")); gsm.begin(9600); //Скорость порта для связи Arduino с GSM модулем waitConnect(); Serial.println(F("GSM connected")); String val = sendATCommand(F("ATI"), true); if (val.indexOf(F("M590")) > -1) ModemID = 1; // Serial.println("Modem M590"); else if (val.indexOf(F("SIM800")) > -1) ModemID = 2; // Serial.println("Modem SIM800"); else if (val.indexOf("A6") > -1) ModemID = 3; // Serial.println("Modem A6"); Serial.println(String(F("ModemID ")) + ModemID); sendATCommand(F("AT+CLIP=1"), true); // включить АОН sendATCommand(F("AT+CMGF=1"), true); // Включить TextMode для SMS sendATCommand(F("AT+CSCS=\"GSM\""), true); // кодировка текста - GSM sendATCommand(F("AT+CNMI=2,2,0,0,0"), true); sendATCommand(F("AT+CREG?"), true); // delay(1000); } String sendATCommand(String cmd, bool waiting) { String atval = ""; // Переменная для хранения результата Serial.println(cmd); // Дублируем команду в монитор порта gsm.println(cmd); // Отправляем команду модулю if (waiting) { // Если необходимо дождаться ответа... atval = waitgsm(); // ... ждем, когда будет передан ответ // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать if (atval.startsWith(cmd)) { // Убираем из ответа дублирующуюся команду atval = atval.substring(atval.indexOf("\r", cmd.length()) + 2); } Serial.println(atval); // Дублируем ответ в монитор порта if (atval.indexOf("OK") > -1) Serial.println("OK!"); } return atval; // Возвращаем результат. Пусто, если проблема } void waitConnect() { // запуск модема int countok = 0; uint32_t msAT = 0; String str; while(countok < 5) { //ждём пять ОК uint32_t ms = millis(); if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс msAT = ms; Serial.println(">>AT"); gsm.println("AT"); // посылаем команду str = ""; delay(100); // ждём ответа str = waitgsm(); if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;} else countok = 0; } } } int sendSMS(String message) { for (int i = 0; i < 2; i++) { sendATCommand("AT+CMGS=\"+" + Master[i] + "\"", true); // Переходим в режим ввода текстового сообщения sendATCommand(message + "\r\n" + (String)((char)26), true); // После текста отправляем перенос строки и Ctrl+Z+ String x = waitgsm(); x.toLowerCase(); if (x.indexOf("+CMGS:") > -1) { Serial.println("OK!!"); return 1; } else Serial.println(F("Timeout!!!")); } return 0; }pasha413
По поводу укоротить сообщение о балансе не поможешь?
AleksandrM, попробуйте.
// max длинна сообщения в данный момент 135 символов. #include <EEPROM.h> #include <OneWire.h> #include <RCSwitch.h> #include <SoftwareSerial.h> #define Ver F("Alarm v4.3.3_UK_Phone[12]\n") OneWire ds(6); // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +. SoftwareSerial gsm(7, 8); // модем подключен к 7 и 8 пинам. RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2. #define DOOR 4 // пин 4. концевик двери. #define PIR 5 // пин 5. датчик движения. #define LED 13 // пин 13. состояние системы. #define GAS 14 // пин A0. датчик дыма. #define BUZ 15 // пин A1. сирена. #define sarai 3258553 // адрес 433 передатчика геркона двери // DOOR - если сработал, на входе "+" HIGH. // SARAI - если сработал, на пин 2 сигнал. // PIR - если сработал, на входе "+" HIGH. // GAS - если сработал, на входе "+" HIGH. // BUZ - если "-" LOW, то горит. // LED - если "-" LOW, то горит. #define on "on" // вкл #define off "off" // выкл int8_t ModemID = 0; // тип модема int8_t Guard = 0; // 1. охрана: 1 - вкл, 0 - выкл. int8_t AlarmRING = 1; // 2. вызов при сработке: 1 - вкл, 0 - выкл. int8_t SendSMS = 1; // 3. отправка смс при сработке: 1 - вкл, 0 - выкл. int8_t DOORon = 1; // 4. контроль концевика двери: 1 - вкл, 0 - выкл. int8_t SARAIon = 1; // 4. контроль концевика двери 2: 1 - вкл, 0 - выкл. int8_t PIRon = 1; // 5. контроль датчика движения: 1 - вкл, 0 - выкл. int8_t GASon = 1; // 6. контроль датчика дыма: 1 - вкл, 0 - выкл. int8_t Sirena = 1; // 7. сирена: 1 - вкл, 0 - выкл. int8_t Firststart = 1; // первый старт. int8_t DOORFlag = 0; // флаг состояние датчика двери. int8_t SARAIFlag = 0; // флаг состояние датчика двери 2. int8_t PIRFlag = 0; // флаг состояние датчика движения. int8_t GASFlag = 0; // флаг состояние датчика газа. int8_t DOORState = LOW; // Состояние концевика двери. int8_t PIRState = LOW; // Состояние датчика движения. int8_t LEDState = HIGH; // Состояние светодиода. int8_t Smoky = LOW; // Состояние датчика газа. int8_t sendsmscaller = 1; // разрешение отправки смс. uint32_t msAT = 0; char Bal[4]; // для временного хранения номера баланса. char Phone[13]; // для временного хранения номера телефона. String AT[] = {"AT+CLIP=1", "AT+CMGF=1", "AT+CSCS=\"GSM\"", "AT+CNMI=2,2,0,0,0", "AT+CREG?"}; // общие АТ команды #define AT_M590 F("AT+CUSD=1") // баланс для М590 #define AT_SIM800_A6 F("AT+CUSD=1,#") // баланс для А6 и СИМ800 String RingPhone = ""; // номер звонившего. String AlarmPhone[5]; // номера для постановки/снятии с охраны и отправки смс. byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ. int p = 0; #define GASThres 400 // предельная концентрация газа #define interval_alarm 20 // Секунд до отключения "тревожного" пина. int previousMillis_alarm = 0; #define interval_led 1000 // для мигания LED, 1 сек. int previousMillis_led = 0; #define interval_door 10 // секунд не смотрим на датчик двери. int previousMillis_door = 0; #define interval_sarai 10 // секунд не смотрим на датчик двери 2. int previousMillis_sarai = 0; #define interval_pir 20 // секунд не смотрим на датчик движения. int previousMillis_pir = 0; #define interval_gas 600 // секунд не смотрим на датчик газа. 10минут int previousMillis_gas = 0; /* EEPROM Data: № ячейки - значение: 0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию. 1 - Guard = 0; // охрана: 0 - выкл. 2 - AlarmRING = 1; // звонок: 1 - вкл. 3 - SendSMS = 1; // отправка смс: 1 - вкл. 4 - DOORon = 1; // концевик двери: 1 - вкл. 5 - SARAIon = 1; // концевик двери сарая: 1 - вкл. 6 - PIRon = 1; // датчик движения: 1 - вкл. 7 - GASon = 1; // датчик дыма: 1 - вкл. 8 - Sirena = 1; // сирена: 1 - вкл. 10 - Firststars = 1; // первый запуск 1. 20 - ячейка памяти баланса, 25, 40, 55, 70, 85 - ячейки памяти телефонов. 100 - ячейка памяти номера последнего звонившего RingPhone. */ void setup() { /// === настройка программы === /// Serial.begin(9600); Serial.println(Ver); pinMode(DOOR, INPUT_PULLUP); // вход датчика двери с подтяжкой на +. pinMode(PIR, INPUT); pinMode(GAS, INPUT); pinMode(BUZ, OUTPUT); pinMode(LED, OUTPUT); // светодиод горит во время запуска. digitalWrite(BUZ, HIGH); // сирена выкл. digitalWrite(PIR, HIGH); // игнорируем при включении. mySwitch.enableReceive(0); // 433 приемник на 2 пине InitModem(); // запускаем инициализация модема. eepromconfig(); Serial.println(eepromtext()); Serial.println(eepromphone()); digitalWrite(LED, HIGH); // гасим светодиод состояния сигнализации. } void loop() { /// === основной цикл программы === /// AlarmPinOff(); // выключаем сирену, если прошло время. if (Guard == 1) { // если на охране Detect(); // проверяем датчики. Led(); // моргаем светодиодом. } if (gsm.available()) { // Если модем, что-то отправил... String val = ""; // Переменная для хранения ответа модуля val = waitgsm(); // Получаем ответ от модема для анализа // Serial.println(val); // Если нужно выводим в монитор порта if (val.indexOf(F("+PBREADY")) > -1) InitModem(); else if (val.indexOf(F("+CLIP: ")) > -1) { // если обнаружен вызов. Serial.println(F("Process RING")); int ind = val.indexOf(F("+CLIP: \"")); // обрезаем номер if (ind >= 0) { // Если информация была найдена ind += 8; // Парсим строку и val = val.substring(ind, val.indexOf("\"", ind)); } delay(3000); // дадим гудок gsm.println(F("ATH")); // сбрасываем вызов. Serial.println("val: " + val); if (CheckPhone(val) == 1) { // проверяем номер, если наш. Serial.println(F("Master Ring OK!")); MasterRing(); // меняем состояние охраны } else Serial.println(F("No Master Ring!")); } else if (val.indexOf(F("+CMT")) > -1) { // если обнаруженa СМС Serial.println(F("Process CMT")); parsesms(val); } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс String bal = ""; if (ModemID == 3) { // команда проверки баланса AT+CUSD=1,#105#,15 // анализируем строку int p1 = val.indexOf(""); // начало строки int p2 = val.lastIndexOf("UAH"); // конец строки val = val.substring(p1+1, p2); Serial.println(F("Input string:")); // пишем в порт пришедшую строку Serial.println(val); Decode7bit(val, bal); Serial.println(F("Decode string:")); // пишем в порт конвертированную строку } else if (ModemID == 1 || 2) { bal = String(val.substring(val.indexOf(",\"") + 2,val.indexOf("\","))); // } Serial.println(bal); sms("SIM " + bal + "\n", 0); // смс на последний звонивший gsm.println(F("AT+CUSD=0")); } } else if (Serial.available()) { // если в мониторе порта что-то ввели String serialval = ""; while (Serial.available()) { // сохраняем входную строку в переменную val. char ch = Serial.read(); serialval += char(ch); // собираем принятые символы в строку delay(3); } sendsmscaller = 0; Komand(serialval); // запускаем консольную программу sendsmscaller = 1; } } String waitgsm() { // Функция ожидания ответа и возврата полученного результата String gsmval = ""; // Переменная для хранения результата uint32_t _timeout = millis() + 5000; // Переменная для отслеживания таймаута (10 секунд) while (!gsm.available() && (millis() < _timeout)) {}; // Ждем ответа5 секунд, если пришел ответ или наступил таймаут, то... if (gsm.available()) { // если GSM модем что-то послал. while (gsm.available()) { // сохраняем входную строку в переменную val. char ch = gsm.read(); gsmval += char(ch); // собираем принятые символы в строку delay(5); } } else { // Если пришел таймаут, то... Serial.println(F("Timeout...")); // ... оповещаем об этом и... } return gsmval; // ... возвращаем результат. Пусто, если проблема } void parsesms(String msg) { String msgheader = ""; String msgsms = ""; String msgphone = ""; msg = msg.substring(msg.indexOf("+CMT: ")); msgheader = msg.substring(0,msg.indexOf("\r")); // Выдергиваем телефон msgsms = msg.substring(msgheader.length() + 2); msgsms = msgsms.substring(0, msgsms.lastIndexOf("OK")); // Выдергиваем текст SMS msgsms.trim(); int Index = msgheader.indexOf("+CMT:"); msgphone = msgheader.substring(Index + 8, Index + 20); msgphone.trim(); Serial.println("Phone: " + msgphone); // Выводим номер телефона Serial.println("Message: " + msgsms); // Выводим текст SMS if (CheckPhone(msgphone) == 1) { // если СМС от хозяина Serial.println(F("Master SMS OK!")); Komand(msgsms); } else Serial.println(F("No Master SMS!")); } int CheckPhone(String phone) { /// === проверка телефона === /// if (Firststart == 0) { // если не первый старт for (int i = 0; i < 5; i++) { if (phone == AlarmPhone[i] && phone != 0) { // если есть вызов, и он наш phone = AlarmPhone[i]; // запоминаем его. RingPhone = AlarmPhone[i]; // запоминаем его. RingPhone.toCharArray(Phone, 13); EEPROM.put(100, Phone); // записываем RingPhone в память. Serial.println(String(F("RingPhone ")) + RingPhone); return 1; // возвращаем 1 - номер наш! } } return 0; // возвращаем 0 - номер не наш! } else if (Firststart == 1) { // иначе (если первый старт) // первый звонивший добавляется как основной мастер номер для управления сигнализацией phone.toCharArray(Phone, 13); EEPROM.put(25, Phone); // пишем номер в EEPROM EEPROM.put(100, Phone); // записываем RingPhone в память. AlarmPhone[0] = Phone; // запишем RingPhone = Phone; // запоминаем его. EEPROM.update(10, 0); // обновляем Firststart Firststart = 0; // пишем 0 Serial.println(String(F("Firststart:")) + Firststart); sms(String(F("Master0:")) + phone + " Ok\n", 0); // смс на звонивший // приходит смс в виде: " Master0:79111234567 Ok " } return 1; } void eepromconfig() { /// === конфигурирование сигнализации === /// if (EEPROM.read(0) != 1) { // если записана не 1 for (int i = 0 ; i < 512 ; i++) { // переписываем все ячейки EEPROM.write(i, 0); } // и записываем: EEPROM.update(1, 0); // Guard охрана выкл. EEPROM.update(2, 1); // AlarmRING вызов вкл. EEPROM.update(3, 1); // SendSMS смс вкл. EEPROM.update(4, 1); // DOORon датчики дверей вкл. EEPROM.update(5, 1); // SARAIon датчики дверей вкл. EEPROM.update(6, 1); // PIRon датчик движения вкл. EEPROM.update(7, 1); // GASon датчик газа вкл. EEPROM.update(8, 1); // Sirena сирена вкл. EEPROM.update(10, 1); // Firststart первый старт!. EEPROM.update(20, 0); // баланс, записываем массив в EEPROM EEPROM.update(0, 1); // Serial.println(F("EEPROM != 1/ RESET!")); } if (EEPROM.read(0) == 1) { Guard = EEPROM.read(1); // Охрана AlarmRING = EEPROM.read(2); // Вызов SendSMS = EEPROM.read(3); // Отправка смс DOORon = EEPROM.read(4); // Датчик двери SARAIon = EEPROM.read(5); // Датчик двери PIRon = EEPROM.read(6); // Датчик движения GASon = EEPROM.read(7); // Датчик газа/дыма Sirena = EEPROM.read(8); // сирена Firststart = EEPROM.read(10); // } } String eepromtext() { /// === состояние системы === /// String SIGN = ""; // текущее состояние системы. String SIRENA = ""; // аварийная сирена. String RING = ""; // текущее состояние вызов. String SMS = ""; // текущее состояние смс. String Door = ""; // текущее состояние датчика двери. String Sarai = ""; // текущее состояние датчика двери. String Pir = ""; // текущее состояние датчика движения. String Gas = ""; // текущее состояние датчика газа. if (Guard == 1) SIGN = F("System on\n"); else SIGN = F("System off\n"); if (Sirena == 1) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n"); if (AlarmRING == 1) RING = F("Ring on\n"); else RING = F("Ring off\n"); if (SendSMS == 1) SMS = F("SMS on\n"); else SMS = F("SMS off\n"); if (DOORon == 1) Door = F("Door on\n"); else Door = F("Door off\n"); if (SARAIon == 1) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n"); if (PIRon == 1) Pir = F("Pir on\n"); else Pir = F("Pir off\n"); if (GASon == 1) Gas = F("Gas on\n"); else Gas = F("Gas off\n"); String LastEvent = SIGN + RING + SMS + SIRENA + Pir + Door + Sarai + Gas; // полное состояние системы и датчиков. return LastEvent; } String eepromphone() { /// === чтение мастер-номеров из EEPROM === /// for (int i = 0; i < 5 ; i++) { EEPROM.get(Adress[i], Phone); // считываем мастер-номера AlarmPhone[i] = Phone; } String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n"; EEPROM.get(100, Phone); // считываем номер последнего звонившего RingPhone = Phone; String ring = String(F("Ring ")) + RingPhone + "\n"; EEPROM.get(20, Bal); // считываем номер баланса String bal = String(F("Balance *")) + Bal + "#\n"; String EEPhone = numbers + ring + bal; return EEPhone; } void Detect() { /// === чтение датчиков === /// DOORState = digitalRead(DOOR); PIRState = digitalRead(PIR); Smoky = analogRead(GAS); if (DOORon == 1) { if (DOORState == HIGH && DOORFlag == 0) { previousMillis_door = millis(); DOORFlag = 1; // Serial.println(F("Dver' otkrita!")); Alarm(); // } else if (DOORState == LOW && DOORFlag == 1) { int currentMillis_door = millis(); if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) { DOORFlag = 0; } } } if (SARAIon == 1) { if (mySwitch.available()) { unsigned long value = mySwitch.getReceivedValue(); if (value == sarai && SARAIFlag == 0) { previousMillis_sarai = millis(); SARAIFlag = 1; // Serial.println(F("Sarai otkrit!")); Alarm(); // } mySwitch.resetAvailable(); } int currentMillis_sarai = millis(); if (((currentMillis_sarai - previousMillis_sarai) / 1000 > interval_sarai)) { SARAIFlag = 0; } } if (PIRon == 1) { if (PIRState == HIGH && PIRFlag == 0) { previousMillis_pir = millis(); PIRFlag = 1; // Serial.println(F("Dvizhenie u dveri!")); Alarm(); // } else if (PIRState == LOW && PIRFlag == 1) { int currentMillis_pir = millis(); if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_pir)) { PIRFlag = 0; } } } if (GASon == 1) { if ((Smoky > GASThres) && GASFlag == 0) { previousMillis_gas = millis(); GASFlag = 1; delay(100); // Serial.println(F("Gas v dome!")); Alarm(); // } else if ((Smoky < GASThres) && GASFlag == 1) { int currentMillis_gas = millis(); if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) { GASFlag = 0; } } } } void Alarm() { /// === запускаем сирену и отправку смс === /// previousMillis_alarm = millis(); if (Sirena == 1) digitalWrite(BUZ, LOW); Serial.println(F("Alarm!!!")); if (SendSMS == 1) { if (DOORFlag == 1) { sms(F("Dver' otkrita!\n"), 1); // смс на все номера } else if (SARAIFlag == 1) { sms(F("Sarai otkrit!\n"), 1); // смс на все номера } else if (PIRFlag == 1) { sms(F("Dvizhenie y dveri!\n"), 1); // смс на все номера } else if (GASFlag == 1) { sms(F("Gas v dome!\n"), 1); // смс на все номера } } if (AlarmRING == 1) { gsm.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру } } void AlarmPinOff() { /// === если прошло время, отключаем сирену === /// int currentMillis_alarm = millis(); if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) { digitalWrite(BUZ, HIGH); } } void MasterRing() { /// === мастер звонков === // if (Guard == 1) GuardOff(); // меняем состояние else if (Guard == 0) GuardOn(); // меняем состояние } void GuardOff() { /// === выключение сигнализации === /// Guard = 0; EEPROM.update(1, Guard); sms(String(F("System->off\n")), 1); // смс на все номера } void GuardOn() { /// === включение сигнализации === /// Guard = 1; EEPROM.update(1, Guard); sms(String(F("System->on\n")), 1); // смс на все номера } void Led() { /// === состояние светодиода === /// // if (Guard == 1) { // если на охране int currentMillis_led = millis(); // светодиод моргает //проверяем не прошел ли нужный интервал, если прошел то if (currentMillis_led - previousMillis_led > interval_led) { // сохраняем время последнего переключения previousMillis_led = currentMillis_led; // если светодиод не горит, то зажигаем, и наоборот if (LEDState == HIGH) LEDState = LOW; else LEDState = HIGH; digitalWrite(LED, LEDState); } // } else digitalWrite(LED, HIGH); // иначе гасим его } void Komand(String kom) { /// === мастер смс === /// Serial.println("-> " + kom); kom.toLowerCase(); if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) { // команды выполняются только с 0 мастер номера if (kom.indexOf(F("reset")) > -1) { // полный сброс ЕЕПРОМ sms(F("System Reset!\n"), 0); // смс на последний номер EEPROM.write(0, 0); eepromconfig(); Serial.println(eepromtext()); Serial.println(eepromphone()); } else if ((p = kom.indexOf(F("master"))) > -1) { // добавление мастер-номера master(kom.substring(p + 6, p + 7).toInt(), kom.substring(p + 8, p + 23)); ///// sms типа: " master1:79111234567 " - ячейка + номер } else if ((p = kom.indexOf(F("balance:"))) > -1) { // добавление номера баланса balnum(kom.substring(p + 8, p + 11)); ///// sms типа: " balance:100 " - номер баланса } else if ((p = kom.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки dellphone(kom.substring(p + 5, p + 6).toInt()); ///// sms типа: " dell:1 " - удалить номер из ячейки 1 } else if (kom.indexOf(F("phone")) > -1) { // инфо о номерах системы sms(eepromphone(), 0); // смс на последний номер } } if ((kom.indexOf(F("info")) > -1) || (kom.indexOf(F("?")) > -1)) { // инфо о состоянии системы eepromconfig(); sms(eepromtext(), 0); // смс на последний номер } else if (kom.indexOf(F("temp")) > -1) { // вкл sms(TempC(), 0); // смс на последний номер } else if (kom.indexOf(F("money")) > -1) { // запрос баланса balance(); } else if (kom.indexOf(F("datchiki")) > -1) { if (kom.indexOf(on) > -1) { // вкл DOORon = 1; SARAIon = 1; PIRon = 1; GASon = 1; EEPROM.update(4, DOORon); EEPROM.update(5, SARAIon); EEPROM.update(6, PIRon); EEPROM.update(7, GASon); } else if (kom.indexOf(off) > -1) { // выкл DOORon = 0; SARAIon = 0; PIRon = 0; GASon = 0; EEPROM.update(4, DOORon); EEPROM.update(5, SARAIon); EEPROM.update(6, PIRon); EEPROM.update(7, GASon); } sms(eepromtext(), 1); // смс на последний номер } else if (kom.indexOf(F("system")) > -1) { // вкл/выкл сигнализацию if (kom.indexOf(on) > -1) { // вкл GuardOn(); } else if (kom.indexOf(off) > -1) { // вкл GuardOff(); } } else if (kom.indexOf(F("sirena")) > -1) { // вкл/выкл сирены if (kom.indexOf(on) > -1) { // вкл Sirena = 1; EEPROM.update(8, Sirena); sms(String(F("Sirena->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл Sirena = 0; EEPROM.update(8, Sirena); sms(String(F("Sirena->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("ring")) > -1) { // вкл/выкл вызов при сработке if (kom.indexOf(on) > -1) { // вкл AlarmRING = 1; EEPROM.update(2, AlarmRING); sms(String(F("Ring->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл AlarmRING = 0; EEPROM.update(2, AlarmRING); sms(String(F("Ring->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("sms")) > -1) { // вкл/выкл смс при сработке if (kom.indexOf(on) > -1) { // вкл SendSMS = 1; EEPROM.update(3, SendSMS); sms(String(F("SMS->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл SendSMS = 0; EEPROM.update(3, SendSMS); sms(String(F("SMS->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("door")) > -1) { // вкл/выкл контроль датчика двери if (kom.indexOf(on) > -1) { // выкл DOORon = 1; EEPROM.update(4, DOORon); sms(String(F("DOOR->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл контроль датчика двери DOORon = 0; EEPROM.update(4, DOORon); sms(String(F("DOOR->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("sarai")) > -1) { // вкл/выкл контроль датчика двери 2 if (kom.indexOf(on) > -1) { // вкл SARAIon = 1; EEPROM.update(5, SARAIon); sms(String(F("SARAI->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл SARAIon = 0; EEPROM.update(5, SARAIon); sms(String(F("SARAI->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("pir")) > -1) { // вкл/выкл контрол датчика движения if (kom.indexOf(on) > -1) { // вкл PIRon = 1; EEPROM.update(6, PIRon); sms(String(F("PIR->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл PIRon = 0; EEPROM.update(6, PIRon); sms(String(F("PIR->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("gas")) > -1) { // вкл/выкл контроль датчика газа if (kom.indexOf(on) > -1) { // вкл GASon = 1; EEPROM.update(7, GASon); sms(String(F("GAS->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл GASon = 0; EEPROM.update(7, GASon); sms(String(F("GAS->off\n")), 1); // смс на все номера } } gsm.println(F("AT+CMGD=1,4")); // стираем смс } void balance() { /// === проверка баланса сим-карты === /// EEPROM.get(20, Bal); // считываем массив символов delay(100); if (ModemID == 1) { gsm.println(AT_M590); delay(100); gsm.println(String("ATD#") + Bal + String("#;")); } else if (ModemID == 2 || ModemID == 3) gsm.println(String(AT_SIM800_A6) + Bal + "#,15"); Serial.println(String(F("Balance#")) + Bal + "#"); } int master (int i, String num) { /// === добавление мастер-номеров === /// if (i < 5 && i != 0) { num.toCharArray(Phone, 13); // конвертируем AlarmPhone[i] = num; // пишем номер EEPROM.put(Adress[i], Phone); // записываем массив в EEPROM sms(String(F("Master")) + i + ":" + num + " add\n", 0); // смс на 0 номер. }// else Serial.println(F("MAX number 4!")); // 4 номера максимум! // 0 номер можно удалить только через RESET!!! return 1; } int dellphone (int i) { /// === удаление мастар-номеров === /// if (i < 5 && i != 0) { sms(String(F("Master")) + i + ":" + AlarmPhone[i] + " dell\n", 0); // смс на 0 номер EEPROM.put(Adress[i], 0); AlarmPhone[i] = ""; // обнулим номер } return 1; } int balnum (String num) { /// === добавляем номер баланса === /// num.toCharArray(Bal, 4); // конвертируем EEPROM.put(20, Bal); // записываем массив в EEPROM sms(String(F("Balance:*")) + num + F("# Ok\n"), 0); // смс на 0 номер return 1; } String TempC() { /// === измеряем температуру === /// String temp; byte data[2]; ds.reset(); ds.write(0xCC); ds.write(0x44); delay(750); ds.reset(); ds.write(0xCC); ds.write(0xBE); data[0] = ds.read(); data[1] = ds.read(); int Temp = (data[1] << 8) + data[0]; Temp = Temp >> 4; temp = String(F("Temp ")) + Temp + "*C"; return temp; } void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === /// byte reminder = 0; int bitstate = 7; for (unsigned int i = 0; i < instr.length(); i++) { byte b = instr[i]; byte bb = b << (7 - bitstate); char c = (bb + reminder) & 0x7F; outstr += c; reminder = b >> bitstate; bitstate--; if (bitstate == 0) { char c = reminder; outstr += c; reminder = 0; bitstate = 7; } } } void InitModem() { /// === инициализация модема === /// gsm.begin(9600); //Скорость порта для связи Arduino с GSM модулем waitConnect(); String val = sendATCommand(F("ATI"), true); for (int i = 0; i < 5; i++) { sendATCommand(AT[i], true); // включить АОН } if (val.indexOf(F("M590")) > -1) ModemID = 1; else if (val.indexOf(F("SIM800")) > -1) ModemID = 2; else if (val.indexOf("A6") > -1) ModemID = 3; Serial.println(String(F("ModemID ")) + ModemID + "\n"); } String sendATCommand(String cmd, bool waiting) { String atval = ""; // Переменная для хранения результата Serial.println(cmd); // Дублируем команду в монитор порта gsm.println(cmd); // Отправляем команду модулю if (waiting) { // Если необходимо дождаться ответа... atval = waitgsm(); // ... ждем, когда будет передан ответ // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать if (atval.startsWith(cmd)) { // Убираем из ответа дублирующуюся команду atval = atval.substring(atval.indexOf("\r", cmd.length()) + 2); } Serial.println(atval); // Дублируем ответ в монитор порта } return atval; // Возвращаем результат. Пусто, если проблема } void waitConnect() { // запуск модема int countok = 0; uint32_t msAT = 0; String str; while(countok < 5) { //ждём пять ОК uint32_t ms = millis(); if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс msAT = ms; Serial.println(">>AT"); gsm.println("AT"); // посылаем команду str = ""; delay(100); // ждём ответа while(gsm.available()) { char ch = gsm.read(); str += ch; } if(str.indexOf("OK") > -1) {Serial.println("OK"); countok++;} else countok = 0; } } } void sms(String text, byte sendnum) { /// === отправка СМС === /// String phone = ""; if (sendsmscaller == 1 && sendnum == 0) { // отправка смс на номер звонившего phone = RingPhone; Serial.println(String(F("SMS send=>")) + phone); gsm.println(String(F("AT+CMGS=\"+")) + phone + "\""); delay(100); gsm.print(text + TempC()); delay(100); gsm.print((char)26); delay(2000); } else if (sendsmscaller == 1 && sendnum == 1) { // отправка смс на все номера for (int i = 0; i < 4 ; i++) { phone = AlarmPhone[i]; if (phone != 0) { Serial.println(String(F("SMS send=>")) + phone); gsm.println(String(F("AT+CMGS=\"+")) + phone + "\""); delay(100); gsm.print(text + TempC()); delay(100); gsm.print((char)26); delay(4000); } } } Serial.println(text + TempC() + "\n"); }Спасибо. Завтра с утра попробую, оставил железку в конторе.Я так понял Вы ограничили длину строки символом
"UAH"?intp1 = val.indexOf("");// начало строки146intp2 = val.lastIndexOf("UAH");// конец строки147val = val.substring(p1+1, p2);Да, других вариантов пока не вижу
Другой вариант я вам, Паша, давно озвучивал - принимайте из модема только то, что нужно, остальное отбрасывайте. Буфером в 32 символа можно принять ответ от GPRS в 500 байт, а уж СМС-ку и подавно.
А вообще - работу с балансом, думаю, вам вообще для пользователей настраивать не надо. Пусть делают сами. Все возможные варианты строк от всех возможных операторов вы все равно в скетч не добавите - да и не нужно это. У нас тут программисткий форум, пусть попотеют хоть немного настроить скетч под себя - а то иначе это получается чистое нахлебничество.
b707, спасибо. Кто-то хочет учиться, самихоть что-то сделать, а кто-то только заливать и все)
Ну а помочь, чем могу тем и помогу. С балансом согласен, очень много разных вариантов получается.
Как вы говорите, для считывания с модема такая процедура годится, или надо что-то иное?:
while (gsm.available()) {
char ch = gsm.read();
gsmval += char(ch);
delay(5);
}
Спасиба за прмощь. Направили в нужную сторону. Вашим способом не получилось, сделал по другому:
Обрезал строку после перекодировки- результат:
SIM Your account 12.01 UAH.
Temp 24*C
AleksandrM, пожалуйста. Я так и хотел, видимо поспешил с работы уйти и не там изменил. Обращайтесь.
вообщем доработал, т.к. не проверялся баланс при входящей смс money и не отправлялись смс на несколько номеров. сейчас это работает. проверяйте.
// max длинна сообщения в данный момент 135 символов. #include <EEPROM.h> #include <OneWire.h> #include <RCSwitch.h> #include <SoftwareSerial.h> #define Ver F("Alarm v4.3.4\n") OneWire ds(6); // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +. SoftwareSerial gsm(7, 8); // модем подключен к 7 и 8 пинам. RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2. #define DOOR 4 // пин 4. концевик двери. #define PIR 5 // пин 5. датчик движения. #define LED 13 // пин 13. состояние системы. #define GAS 14 // пин A0. датчик дыма. #define BUZ 15 // пин A1. сирена. #define sarai 3258553 // адрес 433 передатчика геркона двери // DOOR - если сработал, на входе "+" HIGH. // SARAI - если сработал, на пин 2 сигнал. // PIR - если сработал, на входе "+" HIGH. // GAS - если сработал, на входе "+" HIGH. // BUZ - если "-" LOW, то горит. // LED - если "-" LOW, то горит. #define on "on" // вкл #define off "off" // выкл int8_t ModemID = 0; // тип модема int8_t Guard = 0; // 1. охрана: 1 - вкл, 0 - выкл. int8_t AlarmRING = 1; // 2. вызов при сработке: 1 - вкл, 0 - выкл. int8_t SendSMS = 1; // 3. отправка смс при сработке: 1 - вкл, 0 - выкл. int8_t DOORon = 1; // 4. контроль концевика двери: 1 - вкл, 0 - выкл. int8_t SARAIon = 1; // 4. контроль концевика двери 2: 1 - вкл, 0 - выкл. int8_t PIRon = 1; // 5. контроль датчика движения: 1 - вкл, 0 - выкл. int8_t GASon = 1; // 6. контроль датчика дыма: 1 - вкл, 0 - выкл. int8_t Sirena = 1; // 7. сирена: 1 - вкл, 0 - выкл. int8_t Firststart = 1; // первый старт. int8_t DOORFlag = 0; // флаг состояние датчика двери. int8_t SARAIFlag = 0; // флаг состояние датчика двери 2. int8_t PIRFlag = 0; // флаг состояние датчика движения. int8_t GASFlag = 0; // флаг состояние датчика газа. int8_t DOORState = LOW; // Состояние концевика двери. int8_t PIRState = LOW; // Состояние датчика движения. int8_t LEDState = HIGH; // Состояние светодиода. int8_t Smoky = LOW; // Состояние датчика газа. int8_t sendsmscaller = 1; // разрешение отправки смс. uint32_t msAT = 0; char Bal[4]; // для временного хранения номера баланса. char Phone[14]; // для временного хранения номера телефона, номер до 14 цифр. String AT[] = {"ATE0", "AT+CLIP=1", "AT+CMGF=1", "AT+CSCS=\"GSM\"", "AT+CNMI=2,2,0,0,0", "AT+CREG?"}; // общие АТ команды #define AT_M590 F("AT+CUSD=1") // баланс для М590 #define AT_SIM800_A6 F("AT+CUSD=1,#") // баланс для А6 и СИМ800 String RingPhone = ""; // номер звонившего. String AlarmPhone[5]; // номера для постановки/снятии с охраны и отправки смс. byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ. int p = 0; #define GASThres 400 // предельная концентрация газа #define interval_alarm 20 // Секунд до отключения "тревожного" пина. int previousMillis_alarm = 0; #define interval_led 1000 // для мигания LED, 1 сек. int previousMillis_led = 0; #define interval_door 10 // секунд не смотрим на датчик двери. int previousMillis_door = 0; #define interval_sarai 10 // секунд не смотрим на датчик двери 2. int previousMillis_sarai = 0; #define interval_pir 20 // секунд не смотрим на датчик движения. int previousMillis_pir = 0; #define interval_gas 600 // секунд не смотрим на датчик газа. 10минут int previousMillis_gas = 0; /* EEPROM Data: № ячейки - значение: 0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию. 1 - Guard = 0; // охрана: 0 - выкл. 2 - AlarmRING = 1; // звонок: 1 - вкл. 3 - SendSMS = 1; // отправка смс: 1 - вкл. 4 - DOORon = 1; // концевик двери: 1 - вкл. 5 - SARAIon = 1; // концевик двери сарая: 1 - вкл. 6 - PIRon = 1; // датчик движения: 1 - вкл. 7 - GASon = 1; // датчик дыма: 1 - вкл. 8 - Sirena = 1; // сирена: 1 - вкл. 10 - Firststars = 1; // первый запуск 1. 20 - ячейка памяти баланса, 25, 40, 55, 70, 85 - ячейки памяти телефонов. 100 - ячейка памяти номера последнего звонившего RingPhone. */ void setup() { /// === настройка программы === /// Serial.begin(9600); Serial.println(Ver); pinMode(DOOR, INPUT_PULLUP); // вход датчика двери с подтяжкой на +. pinMode(PIR, INPUT); pinMode(GAS, INPUT); pinMode(BUZ, OUTPUT); pinMode(LED, OUTPUT); // светодиод горит во время запуска. digitalWrite(BUZ, HIGH); // сирена выкл. digitalWrite(PIR, HIGH); // игнорируем при включении. mySwitch.enableReceive(0); // 433 приемник на 2 пине InitModem(); // запускаем инициализация модема. eepromconfig(); Serial.println(eepromtext()); Serial.println(eepromphone()); digitalWrite(LED, HIGH); // гасим светодиод состояния сигнализации. } void loop() { /// === основной цикл программы === /// AlarmPinOff(); // выключаем сирену, если прошло время. if (Guard == 1) { // если на охране Detect(); // проверяем датчики. Led(); // моргаем светодиодом. } if (gsm.available()) { // Если модем, что-то отправил... sendsmscaller = 1; String gval = ""; // Переменная для хранения ответа модуля gval = waitgsm(); // Получаем ответ от модема для анализа // Serial.println("gval:" + gval); // Если нужно выводим в монитор порта if (gval.indexOf(F("+PBREADY")) > -1) InitModem(); else if (gval.indexOf(F("+CLIP")) > -1) { // если обнаружен вызов. gsm.println(F("ATH")); // сбрасываем вызов. Serial.println(F("Process RING")); int ind = gval.indexOf(F("+CLIP: \"")); // обрезаем номер // if (ind >= 0) { // Если информация была найдена ind += 8; // Парсим строку и String ring = gval.substring(ind, gval.indexOf("\"", ind)); // } Serial.println(String(F("RingPhone->")) + ring); if (CheckPhone(ring) == 1) { // проверяем номер, если наш. Serial.println(F("Master Ring OK!")); MasterRing(); // меняем состояние охраны } else Serial.println(F("No Master Ring!")); } else if (gval.indexOf(F("+CMT")) > -1) { // если обнаруженa СМС Serial.println(F("Process CMT")); parsesms(gval); } else if(gval.indexOf(F("+CUSD:")) > -1) { // если пришел баланс String bal = ""; if (ModemID == 3) { // команда проверки баланса AT+CUSD=1,#105#,15 // анализируем строку int p1 = gval.indexOf("\""); // начало строки int p2 = gval.lastIndexOf("\""); // конец строки gval = gval.substring(p1+1,p2); Serial.println(F("Input string:")); // пишем в порт пришедшую строку Serial.println(gval); Decode7bit(gval, bal); Serial.println(F("Decode string:")); // пишем в порт конвертированную строку } else if (ModemID == 1 || 2) { bal = String(gval.substring(gval.indexOf(",\"") + 2,gval.indexOf("\","))); // } Serial.println(bal); sms("SIM " + bal + "\n", 0); // смс на последний звонивший gsm.println(F("AT+CUSD=0")); } } else if (Serial.available()) { // если в мониторе порта что-то ввели String sval = ""; while (Serial.available()) { // сохраняем входную строку в переменную val. char ch = Serial.read(); sval += char(ch); // собираем принятые символы в строку delay(3); } sendsmscaller = 0; Komand(sval); // запускаем консольную программу sendsmscaller = 1; } } String waitgsm() { // Функция ожидания ответа и возврата полученного результата String gsmval = ""; // Переменная для хранения результата uint32_t _timeout = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд) while (!gsm.available() && (millis() < _timeout)) {}; // Ждем ответа5 секунд, если пришел ответ или наступил таймаут, то... if (gsm.available()) { // если GSM модем что-то послал. while (gsm.available()) { // сохраняем входную строку в переменную val. char ch = gsm.read(); gsmval += char(ch); // собираем принятые символы в строку delay(3); } } else { // Если пришел таймаут, то... Serial.println(F("Timeout...")); // ... оповещаем об этом и... } return gsmval; // ... возвращаем результат. Пусто, если проблема } void parsesms(String msg) { String msgheader = ""; String msgsms = ""; String msgphone = ""; msg = msg.substring(msg.indexOf(F("+CMT: "))); msgheader = msg.substring(0,msg.indexOf("\r")); // Выдергиваем телефон msgsms = msg.substring(msgheader.length() + 2); msgsms = msgsms.substring(0, msgsms.lastIndexOf("OK")); // Выдергиваем текст SMS msgsms.trim(); int Index = msgheader.indexOf(F("+CMT:")); Index += 8; // Парсим строку и msgphone = msgheader.substring(Index, msgheader.indexOf("\"", Index)); Serial.println(String(F("Phone: ")) + msgphone); // Выводим номер телефона Serial.println(String(F("Message: ")) + msgsms); // Выводим текст SMS if (CheckPhone(msgphone) == 1) { // если СМС от хозяина Serial.println(F("Master SMS OK!")); Komand(msgsms); } else Serial.println(F("No Master SMS!")); } int CheckPhone(String phone) { /// === проверка телефона === /// if (Firststart == 0) { // если не первый старт for (int i = 0; i < 5; i++) { if (phone == AlarmPhone[i] && phone != 0) { // если есть вызов, и он наш phone = AlarmPhone[i]; // запоминаем его. RingPhone = AlarmPhone[i]; // запоминаем его. RingPhone.toCharArray(Phone, 14); EEPROM.put(100, Phone); // записываем RingPhone в память. // Serial.println(String(F("RingPhone ")) + RingPhone); return 1; // возвращаем 1 - номер наш! } } return 0; // возвращаем 0 - номер не наш! } else if (Firststart == 1) { // иначе (если первый старт) // первый звонивший добавляется как основной мастер номер для управления сигнализацией phone.toCharArray(Phone, 14); EEPROM.put(25, Phone); // пишем номер в EEPROM EEPROM.put(100, Phone); // записываем RingPhone в память. AlarmPhone[0] = Phone; // запишем RingPhone = Phone; // запоминаем его. EEPROM.update(10, 0); // обновляем Firststart Firststart = 0; // пишем 0 Serial.println(String(F("Firststart:")) + Firststart); sms(String(F("Master0:")) + phone + " Ok\n", 0); // смс на звонивший // приходит смс в виде: " Master0:79111234567 Ok " } return 0; } void eepromconfig() { /// === конфигурирование сигнализации === /// if (EEPROM.read(0) != 1) { // если записана не 1 for (int i = 0 ; i < 512 ; i++) { // переписываем все ячейки EEPROM.write(i, 0); } // и записываем: EEPROM.update(1, 0); // Guard охрана выкл. EEPROM.update(2, 1); // AlarmRING вызов вкл. EEPROM.update(3, 1); // SendSMS смс вкл. EEPROM.update(4, 1); // DOORon датчики дверей вкл. EEPROM.update(5, 1); // SARAIon датчики дверей вкл. EEPROM.update(6, 1); // PIRon датчик движения вкл. EEPROM.update(7, 1); // GASon датчик газа вкл. EEPROM.update(8, 1); // Sirena сирена вкл. EEPROM.update(10, 1); // Firststart первый старт!. EEPROM.update(20, 0); // баланс, записываем массив в EEPROM EEPROM.update(0, 1); // Serial.println(F("EEPROM != 1/ RESET!")); } if (EEPROM.read(0) == 1) { Guard = EEPROM.read(1); // Охрана AlarmRING = EEPROM.read(2); // Вызов SendSMS = EEPROM.read(3); // Отправка смс DOORon = EEPROM.read(4); // Датчик двери SARAIon = EEPROM.read(5); // Датчик двери PIRon = EEPROM.read(6); // Датчик движения GASon = EEPROM.read(7); // Датчик газа/дыма Sirena = EEPROM.read(8); // сирена Firststart = EEPROM.read(10); // } } String eepromtext() { /// === состояние системы === /// String SIGN = ""; // текущее состояние системы. String SIRENA = ""; // аварийная сирена. String RING = ""; // текущее состояние вызов. String SMS = ""; // текущее состояние смс. String Door = ""; // текущее состояние датчика двери. String Sarai = ""; // текущее состояние датчика двери. String Pir = ""; // текущее состояние датчика движения. String Gas = ""; // текущее состояние датчика газа. if (Guard == 1) SIGN = F("System on\n"); else SIGN = F("System off\n"); if (Sirena == 1) SIRENA = F("Sirena on\n"); else SIRENA = F("Sirena off\n"); if (AlarmRING == 1) RING = F("Ring on\n"); else RING = F("Ring off\n"); if (SendSMS == 1) SMS = F("SMS on\n"); else SMS = F("SMS off\n"); if (DOORon == 1) Door = F("Door on\n"); else Door = F("Door off\n"); if (SARAIon == 1) Sarai = F("Sarai on\n"); else Sarai = F("Sarai off\n"); if (PIRon == 1) Pir = F("Pir on\n"); else Pir = F("Pir off\n"); if (GASon == 1) Gas = F("Gas on\n"); else Gas = F("Gas off\n"); String LastEvent = SIGN + RING + SMS + SIRENA + Pir + Door + Sarai + Gas; // полное состояние системы и датчиков. return LastEvent; } String eepromphone() { /// === чтение мастер-номеров из EEPROM === /// for (int i = 0; i < 5 ; i++) { EEPROM.get(Adress[i], Phone); // считываем мастер-номера AlarmPhone[i] = Phone; } String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n"; EEPROM.get(100, Phone); // считываем номер последнего звонившего RingPhone = Phone; String ring = String(F("Ring ")) + RingPhone + "\n"; EEPROM.get(20, Bal); // считываем номер баланса String bal = String(F("Balance *")) + Bal + "#\n"; String EEPhone = numbers + ring + bal; return EEPhone; } void Detect() { /// === чтение датчиков === /// DOORState = digitalRead(DOOR); PIRState = digitalRead(PIR); Smoky = analogRead(GAS); if (DOORon == 1) { if (DOORState == HIGH && DOORFlag == 0) { previousMillis_door = millis(); DOORFlag = 1; // Serial.println(F("Dver' otkrita!")); Alarm(); // } else if (DOORState == LOW && DOORFlag == 1) { int currentMillis_door = millis(); if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) { DOORFlag = 0; } } } if (SARAIon == 1) { if (mySwitch.available()) { unsigned long value = mySwitch.getReceivedValue(); if (value == sarai && SARAIFlag == 0) { previousMillis_sarai = millis(); SARAIFlag = 1; // Serial.println(F("Sarai otkrit!")); Alarm(); // } mySwitch.resetAvailable(); } int currentMillis_sarai = millis(); if (((currentMillis_sarai - previousMillis_sarai) / 1000 > interval_sarai)) { SARAIFlag = 0; } } if (PIRon == 1) { if (PIRState == HIGH && PIRFlag == 0) { previousMillis_pir = millis(); PIRFlag = 1; // Serial.println(F("Dvizhenie u dveri!")); Alarm(); // } else if (PIRState == LOW && PIRFlag == 1) { int currentMillis_pir = millis(); if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_pir)) { PIRFlag = 0; } } } if (GASon == 1) { if ((Smoky > GASThres) && GASFlag == 0) { previousMillis_gas = millis(); GASFlag = 1; delay(100); // Serial.println(F("Gas v dome!")); Alarm(); // } else if ((Smoky < GASThres) && GASFlag == 1) { int currentMillis_gas = millis(); if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) { GASFlag = 0; } } } } void Alarm() { /// === запускаем сирену и отправку смс === /// previousMillis_alarm = millis(); if (Sirena == 1) digitalWrite(BUZ, LOW); Serial.println(F("Alarm!!!")); if (SendSMS == 1) { if (DOORFlag == 1) { sms(F("Dver' otkrita!\n"), 1); // смс на все номера } else if (SARAIFlag == 1) { sms(F("Sarai otkrit!\n"), 1); // смс на все номера } else if (PIRFlag == 1) { sms(F("Dvizhenie y dveri!\n"), 1); // смс на все номера } else if (GASFlag == 1) { sms(F("Gas v dome!\n"), 1); // смс на все номера } } if (AlarmRING == 1) { gsm.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру } } void AlarmPinOff() { /// === если прошло время, отключаем сирену === /// int currentMillis_alarm = millis(); if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) { digitalWrite(BUZ, HIGH); } } void MasterRing() { /// === мастер звонков === // if (Guard == 1) GuardOff(); // меняем состояние else if (Guard == 0) GuardOn(); // меняем состояние } void GuardOff() { /// === выключение сигнализации === /// Guard = 0; EEPROM.update(1, Guard); sms(String(F("System->off\n")), 1); // смс на все номера } void GuardOn() { /// === включение сигнализации === /// Guard = 1; EEPROM.update(1, Guard); sms(String(F("System->on\n")), 1); // смс на все номера } void Led() { /// === состояние светодиода === /// // if (Guard == 1) { // если на охране int currentMillis_led = millis(); // светодиод моргает //проверяем не прошел ли нужный интервал, если прошел то if (currentMillis_led - previousMillis_led > interval_led) { // сохраняем время последнего переключения previousMillis_led = currentMillis_led; // если светодиод не горит, то зажигаем, и наоборот if (LEDState == HIGH) LEDState = LOW; else LEDState = HIGH; digitalWrite(LED, LEDState); } // } else digitalWrite(LED, HIGH); // иначе гасим его } void Komand(String kom) { /// === мастер смс === /// Serial.println("Kom->" + kom); kom.toLowerCase(); if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) { // команды выполняются только с 0 мастер номера if (kom.indexOf(F("reset")) > -1) { // полный сброс ЕЕПРОМ sms(F("System Reset!\n"), 0); // смс на последний номер EEPROM.write(0, 0); eepromconfig(); Serial.println(eepromtext()); Serial.println(eepromphone()); } else if ((p = kom.indexOf(F("master"))) > -1) { // добавление мастер-номера master(kom.substring(p + 6, p + 7).toInt(), kom.substring(p + 8, kom.indexOf("\n", p + 8))); ///// sms типа: " master1:79111234567 " - ячейка + номер } else if ((p = kom.indexOf(F("balance:"))) > -1) { // добавление номера баланса balnum(kom.substring(p + 8, p + 11)); ///// sms типа: " balance:100 " - номер баланса } else if ((p = kom.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки dellphone(kom.substring(p + 5, p + 6).toInt()); ///// sms типа: " dell:1 " - удалить номер из ячейки 1 } else if (kom.indexOf(F("phone")) > -1) { // инфо о номерах системы sms(eepromphone(), 0); // смс на последний номер } } if ((kom.indexOf(F("info")) > -1) || (kom.indexOf(F("?")) > -1)) { // инфо о состоянии системы eepromconfig(); sms(eepromtext(), 0); // смс на последний номер } else if (kom.indexOf(F("money")) > -1) { // запрос баланса balance(); } else if (kom.indexOf(F("datchiki")) > -1) { if (kom.indexOf(on) > -1) { // вкл DOORon = 1; SARAIon = 1; PIRon = 1; GASon = 1; EEPROM.update(4, DOORon); EEPROM.update(5, SARAIon); EEPROM.update(6, PIRon); EEPROM.update(7, GASon); } else if (kom.indexOf(off) > -1) { // выкл DOORon = 0; SARAIon = 0; PIRon = 0; GASon = 0; EEPROM.update(4, DOORon); EEPROM.update(5, SARAIon); EEPROM.update(6, PIRon); EEPROM.update(7, GASon); } sms(eepromtext(), 1); // смс на последний номер } else if (kom.indexOf(F("system")) > -1) { // вкл/выкл сигнализацию if (kom.indexOf(on) > -1) { // вкл GuardOn(); } else if (kom.indexOf(off) > -1) { // вкл GuardOff(); } } else if (kom.indexOf(F("sirena")) > -1) { // вкл/выкл сирены if (kom.indexOf(on) > -1) { // вкл Sirena = 1; EEPROM.update(8, Sirena); sms(String(F("Sirena->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл Sirena = 0; EEPROM.update(8, Sirena); sms(String(F("Sirena->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("ring")) > -1) { // вкл/выкл вызов при сработке if (kom.indexOf(on) > -1) { // вкл AlarmRING = 1; EEPROM.update(2, AlarmRING); sms(String(F("Ring->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл AlarmRING = 0; EEPROM.update(2, AlarmRING); sms(String(F("Ring->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("sms")) > -1) { // вкл/выкл смс при сработке if (kom.indexOf(on) > -1) { // вкл SendSMS = 1; EEPROM.update(3, SendSMS); sms(String(F("SMS->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл SendSMS = 0; EEPROM.update(3, SendSMS); sms(String(F("SMS->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("door")) > -1) { // вкл/выкл контроль датчика двери if (kom.indexOf(on) > -1) { // выкл DOORon = 1; EEPROM.update(4, DOORon); sms(String(F("DOOR->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл контроль датчика двери DOORon = 0; EEPROM.update(4, DOORon); sms(String(F("DOOR->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("sarai")) > -1) { // вкл/выкл контроль датчика двери 2 if (kom.indexOf(on) > -1) { // вкл SARAIon = 1; EEPROM.update(5, SARAIon); sms(String(F("SARAI->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл SARAIon = 0; EEPROM.update(5, SARAIon); sms(String(F("SARAI->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("pir")) > -1) { // вкл/выкл контрол датчика движения if (kom.indexOf(on) > -1) { // вкл PIRon = 1; EEPROM.update(6, PIRon); sms(String(F("PIR->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл PIRon = 0; EEPROM.update(6, PIRon); sms(String(F("PIR->off\n")), 1); // смс на все номера } } else if (kom.indexOf(F("gas")) > -1) { // вкл/выкл контроль датчика газа if (kom.indexOf(on) > -1) { // вкл GASon = 1; EEPROM.update(7, GASon); sms(String(F("GAS->on\n")), 1); // смс на все номера } else if (kom.indexOf(off) > -1) { // выкл GASon = 0; EEPROM.update(7, GASon); sms(String(F("GAS->off\n")), 1); // смс на все номера } } gsm.println(F("AT+CMGD=1,4")); // стираем смс } void balance() { /// === проверка баланса сим-карты === /// EEPROM.get(20, Bal); // считываем массив символов Serial.println(String("Modem ") + ModemID); delay(1000); // ждем секунду, т.к. вылетает с ошибкой if (ModemID == 1) { gsm.println(AT_M590); delay(100); gsm.println(String(F("ATD#")) + Bal + "#;"); } else if (ModemID == 2 || ModemID == 3) gsm.println(String(AT_SIM800_A6) + Bal + "#,15"); Serial.println(String(F("Balance#")) + Bal + "#"); } int master (int i, String num) { /// === добавление мастер-номеров === /// if (i < 5 && i != 0) { num.toCharArray(Phone, 14); // конвертируем AlarmPhone[i] = num; // пишем номер EEPROM.put(Adress[i], Phone); // записываем массив в EEPROM sms(String(F("Master")) + i + ":" + num + " add\n", 0); // смс на 0 номер. }// else Serial.println(F("MAX number 4!")); // 4 номера максимум! // 0 номер можно удалить только через RESET!!! return 1; } int dellphone (int i) { /// === удаление мастар-номеров === /// if (i < 5 && i != 0) { sms(String(F("Master")) + i + ":" + AlarmPhone[i] + " dell\n", 0); // смс на 0 номер EEPROM.put(Adress[i], 0); AlarmPhone[i] = ""; // обнулим номер } return 1; } int balnum (String num) { /// === добавляем номер баланса === /// num.toCharArray(Bal, 4); // конвертируем EEPROM.put(20, Bal); // записываем массив в EEPROM sms(String(F("Balance:*")) + num + F("# Ok\n"), 0); // смс на 0 номер return 1; } String TempC() { /// === измеряем температуру === /// String temp; byte data[2]; ds.reset(); ds.write(0xCC); ds.write(0x44); delay(750); ds.reset(); ds.write(0xCC); ds.write(0xBE); data[0] = ds.read(); data[1] = ds.read(); int Temp = (data[1] << 8) + data[0]; Temp = Temp >> 4; temp = String(F("Temp ")) + Temp + "*C"; return temp; } void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === /// byte reminder = 0; int bitstate = 7; for (unsigned int i = 0; i < instr.length(); i++) { byte b = instr[i]; byte bb = b << (7 - bitstate); char c = (bb + reminder) & 0x7F; outstr += c; reminder = b >> bitstate; bitstate--; if (bitstate == 0) { char c = reminder; outstr += c; reminder = 0; bitstate = 7; } } } void InitModem() { /// === инициализация модема === /// gsm.begin(9600); //Скорость порта для связи Arduino с GSM модулем waitConnect(); String val = sendATCommand(F("ATI"), true); if (val.indexOf(F("M590")) > -1) ModemID = 1; else if (val.indexOf(F("SIM800")) > -1) ModemID = 2; else if (val.indexOf("A6") > -1) ModemID = 3; Serial.println(String(F("ModemID ")) + ModemID + "\n"); for (int i = 0; i < 6; i++) { sendATCommand(AT[i], true); // включить АОН } } String sendATCommand(String cmd, bool waiting) { String atval = ""; // Переменная для хранения результата Serial.println(cmd); // Дублируем команду в монитор порта gsm.println(cmd); // Отправляем команду модулю // if (waiting) { // Если необходимо дождаться ответа... atval = waitgsm(); // ... ждем, когда будет передан ответ Serial.println(atval); // Дублируем ответ в монитор порта // } return atval; // Возвращаем результат. Пусто, если проблема } void waitConnect() { // запуск модема int countok = 0; uint32_t msAT = 0; String str; while(countok < 5) { //ждём пять ОК uint32_t ms = millis(); if(( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс msAT = ms; Serial.println(">>AT"); gsm.println("AT"); // посылаем команду str = ""; delay(100); // ждём ответа str = waitgsm(); if (str.indexOf("OK") > -1) { Serial.println("OK"); countok++; } else countok = 0; } } } void sms(String text, byte sendnum) { /// === отправка СМС === /// String phone = ""; text = text + TempC(); if (sendsmscaller == 1 && sendnum == 0) { // отправка смс на номер звонившего phone = RingPhone; // delay(500); sendATCommand("AT+CMGS=\"" + phone + "\"", true); // Переходим в режим ввода текстового сообщения sendATCommand(text + (String)((char)26), true); // После текста отправляем перенос строки и Ctrl+Z Serial.println(String(F("SMS send=>")) + phone); Serial.println(String(F("SMS sended=>")) + phone + "\n" + text + "\n"); } else if (sendsmscaller == 1 && sendnum == 1) { // отправка смс на все номера for (int i = 0; i < 4 ; i++) { phone = AlarmPhone[i]; if (phone != 0) { // delay(500); sendATCommand("AT+CMGS=\"" + phone + "\"", true); // Переходим в режим ввода текстового сообщения sendATCommand(text + (String)((char)26), true); // После текста отправляем перенос строки и Ctrl+Z Serial.println(String(F("SMS send=>")) + phone); Serial.println(String(F("SMS sended=>")) + phone + "\n" + text + "\n"); // delay(2000); } } } else if (sendsmscaller == 0) Serial.println("text:\n" + text + "\n"); }Да будет срач! :)
https://mysku.ru/blog/ebay/43282.html#comment2341680
kvolk, спасибо. Будем изучать
Там кода нет.
А я скачал :)
kvolk, навскидку, можно оптимизировать ваш код процентов на 5, если заменить условия:
if { } if { } if { }на:
if { } else if { } else if { }