SD кажется слишком медленным для SMTP

communication ethernet sd web-service

Я тоже задавал этот вопрос на форуме arduino.

Я использовал SMTP до использования client.print (и client.println), но теперь я пытаюсь переместить как можно больше текста из оперативной памяти на SD (и поэтому мне нужна библиотека <SD.h>). Это не работает, и я думаю, что это может быть потому, что SMTP-сервер "умирает от скуки", ожидая, когда мой Arduino прочитает с SD-карты и запишет ее клиенту (серверу?). В приведенном ниже коде я включил то, что я пытаюсь (оно будет раскомментировано, если вы скопируете+вставите код), и то, что уже работает (что будет прокомментировано, когда вы скопируете+вставите код, но вы можете раскомментировать и прокомментировать другой раздел относительно легко). Текстовый файл у меня есть на SD-карте в коде (с комментариями). Если кто-нибудь может придумать обходной путь, это было бы здорово.

#include <SPI.h>
#include <SD.h>
#include <Ethernet.h>

//-v--- Ethernet -----------
byte MyMac[] = {0xFE, 0xED, 0xBE, 0xEF, 0xFE, 0xED}; // <- The physical address of the machine's network card. Should be unique (no two network cards have the same MAC address)
byte MyIp[] = {1, 1, 1, 1}; // <- This is the not the real IP address, but for the real address I have verified that the static IP works for sending mail
byte Dns[] = {1, 1, 1, 1}; // <- Not the real DNS but I got it once through Serial.println(Ethernet.dnsServerIP()); and I know that it works
byte Gateway[] = {1, 1, 1, 1}; //<- Not real
byte Subnet[] = {1, 1, 1, 1}; //<- Not Real

EthernetClient client ;
//-^--- Ethernet -----------

//-v-- Smtp --------
char ServerChar[] = "blahblah";
//-^-- Smtp --------

//-v--- SD ------
File theFile; String line;
//-^--- SD ------

void setup() {
  Ethernet.begin(MyMac, MyIp, Dns, Gateway, Subnet);
  SD.begin(4);
  bool test = TrySend();
}

void loop() {
  // put your main code here, to run repeatedly:
 
}

bool TrySend(){
 
  //*-v---- What I am trying ---
  bool SuccessOrNot;
 
  if(client.connect(ServerChar, 25)){
    SuccessOrNot = true;
    theFile = SD.open("Smtp.txt");   //Smtp.txt is listed toward the bottom of the code
   
    if(theFile){
      while(theFile.available()){
        client.write( theFile.read() );
      }
      theFile.close();
    }
  }
 
  else{ SuccessOrNot = false; }
  return SuccessOrNot;
  //-^---- What I am trying --- */
 
  /*-v-- The following works if used in place of [What I am trying] ---
  bool SuccessOrNot;
 
  if(client.connect(ServerChar, 25)){
    SuccessOrNot = true;
    client.println("EHLO ktlan");
    client.println("AUTH LOGIN");
    //-v- Most SMTP servers require verification in the form of base64-encoded username and base64-encoded password. However, since your IP must be whitelisted by the SMTP server, you don't need authentication
    //client.println("ThisIsInBase64"); // Encoded version of '[email protected]'
    //client.println("ThisIsInBase64"); // Encoded version of the password
    //-^-
    client.println("MAIL FROM:<[email protected]>");
    client.println("RCPT TO:<[email protected]>");
    client.println("DATA");
    client.println("to:[email protected]");
    client.println("from:[email protected]");
    client.print("SUBJECT: TRIGGER");
    client.println();
    client.println("The temperature Monitor Triggered.");
    client.println(".");
    client.println("QUIT");
  }
  else{ SuccessOrNot = false; }
 
  //-^-- The following works if used in place of [What I am trying] ---*/
}

/*-v--- Smtp.txt -------
EHLO ktlan
AUTH LOGIN
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
DATA
to:[email protected]
from:[email protected]
SUBJECT: TRIGGER

The temperature Monitor Triggered.
.
QUIT

//-^--- Smtp.txt -------*/

// NO NEED for authentication. For many Smtp servers you need:
//client.println("ThisIsInBase64"); // Encoded version of '[email protected]'
//client.println("ThisIsInBase64"); // Encoded version of the password
// My IP must be whitelisted by the SMTP server, and since it is, I don't need authentication

, 👍1

Обсуждение

Было бы очень полезно также увидеть SMTP-серверную сторону вещей (журналов), если у вас есть к ней доступ. Кроме того, вы не ждете никаких ответов от сервера, поэтому нет способа определить, когда сервер готов к вашей следующей команде., @StarCat

Вы читаете и пишете байт за раз, что может быть не оптимальным. Попробуйте сделать это большими кусками (размер страницы SD, если у вас достаточно памяти), @Mat

Многие почтовые серверы откажутся обслуживать клиента, который отправляет EHLO, прежде чем он отправит свой идентификационный баннер., @Majenko

Спасибо всем. Добавил "ReadClient()", он работает []. Пробовал readStringUntil(), печатать построчно, работает [], пробовал не возвращать bool, работает (!?) ... вернитесь обратно к исходному коду, работает []. Я говорю [], потому что при повторной загрузке кода электронная почта отправляет, но не отправляет другую при сбросе кнопки и не отправляет, если повторно загружается с активным последовательным монитором. Был 1 раз в устранении неполадок, он работал полностью, и я видел вывод клиента на последовательный монитор и электронную почту при каждом сбросе. Не мог воспроизвести. Извините за неясность: поскольку я утверждаю, что результаты неповторимы, я должен опубликовать [длинные] инструкции. Я переустанавливаю &, если вы это сделаете., @elscan


1 ответ


1

Попробуйте более простой подход (с некоторым рефакторингом кода)

bool TrySend(){
 
  if(client.connect(ServerChar, 25)){
    theFile = SD.open("Smtp.txt");
   
    if(theFile){
      while(theFile.available()){
        client.print(theFile.readStringUntil('\n'));
        client.print('\n');
      }
      theFile.close();
      return true;
    }
  }
  return false;
}

В качестве примечания вы можете рассмотреть некоторую лучшую структуру кода (например, локальные переменные). Но я предполагаю, что это всего лишь образец/тест. Кроме того, приведенный выше код предполагает, что файл использует \r\n в конце каждой строки. Если у него есть только \n, то вы можете просто использовать: client.println(файл.readStringUntil('\n')); (обратите внимание на печать*ln*). println отправляет оба \r\n.

,