ljean / modbus-tk

Create Modbus app easily with Python
Other
566 stars 212 forks source link

[Question] Server Modbus Simulating several devices error. #122

Open maximeLeurent opened 4 years ago

maximeLeurent commented 4 years ago

Hi,

I am creating a soft that is able to interrogate real object by Modbus_TCP. (I call them devices) For testing my soft i am also creating a simulator, that simulate the behavior of those devices. For this purpose, I am using modbus_tk in my simulator. In each I instansiate one Server, and several slaves, one for each device simulated.

I have developped the normal mode, and now I want my simulator to recreate some error that can occurs in real life : latency, deconnection, error modbus etc.

I start using hooks, such as "modbus.Slave.handle_read_holding_registers_request" It's well fonctionning to simulate Modbus errors, as i can raise those errors in my callback.

But I can't simulate latency for one device, as MobdusServer is monothread, that delay also all the other devices.

I don't know also how to simulated deconnexion for one device and not others.

Do you have any suggestions to develop this fonctionnality? I was thinking about creating one ModbusServer per devices, with a different port for each one. As it will need many refactorisation for me, i would like to know if any other solution exist. Also it creates new threads, I would prefere to reduce the number of thread in my process for performance issue.

ljean commented 4 years ago

Hello,

Yes I think that if you want to test latency independently, the better approach is to have one server per device.

Best luc

Le 14 févr. 2020 à 11:05, maximeLeurent notifications@github.com a écrit :

Hi,

I am creating a soft that is able to interrogate real object by Modbus_TCP. (I call them devices) For testing my soft i am also creating a simulator, that simulate the behavior of those devices. For this purpose, I am using modbus_tk in my simulator. In each I instansiate one Server, and several slaves, one for each device simulated.

I have developped the normal mode, and now I want my simulator to recreate some error that can occurs in real life : latency, deconnection, error modbus etc.

I start using hooks, such as "modbus.Slave.handle_read_holding_registers_request" It's well fonctionning to simulate Modbus errors, as i can raise those errors in my callback.

But I can't simulate latency for one device, as MobdusServer is monothread, that delay also all the other devices.

I don't know also how to simulated deconnexion for one device and not others.

Do you have any suggestions to develop this fonctionnality? I was thinking about creating one ModbusServer per devices, with a different port for each one. As it will need many refactorisation for me, i would like to know if any other solution exist. Also it creates new threads, I would prefere to reduce the number of thread in my process for performance issue.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ljean/modbus-tk/issues/122?email_source=notifications&email_token=AACA2OZXLJ5BJRQWPXHQDBDRCZUF7A5CNFSM4KVEZWZKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4INQUVWA, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACA2O3YIYE64XGTTBU6VE3RCZUF7ANCNFSM4KVEZWZA.

maximeLeurent commented 4 years ago

Hello,

Thanks for your reply.

I have tested this, but it's is not working.

In fact hooks callback are protected with a global lock, so the time.sleep in the callback is blocking all server threads.

Here little piece of code extract from my dev.

class Device():
    def __init__(self, port, slave_id):

        self.mb_server = TcpServer(address="127.0.0.1", port = port)
        self.slave = self.mb_server.add_slave(slave_id)
        self.slave.add_block("hr", cst.HOLDING_REGISTERS, 0, 65535)
        hooks.install_hook("modbus.Slave.handle_read_holding_registers_request", self.callback)
        self.mb_server.start()

    def callback(self, info):
        slave , request_pdu = info
        logging.info(f"{self} Parse  {request_pdu} ")
        if slave == self.slave:
            logging.info("Good reg_number time sleep")
            time.sleep(0.01)