Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Arduino:Примеры/Bridge

Материал из Онлайн справочника
Перейти к: навигация, поиск

Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Библиотека Bridge[1]

Этот пример для Arduino Yun, и он демонстрирует использование библиотеки Bridge для доступа к цифровым и аналоговым контактам Arduino при помощи REST-запросов. Другими словами, он показывает, как при помощи REST-запросов, отправляемых через браузер, создать свой собственный API.

Перед запуском этого скетча убедитесь, что ваш компьютер находится в той же сети, что и Yun.

Закончив с программированием платы, вы сможете делать следующие вещи – запрашивать значение контакта, задавать значение контакта, а также задавать статус контакта (входной/выходной).

Итак, если защита паролем для REST отключена, вы можете отсылать Arduino следующие команды, выполненные в виде URL:

Впрочем, если хотите, вместо браузера можно использовать CURL-команды в командной строке.

Необходимое оборудование

  • Плата Arduino Yun;
  • Компьютер и Yun должны быть расположены в одной сети (проводной или беспроводной);

Необходимое ПО

  • Веб-браузер;

Цепь

Для этого примера цепь не требуется.

Код

Этот скетч показывает, как делать REST-запросы к плате Yun, чтобы считывать контактов или задавать контактам те или иные значения. Вам потребуются библиотеки Bridge, YunServer и YunClient:

  1. #include <Bridge.h>
  2. #include <YunServer.h>
  3. #include <YunClient.h>

Инстацируем сервер YunServer, который позволит Yun «прослушивать» подключающихся клиентов.

  1. YunServer server;

В секции setup() инициализируем последовательную передачу данных (в отладочных целях), а затем включаем встроенный светодиод, подключенный к 13-ому цифровому контакту, тем самым оповещая об активации библиотеки Bridge. Bridge.begin() – это блокирующая функция, а на ее выполнение уйдет примерно 2 секунды. Когда активация Bridge Полужирное начертаниезавершится, светодиод погаснет.

  1. void setup() {
  2.   Serial.begin(9600);
  3.   pinMode(13,OUTPUT);
  4.   digitalWrite(13, LOW);
  5.   Bridge.begin();
  6.   digitalWrite(13, HIGH);

Во второй части секции setup() мы делаем так, чтобы наш инстацированный YunServer «слушал» входящие соединения, но идущие только от локального хоста, т.е. от компьютера. При этом все подключения, идущие к Linux, будут передаваться процессору 32U4 – для последующего анализа и управления контактами. Все это проходит через порт 5555. Затем начинаем работать с сервером при помощи server.begin().

  1. server.listenOnLocalhost();
  2.   server.begin();
  3. }

В блоке loop() создаем экземпляр YunClient для управления соединением. Если клиент подключается, обрабатываем запросы в пользовательской функции (ее описание – ниже), а по завершении закрываем соединение. В конце блока loop() ставим задержку – чтобы процессор не перетруждался.

  1. void loop() {
  2.   YunClient client = server.accept();
  3.  
  4.   if (client) {
  5.     process(client);
  6.     client.stop();
  7.   }
  8.  
  9.   delay(50);
  10. }

Создаем функцию под названием process – она будет принимать YunServer в качестве аргумента. Считываем команду, создавая строку, которая будет хранить в себе входящую информацию. Анализируем REST-команды, определяя их функциональность (т.е. то, на что направлены эти команды – на работу с цифровым контактом, на работу с аналоговым контактом или на то, чтобы задать контакту тот или иной режим работы), а затем передаем информацию соответствующей функции.

  1. void process(YunClient client) {
  2.   String command = client.readStringUntil('/');
  3.  
  4.   if (command == "digital") {
  5.     digitalCommand(client);
  6.   }
  7.   if (command == "analog") {
  8.     analogCommand(client);
  9.   }
  10.   if (command == "mode") {
  11.     modeCommand(client);
  12.   }
  13. }

Создаем функцию для работы с цифровыми контактами. Принимаем YunClient в качестве аргумента. Создаем две локальные переменные, в которых будет храниться информация из команды, т.е. данные о контакте и значении.

  1. void digitalCommand(YunClient client) {
  2.   int pin, value;

Анализируем запрос клиента на предмет информации о контакте при помощи функции client.pareInt().

Если после числа, обозначающего контакт, стоит символ «/», это значит, что у этого URL дальше имеется либо «0», либо «1». То есть при помощи этих значений контакту передается либо значение HIGH, либо значение LOW. Если символа «/» нет, то просто считываем значение с указанного контакта.

  1. pin = client.parseInt();
  2.  
  3.   if (client.read() == '/') {
  4.     value = client.parseInt();
  5.     digitalWrite(pin, value);
  6.   }
  7.   else {
  8.     value = digitalRead(pin);
  9.   }

Шлем клиенту текстовое сообщение о том, что значение такого-то цифрового контакта стало таким-то (например, «Pin D13 set to 1»,т.е. «значение 13-ого цифрового контакта стало 1»), попутно меняя в базе данных значение ключа на то, которое было указано в клиентском запросе.

«Упаковываем» это сообщение в конструкцию F(), благодаря чему оно будет выводиться из flash-памяти. Тем самым мы экономим место в SRAM, что особенно полезно, если вы работаете длинными строками вроде URL. Ключ делаем составным, он будет включать в себя тип контакта (т.е. «D») и его номер (т.е. «2», «5», «13» и т.д.). Например, ключ «D2» будет означать 2-ой цифровой контакт. Значением (value) будет любая величина, которая либо задается клиентом, либо считывается с контакта.

  1. client.print(F("Pin D"));
  2.   client.print(pin);
  3.   client.print(F(" set to "));
  4.   client.println(value);
  5.  
  6.   String key = "D";
  7.   key += pin;
  8.   Bridge.put(key, String(value));
  9. }

