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

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

4.25 много, снижайте, стабильное напряжение надо

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

pasha413 пишет:

это не мусор!

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

12 Call Ready
13  
14 SMS Ready
 

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

 

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

Исправил, но нечего не меняется.

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

pasha413 пишет:

4.25 много, снижайте, стабильное напряжение надо

на данном напряжении модем начал греться

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

Тоже долгодмусился sim800, сделал так и теперь проблем нет,

Преобразователь dc/dc360, вместо потенциометра, резак на 27к. Как раз 4.0В

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

Я использую HW-411.

Нашел Б.П. 5В, попробую с него подать питание. Отпишу когда подам

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

pasha413 пишет:

Тоже долгодмусился sim800, сделал так и теперь проблем нет,

Преобразователь dc/dc360, вместо потенциометра, резак на 27к. Как раз 4.0В

Эксперимент приостанавливается, поехал за новой ардуиной, что то померла эта(

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

ужас, а из-за чего?

:=(

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

pasha413 пишет:

ужас, а из-за чего?

:=(


Ничего не делал, выключил потом включил, чип горячий, нечего не шьет. Если питание только по USB то горит on и L. Если питание 5В то только L

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Теперь ты знаешь, что такое тиристорный эффект.

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

Andy пишет:

Теперь ты знаешь, что такое тиристорный эффект.


Всмысле?)

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

Andy пишет:

В самом прямом смысле: http://www.chipinfo.ru/literature/compeljournal/2005/200502/p8.html

Ну то что плату в мусор то понятно)
Судя по статье, первое это подаем 5V, потом USB. 5V не отключал, только USB)

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

Спасибо этой теме и людям в ней!
Все что мне было надо  - у меня заработало.

На основе ваших скетчев я сделал GSM реле в 3 канала...
С памятью последних положений ну и со всем остальным что тут есть.

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

Djoin пишет:

Спасибо этой теме и людям в ней!
Все что мне было надо  - у меня заработало.

На основе ваших скетчев я сделал GSM реле в 3 канала...
С памятью последних положений ну и со всем остальным что тут есть.

пожалуйста :)

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

pasha413 пишет:
Я вначале писал: "у меня Arduino nano v3 (ATmega168), поэтому как ни крути а все не вместишь в него. Для моих нужд самое то, тем более цена вопроса в итоге проучается около 300р. За эти деньги ничего похожего не купишь.

 

Новая железка на руках, взял тоже Arduino nano v3. У Вас она питается как и модем, от 4.2В?

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

kot488 пишет:

Новая железка на руках, взял тоже Arduino nano v3. У Вас она питается как и модем, от 4.2В?

не, ардуина питается от usb, а для питания модема нужно 4.2В (отдельное питание). вот для вас схема:

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

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

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

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

Вот так сеть отрабатывает отлично

#include <SoftwareSerial.h>
SoftwareSerial SIM800(8, 9);        // 8 - RX Arduino (TX SIM800L), 9 - TX Arduino (RX SIM800L)
void setup() {
  Serial.begin(9600);               // Скорость обмена данными с компьютером
  Serial.println("Start!");
  SIM800.begin(9600);               // Скорость обмена данными с модемом
  SIM800.println("AT");
}

long lastcmd = millis();
void loop() {
  if (SIM800.available())           // Ожидаем прихода данных (ответа) от модема...
    Serial.write(SIM800.read());    // ...и выводим их в Serial
  if (Serial.available())           // Ожидаем команды по Serial...
    SIM800.write(Serial.read());    // ...и отправляем полученную команду модему

  if (millis() - lastcmd > 5000) {  // Прошло ли 5 секунд
    lastcmd = millis();             // Фиксируем время
    SIM800.println("AT+CSQ");       // Запрашиваем информацию о качестве сигнала
  }
}

 

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

A6 питание 5V. читайте pdf на модем

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

pasha413 пишет:

A6 питание 5V. читайте pdf на модем

