Снова MQTT

vlad072
Offline
Зарегистрирован: 01.08.2017

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

vlad072 пишет:

И кому  это? если мне, то не интересно - я все это читал.

В логах брокера что нибудь вразумительное есть? Модем корректно отвечает на все команды? отправка успешна у модема?

vlad072
Offline
Зарегистрирован: 01.08.2017

После отправки 0xC0 0x00 0x1A из порта модема получаю 0xFF 0xC0 0x00 0x1A. Т.е. на сколько я понимаю наружу ничего не уходит.

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

vlad072 пишет:

После отправки 0xC0 0x00 0x1A из порта модема получаю 0xFF 0xC0 0x00 0x1A. Т.е. на сколько я понимаю наружу ничего не уходит.

Что значит из "порта модема получаю" - это откуда?

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

Update : я так понимаю вам модем в ответ дублирует посланную команду - отключите нафиг чтоб не мешало разбираться.

vlad072
Offline
Зарегистрирован: 01.08.2017
void brokerPing() {
  gsm.println("AT+CIPSEND"); if (!gsm.find(">")) return;                                                  .
  gsm.write(0xC0); gsm.write(byte(0x00)); gsm.write(0x1A); 
  delay(100); Serial.print("ping resp: "); while(gsm.available()) Serial.print(" "), Serial.print(gsm.read(), HEX);
}

После вызова функции в терминале вижу: 


ping resp : FF C0 0 1A

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

А что касаемо лога, а что лог... в нём не пишется ничего из обена, там просто коннект, дисконнект и всего то...

Я чё думаю: может не морочится с пингом. пустой паблиш туда кадать какой нибудь до таймута да и всё, по сути эффект будет тот же.

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

Вот смотрю я на код, а с чего вы взяли что ответ от брокера стабильно через 100 миллисекунд придёт, а например не через секунду.

Может быть я не прав, но уже писал - такая архитектура скетча с delay и не дожидаться ответов от модемов и без их анализа - неработоспособна!

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

По поводу пинга - каждый коннект к брокер сотовый оператор считает за новое подключение, соответственно если у вас лимитный интернет и коннктится каждые N секунд - трафик весь быстро закончится. Пинг пакеты на то и придуманы в mqtt чтоб коннктится раз например в сутки, и постоянно проверять связь через M секунд.

vlad072
Offline
Зарегистрирован: 01.08.2017

andycat пишет:
с чего вы взяли что ответ от брокера стабильно через 100 миллисекунд придёт, а например не через секунду.

Делэй поставил уже от безисходности, кстати ставил setTimeout на порт 10000 - эффект нет.. И вообще модем должен что то внятное пинуть в порт после отправки пакета, я его жду. При отправке паблиша или подписки сразу получаю "SEND OK, а тут нифига. Видимо я всё же как то не правильно формирую пакет.

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

Вижу два варианта :
1 сменить брокера - возможно он что то шлёт не так
2 взять наконец то нормальный пример с последовательность АТ команд и делать по аналогии

ЗЫ. Чудес не бывает.

Update :
3. Пересмотреть всю логику работы с модемом - переходить на конечные автоматы или их подобие, т е каждая отправлена команда подразумевает ожидание некоего ответа и или какие то действия и в зависимости от условия - переходить на другие действия.

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

И ещё команда cipsend имеет несколько режимов работы, я отправляю с указанием количества отправояемых байт, а вы как настроили свой модем?)

Пока скетч не выложите - сложно далее что либо обсуждать.

vlad072
Offline
Зарегистрирован: 01.08.2017

Весь скетч

#include <SoftwareSerial.h>

const char*  apn  = "internet.tele2.ru";         // apn<,user,pass>
const char*  broker = "m23.cloudmqtt.com,17155"; // addr,port
const char*  proto = "MQIsdp";
const char*  cid = "BlackBox";
const char*  willt = "notify";
const char*  willm = "BlackBox is died!";
const char*  user = "e4tggrtgerge";
const char*  pass = "ergergerge3334343f34f";

SoftwareSerial gsm(9, 10);

unsigned long t1min = 0;
char* at = "";
char* buff = "";

/*AT+CFUN=1,1
OK
AT+CREG? cycle
+CREG: 0,1
AT+CSTT=internet.tele2.ru
OK
AT+CIICR
OK
AT+CIFSR
10.142.119.220
AT+CDNSCFG=8.8.8.8
OK
AT+CIPSTATUS
OK
STATE: IP STATUS



AT+CIPSTART=TCP,m23.cloudmqtt.com,17015
OK

CONNECT */

bool gprsConnect () {
  gsm.println("AT+CFUN=1,1"); if ( !gsm.find("OK") ) return false;
  delay(3000);
  for (byte i = 0;; i++) { 
    gsm.println("AT+CREG?"); delay(1000);
    if ( gsm.find("+CREG: 0,1") ) break;
    if (i > 10) return false; }
  gsm.println("+CIPMUX=0"); if ( !gsm.find("OK") ) return false;
  gsm.print  ("AT+CSTT="); gsm.println(apn); if ( !gsm.find("OK") ) return false;
  gsm.println("AT+CIICR"); gsm.setTimeout(10000);
  if ( !gsm.find("OK") ) return false; gsm.setTimeout(1000);
  gsm.println("AT+CIFSR"); gsm.readString();
  gsm.println("AT+CDNSCFG=8.8.8.8"); if ( !gsm.find("OK") ) return false;
  gsm.println("AT+CIPSTATUS");
  return gsm.find("STATE: IP STATUS");
}
bool brokerConnect () {
  gsm.print("AT+CIPSTART=TCP,"); gsm.println(broker);
  delay(2000); if (!gsm.find("CONNECT OK")) return false;
  //gsm.println("AT+CIPHEAD=1"); if (!gsm.find("OK")) return false;
  gsm.println("AT+CIPSEND"); if ( !gsm.find(">") ) return false;
  gsm.write(0x10);
  gsm.write(12 + 2+strlen(cid) + 2+strlen(willt) + 2+strlen(willm) + 2+strlen(user) + 2+strlen(pass));
  gsm.write((byte)0x00); gsm.write(0x06); gsm.write("MQIsdp"); gsm.write(0x03); // proto, ver
  gsm.write(0xC6); gsm.write((byte)0x00); gsm.write(0x3C);                      // flags, ka timout
  gsm.write((byte)0x00); gsm.write(strlen(cid)); gsm.write(cid);
  gsm.write((byte)0x00); gsm.write(strlen(willt)); gsm.write(willt);
  gsm.write((byte)0x00); gsm.write(strlen(willm)); gsm.write(willm);
  gsm.write((byte)0x00); gsm.write(strlen(user)); gsm.write(user);
  gsm.write((byte)0x00); gsm.write(strlen(pass)); gsm.write(pass);
  brokerPub("notify", "BlackBox is alive...");
  brokerSub("cmd/#");
  gsm.write(0x1A);
  //return (gsm.read() == "+IPD,1\0");
  //return (gsm.read() == (byte)0);
  return gsm.find("SEND OK");
}
void brokerPub (const char* topic, const char* msg) { 
  gsm.write(0x30);
  gsm.write((2+strlen(topic) + strlen(msg)));
  gsm.write((byte)0x00), gsm.write(strlen(topic)), gsm.write(topic);
  gsm.write(msg);
}
void  brokerSub (const char* topic) {
  gsm.write(0x82);
  gsm.write(strlen(topic) + 5); 
  gsm.write((byte)0x00); gsm.write(0x01)  ;
  gsm.write((byte)0x00); gsm.write(strlen(topic)); gsm.write(topic);
  gsm.write((byte)0x00);
}
bool brokerPing() {////////////////////////////////////00000230: ff c0 00 1a 0d 0a 53 45  |  4e 44 20 4f 4b 0d 0a d0  ÿÀ....SEND OK
  gsm.println("AT+CIPSEND"); if (!gsm.find(">")) return false;//////00000240: 00                                                   .
  gsm.write(0xC0); gsm.write(byte(0x00)); gsm.write(0x1A); 
  delay(1000); Serial.print("ping ret :"); while(gsm.available()) Serial.print(" "), Serial.print(gsm.read(), HEX);
  Serial.println();
  return true; //gsm.find("SEND OK");
}
bool googlePing() {
  gsm.println("AT+CIPPING=8.8.8.8,1");
  return gsm.find("+CIPPING:");
}

void setup() {
  Serial.begin(9600); delay(500);
  gsm.begin(9600); delay(500);
  while (true) {
    Serial.print("gprs connect... ");
    if ( gprsConnect() ) break;
    Serial.println("error!"); }
  Serial.println("OK");
  while (true) {
    Serial.print("broker connect... ");
    if ( brokerConnect() ) break;
    Serial.println("error!"); }
  Serial.println("OK");
  delay(5000);
  pinMode(13, OUTPUT);
}

void loop() {
  if ((millis() - t1min) > 30*1000) t1min = millis(), brokerPing();
  //while(Serial.available()) gsm.write(Serial.read());
  //while(gsm.available()) Serial.write(gsm.read());
  at = "";
  if ( gsm.available() ) at = gsm.readString().c_str();
//    gsm.println("AT+CIPSEND");
//    brokerPub("notify", Serial.readString().c_str());
//    gsm.write(0x1A);

  if ( strstr(at, "cmd/start1") != 0 ) digitalWrite(13, HIGH);//////00000340: ff c0 00 1a 30 0c 00 09  |  63 6d 64 2f 73 74 61 72  ÿÀ..0...cmd/star
  if ( strstr(at, "cmd/start0") != 0 ) digitalWrite(13, LOW); //////00000350: 74 30 0d 0a                                          t0..
  if ( strstr(at, "cmd/stopTimer") != 0 ) {
    Serial.print("stopTimer=");
    for ( byte i = 0;;i++ ) {
      if ( (byte)strstr(at, "stopTimer")[8+i] > 0x30 ) { buff[i] = '\0'; break; }
      buff[i] = strstr(at, "stopTimer")[8+i]; }
    Serial.println(buff);
  }
  if ( strstr(at, "cmd/stopTemp") != 0 ) {
    Serial.print("stopTemp=");
    for ( byte i = 0;;i++ ) {
      if ( (byte)strstr(at, "stopTemp")[7+i] > 0x30 ) { buff[i] = '\0'; break; }
      buff[i] = strstr(at, "stopTemp")[7+i]; }
    Serial.println(buff);
  }
}

 

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

нет команд настройки режима обмена CIPQSEND CIPMODE

нет команды закрытия сессии CIPSHUT

рекомендую все таки сообщать модему сколько будет отправлено байт в команде CIPSEND, а не слать в конце байт 26, это во первых надежнее, во вторых если у вас в передаче будет этот байт - все сломается

 

Читать до просветления:

http://forum.cxem.net/index.php?/topic/195209-%D0%BD%D0%B0%D1%81%D1%82%D...

http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-411540

Вот старенький пример, комментариев нет, функционал - ранняя версия, только отправка и то с одним неприятным косяком.

#include <avr/wdt.h>
#include <avr\pgmspace.h>
#include "s800str.h"

#define USE_UART_LOG 1 // 1 if use HW Serial as Log

#include <SoftwareSerial.h>
SoftwareSerial gsm(GSM_TX, GSM_RX); // установка контактовGSM_TX->RX и GSM_RX->TX для программного порта

byte modem_step = 100; // current work mode mode in table of command
// static steps:
// 100 - delay 15 sec for registration modem in net
// 101 - not wait response, wait incomming call or other commands
// 102 - show info on display by press key and/or sleep modem
unsigned long current_millis; // main timer
#define period_fixed_wait 30000UL // max time wait response
unsigned long timer_reg_modem = 0; // timer registration modem in net and timer response
char resp_buf[maxSizeResponse]; // response buf from modem
byte pos_buf = 0; // current pos response buf
#define max_resp_count_on_one_type_cmd 5 // max 5 response text by one command and one type
byte fl_true_Rresp[max_resp_count_on_one_type_cmd];
char text_Rresp[max_resp_count_on_one_type_cmd][maxSizeResponse];
byte fl_true_Oresp[max_resp_count_on_one_type_cmd];
char text_Oresp[max_resp_count_on_one_type_cmd][maxSizeResponse];
byte startFlag = 1;
byte rresp, oresp;
byte ussdStep = 0;
#define max_size_operator_name 10
char operator_name[max_size_operator_name];

char mqtt_user[] = "********"; // Логи от сервер
char mqtt_pass[] = "***********"; // Пароль от сервера
char mqtt_device[] = "AndycatTest41";
char mqtt_topic_gps_longitude[] = "/gps_l"; // долгота
char mqtt_topic_gps_breadth[] = "/gps_b"; // широта
#define max_size_gps_string 0x20
char data_gps_longitude[max_size_gps_string]; // долгота
char data_gps_breadth[max_size_gps_string]; // широта

byte mqtt_mode = 0;
// 0 - connect mqtt server
// 1 - send data
// 2 - disconnect from server
#define period_send_connect_mqtt 600000UL // connect/disconnect mqtt server
unsigned long timer_send_connect_mqtt = 580000UL;
#define period_send_gps_data 2000UL // send data
unsigned long timer_send_gps_data = 0;

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((used)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}

void setup() {
  MCUSR = 0;
  wdt_disable();
#if (USE_UART_LOG == 1)
  Serial.begin(115200);
  Serial.println("Power ON or WDT reset");
#endif
  gsm.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  pinMode(dtr_sim800_pin, OUTPUT); digitalWrite(dtr_sim800_pin, LOW); // normal mode modem
  pinMode(ledRed_pin, OUTPUT);
  pinMode(ledGre_pin, OUTPUT);
  LEDREDOFF;  LEDGREOFF;
  operator_name[0] = 0;
  wdt_enable(WDTO_8S);
}

void loop() {
  wdt_reset();
  //delay(9000); // test WDT
  current_millis = millis();
  if (((current_millis - timer_send_connect_mqtt) >= period_send_connect_mqtt) && (modem_step == 101) && (!startFlag)) {
    switch (mqtt_mode) {
      case 0: {
          timer_send_connect_mqtt = current_millis;
          modem_step = 32; sendATcmd();
          break;
        }
      case 1: {
          mqtt_mode = 2;
          modem_step = 42; sendATcmd();
          break;
        }
      case 2: {
          modem_step = 45; sendATcmd();
          break;
        }
      default: {}
    }
  }
  if (((current_millis - timer_send_gps_data) >= period_send_gps_data) && (modem_step == 101) && (!startFlag) && (mqtt_mode == 1)) {
    timer_send_gps_data = current_millis;
    // gps data TO text
    data_gps_longitude[0] = random(0, 10) + '0'; data_gps_longitude[1] = 0;
    data_gps_breadth[0] = '9'; data_gps_breadth[1] = random(0, 10) + '0'; data_gps_breadth[2] = 0;
    // send data
    modem_step = 42; sendATcmd();
  }
  if (modem_step == 100) {
    LEDGREOFF;
    if ((current_millis - timer_reg_modem) >= 15000UL) { // wait 15 sec registration modem
      modem_step = 0; sendATcmd();
    }
  } else if (modem_step == 101) {
    LEDGREOFF;
    if (startFlag) {
      LEDREDOFF;
      startFlag = 0;
#if (USE_UART_LOG == 1)
      Serial.println("Ready");
#endif
      digitalWrite(LED_BUILTIN, HIGH);
    }
    // nothing do
    loadDataFromModem();
  } else if (modem_step < 100) {
    LEDGREON;
    if ((rresp == 0) && (oresp == 0)) { // go to next cmd
      modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd();
    } else {
      if ((current_millis - timer_reg_modem) >= period_fixed_wait) {
        if (rresp > 0) {
          resetModem();
        } else if (oresp > 0) { // go to next cmd
          modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd();
        }
      } else {
        // main work
        loadDataFromModem();
      }
    }
  }
}

byte doCmdForModem(byte inByte) {
  byte flGood, flResp;
  if (modem_step < 100) {
    if (rresp > 0) {
      flGood = 0;
      flResp = 0;
      for (byte i = 0; i < rresp; ++i) {
        if (fl_true_Rresp[i] == 0) {
          if (findRespFromBuf(text_Rresp[i])) {
            fl_true_Rresp[i] = 1;
            if ((rresp == 1) || (i == (rresp - 1))) flGood = 1;
            flResp = 1;
          }
          break;
        }
      }
      if (flGood) {
        // manual processing response for good cmd
        switch (modem_step) {
          case 43: { // connected to mqtt server
              if (mqtt_mode == 0)mqtt_mode = 1;
              break;
            }
          case 44: { // re connect to mqtt server
              mqtt_mode = 0;
              break;
            }
          default: {}
        }
        // go to next cmd
        modem_step = s800getNextStepCmdByNum(modem_step);
        if (modem_step < 100) sendATcmd(); return 1;
      }
      if (flResp) {
        clearRespBuf(); return 1;
      }
    }
    // manual processing response
    switch (modem_step) {
      case 24: { // operator name
          if (inByte == '+') {
            ussdStep = 1; operator_name[0] = 0;
          } else if ((ussdStep == 1) && (inByte == '"')) {
            ussdStep = 2;
          } else if (ussdStep == 2) {
            if (inByte == '"') {
              ussdStep = 3;
            } else {
              byte sl = strlen(operator_name);
              if (sl < (max_size_operator_name - 1)) {
                operator_name[sl] = inByte;
                operator_name[sl + 1] = 0;
              }
            }
          }
          break;
        }
      default: {}
    }
  } else { // mode 101
    // find ring or other cmd
  }
  return 0;
}

