Files
uarep-ctl/modbus/server-serial-modbus.py
2024-10-10 14:15:46 +03:00

74 lines
3.4 KiB
Python

#!/usr/bin/env python3
"""
Имитатор сервера Modbus Serial прибора Щ3.
Использовать для отладки. Только сохраняет данные регистров.
"""
import logger
import os
import argparse
from pymodbus.server.sync import StartSerialServer
from pymodbus.datastore import ModbusSlaveContext
from pymodbus.datastore import ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer
DEF_SERIAL = 'COM2' if os.name == 'nt' else '/dev/tty3'
log_file_dir = os.path.join(os.path.expanduser('~'))
log = logger.get_logger(__file__, log_file_dir)
FX_CODES = {2: 'di', 4: 'ir', 3: 'hr', 6: 'hr', 16: 'hr', 22: 'hr', 23: 'hr', 1: 'co', 5: 'co', 15: 'co'}
""" Кодировка регистров в pymodbus """
class CallbackModbusSlaveContext(ModbusSlaveContext):
""" Блок данных, который сохраняет новое значение
в памяти и передаёт операцию в очередь сообщений
для дальнейшей процедуры обработки. """
def __init__(self):
""" """
super(CallbackModbusSlaveContext, self).__init__()
def setValues(self, fx, address, values):
""" Устанавливает требуемые значения хранилища данных.
:param fx:
:param address: Начальный адрес.
:param values: Новые значения, которые необходимо установить.
"""
super(CallbackModbusSlaveContext, self).setValues(fx, address, values)
fx = FX_CODES[fx] if fx in FX_CODES else '**error**'
log.debug('setValues() fx:%s address:%s values:%s' % (fx, address, values))
def getValues(self, fx, address, count=1):
""" Устанавливает требуемые значения хранилища данных.
:param fx:
:param address: Начальный адрес
:param count:
"""
values = super(CallbackModbusSlaveContext, self).getValues(fx, address, count)
fx = FX_CODES[fx] if fx in FX_CODES else '**error**'
log.debug('getValues() fx:%s address:%s values:%s' % (fx, address, values))
return values
def main():
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--serial-baud', default=115200, type=int, help='Скорость последовательного порта, бод')
parser.add_argument('--serial-port', default=DEF_SERIAL, type=str, help='Последовательный порт для подключения клиента')
parser.add_argument('--timeout', default=0.005, type=str, help='Таймаут последовательного порта')
opts, opts_unk = parser.parse_known_args()
print_opts_error(opts_unk)
store = CallbackModbusSlaveContext()
context = ModbusServerContext(slaves=store, single=True)
log.info("серевер-заглушка Modbus serial работает: %s:%d" % (opts.serial_port, opts.serial_baud))
StartSerialServer(context=context, framer=ModbusRtuFramer, port=opts.serial_port, timeout=opts.timeout, baudrate=opts.serial_baud)
def print_opts_error(opts: list) -> None:
for opt in opts:
log.debug('внимание: неизвестный аргумент: \"%s\"\n' % opt)
if __name__ == '__main__':
main()