И на А6 так же тишина(

 

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

Благодаря martinhol с drive2, на данный момент бьюсь над GPRS версией:

#include <EEPROM.h>
#include <RCSwitch.h>
#include <SoftwareSerial.h>
#include <DallasTemperature.h>      // подключаем библиотеку чтения датчиков температуры

SoftwareSerial SIM800(7, 6);        // для новых плат начиная с версии RX,TX
OneWire oneWire(4);                 // и настраиваем  пин 4 как шину подключения датчиков DS18B20
DallasTemperature sensors(&oneWire);
RCSwitch mySwitch = RCSwitch();  // беспроводной датчик двери, пин 2.

#define LED    13           // на светодиод (моргалку)
#define BAT    15           // на батарею, через делитель напряжения 39кОм / 11 кОм
/*  ------------------------------------- ДАТЧИКИ ------------------------*/
#define DOOR   8           // концевик двери. если сработал, на входе "+" HIGH.
#define PIR    9           // датчик движения. если сработал, на входе "+" HIGH.
#define BUZ    10           // сирена. если "-" LOW, то горит.
#define GAS    14           // датчик дыма. если сработал, на входе "+" HIGH.
#define sarai 3258553       // адрес 433 передатчика геркона двери. если сработал, на пин 2 сигнал.

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

#define on  "on"            // вкл
#define off "off"           // выкл
unsigned int p = 0;
#define GASThres 400        // предельная концентрация газа
#define time_sarai 10       // секунд не смотрим на датчик двери 2.
unsigned long lasttime_sarai = 0;
#define interval_led 1000   // для мигания LED, 1 сек.
unsigned long previousMillis_led = 0;
/*  ----------------------------------------- НАСТРОЙКИ MQTT брокера---------------------------------------------------------   */
const char *MQTT_user   = "****";     // api.cloudmqtt.com > Details > User  
const char *MQTT_pass   = "*****"; // api.cloudmqtt.com > Details > Password
const char *MQTT_type   = "****";       // тип протокола
const char *MQTT_CID    = "Home Alarm";    // уникальное имя устройства в сети MQTT
const char *MQTT_SERVER = "******";  // api.cloudmqtt.com > Details > Server  сервер MQTT брокера
const char *PORT        = "******4";                     // api.cloudmqtt.com > Details > Port    порт MQTT брокера
/*  ----------------------------------------- ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ !!!---------------------------------------------------------   */
const char *APN = "internet.tele2.ru";       // тчка доступа выхода в интернет вашего сотового оператора
//String USER = "";                          // имя выхода в интернет вашего сотового оператора
//String PASS = "";                          // пароль доступа выхода в интернет вашего сотового оператора

/*  ----------------------------------------- ДАЛЕЕ НЕ ТРОГАЕМ ---------------------------------------------------------------   */
bool broker = false;                     // статус подклюлючения к брокеру
bool Firststart = true;                  // первый старт.
bool Guard = false;                      // состояние охраны после подачи питания
bool Buzer = false;                      // состояние охраны после подачи питания
bool Ring = false;                       // состояние охраны после подачи питания
bool Sms = false;                        // состояние охраны после подачи питания
bool Door = false;                       // состояние охраны после подачи питания
bool Saray = false;                      // состояние охраны после подачи питания
bool Pir = false;                        // состояние охраны после подачи питания
bool Gas = false;                        // состояние охраны после подачи питания
int interval = 3;                        // интервал отправки данных на сервер после загрузки ардуино
int Timer = 10;                          // Секунд до отключения "тревожного" пина. 
unsigned long lasttimer = 0;
int inDS = 0;
float m = 68.01;                         // делитель для перевода АЦП в вольты для резистров 39/11kOm
float TempDS[11];                        // массив хранения температуры c рахных датчиков 
float Vbat, V_min;                       // переменная хранящая напряжение бортовой сети
unsigned long Time1, Time2 = 0;

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

void setup() {
  Serial.begin(9600);                    //скорость порта
  SIM800.begin(9600);                    //скорость связи с модемом
  SIM800_reset();
  pinMode(DOOR, INPUT_PULLUP);           // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);  digitalWrite(PIR, HIGH); //
  mySwitch.enableReceive(0);             // RF433 приемник на 2 пине
  pinMode(GAS, INPUT);
  pinMode(BUZ, OUTPUT); digitalWrite(BUZ, LOW);  // сирена выкл.
  pinMode(LED, OUTPUT);                  // указываем пин на выход (светодиод)
  Serial.println(F("MQTT alarm\n")); 
  Serial.println(eepromphone());
  Serial.println("");
  eepromconfig();
  Serial.println(eepromtext());
  Serial.println("");
}

void loop() {
  AlarmPinOff();
  if (SIM800.available())  resp_modem();                       // если что-то пришло от SIM800 в Ардуино отправляем для разбора
  if (Serial.available())  resp_serial();                      // если что-то пришло от Ардуино отправляем в SIM800
  if (millis()> Time1 + 10000) Time1 = millis(), detection();  // выполняем функцию detection () каждые 10 сек 
  if (millis()> Time2 + 3600000) {                             // каждый час 
    Time2 = millis(); 
    Signal();
    SIM800.println("AT+CIPSEND"), delay (200);  
    MQTT_PUB ("home/signal", CSQ);
    MQTT_PUB ("home/balance", MONEY);
    SIM800.write(0x1A); 
  }
}

void resp_serial() {     // ---------------- ТРАНСЛИРУЕМ КОМАНДЫ из ПОРТА В МОДЕМ ----------------------------------
  String at = "";   
  int k = 0;
  while (Serial.available()) {
    k = Serial.read();
    at += char(k);
    delay(1);
  }
  Komand(at);                             // запускаем подпрограмму распознавания команд
} 

float VoltRead() {                        // замеряем напряжение на батарее и переводим значения в вольты
  float ADCC = analogRead(BAT);
  ADCC = ADCC / m ;
  Serial.println(String(F("Напряжение: ")) + ADCC + "V");    
  if (ADCC < V_min) V_min = ADCC;                   
  return(ADCC);                           // переводим попугаи в вольты
} 

void detection() {                        // условия проверяемые каждые 10 сек  
  Detect();
  Vbat = VoltRead();                      // замеряем напряжение на батарее
  Serial.println(String(F("Интервал: ")) + interval);
  inDS = 0;
  sensors.requestTemperatures();          // читаем температуру с трех датчиков
  while (inDS < 10) {
    TempDS[inDS] = sensors.getTempCByIndex(inDS);  // читаем температуру
    if (TempDS[inDS] == -127.00) {
      TempDS[inDS]= 80;
      break;                              // пока не доберемся до неподключенного датчика
    }
    inDS++;
  } 
  for (int i=0; i < inDS; i++) {
    Serial.println(String(F("Temp")) + i + "= " + TempDS[i]); 
  }
  Serial.println("");
  interval--;
  if (interval < 1) { 
    interval = 6; 
    if (broker == true) { 
eepromconfig();
eepromtext();
      SIM800.println("AT+CIPSEND"), delay (200);  
/////////////------состояние датчиков----------/////////////
      MQTT_FloatPub ("home/ds0",      TempDS[0],2);
      MQTT_FloatPub ("home/ds1",      TempDS[1],2);
      MQTT_FloatPub ("home/vbat",     Vbat,2);
/////////////------состояние системы----------/////////////
      MQTT_PUB      ("home/guard",    Guard ? "lock" : "unlock");
      MQTT_PUB      ("home/buzer",    Buzer ? "buzeron" : "buzeroff");
      MQTT_PUB      ("home/ring",     Ring ? "ringon" : "ringoff");
      MQTT_PUB      ("home/sms",      Sms ? "smson" : "smsoff");
      MQTT_PUB      ("home/door",     Door ? "dooron" : "dooroff");
      MQTT_PUB      ("home/saray",    Saray ? "sarayon" : "sarayoff");
      MQTT_PUB      ("home/pir",      Pir ? "piron" : "piroff");
      MQTT_PUB      ("home/gas",      Gas ? "gason" : "gasoff");
      MQTT_FloatPub ("home/timer",    Timer, 0);
      MQTT_FloatPub ("home/uptime",   millis()/3600000,0); 
      SIM800.write(0x1A); 
    } else SIM800.println(F("AT+SAPBR=3,1,\"Contype\",\"GPRS\""));    // подключаемся к GPRS 
  }  
}

void  MQTT_FloatPub(const char topic[15], float val, int x) {char st[10]; dtostrf(val,0, x, st), MQTT_PUB (topic, st);}

void  MQTT_PUB(const char MQTT_topic[15], const char MQTT_messege[15]) {          // пакет на публикацию
  SIM800.write(0x30), SIM800.write(strlen(MQTT_topic)+strlen(MQTT_messege)+2);
  SIM800.write((byte)0), SIM800.write(strlen(MQTT_topic)), SIM800.write(MQTT_topic); // топик
  SIM800.write(MQTT_messege);                                                        // сообщение
}

void  MQTT_SUB(const char MQTT_topic[15]) {                                       // пакет подписки на топик
  SIM800.write(0x82), SIM800.write(strlen(MQTT_topic)+5);                         // сумма пакета 
  SIM800.write((byte)0), SIM800.write(0x01), SIM800.write((byte)0);               // просто так нужно
  SIM800.write(strlen(MQTT_topic)), SIM800.write(MQTT_topic);                     // топик
  SIM800.write((byte)0);  
}

void MQTT_SEND(const char MQTT_topic[15], const char MQTT_messege[15]) {
  SIM800.println("AT+CIPSEND"), delay (200);  
  SIM800.write(0x30), SIM800.write(strlen(MQTT_topic)+strlen(MQTT_messege)+2);
  SIM800.write((byte)0), SIM800.write(strlen(MQTT_topic)), SIM800.write(MQTT_topic); // топик
  SIM800.write(MQTT_messege);                                                        // сообщение
  SIM800.write(0x1A); 
}

void resp_modem() {     //------------------ АНЛИЗИРУЕМ БУФЕР ВИРТУАЛЬНОГО ПОРТА МОДЕМА------------------------------
  String at = "";
  int k = 0;
  while (SIM800.available()) {
    k = SIM800.read();
    at += char(k);
    delay(1);           
  }
Serial.println(at);  
  if (at.indexOf(F("SMS Ready")) > -1 || at.indexOf(F("NO CARRIER")) > -1 ) {
    SIM800.println(F("AT+IPR=9600;E1+DDET=1;+CMGF=1;+CSCS=\"gsm\";+CNMI=2,2,0,0,0;+VTD=1;+CMEE=1;&W")); // Активируем АОН и декодер DTMF
    Signal();
/*  -------------------------------------- проверяем соеденеиние с ИНТЕРНЕТ, конектимся к серверу------------------------------------------------------- */
  } else if (at.indexOf(F("+CME ERROR:")) > -1 ) {
    broker = false, delay (50), SIM800.println("AT+CFUN=1,1"), interval = 6 ;
  } else if  (at.indexOf(F("AT+SAPBR=3,1,\"Contype\",\"GPRS\"\r\r\nOK")) > -1 ) {
    SIM800.println(String(("AT+SAPBR=3,1,\"APN\",\"")) + APN + "\""); 
  } else if (at.indexOf(String(("AT+SAPBR=3,1,\"APN\",\"")) + APN + "\"\r\r\nOK") > -1 ) {
    SIM800.println(F("AT+SAPBR=1,1")), delay (1000); // устанавливаем соеденение   
  } else if (at.indexOf(F("AT+SAPBR=1,1\r\r\nOK")) > -1 )  {
    SIM800.println(F("AT+SAPBR=2,1")),delay (1000);  // проверяем статус соединения  
  } else if (at.indexOf(F("+SAPBR: 1,1")) > -1 ) {
    SIM800.println(String(("AT+CIPSTART=\"TCP\",\"")) + MQTT_SERVER + "\",\"" + PORT + "\"");
/*  -------------------------------------- команды управления ------------------------------------------*/
  } else if (at.indexOf(F("home/comandlock"),4) > -1 ) guard(1),   MQTT_SEND ("home/send", "lock");
    else if (at.indexOf(F("home/comandunlock"),4) > -1 ) guard(0), MQTT_SEND ("home/send", "unlock"); 
    else if (at.indexOf(F("home/comandbuzeron"),4) > -1 ) buzer(1), MQTT_SEND ("home/send", "buzeron");
    else if (at.indexOf(F("home/comandbuzeroff"),4) > -1 ) buzer(0), MQTT_SEND ("home/send", "buzeroff");
    else if (at.indexOf(F("home/comandringon"),4) > -1 ) ring(1), MQTT_SEND ("home/send", "ringon");
    else if (at.indexOf(F("home/comandringoff"),4) > -1 ) ring(0), MQTT_SEND ("home/send", "ringoff");
    else if (at.indexOf(F("home/comandsmson"),4) > -1 ) sms(1), MQTT_SEND ("home/send", "smson");
    else if (at.indexOf(F("home/comandsmsoff"),4) > -1 ) sms(0), MQTT_SEND ("home/send", "smsoff");
    else if (at.indexOf(F("home/comanddooron"),4) > -1 ) door(1), MQTT_SEND ("home/send", "dooron");
    else if (at.indexOf(F("home/comanddooroff"),4) > -1 ) door(0), MQTT_SEND ("home/send", "dooroff");
    else if (at.indexOf(F("home/comandpiron"),4) > -1 ) pir(1), MQTT_SEND ("home/send", "piron");
    else if (at.indexOf(F("home/comandpiroff"),4) > -1 ) pir(0), MQTT_SEND ("home/send", "piroff");
    else if (at.indexOf(F("home/comandgason"),4) > -1 ) gas(1), MQTT_SEND ("home/send", "gason");
    else if (at.indexOf(F("home/comandgasoff"),4) > -1 ) gas(0), MQTT_SEND ("home/send", "gasoff");
    else if (at.indexOf(F("home/comandsarayon"),4) > -1 ) saray(1), MQTT_SEND ("home/send", "sarayon");
    else if (at.indexOf(F("home/comandsarayoff"),4) > -1 ) saray(0), MQTT_SEND ("home/send", "sarayoff");
    else if (at.indexOf(F("home/settimer"),4) > -1 ) {
    Timer = at.substring(at.indexOf("") + 17, at.indexOf("") + 20).toInt();
    EEPROM.put(10, Timer); 
  } else if (at.indexOf(F("home/comandrefresh"),4) > -1 ) {
//Serial.println(F("Команда обновления"));
  Serial.println(eepromphone());
  Serial.println("");
    eepromconfig();
    eepromtext();
  Serial.println("");
    SIM800.println("AT+CIPSEND"),   delay (200);  
/////////////------состояние датчиков----------/////////////
    MQTT_FloatPub ("home/ds0",      TempDS[0],2);
    MQTT_FloatPub ("home/ds1",      TempDS[1],2);
    MQTT_FloatPub ("home/vbat",     Vbat,2);
    MQTT_PUB      ("home/door",     DOORFlag ? "dooropen" : "doorclose");
    MQTT_PUB      ("home/pir",      PIRFlag ? "piropen" : "pirclose");
    MQTT_PUB      ("home/saray",    SARAYFlag ? "sarayopen" : "sarayclose");
    MQTT_PUB      ("home/gas",      GASFlag ? "gasopen" : "gasclose");
/////////////------состояние системы----------/////////////
    MQTT_PUB      ("home/guard",    Guard ? "lock" : "unlock");
    MQTT_PUB      ("home/buzer",    Buzer ? "buzeron" : "buzeroff");
    MQTT_PUB      ("home/ring",     Ring ? "ringon" : "ringoff");
    MQTT_PUB      ("home/sms",      Sms ? "smson" : "smsoff");
    MQTT_PUB      ("home/door",     Door ? "dooron" : "dooroff");
    MQTT_PUB      ("home/saray",    Saray ? "sarayon" : "sarayoff");
    MQTT_PUB      ("home/pir",      Pir ? "piron" : "piroff");
    MQTT_PUB      ("home/gas",      Gas ? "gason" : "gasoff");
    MQTT_PUB      ("home/signal",   CSQ);
    MQTT_PUB      ("home/balance",  MONEY);
    MQTT_FloatPub ("home/timer",    Timer, 0);
    MQTT_FloatPub ("home/uptime",   millis()/3600000,0); 
    SIM800.write(0x1A); 
    interval = 6; // швырнуть данные на сервер и ждать 60 сек
  } else if (at.indexOf(F("CONNECT OK\r\n")) > -1 ) MQTT_CONNECT (); // после соединения с сервером отправляем пакет авторизации, публикации и пдписки у брокера
    else if (at.indexOf(F("+CLIP: ")) > -1) {      // если обнаружен вызов.
      SIM800.println(F("ATH"));                 // снимаем трубку  
      for (int i = 0; i < 5; i++) {             // проверяем сохраненные номера
        if (at.indexOf(AlarmPhone[i]) > -1 && AlarmPhone[i] != 0) {  // если он наш
          RingPhone = AlarmPhone[i];            // запоминаем номер звонящего
          RingPhone.toCharArray(Phone, 14);   
          EEPROM.put(100, Phone);               // записываем RingPhone в память. 
        } else if (Firststart) {                // если первый старт
          int ind = at.indexOf(F("+CLIP: \"")); // обрезаем номер ... 
          ind += 8;
          String ring = at.substring(ind, at.indexOf("\"", ind));
          RingPhone = ring;                     // запоминаем номер звонящего 
          ring.toCharArray(Phone, 14);          // сохраняем в переменную Phone
          EEPROM.put(25, Phone);                // пишем номер в EEPROM как основной мастер-номер
          EEPROM.put(100, Phone);               // записываем RingPhone в память. 
          AlarmPhone[0] = Phone;                // запишем
          Firststart = false;                   // пишем 0
          EEPROM.update(10, Firststart);        // обновляем Firststart
Serial.println(String(F("Firststart:")) + Firststart);
//sms(String(F("Master0:")) + ring + " Ok", 0); // смс на звонивший
//sms("Master0:" + ring + " Ok", 0);            // смс на звонивший
        } 
      }
  } else if (at.indexOf(F("+CSQ:")) > -1) {                  // если пришел уровень сигнала
    at = at.substring(at.indexOf(":") + 2, at.indexOf(",")); // парсим ответ об уровне сигнала
    at.trim();                                               // удаляем пробелы вначале и в конце строки
    at.toCharArray(CSQ, 4);    
    Balance();
  } else if (at.indexOf(F("+CUSD:")) > -1) {                 // если пришел баланс
    int p1 = at.indexOf("\"");                               // начало строки
    int p2 = at.lastIndexOf("\"");                           // конец строки
    at = at.substring(p1 + 1, p2);                           // обрезаем строку
    String money = getBalFromString(at);                     // обрезаем числовые
    money.toCharArray(MONEY, 10);                            // конвертируем
    SIM800.println(F("AT+CUSD=0"));   
  } 
}

void MQTT_CONNECT() {
  SIM800.println("AT+CIPSEND"), delay (100);
  SIM800.write(0x10);                                                              // маркер пакета на установку соединения
  SIM800.write(strlen(MQTT_type)+strlen(MQTT_CID)+strlen(MQTT_user)+strlen(MQTT_pass)+12);
  SIM800.write((byte)0),SIM800.write(strlen(MQTT_type)),SIM800.write(MQTT_type);   // тип протокола
  SIM800.write(0x03), SIM800.write(0xC2),SIM800.write((byte)0),SIM800.write(0x3C); // просто так нужно
  SIM800.write((byte)0), SIM800.write(strlen(MQTT_CID)),  SIM800.write(MQTT_CID);  // MQTT  идентификатор устройства
  SIM800.write((byte)0), SIM800.write(strlen(MQTT_user)), SIM800.write(MQTT_user); // MQTT логин
  SIM800.write((byte)0), SIM800.write(strlen(MQTT_pass)), SIM800.write(MQTT_pass); // MQTT пароль
  MQTT_PUB ("home/status", "Подключено");                                          // пакет публикации
  MQTT_SUB ("home/comand");                                                        // пакет подписки на присылаемые команды
  MQTT_SUB ("home/settimer");                                                        // пакет подписки на присылаемые команды
  MQTT_PUB ("home/signal",   CSQ);
  MQTT_PUB ("home/balance",  MONEY);
  MQTT_FloatPub ("home/timer", Timer, 0);
  SIM800.write(0x1A), broker = true;                                              // маркер завершения пакета
}


void Signal() {
  SIM800.println(F("AT+CSQ"));                               // проверяем уровень сигнала сети     
}

void Balance() {
  SIM800.println(String(F("AT+CUSD=1,\"#")) + Bal + ("#\",15"));               // проверяем баланс на симкарте
}

void guard (bool st) {
  Guard = st;
  EEPROM.write(1, st);                      // пишем в EEPROM
}

void buzer(bool st) {
  Buzer = st;
  EEPROM.write(2, st);                      // пишем в EEPROM
}

void ring(bool st) {
  Ring = st;
  EEPROM.write(3, st);                      // пишем в EEPROM
}

void sms(bool st) {
  Sms = st;
  EEPROM.write(4, st);                      // пишем в EEPROM
}

void door(bool st) {
  Door = st;
  EEPROM.write(5, st);                      // пишем в EEPROM
}

void saray(bool st) {
  Saray = st;
  EEPROM.write(6, st);                      // пишем в EEPROM
}

void pir(bool st) {
  Pir = st;
  EEPROM.write(7, st);                      // пишем в EEPROM
}

void gas(bool st) {
  Gas = st;
  EEPROM.write(8, st);                      // пишем в EEPROM
}

String getBalFromString(String str) {            // Функция извлечения цифр из сообщения - для парсинга баланса из USSD-запроса
  bool   flag     = false;
  String result   = "";
  str.replace(",", ".");                          // Если в качестве разделителя десятичных используется запятая - меняем её на точку.
  for (int i = 0; i < str.length(); i++) {
    if (isDigit(str[i]) || (str[i] == (char)46 && flag)) {        // Если начинается группа цифр (при этом, на точку без цифр не обращаем внимания),
      if (result == "" && i > 0 && (String)str[i - 1] == "-") {   // Нельзя забывать, что баланс может быть отрицательным
        result += "-";                            // Добавляем знак в начале
      }
      result += str[i];                           // начинаем собирать их вместе
      if (!flag) flag = true;                     // Выставляем флаг, который указывает на то, что сборка числа началась.
    }
    else  {                                       // Если цифры закончились и флаг говорит о том, что сборка уже была,
      if (str[i] != (char)32) {                   // Если порядок числа отделен пробелом - игнорируем его, иначе...
        if (flag) break;                          // ...считаем, что все.
      }
    }
  }
  return result;                        // Возвращаем полученное число.
}

void SIM800_reset() { // перезагрузка модема 
  SIM800.println("AT+CFUN=1,1");
}                        

void eepromconfig() { /// === конфигурирование сигнализации === ///
  if (EEPROM.read(0) != 1) {           // если по 0 адресу записана не 1, переписываем в память 000
    for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
      EEPROM.write(i, 0);
    }                               // и записываем:
    EEPROM.update(0, 1);            // пишем 1 в 0 адрес
    EEPROM.update(1, 0);            // Guard       охрана выкл.
    EEPROM.update(2, 0);            // Sirena      сирена при сработке вкл.
    EEPROM.update(3, 0);            // RING        вызов при сработке вкл.
    EEPROM.update(4, 0);            // SMS         смс при сработке вкл.
    EEPROM.update(5, 0);            // DOOR        датчики дверей вкл.
    EEPROM.update(6, 0);            // SARAI       датчики дверей вкл.
    EEPROM.update(7, 0);            // PIR         датчик движения вкл.
    EEPROM.update(8, 0);            // GAS         датчик газа вкл.
    EEPROM.update(9, 1);            // Firststart  первый старт!
Serial.println(F("EEPROM != 1/ RESET!"));
  } if (EEPROM.read(0) == 1) {      // если в 0 записана 1, считываем конфигурацию
    Guard      = EEPROM.read(1);    // Охрана
    Buzer      = EEPROM.read(2);    // Сирена
    Ring       = EEPROM.read(3);    // Вызов
    Sms        = EEPROM.read(4);    // Отправка смс
    Door       = EEPROM.read(5);    // Датчик двери
    Saray      = EEPROM.read(6);    // Датчик двери
    Pir        = EEPROM.read(7);    // Датчик движения
    Gas        = EEPROM.read(8);    // Датчик газа/дыма
    Firststart = EEPROM.read(9);    // Первый старт
    EEPROM.get(10, Timer); 
  }
}

