Некоторое время назад я увлекался тем, то писал самодельные прошивки для различных готовых устройств. Так, например, сделал пульт для управления солярием из пульта от охранной сигнализации. А что, смотрите сами:

  • корпус есть отличный;

  • уже встроена клавиатура и не просто, а более-менее надежная;

  • есть светодиодные индикаторы и динамик (пищалка);

  • корпус штатно крепится к стене;

  • все собрано красиво и на вид надежно.

Внутри есть платка с AVR микроконтроллером, разъемом внутрисхемного программирования. Что осталось:

  • вывести наружу com порт для подключения к серверу;

  • приделать реле для включения пускателя солярия;

  • подключить блок питания;

  • и главное – написать саму прошивку.

Рисунок 1 Самодельный пульт управления солярием
Рисунок 1 Самодельный пульт управления солярием

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

Рисунок 2 Снятый с учета ФР переделанный в термопринтер
Рисунок 2 Снятый с учета ФР переделанный в термопринтер

После переделок касс, я начал работу по написанию утилиты для красивой печати. Дело в том, что я также разработчик на 1с, с++ и мне приходилось что-то печатать из кучи разных программ на кучу разных устройств. Поэтому я решил сделать суперуниверсальную программу, которая бы могла все:

  • печатать на разные устройства;

  • работать с 1 и 2 мерными штрих кодами;

  • уметь печатать кучей различных шрифтов;

  • иметь возможности по редактированию отдельных символов и создания целиком новых шрифтов;

  • должна быть возможность работы в режиме командной строки (т.е. программа на 1с готовит заранее текстовый файл, потом дает команду на печать);

  • показывать на экране как будет выглядеть документ после печати;

  • уметь работать со шрифтами двойной ширины/высоты, жирными, подчеркнутыми и т.п.;

  • двигать бумагу вперед и назад на любые требуемые интервалы;

  • и еще все что потребуется.

Рисунок 3 Основное окно программы печати
Рисунок 3 Основное окно программы печати
Рисунок 4 Редактор шрифтов
Рисунок 4 Редактор шрифтов

Постепенно я создал эту программу, и она уже умеет очень много всего, но вот я подхожу к основной теме статьи. Дело в том, что мне попадались на работе, у заказчиков аппараты АТОЛ. Обычно они назывались Fprint-22, Fprint-55 и еще куча вариантов. Это были совершенно разные ккм и общая черта была только та, что все они работали через драйвера Атол. В аппаратах были разные микроконтроллеры, разные термоголовки, и ширина бумаги была от 45 до 80 мм. Но все они работали через атоловские драйвера.

И часто заказчики хотели помимо основных функций (печать чеков) сэкономить на покупке термопринтера и использовать уже имеющуюся кассу для печати различных не фискальных документов. Это могли быть счета в барах, временные пароли для Wi‑Fi, талоны для въезда на территорию, те же коды для включения солярия на 5 или 10 мин. И я понял, что пришла пора для еще одной модернизации программы. Естественно, так просто на кассе не попечатаешь — это же не принтер.

Рисунок 5 Аппарат FPrint-22 печатает из моей программы
Рисунок 5 Аппарат FPrint-22 печатает из моей программы
Рисунок 6 Аппарат FPrint-55 печатает из моей программы
Рисунок 6 Аппарат FPrint-55 печатает из моей программы

Для начала я выделил три основных ветки драйверов. Это была 6…8 версии, 9 ая версия и 10 ая. Все они имели свои особенности.

Чем старше был аппарат, тем больше вероятность, что на самой новой 10-й версии он не заработает. Поскольку я пишу на с++, то взаимодействовать с атоловским драйвером пришлось из с++. Сразу скажу, это был еще тот квест.

Рисунок 7 Переключение версий драйверов
Рисунок 7 Переключение версий драйверов

6…8 версии

Тут как раз оказалось все просто. Сначала объявляем переменную

IFprnM45                   ECR;

 Потом создаем объект:

COleException *e = new COleException;

try

{

       if (!ECR.CreateDispatch("AddIn.FprnM45", e))

             throw e;

}

