GSM устройство управления котлами Webasto и не только

Baron8
Offline
Зарегистрирован: 12.11.2019

изменил строку 1738, сейчас нормально работает на скетче 3.83

MaksVV
Offline
Зарегистрирован: 06.08.2015

в wtt выбирайте w-шина и сделайте лог хотябы минуту и скинуть сюда. 

Baron8 пишет:

изменил строку 1738, сейчас нормально работает на скетче 3.83

но лучше все таки 3.84

Baron8
Offline
Зарегистрирован: 12.11.2019

Вот сделал протоколирование монитором шины с режимами evo и vevo и снял протокол общения wtt с котлом https://drive.google.com/open?id=19zoOT6E9zd9SfIgV5GPKcrwBo-09PMkM когда снимал evo и vevo нажимал обновить, запуск и остановку. При подключению к wtt в конце нажал стереть ошибки

MaksVV
Offline
Зарегистрирован: 06.08.2015

ок поисследую, отличается протокол немного

MaksVV
Offline
Зарегистрирован: 06.08.2015

Baron8. вот скетч эмулятора вашего котла на шине W-BUS v3.1. Заливаете в голую ардуино (просто дуня ни к чему не подключенная, только юсб до компа). И в WTT выбираете вместо к-лайн адаптера  порт , на котором висит ардуина. Запускаете W-шину и поехали. Эмулятор нужен для расшаривания протокола. 

byte buf[40]; // буфер приёма сообщений
bool head =0;
#define sizeMes 29

// Для w-bus 3.1
//      Это команда и индекс  (только из команды нужно мысленно)) убрать старший бит, т.е. если было 0xD0, то это команда 0x50)
//            \/    \/
//            \/    \/
byte answ_message[][sizeMes] = {
{0x4F, 0x02, 0x90, 0xDD, 0xD4, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x03, 0xA0, 0x3B, 0xD4, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x03, 0xA1, 0x3B, 0xD4, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x03, 0xA2, 0x3B, 0xD4, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x03, 0xA1, 0x00, 0xD4, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x03, 0xA3, 0x3B, 0xD4, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x05, 0xB2, 0x03, 0x07, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x09, 0xB8, 0x0A, 0x00, 0x00, 0x02, 0x7E, 0x02, 0x7F, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x03, 0xC4, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x07, 0xD0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x04, 0xD0, 0x03, 0x00, 0x98, 0x00, 0x00, 0x00, 0x95, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x06, 0xD0, 0x04, 0x0D, 0x04, 0x02, 0x80, 0x00, 0x95, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x0B, 0xD0, 0x05, 0x44, 0x2F, 0x58, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x5E, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x0B, 0xD0, 0x06, 0x03, 0xEB, 0x1A, 0x38, 0xF9, 0x02, 0x51, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x09, 0xD0, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x95, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x1B, 0xD0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},///
{0x4F, 0x09, 0xD0, 0x0B, 0x00, 0x00, 0x00, 0x07, 0xF5, 0x28, 0x47, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x09, 0xD0, 0x0C, 0x00, 0x00, 0x27, 0xE2, 0xFF, 0xFF, 0x5F, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x08, 0xD0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x5F, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x05, 0xD0, 0x11, 0x8A, 0x78, 0x79, 0x00, 0x00, 0x98, 0x5F, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x06, 0xD0, 0x12, 0x00, 0x38, 0x18, 0xAB, 0x00, 0x98, 0x5F, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x07, 0xD0, 0x13, 0x03, 0x49, 0x00, 0x00, 0xC1, 0x98, 0x5F, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},


{0x4F, 0x08, 0xD1, 0x01, 0x00, 0x07, 0x05, 0x49, 0x42, 0x71, 0x5F, 0x8E, 0x7C, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x09, 0xD1, 0x02, 0x03, 0x02, 0x51, 0x01, 0x01, 0x18, 0x27, 0x04, 0x14, 0x06, 0x20, 0x27, 0x8E, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x09, 0xD1, 0x03, 0x00, 0x07, 0x22, 0x14, 0x41, 0x00, 0xAC, 0x04, 0x14, 0x06, 0x20, 0x27, 0x8E, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x06, 0xD1, 0x04, 0x02, 0x05, 0x28, 0xB5, 0x41, 0x00, 0xAC, 0x04, 0x14, 0x06, 0x20, 0x27, 0x8E, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x06, 0xD1, 0x05, 0x05, 0x06, 0x02, 0x9B, 0x41, 0x00, 0xAC, 0x04, 0x14, 0x06, 0x20, 0x27, 0x8E, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x9E, 0x25, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x17, 0xD1, 0x07, 0x52, 0x46, 0x35, 0x43, 0x20, 0x09, 0x0A, 0x10, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x02, 0x00, 0x07, 0x05, 0x49, 0x95, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x0A, 0xD1, 0x09, 0x00, 0x00, 0x37, 0x71, 0x62, 0x4B, 0x04, 0x99, 0x31, 0x30, 0x20, 0x32, 0x35, 0x30, 0x34, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x04, 0xD1, 0x0A, 0x31, 0xA3, 0x18, 0x45, 0x58, 0x57, 0x41, 0x99, 0x31, 0x30, 0x20, 0x32, 0x35, 0x30, 0x34, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x0b ,0xd1, 0x0b, 0x55, 0x32 ,0x32, 0x32 ,0x20, 0x20 ,0x20, 0x20, 0x82, 0x30, 0x20, 0x32, 0x35, 0x30, 0x34, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},


//{0x4F, 0x0a ,0xd1, 0x0c, 0x51, 0x7c, 0xc4 ,0xe7 ,0x3f ,0x80 ,0x00 ,0x29, 0x82, 0x30, 0x20, 0x32, 0x35, 0x30, 0x34, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x09 ,0xd1, 0x0c, 0x71, 0x7c, 0x40 ,0xe3 ,0x07 ,0x00 ,0x00 ,0x29, 0x82, 0x30, 0x20, 0x32, 0x35, 0x30, 0x34, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},


//{0x4F, 0x08, 0xD1, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x30, 0xAB ,0x00 ,0x29, 0x82, 0x30, 0x20, 0x32, 0x35, 0x30, 0x34, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x11, 0xD3, 0x02, 0x26, 0x48, 0xff, 0xff, 0xff, 0xff, 0x14, 0x3c, 0x8c, 0xff, 0xff, 0xff, 0xff, 0x06, 0x6E, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},
{0x4F, 0x04, 0xD6, 0x01, 0x00, 0x9C, 0x25, 0x1C, 0x30, 0xD4, 0xFA, 0x40, 0x74, 0x00, 0x00, 0x63, 0x9C, 0x05, 0x6E, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x06, 0xD7, 0x01, 0xB7, 0xA0, 0xC4, 0xA7, 0x30, 0xD4, 0xFA, 0x40, 0x74, 0x00, 0x00, 0x63, 0x9C, 0x05, 0x6E, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5},

{0x4F, 0x04, 0x7F, 0x60, 0x11, 0x45, 0xFF, 0xA7, 0x30, 0xD4, 0xFA, 0x40, 0x74, 0x00, 0x00, 0x63, 0x9C, 0x05, 0x6E, 0x00, 0x13, 0x22, 0x9C, 0x00, 0x70, 0x00, 0x00, 0x00, 0xE5}
};


byte answ50[] = {0x4F, 0x04, 0x7F, 0x50, 0x11, 0x75};
byte answ60[] = {0x4F, 0x04, 0x7F, 0x60, 0x33, 0x67};
byte answ32[] = {0x4F, 0x05, 0xb2, 0x02, 0xad, 0xff, 0xA8};
byte answ510D[] = {0x4F, 0x04, 0x7F, 0x51, 0x11, 0x74};



void setup() 
{

Serial.begin (2400, SERIAL_8E1); // сериал соединение протокол W-Bus
//Serial.begin (10400);          // для котлов TT-C,TT-E и им подобных
}

void loop() {


if (Serial.available()) {
delay (51);

while( Serial.available()) {
    byte inByte = Serial.read();

  if      (!head && inByte == 0xF4) {head = 1; buf[0] = inByte;}
  else if (head) {buf[1] = inByte; head = 0;
if ((buf[1]+2)<40){  for (int i = 2; i<buf[1]+2; i++) buf[i] = Serial.read(); }// пишем в буфер принятое сообщение, если оно в него влазит. 
    
  for (int i=0; i< (buf[1]+2); i++) Serial.write (buf[i]); // делаем эхо принятого сообщения для WTT т.к. проверяем без К-Line адаптера (на нём эхо и так возникнет)
  delay (3);

         if (buf[2]==0x50 && buf[3]>=0x16 && buf[3]<=0x19) Serial.write (answ50, sizeof (answ50));
    else if (buf[2]==0x60 ) Serial.write (answ60, sizeof (answ60));
    else if (buf[2]==0x32 && buf[3]==0x02) Serial.write (answ32, sizeof (answ32));
    else if (buf[2]==0x51 && buf[3]==0x0D) Serial.write (answ510D, sizeof (answ510D));

 else 
   for (byte j = 0; j < sizeof(answ_message)/sizeMes; j++)      {// перебираем весь список сообщений в нашем массиве и выбираем нужное для данного запроса
    
    
    
    
         
    
     if (
        ((answ_message[j][2]&~0x80)==buf[2] && answ_message[j][3] == buf[3] && buf[1]==3 && buf[2]!=0x60) || 
        ((answ_message[j][2]&~0x80)==buf[2] && buf[1]==2 && buf[2]!=0x60) || 
        (buf[2]== answ_message[j][3]) ||
        (buf[1]==4 && (answ_message[j][2]&~0x80)==buf[2])
        ) 
       {
        byte crc; 
        for (int i=0; i<answ_message[j][1]+2 ; i++) {  if (i!=(answ_message[j][1]+1)) crc^=answ_message[j][i];
                                                      else                          {answ_message[j][i]= crc;}  
                                                      Serial.write (answ_message[j][i]);
                                                    }
       }
    
                                                          }


  
  

                 }
  }
  }
  }
  

 

Baron8
Offline
Зарегистрирован: 12.11.2019

Вот запустил, в конце запустил удаление ошибок https://drive.google.com/open?id=1alKIJ8E8zXtYXejeojZEjWFIW3-s9LnX

MaksVV
Offline
Зарегистрирован: 06.08.2015

короче такой скетч пробуй v3.85 . VEVO тебе подходит, выбирай его. Должно определяться пламя и температура. 

const char ver[] = "Firmware 3.84";    // версия прошивки

//---------------------------Настройки MQTT-----------------------------------------------------------------------------

const char ACCESSPOINT[]= "\"internet.mts.by\""; // точка доступа оператора связи симкарты
const char PROTOCOLIUS[] =  "MQIsdp";                // это и оставляем
const char MQTTNAME[]    =  "MaksVV";                // это смотрим на сервере MQTT
const char MQTTUSER[]    =  "iu    w";              // это смотрим на сервере MQTT
const char MQTTPASSWORD[] = "1Q     W";            // это смотрим на сервере MQTT
const char SERVERNAME_PORT[] = "\"m16.cloudmqtt.com\", \"14445\"";       // это смотрим на сервере MQTT
#define TIMEBROKER 80   // продолжительность сессии с брокером , мин (пока такое и оставляем)

