Опубликовано

Взаимодействие Arduino с компьютерной программой Processing

По материалам книги Джереми Блума “Изучаем Arduino: инструменты и методы технического волшебства. 2-е изд.: пер. с англ.“(Глава 7. Последовательный интерфейс USB)

Изучаем Arduino: инструменты и методы технического волшебства. 2-е изд.

Прежде чем рассмотреть взаимодействие Arduino с компьютерной программой, рассмотрим как такое взаимодействие организовано посредством программы Монитора порта.

Отправка одиночных символов для управления светодиодом

Прежде чем приступать к обработке чисел, состоящих из нескольких цифр, разработаем скетч для управления светодиодом с помощью одного символа. В частности, при получении символа “1” скетч будет включать светодиод, а символа “0” — выключать его. Для работы этого скетча нужно подключить светодиод к контакту 9 платы Arduino, как показано на рис. 7.10.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image10.jpeg

Рис. 7.10. Подключение светодиода к контакту 9 платы Arduino (Рисунок создан в программе Fritzing)

Как мы разобрались в предыдущем разделе, при отправке одиночного символа проще всего сравнить его с целевым символом в операторе условия if. Каждый помещаемый в буфер символ сравнивается с символом ‘0’ или ‘1’, и в зависимости от того, с каким символом он совпадает, предпринимается соответствующее действие. Создайте новый скетч, скопируйте в него код из листинга 7.4, загрузите его в свою плату Arduino и экспериментируйте, отправляя одиночные символы 0 и 1 из монитора порта.

Листинг 7.4. Программа single_char_control.ino для управления светодиодом с помощью одиночных символов

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Управление светодиодом с помощью одиночных символов
const int LED=9;
char data; // Переменная для хранения получаемого символа
void setup()
{
Serial.begin(9600); // Запускаем последовательный порт
// со скоростью в бодах = 9600
pinMode(LED, OUTPUT);
}
 
void loop()
{
// Предпринимаем действие только при наличии данных в буфере
if (Serial.available() > 0)
{
data = Serial.read(); // Считываем входящий байт данных
// Включаем светодиод
if (data == '1')
{
digitalWrite(LED, HIGH);
Serial.println("LED ON");
}
 
// Выключаем светодиод
else if (data == '0')
{
digitalWrite(LED, LOW);
Serial.println("LED OFF");
}
}
}

Обратите внимание на то, что вместо простого оператора условия if…else в коде присутствует его вариант if…else…if. Поскольку в каждой передаче вместе с символами управления светодиодом монитор порта также отправляет и символ новой строки, важно удалить этот символ из буфера. Считываемый функцией Serial.read() символ новой строки не проходит проверку на превышение символа ‘0’, и в скетче не предпринимается никакого действия по его обработке. Обрабатываются только получаемые символы ‘0’ и ‘1’. Если же в коде использовался бы вариант if…else, то светодиод выключался бы при получении как символа ‘0’, так и символа новой строки ‘\n’. Более того, даже при получении символа ‘1’ скетч сразу же после включения светодиода выключал бы его при получении символа новой строки ‘\n’, следующего за символом ‘1’.

Управление разноцветным светодиодом с помощью списка значений

Теперь, когда мы знаем, как управлять одним цифровым контактом, рассмотрим, как можно работать одновременно с несколькими, чтобы реализовать более сложные схемы управления. В частности, рассмотрим, как управлять несколькими устройствами, отправляя плате Arduino одновременно набор значений, разделенных запятыми. Для этого эксперимента нам нужно будет подключить к плате Arduino разноцветный светодиод с общим анодом, как показано на монтажной схеме на рис. 7.11.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image11.jpeg

Рис. 7.11. Подключение разноцветного светодиода к плате Arduino (Рисунок создан в программе Fritzing)

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

  • Нам нужно как-то отличить числа от запятых.
  • Последовательность символов нужно преобразовать в целые числа и сопоставить эти числа значениям в диапазоне 0–255 для управления светодиодами, используя функции analogWrite().
  • Нам также нужно учитывать, что мы работаем со светодиодом с общим анодом, и сигналы управления подаются на катоды составляющих его светодиодов. Иными словами, значение 255 выключит светодиод, а значение 0 включит его на полную яркость.
  • Необходимо учитывать возможность, что значения яркости могут состоять из одной, двух или трех цифр.
  • Наша программа должна быть достаточно надежной, способной обрабатывать полученные данные, форматирование которых не соответствует норме, таким образом, чтобы они не искажали данные последующих передач (в разумных пределах).

К счастью среда Arduino IDE содержит очень удобную функцию Serial.parseInt() для определения и извлечения целых чисел. Функция ожидает, пока во входной буфер последовательного порта не поступит нецифровое значение, после чего она преобразовывает все предыдущие цифры в целое число. В нашем случае, первые два значения считываются по обнаружению следующих за ними запятых, а последнее — после обнаружения символа перевода строки.

Чтобы увидеть работу этой функции, загрузите код из листинга 7.5 в свою плату Arduino.

Листинг 7.5. Программа list_control.ino для управления разноцветным светодиодом

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Отправляем одновременно несколько значений
// Данные отправляются в следующем формате: <0-100>,<0-100>,<0,100)>\n
// Здесь числа представляют яркость в процентах красного,
// зеленого и синего светодиодов
// Контакты платы Arduino, к которым подключаются катоды светодиодов
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
void setup()
{
Serial.begin(9600); // Запускаем последовательный порт
// со скоростью в бодах = 9600
Serial.setTimeout(10); // Таймаут, в течение которого
// ожидать целое число
// Задаем выходной режим работы для контактов управления светодиодами
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
// Выключаем светодиоды
// Поскольку светодиод имеет общий анод, для выключения светодиода
// на катод подается сигнал высокого уровня
digitalWrite(RED, HIGH);
digitalWrite(GREEN, HIGH);
digitalWrite(BLUE, HIGH);
}
void loop()
{
// Считываем данные, когда они присутствуют в буфере
if (Serial.available() > 0)
{
// Ожидаем получить три целых числа по последовательному каналу связи
// Функция parseInt() заблокирует исполнение следующего кода
// до тех пора, пока не будет получено действительное целое число
// Целое число определяется по завершающей запятой
// или символу новой строки
// Недействительные символы удаляются перед найденным целым числом,
// а не после него
int val1 = Serial.parseInt();
int val2 = Serial.parseInt();
int val3 = Serial.parseInt();
// После считывания всех целых чисел, очищаем буфер
while (Serial.available())
{
Serial.read();
}
// Ограничиваем полученные значения диапазоном 0–100%
int val1c = constrain(val1,0,100);
int val2c = constrain(val2,0,100);
int val3c = constrain(val3,0,100);
// Сопоставляем аналоговые значения процентным значениям
int rval = map(val1c,0,100,255,0); // Первое действительное
// целое число
int gval = map(val2c,0,100,255,0); // Второе действительное
// целое число
int bval = map(val3c,0,100,255,0); // Третье действительное
// целое число
// Устанавливаем яркость светодиода
analogWrite(RED, rval);
analogWrite(GREEN, gval);
analogWrite(BLUE, bval);
// Выводим на экран использованные значения яркости
Serial.println("Red: " + String(val1c) + "%");
Serial.println("Green: " + String(val2c) + "%");
Serial.println("Blue: " + String(val3c) + "%\n");
}
}

В функции setup() запускаем последовательный интерфейс, а затем с помощью функции setTimeout() задаем величину таймаута, равную 10 мс для функции parseInt(). Если в течение 10 мс по последовательному каналу не будет получен следующий символ, эта функция считает завершенным извлечение текущего целого числа. Это просто мера предосторожности, чтобы не допустить зависания программы в случае отправки неполного списка значений.