String eepromtext() { /// === состояние системы === ///
  String SIGN = "";         // текущее состояние системы.
  String sirena = "";       // сирена при сработке.
  String ring = "";         // вызов при сработке.
  String sms = "";          // смс при сработке.
  String door = "";         // датчика двери.
  String saray = "";        // датчика двери RF433.
  String pir = "";          // датчик движения.
  String gas = "";          // датчик газа.
  
  if (Guard) SIGN = F("System on\n"); else SIGN = F("System off\n");
  if (Buzer) sirena = F("Sirena on\n"); else sirena = F("Sirena off\n");
  if (Ring) ring = F("Ring on\n"); else ring = F("Ring off\n");
  if (Sms) sms = F("SMS on\n"); else sms = F("SMS off\n");
  if (Door) door = F("Door on\n"); else door = F("Door off\n");
  if (Saray) saray = F("Sarai on\n"); else saray = F("Sarai off\n");
  if (Pir) pir = F("Pir on\n"); else pir = F("Pir off\n");
  if (Gas) gas = F("Gas on\n"); else gas = F("Gas off");

  String LastEvent = SIGN + sirena + ring + sms + door + saray + pir + gas; // полное состояние системы и датчиков.
  return LastEvent;
}

String eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
  for (int i = 0; i < 5 ; i++) {
    EEPROM.get(Adress[i], Phone);        // считываем мастер-номера
    AlarmPhone[i] = Phone;
  }
  String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n";
  EEPROM.get(100, Phone);                // считываем номер последнего звонившего
  RingPhone = Phone;
  String ring = String(F("Ring ")) + RingPhone + "\n";
  EEPROM.get(20, Bal);                   // считываем номер баланса
  String bal = String(F("Balance *")) + Bal + "#";
  String EEPhone = numbers + ring + bal;
  return EEPhone;
}

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

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

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

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

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

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

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

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

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  if (DOORState == HIGH && !DOORFlag) {                  // если он сработал
    DOORFlag = true;                                     // ставим флаг
Serial.println(F("Dver' otkrita!"));
    MQTT_SEND ("home/door", "dooropen");
    if (Door) Alarm();                                             // запускаем подпрограмму Alarm        
  } else if (DOORState == LOW && DOORFlag) {                       
      DOORFlag = false;                                  // возвращаем флаг к начальному состоянию
Serial.println(F("Dver' zakrita!"));
      MQTT_SEND ("home/door", "doorclose");
  }
  if (mySwitch.available()) {                            // если датчик сарая включен
    unsigned long value = mySwitch.getReceivedValue();   // считываем значение с RF433
    if (value == sarai && !SARAYFlag) {                  // если он сработал
      lasttime_sarai = millis();                         // запускаем таймер
      SARAYFlag = true;                                  // ставим флаг
Serial.println(F("Sarai otkrit!"));       
//      MQTT_SEND ("home/saray", "sarayopen");
      if (Saray) Alarm();                                           // запускаем подпрограмму Alarm
    }
    mySwitch.resetAvailable();                          
  } 
  if (((millis() - lasttime_sarai)/1000 > time_sarai)) { // если прошол интервал
    SARAYFlag = false;                                   // возвращаем флаг к начальному состоянию
//    MQTT_SEND ("home/saray", "sarayclose");
  }
  if (PIRState == HIGH && !PIRFlag) {                    // если он сработал
    PIRFlag = true;                                      // ставим флаг
Serial.println(F("Dvizhenie u dveri!"));
    MQTT_SEND ("home/pir", "piropen");
    if (Pir) Alarm();                                             // запускаем подпрограмму Alarm
  } else if (PIRState == LOW && PIRFlag) {               // иначе если движения нет
      PIRFlag = false;                                   // возвращаем флаг к начальному состоянию
      MQTT_SEND ("home/pir", "pirclose");
  }
  if ((Smoky > GASThres) && !GASFlag) {                  // если он сработал
    GASFlag = true;                                      // ставим флаг
Serial.println(F("Gas v dome!"));
    MQTT_SEND ("home/gas", "gasopen");
    if (Gas) Alarm();                                             // запускаем подпрограмму Alarm 
  } else if ((Smoky < GASThres) && GASFlag) {            // иначе если газа нет
      GASFlag = false;                                   // возвращаем флаг к начальному состоянию
      MQTT_SEND ("home/gas", "gasclose");
  }
}