//----------------------------------название ячеек еепром----------------------------------------------------------------
#include <EEPROM.h>
enum Cells {
ResetNumber_cell,      //0
TimeWebasto_cell,      //1
ProtocolSTART_cell,    //2
StartByte_cell,        //3
ProtocolSTATUS_cell,   //4
Heater_cell,           //5
delta_cell,            //6
sizeNumber_cell,       //7
TelNumber1_cell =20,  //20
TelNumber2_cell =40,  //40
DallasAddr_cell =60   //60
};


//------------------- распиновка ног ардуино (плата весий 8.5-8.8)--------------------------------------------------------

#define OutWebasto_12V      2  // это +12В выход потенциала вкл/выкл вебасто (напрямую к котлу без таймера). 
#define Dallas_pin          3  // пин шины OneWire для датчиков даллас
#define DopOn               4  // сюда доп канал от сигналки на включение вебасто
#define DopOff              5  // сюда доп канал от сигналки на выключение вебасто
#define Ohrana              6  // Сюда состояние охраны сигналки
#define Trevoga             7  // Сюда состояние тревоги
#define IGN                 8  // Сюда состояние зажигания
#define Sost                9  // Сюда состояние вебасто (+12В когда работает)
#define ResetGSM           12  // пин ресета GSM подключен к реле, разрывающее питание модуля. 
#define Eng                14  // (А0) Сюда состояние работы ДВС
#define StatusWebastoLED   15  // (А1) пин LED  индикация включенности котла
#define StartButtonpin     16  // (А2) пин тактовой кнопки вкл/выкл котла 
#define DTR                17  // пин (А3), управляющий энергосберегающим режимом GSM модуля
#define StartEng           18  // (A4) это импульсный минусовой выход вкл/выкл ДВС. подключать на вход событий сиги.
#define OutWebasto_GndImp  19  // (A5) это импульсный минусовой выход вкл/выкл вебасто (к впайке к кнопке таймера).  
#define Voltmeter_pin      A7  // пин, которым измеряем напряжение питания
#define StartButton         0  // программный номер тактовой кнопки вкл/выкл котла 
#define DopOnButton         1  // программный номер тактовой кнопки (допканала) вкл котла 
#define DopOffButton        2  // программный номер тактовой кнопки (допканала) выкл котла 
const bool RelayON =        1; // логика управления реле ресета GSM, в данном случае включается высоким уровнем на пине
#define GSM_RX             10  // пин софт RX Arduino для соединения с TX модуля SIM800
#define GSM_TX             11  // пин софт TX Arduino для соединения с RX модуля SIM800

//------------------------------------для GSM модуля----------------------------------------------------------------------

#include <SoftwareSerial.h>
      SoftwareSerial SIM800 (GSM_RX, GSM_TX);//Rx, Tx   //UART для соединения с GSM модулем

String currStr = "";
String TelNumber[] = {"", "", "", ""};
byte isStringMessage = 0; 
byte KTOreport = 1;           // флаг кто запросил отчет о запуске котла или ДВС
byte KTOzapros = 0;           // флаг кто запросил баланс или запрос параметров 
byte ResetNumber = 0;         // количество ресетов GSM модуля для статистики (хранится в еепром)
byte SizeTelNumber = 12;      // количество символов в номере телефона


const uint16_t Refresh_interval_heaterON = 30000; // интервал обновления параметров по MQTT при включенном котле, миллисек    
uint32_t prev_refreshMQTT = 0;
uint32_t prevGSMnastr = 0;
const byte interval_doprosGSM = 2; // интервал проверки модема на активность, мин  
uint16_t delayATcommand = 5000;
byte fails = 0;
byte failresets = 0;

bool settingGSM = 1;

enum gsmstatus_  {WaitGSM, echoOFF, EnergySave, Head, setText, setProgctrl, closeIncoming, newMessage, delSMS, setGPRS, setAccPoint,
                  setGPRSconnect, setBrokerconnect, setAuthPack, setSubPack, setPubPack
                 };

byte gsmstatus = WaitGSM;




//------------------- для шины 1-wire и датчиков DS18B20---------------------------------------------------------------------

#include <OneWire.h>    // библиотека для DS18B20
OneWire ds(Dallas_pin); // датчики DS18B20 на нужный пин

enum TempC {VyhlopC, EngineC, UlicaC, SalonC, size_arrayTemp}; // перечисление нужных температур (в конце размер массива температур)

// ниже соответствие адресов датчиков различным температурам 
byte DS18B20 [size_arrayTemp][10] = {
{0x28, 0xFF, 0xB2, 0xB5, 0xC1, 0x17, 0x05, 0xD1, VyhlopC,  -100}, 
{0x28, 0xFF, 0xD3, 0xE2, 0xC1, 0x17, 0x04, 0x0D, EngineC,  -100}, 
{0x28, 0xFF, 0xF8, 0xBC, 0xC1, 0x17, 0x04, 0x48, UlicaC,   -100},  
{0x28, 0xFF, 0x3F, 0xB7, 0xC1, 0x17, 0x05, 0xF1, SalonC,   -100}
};
byte delta = 50;  // разница температур выхлопа и улицы, выше которой считается, что пламя в котле есть. 

int8_t HeaterC = -50;
//---------------------------для организации W-BUS и различные таймеры-----------------------------------------------------------

#include <Button.h>
Button test;

#define K_LINE Serial      //UART для соединения с шиной котла
#define TX 1    
#define NEED 1
#define READY 10



// команды для котлов ЭВО
byte StartByte = 0x20;
const byte HEATER_BEGIN[]         {0x51, 0x0A};
      byte HEATER_START[]         {StartByte, 0x3B};
      byte HEATER_PRESENCE[]      {0x44, StartByte, 0x00};
const byte HEATER_STOP[]          {0x10};
const byte HEATER_STATUS_VEVO[]   {0x50, 0x05};
const byte HEATER_STATUS_EVO[]    {0x50, 0x30, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x1E, 0x32};
const byte HEATER_DTC_REQUEST[]   {0x56, 0x01};
const byte HEATER_DTC_ERASE[]     {0x56, 0x03};

// команды для котлов ТТС/TTE
const byte START_SESSION[]        {0x81};
const byte REQUEST_2A10101[]      {0x2A, 0x01, 0x01};
const byte REQUEST_2A10102[]      {0x2A, 0x01, 0x02};
const byte REQUEST_2A10105[]      {0x2A, 0x01, 0x05};
const byte REQUEST_DTC[]          {0xA1};
const byte START_TTC[]            {0x31, 0x22, 0xFF};
const byte STOP_TTC[]             {0x31, 0x22, 0x00};


enum needAction_ {NO_ACTION, NEED_SMSZAPROS, NEED_SERVICEINFO, NEED_MQTTZAPROS, NEED_DTCCLEAR};// возможные действия, стоящие в очереди
byte needAction = NO_ACTION;                                                  // переменная действия, стоящего в очереди

enum ProtocolSTATUS_ {STATUSBUS, ANALOG};                   // возможные протоколы чтения статуса котла
enum ProtocolSTART_  {STARTBUS, IMPULSE, POTENCIAL};        // возможные протоколы запуска котла
enum Heater_         {TTC_E, VEVO, EVO, HYDRONIC};          // тип котла

byte  ProtocolSTATUS = STATUSBUS; 
byte  ProtocolSTART  = STARTBUS;
byte  Heater         = EVO;

bool noData  = 0;                               // флаг пришли ли данные от котла после запроса. 
byte w_bus_init = 0;                            //состояние инициализация шины w-bus (25мс LOW, 25мс HIGH для  ЭВО
                                                //                                            либо 300ms LOW, 50ms HIGH, 25ms LOW, 3025ms HIGH для TTC 
byte requiredmessage =  1;                      //флаг, что отправляем в данный момент поддержание старта, запрос параметров или запрос ошибок
byte StartMessageRepeat = 0;                    //количество отправленных сообщений на старт котла
byte StopMessageRepeat =  4;                    //количество отправленных сообщений на остановку котла

byte  TimeWebasto = 30;                         //время работы котла, = 30мин

uint32_t currmillis = 0;                        // снимок системного времени
uint32_t Prev_PeriodW_BusMessage = 0;           //переменная для таймера периодической отправки сообщений состояния котла в шину W-Bus 
uint32_t Prev_PeriodW_BusStartStop = 0;         //переменная для таймера периодической отправки сообщений старта/стопа котла в шину W-Bus 
uint32_t prevdelSMS = 0;                        //переменная для таймера периодического удаления СМС 
uint32_t prevVpit = 0;                          //переменная для таймера периодического измерения напряжения АКБ
uint32_t prevInitreset = 0;                     //переменная для таймера сброса инита шины
bool Initreset = 0;                             //переменная для таймера сброса инита шины
uint32_t timerInit = 0; bool timerInitflag = 0; //для таймера инита шины W-BUS
uint32_t prevNeedTimer = 0; bool NeedTimer = 0; //для таймера задержки функций SMSzapros() и ServiceINFO() на время обновления параметров по шине

                   
uint32_t prevReportEngine = 0; bool reportEngine = false;    //таймер задержки на отправку отчёта о запуске двигателя
uint32_t prevReport = 0;bool report = false;                 //таймер задержки на отправку отчёта о запуске котла
uint32_t last_Flame = 0;                                     //для таймера сброса флага пламени, если нет ответов от котла
uint32_t prevGND_impulse = 0; bool GND_impulse_timer = 0;    //для таймера создания импульса GND - для протокола запуска котла импульсом GND 
uint32_t prevStartEng=0; bool StartEng_timer=0;              //для таймера  - старт двигателя: минусовой импульс 1.5 сек на вход событий сигналки для запуска ДВС
uint32_t prevWorkCycleHeater; bool WorkCycleHeater_timer=0;  //для таймера отсчёта цикла работы котла




//---------------------------------Основные переменные--------------------------------------------------------------------------------  

bool webasto = 0;             // флаг команды на работу Webasto. 0 - котел выключен, 1 - котел включен
bool startWebasto_OK = 0;     // флаг успешного запуска котла

float Vpit = 0.0;             // Измеряемое напряжение на выходе ИБП
bool engine =0;               // флаг работает ли ДВС или нет
bool ignition=0;              // флаг включено ли зажигание или нет
bool ohrana=0;                // флаг включена ли охрана или нет
bool trevoga=0;               // флаг включена ли тревога или нет
bool alarmSMS = 0;            // флаг отправлена ли смс о тревоге или нет

bool waterpump = 0;           // флаг работы циркуляционного насоса
bool plug      = 0;           // флаг работы штифта накаливания
bool airfan    = 0;           // флаг работы нагнетателя воздуха
bool fuelpump  = 0;           // флаг работы топливного насоса
bool blowerfan = 0;           // флаг работы вентилятора печки автомобиля
byte DTC[7] ={0};             // коды неисправностей котла



//---------------------------СТАРТОВЫЙ ЦИКЛ--------------------------------------------------------------------------------------------