byte findRespFromBuf(char* textResp) {
  if (resp_buf[pos_buf] > 0) {
    byte idxBuf;
    if (pos_buf == 0) idxBuf = maxSizeResponse - 1; else idxBuf = pos_buf - 1;
    byte lenResp = strlen(textResp);
    byte idxResp = lenResp - 1;
    byte cntResp = 0;
    for (byte i = 0; i < maxSizeResponse; ++i) {
      if (resp_buf[idxBuf] == 0) break;
      if (resp_buf[idxBuf] == textResp[idxResp]) {
        --idxResp;
        if ((++cntResp) == lenResp) return 1;
      } else {
        cntResp = 0; idxResp = lenResp - 1;
      }
      if ((--idxBuf) == 0) idxBuf = maxSizeResponse - 1;
    }
  } else if (pos_buf > 0) {
    if (strPos(resp_buf, textResp) >= 0) {
      return 1;
    }
  }
  return 0;
}

void sendATcmd() {
  char cmdAT[maxSizeATcommand];
  s800getTextCmdByNum(modem_step, cmdAT);
  switch (modem_step) { // manual processing AT cmd
    case 42: {
        gsm.print(cmdAT);
#if (USE_UART_LOG == 1)
        Serial.print(cmdAT);
#endif
        byte fullSize = getSizeMqttPacket();
        gsm.print(fullSize, DEC); gsm.print("\r\n");
#if (USE_UART_LOG == 1)
        Serial.println(fullSize, DEC);
#endif
        break;
      }
    case 43: {
        sendMqttPacket();
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        break;
      }
    default: {
        gsm.print(cmdAT);
#if (USE_UART_LOG == 1)
        Serial.print(cmdAT);
#endif
      }
  }
  timer_reg_modem = current_millis;
  rresp = s800getCountRrespCmdByNum(modem_step);
  oresp = s800getCountOrespCmdByNum(modem_step);
  for (byte i = 0; i < max_resp_count_on_one_type_cmd; ++i) {
    fl_true_Rresp[i] = 0; // max 5 response text by one command and one type
    fl_true_Oresp[i] = 0;
  }
  if (rresp) {
    for (byte i = 0; i < rresp; ++i) {
      s800getRespByNum(0, modem_step, i, text_Rresp[i]);
    }
  }
  if (oresp) {
    for (byte i = 0; i < oresp; ++i) {
      s800getRespByNum(1, modem_step, i, text_Oresp[i]);
    }
  }
  clearRespBuf();
}

void clearRespBuf() {
  memset(resp_buf, 0, maxSizeResponse);
  pos_buf = 0;
}

void loadDataFromModem() {
  if (gsm.available()) {
    while (gsm.available()) {
      byte readByte = gsm.read();
      if (readByte > 0) {
#if (USE_UART_LOG == 1)
        if ((modem_step != 3) && (modem_step != 28) && (modem_step != 21)) Serial.write(readByte);
#endif
        resp_buf[pos_buf] = readByte;
        ++pos_buf;
        if (pos_buf >= maxSizeResponse) pos_buf = 0;
        wdt_reset();
        if (doCmdForModem(readByte) == 1) break;
      }
    }
  }
}

void resetModem() {
  LEDREDON;
  // reset modem
  pinMode(reset_sim800_pin, OUTPUT);
  digitalWrite(reset_sim800_pin, LOW);
  delay(115);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  // new init modem and start new main loop
  timer_reg_modem = current_millis;
  modem_step = 100;
  startFlag = 1;
  operator_name[0] = 0;
  mqtt_mode = 0;
  timer_send_connect_mqtt = 580000UL;
}

byte sendConnectPacket(byte getSize) {
  byte sizeDevice = strlen(mqtt_device); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass);
  byte fullSize = 16 + sizeDevice + sizeUser + sizePass;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)0x04); // Length LSB (4)
  sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name
  sendByteToMQTTclient((byte)0x04); // Protocol Level byte
  sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable
  sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0)
  sendByteToMQTTclient((byte)0x28); // Keep Alive LSB (10) - 40 sec
  // payload
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user
  for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i]));
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass
  for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i]));
}

void sendByteToMQTTclient(byte inByte) {
  gsm.write((byte)(inByte));
#if (USE_UART_LOG == 1)
  if ((inByte < 0x20) || (inByte >= 0x7F)) {
    Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
  } else {
    Serial.write(inByte);
  }
#endif
}

byte sendGPSlData(byte getSize) {
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_gps_longitude); byte sizeData = strlen(data_gps_longitude);
  byte fullSize = 4 + sizeDevice + sizeTopic + sizeData;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_gps_longitude[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(data_gps_longitude[i]));
}

byte sendGPSbData(byte getSize) {
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_gps_breadth); byte sizeData = strlen(data_gps_breadth);
  byte fullSize = 4 + sizeDevice + sizeTopic + sizeData;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_gps_breadth[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(data_gps_breadth[i]));
}

void sendDisConnectPacket() {
  // fixed header
  sendByteToMQTTclient((byte)0xE0); // MQTT Control Packet type 1110 connect, reserved 0000
  sendByteToMQTTclient((byte)0x00); // Remaining Length
}

byte getSizeMqttPacket() {
  switch (mqtt_mode) {
    case 0 : {
        return sendConnectPacket(1);
      }
    case 1 : {
        byte fullSize = sendGPSlData(1);
        fullSize += sendGPSbData(1);
        return fullSize;
      }
    case 2 : {
        return 2;
      }
    default: {}
  }
}

void sendMqttPacket() {
  switch (mqtt_mode) {
    case 0 : {
        sendConnectPacket(0);
        break;
      }
    case 1 : {
        sendGPSlData(0);
        sendGPSbData(0);
        break;
      }
    case 2 : {
        sendDisConnectPacket();
        break;
      }
    default: {}
  }
}


//--s800str.h--
#include <avr\pgmspace.h>

#define maxSizeATcommand 60
#define maxSizeResponse 24

const char at0cmdAT[] PROGMEM = "AT\r\n";
const char at1cmdHTTPACTION[] PROGMEM = "AT+HTTPACTION=0\r\n";
const char at1rsp1[] PROGMEM = "+HTTPACTION:";
const char at1rsp2[] PROGMEM = ",";
const char at2cmdSAPBR11[] PROGMEM = "AT+SAPBR=1,1\r\n";
const char at2rsp1[] PROGMEM = "operation not allowed\r\n";
const char at3cmdREADSMS[] PROGMEM = "AT+CMGL=4\r\n"; // "AT+CMGL=\"ALL\"\r\n";
const char at4cmdDDET[] PROGMEM = "AT+DDET=1\r\n";
const char at5cmdATE0[] PROGMEM = "ATE0\r\n";
const char at6cmdCLIP1[] PROGMEM = "AT+CLIP=1\r\n";
const char at7cmdATS0[] PROGMEM = "ATS0=0\r\n";
const char at8cmdATV1[] PROGMEM = "ATV1\r\n";
const char at9cmdATCMEE2[] PROGMEM = "AT+CMEE=2\r\n";
const char at10cmdATCMGF1[] PROGMEM = "AT+CMGF=0\r\n";
const char at11cmdATCREG[] PROGMEM = "AT+CREG?\r\n";
const char at11rsp1[] PROGMEM = "+CREG:";
const char at11rsp2[] PROGMEM = ",1\r\n";
const char at12cmdDELSMS[] PROGMEM = "AT+CMGDA=6\r\n"; // "AT+CMGDA=\"DEL ALL\"\r\n";
const char at13cmdSAPBR311[] PROGMEM = "AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n";
const char at14cmdSAPBR312[] PROGMEM = "AT+SAPBR=3,1,\"APN\",\"internet\"\r\n";
const char at15cmdSAPBR313[] PROGMEM = "AT+SAPBR=3,1,\"USER\",\"\"\r\n";
const char at16cmdSAPBR314[] PROGMEM = "AT+SAPBR=3,1,\"PWD\",\"\"\r\n";
const char at17cmdSAPBR21[] PROGMEM = "AT+SAPBR=2,1\r\n";
const char at17rsp1[] PROGMEM = "+SAPBR:";
const char at17rsp2[] PROGMEM = ",1,\"";
const char at18cmdHTTPINIT[] PROGMEM = "AT+HTTPINIT\r\n";
const char at19cmdHTTPCID[] PROGMEM = "AT+HTTPPARA=\"CID\",1\r\n";
const char at20cmdHTTPURL[] PROGMEM = "AT+HTTPPARA=\"URL\",\"arduino.ru\"\r\n";
const char at21cmdHTTPREAD[] PROGMEM = "AT+HTTPREAD\r\n";
const char at22cmdHTTPTERM[] PROGMEM = "AT+HTTPTERM\r\n";
const char at23cmdCSCLK1[] PROGMEM = "AT+CSCLK=1\r\n"; // =1 if use DTR pin modem
const char at24cmdGETOPS[] PROGMEM = "AT+COPS?\r\n"; // get operator
const char at25cmdCSQ[] PROGMEM = "AT+CSQ\r\n"; // get net
const char at26cmdCMGS[] PROGMEM = "AT+CMGS="; // begin send sms
const char at26rsp1[] PROGMEM = ">"; // begin send sms
const char at27cmdCMGS[] PROGMEM = "none"; // text sms
const char at27rsp1[] PROGMEM = "+CMGS:"; // text sms
const char at28cmdBALMEG[] PROGMEM = "AT+CUSD=1,\"*100#\"\r\n"; // get balance megafon
const char at28rsp1[] PROGMEM = "+CUSD:";
const char at28rsp2[] PROGMEM = ", 72\r\n";
// init new gprs packet
const char at29cmdCGATT[] PROGMEM = "AT+CGATT?\r\n";
const char at29rsp1[] PROGMEM = "+CGATT: 1\r\n";
const char at30cmdCIPMODE[] PROGMEM = "AT+CIPMODE=0\r\n";
const char at31cmdCIPMUX[] PROGMEM = "AT+CIPMUX=0\r\n";
// set context and open connect
const char at32cmdCIPSTATUS[] PROGMEM = "AT+CIPSTATUS\r\n";
const char at32rsp1[] PROGMEM = "IP INITIAL\r\n";
const char at33cmdCSTT[] PROGMEM = "AT+CSTT=\"internet\"\r\n";
const char at32rsp2[] PROGMEM = "IP START\r\n"; /*34*/
const char at35cmdCIICR[] PROGMEM = "AT+CIICR\r\n";
const char at32rsp3[] PROGMEM = "IP GPRSACT\r\n"; /*36*/
const char at37cmdCIFSR[] PROGMEM = "AT+CIFSR\r\n";
const char at32rsp4[] PROGMEM = "IP STATUS\r\n"; /*38*/
const char at39cmdCIPSTART[] PROGMEM = "AT+CIPSTART=\"TCP\",\"m23.cloudmqtt.com\",15069\r\n";
const char at39rsp1[] PROGMEM = "CONNECT OK\r\n";
const char at32rsp5[] PROGMEM = "STATE: CONNECT OK\r\n"; /*40*/
// send data to server
const char at41cmdCIPQSEND[] PROGMEM = "AT+CIPQSEND=1\r\n";
const char at42cmdCIPSEND[] PROGMEM = "AT+CIPSEND=";
const char at42rsp1[] PROGMEM = ">";
const char at43cmdNull[] PROGMEM = "\r\n";
const char at43rsp1[] PROGMEM = "DATA ACCEPT:";
const char at43rsp2[] PROGMEM = "CLOSED\r\n";
const char at44cmdCIPQSEND0[] PROGMEM = "AT+CIPQSEND=0\r\n";
const char at45cmdCIPCLOSE[] PROGMEM = "AT+CIPCLOSE\r\n";
const char at45rsp1[] PROGMEM = "CLOSE OK\r\n";
const char at46cmdCIPSHUT[] PROGMEM = "AT+CIPSHUT\r\n";
const char at46rsp1[] PROGMEM = "SHUT OK\r\n";

// typical response
const char rspOK[] PROGMEM = "OK\r\n";
const char rspEndLine[] PROGMEM = "\r\n";

const char * const at_list_cmd[] PROGMEM = { // text command
  at0cmdAT, at1cmdHTTPACTION, at2cmdSAPBR11, at3cmdREADSMS, at4cmdDDET,
  at5cmdATE0, at6cmdCLIP1, at7cmdATS0, at8cmdATV1, at9cmdATCMEE2,
  at10cmdATCMGF1, at11cmdATCREG, at12cmdDELSMS, at13cmdSAPBR311,
  at14cmdSAPBR312, at15cmdSAPBR313, at16cmdSAPBR314, at17cmdSAPBR21,
  at18cmdHTTPINIT, at19cmdHTTPCID, at20cmdHTTPURL, at21cmdHTTPREAD, at22cmdHTTPTERM,
  at23cmdCSCLK1, at24cmdGETOPS, at25cmdCSQ, at26cmdCMGS, at27cmdCMGS,
  at28cmdBALMEG,
  at29cmdCGATT, at30cmdCIPMODE, at31cmdCIPMUX,
  at32cmdCIPSTATUS, at33cmdCSTT, at32cmdCIPSTATUS /*34*/, at35cmdCIICR, at32cmdCIPSTATUS /*36*/, at37cmdCIFSR, at32cmdCIPSTATUS /*38*/, at39cmdCIPSTART, at32cmdCIPSTATUS /*40*/,
  at41cmdCIPQSEND, at42cmdCIPSEND, at43cmdNull, at44cmdCIPQSEND0, at45cmdCIPCLOSE, at46cmdCIPSHUT
};

const PROGMEM  uint8_t at_rresp_cmd[] = { // 0-count right response
  1, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
  2, 1, 1,
  2, 1, 2, 1, 2, 1, 2, 2, 2,
  1, 2, 2, 1, 1, 1
};

const PROGMEM  uint8_t at_oresp_cmd[] = { // 1-count other response - need manual action by response
  0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0
};

const PROGMEM  uint8_t at_move_cmd[] = { // step after action cmd
  4, 21, 17, 12, 5, 6, 7, 8, 9, 10, 11, 13, 101, 14, 15, 16, 23, 18, 19, 20, 1, 22, 101, 24, 29, 101, 27, 101, 101,
  30, 31, 101,
  33, 34, 35, 36, 37, 38, 39, 40, 41,
  42, 43, 101, 101, 46, 44
};

const char * const at_list_rresp[] PROGMEM = {
  rspOK, // at0
  rspOK, at1rsp1, at1rsp2, rspEndLine, // at1
  rspOK, // at3
  rspOK, // at4
  rspOK, // at5
  rspOK, // at6
  rspOK, // at7
  rspOK, // at8
  rspOK, // at9
  rspOK, // at10
  at11rsp1, at11rsp2, rspOK, // at11
  rspOK, // at12
  rspOK, // at13
  rspOK, // at14
  rspOK, // at15
  rspOK, // at16
  at17rsp1, at17rsp2, rspOK, // at17
  rspOK, // at18
  rspOK, // at19
  rspOK, // at20
  rspOK, // at21
  rspOK, // at22
  rspOK, // at23
  rspOK, // at24
  rspOK, // at25
  at26rsp1, // at26
  at27rsp1, rspOK, // at27
  rspOK, at28rsp1, at28rsp2, // at28
  at29rsp1, rspOK, // at29
  rspOK, // at30
  rspOK, // at31
  rspOK, at32rsp1, // at32
  rspOK, // at33
  rspOK, at32rsp2, // at34
  rspOK, // at35
  rspOK, at32rsp3, // at36
  rspEndLine, // at37
  rspOK, at32rsp4, // at38
  rspOK, at39rsp1, // at39
  rspOK, at32rsp5, // at40
  rspOK, // at41
  rspEndLine, at42rsp1, // at42
  at43rsp1, rspEndLine, // at43
  rspOK, // at44
  at45rsp1, // at45
  at46rsp1 // at46
};

const char * const at_list_oresp[] PROGMEM = {
  rspOK, at2rsp1 // at2
};

void s800getTextCmdByNum(byte numCmd, char* textCmd);
byte s800getCountRrespCmdByNum(byte numCmd);
byte s800getCountOrespCmdByNum(byte numCmd);
void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd);
byte s800getNextStepCmdByNum(byte numCmd);

#define GSM_RX 3 // пин RX на модуле подключаем к указаному пину на Ардуино TX
#define GSM_TX 2 // пин TX на модуле подключаем к указаному пину на Ардуино RX

#define WORK_LEVEL_LED 0      // 1 if HIGH level ON led, else 0

#define reset_sim800_pin 4 // pin for reset modem
#define dtr_sim800_pin 10 // pin DTR for sleep mode

#define ledRed_pin 7 // pin RED led
#define ledGre_pin 8 // pin GREEN led

#if (WORK_LEVEL_LED == 0)
#define LEDREDON digitalWrite(ledRed_pin,LOW)
#define LEDGREON digitalWrite(ledGre_pin,LOW)
#define LEDREDOFF digitalWrite(ledRed_pin,HIGH)
#define LEDGREOFF digitalWrite(ledGre_pin,HIGH)
#else
#define LEDREDON digitalWrite(ledRed_pin,HIGH)
#define LEDGREON digitalWrite(ledGre_pin,HIGH)
#define LEDREDOFF digitalWrite(ledRed_pin,LOW)
#define LEDGREOFF digitalWrite(ledGre_pin,LOW)
#endif

char* LastPos(char *str1, char *str2);
int strPos(char *str11, char *str22);


