#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <vector>
#include <string>
#include <cstring>
#include <iconv.h>
// Функция для конвертации строки из UTF-8 в CP866 (только для Linux/POSIX)
std::vector<char> convert_utf8_to_cp866(const std::string& input) {
iconv_t cd = iconv_open("CP866", "UTF-8");
if (cd == (iconv_t)-1) {
std::cerr << "Ошибка инициализации iconv (CP866)" << std::endl;
return {};
}
size_t in_bytes = input.size();
size_t out_bytes = in_bytes * 2; // Запас под результат
std::vector<char> output(out_bytes);
char* in_buf = const_cast<char*>(input.c_str());
char* out_buf = output.data();
if (iconv(cd, &in_buf, &in_bytes, &out_buf, &out_bytes) == (size_t)-1) {
std::cerr << "Ошибка конвертации кодировки" << std::endl;
iconv_close(cd);
return {};
}
// Вычисляем реальный размер полученных данных
size_t final_size = output.size() - out_bytes;
output.resize(final_size);
iconv_close(cd);
return output;
}
int main() {
const char* printer_path = "/dev/usb/lp0";
// 1. Формируем управляющие команды PCL 5e
std::string uel = "\x1b%-12345X"; // Универсальный конец задания
std::string enter_pcl = "@PJL ENTER LANGUAGE = PCL\r\n"; // Вход в PCL
std::string reset = "\x1bE"; // Сброс принтера
std::string paper_a4 = "\x1b&l26A"; // Формат бумаги A4
std::string cyrillic_866 = "\x1b(17R"; // Таблица символов PC-866
std::string font_courier = "\x1b(s3B"; // Встроенный шрифт Courier
std::string form_feed = "\x0c"; // Команда выталкивания листа
// 2. Русский текст для печати
std::string text_to_print =
"Привет от C++!\r\n"
"Прямая запись PCL 5e в /dev/usb/lp0 работает.\r\n"
"Тест символов: 1234567890 !@#$%\r\n";
// Конвертируем текст в кодировку CP866
std::vector<char> text_bytes = convert_utf8_to_cp866(text_to_print);
if (text_bytes.empty()) {
return 1;
}
// 3. Собираем финальный бинарный буфер данных
std::vector<char> payload;
auto append_str = [&payload](const std::string& s) {
payload.insert(payload.end(), s.begin(), s.end());
};
append_str(uel);
append_str(enter_pcl);
append_str(reset);
append_str(paper_a4);
append_str(cyrillic_866);
append_str(font_courier);
// Вставляем бинарные байты текста в CP866
payload.insert(payload.end(), text_bytes.begin(), text_bytes.end());
append_str(form_feed);
append_str(uel);
// 4. Открываем порт принтера на запись
int printer_fd = open(printer_path, O_WRONLY);
if (printer_fd == -1) {
std::cerr << "Ошибка: Не удалось открыть " << printer_path << std::endl;
std::cerr << "Проверьте подключение или запустите программу через sudo." << std::endl;
return 1;
}
// 5. Отправляем буфер в принтер
ssize_t bytes_written = write(printer_fd, payload.data(), payload.size());
if (bytes_written == -1) {
std::cerr << "Ошибка записи в устройство принтера." << std::endl;
} else {
std::cout << "Успешно отправлено " << bytes_written << " байт в " << printer_path << std::endl;
}
// Закрываем дескриптор файла
close(printer_fd);
return 0;
}