void setup() 
{


delay (4500);


test.NO(); 
test.pullUp();
test.duration_bounce       (  50);
test.duration_click_Db     ( 250);
test.duration_inactivity_Up(5000);
test.duration_inactivity_Dn(1000);
test.duration_press        ( 500);
test.button(StartButtonpin, DopOn, DopOff);
 
pinMode (DopOn,   INPUT_PULLUP); 
pinMode (DopOff,  INPUT_PULLUP); 
pinMode (Sost,    INPUT_PULLUP); 
pinMode (Ohrana,  INPUT_PULLUP); 
pinMode (Trevoga, INPUT_PULLUP); 
pinMode (IGN,     INPUT_PULLUP); 
pinMode (Eng,     INPUT_PULLUP); 
  
pinMode (OutWebasto_12V,     OUTPUT);  digitalWrite (OutWebasto_12V,      LOW);
pinMode (StartEng,           OUTPUT);  digitalWrite (StartEng,            LOW);
pinMode (13,                 OUTPUT);  digitalWrite (13,                  LOW);
pinMode (StatusWebastoLED,   OUTPUT);  digitalWrite (StatusWebastoLED,    LOW);
pinMode (OutWebasto_GndImp,  OUTPUT);  digitalWrite (OutWebasto_GndImp,   HIGH);
pinMode (DTR,                OUTPUT);  digitalWrite (DTR,                 LOW );  // делаем низкий для вывода GSM из "спячки"
pinMode (ResetGSM,           OUTPUT);  digitalWrite (ResetGSM,        !RelayON);  // реле ресет на данный момент делаем "неактивно"


   SIM800.begin(19200);           // сериал соединение для gsm модуля
   
SizeTelNumber =  EEPROM.read(sizeNumber_cell);
if (SizeTelNumber>25)while(1);
TimeWebasto =    EEPROM.read(TimeWebasto_cell);
ProtocolSTART  = EEPROM.read(ProtocolSTART_cell);
ProtocolSTATUS = EEPROM.read(ProtocolSTATUS_cell);
ResetNumber =    EEPROM.read(ResetNumber_cell);
StartByte =      EEPROM.read(StartByte_cell);
HEATER_START[0] = StartByte;
HEATER_PRESENCE[1] = StartByte;
Heater =         EEPROM.read(Heater_cell);
delta  =         EEPROM.read(delta_cell);
for (int i=0; i<SizeTelNumber; i++) 
    {
      TelNumber[0]+= '0';
      TelNumber[3]+= '0';
      TelNumber[1]+= (char)EEPROM.read (i+TelNumber1_cell);
      TelNumber[2]+= (char)EEPROM.read (i+TelNumber2_cell);
    }


// ниже читаем из еепром адреса датчиков температуры даллас 
for (byte i = 0; i<size_arrayTemp; i++) 
    {
    for (byte k=0; k<9; k++) DS18B20 [i][k] = EEPROM.read(DallasAddr_cell+i*10+k);
    }



        if (Heater == EVO || Heater == VEVO) K_LINE.begin(2400, SERIAL_8E1);
   else if (Heater == TTC_E) K_LINE.begin(10400);


//for (byte i=0; i<20; i++) {digitalWrite (13, !digitalRead(13)); delay (80);}
//digitalWrite (13,0);
fails = 3;
}



//------------------------------------------ЛУП-----------------------------------------------------------------------------------


void loop() {
currmillis = millis();
test.read();

digitalWrite (StatusWebastoLED, webasto);
//digitalWrite (13, startWebasto_OK);
//digitalWrite (13, webasto);

if   (settingGSM) NastroykaGSM ();
else if (fails >= 3) settingGSM = 1;


  if (failresets <= 4)   //если MQTT активен 
    {
    static bool last_MQTTwebasto = 0;
    static bool last_startwebasto_OK = 0;
    if (last_MQTTwebasto != webasto || last_startwebasto_OK != startWebasto_OK && !timerInitflag){MQTTsendDatastream(); last_MQTTwebasto = webasto; last_startwebasto_OK = startWebasto_OK;}
    if (webasto && currmillis - prev_refreshMQTT > Refresh_interval_heaterON) {MQTTsendDatastream(); prev_refreshMQTT = currmillis;}
    }

static uint32_t prevTestModem = 0;
if (!settingGSM && currmillis - prevTestModem > (uint32_t)interval_doprosGSM*60000UL)
    {
      
      if (failresets > 4)  //если MQTT не активен 
      {
         digitalWrite (DTR, LOW);
         delay (150);
         SIM800.println (F("AT"));
         delay (50);
         digitalWrite (DTR, HIGH);
      }
      else {PUBsend ("h/stat",String(webasto) + "&$",0);}  //если MQTT активен 
     fails++; 
     prevTestModem = currmillis;
    }  




if (ProtocolSTATUS==ANALOG) {if (Temper(VyhlopC) - Temper(UlicaC) > delta) startWebasto_OK = 1;
                             else startWebasto_OK = 0;}

if (ProtocolSTART==IMPULSE) {webasto = !digitalRead (Sost);}

   if (!ohrana) alarmSMS = false;
   if (trevoga && !alarmSMS) AlarmSMS ();



readModem();   
DelSMS();
Heater_BUS();
timers_and_buttons ();
izmereniya();

}


//-----------------------------------------------------------конец луп-------------------------------------------------------------



void izmereniya() { 

 engine =  !digitalRead (Eng);
 ignition= !digitalRead (IGN); 
 ohrana=   !digitalRead (Ohrana);  
 trevoga=  !digitalRead (Trevoga);


if (currmillis-prevVpit>7000){

//измерение напряжения борт сети
if (ProtocolSTATUS==ANALOG)
{
   Vpit = (analogRead(Voltmeter_pin) * 4.13) / 1024;             
   Vpit = Vpit / (9700.0/(98930.0+9700.0));  // По формуле Vpit = vout / (R2/(R1+R2)) 
   if (Vpit<0.09)  Vpit=0.0;                  // Округление до нуля 
}  

// ниже измерение датчиков даллас
static bool y=0;        // флаг работы: запрос температуры или её чтение
y=!y;
if (y) {ds.reset();     // сброс шины
        ds.write(0xCC); // обращение ко всем датчикам
        ds.write(0x44); // начать преобразование (без паразитного питания)  
       }
else   {
  for (byte i=0; i<size_arrayTemp; i++){  
    int Temper_ = 20; byte buff[9];
    ds.reset();
    ds.select(DS18B20[i]);
    ds.write(0xBE); // чтение регистров датчиков
    for (byte j=0; j<9; j++) buff[j]=ds.read(); // читаем все 9 байт от датчика
    ds.reset();
    if (OneWire::crc8(buff, 8) == buff[8]){     // если контрольная сумма совпадает 
          Temper_ = buff[0]|(buff[1]<<8);       // читаем температуру из первых двух байт (остальные были нужны только для проверки CRC)
          Temper_ = Temper_ / 16;
          if (Temper_<150 && Temper_>-55) DS18B20[i][9] = Temper_;
}
else DS18B20[i][9] = -101;                     // если контрольная сумма не совпала, пусть t будет -101 градус. 
}}
prevVpit=currmillis;
}}



int8_t Temper (const byte &addressTemp) {for(byte j=0; j<size_arrayTemp; j++){if(DS18B20[j][8]==addressTemp)return(int8_t)DS18B20[j][9];} return-99;}



void timers_and_buttons (){

// опрос допканалов от сигнализации включения/выключение котла и таймер импульса старт/стоп котла 
 
  if (GND_impulse_timer && currmillis - prevGND_impulse > 800) {digitalWrite (OutWebasto_GndImp, HIGH); GND_impulse_timer=false;}
  
//ниже для таймера создания импульса на старт ДВС 
if (StartEng_timer && currmillis - prevStartEng > 1500) {digitalWrite (StartEng, LOW); StartEng_timer=false;}

//ниже для таймера старта котла по шине и аналогу 
if (WorkCycleHeater_timer && currmillis - prevWorkCycleHeater > (uint32_t)TimeWebasto * 60000UL) {StopWebasto();}

// таймер отправки отчета об успешности запуска котла (отчёт через 6 мин после старта)
   if(webasto && report && currmillis - prevReport > 360000UL) 
   { report = false; Queue(NEED_SMSZAPROS);  }

// таймер отправки отчета об успешности запуска ДВС  (отчёт через 90сек после старта)                       
   if(reportEngine && currmillis - prevReportEngine > 90000ul) 
   {reportEngine = false; Queue(NEED_SMSZAPROS);}

//если нажали на допканал - делаем соответствующее состояние котла 
if (test.event_click_Dn (DopOnButton) && !webasto) {StartWebasto(); KTOreport = 1;}  
if (test.event_click_Dn (DopOffButton) && webasto) {StopWebasto();}

//если нажали тактовую кнопку меняем состояние котла на противоположное 
if (test.event_press_short (StartButton)) 
    {
       if   (!webasto) {StartWebasto(); report = false;}
       else {StopWebasto();}
    }
}


void startSMS(byte stat) //__________________Цикл подготовки модуля к отправке СМС-сообщений по первому номеру
{
    if (stat==0) stat = KTOreport;
     digitalWrite (DTR, LOW); // выводим из спячки GSM модуль
         delay (150);
     SIM800.print(F("AT+CMGF=1\r"));
         delay(200);
     SIM800.print(F("AT+CMGS=\"")); SIM800.print(TelNumber[stat]); SIM800.println("\""); 
         delay(200);
}



void EndSMS ()
{
   SIM800.println((char)26);                       // Команда отправки СМС
   delay(3500);
   digitalWrite (DTR, HIGH); // вводим в спячку SIM800 модуль 
   
}

void NastroykaGSM () {

  if (fails >= 3) Reset();

  else if (currmillis - prevGSMnastr > delayATcommand)
  {

    fails ++;

    if (gsmstatus == WaitGSM)               SIM800.println (F("AT"));
    else if (gsmstatus == EnergySave)       SIM800.println (F("AT+CSCLK=1"));
    else if (gsmstatus == Head)             SIM800.println (F("AT+CIPHEAD=1"));
    else if (gsmstatus == echoOFF)          SIM800.println (F("ATE0"));
    else if (gsmstatus == setText)          SIM800.println (F("AT+CMGF=1"));
    else if (gsmstatus == setProgctrl)      SIM800.println (F("AT+IFC=0, 0"));
    else if (gsmstatus == closeIncoming)    SIM800.println (F("AT+GSMBUSY=1"));
    else if (gsmstatus == newMessage)       SIM800.println (F("AT+CNMI=1,2,2,1,0"));
    else if (gsmstatus == delSMS)           SIM800.println (F("AT+CMGDA=\"DEL ALL\""));

    else if (gsmstatus == setGPRS)          SIM800.println (F("AT+SAPBR=3,1, \"Contype\",\"GPRS\""));
    else if (gsmstatus == setAccPoint)      SIM800.print (F("AT+SAPBR=3,1, \"APN\",")), SIM800.println (ACCESSPOINT);
    else if (gsmstatus == setGPRSconnect)   SIM800.println (F("AT+SAPBR=1,1"));
    else if (gsmstatus == setBrokerconnect) SIM800.print (F("AT+CIPSTART=\"TCP\",")),  SIM800.println (SERVERNAME_PORT);
    else if (gsmstatus == setAuthPack)      AUTHsend ();
    else if (gsmstatus == setSubPack)       SUBsend("h/#");
    else if (gsmstatus == setPubPack)       Queue(NEED_MQTTZAPROS), MQTTsendDatastream();
    delayATcommand = 5000;
    prevGSMnastr = currmillis;
  }
}



