Тип bt blink
Будем постепенно знакомиться с основами программирования, платой и другими полезными вещами. Это позволит избежать стресса от потока новой информации.
Хотя я немного разбираюсь в программировании, сегодня притворюсь, что никогда не слышал о языках программирования и постараюсь максимально доходчиво показать, как новичок осваивает новую для себя деятельность.
Во-первых, нам придётся писать примеры на C++-подобном языке. Поэтому можете похвастаться перед знакомыми, что пишите программы на C++. Во-вторых, он очень упрощённый, и вам не нужно бояться его.
01.Basics: Blink
Второй пример будет немного сложнее, ведь придётся подключать плату к компьютеру. Но есть и хорошая новость - нам не понадобятся дополнительные прибамбасы в виде проводов, датчиков, светодиодов, кнопок. Дело в том, что на плате уже есть один маленький встроенный светодиод, вот мы его и включим.
Запускаем скетч File | Examples | 1.Basics | Blink (Файл | Примеры | 1.Basics | Blink). У вас загрузится готовый пример с кодом. С его помощью мы можем увидеть, что плата работает.
Выбираем нашу плату - в меню Tools | Board (Сервис | Плата) должна быть отмечена Arduino Uno (как правило по умолчанию она уже отмечена). У вас может быть другая плата. Естественно, вы должны уже подключить плату к компьютеру через USB-порт для загрузки скетча в микроконтроллер.
Теперь нужно выбрать последовательный порт. Опять идём в меню Tools | Serial Port (Сервис | Последовательный порт) и выбираем нужный порт (обычно это COM3 или COM4).
Теперь нам необходимо загрузить открытый пример Blink на микроконтроллер. Просто щёлкните на кнопкуUpload (Загрузить) и внимательно смотрите на плату. Вы увидите, что светодиоды, помеченные как RX и TX будут мигать. После успешной загрузки примера в контроллер, в строке состояния среды разработки появится надпись Done uploading (Загрузка выполнена).
Через несколько секунд после загрузки, вы можете увидеть, что светодиод, помеченный на плате как 13 (L), будет мигать оранжевым цветом. Поздравляю, вы успешно установили среду разработки и запустили свою первую программу!
Обращу внимание, что в комментариях к коду написано, что листинг менялся несколько раз. Так выглядел код в предыдущий раз.
Сравните с текущей версией.
Теперь вместо создания отдельной переменной led используется встроенная константа LED_BUILTIN. Это удобно, так как в разных платах используются разные значения для встроенного светодиода и таким образом программа получилась универсальной.
С точки зрения кошатника, здесь всё написано правильно. Предложение написано без ошибок, есть даже точка с запятой в конце строки - всё как положено.
Разбор примера
Мы запустили программу, чтобы помигать светодиодом. Но делали это неосознанно, повторяя шаг за шагом описываемые действия. В дальнейшем вам придётся самому писать код, а значит пора ознакомится с основами программирования.
Изучим код шаг за шагом.
В функции setup() мы видим три строчки:
Приблизительный перевод комментариев, которые используется в функции setup() можно перевести как:
Дальше следует сам код, который делает операцию, описанную в комментариях. Обратите внимание, что команда завершается точкой с запятой:
В старых версиях код был немного другим:
Разработчики позже написали более грамотный код, вынеся число 13 в отдельную переменную led.
Комментарий можно перевести как:
Сейчас код обновили, и вместо переменной led используют константу LED_BUILTIN. Такой подход удобен, так как не все платы Arduino имеют встроенный светодиод на порту 13. Если у вас две разные платы и одна из них имеет нестандартный номер, то вам не придётся переписывать пример под каждую плату. Например, у плат MKR1000 встроенный светодиод находится на порту 6.
Нам встретилась новая функция pinMode(), которая устанавливает режим для портов. Функция состоит из двух параметров. В первом параметре указывается порт, с которым мы собираемся работать. Во втором параметре мы сообщаем, как должен работать указанный порт: работать на выход (OUTPUT) или вход (INPUT). В нашем примере, вывод под номером 13 (или другой порт, используемый встроенным светодиодом) должен выводить информацию (посылать сигнал), то есть давать указание мигать светодиоду.
Мы определили в функции setup() необходимые данные для начала работы и теперь можем приступить к непосредственной реализации задачи в функции loop().
Здесь мы видим уже четыре строчки кода. Первая строчка включает светодиод при помощи функции digitalWrite(). В первом параметре мы указываем номер порта, с которым собираемся работать, а во второй указываем константу HIGH. Забегая вперёд, могу сказать что константа HIGH равна 1, и можно было написать digitalWrite(13, 1). Но такая запись не очень удобна, так мельтешение цифр в большом проекте затрудняет чтение кода. А здесь вы сразу видите, что на порту под номером 13 включается светодиод.
Далее идёт команда, отвечающая за паузу - delay(), которая имеет один параметр - количество времени в миллисекундах. В нашем примере мы сделали паузу в одну секунду (1000 миллисекунд = 1 секунда).
Следом идёт уже знакомая нам функция digitalWrite(), но уже с параметром LOW, который выключает светодиод (значение константы LOW равно 0).
И последняя строчка снова делает паузу в одну секунду.
Посмотрим, как работает программа. Когда мы загружаем программу в микроконтроллер, то Arduino активирует порт 13 в режиме выхода (функция setup()), а затем начинает последовательно выполнять четыре строчки из функции loop(): включает диод-пауза-выключает диод-пауза. Когда эти четыре строчки будут выполнены, то они снова будут вызваны и будут повторяться до тех пор, пока мы не выдернем кабель.
Немного о паузе. Теоретически можно убрать вызов функции delay() и программа будет работать. Проблема в другом - контроллер работает с частотой 16 миллионов герц (герц - одно колебание в секунду; если команда длится один такт, вывод переключается 16 миллионов раз в секунду, соответственно, состояние вывода меняется каждые 0,0000000625 секунды), человеческий глаз не способен увидеть реакцию светодиода. Необходимо немного увеличить интервал между двумя командами включения и выключения светодиода.
Что мы можем изменить в данной программе? По большому счету ничего - мы можем установить только собственные значения пауз. Поэкспериментируйте с этим. Другие изменения результата не принесут - нет смысла, например, сейчас использовать другой порт или использовать режим INPUT.
Добавляем свой светодиод (+светодиод)
Мы научились мигать встроенным светодиодом. Но на самом деле у вас не будет возможность пользоваться встроенными компонентами, а придётся самостоятельно собирать нужную конструкцию и взаимодействовать с ней. Поэтому нам понадобится отдельный светодиод, который и будет у нас и мигать, и затухать, и кашу варить (насчёт последнего я, пожалуй, погорячился). Можно использовать любой светодиод - красный, зелёный, синий.
Напомню, что диод проводит ток в одном направлении. Следовательно, необходимо всегда правильно устанавливать светодиод в своих схемах. Встроенный светодиод уже правильно припаян к плате Arduino (скажем спасибо разработчикам).
Из первого примера с встроенным светодиодом мы помним, что он использует вывод под номером 13 (на большинстве плат). На плате есть свободный вывод с этим номером, который находится рядом с выводом GND. Берём светодиод и вставляем в эти выводы. Не забываем, что короткую ножку вставляем в GND, а длинную в вывод 13. У вывода 13 уже установлен резистор, поэтому светодиод не сгорит.
Запускаем снова программу Blink. Теперь будут мигать два светодиода: встроенный и наш. Красота!
Вернёмся к светодиодам. Как правило, в цепи идёт слишком большой ток для светодиодов. Чтобы уменьшить силу тока, используют токопонижающие резисторы (сопротивления). У светодиодов есть важные характеристики: ток питания и напряжение падения (Forward voltage). Невероятно, но факт - светодиоды разных цветов используют разные значения напряжения падения. Максимальный ток для светодиодов колеблется в районе 20 миллиампер. Для вычисления значения сопротивления используют формулу: из напряжения питания вычитаем напряжение падения и результат делим на силу тока в светодиоде в амперах. В документации обычно рекомендуют использовать резистор от 220 ohm до 1K ohm. На практике, можно использовать и 100 ом. Если поставите меньше, то будет риск спалить светодиод. При выполнении опытов с несколькими светодиодами вы можете установить разные резисторы, чтобы увидеть разницу.
На следующем уроке мы поближе познакомимся с цифровыми выводами и попробуем изменять программы под свои нужды.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Вам необходимо обновить браузер или попробовать использовать другой.
D_Jackas
Всем привет. Имею у себя Home-сервер и на нем висит сервер не мало известного Blynk'a. Т.к. присутствует возможность, могу поделиться с сообществом. Ибо для пары девайсов жирновато будет, да и наличие халявной энергии не помешает.
Что такое Blynk:
Blynk - это платформа с приложениями для iOS и Android для управления Arduino, Raspberry Pi, ESP8266 и другими вашими подопытными через Интернет. Это цифровая панель, где вы можете создать графический интерфейс для своего проекта, просто перетаскивая виджеты.
- Скачиваем само приложение с маркета: IOS & Android
- Запускаем.
- На экране приветствия кликаем [Login In].
- Далее над кнопкой входа нажимаем на подобие светофора.
- Переключаем ползунок с BLYNK на CUSTOM и вводим адрес: trsh.su, порт оставляем 9443. Жмем Ок.
- Можем входить
Можно пользоваться. По сути делюсь из-за того, что опять-же жирно для нескольких девайсов и могу поделиться т.к. не жадный, да и вам не придется арендовать белый IP у провайдера.
Немного информации о сервере:
Q: Зачем тебе оно?
A: Просто. Нечего делать
Q: Можно пополнять энергию? И сколько будет стоить?
A: Да можно. Бесплатно. Просто напиши мне.
Q: Обновляешь ли сервер?
A: По мере выхода обновлений
Q: Будешь ли смотреть за моим проектами?
A: Оно мне надо? За своими стараюсь не забывать смотреть.
Q: А если отключишь сервер?
A: Отключится только если по тех. причинам и то буду стараться оповещать заранее.
Q: Забьешь на проект?
A: Только если не будет актуальным. А мне он нужен постоянно.
P.S. Если есть вопросы или пожелания, пишите. Данный "сервер" отдам полностью под комьюнити если будет интересно.
. ВНИМАНИЕ.
На данный момент по умолчанию выдаётся 1 единица энергии! Сделано это для фильтрации от ботов (такие имеются). Чтобы получить энергию (БЕСПЛАТНО), пишите мне в ЛС.
Данное приложение для мобильного устройства позволяет в форме графического конструирования создавать полнофункциональные приложения для связи их с устройствами. Особенностью платформы является простота в создании и адекватность реализации связи с программным кодом в устройстве. Проводник удаленно управляет оборудованием (микроконтроллерами: Arduino, Raspberry через Интернет), может хранить данные, может отображать данные датчика.
В использовании он прост (но нужен бесперебойный интернет; есть версии и для iOS, и для Android). Необходимо установить приложение Blynk на смартфон или планшет. Вручную можно разместить на экране нужные элементы, слайдеры и кнопки. Каждый элемент можно настроить отдельно.
В микроконтроллер встраивается специальная программа, которая призвана выполнять необходимые Вам функции, руководить приборами, получать сведения с датчиков и отсылать их обратно на ваше устройство.
Перевод файла с репозитория blynk-server
Автор перевода: Титенко Максим
Blynk Local Server
Платформа с приложением для iOS и Android для управления Arduino, ESP8266, Raspberry Pi и других плат микроконтроллеров через Интернет.
Что такое Blynk?
Blynk - это платформа с приложениями iOS и Android для управления Arduino, ESP8266, Raspberry Pi и подобных плат микроконтроллеров через Интернет. Вы можете легко создавать графические интерфейсы для всех своих проектов, просто перетаскивая виджеты. Если вам нужна дополнительная информация, перейдите по следующим ссылкам:
Сервер Blynk - это Java сервер с открытым исходным кодом Netty, отвечающий за пересылку данных между мобильным приложением Blynk и различными микроконтроллерами и SBC (например, Arduino, Raspberry Pi и т. д.).
- Требуется Java 8/9 (OpenJDK, Oracle)
- Любая операционная система, которая имеет поддержку java
- Не менее 30 МБ ОЗУ (оперативной памяти) - (может быть меньше при настройке)
- Открытые порты 9443 (для приложения), 8442 (для аппаратного обеспечения без ssl), 8441 (для аппаратного обеспечения с ssl)
Для Windows загрузите Java здесь и установите.
Быстрая настройка локального сервера
- Убедитесь, что вы используете Java 9
java -version Output: java version "9"
java -jar server-0.31.0.jar -dataFolder /path
Вот и всё!
ПРИМЕЧАНИЕ: / path должен быть реальным существующим путем в папку, где вы хотите хранить все свои данные.
Blynk Server successfully started. All server output is stored in current folder in 'logs/blynk.log' file.
Включение почты на локальном сервере
Чтобы включить уведомления по почте на локальном сервере, вам необходимо предоставить свои собственные учетные данные. Создайте файл mail.properties в той же папке, где server.jar .
Пример настройки почты здесь.
ПРЕДУПРЕЖДЕНИЕ: разрешены только учетные записи gmail.
Быстрая настройка локального сервера на Raspberry Pi
- Подключить Raspberry Pi через ssh;
- Установить java 8:
- Убедитесь, что вы используете именно Java 8
java -version Output: java version "1.8"
- Загрузите Blynk сервер Jar файл (или вручную скопируйте его в Raspberry Pi через команду ssh и scp):
java -jar server-0.31.0-java8.jar -dataFolder /home/pi/Blynk
Вот и всё!
Blynk Server successfully started. All server output is stored in current folder in 'logs/blynk.log' file.
Включение автоматического перезапуска сервера в UNIX-системах
- Чтобы включить автоматический перезапуск сервера, найдите файл /etc/rc.local и добавьте:
java -jar /home/pi/server-0.31.0.jar -dataFolder /home/pi/Blynk &
- Или если описанный выше подход не работает, выполните:
- добавьте следующую строку:
@reboot java -jar /home/pi/server-0.31.0.jar -dataFolder /home/pi/Blynk &
Сохранить и выйти.
Включение автоматического перезапуска сервера в Windows
- Создать .bat файл:
- Вставьте в файл одну строку:
java -jar server-0.31.0.jar -dataFolder /home/pi/Blynk
- Добавить файл bat в папку автозагрузки Windows
Вы также можете использовать этот скрипт для запуска сервера.
Инструкция по обновлению для unix - систем
ВАЖНО Сервер должен всегда обновляться до того, как вы обновите приложение Blynk. Чтобы обновить сервер до более новой версии, вам нужно будет убить старый процесс и запустить новый.
- Найти идентификатор процесса сервера Blynk
ps -aux | grep java
- Вы должны увидеть что-то подобное:
username 10539 1.0 12.1 3325808 428948 pts/76 Sl Jan22 9:11 java -jar server-0.31.0.jar
- Убить старый процесс
10539 - идентификатор процесса сервера blynk из вывода команды выше.
- Запустить новый сервер как обычно
После этого вы можете обновить приложение Blynk. Понижение версии сервера не поддерживается.
ВНИМАНИЕ! Не переустанавливайте сервер на более низкие версии. Вы можете потерять все свои данные.
Инструкцию по обновлению для Windows
Открыть диспетчер задач;
Запустить новый сервер как обычно
Изменения в приложение и эскизе
- Укажите настраиваемый путь к серверу в приложении
Изменить тип вашего проводного подключения к интернету с
Измените ваше WiFi подключения с
Изменить ваш Raspberry Pi Javascript c
./blynk-ser.sh -s you_host_or_IP
ВАЖНО Блинк постоянно развивается. Мобильные приложения и сервер часто обновляются. Чтобы избежать проблем во время обновлений, отключите автоматическое обновление для приложения Blynk или одновременно обновите локальный сервер и приложение blynk, чтобы избежать возможных проблем с миграцией.
ВАЖНО Локальный сервер Blynk отличается от сервера Blynk Cloud. Они не связаны вообще. Вы должны создать новую учетную запись при использовании локального сервера Blynk.
Расширенная настройка локального сервера
Для большей гибкости вы можете расширить сервер с большим количеством опций, создав файл server.properties в той же папке, что и server.jar . Пример можно найти здесь. Вы также можете указать любой путь к файлу server.properties через аргумент командной строки -serverConfig . Вы можете делать то же самое с mail.properties через -mailConfig и sms.properties через -smsConfig .
java -jar server-0.31.0.jar -dataFolder /home/pi/Blynk -serverConfig /home/pi/someFolder/server.properties
Доступные параметры сервера:
- Аппаратный простой порт tcp/ip
- Аппаратный порт ssl/tls (для аппаратного обеспечения, поддерживающего сокеты SSL/TLS)
Указывает на cert и ключ, который помещается в ту же папку, что и jar.
server.ssl.cert=./server_embedded.crt server.ssl.key=./server_embedded.pem server.ssl.key.pass=pupkin123
- Уровень отладки журнала. Возможные значения: trace | debug | info | error. Определяет, насколько точным будет запись. Слева направо -> максимальная регистрация до минимума
- Максимально допустимое количество панелей пользователей.
- 100-кратное ограничение скорости на пользователя. Вы также можете расширить этот предел на странице hardware side.
- этот параметр определяет, как часто вы можете отправлять почту / твит / push или любое другое уведомление. Указано в секундах
- Максимально разрешенный размер профиля пользователя. В Кб.
- Количество строк для хранения в терминальном виджете (данные истории терминала)
- Максимально допустимое количество очереди уведомлений. Очередь, ответственная за обработку электронной почты, нажатие, отправка твитов. Из-за проблемы с производительностью - эта очередь обрабатывается в отдельном потоке, это требуется из-за блокировки характера всех вышеперечисленных операций. Обычно ограничение не должно быть достигнуто
- Количество потоков для выполнения операций блокировки - push, twits, emails, db query. Рекомендуется удерживать это значение до минимума, если вам не нужно выполнять много операций блокировки.
- Период для очистки всей пользовательской БД на диск. В миллисекундах
- Указывает максимальный период времени, когда аппаратный сокет может быть бездействующим. После чего сокет будет закрыт из-за неактивности. Через несколько секунд. Оставьте его пустым для тайм-аута бесконечности
- В основном требуется настройка локальных серверов в случае, если пользователь хочет записывать необработанные данные в формате CSV. Дополнительную информацию см. В разделе raw data.
- Список IP-адресов администратора, разделенных запятыми. Разрешить доступ к пользовательскому интерфейсу администратора только для этих IP-адресов. Вы можете установить его для 0.0.0.0/0, чтобы разрешить доступ для всех. Вы можете использовать нотацию CIDR. Например, 192.168.0.53/24.
- Имя и пароль администратора по умолчанию. Будет создан при запуске начального сервера
- Электронная почта, используемая для регистрации сертификата, может быть опущена, если вы уже указали ее в mail.properties.
- Список пользователей с запятыми, которым разрешено создавать учетные записи. Оставьте его пустым, если не требуется никаких ограничений.
Сервер Blynk предоставляет панель администрирования, где вы можете контролировать свой сервер. Она доступна по этому URL-адресу:
ПРЕДУПРЕЖДЕНИЕ Пожалуйста, измените пароль администратора и его имя сразу после входа на страницу администратора. ЭТО МЕРЫ БЕЗОПАСНОСТИ.
ПРЕДУПРЕЖДЕНИЕ По умолчанию параметр allowed.administrator.ips разрешает доступ для всех. Другими словами, доступной с любого другого компьютера. Ограничьте доступ к нему через свойство allowed.administrator.ips .
- Вставить в адресную строку chrome
Включение смс на локальном сервере
Чтобы включить уведомления SMS на локальном сервере, вам необходимо предоставить учетные данные для шлюза SMS (в настоящее время сервер Blynk поддерживает только 1 провайдера - Nexmo. Вам нужно создать файл sms.properties в той же папке, где находится server.jar.
Включение хранилища необработанных данных
По умолчанию необработанное хранилище данных отключено (поскольку он много занимает место на диске). Когда вы включаете его, каждая команда Blynk.virtualWrite будет сохранена в DB. Вам необходимо будет установить PostgreSQL Database (** минимальная требуемая версия - 9.5 **), чтобы включить эту функцию:
1. Включение необработанных данных на сервере
Включить необработанные данные в server.properties :
2. Установите PostgreSQL. Вариант A
sudo apt-get update sudo apt-get install postgresql postgresql-contrib
2. Установите PostgreSQL. Вариант Б
sudo apt-get update apt-get --no-install-recommends install postgresql-9.6 postgresql-contrib-9.6
4. Переместите файл create_schema.sql в папку temp (чтобы избежать проблем с разрешением)
mv create_schema.sql /tmp
Скопируйте его в буфер обмена с консоли.
5. Подключитесь к PostgreSQL
sudo su - postgres psql
6. Создать Blynk DB, проверить пользователя и таблицы
/ tmp / create_schema.sql - путь от шага 4.
Вы должны увидеть следующий вывод:
Теперь запустите свой сервер, и вы увидите следующий текст в файле postgres.log :
2017-03-02 16:17:18.367 - DB url : jdbc:postgresql://localhost:5432/blynk?tcpKeepAlive=true&socketTimeout=150 2017-03-02 16:17:18.367 - DB user : test 2017-03-02 16:17:18.367 - Connecting to DB. 2017-03-02 16:17:18.455 - Connected to database successfully.
ПРЕДУПРЕЖДЕНИЕ: Исходные данные могут очень быстро сократить пространство на диске!
Формат данных CSV
значение, метка времени, DeviceId
Где 10 - значение булавки. 1438022081332 - разница, измеренная в миллисекундах, между текущим временем и полночью, 1 января 1970 г. UTC. Чтобы отобразить дату / время в excel, вы можете использовать формулу:
= ((Column / (60 * 60 * 24) / 1000 + 25569))
0 - идентификатор устройства
Автоматическое создание шифрования сертификатов
У последнего сервера Blynk есть супер классная функция - автоматическая генерация сертификатов Encrypt. Однако он имеет несколько требований:
- Добавить свойство server.host в файл server.properties . Например :
- Добавить свойство contact.email в server.properties . Например :
Это оно! Запускать сервер как обычный, а сертификаты будут генерироваться автоматически.
Руководство шифровки сертификатов SSL / TLS
- Сначала установите certbot на свой сервер (машина, на которой вы собираетесь запускать сервер Blynk)
- Генерирование и проверка сертификатов (ваш сервер должен быть подключен к Интернету и иметь открытые порты 80/443)
./certbot-auto certonly --agree-tos --email YOUR_EMAIL --standalone -d YOUR_HOST
./certbot-auto certonly --agree-tos --email [email protected] --standalone -d blynk.cc
- Затем добавьте файл server.properties (в папку с server.jar)
server.ssl.cert = / и т.д. / letsencrypt / живой / YOUR_HOST / fullchain.pem server.ssl.key = / и т.д. / letsencrypt / живой / YOUR_HOST / privkey.pem server.ssl.key.pass =
Создание собственных сертификатов SSL
- Создать самозаверяющий сертификат и ключ
openssl req -x509 -nodes -days 1825 -newkey rsa: 2048 -keyout server.key -out server.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -in server.key -out server.pem
В качестве вывода вы получите файлы server.crt и server.pem, которые необходимо предоставить для свойств server.ssl.
Установить java для Ubuntu
sudo apt-add-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java9-installer
в случае, если в вашей системе еще нет Java 9.
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT - to-port 8080 sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT - to-port 9443
Включение генерации QR на сервере
sudo apt-get install libxrender1
За маршрутизатором wifi
Если вы хотите запустить сервер Blynk за WiFi-маршрутизатором и хотите, чтобы он был доступен из Интернета, вам необходимо добавить правило переадресации портов на вашем маршрутизаторе. Это необходимо для перенаправления всех запросов, которые поступают на маршрутизатор в локальной сети на сервер Blynk.
Blynk имеет кучу интеграционных тестов, требующих DB, поэтому вам нужно пропустить тесты во время сборки.
mvn clean install -Dmaven.test.skip = true
Как работает Блинк?
Определения команд и состояний: BlynkProtocolDefs.h
S BLYNK_CMD_LOGIN + токен аутентификации SP BLYNK_CMD_PING SP BLYNK_CMD_RESPONSE SP BLYNK_CMD_BRIDGE SP BLYNK_CMD_HARDWARE S BLYNK_CMD_TWEET S BLYNK_CMD_EMAIL S BLYNK_CMD_PUSH_NOTIFICATION
About
Платформа с приложением для iOS и Android для управления Arduino, ESP8266, Raspberry Pi и других плат микроконтроллеров через Интернет.
Читайте также: