Постановка задачи.
В этом проекте посмотрим на практический пример отправки http get запроса при помощи любительского GSM-модуля. Активация GPRS модуля и оправка запроса по TCP будет происходить по нажатию на кнопку.
Для чего нам нужны HTTP-запросы через GPRS?
Если вы не в курсе, то ваша жизнь в наше время не мыслима без http запросов. Вы их отсылаете каждый день по многу раз просто заходя на любой сайт со своего браузера и шарясь по разным страничкам.
Так вот, применительно к любительским микроконтроллерным проектам такие запросы тоже могут быть весьма полезными. Представьте, что у нас есть некий сайт в интернете. На этом сайте мы можем создать скрипт на языке PHP, который мы вставим в текстовый файл и назовем x.php. При обращении к этому файлу извне, наш скрипт будет выполнять операции, которые мы в него заложили.
Какие же это могут быть операции: отправка электронного письма (некоторые мобильные операторы позволяют через емейл отправлять sms); запись в текстовом файле на сервере сайта; запись в базе данных на сервере сайта; внесение изменений в запись базы данных; послать сообщение в скайп; принять и сохранить фото...
Возможность отправки емейла может быть интересна для охранной сигнализации и для долгопериодических сообщений от контроллера, например "Полей меня, с любовью твой фикус".
Запись в базе данных на сервере - это самая крутая возможность данной технологии. Таким образом мы можем собирать данные с разных, не привязанных к проводному или wifi интернету, контроллеров и сохранять их для дальнейшего отображения в виде всевозможных графиков и таблиц на сайте.
Сохранение снимков с фотокамеры полезно для охранной сигнализации и для удаленной визуальной оценки ситуации на объекте, вызывающем для нас интерес.
Как работает HTTP-запрос?
HTTP запрос работает очень просто - если отправим нашему серверу в интернете набор информации с предопределённым синтаксисом, то он пришлёт нам в ответ данные, которые мы от него запросили. Например, говорим ему: "сервер с доменом geekmatic.in.ua, пришли нам пожалуйста содержимое веб-странички RF_radio_modul". И он присылает нам гору текстовой информации, которую содержит эта страничка.
Но скачивание в контроллер какой либо веб-странички полностью нам будет интересно только разве что для парсинга данных с чужих сайтов. Таким образом мы можем например собирать данные о прогнозе погоды с погодного сайта и выводить себе на LCD-экранчик.
А самое интересное для нас в HTTP запросе кроется в возможности, при обращении к веб-страничке на нашем сервере, передать ей набор значений для переменных. Синтаксически это выглядит примерно так
http://geekmatic.in.ua/sensors?sort=pd.name&order=ASC
Это так называемый запрос "GET". Здесь страничке sensors мы передаем значение переменной sort равное "pd.name" и переменной order равное "ASC". Таким же образом мы можем передать например значение переменной temperatura=32 или vlazhnost=60. Максимальная длина текста такого запроса ограничена настроенной на сервере цифрой - порядка нескольких тысяч символов, но через GPRS лучше передавать GET-запросы по-короче. Данный модуль способен передать 2000 байт. Для длинных запросов и для передачи файлов, в том числе и фотографий, используется POST запрос, который не сильно отличается синтаксисом. В этом проекте мы остановимся пока только на GET запросах через GPRS.
Синтаксис стандартного GET запроса выглядит так
GET /page.php HTTP/1.1
или с передаваемыми данными
GET /sensors?sort=pd.name&order=ASC HTTP/1.1
В этом проекте мы передадим HTTP GET запрос с обращением к страничке x.php на сервере geekmatic.in.ua. Моя страничка, при обращении к ней, отправит емейл на мой электронный ящик и смс на мобильный (у оператора киевстар можно активировать соответствующую платную возможность принимать емейлы на смс).
Файл x.php содержит следующий скрипт:
Запрос принят
<? mail("evgeniy@sautcom.kiev.ua", "Datchik dveri", "ALARM Khreschatik st. 1"); mail("38097XXXXXXX@sms.kyivstar.net", "Datchik dveri", "ALARM Khreschatik st. 1"); здесь отправка смс через емейл
?>
При удачном запросе к этому файлу, сервер вернет нам фразу "Запрос принят" и отправит два электронных письма.
Что понадобится для проекта?
Для проекта нам понадобится GSM-модуль, на основе микросхемы NEOWAY M590
Плата контроллера Arduino UNO, а так же источник питания 5 В (я использовал 5 В преобразователя USB 2.0 в TTL UART) и мини кнопка. Если запитать GPRS-модуль от вывода 5 В Arduino UNO, ему не будет хватать мощности и он будет всё время перезагружаться.
Схема подключения GSM GPRS модуля M590 к контроллеру Arduino UNO
Схема подключения показана на следующей картинке. Ваш GPRS модуль может отличаться от используемого в проекте. Поэтому найдите в документации соответсвующие обозначения выводов и соедините их по схеме.
Кнопка подключается без каких либо резисторов, так как мы её дискретный вход подтянем внутренним резистором к плюсу программным способом. Arduino UNO можно питать и от USB-кабеля и тогда провод на вывод 5V не нужен.
Не забываем подключить антенну к модулю NEOWAY M590 и вставить в него симку GSM-оператора. При чем, если вы только-что ее купили, то она требует активации работы и возможно активации GPRS-интернета. Лучше всего её вставить в смартфон, поддерживающий GPRS, и настроить связь с интернетом для этой сим-карты. Теперь её смело можно вставлять в модуль M590 - всё должно работать.
Сам модуль мы не будем все время держать в рабочем состоянии. Для экономии энергии мы его будем включать только при необходимости перед отправкой запроса на сайт.
Как происходит процесс передачи команд модулю от контроллера для организации GET-запроса по GPRS?
Все команды в модуль контроллер будет передавать по программному UART. Для этого мы соединили выводы RX и TX платы Arduino UNO с противоположными выводами TX и RX модуля M590.
GSM модуль управляется предопределённым набором так называемых АТ-команд. Самые простые из них мы упустим здесь из рассмотрения и остановимся на командах, косающихся непосредственно TCP-протокола, который и позволит нам передавать и получать данные по GPRS, используя HTTP GET запросы.
Для начала необходимо подать команду подключения к оператору GPRS по его APN
AT+CGDCONT=1,"IP","www.ab.kyivstar.net" ответом должен быть OK
Дальше подадим команду установки соединения по протоколу PPP
AT+XIIC=1
ответом должен быть OK
Для проверки получения своего IP от оператора отправим
AT+XIIC? ответом должен быть не нулевой айпишник +XIIC: 1, 10.43.55.122
Дальше пишем IP сайта, который необходимо определить при помощи специальных веб-сервисов в интернете, и номер порта - 80.
AT+TCPSETUP=1,185.68.16.25,80
Устанавливаем соединение с сервером сайта и присваиваем этому соединению номер 1 (для данного модуля одновременных соединений может быть целых два, под номером 0 или 1). Ещё сюда необходимо ввести длину передаваемого запроса в байтах
AT+TCPSEND=1, 60 ответом будет >
Только теперь у нас появляется возможность передать тело самого запроса
GET /x.php HTTP/1.1\r\nHost: geekmatic.in.ua\r\n\r\n Сервер должен ответить +TCPRECV и текст "Запрос принят" с нашего PHP скрипта в файле x.php
Загрузка программы в контроллер
Наша программа должна, по нажатию нами на кнопку, активировать GSM модуль подачей кратковременного сигнала на вход BOOT, подождать инициализации модуля в сети оператора, подать АТ-команды по передаче HTTP-запроса на сайт, подождать ответа от сервера и деактивировать GPRS модуль подачей сигнала на вход BOOT.
Готовый текст программы для Arduino UNO выглядит следующим образом
#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 5); // RX, TX номера пинов Arduino UNO для подключения к модулю GSM NEOWAY M590
int buttonState = 0;
int lastButtonState = 0;
int knopka = 2; //номер пина для подключения кнопки, которая должна замыкать этот пин на ноль питания
int bootGSM = 3; // номер пина для включения модуля GSM void setup() { mySerial.begin(115200);
Serial.begin(9600);
pinMode(knopka, INPUT_PULLUP); //инициализация дискретного входа для кнопки и внутренняя подтяжка его на плюс питания
pinMode(bootGSM, OUTPUT); //выходной пин для включения/выключения GSM модуля
digitalWrite(bootGSM, HIGH); //высокий уровень на вход BOOT модуля GSM для его выключения
}
void loop() {
buttonState = digitalRead(knopka); //состояние кнопки в данный момент
if (buttonState < lastButtonState){ //если кнопка поменяла свое значение с единицы на ноль
digitalWrite(bootGSM, LOW); //включить GSM модуль
delay(500);
digitalWrite(bootGSM, HIGH);
delay(1000);
sendAtCmd("ATE0", "+PBREADY", "", 30); //ожидаем инициализацию модуля
sendAtCmd("AT+XISP=0", "OK", "ERROR", 1);
sendAtCmd("AT+CGDCONT=1,\"IP\",\"www.ab.kyivstar.net\"", "OK", "", 2); //подключаемся к оператору GPRS по его APN
sendAtCmd("AT+XIIC=1", "OK", "", 1);
sendAtCmd("AT+XIIC?", "OK", "+XIIC: 0, 0.0.0.0", 1); //проверяем получение IP от оператора
sendAtCmd("AT+TCPSETUP=1,185.68.17.25,80", "OK", "Error", 5); //сюда пишем IP сайта (по имени домена не получится)
String q = "GET /x.php HTTP/1.1\r\nHost: geekmatic.in.ua\r\n\r\n"; //тут вводим путь к необходимому файлу на web-сервере, а так же вводим имя домена сайта
sendAtCmd("AT+TCPSEND=1," + String(q.length(), DEC), ">", "", 5);
sendAtCmd(q + 0x0d, "+TCPRECV", "", 10); //отправка запроса и ожидание ответа от сервера
Serial.println(q);
sendAtCmd("AT+TCPCLOSE=1", "OK", "Error", 1); //закрываем TCP соединение номер 1
digitalWrite(bootGSM, LOW); //выключить GSM модуль
delay(500);
digitalWrite(bootGSM, HIGH);
}
lastButtonState = buttonState;
delay(50);
} //функция отправки AT-команды в модем и диагностика ответа
bool sendAtCmd(String at_send, String ok_answer, String err_answer, uint32_t wait_sec) {
Serial.print("sendAtCmd(");
Serial.print(at_send);
Serial.println(")");
uint32_t exit_ms = millis() + wait_sec * 1000;
String answer;
ok_answer.toUpperCase();
err_answer.toUpperCase();
if (at_send != "") {
mySerial.println(at_send);
}
answer = "";
while (millis() < exit_ms)
{
while (mySerial.available())
answer += (char)mySerial.read();
}
Serial.println(answer);
if (answer != "") {
if (err_answer != "" && (answer.indexOf(err_answer) > -1)) {
Serial.println("AT_ERR");
return false;
}
else if (answer.indexOf(ok_answer) > -1) {
Serial.println("AT_OK");
return true;
}
}
Serial.println("AT_TIMEOUT");
return false;
}
Загружаем данный скрипт в контроллер с поправкой на свой сайт и IP сервера.
Тестируем отправку GET запроса по GPRS
Подключаем все согласно схеме и нажимаем на кнопку. При этом наблюдаем как мигает светодиод на модеме M590 при его включении.
Если включить Монитор порта Arduino IDE, то можно наблюдать последовательность сообщений от контроллера и иметь представление о происходящем бурном общении между нашими чудо-платами.
При удачном выполнении всех директив контроллера модулем GSM, получим в Мониторе порта ответ от сервера. Если вы просто обратились к какой-нибудь веб-странице в интернете, то получите в ответ весь текст страницы в HTML-формате. Я же в результате получил ответ "Запрос принят" и тут же получил емейл со своего сайта и смс на мобилку. При повторном нажатии на кнопку запрос должен повториться.
Выводы
Я давно хотел научиться пользовать GPRS через GSM модем. Когда все наконец сложилось и получилось, я понял, что не так всё и сложно - просто никто не хочет делиться инфой и публиковать правильный синтаксис в интернете.
На практике HTTP запрос получился такой же надёжной и не менее полезной штукой чем SMS. Сразу в уме возникает множество задумок по применению этой фичи. Хотелось бы собрать GPRS GPS-трекер для автомобиля и собирать данные о его похождениях на веб-страничку.
GPRS при пересылке небольших объемов данных выходит на много дешевле чем SMS. UDP запросам и FTP я пока не вижу действенного применения. Хочется попробовать отослать фото с камеры, используя HTTP POST запрос, но возможно сразу лучше начинать играться с более продвинутыми GSM-модулями, такими как A6C.