首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >pymodbus + docker连接问题

pymodbus + docker连接问题
EN

Stack Overflow用户
提问于 2019-11-12 00:05:05
回答 1查看 388关注 0票数 1

我是docker和Modbus的新手,我正在尝试使用Modbus (准确地说是pymodbus工具包)编写自定义的客户端/服务器应用程序,并且我遇到了一些可能使用docker的问题。

我尝试过示例脚本clientserver

我使用的部分是:

服务器(停靠)

代码语言:javascript
运行
复制
from pymodbus.server.sync import StartTcpServer
from pymodbus.server.sync import StartTlsServer
from pymodbus.server.sync import StartUdpServer
from pymodbus.server.sync import StartSerialServer

from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

from pymodbus.transaction import ModbusRtuFramer, ModbusBinaryFramer
# --------------------------------------------------------------------------- #
# configure the service logging
# --------------------------------------------------------------------------- #
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s'
          ' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)


def run_server():
    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)

    identity = ModbusDeviceIdentification()
    identity.VendorName = 'Pymodbus'
    identity.ProductCode = 'PM'
    identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
    identity.ProductName = 'Pymodbus Server'
    identity.ModelName = 'Pymodbus Server'
    identity.MajorMinorRevision = '2.3.0'


    StartTcpServer(context, identity=identity, address=("0.0.0.0", 5020))

if __name__ == "__main__":
    print("running")
    run_server()

而且我只修补了IP地址。我可以让它在本地主机上工作,但当我将服务器部分放在Docker容器中时,我无法与它通信。

我使用docker-compose,.yml如下:

代码语言:javascript
运行
复制
version: '3.4'

services:
  server:
    build: ./server
    #network_mode: host
    expose:
      - 5020
    ports:
      - 5020:5020

客户端

代码语言:javascript
运行
复制
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
# from pymodbus.client.sync import ModbusUdpClient as ModbusClient
# from pymodbus.client.sync import ModbusSerialClient as ModbusClient

# --------------------------------------------------------------------------- #
# configure the client logging
# --------------------------------------------------------------------------- #
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
          '%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)

UNIT = 0x1