//--s800str.cpp--
#include "Arduino.h"
#include "s800str.h"

void s800getTextCmdByNum(byte numCmd, char* textCmd) {
  const char * addrStroki = pgm_read_word_near((int)(at_list_cmd + numCmd));
  strcpy_P(textCmd, addrStroki);
}

byte s800getCountRrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_rresp_cmd + numCmd);
}

byte s800getCountOrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_oresp_cmd + numCmd);
}

byte s800getNextStepCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_move_cmd + numCmd);
}

void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd) {
  byte startPos = 0;
  if (numCmd > 0) for (byte i = 1; i <= numCmd; ++i) {
      switch (typeResp) {
        case 0: {
            startPos += pgm_read_byte_near(at_rresp_cmd + i - 1);
            break;
          }
        case 1: {
            startPos += pgm_read_byte_near(at_oresp_cmd + i - 1);
            break;
          }
        default : {}
      }
    }
  switch (typeResp) {
    case 0: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_rresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    case 1: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_oresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    default : {}
  }
}

char* LastPos(char *str1, char *str2) { // find substring in string
  int L1 = strlen(str1);
  int L2 = strlen(str2);
  for (int i = L1 - L2; i >= 0; i--)
  {
    int j = 0;
    for (; j < L2; j++)
      if ((str1[i + j] != str2[j]))
        break;
    if (j == L2)
      return str1 + i;
  }
  return 0;
}

int strPos(char *str11, char *str22) { // find position in string(1) substring(2)
  char*p = LastPos(str11, str22);
  int n = p - str11;
  return n;
}

 

vlad072
Offline
Зарегистрирован: 01.08.2017

Вобщем опять работает, отвечает как положено 0xD0 0x00. От чего завист и какого чёрта надо серверу - закономерности без бутылки не нашёл. Просто раз несколько переконнектился и заработало.

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

.

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

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

ЗЫ. Вот поэтому у нас и ракеты падают и заказчики скетч не могут запустить и т.д. - потому что разработчик сказал "и так сойдёт, ведь законнектилось в итоге" (

vlad072
Offline
Зарегистрирован: 01.08.2017

А причём здесь вообще cipshut ?? Сервер соединение рвёт при отправке пинга. Вы вообще здесь, в теме?

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

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

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

код для этого примера

http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-411540

#include <avr/wdt.h>
#include <avr\pgmspace.h>
#include "s800str.h"

#define USE_UART_LOG 1 // 1 if use HW Serial as Log

#include <SoftwareSerial.h>
SoftwareSerial gsm(GSM_TX, GSM_RX); // установка контактовGSM_TX->RX и GSM_RX->TX для программного порта

byte modem_step = 100; // current work mode mode in table of command
// static steps:
// 100 - delay 15 sec for registration modem in net
// 101 - not wait response, wait incomming call or other commands
// 102 - show info on display by press key and/or sleep modem
unsigned long current_millis; // main timer
#define period_fixed_wait 10000UL // max time wait response
unsigned long timer_reg_modem = 0; // timer registration modem in net and timer response
char resp_buf[maxSizeResponse]; // response buf from modem
byte pos_buf = 0; // current pos response buf
#define max_resp_count_on_one_type_cmd 5 // max 5 response text by one command and one type
byte fl_true_Rresp[max_resp_count_on_one_type_cmd];
char text_Rresp[max_resp_count_on_one_type_cmd][maxSizeResponse];
byte fl_true_Oresp[max_resp_count_on_one_type_cmd];
char text_Oresp[max_resp_count_on_one_type_cmd][maxSizeResponse];
byte startFlag = 1;
byte rresp, oresp;
byte ussdStep = 0;
#define max_size_operator_name 10
char operator_name[max_size_operator_name];

char mqtt_user[] = "*******"; // Логи от сервер
char mqtt_pass[] = "***********"; // Пароль от сервера
char mqtt_device[] = "AT41";
char mqtt_topic_gps_longitude[] = "/gps_l"; // долгота
char mqtt_topic_gps_breadth[] = "/gps_b"; // широта
char mqtt_topic_key[] = "/key";
char mqtt_topic_vin[] = "/vin";
char mqtt_topic_temp[] = "/temp";
char mqtt_topic_uptime[] = "/uptime";
#define max_size_gps_string 0x20
char data_gps_longitude[max_size_gps_string]; // долгота
char data_gps_breadth[max_size_gps_string]; // широта
char find_str1[max_size_gps_string];
char find_str2[max_size_gps_string];
byte found_key1_status;
byte mqtt_mode = 0;

#define period_send_gps_data 60000UL // minimum 10sec = 10000UL for slow mqtt server
unsigned long timer_send_gps_data = 0;
byte time_live_connect_packet = period_send_gps_data / 1000;

unsigned long timer_uptime = 0;

word modemVin = 999;
float Vdel = 0.096; // R2/(R1+R2)  0.99кОм / (9.88кОм + 0.99кОм)
#define period_read_vin 61791UL // read vin modem
unsigned long timer_read_vin = 0; // get modem power level

#include <OneWire.h>
#define ds_pin A0 // pin DS18B20
OneWire ds18b20(ds_pin);
#define errTemp 1111  // it is error value
word currTemp = errTemp;
#define period_get_temp 137298UL
unsigned long timer_get_temp = 0;
byte reqTemp = 0;

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((used)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}

void setup() {
  MCUSR = 0;
  wdt_disable();
#if (USE_UART_LOG == 1)
  Serial.begin(115200);
  Serial.println("Power ON or WDT reset");
#endif
  gsm.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  pinMode(dtr_sim800_pin, OUTPUT); digitalWrite(dtr_sim800_pin, LOW); // normal mode modem
  randomSeed(analogRead(A2));
  analogReference(INTERNAL);
  getVinModem();
  pinMode(ledRed_pin, OUTPUT);
  pinMode(ledGre_pin, OUTPUT);
  pinMode(ledBlu_pin, OUTPUT); found_key1_status = 0;
  LEDREDOFF;  LEDGREOFF; LEDBLUOFF;
  operator_name[0] = 0;
  wdt_enable(WDTO_8S);
}

void loop() {
  wdt_reset();
  //delay(9000); // test WDT
  current_millis = millis();
  if (((current_millis - timer_send_gps_data) >= period_send_gps_data) && (modem_step == 101) && (!startFlag)) {
    if (mqtt_mode) {
      modem_step = 44; sendATcmd();
    } else {
      timer_send_gps_data = current_millis;
      strcpy(find_str1, mqtt_topic_key);
      strcat(find_str1, "5");
      strcpy(find_str2, mqtt_topic_key);
      strcat(find_str2, "7");
      // gps data TO text
      data_gps_longitude[0] = random(0, 10) + '0'; data_gps_longitude[1] = 0;
      data_gps_breadth[0] = '9'; data_gps_breadth[1] = random(0, 10) + '0'; data_gps_breadth[2] = 0;
      // send data
      modem_step = 32; sendATcmd();
    }
  }
  if (((current_millis - timer_get_temp) >= period_get_temp) && (modem_step == 101)) {
    if (reqTemp) {
      if ((current_millis - timer_get_temp) >= (period_get_temp + 750UL)) {
        if ((current_millis - timer_get_temp) <= (period_get_temp + 1000UL)) {
          currTemp = getTemp2();
#if (USE_UART_LOG == 1)
          Serial.println(currTemp);
#endif
        }
        timer_get_temp = current_millis;
        reqTemp = 0;
      }
    } else {
      getTemp1();
      reqTemp = 1;
    }
  }
  if (((current_millis - timer_read_vin) >= period_read_vin) && (modem_step == 101)) {
    timer_read_vin = current_millis;
    getVinModem();
#if (USE_UART_LOG == 1)
    Serial.println(modemVin);
#endif
  }
  if (modem_step == 100) {
    LEDGREOFF;
    if ((current_millis - timer_reg_modem) >= 15000UL) { // wait 15 sec registration modem
      modem_step = 0; sendATcmd();
    }
  } else if (modem_step == 101) {
    LEDGREOFF;
    if (startFlag) {
      LEDREDOFF;
      startFlag = 0;
#if (USE_UART_LOG == 1)
      Serial.println("Ready");
#endif
      digitalWrite(LED_BUILTIN, HIGH);
    }
    // nothing do
    loadDataFromModem();
  } else if (modem_step < 100) {
    LEDGREON;
    if ((rresp == 0) && (oresp == 0)) { // go to next cmd
      modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd();
    } else {
      if ((current_millis - timer_reg_modem) >= period_fixed_wait) {
        if (rresp > 0) {
          resetModem();
        } else if (oresp > 0) { // go to next cmd
#if (USE_UART_LOG == 1)
          Serial.println("No response!");
#endif
          if (modem_step == 43) {
            timer_send_gps_data = 0;
            mqtt_mode = 0; modem_step = 44; sendATcmd();
          } else {
            modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd();
          }
        }
      } else {
        // main work
        loadDataFromModem();
      }
    }
  }
}

byte doCmdForModem(byte inByte) {
  // processing/find key packets
  if (findRespFromBuf(find_str1)) {
    if (!found_key1_status) {
#if (USE_UART_LOG == 1)
      Serial.println("Key ON");
#endif
      LEDBLUON;
      found_key1_status = 1;
    }
  } else if (findRespFromBuf(find_str2)) {
    if (found_key1_status) {
#if (USE_UART_LOG == 1)
      Serial.println("Key OFF");
#endif
      LEDBLUOFF;
      found_key1_status = 0;
    }
  }
  // --
  byte flGood, flResp;
  if (modem_step < 100) {
    if (rresp > 0) {
      flGood = 0;
      flResp = 0;
      for (byte i = 0; i < rresp; ++i) {
        if (fl_true_Rresp[i] == 0) {
          if (findRespFromBuf(text_Rresp[i])) {
            fl_true_Rresp[i] = 1;
            if ((rresp == 1) || (i == (rresp - 1))) flGood = 1;
            flResp = 1;
          }
          break;
        }
      }
      if (flGood) {
        // manual processing response for good cmd
        switch (modem_step) {
          case 43: {
              mqtt_mode = 1;
              break;
            }
          case 44: {
              mqtt_mode = 0;
              break;
            }
          default: {}
        }
        // go to next cmd
        modem_step = s800getNextStepCmdByNum(modem_step);
        if (modem_step < 100) sendATcmd(); return 1;
      }
      if (flResp) {
        clearRespBuf(); return 1;
      }
    }
    // manual processing response
    switch (modem_step) {
      case 43: { // send data
          // find end TX
          if (findRespFromBuf("SEND OK\r\n")) {
            mqtt_mode = 1;
            // go to next cmd
            modem_step = s800getNextStepCmdByNum(modem_step);
            if (modem_step < 100) sendATcmd(); return 1;
          }
          break;
        }
      case 24: { // operator name
          if (inByte == '+') {
            ussdStep = 1; operator_name[0] = 0;
          } else if ((ussdStep == 1) && (inByte == '"')) {
            ussdStep = 2;
          } else if (ussdStep == 2) {
            if (inByte == '"') {
              ussdStep = 3;
            } else {
              byte sl = strlen(operator_name);
              if (sl < (max_size_operator_name - 1)) {
                operator_name[sl] = inByte;
                operator_name[sl + 1] = 0;
              }
            }
          }
          break;
        }
      default: {}
    }
  } else { // mode 101
    // find ring or other cmd
  }
  return 0;
}

byte findRespFromBuf(char* textResp) {
  if (resp_buf[pos_buf] > 0) {
    byte idxBuf;
    if (pos_buf == 0) idxBuf = maxSizeResponse - 1; else idxBuf = pos_buf - 1;
    byte lenResp = strlen(textResp);
    byte idxResp = lenResp - 1;
    byte cntResp = 0;
    for (byte i = 0; i < maxSizeResponse; ++i) {
      if (resp_buf[idxBuf] == 0) break;
      if (resp_buf[idxBuf] == textResp[idxResp]) {
        --idxResp;
        if ((++cntResp) == lenResp) return 1;
      } else {
        cntResp = 0; idxResp = lenResp - 1;
      }
      if ((--idxBuf) == 0) idxBuf = maxSizeResponse - 1;
    }
  } else if (pos_buf > 0) {
    if (strPos(resp_buf, textResp) >= 0) {
      return 1;
    }
  }
  return 0;
}

void sendATcmd() {
  char cmdAT[maxSizeATcommand];
  s800getTextCmdByNum(modem_step, cmdAT);
  switch (modem_step) { // manual processing AT cmd
    case 42: {
        gsm.print(cmdAT);
#if (USE_UART_LOG == 1)
        Serial.print(cmdAT);
#endif
        byte fullSize = sendConnectPacket(1);
        fullSize += sendGPSlData(1);
        fullSize += sendGPSbData(1);
        fullSize += sendSubscribeKey(1);
        fullSize += sendPubTemp(1);
        fullSize += sendPubVin(1);
        fullSize += sendPubUptime(1);
        //fullSize += 2; // + disconnect packet
        gsm.print(fullSize, DEC); gsm.print("\r\n");
#if (USE_UART_LOG == 1)
        Serial.println(fullSize, DEC);
#endif
        break;
      }
    case 43: {
        sendConnectPacket(0);
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        sendSubscribeKey(0);
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        sendGPSlData(0);
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        sendGPSbData(0);
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        sendPubTemp(0);
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        sendPubVin(0);
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        sendPubUptime(0);
#if (USE_UART_LOG == 1)
        Serial.println("");
#endif
        /*sendDisConnectPacket();
          #if (USE_UART_LOG == 1)
          Serial.println("");
          #endif*/
        break;
      }
    default: {
        gsm.print(cmdAT);
#if (USE_UART_LOG == 1)
        Serial.print(cmdAT);
#endif
      }
  }
  timer_reg_modem = current_millis;
  rresp = s800getCountRrespCmdByNum(modem_step);
  oresp = s800getCountOrespCmdByNum(modem_step);
  for (byte i = 0; i < max_resp_count_on_one_type_cmd; ++i) {
    fl_true_Rresp[i] = 0; // max 5 response text by one command and one type
    fl_true_Oresp[i] = 0;
  }
  if (rresp) {
    for (byte i = 0; i < rresp; ++i) {
      s800getRespByNum(0, modem_step, i, text_Rresp[i]);
    }
  }
  if (oresp) {
    for (byte i = 0; i < oresp; ++i) {
      s800getRespByNum(1, modem_step, i, text_Oresp[i]);
    }
  }
  clearRespBuf();
}

void clearRespBuf() {
  memset(resp_buf, 0, maxSizeResponse);
  pos_buf = 0;
}

void loadDataFromModem() {
  if (gsm.available()) {
    while (gsm.available()) {
      byte readByte = gsm.read();
      if (readByte > 0) {
#if (USE_UART_LOG == 1)
        Serial.write(readByte);
        /*if ((readByte < 0x20) || (readByte >= 0x7F)) {
          Serial.print(" 0x"); Serial.print(readByte, HEX); Serial.print(" ");
          } else {
          Serial.write(readByte);
          }*/
#endif
        resp_buf[pos_buf] = readByte;
        ++pos_buf;
        if (pos_buf >= maxSizeResponse) pos_buf = 0;
        wdt_reset();
        if (doCmdForModem(readByte) == 1) break;
      }
    }
  }
}

void resetModem() {
  LEDREDON;
  // reset modem
  pinMode(reset_sim800_pin, OUTPUT);
  digitalWrite(reset_sim800_pin, LOW);
  delay(115);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  // new init modem and start new main loop
  timer_reg_modem = current_millis;
  modem_step = 100;
  startFlag = 1;
  operator_name[0] = 0;
  mqtt_mode = 0;
  timer_send_gps_data = 0;
  timer_uptime = current_millis;
}

byte sendConnectPacket(byte getSize) {
  byte sizeDevice = strlen(mqtt_device); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass);
  byte fullSize = 16 + sizeDevice + sizeUser + sizePass;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)0x04); // Length LSB (4)
  sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name
  sendByteToMQTTclient((byte)0x04); // Protocol Level byte
  sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable
  sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0)
  sendByteToMQTTclient((byte)time_live_connect_packet); // Keep Alive LSB
  // payload
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user
  for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i]));
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass
  for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i]));
}

void sendByteToMQTTclient(byte inByte) {
  gsm.write((byte)(inByte));
#if (USE_UART_LOG == 1)
  if ((inByte < 0x20) || (inByte >= 0x7F)) {
    Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
  } else {
    Serial.write(inByte);
  }
#endif
}

byte sendGPSlData(byte getSize) {
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_gps_longitude); byte sizeData = strlen(data_gps_longitude);
  byte fullSize = 4 + sizeDevice + sizeTopic + sizeData;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_gps_longitude[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(data_gps_longitude[i]));
}

byte sendGPSbData(byte getSize) {
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_gps_breadth); byte sizeData = strlen(data_gps_breadth);
  byte fullSize = 4 + sizeDevice + sizeTopic + sizeData;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_gps_breadth[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(data_gps_breadth[i]));
}

void sendDisConnectPacket() {
  // fixed header
  sendByteToMQTTclient((byte)0xE0); // MQTT Control Packet type 1110 connect, reserved 0000
  sendByteToMQTTclient((byte)0x00); // Remaining Length
}

byte sendSubscribeKey(byte getSize) {
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_key);
  byte fullSize = 5 + sizeDevice + sizeTopic;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x82); // MQTT Control Packet type (8) 0100, reserved 0010
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)(0x0A)); // Packet Identifier LSB (10)
  // payload
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_key[i]));
  sendByteToMQTTclient((byte)0x00); // Requested QoS(1)
}