void DelSMS ()
{
if (currmillis - prevdelSMS > 7200000ul){  //раз в 2 часа 
 digitalWrite (DTR, LOW); // выводим из спячки SIM800 модуль
    delay (150);
 SIM800.print(F("AT+CMGDA=\"DEL ALL\"\r")); // удаляем все смс, ки
   delay(1500);
 digitalWrite (DTR, HIGH); // вводим в спячку SIM800 модуль 
   delay (150);

  prevdelSMS = currmillis;}
}


//void SMSzapros_ () {if (webasto)SMSzapros(); else {NeedTimer = 1; prevNeedTimer = currmillis; needAction = NEED_SMSZAPROS; w_bus_init = 1;}}

void Queue (const byte &actioN) {needAction = actioN; 
             if (ProtocolSTATUS==STATUSBUS){NeedTimer = 1; prevNeedTimer = currmillis; if (!webasto) w_bus_init = 1;}
        else if (ProtocolSTATUS==ANALOG) {if (needAction==NEED_SMSZAPROS) SMSzapros(); if (needAction==NEED_SERVICEINFO) ServiceINFO();}
                                 } 

void readModem() //_____Цикл чтения входящих СМС-сообщений______________     
{

  static uint32_t timerMQTTreconnect = 0;
  static bool TimerMQTTreconnect = 0;

// если было неудачное подключение к MQTT, ждём час и снова пробуем
if (TimerMQTTreconnect && currmillis - timerMQTTreconnect > 3600000UL) 
    {
      TimerMQTTreconnect = 0; 
      fails = 3;
      settingGSM = 1;
    }





    if (!SIM800.available()) return;
    static bool SaveNumber2 = 0;      // флаг когда необходима запись номера#2, он true
    char currSymb = SIM800.read();

    if ('\r' == currSymb || '&' == currSymb)
       {
         if (isStringMessage!=0&&isStringMessage!=3) //если текущая строка - SMS-сообщение, отреагируем на него соответствующим образом
                {
if      (!currStr.compareTo(F("ZAPROS")))       {Queue(NEED_SMSZAPROS);}             // Передача параметров по СМС
else if (!currStr.compareTo(F("Service-info"))) {Queue(NEED_SERVICEINFO);}           // Передача сервисной информации  по СМС
else if (!currStr.compareTo(F("Erase DTC")))    {Queue(NEED_DTCCLEAR);}              // Запрос на стриание ошибок
else if (!currStr.compareTo(F("ZAPROSTEL")))    {SMSzaprosTEL();}                    // Передача номеров телефонов пользователей по СМС
else if (!currStr.compareTo(F("GSMResets-0")))  {ResetNumber=0; EEPROM.write (ResetNumber_cell, ResetNumber); Queue(NEED_SERVICEINFO);}     //сброс счетчика ресетов GSM модуля
else if (!currStr.compareTo(F("Version")))      {startSMS(isStringMessage);  SIM800.println (ver); EndSMS ();}               //запрос версии ПО


else if (!currStr.compareTo(F("Signal-level"))) {digitalWrite (DTR, LOW);  delay (150); SIM800.println(F("AT+CSQ")); digitalWrite (DTR, HIGH);}                // запрос уровня сигнала GSM
              
else if (!currStr.compareTo(F("Webasto-ON")))  { startSMS(isStringMessage); SIM800.println(F("Webasto ")); 
  
           if (!webasto)  {StartWebasto (); KTOreport = isStringMessage;}
           else SIM800.println(F("uzhe ")); SIM800.println (F("vkluchena")); EndSMS();}

                                                            
else if (!currStr.compareTo(F("Webasto-OFF")))   {startSMS(isStringMessage); SIM800.println(F("Webasto "));  
           if (webasto)StopWebasto ();  // если получили команду на выключение и вебаста в настоящий момент включена - выключаем
           else SIM800.println(F("uzhe "));  SIM800.println(F("otkluchena"));EndSMS();}          

// если получили команду на включение ДВС и он в настоящий момент выключен - включаем
else if (!currStr.compareTo(F("Engine-ON")))  {startSMS(isStringMessage); SIM800.println(F("Dvigatel "));  
           if (!engine)  { digitalWrite (StartEng, HIGH);  prevStartEng=currmillis; StartEng_timer=true; reportEngine = true; prevReportEngine = currmillis; KTOreport = isStringMessage;} 
           else SIM800.println(F("uzhe ")); SIM800.println(F("start")); EndSMS();}
                                                                                 
else if (!currStr.compareTo(F("Engine-OFF")))   {startSMS(isStringMessage); SIM800.println(F("Dvigatel "));  
           if (engine){ digitalWrite (StartEng, HIGH);  prevStartEng=currmillis; StartEng_timer=true; reportEngine = false;} // если получили команду на выключение ДВС и он в настоящий момент работает - выключаем
           else SIM800.println(F("uzhe ")); SIM800.println(F("ostanovlen")); EndSMS();}          
              
else if (!currStr.compareTo(F("Impulse")))   {if (!webasto) {ProtocolSTART = IMPULSE;  EEPROM.write(ProtocolSTART_cell,ProtocolSTART);     
                                            startSMS(isStringMessage); SIM800.println(F("zapusk GND_impulse")); EndSMS();}}

else if (!currStr.compareTo(F("Startbus")))  {if (!webasto) {ProtocolSTART = STARTBUS; EEPROM.write(ProtocolSTART_cell,ProtocolSTART);  webasto = 0;  
                                            startSMS(isStringMessage); SIM800.println(F("zapusk BUS")); EndSMS();}}

else if (!currStr.compareTo(F("Potencial"))) {if (!webasto) {ProtocolSTART = POTENCIAL; EEPROM.write(ProtocolSTART_cell,ProtocolSTART);   
                                            startSMS(isStringMessage); SIM800.println(F("zapusk +12V Potencial")); EndSMS();}}

else if (!currStr.compareTo(F("DallasAddr"))) {startSMS(isStringMessage); SMSDallasAddr(); EndSMS();}

else if (currStr.endsWith(F("Status")))   {if (!webasto) {byte st = currStr.toInt(); if (st >= STATUSBUS && st<=ANALOG )ProtocolSTATUS = st; EEPROM.write(ProtocolSTATUS_cell,ProtocolSTATUS);   
                                            startSMS(isStringMessage); SIM800.print (F("Status: "));
                                                                             if (ProtocolSTATUS == 0)SIM800.println(F("BUS")); 
                                                                        else if (ProtocolSTATUS == 1)SIM800.println(F("Analog"));
                                                                        EndSMS();}}    


else if (currStr.endsWith(F("HeaterType"))) {if (!webasto) {byte st = currStr.toInt(); if (st >= TTC_E && st<=HYDRONIC) Heater = st; EEPROM.write(Heater_cell,Heater);   
                                            startSMS(isStringMessage); SIM800.print (F("Heater: "));
                                                                             if (Heater == 0)SIM800.println(F("TTC_E")), K_LINE.end(),  K_LINE.begin(10400);
                                                                        else if (Heater == 1)SIM800.println(F("VEVO")),  K_LINE.end(),  K_LINE.begin(2400, SERIAL_8E1);
                                                                        else if (Heater == 2)SIM800.println(F("EVO")),   K_LINE.end(),  K_LINE.begin(2400, SERIAL_8E1);
                                                                        else if (Heater == 3)SIM800.println(F("HYDRONIC"));
                                                                             
                                                                        EndSMS();}}      




else if (currStr.endsWith(F("ADDR"))) {if (!webasto) { startSMS(isStringMessage); byte savadr = ConvertAddr(); 
                                                    if (savadr>=0 && savadr<=3) {SIM800.print(F("address ")); TempName(savadr); SIM800.println (F(" saved OK!")); 
                                                    SMSDallasAddr();
                                                                                } 
                                                    else SIM800.println(F("address is incorrect!"));
                                                    
                                                                          EndSMS(); }}      
                                                                                                                                                
                                                                                                                                              
else if (currStr.endsWith(F("Delta")))   {if (!webasto) {delta = currStr.toInt(); //
               EEPROM.write(delta_cell, delta);  startSMS(isStringMessage);
               SIM800.print(F("DeltaT: ")); SIM800.print(delta); SIM800.print(F("*C")); EndSMS();}}
                                                                                                                                            

               
else if (currStr.endsWith(F("min")))   {if (!webasto) {TimeWebasto = currStr.toInt(); // для задания время цикла работы отправить сообщение вида "25 min", где 25 время работы в мин
               if (TimeWebasto>59)  TimeWebasto = 59;
               if (TimeWebasto<=15) TimeWebasto = 15;
               EEPROM.write(TimeWebasto_cell,TimeWebasto);
               startSMS(isStringMessage); SIM800.print(F("Webasto time: ")); SIM800.print(TimeWebasto); SIM800.print(F("min")); EndSMS();}}
               
else if (currStr.endsWith(F("StartByte"))) {byte Z =currStr.toInt(); if (Z>=0x14 && Z<=0x17) StartByte= Z+12; EEPROM.write(StartByte_cell, StartByte); 
HEATER_START[0] = StartByte;
HEATER_PRESENCE[1] = StartByte;
               startSMS(isStringMessage); SIM800.print(F("StartByte: ")); SIM800.print(StartByte, HEX); SIM800.print(F("h")); EndSMS();}

else if (!currStr.compareTo(F("ResetNumbers")))   {if (isStringMessage == 1) {startSMS(isStringMessage); SIM800.println(F("Phone numbers are erased")); EndSMS(); 
                                                                     
             TelNumber[1] = TelNumber[0]; TelNumber[2] = TelNumber[0]; for (int i=0; i<SizeTelNumber; i++) {EEPROM.write (i+TelNumber1_cell,  TelNumber[1][i]); EEPROM.write (i+TelNumber2_cell,  TelNumber[2][i]); }}}

else if (!currStr.compareTo(F("WriteNumber2"))&& isStringMessage == 1)   { 
                SaveNumber2 = 1; startSMS(isStringMessage); SIM800.println(F("Otpravte lyuboye SMS s nomera#2 dlya sohraneniya nomera")); EndSMS();} 

                                                                        

                                                     
else if (!currStr.compareTo(F("Balance")))    SMSbalance();
            isStringMessage = 0;
                }
              
              
else if (isStringMessage==3){ if (!currStr.compareTo(F("WriteNumber1")))   { TelNumber[1] = TelNumber[3]; for (int i=0; i<SizeTelNumber; i++) {EEPROM.write (i+TelNumber1_cell, TelNumber[3][i]);}
              startSMS(1); SIM800.println(F("Tel Number#1 is saving in memory"));  SIM800.print("Tel#1: ");  SIM800.println (TelNumber[1]); EndSMS();
              } 
                                             else if (!currStr.compareTo(F("ZAPROS")))   { SMSzapros();}   
                                             else if (!currStr.compareTo(F("ZAPROSTEL")))   { SMSzaprosTEL();}               // Передача номеров телефонов пользователей по СМС            
               isStringMessage = 0;
              
              }           



                
else if (isStringMessage==0) {  if (TelNumber[1]!=TelNumber[0] && !SaveNumber2){
         
                     if (currStr.startsWith("+CMT: \""+TelNumber[1])) { isStringMessage = 1; KTOzapros = 1; }   
                else if (currStr.startsWith("+CMT: \""+TelNumber[2])) { isStringMessage = 2; KTOzapros = 2; }   
                else if (currStr.startsWith("+CUSD: 0,"))  //если текущая строка начинается с "+CUSD",то следующая строка является запросом баланса
                  {
                  startSMS(KTOzapros);
                  SIM800.print (currStr);
                  EndSMS();
                  }

                else if (currStr.startsWith(F("+CSQ:"))) //если текущая строка начинается с "+CSQ",то значит был запрос на уровень сигнала GSM, отправим ответ запрашивающему
                  {
                  startSMS(KTOzapros);
                  SIM800.print (currStr);
                  EndSMS();
                  }
                                                }

                else if    (currStr.startsWith(F("+CMT:")) && !SaveNumber2) { isStringMessage = 3; for (int i =0; i<SizeTelNumber; i++) {TelNumber[3][i]=currStr[i+7];}}
                else if    (currStr.startsWith(F("+CMT:")) && SaveNumber2) { for (int i =0; i<SizeTelNumber; i++) {TelNumber[3][i]=currStr[i+7]; EEPROM.write (i+TelNumber2_cell, TelNumber[3][i]);} TelNumber[2] = TelNumber[3]; 
              startSMS(2); SIM800.println(F("Vash nomer sochranyon kak Number#2 v pamyati!")); 
              SIM800.print(F("Tel#1: ")); SIM800.println(TelNumber[1]); SIM800.print(F("Tel#2: "));  SIM800.println (TelNumber[2]); EndSMS(); SaveNumber2 = 0; } 

// ----------------------------данные для MQTT

if (currStr.indexOf(F("CLOSED")) > -1 || currStr.indexOf(F("ERROR")) > -1)  {
        fails = 3;
        settingGSM = 1;
      }
      if (currStr.indexOf(F("OK")) > -1) {
        if (!settingGSM){ if (failresets > 4 || (failresets <= 4 && gsmstatus >= setPubPack)) {fails = 0; digitalWrite (DTR, HIGH);}}
        if (settingGSM && gsmstatus > WaitGSM && gsmstatus < setBrokerconnect) {
             // если подключиться к MQTT серверу не удалось, оставляем настройки только для СМС
             // и запускаем таймер на час, чтобы через час ещё раз пробовать:
             if (gsmstatus == delSMS && failresets > 4) 
                  {settingGSM = 0; 
                   digitalWrite (DTR, HIGH);
                   timerMQTTreconnect = currmillis;
                   TimerMQTTreconnect = 1;
                   }  
             gsmstatus++; if (gsmstatus>16)gsmstatus=16;
             fails = 0;
             delayATcommand = 400;
                                                                                }
      }
      if (currStr.indexOf(F("CONNECT")) > -1) if (gsmstatus == setBrokerconnect) {
          gsmstatus++; if (gsmstatus>16)gsmstatus=16;
          fails = 0;
          delayATcommand = 300;
        }
      if (currStr.indexOf(F("SMS Ready")) > -1) if (gsmstatus == WaitGSM) {
          gsmstatus++; if (gsmstatus>16)gsmstatus=16;
          fails = 0;
          delayATcommand = 300;
        }
      if (currStr.indexOf(F("SEND OK")) > -1) {
        fails = 0;
        if (settingGSM && gsmstatus >= setAuthPack && gsmstatus <= setPubPack) {
          if (gsmstatus == setPubPack) {
            settingGSM = 0;
            failresets = 0;
          } delayATcommand = 300;
          gsmstatus++; if (gsmstatus>16)gsmstatus=16;
        }
      }


//-------------------------топики MQTT, принимаемые от брокера
     
      if (currStr.indexOf(F("h/ctrl")) > -1) 
      {
        bool comanda = currStr.substring(currStr.indexOf(F("h/ctrl")) + 6).toInt();
        if (comanda) {StartWebasto(); report = false;} 
        else {StopWebasto();}
      }
      if (currStr.indexOf(F("h/time/ctrl")) > -1) {
        String TimeW = currStr.substring(currStr.indexOf(F("h/time/ctrl")) + 11);
        TimeWebasto = TimeW.toInt();
        EEPROM.write(TimeWebasto_cell,TimeWebasto);
        PUBsend("h/time/stat",  TimeW, 0);
        remTime(0) ;
      }
      if (currStr.indexOf(F("h/refr0")) > -1) {if (!webasto) {Queue(NEED_MQTTZAPROS); delay (100);}   MQTTsendDatastream();}
      if (currStr.indexOf(F("h/resresets")) > -1) {ResetNumber=0; EEPROM.write (ResetNumber_cell, ResetNumber); PUBsend("h/resets",String(ResetNumber),0);}

// ------------------------конец данных для MQTT

              
              } 


               
        currStr = "";
      } 
 
    else if ('\n' != currSymb && '$' != currSymb)  currStr += String(currSymb);
    if (currStr.length()>60) currStr += "\r\n";
}




