Формирование строки текста тела email сообщения

DZ
Offline
Зарегистрирован: 19.12.2018
Есть задача отправлять по емейлу через GPRS показания датчиков температуры и влажности + время
В наличии:
ДАТЧИК ТЕМПЕРАТУРЫ DS18B20
ДАТЧИК ТЕМПЕРАТУРЫ И ВЛАЖНОСТИ DHT22
GSM модуль SIM800L
модуль ЧРВ на базе чипа DS3231
    
Не могу сформировать строку текста тела сообщения. 
С отправкой СМС строка работает и СМС приходит как нужно, с мылом сбоит. Компиляция проходит, а вот после загрузки в Ардуино мыло не отправляется. Если выбросить блок формирования тела сообщения - письмо уходит. 
 
    
sendATCommand("AT+SMTPBODY=75", true);           // количество символов сообщения

    String (Time) = time.gettime("d-m-Y, H:i:s");
    float h = dht.readHumidity();                    // влажность
    float t_out = dht.readTemperature();             // температура внешняя
    detectTemperature();                             // Определяем внешнюю температуру от датчика DS18b20

    String (message) = (String (Time) + ";" + "Ves: " + String(scale_dat, 3) + "kg" + ";" + " t out:" + String(t_out, 3) + "*C" + ";" + " Vlagnost:" + String(h, 3) + "%" + ";" + " t in:" + String(temperature2, 3) + "*C");

    sendATCommand(message + "\r\n" + (String)((char)26), true);                              //После получение ответа от модуля DOWNLOAD. вводим текст письма
                                                                                             //Для отправки в конце сообщения отправляем символ SUB ( (char)26 или Cntrl+Z)
    sendATCommand("AT+SMTPSEND", true); // отправка email     





int detectTemperature()  
{
  byte data[2];
  ds.reset();// Начинаем взаимодействие со сброса всех предыдущих команд и параметров
  ds.write(0xCC); // Даем датчику DS18b20 команду пропустить поиск по адресу. В нашем случае только одно устрйоство
  ds.write(0x44); // Даем датчику DS18b20 команду измерить температуру.
  // Само значение температуры мы еще не получаем - датчик его положит во внутреннюю память

  if (millis() - lastUpdateTime > TEMP_UPDATE_TIME)
  {
    lastUpdateTime = millis();
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);      // Просим передать нам значение регистров со значением температуры
    data[0] = ds.read(); // Читаем младший байт значения температуры
    data[1] = ds.read(); // А теперь старший

    //    Формируем значение
    temperature = (data[1] << 8) + data[0]; temperature = temperature >> 4;

    //    Формируем итоговое значение:
    //    - сперва "склеиваем" значение,
    //    - затем умножаем его на коэффициент, соответсвующий разрешающей способности (для 12 бит по умолчанию - это 0,0625)
    float temperature2 =  ((data[1] << 8) | data[0]) * 0.0625;

    // Выводим полученное значение температуры в монитор порта
    Serial.println(temperature2);

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А где формирование сообщения?

DZ
Offline
Зарегистрирован: 19.12.2018

Ну собственно это по идее должно работать так: 

Берем данные с датчиков, 

 и формируем message для Email

String (message) = (String (Time) + ";"  " t out:" + String(t_out, 3) + "*C" ";" " Vlagnost:" + String(h, 3) + "%" ";" " t in:" + String(temperature2, 3) + "*C");

потом передаем через функцию sendATCommand в SIM800. 

Код строю на основе кода этого парня http://codius.ru/articles/GSM_%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_SIM800L_%D1%87%D0%B0%D1%81%D1%82%D1%8C_2

Код Виктора работает идеально. Мне нравится. 

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

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так "по идее"? Или у Вас есть код? Ничего не понял. Если есть, так чего не выложить? Если есть только идеи, так реализуйте.

DZ
Offline
Зарегистрирован: 19.12.2018

Ну и зачем нужно было себя так утруждать таким ответом?  Нужна всего 1 текстовая строчка, которую нужно сформировать с данных датчиков.  Зачем захламлять большим кодом? 

Код конечно есть.

#include <SoftwareSerial.h> 
#include <iarduino_RTC.h>   
#include <OneWire.h>        
#include <DHT.h>            
#include <DHT_U.h>            

iarduino_RTC time(RTC_DS3231);                       // Объявляем объект time для модуля на базе чипа DS3231

SoftwareSerial SIM800(8, 9); // RX — 9, TX -8
String _response = "";                               // Переменная для хранения ответа модуля

OneWire ds(10); // Создаем объект OneWire для шины 1-Wire, с помощью которого будет осуществляться работа с датчиком
int temperature = 0; // Глобальная переменная для хранения значение температуры с датчика DS18B20
long lastUpdateTime = 0; // Переменная для хранения времени последнего считывания с датчика
const int TEMP_UPDATE_TIME = 2000; // Определяем периодичность проверок

#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  Serial.begin(9600);  // для весов, датчика температуры ds18b20, датчика температуры DHT22
  time.begin();        // Инициируем RTC модуль
  dht.begin();
  Serial.begin(9600); //Скорость сериал порта
  SIM800.begin(9600); //Скорость порта для связи ARDUINO NANO c SIM800l
}