void Alarm() { /// === аварийные сигналы === ///
  if (Buzer) {                              // если включена сирена при сработке
    lasttimer = millis();                       // запускаем таймер сирены
    digitalWrite(BUZ, HIGH);                // запускаем ее
  }
Serial.println(F("Alarm!!!"));
    if (DOORFlag) {                          // если сработал датчик двери
   
    } 
    if (SARAYFlag) {                  // если сработал датчик двери RF433
    
    } 
    if (PIRFlag) {                    // если сработал датчик движения
    
    } 
    if (GASFlag) {                    // если сработал датчик газа
   
    } 
}

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

смс пока не проверял, еще не все добавил, но работает. использую приложение MQTT dash, но оно не устраивает отсутствием уведомлений и виджета.

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

AleksandrM
Offline
Зарегистрирован: 20.07.2017

pasha413 Что должно быть в строке : MQTT_type ?

A6 mini подойдет для проэкта?

 

 

 

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

AleksandrM, про MQTT_type позже напишу.
А6 не подойдёт, хотя если можете переписать под под него, то не проблема (у меня завести gprs на А6 была проблема)

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

pasha413 пишет:
AleksandrM, про MQTT_type позже напишу. А6 не подойдёт, хотя если можете переписать под под него, то не проблема (у меня завести gprs на А6 была проблема)