Вспомним, что поскольку наш разноцветный светодиод с общим анодом, мы управляем составляющими светодиодами, подключая их катоды на землю. Таким образом, подача высокого уровня на катод светодиода препятствует протеканию тока через него, т. е. выключает светодиод. Подобным образом необходимо инвертировать значения аргументов функции analogWrite(), т. е. значение 255 выключает светодиод, а значение 0 включает его на полную яркость. Код главного цикла loop() ожидает наличия данных в буфере последовательного порта и извлекает из него первые три целых числа. Если буфер содержит какие-либо дополнительные данные, все они удаляются функцией Serial.read(), оставляя буфер пустым. Затем вызывается функция constrain(), ограничивающая все значения диапазоном 0–100. Далее функция map() сопоставляет 0 процентов значению 255, а 100 процентов значению 0, чтобы обеспечить использование функции analogWrite(). Наконец, устанавливаются уровни яркости составляющих цветных светодиодов, значения которых также дополнительно выводятся в окно монитора порта. Затем цикл ожидает поступления следующего набора команд.

Загрузите эту программу в свою плату Arduino и откройте окно монитора последовательного порта. Наберите в строке ввода монитора порта три числа со значениями в диапазоне 0–100, например, 80,10,80, и нажмите кнопку Отправить. Попробуйте немного поэкспериментировать, устанавливая разные цвета для светодиода.

Взаимодействие с компьютерной программой

Со временем вам надоест взаимодействовать с платой Arduino посредством программы монитора порта. К счастью, это не единственная программа, с помощью которой можно обмениваться информацией между компьютером и платой Arduino: практически любой язык программирования содержит библиотеки, позволяющие работать с последовательным портом компьютера. Из наиболее популярных языков программирования, обладающих обширными, хорошо задокументированными библиотеками последовательной связи, можно назвать, например, Python, Java, C, Node.js и другие. Таким образом, если вы знаете какой-либо из этих языков программирования, то сможете разрабатывать на нем программы для двустороннего обмена данными через последовательный интерфейс между компьютером и платой Arduino.

В этой книге мы будем использовать для этого язык Processing, поскольку он очень похож на язык программирования Arduino, с которым вы уже знакомы. Более того, язык программирования Arduino разработан на основе языка Processing. Сначала мы разработаем программу на языке Processing для считывания данных, получаемых в последовательный порт, а затем создадим простой графический интерфейс пользователя для отправки команд плате Arduino.

Интерфейс программирования языка Processing достаточно простой, похожий на интерфейс среды Arduino IDE. В этом разделе мы установим язык Processing на компьютер, а затем разработаем на нем простой графический интерфейс для визуального представления данных, получаемых с платы Arduino по последовательному каналу. Разобравшись с работой этой программы, мы создадим другую: графический интерфейс для передачи данных с компьютера на плату Arduino.

Установка Processing