void getVinModem() {
  float Vbat = (analogRead(power_level_pin) * 1.1) / 1023;
  float Vin = Vbat / Vdel;
  modemVin = Vin * 100;
}

void getTemp1() {
  ds18b20.reset();
  ds18b20.write(0xCC);
  ds18b20.write(0x44);
}

word getTemp2() {
  byte dsData[9];
  ds18b20.reset();
  ds18b20.write(0xCC);
  ds18b20.write(0xBE);
  for (byte i = 0; i < 9; i++) dsData[i] = ds18b20.read();
  if (OneWire::crc8(dsData, 8) != dsData[8]) return errTemp;
  word outTemp = (word)(dsData[1] << 8) + dsData[0];
  if ((word)(outTemp & 0x8000) == (word)(0x8000)) {
    outTemp = (~outTemp) + (word)1;
    outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10;
  } else {
    outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10;
    if (outTemp == 0) return errTemp;
    outTemp  += (word)2000;
  }
  return outTemp;
}

byte sendPubTemp(byte getSize) {
  if (currTemp == errTemp) return 0;
  char textTemp[] = "-100.0"; byte textPos = 0; word absTemp = currTemp;
  if (absTemp >= 2000) {
    absTemp -= 2000;
  } else {
    textTemp[textPos] = '-'; ++textPos;
  }
  if (absTemp >= 1000) {
    textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
  } else if (absTemp >= 100) {
    textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
  } else if (absTemp >= 10) {
    textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
  }
  textTemp[textPos] = '.'; ++textPos; textTemp[textPos] = (absTemp % 10) + '0'; ++textPos; textTemp[textPos] = 0;
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_temp); byte sizeData = strlen(textTemp);
  byte fullSize = 4 + sizeDevice + sizeTopic + sizeData;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_temp[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}

byte sendPubVin(byte getSize) {
  if (currTemp == 999) return 0;
  char textTemp[] = " 9.99"; byte textPos = 0; word absTemp = modemVin;
  textTemp[textPos] = (absTemp / 100) + '0'; ++textPos;
  textTemp[textPos] = '.'; ++textPos;
  textTemp[textPos] = (absTemp % 100) / 10 + '0'; ++textPos;
  textTemp[textPos] = (absTemp % 100) % 10 + '0'; ++textPos;
  textTemp[textPos] = 0;
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_vin); byte sizeData = strlen(textTemp);
  byte fullSize = 4 + sizeDevice + sizeTopic + sizeData;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_vin[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}

byte sendPubUptime(byte getSize) {
  char textTemp[] = " 999"; byte textPos = 0;
  unsigned long absTemp = (current_millis - timer_uptime) / 60000;
  absTemp = constrain(absTemp, 0, 999);
  textTemp[textPos] = (absTemp / 100) + '0'; ++textPos;
  textTemp[textPos] = (absTemp % 100) / 10 + '0'; ++textPos;
  textTemp[textPos] = (absTemp % 100) % 10 + '0'; ++textPos;
  textTemp[textPos] = 0;
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_uptime); byte sizeData = strlen(textTemp);
  byte fullSize = 4 + sizeDevice + sizeTopic + sizeData;
  if (getSize) return (fullSize + 2);
  // fixed header
  sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
  sendByteToMQTTclient((byte)(fullSize)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_uptime[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}


//--s800str.h--
#include <avr\pgmspace.h>

#define maxSizeATcommand 60
#define maxSizeResponse 24

const char at0cmdAT[] PROGMEM = "AT\r\n";
const char at1cmdHTTPACTION[] PROGMEM = "AT+HTTPACTION=0\r\n";
const char at1rsp1[] PROGMEM = "+HTTPACTION:";
const char at1rsp2[] PROGMEM = ",";
const char at2cmdSAPBR11[] PROGMEM = "AT+SAPBR=1,1\r\n";
const char at2rsp1[] PROGMEM = "operation not allowed\r\n";
const char at3cmdREADSMS[] PROGMEM = "AT+CMGL=4\r\n"; // "AT+CMGL=\"ALL\"\r\n";
const char at4cmdDDET[] PROGMEM = "AT+DDET=1\r\n";
const char at5cmdATE0[] PROGMEM = "ATE0\r\n";
const char at6cmdCLIP1[] PROGMEM = "AT+CLIP=1\r\n";
const char at7cmdATS0[] PROGMEM = "ATS0=0\r\n";
const char at8cmdATV1[] PROGMEM = "ATV1\r\n";
const char at9cmdATCMEE2[] PROGMEM = "AT+CMEE=2\r\n";
const char at10cmdATCMGF1[] PROGMEM = "AT+CMGF=0\r\n";
const char at11cmdATCREG[] PROGMEM = "AT+CREG?\r\n";
const char at11rsp1[] PROGMEM = "+CREG:";
const char at11rsp2[] PROGMEM = ",1\r\n";
const char at12cmdDELSMS[] PROGMEM = "AT+CMGDA=6\r\n"; // "AT+CMGDA=\"DEL ALL\"\r\n";
const char at13cmdSAPBR311[] PROGMEM = "AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n";
const char at14cmdSAPBR312[] PROGMEM = "AT+SAPBR=3,1,\"APN\",\"internet\"\r\n";
const char at15cmdSAPBR313[] PROGMEM = "AT+SAPBR=3,1,\"USER\",\"\"\r\n";
const char at16cmdSAPBR314[] PROGMEM = "AT+SAPBR=3,1,\"PWD\",\"\"\r\n";
const char at17cmdSAPBR21[] PROGMEM = "AT+SAPBR=2,1\r\n";
const char at17rsp1[] PROGMEM = "+SAPBR:";
const char at17rsp2[] PROGMEM = ",1,\"";
const char at18cmdHTTPINIT[] PROGMEM = "AT+HTTPINIT\r\n";
const char at19cmdHTTPCID[] PROGMEM = "AT+HTTPPARA=\"CID\",1\r\n";
const char at20cmdHTTPURL[] PROGMEM = "AT+HTTPPARA=\"URL\",\"arduino.ru\"\r\n";
const char at21cmdHTTPREAD[] PROGMEM = "AT+HTTPREAD\r\n";
const char at22cmdHTTPTERM[] PROGMEM = "AT+HTTPTERM\r\n";
const char at23cmdCSCLK1[] PROGMEM = "AT+CSCLK=1\r\n"; // =1 if use DTR pin modem
const char at24cmdGETOPS[] PROGMEM = "AT+COPS?\r\n"; // get operator
const char at24rsp1[] PROGMEM = "+COPS:";
const char at24rsp2[] PROGMEM = "\"\r\n";
const char at25cmdCSQ[] PROGMEM = "AT+CSQ\r\n"; // get net
const char at26cmdCMGS[] PROGMEM = "AT+CMGS="; // begin send sms
const char at26rsp1[] PROGMEM = ">"; // begin send sms
const char at27cmdCMGS[] PROGMEM = "none"; // text sms
const char at27rsp1[] PROGMEM = "+CMGS:"; // text sms
const char at28cmdBALMEG[] PROGMEM = "AT+CUSD=1,\"*100#\"\r\n"; // get balance megafon
const char at28rsp1[] PROGMEM = "+CUSD:";
const char at28rsp2[] PROGMEM = ", 72\r\n";
// init new gprs packet
const char at29cmdCGATT[] PROGMEM = "AT+CGATT?\r\n";
const char at29rsp1[] PROGMEM = "+CGATT: 1\r\n";
const char at30cmdCIPMODE[] PROGMEM = "AT+CIPMODE=0\r\n";
const char at31cmdCIPMUX[] PROGMEM = "AT+CIPMUX=0\r\n";
// set context and open connect
const char at32cmdCIPSTATUS[] PROGMEM = "AT+CIPSTATUS\r\n";
const char at32rsp1[] PROGMEM = "IP INITIAL\r\n";
const char at33cmdCSTT[] PROGMEM = "AT+CSTT=\"internet\"\r\n";
const char at32rsp2[] PROGMEM = "IP START\r\n"; /*34*/
const char at35cmdCIICR[] PROGMEM = "AT+CIICR\r\n";
const char at32rsp3[] PROGMEM = "IP GPRSACT\r\n"; /*36*/
const char at37cmdCIFSR[] PROGMEM = "AT+CIFSR\r\n";
const char at32rsp4[] PROGMEM = "IP STATUS\r\n"; /*38*/
const char at39cmdCIPSTART[] PROGMEM = "AT+CIPSTART=\"TCP\",\"m23.cloudmqtt.com\",15069\r\n";
const char at39rsp1[] PROGMEM = "CONNECT OK\r\n";
const char at32rsp5[] PROGMEM = "STATE: CONNECT OK\r\n"; /*40*/
// send data to server
const char at41cmdCIPQSEND[] PROGMEM = "AT+CIPQSEND=0\r\n";
const char at42cmdCIPSEND[] PROGMEM = "AT+CIPSEND=";
const char at42rsp1[] PROGMEM = ">";
const char at43cmdNull[] PROGMEM = "\r\n";
const char at43rsp1[] PROGMEM = "SEND OK\r\n"; /*"SEND OK\r\n"*/
const char at44cmdCIPSHUT[] PROGMEM = "AT+CIPSHUT\r\n";
const char at44rsp1[] PROGMEM = "SHUT OK\r\n";
// set option get data
const char at45cmdCIPHEAD[] PROGMEM = "AT+CIPHEAD=0\r\n";
const char at46cmdCIPSRIP[] PROGMEM = "AT+CIPSRIP=0\r\n";

// typical response
const char rspOK[] PROGMEM = "OK\r\n";
const char rspEndLine[] PROGMEM = "\r\n";

const char * const at_list_cmd[] PROGMEM = { // text command
  at0cmdAT, at1cmdHTTPACTION, at2cmdSAPBR11, at3cmdREADSMS, at4cmdDDET,
  at5cmdATE0, at6cmdCLIP1, at7cmdATS0, at8cmdATV1, at9cmdATCMEE2,
  at10cmdATCMGF1, at11cmdATCREG, at12cmdDELSMS, at13cmdSAPBR311,
  at14cmdSAPBR312, at15cmdSAPBR313, at16cmdSAPBR314, at17cmdSAPBR21,
  at18cmdHTTPINIT, at19cmdHTTPCID, at20cmdHTTPURL, at21cmdHTTPREAD, at22cmdHTTPTERM,
  at23cmdCSCLK1, at24cmdGETOPS, at25cmdCSQ, at26cmdCMGS, at27cmdCMGS,
  at28cmdBALMEG,
  at29cmdCGATT, at30cmdCIPMODE, at31cmdCIPMUX,
  at32cmdCIPSTATUS, at33cmdCSTT, at32cmdCIPSTATUS /*34*/, at35cmdCIICR, at32cmdCIPSTATUS /*36*/, at37cmdCIFSR, at32cmdCIPSTATUS /*38*/, at39cmdCIPSTART, at32cmdCIPSTATUS /*40*/,
  at41cmdCIPQSEND, at42cmdCIPSEND, at43cmdNull, at44cmdCIPSHUT,
  at45cmdCIPHEAD, at46cmdCIPSRIP
};

const PROGMEM  uint8_t at_rresp_cmd[] = { // 0-count right response
  1, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3 /*24*/, 1, 1, 2, 3,
  2, 1, 1,
  2, 1, 2, 1, 2, 1, 2, 2, 2,
  1, 2, 0, 1,
  1, 1
};

const PROGMEM  uint8_t at_oresp_cmd[] = { // 1-count other response - need manual action by response
  0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 1, 0,
  0, 0
};

const PROGMEM  uint8_t at_move_cmd[] = { // step after action cmd
  4, 21, 17, 12, 5, 6, 7, 8, 9, 10, 11, 13, 101, 14, 15, 16, 23, 18, 19, 20, 1, 22, 101, 24 /* ? 24 */, 29, 101, 27, 101, 101,
  30, 31, 45,
  33, 34, 35, 36, 37, 38, 39, 40, 41,
  42, 43, 101, 101,
  46, 101
};

const char * const at_list_rresp[] PROGMEM = {
  rspOK, // at0
  rspOK, at1rsp1, at1rsp2, rspEndLine, // at1
  rspOK, // at3
  rspOK, // at4
  rspOK, // at5
  rspOK, // at6
  rspOK, // at7
  rspOK, // at8
  rspOK, // at9
  rspOK, // at10
  at11rsp1, at11rsp2, rspOK, // at11
  rspOK, // at12
  rspOK, // at13
  rspOK, // at14
  rspOK, // at15
  rspOK, // at16
  at17rsp1, at17rsp2, rspOK, // at17
  rspOK, // at18
  rspOK, // at19
  rspOK, // at20
  rspOK, // at21
  rspOK, // at22
  rspOK, // at23
  at24rsp1, at24rsp2, rspOK, // at24 ?
  rspOK, // at25
  at26rsp1, // at26
  at27rsp1, rspOK, // at27
  rspOK, at28rsp1, at28rsp2, // at28
  at29rsp1, rspOK, // at29
  rspOK, // at30
  rspOK, // at31
  rspOK, at32rsp1, // at32
  rspOK, // at33
  rspOK, at32rsp2, // at34
  rspOK, // at35
  rspOK, at32rsp3, // at36
  rspEndLine, // at37
  rspOK, at32rsp4, // at38
  rspOK, at39rsp1, // at39
  rspOK, at32rsp5, // at40
  rspOK, // at41
  rspEndLine, at42rsp1, // at42
  at44rsp1, // at44
  rspOK, // at45
  rspOK // at46
};

const char * const at_list_oresp[] PROGMEM = {
  rspOK, at2rsp1, // at2
  at43rsp1 // at43
};

void s800getTextCmdByNum(byte numCmd, char* textCmd);
byte s800getCountRrespCmdByNum(byte numCmd);
byte s800getCountOrespCmdByNum(byte numCmd);
void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd);
byte s800getNextStepCmdByNum(byte numCmd);

#define GSM_RX 3 // пин RX на модуле подключаем к указаному пину на Ардуино TX
#define GSM_TX 2 // пин TX на модуле подключаем к указаному пину на Ардуино RX

#define WORK_LEVEL_LED 0      // 1 if HIGH level ON led, else 0

#define reset_sim800_pin 4 // pin for reset modem
#define dtr_sim800_pin 10 // pin DTR for sleep mode

#define power_level_pin A6 // input power level for control

#define ledRed_pin 7 // pin RED led
#define ledGre_pin 8 // pin GREEN led
#define ledBlu_pin 9 // pin BLUE led

#if (WORK_LEVEL_LED == 0)
#define LEDREDON digitalWrite(ledRed_pin,LOW)
#define LEDGREON digitalWrite(ledGre_pin,LOW)
#define LEDBLUON digitalWrite(ledBlu_pin,LOW)
#define LEDREDOFF digitalWrite(ledRed_pin,HIGH)
#define LEDGREOFF digitalWrite(ledGre_pin,HIGH)
#define LEDBLUOFF digitalWrite(ledBlu_pin,HIGH)
#else
#define LEDREDON digitalWrite(ledRed_pin,HIGH)
#define LEDGREON digitalWrite(ledGre_pin,HIGH)
#define LEDBLUON digitalWrite(ledBlu_pin,HIGH)
#define LEDREDOFF digitalWrite(ledRed_pin,LOW)
#define LEDGREOFF digitalWrite(ledGre_pin,LOW)
#define LEDBLUOFF digitalWrite(ledBlu_pin,LOW)
#endif

char* LastPos(char *str1, char *str2);
int strPos(char *str11, char *str22);


//--s800str.cpp--
#include "Arduino.h"
#include "s800str.h"

void s800getTextCmdByNum(byte numCmd, char* textCmd) {
  const char * addrStroki = pgm_read_word_near((int)(at_list_cmd + numCmd));
  strcpy_P(textCmd, addrStroki);
}

byte s800getCountRrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_rresp_cmd + numCmd);
}

byte s800getCountOrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_oresp_cmd + numCmd);
}

byte s800getNextStepCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_move_cmd + numCmd);
}

void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd) {
  byte startPos = 0;
  if (numCmd > 0) for (byte i = 1; i <= numCmd; ++i) {
      switch (typeResp) {
        case 0: {
            startPos += pgm_read_byte_near(at_rresp_cmd + i - 1);
            break;
          }
        case 1: {
            startPos += pgm_read_byte_near(at_oresp_cmd + i - 1);
            break;
          }
        default : {}
      }
    }
  switch (typeResp) {
    case 0: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_rresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    case 1: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_oresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    default : {}
  }
}

char* LastPos(char *str1, char *str2) { // find substring in string
  int L1 = strlen(str1);
  int L2 = strlen(str2);
  for (int i = L1 - L2; i >= 0; i--)
  {
    int j = 0;
    for (; j < L2; j++)
      if ((str1[i + j] != str2[j]))
        break;
    if (j == L2)
      return str1 + i;
  }
  return 0;
}

int strPos(char *str11, char *str22) { // find position in string(1) substring(2)
  char*p = LastPos(str11, str22);
  int n = p - str11;
  return n;
}