Паша. я на А6 в инет выходил без проблем, Яндекс скачивался. Дальше правда не копал, проект с А6 пока заброшен, отодвинут более актуальными задачками :)

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

У меня 2 А6, один трудится на даче - сигналка, второй лежит в запасе.
И 2 сим800 (один не поддерживает gprs - выйду с отпуска буду прошивать)

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

pasha413 пишет:
У меня 2 А6, один трудится на даче - сигналка, второй лежит в запасе. И 2 сим800 (один не поддерживает gprs - выйду с отпуска буду прошивать)

сим800Н  у вас? и как вы его прошьете??

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

pasha413 пишет:

 

смс пока не проверял, еще не все добавил, но работает. использую приложение MQTT dash, но оно не устраивает отсутствием уведомлений и виджета.

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

 

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

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

SIM800l. Где-то ссылку сохранял, завтра кину, все на работе, отпуск же)))
Что-то типа этого
https://elementztechblog.wordpress.com/2016/08/02/updating-firmware-of-s...

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

Не, завтра выйду с отпуска, начну вливаться))

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

pasha413 пишет:
SIM800l. Где-то ссылку сохранял, завтра кину, все на работе, отпуск же))) Что-то типа этого https://elementztechblog.wordpress.com/2016/08/02/updating-firmware-of-sim800-gsm-module/

 

 