Теперь задаем функцию, которая будет аналогичным образом управляться с аналоговыми запросами, только в ключе вместо D поставим A.

  1. void analogCommand(YunClient client) {
  2.   int pin, value;
  3.  
  4.   pin = client.parseInt();
  5.  
  6.   if (client.read() == '/') {
  7.     value = client.parseInt();
  8.     analogWrite(pin, value);
  9.  
  10.     // Отсылаем клиенту обратное сообщение
  11.     client.print(F("Pin D"));
  12.     client.print(pin);
  13.     client.print(F(" set to analog "));
  14.     client.println(value);
  15.  
  16.     String key = "D";
  17.     key += pin;
  18.     Bridge.put(key, String(value));
  19.   }
  20.   else {
  21.     value = analogRead(pin);
  22.  
  23.     client.print(F("Pin A"));
  24.     client.print(pin);
  25.     client.print(F(" reads analog "));
  26.     client.println(value);
  27.  
  28.     String key = "A";
  29.     key += pin;
  30.     Bridge.put(key, String(value));
  31.   }
  32. }

Создаем еще одну функцию, которая будет заниматься запросами, которые будут задавать для контакта его тип – входной (INPUT) или выходной (OUTPUT). Принимаем YunClient как аргумент и создаем локальную переменную, которая будет хранить номер контакта. Далее считываем значение контакта – точно таким же образом, как в функциях для работы с цифровыми и аналоговыми контактами.

  1. void modeCommand(YunClient client) {
  2.   int pin;
  3.   pin = client.parseInt();

Делаем проверку, чтобы убедиться, что URL правильный.

  1. if (client.read() != '/') {
  2.     client.println(F("error"));
  3.     return;
  4.   }

Если URL правильный, сохраняем его в виде строки. Далее меняем режим работы контакта на входной или выходной (в зависимости от того, что сказано в запросе) и сообщаем об этом клиенту. Если строка этим значениям не соответствует, сообщаем клиенту об ошибке.

  1. String mode = client.readStringUntil('\r');
  2.  
  3.   if (mode == "input") {
  4.     pinMode(pin, INPUT);
  5.     // Отсылаем клиенту обратное сообщение:
  6.     client.print(F("Pin D"));
  7.     client.print(pin);
  8.     client.print(F(" configured as INPUT!"));
  9.     return;
  10.   }
  11.  
  12.   if (mode == "output") {
  13.     pinMode(pin, OUTPUT);
  14.     // Отсылаем клиенту обратное сообщение:
  15.     client.print(F("Pin D"));
  16.     client.print(pin);
  17.     client.print(F(" configured as OUTPUT!"));
  18.     return;
  19.   }
  20.  
  21.   client.print(F("error: invalid mode "));
  22.   client.print(mode);
  23. }