Чтобы разрабатывать программы на языке Processing, нам нужно установить этот язык на свой компьютер. Загрузите установочный архив для своей операционной системы со страницы загрузки Processing (https://processing.org/download/) на свой компьютер. Для установки просто распакуйте загруженный архив в какую-либо папку. Запустите приложение Processing, выполнив двойной щелчок мышью по значку приложения. Должно открыться главное окно среды IDE, которое выглядит, как показано на рис. 7.12.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image12.jpeg

Рис. 7.12. Главное окно среды Processing IDE

Управление приложением Processing посредством платы Arduino

Для первого эксперимента с Processing мы будем управлять цветом окна приложения на компьютере с помощью потенциометра, подключенного к плате Arduino. Для этого подключите потенциометр к плате Arduino, руководствуясь монтажной схемой на рис. 7.6. Мы уже знаем, как передавать аналоговые значения сигнала потенциометра на компьютер. Тот факт, что принимаемые на компьютере данные подаются в программу на языке Processing, никак не влияет на способ их передачи.

Создайте новый скетч, вставьте в него код из листинга 7.6 и загрузите его в свою плату Arduino. Эта программа каждые 50 мс отправляет текущее значение величины сигнала с потенциометра на последовательный порт компьютера. Период передачи длительностью 50 мс важен. Если передавать значения с максимально возможной скоростью, то скетч Processing не сможет обрабатывать все поступающие значения, и со временем произойдет переполнение входного буфера последовательного порта компьютера.

Листинг 7.6. Программа Arduino arduino_read_pot.ino для передачи данных на компьютер

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Передача значения уровня сигнала с потенциометра на компьютер
const int POT=0; // Сигнал с потенциометра подается
// на аналоговый контакт A0
int val; // Переменная для хранения сопоставленного
// значения сигнала с потенциометра
void setup()
 
{
Serial.begin(9600); // Запускаем последовательную передачу данных
}
 
void loop()
{
val = map(analogRead(POT), 0, 1023, 0, 255); // Считываем сигнал
// с потенциометра и сопоставляем его
// значению в диапазоне 0–255
Serial.println(val); // Отправляем значение на компьютер
delay(50); // Выдерживаем паузу, чтобы
// не переполнить входной буфер
}

А теперь следует интересная часть задачи: создание скетча Processing для приема и обработки данных, передаваемых платой Arduino. Программа, приведенная в листинге 7.7, считывает данные из входного буфера последовательного порта компьютера, и изменяет яркость одного из основных цветов созданного им окна на основе значений, получаемых от Arduino. Создайте новый скетч Processing и скопируйте в него код из листинга 7.7. Затем вам нужно будет внести в скопированный код одну важную корректировку. В частности, скетчу Processing необходимо знать, на каком последовательном порту ожидать поступающие от Arduino данные. Это будет тот же самый порт, к которому подключена ваша плата Arduino. Поэтому в листинге 7.7 замените COM3 номером этого последовательного порта. (В системах под Linux и Mac OS обозначение этого порта будет выглядеть наподобие /dev/ttyUSB0). Чтобы избежать ошибок при ручном вводе, номер последовательного порта можно скопировать из среды Arduino IDE.

Листинг 7.7. Скетч processing_display_color.pde для приема данных по последовательному каналу и изменения цвета окна

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Скетч Processing для приема данных по последовательному каналу
// и изменения цвета окна
// Импортируем и инициализируем библиотеку последовательного порта
import processing.serial.*;
Serial port;
float brightness = 0; // Переменная для хранения значения сигнала
// с потенциометра
 
void setup()
{
size(500,500); // Размер окна
port = new Serial(this, "COM3", 9600); // Инициализируем
// последовательный порт
port.bufferUntil('\n'); // Конфигурируем порт для чтения
// данных до символа новой строки
}
 
void draw()
{
background(0,0,brightness); // Обновляем окно
}
void serialEvent (Serial port)
{
brightness = float(port.readStringUntil('\n')); // Получаем значение
// от Arduino
}

Скопировав код в свой скетч и указав в нем правильный номер последовательного порта, проверьте, что программа монитора порта среды Arduino IDE не открыта. Последовательный порт компьютера может одновременно использоваться только одной программой. Нажмите кнопку Run окна Processing IDE (левая кнопка со значком треугольника в ней, расположенная в верхнем левом углу окна). Откроется небольшое окно (рис. 7.13). Вращайте подключенный к плате Arduino потенциометр; цвет окна должен плавно изменяться с черного на синий.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image13.jpeg

Increasing analog values

Увеличивающиеся аналоговые значения

Рис. 7.13. Пример исполнения скетча Processing для изменения цвета окна

Убедившись, что наш скетч работает должным образом, рассмотрим пошагово его код, чтобы разобраться, как он работает. В отличие от скетчей Arduino, библиотека для работы с последовательным портом не импортируется автоматически в программы на Processing. Эту задачу выполняет оператор import processing.serial.*, а оператор Serial port создает объект последовательной связи, называющийся port.

Подобно скетчам Arduino, программы на Processing содержат функцию setup(), которая исполняется один раз в начале кода. В данном коде Processing эта функция выполняет настройки последовательного порта и посредством команды size(500,500) создает окно размером 500 × 500 пикселов. Оператор port = new Serial(this, “COM3”, 9600) предоставляет Processing всю необходимую информацию для создания экземпляра объекта последовательного порта. При исполнении в этом скетче данный экземпляр порта (называющийся port) будет поддерживать связь через порт COM3 (или через другой конкретный порт) со скоростью 9600 бод. Скорость последовательной передачи данных должна быть одинаковой, как в скетче Arduino, так и в скетче Processing; в противном случае передаваемые символы будут искажаться в процессе приема. Оператор port.bufferUntil(‘\n’) дает указание Processing помещать полученные данные во входной буфер и не предпринимать никаких действий до тех пор, пока не будет получен символ новой строки.

В Processing вместо цикла loop() предусмотрены другие специальные функции, в частности, функции draw() и serialEvent(). Функция draw() Processing похожа на функцию loop() Arduino: она исполняется в бесконечном цикле и обновляет дисплей. Функция background() устанавливает цвет окна, задавая интенсивность составляющих цветов: красного, зеленого и синего (значения которых передаются функции в аргументах). В данном случае выходной сигнал от потенциометра управляет интенсивностью синего цвета, а для красного и зеленого цветов установлены нулевые значения. Можно изменить управляемый потенциометром цвет, просто разместив аргумент brightness в соответствующей позиции списка аргументов. Значения красного, зеленого и синего цветов задаются значениями в диапазоне от 0 до 255, поэтому значения выходного сигнала с потенциометра перед их передачей сопоставляются значениям в этом диапазоне.

Функция serialEvent() вызывается всякий раз, когда выполняется условие bufferUntil(), заданное в функции setup(). Таким условием является получение символа новой строки. Поступающие по последовательному каналу данные считываются в строку оператором port.readStringUntil(‘\n’). Строку можно рассматривать, как массив текстовых символов. Содержимое строки преобразуется в число с плавающей запятой посредством функции float(). Результат этой функции присваивается переменной brightness, в итоге изменяется цвет фона окна приложения.

Чтобы остановить исполнение приложения Processing, нажмите кнопку Stop в окне среды Processing IDE (круглая кнопка со значком квадрата внутри нее, расположенная справа от кнопки Run).

Передача скетчем Processing данных на плату Arduino

Очевидным следующим шагом будет передача данных в обратном направлении: с компьютера на Arduino. Для этого эксперимента нам нужно будет подключить к плате Arduino разноцветный светодиод с общим анодом, как показано на монтажной схеме на рис. 7.11 и загрузить в плату Arduino программу из листинга 7.5. Только теперь вместо отправки плате Arduino трех числовых значений через монитор порта, мы будем отправлять цвет, выбираемый с помощью палитры цветов, встроенной в Processing.

Создайте в Processing новый скетч, скопируйте в него код, приведенный в листинге 7.8, и запустите программу на исполнение. (Не забудьте изменить номер порта в коде на номер порта, используемый вашей платой Arduino, как это нужно было сделать в предыдущем скетче.)

Листинг 7.8. Скетч processing_control_RGB.pde для управления разноцветным светодиодом на Arduino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import processing.serial.*; // Импортируем библиотеку serial
PImage img; // Объект изображения
Serial port; // Объект последовательного порта
void setup()
{
size(640,256); // Размер изображения в цветовой модели HSV
img = loadImage("hsv.jpg"); // Загружаем фоновое изображение
port = new Serial(this, "COM3", 9600); // Открываем последовательный
// порт
}
void draw()
{
background(0); // Черный фон
image(img,0,0); // Накладываемое изображение
}
void mousePressed()
{
color c = get(mouseX, mouseY); // Получаем цвет RGB в точке,
// где находится курсор мыши
int r = int(map(red(c), 0, 255, 0, 100));
int g = int(map(green(c), 0, 255, 0, 100));
int b = int(map(blue(c), 0, 255, 0, 100));
String colors = r+","+g+","+b+"\n"; // Извлекаем значения из цвета
print(colors); // Выводим значения цветов
// на экран для целей отладки
port.write(colors); // Отправляем значения
// на плату Arduino
}

Скетчи Processing автоматически загружают сопутствующие файлы из папки data, вложенной в папку скетча. Файл hsv.jpg входит в состав кода для этой главы. Загрузите его и поместите в папку data в папке своего скетча. По умолчанию Processing сохраняет скетчи в папке Processing, находящейся в папке Мои документы текущего пользователя, автоматически создавая папку для скетча с таким же самым названием, как и скетч. Структура папок проекта выглядит подобно показанной на рис. 7.14. Изображение в папке data будет использоваться в качестве цветовой палитры.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image14.jpeg

Рис. 7.14. Структура папок проекта Processing

Запустите скетч Processing на исполнение; отроется окно приложения, заполненное палитрой, как на рис. 7.15.

7

Рис. 7.15. Окно программы Processing для выбора цвета

Щелкайте мышью по разным цветам; в консоли окна среды Processing IDE будут выводиться значения составных цветов выбранного цвета, которые передаются на плату Arduino, вызывая соответствующее изменение цвета подключенного к ней разноцветного светодиода.

Убедившись, что все составляющие проекта функционируют должным образом, рассмотрим код скетча Processing более подробно, чтобы разобраться, как он работает. Как и в предыдущем скетче Processing, импортируется библиотека последовательного интерфейса serial и создается объект последовательного порта с названием port. Кроме этого создается объект типа PImage с названием img, который будет содержать фоновое изображение. В функции setup() выполняется инициализация последовательного порта, устанавливается размер окна приложения, равный размеру выводимого в нем изображения, и осуществляется импорт изображения в объект изображения, с помощью оператора img = loadImage(“hsv.jpg”). Операция импорта предполагает, что файл hsv.jpg находится в папке data текущего скетча Processing.

В функции draw() изображение загружается в окно посредством оператора image(img,0,0). В данном случае аргумент img обозначает изображение, которое мы хотим отображать в окне приложения, а аргументы 0,0 обозначают координаты, в которых нужно начинать выводить это изображение. Эти координаты представляют верхний левый угол окна приложения.

При каждом щелчке мышью по изображению палитры в окне приложения вызывается функция mousePressed(). Цвет пиксела, по которому пришелся щелчок, сохраняется в виде объекта типа color с названием c. Сам цвет извлекается методом get(), который предоставляет приложению информацию, откуда получить значения цвета (в данном случае, координаты X и Y щелчка мыши). Затем вызывается функция map(), которая сопоставляет значения составных цветов процентным значениям, ожидаемых скетчем Arduino. Полученные процентные значения далее конкатенируются в строку, которая отправляется по последовательному каналу на плату Arduino. Для справки эти значения также выводятся в консоли главного окна Processing IDE.

Подключите свою плату Arduino (с подсоединенным к ней разноцветным светодиодом) к компьютеру и загрузите в нее код из листинга 7.5. Запустите на исполнение скетч Processing (предварительно исправив в нем номер последовательного порта должным образом), и щелкайте по разным цветам в палитре в открывшемся окне приложения. Выбранный таким образом цвет должен устанавливаться на разноцветном светодиоде, подключенном к плате Arduino.

Резюме

В этой главе мы узнали следующее:

  • Платы Arduino подключаются к компьютеру через преобразователь USB/RS-232.
  • Для преобразования USB/RS-232 в разных платах Arduino может быть предусмотрена специальная микросхема или реализована встроенная поддержка функциональности USB.
  • Плата Arduino может отправлять данные на компьютер через интерфейс USB.
  • Для форматирования текста, выводимого в окне монитора порта, можно использовать символы новой строки и табуляции.
  • Данные передаются по последовательному каналу в виде символов, которые можно преобразовать в целые числа несколькими способами.
  • По последовательному каналу с компьютера в скетч Arduino можно отправлять наборы целых чисел, разделенных запятыми. В скетче Arduino составляющие числа можно извлечь из набора с помощью специальных функций и использовать их в качестве команд для скетча.
  • По последовательному каналу можно отправлять данные из скетча Arduino в программу на Processing, исполняющуюся на компьютере.
  • Из программы на Processing можно отравлять данные в скетч Arduino для управления подключенными к плате Arduino периферийными устройствами.
Опубликовано

Платформа node.js

Большинство программ для веб-сервера в этой книге написаны на основе платформы (фреймворка) node.js, позволяющей программировать в операционной системе на языке JavaScript. Первоначально язык JavaScript предназначался для использования в веб-браузерах, чтобы предоставить пользователям возможности взаимодействия с веб-страницами, которые не обеспечивались средствами HTML[1]. Вскоре он стал стандартным языком программирования приложений для веб-браузеров. В 2009 году Райан Даль (Ryan Dahl) с группой программистов из компании Joyent решили использовать язык JavaScript при создании серверных программ, для чего они и разработали платформу node.js. Впоследствии эта платформа приобрела большую популярность для программирования серверных приложений, а также нашла много других применений.

Весьма примечательно, что созданные созданные с использованием платформы node.js программы могут исполняться на локальном или встроенном компьютере, не требуя для этого установки веб-сервера[2]. Это дает возможность протестировать на локальном компьютере свеженаписанные программы, прежде чем загружать их на веб-сайт. Платформа node.js также позволяет создавать клиент-серверные приложения для использования в домашней сети без необходимости подключения к Интернету. Чтобы упростить выполнение примеров этой книги, в большинстве случаев в качестве сервера в ней задействуется локальный компьютер.

В отличие от среды Processing, для платформы node.js не существует стандартного графического интерфейса пользователя. Работа с ней выполняется с помощью командной строки. Загрузите программу установщика node.js с сайта https://nodejs.org/en/ и установите ее на свой компьютер. Затем откройте окно программы терминала, как описано в предыдущем разделе, и выполните команду:

$ node –v

В ответ на экран должно быть выведено сообщение наподобие следующего:

v6.9.5

Это сообщение содержит информацию о версии node.js, установленной на компьютере. Код для проектов этой книги писался под версию node.js 6.9.5, поэтому для их исполнения на вашем компьютере должна быть установлена эта или более поздняя версия node.js.

Установка набора средств разработки

Для создания программ в node.js требуется также ряд других программных средств разработки, которые могут отсутствовать у начинающих программистов. Такой набор состоит из компиляторов, текстовых редакторов и отладчиков и иногда называется цепочкой инструментов[3] (что подразумевает последовательное их использование). Для компьютеров под Windows большинство этих инструментов доступны в пакете интегрированной среды разработки Microsoft Visual Studio, а под macOS — в интегрированной среде разработки XCode.

Пакет Visual Studio платный, но также существует его бесплатная версия Community Edition. Загрузить любую версию пакета, включая бесплатную, можно по адресу: www.visualstudio.com/downloads/.

Пакет XCode можно загрузить из магазина приложений Mac App Store. После установки этого пакета нужно будет также установить средства XCode для работы в командной строке. Это можно сделать, выполнив следующую команду:

$ xcode-select --install

После установки необходимых программных средств можно устанавливать и node.js.

Пишем код

Итак, создадим в node.js первую программу. Запустите свой текстовый редактор, введите в него следующий код:

console.log("Hello world!");

и сохраните файл под именем hello.js на своем компьютере.

Затем запустите программу терминала и перейдите в каталог, в котором вы сохранили программу. Запустите программу на исполнение, выполнив команду:

$ node hello.js

В результате исполнения этой команды на экран будет выведен следующий текст:

Hello world!

Примерно так же захватывающе, как ваш первый скетч на Processing[4], не так ли?

Веб-сервер на node.js

Платформа node.js первоначально предназначалась для написания веб-серверов, и именно с ее помощью большинство пользователей создают такие программы.

Сервер — это программа, которая предоставляет в сети сервисы другим программам, которые называются клиентами. Клиенты посылают веб-серверу запросы по протоколу HTTP[5]. В ответ на эти запросы сервер отсылает клиенту файлы HTML, изображений, аудио и других элементов веб-сайта. Например, ваш веб-браузер, выполняющий роль клиента, устанавливает подключение к серверу и запрашивает веб-страницу. Серверная программа принимает подключение и доставляет клиентской программе (т. е. браузеру) файлы, представляющие эту веб-страницу.

Протокол HTTP, серверы и клиенты рассматриваются более подробно в главе 3, однако мы и сейчас можем написать простой сервер на node.js.

Пишем код

Создайте в своем домашнем каталоге каталог под названием simpleServer. Затем откройте текстовый редактор, введите в него представленную далее программу и сохраните ее в файле server.js в каталоге simpleServer.

Рассмотрим ее код подробнее, чтобы выяснить, как выглядит общая структура программ node.js:

  1. Подключаются библиотеки:
// подключаем библиотеки и объявляем глобальные переменные:
 
var express = require('express'); // Подключаем библиотеку express
  1. Определяются глобальные переменные:
var server = express(); // создаем объект server,
 
// используя библиотеку express
  1. Определяются функции обратного вызова:
// определяем функцию, которая вызывается
 
// при поступления запроса от клиента:
 
function respondToClient(request, response) {
 
console.log("got a request"); // выводим сообщение
 
//в консоли командной строки
 
//отправляем сообщение клиенту:
 
response.writeHead(200, {"Content-Type": "text/html"});
 
response.write("Hello, client!");
 
response.end();
 
}
  1. Исполняется основной код:
// Запускаем сервер:
 
server.listen (8080);
 
// определяем, что делать при получении запроса клиента:
 
server.get('/*', respondToClient);
 
console.log("Server is listening on port 8080");

Убедитесь в наличии подключения к Интернету, затем перейдите в командной строке в каталог simpleServer и выполните команду:

$ npm install express

Эта команда дает указание npm — диспетчеру пакетов node (node package manager) установить библиотеку express.js, которая необходима для работы сервера. В процессе исполнения команды отображается индикатор выполнения, выводятся несколько предупреждений, и по завершении исполнения снова возвращается командная строка. Теперь выполните следующую команду:

$ node server.js

В результате исполнения этой команды на экран выведется следующий текст:

Server is listening on port 8080 (Сервер прослушивает порт 8080)

После этого предложение командной строки вы увидеть не сможете, поскольку, в отличие от программы из файла hello.js, исполнение которой завершилось после выполнения одной ее строки, эта программа продолжает исполняться. Откройте какой-либо браузер и введите в строку адреса:

$ node server.js
http://localhost:8080

В результате должна открыться страница, наподобие показанной на рис. 1.5.

Рис. 1.5. Результат исполнения программы сервера node.js браузере

При этом в консоли командной строки должно отобразиться сообщение типа следующего:

Got a request! (Получен запрос!)

И так на каждый запрос веб-браузера сервер выводит ответ в консоль командной строки. Иногда после ввода адреса в адресную строку веб-браузер посылает серверу два запроса, одним из которых является запрос favicon — небольшого значка слева от адреса страницы в строке адреса веб-браузера.

Чтобы завершить работу программы веб-сервера, нажмите на клавиатуре комбинацию клавиш <Ctrl>+<C>.

Структура программ node.js

Структура программ node.js (которые иногда называются скриптами или сценариями) иная, чем у скетчей Processing. Рассмотрим некоторые из этих различий.

Прежде всего, JavaScript (и, соответственно, node.js) является языком со слабым контролем типов данных. Это означает, что при объявлении переменных объявлять тип их данных не нужно — достаточно объявить их с помощью ключевого слова var. А JavaScript сам попытается определить тип данных переменной в зависимости от способа ее применения.

Второе, JavaScript является функциональным языком программирования. То есть переменные в нем могут содержать не только значения, но и функции. Все станет вам более понятным, когда вы увидите реализацию этого принципа на практике. Посмотрите на программу веб-сервера из предыдущего раздела. В первой строке программы создается копия (которая называется экземпляром) библиотеки node.js express, которая сохраняется в переменной express. Функции этой библиотеки будут затем вызываться из переменной http. Во второй строке кода функция express() создает экземпляр всей библиотеки express, который сохраняется в переменной server. Далее, в конце программы, вызывается функция listen() объекта server, которая прослушивает порт 8080 на наличие новых запросов от клиентов.

Третье, программы JavaScript исполняются асинхронно. Это означает, что каждая команда начинает исполняться сразу же после запуска предыдущей, не дожидаясь завершения ее исполнения. При вызове функции ей часто передается функция обратного вызова, которая исполняется, когда она готова выдать какие-либо результаты. Пример использования такой функции можно увидеть во второй строке основного кода программы server.js — функция server.get() содержит функцию обратного вызова respondToClient(), которая исполняется при каждом поступлении запроса от нового клиента. Благодаря свойству асинхронности программ JavaScript, сервер может одновременно отвечать на несколько запросов, без необходимости завершить ответ на один, чтобы начать отвечать на другой.

В языке JavaScript используется синтаксис в стиле языков С и Java. В частности, операторы (инструкции) заканчиваются точкой с запятой, а блоки кода заключаются в фигурные скобки. Синтаксис в стиле языка С используется и для условных операторов if-then и операторов цикла for.

Сценарии серверов на node.js обычно имеют такую структуру:

  1. С помощью функции require() подключаются все необходимые библиотеки.
  2. Объявляются переменные, область действия которых охватывает всю программу (глобальные переменные).
  3. Объявляются функции обратного вызова, которые будут использоваться в основном коде.
  4. Исполняется основной код.

В соответствии с этой структурой и создана программа server.js.

Дополнительную информацию по синтаксису node.js вы найдете в руководстве, которое можно загрузить с веб-сайта www.nodejs.org. Более подробно программирование с использованием node.js описано в книге Шелли Пауэрс (Shelley Powers) «Learning Node: Moving to the Server-Side» (издательство O’Reilly). А книга Этана Брауна (Ethan Brown) «Learning JavaScript» (издательство O’Reily) поможет вам в изучении языка JavaScript.

  1. HTML, HyperText Markup Language — язык разметки гипертекстовых документов.
  2. Значимость этого обстоятельства становится понятной в свете того факта, что для исполнения на локальном или удаленном компьютере программ, написанных на другом популярном языке для серверных программ — PHP, требуется наличие веб-сервера — например, Apache.
  3. От англ. toolchain.
  4. К сожалению, русские буквы с консольном режиме в среде node.js не отображаются, поэтому получить здесь «Здравствуй, мир!» у нас не получится.
  5. HTTP, Hypertext Transfer [Transport] Protocol — протокол передачи гипертекста.
Опубликовано

Интерфейсы командной строки и удаленные серверы

Интерфейсы командной строки и удаленные серверы

Одним из наиболее эффективных инструментов, которым мы будем пользоваться для отладки проектов этой книги, является программа удаленного доступа, позволяющая получить доступ к консоли командной строки компьютера. Если вам никогда раньше не приходилось работать с интерфейсом командной строки, это средство может поначалу показаться неудобным, но привыкнуть к нему несложно. Мы будем использовать интерфейс командной строки как для работы с локальным компьютером, так и для получения доступа к веб-серверам и встроенным компьютерам.

На заре компьютерной эры графических интерфейсов пользователя не существовало вообще, и все взаимодействие с компьютером осуществлялось посредством интерфейса командной строки. Многие сетевые администраторы продолжают использовать командную строку в качестве основного интерфейса, поскольку это быстрое и эффективное средство управления, как вы сами сможете в этом убедиться, познакомившись с ним поближе. Интерфейсы командной строки потребляют намного меньше вычислительных ресурсов компьютера, чем графические интерфейсы, поэтому они особенно полезны для взаимодействия с маломощными встроенными процессорами и микроконтроллерами.

Наиболее распространенная версия интерфейса командной строки используется в операционных системах на основе UNIX, включая такие операционные системы, как BSD, Linux, macOS и прочие. Операционные системы, интерфейс командной строки в которых организован таким образом, называются операционными системами в стиле POSIX[1]. Все встречающиеся в этой книге инструкции командной строки предполагают использование интерфейса командной строки именно в этом стиле.

Доступ к интерфейсу командной строки

Доступ к  интерфейсу командной строки на компьютере реализуется через программу эмуляции терминала.

В macOS и Linux

В macOS эта программа называется Terminal и находится в подкаталоге Utilities каталога Applications. В Linux эмулятор командной строки может называться xterm, rxvt, Terminal или Konsole.

 В Windows

Интерфейс командной строки Windows основан на DOS и отличается от интерфейсов командной строки, используемых в операционных системах в стиле POSIX. Найти программу командной строки в Windows можно, набрав cmd в поле поиска меню Пуск. Пока готовилась эта книга, компания Microsoft выпустила интерфейс командной строки в стиле POSIX для Windows 10 (выполните поиск по фразе: bash для Windows 10) — в настоящее время он доступен только в режиме разработчика, но уже выглядит многообещающе. Получить полноценный интерпретатор команд (именно так еще называется интерфейс командной строки) в стиле POSIX на Windows можно, установив программу Cygwin (www.cygwin.com). По мере возможности, примеры этой книги с использованием командной строки для Windows были протестированы под Cygwin и доказали свою работоспособность. В процессе установки Cygwin в обязательном порядке выберите опцию установки пакета Net (входит в список экрана Packages установщика)  тогда будут установлены многие полезные сетевые инструменты, использующие стиль POSIX.

Виртуальные частные серверы

Многие рассматриваемые в этой книге программы представляют собой веб-серверы, для работы с которыми требуется веб-хост. Современные веб-серверы очень просто устанавливать и обслуживать. И если у вас нет своего веб-хоста, можно обратиться к поставщикам услуг веб-хостинга, предоставляющим услуги виртуального частного сервера (ВЧС). У них можно будет создать виртуальный веб-сервер, доступ к которому будет только у вас. Виртуальный веб-сервер позволит вам разобраться с конфигурированием веб-сервера и управлением им, а если вы что-либо наконфигурируете до невозможности восстановления нормальной работы веб-сервера, его можно будет просто удалить нажатием кнопки на веб-панели и создать другой веб-сервер с исходной конфигурацией. Существует ряд поставщиков услуг веб-хостинга, предоставляющих услуги виртуального частного сервера по низкой цене или вообще бесплатно — при условии ограниченного веб-трафика на ваш сервер. Например, такие поставщики услуг веб-хостинга как Digital Ocean (www.digitalocean.com), Amazon Web Services (aws.amazon.com), BlueHost (www.bluehost.com) и DreamHost (www.dreamhost.com) предоставляют услуги ВЧС по вполне доступным расценкам. Некоторые поставщики услуг веб-хостинга также предоставляют скидки для преподавателей и/или студентов, так что уточните у них и эту возможность.

Если вы решили воспользоваться услугами поставщика веб-хостинга и создать виртуальный веб-сервер, предпочтительней выбрать платный бюджетный вариант вместо бесплатного. Это объясняется тем, что в первом случае многие поставщики услуг веб-хостинга также предоставляют средства установки веб-сервера одним щелчком. На панели управления веб-хоста вы просто выбираете необходимые операционную систему и среду программирования или инструменты, которые желаете установить, нажимаете кнопку, и система автоматически устанавливает веб-сервер, сконфигурированный по вашим требованиям. При этом следует иметь в виду, что предоставление доступа к интерфейсу командной строки зависит от конкретного поставщика услуг веб-хостинга — некоторые предоставляют его, а некоторые нет. Так что, уточните и этот момент, прежде чем заключать договор с поставщиком.

Подключение к удаленному веб-хосту

Хотя интерфейс командной строки можно использовать для работы на локальном компьютере, в этой книге он также часто задействуется для доступа к удаленным компьютерам: или к веб-хосту или ко встроенному микропроцессору. Большинство поставщиков веб-хостинга используют Linux, BSD, Solaris или другую UNIX-подобную операционную систему.

Для компьютеров Windows существует несколько программ удаленного доступа, но мы будем пользоваться программой PuTTY, которую можно загрузить по адресу www.puttyssh.org. Процедура установки несложная — с веб-сайта программы загрузите установщик Windows для нее и запустите его на исполнение. На компьютерах под macOS и Linux для удаленного доступа можно использовать программу OpenSSH, которая входит в состав обеих этих операционных систем. Запустить ее на исполнение можно в программе Terminal с помощью команды ssh.

В macOS и Linux

Откройте программу терминала. Обычно терминал предоставляет простое текстовое окно с приветствием наподобие следующего:

Last login: Wed Feb 22 07:20:34 on ttyp1

ComputerName:~ username$

В системах POSIX символ $ называется приглашением командной строки. Когда за этим символом следует мигающий курсор, это означает, что система ожидает ввода команды. Во всех случаях, рассмотренных в этой книге, в командную строку следует ввести все, что следует за этим символом.

Чтобы подключиться к требуемому веб-серверу, выполните в командной строке команду:

ssh имя_пользователя@имя_хоста.com

Разумеется, вместо параметров имя_пользователя и имя_хоста.com введите свои имя пользователя (имя_пользователя) и адрес веб-сервера (имя_хоста.com) соответственно. Введите пароль, который затем потребует удаленный веб-сервер, и вы должны к нему подключиться.

В Windows

Запустите программу PuTTY (рис. 1.3).

Рис. 1.3. Главное окно программы PuTTY

Введите адрес своего веб-сервера (имя_хоста.com) в поле Host Name, установите в разделе Connection type переключатель SSH и нажмите кнопку Open. Затем выполните вход на сервер, введя в соответствующие поля открывшейся панели свои имя пользователя и пароль.

При подключение система потребует согласиться на использование ключа ssh. Это уникальный идентификатор, который позволит вашему компьютеру идентифицировать ваш хост при будущих подключениях к нему. Поэтому дайте свое согласие на использование этого ключа.

Работа с командной строкой

Установив соединение с удаленным веб-сервером, вы увидите примерно такое сообщение:

Last login: Wed Feb 22 08:50:04 2016 from 216.157.45.215

[userid@myhost ~]$

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

$ pwd

Эта команда состоит из первых букв фразы print working directory, которая означает «распечатать рабочий каталог». Она указывает компьютеру отобразить имя и путь текущего каталога. (Многие команды POSIX весьма кратки — чтобы их было легче вводить. С другой стороны, аббревиатурные команды труднее запомнить.) В ответ сервер выведет путь и имя текущего каталога — в моем случае:

/home/igoe

Это рабочий (домашний) каталог учетной записи на сервере. Для вывода списка файлов каталога используется команда ls (list):

$ ls -l .

Точки в конце команды

Точка в конце команды означает «текущий каталог», а две точки — «родительский каталог текущего каталога».

Параметр –l при команде ls означает list long — требование выводить подробный список. В результате исполнения этой команды выводится примерно такой ответ:

total 44

drwxr-xr-x 13 igoe users 4096 Apr 14 11:42 public_html

drwxr-xr-x 3 igoe users 4096 Nov 25 2005 share

Это список всех файлов и вложенных каталогов, содержащихся в текущем каталоге, с указанием их атрибутов:

  • в первом элементе строки (например: drwxr-xr-x) указываются разрешения для действий с этим объектом: чтение, изменение или исполнение;
  • во втором элементе (13) указывается количество ссылок на этот файл из других областей системы;
  • в третьем элементе (igoe) указывается владелец объекта, а в четвертом (users) — группа владельцев;
  • в пятом элементе (4096) указывается размер объекта, а в шестом (Apr 14 11:42) — дата и время последнего изменения;
  • наконец, в последнем элементе (public_html) указывается имя объекта.

В среде POSIX все файлы, имена которых начинаются с точки, в общем случае не отображаются. Это требуется для некоторых особых файлов — таких, например, как файлы паролей или конфигурационные файлы. Чтобы просмотреть содержимое каталога, включая его скрытые файлы, с командой ls нужно использовать параметр: ‑la:

$ ls -la

Для создания нового каталога служит команда: mkdir (make directory):

$ mkdir directoryname

Эта команда создает новый каталог в текущем каталоге. Команда ls –l, выполненная после создания нового каталога, отобразит этот каталог на новой строке в списке объектов текущего каталога. При просмотре содержимого пустого каталога (каким будет вновь созданный каталог) с помощью команды ls -la выводится только две строчки:

drwxr-xr-x 2 tqi6023 users 4096 Feb 17 10:19 .

drwxr-xr-x 4 tqi6023 users 4096 Feb 17 10:19 ..

Первая строчка — с одной точкой в конце — это ссылка на данный каталог, а вторая — с двумя точками в конце — ссылка на родительский каталог. Такие две ссылки будут находиться в любом каталоге, и удалить их нельзя.

Чтобы удалить каталог, служит команда rm (remove directory) с указанием каталога, подлежащего удалению:

$ rmdir directoryname

Удалить можно только пустой каталог, поэтому перед удалением каталога нужно удалить все его содержимое — как файлы, так и вложенные каталоги. Команда rmdir выполняется немедленно, без запроса на подтверждение удаления, поэтому нужно быть осторожным в ее использовании. Не следует также удалять какие бы то ни было каталоги или файлы, которые создавали не вы.

В большинстве веб-хостингов для веб-сайтов пользователей автоматически создается домашний каталог, которая называется html или public_html, — для размещения в нем файлов HTML для общего доступа. Если на вашем веб-сервере такого каталога нет, создайте его с помощью команды mkdir:

$ mkdir html

Для перемещения из одного каталога в другой служит команда cd (change directory) — изменить каталог. Например, перейти из корневого каталога в каталог html можно, выполнив следующую команду:

$ cd html

Чтобы переместиться на один уровень выше в иерархии каталогов, выполняется команда:

$ cd ..

Для возврата в домашний (корневой) каталог к команде cd добавляется параметр ~ (тильда):

$ cd ~

Возвратиться в домашний каталог можно, просто выполнив команду cd без параметров.

Для перехода во вложенный каталог этот каталог указывается после родительского каталога через косую черту / (слэш). Например, чтобы перейти в каталог html в домашнем каталоге, выполняется команда cd~/html. Чтобы указать абсолютный путь из главного каталога сервера (который называется root — корневой), в начале пути файла ставится такая же косая черта — /. Пути без косой черты в их начале называются относительными.

Управление доступом к файлам

Выполните команду ls –l, чтобы вывести список файлов текущего каталога, и рассмотрите поближе разрешения для файлов.

Например, обозначение:

drwx ——

означает, что объект является каталогом (d — directory), и создавший его пользователь (который также называется владельцем) может просматривать или читать его (r — read), записывать в него (w — write), а также исполнять его (x — execute). Рассмотрим другой пример разрешения:

-rw-rw-rw

Дефис в начале означает, что объект является файлом (а не каталогом), и что владелец файла, группа владельцев (обычно владелец является членом этой группы), а также любой другой, кто имеет доступ к файлу, может просматривать его и выполнять запись в него. При этом первая группа rw- задает разрешения владельца, вторая — группы, а третья — всех остальных. Владелец объекта может изменить его разрешения с помощью команды chmod:

$ chmod go-w имя_файла

Параметры этой команды указывают пользователей, которых она затрагивает, и изменяемые разрешения. В приведенном примере мы удаляем разрешения на запись (-w) для группы (g — group) владельцев файла и всех других (o — others), кроме владельца файла. А в следующем примере мы присваиваем права записи и исполнения для группы и других пользователей:

$ chmod go+wx имя_файла

Как вы уже поняли, в параметрах команды chmod буква u означает пользователя (user), g — группу (group), а o — прочих (others). Мы также знаем, что буква r означает разрешения чтения (read), w — записи (write), а x — исполнения (execute). Знак + (плюс) означает присвоение разрешений, а знак – (минус) — лишение их. Будьте осторожны, чтобы случайно не лишить разрешений самого себя (пользователя). Кроме того, выработайте привычку не предоставлять доступа к файлам для групп и прочих, если только в этом нет необходимости, — на крупных поставщиках услуг веб-хостинга иметь соседями по серверу сотни других пользователей — обычное дело.

Создание, просмотр и удаление файлов

Для работы с файлами вам пригодятся еще две программы командной строки: nano и less. Программа nano — это текстовый редактор, и очень простой редактор, поэтому для объемных работ лучше редактировать текст на своем компьютере с помощью какого-либо другого, более удобного, редактора, а затем загружать готовый текст на сервер. Но для небольших правок прямо на сервере программа nano незаменима. Чтобы создать с помощью nano новый файл, выполните следующую команду:

$ nano имя_файла.txt

Откроется окно редактора (рис. 1.4).

Рис. 1.4. Окно текстового редактора nano. В нижней части окна имеется список доступных команд, которые исполняются по нажатию клавиши <Ctrl> совместно с клавишей буквы английского алфавита, указанной слева от соответствующей команды. Например, нажатие комбинации клавиш <Ctrl>+<K> выполняет операцию вырезания (kut) выделенного фрагмента текста

Все команды для работы в nano вводятся с клавиатуры совместно с клавишей <Ctrl>. Например, для выхода из программы нужно нажать комбинацию клавиш <Ctrl>+<X>. Наиболее часто употребляемые команды указаны в нижней части окна редактора.

Удалить любой файл можно с помощью команды rm (remove):

$ rm filename

Подобно команде rmdir, команда rm не выводит запроса на подтверждение удаления файла, поэтому нужно быть осторожным в ее использовании.

Насколько редактор nano удобен для быстрого создания и редактирования небольших текстовых файлов, настолько для чтения таких файлов хорошо подходит редактор less. Этот редактор отображает текстовый файл по одному экрану за раз. Для просмотра текстового файла в less нужно просто ввести имя этого редактора, а за ним требуемый файл:

$ less имя_файла.txt

В результате содержимое файла выводится поэкранно, с приглашением в виде двоеточия (:) в конце экрана. Нажатие клавиши пробела выводит следующий экран текста. Чтобы завершить работу программы, нажмите клавишу <q>. Определенно, похвастаться никакими крутыми наворотами less не может, но со своей основной задачей — просмотром длинных файлов — он справляется «на отлично».

Для просмотра файлов также могут быть полезными команды cat, head и tail.

Команда cat вываливает на экран все содержимое файла без разбиения на его страницы:

$ cat имя_файла.txt

А команды head и tail используются для просмотра начала и конца длинных файлов, соответственно. Количество строк файла для просмотра указывается в параметре, следующем за командой:

$ head -5 имя_файла.txt

В этом случае будут отображены первые пять строк файла имя_файла.txt. Подобным образом команда:

$ tail -10 filename.txt

выводит на экран последние десять строк файла имя_файла.txt.

Команды cat, head и tail очень полезны, когда нужно объединить несколько программ в одну. Эти процедуры рассматриваются в следующем разделе.

Объединение нескольких программ в одну

Операционная система UNIX разрабатывалась по философии «набора малых компонентов со слабыми связями». Иными словами, каждая запускаемая из командной строки программа (такие программы часто называются процессами, хотя одна программа может иногда запускать множественные процессы) должна выполнять только одну задачу, но выполнять ее хорошо. Кроме того, каждая такая программа должна обладать гибкой возможностью автоматического объединения с другими подобными программами. Поскольку результатом работы любой программы командной строки является текстовый вывод, вывод одной программы легко использовать в качестве ввода для другой. Например, при выполнении программы ls для каталога с большим количеством объектов, объекты в начале списка вытесняются с экрана последующими объектами. Но вывод программы ls можно передать программе less, которая уже будет выводить список объектов, помещающихся на экране. Делается это следующим образом:

$ ls -la . | less

В интерфейсах командной строки оператор вертикальная черта (|) называется оператором канала, посредством которого выходные данные одной программы передаются на вход другой для дальнейшей обработки.

Вместо вывода на экран выходные данные программы можно также перенаправлять в какое-либо другое место — например, в файл. Так, список объектов каталога можно сохранить в файл, выполнив следующую команду:

$ ls -la . > список_файлов.txt

Эта команда создает файл список_файлов.txt и сохраняет в нем вывод команды ls. Если файл с таким именем уже существует, его содержимое заменяется выводом команды ls. Вместо замены содержимого существующего файла, новые данные можно добавить к нему в конец:

$ ls -la . >> список_файлов.txt

Одна из причин, по которой такие операции являются возможными, заключается в том, что POSIX-системы рассматривают многие объекты как потоки данных, каждый из которых может заменяться любым другим. Например, выводимый на экран текст называется стандартным потоком выходных данных — standard out, или stdout. А выдаваемые клавиатурой данные являются стандартным потоком входных данных — standard in, или stdin. Файл также является потоком данных, в результате чего с помощью операторов канала и перенаправления можно осуществлять запись байтов в файл (stdin) и чтение из него (stdout).

Поток данных можно представить в виде трубы, в которую байты входят с одного конце, а выходят из другого. Таким образом, первый входящий в такую трубу байт первым же и выходит из нее. Такая организация входа/выхода называется FIFO[2]: первый на входе — первый на выходе. Эти команды совместно с рядом рассмотренных ранее команд и понятий позволяют выполнять довольно-таки хитроумные операции. Мы увидим некоторые примеры таких операций далее в этой главе и в книге.

Кроме рассмотренных, существует много других команд командной оболочки[3]. Список наиболее употребляемых можно получить, выполнив в терминале команду help, а информацию об определенной команде — выполнив команду:

man имя_команды

Чтобы закрыть подключение к серверу или завершить сеанс работы с терминалом на локальном компьютере, выполните команду logout. В некоторых вариантах Linux для этого вместо команды loguot используется команда exit.

На машинах с операционной системой в стиле POSIX — будь то машина под macOS, Linux или одноплатный компьютер — все только что рассмотренные команды должны работать в программе терминала локальной машины так же, как они работают на удаленном сервере через подключение ssh. Большинство этих команд работают и в среде Cygwin на машинах под Windows. Их также можно использовать и на одноплатных компьютерах, как мы увидим далее в этой главе.

Дополнительную информацию о работе с интерфейсом командной строки операционных систем UNIX и Linux вы сможете найти, например, в книге Аарона Ньюкомба (Aaron Newcomb) «Linux for Makers» (издательство Maker Media).

  1. POSIX, Portable Operating System Interface — интерфейс переносимой операционной системы.
  2. FIFO, First In, First Out — первым вошел, первым вышел.
  3. От англ. command shell — программа, которая обрабатывает команды интерфейса командной строки.
Опубликовано

Среда Processing

Одним из программных средств, с которым нам придется иметь дело в этой книге, является многоцелевая программная среда, именуемая Processing. Это бесплатный инструмент с открытым исходным кодом, и его можно загрузить с веб-сайта www.processing.org. Среда Processing основана на платформе Java и предназначена для тех пользователей, которые хотят реализовывать свои проекты без необходимости глубоко вникать в программирование. Тем не менее, Processing — весьма полезный инструмент для знакомства с принципами программирования, поскольку для осуществления серьезных действий: создания сетевого соединения, подключения к внешнему устройству через последовательный порт, управления камерой — требуется сравнительно небольшой объем кода Processing. Поскольку, как уже отмечалось, среда Processing основана на Java, в программы Processing можно включать классы и методы языка Java. Среда может исполняться под macOS, Windows и Linux. Существует также версия Processing для Android. Если по какой-либо причине вам не нравится работать в среде Processing, вы можете использовать приведенные в этой книге примеры ее кода и комментарии к ним в качестве исходных для создания таких примеров в любой среде, которой вы отдаете предпочтение.

Загрузив и установив среду Processing на своем компьютере, запустите ее на выполнение. Откроется окно, наподобие показанного на рис. 1.2.

Рис. 1.2. Окно редактора кода среды Processing

Пишем код

Теперь давайте создадим нашу первую программу в Processing. Введите в окно редактора следующий текст:

1
println("Здравствуй, мир!");

а затем нажмите кнопку Run (Исполнить) — самую левую кнопку на панели инструментов Processing

Не ахти какая программа, но это классическая первая программа на любом языке программирования. Исполнение этой программы выводит текст: Здравствуй, мир! в текстовом поле в нижней области окна редактора. Как видим, ничего сложного.

Программы Processing называются скетчами (sketch), и все данные скетча по умолчанию сохраняются на компьютере в каталоге с именем скетча подкаталога Processing каталога Документы. Впрочем, вы можете сохранять их в любом каталоге на свое усмотрение. Редактор Processing весьма прост и не содержит каких-либо «примочек», отвлекающих внимание. Панель инструментов редактора состоит из кнопок для запуска и остановки исполнения скетчей, открытия существующих скетчей, сохранения скетчей и экспортирования скетчей в апплеты Java. Кроме того, скетчи можно экспортировать в виде автономных приложений.

Пишем код

Рассмотрим теперь более сложную программу, которая демонстрирует некоторые основные структуры программирования Processing.

Контекст использования кода

Все примеры кода в этой книге сопровождаются комментариями, указывающими контекст, в котором они должны использоваться: Processing, Arduino, node.js и т. п.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
Программа рисования треугольников
Контекст: Processing
Рисует треугольник при отпущенной левой кнопке мыши. Очищает окно рисования при нажатии левой кнопки мыши.
*/
 
// объявляем переменные:
float redValue = 0; // переменная для красного цвета
float greenValue = 0; // переменная для зеленого цвета
float blueValue = 0; // переменная для синего цвета
// метод setup() исполняется один раз в начале программы:
void setup() {
size(320, 240); // устанавливаем размер окна рисования
background(0); // устанавливаем черный фон окна рисования
fill(0); // задаем цвет для заполнения фигур (0 = черный)
smooth(); // рисуем фигуры со сглаженными кромками
}
 
// Метод draw() исполняется непрерывно, пока открыто окно рисования.
// Он обновляет окно, а также выполняет любые запрограммированные в нем действия:
void draw() {
// Выбираем произвольные значения красной, зеленой и синей составляющих цвета:
 
redValue = random(255);
 
greenValue = random(255);
blueValue = random(255);
// задаем цвет линии:
stroke(redValue, greenValue, blueValue);
// рисуем при отпущенной левой кнопке мыши (игнорируя все обычные правила):
if (mousePressed == false) {
// рисуем треугольник
triangle(mouseX, mouseY, width/2, height/2, pmouseX, pmouseY);
}
// очищаем окно рисования при нажатии левой кнопки мыши:
else {
background(0);
fill(0);
}
}

Любая программа Processing должна содержать два основных метода (процедуры): setup() и draw(). Метод setup() исполняется один раз в начале программы, устанавливая все начальные условия, — такие как размер окна апплета, начальные значения переменных и т. п. А метод draw() — основной цикл программы, исполняющийся непрерывно, пока окно апплета открыто.
Для переменных Processing нужно задавать тип их данных. В приведенной здесь программе переменные redValue, greenValue и blueValue — плавающего типа (float), т. е. они могут содержать числа с плавающей запятой. Другие распространенные типы данных переменных, с которыми нам придется работать, это:

  1. int — целочисленные значения;
  2. char — однобайтовые значения символов ASCII;
  3. boolean — значения true (истина) или false (ложь);
  4. string — текст;
  5. byte — байт.

Язык программирования Java, а, следовательно, и производный от него язык Processing, являются языками программирования со строгим контролем типов данных. Иными словами, это означает, что переменные должны быть объявлены, прежде чем их можно будет использовать в программе. При этом для каждой объявленной переменной резервируется определенный объем памяти. Например, для переменной типа byte требуется один байт памяти, типа int — четыре байта и т. д. Каждый язык, с которым вам придется иметь дело в этой книге, обрабатывает переменные своим способом, который слегка отличается от способов других языков, поэтому при объявлении и использовании переменных в каждом языке следует быть осторожным.

Подобно языкам Java и JavaScript, синтаксис программ в среде Processing близок по стилю к синтаксису языка С. Как и переменные, все функции в нем также имеют тип данных (и у многих из них тип данных void — т. е. они не возвращают никаких значений в результате исполнения). Все строки кода должны заканчиваться точкой с запятой, а блоки кода заключаются в фигурные скобки. Условные операторы (if-then), операторы цикла (for-next) комментарии также используют синтаксис языка С. За исключением цикла for-next, все эти операторы вы могли видеть в приведенной ранее программе рисования треугольников.

А пример цикла for-next демонстрируется в следующем фрагменте кода:

1
2
for (int myCounter = 0; myCounter &lt;=10; myCounter++) {
println(myCounter);

Попробуйте создать свой скетч с использованием этого цикла. Для создания нового скетча выполните команду New в меню File среды Processing.

Пользователям BASIC и Python

Если вы никогда не использовали цикл for-next в стиле С, этот пример может показаться вам чем-то страшным. В действительности, ничего сложного в нем нет. Все, что приведенный здесь код делает, это сначала устанавливает значение переменной myCounter, а затем исполняет заключенные в фигурные скобки инструкции до тех пор, пока это значение остается меньшим или равным 10. Инструкция myCounter++ указывает программе добавить единицу к значению myCounter при каждом прохождении цикла. Эквивалентный код в BASIC выглядит следующим образом:

1
2
3
for myCounter = 0 to 10
Print myCounter
next

А на языке Python этот же код будет выглядеть так:

1
2
for myCounter in range (0, 10):
print myCounter

Processing — удобный язык для экспериментирования, так позволяет очень быстро создавать интерактивную графику. Он также может служить в качестве введения в программирование на языке Java для начинающих. Если вы уже знакомы с Java, то можете вставлять код Java непосредственно в программы Processing. Возможности Processing также можно расширять с помощью многочисленных библиотек кода, которые несложно найти в Интернете.

Поскольку среда Processing предназначена для использования в качестве инструмента исследования визуального дизайна, в ней отсутствуют многие стандартные элементы пользовательского интерфейса — такие как кнопки и меню с выбором позиций. Это дает вам свободу как дизайнеру, но при этом заставляет быть более изобретательным в программировании, чтобы создавать свои собственные элементы пользовательского интерфейса с нуля.

Дополнительную информацию по синтаксису Processing легко найти в руководстве, которое можно загрузить с веб-сайта www.processing.org. Узнать больше о программировании в Processing можно также из книги «Processing: A Programming Handbook for Visual Designers and Artists» (издательство MIT Press), написанной создателями этого языка Кэйси Ризом и Беном Фрайем, или из их более короткой книги «Getting Started with Processing» (издательство O’Reilly). Также можно воспользоваться отличной книгой для начинающих «Learning Processing» (издательство Morgan Kaufmann), написанной Даниэлем Шифманом (Daniel Shiffman).