首页 > 解决方案 > 通过 Python Socket 库向研华 ADAM-6024 发送命令和接收数据

问题描述

我正在尝试使用 Python 向 Advantech 的基于以太网的 ADAM-6024 数据采集和控制模块发送命令和接收数据。我正在使用 MacBook Pro 并通过以太网连接连接到设备。

以下是 ADAM-6000 系列设备的手册:

http://advdownload.advantech.com/productfile/Downloadfile4/1-1M99LTH/ADAM-6000_User_Manaul_Ed_9.pdf

我编写了一个名为 ADAMConnection 的 python 类,其中包含设置与模块的套接字连接然后向其发送命令并请求响应的方法。

我可以建立套接字连接,但没有运气与设备通信。这是我编写的库:

class ADAMConnection:
    def __init__(self, host, eth_port):
        self.host = host
        self.eth_port = eth_port
        self.adamsock = None

    ###############################################################################
    # ConnectADAM() method
    ###############################################################################
    def OpenADAMConnection( self ):
      self.adamsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      self.adamsock.settimeout(2)
      try:
         self.adamsock.connect((self.host,self.eth_port))
         #self.adamsock.send(str.encode("*RST\r\n")) #Example of what's done in DAQConn
         #TODO: Do we need any initialization commands?
         print("ADAM connected..")
         time.sleep(0.05)
         return True
      except socket.timeout:
         print('\n*************** ERROR *****************')
         print('Attempt to connect to the ADAM timed out. \n' + \
               'Make sure it\'s powered on and plugged in.')
         print('*************** ERROR *****************\n\n')
         return False
      except OSError:
         print('\n*************** ERROR *****************')
         print('Unable to connect to the ADAM. \n' + \
               'Make sure it\'s powered on and plugged in.')
         print('*************** ERROR *****************\n\n')
         return False

    def GetModuleName(self,commandString):
        #self.adamsock.send(str.encode("ASCII STRING")) 
        self.adamsock.send(str.encode(commandString,encoding="ascii")) 
        time.sleep(0.05)
        adam_out = self.adamsock.recv(100) #is the 100 needed?  Maybe try for now
        time.sleep(0.05)
        return adam_out

当我导入这个库并尝试建立套接字连接时,我成功了。我试图通过 ASCII 命令与它交谈,所以我使用端口 502。我知道从这个链接使用这个端口:

http://advdownload.advantech.com/productfile/Downloadfile1/GF-1HBO9/Which%20TCP%20and%20UDP%20Ports%20do%20ADAM%20Ethernet%20Modules%20Use.pdf

但是,当我尝试向 ADAM-6024 模块询问其模块名称时,我得到了我不理解的毫无意义的输出。我首先尝试使用我在手册第 112 页(第一个链接)上找到的 ASCII 语法发送命令来读取模块名称,但收到了似乎是垃圾输出的内容。为了确认这一点,我发送了一条我知道对模块没有意义的命令,并收到了类似的输出。

以下是我用来执行上述操作的python代码:

Python 3.8.5 (default, Sep  4 2020, 02:22:02) 
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ADAMConnection
>>> module1 = ADAMConnection.ADAMConnection("192.168.6.70",502)
>>> module1.OpenADAMConnection()
ADAM connected..
True
>>> module1.GetModuleName("01M0Dh")
b'01M0\x00\x03\x00\x80\x01'
>>> module1.GetModuleName("nonsense")
b'nons\x00\x03s\xe5\x01'

我几乎不精通 Python,对 Modbus/TCP/ASCII/Socket 连接一无所知,所以我不知道我是否遗漏了一些非常明显的东西。任何帮助将不胜感激。

标签: pythonsocketsasciiethernet

解决方案


您成功发送和接收数据是一个好的开始。但是,我不知道您是如何获得命令字符串的"01M0Dh"。本用户手册,第7.4 节 ADAM-6000 模块的 ASCII 命令说:

$aaM

名称读取模块名称
描述返回特定模块的名称
语法$aaM(cr)
 $ 为分隔符
 aa(范围 00~FF)为指定模块的 2 字符十六进制从地址(始终为 01)
 M 指读取型号命令
 (cr) 是终止字符,回车 (0Dh)

这对应于 Python 字符串"$01M\r"

查看您发布的响应数据包以及端口 502,似乎使用了Modbus TCP协议。手册对此有些不清楚,但可能是 ASCII 命令要嵌入到 Modbus TCP 帧中;然后字符串就像 eg "..\0\0\0\5$01M\r"。但是,我不能排除 ASCII 命令是由 UDP 发送到端口 1025。如果您没有通过这种方式成功,您也可以尝试从浏览器中使用 HTTP,如D.2 REST 资源部分所述亚当,例如。http://host/digitalinput/all/value


推荐阅读