byte ConvertAddr() {
  
  byte addrbuf[9];
byte Cs=0;
for (byte i = 0; i<9; i++) {
    char str[]="  ";
    for (byte k = 0; k<2; k++) str[k] = currStr[3*i+k];

 addrbuf[i] = strtol(str,NULL,HEX);
      if (i<7) Cs+= addrbuf[i] = strtol(str,NULL,HEX);
 
  }
if (OneWire::crc8(addrbuf, 7) == addrbuf[7] && addrbuf[8]>=0 && addrbuf[8]<=3) { 

for (byte i = 0; i<size_arrayTemp; i++) {
  if (addrbuf[8]==DS18B20[i][8]) {for (byte k=0; k<9; k++) DS18B20 [i][k] = addrbuf[k], EEPROM.write (DallasAddr_cell+addrbuf[8]*10+k, addrbuf[k]);}
                                        }

return addrbuf[8];
}
else return 20; 
  }

void SMSDallasAddr(){
 
SIM800.println (F("Dallas Addresses:"));

for (byte i = 0; i<size_arrayTemp; i++) {
   TempName(DS18B20[i][8]); SIM800.println(); 
   for (byte k = 0; k<8; k++) {if (DS18B20[i][k]<=0x0F)SIM800.print(F("0")); SIM800.print(DS18B20[i][k],HEX); SIM800.print(F(" "));}
  SIM800.println(); 
  }

   
                              
  }



void SMSzaprosTEL(){
  startSMS(isStringMessage);
  PrintNumbers (); 
  EndSMS();                                 
  }


void SMSbalance() {
digitalWrite (DTR, LOW); // выводим из спячки SIM800 модуль
      delay (150);
SIM800.print(F("AT+CMGF=1\r"));
      delay(200);
SIM800.println (F("AT+CUSD=1,\"#100#\""));    // команда на замену на транслит *111*6*2# у МТС 
      delay(1500);  
digitalWrite (DTR, HIGH); // вводим в спячку SIM800 модуль 
      delay (150);  
                             
     
}