Скетч использует 12290 байт (40%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 985 байт (48%) динамической памяти, оставляя 1063 байт для локальных переменных. Максимум: 2048 байт.

 

alexbmd
Offline
Зарегистрирован: 15.01.2016

Andycat, а зачем сохраняем в mcusr_mirror , если потом не используем? Или я проглядел?

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

alexbmd пишет:
Andycat, а зачем сохраняем в mcusr_mirror , если потом не используем? Или я проглядел?

Это кусок кода для работоспособности wdt на arduino nano

alexbmd
Offline
Зарегистрирован: 15.01.2016

Я понял что это не mqtt. Но это же переменная не используется потом вроде?

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

alexbmd пишет:
Но это же переменная не используется потом вроде?

На форуме была целая тема по поводу этого кода и он вроде из Даташита, и если я правильно помню, концы смотреть в #include <avr/wdt.h>

Щас гуру подтянутся - разьяснят.

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017
закончил небольшой проект, работа SIM800L + MQTT подключение к двум брокерам через два сокета, список команд модема ниже, вдруг кому пригодится.
 
- инициализация
AT
OK
AT+CIPSHUT
SHUT OK
AT+DDET=0
OK
ATE0
OK
AT+CLIP=0
OK
ATS0=0
OK
ATV1
OK
AT+CMEE=2
OK
AT+CMGF=1
OK
AT+CSCLK=0
OK
AT+CIPMODE=0
OK
AT+CIPMUX=1
OK
AT+CIPHEAD=0
OK
AT+CIPSRIP=0
OK
AT+CSTT="internet"
OK
AT+CIICR
OK
AT+CIPSTATUS
OK

STATE: IP GPRSACT
AT+CIFSR
t▒b▒IRU*R▒('LK▒▒,",▒9%J▒▒
                         C: 2,,"","","","INITIAL"
C: 3,,"","","","INITIAL"
C: 4,,"","","","INITIAL"
C: 5,,"","","","INITIAL"

100.70.64.195

OK

STATE: IP STATUS
Ready

 

- подключение к брокерам CIPSTART=X, закрытие сокета для его потом повторного подключения CIPCLOSE=X, или переподключение между брокерами для работы в попеременном режиме
AT+CIPSTART=0,"TCP","m23.cloudmqtt.com",15069
C: 0,,"","","""INTIA"
C 1,"",","""INTIAL
C 2,"",","""INTIL"

OK

0, CONNECT OK
AT+CIPSEND=0
> 0x10 8 0x0  0x4 MQTT 0x4  0xC0  0x0  0xF0  0x0  0x14 12345678901234567890 0x0  0x8 fag******xbt 0x0  0xC ba*****YaX
0, SEND OK

+RECEIVE,0,4:
  0x2  0x1 AT+CIPSEND=0
> 0x82 " 0x0  0xA  0x0  0x1D watering/12345678901234567890 0x1 0/ 0x0  0xB log/connect 0x0  0x0 12345678901234567890 - connected
0, SEND OK

+RECEIVE,0,5:
 0x90  0x3
            0x1 

 

- идет постоянный обмен с брокером PINGREQ, в случае не ответа PINGRESP через некоторое время - меняем брокер
AT+CIPSEND=0
> 0xC0  0x0
0, SEND OK

+RECEIVE,0,2:
 0xD0 

 

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

Последовательность команд SIM800L работы с MQTT брокером, устройство работает 24/7, в случае проблем переподключается между серверами.

// начало работы
Start!
// начало модуля первоначальной настройкой модема
// ждем ответ на команды в течении 5 секунд, в случае отсутствия - перезагрузка модема
ATZ // сбросим настройки модема в default
OK
ATE0 // отключение ЭХО, т е модем в обратку не дублирует команды
OK
ATV1 // развернуты подробный ответ от модема
OK
AT+CMEE=2 // вывод подробных описаний ошибок
OK
AT+CIPSHUT // закрыть все интернет сессии
SHUT OK // этот ответ лучше ждать подольше, до 10 секунд
AT+CLIP=0 // отключение АОН
OK
ATS0=0 // модем не берет трубку при входящем звонке
OK
AT+CMGF=1 // обычный режим вывода SMS
OK
AT+CSCLK=0 // отключение работы энергосберегающего режима через пин DTR
OK
AT+CIPHEAD=0 // не добавлять заголовок при приеме данных
OK
AT+CIPRXGET=0 // автоматический вывод принятых данных
OK
AT+CIPSRIP=0 // не показывать данные отправителя при приеме данных
OK
AT+CSPN? // получить имя оператора из SIM карты
+CSPN: "M2M Express",0 // парсим ответ, в зависимости от того, чья карта стоит, будем использовать разные APN

OK
// инициализация основная закончилась
// переходим в режим регистрации модема у оператора
AT+CREG? // каждые 5 секунд запрашиваем статус
+CREG: 0,2

OK

SMS Ready

// ответ ждем в течении 2х минут, если за это время не зарегестрировались - перезагрузка модема

AT+CREG?
+CREG: 0,3

OK
AT+CREG?
+CREG: 0,3

OK
AT+CREG?
+CREG: 0,3

OK
AT+CREG?
+CREG: 0,0

OK
AT+CREG?
+CREG: 0,0

OK
AT+CREG?
+CREG: 0,0

OK
AT+CREG?
+CREG: 0,5 // успешно зарегестрировались

OK
AT+COPS? // запрашиваем имя оператора
+COPS: 1,0,"MegaFon" // парсим ответ - заносим имя оператора в переменную - потом отдадим на сервер для статистики

OK
AT+CSQ? // запрашиваем уровень связи
+CSQ: 12,0 // парсим ответ, потом отдадим серверу для статистики

OK
AT+CIPMODE=0 // командный режим передачи данных
OK
AT+CMGDA="DEL ALL" // удаление всех SMS на SIM карте
OK
// закончилась полная инициализация модема

// начало модуля соединения с mqtt сервером
// ответы на команды, просто отвечающие ОК, без глобальных изменений так же ждем 5 секунд, в случе отсутствия - проблема - перезагружаем модем
AT+CIPSTATUS // запрашиваем статус сессии
OK

STATE: IP INITIAL
AT + CSTT = "internet.emt.ee" // прописываем APN в зависимости от установленной SIM карты
OK
AT+CIPSTATUS // запрашиваем статус
OK

STATE: IP START
AT+CIICR //  активируем контекст, по даташиту команда выполняется до 62 секунд, оптимально 35 секунд ждать ответ
OK
AT+CIPSTATUS // запрашиваем статус
OK

STATE: IP GPRSACT
AT+CIFSR // получаем адрес
0.137.119.101

OK

STATE: IP STATUS
AT+CIPSTART="TCP","m23.cloudmqtt.com",*****  // коннектимся к серверу
OK
AT+CIPSTATUS // запрашиваем статус
OK

STATE: TCP CONNECTING
AT+CIPSTATUS
OK

STATE: TCP CONNECTING

//
// в течении 10 секунд ждем подключения к серверу, иначе или меняем сервер на резервный или опять поднимаем заново интернет сессию
// общее время ожидания к mqtt серверу ждем в течении 2 минут, иначе перезагрузка модема
//

AT+CIPSTATUS
OK

STATE: TCP CONNECTING
AT+CIPSTATUS
OK

STATE: TCP CONNECTING
AT+CIPSTATUS
CONNECT OK

OK

STATE: CONNECT OK // успешное подключение


// начинаем работать с брокером
AT+CIPSEND
>x10 3x0 x4 MQTTx4 xC0 x0 xFD x0 xF Qw37Tu89u78-91px0 x8 ****** xC *******  // connect packet
SEND OK
AT+CIPSEND
>x82 x1C x0 xA x0 x17 smd/Qw37Tu89u78-91p/cmdx1   x2 x1 // подписываемся на нужные топики
SEND OK
AT+CIPSEND
>05x0 xB log/connectx0 x0 Qw37Tu89u78-91p - connected;MegaFon;12 // отправляем на сервер данные о подключении
23
0
 x90 x3
        x1
SEND OK // после каждой отправки ждем данное подтверждение в течении 8 секунд, в случае отсутствия - переподключаемся к серверу
AT+CIPSEND // каждае 240 секунд (время удержания соединения, меньшее, чем указано в connect packet)
>xC0 x0 // шлем PING REQ , потом ждем 14 секунд PING RESP
SEND OK
xD0 /*пришел PING RESP, если не дождались - реконнект к серверу*/ AT+CIPSEND
>xC0 x0
SEND OK
xD0 AT+CIPSTATUS
OK

STATE: CONNECT OK
AT+CIPCLOSE // принудительно разорвали связь или увидели ответ CLOSED
CLOSE OK
AT+CIPSTATUS // запускаем заново модуль соединения к серверу
OK

STATE: TCP CLOSED // который в зависимости от статуса
AT+CIPSHUT // согласно даташита шлет нужную команду
SHUT OK
AT+CIPSTATUS
OK

STATE: IP INITIAL
AT + CSTT = "internet.emt.ee"
OK
AT+CIPSTATUS
OK

STATE: IP START
AT+CIICR
OK
AT+CIPSTATUS
OK

STATE: IP GPRSACT
AT+CIFSR
0.137.201.64S

OK

STATE: IP STATUS
AT+CIPSTART="TCP","m20.cloudmqtt.com",***** // коннектимся к резервному серверу
OK
AT+CIPSTATUS
OK

STATE: TCP CONNECTING
// .......... ждем коннекта
AT+CIPSTATUS
OK

STATE: TCP CONNECTING
AT+CIPSTATUS
CONNECT OK

OK

STATE: CONNECT OK
AT+CIPSEND
>x10 3x0 x4 MQTTx4 xC0 x0 xFD x0 xF Qw37Tu89u78-91px0 x8 ****** xC *******
SEND OK
AT+CIPSEND
>x82 x1C x0 xA x0 x17 smd/Qw37Tu89u78-91p/cmdx1   x2
SEND OK
AT+CIPSEND
>x82 xC x0 xA x0 x7 log/srvx1  x90 x3
                                      x1
SEND OK
AT+CIPSEND
>05x0 xB log/connectx0 x0 Qw37Tu89u78-91p - connected;MegaFon;12
23
7
 x90 x3
        x1
SEND OK
AT+CIPSTATUS
OK

STATE: CONNECT OK
AT+CIPCLOSE // опять принудительно разрываем связь
CLOSE OK
AT+CIPSTATUS
OK

STATE: TCP CLOSED
AT+CIPSHUT
SHUT OK
AT+CIPSTATUS
OK

STATE: IP INITIAL
AT + CSTT = "internet.emt.ee"
OK
AT+CIPSTATUS
OK

STATE: IP START
AT+CIICR
OK
AT+CIPSTATUS
OK

STATE: IP GPRSACT
AT+CIFSR
0.149.212.52S

OK

STATE: IP STATUS
AT+CIPSTART="TCP","m23.cloudmqtt.com",****** // теперь уже соединяемся с основным сервером
OK
AT+CIPSTATUS
OK

STATE: TCP CONNECTING
// ...... ждем соединения
AT+CIPSTATUS
OK

STATE: TCP CONNECTING
AT+CIPSTATUS
CONNECT OK

OK

STATE: CONNECT OK
AT+CIPSEND
>x10 3x0 x4 MQTTx4 xC0 x0 xFD x0 xF Qw37Tu89u78-91px0 x8 ******* xC ********
SEND OK
AT+CIPSEND
>x82 x1C x0 xA x0 x17 smd/Qw37Tu89u78-91p/cmdx1   x2 x1
SEND OK
AT+CIPSEND
>05x0 xB log/connectx0 x0 Qw37Tu89u78-91p - connected;MegaFon;12
23
0
 x90 x3
        x1
SEND OK
0x1D x17 smd/Qw37Tu89u78-91p/cmdcmd1AT+CIPSEND // пришла команда в подписанный топик, выполнили ее
>0"x0 x18 smd/Qw37Tu89u78-91p/respx0 x0 resp12 // отправили подтверждающий ответ
SEND OK
AT+CIPSEND
>xC0 x0 // бесконечно крутимся в цикле PING REQ
SEND OK
xD0 // PING RESP

-

часть кода, обработка интернет сессии по даташиту

-

void processStatus(byte inBt) { // основной анализ статусов, логика строго по даташиту
  static unsigned long timerConnecting; // таймер для замера времени коннекта к брокеру
  if (findRespFromBuf((char *) "IP INITIAL\r\n", inBt)) {  // если начальный статус                                                           // 0
    needCloseConnect = false; // разрывать связь не надо
    // прописываем APN
    gprsATcmdByIdx(0, false);
    gprsATcmd((char *)getAPNname(opsCard), false);
    gprsATcmd((char *)"\"\r", true);
    currentGprsModem = waitOKcmd; // ждем ОК
  } else if (findRespFromBuf((char *) "IP START\r\n", inBt)) {    // следующий статус                                                    // 1
    gprsATcmdByIdx(1, true); // активируем контекст
    currentGprsModem = waitCIICRcmd; // ждем ОК
  } else if (findRespFromBuf((char *) "IP GPRSACT\r\n", inBt)) {       // следующий статус                                               // 3
    if (needCloseConnect) { // если нужно свзь разорвать
      gprsATcmdByIdx(2, true); // отключаем контекст
      currentGprsModem = waitOKcmd; // ждем ОК
    } else { // если подключаем связь
      gprsATcmdByIdx(3, true); // получаем адрес
      currentGprsModem = waitRNcmd; // ждем вывода
    }
  } else if (findRespFromBuf((char *) "IP STATUS\r\n", inBt)) {      // дальше                                                 // 4
    if (needCloseConnect) { // если рвем связь
      gprsATcmdByIdx(2, true); // отключаем контекст
    } else { // продолжаем подключение
      gprsATcmdByIdx(4, false); // коннектимся к серверу
      if (mainMQTTserver) { // выбор сервера и отправка соотвествующего имени в зависимости от режима
#ifdef DEBUG_MODE
        gprsATcmd((char *)"m20.cloudmqtt.com", false); gprsATcmd((char *)"\",", false); gprsATcmd((char *)"*****", false);
#else
        char strServer[maxSizeBrokerID];
        strcpy(strServer, (char *)mqttServer2); gprsATcmd((char *)strServer, false); gprsATcmd((char *)"\",", false);
        strcpy(strServer, (char *)mqttPort2); gprsATcmd((char *)strServer, false);
#endif
      } else { // основной сервер
#ifdef DEBUG_MODE
        gprsATcmd((char *)"m23.cloudmqtt.com", false); gprsATcmd((char *)"\",", false); gprsATcmd((char *)"*****", false);
#else
        char strServer[maxSizeBrokerID];
        strcpy(strServer, (char *)mqttServer1); gprsATcmd((char *)strServer, false); gprsATcmd((char *)"\",", false);
        strcpy(strServer, (char *)mqttPort1); gprsATcmd((char *)strServer, false);
#endif
      }
      gprsATcmd((char *)"\r", true); // шлем окончание команды
      timerConnecting = currentMillis; // обнуляем таймер ожидания коннекта
    }
    currentGprsModem = waitOKcmd; // ждем ок
  } else if (findRespFromBuf((char *) "CONNECT OK\r\n", inBt)) {     // приконнектилось                                                       // 6
    if (needCloseConnect) { // если нужен разрыв
      gprsATcmdByIdx(5, true); // закрываем контекст
      currentGprsModem = waitOKcmd; // ждем ОК
    } else { // если подключаемся
      currentGprsModem = serverConnected; // успешно выходим
    }
  } else if (findRespFromBuf((char *) "TCP CONNECTING\r\n", inBt)) {           // в процессе подключения                                                 // 5
    if (needCloseConnect) { // если нужно разорвать связь
      gprsATcmdByIdx(2, true); // гасим
      currentGprsModem = waitOKcmd; // ждем ОК
    } else { // ждем подключения
      if ((currentMillis - timerConnecting) >= gprsPeriodConnecting) { // если время вышло
        if (mainMQTTserver) mainMQTTserver = 0; else mainMQTTserver = 1; // меняем сервер
        ++totalReconnectMQTT; // увеличиваем счетчик смены брокеров
        gprsATcmdByIdx(2, true); // гасим контекст
        currentGprsModem = waitOKcmd; // ждем ОК
      } else { // если продолжыется подключение
        currentGprsModem = sendCipStatus; // запрашиваем статус
      }
    }
  } else if (findRespFromBuf((char *) "IP CONFIG\r\n", inBt)) {                // шаг                                            // 2
    currentGprsModem = sendCipStatus; // запрос статуса
  } else if (findRespFromBuf((char *) "TCP CLOSING\r\n", inBt)) {               // шаг                                             // 7
    currentGprsModem = sendCipStatus; // запрос статуса
  } else if (findRespFromBuf((char *) "TCP CLOSED\r\n", inBt)) {                // отключились от сервера                                            // 8
    gprsATcmdByIdx(2, true); // гасим сессию
    currentGprsModem = waitOKcmd; // ждем ОК
  } else if (findRespFromBuf((char *) "DPD DEACT\r\n", inBt)) {                 // отключилась сессия                                           // 9
    currentGprsModem = sendCipStatus; // запрос статуса
  } else if (findRespFromBuf((char *) "CONNECT FAIL\r\n", inBt)) {   // ошибка соединения
    gprsATcmdByIdx(2, true); // гасим сессию
    currentGprsModem = waitOKcmd; // ждем ОК
  }
}

-

к сожалению, какая бы не была хорошая схема, в среднем один из 20и модемов SIM800L зависает наглухо один раз в 50....70 дней, на команды отвечает, а по факту данные не передает. Поэтому рекомендую в схему добавить эл.ключ/реле, в случае принудительной перезагрузки третий раз за 15 минут, тупо отрубать питание. И конечно для стабильной работы строго использовать Hardware UART atmega328p.

 

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

andycat пишет:
Поэтому рекомендую в схему добавить эл.ключ/реле, в случае принудительной перезагрузки третий раз за 15 минут, тупо отрубать питание.

плюсую, также сделал в проекте управления webasto - суровое реле питание рубит. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

просто с правильным SoftwareSerial видимо никто не экспериментировал...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

просто с правильным SoftwareSerial видимо никто не экспериментировал...

А что, в природе такое бывает?

IMHO, SoftwareSerial - костыль, который, возможно, может быть в некоторых экзотических случаях использован для отладки, но который обязательно должен быть удален из финального кода.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

смотрю профессиональные девайсы, а там используется SIM300... более стабилен в работе?
 

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

ua6em пишет:

смотрю профессиональные девайсы

а что в вашем понятии профессиональные девайсы? мой последний проект/заказ c SIM800L развернут на нескольких тысяч устройств, в планах 200000+ , но считать его профессиональным я например не могу.

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

ЗЫ. И вообще ветка про MQTT.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Sim300 применяется в ВЭРС-ПК к примеру, имеет все необходимые сертификаты, можно почистить флуд...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

andycat пишет:

 но считать его профессиональным я например не могу.

Интересно, почему ?

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

brokly пишет:

andycat пишет:

 но считать его профессиональным я например не могу.

Интересно, почему ?

потому что я не профессиональный программист/электронщик и не имею соответствующего сертификата как у какого нибудь КБ с кучей специалистов разной направленности :)

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

Logik
Offline
Зарегистрирован: 05.08.2014

andycat пишет:

 использовать software serial из коробки можно только для вывода какого нибудь не критичного лога. 

Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial  его положит. Список его авторов я уже дето выкладывал. Этих уродов регулярно упоминаю в проклятиях. Надо быть последним фашистским человеконенавистником чтоб такое нахерячить. И да - тех кого устраивает как оно работает - дальше хелоуворда не пробовали. Он просто не может стабильно работать не убив все вокруг.

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

Температура, влажность, давление на BME280+ESP8266(WeMos D1 mini), отправляемые на MQTT сервер.
Код сборная солянка, страшненький, написан наспех на коленке, но работает стабильно.
При включении подключается в течении 2 минут к WiFi точке доступа, в случае облома запускает сервер куда вбиваются данные WiFi и MQTT. Далее получает данные, отправлет и засыпает на 25 минут.

Потребление через понижайку от аккумулятора 18650 ~1.5мА в спящем режиме

#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

#define SEALEVELPRESS_HPA (1013.25)

Adafruit_BME280 bme;

char srvssid[] = "ESterm06";
char srvpass[] = "ESterm06";

ESP8266WebServer server(80);
/* Just a little test message.  Go to http://192.168.4.1 in a web browser
   connected to this access point to see it.
*/
byte wifiset = 0; byte mqttset = 0;

#define eep_max_len_param 0x40
#define eep_max_count_params 7
#define eep_pos_wifi_p1 0x10
#define eep_pos_wifi_p2 0x30
#define eep_pos_mqtt_p1 0x60
#define eep_pos_mqtt_p2 0x80
#define eep_pos_mqtt_p3 0xA0
#define eep_pos_mqtt_p4 0xC0
#define eep_pos_mqtt_p5 0xE0
char eep_str[eep_max_len_param];

#define period_enable_http_server 300000UL // 5min
unsigned long timer_enable_http_server = 0;

#define size_response_buf 0x40
char mqtt_response_buf[size_response_buf];
byte pos_response_mqtt = 0;

#define errTemp 1111
word currTemp = errTemp;
word currHum = errTemp;
word currPres = errTemp;

byte deviceMode = 10; // main mode work device
// 0 connect wifi
// 1 wait connect wifi
// 2 repeat connect wifi
// 3 connect to mqtt server
// 7 load data mqtt
// 8 wifi access point + http server - several minuts after start
// 9 wait get/post answer
// 10 get temp/hum/press
// 11 sleep device

char ssid[eep_max_len_param];
char password[eep_max_len_param];
#define period_test_wifi_connect 500UL
unsigned long timer_test_wifi_connect = 0;
#define period_timeout_wifi_connect 30000UL // 30sec
unsigned long timer_timeout_wifi_connect = 0;
#define period_repeat_wifi_connect 30000UL // 30sec and MQTT repeat
unsigned long timer_repeat_wifi_connect = 0;
WiFiClient client;
char mqtt_server[eep_max_len_param];
int mqtt_port;
char mqtt_user[eep_max_len_param];
char mqtt_pass[eep_max_len_param];
char mqtt_device[eep_max_len_param];
char mqtt_realhard[] = "Pogreb01-CatVil";
char mqtt_topic_temp[] = "/pog";
char mqtt_topic_hum[] = "/hum";
char mqtt_topic_pres[] = "/pre";

unsigned long currentMillis;

#define LEDON digitalWrite(LED_BUILTIN,LOW)
#define LEDOFF digitalWrite(LED_BUILTIN,HIGH)

void ledFlash(byte countFlash) {
  for (byte i = 0; i < countFlash; ++i) {
    LEDON; delay(100); LEDOFF; delay(100);
  }
  delay(400);
}

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  LEDOFF; EEPROMinit();
  Serial.begin(115200); Serial.println("Reset Serial");
  ledFlash(1); loadDataWiFiEEPROM(); loadDataMqttEEPROM();
}

