Мониторинг онлайн касс реализован на получении данных с промежуточных файлов в которые раз в 30 минут данные обновляются доработанным скриптом на Python который был взят отсюда https://грибовы.рф/kontrol-kass-atol-v-zabbix/ который берет список IP адресов касс из файла kassaPrintList такого содержания
192.168.40.2
192.168.40.3
192.168.40.4
192.168.40.5
192.168.40.6
192.168.40.7
192.168.40.8
192.168.40.9
Используем скрипт list_kassa.sh для формирования списка касс в формате JSON для передачи на сервер zabbix.
JSON=$(for i in `cat /etc/zabbix/kassaPrintList`; do printf "{\"{#KASSA}\":\"$i\"},"; done | sed 's/^\(.*\).$/\1/')
printf "{\"data\":["
printf "$JSON"
printf "]}"
Сам скрипт для заполнения параметров по кассе.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import base64
import ctypes
import sys
import json
import datetime
import os
import platform
from pprint import pprint
#from datetime import datetime# Проверьте наличие библиотеки
LIBRARY_PATH = os.path.dirname(os.path.abspath(__file__))
LIBRARY_FILE = os.path.join(LIBRARY_PATH, "libfptr10.so")if not os.path.exists(LIBRARY_FILE):
print(f"Ошибка: библиотека {LIBRARY_FILE} не найдена.")
sys.exit(1)# Проверьте наличие модуля
try:
from lib import IFptr
except ImportError:
print("Ошибка: модуль lib не найден.")
sys.exit(1)# Открываем файл с IP-адресами кассовых аппаратов
file_path = '/etc/zabbix/kassaPrintList'if not os.path.exists(file_path):
print(f"Ошибка: файл {file_path} не найден.")
sys.exit(1)with open(file_path, 'r') as file:
for printer in file:
ip = printer.strip() # Удаляем лишние символы и пробелы # Подключаемся к кассовой машине
fptr = IFptr(LIBRARY_FILE)
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_MODEL, str(IFptr.LIBFPTR_MODEL_ATOL_AUTO))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_PORT, str(IFptr.LIBFPTR_PORT_TCPIP))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPADDRESS, ip)
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPPORT, "5555")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_ACCESS_PASSWORD, "0")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_USER_PASSWORD, "30") fptr.applySingleSettings()
fptr.open()
isOpened = fptr.isOpened() if isOpened == 0:
print(f"Ошибка: не удалось подключиться к кассовой машине с IP {ip}.")
continue # Получаем информацию о кассовом аппарате
fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_REG_INFO)
fptr.fnQueryData() taxationTypes = fptr.getParamInt(1062)
agentSign = fptr.getParamInt(1057)
ffdVersion = fptr.getParamInt(1209)
autoModeSign = fptr.getParamBool(1001)
offlineModeSign = fptr.getParamBool(1002)
encryptionSign = fptr.getParamBool(1056)
internetSign = fptr.getParamBool(1108)
serviceSign = fptr.getParamBool(1109)
bsoSign = fptr.getParamBool(1110)
lotterySign = fptr.getParamBool(1126)
gamblingSign = fptr.getParamBool(1193)
exciseSign = fptr.getParamBool(1207)
machineInstallationSign = fptr.getParamBool(1221)
fnsUrl = fptr.getParamString(1060)
organizationVATIN = fptr.getParamString(1018)
organizationName = fptr.getParamString(1048)
organizationEmail = fptr.getParamString(1117)
paymentsAddress = fptr.getParamString(1187)
registrationNumber = fptr.getParamString(1037)
machineNumber = fptr.getParamString(1036)
ofdVATIN = fptr.getParamString(1017)
ofdName = fptr.getParamString(1046)
ofdStatus = fptr.getParamString(1002) fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_STATUS)
fptr.queryData()
serialNumber = fptr.getParamString(IFptr.LIBFPTR_PARAM_SERIAL_NUMBER)
modelName = fptr.getParamString(IFptr.LIBFPTR_PARAM_MODEL_NAME)
firmwareVersion = fptr.getParamString(IFptr.LIBFPTR_PARAM_UNIT_VERSION) fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_VALIDITY)
fptr.fnQueryData()
dateTime = fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
timestamp = int(dateTime.timestamp())
current_time = datetime.datetime.now()
current_timestamp = int(current_time.timestamp())
difference = timestamp - current_timestamp
delta = datetime.timedelta(seconds=difference)
# delta = datetime.timedelta(seconds=difference)
days = delta.days dt = datetime.datetime.fromtimestamp(timestamp) fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_LAST_RECEIPT)
fptr.fnQueryData()
documentNumber = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER) # Получение информации о неотправленных документах
fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_OFD_EXCHANGE_STATUS)
fptr.fnQueryData()
unsentCount = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENTS_COUNT)
if unsentCount > 0:
unsentFirstNumber = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
unsentDateTime = fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
unsetC = unsentCount
else:
unsetC = 0 # Закрываем соединение
fptr.close()
del fptr # Формируем JSON-объект с данными
data = {
"ffdVersion": ffdVersion,
"organizationName": organizationName,
"ofdName": ofdName,
"serialNumber": serialNumber,
"modelName": modelName,
"dateTime": dt.strftime("%Y-%m-%d"),
# "dateTime": timestamp,
"difference": days,
"documentNumber": documentNumber,
"unsetCount": unsetC,
# "autoModeSign": autoModeSign,
# "offlineModeSign": offlineModeSign,
# "encryptionSign": encryptionSign,
# "internetSign": internetSign,
# "serviceSign": serviceSign,
# "bsoSign": bsoSign,
# "lotterySign": lotterySign,
# "gamblingSign": gamblingSign,
# "exciseSign": exciseSign,
# "machineInstallationSign": machineInstallationSign,
"fnsUrl": fnsUrl,
"organizationVATIN": organizationVATIN,
"organizationName": organizationName,
"organizationEmail": organizationEmail,
"paymentsAddress": paymentsAddress,
"registrationNumber": registrationNumber
} # Записываем данные в JSON-файл
json_file_path = f"/etc/zabbix/{ip}.json"
with open(json_file_path, "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=4) print(f"Информация о кассовом аппарате с IP {ip} успешно записана в файл {json_file_path}.")
Формируется файл с данными такого вида.
{
"ffdVersion": 120,
"organizationName": "ООО \"Рога и копыта\"",
"ofdName": "ООО \"Копыта и рога\"",
"serialNumber": "00123456789073",
"modelName": "АТОЛ 22 v2 Ф",
"dateTime": "2026-11-06",
"difference": 392,
"documentNumber": 0,
"unsetCount": 0,
"fnsUrl": "nalog.gov.ru",
"organizationVATIN": "1123012345 ",
"organizationEmail": "sbis@sbis.ru",
"paymentsAddress": "\"РогаИКопытаМаркет\" Торговый зал",
"registrationNumber": "0009876543210987"
}
В конфигурационный файл zabbix-agent.conf добавляем параметр
UserParameter=kassa.show[*],/etc/zabbix/list_kassa.sh
Далее в Zabbix создаем шаблон с обнаружением.
Далее создаем прототип элемента данных который считывает данные из json файла с параметрами кассы.
Далее создаем прототип с элементом данных указываем тип "Зависимый элемент данных"
В предобработке указывает эти параметры.
По аналогии настраиваем для всех остальных пунктов зависимый элемент данных.
Доступность касс отслеживаем с помощью icmpping
Сам файл Шаблона элементов данных >>>тут<<<