Как стать автором
Обновить

Бесплатная отправка SMS из Arduino без GSM модуля

DIY или Сделай сам


Понадобилось мне слать SMS из ардуинины себе на телефон. Да так, что бы без заморочек с GSM, сим картами и оплатой. Под катом то, что из этого вышло.

Раз GSM не подходит, то слать придется через интернет. В закромах имелся сверх дешевый Wi-Fi модуль ESP8266. Про его предварительную настройку можно почитать в этой отличной статье ссылка.
Перво-наперво полез гуглить различные интернет-сервисы для отправки SMS. Сервисов оказалось много, но вот подходящего среди них не оказалось. Либо 10 SMS в день, либо хотят денег. Да и капчи ардуинине не по зубам. Но тут совершенно случайно наткнулся на на интересный сервис своего мобильного оператора (MTS BY) — всего за 1$ можно подключить услугу приема email в виде SMS ссылка. Что же, полностью бесплатно не получилось, и после оплаты я получил почтовый адрес вида 375XXYYYYYYY@sms.mts.by ( где XX и YYYYYYY — код сети и номер). То есть все свелось к банальной отправке email из arduino.

Но не тут-то было. Оказывается в последнее время все уважающие себя почтовые сервера отказываются принимать почту по 25 порту и без шифрования. А с другими связываться не хотелось, как и привязываться к своему домашнему серверу. Нагуглил вот такой сервис ссылка. В базовом бесплатном варианте дают 6к писем в месяц, что для моего домашнего использования хватает с головой. После регистрации идем в настройки и видим адрес smtp сервера, порт, логин и сгенерированный нам пароль.

Быстро накатал скетч, отправляю email 375XXYYYYYYY@sms.mts.by и… Облом. Отправляю на обычную почту — приходит. Пытался так и эдак переделывать заголовок — все равно письма исчезают в безднах серверов МТС, явно попадая в котел спам фильтра.

Значит нужно «отмыть» почту. В качестве сервиса отмывки выбрал (тихо ненавидимый мною за рекламу) mail.ru. Для отмывки в настройках почты, в разделе «Фильтры и пересылка», создал новое правило:
Настройки
После создания фильтра его понадобилось активировать введя код, пришедший в виде email-SMS на телефон.
Вот и момент триумфа — отправляю email из ардуинины, и через минуту телефон раздается радостным сигналом оповещения, при этом пугая проходящего рядом кота.

Далее скучные технические подробности.
В качестве платы взял Arduino Mega 2560, так как в нем целых три дополнительных последовательных порта (хотя можно и обычный UNO, только дебажить будет сложнее).
ESP8266 подключен: GND -> GND, VCC и CH_PD -> +3.3V, RX -> TX3, TX -> RX3. Скорость ESP8266 настроена на 115200 бод.
Для общения с smtp сервером нужно закодировать свои логин и пароль в Base64.
Можно воспользоваться консолью Linux:
openssl enc -base64 <<< 'email@gmail.com'
openssl enc -base64 <<< 'password'
Или же каким-либо онлайн сервисом, например ссылка.
Ну и собственно код скетча. После включения отправляется СМС и код уходит в вечный цикл. Дополнительные библиотеки не использовал.
Код
#define SSID "wi-fi_login" // ваш SSID
#define PASS "wi-fi_password" // ваш пароль Wi-Fi

#define SMTPServer "s02.atomsmtp.com" //smtp сервер
#define SMTPPort "2525" // smtp порт
#define MailLogin "smtp_example@gmail.com" // логин для smtp
#define MailLoginBase64 "dWd1LCBrb25lNG5vCg==" //логин для smtp в Base64
#define MailPasswordBase64 "aHJlbiB0YW0K" // пароль для smtp в Base64
#define MailRelay "example@mail.ru" // промежуточная почта для "отмывания" email
#define PhoneNumber "375290000000" // номер телефона
#define Message "Hello from Arduino!" //сообщение

#define SERIAL_RX_BUFFER_SIZE 256
#define SERIAL_TX_BUFFER_SIZE 256