void AlarmSMS() {for (byte i = 0; i<2; i++) {startSMS(i+1); SIM800.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!")); EndSMS();} alarmSMS = true;}
 


void PrintNumbers () {for (byte i=0; i<2; i++) {SIM800.print(F("Tel#")); SIM800.print (i+1); SIM800.print(F(" ")); SIM800.println(TelNumber[i+1]);}}




void TempName (const byte &_address_) {     if (_address_== VyhlopC) SIM800.print(F("Vyhlop:  "));
                                       else if (_address_== EngineC) SIM800.print(F("Engine:  "));
                                       else if (_address_== UlicaC)  SIM800.print(F("Ulica:     "));
                                       else if (_address_== SalonC)  SIM800.print(F("Salon:    "));
                                       }

void SMSzapros()

{

  startSMS(isStringMessage);
  if (isStringMessage == 3){
 
 SIM800.println (F("Tel.number#1 not has been save in memory"));
 SIM800.println (F("For save Tel#1 send SMS command \"WriteNumber1\""));
 PrintNumbers ();
  }
  

  
  
  else {
  
SIM800.print (F("Webasto ")); on_off (webasto);
        if (webasto) { 
           SIM800.print (F("StartWebasto "));
           if (startWebasto_OK) SIM800.println (F("OK"));
           else SIM800.println (F("FAIL"));}
SIM800.print (F("Engine    "));  on_off (engine);
SIM800.print (F("IGN        ")); on_off (ignition);
SIM800.print (F("Ohrana  "));    on_off (ohrana);
     if (trevoga)  SIM800.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
     
  SIM800.print(F("Battery: "));      if ((needAction>0 && !noData) || needAction == 0 || ProtocolSTATUS == ANALOG) {SIM800.print (Vpit,1); SIM800.println(F(" V"));}
                                else if (needAction>0 && noData && ProtocolSTATUS != ANALOG) SIM800.println(F(" No Data"));
  
  SIM800.println(F("Temperatures:"));
  if (ProtocolSTATUS != ANALOG){
  SIM800.print(F("Heater:  ")); if ((needAction>0 && !noData) || needAction == 0) {SIM800.print (HeaterC);  grad ();}
                                else if (needAction>0 && noData) SIM800.println(F(" No Data"));}
 
 // ниже распечатаем все температуры   
    for (byte i = 0; i<size_arrayTemp; i++) {
      if (DS18B20[i][8]==VyhlopC && ProtocolSTATUS != ANALOG) {}
      else {TempName(DS18B20[i][8]); SIM800.print (Temper(DS18B20[i][8])); grad ();}}
  

  if (ProtocolSTATUS == STATUSBUS){
  SIM800.print(F("Errors:   ")); if ((needAction>0 && !noData) || needAction == 0) SIM800.println (DTC[0]);
                                else if (needAction>0 && noData) SIM800.println(F(" No Data"));}
  
  
 
  }  
   EndSMS();    
                          
}

void on_off (const bool &stat) {if (stat) SIM800.println (F("ON")); else SIM800.println (F("OFF")); }
void grad () {SIM800.println (F("*C")); }





void ServiceINFO(){
  
       startSMS(isStringMessage);
  SIM800.print(F("Heater:  ")); 
       if (Heater==TTC_E)     SIM800.println(F("TTC/E"));
  else if (Heater==VEVO)      SIM800.println(F("VEVO"));
  else if (Heater==EVO)       SIM800.println(F("EVO"));
  else if (Heater==HYDRONIC)  SIM800.println(F("HYDRONIC"));
  SIM800.print(F("Start:    "));
       if (ProtocolSTART==IMPULSE)   SIM800.println(F("GND Imp"));
  else if (ProtocolSTART==STARTBUS)  {SIM800.print(F("BUS"));
             if (Heater== VEVO || Heater== EVO) {SIM800.print(F(" 0x")); SIM800.println (StartByte, HEX);}
             else SIM800.println();}
  else if (ProtocolSTART==POTENCIAL) SIM800.println(F("Potencial+12V"));
  
  SIM800.print(F("Status:  "));
       if (ProtocolSTATUS==ANALOG)    SIM800.println(F("ANALOG"));
  else if (ProtocolSTATUS==STATUSBUS) SIM800.println(F("BUS"));
  
   
  if (ProtocolSTART!=IMPULSE) {SIM800.print(F("Webasto Time: ")); SIM800.print (TimeWebasto); SIM800.println(F("min"));}
  SIM800.print(F("Modem Resets: ")); SIM800.println (ResetNumber); 

  if (ProtocolSTATUS==ANALOG) {SIM800.print(F("DeltaT:  ")); SIM800.print(delta);SIM800.println(F("*C"));}

  if (ProtocolSTATUS==STATUSBUS){
    if (!noData) {
    SIM800.print(F("   BurnFAN       ")); on_off (airfan);
    SIM800.print(F("   WaterPUMP ")); on_off (waterpump);
    SIM800.print(F("   PLUG            ")); on_off (plug);
    SIM800.print(F("   FuelPUMP    ")); on_off (fuelpump);
    SIM800.print(F("   Blower          ")); on_off (blowerfan);
    
   SIM800.print (F("Errors:  ")); SIM800.println (DTC[0]);
  if (DTC[0] >0) for (byte i=0; i<DTC[0]; i++) {
  if (DTC[i+1]<=0x0F) SIM800.print(F("0"));
     SIM800.print (DTC[i+1], HEX); 
     if (bitRead(DTC[6], i+1)) SIM800.println (F(" Active")); 
     else SIM800.println (F(" Passive"));      }
                             }
 else SIM800.println(F("Heater not answer. No Data"));}
   EndSMS();    
  
  }

void StartWebasto()
{
 if (ProtocolSTART==IMPULSE)
  {
     digitalWrite (OutWebasto_GndImp, LOW); 
     GND_impulse_timer = 1;
     prevGND_impulse = currmillis;
  }

 else 
  {
     StartMessageRepeat = 0;
     webasto = 1; digitalWrite (OutWebasto_12V, HIGH);
     prevWorkCycleHeater=currmillis;
     WorkCycleHeater_timer = true;
  }
report = true; prevReport = currmillis;
w_bus_init = NEED;

}

void StopWebasto()
{
 if (ProtocolSTART==IMPULSE)
   { 
      digitalWrite (OutWebasto_GndImp, LOW); 
      GND_impulse_timer = 1;
      prevGND_impulse = currmillis;
   }
 else 
   {
      StopMessageRepeat = 0;
      webasto = 0; digitalWrite (OutWebasto_12V, LOW);
      WorkCycleHeater_timer = false;
   }
   report = false;
   
   if (ProtocolSTATUS==STATUSBUS) startWebasto_OK = 0;
}



void Heater_BUS (){


static byte header = 0;           // состояние заголовка 
static byte message_size = 0;     // размер тела принимаемого сообщения, кол-во байт
static byte j = 2;                // инкремент
static byte n = 2;
const byte bufsize = 140;  // размер буфера принятого сообщения
static byte buf [bufsize] = {0};  // буфер принятого сообщения
static byte checksum = 0;         // контрольная сумма входящего сообщения
static uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались
static bool RESETheader_timer = 0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались



  
if      (Heater == EVO || Heater == VEVO){
if (webasto) {
    if (StartMessageRepeat<4 && (currmillis-Prev_PeriodW_BusStartStop>800) && w_bus_init >= 9){
  sendMessage (HEATER_START, sizeof(HEATER_START)); 
  StartMessageRepeat++; 
  Prev_PeriodW_BusStartStop = currmillis;
  
    }
  if (StartMessageRepeat>=4){ if (currmillis-Prev_PeriodW_BusMessage>4000)  {
    
         if (requiredmessage==1) sendMessage (HEATER_PRESENCE, sizeof(HEATER_PRESENCE));  
    else if (requiredmessage==2) {if (Heater == EVO) sendMessage (HEATER_STATUS_EVO,  sizeof(HEATER_STATUS_EVO));
                                  if (Heater == VEVO)sendMessage (HEATER_STATUS_VEVO, sizeof(HEATER_STATUS_VEVO));}
    else if (requiredmessage==3) sendMessage (HEATER_DTC_REQUEST, sizeof(HEATER_DTC_REQUEST));  
requiredmessage++; if (requiredmessage > 3) requiredmessage = 1;
StopMessageRepeat = 0;
    
    Prev_PeriodW_BusMessage = currmillis;
    }}}





else if (StopMessageRepeat<4 && (currmillis-Prev_PeriodW_BusStartStop>800)){
  sendMessage (HEATER_STOP, sizeof(HEATER_STOP));
StopMessageRepeat++; 
StartMessageRepeat = 0;
   Prev_PeriodW_BusStartStop = currmillis;
  
  
  }


if (!timerInitflag && w_bus_init==NEED) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); timerInitflag = 1;}
else if ( timerInitflag && (millis() - timerInit>24) && w_bus_init==NEED) {timerInit = currmillis; digitalWrite(TX, 1); w_bus_init=2; }
else if ( timerInitflag && (millis() - timerInit>24) && w_bus_init==2) {K_LINE.begin (2400,SERIAL_8E1 );timerInitflag = 0; w_bus_init=9; 
                                                                   if (needAction>0) sendMessage (HEATER_BEGIN, sizeof(HEATER_BEGIN));  }


if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0){buf[0]=K_LINE.read();  
         if (buf[0]==0x4F || buf[0]==0x44){header = 1; RESETheader_timer=1; prevRESETheader = currmillis; }
         else {header = 0; RESETheader_timer=0;}
         }                  

 // длина сообщения
 else if (header == 1 ){buf[1]=K_LINE.read(); message_size = buf[1]; if (message_size > bufsize) message_size = bufsize;  header = 4;j=2;n=2;checksum = 0;} 

 // пишем тело сообщения 
 else if (header == 4 && j< message_size+n) {
 buf[j] = K_LINE.read();
 
 if (j<message_size+n-1) checksum^= buf[j]; // подсчёт КС
 
 if (j==message_size+n-1) header = 5; 
  j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {  
   
for(byte i = 0; i<n; i++) checksum^=buf[i]; // прибавляем к контрольной сумме старт байты

 // если контрольная сумма верна: 
if ( checksum == buf[message_size+n-1]) {
  
if (Heater == EVO){
    
     if (buf[2]==0xD0 && buf[3]==0x30)                          {    // если получили сообщение с текущими данными
               
                 if  (buf[4] ==0x0A) { 
                          airfan    = (bool)buf[5];                  // получаем флаг работы нагнетателя воздуха
                          plug      = (buf[5] & 0x02)>>1;            // получаем флаг работы штифта накаливания
                          fuelpump  = (buf[5] & 0x04)>>2;            // получаем флаг работы топливного насоса
                          waterpump = (buf[5] & 0x08)>>3;            // получаем флаг работы циркуляционного насоса
                          blowerfan = (buf[6] & 0x10)>>4;            // получаем флаг работы вентилятора печки автомобиля
                  
                                     }
                   
                 if  (buf[6] ==0x0C)  HeaterC = buf[7]-50;           // получаем температуру антифриза в котле 
                 if  (buf[8]==0x0E) {Vpit = (float)(buf[9]<<8|buf[10])/1000.0;}                 // получаем напряжение борт сети
                 if  (buf[11]==0x10) {startWebasto_OK = (bool)buf[12]; last_Flame = currmillis;} // проверяем наличие пламени                                                
                 
                 
                 if (needAction>0 && needAction<NEED_DTCCLEAR) {w_bus_init = 12; sendMessage (HEATER_DTC_REQUEST, sizeof(HEATER_DTC_REQUEST));}
                                                                }

     if (buf[2]==0xD6 && buf[3]==0x01) {if (needAction>0 && needAction<NEED_DTCCLEAR) w_bus_init = 13;
      for (byte h = 0; h< sizeof(DTC); h++) DTC[h]=0;
      DTC[0] = buf[4];
      for (byte h = 0; h< buf[4]; h++) {DTC[h+1]=buf[h*3+5]; bitWrite (DTC[6], h+1,  (buf[h*3+6] & 0x02)>>1);}
            }  
     
     if (buf[2]==0xD6 && buf[3]==0x03)  {startSMS (KTOzapros); SIM800.println (F("DTCs are erased!")); EndSMS(); needAction=0; w_bus_init = 9; NeedTimer = 0;  }                   
     
     
     
     
                                                                
                  }

if (Heater == VEVO){
     if (buf[2]==0xD0 && buf[3]==0x05) { 
            startWebasto_OK = buf[7]; last_Flame = currmillis;      // проверяем наличие пламени у VEVO 
            HeaterC = buf[4]-50;
     
     
     } 
     
                  }


     if (buf[0]==0x44 && buf[2]==0xC4 && buf[3]==0x00) {w_bus_init = 1; delay (500); K_LINE.flush();}             // если получили от котла сбой инита, делаем переинит 
     if (buf[2]==0xD1 && buf[3]==0x0A)  {w_bus_init = 10;   }                                                     // если получили ответ на сообщение старта коммуникации                    
     
  
  
                                        }   

// если контрольная сумма не совпала: 

//else K_LINE.println("CRC fail!!!" );
  
message_size = 0; header=0; RESETheader_timer=0; j=2; checksum = 0;
}




}// end EVO VEVO


else if (Heater == TTC_E){



  
if (!timerInitflag && w_bus_init==NEED) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = currmillis; timerInitflag = 1;}
if ( timerInitflag && (currmillis - timerInit>299)  && w_bus_init==NEED) {timerInit = currmillis; digitalWrite(TX, 1); w_bus_init=2; }
if ( timerInitflag && (currmillis - timerInit>49)   && w_bus_init==2) {timerInit = currmillis; digitalWrite(TX, 0); w_bus_init=3; }
if ( timerInitflag && (currmillis - timerInit>24)   && w_bus_init==3) {timerInit = currmillis; digitalWrite(TX, 1); w_bus_init=4; }
if ( timerInitflag && (currmillis - timerInit>3024) && w_bus_init==4) {K_LINE.begin (10400); timerInitflag = 0; w_bus_init=9;  sendMessage (START_SESSION, sizeof(START_SESSION));}

if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0){buf[0]=K_LINE.read();  
         if (!bitRead (buf[0],6) && bitRead (buf[0],7)){header = 1; RESETheader_timer=1; prevRESETheader = currmillis; }
         
         }                  

 // второй старт байт
 else if (header == 1){buf[1]=K_LINE.read(); if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer=0;}} 

 // третий старт байт
 else if (header == 2){ 
  buf[2]=K_LINE.read(); 
  if (buf[2]==0x51){ message_size = buf[0]; 
  if (buf[0] !=0x80) {header = 4;  message_size&=~0x80; j=3; n=3;}
  else {header = 3; j=4;n=4;}
  if (message_size > bufsize) message_size = bufsize;  checksum = 0;} else {header = 0; RESETheader_timer=0; }
  
                          }  
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
  buf[3]=K_LINE.read(); 
  message_size = buf[3]; 
  if (message_size > bufsize) message_size = bufsize;  
  checksum = 0; header = 4;  
                         }

  // пишем тело сообщения 
 else if (header == 4 && j< message_size+n+1) {
 buf[j] = K_LINE.read(); 
 if (j<message_size+n) checksum+= buf[j]; // подсчёт КС
 
 if (j==message_size+n) header = 5; 
  j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {  

for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты

//for (byte i=0; i<message_size+n+1; i++) {Serial.print (buf[i], HEX); Serial.print(" ");}

 // если контрольная сумма верна: 
if (buf[message_size+n] == checksum) {
  
//  if (buf[n]== 0xC1) Serial.println ("StartSession OK!!!");
  
  
  
  
  }   

// если контрольная сумма не совпала: 
//else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer=0; j=3; checksum = 0;
}

} // end TTC_E



// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && currmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}   

if (currmillis - last_Flame>30000 && ProtocolSTATUS==STATUSBUS) {startWebasto_OK=0; last_Flame = currmillis;}  // делаем статус "нет пламени" через 30 сек, если не получаем сообщения от котла

if (Initreset && currmillis - prevInitreset>18000) {Initreset = 0; w_bus_init = 0;}  // сброс инита, если прошло более 18 сек после отправки последнего сообщения


if (needAction>0 && needAction < NEED_DTCCLEAR && w_bus_init==10) {if (Heater == EVO) sendMessage (HEATER_STATUS_EVO,  sizeof(HEATER_STATUS_EVO));
                                     if (Heater == VEVO)sendMessage (HEATER_STATUS_VEVO, sizeof(HEATER_STATUS_VEVO));
                                     w_bus_init=11;}
if ((NeedTimer && currmillis - prevNeedTimer>11000) || w_bus_init == 13)  {NeedTimer = 0; 
             if (currmillis - prevNeedTimer>11000) noData = 1; 
             if (needAction == NEED_SMSZAPROS)     SMSzapros();
        else if (needAction == NEED_SERVICEINFO) ServiceINFO();
        else if (needAction == NEED_MQTTZAPROS)  {cipsend_begin (); 
                                                  PUBsend ("h/temp/heat", noData ? "fail" : String(HeaterC),1);
                                                  PUBsend ("h/napr", noData ? "fail" : String(Vpit), 1); SIM800.write (0x1A); digitalWrite (DTR, HIGH);}
        else if (needAction == NEED_DTCCLEAR) {startSMS(KTOzapros); SIM800.println (F("DTC not cleared. Heater no answer!")); EndSMS();}
        w_bus_init = 9; noData = 0; needAction = 0; 
        } 
        
 if (needAction==NEED_DTCCLEAR && w_bus_init==10) { sendMessage (HEATER_DTC_ERASE, sizeof(HEATER_DTC_ERASE)); w_bus_init = 20;  }

}


 
 void Reset() {

static bool resettimer = 0;             // для таймера удерживания реле в режиме сброс питания
static uint32_t  resetTimer = 0;        // для таймера удерживания реле в режиме сброс питания
  
  if (!resettimer) {
    digitalWrite (ResetGSM, RelayON);
    resettimer = 1;
    resetTimer = currmillis;
  }
  else if (currmillis - resetTimer > 5000 ) {
    resettimer = 0;

    digitalWrite (ResetGSM, !RelayON);
    digitalWrite (DTR, LOW);
    delay (150);

    prevGSMnastr = currmillis;
    delayATcommand = 150;
    fails = 0;
    failresets ++; if (failresets > 4) failresets = 5;
    gsmstatus = WaitGSM;
    settingGSM = 1;
    ResetNumber++;  EEPROM.write (ResetNumber_cell, ResetNumber);
  }
}




void sendMessage(const byte *command, const size_t size){

 Initreset = 1;  prevInitreset = currmillis;  // включение таймера сброса инита
 
 if (Heater == TTC_E){
  const byte siZe = size+4;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) {
    if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
    if (i==1) Mes[i] = 0x51;
    if (i==2) Mes[i] = 0xF1;    
    if (i==3) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum+=Mes[i] ;K_LINE.write (Mes[i]);  i++;}}
    if (i!=siZe-1) Checksum+=Mes[i];
    else Mes[i] = Checksum;    
    K_LINE.write (Mes[i]); 
      }
  
 }
 else if (Heater == EVO || Heater == VEVO){
  const byte siZe = size+3;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) {
    if (i==0) Mes[i] = 0xF4;
    if (i==1) Mes[i]=size+1; 
    if (i==2) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum^=Mes[i] ;K_LINE.write (Mes[i]); i++;}}
    if (i!=siZe-1) Checksum^=Mes[i];
    else Mes[i] = Checksum;    
    K_LINE.write (Mes[i]); 
      }
  
  }
  }



void AUTHsend () 
{
 cipsend_begin ();
 uint16_t timeBroker       = TIMEBROKER;   
  
  SIM800.write (0x10);
  SIM800.write (strlen(PROTOCOLIUS) + strlen(MQTTNAME) + strlen(MQTTUSER) +  strlen(MQTTPASSWORD) + 12);
  SIM800.write ((byte)0);
  SIM800.write (strlen(PROTOCOLIUS));
  SIM800.write (PROTOCOLIUS);
  SIM800.write (0x03);
  SIM800.write (0xC2);
  
  timeBroker *=60;
  byte * timeBr = (byte*)&timeBroker;
  SIM800.write(*(timeBr+=1)); // время сеанса связи с брокером, сек (ст. байт)
  SIM800.write(*(--timeBr));  // время сеанса связи с брокером, сек (мл. байт)

//SIM800.write (0x04);    // время сеанса связи с брокером, сек (ст. байт)
//SIM800.write (0xB0);    // время сеанса связи с брокером, сек (мл. байт)

  SIM800.write ((byte)0);
  SIM800.write (strlen(MQTTNAME));
  SIM800.write (MQTTNAME);
  SIM800.write ((byte)0);
  SIM800.write (strlen(MQTTUSER));
  SIM800.write (MQTTUSER);
  SIM800.write ((byte)0);
  SIM800.write (strlen(MQTTPASSWORD));
  SIM800.write (MQTTPASSWORD);
  SIM800.write (0x1A);
}

void PUBsend  (char topPub[30], const String Command, const bool &multidata) {

  if (!multidata) {cipsend_begin ();}
  SIM800.write (0x30);
  SIM800.write (strlen (topPub) + Command.length() + 2);
  SIM800.write ((byte)0x00);
  SIM800.write (strlen (topPub));
  SIM800.write (topPub);
  for (byte i = 0; i < Command.length(); i++) SIM800.write (Command[i]);
  if (!multidata) {SIM800.write(0x1A);  digitalWrite (DTR, HIGH);}
}


void SUBsend (char topSub[20]) {
  cipsend_begin ();
  SIM800.write (0x82);
  SIM800.write (strlen(topSub) + 5);
  SIM800.write ((byte)0);
  SIM800.write (0x01);
  SIM800.write ((byte)0);
  SIM800.write (strlen(topSub));
  SIM800.write (topSub);
  SIM800.write ((byte)0x00);
  SIM800.write (0x1A);
}





void  MQTTsendDatastream() 
{
  cipsend_begin ();
  PUBsend ("h/time/stat",  String(TimeWebasto), 1);
  remTime(true);
  PUBsend ("h/stat",       String(webasto) + "&$", 1);
  PUBsend ("h/flame",      String(startWebasto_OK), 1);
  PUBsend ("h/temp/dvs",   String(Temper(EngineC)), 1);
  
  PUBsend ("h/temp/heat", NeedTimer ? "wait" : String(HeaterC),1);
  PUBsend ("h/napr",      NeedTimer ? "wait" : String(Vpit), 1);
  
  PUBsend ("h/temp/ul",    String(Temper(UlicaC)), 1);
  PUBsend ("h/temp/sal",   String(Temper(SalonC)), 1);
  PUBsend ("h/resets",     String(ResetNumber), 1);
  SIM800.write (0x1A);
  prev_refreshMQTT = currmillis;
  digitalWrite (DTR, HIGH);
 }

void remTime   ( bool s) {
  int rem = TimeWebasto - ((currmillis - prevWorkCycleHeater) / 60000ul);
  PUBsend ("h/remtime",    webasto ? String(rem) : "выкл", s);
}

void cipsend_begin () 
{
  digitalWrite (DTR, LOW); delay (150);
  SIM800.println (F("AT+CIPSEND"));
  delay (250);
}


void refreshDataMQTTheaterON ()
{
  
}

 

Baron8
Offline
Зарегистрирован: 12.11.2019

Урааа,заработало Спасибо! Температуру показывает , пламя проверю на выходных когда установлю в машину.Спасибо Большущее за труд!

MaksVV
Offline
Зарегистрирован: 06.08.2015

Ок. Позже можно добавить еще напряжение борт сети , мощность режима работы и флаг блокировки

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Всё заработало , связь не теряет. Ошибка 3А не вылазит . Перегрузок модема не было .

MaksVV
Offline
Зарегистрирован: 06.08.2015

Гуд. Надеюсь позже найду время, добавить ещё один дашборд по диагностике. 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Странно опять эта ошибка 3А, вылезла ,но всё работает , связь стабильная ресетов нет. Сейчас сброшу не и помониторю.

MaksVV
Offline
Зарегистрирован: 06.08.2015

забей на нее.эта ошибка скорее всего возникает, когда шину в-бус садим на GND дольше определенного времени. насколько я знаю она и при диагностике котла к-лайн адаптером иногда возникает. 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Ну да эта ошибка у меня возникала когда я подключался Клайн адаптером к компу , но на смс прошивке её не было, минут 20 назад удалил её , теперь опять появилась. Вроде где то читал про Вебасто , что если счётчик ошибок превысит , какой то там предел , то котел уйдет на полную блокировку

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Но её можно через комп скинуть, но нам вроде это не опасно, но всё равно терзают смутные сомнения , что это не гуд.

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

Baron8 . в твоей ссылке в сообщении #1003 на облачный диск , там были логи подключения девайса к котлу, а сейчас только лог с WTT. зря убрал, пригодились бы. 

Baron8
Offline
Зарегистрирован: 12.11.2019

Всё восстановил , по той же ссылке

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Если котёл имеет шину w-bus, то теперь не нужно выбирать тип котла,  (не важно будь то EVO или EVO V - определит автоматически). Нужно только выбрать тип шины WBUS, ну или если котёл не w-bus, то выбираем соответствующий ТТС_E или Hydronic. Хотя для TTC_E и гидроника протокол ещё не реализован. Только для w-bus а. 

Также там же в папке новый скетч чистки еепром. И там же новые метрики. v.3.86 Тынц. Папка со скетчами

Просьба к Baron8 и Dushman затестить скетч, т.к. у вас как раз оба с W-BUS, но разных версий этой шины, чтобы проверить как девайс автоматически подстраивается. 

даш выглядит так. Рекомендую делать в настройках даша маленький размер метрик. 

Baron8
Offline
Зарегистрирован: 12.11.2019

Со скетчем подготовки еепром понятно , а с основным не нахожу где прописать настройки  mqtt servera

MaksVV
Offline
Зарегистрирован: 06.08.2015

