AdvancedClimateSystems / uModbus

Python implementation of the Modbus protocol.
Mozilla Public License 2.0
211 stars 81 forks source link

How to stop server from example code? #121

Open William-Durand opened 2 years ago

William-Durand commented 2 years ago

This is more a question than an issue.

I try to make a modbus server in a python thread but I don't know how to stop it. I took the exact code I found in the example part of documentation. I set up my app ("get_server(TCPServer, self.interface, RequestHandler)") and I ran this code inside my thread:

            try:
                app.serve_forever()
            finally:
                app.shutdown()
                app.server_close()

Everything works fine except I have to stop my program manually because my thread never stop. The question is: how to stop the "app.serve_forever()" part when I don't need my server anymore?

Just in case, I created an event called "stop_event" which can be set whenever I want to. But I don't really know how to use it to force the server to stop.

Best regards.

grgmm commented 1 year ago

Hi, I have the same issue, please somebody can help us?

tiagocoutinho commented 1 year ago

Here is an example adapted from scripts/examples/simple_tcp_server.py (you will need python >= 3.6):

import time
from socketserver import TCPServer
from collections import defaultdict
from threading import Thread

from umodbus import conf
from umodbus.server.tcp import RequestHandler, get_server

# A very simple data store which maps addresses against their values.
data_store = defaultdict(int)

TCPServer.allow_reuse_address = True
app = get_server(TCPServer, ("", 5020), RequestHandler)

@app.route(slave_ids=[1], function_codes=[1, 2], addresses=list(range(0, 10)))
def read_data_store(slave_id, function_code, address):
    """" Return value of address. """
    return data_store[address]

@app.route(slave_ids=[1], function_codes=[5, 15], addresses=list(range(0, 10)))
def write_data_store(slave_id, function_code, address, value):
    """" Set value for address. """
    data_store[address] = value

def serve(): 
    with app:
        app.serve_forever()

def main():
    server = Thread(target=serve)
    server.start()
    try:
        # whatever main loop you decide to run
        while True:
            time.sleep(1)
    finally:
        app.shutdown()
        server.join()

if __name__ == "__main__":
    main()

I'm not sure if this is what you're looking for but if you press Ctrl-C it should stop the server running on the other thread.