--- title: "📟 FAQ по доступу к Serial из Crystal" date: 2023-05-16T01:29:30+03:00 draft: false tags: [crystal, serial, tips] --- Перевёл FAQ чувака с SOF, на вопрос работы с Serial в Crystal. ## Как мне получить доступ к Serial в Linux/BSD? Открыть его как файл. В Linux/BSD последовательное соединение устанавливается в тот момент, когда устройство было подключено, и затем отображается в разделе `/dev/` (обычно как `/dev/ttyUSB0`). Чтобы получить доступ к этому соединению, просто откройте его как обычный файл. Иногда этого достаточно, чтобы начать взаимодействовать с устройством, поскольку современное оборудование работает со всеми скоростями и флагами по умолчанию. ## Как мне настроить устройство Serial/tty в Linux/BSD? Необходимо установить флаги [termios](https://linux.die.net/man/3/termios) для файла. Если необходимо для соединения установить такие параметры, как скорость передачи данных в бодах, IXON/IXOFF и т.д., это можно сделать еще до запуска вашей программы с помощью команды [stty](https://linux.die.net/man/1/stty), если она доступна. Например чтобы установить скорость передачи данных в бодах, необходимо выполнить следующую команду: `stty -F /dev/ttyUSB0 9600`. И после того, как соединение настроено, можно просто открыть соединение как файл и начать использовать. Вы можете запустить `stty` из Crystal с помощью `Process.run`, если нужен простой способ настройки устройства из вашего приложения. Я бы, вероятно, порекомендовал этот способо в качестве решения. ## Как мне установить флаги termios из Crystal, не используя stty? Используйте функции `termios` напрямую. Crystal предоставляет FileDescriptor с несколькими распространенными настройками `termios`, такими как [cooked](https://crystal-lang.org/api/1.8.2/IO/FileDescriptor.html#cooked%28%26%3Aself-%3E_%29-instance-method), что означает, наличие минимальных привязок [termios](https://github.com/crystal-lang/crystal/blob/master/src/termios.cr). Мы можем начать с использования существующего кода: ```crystal require "termios" # Открываем файл serial_file = File.open("/dev/ttyACM0") raise "Oh no, not a TTY" unless serial_file.tty? # Извлекаем unix FD. Это всего лишь цифра. fd = serial_file.fd # Извлекаем существующие флаги TTY файла raise "Can't access TTY?" unless LibC.tcgetattr(fd, out mode) == 0 # `mode` теперь содержит структуру termios. Давайте включим, ммм.. ISTRIP and IXON mode.c_iflag |= (Termios::InputMode::ISTRIP | Termios::InputMode::IXON).value # Давайте также отключим IXOFF. mode.c_iflag &= ~Termios::InputMode::IXOFF.value # Обнаружение неисправности: в Termios недоступна скорость cfset[ввода-вывода] # Давайте добавим их, чтобы изменить скорость передачи данных в бодах было не так сложно. lib LibC fun cfsetispeed(termios_p : Termios*, speed : SpeedT) : Int fun cfsetospeed(termios_p : Termios*, speed : SpeedT) : Int end # Используйте приведенные выше функции, чтобы установить скорость ввода # и скорость вывода на заданную вами скорость передачи данных в бодах. LibC.cfsetispeed(pointerof(mode), Termios::BaudRate::B9600) LibC.cfsetospeed(pointerof(mode), Termios::BaudRate::B9600) # Пишите свои изменения в FDA. LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode)) # Сделано! Ваш дескриптор serial_file готов к использованию. ``` Чтобы установить другие флаги, обратитесь к [руководству](https://linux.die.net/man/3/termios) termios или к этому замечательному [руководству](https://en.wikibooks.org/wiki/Serial_Programming/termios) по Serial, которое я только что нашел. ## Есть ли библиотека, которая могла бы сделать все это за меня? Нет :(. Но было бы здорово, если бы кто-нибудь написал. Вероятно, что написать библиотеку не составит большого труда, если у кого-нибудь будет личный интерес :) ## Источник - [Crystal-lang Accessing Serial port](https://stackoverflow.com/questions/51069578/crystal-lang-accessing-serial-port) — StackOverFlow.