вот этот модуль хотите перешить?? именно перешить а не файлы в него прописать??

а вы сначала поинтересуйтесь, те пины что вам нужны доступны на этом модуле на фото??

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

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

вот на сим800С там требуемые контакты по любому доступны будут.

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

Short Circuit, у меня 2 модема, один с версией 1308, другой 1418., Вот первый не пошел по gprs, а второй норм. Завтра скину ссылку что я нашел по прошивке (смене по модема)

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

еще раз - должны быть доступны специальные контакты на  модуле.. иначе никак.

 через порт рхтх не  прошивается.

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

по поводу прошивки sim800 вот в этой теме писалось. с поста #9

http://arduino.ru/forum/apparatnye-voprosy/sim800l-ne-mozhet-zaregistrirovat-sim

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

AleksandrM пишет:

pasha413 Что должно быть в строке : MQTT_type ?

A6 mini подойдет для проэкта?

MQIsdp

AleksandrM
Offline
Зарегистрирован: 20.07.2017

Вот столкнулся с такой проблемой....

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

Модем зарегестрирован в сети, звонки на него идут но реакции 0.Модем А6 mini

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

Скетч из этой темы, допиленый под себя.

Как с этой бедой справиться?

Может периодически спрашивать что-то у оператора  и если нет ответа- сброс?

 

 

 

 

 

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

AleksandrM пишет:

Вот столкнулся с такой проблемой....

Может периодически спрашивать что-то у оператора  и если нет ответа- сброс?

 

 

 

 

 


Я периодически спрашиваю регистрацию в сети, если нет то перезагружаю модем

AleksandrM
Offline
Зарегистрирован: 20.07.2017

 

Можна кусочек кода для примера?

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

В loop() {
if (millis()/1000 > timer) { // проверяем каждый час
Signal(); // проверяем уровень сигнала
timer += 360;
} Пост 667 смотрите, не могу с телефона писать...до компа доберусь только в четверг))
Проверяем уровень сигнала и тем самым убиваем 2х зайцев (можно заменить на регистрацию в сети). В подпрограмме sendATcomand(): если не придет ответ на команду, дергаем ногу модема reset. Но это для А6го.
Для sim800 можно программно перезагружать: в 705 посте посмотрите)

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

pasha413 пишет:
Для sim800 можно программно перезагружать

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

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

Можно также ногой, там есть RST

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

Можно также ногой, там есть RST

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

andycat пишет:

pasha413 пишет:
Для sim800 можно программно перезагружать

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

по сравнению с сим300  800й как небо и земля..

виснет крайне редко.

НО!!  производитель рекомендует  снимать питание с модуля для перезагрузки зависшего модуля. Так что по питанию - это самый верный вариант.

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

pasha413 пишет:
В loop() { if (millis()/1000 > timer) { // проверяем каждый час Signal(); // проверяем уровень сигнала timer += 360; } Пост 667 смотрите, не могу с телефона писать...до компа доберусь только в четверг)) Проверяем уровень сигнала и тем самым убиваем 2х зайцев (можно заменить на регистрацию в сети). В подпрограмме sendATcomand(): если не придет ответ на команду, дергаем ногу модема reset. Но это для А6го. Для sim800 можно программно перезагружать: в 705 посте посмотрите)

 

хрен... проверять нужно каждые 3 минуты..

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

Здравствуйте.

Никто не пробовал запустить телеграмбота на arduino + SIM800?

Я вот нашел код

#define TINY_GSM_MODEM_SIM800
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
#include <UniversalTelegramBot.h>

#include <SoftwareSerial.h>
SoftwareSerial SerialAT(7, 6); // RX, TX

//#define DUMP_AT_COMMANDS
#define SerialMon Serial
#ifdef DUMP_AT_COMMANDS
  #include <StreamDebugger.h>
  StreamDebugger debugger(SerialAT, SerialMon);
  TinyGsm modem(debugger);
#else
  TinyGsm modem(SerialAT);
#endif

const char apn[] = "*****"; //apn
const char user[] = ""; //username
const char pass[] = ""; //pass

// Initialize Telegram BOT
#define BOTtoken "*******" // 
int Bot_mtbs = 1000; //mean time between scan messages
long Bot_lasttime; //last time messages' scan has been done

TinyGsmClientSecure client(modem);
UniversalTelegramBot bot(BOTtoken, client);

void setup() {
  Serial.begin(9600);
  SerialAT.begin(9600);
  delay(3000);
  modem.sendAT(GF("+HTTPS=1")); //enable ssl. maybe don't need
  modem.waitResponse();
  if (!modem.hasSSL()) {
    Serial.println(F("SSL is not supported by this modem"));
  return;
  }
  Serial.print(F("Waiting for network..."));
  if (!modem.waitForNetwork()) {
    Serial.println(" fail");
//    delay(10000);
    return;
  }
  Serial.println(" OK");
  Serial.print(F("Connecting to "));
  Serial.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    Serial.println(" fail");
//    delay(10000);
    return;
  } else {Serial.println(" OK");}
  IPAddress local = modem.localIP();
  modem.waitResponse();
  Serial.println(local);
}

void loop() {
  String chat_id = F("*****");
  String text = "HELLO!";
  String parses = "";
  Serial.println(F("Send message"));
  Serial.println(bot.sendMessage(chat_id, text, parses));
  delay(60000);
}

, но долго мучил его (не отправлялось сообщение), нашел все-таки ошибку, оказалось в строке 35 необходимо изменить на 

  modem.sendAT(GF("+HTTPSSL=1")); //enable ssl. maybe don't need

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

может у кого есть идеи?

smesharik
Offline
Зарегистрирован: 31.01.2016

вставлю свои 5 копеек. 

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

Питание как видите, одна понижайка на 5в (ардуино, реле, часы) и вторая на 3.3в на GSM. с другой стороны преобразователь уровней с 3.3 на 5в. Кстате после всякого навесного монтажа работать стало стабильнее, всяких проблем с модемом не стало. Правда есть кое какие косяки по разводке но это выяснилось потом при монтаже уже.

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

Так что код универсален и подстраивается как надо

п.с. в коде #705 ошибка (у меня не захотел работать как надо) 

153 ind += 8;

заменить на ind+=9, а то получается не состыковка по номерам, записывается в памяти как +79123456789 а последний звонивший отображается 79123456789 т.е. без +, и ардуинка не понимает 

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

smesharik, это, как выяснилось, с разными операторами необходимо менять (Теле2 и МТС номер возвращается с + и без). Насколько помню у сим800 питание от 3.6В-4.2В.

smesharik
Offline
Зарегистрирован: 31.01.2016

pasha413 пишет:
smesharik, это, как выяснилось, с разными операторами необходимо менять (Теле2 и МТС номер возвращается с + и без). Насколько помню у сим800 питание от 3.6В-4.2В.

Ну вы меня поняли :) По мануалу 3,4-4,4в. Я где то 3.8 поставил