void setup()
{
	delay(2000);
	Serial3.begin(115200);
	Serial3.setTimeout(5000);
	Serial.begin(115200); // для отладки
	Serial.println("Init");
	Serial3.println("AT+RST"); // сброс и проверка, что модуль готов
	if(WaiteString("Ready", 5000)) {
		while(Serial3.available()) { Serial3.read();}
		Serial.println("WiFi - Module is ready");
	}else{
		Serial.println("Module dosn't respond.");
		while(1);
	}
	delay(100);

	Serial3.println(" AT+CIPMODE=0");
	WaiteString("OK");
	while(Serial3.available()) { Serial3.read();}

	Serial3.println("AT+CIPMUX=1");
	WaiteString("OK");
	while(Serial3.available()) { Serial3.read();}

	// try to connect to wifi
	boolean connected = false;
	for(int i=0;i<5;i++) {
		if(connectWiFi()) {
			connected = true;
			break;
		}
	}
		if (!connected) {
		while(1);
	}
}
void loop()
{
	String cmd = "AT+CIPSTART=0,\"TCP\",\"";
	cmd += String(SMTPServer);
	cmd += "\"," + String(SMTPPort);
	Serial3.println(cmd);

	if(WaiteString("Linked", 5000)) {
		while(Serial3.available()) { Serial3.read();}
		Serial.println("Link");
	}
	else {
		Serial.println("Link fail");
		while (1);
	}

	if (WaiteString("OK", 2000)) {
		while(Serial3.available()) { Serial3.read();}
	}
	else {
		while (1);
	}
  
	Send("HELO 1.2.3.4", true);
	Send("AUTH LOGIN", true);
	Send(MailLoginBase64, true);
	Send(MailPasswordBase64, true);
	Send("MAIL FROM:<" + String(MailLogin) + ">", true);
	Send("RCPT TO:<" + String(MailRelay) + ">", true);
	Send("DATA", true);
	Send("Subject:SMS", false);
	Send("To:\"" + String(PhoneNumber) + "\" <" + String(PhoneNumber) + "@sms.mts.by>", false);
	Send("From: <" + String(MailLogin) + ">", false);
	Send("", false);
	Send(Message, false);
	Send(".", true);
	Send("QUIT", true);

	while(1) {};
}
 
boolean connectWiFi()
{
  Serial3.println("AT+CWMODE=1");
  while (!Serial3.available())	{ delay(10);}
  while (Serial3.available()) {Serial3.read();}
  String cmd="AT+CWJAP=\"";
  cmd+=SSID;
  cmd+="\",\"";
  cmd+=PASS;
  cmd+="\"";
  Serial3.println(cmd);

  if(WaiteString("OK", 8000)){
    Serial.println("Connected to WiFi.");
    return true;
  }else{
    Serial.println("Can not connect to the WiFi.");
    return false;
  }
}

bool Send(String S, bool wait) {
	Serial3.print("AT+CIPSEND=0,");
	Serial3.println(S.length()+2);
	while (!Serial3.available()) { delay(10);}
	if(Serial3.find(">")){
	}else{
		Serial3.println("AT+CIPCLOSE=0");
		delay(1000);
		return false;
	}
	Serial3.print(S + "\r\n");//добаяляем перевод строки
	if (WaitString("OK", 15000)) {
		if (wait) {
			WaitString("+IPD", 15000);
			while(Serial3.available()) {
				Serial3.read();}}
		return true;}
	else {
		return false;}
}

void WaiteString(String S) {
	int L = S.length();
	String T = String(" ");
	while(1) {
		if (Serial3.available()) {
			char c = Serial3.read();
			T = T + String(c);
			if (T.length() > L) T = T.substring(1);
			if (S.charAt(0) == T.charAt(0))
			if (S.compareTo(T) == 0) return;
		}
		else {
			delay(1);
		}
	}
}

bool WaiteString(String S, int Time) {
	int L = S.length();
	String T = String(" ");
	while(Time>0) {
		if (Serial3.available()) {
			char c = Serial3.read();
			T = T + String(c);
			if (T.length() > L) T = T.substring(1);
			if (S.charAt(0) == T.charAt(0))
			if (S.compareTo(T) == 0) return true;
		}
		else {
			delay(1);
			Time--;
		}
	}
	return false;
}

String WaiteString(int Time) {
	String T = String("");
	while(Time>0) {
		if (Serial3.available()) {
			char c = Serial3.read();
			T = T + String(c);
		}
		else {
			delay(1);
			Time--;
		}
	}
	return T;
}
Теги:
Хабы:
Всего голосов 53: ↑45 и ↓8 +37
Просмотры 100K
Комментарии Комментарии 46