Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在循环调用期间继续pymodbus TcpServer操作_Python_Multithreading_Python 2.7_Raspberry Pi_Modbus - Fatal编程技术网

Python 在循环调用期间继续pymodbus TcpServer操作

Python 在循环调用期间继续pymodbus TcpServer操作,python,multithreading,python-2.7,raspberry-pi,modbus,Python,Multithreading,Python 2.7,Raspberry Pi,Modbus,我已经实现了一个pymodbus TcpServer,它根据一些UART通信更新其上下文。我使用LoopingCall进行UART通信并更新modbus上下文。在循环调用期间我发送一些UART消息并等待适当的回答。您可以在下面看到缩短和简化的代码(请注意,代码不是以这种方式运行的,但我希望您可以看到我是如何做的) 为了完整起见,这里是timeout函数(我在Stackoverflow找到了类似的例子) 在我看来,pymodbus TcpServer似乎在循环调用操作期间冻结(更新\u write

我已经实现了一个pymodbus TcpServer,它根据一些UART通信更新其上下文。我使用
LoopingCall
进行UART通信并更新modbus上下文。在
循环调用期间
我发送一些UART消息并等待适当的回答。您可以在下面看到缩短和简化的代码(请注意,代码不是以这种方式运行的,但我希望您可以看到我是如何做的)

为了完整起见,这里是timeout函数(我在Stackoverflow找到了类似的例子)

在我看来,pymodbus TcpServer似乎在
循环调用
操作期间冻结(
更新\u writer()

LoopingCall
是否在自己的线程中运行,还是阻止pymodbus TcpServer操作?我如何实现这一点,使TcpServer不会冻结

顺便说一下:这段代码运行在一个带有raspbian jessie和python-2.7的raspberry上

EDIT:我想我需要修改我的问题,因为
LoopingCall
似乎在主线程中运行,并阻止了其他操作


如何修改代码,以便pymodbus TcpServer在更新任务期间不会被阻止?

TcpServer不会冻结?
否!你的程序被冻结了。需要创建自己的
modbustcp
模块。仔细创建一个通信线程。检查哪些传入、等待、缓冲区已满、数据包健康状况良好等等。如果同时通话和收听,则会出现很多错误@对不起,我真的听不懂你的话。是否也可以在自己的线程中执行
更新_writer()
。(代码也适用于pymodbus)但是我发现modbus tk对于我使用的一些设备(COMAP)更可靠。TcpServer不会冻结?No!你的程序被冻结了。需要创建自己的
modbustcp
模块。仔细创建一个通信线程。检查哪些传入、等待、缓冲区已满、数据包健康状况良好等等。如果同时通话和收听,则会出现很多错误@对不起,我真的听不懂你的话。是否也可以在自己的线程中执行
更新_writer()
。(代码也适用于pymodbus)但是我发现modbus tk对于我使用的一些设备(COMAP)更可靠。
#!/usr/bin/env python
'''
Pymodbus Server With Updating Thread
--------------------------------------------------------------------------

This is an example of having a background thread updating the
context while the server is operating. This can also be done with
a python thread::

    from threading import Thread

    thread = Thread(target=updating_writer, args=(context,))
    thread.start()
'''
#---------------------------------------------------------------------------# 
# import the modbus libraries we need
#---------------------------------------------------------------------------# 
from pymodbus.server.async import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer

#---------------------------------------------------------------------------# 
# import the twisted libraries we need
#---------------------------------------------------------------------------# 
from twisted.internet.task import LoopingCall

#---------------------------------------------------------------------------# 
# define your callback process
#---------------------------------------------------------------------------# 
def updating_writer(a):
    context  = a[0]
    register = 3
    slave_id = 0x00
    address  = 0x10
    _ser_ = serial.Serial(
            #port = '/dev/ttyUSB0',
            port = dev,
            baudrate=115200,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            bytesize=serial.EIGHTBITS
        )
    _ser_.open()
    _ser_.write("Example")
    inbuff = []
    values = []
    @timeout(0.1)
    while True:
        inbuff.append(_ser_.read(1))
        # come kind of checksum calculation, to check if message is complete
        if checkmessage(inbuff):
            values = ord(inbuff[0])
            break
    context[slave_id].setValues(register, address, values)

#---------------------------------------------------------------------------# 
# initialize your data store
#---------------------------------------------------------------------------# 
store = ModbusSlaveContext(
    di = ModbusSequentialDataBlock(0, [17]*100),
    co = ModbusSequentialDataBlock(0, [17]*100),
    hr = ModbusSequentialDataBlock(0, [17]*100),
    ir = ModbusSequentialDataBlock(0, [17]*100))
context = ModbusServerContext(slaves=store, single=True)

#---------------------------------------------------------------------------# 
# initialize the server information
#---------------------------------------------------------------------------# 
identity = ModbusDeviceIdentification()
identity.VendorName  = 'pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl   = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName   = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'

#---------------------------------------------------------------------------# 
# run the server you want
#---------------------------------------------------------------------------# 
time = 5 # 5 seconds delay
loop = LoopingCall(f=updating_writer, a=(context,))
loop.start(time, now=False) # initially delay by time
StartTcpServer(context, identity=identity, address=("localhost", 5020))
from functools import wraps
import errno
import os
import signal

class TimeoutError(Exception):
    pass

def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
    def decorator(func):
        def _handle_timeout(signum, frame):
            raise TimeoutError(error_message)

        def wrapper(*args, **kwargs):
            signal.signal(signal.SIGALRM, _handle_timeout)
            #signal.alarm(seconds)
            signal.setitimer(signal.ITIMER_REAL,seconds)
            try:
                result = func(*args, **kwargs)
            finally:
                #signal.alarm(0)
                signal.setitimer(signal.ITIMER_REAL,0)
            return result

        return wraps(func)(wrapper)

    return decorator