У меня МТС идет с +

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

Использовали код из #705 поста?

smesharik
Offline
Зарегистрирован: 31.01.2016

pasha413 пишет:
Использовали код из #705 поста?

50/50, код создавался параллельно с темой, с 705 взята только работа с GSM модемом

AleksandrM
Offline
Зарегистрирован: 20.07.2017

Такая проблема нарисовалась: При добавлении мастер-номеров приходит сообщение /master1 add/.

Призвонке с добавленного номера 0 реакции как и на SMS. По команде PHONE показывает 1мастер и  добавленный номер.

при звонке с добавленного номера  в монитор порта пишет  "No Master Ring!" Где я что напутал?

/*   
 
     
     SMS команды управления
Звонок на устройство ставит на охрану - снимает с охраны       
z1on           Разрешение контроля Зоны 1
z1off          Запрет контроля Зоны1
z2on           Разрешение контроля Зоны 2
z2off          Запрет контроля Зоны2
z3on           Разрешение контроля Зоны 3
z3off          Запрет контроля Зоны3
z4on           Разрешение контроля Зоны 4
z4off          Запрет контроля Зоны4
out1on         Включение нагрузки 1 канала
out1off        Выключение нагрузки 1 канала
out2on         Включение нагрузки 2 канала
out2off        Выключение нагрузки 2 канала
out3on         Включение нагрузки 3 канала
out3off        Выключение нагрузки 3 канала
out4on         Включение нагрузки 4 канала
out4off        Выключение нагрузки 4 канала
money          Запрос баланса
info           Состояние системы
reset          Полный сброс системы. Первый позвонившый станет супермастером, Ввести номер баланса
balance:101    Для ввода номера баланса
smson          Разрешение отправки sirena:60 при сработке 
smsoff         Запрет отправки sirena:60 при сработке  
ringon         Разрешение звонка при сработке
ringoff        Запрет звонка при сработке
master1:+380*********  добавить мастер номер
sirenaon       Разрешить сирену при сработке
sirena0ff      Запретить сирену при сработке
phone          Список мастер номеров
dell:1         Удаление мастер номеров
systemon       Включить охрану         
systemoff      Выключить охрану 


*/



// max длинна сообщения в данный момент 135 символов.
#include <EEPROM.h>
#include <OneWire.h>
#include <SoftwareSerial.h>
#define Ver F("Alarm  v4.3.4\n")

OneWire ds(13);                  // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +.
SoftwareSerial gsm(8, 9);       // модем подключен к 7 и 8 пинам.
//RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2.
//#define    0  //UART
//#define    1  //UART
#define     DOOR 2              // пин 2. концевик двери.
#define     PIR  3               // пин 3. датчик движения.
//#define PIN4
//#define PIN5
#define     GAS  6               // пин 6. датчик дыма.
#define  SARAI 4
//#define  PIN8 //UART_GSM
//#define  PIN9 //UART_GSM
#define     BUZ 7              // пин 10. сирена.
#define     LED 11              // пин 11. состояние системы.
#define  REG 12           // Выход регулятора температуры
//#define  PIN13//DS18B20
#define  rst  A0
#define   OUT1  A1
#define   OUT2  A2
#define   OUT3  A3
#define   OUT4  A4
#define   POWER A5