Дальше включаем устройство:

ECR.SetDeviceEnabled(true);

И готово, можно делать с кассой все что хочешь. Например,

ECR.FullCut();

Это полная отрезка ленты. В конце вызываем

ECR.ReleaseDispatch();

И все делов. т. е. ничего сложного. Конечно, перед этим надо было установить сами драйвера и зарегистрировать нужные библиотеки.

Потом к проекту на с++ я добавлял файл с заголовками функций fprnm1c.h.

Рисунок 8 Тест драйвера 6ой версии
Рисунок 8 Тест драйвера 6ой версии

10 версия

Для нее я уже не смог повторить тот фокус что для 6ой. Файл с заголовками я нашел, а дальше был затык. Может быть конечно я что‑то не допер, но создать объект fptr10 у меня не получилось. Пришлось подключать на лету dll от 10ой версии fptr10.dll и извлекать из нее функции. Делал я это так:

hDll10 = LoadLibraryA("fptr10.dll");

// загружаем

typedef int (WINAPI *PFN_libfptr_create)(libfptr_handle);

PFN_libfptr_create p_libfptr_create;

// описываю импортируемую функцию

 

libfptr_handle fptr10;

// описываю дескриптор

 

p_libfptr_create = (PFN_libfptr_create)GetProcAddress(hDll10, "libfptr_create");

// получаю ссылку на функцию

 

iRes = (*p_libfptr_create)(&fptr10);

// вызываю саму функцию

Вот так удалось подружиться с 10ой версией драйвера.

Рисунок 9 Тест драйвера 10ой версии
Рисунок 9 Тест драйвера 10ой версии

9 версия

Это была для меня самая нужная версия. Дело в том, что разработчики драйверов применяли несколько видов протокола обмена с кассами. Я знал про 2 и 3 версии. 6ая версия драйверов работала, как я понял со 2ым протоколом, 10ые драйвера с 3им протоколом. А 9ые драйвера были переходными! И в них была возможность выбора 2 или 3 версии протокола! Это было круто, т.к. позволяло работать и со старыми кассами и с новыми. Вот тут я и получил большую часть проблем. Но в итоге все заработало. Делал так:

hDll = LoadLibraryA("fptr.dll");

// загружаем DLL

 

TED::Fptr::IFptr *fptr;

// описываю указатель на дескриптор

 

typedef TED::Fptr::IFptr * (WINAPI *PFN_CreateFptrInterface)(int);

PFN_CreateFptrInterface p_CreateFptrInterface;

// описываю импортируемую функцию

 

p_CreateFptrInterface = (PFN_CreateFptrInterface)GetProcAddress(hDll, "CreateFptrInterface");

// получаю ссылку на функцию

 

fptr = (*p_CreateFptrInterface)(i);

// вызываю саму функцию