Полная версия скетча – ниже:

  1. // Несколько примеров того, какими могут быть команды для этого скетча:
  2. //
  3. // "digital/13"     -> digitalRead(13)
  4. // "digital/13/1"   -> digitalWrite(13, HIGH)
  5. // "analog/2/123"   -> analogWrite(2, 123)
  6. // "analog/2"       -> analogRead(2)
  7. // "mode/13/input"  -> pinMode(13, INPUT)
  8. // "mode/13/output" -> pinMode(13, OUTPUT)
  9.  
  10. #include <Bridge.h>
  11. #include <YunServer.h>
  12. #include <YunClient.h>
  13.  
  14. // Включаем «прослушку» порта 5555 – веб-сервер на Yun будет отправлять туда для нас все HTTP-запросы.
  15.  
  16. YunServer server;
  17.  
  18. void setup() {
  19.   Serial.begin(9600);
  20.  
  21.   // Активируем библиотеку Bridge:
  22.   pinMode(13,OUTPUT);
  23.   digitalWrite(13, LOW);
  24.   Bridge.begin();
  25.   digitalWrite(13, HIGH);
  26.  
  27.   // Начинаем «прослушивать» входящие соединения, но идущие только от локального хоста,
  28.   // т.е. подключения от внешней сети игнорируем:
  29.   server.listenOnLocalhost();
  30.   server.begin();
  31. }
  32.  
  33. void loop() {
  34.   // «Забираем» клиентов, идущих от сервера:
  35.   YunClient client = server.accept();
  36.  
  37.   // Появился ли новый клиент?
  38.   if (client) {
  39.     // Обрабатываем запрос:
  40.     process(client);
  41.  
  42.     // Закрываем соединение и освобождаем ресурсы:
  43.     client.stop();
  44.   }
  45.  
  46.   delay(50); // Задержка каждые 50 миллисекунд
  47. }
  48.  
  49. void process(YunClient client) {
  50.   // Считываем команду:
  51.   String command = client.readStringUntil('/');
  52.  
  53.   // Это «цифровая» (digital) команда?
  54.   if (command == "digital") {
  55.     digitalCommand(client);
  56.   }
  57.  
  58.   // Это «аналоговая» (analog) команда?
  59.   if (command == "analog") {
  60.     analogCommand(client);
  61.   }
  62.  
  63.   // Это команда для смены режима (mode)?
  64.   if (command == "mode") {
  65.     modeCommand(client);
  66.   }
  67. }
  68.  
  69. void digitalCommand(YunClient client) {
  70.   int pin, value;
  71.  
  72.   // Считываем номер контакта
  73.   pin = client.parseInt();
  74.  
  75.   // Если следующим символом является «/», это значит,
  76.   // что полученный запрос идет вместе с некоторым значением
  77.   // и выглядит примерно так: «/digital/13/1»
  78.   if (client.read() == '/') {
  79.     value = client.parseInt();
  80.     digitalWrite(pin, value);
  81.   }
  82.   else {
  83.     value = digitalRead(pin);
  84.   }
  85.  
  86.   // Отсылаем клиенту обратное сообщение:
  87.   client.print(F("Pin D")); // "Контакту D"
  88.   client.print(pin);
  89.   client.print(F(" set to ")); // " присвоено значение "
  90.   client.println(value);
  91.  
  92.   // Обновляем ключ в базе данных на текущее значение контакта:  
  93.   String key = "D";
  94.   key += pin;
  95.   Bridge.put(key, String(value));
  96. }
  97.  
  98. void analogCommand(YunClient client) {
  99.   int pin, value;
  100.  
  101.   // Считываем номер контакта:
  102.   pin = client.parseInt();
  103.  
  104.   // Если следующим символом является «/», это значит,
  105.   // что полученный запрос идет вместе с некоторым значением
  106.   // и выглядит примерно так: "/analog/5/120»
  107.   if (client.read() == '/') {
  108.     // Считываем это значение и выполняем команду:
  109.     value = client.parseInt();
  110.     analogWrite(pin, value);
  111.  
  112.     // Отсылаем клиенту обратное сообщение:
  113.     client.print(F("Pin D")); // "Контакту D"
  114.     client.print(pin);
  115.     client.print(F(" set to analog ")); // " присвоено аналоговое значение "
  116.     client.println(value);
  117.  
  118.     // Обновляем ключ в базе данных на текущее значение контакта:  
  119.     String key = "D";
  120.     key += pin;
  121.     Bridge.put(key, String(value));
  122.   }
  123.   else {
  124.     // Считываем номер аналогового контакта:
  125.     value = analogRead(pin);
  126.  
  127.     // Отсылаем клиенту обратное сообщение:
  128.     client.print(F("Pin A")); // "С контакта A"
  129.     client.print(pin);
  130.     client.print(F(" reads analog ")); // " считано аналоговое значение "
  131.     client.println(value);
  132.  
  133.     // Обновляем ключ в базе данных на текущее значение контакта:
  134.     String key = "A";
  135.     key += pin;
  136.     Bridge.put(key, String(value));
  137.   }
  138. }
  139.  
  140. void modeCommand(YunClient client) {
  141.   int pin;
  142.  
  143.   // Считываем номер контакта:
  144.   pin = client.parseInt();
  145.  
  146.   // Если «/» не является следующим символом, то URL неправильный:
  147.   if (client.read() != '/') {
  148.     client.println(F("error")); // "ошибка"
  149.     return;
  150.   }
  151.  
  152.   String mode = client.readStringUntil('\r');
  153.  
  154.   if (mode == "input") {
  155.     pinMode(pin, INPUT);
  156.     // Отсылаем клиенту обратное сообщение:
  157.     client.print(F("Pin D")); // "Контакт D"
  158.     client.print(pin);
  159.     client.print(F(" configured as INPUT!")); // " сделан входным!"
  160.     return;
  161.   }
  162.  
  163.   if (mode == "output") {
  164.     pinMode(pin, OUTPUT);
  165.     // Отсылаем клиенту обратное сообщение:
  166.     client.print(F("Pin D")); // "Контакт D"
  167.     client.print(pin);
  168.     client.print(F(" configured as OUTPUT!")); // " сделан выходным!"
  169.     return;
  170.   }
  171.  
  172.   client.print(F("error: invalid mode ")); // "Ошибка. Вы указали неверную команду для того, чтобы задать режим – "
  173.   client.print(mode);
  174. }

См.также

Внешние ссылки

  1. Arduino - Bridge