void processMainWork() {
  switch (deviceMode) {
    case 0: { // connect wifi
        WiFi.disconnect(true);
        Serial.print("Connect to WiFi AP "); Serial.println(ssid);
        WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); ++deviceMode; timer_timeout_wifi_connect = currentMillis; timer_test_wifi_connect = currentMillis; break;
      }
    case 1: { // wait connect wifi
        if ((currentMillis - timer_test_wifi_connect) >= period_test_wifi_connect) {
          timer_test_wifi_connect = currentMillis;
          if (WiFi.status() == WL_CONNECTED) {
            Serial.println("WiFi connected"); deviceMode = 3; // connect ok
            ledFlash(3);
          } else {
            Serial.print(".");
            if ((currentMillis - timer_timeout_wifi_connect) >= period_timeout_wifi_connect) {
              Serial.println("WiFi timeout connection"); timer_repeat_wifi_connect = currentMillis; deviceMode = 8; WiFi.disconnect(); // problem connect
            }
          }
        } break;
      }
    case 3: { // connect to mqtt server
        if (client.connect(mqtt_server, mqtt_port)) {
          Serial.println("MQTT connected"); deviceMode = 5; // connect ok
        } else {
          Serial.println("Error MQTT connect"); timer_repeat_wifi_connect = currentMillis; deviceMode = 4; // problem connect
        } break;
      }
    case 4: { // repeat connect mqtt
        if ((currentMillis - timer_repeat_wifi_connect) >= period_repeat_wifi_connect) {
          if (WiFi.status() == WL_CONNECTED) {
            deviceMode = 3;
          } else {
            deviceMode = 0;
          }
        } break;
      }
    case 5: { // send conneck packet and subscribe
        sendConnectPacket(); Serial.println(""); deviceMode = 6; timer_repeat_wifi_connect = currentMillis; break;
      }
    case 6: { // wait response - pause 3 sec
        if ((currentMillis - timer_repeat_wifi_connect) >= 3000UL) {
          deviceMode = 7;
        } else {
          if (client.available()) {
            while (client.available()) {
              byte inByte = client.read();
              if ((inByte < 0x20) || (inByte >= 0x7F)) {
                Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
              } else {
                Serial.write(inByte);
              }
            }
          } // end avail
        } // -
        break;
      }
    case 7: { // send data
        Serial.println(" Need send current temp! ");
        sendPubTemp(); Serial.println("");
        Serial.println(" Need send current hum! ");
        sendPubHum(); Serial.println("");
        Serial.println(" Need send current pres! ");
        sendPubPres(); Serial.println("");
        deviceMode = 11; // sleep
        break;
      }
    case 8: { // start wifi and http server
        WiFi.disconnect(true);
        Serial.print("Configuring access point...");
        WiFi.softAP(srvssid, srvpass);
        IPAddress myIP = WiFi.softAPIP();
        Serial.print("AP IP address: ");
        Serial.println(myIP);
        server.on("/", handleRoot);
        server.on("/setup", HTTP_GET, handleSetupGet);
        server.on("/setup", HTTP_POST, handleSetupPost);
        server.onNotFound(handleNotFound);
        server.begin();
        Serial.println("HTTP server started");
        deviceMode = 9;
        timer_enable_http_server = currentMillis;
        break;
      }
    case 9: {
        server.handleClient();
        if (server.hasArg("action")) {
          if (!wifiset) {
            if (((server.arg("action").indexOf("savewifi")) >= 0) && (server.hasArg("ssid")) && (server.hasArg("pass"))) {
              wifiset = 1;
              Serial.println("There are new WiFi data");
              // save data to eeprom
              byte l = server.arg("ssid").length() + 1;
              server.arg("ssid").toCharArray(eep_str, l); eep_str[l] = 0;
              byte i = 0; while (eep_str[i] > 0) {
                EEPROM.write(eep_pos_wifi_p1 + i, eep_str[i]); ++i;
              } EEPROM.write(eep_pos_wifi_p1 + i, 0);
              l = server.arg("pass").length() + 1;
              server.arg("pass").toCharArray(eep_str, l); eep_str[l] = 0;
              i = 0; while (eep_str[i] > 0) {
                EEPROM.write(eep_pos_wifi_p2 + i, eep_str[i]); ++i;
              } EEPROM.write(eep_pos_wifi_p2 + i, 0);
              EEPROM.commit();
              EEPROM.end();
              EEPROMinit();
              loadDataWiFiEEPROM();
            }
          }
          if (!mqttset) {
            if (((server.arg("action").indexOf("mqttset")) >= 0) && (server.hasArg("host")) && (server.hasArg("port")) && (server.hasArg("user")) && (server.hasArg("pass")) && (server.hasArg("devname"))) {
              mqttset = 1;
              Serial.println("There are new MQTT data");
              // save data to eeprom
              byte l = server.arg("host").length() + 1;
              server.arg("host").toCharArray(eep_str, l); eep_str[l] = 0;
              byte i = 0; while (eep_str[i] > 0) {
                EEPROM.write(eep_pos_mqtt_p1 + i, eep_str[i]); ++i;
              } EEPROM.write(eep_pos_mqtt_p1 + i, 0);
              l = server.arg("port").length() + 1;
              server.arg("port").toCharArray(eep_str, l); eep_str[l] = 0;
              i = 0; while (eep_str[i] > 0) {
                EEPROM.write(eep_pos_mqtt_p2 + i, eep_str[i]); ++i;
              } EEPROM.write(eep_pos_mqtt_p2 + i, 0);
              l = server.arg("user").length() + 1;
              server.arg("user").toCharArray(eep_str, l); eep_str[l] = 0;
              i = 0; while (eep_str[i] > 0) {
                EEPROM.write(eep_pos_mqtt_p3 + i, eep_str[i]); ++i;
              } EEPROM.write(eep_pos_mqtt_p3 + i, 0);
              l = server.arg("pass").length() + 1;
              server.arg("pass").toCharArray(eep_str, l); eep_str[l] = 0;
              i = 0; while (eep_str[i] > 0) {
                EEPROM.write(eep_pos_mqtt_p4 + i, eep_str[i]); ++i;
              } EEPROM.write(eep_pos_mqtt_p4 + i, 0);
              l = server.arg("devname").length() + 1;
              server.arg("devname").toCharArray(eep_str, l); eep_str[l] = 0;
              i = 0; while (eep_str[i] > 0) {
                EEPROM.write(eep_pos_mqtt_p5 + i, eep_str[i]); ++i;
              } EEPROM.write(eep_pos_mqtt_p5 + i, 0);
              EEPROM.commit();
              EEPROM.end();
              EEPROMinit();
              loadDataMqttEEPROM();
            }
          }
        }
        if ((currentMillis - timer_enable_http_server) >= period_enable_http_server) {
          Serial.println("Stop HTTP server");
          server.stop();
          WiFi.disconnect(true);
          deviceMode = 11; // sleep
        }
        break;
      }
    case 10: { // get temp hum press
        if (!bme.begin(0x76)) {
          Serial.println("BME280 problem!");
        } else {
          currTemp = ((word)(bme.readTemperature() * 10)) + 2000;
          currHum = bme.readHumidity();
          currPres = (word)(bme.readPressure() / 133.322368421);
          ledFlash(2);
        }
        deviceMode = 0; // connect to wifi
        break;
      }
    case 11: { // wait 5 sec and sleep
        timer_repeat_wifi_connect = currentMillis;
        ++deviceMode;
        break;
      }
    default: { // wait 5 sec
        if ((currentMillis - timer_repeat_wifi_connect) >= 5000UL) {
          // 12 sleep device
          Serial.println("  sleep device  ");
          WiFi.disconnect(true);
          ESP.deepSleep(1500e6); // sleep 25min
        } else {
          if (client.available()) {
            while (client.available()) {
              byte inByte = client.read();
              if ((inByte < 0x20) || (inByte >= 0x7F)) {
                Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
              } else {
                Serial.write(inByte);
              }
            }
          } // end avail
        } // -
      }
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  currentMillis = millis();
  // main work
  processMainWork();
  // end loop
}

void sendConnectPacket() {
  byte sizeDevice = strlen(mqtt_realhard); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass);
  // fixed header
  sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000
  sendByteToMQTTclient((byte)(16 + sizeDevice + sizeUser + sizePass)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)0x04); // Length LSB (4)
  sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name
  sendByteToMQTTclient((byte)0x04); // Protocol Level byte
  sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable + retain +will flag
  sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0)
  sendByteToMQTTclient((byte)0x28); // Keep Alive LSB (10) - 40 sec
  // payload
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_realhard[i]));
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user
  for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i]));
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass
  for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i]));
}

void sendByteToMQTTclient(byte inByte) {
  client.write((byte)(inByte));
  if ((inByte < 0x20) || (inByte >= 0x7F)) {
    Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
  } else {
    Serial.write(inByte);
  }
}

void sendPubTemp() {
  char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currTemp;
  if (currTemp == errTemp) {
    textTemp[textPos] = 'n'; ++textPos; textTemp[textPos] = 'o'; ++textPos;
  } else {
    if (absTemp >= 2000) {
      textTemp[textPos] = '+'; absTemp -= 2000;
    } else {
      textTemp[textPos] = '-';
    } ++textPos;
    //word bt = absTemp * 0.023; absTemp = absTemp + bt; // correct to true temp
    if (absTemp >= 1000) {
      textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    } else if (absTemp >= 100) {
      textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    } else if (absTemp >= 10) {
      textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    }
    textTemp[textPos] = '.'; ++textPos; textTemp[textPos] = (absTemp % 10) + '0'; ++textPos;
  }
  textTemp[textPos] = ' '; ++textPos; textTemp[textPos] = '`'; ++textPos; textTemp[textPos] = 'C'; ++textPos; textTemp[textPos] = 0;
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_temp); byte sizeData = strlen(textTemp);
  // fixed header
  sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0001 flags
  sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_temp[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}

void sendPubHum() {
  char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currHum;
  if (currHum == errTemp) {
    textTemp[textPos] = 'n'; ++textPos; textTemp[textPos] = 'o'; ++textPos;
  } else {
    if (absTemp >= 1000) {
      textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    } else if (absTemp >= 100) {
      textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    } else if (absTemp >= 10) {
      textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    }
    textTemp[textPos] = (absTemp % 10) + '0'; ++textPos;
  }
  textTemp[textPos] = ' '; ++textPos; textTemp[textPos] = '%'; ++textPos; textTemp[textPos] = 0;
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_hum); byte sizeData = strlen(textTemp);
  // fixed header
  sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0001 flags
  sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_hum[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}

void sendPubPres() {
  char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currPres;
  if (currPres == errTemp) {
    textTemp[textPos] = 'n'; ++textPos; textTemp[textPos] = 'o'; ++textPos;
  } else {
    if (absTemp >= 1000) {
      textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    } else if (absTemp >= 100) {
      textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    } else if (absTemp >= 10) {
      textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
    }
    textTemp[textPos] = (absTemp % 10) + '0'; ++textPos;
  }
  textTemp[textPos] = ' '; ++textPos; textTemp[textPos] = 'm'; ++textPos; textTemp[textPos] = 'm'; ++textPos; textTemp[textPos] = 0;
  byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_pres); byte sizeData = strlen(textTemp);
  // fixed header
  sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0001 flags
  sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
  // Variable header
  sendByteToMQTTclient((byte)0x00); // Length MSB (0)
  sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
  for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
  for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_pres[i]));
  sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
  sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
  // payload
  for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}

byte getByteFromTwoChar(byte byte1, byte byte0) {
  byte resultB;
  if (byte1 >= 0x41) resultB = (byte1 - 0x37) * 16; else  resultB = (byte1 - 0x30) * 16;
  if (byte0 >= 0x41) resultB = resultB + (byte0 - 0x37); else resultB = resultB + (byte0 - 0x30);
  return resultB;
}

void handleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

void handleRoot() {
  wifiset = 0; mqttset = 0;
  server.send(200, "text/html", "<h1>You are connected</h1>");
}

