Фіскальний реєстратор МІНІ-ФП54.01
МІНІ-ФП54.01 — портативний фіскальний реєстратор виробництва Юнісістем. Пристрій має акумулятор, контрольну стрічку в електронній формі, інтерфейси підключення до ПК через USB або RS-232, а також канали передачі даних через Ethernet та GSM/GPRS.
Модель підходить для роздрібної торгівлі, виїзної торгівлі, інтернет-магазинів, аптек, кафе, барів, ресторанів та сфери послуг.
Короткий опис
| Параметр | Значення |
|---|---|
| Назва | МІНІ-ФП54.01 |
| Тип пристрою | Фіскальний реєстратор |
| Виробник | Юнісістем |
| Версія ПЗ | 5401F3 |
| Підключення до ПК | USB або RS-232 |
| Передача даних | Ethernet, GSM/GPRS |
| Bluetooth | Опція |
| Основний офіційний спосіб інтеграції | DLL / OLE-сервер для Windows |
| Альтернативна інтеграція | Пряма робота через протокол обміну |
Важливі висновки для інтеграції
| Статус | Висновок | Коментар |
|---|---|---|
| Рекомендовано | Для Windows використовувати офіційний DLL / OLE-сервер | Це найшвидший шлях інтеграції з POS-системою або Python-застосунком через COM/OLE. |
| Можливо | Для Linux/macOS можна реалізувати власний драйвер через serial-порт | Потрібна реалізація протоколу обміну з фіскальним реєстратором. |
| Обережно | Офіційних Python-прикладів не знайдено | Python можна використовувати через pywin32 або pyserial, але готового SDK саме для Python на сторінці підтримки немає. |
| Не робити | Не підключати одночасно USB і RS-232 до одного ПК | Для роботи з ПК потрібно використовувати один інтерфейс підключення. |
| Не плутати | Ethernet/GSM не є основним інтерфейсом POS-команд | Ethernet і GSM/GPRS використовуються переважно для передачі даних до ДПС. |
Основні характеристики
| Характеристика | Значення |
|---|---|
| Кількість товарів | 16 384 |
| Кількість відділів | 64 |
| Кількість касирів | 32 |
| Кількість символів у рядку | 32 |
| Кількість символів у назві товару | 48 |
| Початкове повідомлення | 12 рядків |
| Заключне повідомлення | 2 рядки |
| Дисплей покупця | Вбудований, 2×16 символів |
| Друк | Термодрук |
| Ширина стрічки | 58 мм |
| Швидкість друку | 8 рядків/с |
| Живлення | Вбудований Li-Pol акумулятор |
| Акумулятор | 7,4 В; 2 А·год, опційно 3,6 А·год |
| RS-232 | 1 порт |
| USB | 1 порт |
| Bluetooth | Опція |
| Грошова скринька | micro-jack 2,5 мм |
| Ethernet | Є |
| GSM/GPRS | Вбудований |
| Габарити | 181 × 123 × 102 мм |
| Маса | 0,73 кг |
Підключення до компʼютера
МІНІ-ФП54.01 може підключатися до компʼютера через:
- USB;
- RS-232 / COM-порт.
Типова схема підключення:
POS-система / касова програма
↓
Драйвер або власна інтеграція
↓
USB або RS-232
↓
МІНІ-ФП54.01
USB-підключення
USB-підключення зручне для сучасних ПК і ноутбуків. Після встановлення USB-драйвера пристрій зазвичай працює як віртуальний COM-порт.
Приклад:
Windows: COM3, COM4, COM5 ... Linux: /dev/ttyUSB0 /dev/ttyACM0 macOS: /dev/tty.usbserial-* /dev/tty.usbmodem-*
| Статус | Примітка |
|---|---|
| Добре | USB простіше використовувати на сучасних робочих місцях. |
| Перевірити | Потрібно встановити USB-драйвер виробника. |
| Ризик | У різних ОС назва порту буде різною, тому її не можна жорстко зашивати в код. |
RS-232 / COM-порт
RS-232 підходить для класичних POS-систем, касових терміналів і embedded-рішень.
| Статус | Примітка |
|---|---|
| Добре | Serial-протокол простіше реалізувати кросплатформно. |
| Перевірити | Потрібен фізичний COM-порт або USB-RS232 адаптер. |
| Ризик | Дешеві USB-RS232 адаптери можуть давати нестабільний звʼязок. |
Ethernet, GSM/GPRS і Bluetooth
Пристрій має Ethernet-порт і GSM/GPRS-модем для передачі даних.
| Інтерфейс | Призначення | Коментар |
|---|---|---|
| USB | Підключення до ПК | Основний варіант для POS-інтеграції. |
| RS-232 | Підключення до ПК | Зручний для serial-інтеграції. |
| Ethernet | Передача даних через інтернет | Використовується для звʼязку з ДПС. |
| GSM/GPRS | Передача даних через мобільну мережу | Дає змогу працювати без дротового інтернету. |
| Bluetooth | Опційне підключення | Може використовуватися зі смартфоном або планшетом за наявності сумісного ПЗ. |
Операційні системи
Windows
Для Windows виробник надає:
- USB-драйвер;
- DLL-бібліотеку / OLE-сервер;
- програму UNI-PROGress для налаштування РРО;
- Uniq Commander для налаштування комунікаційного блоку;
- обробку для «1С:Підприємство».
Рекомендована схема для Windows:
POS-система
↓
Python / C# / 1C / інше ПЗ
↓
OLE/DLL Юнісістем
↓
USB або COM
↓
МІНІ-ФП54.01
| Статус | Висновок |
|---|---|
| Рекомендовано | Windows — найпростіша ОС для інтеграції через офіційний OLE/DLL. |
| Плюс | Можна використовувати Python через pywin32. |
| Уточнити | Потрібно знати реальний ProgID OLE-сервера і точні назви методів. |
Linux
Linux не є основною цільовою платформою для офіційного OLE/DLL-драйвера. Але інтеграція можлива через serial-порт, якщо реалізувати протокол обміну.
Схема:
POS-система
↓
Python-сервіс
↓
pyserial
↓
/dev/ttyUSB0 або /dev/ttyS0
↓
МІНІ-ФП54.01
| Статус | Висновок |
|---|---|
| Можливо | Linux може працювати з пристроєм через serial-порт. |
| Потрібно | Реалізувати протокол обміну. |
| Немає | Готового офіційного Python SDK для Linux не знайдено. |
macOS
Для macOS ситуація аналогічна Linux: готового офіційного OLE/DLL-драйвера немає, але можна працювати через serial-порт, якщо система бачить пристрій як `/dev/tty.*`.
| Статус | Висновок |
|---|---|
| Можливо | Потрібна власна serial-інтеграція. |
| Не готово з коробки | Офіційного macOS SDK не знайдено. |
Варіанти інтеграції
Варіант 1. Через OLE/DLL у Windows
Це найпростіший варіант для Windows.
Python → pywin32 → OLE-сервер → USB/COM → МІНІ-ФП54.01
Переваги:
- не потрібно вручну реалізовувати низькорівневий протокол;
- простіше стартувати;
- можна викликати готові методи драйвера;
- підходить для POS-систем на Windows.
Недоліки:
- залежність від Windows;
- залежність від конкретної версії OLE-сервера;
- потрібно встановити та зареєструвати COM/OLE-компонент;
- потрібно знати ProgID і назви методів.
Варіант 2. Через serial-порт напряму
Цей варіант підходить для Windows, Linux, macOS та embedded-систем.
Python → pyserial → протокол обміну → USB/COM або RS-232 → МІНІ-ФП54.01
Переваги:
- кросплатформність;
- незалежність від OLE;
- можна запускати як локальний сервіс;
- зручно для Docker, Linux POS, Raspberry Pi, embedded-терміналів.
Недоліки:
- потрібно реалізувати протокол обміну;
- потрібно обробляти контрольні суми, ACK/NAK, таймаути, повтори;
- складніше тестувати;
- потрібна офіційна документація протоколу.
Python-інтеграція
Офіційних прикладів саме для Python на сторінці підтримки не знайдено. Але Python можна використовувати у двох режимах:
| Варіант | Пакет Python | ОС | Коментар |
|---|---|---|---|
| OLE/DLL | pywin32 | Windows | Найпростіший варіант, якщо встановлено OLE-сервер. |
| Serial | pyserial | Windows / Linux / macOS | Потрібна реалізація протоколу обміну. |
| Mock-драйвер | pytest / unittest | Будь-яка | Для тестування без фізичного пристрою. |
Python через OLE/DLL у Windows
Встановлення залежності
pip install pywin32
Пошук ProgID OLE-сервера
Після встановлення OLE-сервера потрібно знайти його ProgID.
Приклад через PowerShell:
Get-ChildItem "Registry::HKEY_CLASSES_ROOT" |
Where-Object { $_.Name -match "Ecr|T400|MINI|FP|Unisystem|Uni" } |
Select-Object -First 50
Приклад через Python:
import winreg
keywords = ["Ecr", "T400", "MINI", "FP", "Unisystem", "Uni"]
with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, "") as root:
total = winreg.QueryInfoKey(root)[0]
for index in range(total):
try:
name = winreg.EnumKey(root, index)
if any(keyword.lower() in name.lower() for keyword in keywords):
print(name)
except OSError:
pass
| Статус | Коментар |
|---|---|
| Важливо | Назва ProgID у прикладах нижче умовна. Її треба уточнити після встановлення реального OLE-сервера. |
Базова структура Python-обгортки
import win32com.client
class MiniFP54OleDriver:
"""
Python-обгортка над OLE-сервером Юнісістем.
Увага:
- ProgID потрібно взяти з реальної інсталяції OLE-сервера.
- Назви методів потрібно звірити з документацією до конкретної версії OLE.
"""
def __init__(self, prog_id: str):
self.prog_id = prog_id
self.driver = None
def connect_to_ole(self):
self.driver = win32com.client.Dispatch(self.prog_id)
def open_port(self, port: int, baudrate: int = 115200):
"""
Приклад.
Реальна назва методу може бути OpenPort, openPort або іншою.
"""
return self.driver.OpenPort(port, baudrate)
def close_port(self):
return self.driver.ClosePort()
def get_status(self):
return self.driver.GetStatus()
def get_version(self):
return self.driver.GetSoftVersion()
def open_shift(self):
return self.driver.OpenShift()
def close_shift(self):
return self.driver.ZReport()
def open_receipt(self):
return self.driver.OpenReceipt()
def sell_item(self, name: str, price: float, quantity: float, tax_group: int = 1):
return self.driver.Sale(name, quantity, price, tax_group)
def pay_cash(self, amount: float):
payment_type = 0
return self.driver.Pay(payment_type, amount)
def close_receipt(self):
return self.driver.CloseReceipt()
Приклад smoke-тесту через OLE
from mini_fp54_ole import MiniFP54OleDriver
PROG_ID = "PUT_REAL_PROG_ID_HERE"
driver = MiniFP54OleDriver(PROG_ID)
driver.connect_to_ole()
try:
print("Open port:", driver.open_port(port=3, baudrate=115200))
print("Version:", driver.get_version())
print("Status:", driver.get_status())
finally:
print("Close port:", driver.close_port())
Приклад продажу через OLE
from mini_fp54_ole import MiniFP54OleDriver
driver = MiniFP54OleDriver("PUT_REAL_PROG_ID_HERE") driver.connect_to_ole()
try:
driver.open_port(port=3, baudrate=115200)
driver.open_shift()
driver.open_receipt()
driver.sell_item(
name="Кава",
price=50.00,
quantity=1,
tax_group=1,
)
driver.pay_cash(50.00)
driver.close_receipt()
finally:
driver.close_port()
| Статус | Що треба перевірити перед запуском |
|---|---|
| Обовʼязково | Чи правильний ProgID OLE-сервера. |
| Обовʼязково | Чи правильні назви методів. |
| Обовʼязково | Чи правильний COM-порт. |
| Не запускати в production | Поки не перевірено на тестовому РРО або у нефіскальному режимі. |
Python через serial-порт
Встановлення залежності
pip install pyserial
Базовий serial-клієнт
import serial from dataclasses import dataclass
@dataclass class MiniFP54SerialConfig:
port: str
baudrate: int = 115200
timeout: float = 3.0
encoding: str = "cp1251"
class MiniFP54SerialClient:
"""
Базовий serial-клієнт для МІНІ-ФП54.01.
Це не повний драйвер.
Для реальної роботи потрібно реалізувати офіційний протокол:
- формат пакета;
- службові байти;
- довжину;
- контрольну суму;
- ACK/NAK;
- повтори;
- таймаути;
- парсинг статусів і помилок.
"""
def __init__(self, config: MiniFP54SerialConfig):
self.config = config
self.connection: serial.Serial | None = None
def connect(self):
self.connection = serial.Serial(
port=self.config.port,
baudrate=self.config.baudrate,
timeout=self.config.timeout,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
)
def disconnect(self):
if self.connection and self.connection.is_open:
self.connection.close()
def send_raw(self, payload: bytes, read_size: int = 1024) -> bytes:
if not self.connection or not self.connection.is_open:
raise RuntimeError("Serial port is not open")
self.connection.write(payload)
self.connection.flush()
return self.connection.read(read_size)
def send_text_command(self, command: str) -> str:
"""
Умовний приклад текстової команди.
Реальний формат треба взяти з протоколу обміну.
"""
payload = command.encode(self.config.encoding)
response = self.send_raw(payload)
return response.decode(self.config.encoding, errors="replace")
Приклад smoke-тесту через serial
from mini_fp54_serial import MiniFP54SerialClient, MiniFP54SerialConfig
client = MiniFP54SerialClient(
MiniFP54SerialConfig(
port="COM3", # Linux: "/dev/ttyUSB0"
baudrate=115200,
timeout=3.0,
)
)
client.connect()
try:
response = client.send_text_command("GET_STATUS")
print(response)
finally:
client.disconnect()
| Статус | Коментар |
|---|---|
| Умовний приклад | Команда GET_STATUS наведена як приклад. Реальну команду потрібно брати з протоколу обміну. |
| Корисно | Така структура підходить для побудови власного драйвера. |
| Не достатньо | Без реалізації контрольної суми та службових байтів це не production-драйвер. |
Тестування драйвера без пристрою
Без фізичного МІНІ-ФП54.01 можна тестувати не сам фіскальний реєстратор, а логіку інтеграції.
Мета тестування без пристрою:
- перевірити бізнес-логіку POS-системи;
- перевірити порядок команд;
- перевірити обробку помилок;
- перевірити логування;
- перевірити поведінку при timeout;
- перевірити поведінку при відсутності паперу;
- перевірити поведінку при розриві зʼєднання.
Архітектура тестування без пристрою
POS-система
↓
FiscalDriverInterface
↓
FakeMiniFP54Driver
↓
Unit / integration tests
Інтерфейс драйвера
from abc import ABC, abstractmethod
class FiscalDriverInterface(ABC):
@abstractmethod
def open_shift(self) -> str:
pass
@abstractmethod
def close_shift(self) -> str:
pass
@abstractmethod
def open_receipt(self) -> str:
pass
@abstractmethod
def sell_item(self, name: str, price: float, quantity: float) -> str:
pass
@abstractmethod
def pay_cash(self, amount: float) -> str:
pass
@abstractmethod
def close_receipt(self) -> str:
pass
@abstractmethod
def get_status(self) -> str:
pass
Fake-драйвер
class FakeMiniFP54Driver(FiscalDriverInterface):
def __init__(self):
self.shift_opened = False
self.receipt_opened = False
self.items = []
self.total = 0.0
def open_shift(self) -> str:
if self.shift_opened:
return "ERROR;SHIFT_ALREADY_OPEN"
self.shift_opened = True
return "OK;SHIFT_OPENED"
def close_shift(self) -> str:
if not self.shift_opened:
return "ERROR;SHIFT_NOT_OPEN"
if self.receipt_opened:
return "ERROR;RECEIPT_IS_OPEN"
self.shift_opened = False
return "OK;Z_REPORT_PRINTED"
def open_receipt(self) -> str:
if not self.shift_opened:
return "ERROR;SHIFT_NOT_OPEN"
if self.receipt_opened:
return "ERROR;RECEIPT_ALREADY_OPEN"
self.receipt_opened = True
self.items = []
self.total = 0.0
return "OK;RECEIPT_OPENED"
def sell_item(self, name: str, price: float, quantity: float) -> str:
if not self.receipt_opened:
return "ERROR;RECEIPT_NOT_OPEN"
if price <= 0:
return "ERROR;INVALID_PRICE"
if quantity <= 0:
return "ERROR;INVALID_QUANTITY"
amount = round(price * quantity, 2)
self.items.append(
{
"name": name,
"price": price,
"quantity": quantity,
"amount": amount,
}
)
self.total = round(self.total + amount, 2)
return f"OK;ITEM_ADDED;{amount:.2f}"
def pay_cash(self, amount: float) -> str:
if not self.receipt_opened:
return "ERROR;RECEIPT_NOT_OPEN"
if amount < self.total:
return "ERROR;PAYMENT_LESS_THAN_TOTAL"
change = round(amount - self.total, 2)
return f"OK;PAYMENT_ACCEPTED;CHANGE={change:.2f}"
def close_receipt(self) -> str:
if not self.receipt_opened:
return "ERROR;RECEIPT_NOT_OPEN"
if not self.items:
return "ERROR;EMPTY_RECEIPT"
self.receipt_opened = False
return f"OK;RECEIPT_CLOSED;TOTAL={self.total:.2f}"
def get_status(self) -> str:
return (
"OK;"
f"SHIFT_OPENED={self.shift_opened};"
f"RECEIPT_OPENED={self.receipt_opened}"
)
Unit-тест успішного продажу
def test_success_sale_flow():
driver = FakeMiniFP54Driver()
assert driver.open_shift() == "OK;SHIFT_OPENED"
assert driver.open_receipt() == "OK;RECEIPT_OPENED"
result = driver.sell_item("Кава", price=50.00, quantity=2)
assert result == "OK;ITEM_ADDED;100.00"
result = driver.pay_cash(100.00)
assert result == "OK;PAYMENT_ACCEPTED;CHANGE=0.00"
result = driver.close_receipt()
assert result == "OK;RECEIPT_CLOSED;TOTAL=100.00"
result = driver.close_shift()
assert result == "OK;Z_REPORT_PRINTED"
Unit-тест помилки: чек без відкритої зміни
def test_open_receipt_without_shift():
driver = FakeMiniFP54Driver()
result = driver.open_receipt()
assert result == "ERROR;SHIFT_NOT_OPEN"
Unit-тест помилки: оплата менша за суму чека
def test_payment_less_than_total():
driver = FakeMiniFP54Driver()
driver.open_shift()
driver.open_receipt()
driver.sell_item("Кава", price=50.00, quantity=2)
result = driver.pay_cash(50.00)
assert result == "ERROR;PAYMENT_LESS_THAN_TOTAL"
Емуляція serial-пристрою без фізичного РРО
Для тестування serial-драйвера без пристрою можна зробити локальний емулятор.
Варіант для Linux/macOS
Можна створити пару віртуальних serial-портів через `socat`.
socat -d -d pty,raw,echo=0 pty,raw,echo=0
Після запуску `socat` покаже два порти, наприклад:
/dev/pts/3 /dev/pts/4
Один порт використовує тестовий POS-драйвер, інший — емулятор пристрою.
Простий Python-емулятор
import serial
PORT = "/dev/pts/4" BAUDRATE = 115200
def handle_command(command: str) -> str:
command = command.strip()
if command == "GET_STATUS":
return "OK;READY\n"
if command == "GET_VERSION":
return "OK;MINI-FP54.01;5401F3\n"
if command.startswith("SALE"):
return "OK;ITEM_ADDED\n"
if command.startswith("PAY"):
return "OK;PAYMENT_ACCEPTED\n"
if command == "CLOSE_RECEIPT":
return "OK;RECEIPT_CLOSED\n"
return "ERROR;UNKNOWN_COMMAND\n"
with serial.Serial(PORT, BAUDRATE, timeout=1) as ser:
print(f"Fake MINI-FP54.01 emulator started on {PORT}")
while True:
raw = ser.readline()
if not raw:
continue
command = raw.decode("cp1251", errors="replace")
response = handle_command(command)
ser.write(response.encode("cp1251"))
ser.flush()
| Статус | Коментар |
|---|---|
| Добре для розробки | Емулятор дозволяє тестувати POS-сценарії без фізичного пристрою. |
| Не замінює РРО | Емулятор не перевіряє реальний фіскальний протокол. |
| Не для production | Не можна вважати інтеграцію готовою без тестів із реальним пристроєм. |
Тестування з реальним пристроєм
Підготовка
- Встановити USB-драйвер виробника.
- Встановити DLL/OLE-сервер, якщо використовується Windows.
- Підключити пристрій через USB або RS-232.
- Переконатися, що використовується тільки один інтерфейс.
- Перевірити, який COM-порт отримав пристрій.
- Перевірити наявність паперу.
- Перевірити заряд акумулятора або живлення.
- Перевірити Ethernet або GSM/GPRS для передачі даних.
- Виконати команду отримання статусу.
- Виконати тестовий друк або службову операцію.
Мінімальний чек-лист smoke-тесту
| № | Тест | Очікуваний результат |
|---|---|---|
| 1 | Відкрити порт | Драйвер не повертає помилку |
| 2 | Отримати статус | Пристрій відповідає |
| 3 | Отримати версію ПЗ | Повертається версія пристрою |
| 4 | Перевірити папір | Немає помилки паперу |
| 5 | Відкрити зміну | Зміна відкрита |
| 6 | Відкрити чек | Чек відкритий |
| 7 | Додати товар | Рядок товару надруковано або прийнято |
| 8 | Провести оплату | Оплата прийнята |
| 9 | Закрити чек | Чек закритий |
| 10 | Надрукувати X-звіт | Звіт друкується без закриття зміни |
| 11 | Надрукувати Z-звіт | Зміна закрита |
| 12 | Перевірити передачу даних | Дані передаються через Ethernet або GSM/GPRS |
Робота в реальному режимі
Реальний режим — це робота з фіскалізованим пристроєм, який використовується для реєстрації розрахункових операцій.
Перед запуском
Перед production-запуском потрібно:
- Зареєструвати РРО.
- Виконати фіскалізацію.
- Виконати персоналізацію.
- Налаштувати податкові групи.
- Налаштувати типи оплат.
- Налаштувати касирів.
- Налаштувати заголовок і підвал чека.
- Перевірити передачу даних.
- Перевірити роботу POS-системи з реальним драйвером.
- Провести тестовий день роботи.
| Статус | Правило |
|---|---|
| Обовʼязково | Усі операції продажу мають проходити через фіскальний реєстратор. |
| Обовʼязково | Наприкінці зміни потрібно виконувати Z-звіт. |
| Контроль | Потрібно перевіряти статус передачі даних. |
| Небезпечно | Не можна ігнорувати помилки фіскального реєстратора. |
Типовий робочий цикл
1. Увімкнути фіскальний реєстратор. 2. Перевірити звʼязок із POS-системою. 3. Перевірити папір. 4. Відкрити зміну. 5. Пробивати чеки продажу. 6. За потреби виконувати повернення. 7. За потреби друкувати X-звіт. 8. Наприкінці дня друкувати Z-звіт. 9. Перевірити передачу даних.
Обробка помилок
Типові помилки інтеграції
| Помилка | Причина | Що робити |
|---|---|---|
| Немає звʼязку з пристроєм | Неправильний COM-порт або кабель | Перевірити порт, кабель, драйвер, живлення |
| Timeout | Пристрій не відповідає | Повторити команду, перевірити стан РРО |
| Port busy | Порт зайнятий іншою програмою | Закрити інші програми, які використовують COM-порт |
| Немає паперу | Закінчилась чекова стрічка | Замінити папір і повторити операцію |
| Зміна не відкрита | POS намагається пробити чек без відкритої зміни | Спочатку виконати відкриття зміни |
| Чек уже відкритий | Попередній чек не закритий | Закрити або анулювати чек |
| Помилка передачі даних | Немає Ethernet/GSM-звʼязку | Перевірити інтернет, SIM-карту, налаштування |
Рекомендований retry-механізм
import time
class FiscalCommandError(Exception):
pass
def execute_with_retry(command, retries: int = 3, delay: float = 1.0):
last_error = None
for attempt in range(1, retries + 1):
try:
result = command()
if isinstance(result, str) and result.startswith("OK"):
return result
last_error = result
except Exception as exc:
last_error = exc
time.sleep(delay)
raise FiscalCommandError(f"Command failed after {retries} retries: {last_error}")
Логування
Для production-інтеграції потрібно логувати:
- дату й час команди;
- тип команди;
- параметри команди;
- відповідь пристрою;
- код помилки;
- COM-порт;
- тривалість виконання;
- номер чека;
- номер зміни.
Приклад логування в Python
import logging import time
logging.basicConfig(
filename="mini_fp54.log",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
def log_fiscal_command(command_name: str, callback):
started_at = time.time()
try:
result = callback()
duration = round(time.time() - started_at, 3)
logging.info(
"command=%s duration=%s result=%s",
command_name,
duration,
result,
)
return result
except Exception as exc:
duration = round(time.time() - started_at, 3)
logging.exception(
"command=%s duration=%s error=%s",
command_name,
duration,
exc,
)
raise
Рекомендована структура Python-проєкту
mini_fp54/
├── __init__.py
├── interfaces.py
├── ole_driver.py
├── serial_driver.py
├── fake_driver.py
├── errors.py
├── logger.py
├── config.py
└── tests/
├── test_fake_driver.py
├── test_sale_flow.py
└── test_errors.py
Призначення файлів
| Файл | Призначення |
|---|---|
| interfaces.py | Спільний інтерфейс драйвера |
| ole_driver.py | Робота через OLE/DLL у Windows |
| serial_driver.py | Робота через serial-порт |
| fake_driver.py | Mock-драйвер для тестів |
| errors.py | Власні класи помилок |
| logger.py | Логування команд і відповідей |
| config.py | Налаштування порту, швидкості, режиму роботи |
| tests/ | Unit та integration-тести |
Production checklist
| Статус | Перевірка |
|---|---|
| □ | USB-драйвер встановлено |
| □ | OLE/DLL встановлено, якщо використовується Windows |
| □ | COM-порт визначено |
| □ | Отримання статусу працює |
| □ | Відкриття зміни працює |
| □ | Продаж товару працює |
| □ | Оплата готівкою працює |
| □ | Оплата карткою працює |
| □ | Закриття чека працює |
| □ | X-звіт працює |
| □ | Z-звіт працює |
| □ | Передача даних працює |
| □ | Перевірено поведінку при timeout |
| □ | Перевірено поведінку при відсутності паперу |
| □ | Перевірено поведінку при втраті інтернету |
| □ | Немає hardcoded COM-порту в production-коді |
| □ | Немає ігнорування помилок РРО |
Висновок
МІНІ-ФП54.01 найпростіше інтегрувати у Windows через офіційний DLL/OLE-сервер. Python можна використовувати через пакет `pywin32`, якщо встановлено та зареєстровано OLE-сервер.
Для Linux, macOS або embedded-систем можлива інтеграція через `pyserial`, але для цього потрібно реалізувати протокол обміну з пристроєм. Такий варіант гнучкіший, але складніший і потребує повного тестування з реальним фіскальним реєстратором.
Для розробки без фізичного пристрою варто використовувати mock-драйвер або serial-емулятор. Це дозволяє перевірити POS-логіку, але не замінює тестування з реальним РРО.
Джерела
- Офіційна сторінка МІНІ-ФП54.01: https://unisystem.ua/catalog/fiskalnye-registratory/fiskalnyj-registrator-mini-fp54-01/
- Сторінка підтримки Юнісістем: https://unisystem.ua/podderzhka/