верху вкладки, самая левая

Baron8
Offline
Зарегистрирован: 12.11.2019

я так думаю должно быть 7 вкладок, у меня отображается 6(((

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Сегодня протестирую , отпишусь о результатах. Тут возникла МИСЛЬ  , если в версии с мктт нет функций  управление сигнализацие старлайн . то может вообще удалить из скетча все что с ней связано. Я вот  мечтаю чтоб девайс мог управлять центральным замком , открывать и закрывать двери , т. к. у меня сдох родной радиоключ  а сигу я снял из-за глюков . Вообще же можно впихнуть в девайс простенькую сигу , открыть закрыть двери , и реагировать на датчик закрытия дверей и датчик удара , автозапуск не особо нужен , боюсь на него памяти  не хватит.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Dushman7776 пишет:

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

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

Baron8 пишет:

я так думаю должно быть 7 вкладок, у меня отображается 6(((

да 7 вкладок. Попробуй открывать за файл 3_86. В этой вкладке (3_86) вверху как раз пароли MQTT. ну и так для инфы, у меня IDE 1.8.5.

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Dushman7776 пишет:

при первом запуске дашборда он помигал немного 

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

 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Ну мощность вроде адекватно, до 80 градусов колтла , мощность была 100 процентов , а после стала 50 процентов , и температура сразу тоже под упала до 74 градусов , но я думаю что это нормально , а вот срывов пламени у меня не было , котел исправный .

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Да по сигналке если делать то отдельным дашбордом , а то случайно нажмешь, вообще алгоритм можно такой что если после открытия дверей не пришел сигнал от концевиков дверей в течении 20 секунд, то идет опять закрытие , а если сигнал от концевиков  пришел без команды открыть , то значит это взлом , и смс о взломе , ну и датчик удара можно прикрутить . можно даже стандартный от сигналки какой нибудь типа старлайна. А так конечно памяти там не много осталось, вон  Martinhol  с драйва перешел в своем проекте с ардуино на esp8266  , там памяти побольше и вообще жиру  в этих камнях много, а лучше esp32  но я и в атмегах пока не много понимаю . а по этим еще меньше инфы в сети.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Можно атмегу 1280p прям на плату посадить. Там 16К оперативки и 128К под программу. А то лениво изучать работу с есп

Dushman7776
Offline
Зарегистрирован: 13.01.2019

У меня ардуино мега уже 2 года без дела лежит , хотел 3д принтер делать, да забил на это, можно  ее заюзать, Но у меня знаний в программировании пока маловато , как алгоритм работы составить это я могу а как в код перевести это  ни хрена не понимаю, ПОКА . А плату можно и новую развести ,  вытравить это несложно.

MaksVV
Offline
Зарегистрирован: 06.08.2015

С питанием опять бороться, надо голый МК, а 2560 для меня лично непаябелен.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Не понял про борьбу с питанием, вроде они тоже ни хрена не потребляют , а корпуса 1280 и 2560 одинаковые если под смд . Я не призываю Вас переделывать ваш проект под мои хотелки . Я просто по факту говорю что атмега 328 слаба для более навороченного функционала . Я наверное уже слишком стар для этого дерьма , ну не понимаю я как писать программы , раз 10 пробовал начать плотно изучать программирование под МК , но не преуспел в этом , но все равно пытаюсь разобраться , читаю пояснения в скетчах сравниваю , но пока не очень получается, я могу отремонтировать вещь которая не работает как нужно, но вот создать что то новое на серьезном уровне не получается. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Перепутал мк. Имел ввиду 1284p. По питанию дело в юсб уарт преобразователе и встроенном стабе. 1284 в этом плане чуть больше по размеру 328 , а по памяти вообще огонь. Да и дуня мега большевата в принципе по размеру. Если может только мегу про мини брать ...

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Да размер не критичен , если делать шилдом , то он будет по размеру не больше чем сейчас, стаб можно отключить как и преобразователь юсб , шить можно ,как и про мини , через tx rx . Просто ардуино мегу можно на алике не за дорого купить, а 1284 где взять , я на Али экспресс зарёкся голые микросхемы покупать , только готовые модули.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

На последнем скетче даже ошибка 3А не появлялась ни разу.

Станислав Пимшин
Offline
Зарегистрирован: 18.11.2019

Приветствую Гуру электроники, случилась беда, пролюбил яичко, в смысле пульт управления вебастой THERMO TOP E, теперь продумываю варианты  решения, из беглого чтения темы понял следующее: Имеется вполне рабочая схема со скетчем но через чур много ревизий и допиливания, кроме того имеется и мобильное приложение (не фирма)... Можно для нубаса в данном плане тыкнуть носом в стабильную версию как железа так и ПО.

 

  

Dushman7776
Offline
Зарегистрирован: 13.01.2019

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

Baron8
Offline
Зарегистрирован: 12.11.2019

Привет всем! Теперь и я напишу немножко букв... Изначально по последней прошивке, у меня отображалось 6 вкладок вместо 7ми- Мой косяк ( точнее arduino IDE версия 1.8.1 их не видит, не наступите на мои грабли нужно не ниже 1.8.6) разобрался , зашил в комнате всё гуд, дальше возвращаю вебасту в машину и ... в ожидании чуда... а тишина. Начинаю разбираться , сим не переходит в gprs. меряю напряжение , почти 8 вольт... Короче - сдохла лм393(с дырочкой стала), стабилизатор и сим800Л, дуня живая. Что произошло не знаю, догадки такие- коротнул W-bus на +12 в момент опроса котла. Ну это уже в прошлом, получил детальки и Вуала- Часики . Температуру котла , мощность , напряжение , пламя , количество ошибок показывает! Осталось дело за малым, красиво оформить и распихать по машине.

Спасибо большое Максиму за его огромный труд!

MaksVV
Offline
Зарегистрирован: 06.08.2015

Здоров!

Baron8 пишет:
... у меня отображалось 6 вкладок вместо 7ми- Мой косяк ( точнее arduino IDE версия 1.8.1 их не видит, не наступите на мои грабли нужно не ниже 1.8.6) разобрался

 
а я тебе сразу говорил #1026 вообще-то: 
 
 
MaksVV пишет:
да 7 вкладок. .... ну и так для инфы, у меня IDE 1.8.5.
 
ну ладно, разобрался, красавчик. 
 
Baron8 пишет:
... меряю напряжение , почти 8 вольт... Короче - сдохла лм393(с дырочкой стала), стабилизатор и сим800Л, дуня живая. Что произошло не знаю, догадки такие- коротнул W-bus на +12 в момент опроса котла. Ну это уже в прошлом, получил детальки и Вуала- Часики . Температуру котла , мощность , напряжение , пламя , количество ошибок показывает! Осталось дело за малым, красиво оформить и распихать по машине.
 
всмысле 8 вольт после стаба? и он умер вместе с модемом и lm393? Но это явно не из-за того что шину на +12В замкнул. Скорее всего подстроечный резистор в стабе ты шевельнул или он сам окислился, сместив напряжение до 8В. Надо как то этот вопрос тоже по идее решить, чтобы все надёжно было. А то, думается, со временем напряжение может убегать. 
 
Baron8 пишет:
Спасибо большое Максиму за его огромный труд!
И вам респект за тестирование!
MaksVV
Offline
Зарегистрирован: 06.08.2015

Куда то пропал уважаемый SyntAcc. Год назад он в значительной степени помог продвинуть проект, предоставив логи по TTV и EVO и инфу по протоку ТТV (w-bus 3.3). 

SyntAcc пишет:
Заработало!) Котел стартует (включается продувка, начинается розжиг) но я не стал из-за помпы дожидаться когда выйдет на полную мощность. Самое главное что оно работает).  Теперь надо GSM заказывать с али и собирать полную версию
 
SyntAcc пишет:
MaksVV спасибо тебе огромное за этот проект! Помпу на котле я заменил на СтартВольт VPM03780E, с крепежом есть нюансы, но в общем и целом все ок, работает тихо Запускаю пока что в ручном режиме, вчера и позавчера пришлось перезапускать через 10 минут работы, почему останавливалось ХЗ (холодно в машине сидеть, не отслеживал, посмотрю архив сбоев как потеплеет) но после перезапуска 20-25 минут работало штатно. Сегодня утром температура мотора была -27C°, котел остановился через ~30 минут.

SyntAcc, давай собирай полную версию. И скетч и плата наконец-то почти доведены до ума. И заодно твой w-bus  3.3 проверим. Т.к. 3.1 и 4.0 работают норм. 

Baron8
Offline
Зарегистрирован: 12.11.2019

всмысле 8 вольт после стаба? и он умер вместе с модемом и lm393? Но это явно не из-за того что шину на +12В замкнул. Скорее всего подстроечный резистор в стабе ты шевельнул или он сам окислился, сместив напряжение до 8В. Надо как то этот вопрос тоже по идее решить, чтобы все надёжно было. А то, думается, со временем напряжение может убегать. 

Пытался разобраться - дело в том, что раньше сталкивался с траблами подстроечников , поэтому сразу подобрал постоянный и запаял его. Модем сдох - понятно , высокое напряжение. Непонятка с lm393 , пропаленная дырка в корпусе... вот и пришла в голову идея, что если закоротить ( не исключаю такого , т.к всё было разложено под капотом без изоляции)w-bus , а это выход 7 lm393 (коллектор транзистора) повесить на +12 вольт и подать команду на запуск или обновить  то на 7й ноге пойдут импульсы ( транзистор соединит землю с + 12) то точно сгорит . Дальше можно предположить , что по первой ноге лм пойдёт +12в  на дуню ( а она оказалась крепче стаба ) Ну это уже гадание... думаю частный случай , а подстроечник лучше выкинуть.
Станислав Пимшин
Offline
Зарегистрирован: 18.11.2019

Dushman7776 пишет:

Да по сигналке если делать ...

У меня большинство знакомых юзают Starline... отсюда возникает вопрос, никто ли из присутствующих не снимал алгоритм работы через разъем (к примеру для А91 - Х8-разъем для подключения GSM устройств) для осуществления дистанционного запуска и контроля за охраной?

MaksVV
Offline
Зарегистрирован: 06.08.2015

Думаю никто. Но очень маловероятно, что там протокол не зашифрован. речь ведь идёт о снятии/поставке в охрану в том числе. 

Станислав Пимшин
Offline
Зарегистрирован: 18.11.2019

Есть небольшая идея! Если в качестве общения между сигнализациями (любыми!!! Это реально) и блоком управления по GPRS использовать родной пульт с ОС. Сигнатуру брать с провода состояния сигнализации (к примеру для А91 это 12 выход состояния сигнализации , а срабатывание и обратная связь с дисплея брелка, то есть вместо дисплея МК...
Должно сработать на мой взгляд!

juniks
Offline
Зарегистрирован: 28.05.2019

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

juniks
Offline
Зарегистрирован: 28.05.2019
Станислав Пимшин
Offline
Зарегистрирован: 18.11.2019

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

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Станислав, купите более современную старлайн а94 или ее соплеменника по поколению. Ее гораздо проще подключить к моему девайсу. Единственное, снятие/постановка в охрану только не получится. А через дисплей что то подключать... бред

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

машина какая?