Arduino:Примеры/Bridge: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
м (Замена текста — «<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">» на «<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">»)
 
Нет описания правки
Строка 40: Строка 40:
Вам потребуются библиотеки '''Bridge''', '''YunServer''' и '''YunClient''':
Вам потребуются библиотеки '''Bridge''', '''YunServer''' и '''YunClient''':


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
#include <Bridge.h>
#include <Bridge.h>
#include <YunServer.h>
#include <YunServer.h>
Строка 48: Строка 48:
Инстацируем сервер '''YunServer''', который позволит '''Yun''' '''«прослушивать»''' подключающихся клиентов.
Инстацируем сервер '''YunServer''', который позволит '''Yun''' '''«прослушивать»''' подключающихся клиентов.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
YunServer server;
YunServer server;
</syntaxhighlight>
</syntaxhighlight>
Строка 54: Строка 54:
В секции setup() инициализируем последовательную передачу данных (в отладочных целях), а затем включаем встроенный светодиод, подключенный к '''13-ому цифровому контакту''', тем самым оповещая об активации библиотеки '''Bridge'''. Bridge.begin() – это блокирующая функция, а на ее выполнение уйдет примерно '''2 секунды'''. Когда активация '''Bridge''' '''Полужирное начертание'''завершится, светодиод погаснет.
В секции setup() инициализируем последовательную передачу данных (в отладочных целях), а затем включаем встроенный светодиод, подключенный к '''13-ому цифровому контакту''', тем самым оповещая об активации библиотеки '''Bridge'''. Bridge.begin() – это блокирующая функция, а на ее выполнение уйдет примерно '''2 секунды'''. Когда активация '''Bridge''' '''Полужирное начертание'''завершится, светодиод погаснет.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void setup() {
void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
Строка 65: Строка 65:
Во второй части секции setup() мы делаем так, чтобы наш инстацированный '''YunServer «слушал»''' входящие соединения, но идущие только от локального хоста, т.е. от компьютера. При этом все подключения, идущие к Linux, будут передаваться процессору '''32U4''' – для последующего анализа и управления контактами. Все это проходит через порт '''5555'''. Затем начинаем работать с сервером при помощи server.begin().
Во второй части секции setup() мы делаем так, чтобы наш инстацированный '''YunServer «слушал»''' входящие соединения, но идущие только от локального хоста, т.е. от компьютера. При этом все подключения, идущие к Linux, будут передаваться процессору '''32U4''' – для последующего анализа и управления контактами. Все это проходит через порт '''5555'''. Затем начинаем работать с сервером при помощи server.begin().


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
server.listenOnLocalhost();
server.listenOnLocalhost();
   server.begin();
   server.begin();
Строка 74: Строка 74:
В конце блока loop() ставим задержку – чтобы процессор не перетруждался.
В конце блока loop() ставим задержку – чтобы процессор не перетруждался.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void loop() {
void loop() {
   YunClient client = server.accept();
   YunClient client = server.accept();
Строка 89: Строка 89:
Создаем функцию под названием process – она будет принимать '''YunServer''' в качестве аргумента. Считываем команду, создавая строку, которая будет хранить в себе входящую информацию. Анализируем '''REST-команды''', определяя их функциональность (т.е. то, на что направлены эти команды – на работу с цифровым контактом, на работу с аналоговым контактом или на то, чтобы задать контакту тот или иной режим работы), а затем передаем информацию соответствующей функции.
Создаем функцию под названием process – она будет принимать '''YunServer''' в качестве аргумента. Считываем команду, создавая строку, которая будет хранить в себе входящую информацию. Анализируем '''REST-команды''', определяя их функциональность (т.е. то, на что направлены эти команды – на работу с цифровым контактом, на работу с аналоговым контактом или на то, чтобы задать контакту тот или иной режим работы), а затем передаем информацию соответствующей функции.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void process(YunClient client) {
void process(YunClient client) {
   String command = client.readStringUntil('/');
   String command = client.readStringUntil('/');
Строка 107: Строка 107:
Создаем функцию для работы с цифровыми контактами. Принимаем '''YunClient''' в качестве аргумента. Создаем две локальные переменные, в которых будет храниться информация из команды, т.е. данные о контакте и значении.
Создаем функцию для работы с цифровыми контактами. Принимаем '''YunClient''' в качестве аргумента. Создаем две локальные переменные, в которых будет храниться информация из команды, т.е. данные о контакте и значении.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void digitalCommand(YunClient client) {
void digitalCommand(YunClient client) {
   int pin, value;
   int pin, value;
Строка 116: Строка 116:
Если после числа, обозначающего контакт, стоит символ «/», это значит, что у этого '''URL''' дальше имеется либо '''«0»''', либо '''«1»'''. То есть при помощи этих значений контакту передается либо значение HIGH, либо значение LOW. Если символа '''«/»''' нет, то просто считываем значение с указанного контакта.  
Если после числа, обозначающего контакт, стоит символ «/», это значит, что у этого '''URL''' дальше имеется либо '''«0»''', либо '''«1»'''. То есть при помощи этих значений контакту передается либо значение HIGH, либо значение LOW. Если символа '''«/»''' нет, то просто считываем значение с указанного контакта.  


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
pin = client.parseInt();
pin = client.parseInt();


Строка 133: Строка 133:
Ключ делаем составным, он будет включать в себя тип контакта (т.е. '''«D»''') и его номер (т.е. '''«2», «5», «13» и т.д.'''). Например, ключ '''«D2»''' будет означать '''2-ой цифровой контакт'''. Значением ('''value''')  будет любая величина, которая либо задается клиентом, либо считывается с контакта.
Ключ делаем составным, он будет включать в себя тип контакта (т.е. '''«D»''') и его номер (т.е. '''«2», «5», «13» и т.д.'''). Например, ключ '''«D2»''' будет означать '''2-ой цифровой контакт'''. Значением ('''value''')  будет любая величина, которая либо задается клиентом, либо считывается с контакта.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
client.print(F("Pin D"));
client.print(F("Pin D"));
   client.print(pin);
   client.print(pin);
Строка 147: Строка 147:
Теперь задаем функцию, которая будет аналогичным образом управляться с аналоговыми запросами, только в ключе вместо '''D''' поставим '''A'''.
Теперь задаем функцию, которая будет аналогичным образом управляться с аналоговыми запросами, только в ключе вместо '''D''' поставим '''A'''.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void analogCommand(YunClient client) {
void analogCommand(YunClient client) {
   int pin, value;
   int pin, value;
Строка 184: Строка 184:
Создаем еще одну функцию, которая будет заниматься запросами, которые будут задавать для контакта его тип – входной (INPUT) или выходной (OUTPUT). Принимаем '''YunClient''' как аргумент и создаем локальную переменную, которая будет хранить номер контакта. Далее считываем значение контакта – точно таким же образом, как в функциях для работы с цифровыми и аналоговыми контактами.
Создаем еще одну функцию, которая будет заниматься запросами, которые будут задавать для контакта его тип – входной (INPUT) или выходной (OUTPUT). Принимаем '''YunClient''' как аргумент и создаем локальную переменную, которая будет хранить номер контакта. Далее считываем значение контакта – точно таким же образом, как в функциях для работы с цифровыми и аналоговыми контактами.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void modeCommand(YunClient client) {
void modeCommand(YunClient client) {
   int pin;
   int pin;
Строка 192: Строка 192:
Делаем проверку, чтобы убедиться, что URL правильный.
Делаем проверку, чтобы убедиться, что URL правильный.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
if (client.read() != '/') {
if (client.read() != '/') {
     client.println(F("error"));
     client.println(F("error"));
Строка 201: Строка 201:
Если URL правильный, сохраняем его в виде строки. Далее меняем режим работы контакта на входной или выходной (в зависимости от того, что сказано в запросе) и сообщаем об этом клиенту. Если строка этим значениям не соответствует, сообщаем клиенту об ошибке.
Если URL правильный, сохраняем его в виде строки. Далее меняем режим работы контакта на входной или выходной (в зависимости от того, что сказано в запросе) и сообщаем об этом клиенту. Если строка этим значениям не соответствует, сообщаем клиенту об ошибке.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
String mode = client.readStringUntil('\r');
String mode = client.readStringUntil('\r');


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


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
// Несколько примеров того, какими могут быть команды для этого скетча:
// Несколько примеров того, какими могут быть команды для этого скетча:
//
//

Версия от 18:18, 14 мая 2023

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


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

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

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

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

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

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

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

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

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

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

Цепь

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

Код

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

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

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

YunServer server;

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

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);

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

server.listenOnLocalhost();
  server.begin();
}

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

void loop() {
  YunClient client = server.accept();

  if (client) {
    process(client);
    client.stop();
  }

  delay(50);
}

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

void process(YunClient client) {
  String command = client.readStringUntil('/');

  if (command == "digital") {
    digitalCommand(client);
  }
  if (command == "analog") {
    analogCommand(client);
  }
  if (command == "mode") {
    modeCommand(client);
  }
}

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

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

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

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

pin = client.parseInt();

  if (client.read() == '/') {
    value = client.parseInt();
    digitalWrite(pin, value);
  } 
  else {
    value = digitalRead(pin);
  }

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

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

client.print(F("Pin D"));
  client.print(pin);
  client.print(F(" set to "));
  client.println(value);

  String key = "D";
  key += pin;
  Bridge.put(key, String(value));
}

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

void analogCommand(YunClient client) {
  int pin, value;

  pin = client.parseInt();

  if (client.read() == '/') {
    value = client.parseInt();
    analogWrite(pin, value);

    // Отсылаем клиенту обратное сообщение
    client.print(F("Pin D"));
    client.print(pin);
    client.print(F(" set to analog "));
    client.println(value);

    String key = "D";
    key += pin;
    Bridge.put(key, String(value));
  }
  else {
    value = analogRead(pin);

    client.print(F("Pin A"));
    client.print(pin);
    client.print(F(" reads analog "));
    client.println(value);

    String key = "A";
    key += pin;
    Bridge.put(key, String(value));
  }
}

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

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

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

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

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

String mode = client.readStringUntil('\r');

  if (mode == "input") {
    pinMode(pin, INPUT);
    // Отсылаем клиенту обратное сообщение:
    client.print(F("Pin D"));
    client.print(pin);
    client.print(F(" configured as INPUT!"));
    return;
  }

  if (mode == "output") {
    pinMode(pin, OUTPUT);
    // Отсылаем клиенту обратное сообщение:
    client.print(F("Pin D"));
    client.print(pin);
    client.print(F(" configured as OUTPUT!"));
    return;
  }

  client.print(F("error: invalid mode "));
  client.print(mode);
}

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

// Несколько примеров того, какими могут быть команды для этого скетча:
//
// "digital/13"     -> digitalRead(13)
// "digital/13/1"   -> digitalWrite(13, HIGH)
// "analog/2/123"   -> analogWrite(2, 123)
// "analog/2"       -> analogRead(2)
// "mode/13/input"  -> pinMode(13, INPUT)
// "mode/13/output" -> pinMode(13, OUTPUT)

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

// Включаем «прослушку» порта 5555 – веб-сервер на Yun будет отправлять туда для нас все HTTP-запросы.

YunServer server;

void setup() {
  Serial.begin(9600);

  // Активируем библиотеку Bridge:
  pinMode(13,OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);

  // Начинаем «прослушивать» входящие соединения, но идущие только от локального хоста, 
  // т.е. подключения от внешней сети игнорируем:
  server.listenOnLocalhost();
  server.begin();
}

void loop() {
  // «Забираем» клиентов, идущих от сервера:
  YunClient client = server.accept();

  // Появился ли новый клиент?
  if (client) {
    // Обрабатываем запрос:
    process(client);

    // Закрываем соединение и освобождаем ресурсы:
    client.stop();
  }

  delay(50); // Задержка каждые 50 миллисекунд
}

void process(YunClient client) {
  // Считываем команду:
  String command = client.readStringUntil('/');

  // Это «цифровая» (digital) команда?
  if (command == "digital") {
    digitalCommand(client);
  }

  // Это «аналоговая» (analog) команда?
  if (command == "analog") {
    analogCommand(client);
  }

  // Это команда для смены режима (mode)?
  if (command == "mode") {
    modeCommand(client);
  }
}

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

  // Считываем номер контакта
  pin = client.parseInt();

  // Если следующим символом является «/», это значит, 
  // что полученный запрос идет вместе с некоторым значением 
  // и выглядит примерно так: «/digital/13/1»
  if (client.read() == '/') {
    value = client.parseInt();
    digitalWrite(pin, value);
  } 
  else {
    value = digitalRead(pin);
  }

  // Отсылаем клиенту обратное сообщение:
  client.print(F("Pin D")); // "Контакту D"
  client.print(pin);
  client.print(F(" set to ")); // " присвоено значение "
  client.println(value);

  // Обновляем ключ в базе данных на текущее значение контакта:  
  String key = "D";
  key += pin;
  Bridge.put(key, String(value));
}

void analogCommand(YunClient client) {
  int pin, value;

  // Считываем номер контакта:
  pin = client.parseInt();

  // Если следующим символом является «/», это значит, 
  // что полученный запрос идет вместе с некоторым значением 
  // и выглядит примерно так: "/analog/5/120»
  if (client.read() == '/') {
    // Считываем это значение и выполняем команду:
    value = client.parseInt();
    analogWrite(pin, value);

    // Отсылаем клиенту обратное сообщение:
    client.print(F("Pin D")); // "Контакту D"
    client.print(pin);
    client.print(F(" set to analog ")); // " присвоено аналоговое значение "
    client.println(value);

    // Обновляем ключ в базе данных на текущее значение контакта:  
    String key = "D";
    key += pin;
    Bridge.put(key, String(value));
  }
  else {
    // Считываем номер аналогового контакта:
    value = analogRead(pin);

    // Отсылаем клиенту обратное сообщение:
    client.print(F("Pin A")); // "С контакта A"
    client.print(pin);
    client.print(F(" reads analog ")); // " считано аналоговое значение "
    client.println(value);

    // Обновляем ключ в базе данных на текущее значение контакта:
    String key = "A";
    key += pin;
    Bridge.put(key, String(value));
  }
}

void modeCommand(YunClient client) {
  int pin;

  // Считываем номер контакта:
  pin = client.parseInt();

  // Если «/» не является следующим символом, то URL неправильный:
  if (client.read() != '/') {
    client.println(F("error")); // "ошибка"
    return;
  }

  String mode = client.readStringUntil('\r');

  if (mode == "input") {
    pinMode(pin, INPUT);
    // Отсылаем клиенту обратное сообщение:
    client.print(F("Pin D")); // "Контакт D"
    client.print(pin);
    client.print(F(" configured as INPUT!")); // " сделан входным!"
    return;
  }

  if (mode == "output") {
    pinMode(pin, OUTPUT);
    // Отсылаем клиенту обратное сообщение:
    client.print(F("Pin D")); // "Контакт D"
    client.print(pin);
    client.print(F(" configured as OUTPUT!")); // " сделан выходным!"
    return;
  }

  client.print(F("error: invalid mode ")); // "Ошибка. Вы указали неверную команду для того, чтобы задать режим – "
  client.print(mode);
}

См.также

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