// DOOR     - если сработал, на входе "+" HIGH.
// SARAI    - если сработал, на пин 2 сигнал.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит.
// LED      - если "-" LOW, то горит.
#define on "on"     // вкл
#define off "off"   // выкл
int8_t ModemID = 3;        //    тип модема
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 POWERFlag =1;
int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t SARAIFlag = 0;      // флаг состояние датчика двери 2.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t POWERState= LOW;
int8_t SARAIState = LOW;
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LEDState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t sendsmscaller = 1;  // разрешение отправки смс.
uint32_t msAT = 0;
int tr;
char CSQ[4];

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_power 10      // секунд не смотрим на питание.
int previousMillis_power = 0;
#define interval_pir 20        // секунд не смотрим на датчик движения.
int previousMillis_pir = 0;
#define interval_gas 20      // секунд не смотрим на датчик газа. 10минут
int previousMillis_gas = 0;
unsigned long timer = 300000;
/* EEPROM Data:
  № ячейки - значение:
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:                0 - выкл.
  2 - AlarmRING = 1;   // звонок:                1 - вкл.
  3 - SendSMS = 1;     // отправка смс:          1 - вкл.
  4 - DOORon = 1;      // концевик двери:        1 - вкл.
  5 - SARAIon = 1;     // концевик двери сарая:  1 - вкл.
  6 - PIRon = 1;       // датчик движения:       1 - вкл.
  7 - GASon = 1;       // датчик дыма:           1 - вкл.
  8 - Sirena = 1;      // сирена:                1 - вкл.
  10 - Firststars = 1; // первый запуск          1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// === настройка программы === ///
  Serial.begin(9600);
  Serial.println(Ver);
  pinMode(DOOR, INPUT_PULLUP);
  pinMode(SARAI, INPUT_PULLUP);    // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT_PULLUP);
  pinMode(GAS, INPUT_PULLUP);
  pinMode(BUZ, OUTPUT);
  pinMode(OUT1, OUTPUT);
  pinMode(OUT2, OUTPUT);
  pinMode(OUT3, OUTPUT);
  pinMode(OUT4, OUTPUT);
  pinMode(REG, OUTPUT);
  pinMode(LED, OUTPUT);             // светодиод горит во время запуска.
  digitalWrite(BUZ, LOW);        // сирена выкл.
  digitalWrite(PIR, HIGH);        // игнорируем при включении.
  digitalWrite(OUT1, LOW);
  digitalWrite(OUT2, LOW);
  digitalWrite(OUT3, LOW);
  digitalWrite(OUT4, LOW);
  digitalWrite(REG, LOW);
  pinMode(rst, OUTPUT); digitalWrite(rst, LOW);  //
  //   mySwitch.enableReceive(0);        // 433 приемник на 2 пине
  InitModem();                      // запускаем инициализация модема.
  eepromconfig();
  Serial.println(eepromtext());
  Serial.println(eepromphone());
  digitalWrite(LED, HIGH);        // гасим светодиод состояния сигнализации.

}

void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
   if (millis()/1000 > timer) {  // проверяем каждый час 
    TempC();
    Signal();
    timer += 60; 
  }
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
    regtemp();
  }
  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,p2);
        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("\","))); //
      }
      bal = bal.substring(1, 27);//26
      Serial.println(bal);
      sms("       SIM" "\n" " Na" + 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 Signal() { /// === проверка уровня сигнала сети === ///
  String csq = sendATCommand(F("AT+CSQ"));           
  csq = csq.substring(csq.indexOf(":") + 2, csq.indexOf(",")); // парсим ответ об уровне сигнала
  csq.trim();                                        // удаляем пробелы вначале и в конце строки
  csq.toCharArray(CSQ, 4);                           
}
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("Zona1 on\n"); else Door = F("Zona1 off\n");
  if (SARAIon == 1) Sarai = F("Zona4 on\n"); else Sarai = F("Zona4 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 + Door +Pir  + Gas+  Sarai;             // полное состояние системы и датчиков.
  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 = digitalRead(GAS);
  SARAIState = digitalRead(SARAI);
  POWERState= digitalRead(POWER);


  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 (POWERState == HIGH && POWERFlag == 0) {
      previousMillis_power = millis();
      POWERFlag = 1;
      //Serial.println(F("POWER OFF!"));
      Serial.println(F("POWER LOW!!!"));
      sms(F("POWER LOW!!!!\n"), 1); // смс на все номера
     
      Alarm();                                //
    }
    else if (POWERState == LOW && POWERFlag == 1) {
      int currentMillis_power = millis();
      if (((currentMillis_power - previousMillis_power) / 1000 > interval_power)) {
        POWERFlag = 0;
     // Serial.println(F("POWER LOW!!!"));
      sms(F("POWER Normal\n"), 1); // смс на все номера
     
      }
    }
  

  ////////////////////////////////////////////////////////////////////////////////////
  if (PIRon == 1) {
    if (PIRState == LOW && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
      Serial.println(F("PIR!"));
      Alarm();                                //
    }
    else if (PIRState == HIGH && PIRFlag == 1) {
      int currentMillis_pir = millis();
      if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_pir)) {
        PIRFlag = 0;
      }
    }
  }
  /////////////////////////////////////////////////////////////////
  if (GASon == 1) {
    if (Smoky == LOW && GASFlag == 0) {
      previousMillis_gas = millis();
      GASFlag = 1;
      Serial.println(F("GAS!"));
      Alarm();                                //
    }
    else if (Smoky == HIGH && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_gas)) {
        GASFlag = 0;
      }
    }
  }
  //////////////////////////////////////////////////////
  if (SARAIon == 1) {
    if (SARAIState == HIGH && SARAIFlag == 0) {
      previousMillis_sarai = millis();
      SARAIFlag = 1;
      Serial.println(F("SARAI!"));
      Alarm();                                //
    }
    else if (SARAIon == LOW && SARAIFlag == 1) {
      int currentMillis_sarai = millis();
      if (((currentMillis_sarai - previousMillis_sarai) / 1000 > interval_sarai)) {
        SARAIFlag = 0;
      }
    }
  }
}
void Alarm() { /// === запускаем сирену и отправку смс === ///
  previousMillis_alarm = millis();
  if (Sirena == 1) digitalWrite(BUZ, HIGH);
  Serial.println(F("Alarm!!!"));
  if (SendSMS == 1) {
    if (DOORFlag == 1) {
      Serial.println(F("Dver' otkrita"));
      sms(F("Dver'Zona1 otkrita!\n"), 1); // смс на все номера
    }
    else if (SARAIFlag == 1) {
      Serial.println(F("Sarai"));
      sms(F("Dver'Zona4 otkrita!\n"), 1); // смс на все номера
    }
    else if (PIRFlag == 1) {
      Serial.println(F("PIR"));
      sms(F("POGAR !!!!!\n"), 1); // смс на все номера
     }
  else if (POWERFlag == 1) {
  Serial.println(F("POWER LOW!!!"));
   sms(F("POWER LOW!!!!\n"), 1); // смс на все номера
        
   }
    else if (GASFlag == 1) {
      Serial.println(F("GAS"));
      sms(F("GASSS!\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, LOW);
  }
}
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("out1on"))) > -1) { // Включение канала 1
      digitalWrite(OUT1, HIGH);sms(F("OUT1 ON!!\n"), 1);
     } else if ((p = kom.indexOf(F("out1off"))) > -1) { // Выключение канала 1
      digitalWrite(OUT1, LOW);sms(F("OUT1 OFF!!\n"), 1);
     } else if ((p = kom.indexOf(F("out2on"))) > -1) { // Включение канала 2
      digitalWrite(OUT1, HIGH);sms(F("OUT2 ON!!\n"), 1);
     } else if ((p = kom.indexOf(F("out2off"))) > -1) { // Выключение канала 2
      digitalWrite(OUT1, LOW);sms(F("OUT2 OFF!!\n"), 1);
     } else if ((p = kom.indexOf(F("out3on"))) > -1) { // Включение канала 3
      digitalWrite(OUT1, HIGH);sms(F("OUT3 ON!!\n"), 1);
     } else if ((p = kom.indexOf(F("out3off"))) > -1) { // Выключение канала 3
      digitalWrite(OUT1, LOW);sms(F("OUT3 OFF!!\n"), 1);
     } else if ((p = kom.indexOf(F("out4on"))) > -1) { // Включение канала 4
      digitalWrite(OUT1, HIGH);sms(F("OUT4  ON!!\n"), 1);
     } else if ((p = kom.indexOf(F("out4off"))) > -1) { // Выключение канала 4
      digitalWrite(OUT1, LOW);sms(F("OUT4 OFF!!\n"), 1);
////////////******************************************************************************      
    } 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("z1")) > -1) {  // вкл/выкл контроль датчика двери
    if (kom.indexOf(on) > -1) {  // выкл
      DOORon = 1;
      EEPROM.update(4, DOORon);
      sms(String(F("Zona1->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл контроль датчика двери
      DOORon = 0;
      EEPROM.update(4, DOORon);
      sms(String(F("Zona1->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("z4")) > -1) {  // вкл/выкл контроль датчика двери 2
    if (kom.indexOf(on) > -1) {  // вкл
      SARAIon = 1;
      EEPROM.update(5, SARAIon);
      sms(String(F("Zona4->on\n")), 1); // смс на все номера
    } else if (kom.indexOf(off) > -1) {  // выкл
      SARAIon = 0;
      EEPROM.update(5, SARAIon);
      sms(String(F("Zona4->off\n")), 1); // смс на все номера
    }
  } else if (kom.indexOf(F("z2")) > -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("z3")) > -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;
  tr=Temp;
 
  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();
  sendATCommand(F("ATE0"));              // выключить эхо
  sendATCommand(F("AT+CLIP=1"));         // включить АОН
  sendATCommand(F("AT+CMGF=1"));         // включить текстовый формат смс
  sendATCommand(F("AT+CSCS=\"GSM\""));   // включить кодировку текста gsm
  sendATCommand(F("AT+CNMI=2,2,0,0,0")); // смс прямо в порт
  sendATCommand(F("AT+CREG?"));          // регистрация в сети
  sendATCommand(F("AT+CMGD=1,4"));       // стираем смс
}

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

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

 

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

Номер обрезает нормально:?
"RingPhone ......"