Тут меня ждала еще одна засада. При вызове CreateFptrInterface надо было передавать переменную int. Типа версию драйверов. Я передавал: 9, 0, 1, 6, 8, 10 и вообще хрен знает что, но вызов не срабатывал:‑( В итоге я решил сделать так. Создал цикл от 0 до 10 000 и вызывал эту заразу в цикле со всеми аргументами подряд, пока не вернет нормальное значение. И она вернула! В общем, удалось подобрать число. Если хотите, попробуйте сами подобрать, пишите в коменты что получится.

После этой инициализации можно уже было вызывать разные методы. Но тут встал главный вопрос:

Как печатать?

К драйверу‑то я подключился. Методы вызывались, а дальше?! Как вывести на кассу что‑то нужное, и при этом ее не убить? Для решения этого вопроса, я очень внимательно прочитал руководство программиста по драйверу атол и понял, что единственный шанс — это печатать документ как картинку. Моя программа как раз умела сохранять результат работы в формате BMP, и полдела уже было сделано. Далее я добавил команду для печати уже через драйвер атол и при нажатии соответствующей кнопки сначала формировал BMP файл (конечно же монохром 1 бит на пиксель) и потом уже начинал манипуляции с драйвером. Выглядели они примерно так:

ECR.SetFileName("c:\\tmpbmp.bmp");

ECR.PrintBitMapFromFile();

Рисунок 10 Тест драйвера 9ой версии
Рисунок 10 Тест драйвера 9ой версии

Конечно, тут тоже было много подводных камней. Для начала, сам временный файл. Если на windows 7 я отлично его записывал в корень диска С, то на windows 10 этот номер не прокатывал. Даже запуская программу под администратором, первый раз новый файл было не создать. Если только я сам его туда копировал и давал на него полные права, то перезаписывался файл нормально. Потом пришлось перенести сохранение файла в другую папку.

Также были сложности с шириной и высотой картинки. Разные аппараты имели разные размеры печатной области. Приходилось подстраиваться.

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

«Особый способ» — это когда печатается чек и сразу шапка следующего чека, а потом происходит отрез. Отрезается текущий документ, а первые несколько строк следующего при этом уже напечатаны и скрыты под крышкой аппарата. Следующий документ печатается уже не с начала а, например, с 5ой строки. И тоже после его печати печатаются первые 5 строк следующего. В общем, способ не особо удобный. При нем надо чтобы первые строки везде были одинаковые.

В общем, программа заработала, несколько аппаратов из имеющегося у меня хлама вообще не смогли ничего распечатать, но это были совсем старые модели, которые имели 2 ленты и ширину бумаги 45 мм. У них просто не было вообще команды печать графики.

Комментарии (16)


  1. kolabaister
    00.00.0000 00:00

    В атоловских драйверах же вроде есть нативные методы печати текстовой строки и даже формирования qr и штрих-кода.


    1. Aleks3122 Автор
      00.00.0000 00:00
      +2

      Так мне же не просто строку печатать! А фиг знает что. Может строку, может картинку, может штрих код. При этом каким угодно шрифтом, используя отступы, межсимвольные и межстрочные интервалы. А штрих код тоже может быть разный, и с разным масштабом. Поэтому вся эта кухня в моем приложении, а наружу уже готовый документ идет.


  1. vladbarcelo
    00.00.0000 00:00
    +4

    Мне кажется логичнее временные файлы класть в папку temp - через GetTempPathA какой-нибудь


    1. osmanpasha
      00.00.0000 00:00
      +7

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


  1. BigBeaver
    00.00.0000 00:00
    +1

    Вот бы в обратную сторону)


  1. apppostol
    00.00.0000 00:00

    Интересно, а есть какой-то официальный софт для такого? Или только вот так самим писать. Вы прогу не распространяете случайно, может продаете? Знакомый недавно как раз чем-то подобным интересовался. Чтобы в баре всякие приколюхи печатать можно было.


    1. Aleks3122 Автор
      00.00.0000 00:00

      Т.к. я изначально переделывал старые кассы (а сначала просто выдирал термопринтеры из них) и подключал как придется (через LPT, потом через COM порты), то конечно ничего готового у меня не было. А если бы и нашел - это было бы не универсальное решение. Поэтому начал писать сам под себя. Если вас что-то заинтересовало, пишите в личку, тут рекламировать не буду.


    1. samponet
      00.00.0000 00:00

      Какого плана приколюхи и на каком оборудовании?


  1. Enwony
    00.00.0000 00:00

    Я занимался около 15 лет автоматизацией и обслуживанием фискальных регистраторов (тех, о которых вы пишете), в основном на оборудовании Штрих-М, но и Атолы были, и десяток менее известных производителей - Меркурий, Счетмаш, Искра, СП.
    При переходе на современные фискальные накопители (~2016гг) для старых аппаратов нужна была серьезная доработка - установка нового процессорного модуля (для штриха) или замена материнской платы (для атола), но чаще покупали новый ФР. Поэтому довольно много старых аппаратов были списаны, при этом ресурс печати у них еще довольно большой, их можно найти на авито за 500-1500 руб.
    Но для печати из windows они подходят довольно плохо - печать графики будет медленной (из-за особенностей протокола обмена + невысоких скоростей). Однако они неплохо и довольно быстро печатают тексты и произвольную заранее заготовленную/загруженную графику через штатный драйвер (старый).
    Теоретически, железо там несложное, и вроде даже где-то были попытки написать отдельную прошивку для таких устройств для печати windows, но нет серьезного стимула - устройств не так много.
    К тому же, обычные хорошие термопринтеры(новые) стоят значительно дешевле любого фискального регистратора.


  1. Enwony
    00.00.0000 00:00

    Кстати, чем мне нравятся эти термопринтеры - так это неприхотливостью в работе и сравнительно высокой надежностью. Они боятся воды, чистки ножницами, механического износа и статики (когда отрывают чек, искра может повредить одну из линий печати).


    1. Aleks3122 Автор
      00.00.0000 00:00

      Так я для штрих-ФР/ФРК, штрих-М ФРК и прочих писал прошивку, которая превращала аппарат в _Настоящий_ термопринтер. Было переделано несколько десятков аппаратов. Они печатали из ворда, ексела, пробную страницу. Но потом это все заглохло, т.к. появилось множество всяких xprinter ов из китая, народ их покупал за копейки, потом мучался из за хренового качества печати. А так скорость печати была не очень высокая, т.к. обмен шел через СОМ порт, но качество было идеальным.


  1. Enwony
    00.00.0000 00:00

    А почему скорость печати невысокая? Если правильно помню то у широких аппаратов ширина строки 512 бит (80мм), а высота строки примерно 0.353мм, при скорости печати 150мм/сек - для печати напрямую нужен интерфейс со скоростью около 27Кбайт/сек (у RS232 14Кб/сек), с учетом простейшего RLE - должно хватать вполне.
    Да, вообще здорово, что решение есть (вы его продаете?), но так как аппаратов все меньше, востребованность тоже падает.
    Я люблю находить старым вещам хорошее применение, но такие проекты очень специфичны - как по времени, так и по деталям внедрения. Как правило, клиента интересует только цена и сервис, это значит, распространять нужно среди интеграторов, а они часто не заинтересованы в низких ценах и простых решениях.


    1. samponet
      00.00.0000 00:00

      А у вас какая именно потребность на них печатать?


      1. Enwony
        00.00.0000 00:00

        Никакой серьезной, иногда требуются термопринтеры на автоматизацию (кухонные принтеры/принтеры заказов). Речь идет о штуках в год. Пару раз мы применяли принтеры штрих-м (после перепрошивки в АСПД), но чаще заказчик просто покупает новый термопринтер или б/у Zebra/bixolon/TSC.


  1. Aleks3122 Автор
    00.00.0000 00:00

    Для печати я использовал скорость порта 19200. Никакой компрессии не использовал. Проблема была в том, что драйвер я взял готовый. От какого-то там промышленного термопринтера. Взял этот, т.к. смог расколоть его протокол обмена. Просто что-то печатал и снимал hex дамп. Потом пытался понять как там передаются данные и команды. Затем уже в моей прошивке подстраивался под этот формат, добиваясь чтобы отправленные задания на печать корректно печатал мой "как бы принтер". Полностью конечно я формат не разгадал, но тех команд что я засек, вполне хватало для печати из офисных приложений. Большой проблемой были тайминги, чтобы не переполнялся буфер в штрихе. Там есть микросхема статической памяти, ее и использовал. Пробовал разные скорости обмена, надо было добиться чтобы нормально комп передавал задание, чтобы не переполнялся буфер и чтобы голова все успела напечатать. В итоге остановился на 19200. Некоторые фискальники турбировал. Так в штрихе фрк менял кварц на более быстрый.


  1. samponet
    00.00.0000 00:00

    Недавно возник вопрос печати слипа на этих машинках и он успешно решился аж из vbscript. По документации, если просто печатать некий текст, изгаляться особо не надо- команда открыть нефискальный документ, что-то печатать в win1251 теми же командами драйвера построчно, команда закрыть нефискальный документ. Отрезка по желанию. Все работает как часы, прога меньше полсотни строк. Нет никакой возни со скоростями там и прочим- если настроил ККМ в драйвере, то все отлично. Я распечатывал последний слип с эквайринга сбера, разве что добавить пришлось cp866->win1251, а так любой текстовик запросто.