Передача данных базовой станции Misol Arduino в локальную сеть и Интернет (Народный мониторинг)

Первичной целью разработки базовой станции Misol Arduino было расширение возможностей по передаче получаемых данных пользователям, находящимся в произвольных точках пространства. Современные сетевые технологии предоставляют удобные возможности для передачи необходимых данных в требуемом объеме на любое расстояние. С точки зрения сетевых технологий местонахождение пользователей можно разделить на локальное (в пределах области действия локальной сети) и внешнее (в пределах области действия сети Интернет). Буду считать, что локальным пользователям будут доступны данные в полном объеме, а внешним пользователям перечень передаваемых данных будет ограничен их требованиями. В рассматриваемом случае под внешним пользователем будет считаться сервер интернет ресурса народного мониторинга.

Программное обеспечение, позволяющее перехватывать пакеты данных блока внешних датчиков метеостанции Misol разработано ранее. В этой публикации речь пойдет о том, как полученные данные передать в локальную сеть и в Интернет. Для передачи данных в локальную сеть и Интернет необходимо подключить Arduino Mega к локальной сети. Такое подключение выполняется с помощью сетевой платы, например, Ethernet Shield W5100.

Ethernet Shield W5100 Arduino

Представляет собой плату расширения, устанавливаемую поверх базовой платы Arduino, например, Mega или Uno. Для удобства подключения штыревые контакты снизу удлиненные и дублируются сверху гребенкой, что обеспечивает доступ к контактам базовой платы, даже при подключении платы расширения. Кроме сетевого контроллера W5100, обеспечивающего взаимодействие с сетевым интерфейсом, на плате дополнительно разведен разъем для подключения SD карт памяти. Таким образом, на плате собраны два разных устройства. Выбор доступа к требуемому устройству осуществляется через сигналы CS (Chip Select — выбор микросхемы), в качестве которых используются цифровые сигналы базовой платы. Сигналы CS аппаратно разведены на плате расширения и назначаются в библиотеках. Подключается плата Ethernet Shield W5100 к плате Arduino Mega установкой сверху.

Протоколы передачи данных

Базовым понятием передачи данных является сетевая модель OSI. Она представляет процесс передачи данных, разделенным на различные уровни. В зависимости от уровня, на котором планируется обеспечить передачу данных обратнопропорционально меняются требования к аппаратному и программному обеспечению. Если использовать простые аппаратные средства, то придется разрабатывать объемное программное обеспечение. Если использовать сложные аппаратные средства, то пользовательское программное обеспечение может быть минимальным. Как в большинстве случаев, для решения конкретной задачи целесообразно использовать некий компромиссный вариант. Таким решение является использование транспортного уровня модели OSI, а именно протоколов TCP и UDP.

Протокол TCP

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

Протокол UDP

UDP (англ. User Datagram Protocol — протокол пользовательских датаграмм) — один из ключевых элементов набора сетевых протоколов для Интернета. С UDP компьютерные приложения могут посылать сообщения (в данном случае называемые датаграммами) другим хостам по IP-сети без необходимости предварительного сообщения для установки специальных каналов передачи или путей данных. UDP использует простую модель передачи, без неявных «рукопожатий» для обеспечения надёжности, упорядочивания или целостности данных. Таким образом, UDP предоставляет ненадёжный сервис, и датаграммы могут прийти не по порядку, дублироваться или вовсе исчезнуть без следа. UDP подразумевает, что проверка ошибок и исправление либо не нужны, либо должны исполняться в приложении. 

Оба эти протокола могут быть использованы. Однако, протокол UDP является более простым с точки зрения требуемой программной поддержки и не требует большого объема программной памяти, что является важным требованием при его реализации на аппаратной платформе с ограниченными ресурсами, например, такой как Arduino. В то же время он не обеспечивает гарантированной доставки сообщения. Это необходимо всегда помнить при его использовании. В качестве базового протокола выбирается протокол UDP.

Программная поддержка передачи данных

Разработка программного обеспечения функционирования Arduino основывается на широком использовании библиотек, реализующих различные функции. Для решения поставленных задач потребуются следующие библиотеки:

Для работы с контроллером W5100 разработана библиотека. Её требуется загрузить и установить в среде программирования Arduino. В примерах к библиотеке есть необходимый скетч, который послужит базой. Пример «слушает» заданный порт. Когда на этот порт приходит сообщение, Arduino формирует ответное сообщение. Данный алгоритм работы отличается от требуемого. Для метеостанции нет необходимости ожидать входящего сообщения. В зависимости от потребителя информации (локальный или глобальный (народный мониторинг) требуется посылать пакет с метеоданными с заданной периодичностью. Локальным потребителям данные должны передаваться каждую минуту, а серверу народного мониторинга — каждые пять минут. Кроме того, состав (формат) данных локальному и глобальному потребителю отличается. С учетом этих требований пример был модифицирован.

/*
   https://github.com/arduino-libraries/Ethernet
   https://github.com/arduino-libraries/Ethernet/tree/master/examples/UDPSendReceiveString
  Этот скетч конфигурирует контроллер W5100 Arduino для работы с протоколом UDP и передает строку широковещательным пакетом в локальную сеть.
*/

#include <Ethernet.h>
#include <EthernetUdp.h>

// ----- ***** ----- ***** ----- NET DATA ----- ***** ----- ***** -----
// ----- ***** ----- LOCAL DATA ----- ***** -----
byte MyMAC[] = { 0x3A, 0xF1, 0x7F, 0xA4, 0x56, 0x7E };  // MAC для идентификации устройства 
                                                        // сервером народного мониторинга
IPAddress MyIP ( 192, 168, 0, 199 );
IPAddress MyDNS  ( 192, 168, 0, 1 );
IPAddress MyGateway ( 192, 168, 0, 1 );
IPAddress MySubnet ( 255, 255, 255, 0 );
unsigned int localPort = 9999;            // Порт для приема пакетов UDP
IPAddress NMDNS;
// ----- End LOCAL DATA -----

// ----- ***** ----- Broadcast udp message ----- ***** -----
IPAddress IPBC( 192, 168, 0, 255 );
const unsigned int PORTBC = 8887;         // Порт для отправки пакетов UDP
// ----- End Broadcast -----

// ----- ***** ----- NM ----- ***** -----
byte IPNMDNS[4];    //Для DNS
byte IPNM[] = { 185, 245, 187, 136 };     // IP сервера народного мониторинга.
                                          // Не требуется при включении DNS
int portNM = 8283;
String mac, mac_d;
// ----- End NM -----
// ----- ***** ----- End NET DATA ----- ***** -----


EthernetUDP Udp;            // Определение UDP


#define LUTime 30000;       // Периодичность передачи пакетов локальным пользователям миллисекунды (30 сек)
#define NMTime 300000;      // Периодичность передачи пакетов на народный мониторинг миллисекунд (55 минут)
long TxLUTime, TxNMTime;



// ----- ***** ----- ***** ----- Setup ----- ***** ----- ***** -----
void setup() {

  Ethernet.begin(MyMAC, MyIP);          // Инициализация контроллера W5100 с заданными параметрами

  Serial.begin(115200);                 // Инициализация последовательного порта
  while (!Serial) {                     // Ожидание инициализации последовательного порта
    ;
  }

  if (Ethernet.hardwareStatus() == EthernetNoHardware) {    // Проверка наличия контроллера W5100
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1);                 // Остановка исполнения при отсутствии контроллера W5100
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  Udp.begin(localPort);         // Запуск службы UDP
}   // ----- End Setup -----


// ----- ***** ----- ***** ----- Loop ----- ***** ----- ***** -----
void loop() {

  //  ----- ***** ----- Отправка пакета локальным пользователям ----- ***** -----
  if (TxLUTime < millis()) {    // Передача пакета локальным пользователям

    //  ----- ***** ----- Формирование строки ----- ***** -----
    String strlip = "MeteoData Local User";           // Строка сообщения локальным пользователям
    strlip += ' ';
    strlip += millis();
    strlip += "; ";
    Serial.print("StrLip=: ");
    Serial.print(strlip);
    //  ----- Конец Формирование строки -----

    //  ----- ***** ----- Преобразование строки в массив символов ----- ***** -----
    uint16_t lenBClip = strlip.length();
    Serial.print("\tLen LIP=: ");
    Serial.println(lenBClip);
    char ttsBClip[lenBClip + 1];
    strcpy(ttsBClip, strlip.c_str());
    // ----- Конец Преобразование строки в массив символов -----

    //  ----- ***** ----- Отправка пакета (массива символов) ----- ***** -----
    Udp.beginPacket(IPBC, PORTBC);
    Udp.write(ttsBClip);
    Udp.endPacket();
    // ----- Конец Отправка пакета (массива символов) -----

    //  ----- ***** ----- Задание времени отправки очередного пакета ----- ***** -----
    TxLUTime += LUTime;
    // ----- Конец Задание времени отправки очередного пакета -----

  }  // ---- Конец Передача пакета локальным пользователям ---- -
  //  ----- Конец Отправка пакета локальным пользователям -----


  //  ----- ***** ----- Отправка пакета серверу народного мониторинга ----- ***** -----
  /*
    if (TxNMTime < millis()) {
      Udp.beginPacket(IPNM, portNM);
      Udp.write(ttsNM);
      Udp.endPacket();

      TxNMTime += NMTime;
    }
  */
  // ----- Конец Отправка пакета серверу народного мониторинга -----

}   // ----- Конец Loop -----

Разбор содержания скетча

Назначение скетча

Скетч конфигурирует контроллер W5100 Arduino для работы с протоколом UDP и передают тестовую строку широковещательным пакетом в локальную сеть.

Используемые библиотеки

Для работы потребуются две библиотеки.

Используемые библиотеки.

Сетевые установочные данные

Установочные данные в основном касаются информации, необходимой для работы в локальной (глобальной) сети.

Сетевые установочные данные.

Установочные данные контроллера W5100. Для самого контроллера задаются: MAC (MyMAC), IP (MyIP). IP контроллера W5100 должен быть уникальными для локальной сети, а MAC должен быть уникальным во Вселенной. Но, можно его задать и случайным образом или установить равным МАС устройству, вышедшего из применения, например, не используемой сетевой карте. Кроме того, с помощью MAC производится идентификация устройства на сервере народного мониторинга.
Установочные данные локальной сети. Для взаимодействия с локальной сетью задаются: IP локального сервера DNS (MyDNS); IP шлюза Internet (MyGateway); маска локальной подсети (MySubnet); номер локального порта UDP (localPort); переменная для хранения IP адреса сервера народного мониторинга (NMDNS), полученного от службы DNS.

Широковещание. Следующим блоком идут установки для широковещательных пакетов UDP. В большинстве случаев, данные в локальной сети передаются от источника IP(Tx) к приемнику IP(Rx). Но существует возможность передавать пакеты нескольким пользователям одновременно, несмотря на имеющиеся у них уникальные IP. Такой способ называется широковещанием (broadcast). Реализуется он заданием специального широковещательного адреса. Особенностью этого адреса является задание четвертого октета IP равным 255 (bin = 1111 1111). В данном случае адрес для широковещательной передачи будет: IPAddress IPBC ( 192, 168, 0, 255 ). Пакеты, отправляемые на такой адрес, будут приниматься всеми устройствами в локальной сети. Пакеты будут адресоваться на порт PORTBC = 8887 принимающих устройств. Этот порт должен быть указан для всех устройств, в качестве UDP порта входящих сообщений.

Данные сервера народного мониторинга. Включают IP адрес byte IPNM[] = { 185, 245, 187, 136 }. Его можно получить через любую службу доменных имен или через командную строку.

Запрос IP сервера народного мониторинга.

Зеленым маркером отмечен запрос. Желтым маркером — ответ.

И порт int portNM = 8283.

Порт сервера народного мониторинга.

Настройка и запуск (Setup)

В модуле настройки и запуска производится задание параметров и запуск контроллера W5100, последовательного порта, проверка наличия контроллера W5100 и сетевого подключения, запускается служба UDP.

Рабочий цикл (Loop)

В рабочем цикле производится проверка времени очередной отправки пакета локальным пользователям, формирование и отправка пакета, задание времени отправки очередного пакета.

Проверка времени очередной отправки пакета осуществляется с использованием управляющего оператора if сравнением заданного времени отправки TxLUTime с текущим временем millis(). Если при проверке millis() превышает заданное время отправки, то процедура формирования и отправки пакета выполняется.

Формирование пакета производится в два этапа.
Первый этап. Формируется строка сообщения strlip (string local IP).
Для примера она состоит из строковой константы «MeteoData Local User» и текущего времени в миллисекундах millis(). Для удобства восприятия строка завершается признаком окончания строки с пробелом «; «.
Второй этап. Строка strlip преобразуется в массив символов ttsBClip (transmit text string broadcast local IP) . Преобразование строки в массив обусловлено посимвольной передачей данных.

Отправка сообщения производится заданием контроллеру IP получателя (IPBC) и порта (PORTBC); передачей контроллеру отправляемого сообщения (ttsBClip). При получении отправляемого сообщения контроллер посимвольно передает его в локальную сеть по протоколу UDP. После завершения передачи сообщения контроллер завершает сеанс связи.

Заключительным действием в рабочем цикле является задание времени отправки очередного пакета TxLUTime.

Для подтверждения правильности передаваемых данных формируемая строка strlip и ее длина lenBClip выводятся в последовательный порт.

Процедура отправки сообщения на сервер народного мониторинга аналогична рассмотренной процедуре и в данной публикации не рассматривается.

Проверить отправку сообщения в локальную сеть возможно с помощью программы TCP/IP Builder.

Если в TCP/IP Builder пакеты получены, то задача, поставленная в данной публикации, выполнена. Широковещательные пакеты могут быть приняты любым устройством в локальной сети. Следующими этапами развития проекта домашней метеостанции являются: подключение базовой станции и требуемых датчиков; формирование и отправка данных потребителям в локальной сети и на сервер народного мониторинга; получение актуального IP адреса сервера народного мониторинга через службу DNS; разработка устройства приема широковещательных пакетов и отображение принимаемых данных.