void loop()
{
  
  if (time.minutes == 00 && time.seconds == 0)
  {
    sendATCommand("AT+CFUN=1,1", true);                // перезагрузка модуля при запуске
    sendATCommand("AT", true);                         // Отправили AT для настройки скорости обмена данными

    //Настройки интернет соединения
    sendATCommand("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", true);                               // задаем команду выхода в интернет
    sendATCommand("AT+SAPBR=3,1,\"APN\",\"internet\"", true);                               // настройки APN Vodafone
    sendATCommand("AT+SAPBR=1,1", true);                                                    // To open a GPRS context. установить GPRS соединение

    //Настройки для отправки e-mail :
    //Настройки для отправки e-mail :
    sendATCommand("AT+EMAILCID=1", true);                                                    // Установка CID параметра для email сессии.
    sendATCommand("AT+EMAILTO=30", true);                                                    // Set EMAIL timeout Установка таймаута для SMTP и POP серверов.
    sendATCommand("AT+EMAILSSL=0", true);
    sendATCommand("AT+SMTPSRV=\"SMTP.GMAIL.COM\"", true);                                    // Установка адреса и порта SMTP почтового сервера.
    sendATCommand("AT+SMTPAUTH=1,\"*****@gmail.com\",\"******\"", true);                     // Аутентификация (e-mail адрес, и пароль от e-mail)
    sendATCommand("AT+SMTPFROM=\"******@gmail.com\",\"*****\"", true);                       //от кого письмо (почтовый адрес, имя отправителя)
    sendATCommand("AT+SMTPSUB=\"Test\"", true);                                              //тема письма
    sendATCommand("AT+SMTPRCPT=0,0,\"******@gmail.com\",\"*******\"", true);                // кому письмо (почтовый адрес, имя получателя)
    sendATCommand("AT+SMTPBODY=75", true);

    String (Time) = time.gettime("d-m-Y, H:i:s");
    float h = dht.readHumidity();                    // влажность
    float t_out = dht.readTemperature();             // температура внешняя
    int temperature2 = detectTemperature();          // Определяем внутреннюю температуру от датчика DS18b20 - temperature2

    String (message) = (String (Time) + "; + " t out:" + String(t_out, 3) + "*C" + ";" + " Vlagnost:" + String(h, 3) + "%" + ";" + " t in:" + String(temperature2, 3) + "*C");

    sendATCommand(message + "\r\n" + (String)((char)26), true);                              //После получение ответа от модуля DOWNLOAD. вводим текст письма длиной 19 символов.
    //Для отправки в конце сообщения отправляем символ SUB ( (char)26 или Cntrl+Z)
    
    sendATCommand("AT+SMTPSEND", true);                                                      // Отправка Email
   
    sendATCommand("AT+SAPBR=0,1", true);                                                    //  разорвать GPRS соединение
  }

}

int detectTemperature()
{
  byte data[2];
  ds.reset();// Начинаем взаимодействие со сброса всех предыдущих команд и параметров
  ds.write(0xCC); // Даем датчику DS18b20 команду пропустить поиск по адресу. В нашем случае только одно устрйоство
  ds.write(0x44); // Даем датчику DS18b20 команду измерить температуру.
  // Само значение температуры мы еще не получаем - датчик его положит во внутреннюю память

  if (millis() - lastUpdateTime > TEMP_UPDATE_TIME)
  {
    lastUpdateTime = millis();
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);      // Просим передать нам значение регистров со значением температуры
    data[0] = ds.read(); // Читаем младший байт значения температуры
    data[1] = ds.read(); // А теперь старший

    //    Формируем значение
    temperature = (data[1] << 8) + data[0]; temperature = temperature >> 4;

    //    Формируем итоговое значение:
    //    - сперва "склеиваем" значение,
    //    - затем умножаем его на коэффициент, соответсвующий разрешающей способности (для 12 бит по умолчанию - это 0,0625)
    float temperature2 =  ((data[1] << 8) | data[0]) * 0.0625;

    // Выводим полученное значение температуры в монитор порта
    //Serial.println(temperature2);

  }

}



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(_resp);                                                                 // Дублируем ответ в монитор порта
  }
  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...");                                                          // ... оповещаем об этом и...
  }
  return _resp;                                                                            // ... возвращаем результат. Пусто, если проблема
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DZ пишет:

