Доработка. Добавлен имитатор сервера Modbus Serial прибора Щ3

This commit is contained in:
sasha80
2024-02-29 11:36:27 +03:00
parent 71655c8978
commit a895683bb8
2 changed files with 83 additions and 1 deletions

76
modbus/server-rtu.py Normal file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""
Имитатор сервера Modbus Serial прибора Щ3.
Использовать для отладки.
"""
import logger
import os
import argparse
from pymodbus.server.sync import StartSerialServer
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext, ModbusSparseDataBlock
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(f'setValues() fx:{fx} address:{address} values:{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(f'getValues() fx:{fx} address:{address} values:{values}')
return values
def main():
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-modbus-unit', default=1, type=int, help='Номер устройства Modbus')
parser.add_argument('-serial-baud', default=115200, type=int, help='Скорость последовательного порта, бод')
parser.add_argument('-serial-port', default=DEF_SERIAL, type=str, help='Последовательный порт для подключения клиента Modbus ')
opts, opts_unk = parser.parse_known_args()
print_opts_error(opts_unk)
run_server(opts.serial_port, opts.serial_baud)
def run_server(serial_port, serial_baud):
store = CallbackModbusSlaveContext()
context = ModbusServerContext(slaves=store, single=True)
# timeout=.005 - нужно обязательно указать, иначе не работает
StartSerialServer(context=context, framer=ModbusRtuFramer, port=serial_port, timeout=.005, baudrate=serial_baud)
def print_opts_error(opts: list) -> None:
for opt in opts:
log.debug('внимание: неизвестный аргумент: \"%s\"\n' % opt)
if __name__ == '__main__':
main()

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
SERIAL_PORT2="/home/$(whoami)/tty2" # Порт для подключения драйвера клиента
SERIAL_PORT3="/home/$(whoami)/tty3" # Порт для подключения сервера Modbus
SERIAL_PORT3="/home/$(whoami)/tty3" # Порт для подключения сервера Modbus Serial (Прибор Щ3)
UDP_ADDR="localhost"
UDP_PORT_RX="44100"
UDP_PORT_TX="48000"
@@ -50,6 +50,12 @@ fi
# \---------------------------------------------------------------------------------/
# /---------------------------------------------------------------------------------\
# Запустить сервер Modbus Serial (Прибор Щ3)
xterm -geometry 120x5 -fa Monospace -fs 12 -hold -T "Сервер Modbus Serial Щ3 \"${SERIAL_PORT3}\"" -e "python3 server-rtu.py -serial-port ${SERIAL_PORT3}" &
# \---------------------------------------------------------------------------------/
# /---------------------------------------------------------------------------------\
# Запустить драйвер клиента Modbus
xterm -geometry 120x5 -fa Monospace -fs 12 -hold -T "Драйвер клиента Modbus Serial \"${SERIAL_PORT2} ${UDP_ADDR}:${UDP_PORT_RX}\"" -e "python3 client-serial-tcp.py -serial-port ${SERIAL_PORT2} -udp-addr ${UDP_ADDR} -udp-port-rx ${UDP_PORT_RX} -udp-port-tx ${UDP_PORT_TX}" &