1

我正在处理一个工业环境,我必须在现场记录来自串行设备的读数。我当前的设置涉及连接到 Moxa 5150A 或 5130 串行设备服务器的设备,该服务器通过有线或无线方式连接到我的网络,具体取决于各个设备的位置。目前,我依赖硬件供应商提供的软件来管理数据收集。当前的软件是基于windows X86的,并且由于以前的硬件故障而在我们购买的新硬件上造成了无穷无尽的麻烦。我专门选择 Moxa 串行服务器是因为它们的 linux 驱动程序和兼容性。该设备通过 RS-422(4 线半双工)7 位 1-stop 奇校验和 NO 流控制进行通信,除非请求,否则不会发送任何信息。

我正在开发自己的解决方案,将信息存储在数据库(可能是 MySQL)中。就终端通信而言,这是两部分。我必须发送请求并接收响应。

迄今为止,我已将串行服务器的 Moxa 驱动程序安装到我的 linux 服务器上。我编写了一个从 /dev/ttyrXX 设备读取的 bash 脚本,解释输入并将信息加载到 mysql 数据库中。

      while read line
      do
      something something....
      done < /dev/ttyrXX

我仍在解决一些小的脚本错误,例如在设备脱机时正确重启,然后又重新联机以及其他此类问题,但我的脚本正在读取和记录我的数据,这完全符合我的需要。

该解决方案依赖于两个因素。

1) Moxa 设备支持 FIFO 并允许同时进行多个连接

2) 供应商提供的在单独的 Windows 机器上运行的软件当前正在提交信息请求。

我需要一起删除基于 Windows 的软件。我已经编写并测试了一个脚本,该脚本打印到 /dev/ttyrXX 发出我想要的请求并收到适当的响应,并按照我的第一个脚本的需要记录它们。

     some list of things
     for x in list
     do         
     printf "request" > /dev/ttyrXX
     done

我在使用供应商提供的软件时遇到的主要问题之一是它对接收对每个请求的及时响应的硬编码依赖性。这会产生许多问题,包括完全冻结窗口和设备在不合时宜的时间停止服务时崩溃。

我的两个脚本协同工作以明显更好的间隔收集数据,并且人工干预更少。

这是我的问题。我可以在 Python 中使用什么方法来获得与我的 Bash 脚本相当的结果?

我一直无法找到不需要我打开/关闭文件的与 printf 或 cat 等效的 Python。此外,我查看过的每个终端界面都有内置的或必需的等待响应或在放弃之前阅读这么长时间。我确定那里存在某些东西,我几乎没有运气找到它。我承认我是 Python 的新手,并且只写了几行代码来探索它的能力。

让我说得很清楚。我想写信给我的终端,而不用担心我在写的时候(使用我不在乎的线程或单独的脚本)。我想从我的终端上阅读,而不用担心我的下一段文字何时到来。(我并不是在暗示一个永无止境的循环,但我确实需要它来简单地等待输入)。我希望/需要我的写入和读取完全独立于彼此,而不关心对方昨天、现在或下周在做什么。

先感谢您。

如果有必要,我将能够提供更详细的代码,但是我觉得我在搜索中更需要指导而不是修复错误。虽然我仍然完全愿意接受建议和“永远不要这样做......因为这个......”类型输入

4

3 回答 3

1

听起来您想打开一个文件进行读/写并依次读取每一行。

with open(..., 'r+') as dev:
  for line in dev:
     ...
    print >>dev, 'foo'
于 2012-08-18T05:11:13.200 回答
1

扩展伊格纳西奥所说的内容。听起来最简单的解决方案是让两个脚本在启动时启动。

其中一个打开打开 tty 设备并永远收听它。这是一个阻塞读取。它继续寻找新的输入行,直到它收到(或到达)EOF。在这种情况下,这可能永远不会发生。它看起来像这样:

# tty reader

def listen_to_device():
    with open('/dev/ttyXX', 'r') as tty:
        for line in tty:
            create_db_record(line)

if __name__ == '__main__':
    listen_to_device()

要使其成为完整的工作代码,您唯一需要实现的是“create_db_record”函数。

第二个脚本可能非常相似。但也许它会继续在目录中寻找包含命令的特定文件。当它找到任何东西时,它会一个接一个地将它们发送到 tty 设备。

# tty controller

import os
import shutil
import time

def wait_for_commands():
    while True:
        if os.path.exists('/tmp/commands.txt'):
            with open('/tmp/commands.txt', 'r') as c:
                for command in c:
                    send_command(command)
            shutil.move('/tmp/commands.txt', 'tmp/proccesed-' str(datetime.utcnow()))
        time.sleep(1)


def send_command(command):
    with open('/dev/ttyXX', 'w') as tty:
        # maybe do some additional changes to command here?
        tty.write(command)


if __name__ == '__main__':
    wait_for_command()

您可以在 send_command 函数中添加一些额外的处理代码,以便您在 commands.txt 文件中的指令变得非常简单。

于 2012-08-18T08:10:36.177 回答
1

我会推荐 pyserial (你可以使用它非阻塞),但我不知道它是否正确处理任何不是 RS232 的东西。

我一直无法找到不需要我打开/关闭文件的与 printf 或 cat 等效的 Python。

通常,您只需打开文件并调用 .write() 函数(相当于 printf)或 .readline() 函数。这有什么问题?当您在 shell 脚本中使用“cat”或“echo”或管道时,这也会在后台打开和关闭文件。如果你真的需要重新打开文件出于某种有线原因(例如内核驱动程序出现问题),那么你可以编写一个 python 函数来做到这一点。

此外,我查看过的每个终端界面都有内置的或必需的等待响应或在放弃之前阅读这么长时间。

串行库通常只有读取超时,而不是写入超时(但对于写入,我认为内核驱动程序通常有一个缓冲区,如果你写得太快,理论上可能会溢出......)。

我没有看到这个超时对你来说是个问题吗?如果你可以用两个独立的python程序打开终端,一个写,一个读,你的问题就解决了,对吧?

您应该注意的是,您可以对文件执行阻塞或非阻塞 I/O。默认情况下,一切都会被阻止。您可以使用select()系统调用(也来自 Python)来解决线程或单独进程的所有需求。只要文件可以在没有阻塞的情况下读取/写入,或者出现异常(例如,设备消失)或超时(如果您设置了一个),Select 就会返回。

于 2012-08-18T08:34:33.953 回答