Ну и зачем нужно было себя так утруждать таким ответом?  Нужна всего 1 текстовая строчка, которую нужно сформировать с данных датчиков.  Зачем захламлять большим кодом? 

Вы решили поуить меня, как Вам помогать?

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

Вот когда Вы потрахаетесь полндя с тем, что у шибко умного новичка контроллер спонтанно перегружается, пялясь в клочок вполне нормального кода, а через часы траха узнаете, что он просто с ресета читает, вот тогда будете меня учить. А сейчас: я смотрю только полный код и никогда не смотрю куски. Это моё правило - "не хочете, не ешьте".

Вот, выложили полностью, сейчас попробую посмотреть

DZ
Offline
Зарегистрирован: 19.12.2018

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

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

Заранее спасибо что посмотрите. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Видимо, Вы пошутили, что 

DZ пишет:

 Компиляция проходит,

Просто посчитайте кавычки в строке №61 - их там нечётное количество.

В общем, или выкладывайте нормальный код,  или решайте свои проблемы самостоятельно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DZ пишет:

Нужно было сначала сказать зачем весь код, 

Да, нет, нужно было на просьбу выложить код, просто выложить код, а не начинать "Ну и зачем нужно было ...".

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Строка 14 - переменная имеет неправильный тип, надо unsigned long. Почему - да потому что у millis() какое возвращаемое значение?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Все строки - во флеш, макросом F().

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Строка 107 - объект типа String передаётся по значению, а надо - по ссылке, тогда не будет ненужной работы с оперативкой.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Строка 127 - опять неправильный тип переменной.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Строка 128 - условие будет неправильно работать при пееполнении millis(), т.е. при условии, когда millis() + 10000 - даст переход через 0. Источник трудноуловимых глюков раз в 50 дней :)

DZ
Offline
Зарегистрирован: 19.12.2018

ЕвгенийП Компиляция проходит если выбросить 2 строчки тела сообщения. 

String (message) = (String (Time) + "; + " t out:" + String(t_out, 3) + "*C" + ";" + " Vlagnost:" + String(h, 3) + "%" + ";" + " t in:" + String(temperature2, 3) + "*C");

sendATCommand(message + "\r\n" + (String)((char)26), true);
 
Я про это и говорил.  Я не могу их сформировать самостоятельно. Поэтому и обратился. 
b707
Offline
Зарегистрирован: 26.05.2017

DZ пишет:

 
Я про это и говорил.  Я не могу их сформировать самостоятельно. Поэтому и обратился. 

вам же уже сказали - число кавычек посчитайте. Неужели и кавычки сами расставить не можете?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DZ пишет:

ЕвгенийП Компиляция проходит если выбросить 2 строчки тела сообщения. 

String (message) = (String (Time) + "; + " t out:" + String(t_out, 3) + "*C" + ";" + " Vlagnost:" + String(h, 3) + "%" + ";" + " t in:" + String(temperature2, 3) + "*C");

sendATCommand(message + "\r\n" + (String)((char)26), true);
 
Я про это и говорил.  Я не могу их сформировать самостоятельно. Поэтому и обратился. 

Так я Вам и ответил - посчитайте кавычки.

А заодно, ответьте, пожалуйста, что значают глубокомысленные записи типа:

String (message)

String (Time) 

Вот, просто скажите,что они по Вашему означают?

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

А обратились Вы сюда не для того,чтобы Вам указали на ошибки, адля того, чтобы написали за Вас. Если так, то не по адресу - здесь есть раздел "Ищу исполнителя".