尝试使用 Python 从联网设备上的 TCP 套接字连接获取数据

Trying to get data from a TCP socket connection on a networked device using Python

我正在尝试编写一个简单的 Python 脚本,该脚本连接到多个 Fluke 温湿度计 (DewK 1620A),并将温度和湿度读数写入一个文件,然后我可以将其导入 Splunk。这是我第一次用 Python 尝试任何事情,我真的很接近,但似乎无法确定如何通过 TCP 套接字获取数据。

概览

脚本从外部读取设备列表JSON,然后打开与每个设备的连接,发送命令以获取当前读数,然后将这些读数写入文件。

在我的第一次迭代中,我只是进行了一次“data = s.recv(64)”调用,但设备在返回完整结果时不一致。有时我会得到完整的结果(即“69.64,45.9,0,0”),而其他时候我只会得到部分读数(即“69.64,4”)。

真实循环

在做了一些研究之后,我开始看到有关使用 while True 循环在第二(或第三)遍中获取“其余”数据的建议。我用以下内容更改了简单的 s.recv 调用:

while True:
     data = s.recv(64)           # Retrieve data from device
     if not data:                # If no data exists, break loop
          continue
     f.write(data.decode())      # Write data to logfile

不幸的是,现在脚本将无法完成。我怀疑循环没有退出,但响应不应超过 24 个字节。我不确定如何测试和退出循环。我尝试添加超时,但这会杀死整个脚本。

connectDeviceTCP.py

import datetime
import json
import socket

# the command to be passed to the device
command = "read?\r"

# open the deviceLocation.json file for reading
jsonFile = open("devices.json", "r", encoding="utf-8")

# load the contents of the json file into 
locationFile = json.load(jsonFile)
jsonFile.close()

# for each device, connect & retrieve device readings
for device in locationFile["devices"]:

    location = device["location"]
    host = device["host"]
    portStr = device["port"]

    # convert the portStr variable from string to integer
    port = int(portStr)
    
    # open log file for appending.
    f = open("log/" + location + ".log", "a")

    try:

        # create a socket on client using TCP/IP
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        
        # set socket timeout to 3 seconds
        s.settimeout(10)
        
        # connect to host and port
        s.connect((host, port))

    except TimeoutError:

        # write to the log file if the host cannot be reached
        f.write(('\n{:%Y-%m-%d %H:%M:%S} - '.format(datetime.datetime.now())) + location + " - Error: " + host + ":" + portStr + " does not respond.")

    else:

        # send the command to the device
        s.sendall(command.encode())

        # write the timestamp and location to the log
        f.write(('{:%Y-%m-%d %H:%M:%S} - '.format(datetime.datetime.now())) + location + " - ")

        while True:
            data = s.recv(64)           # Retrieve data from device
            if not data:                # If no data exists, break loop
                break
            f.write(data.decode())      # Write data to logfile
        
        # --- The following work except the device doesn't always spit out all the data.
        # receive message string from device
        #data = s.recv(64)

        # write returned values to log file.
        #f.write(data.decode())

    finally:

        # disconnect the client
        s.close()      

        # close log file
        f.close()

设备与以 \r 终止的线路进行面向线路的通信,因此只需阅读整行 - 将 while True 循环 替换为

        data = s.makefile(newline='\r').readline()
        f.write(data)      # Write data to logfile