def run_sync_client():

    client = ModbusClient('127.0.0.1', port=5020)
    client.connect()

    log.debug("Reading Coils")
    rr = client.read_coils(1, 1, unit=UNIT)
    log.debug(rr)

    log.debug("Write to a Coil and read back")
    rq = client.write_coil(0, True, unit=UNIT)
    rr = client.read_coils(0, 1, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error
    assert(rr.bits[0] == True)          # test the expected value

    log.debug("Write to multiple coils and read back- test 1")
    rq = client.write_coils(1, [True]*8, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error
    rr = client.read_coils(1, 21, unit=UNIT)
    assert(not rr.isError())     # test that we are not an error
    resp = [True]*21

    resp.extend([False]*3)
    assert(rr.bits == resp)         # test the expected value

    log.debug("Write to multiple coils and read back - test 2")
    rq = client.write_coils(1, [False]*8, unit=UNIT)
    rr = client.read_coils(1, 8, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error
    assert(rr.bits == [False]*8)         # test the expected value

    log.debug("Read discrete inputs")
    rr = client.read_discrete_inputs(0, 8, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error

    log.debug("Write to a holding register and read back")
    rq = client.write_register(1, 10, unit=UNIT)
    rr = client.read_holding_registers(1, 1, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error
    assert(rr.registers[0] == 10)       # test the expected value

    log.debug("Write to multiple holding registers and read back")
    rq = client.write_registers(1, [10]*8, unit=UNIT)
    rr = client.read_holding_registers(1, 8, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error
    assert(rr.registers == [10]*8)      # test the expected value

    log.debug("Read input registers")
    rr = client.read_input_registers(1, 8, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error

    arguments = {
        'read_address':    1,
        'read_count':      8,
        'write_address':   1,
        'write_registers': [20]*8,
    }
    log.debug("Read write registeres simulataneously")
    rq = client.readwrite_registers(unit=UNIT, **arguments)
    rr = client.read_holding_registers(1, 8, unit=UNIT)
    assert(not rq.isError())     # test that we are not an error
    assert(rq.registers == [20]*8)      # test the expected value
    assert(rr.registers == [20]*8)      # test the expected value

    client.close()


if __name__ == "__main__":
    run_sync_client()

Docker镜像启动正常,但当我尝试运行客户端脚本时,我得到了一个断言错误,这与没有运行容器时的failed-to-connect错误不同。

代码语言:javascript
运行
复制
2019-11-11 16:57:36,456 MainThread      DEBUG    client         :83       Reading Coils
2019-11-11 16:57:36,456 MainThread      DEBUG    transaction    :115      Current transaction state - IDLE
2019-11-11 16:57:36,456 MainThread      DEBUG    transaction    :120      Running transaction 1
2019-11-11 16:57:36,457 MainThread      DEBUG    transaction    :219      SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x1 0x0 0x1 0x0 0x1
2019-11-11 16:57:36,457 MainThread      DEBUG    sync           :75       New Transaction state 'SENDING'
2019-11-11 16:57:36,457 MainThread      DEBUG    transaction    :228      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2019-11-11 16:57:41,460 MainThread      DEBUG    transaction    :238      Transaction failed. (Modbus Error: [Invalid Message] Incomplete message received, expected at least 8 bytes (0 received)) 
2019-11-11 16:57:41,460 MainThread      DEBUG    socket_framer  :147      Processing: 
2019-11-11 16:57:41,460 MainThread      DEBUG    transaction    :394      Getting transaction 1
2019-11-11 16:57:41,460 MainThread      DEBUG    transaction    :193      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
2019-11-11 16:57:41,460 MainThread      DEBUG    client         :85       Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 8 bytes (0 received)
2019-11-11 16:57:41,460 MainThread      DEBUG    client         :100      Write to a Coil and read back
2019-11-11 16:57:41,461 MainThread      DEBUG    transaction    :115      Current transaction state - TRANSACTION_COMPLETE
2019-11-11 16:57:41,461 MainThread      DEBUG    transaction    :120      Running transaction 2
2019-11-11 16:57:41,461 MainThread      DEBUG    transaction    :219      SEND: 0x0 0x2 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0xff 0x0
2019-11-11 16:57:41,461 MainThread      DEBUG    sync           :75       New Transaction state 'SENDING'
2019-11-11 16:57:41,461 MainThread      DEBUG    transaction    :228      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2019-11-11 16:57:45,001 MainThread      DEBUG    transaction    :304      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2019-11-11 16:57:45,001 MainThread      DEBUG    transaction    :233      RECV: 
2019-11-11 16:57:45,001 MainThread      DEBUG    socket_framer  :147      Processing: 
2019-11-11 16:57:45,001 MainThread      DEBUG    transaction    :394      Getting transaction 2
2019-11-11 16:57:45,001 MainThread      DEBUG    transaction    :193      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
2019-11-11 16:57:45,001 MainThread      DEBUG    transaction    :115      Current transaction state - TRANSACTION_COMPLETE
2019-11-11 16:57:45,001 MainThread      DEBUG    transaction    :120      Running transaction 3
2019-11-11 16:57:45,001 MainThread      DEBUG    transaction    :219      SEND: 0x0 0x3 0x0 0x0 0x0 0x6 0x1 0x1 0x0 0x0 0x0 0x1
2019-11-11 16:57:45,001 MainThread      DEBUG    sync           :75       New Transaction state 'SENDING'
2019-11-11 16:57:45,002 MainThread      DEBUG    transaction    :238      Transaction failed. ([Errno 32] Broken pipe) 
2019-11-11 16:57:45,002 MainThread      DEBUG    socket_framer  :147      Processing: 
2019-11-11 16:57:45,002 MainThread      DEBUG    transaction    :394      Getting transaction 3
2019-11-11 16:57:45,002 MainThread      DEBUG    transaction    :193      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Traceback (most recent call last):
  File "client.py", line 166, in <module>
    run_sync_client()
  File "client.py", line 103, in run_sync_client
    assert(not rq.isError())     # test that we are not an error
AssertionError

我还尝试让容器使用主机接口(使用network-mode: host),效果还不错。因此,我认为我在容器的网络设置中有一些错误。据我所知,docker container确实侦听指定的端口,但我的脚本不是?

我很高兴知道我的错误在哪里,以及如何调试这些东西,我试图在tcpdump和docker network inspect中找到一些东西,但我找不到任何相关的东西。

EN

回答 1

Stack Overflow用户

发布于 2019-11-14 17:53:47

好的,过了一段时间,我意识到,我是从相同的构建中重新部署docker容器-所以我没有对服务器脚本IP进行任何更改,因为docker总是使用第一个构建。现在我知道为什么我应该使用卷装载而不是复制文件了。

我已经重建了docker镜像,服务器IP设置为0.0.0.0 (监听所有IP),并且工作正常。希望这至少能帮助某些人节省一些时间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58804801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档