void handleSetupGet() {
  String message = "<html lang='ru'>\
              <head>\
              <meta charset='utf - 8'>\
              <title>ESP temperature Server</title>\
              </head>\
              <body>\
    <h1>WiFi Acces Point data</h1>\
  <form action='?' method='post'>\
        <div>\
        <label for='ssid'>WiFi SSID: <input type='text' name='ssid' id='ssid' value='";
  message += ssid;
  message += "'></label>\
        </div>\
        <div>\
        <label for='pass'>WiFi Password: <input type='password' name='pass' id='pass' value='";
  message += password;
  message += "'></label>\
        </div>\
        <p></p>\
        <input type='hidden' name='action' value='savewifi'>\
        <input type='submit' value='Save'>\
        </div>\
  </form>\
  <form action='?' method='post'>\
        <div>\
        <label for='host'>Host: <input type='text' name='host' id='host' value='";
  message += mqtt_server;
  message += "'></label>\
        </div>\
        <div>\
        <label for='port'>Port: <input type='text' name='port' id='port' value='";
  message += mqtt_port;
  message += "'></label>\
        </div>\
        <p></p>\
        <div>\
        <label for='user'>User: <input type='text' name='user' id='user' value='";
  message += mqtt_user;
  message += "'></label>\
        </div>\
        <div>\
        <label for='pass'>Password: <input type='password' name='pass' id='pass' value='";
  message += mqtt_pass;
  message += "'></label>\
        </div>\
        <p></p>\
        <div>\
              <label for='devname'>Topic name: <input type='text' name='devname' id='devname' value='";
  message += mqtt_device;
  message += "'></label>\
        </div>\
        <p></p>\
        <input type='hidden' name='action' value='mqttset'>\
        <input type='submit' value='Set'>\
  </form>\
        <p></p>\
  <a href='../'>Return to main page</a>\
              </body>\
              </html>";
  server.send(200, "text/html", message);
}

void handleSetupPost() {
  server.send(200, "text/html", "<html lang='ru'>\
              <head>\
              <meta charset='utf - 8'>\
              <title>ESP temperature Server</title>\
              </head>\
              <body>\
    <h1>OK</h1>\
        <p></p>\
  <a href='../'>Return to main page</a>\
              </body>\
              </html>");
}


char* LastPos(char *str1, char *str2) { // find substring in string
  int L1 = strlen(str1);
  int L2 = strlen(str2);
  for (int i = L1 - L2; i >= 0; i--)
  {
    int j = 0;
    for (; j < L2; j++)
      if ((str1[i + j] != str2[j]))
        break;
    if (j == L2)
      return str1 + i;
  }
  return 0;
}

int strPos(char *str11, char *str22) { // find position in string(1) substring(2)
  char*p = LastPos(str11, str22);
  int n = p - str11;
  return n;
}

void loadDataWiFiEEPROM() {
  byte i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_wifi_p1 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
  strcpy(ssid, eep_str);
  i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_wifi_p2 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
  strcpy(password, eep_str);
}

void EEPROMinit() {
  EEPROM.begin(eep_max_len_param * eep_max_count_params);
}

void loadDataMqttEEPROM() {
  byte i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p1 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
  strcpy(mqtt_server, eep_str);
  i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p2 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
  mqtt_port = atoi(eep_str);
  i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p3 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
  strcpy(mqtt_user, eep_str);
  i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p4 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
  strcpy(mqtt_pass, eep_str);
  i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p5 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
  strcpy(mqtt_device, eep_str);
}

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

Установленные железки в реальных условиях 

sma-etu
Offline
Зарегистрирован: 17.06.2020


Добрый день. Подскажите пожалуйста в чем может быть проблема? Сделал sim800+arduino, брокер был cloudmqtt.com. Все работало стабильно.Решил перенести на другой брокер,www.dioty.co. Возникли трудности. Опубликовать в паблик могу, все передается на брокер, но как только пытаюсь подписаться на топик, сразу закрывает соединение
sma-etu
Offline
Зарегистрирован: 17.06.2020
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>


Adafruit_BME280 bme; // I2C

#include <SoftwareSerial.h>
//В папке с Arduino IDE в файле SoftwareSerial.h строку #define _SS_MAX_RX_BUFF 64 заменяем на  #define _SS_MAX_RX_BUFF 255. 
//#include <DallasTemperature.h>      // https://github.com/milesburton/Arduino-Temperature-Control-Library
#define LCD_ADDR 0x27
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(LCD_ADDR, 20, 4);
//  ----------------------------------------- НАЗНАЧАЕМ ВЫВОДЫ для платок до 1.7.6 (c Arduino Pro Mini) ------------------------------ 

SoftwareSerial SIM800(9, 10);                // для старых плат начиная с версии RX,TX
//String _response = "";



#define LED_Pin      13                     // на светодиод (моргалку) 6-й транзистор
#define rel3      3              
#define rel4      4                   
#define reset_sim800      5                     
#define rel1      6                      // на светодиод (моргалку) 6-й транзистор
#define rel2      7                      // на светодиод (моргалку) 6-й транзистор
#define  SENSOR_H      A0 
#define  MIN        800 //630                    // Определяем минимальное показание датчика (в воздухе),
#define  MAX        350 //330                    // определяем максимальное показание датчика (в воде),
#define  SENSOR_BATT     A2 
#define  ON_SENSOR_BATT  8 
                   // 9. 10 -rs
#define  MIN_BATT   442
#define  MAX_BATT   590



//DallasTemperature sensors(&oneWire);
/*  ----------------------------------------- НАСТРОЙКИ MQTT брокера---------------------------------------------------------   */
const char MQTT_user[20] = "sma-etu@yandex.ru";      // api.cloudmqtt.com > Details > User  
const char MQTT_pass[15] = "4e93f773";  // api.cloudmqtt.com > Details > Password
const char MQTT_type[15] = "MQIsdp";        // тип протокола НЕ ТРОГАТЬ !
const char MQTT_CID[10] = "utep";        // уникальное имя устройства в сети MQTT
String MQTT_SERVER = "mqtt.dioty.co";   // api.cloudmqtt.com > Details > Server  сервер MQTT брокера
String PORT = "1883";                      // api.cloudmqtt.com > Details > Port    порт MQTT брокера НЕ SSL !
/*  ----------------------------------------- ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ !!!---------------------------------------------------------   */

String APN = "internet.mts.ru";             // тчка доступа выхода в интернет вашего сотового оператора


/*  ----------------------------------------- ДАЛЕЕ НЕ ТРОГАЕМ ---------------------------------------------------------------   */

//---------------ПЕРЕМЕННЫЕ-------------------------------------------------

float TempDS[5];                           // массив хранения температуры c разных датчиков 
unsigned long Time_millis, Time1, Time3=0, Time4 = 0, Time5 = 0;
int interval = 3;                           // интервал тправки данных на сервер после загрузки ардуино
unsigned int temperatura_open = 2300, temperatura_clouse = 2200, temperatura_bme280, vlaj_otk = 30, vlaj_zakr = 80 ; //temperatura_clouse_n,temperatura_open_n
unsigned int temp_raznica_open = 0;
bool flag_door = 0, flag_door_super_open = 0; //0 - close 1 - open
bool led_svet = 0;
bool flag_kran = 0;
unsigned int chas=15, minut=0;
unsigned int batt_mass[10];
unsigned int batt_count = 0;

void setup()
{
//================BME280==========================\\

  bme.begin(0x76);
//================================================\\

  lcd.init();
  lcd.setBacklight(true);
  //lcd.backlight();
  lcd.print("Kontr teplici");
         
  pinMode(LED_Pin,     OUTPUT);    
  pinMode(rel1,     OUTPUT);   
  pinMode(rel2,     OUTPUT); 
  
  pinMode(rel3,     OUTPUT);   
  pinMode(rel4,     OUTPUT); 
  
  pinMode(ON_SENSOR_BATT, OUTPUT);
   
  pinMode(reset_sim800,     OUTPUT);  
  
  digitalWrite(reset_sim800, HIGH);   
  digitalWrite(rel1, HIGH); 
  digitalWrite(rel2, HIGH); 
  digitalWrite(rel3, HIGH); 
  digitalWrite(rel4, HIGH);
  digitalWrite(ON_SENSOR_BATT, 0); 
              
  pinMode(3, OUTPUT);                 //  для плат до 1.7.2 с оптопарами

  Serial.begin(9600);                       //скорость порта
  SIM800.begin(9600);                       //скорость связи с модемом 
 // Serial.println("MQTT"); 
    
  //SIM800_reset();
  
  lcd.setCursor(0, 0);
  lcd.print("BATT           ");
  ClouseDoor(3800);
  ClouseKran(4000);

  SIM800_reset();

   lcd.setCursor(18, 1); 
   lcd.print(temperatura_open/100);
   lcd.setCursor(15, 1); 
   lcd.print(temperatura_clouse/100);

   lcd.setCursor(9, 1); 
   lcd.print(vlaj_otk);

   lcd.setCursor(12, 1); 
   lcd.print(vlaj_zakr );
   
}


String sendATCommand(String cmd, bool waiting) {
  String _resp = "";                            // Переменная для хранения результата
     
  Serial.println(cmd);                          // Дублируем команду в монитор порта
  SIM800.println(cmd);                          // Отправляем команду модулю
  if (waiting) {                                // Если необходимо дождаться ответа...
    _resp = waitResponse();                     // ... ждем, когда будет передан ответ
    // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
    if (_resp.startsWith(cmd)) {  // Убираем из ответа дублирующуюся команду
      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
                                }
  //  Serial.println("sendATCommand_otvet1");
    Serial.println(_resp);                      // Дублируем ответ в монитор порта
   if (_resp.indexOf("+CME ERROR:") > -1)  {   interval = 3 ; SIM800_reset(); }   
   // Serial.println("sendATCommand_otvet2");
  }
  return _resp;                                 // Возвращаем результат. Пусто, если проблема
}


String waitResponse() {                         // Функция ожидания ответа и возврата полученного результата
  String _resp = "";                            // Переменная для хранения результата
  long _timeout = millis() + 10000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!SIM800.available() && (millis() < _timeout))  {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  if (SIM800.available()) {                     // Если есть, что считывать...

    _resp = SIM800.readString();                // ... считываем и запоминаем
  }
  else {                                        // Если пришел таймаут, то...

   // Serial.println("Timeout...");               // ... оповещаем об этом и...
 
            SIM800_reset(); 
            interval = 3 ;

  }
  return _resp;                                 // ... возвращаем результат. Пусто, если проблема
}




void loop() 
{
  uint16_t data_sensor_h;  
//_response=0;
//_response= SIM800.available();
//Serial.println(_response);

if (SIM800.available())  resp_modem();                                    // если что-то пришло от SIM800 в Ардуино отправляем для разбора
if (Serial.available())  resp_serial();                                 // если что-то пришло от Ардуино отправляем в SIM800

Time_millis = millis();
if (Time_millis> Time1 + 10000) {Time1 = Time_millis; detection();}               // выполняем функцию detection () каждые 10 сек 

if (interval == 0) {if ((Time_millis> Time3 + 40000)&&(interval == 0)) {Time3 = Time_millis; sendPingPacket();} };              // выполняем функцию sendPingPacket() каждые 50 сек 

if (Time_millis> Time4 + 100000)
           { 
            Time4 = Time_millis;
            interval = 3 ;
            SIM800_reset();  
            lcd.setCursor(10, 3);
            lcd.print("ER"); 
            }
            
if (led_svet){
             // lcd.setCursor(19, 0); lcd.print(" ");
              digitalWrite(LED_Pin, 1);   // зажигаем светодиод
              lcd.setCursor(16, 3); lcd.print (":");
              } else
              {
             // lcd.setCursor(19, 0); lcd.print("#");
              digitalWrite(LED_Pin, 0);   // гасим светодиод
              lcd.setCursor(16, 3); lcd.print (" ");
              }
if ((Time_millis> Time5 + 500)) { 
                                Time5 = Time_millis;              
                                led_svet = !led_svet;
                              }

     
     data_sensor_h = analogRead(SENSOR_H);
     if (data_sensor_h > MIN) data_sensor_h = MIN;
     if (data_sensor_h < MAX) data_sensor_h = MAX;
     data_sensor_h = map(data_sensor_h, MIN, MAX, 0, 100);  // адаптируем значения от 0 до 100,
     TempDS[3] = data_sensor_h;
   /*  lcd.setCursor(15, 0);
     lcd.print(data_sensor_h);
     lcd.setCursor(18, 0);
     lcd.print("%H");
*/

 

if ((chas >= 8 && chas < 17 )&&(interval == 0))
  { lcd.setBacklight(true);
    temp_raznica_open = temperatura_bme280 - temperatura_open;
    if ((temperatura_bme280 >= temperatura_open)&&(flag_door == 0)&&(temperatura_open!=0)&&(temperatura_open>temperatura_clouse))
    {
    flag_door = 1;
    if (temp_raznica_open >= 150) {flag_door_super_open = 1; OpenDoor (3800);} else {flag_door_super_open = 0; OpenDoor (1800);}
    //sendATCommand("AT+CIPSEND", true);    
   // MQTT_PUB ("/sma-etu@yandex.ru/", "OPEN");  
    //SIM800.write((byte)0x1A); 
    }
    else if ((temperatura_bme280 >= (temperatura_open + 150))&&(flag_door == 1)&&(flag_door_super_open == 0))
    {
    flag_door = 1;
    flag_door_super_open = 1;
    OpenDoor (3800);
   // sendATCommand("AT+CIPSEND", true);    
   // MQTT_PUB ("sma/door", "S_OPEN");  
   // SIM800.write((byte)0x1A); 
    }
    else if ((temperatura_bme280 <= temperatura_open)&&(flag_door == 1)&&(flag_door_super_open == 1))
    {
    flag_door = 1;
    ClouseDoor(1800);
    flag_door_super_open = 0;
   // sendATCommand("AT+CIPSEND", true);    
   // MQTT_PUB ("sma/door", "OPEN");  
   // SIM800.write((byte)0x1A); 
    }
    else if((temperatura_bme280 <= temperatura_clouse)&&(flag_door == 1)&&(temperatura_clouse!=0)&&(temperatura_open>temperatura_clouse))
    {
    flag_door = 0;
    flag_door_super_open = 0;
    ClouseDoor(3800);
   // sendATCommand("AT+CIPSEND", true);    
   // MQTT_PUB ("sma/door", "CLOUSE");  
   // SIM800.write((byte)0x1A); 
    }
  }  else 
  {
    lcd.setBacklight(false);
    if (flag_door == 1)
      {    
        flag_door = 0;
        flag_door_super_open = 0;
        ClouseDoor(3800);
       // sendATCommand("AT+CIPSEND", true);    
       // MQTT_PUB ("sma/door", "CLOUSE");  
       // SIM800.write((byte)0x1A); 
      }
  }

if (TempDS[3] < vlaj_otk  && flag_kran == 0&&(interval == 0)) {OpenKran(4000);  flag_kran = 1;}
if (TempDS[3] > vlaj_zakr && flag_kran == 1&&(interval == 0)) {ClouseKran(4000);flag_kran = 0;}


}







void detection(){                                                 // условия проверяемые каждые 10 сек  

   
float PressureMm;
uint16_t data_sensor_batt;
    
     TempDS[0] = bme.readTemperature();          // читаем температуру
     TempDS[1] = bme.readPressure();             // читаем давление 
     TempDS[2] = bme.readHumidity();             // читаем влажность
      
    lcd.setCursor(0, 2);
    lcd.print(TempDS[2],1);//(bme.readHumidity());
    lcd.setCursor(4, 2);
    lcd.print("%H");
    PressureMm = TempDS[1] * 0.00750062;
    lcd.setCursor(6, 2);
    lcd.print(PressureMm,2);
    lcd.setCursor(12, 2);
    lcd.print("mm");
    lcd.setCursor(14, 2);
    lcd.print(TempDS[0],2);//(bme.readTemperature());
    lcd.setCursor(19, 2);
    lcd.print("C");
 
     digitalWrite(ON_SENSOR_BATT, 1);
     temperatura_bme280 = (int)(TempDS[0]*100);
  /*   
     data_sensor_h = analogRead(SENSOR_H);
     if (data_sensor_h > MIN) data_sensor_h = MIN;
     if (data_sensor_h < MAX) data_sensor_h = MAX;
     data_sensor_h = map(data_sensor_h, MIN, MAX, 0, 100);  // адаптируем значения от 0 до 100,
     TempDS[3] = data_sensor_h;*/

     //-----------Влажность почвы----------------------
     if (TempDS[3] <10)                    {lcd.setCursor(15, 0); lcd.print("  "); lcd.setCursor(17, 0); lcd.print(TempDS[3],0);} else   //0-9%
     if (TempDS[3] >=10 && TempDS[3] < 100){lcd.setCursor(15, 0); lcd.print(" ");  lcd.setCursor(16, 0); lcd.print(TempDS[3],0);} else   //10-99%
                                                                                  {lcd.setCursor(15, 0); lcd.print(TempDS[3],0);}        //100%
     lcd.setCursor(18, 0);
     lcd.print("%H");

     data_sensor_batt = analogRead(SENSOR_BATT);
     digitalWrite(ON_SENSOR_BATT, 0);
       //   Serial.println(data_sensor_batt);
     if (data_sensor_batt > MAX_BATT) data_sensor_batt = MAX_BATT;
     if (data_sensor_batt < MIN_BATT) data_sensor_batt = MIN_BATT;
     data_sensor_batt = map(data_sensor_batt, MIN_BATT, MAX_BATT, 0, 100);  // адаптируем значения от 0 до 100,
      if (batt_count < 9) {batt_count ++;} else  {batt_count = 0;}
      
           batt_mass[batt_count] = data_sensor_batt;
           data_sensor_batt = 0;
           for (int i=0; i <= 9; i++) {data_sensor_batt = data_sensor_batt + batt_mass[i];}
           data_sensor_batt = data_sensor_batt / 10;
      
     
     TempDS[4] = data_sensor_batt;
     if (data_sensor_batt < 10)                            {lcd.setCursor(4, 0); lcd.print(data_sensor_batt);lcd.setCursor(5, 0); lcd.print("  ");} else
     if (data_sensor_batt >= 10 && data_sensor_batt < 100) {lcd.setCursor(4, 0); lcd.print(data_sensor_batt);lcd.setCursor(6, 0); lcd.print(" "); } else
                                                           {lcd.setCursor(4, 0); lcd.print(data_sensor_batt);}
    /*  if (interval > 1) 
          {
            lcd.setCursor(0, 3); 
            lcd.print("GPRS CONNECT"); 
            lcd.setCursor(12, 3); 
            lcd.print(interval);
         
            };*/
 

    
    
   /* if (interval == 2) 
    {
 
   
    ///==============================Настройка контекста и открытие соединения==========================\\\\\\\\\\\\\\\\\\\\
    sendATCommand("ATE0", true);               // отключаем возврат команд от модема
    sendATCommand("AT+CMGF=1", true);          //PDU режим приема и отправки SMS  
   // sendATCommand("AT+CMGD=0,4", true);  
    sendATCommand("AT+CLIP=1", true);          // включаем АОН
    sendATCommand("ATS0=0", true);             // вручную поднимать трубку при входящем звонке  
    sendATCommand("AT+CMGF=0", true);          //PDU режим приема и отправки SMS  
   // sendATCommand("AT+CMGDA=\"DEL READ\"", true);  
      
    sendATCommand("AT+SAPBR=2,1", true); 
    sendATCommand("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", true); 
    sendATCommand("AT+SAPBR=3,1, \"APN\",\""+APN+"\"", true); 
    sendATCommand("AT+SAPBR=1,1", true);

    
  
    sendATCommand("AT+CIPSTART=\"TCP\",\""+MQTT_SERVER+"\",\""+PORT+"\"", true),lcd.setCursor(0, 3); lcd.print("GPRS CONNECT"); 
    };  */
    
    if (interval>0){interval--;};    
                
}  



 // ---------------- ТРАНСЛИРУЕМ КОМАНДЫ из ПОРТА В МОДЕМ ---------------------------------- 
void resp_serial ()
      {    
     String at = "";   
     while (Serial.available()) {at = Serial.readString();}
  //int k = 0;
   //while (Serial.available()) k = Serial.read(),at += char(k),delay(1);
     SIM800.println(at);
     at = "";  
     //Serial.println("v modem");  Serial.println(at);
       }   


void sendPingPacket() {

  String time_800;
   Serial.println("ping_start");
  if (interval==0){
   time_800 = sendATCommand("AT+CCLK?", true);
    if (time_800.indexOf("+CCLK:",0) > -1 )
    {
                 chas = time_800.substring(time_800.indexOf("+CCLK:",0)+17, time_800.indexOf("+CCLK:",0)+19).toInt(); 
                 minut = time_800.substring(time_800.indexOf("+CCLK:",0)+20, time_800.indexOf("+CCLK:",0)+22).toInt();
 //                Serial.print (chas);
 //                Serial.print (":");
 //                Serial.println (minut);
     }
           
    if (chas < 10) {lcd.setCursor(14, 3);
                    lcd.print ("0"); 
                    lcd.setCursor(15, 3);
                    lcd.print (chas);
                   } else
                   {
                    lcd.setCursor(14, 3);
                    lcd.print (chas);   
                   }
  //  lcd.setCursor(16, 3);
  //  lcd.print (":");
    if (minut < 10){lcd.setCursor(17, 3);
                    lcd.print ("0"); 
                    lcd.setCursor(18, 3);
                    lcd.print (minut);
                   } else
                   {
                    lcd.setCursor(17, 3);
                    lcd.print (minut);   
                   }
                   
   sendATCommand("AT+CIPSEND", true);
  //==================ping=========================\\
 // SIM800.write((byte)0xC0); // Ping что бы всегда был коннект  
 // SIM800.write((byte)0x00); // Remaining Length
  //==================send data vmesto ping=======================\\

     TempDS[0] = bme.readTemperature();          // читаем 
     TempDS[1] = bme.readPressure();             // читаем давление 
     TempDS[2] = bme.readHumidity();             // читаем влажность

  
      MQTT_FloatPub ("/sma-etu@yandex.ru/te",      TempDS[0],0);                // посылаю данные раз в 20 секунд,  ==== температуру
    //  delay(1000);
      MQTT_FloatPub ("/sma-etu@yandex.ru/po",      TempDS[4],2);              // посылаю данные раз в 20 секунд   ==== заряд батареи 
     //  delay(1000); 
      MQTT_FloatPub ("/sma-etu@yandex.ru/vl",    TempDS[3],0);            // посылаю данные раз в 20 секунд   ==== влажность почвы
  
    
    MQTT_PUB ("/sma-etu@yandex.ru/st", "65280");  
    SIM800.write((byte)0x1A); // Remaining Length
    
    Time4 = millis();
    Serial.println("ping_end");   
  }     

}



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


void MQTT_CONNECT () {
      Serial.println("MQTT_CONNECT_start");
      lcd.setCursor(0, 3); lcd.print("GPRS ON         ");  
     // lcd.setCursor(11, 3); lcd.print("   ");
     // lcd.setCursor(12, 3); lcd.print(" ");  
     // lcd.setCursor(13, 3); lcd.print(" ");      
  sendATCommand("AT+CIPSEND", true);
     
  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(0xC0);
  SIM800.write((byte)0);
  SIM800.write(0x3C); // Keep Alive LSB (10) - 60 sec
  
  SIM800.write((byte)0), SIM800.write(strlen(MQTT_CID)),  SIM800.write(MQTT_CID);  // MQTT  идентификатор устройстваAT+SAPBR
  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 ("/sma-etu@yandex.ru/st", "65280");                                                   // пакет публикации  
 // MQTT_SUB ("/sma-etu@yandex.ru/co");                                                            // пакет подписки на присылаемые команды  
  MQTT_SUB ("/sma-etu@yandex.ru/od");                                                          // температура при которой дверь откроется
 // MQTT_SUB ("/sma-etu@yandex.ru/cd");                                                       // температура при которой дверь закроется  
 // MQTT_SUB ("/sma-etu@yandex.ru/ok");                                                          // влажность при которой дверь откроется
  //MQTT_SUB ("/sma-etu@yandex.ru/ck");   
     
  SIM800.write(0x1A);   
   Serial.println("MQTT_CONNECT_end");}                                         // маркер завершения пакета

void  MQTT_PUB (const char MQTT_topic[32], 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[24]) {                                       // пакет подписки на топик
  
  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 resp_modem (){     //------------------ АНЛИЗИРУЕМ БУФЕР ВИРТУАЛЬНОГО ПОРТА МОДЕМА------------------------------
     String  at = "";
     //while (SIM800.available()) at = SIM800.readString();  // набиваем в переменную at
  int k = 0;
   while (SIM800.available()) k = SIM800.read(),at += char(k),delay(1);           
  // Serial.println("1111111111111");
   Serial.println(at);  
   

if (at.indexOf("+CLIP:") > -1)  {SIM800_reset(); delay (10000), interval = 3 ;}  // костыль 2
else if (at.indexOf("SMS Ready") > -1 || at.indexOf("NO CARRIER") > -1 ) {sendATCommand("AT+CLIP=1;+DDET=1", true);} // Активируем АОН и декодер DTMF
/*  -------------------------------------- проверяем соеденеиние с ИНТЕРНЕТ, конектимся к серверу------------------------------------------------------- */
//else if (at.indexOf("+SAPBR: 1,3") > -1)                                  {SIM800.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\""),     lcd.setCursor(1, 3); lcd.print(at); delay(200);} 
//else if (at.indexOf("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\r\nOK") > -1)    {SIM800.println("AT+SAPBR=3,1, \"APN\",\""+APN+"\""),  lcd.setCursor(1, 3); lcd.print(at); delay (500); }
//else if (at.indexOf("AT+SAPBR=3,1, \"APN\",\""+APN+"\"\r\r\nOK") > -1 )   {SIM800.println("AT+SAPBR=1,1"),  lcd.setCursor(1, 3); lcd.print("GPRS CONNECT"); interval = 2 ;} // устанавливаем соеденение   
//else if (at.indexOf("+SAPBR: 1,1") > -1 )        {delay (200),  SIM800.println("AT+CIPSTART=\"TCP\",\""+MQTT_SERVER+"\",\""+PORT+"\""),  lcd.setCursor(1, 3); lcd.print(at); delay (1000);}
else if (at.indexOf("CONNECT FAIL") > -1 )       {SIM800_reset();  interval = 3 ;}  // костыль 1
else if (at.indexOf("CLOSED") > -1 )             {SIM800_reset();   interval = 3 ;}  // костыль 2
else if (at.indexOf("+CME ERROR:") > -1 )        {SIM800_reset();  interval = 3 ;}   // костыль 4 
else if (at.indexOf("CONNECT OK") > -1){MQTT_CONNECT(); }
  
//else if (at.indexOf("CCLK") > -1){Serial.println("time");}

 
else if (at.indexOf("/sma-etu@yandex.ru/",4) > -1 )      {  
                 sendATCommand("AT+CIPSEND", true);
                 MQTT_FloatPub ("/sma-etu@yandex.ru/", 1 ,2);                      
                 SIM800.write((byte)0x1A); // Remaining Length
                 lcd.setCursor(0, 1); lcd.print("POLIV OFF "); 
  }         
else if (at.indexOf("/sma-etu@yandex.ru/",4) > -1 )      { 
                 sendATCommand("AT+CIPSEND", true);
                 MQTT_FloatPub ("/sma-etu@yandex.ru/", 0,2);                 
                 SIM800.write((byte)0x1A); // Remaining Length
                 lcd.setCursor(0, 1); lcd.print("POLIV ON "); 
  }      
                           
else if (at.indexOf("/sma-etu@yandex.ru/od",4) > -1 )     {
                 temperatura_open = at.substring(at.indexOf("/sma-etu@yandex.ru/od",4)+12, at.indexOf("/sma-etu@yandex.ru/od",4)+14).toInt(); 
                 temperatura_open = temperatura_open * 100;            
                // Serial.print("temperatura_open="); Serial.println(temperatura_open);
                 lcd.setCursor(18, 1); 
                 lcd.print(temperatura_open/100);
  }
                                                  
else if (at.indexOf("/sma-etu@yandex.ru/cd",4) > -1 )     {
                 temperatura_clouse = at.substring(at.indexOf("/sma-etu@yandex.ru/cd",4)+15, at.indexOf("/sma-etu@yandex.ru/cd",4)+17).toInt(); 
                 temperatura_clouse = temperatura_clouse * 100;        
                // Serial.print("temperatura_clouse="); Serial.println(temperatura_clouse);
                 lcd.setCursor(15, 1); 
                 lcd.print(temperatura_clouse/100 );
  }



else if (at.indexOf("/sma-etu@yandex.ru/ok",4) > -1 )     {
                  vlaj_otk = at.substring(at.indexOf("/sma-etu@yandex.ru/ok",4)+10, at.indexOf("/sma-etu@yandex.ru/ok",4)+12).toInt(); 
                 // vlaj_otk =  vlaj_otk;            
                // Serial.print(" vlaj_otk="); Serial.println( vlaj_otk);
                 lcd.setCursor(9, 1); 
                 lcd.print(vlaj_otk);
  }
                                                   
else if (at.indexOf("/sma-etu@yandex.ru/ck",4) > -1 )     {
                 vlaj_zakr = at.substring(at.indexOf("/sma-etu@yandex.ru/ck",4)+12, at.indexOf("/sma-etu@yandex.ru/ck",4)+14).toInt(); 
                 //vlaj_zakr = vlaj_zakr;        
                // Serial.print("vlaj_zakr="); Serial.println(vlaj_zakr);
                 lcd.setCursor(12, 1); 
                 lcd.print(vlaj_zakr );
  }  
 at = "";
                              
 } 


void SIM800_reset()  // перезагрузка модема 
           { Serial.println("RESET MODEM");
             lcd.setCursor(0, 3);
             lcd.print("GPRS RESET "); 
             digitalWrite(reset_sim800, LOW);
             delay (5000);
             digitalWrite(reset_sim800, HIGH);
             delay (5000);
             lcd.setCursor(0, 3);
             lcd.print("GPRS LOAD  0%"); 
             sendATCommand("AT+CFUN=1,1", true);
             sendATCommand("AT+CLTS=1", 1);
             sendATCommand("AT&W", 1);
             lcd.setCursor(10, 3);
             lcd.print("25"); 
             sendATCommand("ATE0", true);               // отключаем возврат команд от модема
             sendATCommand("AT+CMGF=0", true);          //PDU режим приема и отправки SMS  
              // sendATCommand("AT+CMGD=0,4", true);  
             lcd.setCursor(10, 3);
             lcd.print("50"); 
             sendATCommand("AT+CLIP=1", true);          // включаем АОН
             sendATCommand("ATS0=0", true);             // вручную поднимать трубку при входящем звонке  
             sendATCommand("AT+CMGF=0", true);          //PDU режим приема и отправки SMS  
            // sendATCommand("AT+CMGDA=\"DEL READ\"", true);  
            sendATCommand("AT+SAPBR=2,1", true); 
            lcd.setCursor(10, 3);
            lcd.print("70"); 
            sendATCommand("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", true); 
            sendATCommand("AT+SAPBR=3,1, \"APN\",\""+APN+"\"", true); 
            lcd.setCursor(10, 3);
            lcd.print("80");
            sendATCommand("AT+SAPBR=1,1", true);
            lcd.setCursor(10, 3);
            lcd.print("90"); 
            sendATCommand("AT+CIPSTART=\"TCP\",\""+MQTT_SERVER+"\",\""+PORT+"\"", true);
            lcd.setCursor(0, 3);
            lcd.print("GPRS CONNECT "); 
             
            //Serial.println("RESET END");
            } 
            
            
void ClouseDoor(unsigned long ms)
{
   lcd.setCursor(0, 1); 
   if (flag_door_super_open == 1) {lcd.print("DOOR ON  ");} else  {lcd.print("DOOR OFF ");}
   digitalWrite(rel2,LOW );   // CLOUSE
   delay (ms);
   digitalWrite(rel2, HIGH);   // CLOUSE
 }

void OpenDoor(unsigned long ms)
{
   lcd.setCursor(0, 1); 
   if (flag_door_super_open == 1) {lcd.print("DOOR S ON");} else  {lcd.print("DOOR ON  ");}
   digitalWrite(rel1, LOW );   // open
   delay (ms);
   digitalWrite(rel1, HIGH);   // open
  }

void ClouseKran(unsigned long ms)
{
   lcd.setCursor(7, 0); 
   lcd.print("KRAN OFF");
   digitalWrite(rel3,LOW );   // CLOUSE
   delay (ms);
   digitalWrite(rel3, HIGH);   // CLOUSE
 }       
void OpenKran(unsigned long ms)
{
   lcd.setCursor(7, 0); 
   lcd.print("KRAN ON ");
   digitalWrite(rel4,LOW );   // CLOUSE
   delay (ms);
   digitalWrite(rel4, HIGH);   // CLOUSE
 }

 

 

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

sma-etu пишет:



 другой брокер,www.dioty.co. Возникли трудности.

смотреть логи брокера - искать что ему не нравиться

sma-etu
Offline
Зарегистрирован: 17.06.2020

Не подскажите каким образом это делается?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Обычно - глазами.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Logik пишет:

andycat пишет:

 использовать software serial из коробки можно только для вывода какого нибудь не критичного лога. 

Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial  его положит. Он просто не может стабильно работать не убив все вокруг.

Есть еще CustomSoftwareSerial, SomeSerial, я их использую

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

Logik пишет:

andycat пишет:

 использовать software serial из коробки можно только для вывода какого нибудь не критичного лога. 

Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial  его положит. Он просто не может стабильно работать не убив все вокруг.

Есть еще CustomSoftwareSerial, SomeSerial, я их использую

А какая, собственно, разница?

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

PS. Лично я программный COM-порт не использую. Где-то при отладке - еще может быть, а в готовом изделии - никогда.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

А какая, собственно, разница?

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

PS. Лично я программный COM-порт не использую. Где-то при отладке - еще может быть, а в готовом изделии - никогда.

 использует PCINT однако, только захватывает все прерывания, править библиотеку приходится освобождая ненужные, DetSimen написал библиотеку для радиолюбителей использующую софтовый сериал, всё работает при правильном подходе )))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

 использует PCINT однако, только захватывает все прерывания, править библиотеку приходится освобождая ненужные,

Ну переписали мы таким образом библиотеку. Ну пошли у нас прерывания со стороны. И вот тут каждое устройство стало тянуть одеяло на себя. И кто-то из них в этом перетягивании однозначно проиграет. Чудес не бывает: либо с софтсериал полезут ошибки, либо другое устройство будет работать ненормально со всеми вытекающими.

Цитата:

DetSimen написал библиотеку для радиолюбителей использующую софтовый сериал, всё работает при правильном подходе )))

Вот именно - при правильном! А отключить часть пинов от pcint и думать, что все проблемы уже решены - подход явно неправильный.

jeday56
Offline
Зарегистрирован: 05.12.2021

Подскажите как использовать Willmessage. После установки флагов как указать топик и сообщение?